icp_multi.h revision 96341f71538c48dcec873873cabc11477cf26ae9
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; // ptr to root list of all Inova devices 32 33/****************************************************************************/ 34 35static void pci_card_list_init(unsigned short pci_vendor, char display); 36static void pci_card_list_cleanup(unsigned short pci_vendor); 37static struct pcilst_struct *find_free_pci_card_by_device(unsigned short 38 vendor_id, unsigned short device_id); 39static 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); 42static 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 46static int pci_card_alloc(struct pcilst_struct *amcc); 47static int pci_card_free(struct pcilst_struct *amcc); 48static void pci_card_list_display(void); 49static 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 */ 56static 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 */ 106static 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 */ 121static 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 */ 139static 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 */ 165static 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 */ 190static 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 */ 204static 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 */ 220static 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 */ 239static 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 279