2 comedi/drivers/icp_multi.h
6 Author: Anne Smorthit <anne.smorthit@sfwte.ch>
13 #include "../comedidev.h"
15 /****************************************************************************/
17 struct pcilst_struct {
18 struct pcilst_struct *next;
20 struct pci_dev *pcidev;
21 unsigned short vendor;
22 unsigned short device;
23 unsigned char pci_bus;
24 unsigned char pci_slot;
25 unsigned char pci_func;
26 resource_size_t io_addr[5];
30 struct pcilst_struct *inova_devices;
31 /* ptr to root list of all Inova devices */
33 /****************************************************************************/
35 static void pci_card_list_init(unsigned short pci_vendor, char display);
36 static void pci_card_list_cleanup(unsigned short pci_vendor);
37 static struct pcilst_struct *find_free_pci_card_by_device(unsigned short
41 static int find_free_pci_card_by_position(unsigned short vendor_id,
42 unsigned short device_id,
43 unsigned short pci_bus,
44 unsigned short pci_slot,
45 struct pcilst_struct **card);
46 static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
47 unsigned short device_id,
48 unsigned short pci_bus,
49 unsigned short pci_slot);
51 static int pci_card_alloc(struct pcilst_struct *amcc);
52 static int pci_card_free(struct pcilst_struct *amcc);
53 static void pci_card_list_display(void);
54 static int pci_card_data(struct pcilst_struct *amcc,
55 unsigned char *pci_bus, unsigned char *pci_slot,
56 unsigned char *pci_func, resource_size_t * io_addr,
59 /****************************************************************************/
61 /* build list of Inova cards in this system */
62 static void pci_card_list_init(unsigned short pci_vendor, char display)
64 struct pci_dev *pcidev = NULL;
65 struct pcilst_struct *inova, *last;
71 for_each_pci_dev(pcidev) {
72 if (pcidev->vendor == pci_vendor) {
73 inova = kzalloc(sizeof(*inova), GFP_KERNEL);
76 ("icp_multi: pci_card_list_init: allocation failed\n");
81 inova->pcidev = pci_dev_get(pcidev);
85 inova_devices = inova;
89 inova->vendor = pcidev->vendor;
90 inova->device = pcidev->device;
91 inova->pci_bus = pcidev->bus->number;
92 inova->pci_slot = PCI_SLOT(pcidev->devfn);
93 inova->pci_func = PCI_FUNC(pcidev->devfn);
94 /* Note: resources may be invalid if PCI device
95 * not enabled, but they are corrected in
97 for (i = 0; i < 5; i++)
99 pci_resource_start(pcidev, i);
100 inova->irq = pcidev->irq;
105 pci_card_list_display();
108 /****************************************************************************/
109 /* free up list of amcc cards in this system */
110 static void pci_card_list_cleanup(unsigned short pci_vendor)
112 struct pcilst_struct *inova, *next;
114 for (inova = inova_devices; inova; inova = next) {
116 pci_dev_put(inova->pcidev);
120 inova_devices = NULL;
123 /****************************************************************************/
124 /* find first unused card with this device_id */
125 static struct pcilst_struct *find_free_pci_card_by_device(unsigned short
130 struct pcilst_struct *inova, *next;
132 for (inova = inova_devices; inova; inova = next) {
134 if ((!inova->used) && (inova->device == device_id)
135 && (inova->vendor == vendor_id))
143 /****************************************************************************/
144 /* find card on requested position */
145 static int find_free_pci_card_by_position(unsigned short vendor_id,
146 unsigned short device_id,
147 unsigned short pci_bus,
148 unsigned short pci_slot,
149 struct pcilst_struct **card)
151 struct pcilst_struct *inova, *next;
154 for (inova = inova_devices; inova; inova = next) {
156 if ((inova->vendor == vendor_id) && (inova->device == device_id)
157 && (inova->pci_bus == pci_bus)
158 && (inova->pci_slot == pci_slot)) {
159 if (!(inova->used)) {
161 return 0; /* ok, card is found */
163 return 2; /* card exist but is used */
168 return 1; /* no card found */
171 /****************************************************************************/
172 /* mark card as used */
173 static int pci_card_alloc(struct pcilst_struct *inova)
178 printk(" - BUG!! inova is NULL!\n");
184 if (comedi_pci_enable(inova->pcidev, "icp_multi")) {
185 printk(" - Can't enable PCI device and request regions!\n");
188 /* Resources will be accurate now. */
189 for (i = 0; i < 5; i++)
190 inova->io_addr[i] = pci_resource_start(inova->pcidev, i);
191 inova->irq = inova->pcidev->irq;
196 /****************************************************************************/
197 /* mark card as free */
198 static int pci_card_free(struct pcilst_struct *inova)
206 comedi_pci_disable(inova->pcidev);
210 /****************************************************************************/
211 /* display list of found cards */
212 static void pci_card_list_display(void)
214 struct pcilst_struct *inova, *next;
216 printk("Anne's List of pci cards\n");
217 printk("bus:slot:func vendor device io_inova io_daq irq used\n");
219 for (inova = inova_devices; inova; inova = next) {
222 ("%2d %2d %2d 0x%4x 0x%4x 0x%8llx 0x%8llx %2u %2d\n",
223 inova->pci_bus, inova->pci_slot, inova->pci_func,
224 inova->vendor, inova->device,
225 (unsigned long long)inova->io_addr[0],
226 (unsigned long long)inova->io_addr[2], inova->irq,
232 /****************************************************************************/
233 /* return all card information for driver */
234 static int pci_card_data(struct pcilst_struct *inova,
235 unsigned char *pci_bus, unsigned char *pci_slot,
236 unsigned char *pci_func, resource_size_t * io_addr,
243 *pci_bus = inova->pci_bus;
244 *pci_slot = inova->pci_slot;
245 *pci_func = inova->pci_func;
246 for (i = 0; i < 5; i++)
247 io_addr[i] = inova->io_addr[i];
252 /****************************************************************************/
253 /* select and alloc card */
254 static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
255 unsigned short device_id,
256 unsigned short pci_bus,
257 unsigned short pci_slot)
259 struct pcilst_struct *card;
262 if ((pci_bus < 1) & (pci_slot < 1)) { /* use autodetection */
264 card = find_free_pci_card_by_device(vendor_id, device_id);
266 printk(" - Unused card not found in system!\n");
270 switch (find_free_pci_card_by_position(vendor_id, device_id,
275 (" - Card not found on requested position b:s %d:%d!\n",
280 (" - Card on requested position is used b:s %d:%d!\n",
286 err = pci_card_alloc(card);
289 printk(" - Can't allocate card!\n");
290 /* else: error already printed. */