VirtualBox

Changeset 100443 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jul 8, 2023 2:14:42 PM (17 months ago)
Author:
vboxsync
Message:

BIOS: Recognize common hard disk types and set the corresponding CMOS drive type. In the BIOS, point such drive types at the FDPT in ROM.

Location:
trunk/src/VBox/Devices/PC
Files:
2 edited

Legend:

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

    r98103 r100443  
    659659                sum = -sum;
    660660                fdpt->csum = sum;
     661
     662                /* Read the drive type from the CMOS. If it is one of the old
     663                 * IBM compatible drive types (rather than Type 47 or so), point
     664                 * INT 41h/46h at the drive table in ROM.
     665                 * This is required for some old guests which look at INT 41h/46h,
     666                 * but either insist that it point to a high segment (NetWare 2.x)
     667                 * or wipe out all RAM (286 XENIX 2.1.3/2.2.1).
     668                 */
     669                i   = inb_cmos(0x12);
     670                i >>= ((1 - device) * 4);
     671                i  &= 0x0f;
     672                if (i == 0xf)
     673                    i = inb_cmos(0x19 + device);
     674
     675                if (i <= 23) {  // Should be in sync with DevPcBios.cpp
     676                    fdpt = MK_FP(0xF000, 0xE401);
     677                    fdpt += i - 1;
     678                    *int_vec = fdpt;
     679                }
    661680            }
    662681
  • trunk/src/VBox/Devices/PC/DevPcBios.cpp

    r98103 r100443  
    595595
    596596
     597/* Several common PC/AT BIOS drive types. Corresponds to IBM BIOS drive tables. */
     598PDMMEDIAGEOMETRY aGeomPCAT[] = {
     599    /*  cyls    heads   sectors */
     600    {     0,     0,      0 },   /* Type  0 is not used */
     601    {   306,     4,     17 },   /* Type  1,  10MB */
     602    {   615,     4,     17 },   /* Type  2,  20MB */
     603    {   615,     6,     17 },   /* Type  3,  30MB */
     604    {   940,     8,     17 },   /* Type  4,  62MB */
     605    {   940,     6,     17 },   /* Type  5,  47MB */
     606    {   615,     4,     17 },   /* Type  6,  20MB (different WPCOMP from Type 2) */
     607    {   462,     8,     17 },   /* Type  7,  30MB */
     608    {   733,     5,     17 },   /* Type  8,  30MB */
     609    {   900,    15,     17 },   /* Type  9, 117MB */
     610
     611    {   820,     3,     17 },   /* Type 10,  21MB */
     612    {   855,     5,     17 },   /* Type 11,  37MB */
     613    {   855,     7,     17 },   /* Type 12,  52MB */
     614    {   306,     8,     17 },   /* Type 13,  21MB */
     615    {   733,     7,     17 },   /* Type 14,  45MB */
     616    {     0,     0,      0 },   /* Type 15 is not used */
     617    {   612,     4,     17 },   /* Type 16,  21MB */
     618    {   977,     5,     17 },   /* Type 17,  43MB */
     619    {   977,     7,     17 },   /* Type 18,  60MB */
     620    {  1024,     7,     17 },   /* Type 19,  62MB */
     621
     622    {   733,     5,     17 },   /* Type 20,  32MB */
     623    {   733,     7,     17 },   /* Type 21,  45MB */
     624    {   733,     5,     17 },   /* Type 22,  32MB */
     625    {   306,     4,     17 },   /* Type 23,  10MB */
     626};
     627
     628/**
     629 * Attempts to initialize CMOS data for a hard disk matching one of
     630 * the PC/AT BIOS types. Only applicable to the first two drives.
     631 * Returns true if drive is one of the few recognized types.
     632 */
     633static bool pcbiosCmosTryPCATHardDisk(PPDMDEVINS pDevIns, int drive, PCPDMMEDIAGEOMETRY pLCHSGeometry)
     634{
     635    int     type;
     636    int     typeLow;
     637    bool    fCompatGeom = false;
     638
     639    Assert((drive == 0) || (drive == 1));
     640
     641    /* See if drive geometry is one of the ancient PC/AT BIOS types. */
     642    for (type = 0; type < RT_ELEMENTS(aGeomPCAT); ++type) {
     643        if ( (aGeomPCAT[type].cCylinders == pLCHSGeometry->cCylinders)
     644          && (aGeomPCAT[type].cHeads     == pLCHSGeometry->cHeads    )
     645          && (aGeomPCAT[type].cSectors   == pLCHSGeometry->cSectors  )) {
     646            LogRel(("PcBios: Recognized ATA hard disk %d as PC/AT BIOS type %d\n", drive, type));
     647            fCompatGeom = true;
     648            break;
     649        }
     650    }
     651
     652    if (fCompatGeom) {
     653        uint32_t    u32;
     654
     655        /* For types below 15, the type is in CMOS byte 0x12.
     656         * NB: The type for drive 0 is in the high nibble, drive 1
     657         * is in the low nibble.
     658         * For drive types above 15, CMOS byte 0x12 is set to 15
     659         * and actual drive type is in byte 0x19 (drive 0) or
     660         * byte 0x1a (drive 1).
     661         */
     662        typeLow = type < 15 ? type : 15;
     663
     664        /* Always update CMOS byte 0x12. */
     665        u32 = pcbiosCmosRead(pDevIns, 0x12);
     666        u32 &= 0x0f << (4 * drive);
     667        u32 |= typeLow << (4 - 4 * drive);
     668        pcbiosCmosWrite(pDevIns, 0x12, u32);
     669
     670        /* For higher drive types, also update CMOS byte 0x19/0x1a. */
     671        if (type > 15) {
     672            u32 = type;
     673            pcbiosCmosWrite(pDevIns, 0x19 + drive, u32);
     674        }
     675    }
     676
     677    return fCompatGeom;
     678}
     679
     680
    597681/**
    598682 * Initializes the CMOS data for one harddisk.
     
    601685{
    602686    Log2(("%s: offInfo=%#x: LCHS=%d/%d/%d\n", __FUNCTION__, offInfo, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
    603     if (offType)
     687    if (offType) {
     688        uint32_t    u32;
     689        int         drive;
     690
     691        Assert(offType == 0x1a || offType == 0x19);
     692        drive = offType == 0x19 ? 0 : 1;
     693
     694        /* Update CMOS byte 12h. It will always be set to type 0fh for this disk. */
     695        u32 = pcbiosCmosRead(pDevIns, 0x12);
     696        u32 &= 0x0f << (4 * drive);
     697        u32 |= 0x0f << (4 - 4 * drive);
     698        pcbiosCmosWrite(pDevIns, 0x12, u32);
     699
     700        /* Now write the extended drive type at offset 19h or 1Ah. */
    604701        pcbiosCmosWrite(pDevIns, offType, 47);
     702    }
    605703    /* Cylinders low */
    606704    pcbiosCmosWrite(pDevIns, offInfo + 0, RT_MIN(pLCHSGeometry->cCylinders, 1024) & 0xff);
     
    9511049                        break;
    9521050                }
    953                 pcbiosCmosInitHardDisk(pDevIns, offType, offInfo,
    954                                        &LCHSGeometry);
     1051                pcbiosCmosInitHardDisk(pDevIns, offType, offInfo, &LCHSGeometry);
     1052                if (i < 2)
     1053                    pcbiosCmosTryPCATHardDisk(pDevIns, i, &LCHSGeometry);
    9551054            }
    9561055            LogRel(("PcBios: ATA LUN#%d LCHS=%u/%u/%u\n", i, LCHSGeometry.cCylinders, LCHSGeometry.cHeads, LCHSGeometry.cSectors));
    9571056        }
    9581057    }
    959 
    960     /* 0Fh means extended and points to 19h, 1Ah */
    961     u32 = (apHDs[0] ? 0xf0 : 0) | (apHDs[1] ? 0x0f : 0);
    962     pcbiosCmosWrite(pDevIns, 0x12, u32);
    9631058
    9641059    /*
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