Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / int10 / helper_exec.c
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(CARD16 addr, CARD32 *val);
41 static int pciCfg1out(CARD16 addr, CARD32 val);
42 static int pciCfg1inw(CARD16 addr, CARD16 *val);
43 static int pciCfg1outw(CARD16 addr, CARD16 val);
44 static int pciCfg1inb(CARD16 addr, CARD8 *val);
45 static int pciCfg1outb(CARD16 addr, CARD8 val);
46
47 #if defined (_PC)
48 static void SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set);
49 #endif
50
51 #define REG pInt
52
53 int
54 setup_int(xf86Int10InfoPtr pInt)
55 {
56 if (pInt != Int10Current) {
57 if (!MapCurrentInt10(pInt))
58 return -1;
59 Int10Current = pInt;
60 }
61 X86_EAX = (CARD32) pInt->ax;
62 X86_EBX = (CARD32) pInt->bx;
63 X86_ECX = (CARD32) pInt->cx;
64 X86_EDX = (CARD32) pInt->dx;
65 X86_ESI = (CARD32) pInt->si;
66 X86_EDI = (CARD32) pInt->di;
67 X86_EBP = (CARD32) 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
86 finish_int(xf86Int10InfoPtr pInt, int sig)
87 {
88 OsReleaseSignals();
89 pInt->ax = (CARD32) X86_EAX;
90 pInt->bx = (CARD32) X86_EBX;
91 pInt->cx = (CARD32) X86_ECX;
92 pInt->dx = (CARD32) X86_EDX;
93 pInt->si = (CARD32) X86_ESI;
94 pInt->di = (CARD32) X86_EDI;
95 pInt->es = (CARD16) X86_ES;
96 pInt->bp = (CARD32) X86_EBP;
97 pInt->flags = (CARD32) 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 CARD32
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
112 pushw(xf86Int10InfoPtr pInt, CARD16 val)
113 {
114 X86_ESP -= 2;
115 MEM_WW(pInt, ((CARD32) X86_SS << 4) + X86_SP, val);
116 }
117
118 int
119 run_bios_int(int num, xf86Int10InfoPtr pInt)
120 {
121 CARD32 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
167 dump_code(xf86Int10InfoPtr pInt)
168 {
169 int i;
170 CARD32 lina = SEG_ADR((CARD32), X86_CS, IP);
171
172 xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_INFO, 3, "code at 0x%8.8" PRIx32 ":\n",
173 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
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
203 stack_trace(xf86Int10InfoPtr pInt)
204 {
205 int i = 0;
206 unsigned long stack = SEG_ADR((CARD32), X86_SS, SP);
207 unsigned long tail = (CARD32) ((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
224 port_rep_inb(xf86Int10InfoPtr pInt,
225 CARD16 port, CARD32 base, int d_f, CARD32 count)
226 {
227 register int inc = d_f ? -1 : 1;
228 CARD32 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, count, 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
241 port_rep_inw(xf86Int10InfoPtr pInt,
242 CARD16 port, CARD32 base, int d_f, CARD32 count)
243 {
244 register int inc = d_f ? -2 : 2;
245 CARD32 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, count, 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
258 port_rep_inl(xf86Int10InfoPtr pInt,
259 CARD16 port, CARD32 base, int d_f, CARD32 count)
260 {
261 register int inc = d_f ? -4 : 4;
262 CARD32 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, count, 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
275 port_rep_outb(xf86Int10InfoPtr pInt,
276 CARD16 port, CARD32 base, int d_f, CARD32 count)
277 {
278 register int inc = d_f ? -1 : 1;
279 CARD32 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, count, 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
292 port_rep_outw(xf86Int10InfoPtr pInt,
293 CARD16 port, CARD32 base, int d_f, CARD32 count)
294 {
295 register int inc = d_f ? -2 : 2;
296 CARD32 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, count, 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
309 port_rep_outl(xf86Int10InfoPtr pInt,
310 CARD16 port, CARD32 base, int d_f, CARD32 count)
311 {
312 register int inc = d_f ? -4 : 4;
313 CARD32 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, count, 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 CARD8
326 x_inb(CARD16 port)
327 {
328 CARD8 val;
329
330 if (port == 0x40) {
331 Int10Current->inb40time++;
332 val = (CARD8) (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 CARD16
357 x_inw(CARD16 port)
358 {
359 CARD16 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 = (CARD16) (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
380 x_outb(CARD16 port, CARD8 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 = (CARD16) (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
414 x_outw(CARD16 port, CARD16 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 CARD32
425 x_inl(CARD16 port)
426 {
427 CARD32 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, val);
433 }
434 return val;
435 }
436
437 void
438 x_outl(CARD16 port, CARD32 val)
439 {
440 if (!pciCfg1out(port, val)) {
441 if (PRINT_PORT && DEBUG_IO_TRACE())
442 ErrorF(" outl(%#x, %8.8" PRIx32 ")\n", port, val);
443 pci_io_write32(Int10Current->io, port, val);
444 }
445 }
446
447 CARD8
448 Mem_rb(CARD32 addr)
449 {
450 return (*Int10Current->mem->rb) (Int10Current, addr);
451 }
452
453 CARD16
454 Mem_rw(CARD32 addr)
455 {
456 return (*Int10Current->mem->rw) (Int10Current, addr);
457 }
458
459 CARD32
460 Mem_rl(CARD32 addr)
461 {
462 return (*Int10Current->mem->rl) (Int10Current, addr);
463 }
464
465 void
466 Mem_wb(CARD32 addr, CARD8 val)
467 {
468 (*Int10Current->mem->wb) (Int10Current, addr, val);
469 }
470
471 void
472 Mem_ww(CARD32 addr, CARD16 val)
473 {
474 (*Int10Current->mem->ww) (Int10Current, addr, val);
475 }
476
477 void
478 Mem_wl(CARD32 addr, CARD32 val)
479 {
480 (*Int10Current->mem->wl) (Int10Current, addr, val);
481 }
482
483 static CARD32 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 *
494 pci_device_for_cfg_address(CARD32 addr)
495 {
496 struct pci_device *dev = NULL;
497 CARD32 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
519 pciCfg1in(CARD16 addr, CARD32 *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", PciCfg1Addr,
530 *val);
531 return 1;
532 }
533 return 0;
534 }
535
536 static int
537 pciCfg1out(CARD16 addr, CARD32 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", PciCfg1Addr,
546 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
555 pciCfg1inw(CARD16 addr, CARD16 *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", PciCfg1Addr + offset,
571 *val);
572 return 1;
573 }
574 return 0;
575 }
576
577 static int
578 pciCfg1outw(CARD16 addr, CARD16 val)
579 {
580 int shift;
581
582 if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
583 shift = (addr - 0xCF8) * 8;
584 PciCfg1Addr &= ~(0xffff << shift);
585 PciCfg1Addr |= ((CARD32) 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", PciCfg1Addr + offset,
593 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
602 pciCfg1inb(CARD16 addr, CARD8 *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", PciCfg1Addr + offset,
618 *val);
619 return 1;
620 }
621 return 0;
622 }
623
624 static int
625 pciCfg1outb(CARD16 addr, CARD8 val)
626 {
627 int shift;
628
629 if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
630 shift = (addr - 0xCF8) * 8;
631 PciCfg1Addr &= ~(0xff << shift);
632 PciCfg1Addr |= ((CARD32) 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", PciCfg1Addr + offset,
640 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 CARD8
649 bios_checksum(const CARD8 *start, int size)
650 {
651 CARD8 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
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, ~(CARD8) 0x03 & vga->save_msr);
686 pci_io_write8(pInt->io, 0x03C3, ~(CARD8) 0x01 & vga->save_vse);
687 #ifndef __ia64__
688 pci_io_write8(pInt->io, 0x46E8, ~(CARD8) 0x08 & vga->save_46e8);
689 #endif
690 pci_io_write8(pInt->io, 0x0102, ~(CARD8) 0x01 & vga->save_pos102);
691 }
692
693 void
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
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
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
763 xf86InitInt10(int entityIndex)
764 {
765 return xf86ExtendedInitInt10(entityIndex, 0);
766 }