📄 read_write.c
字号:
//
// Get set-up for the transfer
//
devExt->WriteMapRegBase = MapRegisterBase;
baseVa = MmGetMdlVirtualAddress(irp->MdlAddress);
devExt->WriteStartingOffset = devExt->WriteSoFar;
//
// Get the base address and length of the segment to write.
//
devExt->WritePaToDevice = IoMapTransfer(devExt->WriteAdapter,
irp->MdlAddress,
MapRegisterBase,
baseVa+(devExt->WriteSoFar),
&devExt->WriteLength,
TRUE); // WriteToDevice
//
// Update the length transfered so far
//
devExt->WriteSoFar += devExt->WriteLength;
//
// Put the request on the device
//
(VOID)KeSynchronizeExecution(devExt->InterruptObject,
OsrStartWriteOnDevice,
DeviceObject);
return(DeallocateObjectKeepRegisters);
}
///////////////////////////////////////////////////////////////////////////////
//
// OsrStartReadOnDevice
//
// This function performs all the actual hardware manipulation to initiate
// a new read request on the AMCC device. When called, all resources
// (mapping registers) have been allocated for the operation, and we have
// a base address and length of a buffer fragment to be DMA'ed.
//
// INPUTS:
//
// DeviceObject - Address of the DEVICE_OBJECT for our device.
//
// BaseAddress - Logical base address of the requestor's buffer fragment
// to be used as the base address of the transfer
//
// Length - Length in bytes of this fragment to be transfered.
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// None.
//
// IRQL:
//
// This routine is called at IRQL_DISPATCH_LEVEL.
//
// NOTES:
//
// When this routine is called, no other Read operations are in progress on
// the device.
//
///////////////////////////////////////////////////////////////////////////////
BOOLEAN
OsrStartReadOnDevice(IN PVOID SynchronizeContext)
{
ULONG temp;
PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT)SynchronizeContext;
PHYSICAL_ADDRESS baseAddress;
ULONG length;
POSR_DEVICE_EXT devExt = deviceObject->DeviceExtension;
baseAddress = devExt->ReadPaToDevice;
length = devExt->ReadLength;
#if DBG
DbgPrint("StartReadOnDev: Reading BA = 0x%0x, Length = %d.\n",
baseAddress.LowPart, length);
#endif
//
// Pass the device the Physical Base Address of the buffer
//
ASSERT(!baseAddress.HighPart);
WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MWAR_OFF,
baseAddress.LowPart);
//
// ...and the length of the read
//
WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MWTC_OFF, length);
//
// Tell the device to interrupt when the read is complete.
//
// NOTE: In this particular device, "read" operations from the
// device are called "WRITE" operations... since they write to
// MEMORY. Thus, we set the INT_ON_WRITE bit in the Interrupt
// CSR.
//
temp = READ_PORT_ULONG(devExt->AmccBaseRegisterAddress+ICSR_OFF);
#if DBG
DbgPrint("StartDmaRead: Current INTCSR State:\n");
OsrPrintIntcsr(temp);
#endif
temp &= ~AMCC_INT_ACK_BITS;
temp |= AMCC_INT_INT_ON_WRITE;
WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+ICSR_OFF, temp);
//
// Yeeeeha! Start the request by settting the "Write Enable"
// bit in the master CSR
//
temp = READ_PORT_ULONG(devExt->AmccBaseRegisterAddress+MCSR_OFF);
temp &= (AMCC_MCSR_READ_ENABLE |
AMCC_MCSR_READ_FIFO_MGMT |
AMCC_MCSR_READ_PRIORITY |
AMCC_MCSR_WRITE_ENABLE |
AMCC_MCSR_WRITE_FIFO_MGMT |
AMCC_MCSR_WRITE_PRIORITY);
temp |= AMCC_MCSR_WRITE_ENABLE;
WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MCSR_OFF, temp);
return(TRUE);
}
///////////////////////////////////////////////////////////////////////////////
//
// OsrStartWriteOnDevice
//
// This function performs all the actual hardware manipulation to initiate
// a new read request on the AMCC device. When called, all resources
// (mapping registers) have been allocated for the operation, and we have
// a base address and length of a buffer fragment to be DMA'ed.
//
// INPUTS:
//
// DeviceObject - Address of the DEVICE_OBJECT for our device.
//
// BaseAddress - Logical base address of the requestor's buffer fragment
// to be used as the base address of the transfer
//
// Length - Length in bytes of this fragment to be transfered.
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// None.
//
// IRQL:
//
// This routine is called at IRQL_DISPATCH_LEVEL.
//
// NOTES:
//
// When this routine is called, no other Write operations are in progress on
// the device.
//
///////////////////////////////////////////////////////////////////////////////
BOOLEAN
OsrStartWriteOnDevice(IN PVOID SynchronizeContext)
{
ULONG temp;
PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT)SynchronizeContext;
PHYSICAL_ADDRESS baseAddress;
ULONG length;
POSR_DEVICE_EXT devExt = deviceObject->DeviceExtension;
baseAddress = devExt->WritePaToDevice;
length = devExt->WriteLength;
#if DBG
DbgPrint("StartWriteOnDev: Writing BA = 0x%0x, Length = %d.\n",
baseAddress.LowPart, length);
#endif
//
// Pass the device the Physical Base Address of the buffer...
//
ASSERT(!baseAddress.HighPart);
WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MRAR_OFF,
baseAddress.LowPart);
//
// ...and the length of the write operation
//
WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MRTC_OFF, length);
//
// Request the device interrupt when the write operation is complete
//
temp = READ_PORT_ULONG(devExt->AmccBaseRegisterAddress+ICSR_OFF);
#if DBG
DbgPrint("StartWriteOnDev: Current INTCSR State:\n");
OsrPrintIntcsr(temp);
#endif
temp &= ~AMCC_INT_ACK_BITS;
temp |= AMCC_INT_INT_ON_READ;
WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+ICSR_OFF, temp);
//
// Yeeeeha! Start the request by setting the appropriate enable bit.
//
temp = READ_PORT_ULONG(devExt->AmccBaseRegisterAddress+MCSR_OFF);
temp &= (AMCC_MCSR_READ_ENABLE|
AMCC_MCSR_READ_FIFO_MGMT|
AMCC_MCSR_READ_PRIORITY|
AMCC_MCSR_WRITE_ENABLE|
AMCC_MCSR_WRITE_FIFO_MGMT|
AMCC_MCSR_WRITE_PRIORITY);
temp |= AMCC_MCSR_READ_ENABLE;
WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MCSR_OFF, temp);
return(TRUE);
}
///////////////////////////////////////////////////////////////////////////////
//
// OsrProcessQueuedRequests
//
// This interface checks the current state of the read and write
// queues, and starts requests on the device if either are not
// busy.
//
// INPUTS:
//
// devExt - Pointer to device extension of device to start
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// None.
//
// IRQL:
//
//
// NOTES:
//
///////////////////////////////////////////////////////////////////////////////
VOID OsrProcessQueuedRequests(IN OUT POSR_DEVICE_EXT devExt)
{
PVOID entry;
PIRP irp;
KIRQL oldIrql;
//
// See if there's something to start on the WRITE queue
//
KeAcquireSpinLock(&devExt->WriteQueueLock, &oldIrql);
while ( !devExt->CurrentWriteIrp &&
!IsListEmpty(&devExt->WriteQueue) ) {
entry = RemoveHeadList(&devExt->WriteQueue);
irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
#if DBG
DbgPrint("OsrProcessQueued: IRP removed from WRITE queue = 0x%0x\n",irp);
#endif
//
// If this IRP is cancelled, cancel it now, without
// initiating it on the device
//
if (irp->Cancel) {
#if DBG
DbgPrint("OsrProcessQueued: CANCEL flag set in READ IRP removed from queue 0x%0x\n",irp);
#endif
irp->IoStatus.Status = STATUS_CANCELLED;
irp->IoStatus.Information = 0;
//
// Complete the request now
//
IoCompleteRequest(irp, IO_NO_INCREMENT);
} else {
//
// Since we do not cancel in-progress requests
// on this device, we will reset the cancel
// routine in the IRP to NULL.
//
IoSetCancelRoutine(irp, NULL);
//
// Make this IRP the current write IRP, and
// start the request on the device. This routine
// sets devExt->CurrentWriteIrp
//
OsrStartWriteIrp(devExt->FunctionalDeviceObject, irp);
}
} // while (!devExt->CurrentWriteIrp &&
// !IsListEmpty(devExt->WriteQueue) )
//
// Drop the lock
//
KeReleaseSpinLock(&devExt->WriteQueueLock, oldIrql);
//
// See if there's something to start on the READ queue
//
KeAcquireSpinLock(&devExt->ReadQueueLock, &oldIrql);
while ( !devExt->CurrentReadIrp &&
!IsListEmpty(&devExt->ReadQueue) ) {
entry = RemoveHeadList(&devExt->ReadQueue);
irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
#if DBG
DbgPrint("OsrProcessQueued: IRP removed from READ queue = 0x%0x\n",irp);
#endif
//
// If this IRP is cancelled, cancel it now, without
// initiating it on the device
//
if (irp->Cancel) {
#if DBG
DbgPrint("OsrProcessQueued: CANCEL flag set in READ IRP removed from queue 0x%0x\n",irp);
#endif
irp->IoStatus.Status = STATUS_CANCELLED;
irp->IoStatus.Information = 0;
//
// Complete the request now
//
IoCompleteRequest(irp, IO_NO_INCREMENT);
} else {
//
// Since we do not cancel in-progress requests
// on this device, we will reset the cancel
// routine in the IRP to NULL.
//
IoSetCancelRoutine(irp, NULL);
//
// Make this IRP the current read IRP, and
// start the request on the device. This routine
// sets devExt->CurrentReadIrp
//
OsrStartReadIrp(devExt->FunctionalDeviceObject, irp);
}
} // while (!devExt->CurrentReadIrp &&
// !IsListEmpty(devExt->ReadQueue) )
//
// Drop the lock
//
KeReleaseSpinLock(&devExt->ReadQueueLock, oldIrql);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -