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

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();
        !           169:        __asm__("lcall (%%edi)"
        !           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))) {
        !           209:                pci_indirect.address = pcibios_entry;
        !           210: 
        !           211:                save_flags(flags); cli();
        !           212:                __asm__("lcall (%%edi)\n\t"
        !           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();
        !           257:        __asm__ ("lcall (%%edi)\n\t"
        !           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();
        !           282:        __asm__("lcall (%%edi)\n\t"
        !           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();
        !           307:        __asm__("lcall (%%esi)\n\t"
        !           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();
        !           329:        __asm__("lcall (%%esi)\n\t"
        !           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();
        !           351:        __asm__("lcall (%%esi)\n\t"
        !           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();
        !           373:        __asm__("lcall (%%esi)\n\t"
        !           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();
        !           395:        __asm__("lcall (%%esi)\n\t"
        !           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();
        !           417:        __asm__("lcall (%%esi)\n\t"
        !           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);
        !           906:                                bios32_indirect.address = bios32_entry;
        !           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.