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

📄 rs485nt.c

📁 RS485设备驱动源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    //

    parameters = ExAllocatePool(PagedPool,
                     sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne);

    if (!parameters) {
        RS_DbgPrint("RS485NT: ExAllocatePool failed for Rtl in GetConfiguration\n");
        status = STATUS_UNSUCCESSFUL;
    } else {

        RtlZeroMemory(parameters, sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne);

        //
        // Form a path to this driver's Parameters subkey.
        //

        RtlInitUnicodeString(&parametersPath, NULL);

        parametersPath.MaximumLength = RegistryPath->Length + sizeof(L"\\Parameters");

        parametersPath.Buffer = ExAllocatePool(PagedPool, parametersPath.MaximumLength);

        if (!parametersPath.Buffer) {
            RS_DbgPrint("RS485NT: ExAllocatePool failed for Path in GetConfiguration\n");
            status = STATUS_UNSUCCESSFUL;
        }
    }

    if (NT_SUCCESS(status)) {

        //
        // Form the parameters path.
        //

        RtlZeroMemory(parametersPath.Buffer, parametersPath.MaximumLength);
        RtlAppendUnicodeToString(&parametersPath, path);
        RtlAppendUnicodeToString(&parametersPath, L"\\Parameters");

        //
        // Gather all of the "user specified" information from
        // the registry.
        //

        parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
        parameters[0].Name = L"Port Address";
        parameters[0].EntryContext =  &PortAddressDefault;
        parameters[0].DefaultType = REG_DWORD;
        parameters[0].DefaultData = &notThereDefault;
        parameters[0].DefaultLength = sizeof(ULONG);

        parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
        parameters[1].Name = L"IRQ Line";
        parameters[1].EntryContext = &IRQLineDefault;
        parameters[1].DefaultType = REG_DWORD;
        parameters[1].DefaultData = &notThereDefault;
        parameters[1].DefaultLength = sizeof(ULONG);

        parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
        parameters[2].Name = L"Baud Rate";
        parameters[2].EntryContext = &BaudRateDefault;
        parameters[2].DefaultType = REG_DWORD;
        parameters[2].DefaultData = &notThereDefault;
        parameters[2].DefaultLength = sizeof(ULONG);

        parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
        parameters[3].Name = L"Buffer Size";
        parameters[3].EntryContext = &BufferSizeDefault;
        parameters[3].DefaultType = REG_DWORD;
        parameters[3].DefaultData = &notThereDefault;
        parameters[3].DefaultLength = sizeof(ULONG);

        status = RtlQueryRegistryValues(
                     RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
                     parametersPath.Buffer,
                     parameters,
                     NULL,
                     NULL);

        if (!NT_SUCCESS(status)) {
            RS_DbgPrint("RS485NT: RtlQueryRegistryValues failed\n");
        }

        status = STATUS_SUCCESS;
    }

    //
    // Go ahead and assign driver defaults.
    //

    if (PortAddressDefault == notThereDefault) {
        DeviceExtension->PortAddress = (PUCHAR) DEF_PORT_ADDRESS;
    } else {
        DeviceExtension->PortAddress = (PVOID) PortAddressDefault;
    }

    if (IRQLineDefault == notThereDefault) {
        DeviceExtension->IRQLine = DEF_IRQ_LINE;
    } else {
        DeviceExtension->IRQLine = (KIRQL) IRQLineDefault;
    }

    if (BaudRateDefault == notThereDefault) {
        DeviceExtension->BaudRate = DEF_BAUD_RATE;
    } else {
        DeviceExtension->BaudRate = BaudRateDefault;
    }

    if (BufferSizeDefault == notThereDefault) {
        DeviceExtension->BufferSize = DEF_BUFFER_SIZE;
    } else {
        DeviceExtension->BufferSize = BufferSizeDefault;
    }

    //
    // Free the allocated memory before returning.
    //

    if (parametersPath.Buffer)
        ExFreePool(parametersPath.Buffer);
    if (parameters)
        ExFreePool(parameters);
    return (status);
}


