// plx1.h for getting the 2. I/O address of a PLX pci card. // // Tested on i386 Linux (SuSE 7.1), SuSE 9.3, should work on PPC and alpha. // // The function get_second_plx_pci_device_baseaddress(dev_id) returns the second I/O address // of the plx card with the device id dev_id if the return value is positiv and returns // the (negative) error number if the return value is negetiv. // This function can be use for kernel space programs and also for user space programs. // // With the base address the (32 bit) I/O can be done with // in_value=inw(base+address_on_card) and outl(value,base+address_on_card). // // vendor tables, device id tables etc. can be found at http://www.yourvote.com/pci /* 2001 Rolf Freitag, rolf.freitag at email.de This Program is free software; you can redistribute it and/od modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at yout option) any later version. This Program is distributed in the hope that it will be useful, but WITHOUT ANY WARRENTY; without even the implied warrenty of MERCHANTABILITY of FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this Program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef PLX_VENDOR_ID # undef PLX_VENDOR_ID #endif #define PLX_VENDOR_ID 0x10b5 // Vendor ID from PLX #ifdef __KERNEL__ // usual file functions like fopen are not available in kernel space #include // CONFIG_PCI #include // pcibios_find_device .. #include // ENODEV ... #include // printk() #ifdef CONFIG_PCI // if PCI-BIOS can be found long long int get_second_io_plx_pci_device_baseaddress (unsigned short dev_id) { const unsigned short vendor = PLX_VENDOR_ID; //unsigned char bus = 0; // number of the PCI bus //unsigned char dev_fn = 0; // device function //unsigned short index = 0; // index; the first card has 0 //unsigned short int i = 0; // index for counting int result = PCIBIOS_SUCCESSFUL; // for result value from pcibios_find_device unsigned int count = 0; // counter for the plx cards unsigned int base = 0xffffffff; // base address of the first plx card struct pci_dev *pptr = kmalloc (sizeof (*pptr), GFP_KERNEL); // search the card(s) /* for (i = 0; i < 255 && result == PCIBIOS_SUCCESSFUL; i++) { index = i; result = pcibios_find_device (vendor, dev_id, index, &bus, &dev_fn); if (result == PCIBIOS_SUCCESSFUL) count++; } */ if (pci_find_device (vendor, dev_id, pptr)) count = 1; // get the base address of the card if (count > 1) printk (KERN_CRIT "Waring: more than one card with vendor 0x%hx and dev_id 0x%hx is present.\n", vendor, dev_id); if (count >= 1) { // pcibios_read_config_dword (bus, dev_fn, PCI_BASE_ADDRESS_0, &base); pci_read_config_dword (pptr, PCI_BASE_ADDRESS_2, &base); return ((long long int) (base)); // return the second base (I/O) address } else { printk (KERN_CRIT "No card with vendor 0x%hx and dev_id 0x%hx could be found, ", vendor, dev_id); printk (KERN_CRIT "pci error: %d (see /usr/include/linux/pci.h).\n", result); return ((long long int) -ENODEV); // no device } } #endif // CONFIG_PCI #else // user space, pci functions are kernel space functions and not available here #include #include #include #include // ENODEV ... long long int get_second_io_plx_pci_device_baseaddress (unsigned short dev_id) // This function searches in /proc/pci for the plx card with the device id dev_id. { const unsigned short vendor = PLX_VENDOR_ID; unsigned int i1 = 0, i2 = 0; unsigned int count = 0; // counter for the plx cards unsigned int base = 0xffffffff; // base address of the first plx card static FILE *fp = NULL; // input file pointer for /proc/pci char line[255] = ""; unsigned short v = 0, d = 0; // for sscanf char s1[255] = "", s2[255] = "", s3[255] = "", s4[255] = "", s5[255] = "", s6[255] = ""; // search the first card fp = fopen ("/proc/pci", "r"); while (fgets (line, 255, fp) != NULL) // line reading { if (sscanf (line, " %s %s %s %s %hx:%hx %s %s", s1, s2, s3, s4, &v, &d, s5, s6) == 8 && v == vendor && d == dev_id) { // get 1. I/O base while ((fgets (line, 255, fp) != NULL) && (sscanf (line, " %s %s 0x%x [0x%x].", s1, s2, &i1, &i2) != 4)); // get 2. I/O base while ((fgets (line, 255, fp) != NULL) && (sscanf (line, " %s %s 0x%x [0x%x].", s1, s2, &i1, &i2) != 4)); count++; break; } } base = i1; if (count == 0) { fprintf (stderr, "ERROR: PCI error: no card with vendor %hx and dev_id %hx found.\n", vendor, dev_id); return ((long long int) -ENODEV); // no device } else // count the cards { count = 0; rewind (fp); while (fgets (line, 255, fp) != NULL) // line reading if (sscanf (line, " %s id=%hx. %s id=%hx.", s1, &v, s2, &d) == 4 && v == vendor && d == dev_id) count++; fclose (fp); if (count > 1) fprintf (stderr, "Waring: more than one card with vendor %hx and dev_id %hx is present.\n", vendor, dev_id); } return ((long long int) base); } #endif // else from ifdef __KERNEL__ #undef PLX_VENDOR_ID