Annotation of qemu/roms/SLOF/clients/net-snk/app/biosemu/interrupt.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.