]> git.sur5r.net Git - u-boot/blob - board/MAI/bios_emulator/bios.c
* Code cleanup:
[u-boot] / board / MAI / bios_emulator / bios.c
1 /*
2  * Mostly done after the Scitech Bios emulation
3  * Written by Hans-Jörg Frieden
4  * Hyperion Entertainment
5  */
6 #include "x86emu.h"
7 #include "glue.h"
8
9 #undef DEBUG
10 #ifdef DEBUG
11 #define PRINTF(fmt, args...) printf(fmt, ## args)
12 #else
13 #define PRINTF(fmt, args...)
14 #endif
15
16 #define BIOS_SEG 0xFFF0
17 #define PCIBIOS_SUCCESSFUL 0
18 #define PCIBIOS_DEVICE_NOT_FOUND 0x86
19
20 typedef unsigned char UBYTE;
21 typedef unsigned short UWORD;
22 typedef unsigned long ULONG;
23
24 typedef char BYTE;
25 typedef short WORT;
26 typedef long LONG;
27
28 static inline UBYTE read_byte(volatile UBYTE* from)
29 {
30     int x;
31     asm volatile ("lbz %0,%1\n eieio" : "=r" (x) : "m" (*from));
32     return (UBYTE)x;
33 }
34
35 static inline void write_byte(volatile UBYTE *to, int x)
36 {
37     asm volatile ("stb %1,%0\n eieio" : "=m" (*to) : "r" (x));
38 }
39
40 static inline UWORD read_word_little(volatile UWORD *from)
41 {
42     int x;
43     asm volatile ("lhbrx %0,0,%1\n eieio" : "=r" (x) : "r" (from), "m" (*from));
44     return (UWORD)x;
45 }
46
47 static inline UWORD read_word_big(volatile UWORD *from)
48 {
49     int x;
50     asm volatile ("lhz %0,%1\n eieio" : "=r" (x) : "m" (*from));
51     return (UWORD)x;
52 }
53
54 static inline void write_word_little(volatile UWORD *to, int x)
55 {
56     asm volatile ("sthbrx %1,0,%2\n eieio" : "=m" (*to) : "r" (x), "r" (to));
57 }
58
59 static inline void write_word_big(volatile UWORD *to, int x)
60 {
61     asm volatile ("sth %1,%0\n eieio" : "=m" (*to) : "r" (x));
62 }
63
64 static inline ULONG read_long_little(volatile ULONG *from)
65 {
66     unsigned long x;
67     asm volatile ("lwbrx %0,0,%1\n eieio" : "=r" (x) : "r" (from), "m"(*from));
68     return (ULONG)x;
69 }
70
71 static inline ULONG read_long_big(volatile ULONG *from)
72 {
73     unsigned long x;
74     asm volatile ("lwz %0,%1\n eieio" : "=r" (x) : "m" (*from));
75     return (ULONG)x;
76 }
77
78 static inline void write_long_little(volatile ULONG *to, ULONG x)
79 {
80     asm volatile ("stwbrx %1,0,%2\n eieio" : "=m" (*to) : "r" (x), "r" (to));
81 }
82
83 static inline void write_long_big(volatile ULONG *to, ULONG x)
84 {
85     asm volatile ("stw %1,%0\n eieio" : "=m" (*to) : "r" (x));
86 }
87
88 #define port_to_mem(from) (0xFE000000|(from))
89 #define in_byte(from) read_byte( (UBYTE *)port_to_mem(from))
90 #define in_word(from) read_word_little((UWORD *)port_to_mem(from))
91 #define in_long(from) read_long_little((ULONG *)port_to_mem(from))
92 #define out_byte(to, val) write_byte((UBYTE *)port_to_mem(to), val)
93 #define out_word(to, val) write_word_little((UWORD *)port_to_mem(to), val)
94 #define out_long(to, val) write_long_little((ULONG *)port_to_mem(to), val)
95
96 static void X86API undefined_intr(int intno)
97 {
98     extern u16 A1_rdw(u32 addr);
99     if (A1_rdw(intno * 4 + 2) == BIOS_SEG)
100     {
101         PRINTF("Undefined interrupt %xh called AX = %xh, BX = %xh, CX = %xh, DX = %xh\n",
102            intno, M.x86.R_AX, M.x86.R_BX, M.x86.R_CX, M.x86.R_DX);
103         X86EMU_halt_sys();
104     }
105     else
106     {
107         PRINTF("Calling interrupt %xh, AL=%xh, AH=%xh\n", intno, M.x86.R_AL, M.x86.R_AH);
108         X86EMU_prepareForInt(intno);
109     }
110 }
111
112 static void X86API int42(int intno);
113 static void X86API int15(int intno);
114
115 static void X86API int10(int intno)
116 {
117     if (A1_rdw(intno*4+2) == BIOS_SEG)
118         int42(intno);
119     else
120     {
121         PRINTF("int10: branching to %04X:%04X, AL=%xh, AH=%xh\n", A1_rdw(intno*4+2), A1_rdw(intno*4),
122                M.x86.R_AL, M.x86.R_AH);
123         X86EMU_prepareForInt(intno);
124     }
125 }
126
127 static void X86API int1A(int intno)
128 {
129     int device;
130
131     switch(M.x86.R_AX)
132     {
133     case 0xB101: /* PCI Bios Present? */
134         M.x86.R_AL  = 0x00;
135         M.x86.R_EDX = 0x20494350;
136         M.x86.R_BX  = 0x0210;
137         M.x86.R_CL  = 3;
138         CLEAR_FLAG(F_CF);
139         break;
140     case 0xB102: /* Find device */
141         device = mypci_find_device(M.x86.R_DX, M.x86.R_CX, M.x86.R_SI);
142         if (device != -1)
143         {
144             M.x86.R_AH = PCIBIOS_SUCCESSFUL;
145             M.x86.R_BH = mypci_bus(device);
146             M.x86.R_BL = mypci_devfn(device);
147         }
148         else
149         {
150             M.x86.R_AH = PCIBIOS_DEVICE_NOT_FOUND;
151         }
152         CONDITIONAL_SET_FLAG((M.x86.R_AH != PCIBIOS_SUCCESSFUL), F_CF);
153         break;
154     case 0xB103: /* Find PCI class code */
155         M.x86.R_AH = PCIBIOS_DEVICE_NOT_FOUND;
156         /*printf("Find by class not yet implmented"); */
157         CONDITIONAL_SET_FLAG((M.x86.R_AH != PCIBIOS_SUCCESSFUL), F_CF);
158         break;
159     case 0xB108: /* read config byte */
160         M.x86.R_CL = mypci_read_cfg_byte(M.x86.R_BH, M.x86.R_BL, M.x86.R_DI);
161         M.x86.R_AH = PCIBIOS_SUCCESSFUL;
162         CONDITIONAL_SET_FLAG((M.x86.R_AH != PCIBIOS_SUCCESSFUL), F_CF);
163         /*printf("read_config_byte %x,%x,%x -> %x\n", M.x86.R_BH, M.x86.R_BL, M.x86.R_DI, */
164         /*          M.x86.R_CL); */
165         break;
166     case 0xB109: /* read config word */
167         M.x86.R_CX = mypci_read_cfg_word(M.x86.R_BH, M.x86.R_BL, M.x86.R_DI);
168         M.x86.R_AH = PCIBIOS_SUCCESSFUL;
169         CONDITIONAL_SET_FLAG((M.x86.R_AH != PCIBIOS_SUCCESSFUL), F_CF);
170         /*printf("read_config_word %x,%x,%x -> %x\n", M.x86.R_BH, M.x86.R_BL, M.x86.R_DI, */
171         /*          M.x86.R_CX); */
172         break;
173     case 0xB10A: /* read config dword */
174         M.x86.R_ECX = mypci_read_cfg_long(M.x86.R_BH, M.x86.R_BL, M.x86.R_DI);
175         M.x86.R_AH = PCIBIOS_SUCCESSFUL;
176         CONDITIONAL_SET_FLAG((M.x86.R_AH != PCIBIOS_SUCCESSFUL), F_CF);
177         /*printf("read_config_long %x,%x,%x -> %x\n", M.x86.R_BH, M.x86.R_BL, M.x86.R_DI, */
178         /*    M.x86.R_ECX); */
179         break;
180     case 0xB10B: /* write config byte */
181         mypci_write_cfg_byte(M.x86.R_BH, M.x86.R_BL, M.x86.R_DI, M.x86.R_CL);
182         M.x86.R_AH = PCIBIOS_SUCCESSFUL;
183         CONDITIONAL_SET_FLAG((M.x86.R_AH != PCIBIOS_SUCCESSFUL), F_CF);
184         /*printf("write_config_byte %x,%x,%x <- %x\n", M.x86.R_BH, M.x86.R_BL, M.x86.R_DI, */
185         /*    M.x86.R_CL); */
186         break;
187     case 0xB10C: /* write config word */
188         mypci_write_cfg_word(M.x86.R_BH, M.x86.R_BL, M.x86.R_DI, M.x86.R_CX);
189         M.x86.R_AH = PCIBIOS_SUCCESSFUL;
190         CONDITIONAL_SET_FLAG((M.x86.R_AH != PCIBIOS_SUCCESSFUL), F_CF);
191         /*printf("write_config_word %x,%x,%x <- %x\n", M.x86.R_BH, M.x86.R_BL, M.x86.R_DI, */
192         /*          M.x86.R_CX); */
193         break;
194     case 0xB10D: /* write config dword */
195         mypci_write_cfg_long(M.x86.R_BH, M.x86.R_BL, M.x86.R_DI, M.x86.R_ECX);
196         M.x86.R_AH = PCIBIOS_SUCCESSFUL;
197         CONDITIONAL_SET_FLAG((M.x86.R_AH != PCIBIOS_SUCCESSFUL), F_CF);
198         /*printf("write_config_long %x,%x,%x <- %x\n", M.x86.R_BH, M.x86.R_BL, M.x86.R_DI, */
199         /*          M.x86.R_ECX); */
200         break;
201     default:
202         PRINTF("BIOS int %xh: Unknown function AX=%04xh\n", intno, M.x86.R_AX);
203
204     }
205 }
206
207 void bios_init(void)
208 {
209     int i;
210     X86EMU_intrFuncs bios_intr_tab[256];
211
212     for (i=0; i<256; i++)
213     {
214         write_long_little(M.mem_base+i*4, BIOS_SEG<<16);
215         bios_intr_tab[i] = undefined_intr;
216     }
217
218     bios_intr_tab[0x10] = int10;
219     bios_intr_tab[0x1A] = int1A;
220     bios_intr_tab[0x42] = int42;
221     bios_intr_tab[0x15] = int15;
222
223     bios_intr_tab[0x6D] = int42;
224
225     X86EMU_setupIntrFuncs(bios_intr_tab);
226     video_init();
227 }
228
229 unsigned char setup_40x25[] =
230 {
231     0x38, 0x28, 0x2d, 0x0a, 0x1f, 6, 0x19,
232     0x1c, 2, 7, 6, 7, 0, 0, 0, 0
233 };
234
235 unsigned char setup_80x25[] =
236 {
237     0x71, 0x50, 0x5a, 0x0a, 0x1f, 6, 0x19,
238     0x1c, 2, 7, 6, 7, 0, 0, 0, 0
239 };
240
241 unsigned char setup_graphics[] =
242 {
243     0x38, 0x28, 0x20, 0x0a, 0x7f, 6, 0x64,
244     0x70, 2, 1, 6, 7, 0, 0, 0, 0
245 };
246
247 unsigned char setup_bw[] =
248 {
249     0x61, 0x50, 0x52, 0x0f, 0x19, 6, 0x19,
250     0x19, 2, 0x0d, 0x0b, 0x0c, 0, 0, 0, 0
251 };
252
253 unsigned char * setup_modes[] =
254 {
255     setup_40x25,     /* mode 0: 40x25 bw text */
256     setup_40x25,     /* mode 1: 40x25 col text */
257     setup_80x25,     /* mode 2: 80x25 bw text */
258     setup_80x25,     /* mode 3: 80x25 col text */
259     setup_graphics,  /* mode 4: 320x200 col graphics */
260     setup_graphics,  /* mode 5: 320x200 bw graphics */
261     setup_graphics,  /* mode 6: 640x200 bw graphics */
262     setup_bw         /* mode 7: 80x25 mono text */
263 };
264
265 unsigned int setup_cols[] =
266 {
267     40, 40, 80, 80, 40, 40, 80, 80
268 };
269
270 unsigned char setup_modesets[] =
271 {
272      0x2C, 0x28, 0x2D, 0x29, 0x2A, 0x2E, 0x1E, 0x29
273 };
274
275 unsigned int setup_bufsize[] =
276 {
277     2048, 2048, 4096, 2096, 16384, 16384, 16384, 4096
278 };
279
280 void bios_set_mode(int mode)
281 {
282     int i;
283     unsigned char mode_set = setup_modesets[mode]; /* Control register value */
284     unsigned char *setup_regs = setup_modes[mode]; /* Register 3D4 Array */
285
286     /* Switch video off */
287     out_byte(0x3D8, mode_set & 0x37);
288
289     /* Set up parameters at 3D4h */
290     for (i=0; i<16; i++)
291     {
292         out_byte(0x3D4, (unsigned char)i);
293         out_byte(0x3D5, *setup_regs);
294         setup_regs++;
295     }
296
297     /* Enable video */
298     out_byte(0x3D8, mode_set);
299
300     /* Set overscan */
301     if (mode == 6) out_byte(0x3D9, 0x3F);
302     else           out_byte(0x3D9, 0x30);
303 }
304
305 static void bios_print_string(void)
306 {
307     extern void video_bios_print_string(char *string, int x, int y, int attr, int count);
308     char *s = (char *)(M.x86.R_ES<<4) + M.x86.R_BP;
309     int attr;
310     if (M.x86.R_AL & 0x02) attr = - 1;
311     else                   attr = M.x86.R_BL;
312     video_bios_print_string(s, M.x86.R_DH, M.x86.R_DL, attr, M.x86.R_CX);
313 }
314
315 static void X86API int42(int intno)
316 {
317     switch (M.x86.R_AH)
318     {
319     case 0x00:
320         bios_set_mode(M.x86.R_AL);
321         break;
322     case 0x13:
323         bios_print_string();
324         break;
325     default:
326         PRINTF("Warning: VIDEO BIOS interrupt %xh unimplemented function %xh, AL = %xh\n",
327                intno, M.x86.R_AH, M.x86.R_AL);
328     }
329 }
330
331 static void X86API int15(int intno)
332 {
333     PRINTF("Called interrupt 15h: AX = %xh, BX = %xh, CX = %xh, DX = %xh\n",
334            M.x86.R_AX, M.x86.R_BX, M.x86.R_CX, M.x86.R_DX);
335 }