VirtualBox

Ignore:
Timestamp:
Apr 20, 2016 5:42:15 PM (9 years ago)
Author:
vboxsync
Message:

BIOS: Added 286 compatible INT 15h/87h implementation.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/PC/BIOS/system.c

    r59495 r60610  
    6565#pragma aux read_ss = "mov ax, ss" modify exact [ax] nomemory;
    6666
    67 void pm_stack_save(uint16_t cx, uint16_t es, uint16_t si);
     67#if VBOX_BIOS_CPU >= 80386
     68
     69/* The 386+ code uses CR0 to switch to/from protected mode.
     70 * Quite straightforward.
     71 */
     72
     73void pm_stack_save(uint16_t cx, uint16_t es, uint16_t si, uint16_t frame);
    6874#pragma aux pm_stack_save =     \
    6975    ".386"                      \
     
    7480    "mov    ds:[467h], sp"      \
    7581    "mov    ds:[469h], ss"      \
    76     parm [cx] [es] [si] modify nomemory;
     82    parm [cx] [es] [si] [ax] modify nomemory;
    7783
    7884/* Uses position independent code... because it was too hard to figure
     
    103109    modify nomemory;
    104110
    105 void pm_copy(void);
    106 #pragma aux pm_copy =               \
    107     "xor    si, si"                 \
    108     "xor    di, di"                 \
    109     "cld"                           \
    110     "rep    movsw"                  \
    111     modify nomemory;
    112 
    113111/* Restore segment limits to real mode compatible values and
    114112 * return to real mode.
     
    146144    "pop    eax"                \
    147145    "pop    ds"                 \
     146    modify nomemory;
     147
     148#elif VBOX_BIOS_CPU >= 80286
     149
     150/* The 286 code uses LMSW to switch to protected mode but it has to reset
     151 * the CPU to get back to real mode. Ugly! See return_blkmove in orgs.asm
     152 * for the other matching half.
     153 */
     154void pm_stack_save(uint16_t cx, uint16_t es, uint16_t si, uint16_t frame);
     155#pragma aux pm_stack_save =     \
     156    "xor    ax, ax"             \
     157    "mov    ds, ax"             \
     158    "mov    ds:[467h], bx"      \
     159    "mov    ds:[469h], ss"      \
     160    parm [cx] [es] [si] [bx] modify nomemory;
     161
     162/* Uses position independent code... because it was too hard to figure
     163 * out how to code the far call in inline assembler.
     164 * NB: Trashes MSW bits but the CPU will be reset anyway.
     165 */
     166void pm_enter(void);
     167#pragma aux pm_enter =              \
     168    ".286p"                         \
     169    "call   pentry"                 \
     170    "pentry:"                       \
     171    "pop    di"                     \
     172    "add    di, 18h"                \
     173    "push   20h"                    \
     174    "push   di"                     \
     175    "lgdt   fword ptr es:[si+8]"    \
     176    "lidt   fword ptr cs:pmode_IDT" \
     177    "or     al, 1"                  \
     178    "lmsw   ax"                     \
     179    "retf"                          \
     180    "pm_pm:"                        \
     181    "mov    ax, 28h"                \
     182    "mov    ss, ax"                 \
     183    "mov    ax, 10h"                \
     184    "mov    ds, ax"                 \
     185    "mov    ax, 18h"                \
     186    "mov    es, ax"                 \
     187    modify nomemory;
     188
     189/* Set up shutdown status and reset the CPU. The POST code
     190 * will regain control. Port 80h is written with status.
     191 * Code 9 is written to CMOS shutdown status byte (0Fh).
     192 * CPU is triple faulted.                                                    .
     193 */
     194void pm_exit(void);
     195#pragma aux pm_exit =               \
     196    "xor    ax, ax"                 \
     197    "out    80h, al"                \
     198    "mov    al, 0Fh"                \
     199    "out    70h, al"                \
     200    "mov    al, 09h"                \
     201    "out    71h, al"                \
     202    ".286p"                         \
     203    "lidt   fword ptr cs:pmode_IDT" \
     204    "int    3"                      \
     205    modify nomemory;
     206
     207/* Dummy. Actually done in return_blkmove. */
     208void pm_stack_restore(void);
     209#pragma aux pm_stack_restore =  \
     210    "rm_return:"                \
     211    modify nomemory;
     212
     213#endif
     214
     215void pm_copy(void);
     216#pragma aux pm_copy =               \
     217    "xor    si, si"                 \
     218    "xor    di, di"                 \
     219    "cld"                           \
     220    "rep    movsw"                  \
    148221    modify nomemory;
    149222
     
    283356void BIOSCALL int15_function(sys_regs_t r)
    284357{
    285     bx_bool     prev_a20_enable;
    286     uint16_t    base15_00;
    287     uint8_t     base23_16;
    288     uint16_t    ss;
    289358    uint16_t    bRegister;
    290359    uint8_t     irqDisable;
     
    392461        }
    393462
    394     case 0x87:
    395 #if BX_CPU < 3
    396         SET_AH(UNSUPPORTED_FUNCTION);
    397         SET_CF();
    398 #endif
    399         // +++ should probably have descriptor checks
    400         // +++ should have exception handlers
    401 
    402         // turn off interrupts
    403         int_disable();    //@todo: aren't they disabled already?
    404 
    405         prev_a20_enable = set_enable_a20(1); // enable A20 line
    406 
    407         // 128K max of transfer on 386+ ???
    408         // source == destination ???
    409 
    410         // ES:SI points to descriptor table
    411         // offset   use     initially  comments
    412         // ==============================================
    413         // 00..07   Unused  zeros      Null descriptor
    414         // 08..0f   GDT     zeros      filled in by BIOS
    415         // 10..17   source  ssssssss   source of data
    416         // 18..1f   dest    dddddddd   destination of data
    417         // 20..27   CS      zeros      filled in by BIOS
    418         // 28..2f   SS      zeros      filled in by BIOS
    419 
    420         //es:si
    421         //eeee0
    422         //0ssss
    423         //-----
    424 
    425         // check for access rights of source & dest here
    426 
    427         // Initialize GDT descriptor
    428         base15_00 = (ES << 4) + SI;
    429         base23_16 = ES >> 12;
    430         if (base15_00 < (ES<<4))
    431             base23_16++;
    432         write_word(ES, SI+0x08+0, 47);       // limit 15:00 = 6 * 8bytes/descriptor
    433         write_word(ES, SI+0x08+2, base15_00);// base 15:00
    434         write_byte(ES, SI+0x08+4, base23_16);// base 23:16
    435         write_byte(ES, SI+0x08+5, 0x93);     // access
    436         write_word(ES, SI+0x08+6, 0x0000);   // base 31:24/reserved/limit 19:16
    437 
    438         // Initialize CS descriptor
    439         write_word(ES, SI+0x20+0, 0xffff);// limit 15:00 = normal 64K limit
    440         write_word(ES, SI+0x20+2, 0x0000);// base 15:00
    441         write_byte(ES, SI+0x20+4, 0x000f);// base 23:16
    442         write_byte(ES, SI+0x20+5, 0x9b);  // access
    443         write_word(ES, SI+0x20+6, 0x0000);// base 31:24/reserved/limit 19:16
    444 
    445         // Initialize SS descriptor
    446         ss = read_ss();
    447         base15_00 = ss << 4;
    448         base23_16 = ss >> 12;
    449         write_word(ES, SI+0x28+0, 0xffff);   // limit 15:00 = normal 64K limit
    450         write_word(ES, SI+0x28+2, base15_00);// base 15:00
    451         write_byte(ES, SI+0x28+4, base23_16);// base 23:16
    452         write_byte(ES, SI+0x28+5, 0x93);     // access
    453         write_word(ES, SI+0x28+6, 0x0000);   // base 31:24/reserved/limit 19:16
    454 
    455         pm_stack_save(CX, ES, SI);
    456         pm_enter();
    457         pm_copy();
    458         pm_exit();
    459         pm_stack_restore();
    460 
    461         set_enable_a20(prev_a20_enable);
    462 
    463         // turn interrupts back on
    464         int_enable();
    465 
    466         SET_AH(0);
    467         CLEAR_CF();
    468         break;
    469 
    470463    case 0x88:
    471464        // Get the amount of extended memory (above 1M)
     
    830823    }
    831824}
     825
     826#if VBOX_BIOS_CPU >= 80286
     827
     828#undef  FLAGS
     829#define FLAGS   r.ra.flags.u.r16.flags
     830
     831/* Function 0x87 handled separately due to specific stack layout requirements. */
     832void BIOSCALL int15_blkmove(disk_regs_t r)
     833{
     834    bx_bool     prev_a20_enable;
     835    uint16_t    base15_00;
     836    uint8_t     base23_16;
     837    uint16_t    ss;
     838
     839    // +++ should probably have descriptor checks
     840    // +++ should have exception handlers
     841
     842    // turn off interrupts
     843    int_disable();    //@todo: aren't they disabled already?
     844
     845    prev_a20_enable = set_enable_a20(1); // enable A20 line
     846
     847    // 128K max of transfer on 386+ ???
     848    // source == destination ???
     849
     850    // ES:SI points to descriptor table
     851    // offset   use     initially  comments
     852    // ==============================================
     853    // 00..07   Unused  zeros      Null descriptor
     854    // 08..0f   GDT     zeros      filled in by BIOS
     855    // 10..17   source  ssssssss   source of data
     856    // 18..1f   dest    dddddddd   destination of data
     857    // 20..27   CS      zeros      filled in by BIOS
     858    // 28..2f   SS      zeros      filled in by BIOS
     859
     860    //es:si
     861    //eeee0
     862    //0ssss
     863    //-----
     864
     865    // check for access rights of source & dest here
     866
     867    // Initialize GDT descriptor
     868    base15_00 = (ES << 4) + SI;
     869    base23_16 = ES >> 12;
     870    if (base15_00 < (ES<<4))
     871        base23_16++;
     872    write_word(ES, SI+0x08+0, 47);       // limit 15:00 = 6 * 8bytes/descriptor
     873    write_word(ES, SI+0x08+2, base15_00);// base 15:00
     874    write_byte(ES, SI+0x08+4, base23_16);// base 23:16
     875    write_byte(ES, SI+0x08+5, 0x93);     // access
     876    write_word(ES, SI+0x08+6, 0x0000);   // base 31:24/reserved/limit 19:16
     877
     878    // Initialize CS descriptor
     879    write_word(ES, SI+0x20+0, 0xffff);// limit 15:00 = normal 64K limit
     880    write_word(ES, SI+0x20+2, 0x0000);// base 15:00
     881    write_byte(ES, SI+0x20+4, 0x000f);// base 23:16
     882    write_byte(ES, SI+0x20+5, 0x9b);  // access
     883    write_word(ES, SI+0x20+6, 0x0000);// base 31:24/reserved/limit 19:16
     884
     885    // Initialize SS descriptor
     886    ss = read_ss();
     887    base15_00 = ss << 4;
     888    base23_16 = ss >> 12;
     889    write_word(ES, SI+0x28+0, 0xffff);   // limit 15:00 = normal 64K limit
     890    write_word(ES, SI+0x28+2, base15_00);// base 15:00
     891    write_byte(ES, SI+0x28+4, base23_16);// base 23:16
     892    write_byte(ES, SI+0x28+5, 0x93);     // access
     893    write_word(ES, SI+0x28+6, 0x0000);   // base 31:24/reserved/limit 19:16
     894
     895    pm_stack_save(CX, ES, SI, (uint16_t)(void __near *)&r);
     896    pm_enter();
     897    pm_copy();
     898    pm_exit();
     899    pm_stack_restore();
     900
     901    set_enable_a20(prev_a20_enable);
     902
     903    // turn interrupts back on
     904    int_enable();
     905
     906    SET_AH(0);
     907    CLEAR_CF();
     908}
     909#endif
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette