]>
Commit | Line | Data |
---|---|---|
c7de829c WD |
1 | #include "x86emu.h" |
2 | #include "glue.h" | |
3 | ||
4 | ||
5 | /* | |
6 | * This isn't nice, but there are a lot of incompatibilities in the U-Boot and scitech include | |
7 | * files that this is the only really workable solution. | |
8bde7f77 | 8 | * Might be cleaned out later. |
c7de829c WD |
9 | */ |
10 | ||
11 | #ifdef DEBUG | |
12 | #undef DEBUG | |
13 | #endif | |
14 | ||
15 | #undef IO_LOGGING | |
16 | #undef MEM_LOGGING | |
17 | ||
18 | #ifdef IO_LOGGING | |
19 | #define LOGIO(port, format, args...) if (dolog(port)) _printf(format , ## args) | |
20 | #else | |
21 | #define LOGIO(port, format, args...) | |
22 | #endif | |
23 | ||
24 | #ifdef MEM_LOGGIN | |
25 | #define LOGMEM(format, args...) _printf(format , ## args) | |
26 | #else | |
27 | #define LOGMEM(format, args...) | |
28 | #endif | |
29 | ||
30 | #ifdef DEBUG | |
31 | #define PRINTF(format, args...) _printf(format , ## args) | |
32 | #else | |
33 | #define PRINTF(format, argc...) | |
34 | #endif | |
35 | ||
36 | typedef unsigned char UBYTE; | |
37 | typedef unsigned short UWORD; | |
38 | typedef unsigned long ULONG; | |
39 | ||
40 | typedef char BYTE; | |
41 | typedef short WORT; | |
42 | typedef long LONG; | |
43 | ||
44 | #define EMULATOR_MEM_SIZE (1024*1024) | |
45 | #define EMULATOR_BIOS_OFFSET 0xC0000 | |
46 | #define EMULATOR_STRAP_OFFSET 0x30000 | |
47 | #define EMULATOR_STACK_OFFSET 0x20000 | |
8bde7f77 | 48 | #define EMULATOR_LOGO_OFFSET 0x40000 /* If you change this, change the strap code, too */ |
c7de829c WD |
49 | #define VIDEO_BASE (void *)0xFD0B8000 |
50 | ||
51 | extern char *getenv(char *); | |
52 | extern int tstc(void); | |
53 | extern int getc(void); | |
54 | extern unsigned char video_get_attr(void); | |
55 | ||
56 | int atoi(char *string) | |
57 | { | |
58 | int res = 0; | |
59 | while (*string>='0' && *string <='9') | |
60 | { | |
61 | res *= 10; | |
62 | res += *string-'0'; | |
63 | string++; | |
64 | } | |
65 | ||
66 | return res; | |
67 | } | |
68 | ||
69 | void cons_gets(char *buffer) | |
70 | { | |
71 | int i = 0; | |
72 | char c = 0; | |
73 | ||
74 | buffer[0] = 0; | |
8bde7f77 | 75 | if (getenv("x86_runthru")) return; /*FIXME: */ |
c7de829c WD |
76 | while (c != 0x0D && c != 0x0A) |
77 | { | |
78 | while (!tstc()); | |
79 | c = getc(); | |
80 | if (c>=32 && c < 127) | |
81 | { | |
82 | buffer[i] = c; | |
83 | i++; | |
84 | buffer[i] = 0; | |
85 | putc(c); | |
86 | } | |
87 | else | |
88 | { | |
89 | if (c == 0x08) | |
90 | { | |
91 | if (i>0) i--; | |
92 | buffer[i] = 0; | |
93 | } | |
94 | } | |
95 | } | |
96 | buffer[i] = '\n'; | |
97 | buffer[i+1] = 0; | |
98 | } | |
99 | ||
100 | char *bios_date = "08/14/02"; | |
101 | UBYTE model = 0xFC; | |
102 | UBYTE submodel = 0x00; | |
103 | ||
104 | static inline UBYTE read_byte(volatile UBYTE* from) | |
105 | { | |
106 | int x; | |
107 | asm volatile ("lbz %0,%1\n eieio" : "=r" (x) : "m" (*from)); | |
108 | return (UBYTE)x; | |
109 | } | |
110 | ||
111 | static inline void write_byte(volatile UBYTE *to, int x) | |
112 | { | |
113 | asm volatile ("stb %1,%0\n eieio" : "=m" (*to) : "r" (x)); | |
114 | } | |
115 | ||
116 | static inline UWORD read_word_little(volatile UWORD *from) | |
117 | { | |
118 | int x; | |
119 | asm volatile ("lhbrx %0,0,%1\n eieio" : "=r" (x) : "r" (from), "m" (*from)); | |
120 | return (UWORD)x; | |
121 | } | |
122 | ||
123 | static inline UWORD read_word_big(volatile UWORD *from) | |
124 | { | |
125 | int x; | |
126 | asm volatile ("lhz %0,%1\n eieio" : "=r" (x) : "m" (*from)); | |
127 | return (UWORD)x; | |
128 | } | |
129 | ||
130 | static inline void write_word_little(volatile UWORD *to, int x) | |
131 | { | |
132 | asm volatile ("sthbrx %1,0,%2\n eieio" : "=m" (*to) : "r" (x), "r" (to)); | |
133 | } | |
134 | ||
135 | static inline void write_word_big(volatile UWORD *to, int x) | |
136 | { | |
137 | asm volatile ("sth %1,%0\n eieio" : "=m" (*to) : "r" (x)); | |
138 | } | |
139 | ||
140 | static inline ULONG read_long_little(volatile ULONG *from) | |
141 | { | |
142 | unsigned long x; | |
143 | asm volatile ("lwbrx %0,0,%1\n eieio" : "=r" (x) : "r" (from), "m"(*from)); | |
144 | return (ULONG)x; | |
145 | } | |
146 | ||
147 | static inline ULONG read_long_big(volatile ULONG *from) | |
148 | { | |
149 | unsigned long x; | |
150 | asm volatile ("lwz %0,%1\n eieio" : "=r" (x) : "m" (*from)); | |
151 | return (ULONG)x; | |
152 | } | |
153 | ||
154 | static inline void write_long_little(volatile ULONG *to, ULONG x) | |
155 | { | |
156 | asm volatile ("stwbrx %1,0,%2\n eieio" : "=m" (*to) : "r" (x), "r" (to)); | |
157 | } | |
158 | ||
159 | static inline void write_long_big(volatile ULONG *to, ULONG x) | |
160 | { | |
161 | asm volatile ("stw %1,%0\n eieio" : "=m" (*to) : "r" (x)); | |
162 | } | |
163 | ||
164 | static int log_init = 0; | |
165 | static int log_do = 0; | |
166 | static int log_low = 0; | |
167 | ||
168 | int dolog(int port) | |
169 | { | |
8bde7f77 | 170 | if (log_init && log_do) |
c7de829c WD |
171 | { |
172 | if (log_low && port > 0x400) return 0; | |
173 | return 1; | |
174 | } | |
175 | ||
176 | if (!log_init) | |
177 | { | |
178 | log_init = 1; | |
179 | log_do = (getenv("x86_logio") != (char *)0); | |
180 | log_low = (getenv("x86_loglow") != (char *)0); | |
8bde7f77 | 181 | if (log_do) |
c7de829c WD |
182 | { |
183 | if (log_low && port > 0x400) return 0; | |
184 | return 1; | |
185 | } | |
186 | } | |
187 | return 0; | |
188 | } | |
189 | ||
8bde7f77 WD |
190 | /* Converts an emulator address to a physical address. */ |
191 | /* Handles all special cases (bios date, model etc), and might need work */ | |
c7de829c WD |
192 | u32 memaddr(u32 addr) |
193 | { | |
8bde7f77 WD |
194 | /* if (addr >= 0xF0000 && addr < 0xFFFFF) printf("WARNING: Segment F access (0x%x)\n", addr); */ |
195 | /* printf("MemAddr=%p\n", addr); */ | |
c7de829c WD |
196 | if (addr >= 0xA0000 && addr < 0xC0000) |
197 | return 0xFD000000 + addr; | |
198 | else if (addr >= 0xFFFF5 && addr < 0xFFFFE) | |
199 | { | |
200 | return (u32)bios_date+addr-0xFFFF5; | |
201 | } | |
202 | else if (addr == 0xFFFFE) | |
203 | return (u32)&model; | |
204 | else if (addr == 0xFFFFF) | |
205 | return (u32)&submodel; | |
206 | else if (addr >= 0x80000000) | |
207 | { | |
8bde7f77 | 208 | /*printf("Warning: High memory access at 0x%x\n", addr); */ |
c7de829c WD |
209 | return addr; |
210 | } | |
211 | else | |
212 | return (u32)M.mem_base+addr; | |
213 | } | |
214 | ||
215 | u8 A1_rdb(u32 addr) | |
216 | { | |
217 | u8 a = read_byte((UBYTE *)memaddr(addr)); | |
218 | LOGMEM("rdb: %x -> %x\n", addr, a); | |
219 | return a; | |
220 | } | |
221 | ||
222 | u16 A1_rdw(u32 addr) | |
223 | { | |
224 | u16 a = read_word_little((UWORD *)memaddr(addr)); | |
225 | LOGMEM("rdw: %x -> %x\n", addr, a); | |
226 | return a; | |
227 | } | |
228 | ||
229 | u32 A1_rdl(u32 addr) | |
230 | { | |
231 | u32 a = read_long_little((ULONG *)memaddr(addr)); | |
232 | LOGMEM("rdl: %x -> %x\n", addr, a); | |
233 | return a; | |
234 | } | |
235 | ||
236 | void A1_wrb(u32 addr, u8 val) | |
237 | { | |
238 | LOGMEM("wrb: %x <- %x\n", addr, val); | |
239 | write_byte((UBYTE *)memaddr(addr), val); | |
240 | } | |
241 | ||
242 | void A1_wrw(u32 addr, u16 val) | |
243 | { | |
244 | LOGMEM("wrw: %x <- %x\n", addr, val); | |
245 | write_word_little((UWORD *)memaddr(addr), val); | |
246 | } | |
247 | ||
248 | void A1_wrl(u32 addr, u32 val) | |
249 | { | |
250 | LOGMEM("wrl: %x <- %x\n", addr, val); | |
251 | write_long_little((ULONG *)memaddr(addr), val); | |
252 | } | |
253 | ||
8bde7f77 | 254 | X86EMU_memFuncs _A1_mem = |
c7de829c WD |
255 | { |
256 | A1_rdb, | |
257 | A1_rdw, | |
258 | A1_rdl, | |
259 | A1_wrb, | |
260 | A1_wrw, | |
261 | A1_wrl, | |
262 | }; | |
263 | ||
264 | #define ARTICIAS_PCI_CFGADDR 0xfec00cf8 | |
265 | #define ARTICIAS_PCI_CFGDATA 0xfee00cfc | |
266 | #define IOBASE 0xFE000000 | |
267 | ||
268 | #define in_byte(from) read_byte( (UBYTE *)port_to_mem(from)) | |
269 | #define in_word(from) read_word_little((UWORD *)port_to_mem(from)) | |
270 | #define in_long(from) read_long_little((ULONG *)port_to_mem(from)) | |
271 | #define out_byte(to, val) write_byte((UBYTE *)port_to_mem(to), val) | |
272 | #define out_word(to, val) write_word_little((UWORD *)port_to_mem(to), val) | |
273 | #define out_long(to, val) write_long_little((ULONG *)port_to_mem(to), val) | |
274 | ||
275 | u32 port_to_mem(int port) | |
276 | { | |
277 | if (port >= 0xCFC && port <= 0xCFF) return 0xFEE00000+port; | |
278 | else if (port >= 0xCF8 && port <= 0xCFB) return 0xFEC00000+port; | |
279 | else return IOBASE + port; | |
280 | } | |
281 | ||
282 | u8 A1_inb(int port) | |
283 | { | |
284 | u8 a; | |
8bde7f77 | 285 | /*if (port == 0x3BA) return 0; */ |
c7de829c WD |
286 | a = in_byte(port); |
287 | LOGIO(port, "inb: %Xh -> %d (%Xh)\n", port, a, a); | |
288 | return a; | |
289 | } | |
290 | ||
291 | u16 A1_inw(int port) | |
292 | { | |
293 | u16 a = in_word(port); | |
294 | LOGIO(port, "inw: %Xh -> %d (%Xh)\n", port, a, a); | |
295 | return a; | |
296 | } | |
297 | ||
298 | u32 A1_inl(int port) | |
299 | { | |
300 | u32 a = in_long(port); | |
301 | LOGIO(port, "inl: %Xh -> %d (%Xh)\n", port, a, a); | |
302 | return a; | |
303 | } | |
304 | ||
305 | void A1_outb(int port, u8 val) | |
306 | { | |
307 | LOGIO(port, "outb: %Xh <- %d (%Xh)\n", port, val, val); | |
308 | /* if (port == 0xCF8) port = 0xCFB; | |
309 | else if (port == 0xCF9) port = 0xCFA; | |
310 | else if (port == 0xCFA) port = 0xCF9; | |
311 | else if (port == 0xCFB) port = 0xCF8;*/ | |
312 | out_byte(port, val); | |
313 | } | |
314 | ||
315 | void A1_outw(int port, u16 val) | |
316 | { | |
317 | LOGIO(port, "outw: %Xh <- %d (%Xh)\n", port, val, val); | |
318 | out_word(port, val); | |
319 | } | |
320 | ||
321 | void A1_outl(int port, u32 val) | |
322 | { | |
323 | LOGIO(port, "outl: %Xh <- %d (%Xh)\n", port, val, val); | |
324 | out_long(port, val); | |
325 | } | |
326 | ||
8bde7f77 | 327 | X86EMU_pioFuncs _A1_pio = |
c7de829c WD |
328 | { |
329 | A1_inb, | |
330 | A1_inw, | |
331 | A1_inl, | |
332 | A1_outb, | |
333 | A1_outw, | |
334 | A1_outl, | |
335 | }; | |
336 | ||
337 | static int reloced_ops = 0; | |
338 | ||
339 | void reloc_ops(void *reloc_addr) | |
340 | { | |
341 | extern void (*x86emu_optab[256])(u8); | |
342 | extern void (*x86emu_optab2[256])(u8); | |
343 | extern void tables_relocate(unsigned int offset); | |
344 | int i; | |
345 | unsigned long delta; | |
346 | if (reloced_ops == 1) return; | |
347 | reloced_ops = 1; | |
348 | ||
349 | delta = TEXT_BASE - (unsigned long)reloc_addr; | |
350 | ||
351 | for (i=0; i<256; i++) | |
352 | { | |
353 | x86emu_optab[i] -= delta; | |
354 | x86emu_optab2[i] -= delta; | |
355 | } | |
8bde7f77 | 356 | |
c7de829c WD |
357 | _A1_mem.rdb = A1_rdb; |
358 | _A1_mem.rdw = A1_rdw; | |
359 | _A1_mem.rdl = A1_rdl; | |
360 | _A1_mem.wrb = A1_wrb; | |
361 | _A1_mem.wrw = A1_wrw; | |
362 | _A1_mem.wrl = A1_wrl; | |
363 | ||
364 | _A1_pio.inb = A1_inb; | |
365 | _A1_pio.inw = A1_inw; | |
366 | _A1_pio.inl = A1_inl; | |
367 | _A1_pio.outb = A1_outb; | |
368 | _A1_pio.outw = A1_outw; | |
369 | _A1_pio.outl = A1_outl; | |
8bde7f77 | 370 | |
c7de829c WD |
371 | tables_relocate(delta); |
372 | ||
373 | } | |
374 | ||
375 | ||
376 | #define ANY_KEY(text) \ | |
377 | printf(text); \ | |
378 | while (!tstc()); | |
379 | ||
380 | ||
381 | unsigned char more_strap[] = { | |
8bde7f77 | 382 | 0xb4, 0x0, 0xb0, 0x2, 0xcd, 0x10, |
c7de829c | 383 | }; |
8bde7f77 | 384 | #define MORE_STRAP_BYTES 6 /* Additional bytes of strap code */ |
c7de829c WD |
385 | |
386 | ||
387 | unsigned char *done_msg="VGA Initialized\0"; | |
388 | ||
389 | int execute_bios(pci_dev_t gr_dev, void *reloc_addr) | |
390 | { | |
391 | extern void bios_init(void); | |
392 | extern void remove_init_data(void); | |
393 | extern int video_rows(void); | |
394 | extern int video_cols(void); | |
395 | extern int video_size(int, int); | |
396 | u8 *strap; | |
397 | unsigned char *logo; | |
398 | u8 cfg; | |
399 | int i; | |
400 | char c; | |
c7de829c | 401 | char *s; |
c7de829c WD |
402 | #ifdef EASTEREGG |
403 | int easteregg_active = 0; | |
404 | #endif | |
405 | char *pal_reset; | |
406 | u8 *fb; | |
407 | unsigned char *msg; | |
408 | unsigned char current_attr; | |
409 | ||
7c7a23bd | 410 | PRINTF("Trying to remove init data\n"); |
c7de829c WD |
411 | remove_init_data(); |
412 | PRINTF("Removed init data from cache, now in RAM\n"); | |
413 | ||
414 | reloc_ops(reloc_addr); | |
415 | PRINTF("Attempting to run emulator on %02x:%02x:%02x\n", | |
416 | PCI_BUS(gr_dev), PCI_DEV(gr_dev), PCI_FUNC(gr_dev)); | |
417 | ||
8bde7f77 | 418 | /* Enable compatibility hole for emulator access to frame buffer */ |
c7de829c WD |
419 | PRINTF("Enabling compatibility hole\n"); |
420 | enable_compatibility_hole(); | |
421 | ||
8bde7f77 WD |
422 | /* Allocate memory */ |
423 | /* FIXME: We shouldn't use this much memory really. */ | |
c7de829c WD |
424 | memset(&M, 0, sizeof(X86EMU_sysEnv)); |
425 | M.mem_base = malloc(EMULATOR_MEM_SIZE); | |
426 | M.mem_size = EMULATOR_MEM_SIZE; | |
427 | ||
428 | if (!M.mem_base) | |
429 | { | |
430 | PRINTF("Unable to allocate one megabyte for emulator\n"); | |
431 | return 0; | |
432 | } | |
433 | ||
434 | if (attempt_map_rom(gr_dev, M.mem_base + EMULATOR_BIOS_OFFSET) == 0) | |
435 | { | |
436 | PRINTF("Error mapping rom. Emulation terminated\n"); | |
437 | return 0; | |
438 | } | |
439 | ||
7c7a23bd | 440 | #if 1 /*def DEBUG*/ |
c7de829c WD |
441 | s = getenv("x86_ask_start"); |
442 | if (s) | |
443 | { | |
444 | printf("Press 'q' to skip initialization, 'd' for dry init\n'i' for i/o session"); | |
445 | while (!tstc()); | |
446 | c = getc(); | |
447 | if (c == 'q') return 0; | |
448 | if (c == 'd') | |
449 | { | |
450 | extern void bios_set_mode(int mode); | |
451 | bios_set_mode(0x03); | |
452 | return 0; | |
453 | } | |
454 | if (c == 'i') do_inout(); | |
455 | } | |
456 | ||
457 | ||
458 | #endif | |
459 | ||
460 | #ifdef EASTEREGG | |
461 | /* if (tstc()) | |
462 | { | |
463 | if (getc() == 'c') | |
464 | { | |
465 | easteregg_active = 1; | |
466 | } | |
467 | } | |
468 | */ | |
469 | if (getenv("easteregg")) | |
470 | { | |
471 | easteregg_active = 1; | |
472 | } | |
8bde7f77 | 473 | |
c7de829c WD |
474 | if (easteregg_active) |
475 | { | |
8bde7f77 | 476 | /* Yay! */ |
c7de829c WD |
477 | setenv("x86_mode", "1"); |
478 | setenv("vga_fg_color", "11"); | |
479 | setenv("vga_bg_color", "1"); | |
480 | easteregg_active = 1; | |
481 | } | |
482 | #endif | |
483 | ||
484 | strap = (u8*)M.mem_base + EMULATOR_STRAP_OFFSET; | |
485 | ||
486 | { | |
487 | char *m = getenv("x86_mode"); | |
488 | if (m) | |
489 | { | |
490 | more_strap[3] = atoi(m); | |
491 | if (more_strap[3] == 1) video_size(40, 25); | |
492 | else video_size(80, 25); | |
493 | } | |
494 | } | |
495 | ||
8bde7f77 | 496 | /* |
c7de829c | 497 | * Poke the strap routine. This might need a bit of extending |
8bde7f77 | 498 | * if there is a mode switch involved, i.e. we want to int10 |
c7de829c WD |
499 | * afterwards to set a different graphics mode, or alternatively |
500 | * there might be a different start address requirement if the | |
501 | * ROM doesn't have an x86 image in its first image. | |
502 | */ | |
503 | ||
504 | PRINTF("Poking strap...\n"); | |
505 | ||
8bde7f77 | 506 | /* FAR CALL c000:0003 */ |
c7de829c | 507 | *strap++ = 0x9A; *strap++ = 0x03; *strap++ = 0x00; |
8bde7f77 | 508 | *strap++ = 0x00; *strap++ = 0xC0; |
c7de829c WD |
509 | |
510 | #if 1 | |
8bde7f77 | 511 | /* insert additional strap code */ |
c7de829c WD |
512 | for (i=0; i < MORE_STRAP_BYTES; i++) |
513 | { | |
514 | *strap++ = more_strap[i]; | |
515 | } | |
516 | #endif | |
8bde7f77 WD |
517 | /* HALT */ |
518 | *strap++ = 0xF4; | |
c7de829c WD |
519 | |
520 | PRINTF("Setting up logo data\n"); | |
521 | logo = (unsigned char *)M.mem_base + EMULATOR_LOGO_OFFSET; | |
522 | for (i=0; i<16; i++) | |
523 | { | |
524 | *logo++ = 0xFF; | |
525 | } | |
526 | ||
527 | /* | |
528 | * Setup the init parameters. | |
529 | * Per PCI specs, AH must contain the bus and AL | |
530 | * must contain the devfn, encoded as (dev<<3)|fn | |
531 | */ | |
532 | ||
8bde7f77 WD |
533 | /* Execution starts here */ |
534 | M.x86.R_CS = SEG(EMULATOR_STRAP_OFFSET); | |
535 | M.x86.R_IP = OFF(EMULATOR_STRAP_OFFSET); | |
c7de829c | 536 | |
8bde7f77 | 537 | /* Stack at top of ram */ |
c7de829c WD |
538 | M.x86.R_SS = SEG(EMULATOR_STACK_OFFSET); |
539 | M.x86.R_SP = OFF(EMULATOR_STACK_OFFSET); | |
540 | ||
8bde7f77 | 541 | /* Input parameters */ |
c7de829c WD |
542 | M.x86.R_AH = PCI_BUS(gr_dev); |
543 | M.x86.R_AL = (PCI_DEV(gr_dev)<<3) | PCI_FUNC(gr_dev); | |
544 | ||
8bde7f77 | 545 | /* Set the I/O and memory access functions */ |
c7de829c WD |
546 | X86EMU_setupMemFuncs(&_A1_mem); |
547 | X86EMU_setupPioFuncs(&_A1_pio); | |
548 | ||
8bde7f77 WD |
549 | /* Enable timer 2 */ |
550 | cfg = in_byte(0x61); /* Get Misc control */ | |
551 | cfg |= 0x01; /* Enable timer 2 */ | |
552 | out_byte(0x61, cfg); /* output again */ | |
c7de829c | 553 | |
8bde7f77 | 554 | /* Set up the timers */ |
c7de829c WD |
555 | out_byte(0x43, 0x54); |
556 | out_byte(0x41, 0x18); | |
557 | ||
558 | out_byte(0x43, 0x36); | |
559 | out_byte(0x40, 0x00); | |
560 | out_byte(0x40, 0x00); | |
561 | ||
562 | out_byte(0x43, 0xb6); | |
563 | out_byte(0x42, 0x31); | |
564 | out_byte(0x42, 0x13); | |
565 | ||
8bde7f77 | 566 | /* Init the "BIOS". */ |
c7de829c WD |
567 | bios_init(); |
568 | ||
8bde7f77 | 569 | /* Video Card Reset */ |
c7de829c WD |
570 | out_byte(0x3D8, 0); |
571 | out_byte(0x3B8, 1); | |
572 | (void)in_byte(0x3BA); | |
573 | (void)in_byte(0x3DA); | |
574 | out_byte(0x3C0, 0); | |
575 | out_byte(0x61, 0xFC); | |
576 | ||
577 | #ifdef DEBUG | |
578 | s = _getenv("x86_singlestep"); | |
579 | if (s && strcmp(s, "on")==0) | |
580 | { | |
581 | PRINTF("Enabling single stepping for debug\n"); | |
582 | X86EMU_trace_on(); | |
583 | } | |
584 | #endif | |
585 | ||
8bde7f77 | 586 | /* Ready set go... */ |
c7de829c WD |
587 | PRINTF("Running emulator\n"); |
588 | X86EMU_exec(); | |
589 | PRINTF("Done running emulator\n"); | |
590 | ||
591 | /* FIXME: Remove me */ | |
592 | pal_reset = getenv("x86_palette_reset"); | |
593 | if (pal_reset && strcmp(pal_reset, "on") == 0) | |
594 | { | |
595 | PRINTF("Palette reset\n"); | |
8bde7f77 WD |
596 | /*(void)in_byte(0x3da); */ |
597 | /*out_byte(0x3c0, 0); */ | |
c7de829c WD |
598 | |
599 | out_byte(0x3C8, 0); | |
600 | out_byte(0x3C9, 0); | |
601 | out_byte(0x3C9, 0); | |
602 | out_byte(0x3C9, 0); | |
603 | for (i=0; i<254; i++) | |
604 | { | |
605 | out_byte(0x3C9, 63); | |
606 | out_byte(0x3C9, 63); | |
607 | out_byte(0x3C9, 63); | |
608 | } | |
609 | ||
610 | out_byte(0x3c0, 0x20); | |
611 | } | |
612 | /* FIXME: remove me */ | |
613 | #ifdef EASTEREGG | |
614 | if (easteregg_active) | |
615 | { | |
616 | extern void video_easteregg(void); | |
617 | video_easteregg(); | |
618 | } | |
619 | #endif | |
620 | /* | |
621 | current_attr = video_get_attr(); | |
622 | fb = (u8 *)VIDEO_BASE; | |
623 | for (i=0; i<video_rows()*video_cols()*2; i+=2) | |
624 | { | |
625 | *(fb+i) = ' '; | |
626 | *(fb+i+1) = current_attr; | |
627 | } | |
628 | ||
629 | fb = (u8 *)VIDEO_BASE + (video_rows())-1*(video_cols()*2); | |
630 | for (i=0; i<video_cols(); i++) | |
631 | { | |
632 | *(fb + 2*i) = 32; | |
633 | *(fb + 2*i + 1) = 0x17; | |
634 | } | |
635 | ||
636 | msg = done_msg; | |
637 | while (*msg) | |
638 | { | |
639 | *fb = *msg; | |
640 | fb += 2; | |
641 | msg ++; | |
642 | } | |
643 | */ | |
644 | #ifdef DEBUG | |
645 | if (getenv("x86_do_inout")) do_inout(); | |
646 | #endif | |
647 | ||
8bde7f77 | 648 | /*FIXME: dcache_disable(); */ |
c7de829c WD |
649 | return 1; |
650 | } | |
651 | ||
8bde7f77 | 652 | /* Clean up the x86 mess */ |
c7de829c WD |
653 | void shutdown_bios(void) |
654 | { | |
8bde7f77 WD |
655 | /* disable_compatibility_hole(); */ |
656 | /* Free the memory associated */ | |
c7de829c WD |
657 | free(M.mem_base); |
658 | ||
659 | } | |
660 | ||
661 | int to_int(char *buffer) | |
662 | { | |
663 | int base = 0; | |
664 | int res = 0; | |
665 | ||
8bde7f77 | 666 | if (*buffer == '$') |
c7de829c WD |
667 | { |
668 | base = 16; | |
669 | buffer++; | |
670 | } | |
671 | else base = 10; | |
672 | ||
673 | for (;;) | |
674 | { | |
675 | switch(*buffer) | |
676 | { | |
677 | case '0' ... '9': | |
678 | res *= base; | |
679 | res += *buffer - '0'; | |
680 | break; | |
681 | case 'A': | |
682 | case 'a': | |
683 | res *= base; | |
684 | res += 10; | |
685 | break; | |
686 | case 'B': | |
687 | case 'b': | |
688 | res *= base; | |
689 | res += 11; | |
8bde7f77 | 690 | break; |
c7de829c WD |
691 | case 'C': |
692 | case 'c': | |
693 | res *= base; | |
694 | res += 12; | |
8bde7f77 | 695 | break; |
c7de829c WD |
696 | case 'D': |
697 | case 'd': | |
698 | res *= base; | |
699 | res += 13; | |
8bde7f77 | 700 | break; |
c7de829c WD |
701 | case 'E': |
702 | case 'e': | |
703 | res *= base; | |
704 | res += 14; | |
8bde7f77 | 705 | break; |
c7de829c WD |
706 | case 'F': |
707 | case 'f': | |
708 | res *= base; | |
709 | res += 15; | |
8bde7f77 | 710 | break; |
c7de829c WD |
711 | default: |
712 | return res; | |
713 | } | |
714 | buffer++; | |
715 | } | |
716 | return res; | |
717 | } | |
718 | ||
719 | void one_arg(char *buffer, int *a) | |
720 | { | |
721 | while (*buffer && *buffer != '\n') | |
722 | { | |
723 | if (*buffer == ' ') buffer++; | |
724 | else break; | |
725 | } | |
726 | ||
727 | *a = to_int(buffer); | |
728 | } | |
729 | ||
730 | void two_args(char *buffer, int *a, int *b) | |
731 | { | |
732 | while (*buffer && *buffer != '\n') | |
733 | { | |
734 | if (*buffer == ' ') buffer++; | |
735 | else break; | |
736 | } | |
737 | ||
738 | *a = to_int(buffer); | |
739 | ||
740 | while (*buffer && *buffer != '\n') | |
741 | { | |
742 | if (*buffer != ' ') buffer++; | |
743 | else break; | |
744 | } | |
745 | ||
746 | while (*buffer && *buffer != '\n') | |
747 | { | |
748 | if (*buffer == ' ') buffer++; | |
749 | else break; | |
750 | } | |
751 | ||
752 | *b = to_int(buffer); | |
753 | } | |
754 | ||
755 | void do_inout(void) | |
756 | { | |
757 | char buffer[256]; | |
758 | char *arg1, *arg2; | |
759 | int a,b; | |
760 | ||
761 | printf("In/Out Session\nUse 'i[bwl]' for in, 'o[bwl]' for out and 'q' to quit\n"); | |
762 | ||
763 | do | |
764 | { | |
765 | cons_gets(buffer); | |
766 | printf("\n"); | |
767 | ||
768 | *arg1 = buffer; | |
769 | while (*arg1 != ' ' ) arg1++; | |
770 | while (*arg1 == ' ') arg1++; | |
771 | ||
772 | if (buffer[0] == 'i') | |
773 | { | |
774 | one_arg(buffer+2, &a); | |
775 | switch (buffer[1]) | |
776 | { | |
777 | case 'b': | |
778 | printf("in_byte(%xh) = %xh\n", a, A1_inb(a)); | |
779 | break; | |
780 | case 'w': | |
781 | printf("in_word(%xh) = %xh\n", a, A1_inw(a)); | |
782 | break; | |
783 | case 'l': | |
784 | printf("in_dword(%xh) = %xh\n", a, A1_inl(a)); | |
785 | break; | |
786 | default: | |
787 | printf("Invalid length '%c'\n", buffer[1]); | |
788 | break; | |
789 | } | |
790 | } | |
791 | else if (buffer[0] == 'o') | |
792 | { | |
793 | two_args(buffer+2, &a, &b); | |
794 | switch (buffer[1]) | |
795 | { | |
796 | case 'b': | |
797 | printf("out_byte(%d, %d)\n", a, b); | |
798 | A1_outb(a,b); | |
799 | break; | |
800 | case 'w': | |
801 | printf("out_word(%d, %d)\n", a, b); | |
802 | A1_outw(a, b); | |
803 | break; | |
804 | case 'l': | |
805 | printf("out_long(%d, %d)\n", a, b); | |
806 | A1_outl(a, b); | |
807 | break; | |
808 | default: | |
809 | printf("Invalid length '%c'\n", buffer[1]); | |
810 | break; | |
811 | } | |
812 | } else if (buffer[0] == 'q') return; | |
813 | } while (1); | |
814 | } |