xf86int10.c revision 05b261ec
1/* 2 * XFree86 int10 module 3 * execute BIOS int 10h calls in x86 real mode environment 4 * Copyright 1999 Egbert Eich 5 */ 6 7#ifdef HAVE_XORG_CONFIG_H 8#include <xorg-config.h> 9#endif 10 11#include "xf86.h" 12#include "compiler.h" 13#define _INT10_PRIVATE 14#include "xf86int10.h" 15#include "int10Defines.h" 16 17#define REG pInt 18 19xf86Int10InfoPtr Int10Current = NULL; 20 21static int int1A_handler(xf86Int10InfoPtr pInt); 22#ifndef _PC 23static int int42_handler(xf86Int10InfoPtr pInt); 24#endif 25static int intE6_handler(xf86Int10InfoPtr pInt); 26static PCITAG findPci(xf86Int10InfoPtr pInt, unsigned short bx); 27static CARD32 pciSlotBX(pciVideoPtr pvp); 28 29int 30int_handler(xf86Int10InfoPtr pInt) 31{ 32 int num = pInt->num; 33 int ret = 0; 34 35 switch (num) { 36#ifndef _PC 37 case 0x10: 38 case 0x42: 39 case 0x6D: 40 if (getIntVect(pInt, num) == I_S_DEFAULT_INT_VECT) 41 ret = int42_handler(pInt); 42 break; 43#endif 44 case 0x1A: 45 ret = int1A_handler(pInt); 46 break; 47 case 0xe6: 48 ret = intE6_handler(pInt); 49 break; 50 default: 51 break; 52 } 53 54 if (!ret) 55 ret = run_bios_int(num, pInt); 56 57 if (!ret) { 58 xf86DrvMsg(pInt->scrnIndex, X_ERROR, 59 "Halting on int 0x%2.2x!\n", num); 60 dump_registers(pInt); 61 stack_trace(pInt); 62 } 63 64 return ret; 65} 66 67#ifndef _PC 68/* 69 * This is derived from a number of PC system BIOS'es. The intent here is to 70 * provide very primitive video support, before an EGA/VGA BIOS installs its 71 * own interrupt vector. Here, "Ignored" calls should remain so. "Not 72 * Implemented" denotes functionality that can be implemented should the need 73 * arise. What are "Not Implemented" throughout are video memory accesses. 74 * Also, very little input validity checking is done here. 75 */ 76static int 77int42_handler(xf86Int10InfoPtr pInt) 78{ 79 switch (X86_AH) { 80 case 0x00: 81 /* Set Video Mode */ 82 /* Enter: AL = video mode number */ 83 /* Leave: Nothing */ 84 /* Implemented (except for clearing the screen) */ 85 { /* Localise */ 86 IOADDRESS ioport; 87 int i; 88 CARD16 int1d, regvals, tmp; 89 CARD8 mode, cgamode, cgacolour; 90 91 /* 92 * Ignore all mode numbers but 0x00-0x13. Some systems also ignore 93 * 0x0B and 0x0C, but don't do that here. 94 */ 95 if (X86_AL > 0x13) 96 break; 97 98 /* 99 * You didn't think that was really the mode set, did you? There 100 * are only so many slots in the video parameter table... 101 */ 102 mode = X86_AL; 103 ioport = 0x03D4; 104 switch (MEM_RB(pInt, 0x0410) & 0x30) { 105 case 0x30: /* MDA */ 106 mode = 0x07; /* Force mode to 0x07 */ 107 ioport = 0x03B4; 108 break; 109 case 0x10: /* CGA 40x25 */ 110 if (mode >= 0x07) 111 mode = 0x01; 112 break; 113 case 0x20: /* CGA 80x25 (MCGA?) */ 114 if (mode >= 0x07) 115 mode = 0x03; 116 break; 117 case 0x00: /* EGA/VGA */ 118 if (mode >= 0x07) /* Don't try MDA timings */ 119 mode = 0x01; /* !?!?! */ 120 break; 121 } 122 123 /* Locate data in video parameter table */ 124 int1d = MEM_RW(pInt, 0x1d << 2); 125 regvals = ((mode >> 1) << 4) + int1d; 126 cgacolour = 0x30; 127 if (mode == 0x06) { 128 regvals -= 0x10; 129 cgacolour = 0x3F; 130 } 131 132 /** Update BIOS Data Area **/ 133 134 /* Video mode */ 135 MEM_WB(pInt, 0x0449, mode); 136 137 /* Columns */ 138 tmp = MEM_RB(pInt, mode + int1d + 0x48); 139 MEM_WW(pInt, 0x044A, tmp); 140 141 /* Page length */ 142 tmp = MEM_RW(pInt, (mode & 0x06) + int1d + 0x40); 143 MEM_WW(pInt, 0x044C, tmp); 144 145 /* Start Address */ 146 MEM_WW(pInt, 0x044E, 0); 147 148 /* Cursor positions, one for each display page */ 149 for (i = 0x0450; i < 0x0460; i += 2) 150 MEM_WW(pInt, i, 0); 151 152 /* Cursor start & end scanlines */ 153 tmp = MEM_RB(pInt, regvals + 0x0B); 154 MEM_WB(pInt, 0x0460, tmp); 155 tmp = MEM_RB(pInt, regvals + 0x0A); 156 MEM_WB(pInt, 0x0461, tmp); 157 158 /* Current display page number */ 159 MEM_WB(pInt, 0x0462, 0); 160 161 /* CRTC I/O address */ 162 MEM_WW(pInt, 0x0463, ioport); 163 164 /* CGA Mode register value */ 165 cgamode = MEM_RB(pInt, mode + int1d + 0x50); 166 MEM_WB(pInt, 0x0465, cgamode); 167 168 /* CGA Colour register value */ 169 MEM_WB(pInt, 0x0466, cgacolour); 170 171 /* Rows */ 172 MEM_WB(pInt, 0x0484, (25 - 1)); 173 174 /* Remap I/O port number into its domain */ 175 ioport += pInt->ioBase; 176 177 /* Programme the mode */ 178 outb(ioport + 4, cgamode & 0x37); /* Turn off screen */ 179 for (i = 0; i < 0x10; i++) { 180 tmp = MEM_RB(pInt, regvals + i); 181 outb(ioport, i); 182 outb(ioport + 1, tmp); 183 } 184 outb(ioport + 5, cgacolour); /* Select colour mode */ 185 outb(ioport + 4, cgamode); /* Turn on screen */ 186 } 187 break; 188 189 case 0x01: 190 /* Set Cursor Type */ 191 /* Enter: CH = starting line for cursor */ 192 /* CL = ending line for cursor */ 193 /* Leave: Nothing */ 194 /* Implemented */ 195 { /* Localise */ 196 IOADDRESS ioport = MEM_RW(pInt, 0x0463) + pInt->ioBase; 197 198 MEM_WB(pInt, 0x0460, X86_CL); 199 MEM_WB(pInt, 0x0461, X86_CH); 200 201 outb(ioport, 0x0A); 202 outb(ioport + 1, X86_CH); 203 outb(ioport, 0x0B); 204 outb(ioport + 1, X86_CL); 205 } 206 break; 207 208 case 0x02: 209 /* Set Cursor Position */ 210 /* Enter: BH = display page number */ 211 /* DH = row */ 212 /* DL = column */ 213 /* Leave: Nothing */ 214 /* Implemented */ 215 { /* Localise */ 216 IOADDRESS ioport; 217 CARD16 offset; 218 219 MEM_WB(pInt, (X86_BH << 1) + 0x0450, X86_DL); 220 MEM_WB(pInt, (X86_BH << 1) + 0x0451, X86_DH); 221 222 if (X86_BH != MEM_RB(pInt, 0x0462)) 223 break; 224 225 offset = (X86_DH * MEM_RW(pInt, 0x044A)) + X86_DL; 226 offset += MEM_RW(pInt, 0x044E) << 1; 227 228 ioport = MEM_RW(pInt, 0x0463) + pInt->ioBase; 229 outb(ioport, 0x0E); 230 outb(ioport + 1, offset >> 8); 231 outb(ioport, 0x0F); 232 outb(ioport + 1, offset & 0xFF); 233 } 234 break; 235 236 case 0x03: 237 /* Get Cursor Position */ 238 /* Enter: BH = display page number */ 239 /* Leave: CH = starting line for cursor */ 240 /* CL = ending line for cursor */ 241 /* DH = row */ 242 /* DL = column */ 243 /* Implemented */ 244 { /* Localise */ 245 X86_CL = MEM_RB(pInt, 0x0460); 246 X86_CH = MEM_RB(pInt, 0x0461); 247 X86_DL = MEM_RB(pInt, (X86_BH << 1) + 0x0450); 248 X86_DH = MEM_RB(pInt, (X86_BH << 1) + 0x0451); 249 } 250 break; 251 252 case 0x04: 253 /* Get Light Pen Position */ 254 /* Enter: Nothing */ 255 /* Leave: AH = 0x01 (down/triggered) or 0x00 (not) */ 256 /* BX = pixel column */ 257 /* CX = pixel row */ 258 /* DH = character row */ 259 /* DL = character column */ 260 /* Not Implemented */ 261 { /* Localise */ 262 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 263 "int 0x%2.2x(AH=0x04) -- Get Light Pen Position\n", pInt->num); 264 if (xf86GetVerbosity() > 3) { 265 dump_registers(pInt); 266 stack_trace(pInt); 267 } 268 X86_AH = X86_BX = X86_CX = X86_DX = 0; 269 } 270 break; 271 272 case 0x05: 273 /* Set Display Page */ 274 /* Enter: AL = display page number */ 275 /* Leave: Nothing */ 276 /* Implemented */ 277 { /* Localise */ 278 IOADDRESS ioport = MEM_RW(pInt, 0x0463) + pInt->ioBase; 279 CARD16 start; 280 CARD8 x, y; 281 282 /* Calculate new start address */ 283 MEM_WB(pInt, 0x0462, X86_AL); 284 start = X86_AL * MEM_RW(pInt, 0x044C); 285 MEM_WW(pInt, 0x044E, start); 286 start <<= 1; 287 288 /* Update start address */ 289 outb(ioport, 0x0C); 290 outb(ioport + 1, start >> 8); 291 outb(ioport, 0x0D); 292 outb(ioport + 1, start & 0xFF); 293 294 /* Switch cursor position */ 295 y = MEM_RB(pInt, (X86_AL << 1) + 0x0450); 296 x = MEM_RB(pInt, (X86_AL << 1) + 0x0451); 297 start += (y * MEM_RW(pInt, 0x044A)) + x; 298 299 /* Update cursor position */ 300 outb(ioport, 0x0E); 301 outb(ioport + 1, start >> 8); 302 outb(ioport, 0x0F); 303 outb(ioport + 1, start & 0xFF); 304 } 305 break; 306 307 case 0x06: 308 /* Initialise or Scroll Window Up */ 309 /* Enter: AL = lines to scroll up */ 310 /* BH = attribute for blank */ 311 /* CH = upper y of window */ 312 /* CL = left x of window */ 313 /* DH = lower y of window */ 314 /* DL = right x of window */ 315 /* Leave: Nothing */ 316 /* Not Implemented */ 317 { /* Localise */ 318 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 319 "int 0x%2.2x(AH=0x06) -- Initialise or Scroll Window Up\n", 320 pInt->num); 321 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 322 " AL=0x%2.2x, BH=0x%2.2x," 323 " CH=0x%2.2x, CL=0x%2.2x, DH=0x%2.2x, DL=0x%2.2x\n", 324 X86_AL, X86_BH, X86_CH, X86_CL, X86_DH, X86_DL); 325 if (xf86GetVerbosity() > 3) { 326 dump_registers(pInt); 327 stack_trace(pInt); 328 } 329 } 330 break; 331 332 case 0x07: 333 /* Initialise or Scroll Window Down */ 334 /* Enter: AL = lines to scroll down */ 335 /* BH = attribute for blank */ 336 /* CH = upper y of window */ 337 /* CL = left x of window */ 338 /* DH = lower y of window */ 339 /* DL = right x of window */ 340 /* Leave: Nothing */ 341 /* Not Implemented */ 342 { /* Localise */ 343 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 344 "int 0x%2.2x(AH=0x07) -- Initialise or Scroll Window Down\n", 345 pInt->num); 346 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 347 " AL=0x%2.2x, BH=0x%2.2x," 348 " CH=0x%2.2x, CL=0x%2.2x, DH=0x%2.2x, DL=0x%2.2x\n", 349 X86_AL, X86_BH, X86_CH, X86_CL, X86_DH, X86_DL); 350 if (xf86GetVerbosity() > 3) { 351 dump_registers(pInt); 352 stack_trace(pInt); 353 } 354 } 355 break; 356 357 case 0x08: 358 /* Read Character and Attribute at Cursor */ 359 /* Enter: BH = display page number */ 360 /* Leave: AH = attribute */ 361 /* AL = character */ 362 /* Not Implemented */ 363 { /* Localise */ 364 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 365 "int 0x%2.2x(AH=0x08) -- Read Character and Attribute at" 366 " Cursor\n", pInt->num); 367 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 368 "BH=0x%2.2x\n", X86_BH); 369 if (xf86GetVerbosity() > 3) { 370 dump_registers(pInt); 371 stack_trace(pInt); 372 } 373 X86_AX = 0; 374 } 375 break; 376 377 case 0x09: 378 /* Write Character and Attribute at Cursor */ 379 /* Enter: AL = character */ 380 /* BH = display page number */ 381 /* BL = attribute (text) or colour (graphics) */ 382 /* CX = replication count */ 383 /* Leave: Nothing */ 384 /* Not Implemented */ 385 { /* Localise */ 386 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 387 "int 0x%2.2x(AH=0x09) -- Write Character and Attribute at" 388 " Cursor\n", pInt->num); 389 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 390 "AL=0x%2.2x, BH=0x%2.2x, BL=0x%2.2x, CX=0x%4.4x\n", 391 X86_AL, X86_BH, X86_BL, X86_CX); 392 if (xf86GetVerbosity() > 3) { 393 dump_registers(pInt); 394 stack_trace(pInt); 395 } 396 } 397 break; 398 399 case 0x0a: 400 /* Write Character at Cursor */ 401 /* Enter: AL = character */ 402 /* BH = display page number */ 403 /* BL = colour */ 404 /* CX = replication count */ 405 /* Leave: Nothing */ 406 /* Not Implemented */ 407 { /* Localise */ 408 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 409 "int 0x%2.2x(AH=0x0A) -- Write Character at Cursor\n", 410 pInt->num); 411 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 412 "AL=0x%2.2x, BH=0x%2.2x, BL=0x%2.2x, CX=0x%4.4x\n", 413 X86_AL, X86_BH, X86_BL, X86_CX); 414 if (xf86GetVerbosity() > 3) { 415 dump_registers(pInt); 416 stack_trace(pInt); 417 } 418 } 419 break; 420 421 case 0x0b: 422 /* Set Palette, Background or Border */ 423 /* Enter: BH = 0x00 or 0x01 */ 424 /* BL = colour or palette (respectively) */ 425 /* Leave: Nothing */ 426 /* Implemented */ 427 { /* Localise */ 428 IOADDRESS ioport = MEM_RW(pInt, 0x0463) + 5 + pInt->ioBase; 429 CARD8 cgacolour = MEM_RB(pInt, 0x0466); 430 431 if (X86_BH) { 432 cgacolour &= 0xDF; 433 cgacolour |= (X86_BL & 0x01) << 5; 434 } else { 435 cgacolour &= 0xE0; 436 cgacolour |= X86_BL & 0x1F; 437 } 438 439 MEM_WB(pInt, 0x0466, cgacolour); 440 outb(ioport, cgacolour); 441 } 442 break; 443 444 case 0x0c: 445 /* Write Graphics Pixel */ 446 /* Enter: AL = pixel value */ 447 /* BH = display page number */ 448 /* CX = column */ 449 /* DX = row */ 450 /* Leave: Nothing */ 451 /* Not Implemented */ 452 { /* Localise */ 453 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 454 "int 0x%2.2x(AH=0x0C) -- Write Graphics Pixel\n", pInt->num); 455 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 456 "AL=0x%2.2x, BH=0x%2.2x, CX=0x%4.4x, DX=0x%4.4x\n", 457 X86_AL, X86_BH, X86_CX, X86_DX); 458 if (xf86GetVerbosity() > 3) { 459 dump_registers(pInt); 460 stack_trace(pInt); 461 } 462 } 463 break; 464 465 case 0x0d: 466 /* Read Graphics Pixel */ 467 /* Enter: BH = display page number */ 468 /* CX = column */ 469 /* DX = row */ 470 /* Leave: AL = pixel value */ 471 /* Not Implemented */ 472 { /* Localise */ 473 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 474 "int 0x%2.2x(AH=0x0D) -- Read Graphics Pixel\n", pInt->num); 475 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 476 "BH=0x%2.2x, CX=0x%4.4x, DX=0x%4.4x\n", 477 X86_BH, X86_CX, X86_DX); 478 if (xf86GetVerbosity() > 3) { 479 dump_registers(pInt); 480 stack_trace(pInt); 481 } 482 X86_AL = 0; 483 } 484 break; 485 486 case 0x0e: 487 /* Write Character in Teletype Mode */ 488 /* Enter: AL = character */ 489 /* BH = display page number */ 490 /* BL = foreground colour */ 491 /* Leave: Nothing */ 492 /* Not Implemented */ 493 /* WARNING: Emulation of BEL characters will require */ 494 /* emulation of RTC and PC speaker I/O. */ 495 /* Also, this recurses through int 0x10 */ 496 /* which might or might not have been */ 497 /* installed yet. */ 498 { /* Localise */ 499 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 500 "int 0x%2.2x(AH=0x0E) -- Write Character in Teletype Mode\n", 501 pInt->num); 502 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 503 "AL=0x%2.2x, BH=0x%2.2x, BL=0x%2.2x\n", 504 X86_AL, X86_BH, X86_BL); 505 if (xf86GetVerbosity() > 3) { 506 dump_registers(pInt); 507 stack_trace(pInt); 508 } 509 } 510 break; 511 512 case 0x0f: 513 /* Get Video Mode */ 514 /* Enter: Nothing */ 515 /* Leave: AH = number of columns */ 516 /* AL = video mode number */ 517 /* BH = display page number */ 518 /* Implemented */ 519 { /* Localise */ 520 X86_AH = MEM_RW(pInt, 0x044A); 521 X86_AL = MEM_RB(pInt, 0x0449); 522 X86_BH = MEM_RB(pInt, 0x0462); 523 } 524 break; 525 526 case 0x10: 527 /* Colour Control (subfunction in AL) */ 528 /* Enter: Various */ 529 /* Leave: Various */ 530 /* Ignored */ 531 break; 532 533 case 0x11: 534 /* Font Control (subfunction in AL) */ 535 /* Enter: Various */ 536 /* Leave: Various */ 537 /* Ignored */ 538 break; 539 540 case 0x12: 541 /* Miscellaneous (subfunction in BL) */ 542 /* Enter: Various */ 543 /* Leave: Various */ 544 /* Ignored. Previous code here optionally allowed */ 545 /* the enabling and disabling of VGA, but no system */ 546 /* BIOS I've come across actually implements it. */ 547 break; 548 549 case 0x13: 550 /* Write String in Teletype Mode */ 551 /* Enter: AL = write mode */ 552 /* BL = attribute (if (AL & 0x02) == 0) */ 553 /* CX = string length */ 554 /* DH = row */ 555 /* DL = column */ 556 /* ES:BP = string segment:offset */ 557 /* Leave: Nothing */ 558 /* Not Implemented */ 559 /* WARNING: Emulation of BEL characters will require */ 560 /* emulation of RTC and PC speaker I/O. */ 561 /* Also, this recurses through int 0x10 */ 562 /* which might or might not have been */ 563 /* installed yet. */ 564 { /* Localise */ 565 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 566 "int 0x%2.2x(AH=0x13) -- Write String in Teletype Mode\n", 567 pInt->num); 568 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 569 "AL=0x%2.2x, BL=0x%2.2x, CX=0x%4.4x," 570 " DH=0x%2.2x, DL=0x%2.2x, ES:BP=0x%4.4x:0x%4.4x\n", 571 X86_AL, X86_BL, X86_CX, X86_DH, X86_DL, X86_ES, X86_BP); 572 if (xf86GetVerbosity() > 3) { 573 dump_registers(pInt); 574 stack_trace(pInt); 575 } 576 } 577 break; 578 579 default: 580 /* Various extensions */ 581 /* Enter: Various */ 582 /* Leave: Various */ 583 /* Ignored */ 584 break; 585 } 586 587 return 1; 588} 589#endif 590 591#define SUCCESSFUL 0x00 592#define DEVICE_NOT_FOUND 0x86 593#define BAD_REGISTER_NUMBER 0x87 594 595static int 596int1A_handler(xf86Int10InfoPtr pInt) 597{ 598 PCITAG tag; 599 pciVideoPtr pvp; 600 601 if (!(pvp = xf86GetPciInfoForEntity(pInt->entityIndex))) 602 return 0; /* oops */ 603 604#ifdef PRINT_INT 605 ErrorF("int 0x1a: ax=0x%x bx=0x%x cx=0x%x dx=0x%x di=0x%x es=0x%x\n", 606 X86_EAX, X86_EBX, X86_ECX, X86_EDX, X86_EDI, X86_ESI); 607#endif 608 switch (X86_AX) { 609 case 0xb101: 610 X86_EAX &= 0xFF00; /* no config space/special cycle support */ 611 X86_EDX = 0x20494350; /* " ICP" */ 612 X86_EBX = 0x0210; /* Version 2.10 */ 613 X86_ECX &= 0xFF00; 614 X86_ECX |= (pciNumBuses & 0xFF); /* Max bus number in system */ 615 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 616#ifdef PRINT_INT 617 ErrorF("ax=0x%x dx=0x%x bx=0x%x cx=0x%x flags=0x%x\n", 618 X86_EAX, X86_EDX, X86_EBX, X86_ECX, X86_EFLAGS); 619#endif 620 return 1; 621 case 0xb102: 622 if (X86_DX == pvp->vendor && X86_CX == pvp->chipType && X86_ESI == 0) { 623 X86_EAX = X86_AL | (SUCCESSFUL << 8); 624 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 625 X86_EBX = pciSlotBX(pvp); 626 } 627#ifdef SHOW_ALL_DEVICES 628 else 629 if ((pvp = xf86FindPciDeviceVendor(X86_EDX, X86_ECX, X86_ESI, pvp))) { 630 X86_EAX = X86_AL | (SUCCESSFUL << 8); 631 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 632 X86_EBX = pciSlotBX(pvp); 633 } 634#endif 635 else { 636 X86_EAX = X86_AL | (DEVICE_NOT_FOUND << 8); 637 X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ 638 } 639#ifdef PRINT_INT 640 ErrorF("ax=0x%x bx=0x%x flags=0x%x\n", X86_EAX, X86_EBX, X86_EFLAGS); 641#endif 642 return 1; 643 case 0xb103: 644 if (X86_CL == pvp->interface && 645 X86_CH == pvp->subclass && 646 ((X86_ECX & 0xFFFF0000) >> 16) == pvp->class) { 647 X86_EAX = X86_AL | (SUCCESSFUL << 8); 648 X86_EBX = pciSlotBX(pvp); 649 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 650 } 651#ifdef SHOW_ALL_DEVICES 652 else if ((pvp = xf86FindPciClass(X86_CL, X86_CH, 653 (X86_ECX & 0xffff0000) >> 16, 654 X86_ESI, pvp))) { 655 X86_EAX = X86_AL | (SUCCESSFUL << 8); 656 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 657 X86_EBX = pciSlotBX(pvp); 658 } 659#endif 660 else { 661 X86_EAX = X86_AL | (DEVICE_NOT_FOUND << 8); 662 X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ 663 } 664#ifdef PRINT_INT 665 ErrorF("ax=0x%x flags=0x%x\n", X86_EAX, X86_EFLAGS); 666#endif 667 return 1; 668 case 0xb108: 669 if ((tag = findPci(pInt, X86_EBX)) != PCI_NOT_FOUND) { 670 X86_CL = pciReadByte(tag, X86_EDI); 671 X86_EAX = X86_AL | (SUCCESSFUL << 8); 672 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 673 } else { 674 X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); 675 X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ 676 } 677#ifdef PRINT_INT 678 ErrorF("ax=0x%x cx=0x%x flags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS); 679#endif 680 return 1; 681 case 0xb109: 682 if ((tag = findPci(pInt, X86_EBX)) != PCI_NOT_FOUND) { 683 X86_CX = pciReadWord(tag, X86_EDI); 684 X86_EAX = X86_AL | (SUCCESSFUL << 8); 685 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 686 } else { 687 X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); 688 X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ 689 } 690#ifdef PRINT_INT 691 ErrorF("ax=0x%x cx=0x%x flags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS); 692#endif 693 return 1; 694 case 0xb10a: 695 if ((tag = findPci(pInt, X86_EBX)) != PCI_NOT_FOUND) { 696 X86_ECX = pciReadLong(tag, X86_EDI); 697 X86_EAX = X86_AL | (SUCCESSFUL << 8); 698 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 699 } else { 700 X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); 701 X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ 702 } 703#ifdef PRINT_INT 704 ErrorF("ax=0x%x cx=0x%x flags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS); 705#endif 706 return 1; 707 case 0xb10b: 708 if ((tag = findPci(pInt, X86_EBX)) != PCI_NOT_FOUND) { 709 pciWriteByte(tag, X86_EDI, X86_CL); 710 X86_EAX = X86_AL | (SUCCESSFUL << 8); 711 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 712 } else { 713 X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); 714 X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ 715 } 716#ifdef PRINT_INT 717 ErrorF("ax=0x%x flags=0x%x\n", X86_EAX, X86_EFLAGS); 718#endif 719 return 1; 720 case 0xb10c: 721 if ((tag = findPci(pInt, X86_EBX)) != PCI_NOT_FOUND) { 722 pciWriteWord(tag, X86_EDI, X86_CX); 723 X86_EAX = X86_AL | (SUCCESSFUL << 8); 724 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 725 } else { 726 X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); 727 X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ 728 } 729#ifdef PRINT_INT 730 ErrorF("ax=0x%x flags=0x%x\n", X86_EAX, X86_EFLAGS); 731#endif 732 return 1; 733 case 0xb10d: 734 if ((tag = findPci(pInt, X86_EBX)) != PCI_NOT_FOUND) { 735 pciWriteLong(tag, X86_EDI, X86_ECX); 736 X86_EAX = X86_AL | (SUCCESSFUL << 8); 737 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 738 } else { 739 X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); 740 X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ 741 } 742#ifdef PRINT_INT 743 ErrorF("ax=0x%x flags=0x%x\n", X86_EAX, X86_EFLAGS); 744#endif 745 return 1; 746 default: 747 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 748 "int 0x1a subfunction\n"); 749 dump_registers(pInt); 750 if (xf86GetVerbosity() > 3) 751 stack_trace(pInt); 752 return 0; 753 } 754} 755 756static PCITAG 757findPci(xf86Int10InfoPtr pInt, unsigned short bx) 758{ 759 int bus = ((pInt->Tag >> 16) & ~0x00FF) | ((bx >> 8) & 0x00FF); 760 int dev = (bx >> 3) & 0x1F; 761 int func = bx & 0x7; 762 if (xf86IsPciDevPresent(bus, dev, func)) 763 return pciTag(bus, dev, func); 764 return PCI_NOT_FOUND; 765} 766 767static CARD32 768pciSlotBX(pciVideoPtr pvp) 769{ 770 return ((pvp->bus << 8) & 0x00FF00) | (pvp->device << 3) | (pvp->func); 771} 772 773/* 774 * handle initialization 775 */ 776static int 777intE6_handler(xf86Int10InfoPtr pInt) 778{ 779 pciVideoPtr pvp; 780 781 if ((pvp = xf86GetPciInfoForEntity(pInt->entityIndex))) 782 X86_AX = (pvp->bus << 8) | (pvp->device << 3) | (pvp->func & 0x7); 783 pushw(pInt, X86_CS); 784 pushw(pInt, X86_IP); 785 X86_CS = pInt->BIOSseg; 786 X86_EIP = 0x0003; 787 X86_ES = 0; /* standard pc es */ 788 return 1; 789} 790