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