helper_exec.c revision 5a112b11
1/* 2 * XFree86 int10 module 3 * execute BIOS int 10h calls in x86 real mode environment 4 * Copyright 1999 Egbert Eich 5 * 6 * Part of this code was inspired by the VBIOS POSTing code in DOSEMU 7 * developed by the "DOSEMU-Development-Team" 8 */ 9 10/* 11 * To debug port accesses define PRINT_PORT to 1. 12 * Note! You also have to comment out ioperm() 13 * in xf86EnableIO(). Otherwise we won't trap 14 * on PIO. 15 */ 16 17#ifdef HAVE_XORG_CONFIG_H 18#include <xorg-config.h> 19#endif 20 21#define PRINT_PORT 0 22 23#include <unistd.h> 24 25#include <X11/Xos.h> 26#include "xf86.h" 27#include "xf86_OSproc.h" 28#include "compiler.h" 29#define _INT10_PRIVATE 30#include "int10Defines.h" 31#include "xf86int10.h" 32#include "Pci.h" 33#ifdef _X86EMU 34#include "x86emu/x86emui.h" 35#else 36#define DEBUG_IO_TRACE() 0 37#endif 38#include <pciaccess.h> 39 40static int pciCfg1in(uint16_t addr, uint32_t *val); 41static int pciCfg1out(uint16_t addr, uint32_t val); 42static int pciCfg1inw(uint16_t addr, uint16_t *val); 43static int pciCfg1outw(uint16_t addr, uint16_t val); 44static int pciCfg1inb(uint16_t addr, uint8_t *val); 45static int pciCfg1outb(uint16_t addr, uint8_t val); 46 47#if defined (_PC) 48static void SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set); 49#endif 50 51#define REG pInt 52 53int 54setup_int(xf86Int10InfoPtr pInt) 55{ 56 if (pInt != Int10Current) { 57 if (!MapCurrentInt10(pInt)) 58 return -1; 59 Int10Current = pInt; 60 } 61 X86_EAX = (uint32_t) pInt->ax; 62 X86_EBX = (uint32_t) pInt->bx; 63 X86_ECX = (uint32_t) pInt->cx; 64 X86_EDX = (uint32_t) pInt->dx; 65 X86_ESI = (uint32_t) pInt->si; 66 X86_EDI = (uint32_t) pInt->di; 67 X86_EBP = (uint32_t) pInt->bp; 68 X86_ESP = 0x1000; 69 X86_SS = pInt->stackseg >> 4; 70 X86_EIP = 0x0600; 71 X86_CS = 0x0; /* address of 'hlt' */ 72 X86_DS = 0x40; /* standard pc ds */ 73 X86_ES = pInt->es; 74 X86_FS = 0; 75 X86_GS = 0; 76 X86_EFLAGS = X86_IF_MASK | X86_IOPL_MASK; 77#if defined (_PC) 78 if (pInt->Flags & SET_BIOS_SCRATCH) 79 SetResetBIOSVars(pInt, TRUE); 80#endif 81 OsBlockSignals(); 82 return 0; 83} 84 85void 86finish_int(xf86Int10InfoPtr pInt, int sig) 87{ 88 OsReleaseSignals(); 89 pInt->ax = (uint32_t) X86_EAX; 90 pInt->bx = (uint32_t) X86_EBX; 91 pInt->cx = (uint32_t) X86_ECX; 92 pInt->dx = (uint32_t) X86_EDX; 93 pInt->si = (uint32_t) X86_ESI; 94 pInt->di = (uint32_t) X86_EDI; 95 pInt->es = (uint16_t) X86_ES; 96 pInt->bp = (uint32_t) X86_EBP; 97 pInt->flags = (uint32_t) X86_FLAGS; 98#if defined (_PC) 99 if (pInt->Flags & RESTORE_BIOS_SCRATCH) 100 SetResetBIOSVars(pInt, FALSE); 101#endif 102} 103 104/* general software interrupt handler */ 105uint32_t 106getIntVect(xf86Int10InfoPtr pInt, int num) 107{ 108 return MEM_RW(pInt, num << 2) + (MEM_RW(pInt, (num << 2) + 2) << 4); 109} 110 111void 112pushw(xf86Int10InfoPtr pInt, uint16_t val) 113{ 114 X86_ESP -= 2; 115 MEM_WW(pInt, ((uint32_t) X86_SS << 4) + X86_SP, val); 116} 117 118int 119run_bios_int(int num, xf86Int10InfoPtr pInt) 120{ 121 uint32_t eflags; 122 123#ifndef _PC 124 /* check if bios vector is initialized */ 125 if (MEM_RW(pInt, (num << 2) + 2) == (SYS_BIOS >> 4)) { /* SYS_BIOS_SEG ? */ 126 127 if (num == 21 && X86_AH == 0x4e) { 128 xf86DrvMsg(pInt->pScrn->scrnIndex, X_NOTICE, 129 "Failing Find-Matching-File on non-PC" 130 " (int 21, func 4e)\n"); 131 X86_AX = 2; 132 SET_FLAG(F_CF); 133 return 1; 134 } 135 else { 136 xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2, 137 "Ignoring int 0x%02x call\n", num); 138 if (xf86GetVerbosity() > 3) { 139 dump_registers(pInt); 140 stack_trace(pInt); 141 } 142 return 1; 143 } 144 } 145#endif 146#ifdef PRINT_INT 147 ErrorF("calling card BIOS at: "); 148#endif 149 eflags = X86_EFLAGS; 150#if 0 151 eflags = eflags | IF_MASK; 152 X86_EFLAGS = X86_EFLAGS & ~(VIF_MASK | TF_MASK | IF_MASK | NT_MASK); 153#endif 154 pushw(pInt, eflags); 155 pushw(pInt, X86_CS); 156 pushw(pInt, X86_IP); 157 X86_CS = MEM_RW(pInt, (num << 2) + 2); 158 X86_IP = MEM_RW(pInt, num << 2); 159#ifdef PRINT_INT 160 ErrorF("0x%x:%lx\n", X86_CS, X86_EIP); 161#endif 162 return 1; 163} 164 165/* Debugging stuff */ 166void 167dump_code(xf86Int10InfoPtr pInt) 168{ 169 int i; 170 uint32_t lina = SEG_ADR((uint32_t), X86_CS, IP); 171 172 xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_INFO, 3, "code at 0x%8.8" PRIx32 ":\n", 173 (unsigned) lina); 174 for (i = 0; i < 0x10; i++) 175 xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i)); 176 xf86ErrorFVerb(3, "\n"); 177 for (; i < 0x20; i++) 178 xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i)); 179 xf86ErrorFVerb(3, "\n"); 180} 181 182void 183dump_registers(xf86Int10InfoPtr pInt) 184{ 185 xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_INFO, 3, 186 "EAX=0x%8.8lx, EBX=0x%8.8lx, ECX=0x%8.8lx, EDX=0x%8.8lx\n", 187 (unsigned long) X86_EAX, (unsigned long) X86_EBX, 188 (unsigned long) X86_ECX, (unsigned long) X86_EDX); 189 xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_INFO, 3, 190 "ESP=0x%8.8lx, EBP=0x%8.8lx, ESI=0x%8.8lx, EDI=0x%8.8lx\n", 191 (unsigned long) X86_ESP, (unsigned long) X86_EBP, 192 (unsigned long) X86_ESI, (unsigned long) X86_EDI); 193 xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_INFO, 3, 194 "CS=0x%4.4x, SS=0x%4.4x," 195 " DS=0x%4.4x, ES=0x%4.4x, FS=0x%4.4x, GS=0x%4.4x\n", 196 X86_CS, X86_SS, X86_DS, X86_ES, X86_FS, X86_GS); 197 xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_INFO, 3, 198 "EIP=0x%8.8lx, EFLAGS=0x%8.8lx\n", 199 (unsigned long) X86_EIP, (unsigned long) X86_EFLAGS); 200} 201 202void 203stack_trace(xf86Int10InfoPtr pInt) 204{ 205 int i = 0; 206 unsigned long stack = SEG_ADR((uint32_t), X86_SS, SP); 207 unsigned long tail = (uint32_t) ((X86_SS << 4) + 0x1000); 208 209 if (stack >= tail) 210 return; 211 212 xf86MsgVerb(X_INFO, 3, "stack at 0x%8.8lx:\n", stack); 213 for (; stack < tail; stack++) { 214 xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, stack)); 215 i = (i + 1) % 0x10; 216 if (!i) 217 xf86ErrorFVerb(3, "\n"); 218 } 219 if (i) 220 xf86ErrorFVerb(3, "\n"); 221} 222 223int 224port_rep_inb(xf86Int10InfoPtr pInt, 225 uint16_t port, uint32_t base, int d_f, uint32_t count) 226{ 227 register int inc = d_f ? -1 : 1; 228 uint32_t dst = base; 229 230 if (PRINT_PORT && DEBUG_IO_TRACE()) 231 ErrorF(" rep_insb(%#x) %" PRIu32 " bytes at %8.8" PRIx32 " %s\n", 232 port, (unsigned) count, (unsigned) base, d_f ? "up" : "down"); 233 while (count--) { 234 MEM_WB(pInt, dst, x_inb(port)); 235 dst += inc; 236 } 237 return dst - base; 238} 239 240int 241port_rep_inw(xf86Int10InfoPtr pInt, 242 uint16_t port, uint32_t base, int d_f, uint32_t count) 243{ 244 register int inc = d_f ? -2 : 2; 245 uint32_t dst = base; 246 247 if (PRINT_PORT && DEBUG_IO_TRACE()) 248 ErrorF(" rep_insw(%#x) %" PRIu32 " bytes at %8.8" PRIx32 " %s\n", 249 port, (unsigned) count, (unsigned) base, d_f ? "up" : "down"); 250 while (count--) { 251 MEM_WW(pInt, dst, x_inw(port)); 252 dst += inc; 253 } 254 return dst - base; 255} 256 257int 258port_rep_inl(xf86Int10InfoPtr pInt, 259 uint16_t port, uint32_t base, int d_f, uint32_t count) 260{ 261 register int inc = d_f ? -4 : 4; 262 uint32_t dst = base; 263 264 if (PRINT_PORT && DEBUG_IO_TRACE()) 265 ErrorF(" rep_insl(%#x) %" PRIu32 " bytes at %8.8" PRIx32 " %s\n", 266 port, (unsigned) count, (unsigned) base, d_f ? "up" : "down"); 267 while (count--) { 268 MEM_WL(pInt, dst, x_inl(port)); 269 dst += inc; 270 } 271 return dst - base; 272} 273 274int 275port_rep_outb(xf86Int10InfoPtr pInt, 276 uint16_t port, uint32_t base, int d_f, uint32_t count) 277{ 278 register int inc = d_f ? -1 : 1; 279 uint32_t dst = base; 280 281 if (PRINT_PORT && DEBUG_IO_TRACE()) 282 ErrorF(" rep_outb(%#x) %" PRIu32 " bytes at %8.8" PRIx32 " %s\n", 283 port, (unsigned) count, (unsigned) base, d_f ? "up" : "down"); 284 while (count--) { 285 x_outb(port, MEM_RB(pInt, dst)); 286 dst += inc; 287 } 288 return dst - base; 289} 290 291int 292port_rep_outw(xf86Int10InfoPtr pInt, 293 uint16_t port, uint32_t base, int d_f, uint32_t count) 294{ 295 register int inc = d_f ? -2 : 2; 296 uint32_t dst = base; 297 298 if (PRINT_PORT && DEBUG_IO_TRACE()) 299 ErrorF(" rep_outw(%#x) %" PRIu32 " bytes at %8.8" PRIx32 " %s\n", 300 port, (unsigned) count, (unsigned) base, d_f ? "up" : "down"); 301 while (count--) { 302 x_outw(port, MEM_RW(pInt, dst)); 303 dst += inc; 304 } 305 return dst - base; 306} 307 308int 309port_rep_outl(xf86Int10InfoPtr pInt, 310 uint16_t port, uint32_t base, int d_f, uint32_t count) 311{ 312 register int inc = d_f ? -4 : 4; 313 uint32_t dst = base; 314 315 if (PRINT_PORT && DEBUG_IO_TRACE()) 316 ErrorF(" rep_outl(%#x) %" PRIu32 " bytes at %8.8" PRIx32 " %s\n", 317 port, (unsigned) count, (unsigned) base, d_f ? "up" : "down"); 318 while (count--) { 319 x_outl(port, MEM_RL(pInt, dst)); 320 dst += inc; 321 } 322 return dst - base; 323} 324 325uint8_t 326x_inb(uint16_t port) 327{ 328 uint8_t val; 329 330 if (port == 0x40) { 331 Int10Current->inb40time++; 332 val = (uint8_t) (Int10Current->inb40time >> 333 ((Int10Current->inb40time & 1) << 3)); 334 if (PRINT_PORT && DEBUG_IO_TRACE()) 335 ErrorF(" inb(%#x) = %2.2x\n", port, val); 336#ifdef __NOT_YET__ 337 } 338 else if (port < 0x0100) { /* Don't interfere with mainboard */ 339 val = 0; 340 xf86DrvMsgVerb(Int10Current->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2, 341 "inb 0x%4.4x\n", port); 342 if (xf86GetVerbosity() > 3) { 343 dump_registers(Int10Current); 344 stack_trace(Int10Current); 345 } 346#endif /* __NOT_YET__ */ 347 } 348 else if (!pciCfg1inb(port, &val)) { 349 val = pci_io_read8(Int10Current->io, port); 350 if (PRINT_PORT && DEBUG_IO_TRACE()) 351 ErrorF(" inb(%#x) = %2.2x\n", port, val); 352 } 353 return val; 354} 355 356uint16_t 357x_inw(uint16_t port) 358{ 359 uint16_t val; 360 361 if (port == 0x5c) { 362 struct timeval tv; 363 364 /* 365 * Emulate a PC's timer. Typical resolution is 3.26 usec. 366 * Approximate this by dividing by 3. 367 */ 368 X_GETTIMEOFDAY(&tv); 369 val = (uint16_t) (tv.tv_usec / 3); 370 } 371 else if (!pciCfg1inw(port, &val)) { 372 val = pci_io_read16(Int10Current->io, port); 373 if (PRINT_PORT && DEBUG_IO_TRACE()) 374 ErrorF(" inw(%#x) = %4.4x\n", port, val); 375 } 376 return val; 377} 378 379void 380x_outb(uint16_t port, uint8_t val) 381{ 382 if ((port == 0x43) && (val == 0)) { 383 struct timeval tv; 384 385 /* 386 * Emulate a PC's timer 0. Such timers typically have a resolution of 387 * some .838 usec per tick, but this can only provide 1 usec per tick. 388 * (Not that this matters much, given inherent emulation delays.) Use 389 * the bottom bit as a byte select. See inb(0x40) above. 390 */ 391 X_GETTIMEOFDAY(&tv); 392 Int10Current->inb40time = (uint16_t) (tv.tv_usec | 1); 393 if (PRINT_PORT && DEBUG_IO_TRACE()) 394 ErrorF(" outb(%#x, %2.2x)\n", port, val); 395#ifdef __NOT_YET__ 396 } 397 else if (port < 0x0100) { /* Don't interfere with mainboard */ 398 xf86DrvMsgVerb(Int10Current->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2, 399 "outb 0x%4.4x,0x%2.2x\n", port, val); 400 if (xf86GetVerbosity() > 3) { 401 dump_registers(Int10Current); 402 stack_trace(Int10Current); 403 } 404#endif /* __NOT_YET__ */ 405 } 406 else if (!pciCfg1outb(port, val)) { 407 if (PRINT_PORT && DEBUG_IO_TRACE()) 408 ErrorF(" outb(%#x, %2.2x)\n", port, val); 409 pci_io_write8(Int10Current->io, port, val); 410 } 411} 412 413void 414x_outw(uint16_t port, uint16_t val) 415{ 416 417 if (!pciCfg1outw(port, val)) { 418 if (PRINT_PORT && DEBUG_IO_TRACE()) 419 ErrorF(" outw(%#x, %4.4x)\n", port, val); 420 pci_io_write16(Int10Current->io, port, val); 421 } 422} 423 424uint32_t 425x_inl(uint16_t port) 426{ 427 uint32_t val; 428 429 if (!pciCfg1in(port, &val)) { 430 val = pci_io_read32(Int10Current->io, port); 431 if (PRINT_PORT && DEBUG_IO_TRACE()) 432 ErrorF(" inl(%#x) = %8.8" PRIx32 "\n", port, (unsigned) val); 433 } 434 return val; 435} 436 437void 438x_outl(uint16_t port, uint32_t val) 439{ 440 if (!pciCfg1out(port, val)) { 441 if (PRINT_PORT && DEBUG_IO_TRACE()) 442 ErrorF(" outl(%#x, %8.8" PRIx32 ")\n", port, (unsigned) val); 443 pci_io_write32(Int10Current->io, port, val); 444 } 445} 446 447uint8_t 448Mem_rb(uint32_t addr) 449{ 450 return (*Int10Current->mem->rb) (Int10Current, addr); 451} 452 453uint16_t 454Mem_rw(uint32_t addr) 455{ 456 return (*Int10Current->mem->rw) (Int10Current, addr); 457} 458 459uint32_t 460Mem_rl(uint32_t addr) 461{ 462 return (*Int10Current->mem->rl) (Int10Current, addr); 463} 464 465void 466Mem_wb(uint32_t addr, uint8_t val) 467{ 468 (*Int10Current->mem->wb) (Int10Current, addr, val); 469} 470 471void 472Mem_ww(uint32_t addr, uint16_t val) 473{ 474 (*Int10Current->mem->ww) (Int10Current, addr, val); 475} 476 477void 478Mem_wl(uint32_t addr, uint32_t val) 479{ 480 (*Int10Current->mem->wl) (Int10Current, addr, val); 481} 482 483static uint32_t PciCfg1Addr = 0; 484 485#define PCI_DOM_FROM_TAG(tag) (((tag) >> 24) & (PCI_DOM_MASK)) 486#define PCI_BUS_FROM_TAG(tag) (((tag) >> 16) & (PCI_DOMBUS_MASK)) 487#define PCI_DEV_FROM_TAG(tag) (((tag) & 0x0000f800u) >> 11) 488#define PCI_FUNC_FROM_TAG(tag) (((tag) & 0x00000700u) >> 8) 489 490#define PCI_OFFSET(x) ((x) & 0x000000ff) 491#define PCI_TAG(x) ((x) & 0x7fffff00) 492 493static struct pci_device * 494pci_device_for_cfg_address(uint32_t addr) 495{ 496 struct pci_device *dev = NULL; 497 uint32_t tag = PCI_TAG(addr); 498 499 struct pci_slot_match slot_match = { 500 .domain = PCI_DOM_FROM_TAG(tag), 501 .bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(tag)), 502 .dev = PCI_DEV_FROM_TAG(tag), 503 .func = PCI_FUNC_FROM_TAG(tag), 504 .match_data = 0 505 }; 506 507 struct pci_device_iterator *iter = 508 pci_slot_match_iterator_create(&slot_match); 509 510 if (iter) 511 dev = pci_device_next(iter); 512 513 pci_iterator_destroy(iter); 514 515 return dev; 516} 517 518static int 519pciCfg1in(uint16_t addr, uint32_t *val) 520{ 521 if (addr == 0xCF8) { 522 *val = PciCfg1Addr; 523 return 1; 524 } 525 if (addr == 0xCFC) { 526 pci_device_cfg_read_u32(pci_device_for_cfg_address(PciCfg1Addr), 527 /* 528 * XXXMRG 529 * this one is OK - CARD32 is "long" for 32 bit 530 * and "int" for 64 bit 531 */ 532 (uint32_t *) val, PCI_OFFSET(PciCfg1Addr)); 533 if (PRINT_PORT && DEBUG_IO_TRACE()) 534 ErrorF(" cfg_inl(%#" PRIx32 ") = %8.8" PRIx32 "\n", (unsigned) PciCfg1Addr, 535 (unsigned) *val); 536 return 1; 537 } 538 return 0; 539} 540 541static int 542pciCfg1out(uint16_t addr, uint32_t val) 543{ 544 if (addr == 0xCF8) { 545 PciCfg1Addr = val; 546 return 1; 547 } 548 if (addr == 0xCFC) { 549 if (PRINT_PORT && DEBUG_IO_TRACE()) 550 ErrorF(" cfg_outl(%#" PRIx32 ", %8.8" PRIx32 ")\n", (unsigned) PciCfg1Addr, 551 (unsigned) val); 552 pci_device_cfg_write_u32(pci_device_for_cfg_address(PciCfg1Addr), val, 553 PCI_OFFSET(PciCfg1Addr)); 554 return 1; 555 } 556 return 0; 557} 558 559static int 560pciCfg1inw(uint16_t addr, uint16_t *val) 561{ 562 int shift; 563 564 if ((addr >= 0xCF8) && (addr <= 0xCFB)) { 565 shift = (addr - 0xCF8) * 8; 566 *val = (PciCfg1Addr >> shift) & 0xffff; 567 return 1; 568 } 569 if ((addr >= 0xCFC) && (addr <= 0xCFF)) { 570 const unsigned offset = addr - 0xCFC; 571 572 pci_device_cfg_read_u16(pci_device_for_cfg_address(PciCfg1Addr), 573 val, PCI_OFFSET(PciCfg1Addr) + offset); 574 if (PRINT_PORT && DEBUG_IO_TRACE()) 575 ErrorF(" cfg_inw(%#" PRIx32 ") = %4.4x\n", (unsigned) (PciCfg1Addr + offset), 576 (unsigned) *val); 577 return 1; 578 } 579 return 0; 580} 581 582static int 583pciCfg1outw(uint16_t addr, uint16_t val) 584{ 585 int shift; 586 587 if ((addr >= 0xCF8) && (addr <= 0xCFB)) { 588 shift = (addr - 0xCF8) * 8; 589 PciCfg1Addr &= ~(0xffff << shift); 590 PciCfg1Addr |= ((uint32_t) val) << shift; 591 return 1; 592 } 593 if ((addr >= 0xCFC) && (addr <= 0xCFF)) { 594 const unsigned offset = addr - 0xCFC; 595 596 if (PRINT_PORT && DEBUG_IO_TRACE()) 597 ErrorF(" cfg_outw(%#" PRIx32 ", %4.4x)\n", (unsigned) (PciCfg1Addr + offset), 598 (unsigned) val); 599 pci_device_cfg_write_u16(pci_device_for_cfg_address(PciCfg1Addr), val, 600 PCI_OFFSET(PciCfg1Addr) + offset); 601 return 1; 602 } 603 return 0; 604} 605 606static int 607pciCfg1inb(uint16_t addr, uint8_t *val) 608{ 609 int shift; 610 611 if ((addr >= 0xCF8) && (addr <= 0xCFB)) { 612 shift = (addr - 0xCF8) * 8; 613 *val = (PciCfg1Addr >> shift) & 0xff; 614 return 1; 615 } 616 if ((addr >= 0xCFC) && (addr <= 0xCFF)) { 617 const unsigned offset = addr - 0xCFC; 618 619 pci_device_cfg_read_u8(pci_device_for_cfg_address(PciCfg1Addr), 620 val, PCI_OFFSET(PciCfg1Addr) + offset); 621 if (PRINT_PORT && DEBUG_IO_TRACE()) 622 ErrorF(" cfg_inb(%#" PRIx32 ") = %2.2x\n", (unsigned) (PciCfg1Addr + offset), 623 (unsigned) *val); 624 return 1; 625 } 626 return 0; 627} 628 629static int 630pciCfg1outb(uint16_t addr, uint8_t val) 631{ 632 int shift; 633 634 if ((addr >= 0xCF8) && (addr <= 0xCFB)) { 635 shift = (addr - 0xCF8) * 8; 636 PciCfg1Addr &= ~(0xff << shift); 637 PciCfg1Addr |= ((uint32_t) val) << shift; 638 return 1; 639 } 640 if ((addr >= 0xCFC) && (addr <= 0xCFF)) { 641 const unsigned offset = addr - 0xCFC; 642 643 if (PRINT_PORT && DEBUG_IO_TRACE()) 644 ErrorF(" cfg_outb(%#" PRIx32 ", %2.2x)\n", (unsigned) (PciCfg1Addr + offset), 645 (unsigned) val); 646 pci_device_cfg_write_u8(pci_device_for_cfg_address(PciCfg1Addr), val, 647 PCI_OFFSET(PciCfg1Addr) + offset); 648 return 1; 649 } 650 return 0; 651} 652 653uint8_t 654bios_checksum(const uint8_t *start, int size) 655{ 656 uint8_t sum = 0; 657 658 while (size-- > 0) 659 sum += *start++; 660 return sum; 661} 662 663/* 664 * Lock/Unlock legacy VGA. Some Bioses try to be very clever and make 665 * an attempt to detect a legacy ISA card. If they find one they might 666 * act very strange: for example they might configure the card as a 667 * monochrome card. This might cause some drivers to choke. 668 * To avoid this we attempt legacy VGA by writing to all known VGA 669 * disable registers before we call the BIOS initialization and 670 * restore the original values afterwards. In between we hold our 671 * breath. To get to a (possibly existing) ISA card need to disable 672 * our current PCI card. 673 */ 674/* 675 * This is just for booting: we just want to catch pure 676 * legacy vga therefore we don't worry about mmio etc. 677 * This stuff should really go into vgaHW.c. However then 678 * the driver would have to load the vga-module prior to 679 * doing int10. 680 */ 681void 682LockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga) 683{ 684#ifndef NO_LEGACY_VGA 685 vga->save_msr = pci_io_read8(pInt->io, 0x03CC); 686 vga->save_vse = pci_io_read8(pInt->io, 0x03C3); 687#ifndef __ia64__ 688 vga->save_46e8 = pci_io_read8(pInt->io, 0x46E8); 689#endif 690 vga->save_pos102 = pci_io_read8(pInt->io, 0x0102); 691 pci_io_write8(pInt->io, 0x03C2, ~(uint8_t) 0x03 & vga->save_msr); 692 pci_io_write8(pInt->io, 0x03C3, ~(uint8_t) 0x01 & vga->save_vse); 693#ifndef __ia64__ 694 pci_io_write8(pInt->io, 0x46E8, ~(uint8_t) 0x08 & vga->save_46e8); 695#endif 696 pci_io_write8(pInt->io, 0x0102, ~(uint8_t) 0x01 & vga->save_pos102); 697#endif 698} 699 700void 701UnlockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga) 702{ 703#ifndef NO_LEGACY_VGA 704 pci_io_write8(pInt->io, 0x0102, vga->save_pos102); 705#ifndef __ia64__ 706 pci_io_write8(pInt->io, 0x46E8, vga->save_46e8); 707#endif 708 pci_io_write8(pInt->io, 0x03C3, vga->save_vse); 709 pci_io_write8(pInt->io, 0x03C2, vga->save_msr); 710#endif 711} 712 713#if defined (_PC) 714static void 715SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set) 716{ 717 int pagesize = getpagesize(); 718 unsigned char *base; 719 int i; 720 721 if (pci_device_map_legacy 722 (pInt->dev, 0, pagesize, PCI_DEV_MAP_FLAG_WRITABLE, (void **) &base)) 723 return; /* eek */ 724 725 if (set) { 726 for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++) 727 MEM_WW(pInt, i, *(base + i)); 728 } 729 else { 730 for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++) 731 *(base + i) = MEM_RW(pInt, i); 732 } 733 734 pci_device_unmap_legacy(pInt->dev, base, pagesize); 735} 736 737void 738xf86Int10SaveRestoreBIOSVars(xf86Int10InfoPtr pInt, Bool save) 739{ 740 int pagesize = getpagesize(); 741 unsigned char *base; 742 int i; 743 744 if (!xf86IsEntityPrimary(pInt->entityIndex) 745 || (!save && !pInt->BIOSScratch)) 746 return; 747 748 if (pci_device_map_legacy 749 (pInt->dev, 0, pagesize, PCI_DEV_MAP_FLAG_WRITABLE, (void **) &base)) 750 return; /* eek */ 751 752 base += BIOS_SCRATCH_OFF; 753 if (save) { 754 if ((pInt->BIOSScratch = xnfalloc(BIOS_SCRATCH_LEN))) 755 for (i = 0; i < BIOS_SCRATCH_LEN; i++) 756 *(((char *) pInt->BIOSScratch + i)) = *(base + i); 757 } 758 else { 759 if (pInt->BIOSScratch) { 760 for (i = 0; i < BIOS_SCRATCH_LEN; i++) 761 *(base + i) = *(pInt->BIOSScratch + i); 762 free(pInt->BIOSScratch); 763 pInt->BIOSScratch = NULL; 764 } 765 } 766 767 pci_device_unmap_legacy(pInt->dev, base - BIOS_SCRATCH_OFF, pagesize); 768} 769#endif 770 771xf86Int10InfoPtr 772xf86InitInt10(int entityIndex) 773{ 774 return xf86ExtendedInitInt10(entityIndex, 0); 775} 776