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