- Timestamp:
- Aug 29, 2010 3:54:53 PM (14 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevAHCI.cpp
r31087 r32069 100 100 #define AHCI_ATAPI_INQUIRY_REVISION_LENGTH 4 101 101 102 /* MediaEventStatus */ 103 #define ATA_EVENT_STATUS_UNCHANGED 0 /**< medium event status not changed */ 104 #define ATA_EVENT_STATUS_MEDIA_NEW 1 /**< new medium inserted */ 105 #define ATA_EVENT_STATUS_MEDIA_REMOVED 2 /**< medium removed */ 106 #define ATA_EVENT_STATUS_MEDIA_CHANGED 3 /**< medium was removed + new medium was inserted */ 107 #define ATA_EVENT_STATUS_MEDIA_EJECT_REQUESTED 4 /**< medium eject requested (eject button pressed) */ 108 109 /** ATAPI sense info size. */ 110 #define ATAPI_SENSE_SIZE 64 111 102 112 /* Command Header. */ 103 113 typedef struct … … 253 263 /** The ATAPI comnmand data. */ 254 264 uint8_t aATAPICmd[ATAPI_PACKET_SIZE]; 265 /** Size of one sector for the ATAPI transfer. */ 266 size_t cbATAPISector; 255 267 /** Physical address of the command header. - GC */ 256 268 RTGCPHYS GCPhysCmdHdrAddr; … … 402 414 /** Attached device is a CD/DVD drive. */ 403 415 bool fATAPI; 404 405 #if HC_ARCH_BITS == 64 406 uint32_t Alignment3; 407 #endif 416 /** Passthrough SCSI commands. */ 417 bool fATAPIPassthrough; 408 418 409 419 /** Device specific settings. */ … … 441 451 /** Currently active transfer mode (MDMA/UDMA) and speed. */ 442 452 uint8_t uATATransferMode; 443 /** ATAPI sense key. */ 444 uint8_t uATAPISenseKey; 445 /** ATAPI additional sens code. */ 446 uint8_t uATAPIASC; 453 /** ATAPI sense data. */ 454 uint8_t abATAPISense[ATAPI_SENSE_SIZE]; 447 455 /** HACK: Countdown till we report a newly unmounted drive as mounted. */ 448 456 uint8_t cNotifiedMediaChange; 457 /** The same for GET_EVENT_STATUS for mechanism */ 458 volatile uint32_t MediaEventStatus; 449 459 450 460 /** The LUN. */ … … 457 467 /** Bitmask for finished queued tasks. */ 458 468 volatile uint32_t u32QueuedTasksFinished; 469 470 uint32_t u32Alignment6; 459 471 460 472 /** … … 2717 2729 | ((pAhciPortTaskState->enmTxDir != AHCITXDIR_WRITE) ? ATAPI_INT_REASON_IO : 0) 2718 2730 | (!pAhciPortTaskState->cbTransfer ? ATAPI_INT_REASON_CD : 0); 2719 pAhciPort->uATAPISenseKey = SCSI_SENSE_NONE; 2720 pAhciPort->uATAPIASC = SCSI_ASC_NONE; 2721 } 2722 2723 2724 static void atapiCmdError(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, uint8_t uATAPISenseKey, uint8_t uATAPIASC) 2725 { 2726 pAhciPortTaskState->uATARegError = uATAPISenseKey << 4; 2731 memset(pAhciPort->abATAPISense, '\0', sizeof(pAhciPort->abATAPISense)); 2732 pAhciPort->abATAPISense[0] = 0x70; 2733 pAhciPort->abATAPISense[7] = 10; 2734 } 2735 2736 static void atapiCmdError(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, const uint8_t *pabATAPISense, size_t cbATAPISense) 2737 { 2738 Log(("%s: sense=%#x (%s) asc=%#x ascq=%#x (%s)\n", __FUNCTION__, pabATAPISense[2] & 0x0f, SCSISenseText(pabATAPISense[2] & 0x0f), 2739 pabATAPISense[12], pabATAPISense[13], SCSISenseExtText(pabATAPISense[12], pabATAPISense[13]))); 2740 pAhciPortTaskState->uATARegError = pabATAPISense[2] << 4; 2727 2741 pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR; 2728 2742 pAhciPortTaskState->cmdFis[AHCI_CMDFIS_SECTN] = (pAhciPortTaskState->cmdFis[AHCI_CMDFIS_SECTN] & ~7) | 2729 2743 ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; 2730 pAhciPort->uATAPISenseKey = uATAPISenseKey; 2731 pAhciPort->uATAPIASC = uATAPIASC; 2744 memset(pAhciPort->abATAPISense, '\0', sizeof(pAhciPort->abATAPISense)); 2745 memcpy(pAhciPort->abATAPISense, pabATAPISense, RT_MIN(cbATAPISense, sizeof(pAhciPort->abATAPISense))); 2746 } 2747 2748 /** @todo deprecated function - doesn't provide enough info. Replace by direct 2749 * calls to atapiCmdError() with full data. */ 2750 static void atapiCmdErrorSimple(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, uint8_t uATAPISenseKey, uint8_t uATAPIASC) 2751 { 2752 uint8_t abATAPISense[ATAPI_SENSE_SIZE]; 2753 memset(abATAPISense, '\0', sizeof(abATAPISense)); 2754 abATAPISense[0] = 0x70 | (1 << 7); 2755 abATAPISense[2] = uATAPISenseKey & 0x0f; 2756 abATAPISense[7] = 10; 2757 abATAPISense[12] = uATAPIASC; 2758 atapiCmdError(pAhciPort, pAhciPortTaskState, abATAPISense, sizeof(abATAPISense)); 2732 2759 } 2733 2760 … … 2831 2858 2832 2859 static int atapiGetConfigurationSS(PAHCIPORTTASKSTATE, PAHCIPort, int *); 2860 static int atapiGetEventStatusNotificationSS(PAHCIPORTTASKSTATE, PAHCIPort, int *); 2833 2861 static int atapiIdentifySS(PAHCIPORTTASKSTATE, PAHCIPort, int *); 2834 2862 static int atapiInquirySS(PAHCIPORTTASKSTATE, PAHCIPort, int *); … … 2843 2871 static int atapiReadTrackInformationSS(PAHCIPORTTASKSTATE, PAHCIPort, int *); 2844 2872 static int atapiRequestSenseSS(PAHCIPORTTASKSTATE, PAHCIPort, int *); 2845 //static int atapiPassthroughSS(PAHCIPORTTASKSTATE, PAHCIPort, int *);2873 static int atapiPassthroughSS(PAHCIPORTTASKSTATE, PAHCIPort, int *); 2846 2874 2847 2875 /** … … 2852 2880 ATAFN_SS_NULL = 0, 2853 2881 ATAFN_SS_ATAPI_GET_CONFIGURATION, 2882 ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION, 2854 2883 ATAFN_SS_ATAPI_IDENTIFY, 2855 2884 ATAFN_SS_ATAPI_INQUIRY, … … 2864 2893 ATAFN_SS_ATAPI_READ_TRACK_INFORMATION, 2865 2894 ATAFN_SS_ATAPI_REQUEST_SENSE, 2866 //ATAFN_SS_ATAPI_PASSTHROUGH,2895 ATAFN_SS_ATAPI_PASSTHROUGH, 2867 2896 ATAFN_SS_MAX 2868 2897 } ATAPIFN; … … 2876 2905 NULL, 2877 2906 atapiGetConfigurationSS, 2907 atapiGetEventStatusNotificationSS, 2878 2908 atapiIdentifySS, 2879 2909 atapiInquirySS, … … 2887 2917 atapiReadTOCRawSS, 2888 2918 atapiReadTrackInformationSS, 2889 atapiRequestSenseSS 2890 //atapiPassthroughSS2919 atapiRequestSenseSS, 2920 atapiPassthroughSS 2891 2921 }; 2892 2922 … … 2916 2946 p[73] = RT_H2LE_U16(0x003e); /* ATAPI CDROM major */ 2917 2947 p[74] = RT_H2LE_U16(9); /* ATAPI CDROM minor */ 2918 p[75] = RT_H2LE_U16(1); /* queue depth 1 */2919 2948 p[80] = RT_H2LE_U16(0x7e); /* support everything up to ATA/ATAPI-6 */ 2920 2949 p[81] = RT_H2LE_U16(0x22); /* conforms to ATA/ATAPI-6 */ … … 2988 3017 if ((pAhciPortTaskState->aATAPICmd[1] & 0x03) != 1 || ataBE2H_U32(&pAhciPortTaskState->aATAPICmd[2]) != 1) 2989 3018 { 2990 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);3019 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 2991 3020 return VINF_SUCCESS; 2992 3021 } … … 3018 3047 if ((pAhciPortTaskState->aATAPICmd[1] & 0x03) == 3 || ataBE2H_U16(&pAhciPortTaskState->aATAPICmd[2]) != 0) 3019 3048 { 3020 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);3049 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 3021 3050 return VINF_SUCCESS; 3022 3051 } … … 3040 3069 /* Copy the buffer in to the scatter gather list. */ 3041 3070 *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, (void *)&aBuf[0], sizeof(aBuf)); 3071 3072 atapiCmdOK(pAhciPort, pAhciPortTaskState); 3073 return VINF_SUCCESS; 3074 } 3075 3076 3077 static int atapiGetEventStatusNotificationSS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData) 3078 { 3079 uint8_t abBuf[8]; 3080 3081 Assert(pAhciPortTaskState->enmTxDir == AHCITXDIR_READ); 3082 Assert(pAhciPortTaskState->cbTransfer <= 8); 3083 3084 if (!(pAhciPortTaskState->aATAPICmd[1] & 1)) 3085 { 3086 /* no asynchronous operation supported */ 3087 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 3088 return VINF_SUCCESS; 3089 } 3090 3091 uint32_t OldStatus, NewStatus; 3092 do 3093 { 3094 OldStatus = ASMAtomicReadU32(&pAhciPort->MediaEventStatus); 3095 NewStatus = ATA_EVENT_STATUS_UNCHANGED; 3096 switch (OldStatus) 3097 { 3098 case ATA_EVENT_STATUS_MEDIA_NEW: 3099 /* mount */ 3100 ataH2BE_U16(abBuf + 0, 6); 3101 abBuf[2] = 0x04; /* media */ 3102 abBuf[3] = 0x5e; /* suppored = busy|media|external|power|operational */ 3103 abBuf[4] = 0x02; /* new medium */ 3104 abBuf[5] = 0x02; /* medium present / door closed */ 3105 abBuf[6] = 0x00; 3106 abBuf[7] = 0x00; 3107 break; 3108 3109 case ATA_EVENT_STATUS_MEDIA_CHANGED: 3110 case ATA_EVENT_STATUS_MEDIA_REMOVED: 3111 /* umount */ 3112 ataH2BE_U16(abBuf + 0, 6); 3113 abBuf[2] = 0x04; /* media */ 3114 abBuf[3] = 0x5e; /* suppored = busy|media|external|power|operational */ 3115 abBuf[4] = 0x03; /* media removal */ 3116 abBuf[5] = 0x00; /* medium absent / door closed */ 3117 abBuf[6] = 0x00; 3118 abBuf[7] = 0x00; 3119 if (OldStatus == ATA_EVENT_STATUS_MEDIA_CHANGED) 3120 NewStatus = ATA_EVENT_STATUS_MEDIA_NEW; 3121 break; 3122 3123 case ATA_EVENT_STATUS_MEDIA_EJECT_REQUESTED: /* currently unused */ 3124 ataH2BE_U16(abBuf + 0, 6); 3125 abBuf[2] = 0x04; /* media */ 3126 abBuf[3] = 0x5e; /* supported = busy|media|external|power|operational */ 3127 abBuf[4] = 0x01; /* eject requested (eject button pressed) */ 3128 abBuf[5] = 0x02; /* medium present / door closed */ 3129 abBuf[6] = 0x00; 3130 abBuf[7] = 0x00; 3131 break; 3132 3133 case ATA_EVENT_STATUS_UNCHANGED: 3134 default: 3135 ataH2BE_U16(abBuf + 0, 6); 3136 abBuf[2] = 0x01; /* operational change request / notification */ 3137 abBuf[3] = 0x5e; /* suppored = busy|media|external|power|operational */ 3138 abBuf[4] = 0x00; 3139 abBuf[5] = 0x00; 3140 abBuf[6] = 0x00; 3141 abBuf[7] = 0x00; 3142 break; 3143 } 3144 } while (!ASMAtomicCmpXchgU32(&pAhciPort->MediaEventStatus, NewStatus, OldStatus)); 3145 3146 *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, (void *)&abBuf[0], sizeof(abBuf)); 3042 3147 3043 3148 atapiCmdOK(pAhciPort, pAhciPortTaskState); … … 3151 3256 static int atapiRequestSenseSS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData) 3152 3257 { 3153 uint8_t aBuf[18];3154 3155 memset(&aBuf[0], 0, 18);3156 aBuf[0] = 0x70 | (1 << 7);3157 aBuf[2] = pAhciPort->uATAPISenseKey;3158 aBuf[7] = 10;3159 aBuf[12] = pAhciPort->uATAPIASC;3160 3161 3258 /* Copy the buffer in to the scatter gather list. */ 3162 *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, (void *)&aBuf[0], sizeof(aBuf));3259 *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, pAhciPort->abATAPISense, sizeof(pAhciPort->abATAPISense)); 3163 3260 3164 3261 atapiCmdOK(pAhciPort, pAhciPortTaskState); … … 3197 3294 if (iStartTrack > 1 && iStartTrack != 0xaa) 3198 3295 { 3199 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);3296 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 3200 3297 return VINF_SUCCESS; 3201 3298 } … … 3369 3466 } 3370 3467 3468 static int atapiPassthroughSS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData) 3469 { 3470 int rc = VINF_SUCCESS; 3471 uint8_t abATAPISense[ATAPI_SENSE_SIZE]; 3472 uint32_t cbTransfer; 3473 3474 cbTransfer = pAhciPortTaskState->cbTransfer; 3475 3476 /* Simple heuristics: if there is at least one sector of data 3477 * to transfer, it's worth updating the LEDs. */ 3478 if (cbTransfer >= 2048) 3479 { 3480 if (pAhciPortTaskState->enmTxDir != AHCITXDIR_WRITE) 3481 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1; 3482 else 3483 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1; 3484 } 3485 3486 if (cbTransfer > SCSI_MAX_BUFFER_SIZE) 3487 { 3488 /* Linux accepts commands with up to 100KB of data, but expects 3489 * us to handle commands with up to 128KB of data. The usual 3490 * imbalance of powers. */ 3491 uint8_t aATAPICmd[ATAPI_PACKET_SIZE]; 3492 uint32_t iATAPILBA, cSectors, cReqSectors, cbCurrTX; 3493 uint8_t *pbBuf = (uint8_t *)pAhciPortTaskState->pSGListHead[0].pvSeg; 3494 3495 Assert(pAhciPortTaskState->cSGListUsed == 1); 3496 3497 switch (pAhciPortTaskState->aATAPICmd[0]) 3498 { 3499 case SCSI_READ_10: 3500 case SCSI_WRITE_10: 3501 case SCSI_WRITE_AND_VERIFY_10: 3502 iATAPILBA = ataBE2H_U32(pAhciPortTaskState->aATAPICmd + 2); 3503 cSectors = ataBE2H_U16(pAhciPortTaskState->aATAPICmd + 7); 3504 break; 3505 case SCSI_READ_12: 3506 case SCSI_WRITE_12: 3507 iATAPILBA = ataBE2H_U32(pAhciPortTaskState->aATAPICmd + 2); 3508 cSectors = ataBE2H_U32(pAhciPortTaskState->aATAPICmd + 6); 3509 break; 3510 case SCSI_READ_CD: 3511 iATAPILBA = ataBE2H_U32(pAhciPortTaskState->aATAPICmd + 2); 3512 cSectors = ataBE2H_U24(pAhciPortTaskState->aATAPICmd + 6) / pAhciPortTaskState->cbATAPISector; 3513 break; 3514 case SCSI_READ_CD_MSF: 3515 iATAPILBA = ataMSF2LBA(pAhciPortTaskState->aATAPICmd + 3); 3516 cSectors = ataMSF2LBA(pAhciPortTaskState->aATAPICmd + 6) - iATAPILBA; 3517 break; 3518 default: 3519 AssertMsgFailed(("Don't know how to split command %#04x\n", pAhciPortTaskState->aATAPICmd[0])); 3520 //if (s->cErrors++ < MAX_LOG_REL_ERRORS) 3521 LogRel(("AHCI: LUN#%d: CD-ROM passthrough split error\n", pAhciPort->iLUN)); 3522 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE); 3523 return false; 3524 } 3525 memcpy(aATAPICmd, pAhciPortTaskState->aATAPICmd, ATAPI_PACKET_SIZE); 3526 cReqSectors = 0; 3527 for (uint32_t i = cSectors; i > 0; i -= cReqSectors) 3528 { 3529 if (i * pAhciPortTaskState->cbATAPISector > SCSI_MAX_BUFFER_SIZE) 3530 cReqSectors = SCSI_MAX_BUFFER_SIZE / pAhciPortTaskState->cbATAPISector; 3531 else 3532 cReqSectors = i; 3533 cbCurrTX = pAhciPortTaskState->cbATAPISector * cReqSectors; 3534 switch (pAhciPortTaskState->aATAPICmd[0]) 3535 { 3536 case SCSI_READ_10: 3537 case SCSI_WRITE_10: 3538 case SCSI_WRITE_AND_VERIFY_10: 3539 ataH2BE_U32(aATAPICmd + 2, iATAPILBA); 3540 ataH2BE_U16(aATAPICmd + 7, cReqSectors); 3541 break; 3542 case SCSI_READ_12: 3543 case SCSI_WRITE_12: 3544 ataH2BE_U32(aATAPICmd + 2, iATAPILBA); 3545 ataH2BE_U32(aATAPICmd + 6, cReqSectors); 3546 break; 3547 case SCSI_READ_CD: 3548 ataH2BE_U32(aATAPICmd + 2, iATAPILBA); 3549 ataH2BE_U24(aATAPICmd + 6, cbCurrTX); 3550 break; 3551 case SCSI_READ_CD_MSF: 3552 ataLBA2MSF(aATAPICmd + 3, iATAPILBA); 3553 ataLBA2MSF(aATAPICmd + 6, iATAPILBA + cReqSectors); 3554 break; 3555 } 3556 rc = pAhciPort->pDrvBlock->pfnSendCmd(pAhciPort->pDrvBlock, 3557 aATAPICmd, 3558 pAhciPortTaskState->enmTxDir == AHCITXDIR_READ 3559 ? PDMBLOCKTXDIR_FROM_DEVICE 3560 : PDMBLOCKTXDIR_TO_DEVICE, 3561 pbBuf, 3562 &cbCurrTX, 3563 abATAPISense, 3564 sizeof(abATAPISense), 3565 30000 /**< @todo timeout */); 3566 if (rc != VINF_SUCCESS) 3567 break; 3568 iATAPILBA += cReqSectors; 3569 pbBuf += pAhciPortTaskState->cbATAPISector * cReqSectors; 3570 } 3571 } 3572 else 3573 { 3574 PDMBLOCKTXDIR enmBlockTxDir = PDMBLOCKTXDIR_NONE; 3575 3576 if (pAhciPortTaskState->enmTxDir == AHCITXDIR_READ) 3577 enmBlockTxDir = PDMBLOCKTXDIR_FROM_DEVICE; 3578 else if (pAhciPortTaskState->enmTxDir == AHCITXDIR_WRITE) 3579 enmBlockTxDir = PDMBLOCKTXDIR_TO_DEVICE; 3580 else if (pAhciPortTaskState->enmTxDir == AHCITXDIR_NONE) 3581 enmBlockTxDir = PDMBLOCKTXDIR_NONE; 3582 else 3583 AssertMsgFailed(("Invalid transfer direction %d\n", pAhciPortTaskState->enmTxDir)); 3584 3585 rc = pAhciPort->pDrvBlock->pfnSendCmd(pAhciPort->pDrvBlock, 3586 pAhciPortTaskState->aATAPICmd, 3587 enmBlockTxDir, 3588 pAhciPortTaskState->pSGListHead[0].pvSeg, 3589 &cbTransfer, 3590 abATAPISense, 3591 sizeof(abATAPISense), 3592 30000 /**< @todo timeout */); 3593 } 3594 3595 /* Update the LEDs and the read/write statistics. */ 3596 if (cbTransfer >= 2048) 3597 { 3598 if (pAhciPortTaskState->enmTxDir != AHCITXDIR_WRITE) 3599 { 3600 pAhciPort->Led.Actual.s.fReading = 0; 3601 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, cbTransfer); 3602 } 3603 else 3604 { 3605 pAhciPort->Led.Actual.s.fWriting = 0; 3606 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, cbTransfer); 3607 } 3608 } 3609 3610 if (RT_SUCCESS(rc)) 3611 { 3612 Assert(cbTransfer <= pAhciPortTaskState->cbTransfer); 3613 /* Reply with the same amount of data as the real drive. */ 3614 *pcbData = cbTransfer; 3615 3616 if (pAhciPortTaskState->enmTxDir == AHCITXDIR_READ) 3617 { 3618 if (pAhciPortTaskState->aATAPICmd[0] == SCSI_INQUIRY) 3619 { 3620 /* Make sure that the real drive cannot be identified. 3621 * Motivation: changing the VM configuration should be as 3622 * invisible as possible to the guest. */ 3623 ataSCSIPadStr((uint8_t *)pAhciPortTaskState->pSGListHead[0].pvSeg + 8, "VBOX", 8); 3624 ataSCSIPadStr((uint8_t *)pAhciPortTaskState->pSGListHead[0].pvSeg + 16, "CD-ROM", 16); 3625 ataSCSIPadStr((uint8_t *)pAhciPortTaskState->pSGListHead[0].pvSeg + 32, "1.0", 4); 3626 } 3627 if (cbTransfer) 3628 Log3(("ATAPI PT data read (%d): %.*Rhxs\n", cbTransfer, cbTransfer, (uint8_t *)pAhciPortTaskState->pSGListHead[0].pvSeg)); 3629 } 3630 atapiCmdOK(pAhciPort, pAhciPortTaskState); 3631 } 3632 else 3633 { 3634 if (pAhciPort->cErrors < MAX_LOG_REL_ERRORS) 3635 { 3636 uint8_t u8Cmd = pAhciPortTaskState->aATAPICmd[0]; 3637 do 3638 { 3639 /* don't log superflous errors */ 3640 if ( rc == VERR_DEV_IO_ERROR 3641 && ( u8Cmd == SCSI_TEST_UNIT_READY 3642 || u8Cmd == SCSI_READ_CAPACITY 3643 || u8Cmd == SCSI_READ_DVD_STRUCTURE 3644 || u8Cmd == SCSI_READ_TOC_PMA_ATIP)) 3645 break; 3646 pAhciPort->cErrors++; 3647 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM passthrough cmd=%#04x sense=%d ASC=%#02x ASCQ=%#02x %Rrc\n", 3648 pAhciPort->iLUN, u8Cmd, abATAPISense[2] & 0x0f, abATAPISense[12], abATAPISense[13], rc)); 3649 } while (0); 3650 } 3651 atapiCmdError(pAhciPort, pAhciPortTaskState, abATAPISense, sizeof(abATAPISense)); 3652 } 3653 return false; 3654 } 3655 3371 3656 static int atapiDoTransfer(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, ATAPIFN iSourceSink) 3372 3657 { 3373 int cbTransfered ;3658 int cbTransfered = 0; 3374 3659 int rc, rcSourceSink; 3375 3660 … … 3380 3665 */ 3381 3666 ahciScatterGatherListGetTotalBufferSize(pAhciPort, pAhciPortTaskState); 3382 rc = ahciScatterGatherListCreateSafe(pAhciPort, pAhciPortTaskState, false, 0); 3383 AssertRC(rc); 3667 if (pAhciPortTaskState->cbSGBuffers) 3668 { 3669 rc = ahciScatterGatherListCreateSafe(pAhciPort, pAhciPortTaskState, false, 0); 3670 AssertRC(rc); 3671 } 3384 3672 3385 3673 rcSourceSink = g_apfnAtapiFuncs[iSourceSink](pAhciPortTaskState, pAhciPort, &cbTransfered); … … 3387 3675 pAhciPortTaskState->cmdHdr.u32PRDBC = cbTransfered; 3388 3676 3389 rc = ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState); 3390 AssertRC(rc); 3677 LogFlow(("cbTransfered=%d\n", cbTransfered)); 3678 3679 if (pAhciPortTaskState->cbSGBuffers) 3680 { 3681 rc = ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState); 3682 AssertRC(rc); 3683 } 3391 3684 3392 3685 /* Write updated command header into memory of the guest. */ … … 3450 3743 } 3451 3744 3452 static intatapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState)3453 { 3454 int iTxDir = PDMBLOCKTXDIR_NONE;3745 static AHCITXDIR atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState) 3746 { 3747 AHCITXDIR rc = AHCITXDIR_NONE; 3455 3748 const uint8_t *pbPacket; 3456 3749 uint32_t cbMax; … … 3466 3759 { 3467 3760 if (pAhciPort->cNotifiedMediaChange-- > 2) 3468 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);3761 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3469 3762 else 3470 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */3763 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 3471 3764 } 3472 3765 else if (pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 3473 3766 atapiCmdOK(pAhciPort, pAhciPortTaskState); 3474 3767 else 3475 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);3768 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3476 3769 break; 3477 3770 case SCSI_MODE_SENSE_10: … … 3502 3795 default: 3503 3796 case SCSI_PAGECONTROL_SAVED: 3504 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);3797 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED); 3505 3798 break; 3506 3799 } … … 3521 3814 } 3522 3815 else 3523 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);3816 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3524 3817 break; 3525 3818 case SCSI_READ_10: … … 3531 3824 { 3532 3825 pAhciPort->cNotifiedMediaChange-- ; 3533 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */3826 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 3534 3827 break; 3535 3828 } 3536 3829 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 3537 3830 { 3538 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);3831 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3539 3832 break; 3540 3833 } … … 3561 3854 uLastLogTS = RTTimeMilliTS(); 3562 3855 } 3563 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);3856 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 3564 3857 break; 3565 3858 } 3566 3859 atapiReadSectors(pAhciPort, pAhciPortTaskState, iATAPILBA, cSectors, 2048); 3567 iTxDir= AHCITXDIR_READ;3860 rc = AHCITXDIR_READ; 3568 3861 } 3569 3862 break; … … 3575 3868 { 3576 3869 pAhciPort->cNotifiedMediaChange-- ; 3577 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */3870 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 3578 3871 break; 3579 3872 } 3580 3873 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 3581 3874 { 3582 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);3875 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3583 3876 break; 3584 3877 } … … 3602 3895 uLastLogTS = RTTimeMilliTS(); 3603 3896 } 3604 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);3897 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 3605 3898 break; 3606 3899 } … … 3614 3907 /* normal read */ 3615 3908 atapiReadSectors(pAhciPort, pAhciPortTaskState, iATAPILBA, cSectors, 2048); 3616 iTxDir= AHCITXDIR_READ;3909 rc = AHCITXDIR_READ; 3617 3910 break; 3618 3911 case 0xf8: 3619 3912 /* read all data */ 3620 3913 atapiReadSectors(pAhciPort, pAhciPortTaskState, iATAPILBA, cSectors, 2352); 3621 iTxDir= AHCITXDIR_READ;3914 rc = AHCITXDIR_READ; 3622 3915 break; 3623 3916 default: 3624 3917 LogRel(("AHCI ATAPI: LUN#%d: CD-ROM sector format not supported\n", pAhciPort->iLUN)); 3625 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);3918 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 3626 3919 break; 3627 3920 } … … 3634 3927 { 3635 3928 pAhciPort->cNotifiedMediaChange-- ; 3636 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */3929 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 3637 3930 break; 3638 3931 } 3639 3932 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 3640 3933 { 3641 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);3934 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3642 3935 break; 3643 3936 } … … 3655 3948 uLastLogTS = RTTimeMilliTS(); 3656 3949 } 3657 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);3950 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 3658 3951 break; 3659 3952 } … … 3664 3957 case SCSI_START_STOP_UNIT: 3665 3958 { 3666 int rc = VINF_SUCCESS;3959 int rc2 = VINF_SUCCESS; 3667 3960 switch (pbPacket[4] & 3) 3668 3961 { … … 3676 3969 PPDMDEVINS pDevIns = pAhci->CTX_SUFF(pDevIns); 3677 3970 3678 rc = VMR3ReqCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,3679 (PFNRT)pAhciPort->pDrvMount->pfnUnmount, 2, pAhciPort->pDrvMount, false);3680 Assert(RT_SUCCESS(rc ) || (rc == VERR_PDM_MEDIA_LOCKED));3971 rc2 = VMR3ReqCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY, 3972 (PFNRT)pAhciPort->pDrvMount->pfnUnmount, 2, pAhciPort->pDrvMount, false); 3973 Assert(RT_SUCCESS(rc2) || (rc == VERR_PDM_MEDIA_LOCKED)); 3681 3974 } 3682 3975 break; … … 3685 3978 break; 3686 3979 } 3687 if (RT_SUCCESS(rc ))3980 if (RT_SUCCESS(rc2)) 3688 3981 atapiCmdOK(pAhciPort, pAhciPortTaskState); 3689 3982 else 3690 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED);3983 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED); 3691 3984 } 3692 3985 break; … … 3704 3997 { 3705 3998 pAhciPort->cNotifiedMediaChange-- ; 3706 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */3999 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 3707 4000 break; 3708 4001 } 3709 4002 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 3710 4003 { 3711 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);4004 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3712 4005 break; 3713 4006 } … … 3730 4023 default: 3731 4024 error_cmd: 3732 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);4025 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 3733 4026 break; 3734 4027 } … … 3739 4032 { 3740 4033 pAhciPort->cNotifiedMediaChange-- ; 3741 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */4034 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 3742 4035 break; 3743 4036 } 3744 4037 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 3745 4038 { 3746 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);4039 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3747 4040 break; 3748 4041 } … … 3753 4046 { 3754 4047 pAhciPort->cNotifiedMediaChange-- ; 3755 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */4048 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 3756 4049 break; 3757 4050 } 3758 4051 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 3759 4052 { 3760 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);4053 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3761 4054 break; 3762 4055 } … … 3768 4061 { 3769 4062 pAhciPort->cNotifiedMediaChange-- ; 3770 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */4063 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */ 3771 4064 break; 3772 4065 } 3773 4066 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 3774 4067 { 3775 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);4068 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3776 4069 break; 3777 4070 } … … 3789 4082 break; 3790 4083 default: 3791 atapiCmdError (pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);4084 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE); 3792 4085 break; 3793 4086 } 3794 4087 3795 return iTxDir; 4088 return rc; 4089 } 4090 4091 /* 4092 * Parse ATAPI commands, passing them directly to the CD/DVD drive. 4093 */ 4094 static AHCITXDIR atapiParseCmdPassthrough(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState) 4095 { 4096 const uint8_t *pbPacket; 4097 uint32_t cSectors, iATAPILBA; 4098 uint32_t cbTransfer = 0; 4099 AHCITXDIR enmTxDir = AHCITXDIR_NONE; 4100 4101 pbPacket = pAhciPortTaskState->aATAPICmd; 4102 switch (pbPacket[0]) 4103 { 4104 case SCSI_BLANK: 4105 goto sendcmd; 4106 case SCSI_CLOSE_TRACK_SESSION: 4107 goto sendcmd; 4108 case SCSI_ERASE_10: 4109 iATAPILBA = ataBE2H_U32(pbPacket + 2); 4110 cbTransfer = ataBE2H_U16(pbPacket + 7); 4111 Log2(("ATAPI PT: lba %d\n", iATAPILBA)); 4112 enmTxDir = AHCITXDIR_WRITE; 4113 goto sendcmd; 4114 case SCSI_FORMAT_UNIT: 4115 cbTransfer = pAhciPortTaskState->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciPortTaskState->cmdFis[AHCI_CMDFIS_CYLH] << 8); /* use ATAPI transfer length */ 4116 enmTxDir = AHCITXDIR_WRITE; 4117 goto sendcmd; 4118 case SCSI_GET_CONFIGURATION: 4119 cbTransfer = ataBE2H_U16(pbPacket + 7); 4120 enmTxDir = AHCITXDIR_READ; 4121 goto sendcmd; 4122 case SCSI_GET_EVENT_STATUS_NOTIFICATION: 4123 cbTransfer = ataBE2H_U16(pbPacket + 7); 4124 if (ASMAtomicReadU32(&pAhciPort->MediaEventStatus) != ATA_EVENT_STATUS_UNCHANGED) 4125 { 4126 pAhciPortTaskState->cbTransfer = RT_MIN(cbTransfer, 8); 4127 atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION); 4128 break; 4129 } 4130 enmTxDir = AHCITXDIR_READ; 4131 goto sendcmd; 4132 case SCSI_GET_PERFORMANCE: 4133 cbTransfer = pAhciPortTaskState->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciPortTaskState->cmdFis[AHCI_CMDFIS_CYLH] << 8); /* use ATAPI transfer length */ 4134 enmTxDir = AHCITXDIR_READ; 4135 goto sendcmd; 4136 case SCSI_INQUIRY: 4137 cbTransfer = ataBE2H_U16(pbPacket + 3); 4138 enmTxDir = AHCITXDIR_READ; 4139 goto sendcmd; 4140 case SCSI_LOAD_UNLOAD_MEDIUM: 4141 goto sendcmd; 4142 case SCSI_MECHANISM_STATUS: 4143 cbTransfer = ataBE2H_U16(pbPacket + 8); 4144 enmTxDir = AHCITXDIR_READ; 4145 goto sendcmd; 4146 case SCSI_MODE_SELECT_10: 4147 cbTransfer = ataBE2H_U16(pbPacket + 7); 4148 enmTxDir = AHCITXDIR_WRITE; 4149 goto sendcmd; 4150 case SCSI_MODE_SENSE_10: 4151 cbTransfer = ataBE2H_U16(pbPacket + 7); 4152 enmTxDir = AHCITXDIR_READ; 4153 goto sendcmd; 4154 case SCSI_PAUSE_RESUME: 4155 goto sendcmd; 4156 case SCSI_PLAY_AUDIO_10: 4157 goto sendcmd; 4158 case SCSI_PLAY_AUDIO_12: 4159 goto sendcmd; 4160 case SCSI_PLAY_AUDIO_MSF: 4161 goto sendcmd; 4162 case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL: 4163 /** @todo do not forget to unlock when a VM is shut down */ 4164 goto sendcmd; 4165 case SCSI_READ_10: 4166 iATAPILBA = ataBE2H_U32(pbPacket + 2); 4167 cSectors = ataBE2H_U16(pbPacket + 7); 4168 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors)); 4169 pAhciPortTaskState->cbATAPISector = 2048; /**< @todo this size is not always correct */ 4170 cbTransfer = cSectors * pAhciPortTaskState->cbATAPISector; 4171 enmTxDir = AHCITXDIR_READ; 4172 goto sendcmd; 4173 case SCSI_READ_12: 4174 iATAPILBA = ataBE2H_U32(pbPacket + 2); 4175 cSectors = ataBE2H_U32(pbPacket + 6); 4176 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors)); 4177 pAhciPortTaskState->cbATAPISector = 2048; /**< @todo this size is not always correct */ 4178 cbTransfer = cSectors * pAhciPortTaskState->cbATAPISector; 4179 enmTxDir = AHCITXDIR_READ; 4180 goto sendcmd; 4181 case SCSI_READ_BUFFER: 4182 cbTransfer = ataBE2H_U24(pbPacket + 6); 4183 enmTxDir = AHCITXDIR_READ; 4184 goto sendcmd; 4185 case SCSI_READ_BUFFER_CAPACITY: 4186 cbTransfer = ataBE2H_U16(pbPacket + 7); 4187 enmTxDir = AHCITXDIR_READ; 4188 goto sendcmd; 4189 case SCSI_READ_CAPACITY: 4190 cbTransfer = 8; 4191 enmTxDir = AHCITXDIR_READ; 4192 goto sendcmd; 4193 case SCSI_READ_CD: 4194 pAhciPortTaskState->cbATAPISector = 2048; /**< @todo this size is not always correct */ 4195 cbTransfer = ataBE2H_U24(pbPacket + 6) / pAhciPortTaskState->cbATAPISector * pAhciPortTaskState->cbATAPISector; 4196 enmTxDir = AHCITXDIR_READ; 4197 goto sendcmd; 4198 case SCSI_READ_CD_MSF: 4199 cSectors = ataMSF2LBA(pbPacket + 6) - ataMSF2LBA(pbPacket + 3); 4200 if (cSectors > 32) 4201 cSectors = 32; /* Limit transfer size to 64~74K. Safety first. In any case this can only harm software doing CDDA extraction. */ 4202 pAhciPortTaskState->cbATAPISector = 2048; /**< @todo this size is not always correct */ 4203 cbTransfer = cSectors * pAhciPortTaskState->cbATAPISector; 4204 enmTxDir = AHCITXDIR_READ; 4205 goto sendcmd; 4206 case SCSI_READ_DISC_INFORMATION: 4207 cbTransfer = ataBE2H_U16(pbPacket + 7); 4208 enmTxDir = AHCITXDIR_READ; 4209 goto sendcmd; 4210 case SCSI_READ_DVD_STRUCTURE: 4211 cbTransfer = ataBE2H_U16(pbPacket + 8); 4212 enmTxDir = AHCITXDIR_READ; 4213 goto sendcmd; 4214 case SCSI_READ_FORMAT_CAPACITIES: 4215 cbTransfer = ataBE2H_U16(pbPacket + 7); 4216 enmTxDir = AHCITXDIR_READ; 4217 goto sendcmd; 4218 case SCSI_READ_SUBCHANNEL: 4219 cbTransfer = ataBE2H_U16(pbPacket + 7); 4220 enmTxDir = AHCITXDIR_READ; 4221 goto sendcmd; 4222 case SCSI_READ_TOC_PMA_ATIP: 4223 cbTransfer = ataBE2H_U16(pbPacket + 7); 4224 enmTxDir = AHCITXDIR_READ; 4225 goto sendcmd; 4226 case SCSI_READ_TRACK_INFORMATION: 4227 cbTransfer = ataBE2H_U16(pbPacket + 7); 4228 enmTxDir = AHCITXDIR_READ; 4229 goto sendcmd; 4230 case SCSI_REPAIR_TRACK: 4231 goto sendcmd; 4232 case SCSI_REPORT_KEY: 4233 cbTransfer = ataBE2H_U16(pbPacket + 8); 4234 enmTxDir = AHCITXDIR_READ; 4235 goto sendcmd; 4236 case SCSI_REQUEST_SENSE: 4237 cbTransfer = pbPacket[4]; 4238 if ((pAhciPort->abATAPISense[2] & 0x0f) != SCSI_SENSE_NONE) 4239 { 4240 pAhciPortTaskState->cbTransfer = cbTransfer; 4241 pAhciPortTaskState->enmTxDir = AHCITXDIR_READ; 4242 atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_REQUEST_SENSE); 4243 break; 4244 } 4245 enmTxDir = AHCITXDIR_READ; 4246 goto sendcmd; 4247 case SCSI_RESERVE_TRACK: 4248 goto sendcmd; 4249 case SCSI_SCAN: 4250 goto sendcmd; 4251 case SCSI_SEEK_10: 4252 goto sendcmd; 4253 case SCSI_SEND_CUE_SHEET: 4254 cbTransfer = ataBE2H_U24(pbPacket + 6); 4255 enmTxDir = AHCITXDIR_WRITE; 4256 goto sendcmd; 4257 case SCSI_SEND_DVD_STRUCTURE: 4258 cbTransfer = ataBE2H_U16(pbPacket + 8); 4259 enmTxDir = AHCITXDIR_WRITE; 4260 goto sendcmd; 4261 case SCSI_SEND_EVENT: 4262 cbTransfer = ataBE2H_U16(pbPacket + 8); 4263 enmTxDir = AHCITXDIR_WRITE; 4264 goto sendcmd; 4265 case SCSI_SEND_KEY: 4266 cbTransfer = ataBE2H_U16(pbPacket + 8); 4267 enmTxDir = AHCITXDIR_WRITE; 4268 goto sendcmd; 4269 case SCSI_SEND_OPC_INFORMATION: 4270 cbTransfer = ataBE2H_U16(pbPacket + 7); 4271 enmTxDir = AHCITXDIR_WRITE; 4272 goto sendcmd; 4273 case SCSI_SET_CD_SPEED: 4274 goto sendcmd; 4275 case SCSI_SET_READ_AHEAD: 4276 goto sendcmd; 4277 case SCSI_SET_STREAMING: 4278 cbTransfer = ataBE2H_U16(pbPacket + 9); 4279 enmTxDir = AHCITXDIR_WRITE; 4280 goto sendcmd; 4281 case SCSI_START_STOP_UNIT: 4282 goto sendcmd; 4283 case SCSI_STOP_PLAY_SCAN: 4284 goto sendcmd; 4285 case SCSI_SYNCHRONIZE_CACHE: 4286 goto sendcmd; 4287 case SCSI_TEST_UNIT_READY: 4288 goto sendcmd; 4289 case SCSI_VERIFY_10: 4290 goto sendcmd; 4291 case SCSI_WRITE_10: 4292 iATAPILBA = ataBE2H_U32(pbPacket + 2); 4293 cSectors = ataBE2H_U16(pbPacket + 7); 4294 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors)); 4295 pAhciPortTaskState->cbATAPISector = 2048; /**< @todo this size is not always correct */ 4296 cbTransfer = cSectors * pAhciPortTaskState->cbATAPISector; 4297 enmTxDir = AHCITXDIR_WRITE; 4298 goto sendcmd; 4299 case SCSI_WRITE_12: 4300 iATAPILBA = ataBE2H_U32(pbPacket + 2); 4301 cSectors = ataBE2H_U32(pbPacket + 6); 4302 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors)); 4303 pAhciPortTaskState->cbATAPISector = 2048; /**< @todo this size is not always correct */ 4304 cbTransfer = cSectors * pAhciPortTaskState->cbATAPISector; 4305 enmTxDir = AHCITXDIR_WRITE; 4306 goto sendcmd; 4307 case SCSI_WRITE_AND_VERIFY_10: 4308 iATAPILBA = ataBE2H_U32(pbPacket + 2); 4309 cSectors = ataBE2H_U16(pbPacket + 7); 4310 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors)); 4311 /* The sector size is determined by the async I/O thread. */ 4312 pAhciPortTaskState->cbATAPISector = 0; 4313 /* Preliminary, will be corrected once the sector size is known. */ 4314 cbTransfer = cSectors; 4315 enmTxDir = AHCITXDIR_WRITE; 4316 goto sendcmd; 4317 case SCSI_WRITE_BUFFER: 4318 switch (pbPacket[1] & 0x1f) 4319 { 4320 case 0x04: /* download microcode */ 4321 case 0x05: /* download microcode and save */ 4322 case 0x06: /* download microcode with offsets */ 4323 case 0x07: /* download microcode with offsets and save */ 4324 case 0x0e: /* download microcode with offsets and defer activation */ 4325 case 0x0f: /* activate deferred microcode */ 4326 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM passthrough command attempted to update firmware, blocked\n", pAhciPort->iLUN)); 4327 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 4328 break; 4329 default: 4330 cbTransfer = ataBE2H_U16(pbPacket + 6); 4331 enmTxDir = AHCITXDIR_WRITE; 4332 goto sendcmd; 4333 } 4334 break; 4335 case SCSI_REPORT_LUNS: /* Not part of MMC-3, but used by Windows. */ 4336 cbTransfer = ataBE2H_U32(pbPacket + 6); 4337 enmTxDir = AHCITXDIR_READ; 4338 goto sendcmd; 4339 case SCSI_REZERO_UNIT: 4340 /* Obsolete command used by cdrecord. What else would one expect? 4341 * This command is not sent to the drive, it is handled internally, 4342 * as the Linux kernel doesn't like it (message "scsi: unknown 4343 * opcode 0x01" in syslog) and replies with a sense code of 0, 4344 * which sends cdrecord to an endless loop. */ 4345 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE); 4346 break; 4347 default: 4348 LogRel(("AHCI: LUN#%d: passthrough unimplemented for command %#x\n", pAhciPort->iLUN, pbPacket[0])); 4349 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE); 4350 break; 4351 sendcmd: 4352 /* Send a command to the drive, passing data in/out as required. */ 4353 Log2(("ATAPI PT: max size %d\n", cbTransfer)); 4354 if (cbTransfer == 0) 4355 enmTxDir = AHCITXDIR_NONE; 4356 pAhciPortTaskState->enmTxDir = enmTxDir; 4357 pAhciPortTaskState->cbTransfer = cbTransfer; 4358 atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_PASSTHROUGH); 4359 } 4360 4361 return AHCITXDIR_NONE; 4362 } 4363 4364 static AHCITXDIR atapiParseCmd(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState) 4365 { 4366 AHCITXDIR enmTxDir = AHCITXDIR_NONE; 4367 const uint8_t *pbPacket; 4368 4369 pbPacket = pAhciPortTaskState->aATAPICmd; 4370 #ifdef DEBUG 4371 Log(("%s: LUN#%d CMD=%#04x \"%s\"\n", __FUNCTION__, pAhciPort->iLUN, pbPacket[0], SCSICmdText(pbPacket[0]))); 4372 #else /* !DEBUG */ 4373 Log(("%s: LUN#%d CMD=%#04x\n", __FUNCTION__, pAhciPort->iLUN, pbPacket[0])); 4374 #endif /* !DEBUG */ 4375 Log2(("%s: limit=%#x packet: %.*Rhxs\n", __FUNCTION__, pAhciPortTaskState->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciPortTaskState->cmdFis[AHCI_CMDFIS_CYLH] << 8), ATAPI_PACKET_SIZE, pbPacket)); 4376 4377 if (pAhciPort->fATAPIPassthrough) 4378 enmTxDir = atapiParseCmdPassthrough(pAhciPort, pAhciPortTaskState); 4379 else 4380 enmTxDir = atapiParseCmdVirtualATAPI(pAhciPort, pAhciPortTaskState); 4381 4382 return enmTxDir; 3796 4383 } 3797 4384 … … 4037 4624 ahciLog(("%s: cSGEntriesGC=%u\n", __FUNCTION__, cSGLEntriesGCLeft)); 4038 4625 4039 /* Set start address of the entries. */ 4040 GCPhysAddrPRDTLEntryStart = AHCI_RTGCPHYS_FROM_U32(pCmdHdr->u32CmdTblAddrUp, pCmdHdr->u32CmdTblAddr) + AHCI_CMDHDR_PRDT_OFFSET; 4041 4042 do 4043 { 4044 cSGLEntriesGCRead = (cSGLEntriesGCLeft < RT_ELEMENTS(aSGLEntry)) ? cSGLEntriesGCLeft : RT_ELEMENTS(aSGLEntry); 4045 cSGLEntriesGCLeft -= cSGLEntriesGCRead; 4046 4047 /* Read the SG entries. */ 4048 PDMDevHlpPhysRead(pDevIns, GCPhysAddrPRDTLEntryStart, &aSGLEntry[0], cSGLEntriesGCRead * sizeof(SGLEntry)); 4049 4050 for (cActualSGEntry = 0; cActualSGEntry < cSGLEntriesGCRead; cActualSGEntry++) 4626 if (cSGLEntriesGCLeft) 4627 { 4628 /* Set start address of the entries. */ 4629 GCPhysAddrPRDTLEntryStart = AHCI_RTGCPHYS_FROM_U32(pCmdHdr->u32CmdTblAddrUp, pCmdHdr->u32CmdTblAddr) + AHCI_CMDHDR_PRDT_OFFSET; 4630 4631 do 4632 { 4633 cSGLEntriesGCRead = (cSGLEntriesGCLeft < RT_ELEMENTS(aSGLEntry)) ? cSGLEntriesGCLeft : RT_ELEMENTS(aSGLEntry); 4634 cSGLEntriesGCLeft -= cSGLEntriesGCRead; 4635 4636 /* Read the SG entries. */ 4637 PDMDevHlpPhysRead(pDevIns, GCPhysAddrPRDTLEntryStart, &aSGLEntry[0], cSGLEntriesGCRead * sizeof(SGLEntry)); 4638 4639 for (cActualSGEntry = 0; cActualSGEntry < cSGLEntriesGCRead; cActualSGEntry++) 4051 4640 cbSGBuffers += (aSGLEntry[cActualSGEntry].u32DescInf & SGLENTRY_DESCINF_DBC) + 1; 4052 4641 4053 /* Set address to the next entries to read. */4054 GCPhysAddrPRDTLEntryStart += cSGLEntriesGCRead * sizeof(SGLEntry);4055 4056 } while (cSGLEntriesGCLeft);4642 /* Set address to the next entries to read. */ 4643 GCPhysAddrPRDTLEntryStart += cSGLEntriesGCRead * sizeof(SGLEntry); 4644 } while (cSGLEntriesGCLeft); 4645 } 4057 4646 4058 4647 pAhciPortTaskState->cbSGBuffers = cbSGBuffers; … … 5092 5681 } 5093 5682 else 5094 { 5095 int rc2 = atapiParseCmdVirtualATAPI(pAhciPort, pAhciPortTaskState); 5096 } 5683 rc = atapiParseCmd(pAhciPort, pAhciPortTaskState); 5097 5684 break; 5098 5685 case ATA_IDENTIFY_PACKET_DEVICE: … … 5891 6478 } 5892 6479 5893 /**5894 * Called when a media is mounted.5895 *5896 * @param pInterface Pointer to the interface structure containing the called function pointer.5897 */5898 static DECLCALLBACK(void) ahciMountNotify(PPDMIMOUNTNOTIFY pInterface)5899 {5900 PAHCIPort pAhciPort = PDMIMOUNTNOTIFY_2_PAHCIPORT(pInterface);5901 Log(("%s: changing LUN#%d\n", __FUNCTION__, pAhciPort->iLUN));5902 5903 /* Ignore the call if we're called while being attached. */5904 if (!pAhciPort->pDrvBlock)5905 return;5906 5907 pAhciPort->cTotalSectors = pAhciPort->pDrvBlock->pfnGetSize(pAhciPort->pDrvBlock) / 512;5908 5909 /*5910 * Initialize registers5911 */5912 pAhciPort->regCMD |= AHCI_PORT_CMD_CPS;5913 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_CPDS | AHCI_PORT_IS_PRCS);5914 pAhciPort->regSERR |= AHCI_PORT_SERR_N;5915 if (pAhciPort->regIE & AHCI_PORT_IE_CPDE)5916 ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN);5917 }5918 5919 /**5920 * Called when a media is unmounted5921 * @param pInterface Pointer to the interface structure containing the called function pointer.5922 */5923 static DECLCALLBACK(void) ahciUnmountNotify(PPDMIMOUNTNOTIFY pInterface)5924 {5925 PAHCIPort pAhciPort = PDMIMOUNTNOTIFY_2_PAHCIPORT(pInterface);5926 Log(("%s:\n", __FUNCTION__));5927 5928 pAhciPort->cTotalSectors = 0;5929 5930 /*5931 * Inform the guest about the removed device.5932 */5933 pAhciPort->regSSTS = 0;5934 pAhciPort->regCMD &= ~AHCI_PORT_CMD_CPS;5935 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_CPDS | AHCI_PORT_IS_PRCS);5936 pAhciPort->regSERR |= AHCI_PORT_SERR_N;5937 if (pAhciPort->regIE & AHCI_PORT_IE_CPDE)5938 ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN);5939 }5940 5941 6480 /* -=-=-=-=- DBGF -=-=-=-=- */ 5942 6481 … … 6432 6971 6433 6972 /** 6973 * SCSI_GET_EVENT_STATUS_NOTIFICATION should return "medium removed" event 6974 * from now on, regardless if there was a medium inserted or not. 6975 */ 6976 static void ahciMediumRemoved(PAHCIPort pAhciPort) 6977 { 6978 ASMAtomicWriteU32(&pAhciPort->MediaEventStatus, ATA_EVENT_STATUS_MEDIA_REMOVED); 6979 } 6980 6981 6982 /** 6983 * SCSI_GET_EVENT_STATUS_NOTIFICATION should return "medium inserted". If 6984 * there was already a medium inserted, don't forget to send the "medium 6985 * removed" event first. 6986 */ 6987 static void ahciMediumInserted(PAHCIPort pAhciPort) 6988 { 6989 uint32_t OldStatus, NewStatus; 6990 do 6991 { 6992 OldStatus = ASMAtomicReadU32(&pAhciPort->MediaEventStatus); 6993 switch (OldStatus) 6994 { 6995 case ATA_EVENT_STATUS_MEDIA_CHANGED: 6996 case ATA_EVENT_STATUS_MEDIA_REMOVED: 6997 /* no change, we will send "medium removed" + "medium inserted" */ 6998 NewStatus = ATA_EVENT_STATUS_MEDIA_CHANGED; 6999 break; 7000 default: 7001 NewStatus = ATA_EVENT_STATUS_MEDIA_NEW; 7002 break; 7003 } 7004 } while (!ASMAtomicCmpXchgU32(&pAhciPort->MediaEventStatus, NewStatus, OldStatus)); 7005 } 7006 7007 /** 7008 * Called when a media is mounted. 7009 * 7010 * @param pInterface Pointer to the interface structure containing the called function pointer. 7011 */ 7012 static DECLCALLBACK(void) ahciMountNotify(PPDMIMOUNTNOTIFY pInterface) 7013 { 7014 PAHCIPort pAhciPort = PDMIMOUNTNOTIFY_2_PAHCIPORT(pInterface); 7015 Log(("%s: changing LUN#%d\n", __FUNCTION__, pAhciPort->iLUN)); 7016 7017 /* Ignore the call if we're called while being attached. */ 7018 if (!pAhciPort->pDrvBlock) 7019 return; 7020 7021 if (pAhciPort->fATAPI) 7022 { 7023 pAhciPort->cTotalSectors = pAhciPort->pDrvBlock->pfnGetSize(pAhciPort->pDrvBlock) / 2048; 7024 7025 LogRel(("AHCI: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough unchanged\n", pAhciPort->iLUN, pAhciPort->cTotalSectors)); 7026 7027 /* Report media changed in TEST UNIT and other (probably incorrect) places. */ 7028 if (pAhciPort->cNotifiedMediaChange < 2) 7029 pAhciPort->cNotifiedMediaChange = 2; 7030 ahciMediumInserted(pAhciPort); 7031 } 7032 else 7033 { 7034 pAhciPort->cTotalSectors = pAhciPort->pDrvBlock->pfnGetSize(pAhciPort->pDrvBlock) / 512; 7035 7036 /* 7037 * Initialize registers 7038 */ 7039 pAhciPort->regCMD |= AHCI_PORT_CMD_CPS; 7040 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_CPDS | AHCI_PORT_IS_PRCS); 7041 pAhciPort->regSERR |= AHCI_PORT_SERR_N; 7042 if (pAhciPort->regIE & AHCI_PORT_IE_CPDE) 7043 ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN); 7044 } 7045 } 7046 7047 /** 7048 * Called when a media is unmounted 7049 * @param pInterface Pointer to the interface structure containing the called function pointer. 7050 */ 7051 static DECLCALLBACK(void) ahciUnmountNotify(PPDMIMOUNTNOTIFY pInterface) 7052 { 7053 PAHCIPort pAhciPort = PDMIMOUNTNOTIFY_2_PAHCIPORT(pInterface); 7054 Log(("%s:\n", __FUNCTION__)); 7055 7056 pAhciPort->cTotalSectors = 0; 7057 7058 if (pAhciPort->fATAPI) 7059 { 7060 /* 7061 * Whatever I do, XP will not use the GET MEDIA STATUS nor the EVENT stuff. 7062 * However, it will respond to TEST UNIT with a 0x6 0x28 (media changed) sense code. 7063 * So, we'll give it 4 TEST UNIT command to catch up, two which the media is not 7064 * present and 2 in which it is changed. 7065 */ 7066 pAhciPort->cNotifiedMediaChange = 4; 7067 ahciMediumRemoved(pAhciPort); 7068 } 7069 else 7070 { 7071 /* 7072 * Inform the guest about the removed device. 7073 */ 7074 pAhciPort->regSSTS = 0; 7075 pAhciPort->regCMD &= ~AHCI_PORT_CMD_CPS; 7076 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_CPDS | AHCI_PORT_IS_PRCS); 7077 pAhciPort->regSERR |= AHCI_PORT_SERR_N; 7078 if (pAhciPort->regIE & AHCI_PORT_IE_CPDE) 7079 ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN); 7080 } 7081 } 7082 7083 /** 6434 7084 * Configure the attached device for a port. 6435 7085 * … … 6486 7136 } 6487 7137 pAhciPort->fATAPI = (enmType == PDMBLOCKTYPE_CDROM || enmType == PDMBLOCKTYPE_DVD); 7138 pAhciPort->fATAPIPassthrough = pAhciPort->fATAPI ? (pAhciPort->pDrvBlock->pfnSendCmd != NULL) : false; 6488 7139 6489 7140 if (pAhciPort->fATAPI) … … 6642 7293 if (pCtl) 6643 7294 ataControllerDetach(pCtl, fMaster); 7295 7296 if (pAhciPort->fATAPI) 7297 ahciMediumRemoved(pAhciPort); 6644 7298 6645 7299 /* … … 6716 7370 if (RT_SUCCESS(rc)) 6717 7371 { 6718 if (pAhciPort->pDrvBlockAsync) 7372 if ( pAhciPort->pDrvBlockAsync 7373 && !pAhciPort->fATAPI) 6719 7374 { 6720 7375 pAhciPort->fAsyncInterface = true; … … 6744 7399 } 6745 7400 } 7401 7402 if (RT_SUCCESS(rc) && pAhciPort->fATAPI) 7403 ahciMediumInserted(pAhciPort); 6746 7404 } 6747 7405 } -
trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
r31899 r32069 1176 1176 GEN_CHECK_OFF(AHCIPort, fFirstD2HFisSend); 1177 1177 GEN_CHECK_OFF(AHCIPort, fATAPI); 1178 GEN_CHECK_OFF(AHCIPort, fATAPIPassthrough); 1178 1179 GEN_CHECK_OFF(AHCIPort, pDrvBase); 1179 1180 GEN_CHECK_OFF(AHCIPort, pDrvBlock); … … 1190 1191 GEN_CHECK_OFF(AHCIPort, cMultSectors); 1191 1192 GEN_CHECK_OFF(AHCIPort, uATATransferMode); 1192 GEN_CHECK_OFF(AHCIPort, uATAPISenseKey); 1193 GEN_CHECK_OFF(AHCIPort, uATAPIASC); 1193 GEN_CHECK_OFF(AHCIPort, abATAPISense); 1194 1194 GEN_CHECK_OFF(AHCIPort, cNotifiedMediaChange); 1195 1195 GEN_CHECK_OFF(AHCIPort, iLUN);
Note:
See TracChangeset
for help on using the changeset viewer.