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