📄 readwrite.cpp
字号:
// Reset signals to the S5933 itself don't need to be written back as zero. The
// add-on function reset flag must, however, be cleared. Delay a short period of
// time to allow the reset to occur, then write back a zero to the add-on reset bit
LARGE_INTEGER timeout;
timeout.QuadPart = -10 * 10000; // i.e., 10 milliseconds
KeDelayExecutionThread(KernelMode, FALSE, &timeout);
WRITE_PORT_ULONG((PULONG) (pdx->portbase + MCSR), 0);
// Clear any pending interrupts by writing 1's to any that are currently asserted
ULONG intcsr = READ_PORT_ULONG((PULONG) (pdx->portbase + INTCSR));
intcsr &= INTCSR_INTERRUPT_MASK;
WRITE_PORT_ULONG((PULONG) (pdx->portbase + INTCSR), intcsr);
} // ResetDevice
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
VOID SetupDevice(PDEVICE_EXTENSION pdx)
{ // SetupDevice
} // SetupDevice
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
NTSTATUS StartDevice(PDEVICE_OBJECT fdo, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PARTIAL_RESOURCE_LIST translated)
{ // StartDevice
NTSTATUS status;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
// Identify the I/O resources we're supposed to use.
ULONG vector;
KIRQL irql;
KINTERRUPT_MODE mode;
KAFFINITY affinity;
BOOLEAN irqshare;
BOOLEAN gotinterrupt = FALSE;
PHYSICAL_ADDRESS portbase;
BOOLEAN gotport = FALSE;
if (!translated)
return STATUS_DEVICE_CONFIGURATION_ERROR; // no resources assigned??
PCM_PARTIAL_RESOURCE_DESCRIPTOR resource = translated->PartialDescriptors;
ULONG nres = translated->Count;
for (ULONG i = 0; i < nres; ++i, ++resource)
{ // for each resource
switch (resource->Type)
{ // switch on resource type
case CmResourceTypePort:
portbase = resource->u.Port.Start;
pdx->nports = resource->u.Port.Length;
pdx->mappedport = (resource->Flags & CM_RESOURCE_PORT_IO) == 0;
gotport = TRUE;
break;
case CmResourceTypeInterrupt:
irql = (KIRQL) resource->u.Interrupt.Level;
vector = resource->u.Interrupt.Vector;
affinity = resource->u.Interrupt.Affinity;
mode = (resource->Flags == CM_RESOURCE_INTERRUPT_LATCHED)
? Latched : LevelSensitive;
irqshare = resource->ShareDisposition == CmResourceShareShared;
gotinterrupt = TRUE;
break;
default:
KdPrint((DRIVERNAME " - Unexpected I/O resource type %d\n", resource->Type));
break;
} // switch on resource type
} // for each resource
if (!(TRUE
&& gotport
&& gotinterrupt
))
{
KdPrint((DRIVERNAME " - Didn't get expected I/O resources\n"));
return STATUS_DEVICE_CONFIGURATION_ERROR;
}
// Determine bus type before proceeding, just so we don't have a bunch of cleanup
// to do if this call fails
INTERFACE_TYPE bustype;
ULONG junk;
status = IoGetDeviceProperty(pdx->Pdo, DevicePropertyLegacyBusType, sizeof(bustype),
&bustype, &junk);
if (!NT_SUCCESS(status))
{
KdPrint((DRIVERNAME " - IoGetDeviceProperty failed - %X\n", status));
return status;
}
if (pdx->mappedport)
{ // map port address for RISC platform
pdx->portbase = (PUCHAR) MmMapIoSpace(portbase, pdx->nports, MmNonCached);
if (!pdx->mappedport)
{
KdPrint((DRIVERNAME " - Unable to map port range %I64X, length %X\n", portbase, pdx->nports));
return STATUS_INSUFFICIENT_RESOURCES;
}
} // map port address for RISC platform
else
pdx->portbase = (PUCHAR) portbase.QuadPart;
// Configure a DMA adapter object
DEVICE_DESCRIPTION dd;
RtlZeroMemory(&dd, sizeof(dd));
dd.Version = DEVICE_DESCRIPTION_VERSION;
dd.InterfaceType = bustype;
dd.MaximumLength = 0x1000;
dd.Dma32BitAddresses = TRUE;
dd.Master = TRUE;
pdx->AdapterObject = IoGetDmaAdapter(pdx->Pdo, &dd, &pdx->nMapRegisters);
if (!pdx->AdapterObject)
{ // can't create adapter object
KdPrint((DRIVERNAME " - Unable to create DMA adapter object\n"));
if (pdx->portbase && pdx->mappedport)
MmUnmapIoSpace(pdx->portbase, pdx->nports);
pdx->portbase = NULL;
return STATUS_UNSUCCESSFUL;
} // can't create adapter object
ResetDevice(pdx); // reset the device
status = IoConnectInterrupt(&pdx->InterruptObject, (PKSERVICE_ROUTINE) OnInterrupt,
(PVOID) pdx, NULL, vector, irql, irql, mode, irqshare, affinity, FALSE);
if (!NT_SUCCESS(status))
{
KdPrint((DRIVERNAME " - IoConnectInterrupt failed - %X\n", status));
if (pdx->portbase && pdx->mappedport)
MmUnmapIoSpace(pdx->portbase, pdx->nports);
pdx->portbase = NULL;
if (pdx->AdapterObject)
(*pdx->AdapterObject->DmaOperations->PutDmaAdapter)
(pdx->AdapterObject);
pdx->AdapterObject = NULL;
return status;
}
// Initialize the device
KeSynchronizeExecution(pdx->InterruptObject, (PKSYNCHRONIZE_ROUTINE) SetupDevice, pdx);
return STATUS_SUCCESS;
} // StartDevice
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
VOID StartIo(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // StartIo
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);
if (!NT_SUCCESS(status))
{
CompleteRequest(Irp, status, 0);
return;
}
PMDL mdl = Irp->MdlAddress;
pdx->numxfer = 0;
pdx->xfer = pdx->nbytes = MmGetMdlByteCount(mdl);
pdx->vaddr = MmGetMdlVirtualAddress(mdl);
ULONG nregs = ADDRESS_AND_SIZE_TO_SPAN_PAGES(pdx->vaddr, pdx->nbytes);
if (nregs > pdx->nMapRegisters)
{ // staged transfer needed
nregs = pdx->nMapRegisters;
pdx->xfer = nregs * PAGE_SIZE - MmGetMdlByteOffset(mdl);
} // staged transfer needed
pdx->nMapRegistersAllocated = nregs; // save for deallocation later
status = (*pdx->AdapterObject->DmaOperations->AllocateAdapterChannel)
(pdx->AdapterObject, fdo, nregs, (PDRIVER_CONTROL) AdapterControl, pdx);
if (!NT_SUCCESS(status))
{
KdPrint((DRIVERNAME " - AllocateAdapterChannel failed - %X\n", status));
StartNextPacket(&pdx->dqReadWrite, fdo);
CompleteRequest(Irp, status, 0);
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
}
} // StartIo
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
VOID StartTransfer(PDEVICE_EXTENSION pdx, PHYSICAL_ADDRESS address, BOOLEAN isread)
{ // StartTransfer
ULONG mcsr = READ_PORT_ULONG((PULONG) (pdx->portbase + MCSR));
ULONG intcsr = READ_PORT_ULONG((PULONG) (pdx->portbase + INTCSR));
// Setup read or write transfer registers. Note that the S5933 calls a transfer
// from memory to the device a "read"
if (isread)
{ // read from device
mcsr |= MCSR_WRITE_NEED4 | MCSR_WRITE_ENABLE;
intcsr |= INTCSR_WTCI_ENABLE;
WRITE_PORT_ULONG((PULONG) (pdx->portbase + MWTC), pdx->xfer);
WRITE_PORT_ULONG((PULONG) (pdx->portbase + MWAR), address.LowPart);
} // read from device
else
{ // write to device
mcsr |= MCSR_READ_NEED4 | MCSR_READ_ENABLE;
intcsr |= INTCSR_RTCI_ENABLE;
WRITE_PORT_ULONG((PULONG) (pdx->portbase + MRTC), pdx->xfer);
WRITE_PORT_ULONG((PULONG) (pdx->portbase + MRAR), address.LowPart);
} // write to device
// Write modified INTCSR to enable the appropriate interrupt and MCSR to actually
// start the transfer
pdx->busy = TRUE;
WRITE_PORT_ULONG((PULONG) (pdx->portbase + INTCSR), intcsr);
WRITE_PORT_ULONG((PULONG) (pdx->portbase + MCSR), mcsr);
} // StartTransfer
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
VOID StopDevice(IN PDEVICE_OBJECT fdo, BOOLEAN oktouch /* = FALSE */)
{ // StopDevice
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
if (pdx->InterruptObject)
{ // disconnect interrupt
if (oktouch)
ResetDevice(pdx);
IoDisconnectInterrupt(pdx->InterruptObject);
pdx->InterruptObject = NULL;
} // disconnect interrupt
if (pdx->portbase && pdx->mappedport)
MmUnmapIoSpace(pdx->portbase, pdx->nports);
pdx->portbase = NULL;
if (pdx->AdapterObject)
(*pdx->AdapterObject->DmaOperations->PutDmaAdapter)
(pdx->AdapterObject);
pdx->AdapterObject = NULL;
} // StopDevice
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -