VirtualBox

Ignore:
Timestamp:
Apr 5, 2024 2:39:02 PM (10 months ago)
Author:
vboxsync
Message:

BIOS: Run INITIALIZE DRIVE PARAMETERS after resetting drives in the unusual case where logical geometry does not match physical.

File:
1 edited

Legend:

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

    r104067 r104194  
    131131
    132132// ---------------------------------------------------------------------------
     133// ATA/ATAPI driver : initialize device parameters (CHS geometry)
     134// ---------------------------------------------------------------------------
     135uint16_t ata_set_params(bio_dsk_t __far *bios_dsk, uint8_t device)
     136{
     137    uint16_t        iobase1, iobase2;
     138    uint8_t         lheads, lsectors;
     139    uint8_t         pheads, psectors;
     140    uint8_t         status;
     141
     142    psectors = bios_dsk->devices[device].pchs.spt;
     143    pheads   = bios_dsk->devices[device].pchs.heads - 1;
     144
     145    lsectors = bios_dsk->devices[device].lchs.spt;
     146    lheads   = bios_dsk->devices[device].lchs.heads - 1;
     147
     148    if ((psectors == lsectors) && (pheads == lheads)) {
     149        // If LCHS == PCHS, we can save ourselves the bother
     150        // because INITIALIZE DEVICE PARAMETERS won't change anything.
     151        return 0;
     152    }
     153
     154    iobase1 = bios_dsk->channels[device / 2].iobase1;
     155    iobase2 = bios_dsk->channels[device / 2].iobase2;
     156
     157    status = inb(iobase1 + ATA_CB_STAT);
     158    if (status & ATA_CB_STAT_BSY)
     159    {
     160        BX_DEBUG_ATA("%s: disk busy\n", __func__);
     161        return 1;
     162    }
     163
     164    outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
     165    outb(iobase1 + ATA_CB_FR, 0x00);
     166    outb(iobase1 + ATA_CB_SC, lsectors);
     167    outb(iobase1 + ATA_CB_DH, ((device & 1) ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | lheads );
     168    outb(iobase1 + ATA_CB_CMD, ATA_CMD_INITIALIZE_DEVICE_PARAMETERS);
     169
     170    int_enable(); // enable higher priority interrupts
     171
     172    while (1) {
     173        status = inb(iobase1 + ATA_CB_STAT);
     174        if ( !(status & ATA_CB_STAT_BSY) )
     175            break;
     176    }
     177
     178    // Enable interrupts
     179    outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
     180    return 0;
     181}
     182
     183
     184// ---------------------------------------------------------------------------
    133185// ATA/ATAPI driver : software reset
    134186// ---------------------------------------------------------------------------
    135187// ATA-3
    136188// 8.2.1 Software reset - Device 0
     189// NB: If two hard disks are installed on a single channel, *both* are reset
     190//     by setting the SRST bit.
    137191
    138192void   ata_reset(uint16_t device)
    139193{
    140194    uint16_t        iobase1, iobase2;
    141     uint8_t         channel, slave, sn, sc;
     195    uint8_t         channel, sn, sc;
    142196    uint16_t        max;
    143197    uint16_t        pdelay;
     
    146200    bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
    147201    channel = device / 2;
    148     slave = device % 2;
     202    device  = channel * 2;
    149203
    150204    iobase1 = bios_dsk->channels[channel].iobase1;
     
    179233    }
    180234
    181     if (bios_dsk->devices[device].type != DSK_TYPE_NONE) {
    182         // 8.2.1 (g) -- check for sc==sn==0x01
    183         // select device
    184         outb(iobase1+ATA_CB_DH, slave?ATA_CB_DH_DEV1:ATA_CB_DH_DEV0);
    185         sc = inb(iobase1+ATA_CB_SC);
    186         sn = inb(iobase1+ATA_CB_SN);
    187 
    188         if ( (sc==0x01) && (sn==0x01) ) {
    189             // 8.2.1 (i) -- wait for DRDY
    190             max = 0x10; /* Speed up for virtual drives. Disks are immediately ready, CDs never */
    191             while(--max>0) {
    192                 uint8_t status = inb(iobase1+ATA_CB_STAT);
    193                 if ((status & ATA_CB_STAT_RDY) != 0)
    194                     break;
     235    for ( ; (device & ~1) == (channel * 2); ++device) {
     236        if (bios_dsk->devices[device].type == DSK_TYPE_ATA) {
     237            // 8.2.1 (g) -- check for sc==sn==0x01
     238            // select device
     239            outb(iobase1+ATA_CB_DH, (device & 1) ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
     240            sc = inb(iobase1+ATA_CB_SC);
     241            sn = inb(iobase1+ATA_CB_SN);
     242
     243            if ( (sc==0x01) && (sn==0x01) ) {
     244                // 8.2.1 (i) -- wait for DRDY
     245                max = 0x10; /* Speed up for virtual drives. Disks are immediately ready, CDs never */
     246                while(--max>0) {
     247                    uint8_t status = inb(iobase1+ATA_CB_STAT);
     248                    if ((status & ATA_CB_STAT_RDY) != 0)
     249                        break;
     250                }
     251                ata_set_params(bios_dsk, device);
    195252            }
    196253        }
     
    673730                }
    674731            }
     732
     733            // Set the right CHS geometry if needed
     734            ata_set_params(bios_dsk, device);
    675735
    676736            // fill hdidmap
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