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