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