Li-Ta Lo | 8152126 | 2004-07-08 17:18:27 +0000 | [diff] [blame] | 1 | /* $XFree86: xc/programs/Xserver/hw/xfree86/int10/helper_exec.c,v 1.16 2001/04/30 14:34:57 tsi Exp $ */ |
| 2 | /* |
| 3 | * XFree86 int10 module |
| 4 | * execute BIOS int 10h calls in x86 real mode environment |
| 5 | * Copyright 1999 Egbert Eich |
| 6 | * |
| 7 | * Part of this is based on code taken from DOSEMU |
| 8 | * (C) Copyright 1992, ..., 1999 the "DOSEMU-Development-Team" |
| 9 | */ |
| 10 | |
| 11 | /* |
| 12 | * To debug port accesses define PRINT_PORT. |
| 13 | * Note! You also have to comment out ioperm() |
| 14 | * in xf86EnableIO(). Otherwise we won't trap |
| 15 | * on PIO. |
| 16 | */ |
| 17 | #include <x86emu.h> |
Luc Verhaegen | e6e899d | 2009-05-27 11:39:16 +0000 | [diff] [blame^] | 18 | #include "helper_exec.h" |
Li-Ta Lo | 8152126 | 2004-07-08 17:18:27 +0000 | [diff] [blame] | 19 | #include "test.h" |
Luc Verhaegen | e6e899d | 2009-05-27 11:39:16 +0000 | [diff] [blame^] | 20 | #include <sys/io.h> |
Li-Ta Lo | 8152126 | 2004-07-08 17:18:27 +0000 | [diff] [blame] | 21 | #include <sys/time.h> |
Luc Verhaegen | e6e899d | 2009-05-27 11:39:16 +0000 | [diff] [blame^] | 22 | #include <stdio.h> |
| 23 | |
Li-Ta Lo | 8152126 | 2004-07-08 17:18:27 +0000 | [diff] [blame] | 24 | |
| 25 | int port_rep_inb(u16 port, u32 base, int d_f, u32 count); |
| 26 | u8 x_inb(u16 port); |
| 27 | u16 x_inw(u16 port); |
| 28 | void x_outb(u16 port, u8 val); |
| 29 | void x_outw(u16 port, u16 val); |
| 30 | u32 x_inl(u16 port); |
| 31 | void x_outl(u16 port, u32 val); |
| 32 | |
| 33 | /* general software interrupt handler */ |
| 34 | u32 getIntVect(int num) |
| 35 | { |
| 36 | return MEM_RW(num << 2) + (MEM_RW((num << 2) + 2) << 4); |
| 37 | } |
| 38 | |
| 39 | void pushw(u16 val) |
| 40 | { |
| 41 | X86_ESP -= 2; |
| 42 | MEM_WW(((u32) X86_SS << 4) + X86_SP, val); |
| 43 | } |
| 44 | |
| 45 | int run_bios_int(int num) |
| 46 | { |
| 47 | u32 eflags; |
| 48 | |
| 49 | eflags = X86_EFLAGS; |
| 50 | pushw(eflags); |
| 51 | pushw(X86_CS); |
| 52 | pushw(X86_IP); |
| 53 | X86_CS = MEM_RW((num << 2) + 2); |
| 54 | X86_IP = MEM_RW(num << 2); |
| 55 | |
Li-Ta Lo | 8b0356c | 2005-01-11 03:18:39 +0000 | [diff] [blame] | 56 | printf("%s: INT %x CS:IP = %x:%x\n", __FUNCTION__, |
| 57 | num, MEM_RW((num << 2) + 2), MEM_RW(num << 2)); |
Li-Ta Lo | 8152126 | 2004-07-08 17:18:27 +0000 | [diff] [blame] | 58 | |
| 59 | return 1; |
| 60 | } |
| 61 | |
| 62 | int port_rep_inb(u16 port, u32 base, int d_f, u32 count) |
| 63 | { |
| 64 | register int inc = d_f ? -1 : 1; |
| 65 | u32 dst = base; |
| 66 | while (count--) { |
| 67 | MEM_WB(dst, x_inb(port)); |
| 68 | dst += inc; |
| 69 | } |
| 70 | return dst - base; |
| 71 | } |
| 72 | |
| 73 | int port_rep_inw(u16 port, u32 base, int d_f, u32 count) |
| 74 | { |
| 75 | register int inc = d_f ? -2 : 2; |
| 76 | u32 dst = base; |
| 77 | while (count--) { |
| 78 | MEM_WW(dst, x_inw(port)); |
| 79 | dst += inc; |
| 80 | } |
| 81 | return dst - base; |
| 82 | } |
| 83 | |
| 84 | int port_rep_inl(u16 port, u32 base, int d_f, u32 count) |
| 85 | { |
| 86 | register int inc = d_f ? -4 : 4; |
| 87 | u32 dst = base; |
| 88 | while (count--) { |
| 89 | MEM_WL(dst, x_inl(port)); |
| 90 | dst += inc; |
| 91 | } |
| 92 | return dst - base; |
| 93 | } |
| 94 | |
| 95 | int port_rep_outb(u16 port, u32 base, int d_f, u32 count) |
| 96 | { |
| 97 | register int inc = d_f ? -1 : 1; |
| 98 | u32 dst = base; |
| 99 | while (count--) { |
| 100 | x_outb(port, MEM_RB(dst)); |
| 101 | dst += inc; |
| 102 | } |
| 103 | return dst - base; |
| 104 | } |
| 105 | |
| 106 | int port_rep_outw(u16 port, u32 base, int d_f, u32 count) |
| 107 | { |
| 108 | register int inc = d_f ? -2 : 2; |
| 109 | u32 dst = base; |
| 110 | while (count--) { |
| 111 | x_outw(port, MEM_RW(dst)); |
| 112 | dst += inc; |
| 113 | } |
| 114 | return dst - base; |
| 115 | } |
| 116 | |
| 117 | int port_rep_outl(u16 port, u32 base, int d_f, u32 count) |
| 118 | { |
| 119 | register int inc = d_f ? -4 : 4; |
| 120 | u32 dst = base; |
| 121 | while (count--) { |
| 122 | x_outl(port, MEM_RL(dst)); |
| 123 | dst += inc; |
| 124 | } |
| 125 | return dst - base; |
| 126 | } |
| 127 | |
| 128 | u8 x_inb(u16 port) |
| 129 | { |
| 130 | u8 val; |
| 131 | |
| 132 | val = inb(port); |
| 133 | |
Li-Ta Lo | 8b0356c | 2005-01-11 03:18:39 +0000 | [diff] [blame] | 134 | printf("inb(0x%04x) = 0x%02x\n", port, val); |
Li-Ta Lo | 8152126 | 2004-07-08 17:18:27 +0000 | [diff] [blame] | 135 | |
| 136 | return val; |
| 137 | } |
| 138 | |
| 139 | u16 x_inw(u16 port) |
| 140 | { |
| 141 | u16 val; |
| 142 | |
| 143 | val = inw(port); |
| 144 | |
Li-Ta Lo | 8b0356c | 2005-01-11 03:18:39 +0000 | [diff] [blame] | 145 | printf("inw(0x%04x) = 0x%04x\n", port, val); |
Li-Ta Lo | 8152126 | 2004-07-08 17:18:27 +0000 | [diff] [blame] | 146 | return val; |
| 147 | } |
| 148 | |
| 149 | u32 x_inl(u16 port) |
| 150 | { |
| 151 | u32 val; |
| 152 | |
| 153 | val = inl(port); |
| 154 | |
Li-Ta Lo | 8b0356c | 2005-01-11 03:18:39 +0000 | [diff] [blame] | 155 | printf("inl(0x%04x) = 0x%08x\n", port, val); |
Li-Ta Lo | 8152126 | 2004-07-08 17:18:27 +0000 | [diff] [blame] | 156 | return val; |
| 157 | } |
| 158 | |
| 159 | void x_outb(u16 port, u8 val) |
| 160 | { |
Li-Ta Lo | 8b0356c | 2005-01-11 03:18:39 +0000 | [diff] [blame] | 161 | printf("outb(0x%02x, 0x%04x)\n", |
| 162 | val, port); |
Li-Ta Lo | 8152126 | 2004-07-08 17:18:27 +0000 | [diff] [blame] | 163 | outb(val, port); |
| 164 | } |
| 165 | |
| 166 | void x_outw(u16 port, u16 val) |
| 167 | { |
Li-Ta Lo | 8b0356c | 2005-01-11 03:18:39 +0000 | [diff] [blame] | 168 | printf("outw(0x%04x, 0x%04x)\n", val, port); |
Li-Ta Lo | 8152126 | 2004-07-08 17:18:27 +0000 | [diff] [blame] | 169 | outw(val, port); |
| 170 | } |
| 171 | |
| 172 | void x_outl(u16 port, u32 val) |
| 173 | { |
Li-Ta Lo | 8b0356c | 2005-01-11 03:18:39 +0000 | [diff] [blame] | 174 | printf("outl(0x%08x, 0x%04x)\n", val, port); |
Li-Ta Lo | 8152126 | 2004-07-08 17:18:27 +0000 | [diff] [blame] | 175 | outl(val, port); |
| 176 | } |
| 177 | |
| 178 | u8 Mem_rb(int addr) |
| 179 | { |
| 180 | return (*current->mem->rb) (current, addr); |
| 181 | } |
| 182 | |
| 183 | u16 Mem_rw(int addr) |
| 184 | { |
| 185 | return (*current->mem->rw) (current, addr); |
| 186 | } |
| 187 | |
| 188 | u32 Mem_rl(int addr) |
| 189 | { |
| 190 | return (*current->mem->rl) (current, addr); |
| 191 | } |
| 192 | |
| 193 | void Mem_wb(int addr, u8 val) |
| 194 | { |
| 195 | (*current->mem->wb) (current, addr, val); |
| 196 | } |
| 197 | |
| 198 | void Mem_ww(int addr, u16 val) |
| 199 | { |
| 200 | (*current->mem->ww) (current, addr, val); |
| 201 | } |
| 202 | |
| 203 | void Mem_wl(int addr, u32 val) |
| 204 | { |
| 205 | (*current->mem->wl) (current, addr, val); |
| 206 | } |
| 207 | |
| 208 | void getsecs(unsigned long *sec, unsigned long *usec) |
| 209 | { |
| 210 | struct timeval tv; |
| 211 | gettimeofday(&tv, 0); |
| 212 | *sec = tv.tv_sec; |
| 213 | *usec = tv.tv_usec; |
| 214 | } |
| 215 | |
| 216 | #define TAG(Cfg1Addr) (Cfg1Addr & 0xffff00) |
| 217 | #define OFFSET(Cfg1Addr) (Cfg1Addr & 0xff) |
| 218 | |
| 219 | u8 bios_checksum(u8 * start, int size) |
| 220 | { |
| 221 | u8 sum = 0; |
| 222 | |
| 223 | while (size-- > 0) |
| 224 | sum += *start++; |
| 225 | return sum; |
| 226 | } |
| 227 | |
| 228 | /* |
| 229 | * Lock/Unlock legacy VGA. Some Bioses try to be very clever and make |
| 230 | * an attempt to detect a legacy ISA card. If they find one they might |
| 231 | * act very strange: for example they might configure the card as a |
| 232 | * monochrome card. This might cause some drivers to choke. |
| 233 | * To avoid this we attempt legacy VGA by writing to all know VGA |
| 234 | * disable registers before we call the BIOS initialization and |
| 235 | * restore the original values afterwards. In beween we hold our |
| 236 | * breath. To get to a (possibly exising) ISA card need to disable |
| 237 | * our current PCI card. |
| 238 | */ |
| 239 | /* |
| 240 | * This is just for booting: we just want to catch pure |
| 241 | * legacy vga therefore we don't worry about mmio etc. |
| 242 | * This stuff should really go into vgaHW.c. However then |
| 243 | * the driver would have to load the vga-module prior to |
| 244 | * doing int10. |
| 245 | */ |
| 246 | /*void |
| 247 | LockLegacyVGA(int screenIndex,legacyVGAPtr vga) |
| 248 | { |
| 249 | xf86SetCurrentAccess(FALSE, xf86Screens[screenIndex]); |
| 250 | vga->save_msr = inb(0x3CC); |
| 251 | vga->save_vse = inb(0x3C3); |
| 252 | vga->save_46e8 = inb(0x46e8); |
| 253 | vga->save_pos102 = inb(0x102); |
| 254 | outb(0x3C2, ~(u8)0x03 & vga->save_msr); |
| 255 | outb(0x3C3, ~(u8)0x01 & vga->save_vse); |
| 256 | outb(0x46e8, ~(u8)0x08 & vga->save_46e8); |
| 257 | outb(0x102, ~(u8)0x01 & vga->save_pos102); |
| 258 | xf86SetCurrentAccess(TRUE, xf86Screens[screenIndex]); |
| 259 | } |
| 260 | |
| 261 | void |
| 262 | UnlockLegacyVGA(int screenIndex, legacyVGAPtr vga) |
| 263 | { |
| 264 | xf86SetCurrentAccess(FALSE, xf86Screens[screenIndex]); |
| 265 | outb(0x102, vga->save_pos102); |
| 266 | outb(0x46e8, vga->save_46e8); |
| 267 | outb(0x3C3, vga->save_vse); |
| 268 | outb(0x3C2, vga->save_msr); |
| 269 | xf86SetCurrentAccess(TRUE, xf86Screens[screenIndex]); |
| 270 | } |
| 271 | */ |