Beispiel #1
0
/******************************************************************************
 *
 * Function   :  PlxChipInterruptsDisable
 *
 * Description:  Globally disables PLX chip interrupts
 *
 *****************************************************************************/
BOOLEAN
PlxChipInterruptsDisable(
    DEVICE_EXTENSION *pdx
    )
{
    PLX_REG_DATA RegData;


    // Setup for synchronized register access
    RegData.pdx         = pdx;
    RegData.offset      = PCI9054_INT_CTRL_STAT;
    RegData.BitsToSet   = 0;
    RegData.BitsToClear = (1 << 8);

    PlxSynchronizedRegisterModify(
        &RegData
        );

    return TRUE;
}
/******************************************************************************
 *
 * Function   :  PlxPciIntrDisable
 *
 * Description:  Disables specific interrupts of the PLX Chip
 *
 ******************************************************************************/
RETURN_CODE
PlxPciIntrDisable(
    DEVICE_EXTENSION *pdx,
    PLX_INTR         *pPlxIntr
    )
{
    U32          QueueCsr;
    U32          QueueCsr_Original;
    U32          RegisterValue;
    PLX_REG_DATA RegData;


    // Setup to synchronize access to Interrupt Control/Status Register
    RegData.pdx         = pdx;
    RegData.offset      = PCI9080_INT_CTRL_STAT;
    RegData.BitsToSet   = 0;
    RegData.BitsToClear = 0;

    // Inbound Post Queue Interrupt Control/Status Register
    QueueCsr_Original =
        PLX_REG_READ(
            pdx,
            PCI9080_FIFO_CTRL_STAT
            );

    QueueCsr = QueueCsr_Original;


    if (pPlxIntr->OutboundPost)
    {
        PLX_REG_WRITE(
            pdx,
            PCI9080_OUTPOST_INT_MASK,
            (1 << 3)
            );
    }

    if (pPlxIntr->InboundPost)
        QueueCsr |= (1 << 4);

    if (pPlxIntr->OutboundOverflow)
        QueueCsr |= (1 << 6);

    if (pPlxIntr->PciDmaChannel0)
    {
        // Check if DMA interrupt is routed to PCI
        RegisterValue =
            PLX_REG_READ(
                pdx,
                PCI9080_DMA0_MODE
                );

        if (RegisterValue & (1 << 17))
        {
            RegData.BitsToClear |= (1 << 18);

            // Make sure DMA interrupt is routed to IOP
            PLX_REG_WRITE(
                pdx,
                PCI9080_DMA0_MODE,
                RegisterValue & ~(1 << 17)
                );
        }
    }

    if (pPlxIntr->PciDmaChannel1)
    {
        // Check if DMA interrupt is routed to PCI
        RegisterValue =
            PLX_REG_READ(
                pdx,
                PCI9080_DMA1_MODE
                );

        if (RegisterValue & (1 << 17))
        {
            RegData.BitsToClear |= (1 << 19);

            // Make sure DMA interrupt is routed to IOP
            PLX_REG_WRITE(
                pdx,
                PCI9080_DMA1_MODE,
                RegisterValue & ~(1 << 17)
                );
        }
    }

    if (pPlxIntr->IopDmaChannel0)
        RegData.BitsToClear |= (1 << 18);

    if (pPlxIntr->IopDmaChannel1)
        RegData.BitsToClear |= (1 << 19);

    if (pPlxIntr->Mailbox0 || pPlxIntr->Mailbox1 ||
        pPlxIntr->Mailbox2 || pPlxIntr->Mailbox3)
    {
        RegData.BitsToClear |= (1 << 3);
    }

    if (pPlxIntr->PciDoorbell)
        RegData.BitsToClear |= (1 << 9);

    if (pPlxIntr->IopDoorbell)
        RegData.BitsToClear |= (1 << 17);

    if (pPlxIntr->PciMainInt)
        RegData.BitsToClear |= (1 << 8);

    if (pPlxIntr->IopToPciInt)
        RegData.BitsToClear |= (1 << 11);

    if (pPlxIntr->IopMainInt)
        RegData.BitsToClear |= (1 << 16);

    if (pPlxIntr->PciAbort)
        RegData.BitsToClear |= (1 << 10);

    if (pPlxIntr->AbortLSERR)
        RegData.BitsToClear |= (1 << 0);

    if (pPlxIntr->ParityLSERR)
        RegData.BitsToClear |= (1 << 1);

    if (pPlxIntr->RetryAbort)
        RegData.BitsToClear |= (1 << 12);


    // Write register values if they have changed

    if (RegData.BitsToClear != 0)
    {
        // Synchronize write of Interrupt Control/Status Register
        PlxSynchronizedRegisterModify(
            &RegData
            );
    }

    if (QueueCsr != QueueCsr_Original)
    {
        PLX_REG_WRITE(
            pdx,
            PCI9080_FIFO_CTRL_STAT,
            QueueCsr
            );
    }

    return ApiSuccess;
}
/******************************************************************************
 *
 * Function   :  PlxDmaSglChannelOpen
 *
 * Description:  Open a DMA channel for SGL mode
 *
 ******************************************************************************/
