helper_exec.c (21448B)
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 40 static int pciCfg1in(uint16_t addr, uint32_t *val); 41 static int pciCfg1out(uint16_t addr, uint32_t val); 42 static int pciCfg1inw(uint16_t addr, uint16_t *val); 43 static int pciCfg1outw(uint16_t addr, uint16_t val); 44 static int pciCfg1inb(uint16_t addr, uint8_t *val); 45 static int pciCfg1outb(uint16_t addr, uint8_t val); 46 47 #if defined (_PC) 48 static void SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set); 49 #endif 50 51 #define REG pInt 52 53 int 54 setup_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 85 void 86 finish_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 */ 105 uint32_t 106 getIntVect(xf86Int10InfoPtr pInt, int num) 107 { 108 return MEM_RW(pInt, num << 2) + (MEM_RW(pInt, (num << 2) + 2) << 4); 109 } 110 111 void 112 pushw(xf86Int10InfoPtr pInt, uint16_t val) 113 { 114 X86_ESP -= 2; 115 MEM_WW(pInt, ((uint32_t) X86_SS << 4) + X86_SP, val); 116 } 117 118 int 119 run_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 */ 166 void 167 dump_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 182 void 183 dump_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 202 void 203 stack_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 223 int 224 port_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 240 int 241 port_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 257 int 258 port_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 274 int 275 port_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 291 int 292 port_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 308 int 309 port_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 325 uint8_t 326 x_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 356 uint16_t 357 x_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 379 void 380 x_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 413 void 414 x_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 424 uint32_t 425 x_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 437 void 438 x_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 447 uint8_t 448 Mem_rb(uint32_t addr) 449 { 450 return (*Int10Current->mem->rb) (Int10Current, addr); 451 } 452 453 uint16_t 454 Mem_rw(uint32_t addr) 455 { 456 return (*Int10Current->mem->rw) (Int10Current, addr); 457 } 458 459 uint32_t 460 Mem_rl(uint32_t addr) 461 { 462 return (*Int10Current->mem->rl) (Int10Current, addr); 463 } 464 465 void 466 Mem_wb(uint32_t addr, uint8_t val) 467 { 468 (*Int10Current->mem->wb) (Int10Current, addr, val); 469 } 470 471 void 472 Mem_ww(uint32_t addr, uint16_t val) 473 { 474 (*Int10Current->mem->ww) (Int10Current, addr, val); 475 } 476 477 void 478 Mem_wl(uint32_t addr, uint32_t val) 479 { 480 (*Int10Current->mem->wl) (Int10Current, addr, val); 481 } 482 483 static 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 493 static struct pci_device * 494 pci_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 518 static int 519 pciCfg1in(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 (uint32_t *) val, PCI_OFFSET(PciCfg1Addr)); 528 if (PRINT_PORT && DEBUG_IO_TRACE()) 529 ErrorF(" cfg_inl(%#" PRIx32 ") = %8.8" PRIx32 "\n", (unsigned) PciCfg1Addr, 530 (unsigned) *val); 531 return 1; 532 } 533 return 0; 534 } 535 536 static int 537 pciCfg1out(uint16_t addr, uint32_t val) 538 { 539 if (addr == 0xCF8) { 540 PciCfg1Addr = val; 541 return 1; 542 } 543 if (addr == 0xCFC) { 544 if (PRINT_PORT && DEBUG_IO_TRACE()) 545 ErrorF(" cfg_outl(%#" PRIx32 ", %8.8" PRIx32 ")\n", (unsigned) PciCfg1Addr, 546 (unsigned) val); 547 pci_device_cfg_write_u32(pci_device_for_cfg_address(PciCfg1Addr), val, 548 PCI_OFFSET(PciCfg1Addr)); 549 return 1; 550 } 551 return 0; 552 } 553 554 static int 555 pciCfg1inw(uint16_t addr, uint16_t *val) 556 { 557 int shift; 558 559 if ((addr >= 0xCF8) && (addr <= 0xCFB)) { 560 shift = (addr - 0xCF8) * 8; 561 *val = (PciCfg1Addr >> shift) & 0xffff; 562 return 1; 563 } 564 if ((addr >= 0xCFC) && (addr <= 0xCFF)) { 565 const unsigned offset = addr - 0xCFC; 566 567 pci_device_cfg_read_u16(pci_device_for_cfg_address(PciCfg1Addr), 568 val, PCI_OFFSET(PciCfg1Addr) + offset); 569 if (PRINT_PORT && DEBUG_IO_TRACE()) 570 ErrorF(" cfg_inw(%#" PRIx32 ") = %4.4x\n", (unsigned) (PciCfg1Addr + offset), 571 (unsigned) *val); 572 return 1; 573 } 574 return 0; 575 } 576 577 static int 578 pciCfg1outw(uint16_t addr, uint16_t val) 579 { 580 int shift; 581 582 if ((addr >= 0xCF8) && (addr <= 0xCFB)) { 583 shift = (addr - 0xCF8) * 8; 584 PciCfg1Addr &= ~(0xffff << shift); 585 PciCfg1Addr |= ((uint32_t) val) << shift; 586 return 1; 587 } 588 if ((addr >= 0xCFC) && (addr <= 0xCFF)) { 589 const unsigned offset = addr - 0xCFC; 590 591 if (PRINT_PORT && DEBUG_IO_TRACE()) 592 ErrorF(" cfg_outw(%#" PRIx32 ", %4.4x)\n", (unsigned) (PciCfg1Addr + offset), 593 (unsigned) val); 594 pci_device_cfg_write_u16(pci_device_for_cfg_address(PciCfg1Addr), val, 595 PCI_OFFSET(PciCfg1Addr) + offset); 596 return 1; 597 } 598 return 0; 599 } 600 601 static int 602 pciCfg1inb(uint16_t addr, uint8_t *val) 603 { 604 int shift; 605 606 if ((addr >= 0xCF8) && (addr <= 0xCFB)) { 607 shift = (addr - 0xCF8) * 8; 608 *val = (PciCfg1Addr >> shift) & 0xff; 609 return 1; 610 } 611 if ((addr >= 0xCFC) && (addr <= 0xCFF)) { 612 const unsigned offset = addr - 0xCFC; 613 614 pci_device_cfg_read_u8(pci_device_for_cfg_address(PciCfg1Addr), 615 val, PCI_OFFSET(PciCfg1Addr) + offset); 616 if (PRINT_PORT && DEBUG_IO_TRACE()) 617 ErrorF(" cfg_inb(%#" PRIx32 ") = %2.2x\n", (unsigned) (PciCfg1Addr + offset), 618 (unsigned) *val); 619 return 1; 620 } 621 return 0; 622 } 623 624 static int 625 pciCfg1outb(uint16_t addr, uint8_t val) 626 { 627 int shift; 628 629 if ((addr >= 0xCF8) && (addr <= 0xCFB)) { 630 shift = (addr - 0xCF8) * 8; 631 PciCfg1Addr &= ~(0xff << shift); 632 PciCfg1Addr |= ((uint32_t) val) << shift; 633 return 1; 634 } 635 if ((addr >= 0xCFC) && (addr <= 0xCFF)) { 636 const unsigned offset = addr - 0xCFC; 637 638 if (PRINT_PORT && DEBUG_IO_TRACE()) 639 ErrorF(" cfg_outb(%#" PRIx32 ", %2.2x)\n", (unsigned) (PciCfg1Addr + offset), 640 (unsigned) val); 641 pci_device_cfg_write_u8(pci_device_for_cfg_address(PciCfg1Addr), val, 642 PCI_OFFSET(PciCfg1Addr) + offset); 643 return 1; 644 } 645 return 0; 646 } 647 648 uint8_t 649 bios_checksum(const uint8_t *start, int size) 650 { 651 uint8_t sum = 0; 652 653 while (size-- > 0) 654 sum += *start++; 655 return sum; 656 } 657 658 /* 659 * Lock/Unlock legacy VGA. Some Bioses try to be very clever and make 660 * an attempt to detect a legacy ISA card. If they find one they might 661 * act very strange: for example they might configure the card as a 662 * monochrome card. This might cause some drivers to choke. 663 * To avoid this we attempt legacy VGA by writing to all known VGA 664 * disable registers before we call the BIOS initialization and 665 * restore the original values afterwards. In between we hold our 666 * breath. To get to a (possibly existing) ISA card need to disable 667 * our current PCI card. 668 */ 669 /* 670 * This is just for booting: we just want to catch pure 671 * legacy vga therefore we don't worry about mmio etc. 672 * This stuff should really go into vgaHW.c. However then 673 * the driver would have to load the vga-module prior to 674 * doing int10. 675 */ 676 void 677 LockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga) 678 { 679 vga->save_msr = pci_io_read8(pInt->io, 0x03CC); 680 vga->save_vse = pci_io_read8(pInt->io, 0x03C3); 681 #ifndef __ia64__ 682 vga->save_46e8 = pci_io_read8(pInt->io, 0x46E8); 683 #endif 684 vga->save_pos102 = pci_io_read8(pInt->io, 0x0102); 685 pci_io_write8(pInt->io, 0x03C2, ~(uint8_t) 0x03 & vga->save_msr); 686 pci_io_write8(pInt->io, 0x03C3, ~(uint8_t) 0x01 & vga->save_vse); 687 #ifndef __ia64__ 688 pci_io_write8(pInt->io, 0x46E8, ~(uint8_t) 0x08 & vga->save_46e8); 689 #endif 690 pci_io_write8(pInt->io, 0x0102, ~(uint8_t) 0x01 & vga->save_pos102); 691 } 692 693 void 694 UnlockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga) 695 { 696 pci_io_write8(pInt->io, 0x0102, vga->save_pos102); 697 #ifndef __ia64__ 698 pci_io_write8(pInt->io, 0x46E8, vga->save_46e8); 699 #endif 700 pci_io_write8(pInt->io, 0x03C3, vga->save_vse); 701 pci_io_write8(pInt->io, 0x03C2, vga->save_msr); 702 } 703 704 #if defined (_PC) 705 static void 706 SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set) 707 { 708 int pagesize = getpagesize(); 709 unsigned char *base; 710 int i; 711 712 if (pci_device_map_legacy 713 (pInt->dev, 0, pagesize, PCI_DEV_MAP_FLAG_WRITABLE, (void **) &base)) 714 return; /* eek */ 715 716 if (set) { 717 for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++) 718 MEM_WW(pInt, i, *(base + i)); 719 } 720 else { 721 for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++) 722 *(base + i) = MEM_RW(pInt, i); 723 } 724 725 pci_device_unmap_legacy(pInt->dev, base, pagesize); 726 } 727 728 void 729 xf86Int10SaveRestoreBIOSVars(xf86Int10InfoPtr pInt, Bool save) 730 { 731 int pagesize = getpagesize(); 732 unsigned char *base; 733 int i; 734 735 if (!xf86IsEntityPrimary(pInt->entityIndex) 736 || (!save && !pInt->BIOSScratch)) 737 return; 738 739 if (pci_device_map_legacy 740 (pInt->dev, 0, pagesize, PCI_DEV_MAP_FLAG_WRITABLE, (void **) &base)) 741 return; /* eek */ 742 743 base += BIOS_SCRATCH_OFF; 744 if (save) { 745 if ((pInt->BIOSScratch = xnfalloc(BIOS_SCRATCH_LEN))) 746 for (i = 0; i < BIOS_SCRATCH_LEN; i++) 747 *(((char *) pInt->BIOSScratch + i)) = *(base + i); 748 } 749 else { 750 if (pInt->BIOSScratch) { 751 for (i = 0; i < BIOS_SCRATCH_LEN; i++) 752 *(base + i) = *(pInt->BIOSScratch + i); 753 free(pInt->BIOSScratch); 754 pInt->BIOSScratch = NULL; 755 } 756 } 757 758 pci_device_unmap_legacy(pInt->dev, base - BIOS_SCRATCH_OFF, pagesize); 759 } 760 #endif 761 762 xf86Int10InfoPtr 763 xf86InitInt10(int entityIndex) 764 { 765 return xf86ExtendedInitInt10(entityIndex, 0); 766 }