1 /* $NetBSD: pcibios.c,v 1.39 2010/07/26 22:33:23 jym Exp $ */ 2 3 /*- 4 * Copyright (c) 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 1999, by UCHIYAMA Yasushi 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. The name of the developer may NOT be used to endorse or promote products 43 * derived from this software without specific prior written permission. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * SUCH DAMAGE. 56 */ 57 58 /* 59 * Interface to the PCI BIOS and PCI Interrupt Routing table. 60 */ 61 62 #include <sys/cdefs.h> 63 __KERNEL_RCSID(0, "$NetBSD: pcibios.c,v 1.39 2010/07/26 22:33:23 jym Exp $"); 64 65 #include "opt_pcibios.h" 66 #include "opt_pcifixup.h" 67 68 #include <sys/param.h> 69 #include <sys/systm.h> 70 #include <sys/device.h> 71 #include <sys/malloc.h> 72 73 #include <dev/isa/isareg.h> 74 #include <machine/isa_machdep.h> 75 76 #include <dev/pci/pcireg.h> 77 #include <dev/pci/pcivar.h> 78 #include <dev/pci/pcidevs.h> 79 80 #include <i386/pci/pcibios.h> 81 82 #if defined(PCIBIOS_INTR_FIXUP) || defined(PCIBIOS_ADDR_FIXUP) || \ 83 defined(PCIBIOS_BUS_FIXUP) 84 #error The options PCIBIOS_INTR_FIXUP, PCIBIOS_ADDR_FIXUP, and PCIBIOS_BUS_FIXUP have been obsoleted by PCI_INTR_FIXUP, PCI_ADDR_FIXUP, and PCI_BUS_FIXUP. Please adjust your kernel configuration file. 85 #endif 86 87 #ifdef PCI_INTR_FIXUP 88 #include <i386/pci/pci_intr_fixup.h> 89 #endif 90 91 #include <machine/bios32.h> 92 93 #ifdef PCIBIOSVERBOSE 94 int pcibiosverbose = 1; 95 #endif 96 97 int pcibios_present; 98 99 struct pcibios_pir_header pcibios_pir_header; 100 struct pcibios_intr_routing *pcibios_pir_table; 101 int pcibios_pir_table_nentries; 102 int pcibios_max_bus; 103 104 struct bios32_entry pcibios_entry; 105 106 void pcibios_pir_init(void); 107 108 int pcibios_get_status(uint32_t *, uint32_t *, uint32_t *, 109 uint32_t *, uint32_t *, uint32_t *, uint32_t *); 110 int pcibios_get_intr_routing(struct pcibios_intr_routing *, 111 int *, uint16_t *); 112 113 int pcibios_return_code(uint16_t, const char *); 114 115 void pcibios_print_exclirq(void); 116 117 #ifdef PCIBIOS_LIBRETTO_FIXUP 118 /* for Libretto L2/L3 hack */ 119 static void pcibios_fixup_pir_table(void); 120 static void pcibios_fixup_pir_table_mask(struct pcibios_linkmap *); 121 122 struct pcibios_linkmap pir_mask[] = { 123 { 2, 0x0040 }, 124 { 7, 0x0080 }, 125 { 8, 0x0020 }, 126 { 0, 0x0000 } 127 }; 128 #endif 129 130 #ifdef PCIBIOS_SHARP_MM20_FIXUP 131 static void pcibios_mm20_fixup(void); 132 #endif 133 134 #ifdef PCIINTR_DEBUG 135 void pcibios_print_pir_table(void); 136 #endif 137 138 #define PCI_IRQ_TABLE_START 0xf0000 139 #define PCI_IRQ_TABLE_END 0xfffff 140 141 void 142 pcibios_init(void) 143 { 144 struct bios32_entry_info ei; 145 uint32_t rev_maj, rev_min, mech1, mech2, scmech1, scmech2; 146 147 if (bios32_service(BIOS32_MAKESIG('$', 'P', 'C', 'I'), 148 &pcibios_entry, &ei) == 0) { 149 /* 150 * No PCI BIOS found; will fall back on old 151 * mechanism. 152 */ 153 return; 154 } 155 156 /* 157 * We've located the PCI BIOS service; get some information 158 * about it. 159 */ 160 if (pcibios_get_status(&rev_maj, &rev_min, &mech1, &mech2, 161 &scmech1, &scmech2, &pcibios_max_bus) != PCIBIOS_SUCCESS) { 162 /* 163 * We can't use the PCI BIOS; will fall back on old 164 * mechanism. 165 */ 166 return; 167 } 168 169 aprint_normal("PCI BIOS rev. %d.%d found at %#" PRIxPADDR "\n", 170 rev_maj, rev_min >> 4, ei.bei_entry); 171 aprint_verbose("pcibios: config mechanism %s%s, special cycles %s%s, " 172 "last bus %d\n", 173 mech1 ? "[1]" : "[x]", 174 mech2 ? "[2]" : "[x]", 175 scmech1 ? "[1]" : "[x]", 176 scmech2 ? "[2]" : "[x]", 177 pcibios_max_bus); 178 179 /* 180 * The PCI BIOS tells us the config mechanism; fill it in now 181 * so that pci_mode_detect() doesn't have to look for it. 182 */ 183 pci_mode_set(mech1 ? 1 : 2); 184 185 pcibios_present = 1; 186 187 /* 188 * Find the PCI IRQ Routing table. 189 */ 190 pcibios_pir_init(); 191 192 #ifdef PCI_INTR_FIXUP 193 if (pcibios_pir_table != NULL) { 194 int rv; 195 uint16_t pciirq; 196 197 /* 198 * Fixup interrupt routing. 199 */ 200 rv = pci_intr_fixup(NULL, x86_bus_space_io, &pciirq); 201 switch (rv) { 202 case -1: 203 /* Non-fatal error. */ 204 aprint_error("Warning: unable to fix up PCI interrupt " 205 "routing\n"); 206 break; 207 208 case 1: 209 /* Fatal error. */ 210 panic("pcibios_init: interrupt fixup failed"); 211 break; 212 } 213 214 /* 215 * XXX Clear `pciirq' from the ISA interrupt allocation 216 * XXX mask. 217 */ 218 } 219 #endif 220 } 221 222 void 223 pcibios_pir_init(void) 224 { 225 char *devinfo; 226 paddr_t pa; 227 char *p; 228 unsigned char cksum; 229 uint16_t tablesize; 230 uint8_t rev_maj, rev_min; 231 int i; 232 233 for (pa = PCI_IRQ_TABLE_START; pa < PCI_IRQ_TABLE_END; pa += 16) { 234 p = (void *)ISA_HOLE_VADDR(pa); 235 if (*(int *)p != BIOS32_MAKESIG('$', 'P', 'I', 'R')) { 236 /* 237 * XXX: Some laptops (Toshiba/Libretto L series) 238 * use _PIR instead of $PIR. So we try that too. 239 */ 240 if (*(int *)p != BIOS32_MAKESIG('_', 'P', 'I', 'R')) 241 continue; 242 } 243 244 rev_min = *(p + 4); 245 rev_maj = *(p + 5); 246 tablesize = *(uint16_t *)(p + 6); 247 248 cksum = 0; 249 for (i = 0; i < tablesize; i++) 250 cksum += *(unsigned char *)(p + i); 251 252 aprint_normal( 253 "PCI IRQ Routing Table rev. %d.%d found at %#" PRIxPADDR 254 ", size %d bytes (%d entries)\n", rev_maj, rev_min, pa, 255 tablesize, (tablesize - 32) / 16); 256 257 if (cksum != 0) { 258 aprint_error("pcibios_pir_init: bad IRQ table checksum\n"); 259 continue; 260 } 261 262 if (tablesize < 32 || (tablesize % 16) != 0) { 263 aprint_error("pcibios_pir_init: bad IRQ table size\n"); 264 continue; 265 } 266 267 if (rev_maj != 1 || rev_min != 0) { 268 aprint_error("pcibios_pir_init: unsupported IRQ table " 269 "version\n"); 270 continue; 271 } 272 273 /* 274 * We can handle this table! Make a copy of it. 275 */ 276 memcpy(&pcibios_pir_header, p, 32); 277 pcibios_pir_table = malloc(tablesize - 32, M_DEVBUF, 278 M_NOWAIT); 279 if (pcibios_pir_table == NULL) { 280 aprint_error("pcibios_pir_init: no memory for $PIR\n"); 281 return; 282 } 283 memcpy(pcibios_pir_table, p + 32, tablesize - 32); 284 pcibios_pir_table_nentries = (tablesize - 32) / 16; 285 286 aprint_verbose("PCI Interrupt Router at %03d:%02d:%01d", 287 pcibios_pir_header.router_bus, 288 PIR_DEVFUNC_DEVICE(pcibios_pir_header.router_devfunc), 289 PIR_DEVFUNC_FUNCTION(pcibios_pir_header.router_devfunc)); 290 if (pcibios_pir_header.compat_router != 0) { 291 devinfo = malloc(256, M_DEVBUF, M_NOWAIT); 292 if (devinfo) { 293 pci_devinfo(pcibios_pir_header.compat_router, 294 0, 0, devinfo, 256); 295 aprint_verbose(" (%s compatible)", devinfo); 296 free(devinfo, M_DEVBUF); 297 } 298 } 299 aprint_verbose("\n"); 300 pcibios_print_exclirq(); 301 302 #ifdef PCIBIOS_LIBRETTO_FIXUP 303 /* for Libretto L2/L3 hack */ 304 pcibios_fixup_pir_table(); 305 #endif 306 #ifdef PCIBIOS_SHARP_MM20_FIXUP 307 pcibios_mm20_fixup(); 308 #endif 309 #ifdef PCIINTR_DEBUG 310 pcibios_print_pir_table(); 311 #endif 312 return; 313 } 314 315 /* 316 * If there was no PIR table found, try using the PCI BIOS 317 * Get Interrupt Routing call. 318 * 319 * XXX The interface to this call sucks; just allocate enough 320 * XXX room for 32 entries. 321 */ 322 pcibios_pir_table_nentries = 32; 323 pcibios_pir_table = malloc(pcibios_pir_table_nentries * 324 sizeof(*pcibios_pir_table), M_DEVBUF, M_NOWAIT); 325 if (pcibios_pir_table == NULL) { 326 aprint_error("pcibios_pir_init: no memory for $PIR\n"); 327 return; 328 } 329 if (pcibios_get_intr_routing(pcibios_pir_table, 330 &pcibios_pir_table_nentries, 331 &pcibios_pir_header.exclusive_irq) != PCIBIOS_SUCCESS) { 332 aprint_normal("No PCI IRQ Routing information available.\n"); 333 free(pcibios_pir_table, M_DEVBUF); 334 pcibios_pir_table = NULL; 335 pcibios_pir_table_nentries = 0; 336 return; 337 } 338 aprint_verbose("PCI BIOS has %d Interrupt Routing table entries\n", 339 pcibios_pir_table_nentries); 340 pcibios_print_exclirq(); 341 342 #ifdef PCIBIOS_LIBRETTO_FIXUP 343 /* for Libretto L2/L3 hack */ 344 pcibios_fixup_pir_table(); 345 #endif 346 #ifdef PCIBIOS_SHARP_MM20_FIXUP 347 pcibios_mm20_fixup(); 348 #endif 349 #ifdef PCIINTR_DEBUG 350 pcibios_print_pir_table(); 351 #endif 352 } 353 354 int 355 pcibios_get_status(uint32_t *rev_maj, uint32_t *rev_min, 356 uint32_t *mech1, uint32_t *mech2, uint32_t *scmech1, uint32_t *scmech2, 357 uint32_t *maxbus) 358 { 359 uint16_t ax, bx, cx; 360 uint32_t edx; 361 int rv; 362 363 __asm volatile("lcall *(%%edi) ; \ 364 jc 1f ; \ 365 xor %%ah, %%ah ; \ 366 1:" 367 : "=a" (ax), "=b" (bx), "=c" (cx), "=d" (edx) 368 : "0" (0xb101), "D" (&pcibios_entry)); 369 370 rv = pcibios_return_code(ax, "pcibios_get_status"); 371 if (rv != PCIBIOS_SUCCESS) 372 return (rv); 373 374 if (edx != BIOS32_MAKESIG('P', 'C', 'I', ' ')) 375 return (PCIBIOS_SERVICE_NOT_PRESENT); /* XXX */ 376 377 /* 378 * Fill in the various pieces if info we're looking for. 379 */ 380 *mech1 = ax & 1; 381 *mech2 = ax & (1 << 1); 382 *scmech1 = ax & (1 << 4); 383 *scmech2 = ax & (1 << 5); 384 *rev_maj = (bx >> 8) & 0xff; 385 *rev_min = bx & 0xff; 386 *maxbus = cx & 0xff; 387 388 return (PCIBIOS_SUCCESS); 389 } 390 391 int 392 pcibios_get_intr_routing(struct pcibios_intr_routing *table, 393 int *nentries, uint16_t *exclirq) 394 { 395 uint16_t ax, bx; 396 int rv; 397 struct { 398 uint16_t size; 399 void *offset; 400 uint16_t segment; 401 } __packed args; 402 403 args.size = *nentries * sizeof(*table); 404 args.offset = (void *)table; 405 args.segment = GSEL(GDATA_SEL, SEL_KPL); 406 407 memset(table, 0, args.size); 408 409 __asm volatile("lcall *(%%esi) ; \ 410 jc 1f ; \ 411 xor %%ah, %%ah ; \ 412 1: movw %w2, %%ds ; \ 413 movw %w2, %%es" 414 : "=a" (ax), "=b" (bx) 415 : "r" GSEL(GDATA_SEL, SEL_KPL), "0" (0xb10e), "1" (0), 416 "D" (&args), "S" (&pcibios_entry)); 417 418 rv = pcibios_return_code(ax, "pcibios_get_intr_routing"); 419 if (rv != PCIBIOS_SUCCESS) 420 return (rv); 421 422 *nentries = args.size / sizeof(*table); 423 *exclirq = bx; 424 425 return (PCIBIOS_SUCCESS); 426 } 427 428 int 429 pcibios_return_code(uint16_t ax, const char *func) 430 { 431 const char *errstr; 432 int rv = ax >> 8; 433 434 switch (rv) { 435 case PCIBIOS_SUCCESS: 436 return (PCIBIOS_SUCCESS); 437 438 case PCIBIOS_SERVICE_NOT_PRESENT: 439 errstr = "service not present"; 440 break; 441 442 case PCIBIOS_FUNCTION_NOT_SUPPORTED: 443 errstr = "function not supported"; 444 break; 445 446 case PCIBIOS_BAD_VENDOR_ID: 447 errstr = "bad vendor ID"; 448 break; 449 450 case PCIBIOS_DEVICE_NOT_FOUND: 451 errstr = "device not found"; 452 break; 453 454 case PCIBIOS_BAD_REGISTER_NUMBER: 455 errstr = "bad register number"; 456 break; 457 458 case PCIBIOS_SET_FAILED: 459 errstr = "set failed"; 460 break; 461 462 case PCIBIOS_BUFFER_TOO_SMALL: 463 errstr = "buffer too small"; 464 break; 465 466 default: 467 aprint_error("%s: unknown return code 0x%x\n", func, rv); 468 return (rv); 469 } 470 471 aprint_error("%s: %s\n", func, errstr); 472 return (rv); 473 } 474 475 void 476 pcibios_print_exclirq(void) 477 { 478 int i; 479 480 if (pcibios_pir_header.exclusive_irq) { 481 aprint_verbose("PCI Exclusive IRQs:"); 482 for (i = 0; i < 16; i++) { 483 if (pcibios_pir_header.exclusive_irq & (1 << i)) 484 aprint_verbose(" %d", i); 485 } 486 aprint_verbose("\n"); 487 } 488 } 489 490 #ifdef PCIBIOS_LIBRETTO_FIXUP 491 /* for Libretto L2/L3 hack */ 492 static void 493 pcibios_fixup_pir_table(void) 494 { 495 struct pcibios_linkmap *m; 496 497 for (m = pir_mask; m->link != 0; m++) 498 pcibios_fixup_pir_table_mask(m); 499 } 500 501 void 502 pcibios_fixup_pir_table_mask(struct pcibios_linkmap *mask) 503 { 504 int i, j; 505 506 for (i = 0; i < pcibios_pir_table_nentries; i++) { 507 for (j = 0; j < 4; j++) { 508 if (pcibios_pir_table[i].linkmap[j].link == mask->link) { 509 pcibios_pir_table[i].linkmap[j].bitmap 510 &= mask->bitmap; 511 } 512 } 513 } 514 } 515 #endif 516 517 #ifdef PCIINTR_DEBUG 518 void 519 pcibios_print_pir_table(void) 520 { 521 int i, j; 522 523 for (i = 0; i < pcibios_pir_table_nentries; i++) { 524 printf("PIR Entry %d:\n", i); 525 printf("\tBus: %d Device: %d\n", 526 pcibios_pir_table[i].bus, 527 PIR_DEVFUNC_DEVICE(pcibios_pir_table[i].device)); 528 for (j = 0; j < 4; j++) { 529 printf("\t\tINT%c: link 0x%02x bitmap 0x%04x\n", 530 'A' + j, 531 pcibios_pir_table[i].linkmap[j].link, 532 pcibios_pir_table[i].linkmap[j].bitmap); 533 } 534 } 535 } 536 #endif 537 538 #ifdef PCIBIOS_SHARP_MM20_FIXUP 539 /* 540 * This is a gross hack to get the interrupt from the EHCI controller 541 * working on a Sharp MM20. The BIOS is just incredibly buggy. 542 * 543 * The story thus far: 544 * The modern way to route the interrupt is to use ACPI. But using 545 * ACPI fails with an error message about an uninitialized local 546 * variable in the AML code. (It works in Windows, but fails in NetBSD 547 * and Linux.) 548 * 549 * The second attempt is to use PCI Interrupt Routing table. But this 550 * fails because the table does not contain any information about the 551 * interrupt from the EHCI controller. This is probably due to the fact 552 * that the table is compatible with ALi M1543, but the MM20 has an ALi M1563. 553 * The M1563 has additional interrupt lines. The ali1543.c code also 554 * cannot handle the M1653's extended interrupts. And fixing this is 555 * difficult since getting a data sheet from ALi requires signing an NDA. 556 * 557 * The third attempt is to use a BIOS call to route the interrupt 558 * (as FreeBSD does) with manually generated information. But the BIOS call 559 * fails because the BIOS code is not quite position independent. It makes 560 * some assumption about where the code segment register points. 561 * 562 * So the solution is to use the third attempt, but with a patched version 563 * of the BIOS. 564 * -- lennart@augustsson.net 565 */ 566 567 #define BIOS32_START 0xe0000 568 #define BIOS32_SIZE 0x20000 569 570 static char pcibios_shadow[BIOS32_SIZE]; 571 static struct bios32_entry pcibios_entry_shadow; 572 573 /* 574 * Copy BIOS and zap offending instruction. 575 * The bad instruction is 576 * mov %cs:0x63c(%ebx),%ah 577 * NetBSD does not have the code segment set up for this to work. 578 * Using the value 0xff for the table entry seems to work. 579 * The replacement is 580 * mov $0xff,%ah; nop; nop; nop; nop; nop 581 */ 582 static void 583 pcibios_copy_bios(void) 584 { 585 uint8_t *bad_instr; 586 587 memcpy(pcibios_shadow, ISA_HOLE_VADDR(BIOS32_START), BIOS32_SIZE); 588 pcibios_entry_shadow = pcibios_entry; 589 pcibios_entry_shadow.offset = 590 (void*)((u_long)pcibios_shadow + 591 (u_long)pcibios_entry.offset - 592 (u_long)ISA_HOLE_VADDR(BIOS32_START)); 593 594 bad_instr = (uint8_t *)pcibios_entry_shadow.offset + 0x499; 595 if (*bad_instr != 0x2e) 596 panic("bad bios"); 597 bad_instr[0] = 0xb4; bad_instr[1] = 0xff; /* mov $0xff,%ah */ 598 bad_instr[2] = 0x90; /* nop */ 599 bad_instr[3] = 0x90; /* nop */ 600 bad_instr[4] = 0x90; /* nop */ 601 bad_instr[5] = 0x90; /* nop */ 602 bad_instr[6] = 0x90; /* nop */ 603 } 604 605 /* 606 * Call BIOS to route an interrupt. 607 * The PCI device is identified by bus,device,func. 608 * The interrupt is on pin PIN (A-D) and interrupt IRQ. 609 * BIOS knows the magic for the interrupt controller. 610 */ 611 static int 612 pcibios_biosroute(int bus, int device, int func, int pin, int irq) 613 { 614 uint16_t ax, bx, cx; 615 int rv; 616 617 aprint_debug("pcibios_biosroute: b,d,f=%d,%d,%d pin=%x irq=%d\n", 618 bus, device, func, pin+0xa, irq); 619 620 bx = (bus << 8) | (device << 3) | func; 621 cx = (irq << 8) | (0xa + pin); 622 623 __asm volatile("lcall *(%%esi) ; \ 624 jc 1f ; \ 625 xor %%ah, %%ah ; \ 626 1: movw %w1, %%ds ; \ 627 movw %w1, %%es" 628 : "=a" (ax) 629 : "r" GSEL(GDATA_SEL, SEL_KPL), "0" (0xb10f), 630 "b" (bx), "c" (cx), 631 "S" (&pcibios_entry_shadow)); 632 633 rv = pcibios_return_code(ax, "pcibios_biosroute"); 634 635 return rv; 636 } 637 638 #define MM20_PCI_BUS 0 639 #define MM20_PCI_EHCI_DEV 15 640 #define MM20_PCI_EHCI_FUNC 3 641 #define MM20_PCI_EHCI_PIN 3 642 #define MM20_PCI_EHCI_INTR 11 643 #define MM20_PCI_ISA_DEV 3 644 #define MM20_PCI_ISA_FUNC 0 645 646 static void 647 pcibios_mm20_fixup(void) 648 { 649 pci_chipset_tag_t pc; 650 pcitag_t tag; 651 652 /* Copy BIOS */ 653 pcibios_copy_bios(); 654 /* Route the interrupt for the EHCI controller. */ 655 (void)pcibios_biosroute(MM20_PCI_BUS, 656 MM20_PCI_EHCI_DEV, 657 MM20_PCI_EHCI_FUNC, 658 MM20_PCI_EHCI_PIN, 659 MM20_PCI_EHCI_INTR); 660 661 /* Fake some tags. */ 662 pc = NULL; 663 tag = pci_make_tag(pc, MM20_PCI_BUS, MM20_PCI_EHCI_DEV, 664 MM20_PCI_EHCI_FUNC); 665 /* Set interrupt register in EHCI controller */ 666 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, 667 0x50000400 + MM20_PCI_EHCI_INTR); 668 tag = pci_make_tag(pc, MM20_PCI_BUS, MM20_PCI_ISA_DEV, 669 MM20_PCI_ISA_FUNC); 670 /* Set some unknown registers in the ISA bridge. */ 671 pci_conf_write(pc, tag, 0x58, 0xd87f5300); 672 pci_conf_write(pc, tag, 0x74, 0x00000009); 673 } 674 675 #endif /* PCIBIOS_SHARP_MM20_FIXUP */ 676