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@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@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@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@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@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@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@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]