Changeset 78073 in vbox for trunk/src/VBox/Devices/USB
- Timestamp:
- Apr 10, 2019 10:09:05 AM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 129929
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/USB/DevOHCI.cpp
r76553 r78073 906 906 */ 907 907 # define ohciR3SetInterrupt(ohci, intr) ohciR3SetInterruptInt(ohci, VERR_IGNORED, intr, #intr) 908 909 910 /** 911 * Sets the HC in the unrecoverable error state and raises the appropriate interrupt. 912 * 913 * @returns nothing. 914 * @param pThis The OHCI instance. 915 */ 916 DECLINLINE(void) ohciR3RaiseUnrecoverableError(POHCI pThis) 917 { 918 ohciR3SetInterrupt(pThis, OHCI_INTR_UNRECOVERABLE_ERROR); 919 } 908 920 909 921 … … 2081 2093 * Sets up a OHCI transport buffer. 2082 2094 * 2095 * @returns Flags whether the buffer could be initialised successfully. 2083 2096 * @param pBuf Ohci buffer. 2084 2097 * @param cbp Current buffer pointer. 32-bit physical address. 2085 2098 * @param be Last byte in buffer (BufferEnd). 32-bit physical address. 2086 2099 */ 2087 static void ohciR3BufInit(POHCIBUF pBuf, uint32_t cbp, uint32_t be) 2088 { 2100 static bool ohciR3BufInit(POHCIBUF pBuf, uint32_t cbp, uint32_t be) 2101 { 2102 if (RT_UNLIKELY(be < cbp)) 2103 return false; 2104 2089 2105 if (!cbp || !be) 2090 2106 { … … 2111 2127 Log2(("ohci: cbp=%#010x be=%#010x cbTotal=%u PAGE FLIP\n", cbp, be, pBuf->cbTotal)); 2112 2128 } 2129 2130 return true; 2113 2131 } 2114 2132 … … 2660 2678 */ 2661 2679 OHCIBUF Buf; 2662 ohciR3BufInit(&Buf, pTd->cbp, pTd->be); 2680 if (!ohciR3BufInit(&Buf, pTd->cbp, pTd->be)) 2681 { 2682 ohciR3RaiseUnrecoverableError(pThis); 2683 return; 2684 } 2663 2685 uint32_t NewCbp; 2664 2686 if (cbLeft >= Buf.cbTotal) … … 2683 2705 { 2684 2706 Assert(Buf.cVecs > 0); 2707 2708 /* Be paranoid */ 2709 if ( Buf.aVecs[0].cb > cbLeft 2710 || ( Buf.cVecs > 1 2711 && Buf.aVecs[1].cb > (cbLeft - Buf.aVecs[0].cb))) 2712 { 2713 ohciR3RaiseUnrecoverableError(pThis); 2714 return; 2715 } 2716 2685 2717 ohciR3PhysWrite(pThis, Buf.aVecs[0].Addr, pb, Buf.aVecs[0].cb); 2686 2718 if (Buf.cVecs > 1) … … 2790 2822 2791 2823 ohciR3Lock(pThis); 2792 pThis->fIdle = false; /* Mark as active */ 2793 2794 /* get the current end point descriptor. */ 2795 OHCIED Ed; 2796 ohciR3ReadEd(pThis, pUrb->pHci->EdAddr, &Ed); 2797 2798 /* 2799 * Check that the URB hasn't been canceled and then try unlink the TDs. 2800 * 2801 * We drop the URB if the ED is marked halted/skip ASSUMING that this 2802 * means the HCD has canceled the URB. 2803 * 2804 * If we succeed here (i.e. not dropping the URB), the TdCopy members will 2805 * be updated but not yet written. We will delay the writing till we're done 2806 * with the data copying, buffer pointer advancing and error handling. 2807 */ 2808 int cFmAge = ohciR3InFlightRemoveUrb(pThis, pUrb); 2809 if (pUrb->enmStatus == VUSBSTATUS_UNDO) 2810 { 2811 /* Leave the TD alone - the HCD doesn't want us talking to the device. */ 2812 Log(("%s: ohciR3RhXferCompletion: CANCELED {ED=%#010x cTds=%d TD0=%#010x age %d}\n", 2813 pUrb->pszDesc, pUrb->pHci->EdAddr, pUrb->pHci->cTds, pUrb->paTds[0].TdAddr, cFmAge)); 2814 STAM_COUNTER_INC(&pThis->StatDroppedUrbs); 2815 ohciR3Unlock(pThis); 2816 return; 2817 } 2818 bool fHasBeenCanceled = false; 2819 if ( (Ed.HeadP & ED_HEAD_HALTED) 2820 || (Ed.hwinfo & ED_HWINFO_SKIP) 2821 || cFmAge < 0 2822 || (fHasBeenCanceled = ohciR3HasUrbBeenCanceled(pThis, pUrb, &Ed)) 2823 || !ohciR3UnlinkTds(pThis, pUrb, &Ed) 2824 ) 2825 { 2826 Log(("%s: ohciR3RhXferCompletion: DROPPED {ED=%#010x cTds=%d TD0=%#010x age %d} because:%s%s%s%s%s!!!\n", 2827 pUrb->pszDesc, pUrb->pHci->EdAddr, pUrb->pHci->cTds, pUrb->paTds[0].TdAddr, cFmAge, 2828 (Ed.HeadP & ED_HEAD_HALTED) ? " ep halted" : "", 2829 (Ed.hwinfo & ED_HWINFO_SKIP) ? " ep skip" : "", 2830 (Ed.HeadP & ED_PTR_MASK) != pUrb->paTds[0].TdAddr ? " ep head-changed" : "", 2831 cFmAge < 0 ? " td not-in-flight" : "", 2832 fHasBeenCanceled ? " td canceled" : "")); 2833 NOREF(fHasBeenCanceled); 2834 STAM_COUNTER_INC(&pThis->StatDroppedUrbs); 2835 ohciR3Unlock(pThis); 2836 return; 2837 } 2838 2839 /* 2840 * Complete the TD updating and write the back. 2841 * When appropriate also copy data back to the guest memory. 2842 */ 2843 if (pUrb->enmType == VUSBXFERTYPE_ISOC) 2844 ohciR3RhXferCompleteIsochronousURB(pThis, pUrb /*, &Ed , cFmAge*/); 2845 else 2846 ohciR3RhXferCompleteGeneralURB(pThis, pUrb, &Ed, cFmAge); 2847 2848 /* finally write back the endpoint descriptor. */ 2849 ohciR3WriteEd(pThis, pUrb->pHci->EdAddr, &Ed); 2824 2825 /* Do nothing if the HC encountered an unrecoverable error. */ 2826 if (!(pThis->intr_status & OHCI_INTR_UNRECOVERABLE_ERROR)) 2827 { 2828 pThis->fIdle = false; /* Mark as active */ 2829 2830 /* get the current end point descriptor. */ 2831 OHCIED Ed; 2832 ohciR3ReadEd(pThis, pUrb->pHci->EdAddr, &Ed); 2833 2834 /* 2835 * Check that the URB hasn't been canceled and then try unlink the TDs. 2836 * 2837 * We drop the URB if the ED is marked halted/skip ASSUMING that this 2838 * means the HCD has canceled the URB. 2839 * 2840 * If we succeed here (i.e. not dropping the URB), the TdCopy members will 2841 * be updated but not yet written. We will delay the writing till we're done 2842 * with the data copying, buffer pointer advancing and error handling. 2843 */ 2844 int cFmAge = ohciR3InFlightRemoveUrb(pThis, pUrb); 2845 if (pUrb->enmStatus == VUSBSTATUS_UNDO) 2846 { 2847 /* Leave the TD alone - the HCD doesn't want us talking to the device. */ 2848 Log(("%s: ohciR3RhXferCompletion: CANCELED {ED=%#010x cTds=%d TD0=%#010x age %d}\n", 2849 pUrb->pszDesc, pUrb->pHci->EdAddr, pUrb->pHci->cTds, pUrb->paTds[0].TdAddr, cFmAge)); 2850 STAM_COUNTER_INC(&pThis->StatDroppedUrbs); 2851 ohciR3Unlock(pThis); 2852 return; 2853 } 2854 bool fHasBeenCanceled = false; 2855 if ( (Ed.HeadP & ED_HEAD_HALTED) 2856 || (Ed.hwinfo & ED_HWINFO_SKIP) 2857 || cFmAge < 0 2858 || (fHasBeenCanceled = ohciR3HasUrbBeenCanceled(pThis, pUrb, &Ed)) 2859 || !ohciR3UnlinkTds(pThis, pUrb, &Ed) 2860 ) 2861 { 2862 Log(("%s: ohciR3RhXferCompletion: DROPPED {ED=%#010x cTds=%d TD0=%#010x age %d} because:%s%s%s%s%s!!!\n", 2863 pUrb->pszDesc, pUrb->pHci->EdAddr, pUrb->pHci->cTds, pUrb->paTds[0].TdAddr, cFmAge, 2864 (Ed.HeadP & ED_HEAD_HALTED) ? " ep halted" : "", 2865 (Ed.hwinfo & ED_HWINFO_SKIP) ? " ep skip" : "", 2866 (Ed.HeadP & ED_PTR_MASK) != pUrb->paTds[0].TdAddr ? " ep head-changed" : "", 2867 cFmAge < 0 ? " td not-in-flight" : "", 2868 fHasBeenCanceled ? " td canceled" : "")); 2869 NOREF(fHasBeenCanceled); 2870 STAM_COUNTER_INC(&pThis->StatDroppedUrbs); 2871 ohciR3Unlock(pThis); 2872 return; 2873 } 2874 2875 /* 2876 * Complete the TD updating and write the back. 2877 * When appropriate also copy data back to the guest memory. 2878 */ 2879 if (pUrb->enmType == VUSBXFERTYPE_ISOC) 2880 ohciR3RhXferCompleteIsochronousURB(pThis, pUrb /*, &Ed , cFmAge*/); 2881 else 2882 ohciR3RhXferCompleteGeneralURB(pThis, pUrb, &Ed, cFmAge); 2883 2884 /* finally write back the endpoint descriptor. */ 2885 ohciR3WriteEd(pThis, pUrb->pHci->EdAddr, &Ed); 2886 } 2887 2850 2888 ohciR3Unlock(pThis); 2851 2889 } … … 2935 2973 ohciR3ReadTd(pThis, TdAddr, &Td); 2936 2974 OHCIBUF Buf; 2937 ohciR3BufInit(&Buf, Td.cbp, Td.be); 2975 if (!ohciR3BufInit(&Buf, Td.cbp, Td.be)) 2976 { 2977 ohciR3RaiseUnrecoverableError(pThis); 2978 return false; 2979 } 2938 2980 2939 2981 *pNextTdAddr = Td.NextTD & ED_PTR_MASK; … … 2955 2997 default: 2956 2998 Log(("ohciR3ServiceTd: Invalid direction!!!! Td.hwinfo=%#x Ed.hwdinfo=%#x\n", Td.hwinfo, pEd->hwinfo)); 2957 /** @todo Do the correct thing here */2999 ohciR3RaiseUnrecoverableError(pThis); 2958 3000 return false; 2959 3001 } … … 2988 3030 && enmDir != VUSBDIRECTION_IN) 2989 3031 { 3032 /* Be paranoid. */ 3033 if ( Buf.aVecs[0].cb > pUrb->cbData 3034 || ( Buf.cVecs > 1 3035 && Buf.aVecs[1].cb > (pUrb->cbData - Buf.aVecs[0].cb))) 3036 { 3037 ohciR3RaiseUnrecoverableError(pThis); 3038 VUSBIRhFreeUrb(pThis->RootHub.pIRhConn, pUrb); 3039 return false; 3040 } 3041 2990 3042 ohciR3PhysRead(pThis, Buf.aVecs[0].Addr, pUrb->abData, Buf.aVecs[0].cb); 2991 3043 if (Buf.cVecs > 1) … … 3009 3061 Log(("ohciR3ServiceTd: failed submitting TdAddr=%#010x EdAddr=%#010x pUrb=%p!!\n", 3010 3062 TdAddr, EdAddr, pUrb)); 3063 VUSBIRhFreeUrb(pThis->RootHub.pIRhConn, pUrb); 3011 3064 ohciR3InFlightRemove(pThis, TdAddr); 3012 3065 return false; … … 3061 3114 /* read the head */ 3062 3115 ohciR3ReadTd(pThis, TdAddr, &Head.Td); 3063 ohciR3BufInit(&Head.Buf, Head.Td.cbp, Head.Td.be); 3116 if (!ohciR3BufInit(&Head.Buf, Head.Td.cbp, Head.Td.be)) 3117 { 3118 ohciR3RaiseUnrecoverableError(pThis); 3119 return false; 3120 } 3064 3121 Head.TdAddr = TdAddr; 3065 3122 Head.pNext = NULL; … … 3079 3136 pCur->TdAddr = pTail->Td.NextTD & ED_PTR_MASK; 3080 3137 ohciR3ReadTd(pThis, pCur->TdAddr, &pCur->Td); 3081 ohciR3BufInit(&pCur->Buf, pCur->Td.cbp, pCur->Td.be); 3138 if (!ohciR3BufInit(&pCur->Buf, pCur->Td.cbp, pCur->Td.be)) 3139 { 3140 ohciR3RaiseUnrecoverableError(pThis); 3141 return false; 3142 } 3082 3143 3083 3144 /* Don't combine if the direction doesn't match up. There can't actually be … … 3113 3174 default: 3114 3175 Log(("ohciR3ServiceTdMultiple: Invalid direction!!!! Head.Td.hwinfo=%#x Ed.hwdinfo=%#x\n", Head.Td.hwinfo, pEd->hwinfo)); 3115 /** @todo Do the correct thing here */3176 ohciR3RaiseUnrecoverableError(pThis); 3116 3177 return false; 3117 3178 } … … 3180 3241 for (struct OHCITDENTRY *pCur = &Head; pCur; pCur = pCur->pNext, iTd++) 3181 3242 ohciR3InFlightRemove(pThis, pCur->TdAddr); 3243 VUSBIRhFreeUrb(pThis->RootHub.pIRhConn, pUrb); 3182 3244 return false; 3183 3245 } … … 3291 3353 default: 3292 3354 Log(("ohciR3ServiceIsochronousTd: Invalid direction!!!! Ed.hwdinfo=%#x\n", pEd->hwinfo)); 3293 /* Should probably raise an unrecoverable HC error here */3355 ohciR3RaiseUnrecoverableError(pThis); 3294 3356 return false; 3295 3357 } … … 3307 3369 uint32_t cbTotal = 0; 3308 3370 if (((uint32_t)pITd->aPSW[R] >> ITD_PSW_CC_SHIFT) < (OHCI_CC_NOT_ACCESSED_0 >> TD_HWINFO_CC_SHIFT)) 3371 { 3309 3372 Log(("ITdAddr=%RX32 PSW%d.CC=%#x < 'Not Accessed'!\n", ITdAddr, R, pITd->aPSW[R] >> ITD_PSW_CC_SHIFT)); /* => Unrecoverable Error*/ 3373 pThis->intr_status |= OHCI_INTR_UNRECOVERABLE_ERROR; 3374 return false; 3375 } 3310 3376 uint16_t offPrev = aPkts[0].off = (pITd->aPSW[R] & ITD_PSW_OFFSET); 3311 3377 … … 3318 3384 cbTotal += aPkts[iR - R - 1].cb = off - offPrev; 3319 3385 if (off < offPrev) 3386 { 3320 3387 Log(("ITdAddr=%RX32 PSW%d.offset=%#x < offPrev=%#x!\n", ITdAddr, iR, off, offPrev)); /* => Unrecoverable Error*/ 3388 ohciR3RaiseUnrecoverableError(pThis); 3389 return false; 3390 } 3321 3391 if (((uint32_t)PSW >> ITD_PSW_CC_SHIFT) < (OHCI_CC_NOT_ACCESSED_0 >> TD_HWINFO_CC_SHIFT)) 3392 { 3322 3393 Log(("ITdAddr=%RX32 PSW%d.CC=%#x < 'Not Accessed'!\n", ITdAddr, iR, PSW >> ITD_PSW_CC_SHIFT)); /* => Unrecoverable Error*/ 3394 ohciR3RaiseUnrecoverableError(pThis); 3395 return false; 3396 } 3323 3397 offPrev = off; 3324 3398 } … … 3329 3403 + 1 /* BE is inclusive */; 3330 3404 if (offEnd < offPrev) 3405 { 3331 3406 Log(("ITdAddr=%RX32 offEnd=%#x < offPrev=%#x!\n", ITdAddr, offEnd, offPrev)); /* => Unrecoverable Error*/ 3407 ohciR3RaiseUnrecoverableError(pThis); 3408 return false; 3409 } 3332 3410 cbTotal += aPkts[cFrames - 1 - R].cb = offEnd - offPrev; 3333 3411 Assert(cbTotal <= 0x2000); … … 3406 3484 pUrb, cbTotal, EdAddr, 1, ITdAddr, rc)); 3407 3485 ohciR3InFlightRemove(pThis, ITdAddr); 3486 VUSBIRhFreeUrb(pThis->RootHub.pIRhConn, pUrb); 3408 3487 return false; 3409 3488 } … … 4145 4224 # endif 4146 4225 4147 /* Frame boundary, so do EOF stuff here. */ 4148 ohciR3BumpFrameNumber(pThis); 4149 if ( (pThis->dqic != 0x7) && (pThis->dqic != 0)) 4150 pThis->dqic--; 4151 4152 /* Clean up any URBs that have been removed. */ 4153 ohciR3CancelOrphanedURBs(pThis); 4154 4155 /* Start the next frame. */ 4156 ohciR3StartOfFrame(pThis); 4226 if (!(pThis->intr_status & OHCI_INTR_UNRECOVERABLE_ERROR)) 4227 { 4228 /* Frame boundary, so do EOF stuff here. */ 4229 ohciR3BumpFrameNumber(pThis); 4230 if ( (pThis->dqic != 0x7) && (pThis->dqic != 0)) 4231 pThis->dqic--; 4232 4233 /* Clean up any URBs that have been removed. */ 4234 ohciR3CancelOrphanedURBs(pThis); 4235 4236 /* Start the next frame. */ 4237 ohciR3StartOfFrame(pThis); 4238 } 4157 4239 4158 4240 # ifdef VBOX_WITH_OHCI_PHYS_READ_STATS
Note:
See TracChangeset
for help on using the changeset viewer.