1 /******************************************************************************
2  * Copyright (c) 2004, 2008 IBM Corporation
3  * All rights reserved.
4  * This program and the accompanying materials
5  * are made available under the terms of the BSD License
6  * which accompanies this distribution, and is available at
7  * http://www.opensource.org/licenses/bsd-license.php
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12 
13 #include <stdio.h>
14 
15 #include <rtas.h>
16 
17 #include "biosemu.h"
18 #include "mem.h"
19 #include "device.h"
20 #include "debug.h"
21 #include "interrupt.h"
22 
23 #include <x86emu/x86emu.h>
24 #include <x86emu/prim_ops.h>
25 
26 
27 
28 //setup to run the code at the address, that the Interrupt Vector points to...
29 static void
setupInt(int intNum)30 setupInt(int intNum)
31 {
32 	DEBUG_PRINTF_INTR("%s(%x): executing interrupt handler @%08x\n",
33 			  __FUNCTION__, intNum, my_rdl(intNum * 4));
34 	// push current R_FLG... will be popped by IRET
35 	push_word((u16) M.x86.R_FLG);
36 	CLEAR_FLAG(F_IF);
37 	CLEAR_FLAG(F_TF);
38 	// push current CS:IP to the stack, will be popped by IRET
39 	push_word(M.x86.R_CS);
40 	push_word(M.x86.R_IP);
41 	// set CS:IP to the interrupt handler address... so the next executed instruction will
42 	// be the interrupt handler
43 	M.x86.R_CS = my_rdw(intNum * 4 + 2);
44 	M.x86.R_IP = my_rdw(intNum * 4);
45 }
46 
47 // handle int10 (VGA BIOS Interrupt)
48 static void
handleInt10(void)49 handleInt10(void)
50 {
51 	// the data for INT10 is stored in BDA (0000:0400h) offset 49h-66h
52 	// function number in AH
53 	//DEBUG_PRINTF_CS_IP("%s:\n", __FUNCTION__);
54 	//x86emu_dump_xregs();
55 	//if ((M.x86.R_IP == 0x32c2) && (M.x86.R_SI == 0x1ce2)){
56 	//X86EMU_trace_on();
57 	//M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
58 	//}
59 	switch (M.x86.R_AH) {
60 	case 0x00:
61 		// set video mode
62 		// BDA offset 49h is current video mode
63 		my_wrb(0x449, M.x86.R_AL);
64 		if (M.x86.R_AL > 7)
65 			M.x86.R_AL = 0x20;
66 		else if (M.x86.R_AL == 6)
67 			M.x86.R_AL = 0x3f;
68 		else
69 			M.x86.R_AL = 0x30;
70 		break;
71 	case 0x01:
72 		// set cursor shape
73 		// ignore
74 		break;
75 	case 0x02:
76 		// set cursor position
77 		// BH: pagenumber, DX: cursor_pos (DH:row, DL:col)
78 		// BDA offset 50h-60h are 8 cursor position words for
79 		// eight possible video pages
80 		my_wrw(0x450 + (M.x86.R_BH * 2), M.x86.R_DX);
81 		break;
82 	case 0x03:
83 		//get cursor position
84 		// BH: pagenumber
85 		// BDA offset 50h-60h are 8 cursor position words for
86 		// eight possible video pages
87 		M.x86.R_AX = 0;
88 		M.x86.R_CH = 0;	// start scan line ???
89 		M.x86.R_CL = 0;	// end scan line ???
90 		M.x86.R_DX = my_rdw(0x450 + (M.x86.R_BH * 2));
91 		break;
92 	case 0x05:
93 		// set active page
94 		// BDA offset 62h is current page number
95 		my_wrb(0x462, M.x86.R_AL);
96 		break;
97 	case 0x06:
98 		//scroll up windows
99 		break;
100 	case 0x07:
101 		//scroll down windows
102 		break;
103 	case 0x08:
104 		//read character and attribute at position
105 		M.x86.R_AH = 0x07;	// white-on-black
106 		M.x86.R_AL = 0x20;	// a space...
107 		break;
108 	case 0x09:
109 		// write character and attribute
110 		//AL: char, BH: page number, BL: attribute, CX: number of times to write
111 		//BDA offset 62h is current page number
112 		CHECK_DBG(DEBUG_PRINT_INT10) {
113 			uint32_t i = 0;
114 			if (M.x86.R_BH == my_rdb(0x462)) {
115 				for (i = 0; i < M.x86.R_CX; i++)
116 					printf("%c", M.x86.R_AL);
117 			}
118 		}
119 		break;
120 	case 0x0a:
121 		// write character
122 		//AL: char, BH: page number, BL: attribute, CX: number of times to write
123 		//BDA offset 62h is current page number
124 		CHECK_DBG(DEBUG_PRINT_INT10) {
125 			uint32_t i = 0;
126 			if (M.x86.R_BH == my_rdb(0x462)) {
127 				for (i = 0; i < M.x86.R_CX; i++)
128 					printf("%c", M.x86.R_AL);
129 			}
130 		}
131 		break;
132 	case 0x0e:
133 		// teletype output: write character and advance cursor...
134 		//AL: char, BH: page number, BL: attribute
135 		//BDA offset 62h is current page number
136 		CHECK_DBG(DEBUG_PRINT_INT10) {
137 			// we ignore the pagenumber on this call...
138 			//if (M.x86.R_BH == my_rdb(0x462))
139 			{
140 				printf("%c", M.x86.R_AL);
141 				// for debugging, to read all lines
142 				//if (M.x86.R_AL == 0xd) // carriage return
143 				//      printf("\n");
144 			}
145 		}
146 		break;
147 	case 0x0f:
148 		// get video mode
149 		// BDA offset 49h is current video mode
150 		// BDA offset 62h is current page number
151 		// BDA offset 4ah is columns on screen
152 		M.x86.R_AH = 80;	//number of character columns... we hardcode it to 80
153 		M.x86.R_AL = my_rdb(0x449);
154 		M.x86.R_BH = my_rdb(0x462);
155 		break;
156 	default:
157 		printf("%s(): unknown function (%x) for int10 handler.\n",
158 		       __FUNCTION__, M.x86.R_AH);
159 		DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
160 				  M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
161 				  M.x86.R_DX);
162 		HALT_SYS();
163 		break;
164 	}
165 }
166 
167 // this table translates ASCII chars into their XT scan codes:
168 static uint8_t keycode_table[256] = {
169 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 0 - 7
170 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 8 - 15
171 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 16 - 23
172 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 24 - 31
173 	0x39, 0x02, 0x28, 0x04, 0x05, 0x06, 0x08, 0x28,	// 32 - 39
174 	0x0a, 0x0b, 0x09, 0x2b, 0x33, 0x0d, 0x34, 0x35,	// 40 - 47
175 	0x0b, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,	// 48 - 55
176 	0x09, 0x0a, 0x27, 0x27, 0x33, 0x2b, 0x34, 0x35,	// 56 - 63
177 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 64 - 71
178 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 72 - 79
179 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 80 - 87
180 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 88 - 95
181 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 96 - 103
182 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 104 - 111
183 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 112 - 119
184 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 120 - 127
185 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// ...
186 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
188 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 };
202 
203 static void
translate_keycode(uint64_t * keycode)204 translate_keycode(uint64_t * keycode)
205 {
206 	uint8_t scan_code = 0;
207 	uint8_t char_code = 0;
208 	if (*keycode < 256) {
209 		scan_code = keycode_table[*keycode];
210 		char_code = (uint8_t) * keycode & 0xff;
211 	} else {
212 		switch (*keycode) {
213 		case 0x1b50:
214 			// F1
215 			scan_code = 0x3b;
216 			char_code = 0x0;
217 			break;
218 		default:
219 			printf("%s(): unknown multibyte keycode: %llx\n",
220 			       __FUNCTION__, *keycode);
221 			break;
222 		}
223 	}
224 	//assemble scan/char code in keycode
225 	*keycode = (uint64_t) ((((uint16_t) scan_code) << 8) | char_code);
226 }
227 
228 // handle int16 (Keyboard BIOS Interrupt)
229 static void
handleInt16(void)230 handleInt16(void)
231 {
232 	// keyboard buffer is in BIOS Memory Area:
233 	// offset 0x1a (WORD) pointer to next char in keybuffer
234 	// offset 0x1c (WORD) pointer to next insert slot in keybuffer
235 	// offset 0x1e-0x3e: 16 WORD Ring Buffer
236 	// since we currently always read the char from the FW buffer,
237 	// we misuse the ring buffer, we use it as pointer to a uint64_t that stores
238 	// multi-byte keys (e.g. special keys in VT100 terminal)
239 	// and as long as a key is available (not 0) we dont read further keys
240 	uint64_t *keycode = (uint64_t *) (M.mem_base + 0x41e);
241 	int8_t c;
242 	// function number in AH
243 	DEBUG_PRINTF_INTR("%s(): Keyboard Interrupt: function: %x.\n",
244 			  __FUNCTION__, M.x86.R_AH);
245 	DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n", M.x86.R_AX,
246 			  M.x86.R_BX, M.x86.R_CX, M.x86.R_DX);
247 	switch (M.x86.R_AH) {
248 	case 0x00:
249 		// get keystroke
250 		if (*keycode) {
251 			M.x86.R_AX = (uint16_t) * keycode;
252 			// clear keycode
253 			*keycode = 0;
254 		} else {
255 			M.x86.R_AH = 0x61;	// scancode for space key
256 			M.x86.R_AL = 0x20;	// a space
257 		}
258 		break;
259 	case 0x01:
260 		// check keystroke
261 		// ZF set = no keystroke
262 		// read first byte of key code
263 		if (*keycode) {
264 			// already read, but not yet taken
265 			CLEAR_FLAG(F_ZF);
266 			M.x86.R_AX = (uint16_t) * keycode;
267 		} else {
268 			c = getchar();
269 			if (c == -1) {
270 				// no key available
271 				SET_FLAG(F_ZF);
272 			} else {
273 				*keycode = c;
274 
275 				// since after an ESC it may take a while to receive the next char,
276 				// we send something that is not shown on the screen, and then try to get
277 				// the next char
278 				// TODO: only after ESC?? what about other multibyte keys
279 				printf("tt%c%c", 0x08, 0x08);	// 0x08 == Backspace
280 
281 				while ((c = getchar()) != -1) {
282 					*keycode = (*keycode << 8) | c;
283 					DEBUG_PRINTF(" key read: %0llx\n",
284 						     *keycode);
285 				}
286 				translate_keycode(keycode);
287 				DEBUG_PRINTF(" translated key: %0llx\n",
288 					     *keycode);
289 				if (*keycode == 0) {
290 					//not found
291 					SET_FLAG(F_ZF);
292 				} else {
293 					CLEAR_FLAG(F_ZF);
294 					M.x86.R_AX = (uint16_t) * keycode;
295 					//X86EMU_trace_on();
296 					//M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
297 				}
298 			}
299 		}
300 		break;
301 	default:
302 		printf("%s(): unknown function (%x) for int16 handler.\n",
303 		       __FUNCTION__, M.x86.R_AH);
304 		DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
305 				  M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
306 				  M.x86.R_DX);
307 		HALT_SYS();
308 		break;
309 	}
310 }
311 
312 // handle int1a (PCI BIOS Interrupt)
313 static void
handleInt1a(void)314 handleInt1a(void)
315 {
316 	// function number in AX
317 	uint8_t bus, devfn, offs;
318 	switch (M.x86.R_AX) {
319 	case 0xb101:
320 		// Installation check
321 		CLEAR_FLAG(F_CF);	// clear CF
322 		M.x86.R_EDX = 0x20494350;	// " ICP" endian swapped "PCI "
323 		M.x86.R_AL = 0x1;	// Config Space Mechanism 1 supported
324 		M.x86.R_BX = 0x0210;	// PCI Interface Level Version 2.10
325 		M.x86.R_CL = 0xff;	// number of last PCI Bus in system TODO: check!
326 		break;
327 	case 0xb102:
328 		// Find PCI Device
329 		// NOTE: we currently only allow the device to find itself...
330 		// it SHOULD be all we ever need...
331 		// device_id in CX, vendor_id in DX
332 		// device index in SI (i.e. if multiple devices with same vendor/device id
333 		// are connected). We currently only support device index 0
334 		DEBUG_PRINTF_INTR("%s(): function: %x: PCI Find Device\n",
335 				  __FUNCTION__, M.x86.R_AX);
336 		if ((M.x86.R_CX == bios_device.pci_device_id)
337 		    && (M.x86.R_DX == bios_device.pci_vendor_id)
338 		    // device index must be 0
339 		    && (M.x86.R_SI == 0)) {
340 			CLEAR_FLAG(F_CF);
341 			M.x86.R_AH = 0x00;	// return code: success
342 			M.x86.R_BH = bios_device.bus;
343 			M.x86.R_BL = bios_device.devfn;
344 			DEBUG_PRINTF_INTR
345 			    ("%s(): function %x: PCI Find Device --> 0x%04x\n",
346 			     __FUNCTION__, M.x86.R_AX, M.x86.R_BX);
347 		} else {
348 			DEBUG_PRINTF_INTR
349 			    ("%s(): function %x: invalid device/vendor/device index! (%04x/%04x/%02x expected: %04x/%04x/0) \n",
350 			     __FUNCTION__, M.x86.R_AX, M.x86.R_CX, M.x86.R_DX,
351 			     M.x86.R_SI, bios_device.pci_device_id,
352 			     bios_device.pci_vendor_id);
353 			SET_FLAG(F_CF);
354 			M.x86.R_AH = 0x86;	// return code: device not found
355 		}
356 		break;
357 	case 0xb108:		//read configuration byte
358 	case 0xb109:		//read configuration word
359 	case 0xb10a:		//read configuration dword
360 		bus = M.x86.R_BH;
361 		devfn = M.x86.R_BL;
362 		offs = M.x86.R_DI;
363 		if ((bus != bios_device.bus)
364 		    || (devfn != bios_device.devfn)) {
365 			// fail accesses to any device but ours...
366 			printf
367 			    ("%s(): Config read access invalid! bus: %x (%x), devfn: %x (%x), offs: %x\n",
368 			     __FUNCTION__, bus, bios_device.bus, devfn,
369 			     bios_device.devfn, offs);
370 			SET_FLAG(F_CF);
371 			M.x86.R_AH = 0x87;	//return code: bad pci register
372 			HALT_SYS();
373 			return;
374 		} else {
375 			switch (M.x86.R_AX) {
376 			case 0xb108:
377 				M.x86.R_CL =
378 				    (uint8_t) rtas_pci_config_read(bios_device.
379 								   puid, 1,
380 								   bus, devfn,
381 								   offs);
382 				DEBUG_PRINTF_INTR
383 				    ("%s(): function %x: PCI Config Read @%02x --> 0x%02x\n",
384 				     __FUNCTION__, M.x86.R_AX, offs,
385 				     M.x86.R_CL);
386 				break;
387 			case 0xb109:
388 				M.x86.R_CX =
389 				    (uint16_t) rtas_pci_config_read(bios_device.
390 								    puid, 2,
391 								    bus, devfn,
392 								    offs);
393 				DEBUG_PRINTF_INTR
394 				    ("%s(): function %x: PCI Config Read @%02x --> 0x%04x\n",
395 				     __FUNCTION__, M.x86.R_AX, offs,
396 				     M.x86.R_CX);
397 				break;
398 			case 0xb10a:
399 				M.x86.R_ECX =
400 				    (uint32_t) rtas_pci_config_read(bios_device.
401 								    puid, 4,
402 								    bus, devfn,
403 								    offs);
404 				DEBUG_PRINTF_INTR
405 				    ("%s(): function %x: PCI Config Read @%02x --> 0x%08x\n",
406 				     __FUNCTION__, M.x86.R_AX, offs,
407 				     M.x86.R_ECX);
408 				break;
409 			}
410 			CLEAR_FLAG(F_CF);
411 			M.x86.R_AH = 0x0;	// return code: success
412 		}
413 		break;
414 	case 0xb10b:		//write configuration byte
415 	case 0xb10c:		//write configuration word
416 	case 0xb10d:		//write configuration dword
417 		bus = M.x86.R_BH;
418 		devfn = M.x86.R_BL;
419 		offs = M.x86.R_DI;
420 		if ((bus != bios_device.bus)
421 		    || (devfn != bios_device.devfn)) {
422 			// fail accesses to any device but ours...
423 			printf
424 			    ("%s(): Config read access invalid! bus: %x (%x), devfn: %x (%x), offs: %x\n",
425 			     __FUNCTION__, bus, bios_device.bus, devfn,
426 			     bios_device.devfn, offs);
427 			SET_FLAG(F_CF);
428 			M.x86.R_AH = 0x87;	//return code: bad pci register
429 			HALT_SYS();
430 			return;
431 		} else {
432 			switch (M.x86.R_AX) {
433 			case 0xb10b:
434 				rtas_pci_config_write(bios_device.puid, 1, bus,
435 						      devfn, offs, M.x86.R_CL);
436 				DEBUG_PRINTF_INTR
437 				    ("%s(): function %x: PCI Config Write @%02x <-- 0x%02x\n",
438 				     __FUNCTION__, M.x86.R_AX, offs,
439 				     M.x86.R_CL);
440 				break;
441 			case 0xb10c:
442 				rtas_pci_config_write(bios_device.puid, 2, bus,
443 						      devfn, offs, M.x86.R_CX);
444 				DEBUG_PRINTF_INTR
445 				    ("%s(): function %x: PCI Config Write @%02x <-- 0x%04x\n",
446 				     __FUNCTION__, M.x86.R_AX, offs,
447 				     M.x86.R_CX);
448 				break;
449 			case 0xb10d:
450 				rtas_pci_config_write(bios_device.puid, 4, bus,
451 						      devfn, offs, M.x86.R_ECX);
452 				DEBUG_PRINTF_INTR
453 				    ("%s(): function %x: PCI Config Write @%02x <-- 0x%08x\n",
454 				     __FUNCTION__, M.x86.R_AX, offs,
455 				     M.x86.R_ECX);
456 				break;
457 			}
458 			CLEAR_FLAG(F_CF);
459 			M.x86.R_AH = 0x0;	// return code: success
460 		}
461 		break;
462 	default:
463 		printf("%s(): unknown function (%x) for int1a handler.\n",
464 		       __FUNCTION__, M.x86.R_AX);
465 		DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
466 				  M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
467 				  M.x86.R_DX);
468 		HALT_SYS();
469 		break;
470 	}
471 }
472 
473 // main Interrupt Handler routine, should be registered as x86emu interrupt handler
474 void
handleInterrupt(int intNum)475 handleInterrupt(int intNum)
476 {
477 	uint8_t int_handled = 0;
478 #ifndef DEBUG_PRINT_INT10
479 	// this printf makes output by int 10 unreadable...
480 	// so we only enable it, if int10 print is disabled
481 	DEBUG_PRINTF_INTR("%s(%x)\n", __FUNCTION__, intNum);
482 #endif
483 	switch (intNum) {
484 	case 0x10:		//BIOS video interrupt
485 	case 0x42:		// INT 10h relocated by EGA/VGA BIOS
486 	case 0x6d:		// INT 10h relocated by VGA BIOS
487 		// get interrupt vector from IDT (4 bytes per Interrupt starting at address 0
488 		if ((my_rdl(intNum * 4) == 0xF000F065) ||	//F000:F065 is default BIOS interrupt handler address
489 		    (my_rdl(intNum * 4) == 0xF4F4F4F4))	//invalid
490 		{
491 #if 0
492 			// ignore interrupt...
493 			DEBUG_PRINTF_INTR
494 			    ("%s(%x): invalid interrupt Vector (%08x) found, interrupt ignored...\n",
495 			     __FUNCTION__, intNum, my_rdl(intNum * 4));
496 			DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
497 					  M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
498 					  M.x86.R_DX);
499 			//HALT_SYS();
500 #endif
501 			handleInt10();
502 			int_handled = 1;
503 		}
504 		break;
505 	case 0x16:
506 		// Keyboard BIOS Interrupt
507 		handleInt16();
508 		int_handled = 1;
509 		break;
510 	case 0x1a:
511 		// PCI BIOS Interrupt
512 		handleInt1a();
513 		int_handled = 1;
514 		break;
515 	default:
516 		printf("Interrupt %#x (Vector: %x) not implemented\n", intNum,
517 		       my_rdl(intNum * 4));
518 		DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
519 				  M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
520 				  M.x86.R_DX);
521 		int_handled = 1;
522 		HALT_SYS();
523 		break;
524 	}
525 	// if we did not handle the interrupt, jump to the interrupt vector...
526 	if (!int_handled) {
527 		setupInt(intNum);
528 	}
529 }
530 
531 // prepare and execute Interrupt 10 (VGA Interrupt)
532 void
runInt10()533 runInt10()
534 {
535 	// Initialize stack and data segment
536 	M.x86.R_SS = STACK_SEGMENT;
537 	M.x86.R_DS = DATA_SEGMENT;
538 	M.x86.R_SP = STACK_START_OFFSET;
539 
540 	// push a HLT instruction and a pointer to it onto the stack
541 	// any return will pop the pointer and jump to the HLT, thus
542 	// exiting (more or less) cleanly
543 	push_word(0xf4f4);	//F4=HLT
544 	//push_word(M.x86.R_SS);
545 	//push_word(M.x86.R_SP + 2);
546 
547 	// setupInt will push the current CS and IP to the stack to return to it,
548 	// but we want to halt, so set CS:IP to the HLT instruction we just pushed
549 	// to the stack
550 	M.x86.R_CS = M.x86.R_SS;
551 	M.x86.R_IP = M.x86.R_SP;	// + 4;
552 
553 	CHECK_DBG(DEBUG_TRACE_X86EMU) {
554 		X86EMU_trace_on();
555 	}
556 	CHECK_DBG(DEBUG_JMP) {
557 		M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
558 		M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
559 		M.x86.debug |= DEBUG_TRACECALL_F;
560 		M.x86.debug |= DEBUG_TRACECALL_REGS_F;
561 	}
562 	setupInt(0x10);
563 	DEBUG_PRINTF_INTR("%s(): starting execution of INT10...\n",
564 			  __FUNCTION__);
565 	X86EMU_exec();
566 	DEBUG_PRINTF_INTR("%s(): execution finished\n", __FUNCTION__);
567 }
568 
569 // prepare and execute Interrupt 13 (Disk Interrupt)
570 void
runInt13(void)571 runInt13(void)
572 {
573 	// Initialize stack and data segment
574 	M.x86.R_SS = STACK_SEGMENT;
575 	M.x86.R_DS = DATA_SEGMENT;
576 	M.x86.R_SP = STACK_START_OFFSET;
577 
578 	// push a HLT instruction and a pointer to it onto the stack
579 	// any return will pop the pointer and jump to the HLT, thus
580 	// exiting (more or less) cleanly
581 	push_word(0xf4f4);	//F4=HLT
582 	//push_word(M.x86.R_SS);
583 	//push_word(M.x86.R_SP + 2);
584 
585 	// setupInt will push the current CS and IP to the stack to return to it,
586 	// but we want to halt, so set CS:IP to the HLT instruction we just pushed
587 	// to the stack
588 	M.x86.R_CS = M.x86.R_SS;
589 	M.x86.R_IP = M.x86.R_SP;
590 
591 	CHECK_DBG(DEBUG_TRACE_X86EMU) {
592 		X86EMU_trace_on();
593 	}
594 	CHECK_DBG(DEBUG_JMP) {
595 		M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
596 		M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
597 		M.x86.debug |= DEBUG_TRACECALL_F;
598 		M.x86.debug |= DEBUG_TRACECALL_REGS_F;
599 	}
600 
601 	setupInt(0x13);
602 	DEBUG_PRINTF_INTR("%s(): starting execution of INT13...\n",
603 			  __FUNCTION__);
604 	X86EMU_exec();
605 	DEBUG_PRINTF_INTR("%s(): execution finished\n", __FUNCTION__);
606 }
607