⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dispatch.cpp

📁 在vxworks下
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            KeSynchronizeExecution(pdx->pInterruptObject,
									(PKSYNCHRONIZE_ROUTINE)SynchronizedModifyRegister,
									(VOID *)&RegData);

            // Clear Dual Address cycle register
            WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA0_PCI_DAC), 0);
        }
    }

    KeReleaseSpinLock(&(pdx->HardwareAccessLock), OriginalIrqL);

    return RC_SUCCESS;
}

/******************************************************************************
 *
 * Function   :  PlxDmaSglTransfer
 *
 * Description:  Operate a DMA channel for SGL.
 *
 ******************************************************************************/
RETURN_CODE DmaSglTransfer(DEVICE_EXTENSION     *pdx,
						   ULONG				lDmaChannel,
						   ULONG				lMdbAddress)
{
	unsigned char	cShift = 0;
	ULONG			lRegDmaDescription = 0;
	ULONG			lRegValue = 0;
	KIRQL			OriginalIrqL;

	ULONG lRegAddress = (ULONG)pdx->LocalRegisterMemBase;

	// Verify valid DMA channel
	switch (lDmaChannel)
	{
	case 0:
		cShift      = 0;
		lRegDmaDescription = PCI9054_DMA0_DESC_PTR;
		break;
	case 1:
		cShift      = 8;
		lRegDmaDescription = PCI9054_DMA1_DESC_PTR;
		break;
	default:
		KdPrint((DBG_NAME "ERROR - Invalid DMA channel\n"));
		return RC_DMA_CHANNEL_INVALID;
	}

	// Verify that DMA is not in progress
	lRegValue = READ_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA_COMMAND_STAT));

	if ((lRegValue & ((1 << 4) << cShift)) == 0)
	{
		KdPrint((DBG_NAME "ERROR - DmaTransfer() Channel is active\n"));
		return RC_DMA_IN_PROGRESS;
	}

	KeAcquireSpinLock(&(pdx->DmaChannelLock), &OriginalIrqL);

	// Verify DMA Channel was opened correctly
	if (pdx->DmaInfo[lDmaChannel].State != DMA_STATE_SGL)
	{
		KdPrint((DBG_NAME "ERROR - DMA channel has not been opened for SGL DMA\n"));
		KeReleaseSpinLock(&(pdx->DmaChannelLock), OriginalIrqL);
		return RC_DMA_CHANNEL_UNAVAILABLE;
	}
	KeReleaseSpinLock(&(pdx->DmaChannelLock), OriginalIrqL);

	KeAcquireSpinLock(&(pdx->HardwareAccessLock), &OriginalIrqL);

	//Set the first Descriptor Pointer Register 
	// Ensure an SGL transfer will occur & write SGL physical address
	WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + lRegDmaDescription), lMdbAddress | 1);
	KdPrint((DBG_NAME "lMdbAddress = 0x%X.\n", lMdbAddress));
	lRegValue = READ_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA_COMMAND_STAT));

	// Enable and Start DMA
	WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA_COMMAND_STAT),
						lRegValue | (((1 << 0) | (1 << 1)) << cShift));
	KeReleaseSpinLock(&(pdx->HardwareAccessLock), OriginalIrqL);

	return RC_SUCCESS;
}

/******************************************************************************
 *
 * Function   :  PlxDmaSglChannelClose
 *
 * Description:  Close a previously opened channel.
 *
 ******************************************************************************/
RETURN_CODE DmaCloseSglChannel(DEVICE_EXTENSION *pdx,
							   ULONG			lDmaChannel,
							   BOOLEAN			bCheckInProgress)
{
    ULONG	lStatus  = 0;
    KIRQL	OriginalIrqL;

	ULONG	lRegAddress = (ULONG)pdx->LocalRegisterMemBase;
    // Verify valid DMA channel
    if (lDmaChannel > 1)
	{
        KdPrint((DBG_NAME "ERROR - Invalid DMA channel\n"));
        return RC_DMA_CHANNEL_INVALID;
    }

    if (bCheckInProgress)
    {
        // Verify that DMA is not in progress
        lStatus = READ_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA_COMMAND_STAT));
        if (lDmaChannel == 1)
            lStatus = lStatus >> 8;

        if ((lStatus & (1 << 4)) == 0)
        {
            if (lStatus & (1 << 0))
                return RC_DMA_IN_PROGRESS;
            else
                return RC_DMA_PAUSED;
        }
    }

    KeAcquireSpinLock(&(pdx->DmaChannelLock), &OriginalIrqL);

    // Verify DMA Channel was opened correctly
    if (pdx->DmaInfo[lDmaChannel].State != DMA_STATE_SGL)
    {
        KdPrint((DBG_NAME "ERROR - DMA channel has not been opened for SGL DMA\n"));
        KeReleaseSpinLock(&(pdx->DmaChannelLock), OriginalIrqL);
        return RC_DMA_CHANNEL_UNAVAILABLE;
    }

    // Close the channel
    pdx->DmaInfo[lDmaChannel].State = DMA_STATE_CLOSED;

    KeReleaseSpinLock(&(pdx->DmaChannelLock), OriginalIrqL);

    return RC_SUCCESS;
}

