2004-07-08 19:18:27 +02:00
|
|
|
/* $XFree86: xc/programs/Xserver/hw/xfree86/int10/helper_exec.c,v 1.16 2001/04/30 14:34:57 tsi Exp $ */
|
|
|
|
/*
|
|
|
|
* XFree86 int10 module
|
|
|
|
* execute BIOS int 10h calls in x86 real mode environment
|
|
|
|
* Copyright 1999 Egbert Eich
|
|
|
|
*
|
|
|
|
* Part of this is based on code taken from DOSEMU
|
|
|
|
* (C) Copyright 1992, ..., 1999 the "DOSEMU-Development-Team"
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* To debug port accesses define PRINT_PORT.
|
|
|
|
* Note! You also have to comment out ioperm()
|
|
|
|
* in xf86EnableIO(). Otherwise we won't trap
|
|
|
|
* on PIO.
|
|
|
|
*/
|
2009-05-27 13:39:16 +02:00
|
|
|
#include <sys/io.h>
|
2004-07-08 19:18:27 +02:00
|
|
|
#include <sys/time.h>
|
2009-05-27 13:39:16 +02:00
|
|
|
#include <stdio.h>
|
2015-09-28 22:12:04 +02:00
|
|
|
#include <stdtypes.h>
|
|
|
|
#include <x86emu/x86emu.h>
|
|
|
|
#include "helper_exec.h"
|
|
|
|
#include "testbios.h"
|
2004-07-08 19:18:27 +02:00
|
|
|
|
|
|
|
/* general software interrupt handler */
|
|
|
|
u32 getIntVect(int num)
|
|
|
|
{
|
|
|
|
return MEM_RW(num << 2) + (MEM_RW((num << 2) + 2) << 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pushw(u16 val)
|
|
|
|
{
|
|
|
|
X86_ESP -= 2;
|
|
|
|
MEM_WW(((u32) X86_SS << 4) + X86_SP, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
int run_bios_int(int num)
|
|
|
|
{
|
|
|
|
u32 eflags;
|
|
|
|
|
|
|
|
eflags = X86_EFLAGS;
|
|
|
|
pushw(eflags);
|
|
|
|
pushw(X86_CS);
|
|
|
|
pushw(X86_IP);
|
|
|
|
X86_CS = MEM_RW((num << 2) + 2);
|
|
|
|
X86_IP = MEM_RW(num << 2);
|
|
|
|
|
2005-01-11 04:18:39 +01:00
|
|
|
printf("%s: INT %x CS:IP = %x:%x\n", __FUNCTION__,
|
|
|
|
num, MEM_RW((num << 2) + 2), MEM_RW(num << 2));
|
2004-07-08 19:18:27 +02:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-09-28 22:12:04 +02:00
|
|
|
#if 0
|
|
|
|
|
2004-07-08 19:18:27 +02:00
|
|
|
int port_rep_inb(u16 port, u32 base, int d_f, u32 count)
|
|
|
|
{
|
|
|
|
register int inc = d_f ? -1 : 1;
|
|
|
|
u32 dst = base;
|
|
|
|
while (count--) {
|
|
|
|
MEM_WB(dst, x_inb(port));
|
|
|
|
dst += inc;
|
|
|
|
}
|
|
|
|
return dst - base;
|
|
|
|
}
|
|
|
|
|
|
|
|
int port_rep_inw(u16 port, u32 base, int d_f, u32 count)
|
|
|
|
{
|
|
|
|
register int inc = d_f ? -2 : 2;
|
|
|
|
u32 dst = base;
|
|
|
|
while (count--) {
|
|
|
|
MEM_WW(dst, x_inw(port));
|
|
|
|
dst += inc;
|
|
|
|
}
|
|
|
|
return dst - base;
|
|
|
|
}
|
|
|
|
|
|
|
|
int port_rep_inl(u16 port, u32 base, int d_f, u32 count)
|
|
|
|
{
|
|
|
|
register int inc = d_f ? -4 : 4;
|
|
|
|
u32 dst = base;
|
|
|
|
while (count--) {
|
|
|
|
MEM_WL(dst, x_inl(port));
|
|
|
|
dst += inc;
|
|
|
|
}
|
|
|
|
return dst - base;
|
|
|
|
}
|
|
|
|
|
|
|
|
int port_rep_outb(u16 port, u32 base, int d_f, u32 count)
|
|
|
|
{
|
|
|
|
register int inc = d_f ? -1 : 1;
|
|
|
|
u32 dst = base;
|
|
|
|
while (count--) {
|
|
|
|
x_outb(port, MEM_RB(dst));
|
|
|
|
dst += inc;
|
|
|
|
}
|
|
|
|
return dst - base;
|
|
|
|
}
|
|
|
|
|
|
|
|
int port_rep_outw(u16 port, u32 base, int d_f, u32 count)
|
|
|
|
{
|
|
|
|
register int inc = d_f ? -2 : 2;
|
|
|
|
u32 dst = base;
|
|
|
|
while (count--) {
|
|
|
|
x_outw(port, MEM_RW(dst));
|
|
|
|
dst += inc;
|
|
|
|
}
|
|
|
|
return dst - base;
|
|
|
|
}
|
|
|
|
|
|
|
|
int port_rep_outl(u16 port, u32 base, int d_f, u32 count)
|
|
|
|
{
|
|
|
|
register int inc = d_f ? -4 : 4;
|
|
|
|
u32 dst = base;
|
|
|
|
while (count--) {
|
|
|
|
x_outl(port, MEM_RL(dst));
|
|
|
|
dst += inc;
|
|
|
|
}
|
|
|
|
return dst - base;
|
|
|
|
}
|
|
|
|
|
2015-09-28 22:12:04 +02:00
|
|
|
#endif
|
|
|
|
|
2004-07-08 19:18:27 +02:00
|
|
|
u8 x_inb(u16 port)
|
|
|
|
{
|
|
|
|
u8 val;
|
|
|
|
|
|
|
|
val = inb(port);
|
|
|
|
|
2005-01-11 04:18:39 +01:00
|
|
|
printf("inb(0x%04x) = 0x%02x\n", port, val);
|
2004-07-08 19:18:27 +02:00
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
u16 x_inw(u16 port)
|
|
|
|
{
|
|
|
|
u16 val;
|
|
|
|
|
|
|
|
val = inw(port);
|
|
|
|
|
2005-01-11 04:18:39 +01:00
|
|
|
printf("inw(0x%04x) = 0x%04x\n", port, val);
|
2004-07-08 19:18:27 +02:00
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 x_inl(u16 port)
|
|
|
|
{
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
val = inl(port);
|
|
|
|
|
2005-01-11 04:18:39 +01:00
|
|
|
printf("inl(0x%04x) = 0x%08x\n", port, val);
|
2004-07-08 19:18:27 +02:00
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
void x_outb(u16 port, u8 val)
|
|
|
|
{
|
2005-01-11 04:18:39 +01:00
|
|
|
printf("outb(0x%02x, 0x%04x)\n",
|
|
|
|
val, port);
|
2004-07-08 19:18:27 +02:00
|
|
|
outb(val, port);
|
|
|
|
}
|
|
|
|
|
|
|
|
void x_outw(u16 port, u16 val)
|
|
|
|
{
|
2005-01-11 04:18:39 +01:00
|
|
|
printf("outw(0x%04x, 0x%04x)\n", val, port);
|
2004-07-08 19:18:27 +02:00
|
|
|
outw(val, port);
|
|
|
|
}
|
|
|
|
|
|
|
|
void x_outl(u16 port, u32 val)
|
|
|
|
{
|
2005-01-11 04:18:39 +01:00
|
|
|
printf("outl(0x%08x, 0x%04x)\n", val, port);
|
2004-07-08 19:18:27 +02:00
|
|
|
outl(val, port);
|
|
|
|
}
|
|
|
|
|
2015-09-28 22:12:04 +02:00
|
|
|
#if 0
|
2004-07-08 19:18:27 +02:00
|
|
|
u8 Mem_rb(int addr)
|
|
|
|
{
|
|
|
|
return (*current->mem->rb) (current, addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
u16 Mem_rw(int addr)
|
|
|
|
{
|
|
|
|
return (*current->mem->rw) (current, addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 Mem_rl(int addr)
|
|
|
|
{
|
|
|
|
return (*current->mem->rl) (current, addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Mem_wb(int addr, u8 val)
|
|
|
|
{
|
|
|
|
(*current->mem->wb) (current, addr, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Mem_ww(int addr, u16 val)
|
|
|
|
{
|
|
|
|
(*current->mem->ww) (current, addr, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Mem_wl(int addr, u32 val)
|
|
|
|
{
|
|
|
|
(*current->mem->wl) (current, addr, val);
|
|
|
|
}
|
2015-09-28 22:12:04 +02:00
|
|
|
#endif
|
2004-07-08 19:18:27 +02:00
|
|
|
|
|
|
|
void getsecs(unsigned long *sec, unsigned long *usec)
|
|
|
|
{
|
|
|
|
struct timeval tv;
|
|
|
|
gettimeofday(&tv, 0);
|
|
|
|
*sec = tv.tv_sec;
|
|
|
|
*usec = tv.tv_usec;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define TAG(Cfg1Addr) (Cfg1Addr & 0xffff00)
|
|
|
|
#define OFFSET(Cfg1Addr) (Cfg1Addr & 0xff)
|
|
|
|
|
|
|
|
u8 bios_checksum(u8 * start, int size)
|
|
|
|
{
|
|
|
|
u8 sum = 0;
|
|
|
|
|
|
|
|
while (size-- > 0)
|
|
|
|
sum += *start++;
|
|
|
|
return sum;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lock/Unlock legacy VGA. Some Bioses try to be very clever and make
|
|
|
|
* an attempt to detect a legacy ISA card. If they find one they might
|
|
|
|
* act very strange: for example they might configure the card as a
|
|
|
|
* monochrome card. This might cause some drivers to choke.
|
|
|
|
* To avoid this we attempt legacy VGA by writing to all know VGA
|
|
|
|
* disable registers before we call the BIOS initialization and
|
|
|
|
* restore the original values afterwards. In beween we hold our
|
|
|
|
* breath. To get to a (possibly exising) ISA card need to disable
|
|
|
|
* our current PCI card.
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* This is just for booting: we just want to catch pure
|
|
|
|
* legacy vga therefore we don't worry about mmio etc.
|
|
|
|
* This stuff should really go into vgaHW.c. However then
|
|
|
|
* the driver would have to load the vga-module prior to
|
|
|
|
* doing int10.
|
|
|
|
*/
|
|
|
|
/*void
|
|
|
|
LockLegacyVGA(int screenIndex,legacyVGAPtr vga)
|
|
|
|
{
|
|
|
|
xf86SetCurrentAccess(FALSE, xf86Screens[screenIndex]);
|
|
|
|
vga->save_msr = inb(0x3CC);
|
|
|
|
vga->save_vse = inb(0x3C3);
|
|
|
|
vga->save_46e8 = inb(0x46e8);
|
|
|
|
vga->save_pos102 = inb(0x102);
|
|
|
|
outb(0x3C2, ~(u8)0x03 & vga->save_msr);
|
|
|
|
outb(0x3C3, ~(u8)0x01 & vga->save_vse);
|
|
|
|
outb(0x46e8, ~(u8)0x08 & vga->save_46e8);
|
|
|
|
outb(0x102, ~(u8)0x01 & vga->save_pos102);
|
|
|
|
xf86SetCurrentAccess(TRUE, xf86Screens[screenIndex]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
UnlockLegacyVGA(int screenIndex, legacyVGAPtr vga)
|
|
|
|
{
|
|
|
|
xf86SetCurrentAccess(FALSE, xf86Screens[screenIndex]);
|
|
|
|
outb(0x102, vga->save_pos102);
|
|
|
|
outb(0x46e8, vga->save_46e8);
|
|
|
|
outb(0x3C3, vga->save_vse);
|
|
|
|
outb(0x3C2, vga->save_msr);
|
|
|
|
xf86SetCurrentAccess(TRUE, xf86Screens[screenIndex]);
|
|
|
|
}
|
|
|
|
*/
|