//---------------------------------------------------------------------------
// Initialize_RS485
//
// Description:
//  Initializes all data structures and hardware necessary for
//  driver execution
//
// Arguments:
//      DeviceExtension - Pointer to the device extension.
//
// Return Value:
//      NSTATUS
//  
NTSTATUS Initialize_RS485 (IN PRS485NT_DEVICE_EXTENSION DeviceExtension)
{
    UCHAR       ch, Divisor;
    NTSTATUS    status = STATUS_SUCCESS;

    //
    // Initialize all of the 8250 register addresses
    //

    DeviceExtension->ComPort.RBR = DeviceExtension->PortAddress + RX_REGISTER_8250;
    DeviceExtension->ComPort.TBR = DeviceExtension->PortAddress + TX_REGISTER_8250;
    DeviceExtension->ComPort.IER = DeviceExtension->PortAddress + IER_8250;
    DeviceExtension->ComPort.IIR = DeviceExtension->PortAddress + IIR_8250;
    DeviceExtension->ComPort.LCR = DeviceExtension->PortAddress + LCR_8250;
    DeviceExtension->ComPort.MCR = DeviceExtension->PortAddress + MCR_8250;
    DeviceExtension->ComPort.LSR = DeviceExtension->PortAddress + LSR_8250;
    DeviceExtension->ComPort.MSR = DeviceExtension->PortAddress + MSR_8250;
    DeviceExtension->ComPort.BAUD = DeviceExtension->PortAddress + DIVISOR_REGISTER_8250;

    //
    // Initialize any Events
    //

    KeInitializeEvent (&DeviceExtension->XmitDone, SynchronizationEvent, FALSE);

    //
    // Allocate memory for the Transmit and Receive data buffers
    //

    DeviceExtension->RcvBuffer = ExAllocatePool(NonPagedPool, DeviceExtension->BufferSize);

    if (DeviceExtension->RcvBuffer == NULL) {
        RS_DbgPrint("RS485NT: ExAllocatePool failed for RcvBuffer\n");
        status = STATUS_INSUFFICIENT_RESOURCES;
    } else {

        //
        // Setup buffer pointers and counts
        //

        DeviceExtension->RcvBufferPosition = DeviceExtension->RcvBuffer;
        DeviceExtension->RcvBufferEnd = DeviceExtension->RcvBuffer + 
                                        (DeviceExtension->BufferSize - 1);
        DeviceExtension->RcvBufferCount = 0;

    }

    if (NT_SUCCESS(status)) {
        DeviceExtension->XmitBuffer = ExAllocatePool(NonPagedPool, DeviceExtension->BufferSize);
        if (DeviceExtension->RcvBuffer == NULL) {
            RS_DbgPrint("RS485NT: ExAllocatePool failed for XmitBuffer\n");
            status = STATUS_INSUFFICIENT_RESOURCES;
        } else {

            //
            // Setup buffer pointers and counts
            //
            DeviceExtension->XmitBufferPosition = DeviceExtension->XmitBuffer;
            DeviceExtension->XmitBufferEnd = DeviceExtension->XmitBuffer + 
                                            (DeviceExtension->BufferSize - 1);
            DeviceExtension->XmitBufferCount = 0;
        }
    }

    //
    // Clear the interrupt/error Count and get current system time

    DeviceExtension->InterruptCount = 0;
    DeviceExtension->RcvError = 0;
    KeQuerySystemTime (&DeviceExtension->LastQuerySystemTime);

    //
    // Determine the UART divisor value
    //

    switch (DeviceExtension->BaudRate) {
        case 1200:
            Divisor = BAUD_RATE_DIVISOR_1200;
            break;
        case 2400:
            Divisor = BAUD_RATE_DIVISOR_2400;
            break;
        case 4800:
            Divisor = BAUD_RATE_DIVISOR_4800;
            break;
        case 9600:
            Divisor = BAUD_RATE_DIVISOR_9600;
            break;
        case 19200:
            Divisor = BAUD_RATE_DIVISOR_19200;
            break;
        case 38400:
            Divisor = BAUD_RATE_DIVISOR_38400;
            break;
        case 57600:
            Divisor = BAUD_RATE_DIVISOR_57600;
            break;
        case 115200:
            Divisor = BAUD_RATE_DIVISOR_115200;
            break;
        default:
            Divisor = BAUD_RATE_DIVISOR_19200;
            break;
    }

    //
    // Set the baud rate to the divisor value.
    //

    ch = ((READ_PORT_UCHAR (DeviceExtension->ComPort.LCR)) | LCR_ENABLE_DIVISOR_LATCH);
    WRITE_PORT_UCHAR (DeviceExtension->ComPort.LCR, ch);

    ch = READ_PORT_UCHAR (DeviceExtension->ComPort.LCR);
    WRITE_PORT_UCHAR (DeviceExtension->ComPort.BAUD, Divisor);

    ch = ((READ_PORT_UCHAR (DeviceExtension->ComPort.LCR)) & LCR_DISABLE_DIVISOR_LATCH);
    WRITE_PORT_UCHAR (DeviceExtension->ComPort.LCR, ch);

    //
    // The data format = 1 start bit, 8 data bits, 1 stop bit, no parity.
    //

    ch = (LCR_EIGHT_BITS_PER_WORD | LCR_ONE_STOP_BIT | LCR_NO_PARITY);
    WRITE_PORT_UCHAR (DeviceExtension->ComPort.LCR, ch);

    //
    // Enable all UART interrupts on the IBM PC by asserting the GP02 general
    // purpose output. Clear all other MCR bits. Activate DTR for RS485 use.
    //

    ch = MCR_ACTIVATE_GP02 | MCR_ACTIVATE_DTR;
    WRITE_PORT_UCHAR (DeviceExtension->ComPort.MCR, ch);

    //
    // Enable Specific Interrupts
    //

    ch = (IER_ENABLE_RX_DATA_READY_IRQ | IER_ENABLE_TX_BE_IRQ | IER_ENABLE_RX_ERROR_IRQ);
    WRITE_PORT_UCHAR (DeviceExtension->ComPort.IER, ch);

    return status;
}