/******************************************************************************
 *
 * Function   :  PlxDmaShuttleChannelOpen
 *
 * Description:  Open a DMA channel for Shuttle transfers.
 *
 ******************************************************************************/
RETURN_CODE DmaOpenShuttleChannel(DEVICE_EXTENSION			*pdx,
								  ULONG						lDmaChannel,
								  DMA_CHANNEL_DESCRIPTION	*pDmaChannelDescription,
								  PFILE_OBJECT				pFileObject)
{
    ULONG	lMode = 0;
    ULONG	lRegValue = 0;
    ULONG	lThreshold = 0;
    KIRQL	OriginalIrqL;

	ULONG	lRegAddress = (ULONG)pdx->LocalRegisterMemBase;

    // Verify valid DMA channel
    if (lDmaChannel > 1)
    {
        KdPrint((DBG_NAME "ERROR - Invalid DMA channel\n"));
        return RC_DMA_CHANNEL_INVALID;
    }

    KeAcquireSpinLock(&(pdx->DmaChannelLock), &OriginalIrqL);

    // Verify that we can open the channel
    if (pdx->DmaInfo[lDmaChannel].State != DMA_STATE_CLOSED)
    {
        KdPrint((DBG_NAME "ERROR - DMA channel already opened\n"));
        KeReleaseSpinLock(&(pdx->DmaChannelLock), OriginalIrqL);
        return RC_DMA_CHANNEL_UNAVAILABLE;
    }

    // Open the channel
    pdx->DmaInfo[lDmaChannel].State = DMA_STATE_SHUTTLE;

    // Clear the buffer parameters
    pdx->DmaInfo[lDmaChannel].pSgl = NULL;
    pdx->DmaInfo[lDmaChannel].pMdl = NULL;

    KeReleaseSpinLock(&(pdx->DmaChannelLock), OriginalIrqL);

    KeAcquireSpinLock(&(pdx->HardwareAccessLock), &OriginalIrqL);

    if (pDmaChannelDescription != NULL)
    {
        // Get DMA priority
        lRegValue = READ_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_MODE_DMA_ARBITRATION));
        // Clear priority
        lRegValue &= ~((1 << 20) | (1 << 19));

        // Set the priority
        switch (pDmaChannelDescription->DmaChannelPriority)
        {
        case Channel0Highest:
			WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_MODE_DMA_ARBITRATION), lRegValue | (1 << 19));
            break;
        case Channel1Highest:
			WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_MODE_DMA_ARBITRATION), lRegValue | (1 << 20));
            break;
        case Rotational:
			WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_MODE_DMA_ARBITRATION), lRegValue);
            break;
        default:
            KdPrint((DBG_NAME "WARNING - DmaChannelOpen() invalid priority state.\n"));
        }
		lThreshold =(pDmaChannelDescription->PciToLocalAlmostFull <<  0) |
					(pDmaChannelDescription->LocalToPciAlmostEmpty<<  4) |
					(pDmaChannelDescription->LocalToPciAlmostFull <<  8) |
					(pDmaChannelDescription->PciToLocalAlmostEmpty<< 12);
		lMode =	(1 <<  9) |                  // Enable Chaining
				(1 << 10) |                  // Enable DMA Done interrupt
				(1 << 17) |                  // Route interrupts to PCI
				(0 << 18) |                  // Disable Dual-Addressing
				(pDmaChannelDescription->LocalBusWidth					<<  0) |
				(pDmaChannelDescription->InternalWaitStates				<<  2) |
				(pDmaChannelDescription->ReadyInputEnable				<<  6) |
				(pDmaChannelDescription->BTERMInputEnable				<<  7) |
				(pDmaChannelDescription->LocalBurstEnable				<<  8) |
				(pDmaChannelDescription->LocalAddressingMode			<< 11) |
				(pDmaChannelDescription->DemandMode						<< 12) |
				(pDmaChannelDescription->MemoryWriteAndInvalidateMode	<< 13) |
				(pDmaChannelDescription->DmaEOTPinEnable				<< 14) |
				(pDmaChannelDescription->FastSlowTerminateModeSelect	<< 15);

        // Keep track if local address should remain constant
        if (pDmaChannelDescription->LocalAddressingMode)
            pdx->DmaInfo[lDmaChannel].HoldLocalAddressConstant = TRUE;

        // Get DMA Threshold
        lRegValue = READ_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA_THRESHOLD));

        if (lDmaChannel == 0)
        {
            // Setup threshold
			WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA_THRESHOLD), 
								(lRegValue & 0xffff0000) | lThreshold);
            // Write DMA mode
			WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA0_MODE), lMode);
            // Clear Dual Address cycle register
			WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA0_PCI_DAC), 0);
        }
        else
        {
            // Setup threshold
			WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA_THRESHOLD),
								(lRegValue & 0x0000ffff) | (lThreshold << 16));
            // Write DMA mode
			WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA1_MODE), lMode);

            // Clear Dual Address cycle register
			WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA1_PCI_DAC), 0);
        }
    }
    else
    {
        if (lDmaChannel == 0)
        {
            // Enable Chaining & disable DMA Done interrupt
            lRegValue = READ_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA0_MODE));
			
			lRegValue |=  (1 << 9);                // Enable Chaining
            lRegValue &= ~((1 << 10) | (1 << 18)); // Disable DMA Done Int & Dual-Address

			WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA0_MODE), lRegValue);
            // Keep track if local address should remain constant
            if (lRegValue & (1 << 11)) 
                pdx->DmaInfo[0].HoldLocalAddressConstant = TRUE;

            // Clear Dual Address cycle register
			WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA0_PCI_DAC), 0);
        }
        else
        {
            // Enable Chaining & disable DMA Done interrupt
            lRegValue = READ_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA1_MODE));
            lRegValue |=  (1 << 9);                // Enable Chaining
            lRegValue &= ~((1 << 10) | (1 << 18)); // Disable DMA Done Int & Dual-Address

			WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA1_MODE), lRegValue);
            // Keep track if local address should remain constant
            if (lRegValue & (1 << 11)) 
                pdx->DmaInfo[1].HoldLocalAddressConstant = TRUE;

            // Clear Dual Address cycle register
			WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA1_PCI_DAC), 0);
        }
    }

    KeReleaseSpinLock(&(pdx->HardwareAccessLock), OriginalIrqL);

    return RC_SUCCESS;
}

