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#ifndef _PC 24static int int42_handler(xf86Int10InfoPtr pInt); 25#endif 26static int intE6_handler(xf86Int10InfoPtr pInt); 27static struct pci_device *findPci(xf86Int10InfoPtr pInt, unsigned short bx); 28static CARD32 pciSlotBX( const struct pci_device * pvp ); 29 30int 31int_handler(xf86Int10InfoPtr pInt) 32{ 33 int num = pInt->num; 34 int ret = 0; 35 36 switch (num) { 37#ifndef _PC 38 case 0x10: 39 case 0x42: 40 case 0x6D: 41 if (getIntVect(pInt, num) == I_S_DEFAULT_INT_VECT) 42 ret = int42_handler(pInt); 43 break; 44#endif 45 case 0x1A: 46 ret = int1A_handler(pInt); 47 break; 48 case 0xe6: 49 ret = intE6_handler(pInt); 50 break; 51 default: 52 break; 53 } 54 55 if (!ret) 56 ret = run_bios_int(num, pInt); 57 58 if (!ret) { 59 xf86DrvMsg(pInt->scrnIndex, X_ERROR, 60 "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 IOADDRESS 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 /* Remap I/O port number into its domain */ 176 ioport += pInt->ioBase; 177 178 /* Programme the mode */ 179 outb(ioport + 4, cgamode & 0x37); /* Turn off screen */ 180 for (i = 0; i < 0x10; i++) { 181 tmp = MEM_RB(pInt, regvals + i); 182 outb(ioport, i); 183 outb(ioport + 1, tmp); 184 } 185 outb(ioport + 5, cgacolour); /* Select colour mode */ 186 outb(ioport + 4, cgamode); /* Turn on screen */ 187 } 188 break; 189 190 case 0x01: 191 /* Set Cursor Type */ 192 /* Enter: CH = starting line for cursor */ 193 /* CL = ending line for cursor */ 194 /* Leave: Nothing */ 195 /* Implemented */ 196 { /* Localise */ 197 IOADDRESS ioport = MEM_RW(pInt, 0x0463) + pInt->ioBase; 198 199 MEM_WB(pInt, 0x0460, X86_CL); 200 MEM_WB(pInt, 0x0461, X86_CH); 201 202 outb(ioport, 0x0A); 203 outb(ioport + 1, X86_CH); 204 outb(ioport, 0x0B); 205 outb(ioport + 1, X86_CL); 206 } 207 break; 208 209 case 0x02: 210 /* Set Cursor Position */ 211 /* Enter: BH = display page number */ 212 /* DH = row */ 213 /* DL = column */ 214 /* Leave: Nothing */ 215 /* Implemented */ 216 { /* Localise */ 217 IOADDRESS ioport; 218 CARD16 offset; 219 220 MEM_WB(pInt, (X86_BH << 1) + 0x0450, X86_DL); 221 MEM_WB(pInt, (X86_BH << 1) + 0x0451, X86_DH); 222 223 if (X86_BH != MEM_RB(pInt, 0x0462)) 224 break; 225 226 offset = (X86_DH * MEM_RW(pInt, 0x044A)) + X86_DL; 227 offset += MEM_RW(pInt, 0x044E) << 1; 228 229 ioport = MEM_RW(pInt, 0x0463) + pInt->ioBase; 230 outb(ioport, 0x0E); 231 outb(ioport + 1, offset >> 8); 232 outb(ioport, 0x0F); 233 outb(ioport + 1, offset & 0xFF); 234 } 235 break; 236 237 case 0x03: 238 /* Get Cursor Position */ 239 /* Enter: BH = display page number */ 240 /* Leave: CH = starting line for cursor */ 241 /* CL = ending line for cursor */ 242 /* DH = row */ 243 /* DL = column */ 244 /* Implemented */ 245 { /* Localise */ 246 X86_CL = MEM_RB(pInt, 0x0460); 247 X86_CH = MEM_RB(pInt, 0x0461); 248 X86_DL = MEM_RB(pInt, (X86_BH << 1) + 0x0450); 249 X86_DH = MEM_RB(pInt, (X86_BH << 1) + 0x0451); 250 } 251 break; 252 253 case 0x04: 254 /* Get Light Pen Position */ 255 /* Enter: Nothing */ 256 /* Leave: AH = 0x01 (down/triggered) or 0x00 (not) */ 257 /* BX = pixel column */ 258 /* CX = pixel row */ 259 /* DH = character row */ 260 /* DL = character column */ 261 /* Not Implemented */ 262 { /* Localise */ 263 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 264 "int 0x%2.2x(AH=0x04) -- Get Light Pen Position\n", pInt->num); 265 if (xf86GetVerbosity() > 3) { 266 dump_registers(pInt); 267 stack_trace(pInt); 268 } 269 X86_AH = X86_BX = X86_CX = X86_DX = 0; 270 } 271 break; 272 273 case 0x05: 274 /* Set Display Page */ 275 /* Enter: AL = display page number */ 276 /* Leave: Nothing */ 277 /* Implemented */ 278 { /* Localise */ 279 IOADDRESS ioport = MEM_RW(pInt, 0x0463) + pInt->ioBase; 280 CARD16 start; 281 CARD8 x, y; 282 283 /* Calculate new start address */ 284 MEM_WB(pInt, 0x0462, X86_AL); 285 start = X86_AL * MEM_RW(pInt, 0x044C); 286 MEM_WW(pInt, 0x044E, start); 287 start <<= 1; 288 289 /* Update start address */ 290 outb(ioport, 0x0C); 291 outb(ioport + 1, start >> 8); 292 outb(ioport, 0x0D); 293 outb(ioport + 1, start & 0xFF); 294 295 /* Switch cursor position */ 296 y = MEM_RB(pInt, (X86_AL << 1) + 0x0450); 297 x = MEM_RB(pInt, (X86_AL << 1) + 0x0451); 298 start += (y * MEM_RW(pInt, 0x044A)) + x; 299 300 /* Update cursor position */ 301 outb(ioport, 0x0E); 302 outb(ioport + 1, start >> 8); 303 outb(ioport, 0x0F); 304 outb(ioport + 1, start & 0xFF); 305 } 306 break; 307 308 case 0x06: 309 /* Initialise or Scroll Window Up */ 310 /* Enter: AL = lines to scroll up */ 311 /* BH = attribute for blank */ 312 /* CH = upper y of window */ 313 /* CL = left x of window */ 314 /* DH = lower y of window */ 315 /* DL = right x of window */ 316 /* Leave: Nothing */ 317 /* Not Implemented */ 318 { /* Localise */ 319 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 320 "int 0x%2.2x(AH=0x06) -- Initialise or Scroll Window Up\n", 321 pInt->num); 322 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 323 " AL=0x%2.2x, BH=0x%2.2x," 324 " CH=0x%2.2x, CL=0x%2.2x, DH=0x%2.2x, DL=0x%2.2x\n", 325 X86_AL, X86_BH, X86_CH, X86_CL, X86_DH, X86_DL); 326 if (xf86GetVerbosity() > 3) { 327 dump_registers(pInt); 328 stack_trace(pInt); 329 } 330 } 331 break; 332 333 case 0x07: 334 /* Initialise or Scroll Window Down */ 335 /* Enter: AL = lines to scroll down */ 336 /* BH = attribute for blank */ 337 /* CH = upper y of window */ 338 /* CL = left x of window */ 339 /* DH = lower y of window */ 340 /* DL = right x of window */ 341 /* Leave: Nothing */ 342 /* Not Implemented */ 343 { /* Localise */ 344 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 345 "int 0x%2.2x(AH=0x07) -- Initialise or Scroll Window Down\n", 346 pInt->num); 347 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 348 " AL=0x%2.2x, BH=0x%2.2x," 349 " CH=0x%2.2x, CL=0x%2.2x, DH=0x%2.2x, DL=0x%2.2x\n", 350 X86_AL, X86_BH, X86_CH, X86_CL, X86_DH, X86_DL); 351 if (xf86GetVerbosity() > 3) { 352 dump_registers(pInt); 353 stack_trace(pInt); 354 } 355 } 356 break; 357 358 case 0x08: 359 /* Read Character and Attribute at Cursor */ 360 /* Enter: BH = display page number */ 361 /* Leave: AH = attribute */ 362 /* AL = character */ 363 /* Not Implemented */ 364 { /* Localise */ 365 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 366 "int 0x%2.2x(AH=0x08) -- Read Character and Attribute at" 367 " Cursor\n", pInt->num); 368 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 369 "BH=0x%2.2x\n", X86_BH); 370 if (xf86GetVerbosity() > 3) { 371 dump_registers(pInt); 372 stack_trace(pInt); 373 } 374 X86_AX = 0; 375 } 376 break; 377 378 case 0x09: 379 /* Write Character and Attribute at Cursor */ 380 /* Enter: AL = character */ 381 /* BH = display page number */ 382 /* BL = attribute (text) or colour (graphics) */ 383 /* CX = replication count */ 384 /* Leave: Nothing */ 385 /* Not Implemented */ 386 { /* Localise */ 387 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 388 "int 0x%2.2x(AH=0x09) -- Write Character and Attribute at" 389 " Cursor\n", pInt->num); 390 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 391 "AL=0x%2.2x, BH=0x%2.2x, BL=0x%2.2x, CX=0x%4.4x\n", 392 X86_AL, X86_BH, X86_BL, X86_CX); 393 if (xf86GetVerbosity() > 3) { 394 dump_registers(pInt); 395 stack_trace(pInt); 396 } 397 } 398 break; 399 400 case 0x0a: 401 /* Write Character at Cursor */ 402 /* Enter: AL = character */ 403 /* BH = display page number */ 404 /* BL = colour */ 405 /* CX = replication count */ 406 /* Leave: Nothing */ 407 /* Not Implemented */ 408 { /* Localise */ 409 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 410 "int 0x%2.2x(AH=0x0A) -- Write Character at Cursor\n", 411 pInt->num); 412 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 413 "AL=0x%2.2x, BH=0x%2.2x, BL=0x%2.2x, CX=0x%4.4x\n", 414 X86_AL, X86_BH, X86_BL, X86_CX); 415 if (xf86GetVerbosity() > 3) { 416 dump_registers(pInt); 417 stack_trace(pInt); 418 } 419 } 420 break; 421 422 case 0x0b: 423 /* Set Palette, Background or Border */ 424 /* Enter: BH = 0x00 or 0x01 */ 425 /* BL = colour or palette (respectively) */ 426 /* Leave: Nothing */ 427 /* Implemented */ 428 { /* Localise */ 429 IOADDRESS ioport = MEM_RW(pInt, 0x0463) + 5 + pInt->ioBase; 430 CARD8 cgacolour = MEM_RB(pInt, 0x0466); 431 432 if (X86_BH) { 433 cgacolour &= 0xDF; 434 cgacolour |= (X86_BL & 0x01) << 5; 435 } else { 436 cgacolour &= 0xE0; 437 cgacolour |= X86_BL & 0x1F; 438 } 439 440 MEM_WB(pInt, 0x0466, cgacolour); 441 outb(ioport, cgacolour); 442 } 443 break; 444 445 case 0x0c: 446 /* Write Graphics Pixel */ 447 /* Enter: AL = pixel value */ 448 /* BH = display page number */ 449 /* CX = column */ 450 /* DX = row */ 451 /* Leave: Nothing */ 452 /* Not Implemented */ 453 { /* Localise */ 454 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 455 "int 0x%2.2x(AH=0x0C) -- Write Graphics Pixel\n", pInt->num); 456 xf86DrvMsgVerb(pInt->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->scrnIndex, X_NOT_IMPLEMENTED, 2, 475 "int 0x%2.2x(AH=0x0D) -- Read Graphics Pixel\n", pInt->num); 476 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 477 "BH=0x%2.2x, CX=0x%4.4x, DX=0x%4.4x\n", 478 X86_BH, X86_CX, X86_DX); 479 if (xf86GetVerbosity() > 3) { 480 dump_registers(pInt); 481 stack_trace(pInt); 482 } 483 X86_AL = 0; 484 } 485 break; 486 487 case 0x0e: 488 /* Write Character in Teletype Mode */ 489 /* Enter: AL = character */ 490 /* BH = display page number */ 491 /* BL = foreground colour */ 492 /* Leave: Nothing */ 493 /* Not Implemented */ 494 /* WARNING: Emulation of BEL characters will require */ 495 /* emulation of RTC and PC speaker I/O. */ 496 /* Also, this recurses through int 0x10 */ 497 /* which might or might not have been */ 498 /* installed yet. */ 499 { /* Localise */ 500 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 501 "int 0x%2.2x(AH=0x0E) -- Write Character in Teletype Mode\n", 502 pInt->num); 503 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 504 "AL=0x%2.2x, BH=0x%2.2x, BL=0x%2.2x\n", 505 X86_AL, X86_BH, X86_BL); 506 if (xf86GetVerbosity() > 3) { 507 dump_registers(pInt); 508 stack_trace(pInt); 509 } 510 } 511 break; 512 513 case 0x0f: 514 /* Get Video Mode */ 515 /* Enter: Nothing */ 516 /* Leave: AH = number of columns */ 517 /* AL = video mode number */ 518 /* BH = display page number */ 519 /* Implemented */ 520 { /* Localise */ 521 X86_AH = MEM_RW(pInt, 0x044A); 522 X86_AL = MEM_RB(pInt, 0x0449); 523 X86_BH = MEM_RB(pInt, 0x0462); 524 } 525 break; 526 527 case 0x10: 528 /* Colour Control (subfunction in AL) */ 529 /* Enter: Various */ 530 /* Leave: Various */ 531 /* Ignored */ 532 break; 533 534 case 0x11: 535 /* Font Control (subfunction in AL) */ 536 /* Enter: Various */ 537 /* Leave: Various */ 538 /* Ignored */ 539 break; 540 541 case 0x12: 542 /* Miscellaneous (subfunction in BL) */ 543 /* Enter: Various */ 544 /* Leave: Various */ 545 /* Ignored. Previous code here optionally allowed */ 546 /* the enabling and disabling of VGA, but no system */ 547 /* BIOS I've come across actually implements it. */ 548 break; 549 550 case 0x13: 551 /* Write String in Teletype Mode */ 552 /* Enter: AL = write mode */ 553 /* BL = attribute (if (AL & 0x02) == 0) */ 554 /* CX = string length */ 555 /* DH = row */ 556 /* DL = column */ 557 /* ES:BP = string segment:offset */ 558 /* Leave: Nothing */ 559 /* Not Implemented */ 560 /* WARNING: Emulation of BEL characters will require */ 561 /* emulation of RTC and PC speaker I/O. */ 562 /* Also, this recurses through int 0x10 */ 563 /* which might or might not have been */ 564 /* installed yet. */ 565 { /* Localise */ 566 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 567 "int 0x%2.2x(AH=0x13) -- Write String in Teletype Mode\n", 568 pInt->num); 569 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, 570 "AL=0x%2.2x, BL=0x%2.2x, CX=0x%4.4x," 571 " DH=0x%2.2x, DL=0x%2.2x, ES:BP=0x%4.4x:0x%4.4x\n", 572 X86_AL, X86_BL, X86_CX, X86_DH, X86_DL, X86_ES, X86_BP); 573 if (xf86GetVerbosity() > 3) { 574 dump_registers(pInt); 575 stack_trace(pInt); 576 } 577 } 578 break; 579 580 default: 581 /* Various extensions */ 582 /* Enter: Various */ 583 /* Leave: Various */ 584 /* Ignored */ 585 break; 586 } 587 588 return 1; 589} 590#endif 591 592#define SUCCESSFUL 0x00 593#define DEVICE_NOT_FOUND 0x86 594#define BAD_REGISTER_NUMBER 0x87 595 596#ifdef SHOW_ALL_DEVICES 597/** 598 * These functions are meant to be used by the PCI BIOS emulation. Some 599 * BIOSes need to see if there are \b other chips of the same type around so 600 * by setting \c exclude one PCI device can be explicitely excluded, if 601 * required. 602 */ 603static struct pci_device * 604do_find(const struct pci_id_match *m, char n, const struct pci_device * exclude) 605{ 606 struct pci_device *dev; 607 struct pci_device_iterator *iter; 608 609 n++; 610 611 iter = pci_id_match_iterator_create(m); 612 while ((dev = pci_device_next(iter)) != NULL) { 613 if ((dev != exclude) && !(--n)) { 614 break; 615 } 616 } 617 618 pci_iterator_destroy(iter); 619 620 return dev; 621} 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 struct pci_slot_match m = { dev->domain, 667 PCI_MATCH_ANY, 668 PCI_MATCH_ANY, 669 PCI_MATCH_ANY }; 670 struct pci_device_iterator *iter; 671 int i = 0; 672 673 iter = pci_slot_match_iterator_create(&m); 674 675 while ((d = pci_device_next(iter))) 676 if (d->bus > i) 677 i = d->bus; 678 679 pci_iterator_destroy(iter); 680 681 return i; 682} 683 684static int 685int1A_handler(xf86Int10InfoPtr pInt) 686{ 687 struct pci_device * const pvp = xf86GetPciInfoForEntity(pInt->entityIndex); 688 struct pci_device * dev; 689 690 if (pvp == NULL) 691 return 0; /* oops */ 692 693#ifdef PRINT_INT 694 ErrorF("int 0x1a: ax=0x%x bx=0x%x cx=0x%x dx=0x%x di=0x%x es=0x%x\n", 695 X86_EAX, X86_EBX, X86_ECX, X86_EDX, X86_EDI, X86_ESI); 696#endif 697 switch (X86_AX) { 698 case 0xb101: 699 X86_EAX &= 0xFF00; /* no config space/special cycle support */ 700 X86_EDX = 0x20494350; /* " ICP" */ 701 X86_EBX = 0x0210; /* Version 2.10 */ 702 X86_ECX &= 0xFF00; 703 X86_ECX |= int1A_last_bus_number(pvp); 704 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 705#ifdef PRINT_INT 706 ErrorF("ax=0x%x dx=0x%x bx=0x%x cx=0x%x flags=0x%x\n", 707 X86_EAX, X86_EDX, X86_EBX, X86_ECX, X86_EFLAGS); 708#endif 709 return 1; 710 case 0xb102: 711 if ( (X86_DX == pvp->vendor_id) 712 && (X86_CX == pvp->device_id) 713 && (X86_ESI == 0) ) { 714 X86_EAX = X86_AL | (SUCCESSFUL << 8); 715 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 716 X86_EBX = pciSlotBX(pvp); 717 } 718#ifdef SHOW_ALL_DEVICES 719 else 720 if ((dev = find_pci_device_vendor(X86_EDX, X86_ECX, X86_ESI, pvp))) { 721 X86_EAX = X86_AL | (SUCCESSFUL << 8); 722 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 723 X86_EBX = pciSlotBX(dev); 724 } 725#endif 726 else { 727 X86_EAX = X86_AL | (DEVICE_NOT_FOUND << 8); 728 X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ 729 } 730#ifdef PRINT_INT 731 ErrorF("ax=0x%x bx=0x%x flags=0x%x\n", X86_EAX, X86_EBX, X86_EFLAGS); 732#endif 733 return 1; 734 case 0xb103: 735 if ( (X86_ECX & 0x00FFFFFF) == pvp->device_class ) { 736 X86_EAX = X86_AL | (SUCCESSFUL << 8); 737 X86_EBX = pciSlotBX(pvp); 738 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 739 } 740#ifdef SHOW_ALL_DEVICES 741 else if ((dev = find_pci_class(X86_CL, X86_CH, 742 (X86_ECX & 0xffff0000) >> 16, 743 X86_ESI, pvp))) { 744 X86_EAX = X86_AL | (SUCCESSFUL << 8); 745 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 746 X86_EBX = pciSlotBX(dev); 747 } 748#endif 749 else { 750 X86_EAX = X86_AL | (DEVICE_NOT_FOUND << 8); 751 X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ 752 } 753#ifdef PRINT_INT 754 ErrorF("ax=0x%x flags=0x%x\n", X86_EAX, X86_EFLAGS); 755#endif 756 return 1; 757 case 0xb108: 758 if ((dev = findPci(pInt, X86_EBX)) != NULL) { 759 pci_device_cfg_read_u8(dev, & X86_CL, X86_DI); 760 X86_EAX = X86_AL | (SUCCESSFUL << 8); 761 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 762 } else { 763 X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); 764 X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ 765 } 766#ifdef PRINT_INT 767 ErrorF("ax=0x%x cx=0x%x flags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS); 768#endif 769 return 1; 770 case 0xb109: 771 if ((dev = findPci(pInt, X86_EBX)) != NULL) { 772 pci_device_cfg_read_u16(dev, & X86_CX, X86_DI); 773 X86_EAX = X86_AL | (SUCCESSFUL << 8); 774 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 775 } else { 776 X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); 777 X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ 778 } 779#ifdef PRINT_INT 780 ErrorF("ax=0x%x cx=0x%x flags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS); 781#endif 782 return 1; 783 case 0xb10a: 784 if ((dev = findPci(pInt, X86_EBX)) != NULL) { 785 uint32_t ecx; 786 pci_device_cfg_read_u32(dev, & ecx, X86_DI); 787 X86_ECX = ecx; 788 X86_EAX = X86_AL | (SUCCESSFUL << 8); 789 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 790 } else { 791 X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); 792 X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ 793 } 794#ifdef PRINT_INT 795 ErrorF("ax=0x%x cx=0x%x flags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS); 796#endif 797 return 1; 798 case 0xb10b: 799 if ((dev = findPci(pInt, X86_EBX)) != NULL) { 800 pci_device_cfg_write_u8(dev, X86_CL, X86_DI); 801 X86_EAX = X86_AL | (SUCCESSFUL << 8); 802 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 803 } else { 804 X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); 805 X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ 806 } 807#ifdef PRINT_INT 808 ErrorF("ax=0x%x flags=0x%x\n", X86_EAX, X86_EFLAGS); 809#endif 810 return 1; 811 case 0xb10c: 812 if ((dev = findPci(pInt, X86_EBX)) != NULL) { 813 pci_device_cfg_write_u16(dev, X86_CX, X86_DI); 814 X86_EAX = X86_AL | (SUCCESSFUL << 8); 815 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 816 } else { 817 X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); 818 X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ 819 } 820#ifdef PRINT_INT 821 ErrorF("ax=0x%x flags=0x%x\n", X86_EAX, X86_EFLAGS); 822#endif 823 return 1; 824 case 0xb10d: 825 if ((dev = findPci(pInt, X86_EBX)) != NULL) { 826 pci_device_cfg_write_u32(dev, X86_ECX, X86_DI); 827 X86_EAX = X86_AL | (SUCCESSFUL << 8); 828 X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ 829 } else { 830 X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); 831 X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ 832 } 833#ifdef PRINT_INT 834 ErrorF("ax=0x%x flags=0x%x\n", X86_EAX, X86_EFLAGS); 835#endif 836 return 1; 837 default: 838 xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 839 "int 0x1a subfunction\n"); 840 dump_registers(pInt); 841 if (xf86GetVerbosity() > 3) 842 stack_trace(pInt); 843 return 0; 844 } 845} 846 847static struct pci_device * 848findPci(xf86Int10InfoPtr pInt, unsigned short bx) 849{ 850 const unsigned bus = (bx >> 8) & 0x00FF; 851 const unsigned dev = (bx >> 3) & 0x001F; 852 const unsigned func = (bx ) & 0x0007; 853 854 return pci_device_find_by_slot(pInt->dev->domain, bus, dev, func); 855} 856 857static CARD32 858pciSlotBX(const struct pci_device * pvp) 859{ 860 return ((pvp->bus << 8) & 0x00FF00) | (pvp->dev << 3) | (pvp->func); 861} 862 863/* 864 * handle initialization 865 */ 866static int 867intE6_handler(xf86Int10InfoPtr pInt) 868{ 869 struct pci_device * pvp; 870 871 if ((pvp = xf86GetPciInfoForEntity(pInt->entityIndex))) 872 X86_AX = (pvp->bus << 8) | (pvp->dev << 3) | (pvp->func & 0x7); 873 pushw(pInt, X86_CS); 874 pushw(pInt, X86_IP); 875 X86_CS = pInt->BIOSseg; 876 X86_EIP = 0x0003; 877 X86_ES = 0; /* standard pc es */ 878 return 1; 879} 880