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

📄 dispatch.cpp

📁 在vxworks下
💻 CPP
📖 第 1 页 / 共 5 页
字号:
								(VOID *)(PDEVICE_EXTENSION)pdx);

	UnlockDevice(pdx);

	KdPrint((DBG_NAME "DpcForIsr End.\n"));
	CompleteRequestInfo(pIrp, STATUS_SUCCESS, 0);
	IoStartNextPacket(fdo, FALSE);

}												//OnInterrupt DpcForIsr




/******************************************************************************
 *
 * Function   :  DmaOpenBlockChannel
 *
 * Description:  Requests usage of a device's DMA channel.
 *
 ******************************************************************************/
RETURN_CODE DmaOpenBlockChannel(DEVICE_EXTENSION *pdx,
							long lDmaChannel,
							DMA_CHANNEL_DESCRIPTION *pDmaChannelDescription)
{
	ULONG		lMode;
	ULONG		lThreshold;
	KIRQL		OriginalIrqL;
	REG_DATA	RegData;

	ULONG lRegAddress = (ULONG)pdx->LocalRegisterMemBase;
	ULONG lRegValue;

	// Verify valid DMA channel
	if ((lDmaChannel < 0) || (lDmaChannel > 1))
		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;
	}

	KdPrint((DBG_NAME "Now Open Block DMA Channel.\n"));
	// Open the channel
	pdx->DmaInfo[lDmaChannel].State = DMA_STATE_BLOCK;

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

	// Setup for synchronized access to Interrupt register
	RegData.lRegAddress = lRegAddress + PCI9054_INT_CTRL_STAT;
	RegData.lBitsToClear = 0;

	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));
		KdPrint((DBG_NAME "Now Set DMA priority. \n"));
		// 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 =	(0 <<  9) |                  // No Chaining
				(1 << 10) |                  // Enable DMA Done interrupt
				(1 << 17) |                  // Route interrupts to PCI
				(pDmaChannelDescription->LocalBusWidth					<<  0) |  // LocalBusWidth
				(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) |
				(pDmaChannelDescription->DACChainLoad					<< 18);

		// Get DMA Threshold
		lRegValue = READ_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA_THRESHOLD));
		KdPrint((DBG_NAME "Now Set DMA Threshold. \n"));
		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);
			KdPrint((DBG_NAME "The mode is : 0x%X.\n", lMode));

			// Enable PCI & DMA Channel interrupts
			RegData.lBitsToSet = (1 << 8) | (1 << 18);	//
			KeSynchronizeExecution(pdx->pInterruptObject, 
								(PKSYNCHRONIZE_ROUTINE)SynchronizedModifyRegister, 
								(VOID *)&RegData);
		}
		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);
			// Enable PCI & DMA Channel interrupts
			RegData.lBitsToSet = (1 << 8) | (1 << 19);
			KeSynchronizeExecution(pdx->pInterruptObject, 
								(PKSYNCHRONIZE_ROUTINE)SynchronizedModifyRegister, 
								(VOID *)&RegData);
		}
	}	//pDmaChannelDescription != NULL
	else	//pDmaChannelDescription == NULL
	{
		if (lDmaChannel == 0)
		{
			// Disable chaining & route DMA Interrupts to PCI
			lRegValue = READ_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA0_MODE));

			lRegValue |=  (1 << 17);     // Route DMA interrupt to PCI
			lRegValue &= ~(1 << 9);      // Disable Chaining

			WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA0_MODE), lRegValue);
		}
		else
		{
			// Disable chaining & route DMA Interrupts to PCI
			lRegValue = READ_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA1_MODE));

			lRegValue |=  (1 << 17);     // Route DMA interrupt to PCI
			lRegValue &= ~(1 << 9);      // Disable Chaining
			
			WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA1_MODE), lRegValue);
		}
	}	//pDmaChannelDescription == NULL

	KeReleaseSpinLock(&(pdx->HardwareAccessLock), OriginalIrqL);
	KdPrint((DBG_NAME "Block DMA Opened. \n"));
	return RC_SUCCESS;
}

/*********************************************************************
*
* Function   :  SynchronizedModifyRegister
*
* Description:  Register modify to be called with KeSynchronizeExecution()
*
**********************************************************************/
BOOLEAN SynchronizedModifyRegister(PREG_DATA RegData)
{
    ULONG lRegValue;
    lRegValue = READ_REGISTER_ULONG((ULONG *)RegData->lRegAddress);

    lRegValue |= RegData->lBitsToSet;
    lRegValue &= ~(RegData->lBitsToClear);

    WRITE_REGISTER_ULONG((ULONG *)RegData->lRegAddress, lRegValue);

    return TRUE;
}


/******************************************************************************
 *
 * Function   :  DmaBlockTransfer
 *
 * Description:  Performs DMA block transfer.
 *
 ******************************************************************************/
RETURN_CODE DmaBlockTransfer(DEVICE_EXTENSION  *pdx,
						 ULONG		           lDmaChannel,
						 DMA_TRANSFER_ELEMENT *pDmaData)
{
    unsigned char cShift;
    ULONG   lRegDmaBase;
    ULONG   lRegPciHighAddress;
    ULONG	lRegValue;
    KIRQL	OriginalIrqL;
	ULONG	lRegAddress;

    if (pDmaData == NULL)
        return RC_FAILED;
	lRegAddress = (ULONG)pdx->LocalRegisterMemBase;

    // Setup transfer registers
    switch (lDmaChannel)
    {
        case 0:
            cShift				= 0;
            lRegDmaBase			= (ULONG)pdx->LocalRegisterMemBase + PCI9054_DMA0_MODE;
            lRegPciHighAddress	= (ULONG)pdx->LocalRegisterMemBase + PCI9054_DMA0_PCI_DAC;
            break;
        case 1:
            cShift				= 8;
            lRegDmaBase			= (ULONG)pdx->LocalRegisterMemBase + PCI9054_DMA1_MODE;
            lRegPciHighAddress	= (ULONG)pdx->LocalRegisterMemBase + PCI9054_DMA1_PCI_DAC;
            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_BLOCK)
    {
        KdPrint((DBG_NAME "ERROR - DMA Channel has not been opened for Block DMA\n"));

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

        return RC_DMA_CHANNEL_UNAVAILABLE;
    }

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

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

    // Make sure DMA done interrupt is enabled
    lRegValue = READ_REGISTER_ULONG((ULONG *)lRegDmaBase);

    lRegValue |= (1 << 10);
	KdPrint((DBG_NAME "Set DMA done interrupt\n"));
	WRITE_REGISTER_ULONG((ULONG *)lRegDmaBase, lRegValue);

	KdPrint((DBG_NAME "Write PCI Address\n"));
	// Write PCI Address
	WRITE_REGISTER_ULONG((ULONG *)(lRegDmaBase + 0x4), pDmaData->lPciAddress);
	KdPrint((DBG_NAME "Write Local Address\n"));
    // Write Local Address
	WRITE_REGISTER_ULONG((ULONG *)(lRegDmaBase + 0x8), pDmaData->lLocalAddress);
	KdPrint((DBG_NAME "Write Transfer Count\n"));	
    // Write Transfer Count
	WRITE_REGISTER_ULONG((ULONG *)(lRegDmaBase + 0xc), pDmaData->lTransferSize);
	KdPrint((DBG_NAME "Write Descriptor Pointer\n"));
    // Write Descriptor Pointer
    lRegValue = (pDmaData->InterruptAfterTerminalCount << 2) |
                (pDmaData->DirectionOfTransfer		<< 3);
	WRITE_REGISTER_ULONG((ULONG *)(lRegDmaBase + 0x10), lRegValue);
	KdPrint((DBG_NAME "Write the high PCI address\n"));
    // Write the high PCI address
	WRITE_REGISTER_ULONG((ULONG *)(lRegPciHighAddress), pDmaData->lPciDualAddress);
			
	//KdPrint((DBG_NAME "Start Block DMA.\n"));
	lRegValue = READ_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA_COMMAND_STAT));
	lRegValue |= (((1 << 0) | (1 << 1)) << cShift);
	WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA_COMMAND_STAT), lRegValue);

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

	
    return RC_SUCCESS;
}





/******************************************************************************
 *
 * Function   :  DmaRestartBlockTransfer
 *
 * Description:  Start a preprogrammed data transfer again.
 *
 ******************************************************************************/
RETURN_CODE DmaRestartBlockTransfer(DEVICE_EXTENSION *pdx,
									ULONG lDmaChannel,
									ULONG lTransferSize,
									PIRP  pIrp)
{
    unsigned char cShift;
    ULONG	lDmaCountReg;
    ULONG	lRegValue;
    KIRQL	OriginalIrqL;
	ULONG	lRegAddress = (ULONG)pdx->LocalRegisterMemBase;

    // Verify valid DMA channel
    switch (lDmaChannel)
    {
        case 0:
            cShift       = 0;
            lDmaCountReg = PCI9054_DMA0_COUNT;
            break;
        case 1:
            cShift       = 8;
            lDmaCountReg = PCI9054_DMA1_COUNT;
            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_BLOCK)
    {
        KdPrint((DBG_NAME "ERROR - DMA Channel has not been opened for Block DMA\n"));

        KeReleaseSpinLock(&(pdx->DmaChannelLock), OriginalIrqL);
        return RC_DMA_CHANNEL_UNAVAILABLE;
    }

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

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

    // Write the DMA transfer count
	WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + lDmaCountReg), lTransferSize);

    // Enable DMA
	WRITE_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_DMA_COMMAND_STAT), 
						lRegValue | ((1 << 0) << cShift));

    // 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   :  DmaCloseBlockChannel
 *
 * Description:  Close a previously opened channel.
 *
 ******************************************************************************/
RETURN_CODE DmaCloseBlockChannel(DEVICE_EXTENSION *pdx,
								ULONG       lDmaChannel,

⌨️ 快捷键说明

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