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

📄 readwrite.cpp

📁 The PCI Local bus concept was developed to break the PC data I/O bottleneck and clearly opens the d
💻 CPP
📖 第 1 页 / 共 3 页
字号:
												PIRP junk, \
												PVOID MapRegisterBase, \
												PVOID Context)
{
	KdPrint(("SIWDM - Entering SheldonWriteAdapterControl\n"));

	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) Context;
	PIRP Irp = GetCurrentIrp(&pdx->dqReadWrite);
	PMDL Mdl = Irp->MdlAddress;
	PULONG OP = pdx->base[AMCC_OPREGS];

	ULONG intCSR;

	pdx->WriteTransfer.BytesRequested = MmGetMdlByteCount(Mdl);
	pdx->WriteTransfer.BytesRemaining = pdx->WriteTransfer.BytesRequested;
	pdx->WriteTransfer.LogicalAddress = (UCHAR *) MmGetMdlVirtualAddress(Mdl);
	pdx->WriteTransfer.MapRegisterBase = MapRegisterBase;
	pdx->WriteTransfer.Mdl = Mdl;

	// We now have the physical address and size of the first chunk to send
	// Let's now set up the PCI hardware so that when we load MWTC and MWAR 
	// a transfer will occur

/////////////////
// IO and memory mapped
/////////////////
	if( (ULONG)pdx->base[AMCC_OPREGS] & 0xffff0000 ) {
		// Disable PCI FIFO to Add-on Bus Mastering by MCSR bit 14 set to 0
		OP[AMCC_MCSR] &= ~AMCC_BUSMASTERED_WRITE_ENABLE_MASK;
		intCSR = OP[AMCC_INTCSR] & AMCC_PRESERVE_INTCSR_MASK;
		// Disable Ints from Transfer Count = 0 by INTCSR bits 14 15 both zeroed
		OP[AMCC_INTCSR] = intCSR & ~AMCC_BUSMASTERED_WRITE_INT_ENABLE_MASK;
		// Clear FIFO by MCSR bit 25 written with one
		// Will clear fifo before every transfer if executed(implementation dependent)
		// OP[AMCC_MCSR] |= AMCC_BUSMASTERED_WRITE_CLEAR_FIFO_MASK;
		// Write zero into the MWTC
		OP[AMCC_MRTC]=0x0000;
		// Define FIFO Management Scheme as go-on-half-way (4 words) by MCSR bit 13 written as 1
		OP[AMCC_MCSR] |= 0x00002000;
		// Define Read-Write Priority as equal by bits 8 and 12 written as 1
		OP[AMCC_MCSR] = (OP[AMCC_MCSR] | 0x00001000) & ~0x00000100;
	
		// Set the transfer flag before allowing ints
		pdx->WriteTransfer.TransferInProgress = TRUE;

		// Ok, let's do the first call to the code which loads the registers and (re)starts 
		// the transfer.  Later calls will be made by the DPC after each interrupt, until 
		// the transfer is complete.

		DoBusMasteredWrite(pdx);

		// Now re-enable the interrupts and set TIProgress
		intCSR = OP[AMCC_INTCSR] & AMCC_PRESERVE_INTCSR_MASK;
		// Enable Ints from Transfer Count = 0 by INTCSR bits 14 15 both zeroed
		OP[AMCC_INTCSR] = intCSR | AMCC_BUSMASTERED_WRITE_INT_ENABLE_MASK;
		// Enable Add-on to PCI FIFO Bus Mastering by MCSR bit 14 set 1
		OP[AMCC_MCSR] |= AMCC_BUSMASTERED_WRITE_ENABLE_MASK;
	}
	else {
		// Disable PCI FIFO to Add-on Bus Mastering by MCSR bit 14 set to 0
		WRITE_PORT_ULONG(OP + AMCC_MCSR, READ_PORT_ULONG(OP + AMCC_MCSR) & ~AMCC_BUSMASTERED_WRITE_ENABLE_MASK );
		intCSR = READ_PORT_ULONG(OP + AMCC_INTCSR) & AMCC_PRESERVE_INTCSR_MASK;
		// Disable Ints from Transfer Count = 0 by INTCSR bits 14 15 both zeroed
		WRITE_PORT_ULONG(OP + AMCC_INTCSR, intCSR & ~AMCC_BUSMASTERED_WRITE_INT_ENABLE_MASK);
		// Clear FIFO by MCSR bit 25 written with one
		// Will clear fifo before every transfer if executed(implementation dependent)
		// OP[AMCC_MCSR] |= AMCC_BUSMASTERED_WRITE_CLEAR_FIFO_MASK;
		// Write zero into the MWTC
		WRITE_PORT_ULONG(OP + AMCC_MRTC, 0x0000);
		// Define FIFO Management Scheme as go-on-half-way (4 words) by MCSR bit 13 written as 1
		WRITE_PORT_ULONG(OP + AMCC_MCSR, READ_PORT_ULONG(OP + AMCC_MCSR) | 0x00002000);
		// Define Read-Write Priority as equal by bits 8 and 12 written as 1
		WRITE_PORT_ULONG(OP + AMCC_MCSR, (READ_PORT_ULONG(OP + AMCC_MCSR) | 0x00001000) & ~0x00000100);
	
		// Set the transfer flag before allowing ints
		pdx->WriteTransfer.TransferInProgress = TRUE;

		// Ok, let's do the first call to the code which loads the registers and (re)starts 
		// the transfer.  Later calls will be made by the DPC after each interrupt, until 
		// the transfer is complete.

		DoBusMasteredWrite(pdx);

		// Now re-enable the interrupts and set TIProgress
		intCSR = READ_PORT_ULONG(OP + AMCC_INTCSR) & AMCC_PRESERVE_INTCSR_MASK;
		// Enable Ints from Transfer Count = 0 by INTCSR bits 14 15 both zeroed
		WRITE_PORT_ULONG(OP + AMCC_INTCSR, intCSR | AMCC_BUSMASTERED_WRITE_INT_ENABLE_MASK);
		// Enable Add-on to PCI FIFO Bus Mastering by MCSR bit 14 set 1
		WRITE_PORT_ULONG(OP + AMCC_MCSR, READ_PORT_ULONG(OP + AMCC_MCSR) | AMCC_BUSMASTERED_WRITE_ENABLE_MASK);
	}
		
	KdPrint(("SIWDM - Exiting SheldonWriteAdapterControl\n"));

	return DeallocateObjectKeepRegisters;
}

/*

Function Name:

	DoBusMasteredRead

Routine Description:

	Perform a BusMastered Read.

Arguments:

    pdx - pointer to a device extension

Return Value:

	TRUE
*/
BOOLEAN DoBusMasteredRead(IN PDEVICE_EXTENSION pdx)
{
	PULONG OP = pdx->base[AMCC_OPREGS];
	PHYSICAL_ADDRESS PhysicalAddress;
	LARGE_INTEGER When = {-1,-5000000};

	KdPrint(("SIWDM - Entering DoBusMasteredRead\n"));

	// LogicalAddress and BytesRemaining must be set before calling this 
	//	function

	pdx->ReadTransfer.CurrentTransferSize = pdx->ReadTransfer.BytesRemaining;

	PhysicalAddress = 
		pdx->ReadTransfer.Adapter->DmaOperations->MapTransfer
		(
			pdx->ReadTransfer.Adapter,
			pdx->ReadTransfer.Mdl,
			pdx->ReadTransfer.MapRegisterBase,
			pdx->ReadTransfer.LogicalAddress,
			&pdx->ReadTransfer.CurrentTransferSize,
			FALSE
		);

	// if current transfer size is 0, then cannot get physical addr.
	if ( pdx->ReadTransfer.CurrentTransferSize == 0 )
	{
		KdPrint
		((
			"%s%s", 
			"SIWDM - DoBusMasteredRead: ERROR - ", 
			"pdx->ReadTransfer.CurrentTransferSize == 0\n"
		));

		When.QuadPart = 1;
		KeSetTimer
		(
			&pdx->ReadTransfer.Timer, When, &pdx->ReadTransfer.TimerDPC
		);
		return FALSE;
	}

	// convert to microseconds & relative
	When.QuadPart = (ULONGLONG) pdx->Timeout_ms * (LONGLONG) -10000L;

	if(pdx->Timeout_ms != 0)
		KeSetTimer(&pdx->ReadTransfer.Timer, When, &pdx->ReadTransfer.TimerDPC);

	// Load	MWAR and MWTC for this chunk

/////////////////
// IO and memory mapped
/////////////////
	if( (ULONG)pdx->base[AMCC_OPREGS] & 0xffff0000 ) {
		// Write the address into the MWAR
		OP[AMCC_MWAR] = PhysicalAddress.LowPart;

		// Write the count (BYTES) into the MWTC
		OP[AMCC_MWTC] = pdx->ReadTransfer.CurrentTransferSize;
	}
	else {
		// Write the address into the MWAR
		WRITE_PORT_ULONG(OP + AMCC_MWAR, PhysicalAddress.LowPart );

		// Write the count (BYTES) into the MWTC
		WRITE_PORT_ULONG(OP + AMCC_MWTC, pdx->ReadTransfer.CurrentTransferSize );
	}

	// The transfer (re)starts now and will interrupt when this chunk is done
	// but if it doesn't, the timer will let us know.

	KdPrint(("SIWDM - Exiting DoBusMasteredRead\n"));

	return TRUE;
}

