|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.