Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / clients / net-snk / app / biosemu / interrupt.c
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
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
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
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
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
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
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
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
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 }