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
39 vendor_id
, unsigned short device_id
);
40 static int find_free_pci_card_by_position(unsigned short vendor_id
,
41 unsigned short device_id
, unsigned short pci_bus
,
42 unsigned short pci_slot
, struct pcilst_struct
**card
);
43 static struct pcilst_struct
*select_and_alloc_pci_card(unsigned short vendor_id
,
44 unsigned short device_id
, unsigned short pci_bus
,
45 unsigned short pci_slot
);
47 static int pci_card_alloc(struct pcilst_struct
*amcc
);
48 static int pci_card_free(struct pcilst_struct
*amcc
);
49 static void pci_card_list_display(void);
50 static int pci_card_data(struct pcilst_struct
*amcc
,
51 unsigned char *pci_bus
, unsigned char *pci_slot
,
52 unsigned char *pci_func
, resource_size_t
* io_addr
, unsigned int *irq
);
54 /****************************************************************************/
56 /* build list of Inova cards in this system */
57 static void pci_card_list_init(unsigned short pci_vendor
, char display
)
59 struct pci_dev
*pcidev
;
60 struct pcilst_struct
*inova
, *last
;
66 for (pcidev
= pci_get_device(PCI_ANY_ID
, PCI_ANY_ID
, NULL
);
68 pcidev
= pci_get_device(PCI_ANY_ID
, PCI_ANY_ID
, pcidev
)) {
69 if (pcidev
->vendor
== pci_vendor
) {
70 inova
= kmalloc(sizeof(*inova
), GFP_KERNEL
);
72 printk("icp_multi: pci_card_list_init: allocation failed\n");
76 memset(inova
, 0, sizeof(*inova
));
78 inova
->pcidev
= pci_dev_get(pcidev
);
82 inova_devices
= inova
;
86 inova
->vendor
= pcidev
->vendor
;
87 inova
->device
= pcidev
->device
;
88 inova
->pci_bus
= pcidev
->bus
->number
;
89 inova
->pci_slot
= PCI_SLOT(pcidev
->devfn
);
90 inova
->pci_func
= PCI_FUNC(pcidev
->devfn
);
91 /* Note: resources may be invalid if PCI device
92 * not enabled, but they are corrected in
94 for (i
= 0; i
< 5; i
++)
96 pci_resource_start(pcidev
, i
);
97 inova
->irq
= pcidev
->irq
;
102 pci_card_list_display();
105 /****************************************************************************/
106 /* free up list of amcc cards in this system */
107 static void pci_card_list_cleanup(unsigned short pci_vendor
)
109 struct pcilst_struct
*inova
, *next
;
111 for (inova
= inova_devices
; inova
; inova
= next
) {
113 pci_dev_put(inova
->pcidev
);
117 inova_devices
= NULL
;
120 /****************************************************************************/
121 /* find first unused card with this device_id */
122 static struct pcilst_struct
*find_free_pci_card_by_device(unsigned short
123 vendor_id
, unsigned short device_id
)
125 struct pcilst_struct
*inova
, *next
;
127 for (inova
= inova_devices
; inova
; inova
= next
) {
129 if ((!inova
->used
) && (inova
->device
== device_id
)
130 && (inova
->vendor
== vendor_id
))
138 /****************************************************************************/
139 /* find card on requested position */
140 static int find_free_pci_card_by_position(unsigned short vendor_id
,
141 unsigned short device_id
, unsigned short pci_bus
,
142 unsigned short pci_slot
, struct pcilst_struct
**card
)
144 struct pcilst_struct
*inova
, *next
;
147 for (inova
= inova_devices
; inova
; inova
= next
) {
149 if ((inova
->vendor
== vendor_id
) && (inova
->device
== device_id
)
150 && (inova
->pci_bus
== pci_bus
)
151 && (inova
->pci_slot
== pci_slot
)) {
152 if (!(inova
->used
)) {
154 return 0; /* ok, card is found */
156 return 2; /* card exist but is used */
161 return 1; /* no card found */
164 /****************************************************************************/
165 /* mark card as used */
166 static int pci_card_alloc(struct pcilst_struct
*inova
)
171 printk(" - BUG!! inova is NULL!\n");
177 if (comedi_pci_enable(inova
->pcidev
, "icp_multi")) {
178 printk(" - Can't enable PCI device and request regions!\n");
181 /* Resources will be accurate now. */
182 for (i
= 0; i
< 5; i
++)
183 inova
->io_addr
[i
] = pci_resource_start(inova
->pcidev
, i
);
184 inova
->irq
= inova
->pcidev
->irq
;
189 /****************************************************************************/
190 /* mark card as free */
191 static int pci_card_free(struct pcilst_struct
*inova
)
199 comedi_pci_disable(inova
->pcidev
);
203 /****************************************************************************/
204 /* display list of found cards */
205 static void pci_card_list_display(void)
207 struct pcilst_struct
*inova
, *next
;
209 printk("Anne's List of pci cards\n");
210 printk("bus:slot:func vendor device io_inova io_daq irq used\n");
212 for (inova
= inova_devices
; inova
; inova
= next
) {
214 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
);
219 /****************************************************************************/
220 /* return all card information for driver */
221 static int pci_card_data(struct pcilst_struct
*inova
,
222 unsigned char *pci_bus
, unsigned char *pci_slot
,
223 unsigned char *pci_func
, resource_size_t
* io_addr
, unsigned int *irq
)
229 *pci_bus
= inova
->pci_bus
;
230 *pci_slot
= inova
->pci_slot
;
231 *pci_func
= inova
->pci_func
;
232 for (i
= 0; i
< 5; i
++)
233 io_addr
[i
] = inova
->io_addr
[i
];
238 /****************************************************************************/
239 /* select and alloc card */
240 static struct pcilst_struct
*select_and_alloc_pci_card(unsigned short vendor_id
,
241 unsigned short device_id
, unsigned short pci_bus
,
242 unsigned short pci_slot
)
244 struct pcilst_struct
*card
;
247 if ((pci_bus
< 1) & (pci_slot
< 1)) { /* use autodetection */
249 card
= find_free_pci_card_by_device(vendor_id
, device_id
);
251 printk(" - Unused card not found in system!\n");
255 switch (find_free_pci_card_by_position(vendor_id
, device_id
,
256 pci_bus
, pci_slot
, &card
)) {
259 (" - Card not found on requested position b:s %d:%d!\n",
264 (" - Card on requested position is used b:s %d:%d!\n",
270 err
= pci_card_alloc(card
);
273 printk(" - Can't allocate card!\n");
274 /* else: error already printed. */