xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xf86int10.c (32380B)


      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 
     20 xf86Int10InfoPtr Int10Current = NULL;
     21 
     22 static int int1A_handler(xf86Int10InfoPtr pInt);
     23 
     24 #ifndef _PC
     25 static int int42_handler(xf86Int10InfoPtr pInt);
     26 #endif
     27 static int intE6_handler(xf86Int10InfoPtr pInt);
     28 static struct pci_device *findPci(xf86Int10InfoPtr pInt, unsigned short bx);
     29 static CARD32 pciSlotBX(const struct pci_device *pvp);
     30 
     31 int
     32 int_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  */
     77 static int
     78 int42_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  */
    604 static struct pci_device *
    605 do_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 
    624 static struct pci_device *
    625 find_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 
    640 static struct pci_device *
    641 find_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  */
    662 static int
    663 int1A_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 
    686 static int
    687 int1A_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 
    852 static struct pci_device *
    853 findPci(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 
    862 static CARD32
    863 pciSlotBX(const struct pci_device *pvp)
    864 {
    865     return ((pvp->bus << 8) & 0x00FF00) | (pvp->dev << 3) | (pvp->func);
    866 }
    867 
    868 /*
    869  * handle initialization
    870  */
    871 static int
    872 intE6_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 }