/*

Function Name:

	DoBusMasteredWrite

Routine Description:

	Perform a BusMastered Write.

Arguments:

    pdx - pointer to a device extension

Return Value:

	TRUE
*/
BOOLEAN DoBusMasteredWrite(IN PDEVICE_EXTENSION pdx)
{
	PULONG OP = pdx->base[AMCC_OPREGS];
	PHYSICAL_ADDRESS PhysicalAddress;
	LARGE_INTEGER When;
	
	KdPrint(("SIWDM - Entering DoBusMasteredWrite\n"));

	// LogicalAddress and BytesRemaining must be set before calling this 
	//	function

	pdx->WriteTransfer.CurrentTransferSize = pdx->WriteTransfer.BytesRemaining;

	PhysicalAddress = 
		pdx->WriteTransfer.Adapter->DmaOperations->MapTransfer
		(
			pdx->WriteTransfer.Adapter,
			pdx->WriteTransfer.Mdl,
			pdx->WriteTransfer.MapRegisterBase,
			pdx->WriteTransfer.LogicalAddress,
			&pdx->WriteTransfer.CurrentTransferSize,
			TRUE
		);

	// if current transfer size is 0, then cannot get physical addr.
	if ( pdx->WriteTransfer.CurrentTransferSize == 0 )
	{
		KdPrint
		((
			"%s%s", 
			"SIWDM - DoBusMasteredWrite: ERROR - ", 
			"pdx->WriteTransfer.CurrentTransferSize == 0\n"
		));

		When.QuadPart = 1;
		KeSetTimer
		(
			&pdx->ReadTransfer.Timer, When, &pdx->ReadTransfer.TimerDPC
		);
		return FALSE;
	}

	// convert to microseconds & relative
	When.QuadPart = (ULONGLONG) pdx->Timeout_ms * (LONGLONG) -10000L;

	KdPrint
	((
		"SIWDM - DoBusMasteredWrite: Timer = 0x%x\n", 
		&pdx->WriteTransfer.Timer
	));

	KdPrint
	((
		"SIWDM - DoBusMasteredWrite: TimerDPC = 0x%x\n", 
		&pdx->WriteTransfer.TimerDPC
	));

	if(pdx->Timeout_ms != 0)
		KeSetTimer(&pdx->WriteTransfer.Timer, When, &pdx->WriteTransfer.TimerDPC);

	// Load	MRAR and MRTC for this chunk

/////////////////
// IO and memory mapped
/////////////////
	if( (ULONG)pdx->base[AMCC_OPREGS] & 0xffff0000 ) {
		// Write the address into the MRAR, before the count
		OP[AMCC_MRAR]=PhysicalAddress.LowPart;

		// Write the count (in BYTES) into the MRTC
		OP[AMCC_MRTC]=pdx->WriteTransfer.CurrentTransferSize;
	}
	else {
		// Write the address into the MRAR, before the count
		WRITE_PORT_ULONG(OP + AMCC_MRAR, PhysicalAddress.LowPart);

		// Write the count (in BYTES) into the MRTC
		WRITE_PORT_ULONG(OP + AMCC_MRTC, pdx->WriteTransfer.CurrentTransferSize);
	}

	// The transfer begins now and will interrupt when done
	// but if it doesn't, the timer will let us know.

	KdPrint(("SIWDM - Exiting DoBusMasteredWrite\n"));

	return TRUE;
}

