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