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

📄 4.c

📁 基于80C196KC微处理器的高速串行通讯、单片机将FIFO中的数据读取出来后
💻 C
📖 第 1 页 / 共 3 页
字号:
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 (&amt;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 = &amt;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 = &amt;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 (&amt;CurrentSystemTime); 
ElapsedTime.QuadPart = CurrentSystemTime.QuadPart - 
deviceExtension->LastQuerySystemTime.QuadPart; 
ElapsedTime.QuadPart /= 10000; 

RtlMoveMemory (ioBuffer, &amt;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 (&amt;deviceLinkUnicodeString, deviceLinkBuffer); 

IoDeleteSymbolicLink (&amt;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. 
// 

⌨️ 快捷键说明

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