Changeset 65965 in vbox
- Timestamp:
- Mar 7, 2017 10:45:04 AM (8 years ago)
- File:
-
- 1 edited
-
trunk/src/VBox/Devices/Storage/DrvHostDVD.cpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DrvHostDVD.cpp
r65113 r65965 93 93 94 94 95 /** 96 * Parse the CDB and check whether it can be passed through safely. 97 * 98 * @returns Flag whether to passthrough to the device is considered safe. 99 * @param pThis The host DVD driver instance. 100 * @param pReq The request. 101 * @param pbCdb The CDB to parse. 102 * @param cbCdb Size of the CDB in bytes. 103 * @param cbBuf Size of the guest buffer. 104 * @param penmTxDir Where to store the transfer direction (guest to host or vice versa). 105 * @param pcbXfer Where to store the transfer size encoded in the CDB. 106 * @param pcbSector Where to store the sector size used for the transfer. 107 * @param pu8ScsiSts Where to store the SCSI status code. 108 */ 95 109 static bool drvHostDvdParseCdb(PDRVHOSTDVD pThis, PDRVHOSTBASEREQ pReq, 96 110 const uint8_t *pbCdb, size_t cbCdb, size_t cbBuf, … … 98 112 size_t *pcbSector, uint8_t *pu8ScsiSts) 99 113 { 100 uint32_t uLba = 0;101 uint32_t cSectors = 0;102 size_t cbSector = 0;103 size_t cbXfer = 0;104 114 bool fPassthrough = false; 105 PDMMEDIATXDIR enmTxDir = PDMMEDIATXDIR_NONE; 106 107 RT_NOREF(cbCdb); 108 109 switch (pbCdb[0]) 115 116 if ( pbCdb[0] == SCSI_REQUEST_SENSE 117 && (pThis->abATAPISense[2] & 0x0f) != SCSI_SENSE_NONE) 110 118 { 111 /* First the commands we can pass through without further processing. */ 112 case SCSI_BLANK: 113 case SCSI_CLOSE_TRACK_SESSION: 114 case SCSI_LOAD_UNLOAD_MEDIUM: 115 case SCSI_PAUSE_RESUME: 116 case SCSI_PLAY_AUDIO_10: 117 case SCSI_PLAY_AUDIO_12: 118 case SCSI_PLAY_AUDIO_MSF: 119 case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL: 120 case SCSI_REPAIR_TRACK: 121 case SCSI_RESERVE_TRACK: 122 case SCSI_SCAN: 123 case SCSI_SEEK_10: 124 case SCSI_SET_CD_SPEED: 125 case SCSI_SET_READ_AHEAD: 126 case SCSI_START_STOP_UNIT: 127 case SCSI_STOP_PLAY_SCAN: 128 case SCSI_SYNCHRONIZE_CACHE: 129 case SCSI_TEST_UNIT_READY: 130 case SCSI_VERIFY_10: 131 fPassthrough = true; 132 break; 133 case SCSI_ERASE_10: 134 uLba = scsiBE2H_U32(pbCdb + 2); 135 cbXfer = scsiBE2H_U16(pbCdb + 7); 136 enmTxDir = PDMMEDIATXDIR_TO_DEVICE; 137 fPassthrough = true; 138 break; 139 case SCSI_FORMAT_UNIT: 140 cbXfer = cbBuf; 141 enmTxDir = PDMMEDIATXDIR_TO_DEVICE; 142 fPassthrough = true; 143 break; 144 case SCSI_GET_CONFIGURATION: 145 cbXfer = scsiBE2H_U16(pbCdb + 7); 146 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE; 147 fPassthrough = true; 148 break; 149 case SCSI_GET_EVENT_STATUS_NOTIFICATION: 150 cbXfer = scsiBE2H_U16(pbCdb + 7); 151 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE; 152 fPassthrough = true; 153 break; 154 case SCSI_GET_PERFORMANCE: 155 cbXfer = cbBuf; 156 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE; 157 fPassthrough = true; 158 break; 159 case SCSI_INQUIRY: 160 cbXfer = scsiBE2H_U16(pbCdb + 3); 161 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE; 162 fPassthrough = true; 163 break; 164 case SCSI_MECHANISM_STATUS: 165 cbXfer = scsiBE2H_U16(pbCdb + 8); 166 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE; 167 fPassthrough = true; 168 break; 169 case SCSI_MODE_SELECT_10: 170 cbXfer = scsiBE2H_U16(pbCdb + 7); 171 enmTxDir = PDMMEDIATXDIR_TO_DEVICE; 172 fPassthrough = true; 173 break; 174 case SCSI_MODE_SENSE_10: 175 cbXfer = scsiBE2H_U16(pbCdb + 7); 176 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE; 177 fPassthrough = true; 178 break; 179 case SCSI_READ_10: 180 uLba = scsiBE2H_U32(pbCdb + 2); 181 cSectors = scsiBE2H_U16(pbCdb + 7); 182 cbSector = 2048; 183 cbXfer = cSectors * cbSector; 184 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE; 185 fPassthrough = true; 186 break; 187 case SCSI_READ_12: 188 uLba = scsiBE2H_U32(pbCdb + 2); 189 cSectors = scsiBE2H_U32(pbCdb + 6); 190 cbSector = 2048; 191 cbXfer = cSectors * cbSector; 192 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE; 193 fPassthrough = true; 194 break; 195 case SCSI_READ_BUFFER: 196 cbXfer = scsiBE2H_U24(pbCdb + 6); 197 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE; 198 fPassthrough = true; 199 break; 200 case SCSI_READ_BUFFER_CAPACITY: 201 cbXfer = scsiBE2H_U16(pbCdb + 7); 202 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE; 203 fPassthrough = true; 204 break; 205 case SCSI_READ_CAPACITY: 206 cbXfer = 8; 207 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE; 208 fPassthrough = true; 209 break; 210 case SCSI_READ_CD: 211 case SCSI_READ_CD_MSF: 119 /* Handle the command here and copy sense data over. */ 120 void *pvBuf = NULL; 121 int rc = drvHostBaseBufferRetain(&pThis->Core, pReq, cbBuf, false /*fWrite*/, &pvBuf); 122 if (RT_SUCCESS(rc)) 212 123 { 213 /* Get sector size based on the expected sector type field. */ 214 switch ((pbCdb[1] >> 2) & 0x7) 215 { 216 case 0x0: /* All types. */ 217 { 218 uint32_t iLbaStart; 219 220 if (pbCdb[0] == SCSI_READ_CD) 221 iLbaStart = scsiBE2H_U32(&pbCdb[2]); 222 else 223 iLbaStart = scsiMSF2LBA(&pbCdb[3]); 224 225 if (pThis->pTrackList) 226 cbSector = ATAPIPassthroughTrackListGetSectorSizeFromLba(pThis->pTrackList, iLbaStart); 227 else 228 cbSector = 2048; /* Might be incorrect if we couldn't determine the type. */ 229 break; 230 } 231 case 0x1: /* CD-DA */ 232 cbSector = 2352; 233 break; 234 case 0x2: /* Mode 1 */ 235 cbSector = 2048; 236 break; 237 case 0x3: /* Mode 2 formless */ 238 cbSector = 2336; 239 break; 240 case 0x4: /* Mode 2 form 1 */ 241 cbSector = 2048; 242 break; 243 case 0x5: /* Mode 2 form 2 */ 244 cbSector = 2324; 245 break; 246 default: /* Reserved */ 247 AssertMsgFailed(("Unknown sector type\n")); 248 cbSector = 0; /** @todo we should probably fail the command here already. */ 249 } 250 251 if (pbCdb[0] == SCSI_READ_CD) 252 cbXfer = scsiBE2H_U24(pbCdb + 6) * cbSector; 253 else /* SCSI_READ_MSF */ 254 { 255 cSectors = scsiMSF2LBA(pbCdb + 6) - scsiMSF2LBA(pbCdb + 3); 256 if (cSectors > 32) 257 cSectors = 32; /* Limit transfer size to 64~74K. Safety first. In any case this can only harm software doing CDDA extraction. */ 258 cbXfer = cSectors * cbSector; 259 } 260 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE; 261 fPassthrough = true; 262 break; 124 memcpy(pvBuf, &pThis->abATAPISense[0], RT_MIN(sizeof(pThis->abATAPISense), cbBuf)); 125 rc = drvHostBaseBufferRelease(&pThis->Core, pReq, cbBuf, false /* fWrite */, pvBuf); 126 AssertRC(rc); 127 drvHostDvdCmdOK(pThis); 128 *pu8ScsiSts = SCSI_STATUS_OK; 263 129 } 264 case SCSI_READ_DISC_INFORMATION:265 cbXfer = scsiBE2H_U16(pbCdb + 7);266 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE;267 fPassthrough = true;268 break;269 case SCSI_READ_DVD_STRUCTURE:270 cbXfer = scsiBE2H_U16(pbCdb + 8);271 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE;272 fPassthrough = true;273 break;274 case SCSI_READ_FORMAT_CAPACITIES:275 cbXfer = scsiBE2H_U16(pbCdb + 7);276 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE;277 fPassthrough = true;278 break;279 case SCSI_READ_SUBCHANNEL:280 cbXfer = scsiBE2H_U16(pbCdb + 7);281 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE;282 fPassthrough = true;283 break;284 case SCSI_READ_TOC_PMA_ATIP:285 cbXfer = scsiBE2H_U16(pbCdb + 7);286 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE;287 fPassthrough = true;288 break;289 case SCSI_READ_TRACK_INFORMATION:290 cbXfer = scsiBE2H_U16(pbCdb + 7);291 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE;292 fPassthrough = true;293 break;294 case SCSI_REPORT_KEY:295 cbXfer = scsiBE2H_U16(pbCdb + 8);296 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE;297 fPassthrough = true;298 break;299 case SCSI_REQUEST_SENSE:300 cbXfer = pbCdb[4];301 if ((pThis->abATAPISense[2] & 0x0f) != SCSI_SENSE_NONE)302 {303 /* Copy sense data over. */304 void *pvBuf = NULL;305 int rc = drvHostBaseBufferRetain(&pThis->Core, pReq, cbBuf, false /*fWrite*/, &pvBuf);306 if (RT_SUCCESS(rc))307 {308 memcpy(pvBuf, &pThis->abATAPISense[0], RT_MIN(sizeof(pThis->abATAPISense), cbBuf));309 rc = drvHostBaseBufferRelease(&pThis->Core, pReq, cbBuf, false /* fWrite */, pvBuf);310 AssertRC(rc);311 drvHostDvdCmdOK(pThis);312 *pu8ScsiSts = SCSI_STATUS_OK;313 }314 break;315 }316 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE;317 fPassthrough = true;318 break;319 case SCSI_SEND_CUE_SHEET:320 cbXfer = scsiBE2H_U24(pbCdb + 6);321 enmTxDir = PDMMEDIATXDIR_TO_DEVICE;322 fPassthrough = true;323 break;324 case SCSI_SEND_DVD_STRUCTURE:325 cbXfer = scsiBE2H_U16(pbCdb + 8);326 enmTxDir = PDMMEDIATXDIR_TO_DEVICE;327 fPassthrough = true;328 break;329 case SCSI_SEND_EVENT:330 cbXfer = scsiBE2H_U16(pbCdb + 8);331 enmTxDir = PDMMEDIATXDIR_TO_DEVICE;332 fPassthrough = true;333 break;334 case SCSI_SEND_KEY:335 cbXfer = scsiBE2H_U16(pbCdb + 8);336 enmTxDir = PDMMEDIATXDIR_TO_DEVICE;337 fPassthrough = true;338 break;339 case SCSI_SEND_OPC_INFORMATION:340 cbXfer = scsiBE2H_U16(pbCdb + 7);341 enmTxDir = PDMMEDIATXDIR_TO_DEVICE;342 fPassthrough = true;343 break;344 case SCSI_SET_STREAMING:345 cbXfer = scsiBE2H_U16(pbCdb + 9);346 enmTxDir = PDMMEDIATXDIR_TO_DEVICE;347 fPassthrough = true;348 break;349 case SCSI_WRITE_10:350 case SCSI_WRITE_AND_VERIFY_10:351 uLba = scsiBE2H_U32(pbCdb + 2);352 cSectors = scsiBE2H_U16(pbCdb + 7);353 if (pThis->pTrackList)354 cbSector = ATAPIPassthroughTrackListGetSectorSizeFromLba(pThis->pTrackList, uLba);355 else356 cbSector = 2048;357 cbXfer = cSectors * cbSector;358 enmTxDir = PDMMEDIATXDIR_TO_DEVICE;359 fPassthrough = true;360 break;361 case SCSI_WRITE_12:362 uLba = scsiBE2H_U32(pbCdb + 2);363 cSectors = scsiBE2H_U32(pbCdb + 6);364 if (pThis->pTrackList)365 cbSector = ATAPIPassthroughTrackListGetSectorSizeFromLba(pThis->pTrackList, uLba);366 else367 cbSector = 2048;368 cbXfer = cSectors * cbSector;369 enmTxDir = PDMMEDIATXDIR_TO_DEVICE;370 fPassthrough = true;371 break;372 case SCSI_WRITE_BUFFER:373 switch (pbCdb[1] & 0x1f)374 {375 case 0x04: /* download microcode */376 case 0x05: /* download microcode and save */377 case 0x06: /* download microcode with offsets */378 case 0x07: /* download microcode with offsets and save */379 case 0x0e: /* download microcode with offsets and defer activation */380 case 0x0f: /* activate deferred microcode */381 LogRel(("HostDVD#%u: CD-ROM passthrough command attempted to update firmware, blocked\n", pThis->Core.pDrvIns->iInstance));382 *pu8ScsiSts = drvHostDvdCmdErrorSimple(pThis, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);383 break;384 default:385 cbXfer = scsiBE2H_U16(pbCdb + 6);386 enmTxDir = PDMMEDIATXDIR_TO_DEVICE;387 fPassthrough = true;388 break;389 }390 break;391 case SCSI_REPORT_LUNS: /* Not part of MMC-3, but used by Windows. */392 cbXfer = scsiBE2H_U32(pbCdb + 6);393 enmTxDir = PDMMEDIATXDIR_FROM_DEVICE;394 fPassthrough = true;395 break;396 case SCSI_REZERO_UNIT:397 /* Obsolete command used by cdrecord. What else would one expect?398 * This command is not sent to the drive, it is handled internally,399 * as the Linux kernel doesn't like it (message "scsi: unknown400 * opcode 0x01" in syslog) and replies with a sense code of 0,401 * which sends cdrecord to an endless loop. */402 *pu8ScsiSts = drvHostDvdCmdErrorSimple(pThis, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);403 break;404 default:405 LogRel(("HostDVD#%u: Passthrough unimplemented for command %#x\n", pThis->Core.pDrvIns->iInstance, pbCdb[0]));406 *pu8ScsiSts = drvHostDvdCmdErrorSimple(pThis, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);407 break;408 130 } 409 410 if (fPassthrough) 411 { 412 *penmTxDir = enmTxDir; 413 *pcbXfer = cbXfer; 414 *pcbSector = cbSector; 415 } 131 else 132 fPassthrough = ATAPIPassthroughParseCdb(pbCdb, cbCdb, cbBuf, pThis->pTrackList, 133 &pThis->abATAPISense[0], sizeof(pThis->abATAPISense), 134 penmTxDir, pcbXfer, pcbSector, pu8ScsiSts); 416 135 417 136 return fPassthrough; 418 137 } 138 419 139 420 140 /**
Note:
See TracChangeset
for help on using the changeset viewer.