RETURN_CODE
PlxDmaSglChannelOpen(
    DEVICE_EXTENSION *pdx,
    DMA_CHANNEL       channel,
    DMA_CHANNEL_DESC *pDesc,
    VOID             *pOwner
    )
{
    U8           i;
    U32          mode;
    U32          RegValue;
    U32          threshold;
    PLX_REG_DATA RegData;


    // Verify valid DMA channel
    switch (channel)
    {
        case PrimaryPciChannel0:
            i = 0;
            break;

        case PrimaryPciChannel1:
            i = 1;
            break;

        default:
            DebugPrintf(("ERROR - Invalid DMA channel\n"));
            return ApiDmaChannelInvalid;
    }

    spin_lock(
        &(pdx->Lock_DmaChannel)
        );

    // Verify that we can open the channel
    if (pdx->DmaInfo[i].state != DmaStateClosed)
    {
        DebugPrintf(("ERROR - DMA channel already opened\n"));

        spin_unlock(
            &(pdx->Lock_DmaChannel)
            );

        return ApiDmaChannelUnavailable;
    }

    // Open the channel
    pdx->DmaInfo[i].state = DmaStateSgl;

    // Record the Owner
    pdx->DmaInfo[i].pOwner = pOwner;

    // Mark DMA as free
    pdx->DmaInfo[i].bPending = FALSE;

    spin_unlock(
        &(pdx->Lock_DmaChannel)
        );

    // Setup for synchronized access to Interrupt register
    RegData.pdx         = pdx;
    RegData.offset      = PCI9080_INT_CTRL_STAT;
    RegData.BitsToClear = 0;

    spin_lock(
        &(pdx->Lock_HwAccess)
        );

    // Get DMA priority
    RegValue =
        PLX_REG_READ(
            pdx,
            PCI9080_LOCAL_DMA_ARBIT
            );

    // Clear priority
    RegValue &= ~((1 << 20) | (1 << 19));

    // Set the priority
    switch (pDesc->DmaChannelPriority)
    {
        case Channel0Highest:
            PLX_REG_WRITE(
                pdx,
                PCI9080_LOCAL_DMA_ARBIT,
                RegValue | (1 << 19)
                );
            break;

        case Channel1Highest:
            PLX_REG_WRITE(
                pdx,
                PCI9080_LOCAL_DMA_ARBIT,
                RegValue | (1 << 20)
                );
            break;

        case Rotational:
            PLX_REG_WRITE(
                pdx,
                PCI9080_LOCAL_DMA_ARBIT,
                RegValue
                );
            break;

        default:
            DebugPrintf((
                "WARNING - DmaChannelOpen() invalid priority state\n"
                ));
            break;
    }


    threshold =
        (pDesc->TholdForIopWrites <<  0) |
        (pDesc->TholdForIopReads  <<  4) |
        (pDesc->TholdForPciWrites <<  8) |
        (pDesc->TholdForPciReads  << 12);

    mode =
        (1 <<  9) |                  // Enable Chaining
        (1 << 10) |                  // Enable DMA Done interrupt
        (1 << 17) |                  // Route interrupts to PCI
        (pDesc->IopBusWidth              <<  0) |
        (pDesc->WaitStates               <<  2) |
        (pDesc->EnableReadyInput         <<  6) |
        (pDesc->EnableBTERMInput         <<  7) |
        (pDesc->EnableIopBurst           <<  8) |
        (pDesc->HoldIopAddrConst         << 11) |
        (pDesc->DemandMode               << 12) |
        (pDesc->EnableWriteInvalidMode   << 13) |
        (pDesc->EnableDmaEOTPin          << 14) |
        (pDesc->DmaStopTransferMode      << 15);

    // Keep track if local address should remain constant
    if (pDesc->HoldIopAddrConst)
        pdx->DmaInfo[i].bLocalAddrConstant = TRUE;

    // Get DMA Threshold
    RegValue =
        PLX_REG_READ(
            pdx,
            PCI9080_DMA_THRESHOLD
            );

    if (channel == PrimaryPciChannel0)
    {
        // Setup threshold
        PLX_REG_WRITE(
            pdx,
            PCI9080_DMA_THRESHOLD,
            (RegValue & 0xffff0000) | threshold
            );

        // Write DMA mode
        PLX_REG_WRITE(
            pdx,
            PCI9080_DMA0_MODE,
            mode
            );

        // Enable DMA Channel interrupt
        RegData.BitsToSet = (1 << 18);
        PlxSynchronizedRegisterModify(
            &RegData
            );
    }
    else
    {
        // Setup threshold
        PLX_REG_WRITE(
            pdx,
            PCI9080_DMA_THRESHOLD,
            (RegValue & 0x0000ffff) | (threshold << 16)
            );

        // Write DMA mode
        PLX_REG_WRITE(
            pdx,
            PCI9080_DMA1_MODE,
            mode
            );

        // Enable DMA Channel interrupt
        RegData.BitsToSet = (1 << 19);
        PlxSynchronizedRegisterModify(
            &RegData
            );
    }

    spin_unlock(
        &(pdx->Lock_HwAccess)
        );

    return ApiSuccess;
}
Beispiel #4
0
/*******************************************************************************
 *
 * Function   :  PlxInterruptDisable
 *
 * Description:  Disables specific interrupts of the PLX Chip
 *
 ******************************************************************************/
