Changeset 89266 in vbox for trunk/src/VBox/Devices/Storage
- Timestamp:
- May 25, 2021 11:10:45 AM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 144609
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevBusLogic.cpp
r89197 r89266 336 336 volatile uint8_t regGeometry; 337 337 /** Pending (delayed) interrupt. */ 338 uint8_tuPendingIntr;338 volatile uint8_t uPendingIntr; 339 339 340 340 /** Command code the guest issued. */ … … 395 395 /** Whether a notification to R3 was sent. */ 396 396 volatile bool fNotificationSent; 397 /** Flag whether a BIOS request is pending. */ 398 volatile bool fBiosReqPending; 397 399 398 400 /** Whether strict round robin is enabled. */ … … 996 998 } BUSLOGICREQ; 997 999 1000 /** 1001 * S/G buffer copy arguments. 1002 */ 1003 typedef struct BUSLOGICCOPYARGS 1004 { 1005 /** Pointer to the shared BusLogic instance data. */ 1006 PBUSLOGIC pThis; 1007 /** Pointer to the device instance data. */ 1008 PPDMDEVINS pDevIns; 1009 /** Pointer to the SCSI command buffer. */ 1010 PESCMD pCmd; 1011 /** Number of bytes copied already. */ 1012 size_t cbCopied; 1013 } BUSLOGICCOPYARGS; 1014 /** Pointer to BUSLOGICCOPYARGS. */ 1015 typedef BUSLOGICCOPYARGS *PBUSLOGICCOPYARGS; 1016 998 1017 #ifdef IN_RING3 999 1018 /** … … 1885 1904 bool fSuppressIrq = false; 1886 1905 bool fSuppressCMDC = false; 1906 bool fCmdComplete = true; 1887 1907 1888 1908 LogFlowFunc(("pThis=%#p\n", pThis)); … … 2021 2041 /* Second pass - process received data. */ 2022 2042 Log(("Execute SCSI cmd: received %u bytes\n", pThis->aCommandBuffer[0])); 2023 2024 2043 pCmd = (PESCMD)pThis->aCommandBuffer; 2025 2044 Log(("Addr %08X, cbData %08X, cbCDB=%u\n", pCmd->u32PhysAddrData, pCmd->cbData, pCmd->cbCDB)); 2045 2046 if (!ASMAtomicXchgBool(&pThis->fBiosReqPending, true)) 2047 { 2048 /* Wake up the worker thread. */ 2049 int rc2 = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEvtProcess); 2050 AssertRC(rc2); 2051 } 2052 2053 fCmdComplete = false; 2026 2054 } 2027 // This is currently a dummy - just fails every command.2028 pThis->cbReplyParametersLeft = 4;2029 pThis->aReplyBuffer[0] = pThis->aReplyBuffer[1] = 0;2030 pThis->aReplyBuffer[2] = 0x11; /* HBA status (timeout). */2031 pThis->aReplyBuffer[3] = 0; /* Device status. */2032 2055 break; 2033 2056 … … 2424 2447 } 2425 2448 2426 /* Set the data in ready bit in the status register in case the command has a reply. */ 2427 if (pThis->cbReplyParametersLeft) 2428 pThis->regStatus |= BL_STAT_DIRRDY; 2429 else if (!pThis->cbCommandParametersLeft) 2430 buslogicCommandComplete(pDevIns, pThis, fSuppressIrq, fSuppressCMDC); 2449 if (fCmdComplete) 2450 { 2451 /* Set the data in ready bit in the status register in case the command has a reply. */ 2452 if (pThis->cbReplyParametersLeft) 2453 pThis->regStatus |= BL_STAT_DIRRDY; 2454 else if (!pThis->cbCommandParametersLeft) 2455 buslogicCommandComplete(pDevIns, pThis, fSuppressIrq, fSuppressCMDC); 2456 } 2431 2457 2432 2458 return rc; … … 2875 2901 } 2876 2902 2903 /** 2904 * Completes a request initiated by the BIOS through the BUSLOGICCOMMAND_EXECUTE_SCSI_COMMAND command. 2905 * 2906 * @returns nothing. 2907 * @param pThis Pointer to the shared BusLogic instance data. 2908 * @param u8ScsiSts The SCSI status code. 2909 */ 2910 static void buslogicR3ReqCompleteBios(PBUSLOGIC pThis, uint8_t u8ScsiSts) 2911 { 2912 pThis->cbReplyParametersLeft = 4; 2913 pThis->aReplyBuffer[0] = pThis->aReplyBuffer[1] = 0; 2914 pThis->aReplyBuffer[2] = u8ScsiSts; 2915 pThis->aReplyBuffer[3] = 0; 2916 2917 pThis->regStatus |= BL_STAT_DIRRDY; 2918 } 2877 2919 2878 2920 static int buslogicR3ReqComplete(PPDMDEVINS pDevIns, PBUSLOGIC pThis, PBUSLOGICCC pThisCC, PBUSLOGICREQ pReq, int rcReq) … … 2885 2927 LogFlowFunc(("after decrement %u\n", pTgtDev->cOutstandingRequests)); 2886 2928 2887 if (pReq->pbSenseBuffer) 2888 buslogicR3SenseBufferFree(pReq, (pReq->u8ScsiSts != SCSI_STATUS_OK)); 2889 2890 /* Update residual data length. */ 2891 if ( (pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH) 2892 || (pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER)) 2893 { 2894 size_t cbResidual = 0; 2895 int rc = pTgtDev->pDrvMediaEx->pfnIoReqQueryResidual(pTgtDev->pDrvMediaEx, pReq->hIoReq, &cbResidual); 2896 AssertRC(rc); Assert(cbResidual == (uint32_t)cbResidual); 2897 2898 if (pReq->fIs24Bit) 2899 U32_TO_LEN(pReq->CCBGuest.o.acbData, (uint32_t)cbResidual); 2929 if (pReq->fBIOS) 2930 { 2931 uint8_t u8ScsiSts = pReq->u8ScsiSts; 2932 pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq); 2933 buslogicR3ReqCompleteBios(pThis, u8ScsiSts); 2934 } 2935 else 2936 { 2937 if (pReq->pbSenseBuffer) 2938 buslogicR3SenseBufferFree(pReq, (pReq->u8ScsiSts != SCSI_STATUS_OK)); 2939 2940 /* Update residual data length. */ 2941 if ( (pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH) 2942 || (pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER)) 2943 { 2944 size_t cbResidual = 0; 2945 int rc = pTgtDev->pDrvMediaEx->pfnIoReqQueryResidual(pTgtDev->pDrvMediaEx, pReq->hIoReq, &cbResidual); 2946 AssertRC(rc); Assert(cbResidual == (uint32_t)cbResidual); 2947 2948 if (pReq->fIs24Bit) 2949 U32_TO_LEN(pReq->CCBGuest.o.acbData, (uint32_t)cbResidual); 2950 else 2951 pReq->CCBGuest.n.cbData = (uint32_t)cbResidual; 2952 } 2953 2954 /* 2955 * Save vital things from the request and free it before posting completion 2956 * to avoid that the guest submits a new request with the same ID as the still 2957 * allocated one. 2958 */ 2959 #ifdef LOG_ENABLED 2960 bool fIs24Bit = pReq->fIs24Bit; 2961 #endif 2962 uint8_t u8ScsiSts = pReq->u8ScsiSts; 2963 RTGCPHYS GCPhysAddrCCB = pReq->GCPhysAddrCCB; 2964 CCBU CCBGuest; 2965 memcpy(&CCBGuest, &pReq->CCBGuest, sizeof(CCBU)); 2966 2967 pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq); 2968 if (u8ScsiSts == SCSI_STATUS_OK) 2969 buslogicR3SendIncomingMailbox(pDevIns, pThis, GCPhysAddrCCB, &CCBGuest, 2970 BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED, 2971 BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD, 2972 BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITHOUT_ERROR); 2973 else if (u8ScsiSts == SCSI_STATUS_CHECK_CONDITION) 2974 buslogicR3SendIncomingMailbox(pDevIns, pThis, GCPhysAddrCCB, &CCBGuest, 2975 BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED, 2976 BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_CHECK_CONDITION, 2977 BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR); 2900 2978 else 2901 pReq->CCBGuest.n.cbData = (uint32_t)cbResidual; 2902 } 2903 2904 /* 2905 * Save vital things from the request and free it before posting completion 2906 * to avoid that the guest submits a new request with the same ID as the still 2907 * allocated one. 2908 */ 2979 AssertMsgFailed(("invalid completion status %u\n", u8ScsiSts)); 2980 2909 2981 #ifdef LOG_ENABLED 2910 bool fIs24Bit = pReq->fIs24Bit;2982 buslogicR3DumpCCBInfo(&CCBGuest, fIs24Bit); 2911 2983 #endif 2912 uint8_t u8ScsiSts = pReq->u8ScsiSts; 2913 RTGCPHYS GCPhysAddrCCB = pReq->GCPhysAddrCCB; 2914 CCBU CCBGuest; 2915 memcpy(&CCBGuest, &pReq->CCBGuest, sizeof(CCBU)); 2916 2917 pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq); 2918 if (u8ScsiSts == SCSI_STATUS_OK) 2919 buslogicR3SendIncomingMailbox(pDevIns, pThis, GCPhysAddrCCB, &CCBGuest, 2920 BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED, 2921 BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD, 2922 BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITHOUT_ERROR); 2923 else if (u8ScsiSts == SCSI_STATUS_CHECK_CONDITION) 2924 buslogicR3SendIncomingMailbox(pDevIns, pThis, GCPhysAddrCCB, &CCBGuest, 2925 BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED, 2926 BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_CHECK_CONDITION, 2927 BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR); 2928 else 2929 AssertMsgFailed(("invalid completion status %u\n", u8ScsiSts)); 2930 2931 #ifdef LOG_ENABLED 2932 buslogicR3DumpCCBInfo(&CCBGuest, fIs24Bit); 2933 #endif 2984 } 2934 2985 2935 2986 if (pTgtDev->cOutstandingRequests == 0 && pThisCC->fSignalIdle) … … 2957 3008 2958 3009 return VINF_SUCCESS; 3010 } 3011 3012 static DECLCALLBACK(size_t) buslogicR3CopySgToGuestBios(PCRTSGBUF pSgBuf, const void *pvSrc, size_t cbSrc, void *pvUser) 3013 { 3014 PBUSLOGICCOPYARGS pArgs = (PBUSLOGICCOPYARGS)pvUser; 3015 size_t cbThisCopy = RT_MIN(cbSrc, pArgs->pCmd->cbData - pArgs->cbCopied); 3016 RT_NOREF(pSgBuf); 3017 3018 blPhysWriteUser(pArgs->pDevIns, pArgs->pThis, pArgs->pCmd->u32PhysAddrData + pArgs->cbCopied, pvSrc, cbThisCopy); 3019 pArgs->cbCopied += cbThisCopy; 3020 return cbThisCopy; 2959 3021 } 2960 3022 … … 2971 3033 RT_NOREF(hIoReq); 2972 3034 2973 size_t cbCopied = buslogicR3CopySgBufToGuest(pDevIns, PDMDEVINS_2_DATA(pDevIns, PBUSLOGIC), pReq, pSgBuf, offDst, cbCopy); 3035 size_t cbCopied = 0; 3036 if (RT_LIKELY(!pReq->fBIOS)) 3037 cbCopied = buslogicR3CopySgBufToGuest(pDevIns, PDMDEVINS_2_DATA(pDevIns, PBUSLOGIC), pReq, pSgBuf, offDst, cbCopy); 3038 else 3039 { 3040 BUSLOGICCOPYARGS Args; 3041 PBUSLOGIC pThis = PDMDEVINS_2_DATA(pDevIns, PBUSLOGIC); 3042 PESCMD pCmd = (PESCMD)pThis->aCommandBuffer; 3043 3044 Args.pCmd = pCmd; 3045 Args.pThis = pThis; 3046 Args.pDevIns = pDevIns; 3047 Args.cbCopied = 0; 3048 cbCopied = RTSgBufCopyToFn(pSgBuf, RT_MIN(pCmd->cbData, cbCopy), buslogicR3CopySgToGuestBios, &Args); 3049 } 2974 3050 return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_OVERFLOW; 3051 } 3052 3053 static DECLCALLBACK(size_t) buslogicR3CopySgFromGuestBios(PCRTSGBUF pSgBuf, void *pvDst, size_t cbDst, void *pvUser) 3054 { 3055 PBUSLOGICCOPYARGS pArgs = (PBUSLOGICCOPYARGS)pvUser; 3056 size_t cbThisCopy = RT_MIN(cbDst, pArgs->pCmd->cbData - pArgs->cbCopied); 3057 RT_NOREF(pSgBuf); 3058 3059 blPhysReadUser(pArgs->pDevIns, pArgs->pThis, pArgs->pCmd->u32PhysAddrData + pArgs->cbCopied, pvDst, cbThisCopy); 3060 pArgs->cbCopied += cbThisCopy; 3061 return cbThisCopy; 2975 3062 } 2976 3063 … … 2987 3074 PBUSLOGICREQ pReq = (PBUSLOGICREQ)pvIoReqAlloc; 2988 3075 2989 size_t cbCopied = buslogicR3CopySgBufFromGuest(pDevIns, PDMDEVINS_2_DATA(pDevIns, PBUSLOGIC), pReq, pSgBuf, offSrc, cbCopy); 3076 size_t cbCopied = 0; 3077 if (RT_LIKELY(!pReq->fBIOS)) 3078 cbCopied = buslogicR3CopySgBufFromGuest(pDevIns, PDMDEVINS_2_DATA(pDevIns, PBUSLOGIC), pReq, pSgBuf, offSrc, cbCopy); 3079 else 3080 { 3081 BUSLOGICCOPYARGS Args; 3082 PBUSLOGIC pThis = PDMDEVINS_2_DATA(pDevIns, PBUSLOGIC); 3083 PESCMD pCmd = (PESCMD)pThis->aCommandBuffer; 3084 3085 Args.pCmd = pCmd; 3086 Args.pThis = pThis; 3087 Args.pDevIns = pDevIns; 3088 Args.cbCopied = 0; 3089 cbCopied = RTSgBufCopyFromFn(pSgBuf, RT_MIN(pCmd->cbData, cbCopy), buslogicR3CopySgFromGuestBios, &Args); 3090 } 3091 2990 3092 return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_UNDERRUN; 2991 3093 } … … 3269 3371 return rc; 3270 3372 } 3373 3374 /** 3375 * Processes a SCSI request issued by the BIOS with the BUSLOGICCOMMAND_EXECUTE_SCSI_COMMAND command. 3376 * 3377 * @returns nothing. 3378 * @param pDevIns The device instance. 3379 * @param pThis Pointer to the shared BusLogic instance data. 3380 * @param pThisCC Pointer to the ring-3 BusLogic instance data. 3381 */ 3382 static void buslogicR3ProcessBiosReq(PPDMDEVINS pDevIns, PBUSLOGIC pThis, PBUSLOGICCC pThisCC) 3383 { 3384 PESCMD pCmd = (PESCMD)pThis->aCommandBuffer; 3385 3386 if (RT_LIKELY( pCmd->uTargetId < RT_ELEMENTS(pThisCC->aDeviceStates) 3387 && pCmd->cbCDB <= 16)) 3388 { 3389 PBUSLOGICDEVICE pTgtDev = &pThisCC->aDeviceStates[pCmd->uTargetId]; 3390 3391 /* Check if device is present on bus. If not return error immediately and don't process this further. */ 3392 if (RT_LIKELY(pTgtDev->fPresent)) 3393 { 3394 PDMMEDIAEXIOREQ hIoReq; 3395 PBUSLOGICREQ pReq; 3396 int rc = pTgtDev->pDrvMediaEx->pfnIoReqAlloc(pTgtDev->pDrvMediaEx, &hIoReq, (void **)&pReq, 3397 0, PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR); 3398 if (RT_SUCCESS(rc)) 3399 { 3400 pReq->pTargetDevice = pTgtDev; 3401 pReq->GCPhysAddrCCB = 0; 3402 pReq->fBIOS = true; 3403 pReq->hIoReq = hIoReq; 3404 pReq->fIs24Bit = false; 3405 3406 uint32_t uLun = pCmd->uLogicalUnit; 3407 3408 PDMMEDIAEXIOREQSCSITXDIR enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN; 3409 3410 if (pCmd->uDataDirection == 2) 3411 enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE; 3412 else if (pCmd->uDataDirection == 1) 3413 enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE; 3414 3415 ASMAtomicIncU32(&pTgtDev->cOutstandingRequests); 3416 rc = pTgtDev->pDrvMediaEx->pfnIoReqSendScsiCmd(pTgtDev->pDrvMediaEx, pReq->hIoReq, uLun, 3417 &pCmd->abCDB[0], pCmd->cbCDB, 3418 enmXferDir, NULL, pCmd->cbData, NULL, 0 /*cbSense*/, NULL, 3419 &pReq->u8ScsiSts, 30 * RT_MS_1SEC); 3420 if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS) 3421 buslogicR3ReqComplete(pDevIns, pThis, pThisCC, pReq, rc); 3422 } 3423 else 3424 buslogicR3ReqCompleteBios(pThis, SCSI_STATUS_CHECK_CONDITION); 3425 } 3426 else 3427 buslogicR3ReqCompleteBios(pThis, SCSI_STATUS_CHECK_CONDITION); 3428 } 3429 else 3430 buslogicR3ReqCompleteBios(pThis, SCSI_STATUS_CHECK_CONDITION); 3431 } 3432 3271 3433 3272 3434 /** @callback_method_impl{FNSSMDEVLIVEEXEC} */ … … 3602 3764 ASMAtomicWriteBool(&pThisCC->fWrkThreadSleeping, false); 3603 3765 3604 3605 ASMAtomicXchgU32(&pThis->cMailboxesReady, 0); /** @todo Actually not required anymore but to stay compatible with older saved states. */ 3606 3607 /* Process mailboxes. */ 3608 do 3609 { 3610 rc = buslogicR3ProcessMailboxNext(pDevIns, pThis, pThisCC); 3611 AssertMsg(RT_SUCCESS(rc) || rc == VERR_NO_DATA, ("Processing mailbox failed rc=%Rrc\n", rc)); 3612 } while (RT_SUCCESS(rc)); 3766 if (ASMAtomicXchgBool(&pThis->fBiosReqPending, false)) 3767 buslogicR3ProcessBiosReq(pDevIns, pThis, pThisCC); 3768 3769 if (ASMAtomicXchgU32(&pThis->cMailboxesReady, 0)) 3770 { 3771 /* Process mailboxes. */ 3772 do 3773 { 3774 rc = buslogicR3ProcessMailboxNext(pDevIns, pThis, pThisCC); 3775 AssertMsg(RT_SUCCESS(rc) || rc == VERR_NO_DATA, ("Processing mailbox failed rc=%Rrc\n", rc)); 3776 } while (RT_SUCCESS(rc)); 3777 } 3613 3778 } /* While running */ 3614 3779
Note:
See TracChangeset
for help on using the changeset viewer.