VirtualBox

Changeset 78394 in vbox for trunk/src/VBox


Ignore:
Timestamp:
May 6, 2019 3:14:09 PM (6 years ago)
Author:
vboxsync
Message:

DevATA: Minor cleanup, better compatibility with old ATA devices, streamline task register reads when busy (see bugref:5869).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevATA.cpp

    r77580 r78394  
    17401740    if (RT_SUCCESS(rc))
    17411741    {
    1742         ataR3SetSector(s, iLBA + cSectors);
     1742        /* When READ SECTORS etc. finishes, the address in the task
     1743         * file register points at the last sector read, not at the next
     1744         * sector that would be read. This ensures the registers always
     1745         * contain a valid sector address.
     1746         */
    17431747        if (s->cbElementaryTransfer == s->cbTotalTransfer)
     1748        {
    17441749            s->iSourceSink = ATAFN_SS_NULL;
     1750            ataR3SetSector(s, iLBA + cSectors - 1);
     1751        }
     1752        else
     1753            ataR3SetSector(s, iLBA + cSectors);
     1754        s->uATARegNSector -= cSectors;
    17451755        ataR3CmdOK(s, ATA_STAT_SEEK);
    17461756    }
     
    39603970    ataR3LockEnter(pCtl);
    39613971    ataR3CmdOK(s, ATA_STAT_SEEK);
    3962     ataHCSetIRQ(s);
    39633972    return false;
    39643973}
     
    39743983    ataR3LockEnter(pCtl);
    39753984    ataR3CmdOK(s, ATA_STAT_SEEK);
    3976     ataHCSetIRQ(s);
    39773985    return false;
    39783986}
     
    43574365 *     Device 1 responds to writes (except commands are not executed) but does
    43584366 *     not respond to reads. If Device 1 selected, normal behavior applies.
    4359  *     See ATAPI-6 clause 9.16.2 and Table 15 in clause 7.1.
     4367 *     See ATA-6 clause 9.16.2 and Table 15 in clause 7.1.
     4368 *
     4369 * Note: Task file register writes with BSY=1 and/or DRQ=1 are problematic.
     4370 * Newer ATA/ATAPI specifications define that writes with BSY=0 and DRQ=1
     4371 * are a "host malfunction" and ignored (see e.g. Table 15 in clause 7.1 of
     4372 * the ATA-6 specification).
     4373 *  However, the results of writes with BSY=1 are "indeterminate", with the
     4374 * sole exception of writing the DEVICE RESET command (if supported). We
     4375 * choose to ignore the writes when BSY=1.
     4376 *
     4377 * Note: Ignoring writes to the Device/Head register when BSY=1 or DRQ=1 has the
     4378 * convenient side effect that the non-selected device (if any) is guaranteed
     4379 * to have BSY=0 and DRQ=0.
    43604380 */
    43614381
     
    43674387    {
    43684388        case 0:
     4389            Assert(0);  /* This handler is not used for the Data register! */
    43694390            break;
    43704391        case 1: /* feature register */
     
    44104431            break;
    44114432        case 6: /* drive/head */
     4433            if (pCtl->aIfs[pCtl->iAIOIf].uATARegStatus & ATA_STAT_DRQ)
     4434            {
     4435                Log(("DRQ=1, register write ignored!\n"));
     4436                break;
     4437            }
    44124438            pCtl->aIfs[0].uATARegSelect = (val & ~0x10) | 0xa0;
    44134439            pCtl->aIfs[1].uATARegSelect = (val | 0x10) | 0xa0;
     
    44664492
    44674493
     4494/*
     4495 * Note: When the BSY bit is set, generally no other bits in the Status register
     4496 * are valid and no other registers can be read. Newer ATA specs explicitly define
     4497 * (e.g. clause 7.1, table 16 in ATA-6) that if any command block register is
     4498 * read with BSY=1, the Status register contents are always returned instead.
     4499 */
    44684500static int ataIOPortReadU8(PATACONTROLLER pCtl, uint32_t addr, uint32_t *pu32)
    44694501{
     
    45024534        }
    45034535    }
     4536
     4537    /*
     4538     * If the device is busy, the Status register is always read, but when reading the
     4539     * Status register proper, special semantics apply. See status register handling
     4540     * with interrupt clearing and yields below.
     4541     * NB: This can't happen for non-present devices as those never become busy.
     4542     */
     4543    if (RT_UNLIKELY(s->uATARegStatus & ATA_STAT_BUSY))
     4544    {
     4545        Assert(s->pDrvMedia);
     4546        if ((addr & 7) != 7)
     4547        {
     4548            *pu32 = s->uATARegStatus;
     4549            Log2(("%s: LUN#%d addr=%#x val=%#04x (BSY=1, returning status!)\n", __FUNCTION__, s->iLUN, addr, *pu32));
     4550            return VINF_SUCCESS;
     4551        }
     4552    }
     4553
    45044554    fHOB = !!(s->uATARegDevCtl & (1 << 7));
    45054555    switch (addr & 7)
    45064556    {
     4557        default:/* only to satisfy certain compilers, all cases are already handled */
    45074558        case 0: /* data register */
     4559            Assert(0);  /* This handler is not used for the Data register! */
    45084560            val = 0xff;
    45094561            break;
     
    45524604                val = s->uATARegSelect;
    45534605            break;
    4554         default:
    45554606        case 7: /* primary status */
    45564607        {
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