Annotation of embedaddon/pciutils/lib/i386-ports.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *     The PCI Library -- Direct Configuration access via i386 Ports
                      3:  *
                      4:  *     Copyright (c) 1997--2006 Martin Mares <mj@ucw.cz>
                      5:  *
                      6:  *     Can be freely distributed and used under the terms of the GNU GPL.
                      7:  */
                      8: 
                      9: #define _GNU_SOURCE
                     10: 
                     11: #include "internal.h"
                     12: 
                     13: #include <unistd.h>
                     14: 
                     15: #if defined(PCI_OS_LINUX)
                     16: #include "i386-io-linux.h"
                     17: #elif defined(PCI_OS_GNU)
                     18: #include "i386-io-hurd.h"
                     19: #elif defined(PCI_OS_SUNOS)
                     20: #include "i386-io-sunos.h"
                     21: #elif defined(PCI_OS_WINDOWS)
                     22: #include "i386-io-windows.h"
                     23: #elif defined(PCI_OS_CYGWIN)
                     24: #include "i386-io-cygwin.h"
                     25: #elif defined(PCI_OS_HAIKU)
                     26: #include "i386-io-haiku.h"
                     27: #elif defined(PCI_OS_BEOS)
                     28: #include "i386-io-beos.h"
                     29: #else
                     30: #error Do not know how to access I/O ports on this OS.
                     31: #endif
                     32: 
                     33: static int conf12_io_enabled = -1;             /* -1=haven't tried, 0=failed, 1=succeeded */
                     34: 
                     35: static int
                     36: conf12_setup_io(struct pci_access *a)
                     37: {
                     38:   if (conf12_io_enabled < 0)
                     39:     conf12_io_enabled = intel_setup_io(a);
                     40:   return conf12_io_enabled;
                     41: }
                     42: 
                     43: static void
                     44: conf12_init(struct pci_access *a)
                     45: {
                     46:   if (!conf12_setup_io(a))
                     47:     a->error("No permission to access I/O ports (you probably have to be root).");
                     48: }
                     49: 
                     50: static void
                     51: conf12_cleanup(struct pci_access *a UNUSED)
                     52: {
                     53:   if (conf12_io_enabled > 0)
                     54:     conf12_io_enabled = intel_cleanup_io(a);
                     55: }
                     56: 
                     57: /*
                     58:  * Before we decide to use direct hardware access mechanisms, we try to do some
                     59:  * trivial checks to ensure it at least _seems_ to be working -- we just test
                     60:  * whether bus 00 contains a host bridge (this is similar to checking
                     61:  * techniques used in XFree86, but ours should be more reliable since we
                     62:  * attempt to make use of direct access hints provided by the PCI BIOS).
                     63:  *
                     64:  * This should be close to trivial, but it isn't, because there are buggy
                     65:  * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
                     66:  */
                     67: 
                     68: static int
                     69: intel_sanity_check(struct pci_access *a, struct pci_methods *m)
                     70: {
                     71:   struct pci_dev d;
                     72: 
                     73:   a->debug("...sanity check");
                     74:   d.bus = 0;
                     75:   d.func = 0;
                     76:   for (d.dev = 0; d.dev < 32; d.dev++)
                     77:     {
                     78:       u16 class, vendor;
                     79:       if (m->read(&d, PCI_CLASS_DEVICE, (byte *) &class, sizeof(class)) &&
                     80:          (class == cpu_to_le16(PCI_CLASS_BRIDGE_HOST) || class == cpu_to_le16(PCI_CLASS_DISPLAY_VGA)) ||
                     81:          m->read(&d, PCI_VENDOR_ID, (byte *) &vendor, sizeof(vendor)) &&
                     82:          (vendor == cpu_to_le16(PCI_VENDOR_ID_INTEL) || vendor == cpu_to_le16(PCI_VENDOR_ID_COMPAQ)))
                     83:        {
                     84:          a->debug("...outside the Asylum at 0/%02x/0", d.dev);
                     85:          return 1;
                     86:        }
                     87:     }
                     88:   a->debug("...insane");
                     89:   return 0;
                     90: }
                     91: 
                     92: /*
                     93:  *     Configuration type 1
                     94:  */
                     95: 
                     96: #define CONFIG_CMD(bus, device_fn, where)   (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
                     97: 
                     98: static int
                     99: conf1_detect(struct pci_access *a)
                    100: {
                    101:   unsigned int tmp;
                    102:   int res = 0;
                    103: 
                    104:   if (!conf12_setup_io(a))
                    105:     {
                    106:       a->debug("...no I/O permission");
                    107:       return 0;
                    108:     }
                    109:   outb (0x01, 0xCFB);
                    110:   tmp = inl (0xCF8);
                    111:   outl (0x80000000, 0xCF8);
                    112:   if (inl (0xCF8) == 0x80000000)
                    113:     res = 1;
                    114:   outl (tmp, 0xCF8);
                    115:   if (res)
                    116:     res = intel_sanity_check(a, &pm_intel_conf1);
                    117:   return res;
                    118: }
                    119: 
                    120: static int
                    121: conf1_read(struct pci_dev *d, int pos, byte *buf, int len)
                    122: {
                    123:   int addr = 0xcfc + (pos&3);
                    124: 
                    125:   if (pos >= 256)
                    126:     return 0;
                    127: 
                    128:   outl(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos&~3), 0xcf8);
                    129: 
                    130:   switch (len)
                    131:     {
                    132:     case 1:
                    133:       buf[0] = inb(addr);
                    134:       break;
                    135:     case 2:
                    136:       ((u16 *) buf)[0] = cpu_to_le16(inw(addr));
                    137:       break;
                    138:     case 4:
                    139:       ((u32 *) buf)[0] = cpu_to_le32(inl(addr));
                    140:       break;
                    141:     default:
                    142:       return pci_generic_block_read(d, pos, buf, len);
                    143:     }
                    144:   return 1;
                    145: }
                    146: 
                    147: static int
                    148: conf1_write(struct pci_dev *d, int pos, byte *buf, int len)
                    149: {
                    150:   int addr = 0xcfc + (pos&3);
                    151: 
                    152:   if (pos >= 256)
                    153:     return 0;
                    154: 
                    155:   outl(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos&~3), 0xcf8);
                    156: 
                    157:   switch (len)
                    158:     {
                    159:     case 1:
                    160:       outb(buf[0], addr);
                    161:       break;
                    162:     case 2:
                    163:       outw(le16_to_cpu(((u16 *) buf)[0]), addr);
                    164:       break;
                    165:     case 4:
                    166:       outl(le32_to_cpu(((u32 *) buf)[0]), addr);
                    167:       break;
                    168:     default:
                    169:       return pci_generic_block_write(d, pos, buf, len);
                    170:     }
                    171:   return 1;
                    172: }
                    173: 
                    174: /*
                    175:  *     Configuration type 2. Obsolete and brain-damaged, but existing.
                    176:  */
                    177: 
                    178: static int
                    179: conf2_detect(struct pci_access *a)
                    180: {
                    181:   if (!conf12_setup_io(a))
                    182:     {
                    183:       a->debug("...no I/O permission");
                    184:       return 0;
                    185:     }
                    186: 
                    187:   /* This is ugly and tends to produce false positives. Beware. */
                    188: 
                    189:   outb(0x00, 0xCFB);
                    190:   outb(0x00, 0xCF8);
                    191:   outb(0x00, 0xCFA);
                    192:   if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00)
                    193:     return intel_sanity_check(a, &pm_intel_conf2);
                    194:   else
                    195:     return 0;
                    196: }
                    197: 
                    198: static int
                    199: conf2_read(struct pci_dev *d, int pos, byte *buf, int len)
                    200: {
                    201:   int addr = 0xc000 | (d->dev << 8) | pos;
                    202: 
                    203:   if (pos >= 256)
                    204:     return 0;
                    205: 
                    206:   if (d->dev >= 16)
                    207:     /* conf2 supports only 16 devices per bus */
                    208:     return 0;
                    209:   outb((d->func << 1) | 0xf0, 0xcf8);
                    210:   outb(d->bus, 0xcfa);
                    211:   switch (len)
                    212:     {
                    213:     case 1:
                    214:       buf[0] = inb(addr);
                    215:       break;
                    216:     case 2:
                    217:       ((u16 *) buf)[0] = cpu_to_le16(inw(addr));
                    218:       break;
                    219:     case 4:
                    220:       ((u32 *) buf)[0] = cpu_to_le32(inl(addr));
                    221:       break;
                    222:     default:
                    223:       outb(0, 0xcf8);
                    224:       return pci_generic_block_read(d, pos, buf, len);
                    225:     }
                    226:   outb(0, 0xcf8);
                    227:   return 1;
                    228: }
                    229: 
                    230: static int
                    231: conf2_write(struct pci_dev *d, int pos, byte *buf, int len)
                    232: {
                    233:   int addr = 0xc000 | (d->dev << 8) | pos;
                    234: 
                    235:   if (pos >= 256)
                    236:     return 0;
                    237: 
                    238:   if (d->dev >= 16)
                    239:     d->access->error("conf2_write: only first 16 devices exist.");
                    240:   outb((d->func << 1) | 0xf0, 0xcf8);
                    241:   outb(d->bus, 0xcfa);
                    242:   switch (len)
                    243:     {
                    244:     case 1:
                    245:       outb(buf[0], addr);
                    246:       break;
                    247:     case 2:
                    248:       outw(le16_to_cpu(* (u16 *) buf), addr);
                    249:       break;
                    250:     case 4:
                    251:       outl(le32_to_cpu(* (u32 *) buf), addr);
                    252:       break;
                    253:     default:
                    254:       outb(0, 0xcf8);
                    255:       return pci_generic_block_write(d, pos, buf, len);
                    256:     }
                    257:   outb(0, 0xcf8);
                    258:   return 1;
                    259: }
                    260: 
                    261: struct pci_methods pm_intel_conf1 = {
                    262:   "intel-conf1",
                    263:   "Raw I/O port access using Intel conf1 interface",
                    264:   NULL,                                        /* config */
                    265:   conf1_detect,
                    266:   conf12_init,
                    267:   conf12_cleanup,
                    268:   pci_generic_scan,
                    269:   pci_generic_fill_info,
                    270:   conf1_read,
                    271:   conf1_write,
                    272:   NULL,                                        /* read_vpd */
                    273:   NULL,                                        /* init_dev */
                    274:   NULL                                 /* cleanup_dev */
                    275: };
                    276: 
                    277: struct pci_methods pm_intel_conf2 = {
                    278:   "intel-conf2",
                    279:   "Raw I/O port access using Intel conf2 interface",
                    280:   NULL,                                        /* config */
                    281:   conf2_detect,
                    282:   conf12_init,
                    283:   conf12_cleanup,
                    284:   pci_generic_scan,
                    285:   pci_generic_fill_info,
                    286:   conf2_read,
                    287:   conf2_write,
                    288:   NULL,                                        /* read_vpd */
                    289:   NULL,                                        /* init_dev */
                    290:   NULL                                 /* cleanup_dev */
                    291: };

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>