Changeset 66955 in vbox for trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunMmc.cpp
- Timestamp:
- May 18, 2017 3:57:16 PM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 115496
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunMmc.cpp
r66164 r66955 73 73 /** Size of the virtual disk. */ 74 74 uint64_t cSectors; 75 /** Sector size. */76 uint32_t cbSector;77 75 /** Medium locked indicator. */ 78 76 bool fLocked; … … 144 142 static int mmcReadTOCNormal(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq, uint16_t cbMaxTransfer, bool fMSF) 145 143 { 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. */ 148 145 uint8_t *pbBuf = aReply; 149 146 uint8_t *q; 150 147 uint8_t iStartTrack; 151 148 uint32_t cbSize; 149 uint32_t cTracks = vscsiLunMediumGetRegionCount(pVScsiLun); 152 150 153 151 iStartTrack = pVScsiReq->pbCDB[6]; 154 if (iStartTrack > 1 && iStartTrack != 0xaa) 155 { 152 if (iStartTrack == 0) 153 iStartTrack = 1; 154 if (iStartTrack > cTracks && iStartTrack != 0xaa) 156 155 return vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 157 } 156 158 157 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 */ 167 178 if (fMSF) 168 179 { 169 *q++ = 0; 170 scsiLBA2MSF(q, 0);180 *q++ = 0; /* reserved */ 181 scsiLBA2MSF(q, (uint32_t)uLbaStart); 171 182 q += 3; 172 183 } … … 174 185 { 175 186 /* sector 0 */ 176 scsiH2BE_U32(q, 0);187 scsiH2BE_U32(q, (uint32_t)uLbaStart); 177 188 q += 4; 178 189 } 179 190 } 180 191 /* 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; 185 206 if (fMSF) 186 207 { 187 *q++ = 0; 188 scsiLBA2MSF(q, pVScsiLunMmc->cSectors);208 *q++ = 0; /* reserved */ 209 scsiLBA2MSF(q, (uint32_t)uLbaStart); 189 210 q += 3; 190 211 } 191 212 else 192 213 { 193 scsiH2BE_U32(q, pVScsiLunMmc->cSectors);214 scsiH2BE_U32(q, (uint32_t)uLbaStart); 194 215 q += 4; 195 216 } … … 201 222 202 223 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, cbMaxTransfer); 203 204 224 return vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 205 225 } … … 217 237 pbBuf[2] = 0x01; /* first complete session number */ 218 238 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 220 250 pbBuf[6] = 1; /* first track in last complete session */ 221 251 … … 855 885 } 856 886 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 */ 895 static 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 857 987 static DECLCALLBACK(int) vscsiLunMmcInit(PVSCSILUNINT pVScsiLun) 858 988 { 859 989 PVSCSILUNMMC pVScsiLunMmc = (PVSCSILUNMMC)pVScsiLun; 860 uint64_t cbDisk = 0;861 990 int rc = VINF_SUCCESS; 862 991 863 992 ASMAtomicWriteU32((volatile uint32_t *)&pVScsiLunMmc->MediaEventStatus, MMCEVENTSTATUSTYPE_UNCHANGED); 864 993 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 } 869 1006 870 1007 return rc; … … 883 1020 uint64_t uLbaStart = 0; 884 1021 uint32_t cSectorTransfer = 0; 1022 size_t cbSector = 0; 885 1023 int rc = VINF_SUCCESS; 886 1024 int rcReq = SCSI_STATUS_OK; … … 963 1101 else 964 1102 scsiH2BE_U32(aReply, pVScsiLunMmc->cSectors - 1); 965 scsiH2BE_U32(&aReply[4], pVScsiLunMmc->cbSector);1103 scsiH2BE_U32(&aReply[4], _2K); 966 1104 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply)); 967 1105 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); … … 1035 1173 | ((pVScsiReq->pbCDB[1] & 0x1f) << 16)); 1036 1174 cSectorTransfer = pVScsiReq->pbCDB[4]; 1175 cbSector = _2K; 1037 1176 break; 1038 1177 } … … 1042 1181 uLbaStart = scsiBE2H_U32(&pVScsiReq->pbCDB[2]); 1043 1182 cSectorTransfer = scsiBE2H_U16(&pVScsiReq->pbCDB[7]); 1183 cbSector = _2K; 1044 1184 break; 1045 1185 } … … 1049 1189 uLbaStart = scsiBE2H_U32(&pVScsiReq->pbCDB[2]); 1050 1190 cSectorTransfer = scsiBE2H_U32(&pVScsiReq->pbCDB[6]); 1191 cbSector = _2K; 1051 1192 break; 1052 1193 } … … 1056 1197 uLbaStart = scsiBE2H_U64(&pVScsiReq->pbCDB[2]); 1057 1198 cSectorTransfer = scsiBE2H_U32(&pVScsiReq->pbCDB[10]); 1199 cbSector = _2K; 1058 1200 break; 1059 1201 } … … 1062 1204 uLbaStart = scsiBE2H_U32(&pVScsiReq->pbCDB[2]); 1063 1205 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) 1065 1223 { 1066 case 0x00: 1224 if (uChnSel == 0) 1225 { 1067 1226 /* nothing */ 1068 1227 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 1069 break;1070 case 0x10:1071 /* normal read */1228 } 1229 else 1230 { 1072 1231 enmTxDir = VSCSIIOREQTXDIR_READ; 1073 break; 1074 case 0xf8: 1232 cbSector = 2352; 1233 } 1234 } 1235 else 1236 { 1237 switch (uChnSel) 1075 1238 { 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: 1086 1249 { 1087 size_t cbTmp = RTSgBufAdvance(&SgBuf, 16); 1088 if (cbTmp < 16) 1250 if (cbSectorRegion == 2048) 1089 1251 { 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); 1125 1261 for (uint32_t uLba = (uint32_t)uLbaStart; uLba < uLbaStart + cSectorTransfer; uLba++) 1126 1262 { 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; 1138 1271 while (cbTmp) 1139 1272 { 1140 1273 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 } 1144 1280 1145 1281 cbTmp -= cbBuf; 1282 cSegsNew++; 1146 1283 } 1147 1284 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 } 1155 1291 } 1156 1292 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); 1160 1344 } 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; 1164 1352 } 1165 else1353 default: 1166 1354 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; 1169 1357 } 1170 default:1171 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST,1172 SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);1173 break;1174 1358 } 1175 1359 break; … … 1269 1453 memset(aReply, 0, sizeof(aReply)); 1270 1454 scsiH2BE_U64(aReply, pVScsiLunMmc->cSectors - 1); 1271 scsiH2BE_U32(&aReply[8], pVScsiLunMmc->cbSector);1455 scsiH2BE_U32(&aReply[8], _2K); 1272 1456 /* Leave the rest 0 */ 1273 1457 … … 1358 1542 aReply[4] = 1; /* number of sessions (LSB) */ 1359 1543 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) */ 1361 1545 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 */ 1362 1546 aReply[8] = 0; /* disc type = CD-ROM */ … … 1373 1557 { 1374 1558 size_t cbMax = scsiBE2H_U16(&pVScsiReq->pbCDB[7]); 1375 1376 1559 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); 1400 1561 break; 1401 1562 } … … 1425 1586 __FUNCTION__, uLbaStart, cSectorTransfer)); 1426 1587 1427 vscsiReqSetXferSize(pVScsiReq, cSectorTransfer * pVScsiLunMmc->cbSector);1588 vscsiReqSetXferSize(pVScsiReq, cSectorTransfer * cbSector); 1428 1589 if (RT_UNLIKELY(uLbaStart + cSectorTransfer > pVScsiLunMmc->cSectors)) 1429 1590 { … … 1439 1600 else 1440 1601 { 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 } 1445 1626 } 1446 1627 } … … 1462 1643 static DECLCALLBACK(int) vscsiLunMmcMediumInserted(PVSCSILUNINT pVScsiLun) 1463 1644 { 1645 int rc = VINF_SUCCESS; 1464 1646 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 1467 1660 if (RT_SUCCESS(rc)) 1468 1661 { 1469 pVScsiLunMmc->cSectors = cbDisk / pVScsiLunMmc->cbSector;1470 1471 1662 uint32_t OldStatus, NewStatus; 1472 1663 do
Note:
See TracChangeset
for help on using the changeset viewer.