VirtualBox

Changeset 92345 in vbox


Ignore:
Timestamp:
Nov 11, 2021 9:07:02 AM (3 years ago)
Author:
vboxsync
Message:

DevATA: Made INITIALIZE DEVICE PARAMETERS affect CHS translation, like a real IDE drive would (see bugref:5869).

File:
1 edited

Legend:

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

    r91920 r92345  
    207207    /** Currently configured number of sectors in a multi-sector transfer. */
    208208    uint8_t                             cMultSectors;
    209     /** PCHS disk geometry. */
     209    /** Physical CHS disk geometry (static). */
    210210    PDMMEDIAGEOMETRY                    PCHSGeometry;
     211    /** Translated CHS disk geometry (variable). */
     212    PDMMEDIAGEOMETRY                    XCHSGeometry;
    211213    /** Total number of sectors on this disk. */
    212214    uint64_t                            cTotalSectors;
     
    380382
    381383    /** Padding the structure to a multiple of 4096 for better I/O buffer alignment. */
    382     uint8_t                             abAlignment4[7 + 3544];
     384    uint8_t                             abAlignment4[7 + 3528];
    383385} ATADEVSTATE;
    384386AssertCompileMemberAlignment(ATADEVSTATE, cTotalSectors, 8);
     
    13591361    Assert(uErrorCode);
    13601362    s->uATARegError = uErrorCode;
    1361     ataSetStatusValue(pCtl, s, ATA_STAT_READY | ATA_STAT_ERR);
     1363    ataSetStatusValue(pCtl, s, ATA_STAT_READY | ATA_STAT_SEEK | ATA_STAT_ERR);
    13621364    s->cbTotalTransfer = 0;
    13631365    s->cbElementaryTransfer = 0;
     
    14161418    p[52] = RT_H2LE_U16(240); /* DMA transfer cycle */
    14171419    p[53] = RT_H2LE_U16(1 | 1 << 1 | 1 << 2); /* words 54-58,64-70,88 valid */
    1418     p[54] = RT_H2LE_U16(RT_MIN(s->PCHSGeometry.cCylinders, 16383));
    1419     p[55] = RT_H2LE_U16(s->PCHSGeometry.cHeads);
    1420     p[56] = RT_H2LE_U16(s->PCHSGeometry.cSectors);
    1421     p[57] = RT_H2LE_U16(  RT_MIN(s->PCHSGeometry.cCylinders, 16383)
    1422                         * s->PCHSGeometry.cHeads
    1423                         * s->PCHSGeometry.cSectors);
    1424     p[58] = RT_H2LE_U16(  RT_MIN(s->PCHSGeometry.cCylinders, 16383)
    1425                         * s->PCHSGeometry.cHeads
    1426                         * s->PCHSGeometry.cSectors >> 16);
     1420    p[54] = RT_H2LE_U16(RT_MIN(s->XCHSGeometry.cCylinders, 16383));
     1421    p[55] = RT_H2LE_U16(s->XCHSGeometry.cHeads);
     1422    p[56] = RT_H2LE_U16(s->XCHSGeometry.cSectors);
     1423    p[57] = RT_H2LE_U16(  RT_MIN(s->XCHSGeometry.cCylinders, 16383)
     1424                        * s->XCHSGeometry.cHeads
     1425                        * s->XCHSGeometry.cSectors);
     1426    p[58] = RT_H2LE_U16(  RT_MIN(s->XCHSGeometry.cCylinders, 16383)
     1427                        * s->XCHSGeometry.cHeads
     1428                        * s->XCHSGeometry.cSectors >> 16);
    14271429    if (s->cMultSectors)
    14281430        p[59] = RT_H2LE_U16(0x100 | s->cMultSectors);
     
    16341636    {
    16351637        /* CHS */
    1636         iLBA = (((uint32_t)s->uATARegHCyl << 8) | s->uATARegLCyl) * s->PCHSGeometry.cHeads * s->PCHSGeometry.cSectors
    1637              + (s->uATARegSelect & 0x0f) * s->PCHSGeometry.cSectors
     1638        iLBA = (((uint32_t)s->uATARegHCyl << 8) | s->uATARegLCyl) * s->XCHSGeometry.cHeads * s->XCHSGeometry.cSectors
     1639             + (s->uATARegSelect & 0x0f) * s->XCHSGeometry.cSectors
    16381640             + (s->uATARegSector - 1);
    16391641        LogFlowFunc(("CHS %u/%u/%u -> LBA %llu\n", ((uint32_t)s->uATARegHCyl << 8) | s->uATARegLCyl, s->uATARegSelect & 0x0f, s->uATARegSector, iLBA));
     
    16701672    {
    16711673        /* CHS */
    1672         AssertMsgReturnVoid(s->PCHSGeometry.cHeads && s->PCHSGeometry.cSectors, ("Device geometry not set!\n"));
    1673         cyl = iLBA / (s->PCHSGeometry.cHeads * s->PCHSGeometry.cSectors);
    1674         r = iLBA % (s->PCHSGeometry.cHeads * s->PCHSGeometry.cSectors);
     1674        AssertMsgReturnVoid(s->XCHSGeometry.cHeads && s->XCHSGeometry.cSectors, ("Device geometry not set!\n"));
     1675        cyl = iLBA / (s->XCHSGeometry.cHeads * s->XCHSGeometry.cSectors);
     1676        r = iLBA % (s->XCHSGeometry.cHeads * s->XCHSGeometry.cSectors);
    16751677        s->uATARegHCyl = cyl >> 8;
    16761678        s->uATARegLCyl = cyl;
    1677         s->uATARegSelect = (s->uATARegSelect & 0xf0) | ((r / s->PCHSGeometry.cSectors) & 0x0f);
    1678         s->uATARegSector = (r % s->PCHSGeometry.cSectors) + 1;
     1679        s->uATARegSelect = (s->uATARegSelect & 0xf0) | ((r / s->XCHSGeometry.cSectors) & 0x0f);
     1680        s->uATARegSector = (r % s->XCHSGeometry.cSectors) + 1;
    16791681        LogFlowFunc(("LBA %llu -> CHS %u/%u/%u\n", iLBA, cyl, s->uATARegSelect & 0x0f, s->uATARegSector));
    16801682    }
     
    41364138static void ataR3ResetDevice(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s)
    41374139{
     4140    LogFlowFunc(("\n"));
    41384141    s->cMultSectors = ATA_MAX_MULT_SECTORS;
    41394142    s->cNotifiedMediaChange = 0;
     
    41434146
    41444147    s->uATARegSelect = 0x20;
    4145     ataSetStatusValue(pCtl, s, ATA_STAT_READY);
     4148    ataSetStatusValue(pCtl, s, ATA_STAT_READY | ATA_STAT_SEEK);
    41464149    ataR3SetSignature(s);
    41474150    s->cbTotalTransfer = 0;
     
    41564159    s->uATATransferMode = ATA_MODE_UDMA | 2; /* PIIX3 supports only up to UDMA2 */
    41574160
     4161    s->XCHSGeometry = s->PCHSGeometry;  /* Restore default CHS translation. */
     4162
    41584163    s->uATARegFeature = 0;
    41594164}
     
    41994204    RT_NOREF(pDevR3);
    42004205    LogFlowFunc(("\n"));
    4201     LogRel(("ATA: LUN#%d: INITIALIZE DEVICE PARAMETERS: %u logical sectors, %u heads\n",
    4202             s->iLUN, s->uATARegNSector, (s->uATARegSelect & 0x0f) + 1));
    4203     ataR3LockLeave(pDevIns, pCtl);
    4204     RTThreadSleep(pCtl->msDelayIRQ);
    4205     ataR3LockEnter(pDevIns, pCtl);
    4206     ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
     4206
     4207    /* Technical Note:
     4208     * On ST506 type drives with a separate controller, the INITIALIZE DRIVE PARAMETERS command was
     4209     * required to inform the controller of drive geometry. The controller needed to know the
     4210     * number of heads and sectors per track so that it could correctly advance to the next track
     4211     * or cylinder when executing multi-sector commands. Setting a geometry that didn't match the
     4212     * drive made very little sense because sectors had fixed CHS addresses. It was at best
     4213     * possible to reduce the drive's capacity by limiting the number of heads and/or sectors
     4214     * per track.
     4215     *
     4216     * IDE drives inherently have to know their true geometry, but most of them also support
     4217     * programmable translation that can be set through the INITIALIZE DEVICE PARAMETERS command.
     4218     * In fact most older IDE drives typically weren't operated using their default (native) geometry,
     4219     * and with newer IDE drives that's not even an option.
     4220     *
     4221     * Up to and including ATA-5, the standard defined a CHS to LBA translation (since ATA-6, CHS
     4222     * support is optional):
     4223     *
     4224     * LBA = (((cyl_num * heads_per_cyl) + head_num) * sectors_per_track) + sector_num - 1
     4225     *
     4226     * The INITIALIZE DEVICE PARAMETERS command sets the heads_per_cyl and sectors_per_track
     4227     * values used in the above formula.
     4228     *
     4229     * Drives must obviously support an INITIALIZE DRIVE PARAMETERS command matching the drive's
     4230     * default CHS translation. Everything else is optional.
     4231     *
     4232     * We support any geometry with non-zero sectors per track because there's no reason not to;
     4233     * this behavior is common in many if not most IDE drives.
     4234     */
     4235
     4236    PDMMEDIAGEOMETRY    Geom = { 0 };
     4237
     4238    Geom.cHeads   = (s->uATARegSelect & 0x0f) + 1;  /* Effective range 1-16. */
     4239    Geom.cSectors = s->uATARegNSector;              /* Range 0-255, zero is not valid. */
     4240
     4241    if (Geom.cSectors)
     4242    {
     4243        uint64_t cCylinders = s->cTotalSectors / (Geom.cHeads * Geom.cSectors);
     4244        Geom.cCylinders = RT_MAX(RT_MIN(cCylinders, 16383), 1);
     4245
     4246        s->XCHSGeometry = Geom;
     4247
     4248        ataR3LockLeave(pDevIns, pCtl);
     4249        LogRel(("ATA: LUN#%d: INITIALIZE DEVICE PARAMETERS: %u sectors per track, %u heads\n",
     4250                s->iLUN, s->uATARegNSector, (s->uATARegSelect & 0x0f) + 1));
     4251        RTThreadSleep(pCtl->msDelayIRQ);
     4252        ataR3LockEnter(pDevIns, pCtl);
     4253        ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
     4254    }
     4255    else
     4256    {
     4257        ataR3LockLeave(pDevIns, pCtl);
     4258        LogRel(("ATA: LUN#%d: INITIALIZE DEVICE PARAMETERS error (zero sectors per track)!\n", s->iLUN));
     4259        RTThreadSleep(pCtl->msDelayIRQ);
     4260        ataR3LockEnter(pDevIns, pCtl);
     4261        ataR3CmdError(pCtl, s, ABRT_ERR);
     4262    }
    42074263    return false;
    42084264}
     
    69617017            LogRel(("PIIX3 ATA: LUN#%d: TRIM enabled\n", pIf->iLUN));
    69627018    }
     7019    /* Initialize the translated geometry. */
     7020    pIf->XCHSGeometry = pIf->PCHSGeometry;
    69637021
    69647022    /*
     
    72057263            pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].aIfs[j].fIrqPending);
    72067264            pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].cMultSectors);
    7207             pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].PCHSGeometry.cCylinders);
    7208             pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].PCHSGeometry.cHeads);
    7209             pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].PCHSGeometry.cSectors);
     7265            pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].XCHSGeometry.cCylinders);
     7266            pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].XCHSGeometry.cHeads);
     7267            pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].XCHSGeometry.cSectors);
    72107268            pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].cSectorsPerIRQ);
    72117269            pHlp->pfnSSMPutU64(pSSM, pThis->aCts[i].aIfs[j].cTotalSectors);
     
    73877445            pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].aIfs[j].fIrqPending);
    73887446            pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].cMultSectors);
    7389             pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].PCHSGeometry.cCylinders);
    7390             pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].PCHSGeometry.cHeads);
    7391             pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].PCHSGeometry.cSectors);
     7447            pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].XCHSGeometry.cCylinders);
     7448            pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].XCHSGeometry.cHeads);
     7449            pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].XCHSGeometry.cSectors);
    73927450            pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].cSectorsPerIRQ);
    73937451            pHlp->pfnSSMGetU64(pSSM, &pThis->aCts[i].aIfs[j].cTotalSectors);
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