VirtualBox

Changeset 304 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jan 25, 2007 3:36:19 PM (18 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
17853
Message:

Fixed a collection of bugs in capability reporting. Added 3 ATAPI
commands which are used frequently by Linux automount tools.

File:
1 edited

Legend:

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

    r262 r304  
    435435static void ataExecuteDeviceDiagnosticSS(ATADevState *);
    436436static void ataPacketSS(ATADevState *);
     437static void atapiGetConfigurationSS(ATADevState *);
    437438static void atapiIdentifySS(ATADevState *);
    438439static void atapiInquirySS(ATADevState *);
     
    442443static void atapiReadSS(ATADevState *);
    443444static void atapiReadCapacitySS(ATADevState *);
     445static void atapiReadDiscInformationSS(ATADevState *);
    444446static void atapiReadTOCNormalSS(ATADevState *);
    445447static void atapiReadTOCMultiSS(ATADevState *);
    446448static void atapiReadTOCRawSS(ATADevState *);
     449static void atapiReadTrackInformationSS(ATADevState *);
    447450static void atapiRequestSenseSS(ATADevState *);
    448451static void atapiPassthroughSS(ATADevState *);
     
    486489    ATAFN_SS_EXECUTE_DEVICE_DIAGNOSTIC,
    487490    ATAFN_SS_PACKET,
     491    ATAFN_SS_ATAPI_GET_CONFIGURATION,
    488492    ATAFN_SS_ATAPI_IDENTIFY,
    489493    ATAFN_SS_ATAPI_INQUIRY,
     
    493497    ATAFN_SS_ATAPI_READ,
    494498    ATAFN_SS_ATAPI_READ_CAPACITY,
     499    ATAFN_SS_ATAPI_READ_DISC_INFORMATION,
    495500    ATAFN_SS_ATAPI_READ_TOC_NORMAL,
    496501    ATAFN_SS_ATAPI_READ_TOC_MULTI,
    497502    ATAFN_SS_ATAPI_READ_TOC_RAW,
     503    ATAFN_SS_ATAPI_READ_TRACK_INFORMATION,
    498504    ATAFN_SS_ATAPI_REQUEST_SENSE,
    499505    ATAFN_SS_ATAPI_PASSTHROUGH,
     
    514520    ataExecuteDeviceDiagnosticSS,
    515521    ataPacketSS,
     522    atapiGetConfigurationSS,
    516523    atapiIdentifySS,
    517524    atapiInquirySS,
     
    521528    atapiReadSS,
    522529    atapiReadCapacitySS,
     530    atapiReadDiscInformationSS,
    523531    atapiReadTOCNormalSS,
    524532    atapiReadTOCMultiSS,
    525533    atapiReadTOCRawSS,
     534    atapiReadTrackInformationSS,
    526535    atapiRequestSenseSS,
    527536    atapiPassthroughSS
     
    17601769
    17611770    Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
    1762     Assert(s->cbElementaryTransfer <= 36);
     1771    Assert(s->cbElementaryTransfer <= 8);
    17631772    ataH2BE_U32(pbBuf, s->cTotalSectors - 1);
    17641773    ataH2BE_U32(pbBuf + 4, 2048);
     1774    s->iSourceSink = ATAFN_SS_NULL;
     1775    atapiCmdOK(s);
     1776}
     1777
     1778
     1779static void atapiReadDiscInformationSS(ATADevState *s)
     1780{
     1781    uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer);
     1782
     1783    Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
     1784    Assert(s->cbElementaryTransfer <= 34);
     1785    memset(pbBuf, '\0', 34);
     1786    ataH2BE_U16(pbBuf, 32);
     1787    pbBuf[2] = (0 << 4) | (3 << 2) | (2 << 0); /* not erasable, complete session, complete disc */
     1788    pbBuf[3] = 1; /* number of first track */
     1789    pbBuf[4] = 1; /* number of sessions (LSB) */
     1790    pbBuf[5] = 1; /* first track number in last session (LSB) */
     1791    pbBuf[6] = 1; /* last track number in last session (LSB) */
     1792    pbBuf[7] = (0 << 7) | (0 << 6) | (1 << 5) | (0 << 2) | (0 << 0); /* disc id not valid, disc bar code not valid, unrestricted use, not dirty, not RW medium */
     1793    pbBuf[8] = 0; /* disc type = CD-ROM */
     1794    pbBuf[9] = 0; /* number of sessions (MSB) */
     1795    pbBuf[10] = 0; /* number of sessions (MSB) */
     1796    pbBuf[11] = 0; /* number of sessions (MSB) */
     1797    ataH2BE_U32(pbBuf + 16, 0x00ffffff); /* last session lead-in start time is not available */
     1798    ataH2BE_U32(pbBuf + 20, 0x00ffffff); /* last possible start time for lead-out is not available */
     1799    s->iSourceSink = ATAFN_SS_NULL;
     1800    atapiCmdOK(s);
     1801}
     1802
     1803
     1804static void atapiReadTrackInformationSS(ATADevState *s)
     1805{
     1806    uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer);
     1807
     1808    Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
     1809    Assert(s->cbElementaryTransfer <= 36);
     1810    /* Accept address/number type of 1 only, and only track 1 exists. */
     1811    if ((s->aATAPICmd[1] & 0x03) != 1 || ataBE2H_U32(&s->aATAPICmd[2]) != 1)
     1812    {
     1813        atapiCmdError(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
     1814        return;
     1815    }
     1816    memset(pbBuf, '\0', 36);
     1817    ataH2BE_U16(pbBuf, 34);
     1818    pbBuf[2] = 1; /* track number (LSB) */
     1819    pbBuf[3] = 1; /* session number (LSB) */
     1820    pbBuf[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */
     1821    pbBuf[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */
     1822    pbBuf[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */
     1823    ataH2BE_U32(pbBuf + 8, 0); /* track start address is 0 */
     1824    ataH2BE_U32(pbBuf + 24, s->cTotalSectors); /* track size */
     1825    pbBuf[32] = 0; /* track number (MSB) */
     1826    pbBuf[33] = 0; /* session number (MSB) */
     1827    s->iSourceSink = ATAFN_SS_NULL;
     1828    atapiCmdOK(s);
     1829}
     1830
     1831
     1832static void atapiGetConfigurationSS(ATADevState *s)
     1833{
     1834    uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer);
     1835
     1836    Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
     1837    Assert(s->cbElementaryTransfer <= 32);
     1838    /* Accept request type of 0 or 1 only, and only starting feature 0. */
     1839    if (((s->aATAPICmd[1] & 0x03) != 0 && (s->aATAPICmd[1] & 0x03) != 1) || ataBE2H_U16(&s->aATAPICmd[2]) != 0)
     1840    {
     1841        atapiCmdError(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
     1842        return;
     1843    }
     1844    memset(pbBuf, '\0', 32);
     1845    ataH2BE_U32(pbBuf, 12);
     1846    ataH2BE_U16(pbBuf + 6, 8); /* current profile: cd-rom read-only */
     1847
     1848    ataH2BE_U16(pbBuf + 8, 0); /* feature 0: list of profiles supported */
     1849    pbBuf[10] = (0 << 2) | (1 << 1) | (1 || 0); /* version 0, persistent, current */
     1850    pbBuf[11] = 4; /* additional bytes for profiles */
     1851    ataH2BE_U16(pbBuf + 12, 8); /* profile: cd-rom read-only */
     1852    pbBuf[14] = (1 << 0); /* current profile */
    17651853    s->iSourceSink = ATAFN_SS_NULL;
    17661854    atapiCmdOK(s);
     
    18271915
    18281916    Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
    1829     Assert(s->cbElementaryTransfer <= 28);
    1830     ataH2BE_U16(&pbBuf[0], 28 + 6);
     1917    Assert(s->cbElementaryTransfer <= 40);
     1918    ataH2BE_U16(&pbBuf[0], 38);
    18311919    pbBuf[2] = 0x70;
    18321920    pbBuf[3] = 0;
     
    18371925
    18381926    pbBuf[8] = 0x2a;
    1839     pbBuf[9] = 0x12;
    1840     pbBuf[10] = 0x00;
    1841     pbBuf[11] = 0x00;
    1842 
    1843     pbBuf[12] = 0x70;
    1844     pbBuf[13] = 3 << 5;
    1845     pbBuf[14] = (1 << 0) | (1 << 3) | (1 << 5);
     1927    pbBuf[9] = 30; /* page length */
     1928    pbBuf[10] = 0x08; /* DVD-ROM read support */
     1929    pbBuf[11] = 0x00; /* no write support */
     1930    /* The following claims we support audio play. This is obviously false,
     1931     * but the Linux generic CDROM support makes many features depend on this
     1932     * capability. If it's not set, this causes many things to be disabled. */
     1933    pbBuf[12] = 0x71; /* multisession support, mode 2 form 1/2 support, audio play */
     1934    pbBuf[13] = 0x00; /* no subchannel reads supported */
     1935    pbBuf[14] = (1 << 0) | (1 << 3) | (1 << 5); /* lock supported, eject supported, tray type loading mechanism */
    18461936    if (s->pDrvMount->pfnIsLocked(s->pDrvMount))
    1847         pbBuf[6] |= 1 << 1;
    1848     pbBuf[15] = 0x00;
    1849     ataH2BE_U16(&pbBuf[16], 706);
    1850     pbBuf[18] = 0;
    1851     pbBuf[19] = 2;
    1852     ataH2BE_U16(&pbBuf[20], 512);
    1853     ataH2BE_U16(&pbBuf[22], 706);
    1854     pbBuf[24] = 0;
    1855     pbBuf[25] = 0;
    1856     pbBuf[26] = 0;
    1857     pbBuf[27] = 0;
     1937        pbBuf[14] |= 1 << 1; /* report lock state */
     1938    pbBuf[15] = 0; /* no subchannel reads supported, no separate audio volume control, no changer etc. */
     1939    ataH2BE_U16(&pbBuf[16], 5632); /* (obsolete) claim 32x speed support */
     1940    ataH2BE_U16(&pbBuf[18], 2); /* number of audio volume levels */
     1941    ataH2BE_U16(&pbBuf[20], s->cbIOBuffer / _1K); /* buffer size supported in Kbyte */
     1942    ataH2BE_U16(&pbBuf[22], 5632); /* (obsolete) current read speed 32x */
     1943    pbBuf[24] = 0; /* reserved */
     1944    pbBuf[25] = 0; /* reserved for digital audio (see idx 15) */
     1945    ataH2BE_U16(&pbBuf[26], 0); /* (obsolete) maximum write speed */
     1946    ataH2BE_U16(&pbBuf[28], 0); /* (obsolete) current write speed */
     1947    ataH2BE_U16(&pbBuf[30], 0); /* copy management revision supported 0=no CSS */
     1948    pbBuf[32] = 0; /* reserved */
     1949    pbBuf[33] = 0; /* reserved */
     1950    pbBuf[34] = 0; /* reserved */
     1951    pbBuf[35] = 1; /* rotation control CAV */
     1952    ataH2BE_U16(&pbBuf[36], 0); /* current write speed */
     1953    ataH2BE_U16(&pbBuf[38], 0); /* number of write speed performance descriptors */
    18581954    s->iSourceSink = ATAFN_SS_NULL;
    18591955    atapiCmdOK(s);
     
    19212017        {
    19222018            *q++ = 0; /* reserved */
    1923             *q++ = 0; /* minute */
    1924             *q++ = 2; /* second */
    1925             *q++ = 0; /* frame */
     2019            ataLBA2MSF(q, 0);
     2020            q += 3;
    19262021        }
    19272022        else
     
    19342029    /* lead out track */
    19352030    *q++ = 0; /* reserved */
    1936     *q++ = 0x16; /* ADR, control */
     2031    *q++ = 0x14; /* ADR, control */
    19372032    *q++ = 0xaa; /* track number */
    19382033    *q++ = 0; /* reserved */
     
    19602055{
    19612056    uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer);
     2057    bool fMSF;
    19622058
    19632059    Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
    19642060    Assert(s->cbElementaryTransfer <= 12);
     2061    fMSF = (s->aATAPICmd[1] >> 1) & 1;
    19652062    /* multi session: only a single session defined */
     2063/** @todo double-check this stuff against what a real drive says for a CD-ROM (not a CD-R) with only a single data session. Maybe solve the problem with "cdrdao read-toc" not being able to figure out whether numbers are in BCD or hex. */
    19662064    memset(pbBuf, 0, 12);
    19672065    pbBuf[1] = 0x0a;
    19682066    pbBuf[2] = 0x01;
    19692067    pbBuf[3] = 0x01;
     2068    pbBuf[5] = 0x14; /* ADR, control */
     2069    pbBuf[6] = 1; /* first track in last complete session */
     2070    if (fMSF)
     2071    {
     2072        pbBuf[8] = 0; /* reserved */
     2073        ataLBA2MSF(&pbBuf[9], 0);
     2074    }
     2075    else
     2076    {
     2077        /* sector 0 */
     2078        ataH2BE_U32(pbBuf + 8, 0);
     2079    }
    19702080    s->iSourceSink = ATAFN_SS_NULL;
    19712081    atapiCmdOK(s);
     
    19902100    *q++ = 0x14; /* data track */
    19912101    *q++ = 0; /* track number */
    1992     *q++ = 0xa0; /* lead-in */
     2102    *q++ = 0xa0; /* first track in program area */
    19932103    *q++ = 0; /* min */
    19942104    *q++ = 0; /* sec */
     
    19962106    *q++ = 0;
    19972107    *q++ = 1; /* first track */
    1998     *q++ = 0x00; /* disk type */
    1999     *q++ = 0x00;
     2108    *q++ = 0x00; /* disk type CD-DA or CD data */
     2109    *q++ = 0;
    20002110
    20012111    *q++ = 1; /* session number */
    20022112    *q++ = 0x14; /* data track */
    20032113    *q++ = 0; /* track number */
    2004     *q++ = 0xa1;
     2114    *q++ = 0xa1; /* last track in program area */
    20052115    *q++ = 0; /* min */
    20062116    *q++ = 0; /* sec */
     
    20082118    *q++ = 0;
    20092119    *q++ = 1; /* last track */
    2010     *q++ = 0x00;
    2011     *q++ = 0x00;
     2120    *q++ = 0;
     2121    *q++ = 0;
    20122122
    20132123    *q++ = 1; /* session number */
     
    20372147    *q++ = 0; /* sec */
    20382148    *q++ = 0; /* frame */
    2039     *q++ = 0;
    2040     *q++ = 0;
    2041     *q++ = 0;
    2042     *q++ = 0;
     2149    if (fMSF)
     2150    {
     2151        *q++ = 0; /* reserved */
     2152        ataLBA2MSF(q, 0);
     2153        q += 3;
     2154    }
     2155    else
     2156    {
     2157        /* sector 0 */
     2158        ataH2BE_U32(q, 0);
     2159        q += 4;
     2160    }
    20432161
    20442162    cbSize = q - pbBuf;
     
    20892207                                break;
    20902208                            case SCSI_MODEPAGE_CD_STATUS:
    2091                                 ataStartTransfer(s, RT_MIN(cbMax, 28), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS, true);
     2209                                ataStartTransfer(s, RT_MIN(cbMax, 40), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS, true);
    20922210                                break;
    20932211                            default:
     
    23122430                }
    23132431                cbMax = ataBE2H_U16(pbPacket + 7);
    2314                 format = pbPacket[9] >> 6;
     2432                /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits),
     2433                 * but Linux kernel uses offset 9 (topmost 2 bits). Hope that
     2434                 * the other field is clear... */
     2435                format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6);
    23152436                switch (format)
    23162437                {
     
    23442465            }
    23452466            ataStartTransfer(s, 8, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_CAPACITY, true);
     2467            break;
     2468        case SCSI_READ_DISC_INFORMATION:
     2469            if (s->cNotifiedMediaChange > 0)
     2470            {
     2471                s->cNotifiedMediaChange-- ;
     2472                atapiCmdError(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     2473                break;
     2474            }
     2475            else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
     2476            {
     2477                atapiCmdError(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     2478                break;
     2479            }
     2480            cbMax = ataBE2H_U16(pbPacket + 7);
     2481            ataStartTransfer(s, RT_MIN(cbMax, 34), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_DISC_INFORMATION, true);
     2482            break;
     2483        case SCSI_READ_TRACK_INFORMATION:
     2484            if (s->cNotifiedMediaChange > 0)
     2485            {
     2486                s->cNotifiedMediaChange-- ;
     2487                atapiCmdError(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     2488                break;
     2489            }
     2490            else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
     2491            {
     2492                atapiCmdError(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     2493                break;
     2494            }
     2495            cbMax = ataBE2H_U16(pbPacket + 7);
     2496            ataStartTransfer(s, RT_MIN(cbMax, 36), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TRACK_INFORMATION, true);
     2497            break;
     2498        case SCSI_GET_CONFIGURATION:
     2499            if (s->cNotifiedMediaChange > 0)
     2500            {
     2501                s->cNotifiedMediaChange-- ;
     2502                atapiCmdError(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     2503                break;
     2504            }
     2505            else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
     2506            {
     2507                atapiCmdError(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     2508                break;
     2509            }
     2510            cbMax = ataBE2H_U16(pbPacket + 7);
     2511            ataStartTransfer(s, RT_MIN(cbMax, 32), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_GET_CONFIGURATION, true);
    23462512            break;
    23472513        case SCSI_INQUIRY:
     
    44184584#endif /* IN_GC */
    44194585
     4586        if (cbTransfer)
     4587            Log3(("%s: addr=%#x val=%.*Vhxs\n", __FUNCTION__, Port, cbTransfer, s->CTXSUFF(pbIOBuffer) + s->iIOBufferPIODataStart));
    44204588        s->iIOBufferPIODataStart += cbTransfer;
    44214589        *pGCPtrDst = (RTGCPTR)((RTGCUINTPTR)GCDst + cbTransfer);
     
    44734641#endif /* IN_GC */
    44744642
     4643        if (cbTransfer)
     4644            Log3(("%s: addr=%#x val=%.*Vhxs\n", __FUNCTION__, Port, cbTransfer, s->CTXSUFF(pbIOBuffer) + s->iIOBufferPIODataStart));
    44754645        s->iIOBufferPIODataStart += cbTransfer;
    44764646        *pGCPtrSrc = (RTGCPTR)((RTGCUINTPTR)GCSrc + cbTransfer);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette