VirtualBox

Changeset 83141 in vbox


Ignore:
Timestamp:
Feb 24, 2020 5:50:34 PM (5 years ago)
Author:
vboxsync
Message:

DevBusLogic: Improved interrupt reporting logic to match real hardware. Fixed a problem with FETCH HOST ADAPTER LOCAL RAM not resetting the DIRRDY bit (broke Linux driver). See bugref:5112.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevBusLogic.cpp

    r83132 r83141  
    10341034
    10351035/**
    1036  * Assert IRQ line of the BusLogic adapter.
     1036 * Assert IRQ line of the BusLogic adapter. Rather than using
     1037 * the more modern method of the guest explicitly only clearing
     1038 * the interrupt causes it handled, BusLogic never reports all
     1039 * interrupts at once. Instead, new interrupts are postponed if
     1040 * an interrupt of a different type is still pending.
    10371041 *
    10381042 * @returns nothing.
     
    10441048static void buslogicSetInterrupt(PPDMDEVINS pDevIns, PBUSLOGIC pThis, bool fSuppressIrq, uint8_t uIrqType)
    10451049{
    1046     LogFlowFunc(("pThis=%#p\n", pThis));
    1047 
    1048     /* The CMDC interrupt has priority over IMBL and OMBR. */
    1049     if (uIrqType & (BL_INTR_IMBL | BL_INTR_OMBR))
    1050     {
     1050    LogFlowFunc(("pThis=%#p, setting %#02x (current %#02x, pending %#02x)\n",
     1051                 pThis, uIrqType, pThis->regInterrupt, pThis->uPendingIntr));
     1052
     1053    /* A CMDC interrupt overrides other pending interrupts. The documentation may claim
     1054     * otherwise, but a real BT-958 replaces a pending IMBL with a CMDC; the IMBL simply
     1055     * vanishes. However, if there's a CMDC already active, another CMDC is latched and
     1056     * reported once the first CMDC is cleared.
     1057     */
     1058    if (uIrqType & BL_INTR_CMDC)
     1059    {
     1060        Assert(uIrqType == BL_INTR_CMDC);
     1061        if ((pThis->regInterrupt & BL_INTR_INTV) && !(pThis->regInterrupt & BL_INTR_CMDC))
     1062            Log(("CMDC overriding pending interrupt! (was %02x)\n", pThis->regInterrupt));
    10511063        if (!(pThis->regInterrupt & BL_INTR_CMDC))
    1052             pThis->regInterrupt |= uIrqType;    /* Report now. */
     1064            pThis->regInterrupt |= uIrqType | BL_INTR_INTV; /* Report now. */
    10531065        else
    1054             pThis->uPendingIntr |= uIrqType;    /* Report later. */
    1055     }
    1056     else if (uIrqType & BL_INTR_CMDC)
    1057     {
    1058         AssertMsg(pThis->regInterrupt == 0 || pThis->regInterrupt == (BL_INTR_INTV | BL_INTR_CMDC),
    1059                   ("regInterrupt=%02X\n", pThis->regInterrupt));
    1060         pThis->regInterrupt |= uIrqType;
    1061     }
    1062     else
    1063         AssertMsgFailed(("Invalid interrupt state!\n"));
    1064 
    1065     pThis->regInterrupt |= BL_INTR_INTV;
     1066            pThis->uPendingIntr |= uIrqType;                /* Report later. */
     1067    }
     1068    else if (uIrqType & (BL_INTR_IMBL | BL_INTR_OMBR))
     1069    {
     1070        /* If the CMDC interrupt is pending, store IMBL/OMBR for later. Note that IMBL
     1071         * and OMBR can be reported together even if an interrupt of the other type is
     1072         * already pending.
     1073         */
     1074        if (!(pThis->regInterrupt & BL_INTR_CMDC))
     1075            pThis->regInterrupt |= uIrqType | BL_INTR_INTV; /* Report now. */
     1076        else
     1077            pThis->uPendingIntr |= uIrqType;                /* Report later. */
     1078    }
     1079    else    /* We do not expect to see BL_INTR_RSTS at this point. */
     1080        AssertMsgFailed(("Invalid interrupt state (unknown interrupt cause)!\n"));
     1081    AssertMsg(pThis->regInterrupt, ("Invalid interrupt state (interrupt not set)!\n"));
     1082    AssertMsg(pThis->regInterrupt != BL_INTR_INTV, ("Invalid interrupt state (set but no cause)!\n"));
     1083
    10661084    if (pThis->fIRQEnabled && !fSuppressIrq)
    10671085    {
     
    11851203/**
    11861204 * Resets the command state machine for the next command and notifies the guest.
     1205 * Note that suppressing CMDC also suppresses the interrupt, but not vice versa.
    11871206 *
    11881207 * @returns nothing.
     
    11991218    pThis->fUseLocalRam = false;
    12001219    pThis->regStatus |= BL_STAT_HARDY;
     1220    pThis->regStatus &= ~BL_STAT_DIRRDY;
    12011221    pThis->iReply = 0;
    12021222
    1203     /* The Enable OMBR command does not set CMDC when successful. */
     1223    /* Some commands do not set CMDC when successful. */
    12041224    if (!fSuppressCMDC)
    12051225    {
    12061226        /* Notify that the command is complete. */
    1207         pThis->regStatus &= ~BL_STAT_DIRRDY;
    12081227        buslogicSetInterrupt(pDevIns, pThis, fSuppressIrq, BL_INTR_CMDC);
    12091228    }
     
    22402259            else
    22412260                pThis->fIRQEnabled = true;
    2242             /* No interrupt signaled regardless of enable/disable. */
     2261            /* No interrupt signaled regardless of enable/disable. NB: CMDC is still signaled! */
    22432262            fSuppressIrq = true;
    22442263            break;
     
    23482367        pThis->regStatus |= BL_STAT_DIRRDY;
    23492368    else if (!pThis->cbCommandParametersLeft)
    2350         buslogicCommandComplete(pDevIns, pThis, fSuppressIrq, fSuppressCMDC );
     2369        buslogicCommandComplete(pDevIns, pThis, fSuppressIrq, fSuppressCMDC);
    23512370
    23522371    return rc;
     
    24182437                     */
    24192438                    if (pThis->uOperationCode == BUSLOGICCOMMAND_FETCH_HOST_ADAPTER_LOCAL_RAM)
    2420                         buslogicCommandComplete(pDevIns, pThis, true /* fSuppressIrq */, true /* fSuppressCMDC */ );
     2439                        buslogicCommandComplete(pDevIns, pThis, true /* fSuppressIrq */, true /* fSuppressCMDC */);
    24212440                    else
    24222441                        buslogicCommandComplete(pDevIns, pThis, false, false);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette