]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/staging/comedi/drivers/icp_multi.h
Staging: comedi: usbdux[fast] firmware upload changes
[linux-2.6-omap-h63xx.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;    // ptr to root list of all Inova devices
32
33 /****************************************************************************/
34
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
38         vendor_id, unsigned short device_id);
39 static int find_free_pci_card_by_position(unsigned short vendor_id,
40         unsigned short device_id, unsigned short pci_bus,
41         unsigned short pci_slot, struct pcilst_struct **card);
42 static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
43         unsigned short device_id, unsigned short pci_bus,
44         unsigned short pci_slot);
45
46 static int pci_card_alloc(struct pcilst_struct *amcc);
47 static int pci_card_free(struct pcilst_struct *amcc);
48 static void pci_card_list_display(void);
49 static int pci_card_data(struct pcilst_struct *amcc,
50         unsigned char *pci_bus, unsigned char *pci_slot,
51         unsigned char *pci_func, resource_size_t * io_addr, unsigned int *irq);
52
53 /****************************************************************************/
54
55 /* build list of Inova cards in this system */
56 static void pci_card_list_init(unsigned short pci_vendor, char display)
57 {
58         struct pci_dev *pcidev;
59         struct pcilst_struct *inova, *last;
60         int i;
61
62         inova_devices = NULL;
63         last = NULL;
64
65         for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
66                 pcidev != NULL;
67                 pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
68                 if (pcidev->vendor == pci_vendor) {
69                         inova = kmalloc(sizeof(*inova), GFP_KERNEL);
70                         if (!inova) {
71                                 printk("icp_multi: pci_card_list_init: allocation failed\n");
72                                 pci_dev_put(pcidev);
73                                 break;
74                         }
75                         memset(inova, 0, sizeof(*inova));
76
77                         inova->pcidev = pci_dev_get(pcidev);
78                         if (last) {
79                                 last->next = inova;
80                         } else {
81                                 inova_devices = inova;
82                         }
83                         last = inova;
84
85                         inova->vendor = pcidev->vendor;
86                         inova->device = pcidev->device;
87                         inova->pci_bus = pcidev->bus->number;
88                         inova->pci_slot = PCI_SLOT(pcidev->devfn);
89                         inova->pci_func = PCI_FUNC(pcidev->devfn);
90                         /* Note: resources may be invalid if PCI device
91                          * not enabled, but they are corrected in
92                          * pci_card_alloc. */
93                         for (i = 0; i < 5; i++)
94                                 inova->io_addr[i] =
95                                         pci_resource_start(pcidev, i);
96                         inova->irq = pcidev->irq;
97                 }
98         }
99
100         if (display)
101                 pci_card_list_display();
102 }
103
104 /****************************************************************************/
105 /* free up list of amcc cards in this system */
106 static void pci_card_list_cleanup(unsigned short pci_vendor)
107 {
108         struct pcilst_struct *inova, *next;
109
110         for (inova = inova_devices; inova; inova = next) {
111                 next = inova->next;
112                 pci_dev_put(inova->pcidev);
113                 kfree(inova);
114         }
115
116         inova_devices = NULL;
117 }
118
119 /****************************************************************************/
120 /* find first unused card with this device_id */
121 static struct pcilst_struct *find_free_pci_card_by_device(unsigned short
122         vendor_id, unsigned short device_id)
123 {
124         struct pcilst_struct *inova, *next;
125
126         for (inova = inova_devices; inova; inova = next) {
127                 next = inova->next;
128                 if ((!inova->used) && (inova->device == device_id)
129                         && (inova->vendor == vendor_id))
130                         return inova;
131
132         }
133
134         return NULL;
135 }
136
137 /****************************************************************************/
138 /* find card on requested position */
139 static int find_free_pci_card_by_position(unsigned short vendor_id,
140         unsigned short device_id, unsigned short pci_bus,
141         unsigned short pci_slot, struct pcilst_struct **card)
142 {
143         struct pcilst_struct *inova, *next;
144
145         *card = NULL;
146         for (inova = inova_devices; inova; inova = next) {
147                 next = inova->next;
148                 if ((inova->vendor == vendor_id) && (inova->device == device_id)
149                         && (inova->pci_bus == pci_bus)
150                         && (inova->pci_slot == pci_slot)) {
151                         if (!(inova->used)) {
152                                 *card = inova;
153                                 return 0;       // ok, card is found
154                         } else {
155                                 return 2;       // card exist but is used
156                         }
157                 }
158         }
159
160         return 1;               // no card found
161 }
162
163 /****************************************************************************/
164 /* mark card as used */
165 static int pci_card_alloc(struct pcilst_struct *inova)
166 {
167         int i;
168
169         if (!inova) {
170                 rt_printk(" - BUG!! inova is NULL!\n");
171                 return -1;
172         }
173
174         if (inova->used)
175                 return 1;
176         if (comedi_pci_enable(inova->pcidev, "icp_multi")) {
177                 rt_printk(" - Can't enable PCI device and request regions!\n");
178                 return -1;
179         }
180         /* Resources will be accurate now. */
181         for (i = 0; i < 5; i++)
182                 inova->io_addr[i] = pci_resource_start(inova->pcidev, i);
183         inova->irq = inova->pcidev->irq;
184         inova->used = 1;
185         return 0;
186 }
187
188 /****************************************************************************/
189 /* mark card as free */
190 static int pci_card_free(struct pcilst_struct *inova)
191 {
192         if (!inova)
193                 return -1;
194
195         if (!inova->used)
196                 return 1;
197         inova->used = 0;
198         comedi_pci_disable(inova->pcidev);
199         return 0;
200 }
201
202 /****************************************************************************/
203 /* display list of found cards */
204 static void pci_card_list_display(void)
205 {
206         struct pcilst_struct *inova, *next;
207
208         printk("Anne's List of pci cards\n");
209         printk("bus:slot:func vendor device io_inova io_daq irq used\n");
210
211         for (inova = inova_devices; inova; inova = next) {
212                 next = inova->next;
213                 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);
214
215         }
216 }
217
218 /****************************************************************************/
219 /* return all card information for driver */
220 static int pci_card_data(struct pcilst_struct *inova,
221         unsigned char *pci_bus, unsigned char *pci_slot,
222         unsigned char *pci_func, resource_size_t * io_addr, unsigned int *irq)
223 {
224         int i;
225
226         if (!inova)
227                 return -1;
228         *pci_bus = inova->pci_bus;
229         *pci_slot = inova->pci_slot;
230         *pci_func = inova->pci_func;
231         for (i = 0; i < 5; i++)
232                 io_addr[i] = inova->io_addr[i];
233         *irq = inova->irq;
234         return 0;
235 }
236
237 /****************************************************************************/
238 /* select and alloc card */
239 static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
240         unsigned short device_id, unsigned short pci_bus,
241         unsigned short pci_slot)
242 {
243         struct pcilst_struct *card;
244         int err;
245
246         if ((pci_bus < 1) & (pci_slot < 1)) {   // use autodetection
247                 if ((card = find_free_pci_card_by_device(vendor_id,
248                                         device_id)) == NULL) {
249                         rt_printk(" - Unused card not found in system!\n");
250                         return NULL;
251                 }
252         } else {
253                 switch (find_free_pci_card_by_position(vendor_id, device_id,
254                                 pci_bus, pci_slot, &card)) {
255                 case 1:
256                         rt_printk
257                                 (" - Card not found on requested position b:s %d:%d!\n",
258                                 pci_bus, pci_slot);
259                         return NULL;
260                 case 2:
261                         rt_printk
262                                 (" - Card on requested position is used b:s %d:%d!\n",
263                                 pci_bus, pci_slot);
264                         return NULL;
265                 }
266         }
267
268         if ((err = pci_card_alloc(card)) != 0) {
269                 if (err > 0)
270                         rt_printk(" - Can't allocate card!\n");
271                 /* else: error already printed. */
272                 return NULL;
273         }
274
275         return card;
276 }
277
278 #endif