/******************************************************************************
 *
 * Function   :  PlxDmaShuttleTransfer
 *
 * Description:  Performs a DMA transfer using Shuttle mode.
 *
 ******************************************************************************/
RETURN_CODE DmaShuttleTransfer(DEVICE_EXTENSION     *pdx,
							   ULONG				lDmaChannel,
							   DMA_TRANSFER_ELEMENT *pDmaData)
{
	UCHAR	cShift = 0;
    ULONG	lRegDmaDescription = 0;
    ULONG	lRegValue = 0;
    KIRQL	OriginalIrqL;
    PVOID	pSglPciAddress = NULL;

	ULONG	lRegAddress = (ULONG)pdx->LocalRegisterMemBase;

    if (pDmaData == NULL)
        return RC_NULL_PARAMETER;

    // Verify valid DMA channel
    switch (lDmaChannel)
    {
    case 0:
        cShift      = 0;
        lRegDmaDescription = PCI9054_DMA0_DESC_PTR;
        break;
    case 1:
        cShift      = 8;
        lRegDmaDescription = PCI9054_DMA1_DESC_PTR;
        break;
    default:
        KdPrint((DBG_NAME "ERROR - Invalid DMA channel\n"));
        return RC_DMA_CHANNEL_INVALID;
    }

    // Verify that DMA is not in progress
    lRegValue = READ_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA_COMMAND_STAT));
    if ((lRegValue & ((1 << 4) << cShift)) == 0)
    {
        KdPrint((DBG_NAME "ERROR - DmaTransfer() Channel is active\n"));
        return RC_DMA_IN_PROGRESS;
    }

    KeAcquireSpinLock(&(pdx->DmaChannelLock), &OriginalIrqL);

    // Verify DMA Channel was opened correctly
    if (pdx->DmaInfo[lDmaChannel].State != DMA_STATE_SHUTTLE)
    {
        KdPrint((DBG_NAME "ERROR - DMA channel has not been opened for Shuttle DMA\n"));

        KeReleaseSpinLock(&(pdx->DmaChannelLock), OriginalIrqL);

        return RC_DMA_CHANNEL_UNAVAILABLE;
    }

    // Verify no transfer is in progress
    if ((pdx->DmaInfo[lDmaChannel].pSgl != NULL) ||
        (pdx->DmaInfo[lDmaChannel].pMdl != NULL))
    {
        KdPrint((DBG_NAME "ERROR - DMA Channel is active\n"));

        KeReleaseSpinLock(&(pdx->DmaChannelLock), OriginalIrqL);

        return RC_DMA_IN_PROGRESS;
	}

    KeReleaseSpinLock(&(pdx->DmaChannelLock), OriginalIrqL);
/*
    SglPciAddress =
        PlxLockBufferAndBuildSgl(
            pdx,
            i,
            pDmaData->Pci9054Dma.LowPciAddr,
            pDmaData->Pci9054Dma.IopAddr,
            pDmaData->Pci9054Dma.TransferCount,
            (U8)pDmaData->Pci9054Dma.IopToPciDma,
            TRUE
            );
*/
    if (pSglPciAddress == NULL)
    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -