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