Пример #1
0
/******************************************************************************
 *
 * Function   :  PlxChip_DmaChannelClose
 *
 * Description:  Close a previously opened channel
 *
 ******************************************************************************/
PLX_STATUS
PlxChip_DmaChannelClose(
    DEVICE_EXTENSION *pdx,
    U8                channel,
    BOOLEAN           bCheckInProgress,
    VOID             *pOwner
    )
{
    PLX_STATUS status;


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

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

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

    // Verify DMA channel was opened
    if (pdx->DmaInfo[channel].bOpen == FALSE)
    {
        DebugPrintf(("ERROR - DMA channel has not been opened\n"));
        return ApiDmaChannelUnavailable;
    }

    // Verify owner
    if (pdx->DmaInfo[channel].pOwner != pOwner)
    {
        DebugPrintf(("ERROR - DMA owned by different process\n"));
        return ApiDeviceInUse;
    }

    // Check DMA status
    status =
        PlxChip_DmaStatus(
            pdx,
            channel,
            pOwner
            );

    // Verify DMA is not in progress
    if (status != ApiDmaDone)
    {
        // DMA is still in progress
        if (bCheckInProgress)
            return status;

        DebugPrintf(("DMA in progress, aborting...\n"));

        // Force DMA abort, which may generate a DMA done interrupt
        PlxChip_DmaControl(
            pdx,
            channel,
            DmaAbort,
            pOwner
            );

        // Small delay to let driver cleanup if DMA interrupts
        Plx_sleep( 100 );
    }

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

    // Close the channel
    pdx->DmaInfo[channel].bOpen = FALSE;

    // Clear owner information
    pdx->DmaInfo[channel].pOwner = NULL;

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

    // If DMA is hung, an SGL transfer could be pending, so release user buffer
    if (pdx->DmaInfo[channel].bSglPending)
    {
        PlxSglDmaTransferComplete(
            pdx,
            channel
            );
    }

    // Release memory previously used for SGL descriptors
    if (pdx->DmaInfo[channel].SglBuffer.pKernelVa != NULL)
    {
        DebugPrintf(("Releasing memory used for SGL descriptors...\n"));

        Plx_dma_buffer_free(
            pdx,
            &pdx->DmaInfo[channel].SglBuffer
            );
    }

    return ApiSuccess;
}
Пример #2
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;
}
Пример #3
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
            );
    }
}