/****************************************************************************** * * 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; }
/****************************************************************************** * * 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; }
/****************************************************************************** * * 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 ); } }