helper_exec.c revision 5a112b11
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(uint16_t addr, uint32_t *val);
41static int pciCfg1out(uint16_t addr, uint32_t val);
42static int pciCfg1inw(uint16_t addr, uint16_t *val);
43static int pciCfg1outw(uint16_t addr, uint16_t val);
44static int pciCfg1inb(uint16_t addr, uint8_t *val);
45static int pciCfg1outb(uint16_t addr, uint8_t val);
46
47#if defined (_PC)
48static void SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set);
49#endif
50
51#define REG pInt
52
53int
54setup_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
85void
86finish_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 */
105uint32_t
106getIntVect(xf86Int10InfoPtr pInt, int num)
107{
108    return MEM_RW(pInt, num << 2) + (MEM_RW(pInt, (num << 2) + 2) << 4);
109}
110
111void
112pushw(xf86Int10InfoPtr pInt, uint16_t val)
113{
114    X86_ESP -= 2;
115    MEM_WW(pInt, ((uint32_t) X86_SS << 4) + X86_SP, val);
116}
117
118int
119run_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 */
166void
167dump_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
182void
183dump_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
202void
203stack_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
223int
224port_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
240int
241port_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
257int
258port_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
274int
275port_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
291int
292port_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
308int
309port_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
325uint8_t
326x_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
356uint16_t
357x_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
379void
380x_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
413void
414x_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
424uint32_t
425x_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
437void
438x_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
447uint8_t
448Mem_rb(uint32_t addr)
449{
450    return (*Int10Current->mem->rb) (Int10Current, addr);
451}
452
453uint16_t
454Mem_rw(uint32_t addr)
455{
456    return (*Int10Current->mem->rw) (Int10Current, addr);
457}
458
459uint32_t
460Mem_rl(uint32_t addr)
461{
462    return (*Int10Current->mem->rl) (Int10Current, addr);
463}
464
465void
466Mem_wb(uint32_t addr, uint8_t val)
467{
468    (*Int10Current->mem->wb) (Int10Current, addr, val);
469}
470
471void
472Mem_ww(uint32_t addr, uint16_t val)
473{
474    (*Int10Current->mem->ww) (Int10Current, addr, val);
475}
476
477void
478Mem_wl(uint32_t addr, uint32_t val)
479{
480    (*Int10Current->mem->wl) (Int10Current, addr, val);
481}
482
483static 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
493static struct pci_device *
494pci_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
518static int
519pciCfg1in(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				/*
528				 * XXXMRG
529				 * this one is OK - CARD32 is "long" for 32 bit
530				 * and "int" for 64 bit
531				 */
532                                (uint32_t *) val, PCI_OFFSET(PciCfg1Addr));
533        if (PRINT_PORT && DEBUG_IO_TRACE())
534            ErrorF(" cfg_inl(%#" PRIx32 ") = %8.8" PRIx32 "\n", (unsigned) PciCfg1Addr,
535                   (unsigned) *val);
536        return 1;
537    }
538    return 0;
539}
540
541static int
542pciCfg1out(uint16_t addr, uint32_t val)
543{
544    if (addr == 0xCF8) {
545        PciCfg1Addr = val;
546        return 1;
547    }
548    if (addr == 0xCFC) {
549        if (PRINT_PORT && DEBUG_IO_TRACE())
550            ErrorF(" cfg_outl(%#" PRIx32 ", %8.8" PRIx32 ")\n", (unsigned) PciCfg1Addr,
551                   (unsigned) val);
552        pci_device_cfg_write_u32(pci_device_for_cfg_address(PciCfg1Addr), val,
553                                 PCI_OFFSET(PciCfg1Addr));
554        return 1;
555    }
556    return 0;
557}
558
559static int
560pciCfg1inw(uint16_t addr, uint16_t *val)
561{
562    int shift;
563
564    if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
565        shift = (addr - 0xCF8) * 8;
566        *val = (PciCfg1Addr >> shift) & 0xffff;
567        return 1;
568    }
569    if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
570        const unsigned offset = addr - 0xCFC;
571
572        pci_device_cfg_read_u16(pci_device_for_cfg_address(PciCfg1Addr),
573                                val, PCI_OFFSET(PciCfg1Addr) + offset);
574        if (PRINT_PORT && DEBUG_IO_TRACE())
575            ErrorF(" cfg_inw(%#" PRIx32 ") = %4.4x\n", (unsigned) (PciCfg1Addr + offset),
576                   (unsigned) *val);
577        return 1;
578    }
579    return 0;
580}
581
582static int
583pciCfg1outw(uint16_t addr, uint16_t val)
584{
585    int shift;
586
587    if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
588        shift = (addr - 0xCF8) * 8;
589        PciCfg1Addr &= ~(0xffff << shift);
590        PciCfg1Addr |= ((uint32_t) val) << shift;
591        return 1;
592    }
593    if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
594        const unsigned offset = addr - 0xCFC;
595
596        if (PRINT_PORT && DEBUG_IO_TRACE())
597            ErrorF(" cfg_outw(%#" PRIx32 ", %4.4x)\n", (unsigned) (PciCfg1Addr + offset),
598                   (unsigned) val);
599        pci_device_cfg_write_u16(pci_device_for_cfg_address(PciCfg1Addr), val,
600                                 PCI_OFFSET(PciCfg1Addr) + offset);
601        return 1;
602    }
603    return 0;
604}
605
606static int
607pciCfg1inb(uint16_t addr, uint8_t *val)
608{
609    int shift;
610
611    if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
612        shift = (addr - 0xCF8) * 8;
613        *val = (PciCfg1Addr >> shift) & 0xff;
614        return 1;
615    }
616    if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
617        const unsigned offset = addr - 0xCFC;
618
619        pci_device_cfg_read_u8(pci_device_for_cfg_address(PciCfg1Addr),
620                               val, PCI_OFFSET(PciCfg1Addr) + offset);
621        if (PRINT_PORT && DEBUG_IO_TRACE())
622            ErrorF(" cfg_inb(%#" PRIx32 ") = %2.2x\n", (unsigned) (PciCfg1Addr + offset),
623                   (unsigned) *val);
624        return 1;
625    }
626    return 0;
627}
628
629static int
630pciCfg1outb(uint16_t addr, uint8_t val)
631{
632    int shift;
633
634    if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
635        shift = (addr - 0xCF8) * 8;
636        PciCfg1Addr &= ~(0xff << shift);
637        PciCfg1Addr |= ((uint32_t) val) << shift;
638        return 1;
639    }
640    if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
641        const unsigned offset = addr - 0xCFC;
642
643        if (PRINT_PORT && DEBUG_IO_TRACE())
644            ErrorF(" cfg_outb(%#" PRIx32 ", %2.2x)\n", (unsigned) (PciCfg1Addr + offset),
645                   (unsigned) val);
646        pci_device_cfg_write_u8(pci_device_for_cfg_address(PciCfg1Addr), val,
647                                PCI_OFFSET(PciCfg1Addr) + offset);
648        return 1;
649    }
650    return 0;
651}
652
653uint8_t
654bios_checksum(const uint8_t *start, int size)
655{
656    uint8_t sum = 0;
657
658    while (size-- > 0)
659        sum += *start++;
660    return sum;
661}
662
663/*
664 * Lock/Unlock legacy VGA. Some Bioses try to be very clever and make
665 * an attempt to detect a legacy ISA card. If they find one they might
666 * act very strange: for example they might configure the card as a
667 * monochrome card. This might cause some drivers to choke.
668 * To avoid this we attempt legacy VGA by writing to all known VGA
669 * disable registers before we call the BIOS initialization and
670 * restore the original values afterwards. In between we hold our
671 * breath. To get to a (possibly existing) ISA card need to disable
672 * our current PCI card.
673 */
674/*
675 * This is just for booting: we just want to catch pure
676 * legacy vga therefore we don't worry about mmio etc.
677 * This stuff should really go into vgaHW.c. However then
678 * the driver would have to load the vga-module prior to
679 * doing int10.
680 */
681void
682LockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga)
683{
684#ifndef NO_LEGACY_VGA
685    vga->save_msr = pci_io_read8(pInt->io, 0x03CC);
686    vga->save_vse = pci_io_read8(pInt->io, 0x03C3);
687#ifndef __ia64__
688    vga->save_46e8 = pci_io_read8(pInt->io, 0x46E8);
689#endif
690    vga->save_pos102 = pci_io_read8(pInt->io, 0x0102);
691    pci_io_write8(pInt->io, 0x03C2, ~(uint8_t) 0x03 & vga->save_msr);
692    pci_io_write8(pInt->io, 0x03C3, ~(uint8_t) 0x01 & vga->save_vse);
693#ifndef __ia64__
694    pci_io_write8(pInt->io, 0x46E8, ~(uint8_t) 0x08 & vga->save_46e8);
695#endif
696    pci_io_write8(pInt->io, 0x0102, ~(uint8_t) 0x01 & vga->save_pos102);
697#endif
698}
699
700void
701UnlockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga)
702{
703#ifndef NO_LEGACY_VGA
704    pci_io_write8(pInt->io, 0x0102, vga->save_pos102);
705#ifndef __ia64__
706    pci_io_write8(pInt->io, 0x46E8, vga->save_46e8);
707#endif
708    pci_io_write8(pInt->io, 0x03C3, vga->save_vse);
709    pci_io_write8(pInt->io, 0x03C2, vga->save_msr);
710#endif
711}
712
713#if defined (_PC)
714static void
715SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set)
716{
717    int pagesize = getpagesize();
718    unsigned char *base;
719    int i;
720
721    if (pci_device_map_legacy
722        (pInt->dev, 0, pagesize, PCI_DEV_MAP_FLAG_WRITABLE, (void **) &base))
723        return;                 /* eek */
724
725    if (set) {
726        for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++)
727            MEM_WW(pInt, i, *(base + i));
728    }
729    else {
730        for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++)
731            *(base + i) = MEM_RW(pInt, i);
732    }
733
734    pci_device_unmap_legacy(pInt->dev, base, pagesize);
735}
736
737void
738xf86Int10SaveRestoreBIOSVars(xf86Int10InfoPtr pInt, Bool save)
739{
740    int pagesize = getpagesize();
741    unsigned char *base;
742    int i;
743
744    if (!xf86IsEntityPrimary(pInt->entityIndex)
745        || (!save && !pInt->BIOSScratch))
746        return;
747
748    if (pci_device_map_legacy
749        (pInt->dev, 0, pagesize, PCI_DEV_MAP_FLAG_WRITABLE, (void **) &base))
750        return;                 /* eek */
751
752    base += BIOS_SCRATCH_OFF;
753    if (save) {
754        if ((pInt->BIOSScratch = xnfalloc(BIOS_SCRATCH_LEN)))
755            for (i = 0; i < BIOS_SCRATCH_LEN; i++)
756                *(((char *) pInt->BIOSScratch + i)) = *(base + i);
757    }
758    else {
759        if (pInt->BIOSScratch) {
760            for (i = 0; i < BIOS_SCRATCH_LEN; i++)
761                *(base + i) = *(pInt->BIOSScratch + i);
762            free(pInt->BIOSScratch);
763            pInt->BIOSScratch = NULL;
764        }
765    }
766
767    pci_device_unmap_legacy(pInt->dev, base - BIOS_SCRATCH_OFF, pagesize);
768}
769#endif
770
771xf86Int10InfoPtr
772xf86InitInt10(int entityIndex)
773{
774    return xf86ExtendedInitInt10(entityIndex, 0);
775}
776