Annotation of Gnu-Mach/linux/src/arch/i386/kernel/bios32.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * bios32.c - BIOS32, PCI BIOS functions.
                      3:  *
                      4:  * $Id: bios32.c,v 1.1 1999/04/26 05:50:57 tb Exp $
                      5:  *
                      6:  * Sponsored by
                      7:  *     iX Multiuser Multitasking Magazine
                      8:  *     Hannover, Germany
                      9:  *     [email protected]
                     10:  *
                     11:  * Copyright 1993, 1994 Drew Eckhardt
                     12:  *      Visionary Computing
                     13:  *      (Unix and Linux consulting and custom programming)
                     14:  *      [email protected]
                     15:  *      +1 (303) 786-7975
                     16:  *
                     17:  * For more information, please consult
                     18:  *
                     19:  * PCI BIOS Specification Revision
                     20:  * PCI Local Bus Specification
                     21:  * PCI System Design Guide
                     22:  *
                     23:  * PCI Special Interest Group
                     24:  * M/S HF3-15A
                     25:  * 5200 N.E. Elam Young Parkway
                     26:  * Hillsboro, Oregon 97124-6497
                     27:  * +1 (503) 696-2000
                     28:  * +1 (800) 433-5177
                     29:  *
                     30:  * Manuals are $25 each or $50 for all three, plus $7 shipping
                     31:  * within the United States, $35 abroad.
                     32:  *
                     33:  *
                     34:  * CHANGELOG :
                     35:  * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION
                     36:  *     Revision 2.0 present on <[email protected]>'s ASUS mainboard.
                     37:  *
                     38:  * Jan 5,  1995 : Modified to probe PCI hardware at boot time by Frederic
                     39:  *     Potter, [email protected]
                     40:  *
                     41:  * Jan 10, 1995 : Modified to store the information about configured pci
                     42:  *      devices into a list, which can be accessed via /proc/pci by
                     43:  *      Curtis Varner, [email protected]
                     44:  *
                     45:  * Jan 12, 1995 : CPU-PCI bridge optimization support by Frederic Potter.
                     46:  *     Alpha version. Intel & UMC chipset support only.
                     47:  *
                     48:  * Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code
                     49:  *     moved to drivers/pci/pci.c.
                     50:  *
                     51:  * Dec 7, 1996  : Added support for direct configuration access of boards
                     52:  *      with Intel compatible access schemes ([email protected])
                     53:  *
                     54:  * Feb 3, 1997  : Set internal functions to static, save/restore flags
                     55:  *     avoid dead locks reading broken PCI BIOS, [email protected] 
                     56:  *
                     57:  * Apr 26, 1997 : Fixed case when there is BIOS32, but not PCI BIOS
                     58:  *     ([email protected])
                     59:  *
                     60:  * May 7,  1997 : Added some missing cli()'s. [mj]
                     61:  * 
                     62:  * Jun 20, 1997 : Corrected problems in "conf1" type accesses.
                     63:  *      ([email protected])
                     64:  */
                     65: 
                     66: #include <linux/config.h>
                     67: #include <linux/types.h>
                     68: #include <linux/kernel.h>
                     69: #include <linux/bios32.h>
                     70: #include <linux/pci.h>
                     71: 
                     72: #include <asm/segment.h>
                     73: #include <asm/system.h>
                     74: #include <asm/io.h>
                     75: 
                     76: #define PCIBIOS_PCI_FUNCTION_ID        0xb1XX
                     77: #define PCIBIOS_PCI_BIOS_PRESENT       0xb101
                     78: #define PCIBIOS_FIND_PCI_DEVICE                0xb102
                     79: #define PCIBIOS_FIND_PCI_CLASS_CODE    0xb103
                     80: #define PCIBIOS_GENERATE_SPECIAL_CYCLE 0xb106
                     81: #define PCIBIOS_READ_CONFIG_BYTE       0xb108
                     82: #define PCIBIOS_READ_CONFIG_WORD       0xb109
                     83: #define PCIBIOS_READ_CONFIG_DWORD      0xb10a
                     84: #define PCIBIOS_WRITE_CONFIG_BYTE      0xb10b
                     85: #define PCIBIOS_WRITE_CONFIG_WORD      0xb10c
                     86: #define PCIBIOS_WRITE_CONFIG_DWORD     0xb10d
                     87: 
                     88: 
                     89: /* BIOS32 signature: "_32_" */
                     90: #define BIOS32_SIGNATURE       (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
                     91: 
                     92: /* PCI signature: "PCI " */
                     93: #define PCI_SIGNATURE          (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))
                     94: 
                     95: /* PCI service signature: "$PCI" */
                     96: #define PCI_SERVICE            (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))
                     97: 
                     98: /*
                     99:  * This is the standard structure used to identify the entry point
                    100:  * to the BIOS32 Service Directory, as documented in
                    101:  *     Standard BIOS 32-bit Service Directory Proposal
                    102:  *     Revision 0.4 May 24, 1993
                    103:  *     Phoenix Technologies Ltd.
                    104:  *     Norwood, MA
                    105:  * and the PCI BIOS specification.
                    106:  */
                    107: 
                    108: union bios32 {
                    109:        struct {
                    110:                unsigned long signature;        /* _32_ */
                    111:                unsigned long entry;            /* 32 bit physical address */
                    112:                unsigned char revision;         /* Revision level, 0 */
                    113:                unsigned char length;           /* Length in paragraphs should be 01 */
                    114:                unsigned char checksum;         /* All bytes must add up to zero */
                    115:                unsigned char reserved[5];      /* Must be zero */
                    116:        } fields;
                    117:        char chars[16];
                    118: };
                    119: 
                    120: #ifdef CONFIG_PCI
                    121: /*
                    122:  * Physical address of the service directory.  I don't know if we're
                    123:  * allowed to have more than one of these or not, so just in case
                    124:  * we'll make pcibios_present() take a memory start parameter and store
                    125:  * the array there.
                    126:  */
                    127: 
                    128: static unsigned long bios32_entry = 0;
                    129: static struct {
                    130:        unsigned long address;
                    131:        unsigned short segment;
                    132: } bios32_indirect = { 0, KERNEL_CS };
                    133: 
                    134: 
                    135: /*
                    136:  * function table for accessing PCI configuration space
                    137:  */
                    138: struct pci_access {
                    139:     int (*find_device)(unsigned short, unsigned short, unsigned short, unsigned char *, unsigned char *);
                    140:     int (*find_class)(unsigned int, unsigned short, unsigned char *, unsigned char *);
                    141:     int (*read_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char *);
                    142:     int (*read_config_word)(unsigned char, unsigned char, unsigned char, unsigned short *);
                    143:     int (*read_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int *);
                    144:     int (*write_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char);
                    145:     int (*write_config_word)(unsigned char, unsigned char, unsigned char, unsigned short);
                    146:     int (*write_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int);
                    147: };
                    148: 
                    149: /*
                    150:  * pointer to selected PCI access function table
                    151:  */
                    152: static struct pci_access *access_pci = NULL;
                    153: 
                    154: 
                    155: 
                    156: /*
                    157:  * Returns the entry point for the given service, NULL on error
                    158:  */
                    159: 
                    160: static unsigned long bios32_service(unsigned long service)
                    161: {
                    162:        unsigned char return_code;      /* %al */
                    163:        unsigned long address;          /* %ebx */
                    164:        unsigned long length;           /* %ecx */
                    165:        unsigned long entry;            /* %edx */
                    166:        unsigned long flags;
                    167: 
                    168:        save_flags(flags); cli();
1.1.1.2 ! root      169:        __asm__("lcall *(%%edi); cld"
1.1       root      170:                : "=a" (return_code),
                    171:                  "=b" (address),
                    172:                  "=c" (length),
                    173:                  "=d" (entry)
                    174:                : "0" (service),
                    175:                  "1" (0),
                    176:                  "D" (&bios32_indirect));
                    177:        restore_flags(flags);
                    178: 
                    179:        switch (return_code) {
                    180:                case 0:
                    181:                        return address + entry;
                    182:                case 0x80:      /* Not present */
                    183:                        printk("bios32_service(0x%lx) : not present\n", service);
                    184:                        return 0;
                    185:                default: /* Shouldn't happen */
                    186:                        printk("bios32_service(0x%lx) : returned 0x%x, mail [email protected]\n",
                    187:                                service, return_code);
                    188:                        return 0;
                    189:        }
                    190: }
                    191: 
                    192: static long pcibios_entry = 0;
                    193: static struct {
                    194:        unsigned long address;
                    195:        unsigned short segment;
                    196: } pci_indirect = { 0, KERNEL_CS };
                    197: 
                    198: 
                    199: static int check_pcibios(void)
                    200: {
                    201:        unsigned long signature;
                    202:        unsigned char present_status;
                    203:        unsigned char major_revision;
                    204:        unsigned char minor_revision;
                    205:        unsigned long flags;
                    206:        int pack;
                    207: 
                    208:        if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
1.1.1.2 ! root      209:                pci_indirect.address = phystokv(pcibios_entry);
1.1       root      210: 
                    211:                save_flags(flags); cli();
1.1.1.2 ! root      212:                __asm__("lcall *(%%edi); cld\n\t"
1.1       root      213:                        "jc 1f\n\t"
                    214:                        "xor %%ah, %%ah\n"
                    215:                        "1:\tshl $8, %%eax\n\t"
                    216:                        "movw %%bx, %%ax"
                    217:                        : "=d" (signature),
                    218:                          "=a" (pack)
                    219:                        : "1" (PCIBIOS_PCI_BIOS_PRESENT),
                    220:                          "D" (&pci_indirect)
                    221:                        : "bx", "cx");
                    222:                restore_flags(flags);
                    223: 
                    224:                present_status = (pack >> 16) & 0xff;
                    225:                major_revision = (pack >> 8) & 0xff;
                    226:                minor_revision = pack & 0xff;
                    227:                if (present_status || (signature != PCI_SIGNATURE)) {
                    228:                        printk ("pcibios_init : %s : BIOS32 Service Directory says PCI BIOS is present,\n"
                    229:                                "       but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n"
                    230:                                "       and signature of 0x%08lx (%c%c%c%c).  mail [email protected]\n",
                    231:                                (signature == PCI_SIGNATURE) ?  "WARNING" : "ERROR",
                    232:                                present_status, signature,
                    233:                                (char) (signature >>  0), (char) (signature >>  8),
                    234:                                (char) (signature >> 16), (char) (signature >> 24));
                    235: 
                    236:                        if (signature != PCI_SIGNATURE)
                    237:                                pcibios_entry = 0;
                    238:                }
                    239:                if (pcibios_entry) {
                    240:                        printk ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%lx\n",
                    241:                                major_revision, minor_revision, pcibios_entry);
                    242:                        return 1;
                    243:                }
                    244:        }
                    245:        return 0;
                    246: }
                    247: 
                    248: 
                    249: static int pci_bios_find_class (unsigned int class_code, unsigned short index,
                    250:        unsigned char *bus, unsigned char *device_fn)
                    251: {
                    252:        unsigned long bx;
                    253:        unsigned long ret;
                    254:        unsigned long flags;
                    255: 
                    256:        save_flags(flags); cli();
1.1.1.2 ! root      257:        __asm__ ("lcall *(%%edi); cld\n\t"
1.1       root      258:                "jc 1f\n\t"
                    259:                "xor %%ah, %%ah\n"
                    260:                "1:"
                    261:                : "=b" (bx),
                    262:                  "=a" (ret)
                    263:                : "1" (PCIBIOS_FIND_PCI_CLASS_CODE),
                    264:                  "c" (class_code),
                    265:                  "S" ((int) index),
                    266:                  "D" (&pci_indirect));
                    267:        restore_flags(flags);
                    268:        *bus = (bx >> 8) & 0xff;
                    269:        *device_fn = bx & 0xff;
                    270:        return (int) (ret & 0xff00) >> 8;
                    271: }
                    272: 
                    273: 
                    274: static int pci_bios_find_device (unsigned short vendor, unsigned short device_id,
                    275:        unsigned short index, unsigned char *bus, unsigned char *device_fn)
                    276: {
                    277:        unsigned short bx;
                    278:        unsigned short ret;
                    279:        unsigned long flags;
                    280: 
                    281:        save_flags(flags); cli();
1.1.1.2 ! root      282:        __asm__("lcall *(%%edi); cld\n\t"
1.1       root      283:                "jc 1f\n\t"
                    284:                "xor %%ah, %%ah\n"
                    285:                "1:"
                    286:                : "=b" (bx),
                    287:                  "=a" (ret)
                    288:                : "1" (PCIBIOS_FIND_PCI_DEVICE),
                    289:                  "c" (device_id),
                    290:                  "d" (vendor),
                    291:                  "S" ((int) index),
                    292:                  "D" (&pci_indirect));
                    293:        restore_flags(flags);
                    294:        *bus = (bx >> 8) & 0xff;
                    295:        *device_fn = bx & 0xff;
                    296:        return (int) (ret & 0xff00) >> 8;
                    297: }
                    298: 
                    299: static int pci_bios_read_config_byte(unsigned char bus,
                    300:        unsigned char device_fn, unsigned char where, unsigned char *value)
                    301: {
                    302:        unsigned long ret;
                    303:        unsigned long bx = (bus << 8) | device_fn;
                    304:        unsigned long flags;
                    305: 
                    306:        save_flags(flags); cli();
1.1.1.2 ! root      307:        __asm__("lcall *(%%esi); cld\n\t"
1.1       root      308:                "jc 1f\n\t"
                    309:                "xor %%ah, %%ah\n"
                    310:                "1:"
                    311:                : "=c" (*value),
                    312:                  "=a" (ret)
                    313:                : "1" (PCIBIOS_READ_CONFIG_BYTE),
                    314:                  "b" (bx),
                    315:                  "D" ((long) where),
                    316:                  "S" (&pci_indirect));
                    317:        restore_flags(flags);
                    318:        return (int) (ret & 0xff00) >> 8;
                    319: }
                    320: 
                    321: static int pci_bios_read_config_word (unsigned char bus,
                    322:        unsigned char device_fn, unsigned char where, unsigned short *value)
                    323: {
                    324:        unsigned long ret;
                    325:        unsigned long bx = (bus << 8) | device_fn;
                    326:        unsigned long flags;
                    327: 
                    328:        save_flags(flags); cli();
1.1.1.2 ! root      329:        __asm__("lcall *(%%esi); cld\n\t"
1.1       root      330:                "jc 1f\n\t"
                    331:                "xor %%ah, %%ah\n"
                    332:                "1:"
                    333:                : "=c" (*value),
                    334:                  "=a" (ret)
                    335:                : "1" (PCIBIOS_READ_CONFIG_WORD),
                    336:                  "b" (bx),
                    337:                  "D" ((long) where),
                    338:                  "S" (&pci_indirect));
                    339:        restore_flags(flags);
                    340:        return (int) (ret & 0xff00) >> 8;
                    341: }
                    342: 
                    343: static int pci_bios_read_config_dword (unsigned char bus,
                    344:        unsigned char device_fn, unsigned char where, unsigned int *value)
                    345: {
                    346:        unsigned long ret;
                    347:        unsigned long bx = (bus << 8) | device_fn;
                    348:        unsigned long flags;
                    349: 
                    350:        save_flags(flags); cli();
1.1.1.2 ! root      351:        __asm__("lcall *(%%esi); cld\n\t"
1.1       root      352:                "jc 1f\n\t"
                    353:                "xor %%ah, %%ah\n"
                    354:                "1:"
                    355:                : "=c" (*value),
                    356:                  "=a" (ret)
                    357:                : "1" (PCIBIOS_READ_CONFIG_DWORD),
                    358:                  "b" (bx),
                    359:                  "D" ((long) where),
                    360:                  "S" (&pci_indirect));
                    361:        restore_flags(flags);
                    362:        return (int) (ret & 0xff00) >> 8;
                    363: }
                    364: 
                    365: static int pci_bios_write_config_byte (unsigned char bus,
                    366:        unsigned char device_fn, unsigned char where, unsigned char value)
                    367: {
                    368:        unsigned long ret;
                    369:        unsigned long bx = (bus << 8) | device_fn;
                    370:        unsigned long flags;
                    371: 
                    372:        save_flags(flags); cli();
1.1.1.2 ! root      373:        __asm__("lcall *(%%esi); cld\n\t"
1.1       root      374:                "jc 1f\n\t"
                    375:                "xor %%ah, %%ah\n"
                    376:                "1:"
                    377:                : "=a" (ret)
                    378:                : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
                    379:                  "c" (value),
                    380:                  "b" (bx),
                    381:                  "D" ((long) where),
                    382:                  "S" (&pci_indirect));
                    383:        restore_flags(flags);
                    384:        return (int) (ret & 0xff00) >> 8;
                    385: }
                    386: 
                    387: static int pci_bios_write_config_word (unsigned char bus,
                    388:        unsigned char device_fn, unsigned char where, unsigned short value)
                    389: {
                    390:        unsigned long ret;
                    391:        unsigned long bx = (bus << 8) | device_fn;
                    392:        unsigned long flags;
                    393: 
                    394:        save_flags(flags); cli();
1.1.1.2 ! root      395:        __asm__("lcall *(%%esi); cld\n\t"
1.1       root      396:                "jc 1f\n\t"
                    397:                "xor %%ah, %%ah\n"
                    398:                "1:"
                    399:                : "=a" (ret)
                    400:                : "0" (PCIBIOS_WRITE_CONFIG_WORD),
                    401:                  "c" (value),
                    402:                  "b" (bx),
                    403:                  "D" ((long) where),
                    404:                  "S" (&pci_indirect));
                    405:        restore_flags(flags);
                    406:        return (int) (ret & 0xff00) >> 8;
                    407: }
                    408: 
                    409: static int pci_bios_write_config_dword (unsigned char bus,
                    410:        unsigned char device_fn, unsigned char where, unsigned int value)
                    411: {
                    412:        unsigned long ret;
                    413:        unsigned long bx = (bus << 8) | device_fn;
                    414:        unsigned long flags;
                    415: 
                    416:        save_flags(flags); cli();
1.1.1.2 ! root      417:        __asm__("lcall *(%%esi); cld\n\t"
1.1       root      418:                "jc 1f\n\t"
                    419:                "xor %%ah, %%ah\n"
                    420:                "1:"
                    421:                : "=a" (ret)
                    422:                : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
                    423:                  "c" (value),
                    424:                  "b" (bx),
                    425:                  "D" ((long) where),
                    426:                  "S" (&pci_indirect));
                    427:        restore_flags(flags);
                    428:        return (int) (ret & 0xff00) >> 8;
                    429: }
                    430: 
                    431: /*
                    432:  * function table for BIOS32 access
                    433:  */
                    434: static struct pci_access pci_bios_access = {
                    435:       pci_bios_find_device,
                    436:       pci_bios_find_class,
                    437:       pci_bios_read_config_byte,
                    438:       pci_bios_read_config_word,
                    439:       pci_bios_read_config_dword,
                    440:       pci_bios_write_config_byte,
                    441:       pci_bios_write_config_word,
                    442:       pci_bios_write_config_dword
                    443: };
                    444: 
                    445: 
                    446: 
                    447: /*
                    448:  * Given the vendor and device ids, find the n'th instance of that device
                    449:  * in the system.  
                    450:  */
                    451: static int pci_direct_find_device (unsigned short vendor, unsigned short device_id,
                    452:                           unsigned short index, unsigned char *bus,
                    453:                           unsigned char *devfn)
                    454: {
                    455:     unsigned int curr = 0;
                    456:     struct pci_dev *dev;
                    457: 
                    458:     for (dev = pci_devices; dev; dev = dev->next) {
                    459:        if (dev->vendor == vendor && dev->device == device_id) {
                    460:            if (curr == index) {
                    461:                *devfn = dev->devfn;
                    462:                *bus = dev->bus->number;
                    463:                return PCIBIOS_SUCCESSFUL;
                    464:            }
                    465:            ++curr;
                    466:        }
                    467:     }
                    468:     return PCIBIOS_DEVICE_NOT_FOUND;
                    469: }
                    470: 
                    471: 
                    472: /*
                    473:  * Given the class, find the n'th instance of that device
                    474:  * in the system.
                    475:  */
                    476: static int pci_direct_find_class (unsigned int class_code, unsigned short index,
                    477:                          unsigned char *bus, unsigned char *devfn)
                    478: {
                    479:     unsigned int curr = 0;
                    480:     struct pci_dev *dev;
                    481: 
                    482:     for (dev = pci_devices; dev; dev = dev->next) {
                    483:        if (dev->class == class_code) {
                    484:            if (curr == index) {
                    485:                *devfn = dev->devfn;
                    486:                *bus = dev->bus->number;
                    487:                return PCIBIOS_SUCCESSFUL;
                    488:            }
                    489:            ++curr;
                    490:        }
                    491:     }
                    492:     return PCIBIOS_DEVICE_NOT_FOUND;
                    493: }
                    494: 
                    495: /*
                    496:  * Functions for accessing PCI configuration space with type 1 accesses
                    497:  */
                    498: #define CONFIG_CMD(bus, device_fn, where)   (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
                    499: 
                    500: static int pci_conf1_read_config_byte(unsigned char bus, unsigned char device_fn,
                    501:                               unsigned char where, unsigned char *value)
                    502: {
                    503:     unsigned long flags;
                    504: 
                    505:     save_flags(flags); cli();
                    506:     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
                    507:     *value = inb(0xCFC + (where&3));
                    508:     restore_flags(flags);
                    509:     return PCIBIOS_SUCCESSFUL;
                    510: }
                    511: 
                    512: static int pci_conf1_read_config_word (unsigned char bus,
                    513:     unsigned char device_fn, unsigned char where, unsigned short *value)
                    514: {
                    515:     unsigned long flags;
                    516: 
                    517:     if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
                    518:     save_flags(flags); cli();
                    519:     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);    
                    520:     *value = inw(0xCFC + (where&2));
                    521:     restore_flags(flags);
                    522:     return PCIBIOS_SUCCESSFUL;    
                    523: }
                    524: 
                    525: static int pci_conf1_read_config_dword (unsigned char bus, unsigned char device_fn, 
                    526:                                 unsigned char where, unsigned int *value)
                    527: {
                    528:     unsigned long flags;
                    529: 
                    530:     if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
                    531:     save_flags(flags); cli();
                    532:     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
                    533:     *value = inl(0xCFC);
                    534:     restore_flags(flags);
                    535:     return PCIBIOS_SUCCESSFUL;    
                    536: }
                    537: 
                    538: static int pci_conf1_write_config_byte (unsigned char bus, unsigned char device_fn, 
                    539:                                 unsigned char where, unsigned char value)
                    540: {
                    541:     unsigned long flags;
                    542: 
                    543:     save_flags(flags); cli();
                    544:     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);    
                    545:     outb(value, 0xCFC + (where&3));
                    546:     restore_flags(flags);
                    547:     return PCIBIOS_SUCCESSFUL;
                    548: }
                    549: 
                    550: static int pci_conf1_write_config_word (unsigned char bus, unsigned char device_fn, 
                    551:                                 unsigned char where, unsigned short value)
                    552: {
                    553:     unsigned long flags;
                    554: 
                    555:     if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
                    556:     save_flags(flags); cli();
                    557:     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
                    558:     outw(value, 0xCFC + (where&2));
                    559:     restore_flags(flags);
                    560:     return PCIBIOS_SUCCESSFUL;
                    561: }
                    562: 
                    563: static int pci_conf1_write_config_dword (unsigned char bus, unsigned char device_fn, 
                    564:                                  unsigned char where, unsigned int value)
                    565: {
                    566:     unsigned long flags;
                    567: 
                    568:     if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
                    569:     save_flags(flags); cli();
                    570:     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
                    571:     outl(value, 0xCFC);
                    572:     restore_flags(flags);
                    573:     return PCIBIOS_SUCCESSFUL;
                    574: }
                    575: 
                    576: #undef CONFIG_CMD
                    577: 
                    578: /*
                    579:  * functiontable for type 1
                    580:  */
                    581: static struct pci_access pci_direct_conf1 = {
                    582:       pci_direct_find_device,
                    583:       pci_direct_find_class,
                    584:       pci_conf1_read_config_byte,
                    585:       pci_conf1_read_config_word,
                    586:       pci_conf1_read_config_dword,
                    587:       pci_conf1_write_config_byte,
                    588:       pci_conf1_write_config_word,
                    589:       pci_conf1_write_config_dword
                    590: };
                    591: 
                    592: /*
                    593:  * Functions for accessing PCI configuration space with type 2 accesses
                    594:  */
                    595: #define IOADDR(devfn, where)   ((0xC000 | ((devfn & 0x78) << 5)) + where)
                    596: #define FUNC(devfn)            (((devfn & 7) << 1) | 0xf0)
                    597: 
                    598: static int pci_conf2_read_config_byte(unsigned char bus, unsigned char device_fn, 
                    599:                               unsigned char where, unsigned char *value)
                    600: {
                    601:     unsigned long flags;
                    602: 
                    603:     if (device_fn & 0x80)
                    604:        return PCIBIOS_DEVICE_NOT_FOUND;
                    605:     save_flags(flags); cli();
                    606:     outb (FUNC(device_fn), 0xCF8);
                    607:     outb (bus, 0xCFA);
                    608:     *value = inb(IOADDR(device_fn,where));
                    609:     outb (0, 0xCF8);
                    610:     restore_flags(flags);
                    611:     return PCIBIOS_SUCCESSFUL;
                    612: }
                    613: 
                    614: static int pci_conf2_read_config_word (unsigned char bus, unsigned char device_fn, 
                    615:                                unsigned char where, unsigned short *value)
                    616: {
                    617:     unsigned long flags;
                    618: 
                    619:     if (device_fn & 0x80)
                    620:        return PCIBIOS_DEVICE_NOT_FOUND;
                    621:     save_flags(flags); cli();
                    622:     outb (FUNC(device_fn), 0xCF8);
                    623:     outb (bus, 0xCFA);
                    624:     *value = inw(IOADDR(device_fn,where));
                    625:     outb (0, 0xCF8);
                    626:     restore_flags(flags);
                    627:     return PCIBIOS_SUCCESSFUL;
                    628: }
                    629: 
                    630: static int pci_conf2_read_config_dword (unsigned char bus, unsigned char device_fn, 
                    631:                                 unsigned char where, unsigned int *value)
                    632: {
                    633:     unsigned long flags;
                    634: 
                    635:     if (device_fn & 0x80)
                    636:        return PCIBIOS_DEVICE_NOT_FOUND;
                    637:     save_flags(flags); cli();
                    638:     outb (FUNC(device_fn), 0xCF8);
                    639:     outb (bus, 0xCFA);
                    640:     *value = inl (IOADDR(device_fn,where));    
                    641:     outb (0, 0xCF8);    
                    642:     restore_flags(flags);
                    643:     return PCIBIOS_SUCCESSFUL;
                    644: }
                    645: 
                    646: static int pci_conf2_write_config_byte (unsigned char bus, unsigned char device_fn, 
                    647:                                 unsigned char where, unsigned char value)
                    648: {
                    649:     unsigned long flags;
                    650: 
                    651:     save_flags(flags); cli();
                    652:     outb (FUNC(device_fn), 0xCF8);
                    653:     outb (bus, 0xCFA);
                    654:     outb (value, IOADDR(device_fn,where));
                    655:     outb (0, 0xCF8);    
                    656:     restore_flags(flags);
                    657:     return PCIBIOS_SUCCESSFUL;
                    658: }
                    659: 
                    660: static int pci_conf2_write_config_word (unsigned char bus, unsigned char device_fn, 
                    661:                                 unsigned char where, unsigned short value)
                    662: {
                    663:     unsigned long flags;
                    664: 
                    665:     save_flags(flags); cli();
                    666:     outb (FUNC(device_fn), 0xCF8);
                    667:     outb (bus, 0xCFA);
                    668:     outw (value, IOADDR(device_fn,where));
                    669:     outb (0, 0xCF8);    
                    670:     restore_flags(flags);
                    671:     return PCIBIOS_SUCCESSFUL;
                    672: }
                    673: 
                    674: static int pci_conf2_write_config_dword (unsigned char bus, unsigned char device_fn, 
                    675:                                  unsigned char where, unsigned int value)
                    676: {
                    677:     unsigned long flags;
                    678: 
                    679:     save_flags(flags); cli();
                    680:     outb (FUNC(device_fn), 0xCF8);
                    681:     outb (bus, 0xCFA);
                    682:     outl (value, IOADDR(device_fn,where));    
                    683:     outb (0, 0xCF8);    
                    684:     restore_flags(flags);
                    685:     return PCIBIOS_SUCCESSFUL;
                    686: }
                    687: 
                    688: #undef IOADDR
                    689: #undef FUNC
                    690: 
                    691: /*
                    692:  * functiontable for type 2
                    693:  */
                    694: static struct pci_access pci_direct_conf2 = {
                    695:       pci_direct_find_device,
                    696:       pci_direct_find_class,
                    697:       pci_conf2_read_config_byte,
                    698:       pci_conf2_read_config_word,
                    699:       pci_conf2_read_config_dword,
                    700:       pci_conf2_write_config_byte,
                    701:       pci_conf2_write_config_word,
                    702:       pci_conf2_write_config_dword
                    703: };
                    704: 
                    705: 
                    706: static struct pci_access *check_direct_pci(void)
                    707: {
                    708:     unsigned int tmp;
                    709:     unsigned long flags;
                    710: 
                    711:     save_flags(flags); cli();
                    712: 
                    713:     /*
                    714:      * check if configuration type 1 works
                    715:      */
                    716:     outb (0x01, 0xCFB);
                    717:     tmp = inl (0xCF8);
                    718:     outl (0x80000000, 0xCF8);
                    719:     if (inl (0xCF8) == 0x80000000) {
                    720:        outl (tmp, 0xCF8);
                    721:        restore_flags(flags);
                    722:        printk("pcibios_init: Using configuration type 1\n");
                    723:        return &pci_direct_conf1;
                    724:     }
                    725:     outl (tmp, 0xCF8);
                    726: 
                    727:     /*
                    728:      * check if configuration type 2 works
                    729:      */
                    730:     outb (0x00, 0xCFB);
                    731:     outb (0x00, 0xCF8);
                    732:     outb (0x00, 0xCFA);
                    733:     if (inb (0xCF8) == 0x00 && inb (0xCFB) == 0x00) {
                    734:        restore_flags(flags);
                    735:        printk("pcibios_init: Using configuration type 2\n");
                    736:        return &pci_direct_conf2;
                    737:     }
                    738:     restore_flags(flags);
                    739:     printk("pcibios_init: Not supported chipset for direct PCI access !\n");
                    740:     return NULL;
                    741: }
                    742: 
                    743: 
                    744: /*
                    745:  * access defined pcibios functions via
                    746:  * the function table
                    747:  */
                    748: 
                    749: int pcibios_present(void)
                    750: {
                    751:        return access_pci ? 1 : 0;
                    752: }
                    753: 
                    754: int pcibios_find_class (unsigned int class_code, unsigned short index,
                    755:        unsigned char *bus, unsigned char *device_fn)
                    756: {
                    757:    if (access_pci && access_pci->find_class)
                    758:       return access_pci->find_class(class_code, index, bus, device_fn);
                    759:     
                    760:     return PCIBIOS_FUNC_NOT_SUPPORTED;
                    761: }
                    762: 
                    763: int pcibios_find_device (unsigned short vendor, unsigned short device_id,
                    764:        unsigned short index, unsigned char *bus, unsigned char *device_fn)
                    765: {
                    766:     if (access_pci && access_pci->find_device)
                    767:       return access_pci->find_device(vendor, device_id, index, bus, device_fn);
                    768:     
                    769:     return PCIBIOS_FUNC_NOT_SUPPORTED;
                    770: }
                    771: 
                    772: int pcibios_read_config_byte (unsigned char bus,
                    773:        unsigned char device_fn, unsigned char where, unsigned char *value)
                    774: {
                    775:     if (access_pci && access_pci->read_config_byte)
                    776:       return access_pci->read_config_byte(bus, device_fn, where, value);
                    777:     
                    778:     return PCIBIOS_FUNC_NOT_SUPPORTED;
                    779: }
                    780: 
                    781: int pcibios_read_config_word (unsigned char bus,
                    782:        unsigned char device_fn, unsigned char where, unsigned short *value)
                    783: {
                    784:     if (access_pci && access_pci->read_config_word)
                    785:       return access_pci->read_config_word(bus, device_fn, where, value);
                    786:     
                    787:     return PCIBIOS_FUNC_NOT_SUPPORTED;
                    788: }
                    789: 
                    790: int pcibios_read_config_dword (unsigned char bus,
                    791:        unsigned char device_fn, unsigned char where, unsigned int *value)
                    792: {
                    793:     if (access_pci && access_pci->read_config_dword)
                    794:       return access_pci->read_config_dword(bus, device_fn, where, value);
                    795:     
                    796:     return PCIBIOS_FUNC_NOT_SUPPORTED;
                    797: }
                    798: 
                    799: int pcibios_write_config_byte (unsigned char bus,
                    800:        unsigned char device_fn, unsigned char where, unsigned char value)
                    801: {
                    802:     if (access_pci && access_pci->write_config_byte)
                    803:       return access_pci->write_config_byte(bus, device_fn, where, value);
                    804:     
                    805:     return PCIBIOS_FUNC_NOT_SUPPORTED;
                    806: }
                    807: 
                    808: int pcibios_write_config_word (unsigned char bus,
                    809:        unsigned char device_fn, unsigned char where, unsigned short value)
                    810: {
                    811:     if (access_pci && access_pci->write_config_word)
                    812:       return access_pci->write_config_word(bus, device_fn, where, value);
                    813:     
                    814:     return PCIBIOS_FUNC_NOT_SUPPORTED;    
                    815: }
                    816: 
                    817: int pcibios_write_config_dword (unsigned char bus,
                    818:        unsigned char device_fn, unsigned char where, unsigned int value)
                    819: {
                    820:     if (access_pci && access_pci->write_config_dword)
                    821:       return access_pci->write_config_dword(bus, device_fn, where, value);
                    822:     
                    823:     return PCIBIOS_FUNC_NOT_SUPPORTED;
                    824: }
                    825: 
                    826: const char *pcibios_strerror (int error)
                    827: {
                    828:        static char buf[80];
                    829: 
                    830:        switch (error) {
                    831:                case PCIBIOS_SUCCESSFUL:
                    832:                        return "SUCCESSFUL";
                    833: 
                    834:                case PCIBIOS_FUNC_NOT_SUPPORTED:
                    835:                        return "FUNC_NOT_SUPPORTED";
                    836: 
                    837:                case PCIBIOS_BAD_VENDOR_ID:
                    838:                        return "SUCCESSFUL";
                    839: 
                    840:                case PCIBIOS_DEVICE_NOT_FOUND:
                    841:                        return "DEVICE_NOT_FOUND";
                    842: 
                    843:                case PCIBIOS_BAD_REGISTER_NUMBER:
                    844:                        return "BAD_REGISTER_NUMBER";
                    845: 
                    846:                 case PCIBIOS_SET_FAILED:          
                    847:                        return "SET_FAILED";
                    848: 
                    849:                 case PCIBIOS_BUFFER_TOO_SMALL:    
                    850:                        return "BUFFER_TOO_SMALL";
                    851: 
                    852:                default:
                    853:                        sprintf (buf, "UNKNOWN RETURN 0x%x", error);
                    854:                        return buf;
                    855:        }
                    856: }
                    857: 
                    858: 
                    859: unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
                    860: {
                    861:     return mem_start;
                    862: }
                    863: 
                    864: #endif
                    865: 
                    866: unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end)
                    867: {
                    868: #ifdef CONFIG_PCI
                    869:        union bios32 *check;
                    870:        unsigned char sum;
                    871:        int i, length;
                    872: 
                    873:        /*
                    874:         * Follow the standard procedure for locating the BIOS32 Service
                    875:         * directory by scanning the permissible address range from
                    876:         * 0xe0000 through 0xfffff for a valid BIOS32 structure.
                    877:         *
                    878:         */
                    879: 
                    880:        for (check = (union bios32 *) 0xe0000;
                    881:             check <= (union bios32 *) 0xffff0;
                    882:             ++check) {
                    883:                if (check->fields.signature != BIOS32_SIGNATURE)
                    884:                        continue;
                    885:                length = check->fields.length * 16;
                    886:                if (!length)
                    887:                        continue;
                    888:                sum = 0;
                    889:                for (i = 0; i < length ; ++i)
                    890:                        sum += check->chars[i];
                    891:                if (sum != 0)
                    892:                        continue;
                    893:                if (check->fields.revision != 0) {
                    894:                        printk("pcibios_init : unsupported revision %d at 0x%p, mail [email protected]\n",
                    895:                                check->fields.revision, check);
                    896:                        continue;
                    897:                }
                    898:                printk ("pcibios_init : BIOS32 Service Directory structure at 0x%p\n", check);
                    899:                if (!bios32_entry) {
                    900:                        if (check->fields.entry >= 0x100000) {
                    901:                                printk("pcibios_init: entry in high memory, trying direct PCI access\n");
                    902:                                access_pci = check_direct_pci();
                    903:                        } else {
                    904:                                bios32_entry = check->fields.entry;
                    905:                                printk ("pcibios_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
1.1.1.2 ! root      906:                                bios32_indirect.address = phystokv(bios32_entry);
1.1       root      907:                        }
                    908:                }
                    909:        }
                    910:        if (bios32_entry && check_pcibios())
                    911:                access_pci = &pci_bios_access;
                    912: #endif
                    913:        return memory_start;
                    914: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.