- Timestamp:
- Apr 10, 2012 8:22:56 AM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 77360
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevATA.cpp
r40774 r40841 303 303 /** The revision string for SCSI INQUIRY commands. */ 304 304 char szInquiryRevision[ATAPI_INQUIRY_REVISION_LENGTH+1]; 305 306 uint8_t abAlignment3[7]; 305 /** Size of the current CUE sheet in bytes. */ 306 uint32_t cbCueSheet; 307 /** Align pbCueSheet correctly. */ 308 uint32_t u32Alignment3; 309 /** The current CUE Sheet if passthrough is used. */ 310 R3PTRTYPE(uint8_t *) pbCueSheet; 311 312 uint8_t abAlignment4[HC_ARCH_BITS == 64 ? 7 : 3]; 307 313 } ATADevState; 308 314 AssertCompileMemberAlignment(ATADevState, cTotalSectors, 8); … … 1127 1133 } 1128 1134 1135 /** 1136 * Compares two MSF values. 1137 * 1138 * @returns 1 if the first value is greater than the second value. 1139 * 0 if both are equal 1140 * -1 if the first value is smaller than the second value. 1141 */ 1142 DECLINLINE(int) atapiCmpMSF(const uint8_t *pbMSF1, const uint8_t *pbMSF2) 1143 { 1144 int iRes = 0; 1145 1146 for (unsigned i = 0; i < 3; i++) 1147 { 1148 if (pbMSF1[i] < pbMSF2[i]) 1149 { 1150 iRes = -1; 1151 break; 1152 } 1153 else if (pbMSF1[i] > pbMSF2[i]) 1154 { 1155 iRes = 1; 1156 break; 1157 } 1158 } 1159 1160 return iRes; 1161 } 1162 1163 /** 1164 * Return the correct sector size from the given LBA. 1165 * 1166 * @returns Sector size. 1167 * @param s ATA Device state. 1168 * @param iATAPILBA The LBA. 1169 */ 1170 static size_t atapiGetSectorSizeFromLba(ATADevState *s, uint32_t iATAPILBA) 1171 { 1172 size_t cbATAPISector = 2048; 1173 1174 /* 1175 * Check if there is a valid CUE Sheet we can use, 1176 * otherwise we just return the standard sector size. 1177 */ 1178 if (s->pbCueSheet) 1179 { 1180 uint8_t *pbCueSheetEntry = NULL; 1181 uint8_t iMSF[3]; 1182 1183 /* 1184 * Convert the LBA to the MSF format so we can look it up in the cue sheet. 1185 * Note that it is possible to have negative LBA values for the Lead-In area. 1186 * See MMC6 spec chapter 6.46.3.3 for more details. 1187 */ 1188 LogFlowFunc(("iATAPILBA=%#x (signed: %d unsigned: %u)\n", 1189 iATAPILBA, (int32_t)iATAPILBA, iATAPILBA)); 1190 1191 if ( iATAPILBA > UINT32_C(0xffff4fa1) 1192 && (int32_t)iATAPILBA < -150) 1193 { 1194 /* Lead-In area, this is always the first entry in the cue sheet. */ 1195 pbCueSheetEntry = s->pbCueSheet; 1196 LogFlowFunc(("Selected Lead-In area\n")); 1197 } 1198 else 1199 { 1200 iATAPILBA += 150; 1201 iMSF[0] = (iATAPILBA / 75) / 60; 1202 iMSF[1] = (iATAPILBA / 75) % 60; 1203 iMSF[2] = iATAPILBA % 75; 1204 1205 pbCueSheetEntry = s->pbCueSheet + 8; /* Start after the Lead-in track. */ 1206 1207 /* Go through the CUE sheet and find the correct entry. */ 1208 for (unsigned i = 0; i < (s->cbCueSheet / 8) - 2; i++) 1209 { 1210 if ( atapiCmpMSF(&pbCueSheetEntry[5], iMSF) != 1 1211 && atapiCmpMSF(&pbCueSheetEntry[8+5], iMSF) == 1) 1212 break; 1213 pbCueSheetEntry += 8; 1214 } 1215 LogFlowFunc(("Selected CUE sheet entry iMin=%u iSec=%u iFrame=%u\n", 1216 pbCueSheetEntry[5], pbCueSheetEntry[6], pbCueSheetEntry[7])); 1217 } 1218 1219 if (pbCueSheetEntry) 1220 { 1221 /* Determine size of main data based on the data form field. */ 1222 switch (pbCueSheetEntry[3] & 0x3f) 1223 { 1224 case 0x00: /* CD-DA with data. */ 1225 case 0x11: /* CD-ROM mode 1 */ 1226 case 0x13: 1227 case 0x21: /* CD-ROM XA, CD-I */ 1228 case 0x23: 1229 case 0x31: /* CD-ROM Mode 2 */ 1230 case 0x33: 1231 cbATAPISector = 2352; 1232 break; 1233 case 0x01: /* CD-DA without data (used for pauses between tracks). */ 1234 case 0x14: 1235 case 0x24: 1236 case 0x34: 1237 cbATAPISector = 0; 1238 break; 1239 case 0x10: /* CD-ROM mode 1 */ 1240 case 0x12: 1241 cbATAPISector = 2048; 1242 break; 1243 case 0x20: /* CD-ROM XA, CD-I */ 1244 case 0x22: 1245 case 0x30: /* CD-ROM Mode 2 */ 1246 case 0x32: 1247 cbATAPISector = 2336; 1248 break; 1249 default: /* Reserved, invalid mode. Log and leave default sector size. */ 1250 LogRel(("ATA: Invalid data form mode %u for current CUE sheet\n", 1251 pbCueSheetEntry[3] & 0x3f)); 1252 } 1253 1254 /* Determine size of sub channel data based on data form field. */ 1255 switch ((pbCueSheetEntry[3] & 0xc0) >> 6) 1256 { 1257 case 0x00: /* Sub channel all zeroes, autogenerated by the drive. */ 1258 break; 1259 case 0x01: 1260 case 0x03: 1261 cbATAPISector += 96; 1262 break; 1263 default: 1264 LogRel(("ATA: Invalid sub-channel data form mode %u for current CUE sheet\n", 1265 pbCueSheetEntry[3] & 0xc0)); 1266 } 1267 } 1268 } 1269 1270 LogFlowFunc(("cbATAPISector=%zu\n", cbATAPISector)); 1271 return cbATAPISector; 1272 } 1129 1273 1130 1274 static void ataCmdOK(ATADevState *s, uint8_t status) … … 1917 2061 PDMCritSectLeave(&pCtl->lock); 1918 2062 2063 #if defined(LOG_ENABLED) 2064 char szBuf[1024]; 2065 2066 memset(szBuf, 0, sizeof(szBuf)); 2067 2068 switch (s->aATAPICmd[0]) 2069 { 2070 case SCSI_MODE_SELECT_10: 2071 { 2072 size_t cbBlkDescLength = ataBE2H_U16(&s->CTX_SUFF(pbIOBuffer)[6]); 2073 2074 SCSILogModePage(szBuf, sizeof(szBuf) - 1, 2075 s->CTX_SUFF(pbIOBuffer) + 8 + cbBlkDescLength, 2076 cbTransfer - 8 - cbBlkDescLength); 2077 break; 2078 } 2079 case SCSI_SEND_CUE_SHEET: 2080 { 2081 SCSILogCueSheet(szBuf, sizeof(szBuf) - 1, 2082 s->CTX_SUFF(pbIOBuffer), cbTransfer); 2083 break; 2084 } 2085 default: 2086 break; 2087 } 2088 2089 Log2(("%s\n", szBuf)); 2090 #endif 2091 1919 2092 if (pProf) { STAM_PROFILE_ADV_START(pProf, b); } 1920 2093 if ( cbTransfer > SCSI_MAX_BUFFER_SIZE … … 2063 2236 if (RT_SUCCESS(rc)) 2064 2237 { 2238 /* Do post processing for certain commands. */ 2239 switch (s->aATAPICmd[0]) 2240 { 2241 case SCSI_SEND_CUE_SHEET: 2242 { 2243 /* Save the CUE sheet to determine sector sizes during writes */ 2244 if (s->pbCueSheet) 2245 { 2246 s->cbCueSheet = 0; 2247 RTMemFree(s->pbCueSheet); 2248 } 2249 2250 s->pbCueSheet = (uint8_t *)RTMemAllocZ(s->cbElementaryTransfer); 2251 if (s->pbCueSheet) 2252 { 2253 s->cbCueSheet = s->cbElementaryTransfer; 2254 memcpy(s->pbCueSheet, s->CTX_SUFF(pbIOBuffer), s->cbElementaryTransfer); 2255 } 2256 else if (s->cErrors++ < MAX_LOG_REL_ERRORS) 2257 LogRel(("ATA: Out of memory while saving the CUE sheet, burning disc might fail\n")); 2258 break; 2259 } 2260 case SCSI_SYNCHRONIZE_CACHE: 2261 { 2262 /* Free the current CUE sheet after session at once recording. */ 2263 if (s->pbCueSheet) 2264 { 2265 s->cbCueSheet = 0; 2266 RTMemFree(s->pbCueSheet); 2267 } 2268 break; 2269 } 2270 } 2271 2065 2272 if (s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE) 2066 2273 { … … 3557 3764 goto sendcmd; 3558 3765 case SCSI_WRITE_10: 3766 case SCSI_WRITE_AND_VERIFY_10: 3559 3767 iATAPILBA = ataBE2H_U32(pbPacket + 2); 3560 3768 cSectors = ataBE2H_U16(pbPacket + 7); 3561 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors)); 3562 #if 0 3563 /* The sector size is determined by the async I/O thread. */ 3564 s->cbATAPISector = 0; 3565 /* Preliminary, will be corrected once the sector size is known. */ 3566 cbTransfer = cSectors; 3567 #else 3568 s->cbATAPISector = 2048; /**< @todo this size is not always correct */ 3769 s->cbATAPISector = atapiGetSectorSizeFromLba(s, iATAPILBA); 3770 Log2(("ATAPI PT: lba %d sectors %d sector size %d\n", iATAPILBA, cSectors, s->cbATAPISector)); 3569 3771 cbTransfer = cSectors * s->cbATAPISector; 3570 #endif3571 3772 uTxDir = PDMBLOCKTXDIR_TO_DEVICE; 3572 3773 goto sendcmd; … … 3574 3775 iATAPILBA = ataBE2H_U32(pbPacket + 2); 3575 3776 cSectors = ataBE2H_U32(pbPacket + 6); 3576 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors)); 3577 #if 0 3578 /* The sector size is determined by the async I/O thread. */ 3579 s->cbATAPISector = 0; 3580 /* Preliminary, will be corrected once the sector size is known. */ 3581 cbTransfer = cSectors; 3582 #else 3583 s->cbATAPISector = 2048; /**< @todo this size is not always correct */ 3777 s->cbATAPISector = atapiGetSectorSizeFromLba(s, iATAPILBA); 3778 Log2(("ATAPI PT: lba %d sectors %d sector size %d\n", iATAPILBA, cSectors, s->cbATAPISector)); 3584 3779 cbTransfer = cSectors * s->cbATAPISector; 3585 #endif3586 uTxDir = PDMBLOCKTXDIR_TO_DEVICE;3587 goto sendcmd;3588 case SCSI_WRITE_AND_VERIFY_10:3589 iATAPILBA = ataBE2H_U32(pbPacket + 2);3590 cSectors = ataBE2H_U16(pbPacket + 7);3591 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));3592 /* The sector size is determined by the async I/O thread. */3593 s->cbATAPISector = 0;3594 /* Preliminary, will be corrected once the sector size is known. */3595 cbTransfer = cSectors;3596 3780 uTxDir = PDMBLOCKTXDIR_TO_DEVICE; 3597 3781 goto sendcmd; … … 4823 5007 { 4824 5008 dmalen = RT_MIN(cbBuffer, iIOBufferEnd - iIOBufferCur); 4825 Log2(("%s: DMA desc %#010x: addr=%#010x size=%#010x \n", __FUNCTION__,4826 (int)pDesc, pBuffer, cbBuffer ));5009 Log2(("%s: DMA desc %#010x: addr=%#010x size=%#010x orig_size=%#010x\n", __FUNCTION__, 5010 (int)pDesc, pBuffer, cbBuffer, RT_LE2H_U32(DMADesc.cbBuffer) & 0xfffe)); 4827 5011 if (uTxDir == PDMBLOCKTXDIR_FROM_DEVICE) 4828 5012 PDMDevHlpPhysWrite(pDevIns, pBuffer, s->CTX_SUFF(pbIOBuffer) + iIOBufferCur, dmalen); … … 6108 6292 LogRel(("PIIX3 ATA Dtor: Ctl#%u actually completed.\n", i)); 6109 6293 } 6294 } 6295 6296 for (uint32_t iIf = 0; iIf < RT_ELEMENTS(pThis->aCts[i].aIfs); iIf++) 6297 { 6298 if (pThis->aCts[i].aIfs[iIf].pbCueSheet) 6299 RTMemFree(pThis->aCts[i].aIfs[iIf].pbCueSheet); 6110 6300 } 6111 6301 } -
trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
r40040 r40841 811 811 GEN_CHECK_OFF(ATADevState, szInquiryRevision); 812 812 GEN_CHECK_OFF(ATADevState, szInquiryRevision[ATAPI_INQUIRY_REVISION_LENGTH]); 813 GEN_CHECK_OFF(ATADevState, cbCueSheet); 814 GEN_CHECK_OFF(ATADevState, pbCueSheet); 813 815 GEN_CHECK_SIZE(ATATransferRequest); 814 816 GEN_CHECK_OFF(ATATransferRequest, iIf);
Note:
See TracChangeset
for help on using the changeset viewer.