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