blob: 909cb3cf94c19bc6e4ef88272136bfe5710eba3c [file] [log] [blame]
wdenkc7de8292002-11-19 11:04:11 +00001#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.
wdenk8bde7f72003-06-27 21:31:46 +00008 * Might be cleaned out later.
wdenkc7de8292002-11-19 11:04:11 +00009 */
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
36typedef unsigned char UBYTE;
37typedef unsigned short UWORD;
38typedef unsigned long ULONG;
39
40typedef char BYTE;
41typedef short WORT;
42typedef 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
wdenk8bde7f72003-06-27 21:31:46 +000048#define EMULATOR_LOGO_OFFSET 0x40000 /* If you change this, change the strap code, too */
wdenkc7de8292002-11-19 11:04:11 +000049#define VIDEO_BASE (void *)0xFD0B8000
50
51extern char *getenv(char *);
52extern int tstc(void);
53extern int getc(void);
54extern unsigned char video_get_attr(void);
55
56int 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
69void cons_gets(char *buffer)
70{
71 int i = 0;
72 char c = 0;
73
74 buffer[0] = 0;
wdenk8bde7f72003-06-27 21:31:46 +000075 if (getenv("x86_runthru")) return; /*FIXME: */
wdenkc7de8292002-11-19 11:04:11 +000076 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
100char *bios_date = "08/14/02";
101UBYTE model = 0xFC;
102UBYTE submodel = 0x00;
103
104static 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
111static inline void write_byte(volatile UBYTE *to, int x)
112{
113 asm volatile ("stb %1,%0\n eieio" : "=m" (*to) : "r" (x));
114}
115
116static 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
123static 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
130static 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
135static 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
140static 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
147static 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
154static 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
159static 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
164static int log_init = 0;
165static int log_do = 0;
166static int log_low = 0;
167
168int dolog(int port)
169{
wdenk8bde7f72003-06-27 21:31:46 +0000170 if (log_init && log_do)
wdenkc7de8292002-11-19 11:04:11 +0000171 {
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);
wdenk8bde7f72003-06-27 21:31:46 +0000181 if (log_do)
wdenkc7de8292002-11-19 11:04:11 +0000182 {
183 if (log_low && port > 0x400) return 0;
184 return 1;
185 }
186 }
187 return 0;
188}
189
wdenk8bde7f72003-06-27 21:31:46 +0000190/* Converts an emulator address to a physical address. */
191/* Handles all special cases (bios date, model etc), and might need work */
wdenkc7de8292002-11-19 11:04:11 +0000192u32 memaddr(u32 addr)
193{
wdenk8bde7f72003-06-27 21:31:46 +0000194/* if (addr >= 0xF0000 && addr < 0xFFFFF) printf("WARNING: Segment F access (0x%x)\n", addr); */
195/* printf("MemAddr=%p\n", addr); */
wdenkc7de8292002-11-19 11:04:11 +0000196 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 {
wdenk8bde7f72003-06-27 21:31:46 +0000208 /*printf("Warning: High memory access at 0x%x\n", addr); */
wdenkc7de8292002-11-19 11:04:11 +0000209 return addr;
210 }
211 else
212 return (u32)M.mem_base+addr;
213}
214
215u8 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
222u16 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
229u32 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
236void A1_wrb(u32 addr, u8 val)
237{
238 LOGMEM("wrb: %x <- %x\n", addr, val);
239 write_byte((UBYTE *)memaddr(addr), val);
240}
241
242void 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
248void 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
wdenk8bde7f72003-06-27 21:31:46 +0000254X86EMU_memFuncs _A1_mem =
wdenkc7de8292002-11-19 11:04:11 +0000255{
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
275u32 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
282u8 A1_inb(int port)
283{
284 u8 a;
wdenk8bde7f72003-06-27 21:31:46 +0000285 /*if (port == 0x3BA) return 0; */
wdenkc7de8292002-11-19 11:04:11 +0000286 a = in_byte(port);
287 LOGIO(port, "inb: %Xh -> %d (%Xh)\n", port, a, a);
288 return a;
289}
290
291u16 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
298u32 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
305void 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
315void 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
321void 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
wdenk8bde7f72003-06-27 21:31:46 +0000327X86EMU_pioFuncs _A1_pio =
wdenkc7de8292002-11-19 11:04:11 +0000328{
329 A1_inb,
330 A1_inw,
331 A1_inl,
332 A1_outb,
333 A1_outw,
334 A1_outl,
335};
336
337static int reloced_ops = 0;
338
339void 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 }
wdenk8bde7f72003-06-27 21:31:46 +0000356
wdenkc7de8292002-11-19 11:04:11 +0000357 _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;
wdenk8bde7f72003-06-27 21:31:46 +0000370
wdenkc7de8292002-11-19 11:04:11 +0000371 tables_relocate(delta);
372
373}
374
375
376#define ANY_KEY(text) \
377 printf(text); \
378 while (!tstc());
379
380
381unsigned char more_strap[] = {
wdenk8bde7f72003-06-27 21:31:46 +0000382 0xb4, 0x0, 0xb0, 0x2, 0xcd, 0x10,
wdenkc7de8292002-11-19 11:04:11 +0000383};
wdenk8bde7f72003-06-27 21:31:46 +0000384#define MORE_STRAP_BYTES 6 /* Additional bytes of strap code */
wdenkc7de8292002-11-19 11:04:11 +0000385
386
387unsigned char *done_msg="VGA Initialized\0";
388
389int 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;
wdenkc7de8292002-11-19 11:04:11 +0000401 char *s;
wdenkc7de8292002-11-19 11:04:11 +0000402#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
wdenk7c7a23b2002-12-07 00:20:59 +0000410 PRINTF("Trying to remove init data\n");
wdenkc7de8292002-11-19 11:04:11 +0000411 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
wdenk8bde7f72003-06-27 21:31:46 +0000418 /* Enable compatibility hole for emulator access to frame buffer */
wdenkc7de8292002-11-19 11:04:11 +0000419 PRINTF("Enabling compatibility hole\n");
420 enable_compatibility_hole();
421
wdenk8bde7f72003-06-27 21:31:46 +0000422 /* Allocate memory */
423 /* FIXME: We shouldn't use this much memory really. */
wdenkc7de8292002-11-19 11:04:11 +0000424 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
wdenk7c7a23b2002-12-07 00:20:59 +0000440#if 1 /*def DEBUG*/
wdenkc7de8292002-11-19 11:04:11 +0000441 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 }
wdenk8bde7f72003-06-27 21:31:46 +0000473
wdenkc7de8292002-11-19 11:04:11 +0000474 if (easteregg_active)
475 {
wdenk8bde7f72003-06-27 21:31:46 +0000476 /* Yay! */
wdenkc7de8292002-11-19 11:04:11 +0000477 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
wdenk8bde7f72003-06-27 21:31:46 +0000496 /*
wdenkc7de8292002-11-19 11:04:11 +0000497 * Poke the strap routine. This might need a bit of extending
wdenk8bde7f72003-06-27 21:31:46 +0000498 * if there is a mode switch involved, i.e. we want to int10
wdenkc7de8292002-11-19 11:04:11 +0000499 * 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
wdenk8bde7f72003-06-27 21:31:46 +0000506 /* FAR CALL c000:0003 */
wdenkc7de8292002-11-19 11:04:11 +0000507 *strap++ = 0x9A; *strap++ = 0x03; *strap++ = 0x00;
wdenk8bde7f72003-06-27 21:31:46 +0000508 *strap++ = 0x00; *strap++ = 0xC0;
wdenkc7de8292002-11-19 11:04:11 +0000509
510#if 1
wdenk8bde7f72003-06-27 21:31:46 +0000511 /* insert additional strap code */
wdenkc7de8292002-11-19 11:04:11 +0000512 for (i=0; i < MORE_STRAP_BYTES; i++)
513 {
514 *strap++ = more_strap[i];
515 }
516#endif
wdenk8bde7f72003-06-27 21:31:46 +0000517 /* HALT */
518 *strap++ = 0xF4;
wdenkc7de8292002-11-19 11:04:11 +0000519
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
wdenk8bde7f72003-06-27 21:31:46 +0000533 /* Execution starts here */
534 M.x86.R_CS = SEG(EMULATOR_STRAP_OFFSET);
535 M.x86.R_IP = OFF(EMULATOR_STRAP_OFFSET);
wdenkc7de8292002-11-19 11:04:11 +0000536
wdenk8bde7f72003-06-27 21:31:46 +0000537 /* Stack at top of ram */
wdenkc7de8292002-11-19 11:04:11 +0000538 M.x86.R_SS = SEG(EMULATOR_STACK_OFFSET);
539 M.x86.R_SP = OFF(EMULATOR_STACK_OFFSET);
540
wdenk8bde7f72003-06-27 21:31:46 +0000541 /* Input parameters */
wdenkc7de8292002-11-19 11:04:11 +0000542 M.x86.R_AH = PCI_BUS(gr_dev);
543 M.x86.R_AL = (PCI_DEV(gr_dev)<<3) | PCI_FUNC(gr_dev);
544
wdenk8bde7f72003-06-27 21:31:46 +0000545 /* Set the I/O and memory access functions */
wdenkc7de8292002-11-19 11:04:11 +0000546 X86EMU_setupMemFuncs(&_A1_mem);
547 X86EMU_setupPioFuncs(&_A1_pio);
548
wdenk8bde7f72003-06-27 21:31:46 +0000549 /* Enable timer 2 */
550 cfg = in_byte(0x61); /* Get Misc control */
551 cfg |= 0x01; /* Enable timer 2 */
552 out_byte(0x61, cfg); /* output again */
wdenkc7de8292002-11-19 11:04:11 +0000553
wdenk8bde7f72003-06-27 21:31:46 +0000554 /* Set up the timers */
wdenkc7de8292002-11-19 11:04:11 +0000555 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
wdenk8bde7f72003-06-27 21:31:46 +0000566 /* Init the "BIOS". */
wdenkc7de8292002-11-19 11:04:11 +0000567 bios_init();
568
wdenk8bde7f72003-06-27 21:31:46 +0000569 /* Video Card Reset */
wdenkc7de8292002-11-19 11:04:11 +0000570 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
wdenk8bde7f72003-06-27 21:31:46 +0000586 /* Ready set go... */
wdenkc7de8292002-11-19 11:04:11 +0000587 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");
wdenk8bde7f72003-06-27 21:31:46 +0000596 /*(void)in_byte(0x3da); */
597 /*out_byte(0x3c0, 0); */
wdenkc7de8292002-11-19 11:04:11 +0000598
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
wdenk8bde7f72003-06-27 21:31:46 +0000648/*FIXME: dcache_disable(); */
wdenkc7de8292002-11-19 11:04:11 +0000649 return 1;
650}
651
wdenk8bde7f72003-06-27 21:31:46 +0000652/* Clean up the x86 mess */
wdenkc7de8292002-11-19 11:04:11 +0000653void shutdown_bios(void)
654{
wdenk8bde7f72003-06-27 21:31:46 +0000655/* disable_compatibility_hole(); */
656 /* Free the memory associated */
wdenkc7de8292002-11-19 11:04:11 +0000657 free(M.mem_base);
658
659}
660
661int to_int(char *buffer)
662{
663 int base = 0;
664 int res = 0;
665
wdenk8bde7f72003-06-27 21:31:46 +0000666 if (*buffer == '$')
wdenkc7de8292002-11-19 11:04:11 +0000667 {
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;
wdenk8bde7f72003-06-27 21:31:46 +0000690 break;
wdenkc7de8292002-11-19 11:04:11 +0000691 case 'C':
692 case 'c':
693 res *= base;
694 res += 12;
wdenk8bde7f72003-06-27 21:31:46 +0000695 break;
wdenkc7de8292002-11-19 11:04:11 +0000696 case 'D':
697 case 'd':
698 res *= base;
699 res += 13;
wdenk8bde7f72003-06-27 21:31:46 +0000700 break;
wdenkc7de8292002-11-19 11:04:11 +0000701 case 'E':
702 case 'e':
703 res *= base;
704 res += 14;
wdenk8bde7f72003-06-27 21:31:46 +0000705 break;
wdenkc7de8292002-11-19 11:04:11 +0000706 case 'F':
707 case 'f':
708 res *= base;
709 res += 15;
wdenk8bde7f72003-06-27 21:31:46 +0000710 break;
wdenkc7de8292002-11-19 11:04:11 +0000711 default:
712 return res;
713 }
714 buffer++;
715 }
716 return res;
717}
718
719void 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
730void 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
755void 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}