helper_exec.c revision af31da9a
1/*
2 *                   XFree86 int10 module
3 *   execute BIOS int 10h calls in x86 real mode environment
4 *                 Copyright 1999 Egbert Eich
5 *
6 *   Part of this code was inspired  by the VBIOS POSTing code in DOSEMU
7 *   developed by the "DOSEMU-Development-Team"
8 */
9
10/*
11 * To debug port accesses define PRINT_PORT to 1.
12 * Note! You also have to comment out ioperm()
13 * in xf86EnableIO(). Otherwise we won't trap
14 * on PIO.
15 */
16
17#ifdef HAVE_XORG_CONFIG_H
18#include <xorg-config.h>
19#endif
20
21#define PRINT_PORT 0
22
23#include <unistd.h>
24
25#include <X11/Xos.h>
26#include "xf86.h"
27#include "xf86_OSproc.h"
28#include "compiler.h"
29#define _INT10_PRIVATE
30#include "int10Defines.h"
31#include "xf86int10.h"
32#include "Pci.h"
33#ifdef _X86EMU
34#include "x86emu/x86emui.h"
35#else
36#define DEBUG_IO_TRACE() 0
37#endif
38#include <pciaccess.h>
39
40static int pciCfg1in(CARD16 addr, CARD32 *val);
41static int pciCfg1out(CARD16 addr, CARD32 val);
42static int pciCfg1inw(CARD16 addr, CARD16 *val);
43static int pciCfg1outw(CARD16 addr, CARD16 val);
44static int pciCfg1inb(CARD16 addr, CARD8 *val);
45static int pciCfg1outb(CARD16 addr, CARD8 val);
46#if defined (_PC)
47static void SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set);
48#endif
49
50#define REG pInt
51
52int
53setup_int(xf86Int10InfoPtr pInt)
54{
55    if (pInt != Int10Current) {
56	if (!MapCurrentInt10(pInt))
57	    return -1;
58	Int10Current = pInt;
59    }
60    X86_EAX = (CARD32) pInt->ax;
61    X86_EBX = (CARD32) pInt->bx;
62    X86_ECX = (CARD32) pInt->cx;
63    X86_EDX = (CARD32) pInt->dx;
64    X86_ESI = (CARD32) pInt->si;
65    X86_EDI = (CARD32) pInt->di;
66    X86_EBP = (CARD32) pInt->bp;
67    X86_ESP = 0x1000; X86_SS = pInt->stackseg >> 4;
68    X86_EIP = 0x0600; X86_CS = 0x0;	/* address of 'hlt' */
69    X86_DS = 0x40;			/* standard pc ds */
70    X86_ES = pInt->es;
71    X86_FS = 0;
72    X86_GS = 0;
73    X86_EFLAGS = X86_IF_MASK | X86_IOPL_MASK;
74#if defined (_PC)
75    if (pInt->Flags & SET_BIOS_SCRATCH)
76	SetResetBIOSVars(pInt, TRUE);
77#endif
78    return xf86BlockSIGIO();
79}
80
81void
82finish_int(xf86Int10InfoPtr pInt, int sig)
83{
84    xf86UnblockSIGIO(sig);
85    pInt->ax = (CARD32) X86_EAX;
86    pInt->bx = (CARD32) X86_EBX;
87    pInt->cx = (CARD32) X86_ECX;
88    pInt->dx = (CARD32) X86_EDX;
89    pInt->si = (CARD32) X86_ESI;
90    pInt->di = (CARD32) X86_EDI;
91    pInt->es = (CARD16) X86_ES;
92    pInt->bp = (CARD32) X86_EBP;
93    pInt->flags = (CARD32) X86_FLAGS;
94#if defined (_PC)
95    if (pInt->Flags & RESTORE_BIOS_SCRATCH)
96	SetResetBIOSVars(pInt, FALSE);
97#endif
98}
99
100/* general software interrupt handler */
101CARD32
102getIntVect(xf86Int10InfoPtr pInt,int num)
103{
104    return MEM_RW(pInt, num << 2) + (MEM_RW(pInt, (num << 2) + 2) << 4);
105}
106
107void
108pushw(xf86Int10InfoPtr pInt, CARD16 val)
109{
110    X86_ESP -= 2;
111    MEM_WW(pInt, ((CARD32) X86_SS << 4) + X86_SP, val);
112}
113
114int
115run_bios_int(int num, xf86Int10InfoPtr pInt)
116{
117    CARD32 eflags;
118#ifndef _PC
119    /* check if bios vector is initialized */
120    if (MEM_RW(pInt, (num << 2) + 2) == (SYS_BIOS >> 4)) { /* SYS_BIOS_SEG ?*/
121
122	if (num == 21 && X86_AH == 0x4e) {
123 	    xf86DrvMsg(pInt->scrnIndex, X_NOTICE,
124		       "Failing Find-Matching-File on non-PC"
125			" (int 21, func 4e)\n");
126 	    X86_AX = 2;
127 	    SET_FLAG(F_CF);
128 	    return 1;
129 	} else {
130	    xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2,
131			   "Ignoring int 0x%02x call\n", num);
132	    if (xf86GetVerbosity() > 3) {
133		dump_registers(pInt);
134		stack_trace(pInt);
135	    }
136	    return 1;
137	}
138    }
139#endif
140#ifdef PRINT_INT
141    ErrorF("calling card BIOS at: ");
142#endif
143    eflags = X86_EFLAGS;
144#if 0
145    eflags = eflags | IF_MASK;
146    X86_EFLAGS = X86_EFLAGS  & ~(VIF_MASK | TF_MASK | IF_MASK | NT_MASK);
147#endif
148    pushw(pInt, eflags);
149    pushw(pInt, X86_CS);
150    pushw(pInt, X86_IP);
151    X86_CS = MEM_RW(pInt, (num << 2) + 2);
152    X86_IP = MEM_RW(pInt,  num << 2);
153#ifdef PRINT_INT
154    ErrorF("0x%x:%lx\n", X86_CS, X86_EIP);
155#endif
156    return 1;
157}
158
159/* Debugging stuff */
160void
161dump_code(xf86Int10InfoPtr pInt)
162{
163    int i;
164    unsigned long lina = SEG_ADR((CARD32), X86_CS, IP);
165
166    xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, "code at 0x%8.8lx:\n", lina);
167    for (i=0; i<0x10; i++)
168	xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i));
169    xf86ErrorFVerb(3, "\n");
170    for (; i<0x20; i++)
171	xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i));
172    xf86ErrorFVerb(3, "\n");
173}
174
175void
176dump_registers(xf86Int10InfoPtr pInt)
177{
178    xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3,
179	"EAX=0x%8.8lx, EBX=0x%8.8lx, ECX=0x%8.8lx, EDX=0x%8.8lx\n",
180	(unsigned long)X86_EAX, (unsigned long)X86_EBX,
181	(unsigned long)X86_ECX, (unsigned long)X86_EDX);
182    xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3,
183	"ESP=0x%8.8lx, EBP=0x%8.8lx, ESI=0x%8.8lx, EDI=0x%8.8lx\n",
184	(unsigned long)X86_ESP, (unsigned long)X86_EBP,
185	(unsigned long)X86_ESI, (unsigned long)X86_EDI);
186    xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3,
187	"CS=0x%4.4x, SS=0x%4.4x,"
188	" DS=0x%4.4x, ES=0x%4.4x, FS=0x%4.4x, GS=0x%4.4x\n",
189	X86_CS, X86_SS, X86_DS, X86_ES, X86_FS, X86_GS);
190    xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3,
191	"EIP=0x%8.8lx, EFLAGS=0x%8.8lx\n",
192	(unsigned long)X86_EIP, (unsigned long)X86_EFLAGS);
193}
194
195void
196stack_trace(xf86Int10InfoPtr pInt)
197{
198    int i = 0;
199    unsigned long stack = SEG_ADR((CARD32), X86_SS, SP);
200    unsigned long tail  = (CARD32)((X86_SS << 4) + 0x1000);
201
202    if (stack >= tail) return;
203
204    xf86MsgVerb(X_INFO, 3, "stack at 0x%8.8lx:\n", stack);
205    for (; stack < tail; stack++) {
206	xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, stack));
207	i = (i + 1) % 0x10;
208	if (!i)
209	    xf86ErrorFVerb(3, "\n");
210    }
211    if (i)
212	xf86ErrorFVerb(3, "\n");
213}
214
215int
216port_rep_inb(xf86Int10InfoPtr pInt,
217	     CARD16 port, CARD32 base, int d_f, CARD32 count)
218{
219    register int inc = d_f ? -1 : 1;
220    CARD32 dst = base;
221    if (PRINT_PORT && DEBUG_IO_TRACE())
222	ErrorF(" rep_insb(%#x) %ld bytes at %8.8lx %s\n",
223		port, count, base, d_f ? "up" : "down");
224    while (count--) {
225	MEM_WB(pInt, dst, x_inb(port));
226	dst += inc;
227    }
228    return dst - base;
229}
230
231int
232port_rep_inw(xf86Int10InfoPtr pInt,
233	     CARD16 port, CARD32 base, int d_f, CARD32 count)
234{
235    register int inc = d_f ? -2 : 2;
236    CARD32 dst = base;
237    if (PRINT_PORT && DEBUG_IO_TRACE())
238	ErrorF(" rep_insw(%#x) %ld bytes at %8.8lx %s\n",
239	     port, count, base, d_f ? "up" : "down");
240    while (count--) {
241	MEM_WW(pInt, dst, x_inw(port));
242	dst += inc;
243    }
244    return dst - base;
245}
246
247int
248port_rep_inl(xf86Int10InfoPtr pInt,
249	     CARD16 port, CARD32 base, int d_f, CARD32 count)
250{
251    register int inc = d_f ? -4 : 4;
252    CARD32 dst = base;
253    if (PRINT_PORT && DEBUG_IO_TRACE())
254	ErrorF(" rep_insl(%#x) %ld bytes at %8.8lx %s\n",
255	     port, count, base, d_f ? "up" : "down");
256    while (count--) {
257	MEM_WL(pInt, dst, x_inl(port));
258	dst += inc;
259    }
260    return dst - base;
261}
262
263int
264port_rep_outb(xf86Int10InfoPtr pInt,
265	      CARD16 port, CARD32 base, int d_f, CARD32 count)
266{
267    register int inc = d_f ? -1 : 1;
268    CARD32 dst = base;
269    if (PRINT_PORT && DEBUG_IO_TRACE())
270	ErrorF(" rep_outb(%#x) %ld bytes at %8.8lx %s\n",
271	     port, count, base, d_f ? "up" : "down");
272    while (count--) {
273	x_outb(port, MEM_RB(pInt, dst));
274	dst += inc;
275    }
276    return dst - base;
277}
278
279int
280port_rep_outw(xf86Int10InfoPtr pInt,
281	      CARD16 port, CARD32 base, int d_f, CARD32 count)
282{
283    register int inc = d_f ? -2 : 2;
284    CARD32 dst = base;
285    if (PRINT_PORT && DEBUG_IO_TRACE())
286	ErrorF(" rep_outw(%#x) %ld bytes at %8.8lx %s\n",
287	     port, count, base, d_f ? "up" : "down");
288    while (count--) {
289	x_outw(port, MEM_RW(pInt, dst));
290	dst += inc;
291    }
292    return dst - base;
293}
294
295int
296port_rep_outl(xf86Int10InfoPtr pInt,
297	      CARD16 port, CARD32 base, int d_f, CARD32 count)
298{
299    register int inc = d_f ? -4 : 4;
300    CARD32 dst = base;
301    if (PRINT_PORT && DEBUG_IO_TRACE())
302	ErrorF(" rep_outl(%#x) %ld bytes at %8.8lx %s\n",
303	     port, count, base, d_f ? "up" : "down");
304    while (count--) {
305	x_outl(port, MEM_RL(pInt, dst));
306	dst += inc;
307    }
308    return dst - base;
309}
310
311CARD8
312x_inb(CARD16 port)
313{
314    CARD8 val;
315
316    if (port == 0x40) {
317	Int10Current->inb40time++;
318	val = (CARD8)(Int10Current->inb40time >>
319		      ((Int10Current->inb40time & 1) << 3));
320	if (PRINT_PORT && DEBUG_IO_TRACE())
321	    ErrorF(" inb(%#x) = %2.2x\n", port, val);
322#ifdef __NOT_YET__
323    } else if (port < 0x0100) {		/* Don't interfere with mainboard */
324	val = 0;
325	xf86DrvMsgVerb(Int10Current->scrnIndex, X_NOT_IMPLEMENTED, 2,
326	    "inb 0x%4.4x\n", port);
327	if (xf86GetVerbosity() > 3) {
328	    dump_registers(Int10Current);
329	    stack_trace(Int10Current);
330	}
331#endif /* __NOT_YET__ */
332    } else if (!pciCfg1inb(port, &val)) {
333	val = inb(Int10Current->ioBase + port);
334	if (PRINT_PORT && DEBUG_IO_TRACE())
335	    ErrorF(" inb(%#x) = %2.2x\n", port, val);
336    }
337    return val;
338}
339
340CARD16
341x_inw(CARD16 port)
342{
343    CARD16 val;
344
345    if (port == 0x5c) {
346	struct timeval tv;
347
348	/*
349	 * Emulate a PC98's timer.  Typical resolution is 3.26 usec.
350	 * Approximate this by dividing by 3.
351	 */
352	X_GETTIMEOFDAY(&tv);
353	val = (CARD16)(tv.tv_usec / 3);
354    } else if (!pciCfg1inw(port, &val)) {
355	val = inw(Int10Current->ioBase + port);
356	if (PRINT_PORT && DEBUG_IO_TRACE())
357	    ErrorF(" inw(%#x) = %4.4x\n", port, val);
358    }
359    return val;
360}
361
362void
363x_outb(CARD16 port, CARD8 val)
364{
365    if ((port == 0x43) && (val == 0)) {
366	struct timeval tv;
367	/*
368	 * Emulate a PC's timer 0.  Such timers typically have a resolution of
369	 * some .838 usec per tick, but this can only provide 1 usec per tick.
370	 * (Not that this matters much, given inherent emulation delays.)  Use
371	 * the bottom bit as a byte select.  See inb(0x40) above.
372	 */
373	X_GETTIMEOFDAY(&tv);
374	Int10Current->inb40time = (CARD16)(tv.tv_usec | 1);
375	if (PRINT_PORT && DEBUG_IO_TRACE())
376	    ErrorF(" outb(%#x, %2.2x)\n", port, val);
377#ifdef __NOT_YET__
378    } else if (port < 0x0100) {		/* Don't interfere with mainboard */
379	xf86DrvMsgVerb(Int10Current->scrnIndex, X_NOT_IMPLEMENTED, 2,
380	    "outb 0x%4.4x,0x%2.2x\n", port, val);
381	if (xf86GetVerbosity() > 3) {
382	    dump_registers(Int10Current);
383	    stack_trace(Int10Current);
384	}
385#endif /* __NOT_YET__ */
386    } else if (!pciCfg1outb(port, val)) {
387	if (PRINT_PORT && DEBUG_IO_TRACE())
388	    ErrorF(" outb(%#x, %2.2x)\n", port, val);
389	outb(Int10Current->ioBase + port, val);
390    }
391}
392
393void
394x_outw(CARD16 port, CARD16 val)
395{
396
397    if (!pciCfg1outw(port, val)) {
398	if (PRINT_PORT && DEBUG_IO_TRACE())
399	    ErrorF(" outw(%#x, %4.4x)\n", port, val);
400	outw(Int10Current->ioBase + port, val);
401    }
402}
403
404CARD32
405x_inl(CARD16 port)
406{
407    CARD32 val;
408
409    if (!pciCfg1in(port, &val)) {
410	val = inl(Int10Current->ioBase + port);
411	if (PRINT_PORT && DEBUG_IO_TRACE())
412	    ErrorF(" inl(%#x) = %8.8lx\n", port, val);
413    }
414    return val;
415}
416
417void
418x_outl(CARD16 port, CARD32 val)
419{
420    if (!pciCfg1out(port, val)) {
421	if (PRINT_PORT && DEBUG_IO_TRACE())
422	    ErrorF(" outl(%#x, %8.8lx)\n", port, val);
423	outl(Int10Current->ioBase + port, val);
424    }
425}
426
427CARD8
428Mem_rb(CARD32 addr)
429{
430    return (*Int10Current->mem->rb)(Int10Current, addr);
431}
432
433CARD16
434Mem_rw(CARD32 addr)
435{
436    return (*Int10Current->mem->rw)(Int10Current, addr);
437}
438
439CARD32
440Mem_rl(CARD32 addr)
441{
442    return (*Int10Current->mem->rl)(Int10Current, addr);
443}
444
445void
446Mem_wb(CARD32 addr, CARD8 val)
447{
448    (*Int10Current->mem->wb)(Int10Current, addr, val);
449}
450
451void
452Mem_ww(CARD32 addr, CARD16 val)
453{
454    (*Int10Current->mem->ww)(Int10Current, addr, val);
455}
456
457void
458Mem_wl(CARD32 addr, CARD32 val)
459{
460    (*Int10Current->mem->wl)(Int10Current, addr, val);
461}
462
463static CARD32 PciCfg1Addr = 0;
464
465#define PCI_OFFSET(x) ((x) & 0x000000ff)
466#define PCI_TAG(x)    ((x) & 0x7fffff00)
467
468static struct pci_device*
469pci_device_for_cfg_address (CARD32 addr)
470{
471	struct pci_device *dev = NULL;
472	PCITAG tag = PCI_TAG(addr);
473	struct pci_slot_match slot_match = {
474		.domain = PCI_DOM_FROM_TAG(tag),
475		.bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(tag)),
476		.dev = PCI_DEV_FROM_TAG(tag),
477		.func = PCI_FUNC_FROM_TAG(tag),
478		.match_data = 0
479	};
480
481	struct pci_device_iterator *iter =
482	    pci_slot_match_iterator_create (&slot_match);
483
484	if (iter)
485		dev = pci_device_next(iter);
486
487	pci_iterator_destroy(iter);
488
489	return dev;
490}
491
492static int
493pciCfg1in(CARD16 addr, CARD32 *val)
494{
495    if (addr == 0xCF8) {
496	*val = PciCfg1Addr;
497	return 1;
498    }
499    if (addr == 0xCFC) {
500	pci_device_cfg_read_u32(pci_device_for_cfg_address(PciCfg1Addr),
501			/*
502			 * XXXMRG
503			 * this one is OK - CARD32 is "long" for 32 bit
504			 * and "int" for 64 bit
505			 */
506			(uint32_t *)
507			val, PCI_OFFSET(PciCfg1Addr));
508	if (PRINT_PORT && DEBUG_IO_TRACE())
509	    ErrorF(" cfg_inl(%#lx) = %8.8lx\n", PciCfg1Addr, *val);
510	return 1;
511    }
512    return 0;
513}
514
515static int
516pciCfg1out(CARD16 addr, CARD32 val)
517{
518    if (addr == 0xCF8) {
519	PciCfg1Addr = val;
520	return 1;
521    }
522    if (addr == 0xCFC) {
523	if (PRINT_PORT && DEBUG_IO_TRACE())
524	    ErrorF(" cfg_outl(%#lx, %8.8lx)\n", PciCfg1Addr, val);
525	pci_device_cfg_write_u32(pci_device_for_cfg_address(PciCfg1Addr),
526			val, PCI_OFFSET(PciCfg1Addr));
527	return 1;
528    }
529    return 0;
530}
531
532static int
533pciCfg1inw(CARD16 addr, CARD16 *val)
534{
535    int shift;
536
537    if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
538	shift = (addr - 0xCF8) * 8;
539	*val = (PciCfg1Addr >> shift) & 0xffff;
540	return 1;
541    }
542    if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
543	const unsigned offset = addr - 0xCFC;
544
545	pci_device_cfg_read_u16(pci_device_for_cfg_address(PciCfg1Addr),
546			val, PCI_OFFSET(PciCfg1Addr) + offset);
547	if (PRINT_PORT && DEBUG_IO_TRACE())
548	    ErrorF(" cfg_inw(%#lx) = %4.4x\n", PciCfg1Addr + offset, *val);
549	return 1;
550    }
551    return 0;
552}
553
554static int
555pciCfg1outw(CARD16 addr, CARD16 val)
556{
557    int shift;
558
559    if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
560	shift = (addr - 0xCF8) * 8;
561	PciCfg1Addr &= ~(0xffff << shift);
562	PciCfg1Addr |= ((CARD32) val) << shift;
563	return 1;
564    }
565    if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
566	const unsigned offset = addr - 0xCFC;
567
568	if (PRINT_PORT && DEBUG_IO_TRACE())
569	    ErrorF(" cfg_outw(%#lx, %4.4x)\n", PciCfg1Addr + offset, val);
570	pci_device_cfg_write_u16(pci_device_for_cfg_address(PciCfg1Addr),
571			val, PCI_OFFSET(PciCfg1Addr) + offset);
572	return 1;
573    }
574    return 0;
575}
576
577static int
578pciCfg1inb(CARD16 addr, CARD8 *val)
579{
580    int shift;
581
582    if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
583	shift = (addr - 0xCF8) * 8;
584	*val = (PciCfg1Addr >> shift) & 0xff;
585	return 1;
586    }
587    if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
588	const unsigned offset = addr - 0xCFC;
589
590	pci_device_cfg_read_u8(pci_device_for_cfg_address(PciCfg1Addr),
591			val, PCI_OFFSET(PciCfg1Addr) + offset);
592	if (PRINT_PORT && DEBUG_IO_TRACE())
593	    ErrorF(" cfg_inb(%#lx) = %2.2x\n", PciCfg1Addr + offset, *val);
594	return 1;
595    }
596    return 0;
597}
598
599static int
600pciCfg1outb(CARD16 addr, CARD8 val)
601{
602    int shift;
603
604    if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
605	shift = (addr - 0xCF8) * 8;
606	PciCfg1Addr &= ~(0xff << shift);
607	PciCfg1Addr |= ((CARD32) val) << shift;
608	return 1;
609    }
610    if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
611	const unsigned offset = addr - 0xCFC;
612
613	if (PRINT_PORT && DEBUG_IO_TRACE())
614	    ErrorF(" cfg_outb(%#lx, %2.2x)\n", PciCfg1Addr + offset, val);
615	pci_device_cfg_write_u8(pci_device_for_cfg_address(PciCfg1Addr),
616			val, PCI_OFFSET(PciCfg1Addr) + offset);
617	return 1;
618    }
619    return 0;
620}
621
622CARD8
623bios_checksum(const CARD8 *start, int size)
624{
625    CARD8 sum = 0;
626
627    while (size-- > 0)
628	sum += *start++;
629    return sum;
630}
631
632/*
633 * Lock/Unlock legacy VGA. Some Bioses try to be very clever and make
634 * an attempt to detect a legacy ISA card. If they find one they might
635 * act very strange: for example they might configure the card as a
636 * monochrome card. This might cause some drivers to choke.
637 * To avoid this we attempt legacy VGA by writing to all know VGA
638 * disable registers before we call the BIOS initialization and
639 * restore the original values afterwards. In beween we hold our
640 * breath. To get to a (possibly exising) ISA card need to disable
641 * our current PCI card.
642 */
643/*
644 * This is just for booting: we just want to catch pure
645 * legacy vga therefore we don't worry about mmio etc.
646 * This stuff should really go into vgaHW.c. However then
647 * the driver would have to load the vga-module prior to
648 * doing int10.
649 */
650void
651LockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga)
652{
653#ifndef NO_LEGACY_VGA
654    vga->save_msr    = inb(pInt->ioBase + 0x03CC);
655    vga->save_vse    = inb(pInt->ioBase + 0x03C3);
656#ifndef __ia64__
657    vga->save_46e8   = inb(pInt->ioBase + 0x46E8);
658#endif
659    vga->save_pos102 = inb(pInt->ioBase + 0x0102);
660    outb(pInt->ioBase + 0x03C2, ~(CARD8)0x03 & vga->save_msr);
661    outb(pInt->ioBase + 0x03C3, ~(CARD8)0x01 & vga->save_vse);
662#ifndef __ia64__
663    outb(pInt->ioBase + 0x46E8, ~(CARD8)0x08 & vga->save_46e8);
664#endif
665    outb(pInt->ioBase + 0x0102, ~(CARD8)0x01 & vga->save_pos102);
666#endif
667}
668
669void
670UnlockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga)
671{
672#ifndef NO_LEGACY_VGA
673    outb(pInt->ioBase + 0x0102, vga->save_pos102);
674#ifndef __ia64__
675    outb(pInt->ioBase + 0x46E8, vga->save_46e8);
676#endif
677    outb(pInt->ioBase + 0x03C3, vga->save_vse);
678    outb(pInt->ioBase + 0x03C2, vga->save_msr);
679#endif
680}
681
682#if defined (_PC)
683static void
684SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set)
685{
686    int pagesize = getpagesize();
687    unsigned char* base = xf86MapVidMem(pInt->scrnIndex,
688					VIDMEM_MMIO, 0, pagesize);
689    int i;
690
691    if (set) {
692	for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++)
693	    MEM_WW(pInt, i, *(base + i));
694    } else {
695	for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++)
696	    *(base + i) = MEM_RW(pInt, i);
697    }
698
699    xf86UnMapVidMem(pInt->scrnIndex,base,pagesize);
700}
701
702void
703xf86Int10SaveRestoreBIOSVars(xf86Int10InfoPtr pInt, Bool save)
704{
705    int pagesize = getpagesize();
706    unsigned char* base;
707    int i;
708
709    if (!xf86IsEntityPrimary(pInt->entityIndex)
710	|| (!save && !pInt->BIOSScratch))
711	return;
712
713    base = xf86MapVidMem(pInt->scrnIndex, VIDMEM_MMIO, 0, pagesize);
714    base += BIOS_SCRATCH_OFF;
715    if (save) {
716	if ((pInt->BIOSScratch
717	     = xnfalloc(BIOS_SCRATCH_LEN)))
718	    for (i = 0; i < BIOS_SCRATCH_LEN; i++)
719		*(((char*)pInt->BIOSScratch + i)) = *(base + i);
720    } else {
721	if (pInt->BIOSScratch) {
722	    for (i = 0; i < BIOS_SCRATCH_LEN; i++)
723		*(base + i) = *(pInt->BIOSScratch + i);
724	    free(pInt->BIOSScratch);
725	    pInt->BIOSScratch = NULL;
726	}
727    }
728
729    xf86UnMapVidMem(pInt->scrnIndex,base - BIOS_SCRATCH_OFF ,pagesize);
730}
731#endif
732
733xf86Int10InfoPtr
734xf86InitInt10(int entityIndex)
735{
736    return xf86ExtendedInitInt10(entityIndex, 0);
737}
738