2 comedi/drivers/icp_multi.h
6 Author: Anne Smorthit <anne.smorthit@sfwte.ch>
13 #include "../comedidev.h"
14 #include "comedi_pci.h"
16 /****************************************************************************/
18 struct pcilst_struct {
19 struct pcilst_struct *next;
21 struct pci_dev *pcidev;
22 unsigned short vendor;
23 unsigned short device;
24 unsigned char pci_bus;
25 unsigned char pci_slot;
26 unsigned char pci_func;
27 resource_size_t io_addr[5];
31 struct pcilst_struct *inova_devices;
32 /* ptr to root list of all Inova devices */
34 /****************************************************************************/
36 static void pci_card_list_init(unsigned short pci_vendor, char display);
37 static void pci_card_list_cleanup(unsigned short pci_vendor);
38 static struct pcilst_struct *find_free_pci_card_by_device(unsigned short
42 static int find_free_pci_card_by_position(unsigned short vendor_id,
43 unsigned short device_id,
44 unsigned short pci_bus,
45 unsigned short pci_slot,
46 struct pcilst_struct **card);
47 static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
48 unsigned short device_id,
49 unsigned short pci_bus,
50 unsigned short pci_slot);
52 static int pci_card_alloc(struct pcilst_struct *amcc);
53 static int pci_card_free(struct pcilst_struct *amcc);
54 static void pci_card_list_display(void);
55 static int pci_card_data(struct pcilst_struct *amcc,
56 unsigned char *pci_bus, unsigned char *pci_slot,
57 unsigned char *pci_func, resource_size_t * io_addr,
60 /****************************************************************************/
62 /* build list of Inova cards in this system */
63 static void pci_card_list_init(unsigned short pci_vendor, char display)
65 struct pci_dev *pcidev;
66 struct pcilst_struct *inova, *last;
72 for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
74 pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
75 if (pcidev->vendor == pci_vendor) {
76 inova = kmalloc(sizeof(*inova), GFP_KERNEL);
79 ("icp_multi: pci_card_list_init: allocation failed\n");
83 memset(inova, 0, sizeof(*inova));
85 inova->pcidev = pci_dev_get(pcidev);
89 inova_devices = inova;
93 inova->vendor = pcidev->vendor;
94 inova->device = pcidev->device;
95 inova->pci_bus = pcidev->bus->number;
96 inova->pci_slot = PCI_SLOT(pcidev->devfn);
97 inova->pci_func = PCI_FUNC(pcidev->devfn);
98 /* Note: resources may be invalid if PCI device
99 * not enabled, but they are corrected in
101 for (i = 0; i < 5; i++)
103 pci_resource_start(pcidev, i);
104 inova->irq = pcidev->irq;
109 pci_card_list_display();
112 /****************************************************************************/
113 /* free up list of amcc cards in this system */
114 static void pci_card_list_cleanup(unsigned short pci_vendor)
116 struct pcilst_struct *inova, *next;
118 for (inova = inova_devices; inova; inova = next) {
120 pci_dev_put(inova->pcidev);
124 inova_devices = NULL;
127 /****************************************************************************/
128 /* find first unused card with this device_id */
129 static struct pcilst_struct *find_free_pci_card_by_device(unsigned short
134 struct pcilst_struct *inova, *next;
136 for (inova = inova_devices; inova; inova = next) {
138 if ((!inova->used) && (inova->device == device_id)
139 && (inova->vendor == vendor_id))
147 /****************************************************************************/
148 /* find card on requested position */
149 static int find_free_pci_card_by_position(unsigned short vendor_id,
150 unsigned short device_id,
151 unsigned short pci_bus,
152 unsigned short pci_slot,
153 struct pcilst_struct **card)
155 struct pcilst_struct *inova, *next;
158 for (inova = inova_devices; inova; inova = next) {
160 if ((inova->vendor == vendor_id) && (inova->device == device_id)
161 && (inova->pci_bus == pci_bus)
162 && (inova->pci_slot == pci_slot)) {
163 if (!(inova->used)) {
165 return 0; /* ok, card is found */
167 return 2; /* card exist but is used */
172 return 1; /* no card found */
175 /****************************************************************************/
176 /* mark card as used */
177 static int pci_card_alloc(struct pcilst_struct *inova)
182 printk(" - BUG!! inova is NULL!\n");
188 if (comedi_pci_enable(inova->pcidev, "icp_multi")) {
189 printk(" - Can't enable PCI device and request regions!\n");
192 /* Resources will be accurate now. */
193 for (i = 0; i < 5; i++)
194 inova->io_addr[i] = pci_resource_start(inova->pcidev, i);
195 inova->irq = inova->pcidev->irq;
200 /****************************************************************************/
201 /* mark card as free */
202 static int pci_card_free(struct pcilst_struct *inova)
210 comedi_pci_disable(inova->pcidev);
214 /****************************************************************************/
215 /* display list of found cards */
216 static void pci_card_list_display(void)
218 struct pcilst_struct *inova, *next;
220 printk("Anne's List of pci cards\n");
221 printk("bus:slot:func vendor device io_inova io_daq irq used\n");
223 for (inova = inova_devices; inova; inova = next) {
226 ("%2d %2d %2d 0x%4x 0x%4x 0x%8llx 0x%8llx %2u %2d\n",
227 inova->pci_bus, inova->pci_slot, inova->pci_func,
228 inova->vendor, inova->device,
229 (unsigned long long)inova->io_addr[0],
230 (unsigned long long)inova->io_addr[2], inova->irq,
236 /****************************************************************************/
237 /* return all card information for driver */
238 static int pci_card_data(struct pcilst_struct *inova,
239 unsigned char *pci_bus, unsigned char *pci_slot,
240 unsigned char *pci_func, resource_size_t * io_addr,
247 *pci_bus = inova->pci_bus;
248 *pci_slot = inova->pci_slot;
249 *pci_func = inova->pci_func;
250 for (i = 0; i < 5; i++)
251 io_addr[i] = inova->io_addr[i];
256 /****************************************************************************/
257 /* select and alloc card */
258 static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
259 unsigned short device_id,
260 unsigned short pci_bus,
261 unsigned short pci_slot)
263 struct pcilst_struct *card;
266 if ((pci_bus < 1) & (pci_slot < 1)) { /* use autodetection */
268 card = find_free_pci_card_by_device(vendor_id, device_id);
270 printk(" - Unused card not found in system!\n");
274 switch (find_free_pci_card_by_position(vendor_id, device_id,
279 (" - Card not found on requested position b:s %d:%d!\n",
284 (" - Card on requested position is used b:s %d:%d!\n",
290 err = pci_card_alloc(card);
293 printk(" - Can't allocate card!\n");
294 /* else: error already printed. */