VirtualBox

Ignore:
Timestamp:
May 18, 2017 3:57:16 PM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
115496
Message:

Devices/Storage/DrvSCSI,VSCSI: Support CD/DVD images with multiple tracks like for DevATA to bring the AHCI and SCSI controllers up to the same feature level

File:
1 edited

Legend:

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

    r66164 r66955  
    7373    /** Size of the virtual disk. */
    7474    uint64_t                    cSectors;
    75     /** Sector size. */
    76     uint32_t                    cbSector;
    7775    /** Medium locked indicator. */
    7876    bool                        fLocked;
     
    144142static int mmcReadTOCNormal(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq, uint16_t cbMaxTransfer, bool fMSF)
    145143{
    146     PVSCSILUNMMC    pVScsiLunMmc = (PVSCSILUNMMC)pVScsiLun;
    147     uint8_t         aReply[32];
     144    uint8_t         aReply[2+99*8 + 32]; RT_ZERO(aReply); /* Maximum possible reply plus some safety. */
    148145    uint8_t         *pbBuf = aReply;
    149146    uint8_t         *q;
    150147    uint8_t         iStartTrack;
    151148    uint32_t        cbSize;
     149    uint32_t        cTracks = vscsiLunMediumGetRegionCount(pVScsiLun);
    152150
    153151    iStartTrack = pVScsiReq->pbCDB[6];
    154     if (iStartTrack > 1 && iStartTrack != 0xaa)
    155     {
     152    if (iStartTrack == 0)
     153        iStartTrack = 1;
     154    if (iStartTrack > cTracks && iStartTrack != 0xaa)
    156155        return vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
    157     }
     156
    158157    q = pbBuf + 2;
    159     *q++ = 1;   /* first session */
    160     *q++ = 1;   /* last session */
    161     if (iStartTrack <= 1)
    162     {
    163         *q++ = 0;       /* reserved */
    164         *q++ = 0x14;    /* ADR, CONTROL */
    165         *q++ = 1;       /* track number */
    166         *q++ = 0;       /* reserved */
     158    *q++ = iStartTrack; /* first track number */
     159    *q++ = cTracks;     /* last track number */
     160    for (uint32_t iTrack = iStartTrack; iTrack <= cTracks; iTrack++)
     161    {
     162        uint64_t uLbaStart = 0;
     163        VDREGIONDATAFORM enmDataForm = VDREGIONDATAFORM_MODE1_2048;
     164
     165        int rc = vscsiLunMediumQueryRegionProperties(pVScsiLun, iTrack - 1, &uLbaStart,
     166                                                     NULL, NULL, &enmDataForm);
     167        AssertRC(rc);
     168
     169        *q++ = 0;                  /* reserved */
     170
     171        if (enmDataForm == VDREGIONDATAFORM_CDDA)
     172            *q++ = 0x10;           /* ADR, control */
     173        else
     174            *q++ = 0x14;           /* ADR, control */
     175
     176        *q++ = (uint8_t)iTrack;    /* track number */
     177        *q++ = 0;                  /* reserved */
    167178        if (fMSF)
    168179        {
    169             *q++ = 0;   /* reserved */
    170             scsiLBA2MSF(q, 0);
     180            *q++ = 0; /* reserved */
     181            scsiLBA2MSF(q, (uint32_t)uLbaStart);
    171182            q += 3;
    172183        }
     
    174185        {
    175186            /* sector 0 */
    176             scsiH2BE_U32(q, 0);
     187            scsiH2BE_U32(q, (uint32_t)uLbaStart);
    177188            q += 4;
    178189        }
    179190    }
    180191    /* lead out track */
    181     *q++ = 0;       /* reserved */
    182     *q++ = 0x14;    /* ADR, CONTROL */
    183     *q++ = 0xaa;    /* track number */
    184     *q++ = 0;       /* reserved */
     192    *q++ = 0; /* reserved */
     193    *q++ = 0x14; /* ADR, control */
     194    *q++ = 0xaa; /* track number */
     195    *q++ = 0; /* reserved */
     196
     197    /* Query start and length of last track to get the start of the lead out track. */
     198    uint64_t uLbaStart = 0;
     199    uint64_t cBlocks = 0;
     200
     201    int rc = vscsiLunMediumQueryRegionProperties(pVScsiLun, cTracks - 1, &uLbaStart,
     202                                                 &cBlocks, NULL, NULL);
     203    AssertRC(rc);
     204
     205    uLbaStart += cBlocks;
    185206    if (fMSF)
    186207    {
    187         *q++ = 0;   /* reserved */
    188         scsiLBA2MSF(q, pVScsiLunMmc->cSectors);
     208        *q++ = 0; /* reserved */
     209        scsiLBA2MSF(q, (uint32_t)uLbaStart);
    189210        q += 3;
    190211    }
    191212    else
    192213    {
    193         scsiH2BE_U32(q, pVScsiLunMmc->cSectors);
     214        scsiH2BE_U32(q, (uint32_t)uLbaStart);
    194215        q += 4;
    195216    }
     
    201222
    202223    RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, cbMaxTransfer);
    203 
    204224    return vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
    205225}
     
    217237    pbBuf[2] = 0x01;    /* first complete session number */
    218238    pbBuf[3] = 0x01;    /* last complete session number */
    219     pbBuf[5] = 0x14;    /* ADR, CONTROL */
     239
     240    VDREGIONDATAFORM enmDataForm = VDREGIONDATAFORM_MODE1_2048;
     241    int rc = vscsiLunMediumQueryRegionProperties(pVScsiLun, 0, NULL,
     242                                                 NULL, NULL, &enmDataForm);
     243    AssertRC(rc);
     244
     245    if (enmDataForm == VDREGIONDATAFORM_CDDA)
     246        pbBuf[5] = 0x10;           /* ADR, control */
     247    else
     248        pbBuf[5] = 0x14;           /* ADR, control */
     249
    220250    pbBuf[6] = 1;       /* first track in last complete session */
    221251
     
    855885}
    856886
     887/**
     888 * Processes a READ TRACK INFORMATION SCSI request.
     889 *
     890 * @returns SCSI status code.
     891 * @param   pVScsiLunMmc  The MMC LUN instance.
     892 * @param   pVScsiReq     The VSCSI request.
     893 * @param   cbMaxTransfer The maximum transfer size.
     894 */
     895static int vscsiLunMmcReadTrackInformation(PVSCSILUNMMC pVScsiLunMmc, PVSCSIREQINT pVScsiReq,
     896                                           size_t cbMaxTransfer)
     897{
     898    int rcReq;
     899    uint32_t u32LogAddr = scsiBE2H_U32(&pVScsiReq->pbCDB[2]);
     900    uint8_t u8LogAddrType = pVScsiReq->pbCDB[1] & 0x03;
     901
     902    int rc = VINF_SUCCESS;
     903    uint64_t u64LbaStart = 0;
     904    uint32_t uRegion = 0;
     905    uint64_t cBlocks = 0;
     906    uint64_t cbBlock = 0;
     907    VDREGIONDATAFORM enmDataForm = VDREGIONDATAFORM_INVALID;
     908
     909    switch (u8LogAddrType)
     910    {
     911        case 0x00:
     912            rc = vscsiLunMediumQueryRegionPropertiesForLba(&pVScsiLunMmc->Core, u32LogAddr, &uRegion,
     913                                                           NULL, NULL, NULL);
     914            if (RT_SUCCESS(rc))
     915                rc = vscsiLunMediumQueryRegionProperties(&pVScsiLunMmc->Core, uRegion, &u64LbaStart,
     916                                                         &cBlocks, &cbBlock, &enmDataForm);
     917            break;
     918        case 0x01:
     919        {
     920            if (u32LogAddr >= 1)
     921            {
     922                uRegion = u32LogAddr - 1;
     923                rc = vscsiLunMediumQueryRegionProperties(&pVScsiLunMmc->Core, uRegion, &u64LbaStart,
     924                                                         &cBlocks, &cbBlock, &enmDataForm);
     925            }
     926            else
     927                rc = VERR_NOT_FOUND; /** @todo: Return lead-in information. */
     928            break;
     929        }
     930        case 0x02:
     931        default:
     932            rc = VERR_INVALID_PARAMETER;
     933    }
     934
     935    if (RT_SUCCESS(rc))
     936    {
     937        uint8_t u8DataMode = 0xf; /* Unknown data mode. */
     938        uint8_t u8TrackMode = 0;
     939        uint8_t aReply[36];
     940        RT_ZERO(aReply);
     941
     942        switch (enmDataForm)
     943        {
     944            case VDREGIONDATAFORM_MODE1_2048:
     945            case VDREGIONDATAFORM_MODE1_2352:
     946            case VDREGIONDATAFORM_MODE1_0:
     947                u8DataMode = 1;
     948                break;
     949            case VDREGIONDATAFORM_XA_2336:
     950            case VDREGIONDATAFORM_XA_2352:
     951            case VDREGIONDATAFORM_XA_0:
     952            case VDREGIONDATAFORM_MODE2_2336:
     953            case VDREGIONDATAFORM_MODE2_2352:
     954            case VDREGIONDATAFORM_MODE2_0:
     955                u8DataMode = 2;
     956                break;
     957            default:
     958                u8DataMode = 0xf;
     959        }
     960
     961        if (enmDataForm == VDREGIONDATAFORM_CDDA)
     962            u8TrackMode = 0x0;
     963        else
     964            u8TrackMode = 0x4;
     965
     966        scsiH2BE_U16(&aReply[0], 34);
     967        aReply[2] = uRegion + 1;                                            /* track number (LSB) */
     968        aReply[3] = 1;                                                      /* session number (LSB) */
     969        aReply[5] = (0 << 5) | (0 << 4) | u8TrackMode;                      /* not damaged, primary copy, data track */
     970        aReply[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | u8DataMode; /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */
     971        aReply[7] = (0 << 1) | (0 << 0);                                    /* last recorded address not valid, next recordable address not valid */
     972        scsiH2BE_U32(&aReply[8], (uint32_t)u64LbaStart);                    /* track start address is 0 */
     973        scsiH2BE_U32(&aReply[24], (uint32_t)cBlocks);                       /* track size */
     974        aReply[32] = 0;                                                     /* track number (MSB) */
     975        aReply[33] = 0;                                                     /* session number (MSB) */
     976
     977        RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, RT_MIN(sizeof(aReply), cbMaxTransfer));
     978        rcReq = vscsiLunReqSenseOkSet(&pVScsiLunMmc->Core, pVScsiReq);
     979    }
     980    else
     981        rcReq = vscsiLunReqSenseErrorSet(&pVScsiLunMmc->Core, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST,
     982                                         SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
     983
     984    return rcReq;
     985}
     986
    857987static DECLCALLBACK(int) vscsiLunMmcInit(PVSCSILUNINT pVScsiLun)
    858988{
    859989    PVSCSILUNMMC    pVScsiLunMmc = (PVSCSILUNMMC)pVScsiLun;
    860     uint64_t        cbDisk = 0;
    861990    int             rc = VINF_SUCCESS;
    862991
    863992    ASMAtomicWriteU32((volatile uint32_t *)&pVScsiLunMmc->MediaEventStatus, MMCEVENTSTATUSTYPE_UNCHANGED);
    864993    pVScsiLunMmc->u32MediaTrackType = MMC_MEDIA_TYPE_UNKNOWN;
    865     pVScsiLunMmc->cbSector          = 2048;  /* Default to 2K sectors. */
    866     rc = vscsiLunMediumGetSize(pVScsiLun, &cbDisk);
    867     if (RT_SUCCESS(rc))
    868         pVScsiLunMmc->cSectors = cbDisk / pVScsiLunMmc->cbSector;
     994    pVScsiLunMmc->cSectors          = 0;
     995
     996    uint32_t cTracks = vscsiLunMediumGetRegionCount(pVScsiLun);
     997    for (uint32_t i = 0; i < cTracks; i++)
     998    {
     999        uint64_t cBlocks = 0;
     1000        rc = vscsiLunMediumQueryRegionProperties(pVScsiLun, i, NULL, &cBlocks,
     1001                                                 NULL, NULL);
     1002        AssertRC(rc);
     1003
     1004        pVScsiLunMmc->cSectors += cBlocks;
     1005    }
    8691006
    8701007    return rc;
     
    8831020    uint64_t        uLbaStart = 0;
    8841021    uint32_t        cSectorTransfer = 0;
     1022    size_t          cbSector = 0;
    8851023    int             rc = VINF_SUCCESS;
    8861024    int             rcReq = SCSI_STATUS_OK;
     
    9631101                else
    9641102                    scsiH2BE_U32(aReply, pVScsiLunMmc->cSectors - 1);
    965                 scsiH2BE_U32(&aReply[4], pVScsiLunMmc->cbSector);
     1103                scsiH2BE_U32(&aReply[4], _2K);
    9661104                RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
    9671105                rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
     
    10351173                                            | ((pVScsiReq->pbCDB[1] & 0x1f) << 16));
    10361174                cSectorTransfer = pVScsiReq->pbCDB[4];
     1175                cbSector        = _2K;
    10371176                break;
    10381177            }
     
    10421181                uLbaStart       = scsiBE2H_U32(&pVScsiReq->pbCDB[2]);
    10431182                cSectorTransfer = scsiBE2H_U16(&pVScsiReq->pbCDB[7]);
     1183                cbSector        = _2K;
    10441184                break;
    10451185            }
     
    10491189                uLbaStart       = scsiBE2H_U32(&pVScsiReq->pbCDB[2]);
    10501190                cSectorTransfer = scsiBE2H_U32(&pVScsiReq->pbCDB[6]);
     1191                cbSector        = _2K;
    10511192                break;
    10521193            }
     
    10561197                uLbaStart       = scsiBE2H_U64(&pVScsiReq->pbCDB[2]);
    10571198                cSectorTransfer = scsiBE2H_U32(&pVScsiReq->pbCDB[10]);
     1199                cbSector        = _2K;
    10581200                break;
    10591201            }
     
    10621204                uLbaStart       = scsiBE2H_U32(&pVScsiReq->pbCDB[2]);
    10631205                cSectorTransfer = (pVScsiReq->pbCDB[6] << 16) | (pVScsiReq->pbCDB[7] << 8) | pVScsiReq->pbCDB[8];
    1064                 switch (pVScsiReq->pbCDB[9] & 0xf8)
     1206
     1207                /*
     1208                 * If the LBA is in an audio track we are required to ignore pretty much all
     1209                 * of the channel selection values (except 0x00) and map everything to 0x10
     1210                 * which means read user data with a sector size of 2352 bytes.
     1211                 *
     1212                 * (MMC-6 chapter 6.19.2.6)
     1213                 */
     1214                uint8_t uChnSel = pVScsiReq->pbCDB[9] & 0xf8;
     1215                VDREGIONDATAFORM enmDataForm;
     1216                uint64_t cbSectorRegion = 0;
     1217                rc = vscsiLunMediumQueryRegionPropertiesForLba(pVScsiLun, uLbaStart,
     1218                                                               NULL, NULL, &cbSectorRegion,
     1219                                                               &enmDataForm);
     1220                AssertRC(rc);
     1221
     1222                if (enmDataForm == VDREGIONDATAFORM_CDDA)
    10651223                {
    1066                     case 0x00:
     1224                    if (uChnSel == 0)
     1225                    {
    10671226                        /* nothing */
    10681227                        rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
    1069                         break;
    1070                     case 0x10:
    1071                         /* normal read */
     1228                    }
     1229                    else
     1230                    {
    10721231                        enmTxDir = VSCSIIOREQTXDIR_READ;
    1073                         break;
    1074                     case 0xf8:
     1232                        cbSector = 2352;
     1233                    }
     1234                }
     1235                else
     1236                {
     1237                    switch (uChnSel)
    10751238                    {
    1076                         /*
    1077                          * Read all data, sector size is 2352.
    1078                          * Rearrange the buffer and fill the gaps with the sync bytes.
    1079                          */
    1080                         /* Count the number of segments for the buffer we require. */
    1081                         RTSGBUF SgBuf;
    1082                         bool fBufTooSmall = false;
    1083                         uint32_t cSegsNew = 0;
    1084                         RTSgBufClone(&SgBuf, &pVScsiReq->SgBuf);
    1085                         for (uint32_t uLba = (uint32_t)uLbaStart; uLba < uLbaStart + cSectorTransfer; uLba++)
     1239                        case 0x00:
     1240                            /* nothing */
     1241                            rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
     1242                            break;
     1243                        case 0x10:
     1244                            /* normal read */
     1245                            enmTxDir = VSCSIIOREQTXDIR_READ;
     1246                            cbSector = _2K;
     1247                            break;
     1248                        case 0xf8:
    10861249                        {
    1087                             size_t cbTmp = RTSgBufAdvance(&SgBuf, 16);
    1088                             if (cbTmp < 16)
     1250                            if (cbSectorRegion == 2048)
    10891251                            {
    1090                                 fBufTooSmall = true;
    1091                                 break;
    1092                             }
    1093 
    1094                             cbTmp = 2048;
    1095                             while (cbTmp)
    1096                             {
    1097                                 size_t cbBuf = cbTmp;
    1098                                 RTSgBufGetNextSegment(&SgBuf, &cbBuf);
    1099                                 if (!cbBuf)
    1100                                 {
    1101                                     fBufTooSmall = true;
    1102                                     break;
    1103                                 }
    1104 
    1105                                 cbTmp -= cbBuf;
    1106                                 cSegsNew++;
    1107                             }
    1108 
    1109                             cbTmp = RTSgBufAdvance(&SgBuf, 280);
    1110                             if (cbTmp < 280)
    1111                             {
    1112                                 fBufTooSmall = true;
    1113                                 break;
    1114                             }
    1115                         }
    1116 
    1117                         if (!fBufTooSmall)
    1118                         {
    1119                             PRTSGSEG paSegsNew = (PRTSGSEG)RTMemAllocZ(cSegsNew * sizeof(RTSGSEG));
    1120                             if (paSegsNew)
    1121                             {
    1122                                 enmTxDir = VSCSIIOREQTXDIR_READ;
    1123 
    1124                                 uint32_t idxSeg = 0;
     1252                                /*
     1253                                 * Read all data, sector size is 2352.
     1254                                 * Rearrange the buffer and fill the gaps with the sync bytes.
     1255                                 */
     1256                                /* Count the number of segments for the buffer we require. */
     1257                                RTSGBUF SgBuf;
     1258                                bool fBufTooSmall = false;
     1259                                uint32_t cSegsNew = 0;
     1260                                RTSgBufClone(&SgBuf, &pVScsiReq->SgBuf);
    11251261                                for (uint32_t uLba = (uint32_t)uLbaStart; uLba < uLbaStart + cSectorTransfer; uLba++)
    11261262                                {
    1127                                     /* Sync bytes, see 4.2.3.8 CD Main Channel Block Formats */
    1128                                     uint8_t abBuf[16];
    1129                                     abBuf[0] = 0x00;
    1130                                     memset(&abBuf[1], 0xff, 10);
    1131                                     abBuf[11] = 0x00;
    1132                                     /* MSF */
    1133                                     scsiLBA2MSF(&abBuf[12], uLba);
    1134                                     abBuf[15] = 0x01; /* mode 1 data */
    1135                                     RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, &abBuf[0], sizeof(abBuf));
    1136 
    1137                                     size_t cbTmp = 2048;
     1263                                    size_t cbTmp = RTSgBufAdvance(&SgBuf, 16);
     1264                                    if (cbTmp < 16)
     1265                                    {
     1266                                        fBufTooSmall = true;
     1267                                        break;
     1268                                    }
     1269
     1270                                    cbTmp = 2048;
    11381271                                    while (cbTmp)
    11391272                                    {
    11401273                                        size_t cbBuf = cbTmp;
    1141                                         paSegsNew[idxSeg].pvSeg = RTSgBufGetNextSegment(&pVScsiReq->SgBuf, &cbBuf);
    1142                                         paSegsNew[idxSeg].cbSeg = cbBuf;
    1143                                         idxSeg++;
     1274                                        RTSgBufGetNextSegment(&SgBuf, &cbBuf);
     1275                                        if (!cbBuf)
     1276                                        {
     1277                                            fBufTooSmall = true;
     1278                                            break;
     1279                                        }
    11441280
    11451281                                        cbTmp -= cbBuf;
     1282                                        cSegsNew++;
    11461283                                    }
    11471284
    1148                                     /**
    1149                                      * @todo: maybe compute ECC and parity, layout is:
    1150                                      * 2072 4   EDC
    1151                                      * 2076 172 P parity symbols
    1152                                      * 2248 104 Q parity symbols
    1153                                      */
    1154                                     RTSgBufSet(&pVScsiReq->SgBuf, 0, 280);
     1285                                    cbTmp = RTSgBufAdvance(&SgBuf, 280);
     1286                                    if (cbTmp < 280)
     1287                                    {
     1288                                        fBufTooSmall = true;
     1289                                        break;
     1290                                    }
    11551291                                }
    11561292
    1157                                 paSegs = paSegsNew;
    1158                                 cSegs  = cSegsNew;
    1159                                 pVScsiReq->pvLun = paSegsNew;
     1293                                if (!fBufTooSmall)
     1294                                {
     1295                                    PRTSGSEG paSegsNew = (PRTSGSEG)RTMemAllocZ(cSegsNew * sizeof(RTSGSEG));
     1296                                    if (paSegsNew)
     1297                                    {
     1298                                        enmTxDir = VSCSIIOREQTXDIR_READ;
     1299
     1300                                        uint32_t idxSeg = 0;
     1301                                        for (uint32_t uLba = (uint32_t)uLbaStart; uLba < uLbaStart + cSectorTransfer; uLba++)
     1302                                        {
     1303                                            /* Sync bytes, see 4.2.3.8 CD Main Channel Block Formats */
     1304                                            uint8_t abBuf[16];
     1305                                            abBuf[0] = 0x00;
     1306                                            memset(&abBuf[1], 0xff, 10);
     1307                                            abBuf[11] = 0x00;
     1308                                            /* MSF */
     1309                                            scsiLBA2MSF(&abBuf[12], uLba);
     1310                                            abBuf[15] = 0x01; /* mode 1 data */
     1311                                            RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, &abBuf[0], sizeof(abBuf));
     1312
     1313                                            size_t cbTmp = 2048;
     1314                                            while (cbTmp)
     1315                                            {
     1316                                                size_t cbBuf = cbTmp;
     1317                                                paSegsNew[idxSeg].pvSeg = RTSgBufGetNextSegment(&pVScsiReq->SgBuf, &cbBuf);
     1318                                                paSegsNew[idxSeg].cbSeg = cbBuf;
     1319                                                idxSeg++;
     1320
     1321                                                cbTmp -= cbBuf;
     1322                                            }
     1323
     1324                                            /**
     1325                                             * @todo: maybe compute ECC and parity, layout is:
     1326                                             * 2072 4   EDC
     1327                                             * 2076 172 P parity symbols
     1328                                             * 2248 104 Q parity symbols
     1329                                             */
     1330                                            RTSgBufSet(&pVScsiReq->SgBuf, 0, 280);
     1331                                        }
     1332
     1333                                        paSegs = paSegsNew;
     1334                                        cSegs  = cSegsNew;
     1335                                        pVScsiReq->pvLun = paSegsNew;
     1336                                    }
     1337                                    else
     1338                                        rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST,
     1339                                                                         SCSI_ASC_LOGICAL_BLOCK_OOR, 0x00);
     1340                                }
     1341                                else
     1342                                    rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST,
     1343                                                                     SCSI_ASC_LOGICAL_BLOCK_OOR, 0x00);
    11601344                            }
    1161                             else
    1162                                 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST,
    1163                                                                  SCSI_ASC_LOGICAL_BLOCK_OOR, 0x00);
     1345                            else if (cbSectorRegion == 2352)
     1346                            {
     1347                                /* Sector size matches what is read. */
     1348                                cbSector = cbSectorRegion;
     1349                                enmTxDir = VSCSIIOREQTXDIR_READ;
     1350                            }
     1351                            break;
    11641352                        }
    1165                         else
     1353                        default:
    11661354                            rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST,
    1167                                                              SCSI_ASC_LOGICAL_BLOCK_OOR, 0x00);
    1168                         break;
     1355                                                             SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
     1356                            break;
    11691357                    }
    1170                     default:
    1171                         rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST,
    1172                                                          SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
    1173                         break;
    11741358                }
    11751359                break;
     
    12691453                        memset(aReply, 0, sizeof(aReply));
    12701454                        scsiH2BE_U64(aReply, pVScsiLunMmc->cSectors - 1);
    1271                         scsiH2BE_U32(&aReply[8], pVScsiLunMmc->cbSector);
     1455                        scsiH2BE_U32(&aReply[8], _2K);
    12721456                        /* Leave the rest 0 */
    12731457
     
    13581542                aReply[4] = 1; /* number of sessions (LSB) */
    13591543                aReply[5] = 1; /* first track number in last session (LSB) */
    1360                 aReply[6] = 1; /* last track number in last session (LSB) */
     1544                aReply[6] = (uint8_t)vscsiLunMediumGetRegionCount(pVScsiLun); /* last track number in last session (LSB) */
    13611545                aReply[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 */
    13621546                aReply[8] = 0; /* disc type = CD-ROM */
     
    13731557            {
    13741558                size_t cbMax = scsiBE2H_U16(&pVScsiReq->pbCDB[7]);
    1375 
    13761559                vscsiReqSetXferSize(pVScsiReq, cbMax);
    1377                 /* Accept address/number type of 1 only, and only track 1 exists. */
    1378                 if ((pVScsiReq->pbCDB[1] & 0x03) != 1 || scsiBE2H_U32(&pVScsiReq->pbCDB[2]) != 1)
    1379                     rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST,
    1380                                                      SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
    1381                 else
    1382                 {
    1383                     uint8_t aReply[36];
    1384                     RT_ZERO(aReply);
    1385 
    1386                     scsiH2BE_U16(&aReply[0], 34);
    1387                     aReply[2] = 1; /* track number (LSB) */
    1388                     aReply[3] = 1; /* session number (LSB) */
    1389                     aReply[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */
    1390                     aReply[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 */
    1391                     aReply[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */
    1392                     scsiH2BE_U32(&aReply[8], 0); /* track start address is 0 */
    1393                     scsiH2BE_U32(&aReply[24], pVScsiLunMmc->cSectors); /* track size */
    1394                     aReply[32] = 0; /* track number (MSB) */
    1395                     aReply[33] = 0; /* session number (MSB) */
    1396 
    1397                     RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, RT_MIN(sizeof(aReply), cbMax));
    1398                     rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
    1399                 }
     1560                rcReq = vscsiLunMmcReadTrackInformation(pVScsiLunMmc, pVScsiReq, cbMax);
    14001561                break;
    14011562            }
     
    14251586                 __FUNCTION__, uLbaStart, cSectorTransfer));
    14261587
    1427         vscsiReqSetXferSize(pVScsiReq, cSectorTransfer * pVScsiLunMmc->cbSector);
     1588        vscsiReqSetXferSize(pVScsiReq, cSectorTransfer * cbSector);
    14281589        if (RT_UNLIKELY(uLbaStart + cSectorTransfer > pVScsiLunMmc->cSectors))
    14291590        {
     
    14391600        else
    14401601        {
    1441             /* Enqueue new I/O request */
    1442             rc = vscsiIoReqTransferEnqueueEx(pVScsiLun, pVScsiReq, enmTxDir,
    1443                                              uLbaStart * pVScsiLunMmc->cbSector,
    1444                                              paSegs, cSegs, cSectorTransfer * pVScsiLunMmc->cbSector);
     1602            /* Check that the sector size is valid. */
     1603            VDREGIONDATAFORM enmDataForm = VDREGIONDATAFORM_INVALID;
     1604            rc = vscsiLunMediumQueryRegionPropertiesForLba(pVScsiLun, uLbaStart,
     1605                                                           NULL, NULL, NULL, &enmDataForm);
     1606            AssertRC(rc);
     1607            if (   enmDataForm != VDREGIONDATAFORM_MODE1_2048
     1608                && enmDataForm != VDREGIONDATAFORM_MODE1_2352
     1609                && enmDataForm != VDREGIONDATAFORM_MODE2_2336
     1610                && enmDataForm != VDREGIONDATAFORM_MODE2_2352
     1611                && enmDataForm != VDREGIONDATAFORM_RAW
     1612                && cbSector == _2K)
     1613            {
     1614                rcReq = vscsiLunReqSenseErrorInfoSet(pVScsiLun, pVScsiReq,
     1615                                                     SCSI_SENSE_ILLEGAL_REQUEST | SCSI_SENSE_FLAG_ILI,
     1616                                                     SCSI_ASC_ILLEGAL_MODE_FOR_THIS_TRACK, 0, uLbaStart);
     1617                vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS);
     1618            }
     1619            else
     1620            {
     1621                /* Enqueue new I/O request */
     1622                rc = vscsiIoReqTransferEnqueueEx(pVScsiLun, pVScsiReq, enmTxDir,
     1623                                                 uLbaStart * cbSector,
     1624                                                 paSegs, cSegs, cSectorTransfer * cbSector);
     1625            }
    14451626        }
    14461627    }
     
    14621643static DECLCALLBACK(int) vscsiLunMmcMediumInserted(PVSCSILUNINT pVScsiLun)
    14631644{
     1645    int rc = VINF_SUCCESS;
    14641646    PVSCSILUNMMC pVScsiLunMmc = (PVSCSILUNMMC)pVScsiLun;
    1465     uint64_t cbDisk = 0;
    1466     int rc = vscsiLunMediumGetSize(pVScsiLun, &cbDisk);
     1647
     1648    pVScsiLunMmc->cSectors = 0;
     1649    uint32_t cTracks = vscsiLunMediumGetRegionCount(pVScsiLun);
     1650    for (uint32_t i = 0; i < cTracks && RT_SUCCESS(rc); i++)
     1651    {
     1652        uint64_t cBlocks = 0;
     1653        rc = vscsiLunMediumQueryRegionProperties(pVScsiLun, i, NULL, &cBlocks,
     1654                                                 NULL, NULL);
     1655        if (RT_FAILURE(rc))
     1656            break;
     1657        pVScsiLunMmc->cSectors += cBlocks;
     1658    }
     1659
    14671660    if (RT_SUCCESS(rc))
    14681661    {
    1469         pVScsiLunMmc->cSectors = cbDisk / pVScsiLunMmc->cbSector;
    1470 
    14711662        uint32_t OldStatus, NewStatus;
    14721663        do
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