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