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