//---------------------------------------------------------------------------
// RS485_Write 
//
// Description:
//  Called by DispatchRoutine in response to a Write request.
//
// Arguments:
//      DeviceExtension - The device extension strtucture
//      Irp             - The Irp associated with this IO
//
// Return Value:
//      NTSTATUS
//
NTSTATUS RS485_Write (IN PRS485NT_DEVICE_EXTENSION  DeviceExtension, IN PIRP Irp)
{
    ULONG   Length;
    UCHAR   ch;

    Length = IoGetCurrentIrpStackLocation(Irp)->Parameters.Write.Length;
    Irp->IoStatus.Information = 0L;

    //
    // Check for a zero length write.
    //

    if (Length) {

        if (Length >= DeviceExtension->BufferSize) {

            //
            // Not enough room in the buffer
            //

            Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
        } else {

            //
            // Clear the Transmit complete event
            //

            KeClearEvent (&DeviceExtension->XmitDone);

            //
            // Copy the buffer into the DeviceExtension
            //

            RtlMoveMemory (DeviceExtension->XmitBuffer, 
                           Irp->AssociatedIrp.SystemBuffer, Length);

            DeviceExtension->XmitBufferCount = Length;
            DeviceExtension->XmitBufferPosition = DeviceExtension->XmitBuffer;

            //
            // Assert RTS
            //

            ch = READ_PORT_UCHAR (DeviceExtension->ComPort.MCR) | MCR_ACTIVATE_RTS;
            WRITE_PORT_UCHAR (DeviceExtension->ComPort.MCR, ch);

            //
            // Kick start the UART by jamming one byte out
            //

            WRITE_PORT_UCHAR (DeviceExtension->ComPort.TBR, 
                              *DeviceExtension->XmitBufferPosition);

            DeviceExtension->XmitBufferPosition++;
            DeviceExtension->XmitBufferCount--;

            //
            // Wait for the complete buffer to be sent
            //
            RS_DbgPrint ("RS485NT: Write KeWaitForSingleObject\n");
            KeWaitForSingleObject (&DeviceExtension->XmitDone, Executive, 
                                   FALSE, KernelMode, NULL);

            //
            // Set the number of bytes written
            //

            Irp->IoStatus.Information = Length;
        }

    } else {
        //
        // Nothing to write, so return SUCCESS (and do nothing!)
        //
        Irp->IoStatus.Status = STATUS_SUCCESS;
    }

    return STATUS_SUCCESS;
}


//---------------------------------------------------------------------------
// RS485_Read
//
// Description:
//  Called by DispatchRoutine in response to a Read request.
//
// Arguments:
//      DeviceExtension - The device extension strtucture
//      Irp             - The Irp associated with this IO
//
// Return Value:
//      NTSTATUS
//
NTSTATUS RS485_Read (IN PRS485NT_DEVICE_EXTENSION  DeviceExtension, IN PIRP Irp)
{
    ULONG   Length;
    KIRQL   OldIrql;
    
    Length = IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length;
    Irp->IoStatus.Information = 0L;

    //
    // Check for a zero length read.
    //

    if (Length) {

        //
        // Read in the minimum amount (User buffer or Device Extension buffer)
        //

        if (Length > DeviceExtension->RcvBufferCount) {
            Length = DeviceExtension->RcvBufferCount;
        }

        //
        // Synchronize - LOCK
        //

        KeRaiseIrql ((KIRQL)(DeviceExtension->Irql+1), &OldIrql);

        //
        // Copy the buffer from the DeviceExtension
        //
        RtlMoveMemory (Irp->AssociatedIrp.SystemBuffer, 
                       DeviceExtension->RcvBuffer, Length);

        //
        // Clear the Rcv buffer info
        //

        DeviceExtension->RcvBufferCount = 0;
        DeviceExtension->RcvBufferPosition = DeviceExtension->RcvBuffer;

        //
        // Synchronize - UNLOCK
        //

        KeLowerIrql (OldIrql);

        //
        // Set the number of bytes actually read
        //

        Irp->IoStatus.Information = Length;

    } else {
        //
        // Nothing to read, so return SUCCESS (and do nothing!)
        //
        Irp->IoStatus.Status = STATUS_SUCCESS;
    }

    return STATUS_SUCCESS;
}

⌨️ 快捷键说明

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