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