?? rs485nt.c
字號:
//
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(¶metersPath, 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(¶metersPath, path);
RtlAppendUnicodeToString(¶metersPath, 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 = ¬ThereDefault;
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 = ¬ThereDefault;
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 = ¬ThereDefault;
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 = ¬ThereDefault;
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 + -