diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/comedi/drivers/icp_multi.c | 89 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers/icp_multi.h | 297 |
2 files changed, 25 insertions, 361 deletions
diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index 4673a89..14b4ce5 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -44,10 +44,7 @@ There are 4 x 12-bit Analogue Outputs. Ranges : 5V, 10V, +/-5V, +/-10V 4 x 16-bit counters -Options: - [0] - PCI bus number - if bus number and slot number are 0, - then driver search for first unused card - [1] - PCI slot number +Configuration options: not applicable, uses PCI auto config */ #include <linux/interrupt.h> @@ -56,8 +53,6 @@ Options: #include <linux/delay.h> #include <linux/pci.h> -#include "icp_multi.h" - #define PCI_DEVICE_ID_ICP_MULTI 0x8000 #define ICP_MULTI_ADC_CSR 0 /* R/W: ADC command/status register */ @@ -117,18 +112,10 @@ static const char range_codes_analog[] = { 0x00, 0x20, 0x10, 0x30 }; Data & Structure declarations ============================================================================== */ -static unsigned short pci_list_builded; /*>0 list of card is known */ - -struct boardtype { - const char *name; /* driver name */ - int device_id; -}; struct icp_multi_private { - struct pcilst_struct *card; /* pointer to card */ char valid; /* card is usable */ void __iomem *io_addr; /* Pointer to mapped io address */ - resource_size_t phys_iobase; /* Physical io address */ unsigned int AdcCmdStatus; /* ADC Command/Status register */ unsigned int DacCmdStatus; /* DAC Command/Status register */ unsigned int IntEnable; /* Interrupt Enable register */ @@ -144,7 +131,6 @@ struct icp_multi_private { }; #define devpriv ((struct icp_multi_private *)dev->private) -#define this_board ((const struct boardtype *)dev->board_ptr) /* ============================================================================== @@ -696,60 +682,43 @@ static int icp_multi_reset(struct comedi_device *dev) return 0; } -static int icp_multi_attach(struct comedi_device *dev, - struct comedi_devconfig *it) +static int icp_multi_attach_pci(struct comedi_device *dev, + struct pci_dev *pcidev) { struct comedi_subdevice *s; + resource_size_t iobase; int ret; - unsigned int irq; - struct pcilst_struct *card = NULL; - resource_size_t io_addr[5], iobase; - unsigned char pci_bus, pci_slot, pci_func; + + comedi_set_hw_dev(dev, &pcidev->dev); + dev->board_name = dev->driver->driver_name; ret = alloc_private(dev, sizeof(struct icp_multi_private)); if (ret < 0) return ret; - /* Initialise list of PCI cards in system, if not already done so */ - if (pci_list_builded++ == 0) - pci_card_list_init(PCI_VENDOR_ID_ICP, 0); - - card = select_and_alloc_pci_card(PCI_VENDOR_ID_ICP, - this_board->device_id, it->options[0], - it->options[1]); - - if (card == NULL) - return -EIO; - - devpriv->card = card; - - if ((pci_card_data(card, &pci_bus, &pci_slot, &pci_func, &io_addr[0], - &irq)) < 0) - return -EIO; + ret = comedi_pci_enable(pcidev, dev->board_name); + if (ret) + return ret; + iobase = pci_resource_start(pcidev, 2); + dev->iobase = iobase; - iobase = io_addr[2]; - devpriv->phys_iobase = iobase; devpriv->io_addr = ioremap(iobase, ICP_MULTI_SIZE); - if (devpriv->io_addr == NULL) + if (!devpriv->io_addr) return -ENOMEM; - dev->board_name = this_board->name; - ret = comedi_alloc_subdevices(dev, 5); if (ret) return ret; icp_multi_reset(dev); - if (irq) { - if (request_irq(irq, interrupt_service_icp_multi, - IRQF_SHARED, "Inova Icp Multi", dev)) { - irq = 0; /* Can't use IRQ */ - } + if (pcidev->irq) { + ret = request_irq(pcidev->irq, interrupt_service_icp_multi, + IRQF_SHARED, dev->board_name, dev); + if (ret == 0) + dev->irq = pcidev->irq; } - dev->irq = irq; - s = &dev->subdevices[0]; dev->read_subdev = s; s->type = COMEDI_SUBD_AI; @@ -811,6 +780,8 @@ static int icp_multi_attach(struct comedi_device *dev, static void icp_multi_detach(struct comedi_device *dev) { + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + if (dev->private) if (devpriv->valid) icp_multi_reset(dev); @@ -818,27 +789,17 @@ static void icp_multi_detach(struct comedi_device *dev) free_irq(dev->irq, dev); if (dev->private && devpriv->io_addr) iounmap(devpriv->io_addr); - if (dev->private && devpriv->card) - pci_card_free(devpriv->card); - if (--pci_list_builded == 0) - pci_card_list_cleanup(PCI_VENDOR_ID_ICP); + if (pcidev) { + if (dev->iobase) + comedi_pci_disable(pcidev); + } } -static const struct boardtype boardtypes[] = { - { - .name = "icp_multi", - .device_id = PCI_DEVICE_ID_ICP_MULTI, - }, -}; - static struct comedi_driver icp_multi_driver = { .driver_name = "icp_multi", .module = THIS_MODULE, - .attach = icp_multi_attach, + .attach_pci = icp_multi_attach_pci, .detach = icp_multi_detach, - .num_names = ARRAY_SIZE(boardtypes), - .board_name = &boardtypes[0].name, - .offset = sizeof(struct boardtype), }; static int __devinit icp_multi_pci_probe(struct pci_dev *dev, diff --git a/drivers/staging/comedi/drivers/icp_multi.h b/drivers/staging/comedi/drivers/icp_multi.h deleted file mode 100644 index dbf9908..0000000 --- a/drivers/staging/comedi/drivers/icp_multi.h +++ /dev/null @@ -1,297 +0,0 @@ -/* - comedi/drivers/icp_multi.h - - Stuff for ICP Multi - - Author: Anne Smorthit <anne.smorthit@sfwte.ch> - -*/ - -#ifndef _ICP_MULTI_H_ -#define _ICP_MULTI_H_ - -#include "../comedidev.h" - -/****************************************************************************/ - -struct pcilst_struct { - struct pcilst_struct *next; - int used; - struct pci_dev *pcidev; - unsigned short vendor; - unsigned short device; - unsigned char pci_bus; - unsigned char pci_slot; - unsigned char pci_func; - resource_size_t io_addr[5]; - unsigned int irq; -}; - -struct pcilst_struct *inova_devices; -/* ptr to root list of all Inova devices */ - -/****************************************************************************/ - -static void pci_card_list_init(unsigned short pci_vendor, char display); -static void pci_card_list_cleanup(unsigned short pci_vendor); -static struct pcilst_struct *find_free_pci_card_by_device(unsigned short - vendor_id, - unsigned short - device_id); -static int find_free_pci_card_by_position(unsigned short vendor_id, - unsigned short device_id, - unsigned short pci_bus, - unsigned short pci_slot, - struct pcilst_struct **card); -static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id, - unsigned short device_id, - unsigned short pci_bus, - unsigned short pci_slot); - -static int pci_card_alloc(struct pcilst_struct *amcc); -static int pci_card_free(struct pcilst_struct *amcc); -static void pci_card_list_display(void); -static int pci_card_data(struct pcilst_struct *amcc, - unsigned char *pci_bus, unsigned char *pci_slot, - unsigned char *pci_func, resource_size_t * io_addr, - unsigned int *irq); - -/****************************************************************************/ - -/* build list of Inova cards in this system */ -static void pci_card_list_init(unsigned short pci_vendor, char display) -{ - struct pci_dev *pcidev = NULL; - struct pcilst_struct *inova, *last; - int i; - - inova_devices = NULL; - last = NULL; - - for_each_pci_dev(pcidev) { - if (pcidev->vendor == pci_vendor) { - inova = kzalloc(sizeof(*inova), GFP_KERNEL); - if (!inova) { - printk - ("icp_multi: pci_card_list_init: allocation failed\n"); - pci_dev_put(pcidev); - break; - } - - inova->pcidev = pci_dev_get(pcidev); - if (last) { - last->next = inova; - } else { - inova_devices = inova; - } - last = inova; - - inova->vendor = pcidev->vendor; - inova->device = pcidev->device; - inova->pci_bus = pcidev->bus->number; - inova->pci_slot = PCI_SLOT(pcidev->devfn); - inova->pci_func = PCI_FUNC(pcidev->devfn); - /* Note: resources may be invalid if PCI device - * not enabled, but they are corrected in - * pci_card_alloc. */ - for (i = 0; i < 5; i++) - inova->io_addr[i] = - pci_resource_start(pcidev, i); - inova->irq = pcidev->irq; - } - } - - if (display) - pci_card_list_display(); -} - -/****************************************************************************/ -/* free up list of amcc cards in this system */ -static void pci_card_list_cleanup(unsigned short pci_vendor) -{ - struct pcilst_struct *inova, *next; - - for (inova = inova_devices; inova; inova = next) { - next = inova->next; - pci_dev_put(inova->pcidev); - kfree(inova); - } - - inova_devices = NULL; -} - -/****************************************************************************/ -/* find first unused card with this device_id */ -static struct pcilst_struct *find_free_pci_card_by_device(unsigned short - vendor_id, - unsigned short - device_id) -{ - struct pcilst_struct *inova, *next; - - for (inova = inova_devices; inova; inova = next) { - next = inova->next; - if ((!inova->used) && (inova->device == device_id) - && (inova->vendor == vendor_id)) - return inova; - - } - - return NULL; -} - -/****************************************************************************/ -/* find card on requested position */ -static int find_free_pci_card_by_position(unsigned short vendor_id, - unsigned short device_id, - unsigned short pci_bus, - unsigned short pci_slot, - struct pcilst_struct **card) -{ - struct pcilst_struct *inova, *next; - - *card = NULL; - for (inova = inova_devices; inova; inova = next) { - next = inova->next; - if ((inova->vendor == vendor_id) && (inova->device == device_id) - && (inova->pci_bus == pci_bus) - && (inova->pci_slot == pci_slot)) { - if (!(inova->used)) { - *card = inova; - return 0; /* ok, card is found */ - } else { - return 2; /* card exist but is used */ - } - } - } - - return 1; /* no card found */ -} - -/****************************************************************************/ -/* mark card as used */ -static int pci_card_alloc(struct pcilst_struct *inova) -{ - int i; - - if (!inova) { - printk(" - BUG!! inova is NULL!\n"); - return -1; - } - - if (inova->used) - return 1; - if (comedi_pci_enable(inova->pcidev, "icp_multi")) { - printk(" - Can't enable PCI device and request regions!\n"); - return -1; - } - /* Resources will be accurate now. */ - for (i = 0; i < 5; i++) - inova->io_addr[i] = pci_resource_start(inova->pcidev, i); - inova->irq = inova->pcidev->irq; - inova->used = 1; - return 0; -} - -/****************************************************************************/ -/* mark card as free */ -static int pci_card_free(struct pcilst_struct *inova) -{ - if (!inova) - return -1; - - if (!inova->used) - return 1; - inova->used = 0; - comedi_pci_disable(inova->pcidev); - return 0; -} - -/****************************************************************************/ -/* display list of found cards */ -static void pci_card_list_display(void) -{ - struct pcilst_struct *inova, *next; - - printk("Anne's List of pci cards\n"); - printk("bus:slot:func vendor device io_inova io_daq irq used\n"); - - for (inova = inova_devices; inova; inova = next) { - next = inova->next; - printk - ("%2d %2d %2d 0x%4x 0x%4x 0x%8llx 0x%8llx %2u %2d\n", - inova->pci_bus, inova->pci_slot, inova->pci_func, - inova->vendor, inova->device, - (unsigned long long)inova->io_addr[0], - (unsigned long long)inova->io_addr[2], inova->irq, - inova->used); - - } -} - -/****************************************************************************/ -/* return all card information for driver */ -static int pci_card_data(struct pcilst_struct *inova, - unsigned char *pci_bus, unsigned char *pci_slot, - unsigned char *pci_func, resource_size_t * io_addr, - unsigned int *irq) -{ - int i; - - if (!inova) - return -1; - *pci_bus = inova->pci_bus; - *pci_slot = inova->pci_slot; - *pci_func = inova->pci_func; - for (i = 0; i < 5; i++) - io_addr[i] = inova->io_addr[i]; - *irq = inova->irq; - return 0; -} - -/****************************************************************************/ -/* select and alloc card */ -static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id, - unsigned short device_id, - unsigned short pci_bus, - unsigned short pci_slot) -{ - struct pcilst_struct *card; - int err; - - if ((pci_bus < 1) & (pci_slot < 1)) { /* use autodetection */ - - card = find_free_pci_card_by_device(vendor_id, device_id); - if (card == NULL) { - printk(" - Unused card not found in system!\n"); - return NULL; - } - } else { - switch (find_free_pci_card_by_position(vendor_id, device_id, - pci_bus, pci_slot, - &card)) { - case 1: - printk - (" - Card not found on requested position b:s %d:%d!\n", - pci_bus, pci_slot); - return NULL; - case 2: - printk - (" - Card on requested position is used b:s %d:%d!\n", - pci_bus, pci_slot); - return NULL; - } - } - - err = pci_card_alloc(card); - if (err != 0) { - if (err > 0) - printk(" - Can't allocate card!\n"); - /* else: error already printed. */ - return NULL; - } - - return card; -} - -#endif |