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