]>
git.ipfire.org Git - people/ms/u-boot.git/blob - board/MAI/bios_emulator/x86interface.c
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.
8 * Might be cleaned out later.
19 #define LOGIO(port, format, args...) if (dolog(port)) _printf(format , ## args)
21 #define LOGIO(port, format, args...)
25 #define LOGMEM(format, args...) _printf(format , ## args)
27 #define LOGMEM(format, args...)
31 #define PRINTF(format, args...) _printf(format , ## args)
33 #define PRINTF(format, argc...)
36 typedef unsigned char UBYTE
;
37 typedef unsigned short UWORD
;
38 typedef unsigned long ULONG
;
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
48 #define EMULATOR_LOGO_OFFSET 0x40000 /* If you change this, change the strap code, too */
49 #define VIDEO_BASE (void *)0xFD0B8000
51 extern char *getenv(char *);
52 extern int tstc(void);
53 extern int getc(void);
54 extern unsigned char video_get_attr(void);
56 int atoi(char *string
)
59 while (*string
>='0' && *string
<='9')
69 void cons_gets(char *buffer
)
75 if (getenv("x86_runthru")) return; /*FIXME: */
76 while (c
!= 0x0D && c
!= 0x0A)
100 char *bios_date
= "08/14/02";
102 UBYTE submodel
= 0x00;
104 static inline UBYTE
read_byte(volatile UBYTE
* from
)
107 asm volatile ("lbz %0,%1\n eieio" : "=r" (x
) : "m" (*from
));
111 static inline void write_byte(volatile UBYTE
*to
, int x
)
113 asm volatile ("stb %1,%0\n eieio" : "=m" (*to
) : "r" (x
));
116 static inline UWORD
read_word_little(volatile UWORD
*from
)
119 asm volatile ("lhbrx %0,0,%1\n eieio" : "=r" (x
) : "r" (from
), "m" (*from
));
123 static inline UWORD
read_word_big(volatile UWORD
*from
)
126 asm volatile ("lhz %0,%1\n eieio" : "=r" (x
) : "m" (*from
));
130 static inline void write_word_little(volatile UWORD
*to
, int x
)
132 asm volatile ("sthbrx %1,0,%2\n eieio" : "=m" (*to
) : "r" (x
), "r" (to
));
135 static inline void write_word_big(volatile UWORD
*to
, int x
)
137 asm volatile ("sth %1,%0\n eieio" : "=m" (*to
) : "r" (x
));
140 static inline ULONG
read_long_little(volatile ULONG
*from
)
143 asm volatile ("lwbrx %0,0,%1\n eieio" : "=r" (x
) : "r" (from
), "m"(*from
));
147 static inline ULONG
read_long_big(volatile ULONG
*from
)
150 asm volatile ("lwz %0,%1\n eieio" : "=r" (x
) : "m" (*from
));
154 static inline void write_long_little(volatile ULONG
*to
, ULONG x
)
156 asm volatile ("stwbrx %1,0,%2\n eieio" : "=m" (*to
) : "r" (x
), "r" (to
));
159 static inline void write_long_big(volatile ULONG
*to
, ULONG x
)
161 asm volatile ("stw %1,%0\n eieio" : "=m" (*to
) : "r" (x
));
164 static int log_init
= 0;
165 static int log_do
= 0;
166 static int log_low
= 0;
170 if (log_init
&& log_do
)
172 if (log_low
&& port
> 0x400) return 0;
179 log_do
= (getenv("x86_logio") != (char *)0);
180 log_low
= (getenv("x86_loglow") != (char *)0);
183 if (log_low
&& port
> 0x400) return 0;
190 /* Converts an emulator address to a physical address. */
191 /* Handles all special cases (bios date, model etc), and might need work */
192 u32
memaddr(u32 addr
)
194 /* if (addr >= 0xF0000 && addr < 0xFFFFF) printf("WARNING: Segment F access (0x%x)\n", addr); */
195 /* printf("MemAddr=%p\n", addr); */
196 if (addr
>= 0xA0000 && addr
< 0xC0000)
197 return 0xFD000000 + addr
;
198 else if (addr
>= 0xFFFF5 && addr
< 0xFFFFE)
200 return (u32
)bios_date
+addr
-0xFFFF5;
202 else if (addr
== 0xFFFFE)
204 else if (addr
== 0xFFFFF)
205 return (u32
)&submodel
;
206 else if (addr
>= 0x80000000)
208 /*printf("Warning: High memory access at 0x%x\n", addr); */
212 return (u32
)M
.mem_base
+addr
;
217 u8 a
= read_byte((UBYTE
*)memaddr(addr
));
218 LOGMEM("rdb: %x -> %x\n", addr
, a
);
224 u16 a
= read_word_little((UWORD
*)memaddr(addr
));
225 LOGMEM("rdw: %x -> %x\n", addr
, a
);
231 u32 a
= read_long_little((ULONG
*)memaddr(addr
));
232 LOGMEM("rdl: %x -> %x\n", addr
, a
);
236 void A1_wrb(u32 addr
, u8 val
)
238 LOGMEM("wrb: %x <- %x\n", addr
, val
);
239 write_byte((UBYTE
*)memaddr(addr
), val
);
242 void A1_wrw(u32 addr
, u16 val
)
244 LOGMEM("wrw: %x <- %x\n", addr
, val
);
245 write_word_little((UWORD
*)memaddr(addr
), val
);
248 void A1_wrl(u32 addr
, u32 val
)
250 LOGMEM("wrl: %x <- %x\n", addr
, val
);
251 write_long_little((ULONG
*)memaddr(addr
), val
);
254 X86EMU_memFuncs _A1_mem
=
264 #define ARTICIAS_PCI_CFGADDR 0xfec00cf8
265 #define ARTICIAS_PCI_CFGDATA 0xfee00cfc
266 #define IOBASE 0xFE000000
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)
275 u32
port_to_mem(int port
)
277 if (port
>= 0xCFC && port
<= 0xCFF) return 0xFEE00000+port
;
278 else if (port
>= 0xCF8 && port
<= 0xCFB) return 0xFEC00000+port
;
279 else return IOBASE
+ port
;
285 /*if (port == 0x3BA) return 0; */
287 LOGIO(port
, "inb: %Xh -> %d (%Xh)\n", port
, a
, a
);
293 u16 a
= in_word(port
);
294 LOGIO(port
, "inw: %Xh -> %d (%Xh)\n", port
, a
, a
);
300 u32 a
= in_long(port
);
301 LOGIO(port
, "inl: %Xh -> %d (%Xh)\n", port
, a
, a
);
305 void A1_outb(int port
, u8 val
)
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;*/
315 void A1_outw(int port
, u16 val
)
317 LOGIO(port
, "outw: %Xh <- %d (%Xh)\n", port
, val
, val
);
321 void A1_outl(int port
, u32 val
)
323 LOGIO(port
, "outl: %Xh <- %d (%Xh)\n", port
, val
, val
);
327 X86EMU_pioFuncs _A1_pio
=
337 static int reloced_ops
= 0;
339 void reloc_ops(void *reloc_addr
)
341 extern void (*x86emu_optab
[256])(u8
);
342 extern void (*x86emu_optab2
[256])(u8
);
343 extern void tables_relocate(unsigned int offset
);
346 if (reloced_ops
== 1) return;
349 delta
= TEXT_BASE
- (unsigned long)reloc_addr
;
351 for (i
=0; i
<256; i
++)
353 x86emu_optab
[i
] -= delta
;
354 x86emu_optab2
[i
] -= delta
;
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
;
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
;
371 tables_relocate(delta
);
376 #define ANY_KEY(text) \
381 unsigned char more_strap
[] = {
382 0xb4, 0x0, 0xb0, 0x2, 0xcd, 0x10,
384 #define MORE_STRAP_BYTES 6 /* Additional bytes of strap code */
387 unsigned char *done_msg
="VGA Initialized\0";
389 int execute_bios(pci_dev_t gr_dev
, void *reloc_addr
)
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);
403 int easteregg_active
= 0;
408 unsigned char current_attr
;
410 PRINTF("Trying to remove init data\n");
412 PRINTF("Removed init data from cache, now in RAM\n");
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
));
418 /* Enable compatibility hole for emulator access to frame buffer */
419 PRINTF("Enabling compatibility hole\n");
420 enable_compatibility_hole();
422 /* Allocate memory */
423 /* FIXME: We shouldn't use this much memory really. */
424 memset(&M
, 0, sizeof(X86EMU_sysEnv
));
425 M
.mem_base
= malloc(EMULATOR_MEM_SIZE
);
426 M
.mem_size
= EMULATOR_MEM_SIZE
;
430 PRINTF("Unable to allocate one megabyte for emulator\n");
434 if (attempt_map_rom(gr_dev
, M
.mem_base
+ EMULATOR_BIOS_OFFSET
) == 0)
436 PRINTF("Error mapping rom. Emulation terminated\n");
441 s
= getenv("x86_ask_start");
444 printf("Press 'q' to skip initialization, 'd' for dry init\n'i' for i/o session");
447 if (c
== 'q') return 0;
450 extern void bios_set_mode(int mode
);
454 if (c
== 'i') do_inout();
465 easteregg_active = 1;
469 if (getenv("easteregg"))
471 easteregg_active
= 1;
474 if (easteregg_active
)
477 setenv("x86_mode", "1");
478 setenv("vga_fg_color", "11");
479 setenv("vga_bg_color", "1");
480 easteregg_active
= 1;
484 strap
= (u8
*)M
.mem_base
+ EMULATOR_STRAP_OFFSET
;
487 char *m
= getenv("x86_mode");
490 more_strap
[3] = atoi(m
);
491 if (more_strap
[3] == 1) video_size(40, 25);
492 else video_size(80, 25);
497 * Poke the strap routine. This might need a bit of extending
498 * if there is a mode switch involved, i.e. we want to int10
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.
504 PRINTF("Poking strap...\n");
506 /* FAR CALL c000:0003 */
507 *strap
++ = 0x9A; *strap
++ = 0x03; *strap
++ = 0x00;
508 *strap
++ = 0x00; *strap
++ = 0xC0;
511 /* insert additional strap code */
512 for (i
=0; i
< MORE_STRAP_BYTES
; i
++)
514 *strap
++ = more_strap
[i
];
520 PRINTF("Setting up logo data\n");
521 logo
= (unsigned char *)M
.mem_base
+ EMULATOR_LOGO_OFFSET
;
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
533 /* Execution starts here */
534 M
.x86
.R_CS
= SEG(EMULATOR_STRAP_OFFSET
);
535 M
.x86
.R_IP
= OFF(EMULATOR_STRAP_OFFSET
);
537 /* Stack at top of ram */
538 M
.x86
.R_SS
= SEG(EMULATOR_STACK_OFFSET
);
539 M
.x86
.R_SP
= OFF(EMULATOR_STACK_OFFSET
);
541 /* Input parameters */
542 M
.x86
.R_AH
= PCI_BUS(gr_dev
);
543 M
.x86
.R_AL
= (PCI_DEV(gr_dev
)<<3) | PCI_FUNC(gr_dev
);
545 /* Set the I/O and memory access functions */
546 X86EMU_setupMemFuncs(&_A1_mem
);
547 X86EMU_setupPioFuncs(&_A1_pio
);
550 cfg
= in_byte(0x61); /* Get Misc control */
551 cfg
|= 0x01; /* Enable timer 2 */
552 out_byte(0x61, cfg
); /* output again */
554 /* Set up the timers */
555 out_byte(0x43, 0x54);
556 out_byte(0x41, 0x18);
558 out_byte(0x43, 0x36);
559 out_byte(0x40, 0x00);
560 out_byte(0x40, 0x00);
562 out_byte(0x43, 0xb6);
563 out_byte(0x42, 0x31);
564 out_byte(0x42, 0x13);
566 /* Init the "BIOS". */
569 /* Video Card Reset */
572 (void)in_byte(0x3BA);
573 (void)in_byte(0x3DA);
575 out_byte(0x61, 0xFC);
578 s
= _getenv("x86_singlestep");
579 if (s
&& strcmp(s
, "on")==0)
581 PRINTF("Enabling single stepping for debug\n");
586 /* Ready set go... */
587 PRINTF("Running emulator\n");
589 PRINTF("Done running emulator\n");
591 /* FIXME: Remove me */
592 pal_reset
= getenv("x86_palette_reset");
593 if (pal_reset
&& strcmp(pal_reset
, "on") == 0)
595 PRINTF("Palette reset\n");
596 /*(void)in_byte(0x3da); */
597 /*out_byte(0x3c0, 0); */
603 for (i
=0; i
<254; i
++)
610 out_byte(0x3c0, 0x20);
612 /* FIXME: remove me */
614 if (easteregg_active
)
616 extern void video_easteregg(void);
621 current_attr = video_get_attr();
622 fb = (u8 *)VIDEO_BASE;
623 for (i=0; i<video_rows()*video_cols()*2; i+=2)
626 *(fb+i+1) = current_attr;
629 fb = (u8 *)VIDEO_BASE + (video_rows())-1*(video_cols()*2);
630 for (i=0; i<video_cols(); i++)
633 *(fb + 2*i + 1) = 0x17;
645 if (getenv("x86_do_inout")) do_inout();
648 /*FIXME: dcache_disable(); */
652 /* Clean up the x86 mess */
653 void shutdown_bios(void)
655 /* disable_compatibility_hole(); */
656 /* Free the memory associated */
661 int to_int(char *buffer
)
679 res
+= *buffer
- '0';
719 void one_arg(char *buffer
, int *a
)
721 while (*buffer
&& *buffer
!= '\n')
723 if (*buffer
== ' ') buffer
++;
730 void two_args(char *buffer
, int *a
, int *b
)
732 while (*buffer
&& *buffer
!= '\n')
734 if (*buffer
== ' ') buffer
++;
740 while (*buffer
&& *buffer
!= '\n')
742 if (*buffer
!= ' ') buffer
++;
746 while (*buffer
&& *buffer
!= '\n')
748 if (*buffer
== ' ') buffer
++;
761 printf("In/Out Session\nUse 'i[bwl]' for in, 'o[bwl]' for out and 'q' to quit\n");
769 while (*arg1
!= ' ' ) arg1
++;
770 while (*arg1
== ' ') arg1
++;
772 if (buffer
[0] == 'i')
774 one_arg(buffer
+2, &a
);
778 printf("in_byte(%xh) = %xh\n", a
, A1_inb(a
));
781 printf("in_word(%xh) = %xh\n", a
, A1_inw(a
));
784 printf("in_dword(%xh) = %xh\n", a
, A1_inl(a
));
787 printf("Invalid length '%c'\n", buffer
[1]);
791 else if (buffer
[0] == 'o')
793 two_args(buffer
+2, &a
, &b
);
797 printf("out_byte(%d, %d)\n", a
, b
);
801 printf("out_word(%d, %d)\n", a
, b
);
805 printf("out_long(%d, %d)\n", a
, b
);
809 printf("Invalid length '%c'\n", buffer
[1]);
812 } else if (buffer
[0] == 'q') return;