/*

Function Name:

	SheldonTimerRoutine

Routine Description:

	Performs the Timeout for BusMastered Transfers.
	Retires the IRP and resets the hardware.

Arguments:

    Dpc - pointer to a dpc object

	Context - pointer to a device extension

	junk1 - invalid parameter, for custom timer DPC's

	junk2 - invalid parameter

Return Value:

*/
VOID SheldonTimerRoutine(PKDPC Dpc, PVOID Context, PVOID junk1, PVOID junk2)
{
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) Context;
	ULONG mcsr, intCSR;
	PIRP Irp;

	KdPrint(("SIWDM - Entering SheldonTimerRoutine\n"));

	// figure out what kind of a transfer was in progress

	// a read went wrong
	if(Dpc == &(pdx->ReadTransfer.TimerDPC) && pdx->ReadTransfer.TransferInProgress)
	{
		// turn off the transfer
/////////////////
// IO and memory mapped
/////////////////
		if( (ULONG)pdx->base[AMCC_OPREGS] & 0xffff0000 ) {
			mcsr = READ_REGISTER_ULONG(pdx->base[AMCC_OPREGS] + AMCC_MCSR);
			// shut off go signal for reads
			mcsr &= ~AMCC_BUSMASTERED_READ_ENABLE_MASK;
			WRITE_REGISTER_ULONG(pdx->base[AMCC_OPREGS] + AMCC_MCSR, mcsr);

			// shut off and clear the interrupt
			intCSR = READ_REGISTER_ULONG(pdx->base[AMCC_OPREGS] + AMCC_INTCSR);
			// clear the "write 1 clear" bits to avoid problems
			intCSR &= AMCC_PRESERVE_INTCSR_MASK;
			// shut off ints for reads
			intCSR &= ~AMCC_BUSMASTERED_READ_INT_ENABLE_MASK;
			// clear the read's int bit
			intCSR |= AMCC_BUSMASTERED_READ_INT_OCCURRED_MASK;
			WRITE_REGISTER_ULONG(pdx->base[AMCC_OPREGS] + AMCC_INTCSR, intCSR);

			// update the status
			pdx->ReadTransfer.TransferInProgress = FALSE;

			// Conclude the previous "DMA" Transfer
			pdx->ReadTransfer.Adapter->DmaOperations->FlushAdapterBuffers(
				pdx->ReadTransfer.Adapter,
				pdx->ReadTransfer.Mdl,
				pdx->ReadTransfer.MapRegisterBase,
				pdx->ReadTransfer.LogicalAddress,
				pdx->ReadTransfer.CurrentTransferSize,
				FALSE);

			pdx->ReadTransfer.Adapter->DmaOperations->FreeMapRegisters(
				pdx->ReadTransfer.Adapter,
				pdx->ReadTransfer.MapRegisterBase,
				pdx->ReadTransfer.NumberOfMapRegisters);

			// Close out this IRP
			Irp = pdx->ReadTransfer.pIrp;
			Irp->IoStatus.Information =
				pdx->ReadTransfer.BytesRequested - pdx->ReadTransfer.BytesRemaining
				+ pdx->ReadTransfer.CurrentTransferSize
				- READ_REGISTER_ULONG(pdx->base[AMCC_OPREGS] + AMCC_MWTC);

			Irp->IoStatus.Status = STATUS_IO_TIMEOUT;
				
			// This one's done. Begin working on the next
			StartNextPacket(&pdx->dqReadWrite, pdx->DeviceObject);
			UnlockDevice(pdx);
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
		}
		else {
			mcsr = READ_PORT_ULONG(pdx->base[AMCC_OPREGS] + AMCC_MCSR);
			// shut off go signal for reads
			mcsr &= ~AMCC_BUSMASTERED_READ_ENABLE_MASK;
			WRITE_PORT_ULONG(pdx->base[AMCC_OPREGS] + AMCC_MCSR, mcsr);

			// shut off and clear the interrupt
			intCSR = READ_PORT_ULONG(pdx->base[AMCC_OPREGS] + AMCC_INTCSR);
			// clear the "write 1 clear" bits to avoid problems
			intCSR &= AMCC_PRESERVE_INTCSR_MASK;
			// shut off ints for reads
			intCSR &= ~AMCC_BUSMASTERED_READ_INT_ENABLE_MASK;
			// clear the read's int bit
			intCSR |= AMCC_BUSMASTERED_READ_INT_OCCURRED_MASK;
			WRITE_PORT_ULONG(pdx->base[AMCC_OPREGS] + AMCC_INTCSR, intCSR);

			// update the status
			pdx->ReadTransfer.TransferInProgress = FALSE;

			// Conclude the previous "DMA" Transfer
			pdx->ReadTransfer.Adapter->DmaOperations->FlushAdapterBuffers(
				pdx->ReadTransfer.Adapter,
				pdx->ReadTransfer.Mdl,
				pdx->ReadTransfer.MapRegisterBase,
				pdx->ReadTransfer.LogicalAddress,
				pdx->ReadTransfer.CurrentTransferSize,
				FALSE);

			pdx->ReadTransfer.Adapter->DmaOperations->FreeMapRegisters(
				pdx->ReadTransfer.Adapter,
				pdx->ReadTransfer.MapRegisterBase,
				pdx->ReadTransfer.NumberOfMapRegisters);

			// Close out this IRP
			Irp = pdx->ReadTransfer.pIrp;
			Irp->IoStatus.Information =
				pdx->ReadTransfer.BytesRequested - pdx->ReadTransfer.BytesRemaining
				+ pdx->ReadTransfer.CurrentTransferSize
				- READ_PORT_ULONG(pdx->base[AMCC_OPREGS] + AMCC_MWTC);

			Irp->IoStatus.Status = STATUS_IO_TIMEOUT;
				
			// This one's done. Begin working on the next
			StartNextPacket(&pdx->dqReadWrite, pdx->DeviceObject);
			UnlockDevice(pdx);
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
		}

	}
	// a write went wrong
	else if(Dpc == &(pdx->WriteTransfer.TimerDPC) && pdx->WriteTransfer.TransferInProgress)
	{
		// stop the transfer and clear the FIFO
/////////////////
// IO and memory mapped
/////////////////
		if( (ULONG)pdx->base[AMCC_OPREGS] & 0xffff0000 ) {
			mcsr = READ_REGISTER_ULONG(pdx->base[AMCC_OPREGS] + AMCC_MCSR);
			// shut off go signal for writes
			mcsr &= ~AMCC_BUSMASTERED_WRITE_ENABLE_MASK;
			WRITE_REGISTER_ULONG(pdx->base[AMCC_OPREGS] + AMCC_MCSR, mcsr);

			// shut off the hardware ints
			intCSR = READ_REGISTER_ULONG(pdx->base[AMCC_OPREGS] + AMCC_INTCSR);
			// clear the "write 1 clear" bits to avoid problems
			intCSR &= AMCC_PRESERVE_INTCSR_MASK;
			// shut off ints for writes
			intCSR &= ~AMCC_BUSMASTERED_WRITE_INT_ENABLE_MASK;
			// clear the write int bit
			intCSR |= AMCC_BUSMASTERED_WRITE_INT_OCCURRED_MASK;
			WRITE_REGISTER_ULONG(pdx->base[AMCC_OPREGS] + AMCC_INTCSR, intCSR);

			// set the internal state to inactive
			pdx->WriteTransfer.TransferInProgress = FALSE;

			// Conclude the previous "DMA" Transfer
			pdx->WriteTransfer.Adapter->DmaOperations->FlushAdapterBuffers(
				pdx->WriteTransfer.Adapter,
				pdx->WriteTransfer.Mdl,
				pdx->WriteTransfer.MapRegisterBase,
				pdx->WriteTransfer.LogicalAddress,
				pdx->WriteTransfer.CurrentTransferSize,
				TRUE);

			pdx->WriteTransfer.Adapter->DmaOperations->FreeMapRegisters(
				pdx->WriteTransfer.Adapter,
				pdx->WriteTransfer.MapRegisterBase,

⌨️ 快捷键说明

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