VirtualBox

Changeset 104194 in vbox for trunk


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.

Location:
trunk/src/VBox/Devices/PC/BIOS
Files:
4 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
  • trunk/src/VBox/Devices/PC/BIOS/disk.c

    r98103 r104194  
    314314
    315315    case 0x00: /* disk controller reset */
    316 #ifdef VBOX_WITH_SCSI
    317         /* SCSI controller does not need a reset. */
    318         if (!VBOX_IS_SCSI_DEVICE(device))
    319 #endif
    320         ata_reset (device);
     316        /* For ATA drives only. NB: This resets both drives on a channel. */
     317        if (VBOX_IS_ATA_DEVICE(device))
     318            ata_reset(device);
    321319        goto int13_success;
    322320        break;
  • trunk/src/VBox/Devices/PC/BIOS/ebda.h

    r104142 r104194  
    7777#define BX_USE_ATADRV           1
    7878#define BX_ELTORITO_BOOT        1
     79
     80#define VBOX_IS_ATA_DEVICE(device_id) (device_id < BX_MAX_ATA_DEVICES)
    7981
    8082#ifdef VBOX_WITH_SCSI
  • trunk/src/VBox/Devices/PC/BIOS/notes.txt

    r100483 r104194  
    7676  at least in protected mode, assumes that those vectors must point into
    7777  the F000h segment.
     78
     79- NetWare 2.0a INSTALL and VREPAIR utilities run in real mode but have their
     80  own ATA disk driver. Like NetWare itself, the utilities obtain drive
     81  geometry from the FDPT, but unlike NetWare, they assume that the drive
     82  already had the correct geometry set during POST and that INT 13h/00h
     83  will keep it in place by executing INITIALIZE DRIVE PARAMETERS.
     84  NB: The BIOS itself always uses LBA and thus does not depend on the
     85  drive's current CHS geometry at all.
    7886
    7987- Windows NT (including XP) uses INT 13h/08h to obtain the DPT for each floppy
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