PLX_STATUS
PlxInterruptDisable(
    DEVICE_EXTENSION *pdx,
    PLX_INTERRUPT    *pPlxIntr
    )
{
    U32          RegValue;
    PLX_REG_DATA RegData;


    // Only 16 doorbell interrupts are supported
    pPlxIntr->Doorbell &= 0xFFFF;

    // Disable doorbell interrupts
    if (pPlxIntr->Doorbell)
    {
        PLX_PCI_REG_READ(
            pdx,
            0xc4,
            &RegValue
            );

        // Clear doorbell interrupts that are set
        RegValue &= 0xFFFF0000 | (~pPlxIntr->Doorbell & 0xFFFF);

        PLX_PCI_REG_WRITE(
            pdx,
            0xc4,
            RegValue
            );
    }

    // Setup to synchronize access to interrupt register
    RegData.pdx         = pdx;
    RegData.offset      = 0xc8;
    RegData.BitsToSet   = 0;
    RegData.BitsToClear = 0;

    if (pPlxIntr->Message & (1 << 0))
        RegData.BitsToClear |= (1 << 24);

    if (pPlxIntr->Message & (1 << 1))
        RegData.BitsToClear |= (1 << 25);

    if (pPlxIntr->Message & (1 << 2))
        RegData.BitsToClear |= (1 << 26);

    if (pPlxIntr->Message & (1 << 3))
        RegData.BitsToClear |= (1 << 27);

    if (pPlxIntr->ResetDeassert)
        RegData.BitsToClear |= (1 << 28);

    if (pPlxIntr->PmeDeassert)
        RegData.BitsToClear |= (1 << 29);

    if (pPlxIntr->GPIO_14_15)
        RegData.BitsToClear |= (1 << 30);

    if (pPlxIntr->GPIO_4_5)
        RegData.BitsToClear |= (1 << 31);

    // Write register values if they have changed
    if (RegData.BitsToClear != 0)
    {
        // Synchronize write to interrupt register
        PlxSynchronizedRegisterModify(
            &RegData
            );
    }

    return ApiSuccess;
}
Beispiel #5
0
/******************************************************************************
 *
 * Function   :  PlxChip_DmaChannelOpen
 *
 * Description:  Open a DMA channel
 *
 ******************************************************************************/
