Staging: comedi: Give the addi_apci_* drivers different driver names
[pandora-kernel.git] / drivers / staging / comedi / drivers / icp_multi.h
1 /*
2     comedi/drivers/icp_multi.h
3
4     Stuff for ICP Multi
5
6     Author: Anne Smorthit <anne.smorthit@sfwte.ch>
7
8 */
9
10 #ifndef _ICP_MULTI_H_
11 #define _ICP_MULTI_H_
12
13 #include "../comedidev.h"
14 #include "comedi_pci.h"
15
16 /****************************************************************************/
17
18 struct pcilst_struct {
19         struct pcilst_struct *next;
20         int used;
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];
28         unsigned int irq;
29 };
30
31 struct pcilst_struct *inova_devices;
32 /* ptr to root list of all Inova devices */
33
34 /****************************************************************************/
35
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,
40                                                           unsigned short
41                                                           device_id);
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);
51
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,
58                          unsigned int *irq);
59
60 /****************************************************************************/
61
62 /* build list of Inova cards in this system */
63 static void pci_card_list_init(unsigned short pci_vendor, char display)
64 {
65         struct pci_dev *pcidev;
66         struct pcilst_struct *inova, *last;
67         int i;
68
69         inova_devices = NULL;
70         last = NULL;
71
72         for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
73              pcidev != NULL;
74              pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
75                 if (pcidev->vendor == pci_vendor) {
76                         inova = kzalloc(sizeof(*inova), GFP_KERNEL);
77                         if (!inova) {
78                                 printk
79                                     ("icp_multi: pci_card_list_init: allocation failed\n");
80                                 pci_dev_put(pcidev);
81                                 break;
82                         }
83
84                         inova->pcidev = pci_dev_get(pcidev);
85                         if (last) {
86                                 last->next = inova;
87                         } else {
88                                 inova_devices = inova;
89                         }
90                         last = inova;
91
92                         inova->vendor = pcidev->vendor;
93                         inova->device = pcidev->device;
94                         inova->pci_bus = pcidev->bus->number;
95                         inova->pci_slot = PCI_SLOT(pcidev->devfn);
96                         inova->pci_func = PCI_FUNC(pcidev->devfn);
97                         /* Note: resources may be invalid if PCI device
98                          * not enabled, but they are corrected in
99                          * pci_card_alloc. */
100                         for (i = 0; i < 5; i++)
101                                 inova->io_addr[i] =
102                                     pci_resource_start(pcidev, i);
103                         inova->irq = pcidev->irq;
104                 }
105         }
106
107         if (display)
108                 pci_card_list_display();
109 }
110
111 /****************************************************************************/
112 /* free up list of amcc cards in this system */
113 static void pci_card_list_cleanup(unsigned short pci_vendor)
114 {
115         struct pcilst_struct *inova, *next;
116
117         for (inova = inova_devices; inova; inova = next) {
118                 next = inova->next;
119                 pci_dev_put(inova->pcidev);
120                 kfree(inova);
121         }
122
123         inova_devices = NULL;
124 }
125
126 /****************************************************************************/
127 /* find first unused card with this device_id */
128 static struct pcilst_struct *find_free_pci_card_by_device(unsigned short
129                                                           vendor_id,
130                                                           unsigned short
131                                                           device_id)
132 {
133         struct pcilst_struct *inova, *next;
134
135         for (inova = inova_devices; inova; inova = next) {
136                 next = inova->next;
137                 if ((!inova->used) && (inova->device == device_id)
138                     && (inova->vendor == vendor_id))
139                         return inova;
140
141         }
142
143         return NULL;
144 }
145
146 /****************************************************************************/
147 /* find card on requested position */
148 static int find_free_pci_card_by_position(unsigned short vendor_id,
149                                           unsigned short device_id,
150                                           unsigned short pci_bus,
151                                           unsigned short pci_slot,
152                                           struct pcilst_struct **card)
153 {
154         struct pcilst_struct *inova, *next;
155
156         *card = NULL;
157         for (inova = inova_devices; inova; inova = next) {
158                 next = inova->next;
159                 if ((inova->vendor == vendor_id) && (inova->device == device_id)
160                     && (inova->pci_bus == pci_bus)
161                     && (inova->pci_slot == pci_slot)) {
162                         if (!(inova->used)) {
163                                 *card = inova;
164                                 return 0;       /* ok, card is found */
165                         } else {
166                                 return 2;       /* card exist but is used */
167                         }
168                 }
169         }
170
171         return 1;               /* no card found */
172 }
173
174 /****************************************************************************/
175 /* mark card as used */
176 static int pci_card_alloc(struct pcilst_struct *inova)
177 {
178         int i;
179
180         if (!inova) {
181                 printk(" - BUG!! inova is NULL!\n");
182                 return -1;
183         }
184
185         if (inova->used)
186                 return 1;
187         if (comedi_pci_enable(inova->pcidev, "icp_multi")) {
188                 printk(" - Can't enable PCI device and request regions!\n");
189                 return -1;
190         }
191         /* Resources will be accurate now. */
192         for (i = 0; i < 5; i++)
193                 inova->io_addr[i] = pci_resource_start(inova->pcidev, i);
194         inova->irq = inova->pcidev->irq;
195         inova->used = 1;
196         return 0;
197 }
198
199 /****************************************************************************/
200 /* mark card as free */
201 static int pci_card_free(struct pcilst_struct *inova)
202 {
203         if (!inova)
204                 return -1;
205
206         if (!inova->used)
207                 return 1;
208         inova->used = 0;
209         comedi_pci_disable(inova->pcidev);
210         return 0;
211 }
212
213 /****************************************************************************/
214 /* display list of found cards */
215 static void pci_card_list_display(void)
216 {
217         struct pcilst_struct *inova, *next;
218
219         printk("Anne's List of pci cards\n");
220         printk("bus:slot:func vendor device io_inova io_daq irq used\n");
221
222         for (inova = inova_devices; inova; inova = next) {
223                 next = inova->next;
224                 printk
225                     ("%2d   %2d   %2d  0x%4x 0x%4x   0x%8llx 0x%8llx  %2u  %2d\n",
226                      inova->pci_bus, inova->pci_slot, inova->pci_func,
227                      inova->vendor, inova->device,
228                      (unsigned long long)inova->io_addr[0],
229                      (unsigned long long)inova->io_addr[2], inova->irq,
230                      inova->used);
231
232         }
233 }
234
235 /****************************************************************************/
236 /* return all card information for driver */
237 static int pci_card_data(struct pcilst_struct *inova,
238                          unsigned char *pci_bus, unsigned char *pci_slot,
239                          unsigned char *pci_func, resource_size_t * io_addr,
240                          unsigned int *irq)
241 {
242         int i;
243
244         if (!inova)
245                 return -1;
246         *pci_bus = inova->pci_bus;
247         *pci_slot = inova->pci_slot;
248         *pci_func = inova->pci_func;
249         for (i = 0; i < 5; i++)
250                 io_addr[i] = inova->io_addr[i];
251         *irq = inova->irq;
252         return 0;
253 }
254
255 /****************************************************************************/
256 /* select and alloc card */
257 static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
258                                                        unsigned short device_id,
259                                                        unsigned short pci_bus,
260                                                        unsigned short pci_slot)
261 {
262         struct pcilst_struct *card;
263         int err;
264
265         if ((pci_bus < 1) & (pci_slot < 1)) {   /* use autodetection */
266
267                 card = find_free_pci_card_by_device(vendor_id, device_id);
268                 if (card == NULL) {
269                         printk(" - Unused card not found in system!\n");
270                         return NULL;
271                 }
272         } else {
273                 switch (find_free_pci_card_by_position(vendor_id, device_id,
274                                                        pci_bus, pci_slot,
275                                                        &card)) {
276                 case 1:
277                         printk
278                             (" - Card not found on requested position b:s %d:%d!\n",
279                              pci_bus, pci_slot);
280                         return NULL;
281                 case 2:
282                         printk
283                             (" - Card on requested position is used b:s %d:%d!\n",
284                              pci_bus, pci_slot);
285                         return NULL;
286                 }
287         }
288
289         err = pci_card_alloc(card);
290         if (err != 0) {
291                 if (err > 0)
292                         printk(" - Can't allocate card!\n");
293                 /* else: error already printed. */
294                 return NULL;
295         }
296
297         return card;
298 }
299
300 #endif