icp_multi.h revision 7a6cb0d5497418599d2125b670926b75e673861c
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 = 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 */ 113static 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 */ 128static 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 */ 148static 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 */ 176static 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 */ 201static 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 */ 215static 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 */ 237static 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 */ 257static 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 301