Start of the serial driver:
Handle write support and some IOCTL codes
First serial port is mapped to COM3 and second serial port is mapped to
COM4. This prevents conflicts with existing code.
Added: trunk/reactos/drivers/dd/serial/cleanup.c
Added: trunk/reactos/drivers/dd/serial/close.c
Added: trunk/reactos/drivers/dd/serial/create.c
Added: trunk/reactos/drivers/dd/serial/devctrl.c
Added: trunk/reactos/drivers/dd/serial/info.c
Modified: trunk/reactos/drivers/dd/serial/makefile
Added: trunk/reactos/drivers/dd/serial/misc.c
Added: trunk/reactos/drivers/dd/serial/pnp.c
Added: trunk/reactos/drivers/dd/serial/power.c
Added: trunk/reactos/drivers/dd/serial/rw.c
Modified: trunk/reactos/drivers/dd/serial/serial.c
Added: trunk/reactos/drivers/dd/serial/serial.h
_____
Added: trunk/reactos/drivers/dd/serial/cleanup.c
--- trunk/reactos/drivers/dd/serial/cleanup.c 2005-03-14 20:38:32 UTC
(rev 14073)
+++ trunk/reactos/drivers/dd/serial/cleanup.c 2005-03-14 20:59:50 UTC
(rev 14074)
@@ -0,0 +1,22 @@
+/* $Id:
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: drivers/dd/serial/cleanup.c
+ * PURPOSE: Serial IRP_MJ_CLEANUP operations
+ *
+ * PROGRAMMERS: HervÚ Poussineau (poussine(a)freesurf.fr)
+ */
+
+#define NDEBUG
+#include "serial.h"
+
+NTSTATUS STDCALL
+SerialCleanup(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ DPRINT("Serial: IRP_MJ_CLEANUP\n");
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_SUCCESS;
+}
_____
Added: trunk/reactos/drivers/dd/serial/close.c
--- trunk/reactos/drivers/dd/serial/close.c 2005-03-14 20:38:32 UTC
(rev 14073)
+++ trunk/reactos/drivers/dd/serial/close.c 2005-03-14 20:59:50 UTC
(rev 14074)
@@ -0,0 +1,22 @@
+/* $Id:
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: drivers/dd/serial/close.c
+ * PURPOSE: Serial IRP_MJ_CLOSE operations
+ *
+ * PROGRAMMERS: HervÚ Poussineau (poussine(a)freesurf.fr)
+ */
+
+#define NDEBUG
+#include "serial.h"
+
+NTSTATUS STDCALL
+SerialClose(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ DPRINT("Serial: IRP_MJ_CLOSE\n");
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_SUCCESS;
+}
_____
Added: trunk/reactos/drivers/dd/serial/create.c
--- trunk/reactos/drivers/dd/serial/create.c 2005-03-14 20:38:32 UTC
(rev 14073)
+++ trunk/reactos/drivers/dd/serial/create.c 2005-03-14 20:59:50 UTC
(rev 14074)
@@ -0,0 +1,52 @@
+/* $Id:
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: drivers/dd/serial/create.c
+ * PURPOSE: Serial IRP_MJ_CREATE operations
+ *
+ * PROGRAMMERS: HervÚ Poussineau (poussine(a)freesurf.fr)
+ */
+
+#define NDEBUG
+#include "serial.h"
+
+NTSTATUS STDCALL
+SerialCreate(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION Stack;
+ PFILE_OBJECT FileObject;
+ PSERIAL_DEVICE_EXTENSION DeviceExtension;
+ NTSTATUS Status;
+
+ DPRINT("Serial: IRP_MJ_CREATE\n");
+ Stack = IoGetCurrentIrpStackLocation(Irp);
+ FileObject = Stack->FileObject;
+ DeviceExtension =
(PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ if (Stack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
+ {
+ CHECKPOINT;
+ Status = STATUS_NOT_A_DIRECTORY;
+ goto ByeBye;
+ }
+
+ if (FileObject->FileName.Length != 0 ||
+ FileObject->RelatedFileObject != NULL)
+ {
+ CHECKPOINT;
+ Status = STATUS_ACCESS_DENIED;
+ goto ByeBye;
+ }
+
+ DPRINT("Serial: open COM%lu: successfull\n",
DeviceExtension->ComPort);
+ Status = STATUS_SUCCESS;
+
+ByeBye:
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+}
_____
Added: trunk/reactos/drivers/dd/serial/devctrl.c
--- trunk/reactos/drivers/dd/serial/devctrl.c 2005-03-14 20:38:32 UTC
(rev 14073)
+++ trunk/reactos/drivers/dd/serial/devctrl.c 2005-03-14 20:59:50 UTC
(rev 14074)
@@ -0,0 +1,551 @@
+/* $Id:
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: drivers/dd/serial/devctrl.c
+ * PURPOSE: Serial IRP_MJ_DEVICE_CONTROL operations
+ *
+ * PROGRAMMERS: HervÚ Poussineau (poussine(a)freesurf.fr)
+ */
+/* FIXME: call IoAcquireRemoveLock/IoReleaseRemoveLock around each I/O
operation */
+
+#define NDEBUG
+#include "serial.h"
+
+NTSTATUS STDCALL
+SerialSetBaudRate(
+ IN PSERIAL_DEVICE_EXTENSION DeviceExtension,
+ IN ULONG NewBaudRate)
+{
+ USHORT divisor;
+ PUCHAR ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ if (NewBaudRate & SERIAL_BAUD_USER)
+ {
+ divisor = (USHORT)(BAUD_CLOCK / (CLOCKS_PER_BIT *
(NewBaudRate & ~SERIAL_BAUD_USER)));
+ }
+ else
+ {
+ switch (NewBaudRate)
+ {
+ case SERIAL_BAUD_075: divisor = 0x600; break;
+ case SERIAL_BAUD_110: divisor = 0x400; break;
+ case SERIAL_BAUD_134_5: divisor = 0x360; break;
+ case SERIAL_BAUD_150: divisor = 0x300; break;
+ case SERIAL_BAUD_300: divisor = 0x180; break;
+ case SERIAL_BAUD_600: divisor = 0xc0; break;
+ case SERIAL_BAUD_1200: divisor = 0x60; break;
+ case SERIAL_BAUD_1800: divisor = 0x40; break;
+ case SERIAL_BAUD_2400: divisor = 0x30; break;
+ case SERIAL_BAUD_4800: divisor = 0x18; break;
+ case SERIAL_BAUD_7200: divisor = 0x10; break;
+ case SERIAL_BAUD_9600: divisor = 0xc; break;
+ case SERIAL_BAUD_14400: divisor = 0x8; break;
+ case SERIAL_BAUD_38400: divisor = 0x3; break;
+ case SERIAL_BAUD_57600: divisor = 0x2; break;
+ case SERIAL_BAUD_115200: divisor = 0x1; break;
+ case SERIAL_BAUD_56K: divisor = 0x2; break;
+ case SERIAL_BAUD_128K: divisor = 0x1; break;
+ default: Status = STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ Status =
IoAcquireRemoveLock(&DeviceExtension->RemoveLock,
(PVOID)DeviceExtension->ComPort);
+ if (NT_SUCCESS(Status))
+ {
+ UCHAR Lcr;
+ DPRINT("Serial: SerialSetBaudRate(COM%lu, %lu
Bauds)\n", DeviceExtension->ComPort, BAUD_CLOCK / (CLOCKS_PER_BIT *
divisor));
+ /* FIXME: update DeviceExtension->LowerDevice
when modifying LCR? */
+ /* Set Bit 7 of LCR to expose baud registers */
+ Lcr = READ_PORT_UCHAR(SER_LCR(ComPortBase));
+ Lcr |= SR_LCR_DLAB;
+ WRITE_PORT_UCHAR(SER_LCR(ComPortBase), Lcr);
+ /* Write the baud rate */
+ WRITE_PORT_UCHAR(SER_DLL(ComPortBase), divisor &
0xff);
+ WRITE_PORT_UCHAR(SER_DLM(ComPortBase), divisor
> 8);
+ /* Switch back to normal registers
*/
+ Lcr ^= SR_LCR_DLAB;
+ WRITE_PORT_UCHAR(SER_LCR(ComPortBase), Lcr);
+
+
IoReleaseRemoveLock(&DeviceExtension->RemoveLock,
(PVOID)DeviceExtension->ComPort);
+ }
+ }
+
+ if (NT_SUCCESS(Status))
+ DeviceExtension->BaudRate = NewBaudRate;
+ return Status;
+}
+
+NTSTATUS STDCALL
+SerialSetLineControl(
+ IN PSERIAL_DEVICE_EXTENSION DeviceExtension,
+ IN PSERIAL_LINE_CONTROL NewSettings)
+{
+ UCHAR Lcr = 0;
+ NTSTATUS Status;
+
+ DPRINT("Serial: SerialSetLineControl(COM%lu, Settings { %lu %lu
%lu })\n",
+ DeviceExtension->ComPort, NewSettings->StopBits,
NewSettings->Parity, NewSettings->WordLength);
+
+ /* Verify parameters */
+ switch (NewSettings->WordLength)
+ {
+ case 5: Lcr |= SR_LCR_CS5; break;
+ case 6: Lcr |= SR_LCR_CS6; break;
+ case 7: Lcr |= SR_LCR_CS7; break;
+ case 8: Lcr |= SR_LCR_CS8; break;
+ default: return STATUS_INVALID_PARAMETER;
+ }
+
+ if (NewSettings->WordLength < 5 || NewSettings->WordLength > 8)
+ return STATUS_INVALID_PARAMETER;
+
+ switch (NewSettings->Parity)
+ {
+ case NO_PARITY: Lcr |= SR_LCR_PNO; break;
+ case ODD_PARITY: Lcr |= SR_LCR_POD; break;
+ case EVEN_PARITY: Lcr |= SR_LCR_PEV; break;
+ case MARK_PARITY: Lcr |= SR_LCR_PMK; break;
+ case SPACE_PARITY: Lcr |= SR_LCR_PSP; break;
+ default: return STATUS_INVALID_PARAMETER;
+ }
+
+ switch (NewSettings->StopBits)
+ {
+ case STOP_BIT_1:
+ Lcr |= SR_LCR_ST1;
+ break;
+ case STOP_BITS_1_5:
+ if (NewSettings->WordLength != 5)
+ return STATUS_INVALID_PARAMETER;
+ Lcr |= SR_LCR_ST2;
+ break;
+ case STOP_BITS_2:
+ if (NewSettings->WordLength < 6 ||
NewSettings->WordLength > 8)
+ return STATUS_INVALID_PARAMETER;
+ Lcr |= SR_LCR_ST2;
+ break;
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Update current parameters */
+ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock,
(PVOID)DeviceExtension->ComPort);
+ if (!NT_SUCCESS(Status))
+ return Status;
+ WRITE_PORT_UCHAR(SER_LCR((PUCHAR)DeviceExtension->BaseAddress),
Lcr);
+ IoReleaseRemoveLock(&DeviceExtension->RemoveLock,
(PVOID)DeviceExtension->ComPort);
+
+ if (NT_SUCCESS(Status))
+ DeviceExtension->SerialLineControl = *NewSettings;
+
+ return Status;
+}
+
+NTSTATUS STDCALL
+SerialDeviceControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION Stack;
+ PSERIAL_DEVICE_EXTENSION DeviceExtension;
+ ULONG LengthIn, LengthOut;
+ ULONG Information = 0;
+ PUCHAR Buffer;
+ PUCHAR ComPortBase;
+ NTSTATUS Status;
+
+ DPRINT("Serial: IRP_MJ_DEVICE_CONTROL dispatch\n");
+
+ /* FIXME: pend operation if possible */
+
+ Stack = IoGetCurrentIrpStackLocation(Irp);
+ LengthIn = Stack->Parameters.DeviceIoControl.InputBufferLength;
+ LengthOut =
Stack->Parameters.DeviceIoControl.OutputBufferLength;
+ Buffer = Irp->AssociatedIrp.SystemBuffer;
+ DeviceExtension =
(PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
+
+ /* FIXME: need to probe buffers */
+ /* FIXME: see
http://www.osronline.com/ddkx/serial/serref_61bm.htm */
+ switch (Stack->Parameters.DeviceIoControl.IoControlCode)
+ {
+ case IOCTL_SERIAL_CLEAR_STATS:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_CLEAR_STATS not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_CLR_DTR:
+ {
+ DPRINT("Serial: IOCTL_SERIAL_CLR_DTR\n");
+ /* FIXME: If the handshake flow control of the
device is configured to
+ * automatically use DTR, return
STATUS_INVALID_PARAMETER */
+ DeviceExtension->MCR &= ~SR_MCR_DTR;
+ WRITE_PORT_UCHAR(SER_MCR(ComPortBase),
DeviceExtension->MCR);
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ case IOCTL_SERIAL_CLR_RTS:
+ {
+ DPRINT("Serial: IOCTL_SERIAL_CLR_RTS\n");
+ /* FIXME: If the handshake flow control of the
device is configured to
+ * automatically use RTS, return
STATUS_INVALID_PARAMETER */
+ DeviceExtension->MCR &= ~SR_MCR_RTS;
+ WRITE_PORT_UCHAR(SER_MCR(ComPortBase),
DeviceExtension->MCR);
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ case IOCTL_SERIAL_CONFIG_SIZE:
+ {
+ /* Obsolete on Microsoft Windows 2000+ */
+ PULONG pConfigSize;
+ DPRINT("Serial: IOCTL_SERIAL_CONFIG_SIZE\n");
+ if (LengthOut != sizeof(ULONG) || Buffer ==
NULL)
+ Status = STATUS_INVALID_PARAMETER;
+ else
+ {
+ pConfigSize = (PULONG)Buffer;
+ *pConfigSize = 0;
+ Status = STATUS_SUCCESS;
+ }
+ break;
+ }
+ case IOCTL_SERIAL_GET_BAUD_RATE:
+ {
+ DPRINT("Serial: IOCTL_SERIAL_GET_BAUD_RATE\n");
+ if (LengthOut < sizeof(SERIAL_BAUD_RATE))
+ Status = STATUS_BUFFER_TOO_SMALL;
+ else if (Buffer == NULL)
+ Status = STATUS_INVALID_PARAMETER;
+ else
+ {
+ ((PSERIAL_BAUD_RATE)Buffer)->BaudRate =
DeviceExtension->BaudRate;
+ Information = sizeof(SERIAL_BAUD_RATE);
+ Status = STATUS_SUCCESS;
+ }
+ }
+ case IOCTL_SERIAL_GET_CHARS:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_GET_CHARS not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_GET_COMMSTATUS:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_GET_COMMSTATUS not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_GET_DTRRTS:
+ {
+ PULONG pDtrRts;
+ DPRINT("Serial: IOCTL_SERIAL_GET_DTRRTS\n");
+ if (LengthOut != sizeof(ULONG) || Buffer ==
NULL)
+ Status = STATUS_INVALID_PARAMETER;
+ else
+ {
+ pDtrRts = (PULONG)Buffer;
+ *pDtrRts = 0;
+ if (DeviceExtension->MCR & SR_MCR_DTR)
+ *pDtrRts |= SERIAL_DTR_STATE;
+ if (DeviceExtension->MCR & SR_MCR_RTS)
+ *pDtrRts |= SERIAL_RTS_STATE;
+ Status = STATUS_SUCCESS;
+ }
+ break;
+ }
+ case IOCTL_SERIAL_GET_HANDFLOW:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_GET_HANDFLOW not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_GET_LINE_CONTROL:
+ {
+ DPRINT("Serial:
IOCTL_SERIAL_GET_LINE_CONTROL\n");
+ if (LengthOut < sizeof(SERIAL_LINE_CONTROL))
+ Status = STATUS_BUFFER_TOO_SMALL;
+ else if (Buffer == NULL)
+ Status = STATUS_INVALID_PARAMETER;
+ else
+ {
+ *((PSERIAL_LINE_CONTROL)Buffer) =
DeviceExtension->SerialLineControl;
+ Information =
sizeof(SERIAL_LINE_CONTROL);
+ Status = STATUS_SUCCESS;
+ }
+ break;
+ }
+ case IOCTL_SERIAL_GET_MODEM_CONTROL:
+ {
+ PULONG pMCR;
+ DPRINT("Serial:
IOCTL_SERIAL_GET_MODEM_CONTROL\n");
+ if (LengthOut != sizeof(ULONG) || Buffer ==
NULL)
+ Status = STATUS_INVALID_PARAMETER;
+ else
+ {
+ pMCR = (PULONG)Buffer;
+ *pMCR = DeviceExtension->MCR;
+ Status = STATUS_SUCCESS;
+ }
+ break;
+ }
+ case IOCTL_SERIAL_GET_MODEMSTATUS:
+ {
+ PULONG pMSR;
+ DPRINT("Serial:
IOCTL_SERIAL_GET_MODEMSTATUS\n");
+ if (LengthOut != sizeof(ULONG) || Buffer ==
NULL)
+ Status = STATUS_INVALID_PARAMETER;
+ else
+ {
+ pMSR = (PULONG)Buffer;
+ *pMSR = DeviceExtension->MSR;
+ Status = STATUS_SUCCESS;
+ }
+ break;
+ }
+ case IOCTL_SERIAL_GET_PROPERTIES:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_GET_PROPERTIES not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_GET_STATS:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_GET_STATS not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_GET_TIMEOUTS:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_GET_TIMEOUTS not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_GET_WAIT_MASK:
+ {
+ PULONG pWaitMask;
+ DPRINT("Serial: IOCTL_SERIAL_GET_WAIT_MASK\n");
+ if (LengthOut != sizeof(ULONG) || Buffer ==
NULL)
+ Status = STATUS_INVALID_PARAMETER;
+ else
+ {
+ pWaitMask = (PULONG)Buffer;
+ *pWaitMask = DeviceExtension->WaitMask;
+ Status = STATUS_SUCCESS;
+ }
+ break;
+ }
+ case IOCTL_SERIAL_IMMEDIATE_CHAR:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_IMMEDIATE_CHAR not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_LSRMST_INSERT:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_LSRMST_INSERT not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_PURGE:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_PURGE not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_RESET_DEVICE:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_RESET_DEVICE not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_SET_BAUD_RATE:
+ {
+ PULONG pNewBaudRate;
+ DPRINT("Serial: IOCTL_SERIAL_SET_BAUD_RATE\n");
+ if (LengthIn != sizeof(ULONG) || Buffer == NULL)
+ Status = STATUS_INVALID_PARAMETER;
+ else
+ {
+ pNewBaudRate = (PULONG)Buffer;
+ Status =
SerialSetBaudRate(DeviceExtension, *pNewBaudRate);
+ }
+ break;
+ }
+ case IOCTL_SERIAL_SET_BREAK_OFF:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_SET_BREAK_OFF not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_SET_BREAK_ON:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_SET_BREAK_ON not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_SET_CHARS:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_SET_CHARS not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_SET_DTR:
+ {
+ /* FIXME: If the handshake flow control of the
device is configured to
+ * automatically use DTR, return
STATUS_INVALID_PARAMETER */
+ DPRINT("Serial: IOCTL_SERIAL_SET_DTR\n");
+ if (!(DeviceExtension->MCR & SR_MCR_DTR))
+ {
+ DeviceExtension->MCR |= SR_MCR_DTR;
+ WRITE_PORT_UCHAR(SER_MCR(ComPortBase),
DeviceExtension->MCR);
+ }
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ case IOCTL_SERIAL_SET_FIFO_CONTROL:
+ {
+ DPRINT("Serial:
IOCTL_SERIAL_SET_FIFO_CONTROL\n");
+ if (LengthIn != sizeof(ULONG) || Buffer == NULL)
+ Status = STATUS_INVALID_PARAMETER;
+ else
+ {
+ WRITE_PORT_UCHAR(SER_FCR(ComPortBase),
(UCHAR)((*(PULONG)Buffer) & 0xff));
+ Status = STATUS_SUCCESS;
+ }
+ break;
+ }
+ case IOCTL_SERIAL_SET_HANDFLOW:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_SET_HANDFLOW not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_SET_LINE_CONTROL:
+ {
+ DPRINT("Serial:
IOCTL_SERIAL_SET_LINE_CONTROL\n");
+ if (LengthIn < sizeof(SERIAL_LINE_CONTROL))
+ Status = STATUS_BUFFER_TOO_SMALL;
+ else if (Buffer == NULL)
+ Status = STATUS_INVALID_PARAMETER;
+ else
+ Status =
SerialSetLineControl(DeviceExtension, (PSERIAL_LINE_CONTROL)Buffer);
+ break;
+ }
+ case IOCTL_SERIAL_SET_MODEM_CONTROL:
+ {
+ PULONG pMCR;
+ DPRINT("Serial:
IOCTL_SERIAL_SET_MODEM_CONTROL\n");
+ if (LengthIn != sizeof(ULONG) || Buffer == NULL)
+ Status = STATUS_INVALID_PARAMETER;
+ else
+ {
+ pMCR = (PULONG)Buffer;
+ DeviceExtension->MCR = (UCHAR)(*pMCR &
0xff);
+ WRITE_PORT_UCHAR(SER_MCR(ComPortBase),
DeviceExtension->MCR);
+ Status = STATUS_SUCCESS;
+ }
+ break;
+ }
+ case IOCTL_SERIAL_SET_QUEUE_SIZE:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_SET_QUEUE_SIZE not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_SET_RTS:
+ {
+ /* FIXME: If the handshake flow control of the
device is configured to
+ * automatically use DTR, return
STATUS_INVALID_PARAMETER */
+ DPRINT("Serial: IOCTL_SERIAL_SET_RTS\n");
+ if (!(DeviceExtension->MCR & SR_MCR_RTS))
+ {
+ DeviceExtension->MCR |= SR_MCR_RTS;
+ WRITE_PORT_UCHAR(SER_MCR(ComPortBase),
DeviceExtension->MCR);
+ }
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ case IOCTL_SERIAL_SET_TIMEOUTS:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_SET_TIMEOUTS not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_SET_WAIT_MASK:
+ {
+ PULONG pWaitMask;
+ DPRINT("Serial: IOCTL_SERIAL_SET_WAIT_MASK\n");
+ if (LengthIn != sizeof(ULONG) || Buffer == NULL)
+ Status = STATUS_INVALID_PARAMETER;
+ else
+ {
+ pWaitMask = (PULONG)Buffer;
+ DeviceExtension->WaitMask = *pWaitMask;
+ Status = STATUS_SUCCESS;
+ }
+ break;
+ }
+ case IOCTL_SERIAL_SET_XOFF:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_SET_XOFF not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_SET_XON:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_SET_XON not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_WAIT_ON_MASK:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_WAIT_ON_MASK not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ case IOCTL_SERIAL_XOFF_COUNTER:
+ {
+ /* FIXME */
+ DPRINT1("Serial: IOCTL_SERIAL_XOFF_COUNTER not
implemented.\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ default:
+ {
+ /* Pass Irp to lower driver */
+ DPRINT("Serial: Unknown IOCTL code 0x%x\n",
Stack->Parameters.DeviceIoControl.IoControlCode);
+ IoSkipCurrentIrpStackLocation(Irp);
+ return
IoCallDriver(DeviceExtension->LowerDevice, Irp);
+ }
+ }
+
+ Irp->IoStatus.Information = Information;
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+}
_____
Added: trunk/reactos/drivers/dd/serial/info.c
--- trunk/reactos/drivers/dd/serial/info.c 2005-03-14 20:38:32 UTC
(rev 14073)
+++ trunk/reactos/drivers/dd/serial/info.c 2005-03-14 20:59:50 UTC
(rev 14074)
@@ -0,0 +1,79 @@
+/* $Id:
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: drivers/dd/serial/info.c
+ * PURPOSE: Serial IRP_MJ_QUERY_INFORMATION operations
+ *
+ * PROGRAMMERS: HervÚ Poussineau (poussine(a)freesurf.fr)
+ */
+
+#define NDEBUG2
+#include "serial.h"
+
+NTSTATUS STDCALL
+SerialQueryInformation(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PSERIAL_DEVICE_EXTENSION DeviceExtension;
+ PIO_STACK_LOCATION Stack;
+ PVOID SystemBuffer;
+ ULONG BufferLength;
+ NTSTATUS Status;
+
+ DeviceExtension =
(PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ Stack = IoGetCurrentIrpStackLocation(Irp);
+ SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
+ BufferLength = Stack->Parameters.QueryFile.Length;
+
+ switch (Stack->Parameters.QueryFile.FileInformationClass)
+ {
+ case FileStandardInformation:
+ {
+ PFILE_STANDARD_INFORMATION StandardInfo =
(PFILE_STANDARD_INFORMATION)SystemBuffer;
+
+ DPRINT("Serial: IRP_MJ_QUERY_INFORMATION /
FileStandardInformation\n");
+ if (BufferLength <
sizeof(FILE_STANDARD_INFORMATION))
+ Status = STATUS_BUFFER_OVERFLOW;
+ else
+ {
+ StandardInfo->AllocationSize.QuadPart =
0;
+ StandardInfo->EndOfFile.QuadPart = 0;
+ StandardInfo->Directory = FALSE;
+ StandardInfo->NumberOfLinks = 0;
+ StandardInfo->DeletePending = FALSE; /*
FIXME: should be TRUE sometimes */
+ Status = STATUS_SUCCESS;
+ }
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ break;
+ }
+ case FilePositionInformation:
+ {
+ PFILE_POSITION_INFORMATION PositionInfo =
(PFILE_POSITION_INFORMATION)SystemBuffer;
+
+ DPRINT("Serial: IRP_MJ_QUERY_INFORMATION /
FilePositionInformation\n");
+ if (BufferLength <
sizeof(PFILE_POSITION_INFORMATION))
+ Status = STATUS_BUFFER_OVERFLOW;
+ else
+ {
+ PositionInfo->CurrentByteOffset.QuadPart
= 0;
+ Status = STATUS_SUCCESS;
+ }
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ break;
+ }
+ default:
+ {
+ DPRINT("Serial: IRP_MJ_QUERY_INFORMATION:
Unexpected file information class 0x%02x\n",
Stack->Parameters.QueryFile.FileInformationClass);
+ IoSkipCurrentIrpStackLocation(Irp);
+ Status =
IoCallDriver(DeviceExtension->LowerDevice, Irp);
+ }
+ }
+
+ return Status;
+}
_____
Modified: trunk/reactos/drivers/dd/serial/makefile
--- trunk/reactos/drivers/dd/serial/makefile 2005-03-14 20:38:32 UTC
(rev 14073)
+++ trunk/reactos/drivers/dd/serial/makefile 2005-03-14 20:59:50 UTC
(rev 14074)
@@ -6,7 +6,17 @@
TARGET_NAME = serial
-TARGET_OBJECTS = serial.o
+TARGET_OBJECTS = \
+ cleanup.o \
+ close.o \
+ create.o \
+ devctrl.o \
+ info.o \
+ misc.o \
+ pnp.o \
+ power.o \
+ rw.o \
+ serial.o
TARGET_CFLAGS = -Wall -Werror -D__USE_W32API
_____
Added: trunk/reactos/drivers/dd/serial/misc.c
--- trunk/reactos/drivers/dd/serial/misc.c 2005-03-14 20:38:32 UTC
(rev 14073)
+++ trunk/reactos/drivers/dd/serial/misc.c 2005-03-14 20:59:50 UTC
(rev 14074)
@@ -0,0 +1,175 @@
+/* $Id:
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: drivers/dd/serial/misc.c
+ * PURPOSE: Misceallenous operations
+ *
+ * PROGRAMMERS: HervÚ Poussineau (poussine(a)freesurf.fr)
+ */
+
+#define NDEBUG
+#include "serial.h"
+
+NTSTATUS
+ForwardIrpAndWaitCompletion(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context)
+{
+ if (Irp->PendingReturned)
+ KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS
+ForwardIrpAndWait(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PDEVICE_OBJECT LowerDevice =
((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
+ KEVENT Event;
+ NTSTATUS Status;
+
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+
+ DPRINT("Serial: Calling lower device %p [%wZ]\n", LowerDevice,
&LowerDevice->DriverObject->DriverName);
+ IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event,
TRUE, TRUE, TRUE);
+
+ Status = IoCallDriver(LowerDevice, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ Status = KeWaitForSingleObject(&Event, Suspended,
KernelMode, FALSE, NULL);
+ if (NT_SUCCESS(Status))
+ Status = Irp->IoStatus.Status;
+ }
+
+ return Status;
+}
+
+BOOLEAN STDCALL
+SerialInterruptService(
+ IN PKINTERRUPT Interrupt,
+ IN OUT PVOID ServiceContext)
+{
+ PDEVICE_OBJECT DeviceObject;
+ PSERIAL_DEVICE_EXTENSION DeviceExtension;
+ PUCHAR ComPortBase;
+ UCHAR Iir;
+
+ DeviceObject = (PDEVICE_OBJECT)ServiceContext;
+ DeviceExtension =
(PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
+
+ DPRINT1("Serial: Maybe our interrupt?\n"); /* FIXME */
+
+ Iir = READ_PORT_UCHAR(SER_IIR(ComPortBase));
+#if 0
+ if (Iir == 0xff)
+ return TRUE;
+ CHECKPOINT1;
+ Iir &= SR_IIR_ID_MASK;
+ if (!(Iir & SR_IIR_SELF)) { return FALSE; }
+ CHECKPOINT1;
+#else
+ Iir &= SR_IIR_ID_MASK;
+ Iir |= SR_IIR_SELF;
+#endif
+ DPRINT1("Serial: Iir = 0x%x\n", Iir);
+
+ switch (Iir)
+ {
+ case SR_IIR_MSR_CHANGE:
+ {
+ DPRINT1("Serial: SR_IIR_MSR_CHANGE\n");
+ DeviceExtension->MSR =
READ_PORT_UCHAR(SER_MSR(ComPortBase));
+ /* FIXME: what to do? */
+ //return KeInsertQueueDpc (&Self->MsrChangeDpc,
Self, 0);
+ //return TRUE;
+ break;
+ }
+ case SR_IIR_THR_EMPTY:
+ {
+ DPRINT1("Serial: SR_IIR_THR_EMPTY\n");
+ break;
+ /*if (!Self->WaitingSendBytes.Empty() &&
+ (READ_PORT_UCHAR( Self->Port + UART_LSR ) &
LSR_THR_EMPTY) )
+ WRITE_PORT_UCHAR( Self->Port + UART_THR,
+ Self->WaitingSendBytes.PopFront() );
+ return KeInsertQueueDpc( &Self->TransmitDpc,
Self, 0 );*/
+ }
+ case SR_IIR_DATA_RECEIVED:
+ {
+ DPRINT1("Serial: SR_IIR_DATA_RECEIVED\n");
+ if (READ_PORT_UCHAR(SER_LSR(ComPortBase)) &
SR_LSR_DR)
+ {
+ DPRINT1("Serial: Byte received: 0x%x\n",
READ_PORT_UCHAR(SER_RBR(ComPortBase)));
+ return TRUE;
+ }
+ break;
+ /*if( READ_PORT_UCHAR( Self->Port + UART_LSR ) &
LSR_DATA_RECEIVED )
+ Self->WaitingReadBytes.PushBack
+ ( READ_PORT_UCHAR( Self->Port + UART_RDR
) );
+ return KeInsertQueueDpc( &Self->DataInDpc, Self,
0 );*/
+ }
+ case SR_IIR_ERROR:
+ {
+ DPRINT1("Serial: SR_IIR_ERROR\n");
+ break;
+ /*Error = READ_PORT_UCHAR( Self->Port + UART_LSR
);
+ if( Error & LSR_OVERRUN )
+ Self->WaitingReadBytes.PushBack(
SerialFifo::OVERRUN );
+ if( Error & LSR_PARITY_ERROR )
+ Self->WaitingReadBytes.PushBack(
SerialFifo::PARITY );
+ if( Error & LSR_FRAMING_ERROR )
+ Self->WaitingReadBytes.PushBack(
SerialFifo::FRAMING );
+ if( Error & LSR_BREAK )
+ Self->WaitingReadBytes.PushBack(
SerialFifo::BREAK );
+ if( Error & LSR_TIMEOUT )
+ Self->WaitingReadBytes.PushBack(
SerialFifo::TIMEOUT );
+ return KeInsertQueueDpc( &Self->DataInDpc, Self,
0 );*/
+ }
+ }
+ return FALSE;
+#if 0
+ InterruptId = READ_PORT_UCHAR(SER_IIR(ComPortBase)) &
SR_IIR_IID;
+ DPRINT1("Serial: Interrupt catched: id = %x\n",
InterruptId);
+ /* FIXME: sometimes, update DeviceExtension->IER */
+ /* FIXME: sometimes, update DeviceExtension->MCR */
+ /* FIXME: sometimes, update DeviceExtension->MSR */
+ switch (InterruptId)
+ {
+ case 3 << 1:
+ {
+ /* line status changed */
+ DPRINT("Serial: Line status changed\n");
+ break;
+ }
+ case 2 << 1:
+ {
+ /* data available */
+ UCHAR ReceivedByte =
READ_PORT_UCHAR(ComPortBase);
+ DPRINT("Serial: Data available\n");
+ DPRINT1("Serial: received %d\n",
ReceivedByte);
+ //Buffer[Information++] = ReceivedByte;
+ }
+ case 1 << 1:
+ {
+ /* transmit register empty */
+ DPRINT("Serial: Transmit register
empty\n");
+ }
+ case 0 << 1:
+ {
+ /* modem status change */
+ UCHAR ReceivedByte =
READ_PORT_UCHAR(SER_MSR(ComPortBase));
+ DPRINT("Serial: Modem status change\n");
+ DPRINT1("Serial: new status = 0x%02x\n",
ReceivedByte);
+ }
+ }
+ return TRUE;
+ }
+ else
+ return FALSE;
+#endif
+}
_____
Added: trunk/reactos/drivers/dd/serial/pnp.c
--- trunk/reactos/drivers/dd/serial/pnp.c 2005-03-14 20:38:32 UTC
(rev 14073)
+++ trunk/reactos/drivers/dd/serial/pnp.c 2005-03-14 20:59:50 UTC
(rev 14074)
@@ -0,0 +1,275 @@
+/* $Id:
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: drivers/dd/serial/pnp.c
+ * PURPOSE: Serial IRP_MJ_PNP operations
+ *
+ * PROGRAMMERS: HervÚ Poussineau (poussine(a)freesurf.fr)
+ */
+/* FIXME: call IoAcquireRemoveLock/IoReleaseRemoveLock around each I/O
operation */
+
+#define NDEBUG
+#include "serial.h"
+
+NTSTATUS STDCALL
+SerialAddDevice(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT Pdo)
+{
+ PDEVICE_OBJECT Fdo;
+ PSERIAL_DEVICE_EXTENSION DeviceExtension;
+ NTSTATUS Status;
+ WCHAR DeviceNameBuffer[32];
+ UNICODE_STRING DeviceName;
+ static ULONG DeviceNumber = 0;
+
+ DPRINT("Serial: SerialAddDevice called\n");
+
+ /* Create new device object */
+ swprintf(DeviceNameBuffer, L"\\Device\\Serial%lu",
DeviceNumber);
+ RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
+ Status = IoCreateDevice(DriverObject,
+ sizeof(SERIAL_DEVICE_EXTENSION),
+ &DeviceName,
+ FILE_DEVICE_SERIAL_PORT,
+ FILE_DEVICE_SECURE_OPEN,
+ FALSE,
+ &Fdo);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Serial: IoCreateDevice() failed with status
0x%08x\n", Status);
[truncated at 1000 lines; 773 more skipped]