?? rs485nt.c
字號:
ch = READ_PORT_UCHAR (DeviceExtension->ComPort.MSR);
break;
default:
break;
}
ch = READ_PORT_UCHAR (DeviceExtension->ComPort.IIR); // Read the IIR again for the next loop
}
//
// Return TRUE to signify this was our interrupt and we serviced it.
//
return TRUE;
}
//---------------------------------------------------------------------------
// RS485_Dpc_Routine
//
// Description:
// This DPC for ISR is issued by RS485_Isr to complete Transmit processing
// by setting the XmitDone event.
//
// Arguments:
// Dpc - not used
// DeviceObject - Pointer to the Device object
// Irp - not used
// Context - not used
//
// Return Value:
// none
//
VOID RS485_Dpc_Routine (IN PKDPC Dpc, IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp, IN PVOID Context)
{
PRS485NT_DEVICE_EXTENSION DeviceExtension;
DeviceExtension = DeviceObject->DeviceExtension;
//
// Set the Xmit Done event
//
KeSetEvent (&DeviceExtension->XmitDone, 0, FALSE);
RS_DbgPrint ("RS485NT: Dpc Routine KeSetEvent\n");
return;
}
//---------------------------------------------------------------------------
// ReportUsage
//
// Description:
// This routine registers (reports) the I/O and IRQ usage for this driver.
//
// Arguments:
// DriverObject - Pointer to the driver object
// DeviceObject - Pointer to the Device object
// PortAddress - Address of I/O port used
// ConflictDetected - TRUE if a resource conflict was detected.
//
// Return Value:
// TRUE - If a Resource conflict was detected
// FALSE - If no conflict was detected
//
BOOLEAN ReportUsage(IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT DeviceObject,
IN PHYSICAL_ADDRESS PortAddress,
IN BOOLEAN *ConflictDetected)
{
PRS485NT_DEVICE_EXTENSION extension;
ULONG sizeOfResourceList;
PCM_RESOURCE_LIST resourceList;
PCM_FULL_RESOURCE_DESCRIPTOR nextFrd;
PCM_PARTIAL_RESOURCE_DESCRIPTOR partial;
extension = (PRS485NT_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
//
// The size of the resource list is going to be one full descriptor
// which already has one partial descriptor included, plus another
// partial descriptor. One partial descriptor will be for the
// interrupt, and the other for the port addresses.
//
sizeOfResourceList = sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
//
// The full resource descriptor already contains one
// partial. Make room for one more.
//
// It will hold the irq "prd", and the port "prd".
// ("prd" = partial resource descriptor)
//
sizeOfResourceList += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
//
// Now we increment the length of the resource list by field offset
// of the first frd. This will give us the length of what preceeds
// the first frd in the resource list.
// (frd = full resource descriptor)
//
sizeOfResourceList += FIELD_OFFSET(CM_RESOURCE_LIST, List[0]);
resourceList = ExAllocatePool(PagedPool, sizeOfResourceList);
if (!resourceList) {
return FALSE;
}
//
// Zero out the list
//
RtlZeroMemory(resourceList, sizeOfResourceList);
resourceList->Count = 1;
nextFrd = &resourceList->List[0];
nextFrd->InterfaceType = Isa;
nextFrd->BusNumber = 0;
//
// We are going to report port addresses and interrupt
//
nextFrd->PartialResourceList.Count = 2;
//
// Now fill in the port data. We don't wish to share
// this port range with anyone.
//
// Note: the port address we pass in is the one we got
// back from HalTranslateBusAddress.
//
partial = &nextFrd->PartialResourceList.PartialDescriptors[0];
partial->Type = CmResourceTypePort;
partial->ShareDisposition = CmResourceShareDriverExclusive;
partial->Flags = CM_RESOURCE_PORT_IO;
partial->u.Port.Start = PortAddress;
partial->u.Port.Length = DEF_PORT_RANGE;
partial++;
//
// Now fill in the irq stuff.
//
// Note: for IoReportResourceUsage, the Interrupt.Level and
// Interrupt.Vector are bus-specific level and vector, just
// as we passed in to HalGetInterruptVector, not the mapped
// system vector we got back from HalGetInterruptVector.
//
partial->Type = CmResourceTypeInterrupt;
partial->u.Interrupt.Level = extension->IRQLine;
partial->u.Interrupt.Vector = extension->IRQLine;
partial->ShareDisposition = CmResourceShareDriverExclusive;
partial->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
IoReportResourceUsage(
NULL,
DriverObject,
resourceList,
sizeOfResourceList,
NULL,
NULL,
0,
FALSE,
ConflictDetected);
//
// The above routine sets the BOOLEAN parameter ConflictDetected
// to TRUE if a conflict was detected.
//
ExFreePool(resourceList);
return (*ConflictDetected);
}
//---------------------------------------------------------------------------
//
//
// Routine Description:
//
// Process the IRPs sent to this device.
//
// Arguments:
//
// DeviceObject - pointer to a device object
//
// Irp - pointer to an I/O Request Packet
//
// Return Value:
//
//
NTSTATUS DispatchRoutine (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION irpStack;
PRS485NT_DEVICE_EXTENSION deviceExtension;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG ioControlCode;
NTSTATUS ntStatus;
LARGE_INTEGER CurrentSystemTime;
LARGE_INTEGER ElapsedTime;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
irpStack = IoGetCurrentIrpStackLocation (Irp);
//
// Get a pointer to the device extension
//
deviceExtension = DeviceObject->DeviceExtension;
//
// Get the pointer to the input/output buffer and it's length
//
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
switch (irpStack->MajorFunction) {
case IRP_MJ_CREATE:
{
RS_DbgPrint ("RS485NT: IRP_MJ_CREATE\n");
break;
}
case IRP_MJ_CLOSE:
{
RS_DbgPrint ("RS485NT: IRP_MJ_CLOSE\n");
break;
}
case IRP_MJ_READ:
{
RS_DbgPrint ("RS485NT: IRP_MJ_READ\n");
RS485_Read (deviceExtension, Irp);
break;
}
case IRP_MJ_WRITE:
{
RS_DbgPrint ("RS485NT: IRP_MJ_WRITE\n");
RS485_Write (deviceExtension, Irp);
break;
}
case IRP_MJ_DEVICE_CONTROL:
{
RS_DbgPrint ("RS485NT: IRP_MJ_DEVICE_CONTROL - ");
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (ioControlCode)
{
case IOCTL_RS485NT_HELLO:
{
RS_DbgPrint ("HELLO\n");
//
// Some app is saying hello
//
break;
}
case IOCTL_RS485NT_GET_RCV_COUNT:
{
RS_DbgPrint ("GET_RCV_COUNT\n");
if (outputBufferLength >= 4) {
//
// Return the current receive buffer count
//
*(ULONG *)ioBuffer = deviceExtension->RcvBufferCount;
Irp->IoStatus.Information = 4;
}
break;
}
case IOCTL_RS485NT_LAST_RCVD_TIME:
{
RS_DbgPrint ("LAST_RCVD_TIME\n");
if (outputBufferLength >= 8) {
//
// Get the current system time and convert to Milliseconds
//
KeQuerySystemTime (&CurrentSystemTime);
ElapsedTime.QuadPart = CurrentSystemTime.QuadPart -
deviceExtension->LastQuerySystemTime.QuadPart;
ElapsedTime.QuadPart /= 10000;
RtlMoveMemory (ioBuffer, &ElapsedTime, 8);
Irp->IoStatus.Information = 8;
}
break;
}
default:
{
RS_DbgPrint ("RS485NT: Unknown IRP_MJ_DEVICE_CONTROL\n");
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
break;
}
}
break;
}
default:
{
RS_DbgPrint ("RS485NT: Unhandled IRP_MJ function\n");
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
break;
}
}
//
// DON'T get cute and try to use the status field of
// the irp in the return status. That IRP IS GONE as
// soon as you call IoCompleteRequest.
//
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
RS_DbgPrint ("RS485NT: DisptachRoutine exit.\n");
//
// We never have pending operation so always return the status code.
//
return ntStatus;
}
//---------------------------------------------------------------------------
// UnloadDriver
//
// Description:
// Free all the allocated resources, etc.
//
// Arguments:
// DriverObject - pointer to a driver object
//
// Return Value:
// None
//
VOID UnloadDriver (IN PDRIVER_OBJECT DriverObject)
{
WCHAR deviceLinkBuffer[] = L"\\DosDevices\\RS485NT";
UNICODE_STRING deviceLinkUnicodeString;
PRS485NT_DEVICE_EXTENSION extension;
extension = DriverObject->DeviceObject->DeviceExtension;
//
// Deactivate all of the MCR interrupt sources.
//
WRITE_PORT_UCHAR (extension->ComPort.MCR, MCR_DEACTIVATE_ALL);
//
// Free any resources
//
IoDisconnectInterrupt (extension->InterruptObject);
//
// Delete the symbolic link
//
RtlInitUnicodeString (&deviceLinkUnicodeString, deviceLinkBuffer);
IoDeleteSymbolicLink (&deviceLinkUnicodeString);
//
// Delete the device object
//
IoDeleteDevice (DriverObject->DeviceObject);
RS_DbgPrint ("RS485NT: Unloaded\n");
return;
}
//---------------------------------------------------------------------------
// GetConfiguration
//
// Description:
// Obtains driver configuration information from the Registry.
//
// Arguments:
// DeviceExtension - Pointer to the device extension.
// RegistryPath - Pointer to the null-terminated Unicode name of the
// registry path for this driver.
//
// Return Value:
// NTSTATUS
//
NTSTATUS GetConfiguration(IN PRS485NT_DEVICE_EXTENSION DeviceExtension,
IN PUNICODE_STRING RegistryPath)
{
PRTL_QUERY_REGISTRY_TABLE parameters = NULL;
UNICODE_STRING parametersPath;
ULONG notThereDefault = 1234567;
ULONG PortAddressDefault;
ULONG IRQLineDefault;
ULONG BaudRateDefault;
ULONG BufferSizeDefault;
NTSTATUS status = STATUS_SUCCESS;
PWSTR path = NULL;
USHORT queriesPlusOne = 5;
parametersPath.Buffer = NULL;
//
// Registry path is already null-terminated, so just use it.
//
path = RegistryPath->Buffer;
//
// Allocate the Rtl query table.
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -