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

📄 rs485nt.c

📁 RS485设备驱动源代码
💻 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 (&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.

⌨️ 快捷键说明

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