PLX_STATUS
PlxChip_DmaChannelOpen(
    DEVICE_EXTENSION *pdx,
    U8                channel,
    VOID             *pOwner
    )
{
    PLX_REG_DATA RegData;


    // Verify valid DMA channel
    switch (channel)
    {
        case 0:
        case 1:
            break;

        default:
            DebugPrintf(("ERROR - Invalid DMA channel\n"));
            return ApiDmaChannelInvalid;
    }

    spin_lock(
        &(pdx->Lock_Dma[channel])
        );

    // Verify that we can open the channel
    if (pdx->DmaInfo[channel].bOpen)
    {
        DebugPrintf(("ERROR - DMA channel already opened\n"));

        spin_unlock(
            &(pdx->Lock_Dma[channel])
            );

        return ApiDmaChannelUnavailable;
    }

    // Open the channel
    pdx->DmaInfo[channel].bOpen = TRUE;

    // Record the Owner
    pdx->DmaInfo[channel].pOwner = pOwner;

    // No SGL DMA is pending
    pdx->DmaInfo[channel].bSglPending = FALSE;

    spin_unlock(
        &(pdx->Lock_Dma[channel])
        );

    // Setup for synchronized access to Interrupt register
    RegData.pdx         = pdx;
    RegData.offset      = PCI9056_INT_CTRL_STAT;
    RegData.BitsToClear = 0;

    // Enable DMA channel interrupt
    if (channel == 0)
        RegData.BitsToSet = (1 << 18);
    else
        RegData.BitsToSet = (1 << 19);

    // Update interrupt register
    PlxSynchronizedRegisterModify(
        &RegData
        );

    DebugPrintf((
        "Opened DMA channel %d\n",
        channel
        ));

    return ApiSuccess;
}
Beispiel #6
0
/******************************************************************************
 *
 * Function   :  PlxChip_InterruptDisable
 *
 * Description:  Disables specific interrupts of the PLX Chip
 *
 ******************************************************************************/
PLX_STATUS
PlxChip_InterruptDisable(
    DEVICE_EXTENSION *pdx,
    PLX_INTERRUPT    *pPlxIntr
    )
{
    U32          QueueCsr;
    U32          QueueCsr_Original;
    U32          RegValue;
    PLX_REG_DATA RegData;


    // Setup to synchronize access to Interrupt Control/Status Register
    RegData.pdx         = pdx;
    RegData.offset      = PCI9056_INT_CTRL_STAT;
    RegData.BitsToSet   = 0;
    RegData.BitsToClear = 0;

    if (pPlxIntr->PciMain)
        RegData.BitsToClear |= (1 << 8);

    if (pPlxIntr->PciAbort)
        RegData.BitsToClear |= (1 << 10);

    if (pPlxIntr->TargetRetryAbort)
        RegData.BitsToClear |= (1 << 12);

    if (pPlxIntr->LocalToPci & (1 << 0))
        RegData.BitsToClear |= (1 << 11);

    if (pPlxIntr->Doorbell)
        RegData.BitsToClear |= (1 << 9);

    if (pPlxIntr->DmaDone & (1 << 0))
    {
        // Check if DMA interrupt is routed to PCI
        RegValue =
            PLX_9000_REG_READ(
                pdx,
                PCI9056_DMA0_MODE
                );

        if (RegValue & (1 << 17))
        {
            RegData.BitsToClear |= (1 << 18);

            // Disable DMA interrupt enable
            PLX_9000_REG_WRITE(
                pdx,
                PCI9056_DMA0_MODE,
                RegValue & ~(1 << 10)
                );
        }
    }

    if (pPlxIntr->DmaDone & (1 << 1))
    {
        // Check if DMA interrupt is routed to PCI
        RegValue =
            PLX_9000_REG_READ(
                pdx,
                PCI9056_DMA1_MODE
                );

        if (RegValue & (1 << 17))
        {
            RegData.BitsToClear |= (1 << 19);

            // Disable DMA interrupt enable
            PLX_9000_REG_WRITE(
                pdx,
                PCI9056_DMA1_MODE,
                RegValue & ~(1 << 10)
                );
        }
    }

    // Inbound Post Queue Interrupt Control/Status Register
    QueueCsr_Original =
        PLX_9000_REG_READ(
            pdx,
            PCI9056_FIFO_CTRL_STAT
            );

    QueueCsr = QueueCsr_Original;

    if (pPlxIntr->MuOutboundPost)
    {
        PLX_9000_REG_WRITE(
            pdx,
            PCI9056_OUTPOST_INT_MASK,
            (1 << 3)
            );
    }

    if (pPlxIntr->MuInboundPost)
        QueueCsr |= (1 << 4);

    if (pPlxIntr->MuOutboundOverflow)
        QueueCsr |= (1 << 6);

    // Write register values if they have changed
    if (RegData.BitsToClear != 0)
    {
        // Synchronize write of Interrupt Control/Status Register
        PlxSynchronizedRegisterModify(
            &RegData
            );
    }

    if (QueueCsr != QueueCsr_Original)
    {
        PLX_9000_REG_WRITE(
            pdx,
            PCI9056_FIFO_CTRL_STAT,
            QueueCsr
            );
    }

    return ApiSuccess;
}