Changeset 50282 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Jan 30, 2014 11:20:09 AM (11 years ago)
- Location:
- trunk/src/VBox/Devices/Storage
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevAHCI.cpp
r50037 r50282 4142 4142 { 4143 4143 case 0x0: /* Physical format information */ 4144 { 4145 int layer = pAhciReq->aATAPICmd[6]; 4146 uint64_t total_sectors; 4147 4148 if (layer != 0) 4144 4149 { 4145 int layer = pAhciReq->aATAPICmd[6]; 4146 uint64_t total_sectors; 4147 4148 if (layer != 0) 4149 { 4150 uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET; 4151 break; 4152 } 4153 4154 total_sectors = pAhciPort->cTotalSectors; 4155 total_sectors >>= 2; 4156 if (total_sectors == 0) 4157 { 4158 uASC = -SCSI_ASC_MEDIUM_NOT_PRESENT; 4159 break; 4160 } 4161 4162 buf[4] = 1; /* DVD-ROM, part version 1 */ 4163 buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ 4164 buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ 4165 buf[7] = 0; /* default densities */ 4166 4167 /* FIXME: 0x30000 per spec? */ 4168 ataH2BE_U32(buf + 8, 0); /* start sector */ 4169 ataH2BE_U32(buf + 12, total_sectors - 1); /* end sector */ 4170 ataH2BE_U32(buf + 16, total_sectors - 1); /* l0 end sector */ 4171 4172 /* Size of buffer, not including 2 byte size field */ 4173 ataH2BE_U32(&buf[0], 2048 + 2); 4174 4175 /* 2k data + 4 byte header */ 4176 uASC = (2048 + 4); 4150 uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET; 4151 break; 4177 4152 } 4153 4154 total_sectors = pAhciPort->cTotalSectors; 4155 total_sectors >>= 2; 4156 if (total_sectors == 0) 4157 { 4158 uASC = -SCSI_ASC_MEDIUM_NOT_PRESENT; 4159 break; 4160 } 4161 4162 buf[4] = 1; /* DVD-ROM, part version 1 */ 4163 buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ 4164 buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ 4165 buf[7] = 0; /* default densities */ 4166 4167 /* FIXME: 0x30000 per spec? */ 4168 ataH2BE_U32(buf + 8, 0); /* start sector */ 4169 ataH2BE_U32(buf + 12, total_sectors - 1); /* end sector */ 4170 ataH2BE_U32(buf + 16, total_sectors - 1); /* l0 end sector */ 4171 4172 /* Size of buffer, not including 2 byte size field */ 4173 ataH2BE_U32(&buf[0], 2048 + 2); 4174 4175 /* 2k data + 4 byte header */ 4176 uASC = (2048 + 4); 4178 4177 break; 4178 } 4179 4179 case 0x01: /* DVD copyright information */ 4180 4180 buf[4] = 0; /* no copyright data */ … … 4346 4346 static AHCITXDIR atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIREQ pAhciReq) 4347 4347 { 4348 AHCITXDIR rc= AHCITXDIR_NONE;4348 AHCITXDIR enmTxDir = AHCITXDIR_NONE; 4349 4349 const uint8_t *pbPacket; 4350 4350 uint32_t cbMax; … … 4374 4374 break; 4375 4375 case SCSI_MODE_SENSE_10: 4376 { 4377 uint8_t uPageControl, uPageCode; 4378 cbMax = ataBE2H_U16(pbPacket + 7); 4379 uPageControl = pbPacket[2] >> 6; 4380 uPageCode = pbPacket[2] & 0x3f; 4381 switch (uPageControl) 4376 4382 { 4377 uint8_t uPageControl, uPageCode; 4378 cbMax = ataBE2H_U16(pbPacket + 7); 4379 uPageControl = pbPacket[2] >> 6; 4380 uPageCode = pbPacket[2] & 0x3f; 4381 switch (uPageControl) 4382 { 4383 case SCSI_PAGECONTROL_CURRENT: 4384 switch (uPageCode) 4385 { 4386 case SCSI_MODEPAGE_ERROR_RECOVERY: 4387 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY); 4388 break; 4389 case SCSI_MODEPAGE_CD_STATUS: 4390 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS); 4391 break; 4392 default: 4393 goto error_cmd; 4394 } 4395 break; 4396 case SCSI_PAGECONTROL_CHANGEABLE: 4397 goto error_cmd; 4398 case SCSI_PAGECONTROL_DEFAULT: 4399 goto error_cmd; 4400 default: 4401 case SCSI_PAGECONTROL_SAVED: 4402 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED); 4403 break; 4404 } 4383 case SCSI_PAGECONTROL_CURRENT: 4384 switch (uPageCode) 4385 { 4386 case SCSI_MODEPAGE_ERROR_RECOVERY: 4387 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY); 4388 break; 4389 case SCSI_MODEPAGE_CD_STATUS: 4390 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS); 4391 break; 4392 default: 4393 goto error_cmd; 4394 } 4395 break; 4396 case SCSI_PAGECONTROL_CHANGEABLE: 4397 goto error_cmd; 4398 case SCSI_PAGECONTROL_DEFAULT: 4399 goto error_cmd; 4400 default: 4401 case SCSI_PAGECONTROL_SAVED: 4402 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED); 4403 break; 4405 4404 } 4406 4405 break; 4406 } 4407 4407 case SCSI_REQUEST_SENSE: 4408 4408 cbMax = pbPacket[4]; … … 4423 4423 case SCSI_READ_10: 4424 4424 case SCSI_READ_12: 4425 { 4426 uint32_t cSectors, iATAPILBA; 4427 4428 if (pAhciPort->cNotifiedMediaChange > 0) 4425 4429 { 4426 uint32_t cSectors, iATAPILBA; 4427 4428 if (pAhciPort->cNotifiedMediaChange > 0) 4430 pAhciPort->cNotifiedMediaChange-- ; 4431 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 4432 break; 4433 } 4434 if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 4435 { 4436 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4437 break; 4438 } 4439 if (pbPacket[0] == SCSI_READ_10) 4440 cSectors = ataBE2H_U16(pbPacket + 7); 4441 else 4442 cSectors = ataBE2H_U32(pbPacket + 6); 4443 iATAPILBA = ataBE2H_U32(pbPacket + 2); 4444 if (cSectors == 0) 4445 { 4446 atapiCmdOK(pAhciPort, pAhciReq); 4447 break; 4448 } 4449 if ((uint64_t)iATAPILBA + cSectors > pAhciPort->cTotalSectors) 4450 { 4451 /* Rate limited logging, one log line per second. For 4452 * guests that insist on reading from places outside the 4453 * valid area this often generates too many release log 4454 * entries otherwise. */ 4455 static uint64_t s_uLastLogTS = 0; 4456 if (RTTimeMilliTS() >= s_uLastLogTS + 1000) 4429 4457 { 4430 pAhciPort->cNotifiedMediaChange-- ; 4431 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 4458 LogRel(("AHCI ATAPI: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA + cSectors)); 4459 s_uLastLogTS = RTTimeMilliTS(); 4460 } 4461 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 4462 break; 4463 } 4464 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048); 4465 enmTxDir = AHCITXDIR_READ; 4466 break; 4467 } 4468 case SCSI_READ_CD: 4469 { 4470 uint32_t cSectors, iATAPILBA; 4471 4472 if (pAhciPort->cNotifiedMediaChange > 0) 4473 { 4474 pAhciPort->cNotifiedMediaChange-- ; 4475 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 4476 break; 4477 } 4478 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 4479 { 4480 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4481 break; 4482 } 4483 cSectors = (pbPacket[6] << 16) | (pbPacket[7] << 8) | pbPacket[8]; 4484 iATAPILBA = ataBE2H_U32(pbPacket + 2); 4485 if (cSectors == 0) 4486 { 4487 atapiCmdOK(pAhciPort, pAhciReq); 4488 break; 4489 } 4490 if ((uint64_t)iATAPILBA + cSectors > pAhciPort->cTotalSectors) 4491 { 4492 /* Rate limited logging, one log line per second. For 4493 * guests that insist on reading from places outside the 4494 * valid area this often generates too many release log 4495 * entries otherwise. */ 4496 static uint64_t s_uLastLogTS = 0; 4497 if (RTTimeMilliTS() >= s_uLastLogTS + 1000) 4498 { 4499 LogRel(("AHCI ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA + cSectors)); 4500 s_uLastLogTS = RTTimeMilliTS(); 4501 } 4502 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 4503 break; 4504 } 4505 switch (pbPacket[9] & 0xf8) 4506 { 4507 case 0x00: 4508 /* nothing */ 4509 atapiCmdOK(pAhciPort, pAhciReq); 4510 break; 4511 case 0x10: 4512 /* normal read */ 4513 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048); 4514 enmTxDir = AHCITXDIR_READ; 4515 break; 4516 case 0xf8: 4517 /* read all data */ 4518 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2352); 4519 enmTxDir = AHCITXDIR_READ; 4520 break; 4521 default: 4522 LogRel(("AHCI ATAPI: LUN#%d: CD-ROM sector format not supported\n", pAhciPort->iLUN)); 4523 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 4524 break; 4525 } 4526 break; 4527 } 4528 case SCSI_SEEK_10: 4529 { 4530 uint32_t iATAPILBA; 4531 if (pAhciPort->cNotifiedMediaChange > 0) 4532 { 4533 pAhciPort->cNotifiedMediaChange-- ; 4534 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 4535 break; 4536 } 4537 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 4538 { 4539 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4540 break; 4541 } 4542 iATAPILBA = ataBE2H_U32(pbPacket + 2); 4543 if (iATAPILBA > pAhciPort->cTotalSectors) 4544 { 4545 /* Rate limited logging, one log line per second. For 4546 * guests that insist on seeking to places outside the 4547 * valid area this often generates too many release log 4548 * entries otherwise. */ 4549 static uint64_t s_uLastLogTS = 0; 4550 if (RTTimeMilliTS() >= s_uLastLogTS + 1000) 4551 { 4552 LogRel(("AHCI ATAPI: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA)); 4553 s_uLastLogTS = RTTimeMilliTS(); 4554 } 4555 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 4556 break; 4557 } 4558 atapiCmdOK(pAhciPort, pAhciReq); 4559 pAhciReq->uATARegStatus |= ATA_STAT_SEEK; /* Linux expects this. */ 4560 break; 4561 } 4562 case SCSI_START_STOP_UNIT: 4563 { 4564 int rc = VINF_SUCCESS; 4565 switch (pbPacket[4] & 3) 4566 { 4567 case 0: /* 00 - Stop motor */ 4568 case 1: /* 01 - Start motor */ 4569 break; 4570 case 2: /* 10 - Eject media */ 4571 { 4572 /* This must be done from EMT. */ 4573 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci); 4574 PPDMDEVINS pDevIns = pAhci->CTX_SUFF(pDevIns); 4575 4576 rc = VMR3ReqPriorityCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY, 4577 (PFNRT)pAhciPort->pDrvMount->pfnUnmount, 3, 4578 pAhciPort->pDrvMount, false/*=fForce*/, true/*=fEject*/); 4579 Assert(RT_SUCCESS(rc) || rc == VERR_PDM_MEDIA_LOCKED || rc = VERR_PDM_MEDIA_NOT_MOUNTED); 4580 if (RT_SUCCESS(rc) && pAhci->pMediaNotify) 4581 { 4582 rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY, 4583 (PFNRT)pAhci->pMediaNotify->pfnEjected, 2, 4584 pAhci->pMediaNotify, pAhciPort->iLUN); 4585 AssertRC(rc); 4586 } 4432 4587 break; 4433 4588 } 4434 if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 4435 { 4436 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4589 case 3: /* 11 - Load media */ 4590 /** @todo rc = s->pDrvMount->pfnLoadMedia(s->pDrvMount) */ 4437 4591 break; 4438 } 4439 if (pbPacket[0] == SCSI_READ_10) 4440 cSectors = ataBE2H_U16(pbPacket + 7); 4441 else 4442 cSectors = ataBE2H_U32(pbPacket + 6); 4443 iATAPILBA = ataBE2H_U32(pbPacket + 2); 4444 if (cSectors == 0) 4445 { 4446 atapiCmdOK(pAhciPort, pAhciReq); 4592 } 4593 if (RT_SUCCESS(rc)) 4594 atapiCmdOK(pAhciPort, pAhciReq); 4595 else 4596 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED); 4597 break; 4598 } 4599 case SCSI_MECHANISM_STATUS: 4600 { 4601 cbMax = ataBE2H_U16(pbPacket + 8); 4602 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MECHANISM_STATUS); 4603 break; 4604 } 4605 case SCSI_READ_TOC_PMA_ATIP: 4606 { 4607 uint8_t format; 4608 4609 if (pAhciPort->cNotifiedMediaChange > 0) 4610 { 4611 pAhciPort->cNotifiedMediaChange-- ; 4612 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 4613 break; 4614 } 4615 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 4616 { 4617 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4618 break; 4619 } 4620 cbMax = ataBE2H_U16(pbPacket + 7); 4621 /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits), 4622 * but Linux kernel uses offset 9 (topmost 2 bits). Hope that 4623 * the other field is clear... */ 4624 format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6); 4625 switch (format) 4626 { 4627 case 0: 4628 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_NORMAL); 4447 4629 break; 4448 } 4449 if ((uint64_t)iATAPILBA + cSectors > pAhciPort->cTotalSectors) 4450 { 4451 /* Rate limited logging, one log line per second. For 4452 * guests that insist on reading from places outside the 4453 * valid area this often generates too many release log 4454 * entries otherwise. */ 4455 static uint64_t s_uLastLogTS = 0; 4456 if (RTTimeMilliTS() >= s_uLastLogTS + 1000) 4457 { 4458 LogRel(("AHCI ATAPI: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA + cSectors)); 4459 s_uLastLogTS = RTTimeMilliTS(); 4460 } 4461 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 4630 case 1: 4631 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_MULTI); 4462 4632 break; 4463 } 4464 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048); 4465 rc = AHCITXDIR_READ; 4633 case 2: 4634 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_RAW); 4635 break; 4636 default: 4637 error_cmd: 4638 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 4639 break; 4466 4640 } 4467 4641 break; 4468 case SCSI_READ_CD: 4469 { 4470 uint32_t cSectors, iATAPILBA; 4471 4472 if (pAhciPort->cNotifiedMediaChange > 0) 4473 { 4474 pAhciPort->cNotifiedMediaChange-- ; 4475 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 4476 break; 4477 } 4478 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 4479 { 4480 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4481 break; 4482 } 4483 cSectors = (pbPacket[6] << 16) | (pbPacket[7] << 8) | pbPacket[8]; 4484 iATAPILBA = ataBE2H_U32(pbPacket + 2); 4485 if (cSectors == 0) 4486 { 4487 atapiCmdOK(pAhciPort, pAhciReq); 4488 break; 4489 } 4490 if ((uint64_t)iATAPILBA + cSectors > pAhciPort->cTotalSectors) 4491 { 4492 /* Rate limited logging, one log line per second. For 4493 * guests that insist on reading from places outside the 4494 * valid area this often generates too many release log 4495 * entries otherwise. */ 4496 static uint64_t s_uLastLogTS = 0; 4497 if (RTTimeMilliTS() >= s_uLastLogTS + 1000) 4498 { 4499 LogRel(("AHCI ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA + cSectors)); 4500 s_uLastLogTS = RTTimeMilliTS(); 4501 } 4502 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 4503 break; 4504 } 4505 switch (pbPacket[9] & 0xf8) 4506 { 4507 case 0x00: 4508 /* nothing */ 4509 atapiCmdOK(pAhciPort, pAhciReq); 4510 break; 4511 case 0x10: 4512 /* normal read */ 4513 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048); 4514 rc = AHCITXDIR_READ; 4515 break; 4516 case 0xf8: 4517 /* read all data */ 4518 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2352); 4519 rc = AHCITXDIR_READ; 4520 break; 4521 default: 4522 LogRel(("AHCI ATAPI: LUN#%d: CD-ROM sector format not supported\n", pAhciPort->iLUN)); 4523 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 4524 break; 4525 } 4526 } 4527 break; 4528 case SCSI_SEEK_10: 4529 { 4530 uint32_t iATAPILBA; 4531 if (pAhciPort->cNotifiedMediaChange > 0) 4532 { 4533 pAhciPort->cNotifiedMediaChange-- ; 4534 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 4535 break; 4536 } 4537 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 4538 { 4539 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4540 break; 4541 } 4542 iATAPILBA = ataBE2H_U32(pbPacket + 2); 4543 if (iATAPILBA > pAhciPort->cTotalSectors) 4544 { 4545 /* Rate limited logging, one log line per second. For 4546 * guests that insist on seeking to places outside the 4547 * valid area this often generates too many release log 4548 * entries otherwise. */ 4549 static uint64_t s_uLastLogTS = 0; 4550 if (RTTimeMilliTS() >= s_uLastLogTS + 1000) 4551 { 4552 LogRel(("AHCI ATAPI: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA)); 4553 s_uLastLogTS = RTTimeMilliTS(); 4554 } 4555 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 4556 break; 4557 } 4558 atapiCmdOK(pAhciPort, pAhciReq); 4559 pAhciReq->uATARegStatus |= ATA_STAT_SEEK; /* Linux expects this. */ 4560 } 4561 break; 4562 case SCSI_START_STOP_UNIT: 4563 { 4564 int rc2 = VINF_SUCCESS; 4565 switch (pbPacket[4] & 3) 4566 { 4567 case 0: /* 00 - Stop motor */ 4568 case 1: /* 01 - Start motor */ 4569 break; 4570 case 2: /* 10 - Eject media */ 4571 { 4572 /* This must be done from EMT. */ 4573 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci); 4574 PPDMDEVINS pDevIns = pAhci->CTX_SUFF(pDevIns); 4575 4576 rc2 = VMR3ReqPriorityCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY, 4577 (PFNRT)pAhciPort->pDrvMount->pfnUnmount, 3, 4578 pAhciPort->pDrvMount, false/*=fForce*/, true/*=fEject*/); 4579 Assert(RT_SUCCESS(rc2) || (rc2 == VERR_PDM_MEDIA_LOCKED) || (rc2 = VERR_PDM_MEDIA_NOT_MOUNTED)); 4580 if (RT_SUCCESS(rc) && pAhci->pMediaNotify) 4581 { 4582 rc2 = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY, 4583 (PFNRT)pAhci->pMediaNotify->pfnEjected, 2, 4584 pAhci->pMediaNotify, pAhciPort->iLUN); 4585 AssertRC(rc); 4586 } 4587 break; 4588 } 4589 case 3: /* 11 - Load media */ 4590 /** @todo rc = s->pDrvMount->pfnLoadMedia(s->pDrvMount) */ 4591 break; 4592 } 4593 if (RT_SUCCESS(rc2)) 4594 atapiCmdOK(pAhciPort, pAhciReq); 4595 else 4596 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED); 4597 } 4598 break; 4599 case SCSI_MECHANISM_STATUS: 4600 { 4601 cbMax = ataBE2H_U16(pbPacket + 8); 4602 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MECHANISM_STATUS); 4603 } 4604 break; 4605 case SCSI_READ_TOC_PMA_ATIP: 4606 { 4607 uint8_t format; 4608 4609 if (pAhciPort->cNotifiedMediaChange > 0) 4610 { 4611 pAhciPort->cNotifiedMediaChange-- ; 4612 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 4613 break; 4614 } 4615 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 4616 { 4617 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4618 break; 4619 } 4620 cbMax = ataBE2H_U16(pbPacket + 7); 4621 /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits), 4622 * but Linux kernel uses offset 9 (topmost 2 bits). Hope that 4623 * the other field is clear... */ 4624 format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6); 4625 switch (format) 4626 { 4627 case 0: 4628 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_NORMAL); 4629 break; 4630 case 1: 4631 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_MULTI); 4632 break; 4633 case 2: 4634 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_RAW); 4635 break; 4636 default: 4637 error_cmd: 4638 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 4639 break; 4640 } 4641 } 4642 break; 4642 } 4643 4643 case SCSI_READ_CAPACITY: 4644 4644 if (pAhciPort->cNotifiedMediaChange > 0) … … 4703 4703 } 4704 4704 4705 return rc;4705 return enmTxDir; 4706 4706 } 4707 4707 … … 6060 6060 static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis) 6061 6061 { 6062 AHCITXDIR rc= AHCITXDIR_NONE;6062 AHCITXDIR enmTxDir = AHCITXDIR_NONE; 6063 6063 bool fLBA48 = false; 6064 6064 CmdHdr *pCmdHdr = &pAhciReq->cmdHdr; … … 6110 6110 break; 6111 6111 case 0x82: /* write cache disable */ 6112 rc= AHCITXDIR_FLUSH;6112 enmTxDir = AHCITXDIR_FLUSH; 6113 6113 break; 6114 6114 case 0x03: 6115 { /* set transfer mode */ 6115 { 6116 /* set transfer mode */ 6116 6117 Log2(("%s: transfer mode %#04x\n", __FUNCTION__, pCmdFis[AHCI_CMDFIS_SECTC])); 6117 6118 switch (pCmdFis[AHCI_CMDFIS_SECTC] & 0xf8) … … 6151 6152 case ATA_FLUSH_CACHE_EXT: 6152 6153 case ATA_FLUSH_CACHE: 6153 rc= AHCITXDIR_FLUSH;6154 enmTxDir = AHCITXDIR_FLUSH; 6154 6155 break; 6155 6156 case ATA_PACKET: … … 6160 6161 } 6161 6162 else 6162 rc= atapiParseCmd(pAhciPort, pAhciReq);6163 enmTxDir = atapiParseCmd(pAhciPort, pAhciReq); 6163 6164 break; 6164 6165 case ATA_IDENTIFY_PACKET_DEVICE: … … 6215 6216 pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector; 6216 6217 pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * pAhciPort->cbSector; 6217 rc= AHCITXDIR_READ;6218 enmTxDir = AHCITXDIR_READ; 6218 6219 break; 6219 6220 } … … 6224 6225 pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector; 6225 6226 pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * pAhciPort->cbSector; 6226 rc= AHCITXDIR_WRITE;6227 enmTxDir = AHCITXDIR_WRITE; 6227 6228 break; 6228 6229 } … … 6232 6233 pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector; 6233 6234 pAhciReq->fFlags |= AHCI_REQ_IS_QUEUED; 6234 rc= AHCITXDIR_READ;6235 enmTxDir = AHCITXDIR_READ; 6235 6236 break; 6236 6237 } … … 6240 6241 pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector; 6241 6242 pAhciReq->fFlags |= AHCI_REQ_IS_QUEUED; 6242 rc= AHCITXDIR_WRITE;6243 enmTxDir = AHCITXDIR_WRITE; 6243 6244 break; 6244 6245 } … … 6321 6322 } 6322 6323 else 6323 rc= AHCITXDIR_TRIM;6324 enmTxDir = AHCITXDIR_TRIM; 6324 6325 break; 6325 6326 } … … 6340 6341 } 6341 6342 6342 return rc;6343 return enmTxDir; 6343 6344 } 6344 6345 -
trunk/src/VBox/Devices/Storage/DevATA.cpp
r48744 r50282 1862 1862 break; 1863 1863 case 2352: 1864 { 1865 uint8_t *pbBuf = s->CTX_SUFF(pbIOBuffer); 1866 1867 for (uint32_t i = s->iATAPILBA; i < s->iATAPILBA + cSectors; i++) 1864 1868 { 1865 uint8_t *pbBuf = s->CTX_SUFF(pbIOBuffer); 1866 1867 for (uint32_t i = s->iATAPILBA; i < s->iATAPILBA + cSectors; i++) 1868 { 1869 /* Sync bytes, see 4.2.3.8 CD Main Channel Block Formats */ 1870 *pbBuf++ = 0x00; 1871 memset(pbBuf, 0xff, 10); 1872 pbBuf += 10; 1873 *pbBuf++ = 0x00; 1874 /* MSF */ 1875 ataLBA2MSF(pbBuf, i); 1876 pbBuf += 3; 1877 *pbBuf++ = 0x01; /* mode 1 data */ 1878 /* data */ 1879 rc = s->pDrvBlock->pfnRead(s->pDrvBlock, (uint64_t)i * 2048, pbBuf, 2048); 1880 if (RT_FAILURE(rc)) 1881 break; 1882 pbBuf += 2048; 1883 /** 1884 * @todo: maybe compute ECC and parity, layout is: 1885 * 2072 4 EDC 1886 * 2076 172 P parity symbols 1887 * 2248 104 Q parity symbols 1888 */ 1889 memset(pbBuf, 0, 280); 1890 pbBuf += 280; 1891 } 1869 /* Sync bytes, see 4.2.3.8 CD Main Channel Block Formats */ 1870 *pbBuf++ = 0x00; 1871 memset(pbBuf, 0xff, 10); 1872 pbBuf += 10; 1873 *pbBuf++ = 0x00; 1874 /* MSF */ 1875 ataLBA2MSF(pbBuf, i); 1876 pbBuf += 3; 1877 *pbBuf++ = 0x01; /* mode 1 data */ 1878 /* data */ 1879 rc = s->pDrvBlock->pfnRead(s->pDrvBlock, (uint64_t)i * 2048, pbBuf, 2048); 1880 if (RT_FAILURE(rc)) 1881 break; 1882 pbBuf += 2048; 1883 /** 1884 * @todo: maybe compute ECC and parity, layout is: 1885 * 2072 4 EDC 1886 * 2076 172 P parity symbols 1887 * 2248 104 Q parity symbols 1888 */ 1889 memset(pbBuf, 0, 280); 1890 pbBuf += 280; 1892 1891 } 1893 1892 break; 1893 } 1894 1894 default: 1895 1895 break; … … 2271 2271 { 2272 2272 case 0x0: /* Physical format information */ 2273 { 2274 int layer = s->aATAPICmd[6]; 2275 uint64_t total_sectors; 2276 2277 if (layer != 0) 2273 2278 { 2274 int layer = s->aATAPICmd[6]; 2275 uint64_t total_sectors; 2276 2277 if (layer != 0) 2278 { 2279 uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET; 2280 break; 2281 } 2282 2283 total_sectors = s->cTotalSectors; 2284 total_sectors >>= 2; 2285 if (total_sectors == 0) 2286 { 2287 uASC = -SCSI_ASC_MEDIUM_NOT_PRESENT; 2288 break; 2289 } 2290 2291 buf[4] = 1; /* DVD-ROM, part version 1 */ 2292 buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ 2293 buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ 2294 buf[7] = 0; /* default densities */ 2295 2296 /* FIXME: 0x30000 per spec? */ 2297 ataH2BE_U32(buf + 8, 0); /* start sector */ 2298 ataH2BE_U32(buf + 12, total_sectors - 1); /* end sector */ 2299 ataH2BE_U32(buf + 16, total_sectors - 1); /* l0 end sector */ 2300 2301 /* Size of buffer, not including 2 byte size field */ 2302 ataH2BE_U32(&buf[0], 2048 + 2); 2303 2304 /* 2k data + 4 byte header */ 2305 uASC = (2048 + 4); 2279 uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET; 2280 break; 2306 2281 } 2282 2283 total_sectors = s->cTotalSectors; 2284 total_sectors >>= 2; 2285 if (total_sectors == 0) 2286 { 2287 uASC = -SCSI_ASC_MEDIUM_NOT_PRESENT; 2288 break; 2289 } 2290 2291 buf[4] = 1; /* DVD-ROM, part version 1 */ 2292 buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ 2293 buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ 2294 buf[7] = 0; /* default densities */ 2295 2296 /* FIXME: 0x30000 per spec? */ 2297 ataH2BE_U32(buf + 8, 0); /* start sector */ 2298 ataH2BE_U32(buf + 12, total_sectors - 1); /* end sector */ 2299 ataH2BE_U32(buf + 16, total_sectors - 1); /* l0 end sector */ 2300 2301 /* Size of buffer, not including 2 byte size field */ 2302 ataH2BE_U32(&buf[0], 2048 + 2); 2303 2304 /* 2k data + 4 byte header */ 2305 uASC = (2048 + 4); 2307 2306 break; 2307 } 2308 2308 case 0x01: /* DVD copyright information */ 2309 2309 buf[4] = 0; /* no copyright data */ … … 3070 3070 break; 3071 3071 case SCSI_MODE_SENSE_10: 3072 { 3073 uint8_t uPageControl, uPageCode; 3074 cbMax = ataBE2H_U16(pbPacket + 7); 3075 uPageControl = pbPacket[2] >> 6; 3076 uPageCode = pbPacket[2] & 0x3f; 3077 switch (uPageControl) 3072 3078 { 3073 uint8_t uPageControl, uPageCode; 3074 cbMax = ataBE2H_U16(pbPacket + 7); 3075 uPageControl = pbPacket[2] >> 6; 3076 uPageCode = pbPacket[2] & 0x3f; 3077 switch (uPageControl) 3078 { 3079 case SCSI_PAGECONTROL_CURRENT: 3080 switch (uPageCode) 3081 { 3082 case SCSI_MODEPAGE_ERROR_RECOVERY: 3083 ataStartTransfer(s, RT_MIN(cbMax, 16), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY, true); 3084 break; 3085 case SCSI_MODEPAGE_CD_STATUS: 3086 ataStartTransfer(s, RT_MIN(cbMax, 40), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS, true); 3087 break; 3088 default: 3089 goto error_cmd; 3090 } 3091 break; 3092 case SCSI_PAGECONTROL_CHANGEABLE: 3093 goto error_cmd; 3094 case SCSI_PAGECONTROL_DEFAULT: 3095 goto error_cmd; 3096 default: 3097 case SCSI_PAGECONTROL_SAVED: 3098 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED); 3099 break; 3100 } 3079 case SCSI_PAGECONTROL_CURRENT: 3080 switch (uPageCode) 3081 { 3082 case SCSI_MODEPAGE_ERROR_RECOVERY: 3083 ataStartTransfer(s, RT_MIN(cbMax, 16), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY, true); 3084 break; 3085 case SCSI_MODEPAGE_CD_STATUS: 3086 ataStartTransfer(s, RT_MIN(cbMax, 40), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS, true); 3087 break; 3088 default: 3089 goto error_cmd; 3090 } 3091 break; 3092 case SCSI_PAGECONTROL_CHANGEABLE: 3093 goto error_cmd; 3094 case SCSI_PAGECONTROL_DEFAULT: 3095 goto error_cmd; 3096 default: 3097 case SCSI_PAGECONTROL_SAVED: 3098 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED); 3099 break; 3101 3100 } 3102 3101 break; 3102 } 3103 3103 case SCSI_REQUEST_SENSE: 3104 3104 cbMax = pbPacket[4]; … … 3119 3119 case SCSI_READ_10: 3120 3120 case SCSI_READ_12: 3121 { 3122 uint32_t cSectors, iATAPILBA; 3123 3124 if (s->cNotifiedMediaChange > 0) 3121 3125 { 3122 uint32_t cSectors, iATAPILBA; 3123 3124 if (s->cNotifiedMediaChange > 0) 3126 s->cNotifiedMediaChange-- ; 3127 atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 3128 break; 3129 } 3130 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount)) 3131 { 3132 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3133 break; 3134 } 3135 if (pbPacket[0] == SCSI_READ_10) 3136 cSectors = ataBE2H_U16(pbPacket + 7); 3137 else 3138 cSectors = ataBE2H_U32(pbPacket + 6); 3139 iATAPILBA = ataBE2H_U32(pbPacket + 2); 3140 if (cSectors == 0) 3141 { 3142 atapiCmdOK(s); 3143 break; 3144 } 3145 if ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors) 3146 { 3147 /* Rate limited logging, one log line per second. For 3148 * guests that insist on reading from places outside the 3149 * valid area this often generates too many release log 3150 * entries otherwise. */ 3151 static uint64_t uLastLogTS = 0; 3152 if (RTTimeMilliTS() >= uLastLogTS + 1000) 3125 3153 { 3126 s->cNotifiedMediaChange-- ; 3127 atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 3154 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors)); 3155 uLastLogTS = RTTimeMilliTS(); 3156 } 3157 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 3158 break; 3159 } 3160 atapiReadSectors(s, iATAPILBA, cSectors, 2048); 3161 break; 3162 } 3163 case SCSI_READ_CD: 3164 { 3165 uint32_t cSectors, iATAPILBA; 3166 3167 if (s->cNotifiedMediaChange > 0) 3168 { 3169 s->cNotifiedMediaChange-- ; 3170 atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 3171 break; 3172 } 3173 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount)) 3174 { 3175 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3176 break; 3177 } 3178 cSectors = (pbPacket[6] << 16) | (pbPacket[7] << 8) | pbPacket[8]; 3179 iATAPILBA = ataBE2H_U32(pbPacket + 2); 3180 if (cSectors == 0) 3181 { 3182 atapiCmdOK(s); 3183 break; 3184 } 3185 if ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors) 3186 { 3187 /* Rate limited logging, one log line per second. For 3188 * guests that insist on reading from places outside the 3189 * valid area this often generates too many release log 3190 * entries otherwise. */ 3191 static uint64_t uLastLogTS = 0; 3192 if (RTTimeMilliTS() >= uLastLogTS + 1000) 3193 { 3194 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors)); 3195 uLastLogTS = RTTimeMilliTS(); 3196 } 3197 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 3198 break; 3199 } 3200 switch (pbPacket[9] & 0xf8) 3201 { 3202 case 0x00: 3203 /* nothing */ 3204 atapiCmdOK(s); 3205 break; 3206 case 0x10: 3207 /* normal read */ 3208 atapiReadSectors(s, iATAPILBA, cSectors, 2048); 3209 break; 3210 case 0xf8: 3211 /* read all data */ 3212 atapiReadSectors(s, iATAPILBA, cSectors, 2352); 3213 break; 3214 default: 3215 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM sector format not supported (%#x)\n", s->iLUN, pbPacket[9] & 0xf8)); 3216 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 3217 break; 3218 } 3219 break; 3220 } 3221 case SCSI_SEEK_10: 3222 { 3223 uint32_t iATAPILBA; 3224 if (s->cNotifiedMediaChange > 0) 3225 { 3226 s->cNotifiedMediaChange-- ; 3227 atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 3228 break; 3229 } 3230 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount)) 3231 { 3232 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3233 break; 3234 } 3235 iATAPILBA = ataBE2H_U32(pbPacket + 2); 3236 if (iATAPILBA > s->cTotalSectors) 3237 { 3238 /* Rate limited logging, one log line per second. For 3239 * guests that insist on seeking to places outside the 3240 * valid area this often generates too many release log 3241 * entries otherwise. */ 3242 static uint64_t uLastLogTS = 0; 3243 if (RTTimeMilliTS() >= uLastLogTS + 1000) 3244 { 3245 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", s->iLUN, (uint64_t)iATAPILBA)); 3246 uLastLogTS = RTTimeMilliTS(); 3247 } 3248 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 3249 break; 3250 } 3251 atapiCmdOK(s); 3252 ataSetStatus(s, ATA_STAT_SEEK); /* Linux expects this. */ 3253 break; 3254 } 3255 case SCSI_START_STOP_UNIT: 3256 { 3257 int rc = VINF_SUCCESS; 3258 switch (pbPacket[4] & 3) 3259 { 3260 case 0: /* 00 - Stop motor */ 3261 case 1: /* 01 - Start motor */ 3262 break; 3263 case 2: /* 10 - Eject media */ 3264 { 3265 /* This must be done from EMT. */ 3266 PATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s); 3267 PPDMDEVINS pDevIns = ATADEVSTATE_2_DEVINS(s); 3268 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); 3269 3270 PDMCritSectLeave(&pCtl->lock); 3271 rc = VMR3ReqPriorityCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY, 3272 (PFNRT)s->pDrvMount->pfnUnmount, 3, 3273 s->pDrvMount, false /*=fForce*/, true /*=fEject*/); 3274 Assert(RT_SUCCESS(rc) || rc == VERR_PDM_MEDIA_LOCKED || rc = VERR_PDM_MEDIA_NOT_MOUNTED); 3275 if (RT_SUCCESS(rc) && pThis->pMediaNotify) 3276 { 3277 rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY, 3278 (PFNRT)pThis->pMediaNotify->pfnEjected, 2, 3279 pThis->pMediaNotify, s->iLUN); 3280 AssertRC(rc); 3281 } 3282 { 3283 STAM_PROFILE_START(&pCtl->StatLockWait, a); 3284 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS); 3285 STAM_PROFILE_STOP(&pCtl->StatLockWait, a); 3286 } 3128 3287 break; 3129 3288 } 3130 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount)) 3131 { 3132 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3289 case 3: /* 11 - Load media */ 3290 /** @todo rc = s->pDrvMount->pfnLoadMedia(s->pDrvMount) */ 3133 3291 break; 3134 } 3135 if (pbPacket[0] == SCSI_READ_10) 3136 cSectors = ataBE2H_U16(pbPacket + 7); 3137 else 3138 cSectors = ataBE2H_U32(pbPacket + 6); 3139 iATAPILBA = ataBE2H_U32(pbPacket + 2); 3140 if (cSectors == 0) 3141 { 3142 atapiCmdOK(s); 3292 } 3293 if (RT_SUCCESS(rc)) 3294 atapiCmdOK(s); 3295 else 3296 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED); 3297 break; 3298 } 3299 case SCSI_MECHANISM_STATUS: 3300 { 3301 cbMax = ataBE2H_U16(pbPacket + 8); 3302 ataStartTransfer(s, RT_MIN(cbMax, 8), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MECHANISM_STATUS, true); 3303 break; 3304 } 3305 case SCSI_READ_TOC_PMA_ATIP: 3306 { 3307 uint8_t format; 3308 3309 if (s->cNotifiedMediaChange > 0) 3310 { 3311 s->cNotifiedMediaChange-- ; 3312 atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 3313 break; 3314 } 3315 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount)) 3316 { 3317 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3318 break; 3319 } 3320 cbMax = ataBE2H_U16(pbPacket + 7); 3321 /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits), 3322 * but Linux kernel uses offset 9 (topmost 2 bits). Hope that 3323 * the other field is clear... */ 3324 format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6); 3325 switch (format) 3326 { 3327 case 0: 3328 ataStartTransfer(s, cbMax, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_NORMAL, true); 3143 3329 break; 3144 } 3145 if ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors) 3146 { 3147 /* Rate limited logging, one log line per second. For 3148 * guests that insist on reading from places outside the 3149 * valid area this often generates too many release log 3150 * entries otherwise. */ 3151 static uint64_t uLastLogTS = 0; 3152 if (RTTimeMilliTS() >= uLastLogTS + 1000) 3153 { 3154 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors)); 3155 uLastLogTS = RTTimeMilliTS(); 3156 } 3157 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 3330 case 1: 3331 ataStartTransfer(s, RT_MIN(cbMax, 12), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_MULTI, true); 3158 3332 break; 3159 } 3160 atapiReadSectors(s, iATAPILBA, cSectors, 2048); 3333 case 2: 3334 ataStartTransfer(s, cbMax, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_RAW, true); 3335 break; 3336 default: 3337 error_cmd: 3338 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 3339 break; 3161 3340 } 3162 3341 break; 3163 case SCSI_READ_CD: 3164 { 3165 uint32_t cSectors, iATAPILBA; 3166 3167 if (s->cNotifiedMediaChange > 0) 3168 { 3169 s->cNotifiedMediaChange-- ; 3170 atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 3171 break; 3172 } 3173 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount)) 3174 { 3175 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3176 break; 3177 } 3178 cSectors = (pbPacket[6] << 16) | (pbPacket[7] << 8) | pbPacket[8]; 3179 iATAPILBA = ataBE2H_U32(pbPacket + 2); 3180 if (cSectors == 0) 3181 { 3182 atapiCmdOK(s); 3183 break; 3184 } 3185 if ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors) 3186 { 3187 /* Rate limited logging, one log line per second. For 3188 * guests that insist on reading from places outside the 3189 * valid area this often generates too many release log 3190 * entries otherwise. */ 3191 static uint64_t uLastLogTS = 0; 3192 if (RTTimeMilliTS() >= uLastLogTS + 1000) 3193 { 3194 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors)); 3195 uLastLogTS = RTTimeMilliTS(); 3196 } 3197 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 3198 break; 3199 } 3200 switch (pbPacket[9] & 0xf8) 3201 { 3202 case 0x00: 3203 /* nothing */ 3204 atapiCmdOK(s); 3205 break; 3206 case 0x10: 3207 /* normal read */ 3208 atapiReadSectors(s, iATAPILBA, cSectors, 2048); 3209 break; 3210 case 0xf8: 3211 /* read all data */ 3212 atapiReadSectors(s, iATAPILBA, cSectors, 2352); 3213 break; 3214 default: 3215 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM sector format not supported (%#x)\n", s->iLUN, pbPacket[9] & 0xf8)); 3216 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 3217 break; 3218 } 3219 } 3220 break; 3221 case SCSI_SEEK_10: 3222 { 3223 uint32_t iATAPILBA; 3224 if (s->cNotifiedMediaChange > 0) 3225 { 3226 s->cNotifiedMediaChange-- ; 3227 atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 3228 break; 3229 } 3230 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount)) 3231 { 3232 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3233 break; 3234 } 3235 iATAPILBA = ataBE2H_U32(pbPacket + 2); 3236 if (iATAPILBA > s->cTotalSectors) 3237 { 3238 /* Rate limited logging, one log line per second. For 3239 * guests that insist on seeking to places outside the 3240 * valid area this often generates too many release log 3241 * entries otherwise. */ 3242 static uint64_t uLastLogTS = 0; 3243 if (RTTimeMilliTS() >= uLastLogTS + 1000) 3244 { 3245 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", s->iLUN, (uint64_t)iATAPILBA)); 3246 uLastLogTS = RTTimeMilliTS(); 3247 } 3248 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 3249 break; 3250 } 3251 atapiCmdOK(s); 3252 ataSetStatus(s, ATA_STAT_SEEK); /* Linux expects this. */ 3253 } 3254 break; 3255 case SCSI_START_STOP_UNIT: 3256 { 3257 int rc = VINF_SUCCESS; 3258 switch (pbPacket[4] & 3) 3259 { 3260 case 0: /* 00 - Stop motor */ 3261 case 1: /* 01 - Start motor */ 3262 break; 3263 case 2: /* 10 - Eject media */ 3264 { 3265 /* This must be done from EMT. */ 3266 PATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s); 3267 PPDMDEVINS pDevIns = ATADEVSTATE_2_DEVINS(s); 3268 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); 3269 3270 PDMCritSectLeave(&pCtl->lock); 3271 rc = VMR3ReqPriorityCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY, 3272 (PFNRT)s->pDrvMount->pfnUnmount, 3, 3273 s->pDrvMount, false /*=fForce*/, true /*=fEject*/); 3274 Assert(RT_SUCCESS(rc) || (rc == VERR_PDM_MEDIA_LOCKED) || (rc = VERR_PDM_MEDIA_NOT_MOUNTED)); 3275 if (RT_SUCCESS(rc) && pThis->pMediaNotify) 3276 { 3277 rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY, 3278 (PFNRT)pThis->pMediaNotify->pfnEjected, 2, 3279 pThis->pMediaNotify, s->iLUN); 3280 AssertRC(rc); 3281 } 3282 { 3283 STAM_PROFILE_START(&pCtl->StatLockWait, a); 3284 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS); 3285 STAM_PROFILE_STOP(&pCtl->StatLockWait, a); 3286 } 3287 break; 3288 } 3289 case 3: /* 11 - Load media */ 3290 /** @todo rc = s->pDrvMount->pfnLoadMedia(s->pDrvMount) */ 3291 break; 3292 } 3293 if (RT_SUCCESS(rc)) 3294 atapiCmdOK(s); 3295 else 3296 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED); 3297 } 3298 break; 3299 case SCSI_MECHANISM_STATUS: 3300 { 3301 cbMax = ataBE2H_U16(pbPacket + 8); 3302 ataStartTransfer(s, RT_MIN(cbMax, 8), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MECHANISM_STATUS, true); 3303 } 3304 break; 3305 case SCSI_READ_TOC_PMA_ATIP: 3306 { 3307 uint8_t format; 3308 3309 if (s->cNotifiedMediaChange > 0) 3310 { 3311 s->cNotifiedMediaChange-- ; 3312 atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 3313 break; 3314 } 3315 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount)) 3316 { 3317 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3318 break; 3319 } 3320 cbMax = ataBE2H_U16(pbPacket + 7); 3321 /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits), 3322 * but Linux kernel uses offset 9 (topmost 2 bits). Hope that 3323 * the other field is clear... */ 3324 format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6); 3325 switch (format) 3326 { 3327 case 0: 3328 ataStartTransfer(s, cbMax, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_NORMAL, true); 3329 break; 3330 case 1: 3331 ataStartTransfer(s, RT_MIN(cbMax, 12), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_MULTI, true); 3332 break; 3333 case 2: 3334 ataStartTransfer(s, cbMax, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_RAW, true); 3335 break; 3336 default: 3337 error_cmd: 3338 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 3339 break; 3340 } 3341 } 3342 break; 3342 } 3343 3343 case SCSI_READ_CAPACITY: 3344 3344 if (s->cNotifiedMediaChange > 0)
Note:
See TracChangeset
for help on using the changeset viewer.