Ejemplo n.º 1
0
/******************************************************************************
 *
 * Function   :  PlxChipInterruptsDisable
 *
 * Description:  Globally disables PLX chip interrupts
 *
 *****************************************************************************/
BOOLEAN
PlxChipInterruptsDisable(
    DEVICE_EXTENSION *pdx
    )
{
    U32 RegValue;


    // Disable doorbell interrupts
    PLX_PCI_REG_READ(
        pdx,
        0xc4,
        &RegValue
        );

    RegValue &= ~0xFFFF;

    PLX_PCI_REG_WRITE(
        pdx,
        0xc4,
        RegValue
        );

    // Disable Message, S_RSTIN, S_PME, & GPIO interrupts
    PLX_PCI_REG_WRITE(
        pdx,
        0xc8,
        0x00000000
        );

    return TRUE;
}
Ejemplo n.º 2
0
/*******************************************************************************
 *
 * Function   :  DpcForIsr
 *
 * Description:  This routine will be triggered by the ISR to service an interrupt
 *
 ******************************************************************************/
VOID
DpcForIsr(
    PLX_DPC_PARAM *pArg1
    )
{
    U32                 RegValue;
    unsigned long       flags;
    DEVICE_EXTENSION   *pdx;
    PLX_INTERRUPT_DATA  IntData;


    // Get the device extension
    pdx =
        container_of(
            pArg1,
            DEVICE_EXTENSION,
            Task_DpcForIsr
            );

    // Abort DPC if device is being stopped and resources released
    if ((pdx->State != PLX_STATE_STARTED) || (pdx->PciBar[0].pVa == NULL))
    {
        DebugPrintf(("DPC aborted, device is stopping\n"));

        // Flag DPC is no longer pending
        pdx->bDpcPending = FALSE;

        return;
    }

    // Get interrupt source
    IntData.Source_Ints     = pdx->Source_Ints;
    IntData.Source_Doorbell = 0;

    // Local Interrupt 1
    if (IntData.Source_Ints & INTR_TYPE_LOCAL_1)
    {
        // Synchronize access to Interrupt Control/Status Register
        spin_lock_irqsave( &(pdx->Lock_Isr), flags );

        // Mask local interrupt 1 since true source is unknown
        RegValue =
            PLX_9000_REG_READ(
                pdx,
                PCI9056_INT_CTRL_STAT
                );

        RegValue &= ~(1 << 11);

        PLX_9000_REG_WRITE(
            pdx,
            PCI9056_INT_CTRL_STAT,
            RegValue
            );

        spin_unlock_irqrestore( &(pdx->Lock_Isr), flags );
    }

    // Doorbell Interrupt
    if (IntData.Source_Ints & INTR_TYPE_DOORBELL)
    {
        // Get Doorbell register
        RegValue =
            PLX_9000_REG_READ(
                pdx,
                PCI9056_PCI_DOORBELL
                );

        // Clear Doorbell interrupt
        PLX_9000_REG_WRITE(
            pdx,
            PCI9056_PCI_DOORBELL,
            RegValue
            );

        // Save the doorbell value
        IntData.Source_Doorbell = RegValue;
    }

    // PCI Abort interrupt
    if (IntData.Source_Ints & INTR_TYPE_PCI_ABORT)
    {
        // Get the PCI Command register
        PLX_PCI_REG_READ(
            pdx,
            0x04,
            &RegValue
            );

        // Write to back to clear PCI Abort
        PLX_PCI_REG_WRITE(
            pdx,
            0x04,
            RegValue
            );
    }

    // DMA Channel 0 interrupt
    if (IntData.Source_Ints & INTR_TYPE_DMA_0)
    {
        // Get DMA Control/Status
        RegValue =
            PLX_9000_REG_READ(
                pdx,
                PCI9056_DMA_COMMAND_STAT
                );

        // Clear DMA interrupt
        PLX_9000_REG_WRITE(
            pdx,
            PCI9056_DMA_COMMAND_STAT,
            RegValue | (1 << 3)
            );

        RegValue =
            PLX_9000_REG_READ(
                pdx,
                PCI9056_DMA0_MODE
                );

        // Check if SGL is enabled & cleanup
        if (RegValue & (1 << 9))
        {
            PlxSglDmaTransferComplete(
                pdx,
                0
                );
        }
    }

    // DMA Channel 1 interrupt
    if (IntData.Source_Ints & INTR_TYPE_DMA_1)
    {
        // Get DMA Control/Status
        RegValue =
            PLX_9000_REG_READ(
                pdx,
                PCI9056_DMA_COMMAND_STAT
                );

        // Clear DMA interrupt
        PLX_9000_REG_WRITE(
            pdx,
            PCI9056_DMA_COMMAND_STAT,
            RegValue | (1 << 11)
            );

        RegValue =
            PLX_9000_REG_READ(
                pdx,
                PCI9056_DMA1_MODE
                );

        // Check if SGL is enabled & cleanup
        if (RegValue & (1 << 9))
        {
            PlxSglDmaTransferComplete(
                pdx,
                1
                );
        }
    }

    // Outbound post FIFO interrupt
    if (IntData.Source_Ints & INTR_TYPE_OUTBOUND_POST)
    {
        // Mask Outbound Post interrupt
        PLX_9000_REG_WRITE(
            pdx,
            PCI9056_OUTPOST_INT_MASK,
            (1 << 3)
            );
    }

    // Signal any objects waiting for notification
    PlxSignalNotifications(
        pdx,
        &IntData
        );

    // Re-enable interrupts
    PlxChipInterruptsEnable(
        pdx
        );

    // Flag a DPC is no longer pending
    pdx->bDpcPending = FALSE;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
/******************************************************************************
 *
 * Function   :  PlxChip_BoardReset
 *
 * Description:  Resets a device using software reset feature of PLX chip
 *
 ******************************************************************************/
PLX_STATUS
PlxChip_BoardReset(
    DEVICE_EXTENSION *pdx
    )
{
    U8  MU_Enabled;
    U8  EepromPresent;
    U32 RegValue;
    U32 RegInterrupt;
    U32 RegHotSwap;
    U32 RegPowerMgmnt;


    // Clear any PCI errors (04[31:27])
    PLX_PCI_REG_READ(
        pdx,
        0x04,
        &RegValue
        );

    if (RegValue & (0xf8 << 24))
    {
        // Write value back to clear aborts
        PLX_PCI_REG_WRITE(
            pdx,
            0x04,
            RegValue
            );
    }

    // Save state of I2O Decode Enable
    RegValue =
        PLX_9000_REG_READ(
            pdx,
            PCI9056_FIFO_CTRL_STAT
            );

    MU_Enabled = (U8)(RegValue & (1 << 0));

    // Determine if an EEPROM is present
    RegValue =
        PLX_9000_REG_READ(
            pdx,
            PCI9056_EEPROM_CTRL_STAT
            );

    // Make sure S/W Reset & EEPROM reload bits are clear
    RegValue &= ~((1 << 30) | (1 << 29));

    // Remember if EEPROM is present
    EepromPresent = (U8)((RegValue >> 28) & (1 << 0));

    // Save interrupt line
    PLX_PCI_REG_READ(
        pdx,
        0x3C,
        &RegInterrupt
        );

    // Save some registers if EEPROM present
    if (EepromPresent)
    {
        PLX_PCI_REG_READ(
            pdx,
            PCI9056_HS_CAP_ID,
            &RegHotSwap
            );

        PLX_PCI_REG_READ(
            pdx,
            PCI9056_PM_CSR,
            &RegPowerMgmnt
            );
    }

    // Issue Software Reset to hold PLX chip in reset
    PLX_9000_REG_WRITE(
        pdx,
        PCI9056_EEPROM_CTRL_STAT,
        RegValue | (1 << 30)
        );

    // Delay for a bit
    Plx_sleep(100);

    // Bring chip out of reset
    PLX_9000_REG_WRITE(
        pdx,
        PCI9056_EEPROM_CTRL_STAT,
        RegValue
        );

    // Issue EEPROM reload in case now programmed
    PLX_9000_REG_WRITE(
        pdx,
        PCI9056_EEPROM_CTRL_STAT,
        RegValue | (1 << 29)
        );

    // Delay for a bit
    Plx_sleep(10);

    // Clear EEPROM reload
    PLX_9000_REG_WRITE(
        pdx,
        PCI9056_EEPROM_CTRL_STAT,
        RegValue
        );

    // Restore I2O Decode Enable state
    if (MU_Enabled)
    {
        // Save state of I2O Decode Enable
        RegValue =
            PLX_9000_REG_READ(
                pdx,
                PCI9056_FIFO_CTRL_STAT
                );

        PLX_9000_REG_WRITE(
            pdx,
            PCI9056_FIFO_CTRL_STAT,
            RegValue | (1 << 0)
            );
    }

    // Restore interrupt line
    PLX_PCI_REG_WRITE(
        pdx,
        0x3C,
        RegInterrupt
        );

    // If EEPROM was present, restore registers
    if (EepromPresent)
    {
        // Mask out HS bits that can be cleared
        RegHotSwap &= ~((1 << 23) | (1 << 22) | (1 << 17));

        PLX_PCI_REG_WRITE(
            pdx,
            PCI9056_HS_CAP_ID,
            RegHotSwap
            );

        // Mask out PM bits that can be cleared
        RegPowerMgmnt &= ~(1 << 15);

        PLX_PCI_REG_READ(
            pdx,
            PCI9056_PM_CSR,
            &RegPowerMgmnt
            );
    }

    return ApiSuccess;
}
Ejemplo n.º 5
0
/******************************************************************************
 *
 * Function   :  PlxPciBoardReset
 *
 * Description:  Resets a device using software reset feature of PLX chip
 *
 ******************************************************************************/
VOID
PlxPciBoardReset(
    DEVICE_EXTENSION *pdx
    )
{
    U8  MU_Enabled;
    U8  EepromPresent;
    U32 RegValue;
    U32 RegInterrupt;
    U32 RegMailbox0;
    U32 RegMailbox1;


    // Added to avoid compiler warnings
    RegMailbox0 = 0;
    RegMailbox1 = 0;

    // Clear any PCI errors
    PLX_PCI_REG_READ(
        pdx,
        CFG_COMMAND,
        &RegValue
        );

    if (RegValue & (0xf8 << 24))
    {
        // Write value back to clear aborts
        PLX_PCI_REG_WRITE(
            pdx,
            CFG_COMMAND,
            RegValue
            );
    }

    // Save state of I2O Decode Enable
    RegValue =
        PLX_REG_READ(
            pdx,
            PCI9080_FIFO_CTRL_STAT
            );

    MU_Enabled = (U8)(RegValue & (1 << 0));

    // Determine if an EEPROM is present
    RegValue =
        PLX_REG_READ(
            pdx,
            PCI9080_EEPROM_CTRL_STAT
            );

    // Make sure S/W Reset & EEPROM reload bits are clear
    RegValue &= ~((1 << 30) | (1 << 29));

    // Remember if EEPROM is present
    EepromPresent = (U8)((RegValue >> 28) & (1 << 0));

    // Save some registers if EEPROM present
    if (RegValue & (1 << 28))
    {
        RegMailbox0 =
            PLX_REG_READ(
                pdx,
                PCI9080_MAILBOX0
                );

        RegMailbox1 =
            PLX_REG_READ(
                pdx,
                PCI9080_MAILBOX1
                );

        PLX_PCI_REG_READ(
            pdx,
            CFG_INT_LINE,
            &RegInterrupt
            );
    }

    // Issue Software Reset to hold PLX chip in reset
    PLX_REG_WRITE(
        pdx,
        PCI9080_EEPROM_CTRL_STAT,
        RegValue | (1 << 30)
        );

    // Delay for a bit
    Plx_sleep(100);

    // Bring chip out of reset
    PLX_REG_WRITE(
        pdx,
        PCI9080_EEPROM_CTRL_STAT,
        RegValue
        );

    // Issue EEPROM reload in case now programmed
    PLX_REG_WRITE(
        pdx,
        PCI9080_EEPROM_CTRL_STAT,
        RegValue | (1 << 29)
        );

    // Delay for a bit
    Plx_sleep(10);

    // Clear EEPROM reload
    PLX_REG_WRITE(
        pdx,
        PCI9080_EEPROM_CTRL_STAT,
        RegValue
        );

    // Restore I2O Decode Enable state
    if (MU_Enabled)
    {
        // Save state of I2O Decode Enable
        RegValue =
            PLX_REG_READ(
                pdx,
                PCI9080_FIFO_CTRL_STAT
                );

        PLX_REG_WRITE(
            pdx,
            PCI9080_FIFO_CTRL_STAT,
            RegValue | (1 << 0)
            );
    }

    // If EEPROM was present, restore registers
    if (EepromPresent)
    {
        // Restore saved registers
        PLX_REG_WRITE(
            pdx,
            PCI9080_MAILBOX0,
            RegMailbox0
            );

        PLX_REG_WRITE(
            pdx,
            PCI9080_MAILBOX1,
            RegMailbox1
            );

        PLX_PCI_REG_WRITE(
            pdx,
            CFG_INT_LINE,
            RegInterrupt
            );
    }
}