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