儲存庫 vbox 的更動 65966
- 時間撮記:
- 2017-3-7 上午10:47:19 (8 年 以前)
- 檔案:
-
- 修改 1 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/src/VBox/Devices/Storage/DevATA.cpp
r65960 r65966 3397 3397 static void atapiR3ParseCmdPassthrough(ATADevState *s) 3398 3398 { 3399 const uint8_t *pbPacket; 3400 uint8_t *pbBuf; 3401 uint32_t cSectors, iATAPILBA; 3402 uint32_t cbTransfer = 0; 3399 const uint8_t *pbPacket = &s->aATAPICmd[0]; 3400 size_t cbTransfer = 0; 3403 3401 PDMMEDIATXDIR uTxDir = PDMMEDIATXDIR_NONE; 3404 3405 pbPacket = s->aATAPICmd; 3406 pbBuf = s->CTX_SUFF(pbIOBuffer); 3407 switch (pbPacket[0]) 3408 { 3409 case SCSI_BLANK: 3410 goto sendcmd; 3411 case SCSI_CLOSE_TRACK_SESSION: 3412 goto sendcmd; 3413 case SCSI_ERASE_10: 3414 iATAPILBA = scsiBE2H_U32(pbPacket + 2); 3415 cbTransfer = scsiBE2H_U16(pbPacket + 7); 3416 Log2(("ATAPI PT: lba %d\n", iATAPILBA)); 3417 uTxDir = PDMMEDIATXDIR_TO_DEVICE; 3418 goto sendcmd; 3419 case SCSI_FORMAT_UNIT: 3420 cbTransfer = s->uATARegLCyl | (s->uATARegHCyl << 8); /* use ATAPI transfer length */ 3421 uTxDir = PDMMEDIATXDIR_TO_DEVICE; 3422 goto sendcmd; 3423 case SCSI_GET_CONFIGURATION: 3424 cbTransfer = scsiBE2H_U16(pbPacket + 7); 3425 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3426 goto sendcmd; 3427 case SCSI_GET_EVENT_STATUS_NOTIFICATION: 3428 cbTransfer = scsiBE2H_U16(pbPacket + 7); 3429 if (ASMAtomicReadU32(&s->MediaEventStatus) != ATA_EVENT_STATUS_UNCHANGED) 3430 { 3431 ataR3StartTransfer(s, RT_MIN(cbTransfer, 8), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION, true); 3432 break; 3433 } 3434 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3435 goto sendcmd; 3436 case SCSI_GET_PERFORMANCE: 3437 cbTransfer = s->uATARegLCyl | (s->uATARegHCyl << 8); /* use ATAPI transfer length */ 3438 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3439 goto sendcmd; 3440 case SCSI_INQUIRY: 3441 cbTransfer = scsiBE2H_U16(pbPacket + 3); 3442 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3443 goto sendcmd; 3444 case SCSI_LOAD_UNLOAD_MEDIUM: 3445 goto sendcmd; 3446 case SCSI_MECHANISM_STATUS: 3447 cbTransfer = scsiBE2H_U16(pbPacket + 8); 3448 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3449 goto sendcmd; 3450 case SCSI_MODE_SELECT_10: 3451 cbTransfer = scsiBE2H_U16(pbPacket + 7); 3452 uTxDir = PDMMEDIATXDIR_TO_DEVICE; 3453 goto sendcmd; 3454 case SCSI_MODE_SENSE_10: 3455 cbTransfer = scsiBE2H_U16(pbPacket + 7); 3456 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3457 goto sendcmd; 3458 case SCSI_PAUSE_RESUME: 3459 goto sendcmd; 3460 case SCSI_PLAY_AUDIO_10: 3461 goto sendcmd; 3462 case SCSI_PLAY_AUDIO_12: 3463 goto sendcmd; 3464 case SCSI_PLAY_AUDIO_MSF: 3465 goto sendcmd; 3466 case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL: 3467 /** @todo do not forget to unlock when a VM is shut down */ 3468 goto sendcmd; 3469 case SCSI_READ_10: 3470 iATAPILBA = scsiBE2H_U32(pbPacket + 2); 3471 cSectors = scsiBE2H_U16(pbPacket + 7); 3472 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors)); 3473 s->cbATAPISector = 2048; 3474 cbTransfer = cSectors * s->cbATAPISector; 3475 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3476 goto sendcmd; 3477 case SCSI_READ_12: 3478 iATAPILBA = scsiBE2H_U32(pbPacket + 2); 3479 cSectors = scsiBE2H_U32(pbPacket + 6); 3480 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors)); 3481 s->cbATAPISector = 2048; 3482 cbTransfer = cSectors * s->cbATAPISector; 3483 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3484 goto sendcmd; 3485 case SCSI_READ_BUFFER: 3486 cbTransfer = scsiBE2H_U24(pbPacket + 6); 3487 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3488 goto sendcmd; 3489 case SCSI_READ_BUFFER_CAPACITY: 3490 cbTransfer = scsiBE2H_U16(pbPacket + 7); 3491 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3492 goto sendcmd; 3493 case SCSI_READ_CAPACITY: 3494 cbTransfer = 8; 3495 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3496 goto sendcmd; 3497 case SCSI_READ_CD: 3498 case SCSI_READ_CD_MSF: 3499 { 3500 /* Get sector size based on the expected sector type field. */ 3501 switch ((pbPacket[1] >> 2) & 0x7) 3502 { 3503 case 0x0: /* All types. */ 3504 { 3505 uint32_t iLbaStart; 3506 3507 if (pbPacket[0] == SCSI_READ_CD) 3508 iLbaStart = scsiBE2H_U32(&pbPacket[2]); 3509 else 3510 iLbaStart = scsiMSF2LBA(&pbPacket[3]); 3511 3512 if (s->pTrackList) 3513 s->cbATAPISector = ATAPIPassthroughTrackListGetSectorSizeFromLba(s->pTrackList, iLbaStart); 3514 else 3515 s->cbATAPISector = 2048; /* Might be incorrect if we couldn't determine the type. */ 3516 break; 3517 } 3518 case 0x1: /* CD-DA */ 3519 s->cbATAPISector = 2352; 3520 break; 3521 case 0x2: /* Mode 1 */ 3522 s->cbATAPISector = 2048; 3523 break; 3524 case 0x3: /* Mode 2 formless */ 3525 s->cbATAPISector = 2336; 3526 break; 3527 case 0x4: /* Mode 2 form 1 */ 3528 s->cbATAPISector = 2048; 3529 break; 3530 case 0x5: /* Mode 2 form 2 */ 3531 s->cbATAPISector = 2324; 3532 break; 3533 default: /* Reserved */ 3534 AssertMsgFailed(("Unknown sector type\n")); 3535 s->cbATAPISector = 0; /** @todo we should probably fail the command here already. */ 3536 } 3537 3538 if (pbPacket[0] == SCSI_READ_CD) 3539 cbTransfer = scsiBE2H_U24(pbPacket + 6) * s->cbATAPISector; 3540 else /* SCSI_READ_MSF */ 3541 { 3542 cSectors = scsiMSF2LBA(pbPacket + 6) - scsiMSF2LBA(pbPacket + 3); 3543 if (cSectors > 32) 3544 cSectors = 32; /* Limit transfer size to 64~74K. Safety first. In any case this can only harm software doing CDDA extraction. */ 3545 cbTransfer = cSectors * s->cbATAPISector; 3546 } 3547 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3548 goto sendcmd; 3549 } 3550 case SCSI_READ_DISC_INFORMATION: 3551 cbTransfer = scsiBE2H_U16(pbPacket + 7); 3552 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3553 goto sendcmd; 3554 case SCSI_READ_DVD_STRUCTURE: 3555 cbTransfer = scsiBE2H_U16(pbPacket + 8); 3556 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3557 goto sendcmd; 3558 case SCSI_READ_FORMAT_CAPACITIES: 3559 cbTransfer = scsiBE2H_U16(pbPacket + 7); 3560 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3561 goto sendcmd; 3562 case SCSI_READ_SUBCHANNEL: 3563 cbTransfer = scsiBE2H_U16(pbPacket + 7); 3564 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3565 goto sendcmd; 3566 case SCSI_READ_TOC_PMA_ATIP: 3567 cbTransfer = scsiBE2H_U16(pbPacket + 7); 3568 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3569 goto sendcmd; 3570 case SCSI_READ_TRACK_INFORMATION: 3571 cbTransfer = scsiBE2H_U16(pbPacket + 7); 3572 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3573 goto sendcmd; 3574 case SCSI_REPAIR_TRACK: 3575 goto sendcmd; 3576 case SCSI_REPORT_KEY: 3577 cbTransfer = scsiBE2H_U16(pbPacket + 8); 3578 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3579 goto sendcmd; 3580 case SCSI_REQUEST_SENSE: 3581 cbTransfer = pbPacket[4]; 3582 if ((s->abATAPISense[2] & 0x0f) != SCSI_SENSE_NONE) 3583 { 3584 ataR3StartTransfer(s, RT_MIN(cbTransfer, 18), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_REQUEST_SENSE, true); 3585 break; 3586 } 3587 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3588 goto sendcmd; 3589 case SCSI_RESERVE_TRACK: 3590 goto sendcmd; 3591 case SCSI_SCAN: 3592 goto sendcmd; 3593 case SCSI_SEEK_10: 3594 goto sendcmd; 3595 case SCSI_SEND_CUE_SHEET: 3596 cbTransfer = scsiBE2H_U24(pbPacket + 6); 3597 uTxDir = PDMMEDIATXDIR_TO_DEVICE; 3598 goto sendcmd; 3599 case SCSI_SEND_DVD_STRUCTURE: 3600 cbTransfer = scsiBE2H_U16(pbPacket + 8); 3601 uTxDir = PDMMEDIATXDIR_TO_DEVICE; 3602 goto sendcmd; 3603 case SCSI_SEND_EVENT: 3604 cbTransfer = scsiBE2H_U16(pbPacket + 8); 3605 uTxDir = PDMMEDIATXDIR_TO_DEVICE; 3606 goto sendcmd; 3607 case SCSI_SEND_KEY: 3608 cbTransfer = scsiBE2H_U16(pbPacket + 8); 3609 uTxDir = PDMMEDIATXDIR_TO_DEVICE; 3610 goto sendcmd; 3611 case SCSI_SEND_OPC_INFORMATION: 3612 cbTransfer = scsiBE2H_U16(pbPacket + 7); 3613 uTxDir = PDMMEDIATXDIR_TO_DEVICE; 3614 goto sendcmd; 3615 case SCSI_SET_CD_SPEED: 3616 goto sendcmd; 3617 case SCSI_SET_READ_AHEAD: 3618 goto sendcmd; 3619 case SCSI_SET_STREAMING: 3620 cbTransfer = scsiBE2H_U16(pbPacket + 9); 3621 uTxDir = PDMMEDIATXDIR_TO_DEVICE; 3622 goto sendcmd; 3623 case SCSI_START_STOP_UNIT: 3624 goto sendcmd; 3625 case SCSI_STOP_PLAY_SCAN: 3626 goto sendcmd; 3627 case SCSI_SYNCHRONIZE_CACHE: 3628 goto sendcmd; 3629 case SCSI_TEST_UNIT_READY: 3630 goto sendcmd; 3631 case SCSI_VERIFY_10: 3632 goto sendcmd; 3633 case SCSI_WRITE_10: 3634 case SCSI_WRITE_AND_VERIFY_10: 3635 iATAPILBA = scsiBE2H_U32(pbPacket + 2); 3636 cSectors = scsiBE2H_U16(pbPacket + 7); 3637 if (s->pTrackList) 3638 s->cbATAPISector = ATAPIPassthroughTrackListGetSectorSizeFromLba(s->pTrackList, iATAPILBA); 3639 else 3640 s->cbATAPISector = 2048; 3641 Log2(("ATAPI PT: lba %d sectors %d sector size %d\n", iATAPILBA, cSectors, s->cbATAPISector)); 3642 cbTransfer = cSectors * s->cbATAPISector; 3643 uTxDir = PDMMEDIATXDIR_TO_DEVICE; 3644 goto sendcmd; 3645 case SCSI_WRITE_12: 3646 iATAPILBA = scsiBE2H_U32(pbPacket + 2); 3647 cSectors = scsiBE2H_U32(pbPacket + 6); 3648 if (s->pTrackList) 3649 s->cbATAPISector = ATAPIPassthroughTrackListGetSectorSizeFromLba(s->pTrackList, iATAPILBA); 3650 else 3651 s->cbATAPISector = 2048; 3652 Log2(("ATAPI PT: lba %d sectors %d sector size %d\n", iATAPILBA, cSectors, s->cbATAPISector)); 3653 cbTransfer = cSectors * s->cbATAPISector; 3654 uTxDir = PDMMEDIATXDIR_TO_DEVICE; 3655 goto sendcmd; 3656 case SCSI_WRITE_BUFFER: 3657 switch (pbPacket[1] & 0x1f) 3658 { 3659 case 0x04: /* download microcode */ 3660 case 0x05: /* download microcode and save */ 3661 case 0x06: /* download microcode with offsets */ 3662 case 0x07: /* download microcode with offsets and save */ 3663 case 0x0e: /* download microcode with offsets and defer activation */ 3664 case 0x0f: /* activate deferred microcode */ 3665 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM passthrough command attempted to update firmware, blocked\n", s->iLUN)); 3666 atapiR3CmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 3667 break; 3668 default: 3669 cbTransfer = scsiBE2H_U16(pbPacket + 6); 3670 uTxDir = PDMMEDIATXDIR_TO_DEVICE; 3671 goto sendcmd; 3672 } 3673 break; 3674 case SCSI_REPORT_LUNS: /* Not part of MMC-3, but used by Windows. */ 3675 cbTransfer = scsiBE2H_U32(pbPacket + 6); 3676 uTxDir = PDMMEDIATXDIR_FROM_DEVICE; 3677 goto sendcmd; 3678 case SCSI_REZERO_UNIT: 3679 /* Obsolete command used by cdrecord. What else would one expect? 3680 * This command is not sent to the drive, it is handled internally, 3681 * as the Linux kernel doesn't like it (message "scsi: unknown 3682 * opcode 0x01" in syslog) and replies with a sense code of 0, 3683 * which sends cdrecord to an endless loop. */ 3684 atapiR3CmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE); 3685 break; 3686 default: 3687 LogRel(("PIIX3 ATA: LUN#%d: passthrough unimplemented for command %#x\n", s->iLUN, pbPacket[0])); 3688 atapiR3CmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE); 3689 break; 3690 sendcmd: 3402 uint8_t u8ScsiSts = SCSI_STATUS_OK; 3403 3404 /* Some cases we have to handle here. */ 3405 if ( pbPacket[0] == SCSI_GET_EVENT_STATUS_NOTIFICATION 3406 && ASMAtomicReadU32(&s->MediaEventStatus) != ATA_EVENT_STATUS_UNCHANGED) 3407 { 3408 cbTransfer = scsiBE2H_U16(pbPacket + 7); 3409 ataR3StartTransfer(s, RT_MIN(cbTransfer, 8), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION, true); 3410 } 3411 else if ( pbPacket[0] == SCSI_REQUEST_SENSE 3412 && (s->abATAPISense[2] & 0x0f) != SCSI_SENSE_NONE) 3413 ataR3StartTransfer(s, RT_MIN(pbPacket[4], 18), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_REQUEST_SENSE, true); 3414 else 3415 { 3416 size_t cbBuf = 0; 3417 size_t cbATAPISector = 0; 3418 if (pbPacket[0] == SCSI_FORMAT_UNIT || pbPacket[0] == SCSI_GET_PERFORMANCE) 3419 cbBuf = s->uATARegLCyl | (s->uATARegHCyl << 8); /* use ATAPI transfer length */ 3420 3421 bool fPassthrough = ATAPIPassthroughParseCdb(pbPacket, sizeof(s->aATAPICmd), cbBuf, s->pTrackList, 3422 &s->abATAPISense[0], sizeof(s->abATAPISense), &uTxDir, &cbTransfer, 3423 &cbATAPISector, &u8ScsiSts); 3424 if (fPassthrough) 3425 { 3426 s->cbATAPISector = (uint32_t)cbATAPISector; 3427 Assert(s->cbATAPISector == (uint32_t)cbATAPISector); 3428 3691 3429 /* 3692 3430 * Send a command to the drive, passing data in/out as required. … … 3698 3436 uTxDir = PDMMEDIATXDIR_NONE; 3699 3437 ataR3StartTransfer(s, cbTransfer, uTxDir, ATAFN_BT_ATAPI_PASSTHROUGH_CMD, ATAFN_SS_ATAPI_PASSTHROUGH, true); 3438 } 3439 else if (u8ScsiSts == SCSI_STATUS_CHECK_CONDITION) 3440 { 3441 /* Sense data is already set, end the request and notify the guest. */ 3442 Log(("%s: sense=%#x (%s) asc=%#x ascq=%#x (%s)\n", __FUNCTION__, s->abATAPISense[2] & 0x0f, SCSISenseText(s->abATAPISense[2] & 0x0f), 3443 s->abATAPISense[12], s->abATAPISense[13], SCSISenseExtText(s->abATAPISense[12], s->abATAPISense[13]))); 3444 s->uATARegError = s->abATAPISense[2] << 4; 3445 ataSetStatusValue(s, ATA_STAT_READY | ATA_STAT_ERR); 3446 s->uATARegNSector = (s->uATARegNSector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; 3447 Log2(("%s: interrupt reason %#04x\n", __FUNCTION__, s->uATARegNSector)); 3448 s->cbTotalTransfer = 0; 3449 s->cbElementaryTransfer = 0; 3450 s->cbAtapiPassthroughTransfer = 0; 3451 s->iIOBufferCur = 0; 3452 s->iIOBufferEnd = 0; 3453 s->uTxDir = PDMMEDIATXDIR_NONE; 3454 s->iBeginTransfer = ATAFN_BT_NULL; 3455 s->iSourceSink = ATAFN_SS_NULL; 3456 } 3457 else if (u8ScsiSts == SCSI_STATUS_OK) 3458 atapiR3CmdOK(s); 3700 3459 } 3701 3460 }
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器