Annotation of Gnu-Mach/i386/i386at/gpl/linux/pci/bios32.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * bios32.c - BIOS32, PCI BIOS functions.
                      3:  *
                      4:  * Sponsored by
                      5:  *     iX Multiuser Multitasking Magazine
                      6:  *     Hannover, Germany
                      7:  *     [email protected]
                      8:  *
                      9:  * Copyright 1993, 1994 Drew Eckhardt
                     10:  *      Visionary Computing
                     11:  *      (Unix and Linux consulting and custom programming)
                     12:  *      [email protected]
                     13:  *      +1 (303) 786-7975
                     14:  *
                     15:  * For more information, please consult
                     16:  *
                     17:  * PCI BIOS Specification Revision
                     18:  * PCI Local Bus Specification
                     19:  * PCI System Design Guide
                     20:  *
                     21:  * PCI Special Interest Group
                     22:  * M/S HF3-15A
                     23:  * 5200 N.E. Elam Young Parkway
                     24:  * Hillsboro, Oregon 97124-6497
                     25:  * +1 (503) 696-2000
                     26:  * +1 (800) 433-5177
                     27:  *
                     28:  * Manuals are $25 each or $50 for all three, plus $7 shipping
                     29:  * within the United States, $35 abroad.
                     30:  *
                     31:  *
                     32:  * CHANGELOG :
                     33:  * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION
                     34:  *     Revision 2.0 present on <[email protected]>'s ASUS mainboard.
                     35:  *
                     36:  * Jan 5,  1995 : Modified to probe PCI hardware at boot time by Frederic
                     37:  *     Potter, [email protected]
                     38:  *
                     39:  * Jan 10, 1995 : Modified to store the information about configured pci
                     40:  *      devices into a list, which can be accessed via /proc/pci by
                     41:  *      Curtis Varner, [email protected]
                     42:  *
                     43:  * Jan 12, 1995 : CPU-PCI bridge optimization support by Frederic Potter.
                     44:  *     Alpha version. Intel & UMC chipset support only.
                     45:  *
                     46:  * Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code
                     47:  *     moved to drivers/pci/pci.c.
                     48:  *
                     49:  *
                     50:  */
                     51: 
                     52: #include <linux/config.h>
                     53: #include <linux/types.h>
                     54: #include <linux/kernel.h>
                     55: #include <linux/bios32.h>
                     56: #include <linux/pci.h>
                     57: 
                     58: #include <asm/segment.h>
                     59: 
                     60: #define PCIBIOS_PCI_FUNCTION_ID        0xb1XX
                     61: #define PCIBIOS_PCI_BIOS_PRESENT       0xb101
                     62: #define PCIBIOS_FIND_PCI_DEVICE                0xb102
                     63: #define PCIBIOS_FIND_PCI_CLASS_CODE    0xb103
                     64: #define PCIBIOS_GENERATE_SPECIAL_CYCLE 0xb106
                     65: #define PCIBIOS_READ_CONFIG_BYTE       0xb108
                     66: #define PCIBIOS_READ_CONFIG_WORD       0xb109
                     67: #define PCIBIOS_READ_CONFIG_DWORD      0xb10a
                     68: #define PCIBIOS_WRITE_CONFIG_BYTE      0xb10b
                     69: #define PCIBIOS_WRITE_CONFIG_WORD      0xb10c
                     70: #define PCIBIOS_WRITE_CONFIG_DWORD     0xb10d
                     71: 
                     72: 
                     73: /* BIOS32 signature: "_32_" */
                     74: #define BIOS32_SIGNATURE       (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
                     75: 
                     76: /* PCI signature: "PCI " */
                     77: #define PCI_SIGNATURE          (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))
                     78: 
                     79: /* PCI service signature: "$PCI" */
                     80: #define PCI_SERVICE            (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))
                     81: 
                     82: /*
                     83:  * This is the standard structure used to identify the entry point
                     84:  * to the BIOS32 Service Directory, as documented in
                     85:  *     Standard BIOS 32-bit Service Directory Proposal
                     86:  *     Revision 0.4 May 24, 1993
                     87:  *     Phoenix Technologies Ltd.
                     88:  *     Norwood, MA
                     89:  * and the PCI BIOS specification.
                     90:  */
                     91: 
                     92: union bios32 {
                     93:        struct {
                     94:                unsigned long signature;        /* _32_ */
                     95:                unsigned long entry;            /* 32 bit physical address */
                     96:                unsigned char revision;         /* Revision level, 0 */
                     97:                unsigned char length;           /* Length in paragraphs should be 01 */
                     98:                unsigned char checksum;         /* All bytes must add up to zero */
                     99:                unsigned char reserved[5];      /* Must be zero */
                    100:        } fields;
                    101:        char chars[16];
                    102: };
                    103: 
                    104: /*
                    105:  * Physical address of the service directory.  I don't know if we're
                    106:  * allowed to have more than one of these or not, so just in case
                    107:  * we'll make pcibios_present() take a memory start parameter and store
                    108:  * the array there.
                    109:  */
                    110: 
                    111: static unsigned long bios32_entry = 0;
                    112: static struct {
                    113:        unsigned long address;
                    114:        unsigned short segment;
                    115: } bios32_indirect = { 0, KERNEL_CS };
                    116: 
                    117: #ifdef CONFIG_PCI
                    118: /*
                    119:  * Returns the entry point for the given service, NULL on error
                    120:  */
                    121: 
                    122: static unsigned long bios32_service(unsigned long service)
                    123: {
                    124:        unsigned char return_code;      /* %al */
                    125:        unsigned long address;          /* %ebx */
                    126:        unsigned long length;           /* %ecx */
                    127:        unsigned long entry;            /* %edx */
                    128: 
                    129:        __asm__("lcall (%%edi)"
                    130:                : "=a" (return_code),
                    131:                  "=b" (address),
                    132:                  "=c" (length),
                    133:                  "=d" (entry)
                    134:                : "0" (service),
                    135:                  "1" (0),
                    136:                  "D" (&bios32_indirect));
                    137: 
                    138:        switch (return_code) {
                    139:                case 0:
                    140:                        return address + entry;
                    141:                case 0x80:      /* Not present */
                    142:                        printk("bios32_service(%ld) : not present\n", service);
                    143:                        return 0;
                    144:                default: /* Shouldn't happen */
                    145:                        printk("bios32_service(%ld) : returned 0x%x, mail [email protected]\n",
                    146:                                service, return_code);
                    147:                        return 0;
                    148:        }
                    149: }
                    150: 
                    151: static long pcibios_entry = 0;
                    152: static struct {
                    153:        unsigned long address;
                    154:        unsigned short segment;
                    155: } pci_indirect = { 0, KERNEL_CS };
                    156: 
                    157: 
                    158: extern unsigned long check_pcibios(unsigned long memory_start, unsigned long memory_end)
                    159: {
                    160:        unsigned long signature;
                    161:        unsigned char present_status;
                    162:        unsigned char major_revision;
                    163:        unsigned char minor_revision;
                    164:        int pack;
                    165: 
                    166:        if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
                    167:                pci_indirect.address = pcibios_entry;
                    168: 
                    169:                __asm__("lcall (%%edi)\n\t"
                    170:                        "jc 1f\n\t"
                    171:                        "xor %%ah, %%ah\n"
                    172:                        "1:\tshl $8, %%eax\n\t"
                    173:                        "movw %%bx, %%ax"
                    174:                        : "=d" (signature),
                    175:                          "=a" (pack)
                    176:                        : "1" (PCIBIOS_PCI_BIOS_PRESENT),
                    177:                          "D" (&pci_indirect)
                    178:                        : "bx", "cx");
                    179: 
                    180:                present_status = (pack >> 16) & 0xff;
                    181:                major_revision = (pack >> 8) & 0xff;
                    182:                minor_revision = pack & 0xff;
                    183:                if (present_status || (signature != PCI_SIGNATURE)) {
                    184:                        printk ("pcibios_init : %s : BIOS32 Service Directory says PCI BIOS is present,\n"
                    185:                                "       but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n"
                    186:                                "       and signature of 0x%08lx (%c%c%c%c).  mail [email protected]\n",
                    187:                                (signature == PCI_SIGNATURE) ?  "WARNING" : "ERROR",
                    188:                                present_status, signature,
                    189:                                (char) (signature >>  0), (char) (signature >>  8),
                    190:                                (char) (signature >> 16), (char) (signature >> 24));
                    191: 
                    192:                        if (signature != PCI_SIGNATURE)
                    193:                                pcibios_entry = 0;
                    194:                }
                    195: #if 0
                    196:                if (pcibios_entry) {
                    197:                        printk ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%lx\n",
                    198:                                major_revision, minor_revision, pcibios_entry);
                    199:                }
                    200: #endif
                    201:        }
                    202:        return memory_start;
                    203: }
                    204: 
                    205: int pcibios_present(void)
                    206: {
                    207:        return pcibios_entry ? 1 : 0;
                    208: }
                    209: 
                    210: int pcibios_find_class (unsigned int class_code, unsigned short index,
                    211:        unsigned char *bus, unsigned char *device_fn)
                    212: {
                    213:        unsigned long bx;
                    214:        unsigned long ret;
                    215: 
                    216:        __asm__ ("lcall (%%edi)\n\t"
                    217:                "jc 1f\n\t"
                    218:                "xor %%ah, %%ah\n"
                    219:                "1:"
                    220:                : "=b" (bx),
                    221:                  "=a" (ret)
                    222:                : "1" (PCIBIOS_FIND_PCI_CLASS_CODE),
                    223:                  "c" (class_code),
                    224:                  "S" ((int) index),
                    225:                  "D" (&pci_indirect));
                    226:        *bus = (bx >> 8) & 0xff;
                    227:        *device_fn = bx & 0xff;
                    228:        return (int) (ret & 0xff00) >> 8;
                    229: }
                    230: 
                    231: 
                    232: int pcibios_find_device (unsigned short vendor, unsigned short device_id,
                    233:        unsigned short index, unsigned char *bus, unsigned char *device_fn)
                    234: {
                    235:        unsigned short bx;
                    236:        unsigned short ret;
                    237: 
                    238:        __asm__("lcall (%%edi)\n\t"
                    239:                "jc 1f\n\t"
                    240:                "xor %%ah, %%ah\n"
                    241:                "1:"
                    242:                : "=b" (bx),
                    243:                  "=a" (ret)
                    244:                : "1" (PCIBIOS_FIND_PCI_DEVICE),
                    245:                  "c" (device_id),
                    246:                  "d" (vendor),
                    247:                  "S" ((int) index),
                    248:                  "D" (&pci_indirect));
                    249:        *bus = (bx >> 8) & 0xff;
                    250:        *device_fn = bx & 0xff;
                    251:        return (int) (ret & 0xff00) >> 8;
                    252: }
                    253: 
                    254: int pcibios_read_config_byte(unsigned char bus,
                    255:        unsigned char device_fn, unsigned char where, unsigned char *value)
                    256: {
                    257:        unsigned long ret;
                    258:        unsigned long bx = (bus << 8) | device_fn;
                    259: 
                    260:        __asm__("lcall (%%esi)\n\t"
                    261:                "jc 1f\n\t"
                    262:                "xor %%ah, %%ah\n"
                    263:                "1:"
                    264:                : "=c" (*value),
                    265:                  "=a" (ret)
                    266:                : "1" (PCIBIOS_READ_CONFIG_BYTE),
                    267:                  "b" (bx),
                    268:                  "D" ((long) where),
                    269:                  "S" (&pci_indirect));
                    270:        return (int) (ret & 0xff00) >> 8;
                    271: }
                    272: 
                    273: int pcibios_read_config_word (unsigned char bus,
                    274:        unsigned char device_fn, unsigned char where, unsigned short *value)
                    275: {
                    276:        unsigned long ret;
                    277:        unsigned long bx = (bus << 8) | device_fn;
                    278: 
                    279:        __asm__("lcall (%%esi)\n\t"
                    280:                "jc 1f\n\t"
                    281:                "xor %%ah, %%ah\n"
                    282:                "1:"
                    283:                : "=c" (*value),
                    284:                  "=a" (ret)
                    285:                : "1" (PCIBIOS_READ_CONFIG_WORD),
                    286:                  "b" (bx),
                    287:                  "D" ((long) where),
                    288:                  "S" (&pci_indirect));
                    289:        return (int) (ret & 0xff00) >> 8;
                    290: }
                    291: 
                    292: int pcibios_read_config_dword (unsigned char bus,
                    293:        unsigned char device_fn, unsigned char where, unsigned int *value)
                    294: {
                    295:        unsigned long ret;
                    296:        unsigned long bx = (bus << 8) | device_fn;
                    297: 
                    298:        __asm__("lcall (%%esi)\n\t"
                    299:                "jc 1f\n\t"
                    300:                "xor %%ah, %%ah\n"
                    301:                "1:"
                    302:                : "=c" (*value),
                    303:                  "=a" (ret)
                    304:                : "1" (PCIBIOS_READ_CONFIG_DWORD),
                    305:                  "b" (bx),
                    306:                  "D" ((long) where),
                    307:                  "S" (&pci_indirect));
                    308:        return (int) (ret & 0xff00) >> 8;
                    309: }
                    310: 
                    311: int pcibios_write_config_byte (unsigned char bus,
                    312:        unsigned char device_fn, unsigned char where, unsigned char value)
                    313: {
                    314:        unsigned long ret;
                    315:        unsigned long bx = (bus << 8) | device_fn;
                    316: 
                    317:        __asm__("lcall (%%esi)\n\t"
                    318:                "jc 1f\n\t"
                    319:                "xor %%ah, %%ah\n"
                    320:                "1:"
                    321:                : "=a" (ret)
                    322:                : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
                    323:                  "c" (value),
                    324:                  "b" (bx),
                    325:                  "D" ((long) where),
                    326:                  "S" (&pci_indirect));
                    327:        return (int) (ret & 0xff00) >> 8;
                    328: }
                    329: 
                    330: int pcibios_write_config_word (unsigned char bus,
                    331:        unsigned char device_fn, unsigned char where, unsigned short value)
                    332: {
                    333:        unsigned long ret;
                    334:        unsigned long bx = (bus << 8) | device_fn;
                    335: 
                    336:        __asm__("lcall (%%esi)\n\t"
                    337:                "jc 1f\n\t"
                    338:                "xor %%ah, %%ah\n"
                    339:                "1:"
                    340:                : "=a" (ret)
                    341:                : "0" (PCIBIOS_WRITE_CONFIG_WORD),
                    342:                  "c" (value),
                    343:                  "b" (bx),
                    344:                  "D" ((long) where),
                    345:                  "S" (&pci_indirect));
                    346:        return (int) (ret & 0xff00) >> 8;
                    347: }
                    348: 
                    349: int pcibios_write_config_dword (unsigned char bus,
                    350:        unsigned char device_fn, unsigned char where, unsigned int value)
                    351: {
                    352:        unsigned long ret;
                    353:        unsigned long bx = (bus << 8) | device_fn;
                    354: 
                    355:        __asm__("lcall (%%esi)\n\t"
                    356:                "jc 1f\n\t"
                    357:                "xor %%ah, %%ah\n"
                    358:                "1:"
                    359:                : "=a" (ret)
                    360:                : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
                    361:                  "c" (value),
                    362:                  "b" (bx),
                    363:                  "D" ((long) where),
                    364:                  "S" (&pci_indirect));
                    365:        return (int) (ret & 0xff00) >> 8;
                    366: }
                    367: 
                    368: const char *pcibios_strerror (int error)
                    369: {
                    370:        static char buf[80];
                    371: 
                    372:        switch (error) {
                    373:                case PCIBIOS_SUCCESSFUL:
                    374:                        return "SUCCESSFUL";
                    375: 
                    376:                case PCIBIOS_FUNC_NOT_SUPPORTED:
                    377:                        return "FUNC_NOT_SUPPORTED";
                    378: 
                    379:                case PCIBIOS_BAD_VENDOR_ID:
                    380:                        return "SUCCESSFUL";
                    381: 
                    382:                case PCIBIOS_DEVICE_NOT_FOUND:
                    383:                        return "DEVICE_NOT_FOUND";
                    384: 
                    385:                case PCIBIOS_BAD_REGISTER_NUMBER:
                    386:                        return "BAD_REGISTER_NUMBER";
                    387: 
                    388:                 case PCIBIOS_SET_FAILED:          
                    389:                        return "SET_FAILED";
                    390: 
                    391:                 case PCIBIOS_BUFFER_TOO_SMALL:    
                    392:                        return "BUFFER_TOO_SMALL";
                    393: 
                    394:                default:
                    395:                        sprintf (buf, "UNKNOWN RETURN 0x%x", error);
                    396:                        return buf;
                    397:        }
                    398: }
                    399: 
                    400: 
                    401: unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
                    402: {
                    403: return mem_start;
                    404: }
                    405: 
                    406: 
                    407: #endif
                    408: 
                    409: unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end)
                    410: {
                    411:        union bios32 *check;
                    412:        unsigned char sum;
                    413:        int i, length;
                    414: 
                    415:        /*
                    416:         * Follow the standard procedure for locating the BIOS32 Service
                    417:         * directory by scanning the permissible address range from
                    418:         * 0xe0000 through 0xfffff for a valid BIOS32 structure.
                    419:         *
                    420:         */
                    421: 
                    422:        for (check = (union bios32 *) 0xe0000; check <= (union bios32 *) 0xffff0; ++check) {
                    423:                if (check->fields.signature != BIOS32_SIGNATURE)
                    424:                        continue;
                    425:                length = check->fields.length * 16;
                    426:                if (!length)
                    427:                        continue;
                    428:                sum = 0;
                    429:                for (i = 0; i < length ; ++i)
                    430:                        sum += check->chars[i];
                    431:                if (sum != 0)
                    432:                        continue;
                    433:                if (check->fields.revision != 0) {
                    434:                        printk("pcibios_init : unsupported revision %d at 0x%p, mail [email protected]\n",
                    435:                                check->fields.revision, check);
                    436:                        continue;
                    437:                }
                    438: #if 0
                    439:                printk ("pcibios_init : BIOS32 Service Directory structure at 0x%p\n", check);
                    440: #endif
                    441:                if (!bios32_entry) {
                    442:                        if (check->fields.entry >= 0x100000) {
                    443:                                printk("pcibios_init: entry in high memory, unable to access\n");
                    444:                        } else {
                    445:                                bios32_indirect.address = bios32_entry = check->fields.entry;
                    446: #if 0
                    447:                                printk ("pcibios_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
                    448: #endif
                    449:                        }
                    450:                } else {
                    451:                        printk ("pcibios_init : multiple entries, mail [email protected]\n");
                    452:                        /*
                    453:                         * Jeremy Fitzhardinge reports at least one PCI BIOS
                    454:                         * with two different service directories, and as both
                    455:                         * worked for him, we'll just mention the fact, and
                    456:                         * not actually disallow it..
                    457:                         */
                    458:                }
                    459:        }
                    460: #ifdef CONFIG_PCI
                    461:        if (bios32_entry) {
                    462:                memory_start = check_pcibios (memory_start, memory_end);
                    463:        }
                    464: #endif
                    465:        return memory_start;
                    466: }

unix.superglobalmegacorp.com

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