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