Implement legacy detection (it should be able to detect the first two serial ports)
Implement reading by polling (expect lots of bugs!)
Use receive and send queues
Better handling of some IRPs
Lots of small bugs fixes
Added: trunk/reactos/drivers/dd/serial/circularbuffer.c
Modified: trunk/reactos/drivers/dd/serial/cleanup.c
Modified: trunk/reactos/drivers/dd/serial/devctrl.c
Modified: trunk/reactos/drivers/dd/serial/info.c
Added: trunk/reactos/drivers/dd/serial/legacy.c
Modified: trunk/reactos/drivers/dd/serial/makefile
Modified: trunk/reactos/drivers/dd/serial/misc.c
Modified: trunk/reactos/drivers/dd/serial/pnp.c
Modified: trunk/reactos/drivers/dd/serial/power.c
Modified: trunk/reactos/drivers/dd/serial/rw.c
Modified: trunk/reactos/drivers/dd/serial/serial.c
Modified: trunk/reactos/drivers/dd/serial/serial.h

Added: trunk/reactos/drivers/dd/serial/circularbuffer.c
--- trunk/reactos/drivers/dd/serial/circularbuffer.c	2005-03-18 13:52:21 UTC (rev 14176)
+++ trunk/reactos/drivers/dd/serial/circularbuffer.c	2005-03-18 16:01:35 UTC (rev 14177)
@@ -0,0 +1,67 @@
+/* $Id:
+ * 
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            drivers/dd/serial/circularbuffer.c
+ * PURPOSE:         Operations on a circular buffer
+ * 
+ * PROGRAMMERS:     HervÚ Poussineau (poussine@freesurf.fr)
+ */
+
+//#define NDEBUG
+#include "serial.h"
+
+NTSTATUS
+InitializeCircularBuffer(
+	IN PCIRCULAR_BUFFER pBuffer,
+	IN ULONG BufferSize)
+{
+	pBuffer->Buffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize * sizeof(UCHAR), SERIAL_TAG);
+	if (!pBuffer->Buffer)
+		return STATUS_INSUFFICIENT_RESOURCES;
+	pBuffer->Length = BufferSize;
+	pBuffer->ReadPosition = pBuffer->WritePosition = 0;
+	return STATUS_SUCCESS;
+}
+
+NTSTATUS
+FreeCircularBuffer(
+	IN PCIRCULAR_BUFFER pBuffer)
+{
+	ExFreePoolWithTag(pBuffer->Buffer, SERIAL_TAG);
+	return STATUS_SUCCESS;
+}
+
+BOOLEAN
+IsCircularBufferEmpty(
+	IN PCIRCULAR_BUFFER pBuffer)
+{
+	return (pBuffer->ReadPosition == pBuffer->WritePosition);
+}
+
+NTSTATUS
+PushCircularBufferEntry(
+	IN PCIRCULAR_BUFFER pBuffer,
+	IN UCHAR Entry)
+{
+	ASSERT(pBuffer->Length);
+	ULONG NextPosition = (pBuffer->WritePosition + 1) % pBuffer->Length;
+	if (NextPosition == pBuffer->ReadPosition)
+		return STATUS_BUFFER_TOO_SMALL;
+	pBuffer->Buffer[pBuffer->WritePosition] = Entry;
+	pBuffer->WritePosition = NextPosition;
+	return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PopCircularBufferEntry(
+	IN PCIRCULAR_BUFFER pBuffer,
+	OUT PUCHAR Entry)
+{
+	ASSERT(pBuffer->Length);
+	if (IsCircularBufferEmpty(pBuffer))
+		return STATUS_ARRAY_BOUNDS_EXCEEDED;
+	*Entry = pBuffer->Buffer[pBuffer->ReadPosition];
+	pBuffer->ReadPosition = (pBuffer->ReadPosition + 1) % pBuffer->Length;
+	return STATUS_SUCCESS;
+}

Modified: trunk/reactos/drivers/dd/serial/cleanup.c
--- trunk/reactos/drivers/dd/serial/cleanup.c	2005-03-18 13:52:21 UTC (rev 14176)
+++ trunk/reactos/drivers/dd/serial/cleanup.c	2005-03-18 16:01:35 UTC (rev 14177)
@@ -17,6 +17,8 @@
 	IN PIRP Irp)
 {
 	DPRINT("Serial: IRP_MJ_CLEANUP\n");
+	Irp->IoStatus.Information = 0;
+	Irp->IoStatus.Status = STATUS_SUCCESS;
 	IoCompleteRequest(Irp, IO_NO_INCREMENT);
 	return STATUS_SUCCESS;
 }

Modified: trunk/reactos/drivers/dd/serial/devctrl.c
--- trunk/reactos/drivers/dd/serial/devctrl.c	2005-03-18 13:52:21 UTC (rev 14176)
+++ trunk/reactos/drivers/dd/serial/devctrl.c	2005-03-18 16:01:35 UTC (rev 14177)
@@ -19,34 +19,36 @@
 {
 	USHORT divisor;
 	PUCHAR ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
+	ULONG BaudRate;
 	NTSTATUS Status = STATUS_SUCCESS;
 	
 	if (NewBaudRate & SERIAL_BAUD_USER)
 	{
-		divisor = (USHORT)(BAUD_CLOCK / (CLOCKS_PER_BIT * (NewBaudRate & ~SERIAL_BAUD_USER)));
+		BaudRate = NewBaudRate & ~SERIAL_BAUD_USER;
+		divisor = (USHORT)(BAUD_CLOCK / (CLOCKS_PER_BIT * BaudRate));
 	}
 	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;
+			case SERIAL_BAUD_075:    divisor = 0x600; BaudRate = 75; break;
+			case SERIAL_BAUD_110:    divisor = 0x400; BaudRate = 110; break;
+			case SERIAL_BAUD_134_5:  divisor = 0x360; BaudRate = 134; break;
+			case SERIAL_BAUD_150:    divisor = 0x300; BaudRate = 150; break;
+			case SERIAL_BAUD_300:    divisor = 0x180; BaudRate = 300; break;
+			case SERIAL_BAUD_600:    divisor = 0xc0;  BaudRate = 600; break;
+			case SERIAL_BAUD_1200:   divisor = 0x60;  BaudRate = 1200; break;
+			case SERIAL_BAUD_1800:   divisor = 0x40;  BaudRate = 1800; break;
+			case SERIAL_BAUD_2400:   divisor = 0x30;  BaudRate = 2400; break;
+			case SERIAL_BAUD_4800:   divisor = 0x18;  BaudRate = 4800; break;
+			case SERIAL_BAUD_7200:   divisor = 0x10;  BaudRate = 7200; break;
+			case SERIAL_BAUD_9600:   divisor = 0xc;   BaudRate = 9600; break;
+			case SERIAL_BAUD_14400:  divisor = 0x8;   BaudRate = 14400; break;
+			case SERIAL_BAUD_38400:  divisor = 0x3;   BaudRate = 38400; break;
+			case SERIAL_BAUD_57600:  divisor = 0x2;   BaudRate = 57600; break;
+			case SERIAL_BAUD_115200: divisor = 0x1;   BaudRate = 115200; break;
+			case SERIAL_BAUD_56K:    divisor = 0x2;   BaudRate = 57600; break;
+			case SERIAL_BAUD_128K:   divisor = 0x1;   BaudRate = 115200; break;
 			default: Status = STATUS_INVALID_PARAMETER;
 		}
 	}
@@ -57,7 +59,7 @@
 		if (NT_SUCCESS(Status))
 		{
 			UCHAR Lcr;
-			DPRINT("Serial: SerialSetBaudRate(COM%lu, %lu Bauds)\n", DeviceExtension->ComPort, BAUD_CLOCK / (CLOCKS_PER_BIT * divisor));
+			DPRINT("Serial: SerialSetBaudRate(COM%lu, %lu Bauds)\n", DeviceExtension->ComPort, BaudRate);
 			/* FIXME: update DeviceExtension->LowerDevice when modifying LCR? */
 			/* Set Bit 7 of LCR to expose baud registers */
 			Lcr = READ_PORT_UCHAR(SER_LCR(ComPortBase));
@@ -84,6 +86,7 @@
 	IN PSERIAL_DEVICE_EXTENSION DeviceExtension,
 	IN PSERIAL_LINE_CONTROL NewSettings)
 {
+	PUCHAR ComPortBase;
 	UCHAR Lcr = 0;
 	NTSTATUS Status;
 	
@@ -133,10 +136,14 @@
 	}
 	
 	/* Update current parameters */
+	ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
 	Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
 	if (!NT_SUCCESS(Status))
 		return Status;
-	WRITE_PORT_UCHAR(SER_LCR((PUCHAR)DeviceExtension->BaseAddress), Lcr);
+	WRITE_PORT_UCHAR(SER_LCR(ComPortBase), Lcr);
+	
+	/* Read junk out of RBR */
+	READ_PORT_UCHAR(SER_RBR(ComPortBase));
 	IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
 	
 	if (NT_SUCCESS(Status))
@@ -145,7 +152,7 @@
 	return Status;
 }
 
-BOOL
+BOOLEAN
 SerialClearPerfStats(
 	IN PSERIALPERF_STATS pSerialPerfStats)
 {
@@ -153,7 +160,7 @@
 	return TRUE;
 }
 
-BOOL
+BOOLEAN
 SerialGetPerfStats(IN PIRP pIrp)
 {
 	PSERIAL_DEVICE_EXTENSION pDeviceExtension;
@@ -349,7 +356,7 @@
 		}
 		case IOCTL_SERIAL_GET_STATS:
 		{
-			DPRINT1("Serial: IOCTL_SERIAL_GET_STATS\n");
+			DPRINT("Serial: IOCTL_SERIAL_GET_STATS\n");
 			if (LengthOut < sizeof(SERIALPERF_STATS))
 			{
 				DPRINT("Serial: return STATUS_BUFFER_TOO_SMALL\n");
@@ -364,16 +371,21 @@
 			{
 				KeSynchronizeExecution(DeviceExtension->Interrupt,
 					(PKSYNCHRONIZE_ROUTINE)SerialGetPerfStats, Irp);
-					Status = STATUS_SUCCESS;
-					Information = sizeof(SERIALPERF_STATS);
+				Status = STATUS_SUCCESS;
+				Information = sizeof(SERIALPERF_STATS);
 			}
 			break;
 		}
 		case IOCTL_SERIAL_GET_TIMEOUTS:
 		{
-			/* FIXME */
-			DPRINT1("Serial: IOCTL_SERIAL_GET_TIMEOUTS not implemented.\n");
-			Status = STATUS_NOT_IMPLEMENTED;
+			DPRINT("Serial: IOCTL_SERIAL_GET_TIMEOUTS\n");
+			if (LengthOut != sizeof(SERIAL_TIMEOUTS) || Buffer == NULL)
+				Status = STATUS_INVALID_PARAMETER;
+			else
+			{
+				*(PSERIAL_TIMEOUTS)Buffer = DeviceExtension->SerialTimeOuts;
+				Status = STATUS_SUCCESS;
+			}
 			break;
 		}
 		case IOCTL_SERIAL_GET_WAIT_MASK:
@@ -532,9 +544,14 @@
 		}
 		case IOCTL_SERIAL_SET_TIMEOUTS:
 		{
-			/* FIXME */
-			DPRINT1("Serial: IOCTL_SERIAL_SET_TIMEOUTS not implemented.\n");
-			Status = STATUS_NOT_IMPLEMENTED;
+			DPRINT("Serial: IOCTL_SERIAL_SET_TIMEOUTS\n");
+			if (LengthIn != sizeof(SERIAL_TIMEOUTS) || Buffer == NULL)
+				Status = STATUS_INVALID_PARAMETER;
+			else
+			{
+				DeviceExtension->SerialTimeOuts = *(PSERIAL_TIMEOUTS)Buffer;
+				Status = STATUS_SUCCESS;
+			}
 			break;
 		}
 		case IOCTL_SERIAL_SET_WAIT_MASK:

Modified: trunk/reactos/drivers/dd/serial/info.c
--- trunk/reactos/drivers/dd/serial/info.c	2005-03-18 13:52:21 UTC (rev 14176)
+++ trunk/reactos/drivers/dd/serial/info.c	2005-03-18 16:01:35 UTC (rev 14177)
@@ -20,6 +20,7 @@
 	PIO_STACK_LOCATION Stack;
 	PVOID SystemBuffer;
 	ULONG BufferLength;
+	ULONG Information = 0;
 	NTSTATUS Status;
 	
 	DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
@@ -45,9 +46,6 @@
   				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:
@@ -62,18 +60,17 @@
 				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 ForwardIrpAndForget(DeviceObject, Irp);
 		}
 	}
 	
+	Irp->IoStatus.Information = Information;
+	Irp->IoStatus.Status = Status;
+	IoCompleteRequest(Irp, IO_NO_INCREMENT);
 	return Status;
 }

Added: trunk/reactos/drivers/dd/serial/legacy.c
--- trunk/reactos/drivers/dd/serial/legacy.c	2005-03-18 13:52:21 UTC (rev 14176)
+++ trunk/reactos/drivers/dd/serial/legacy.c	2005-03-18 16:01:35 UTC (rev 14177)
@@ -0,0 +1,162 @@
+/* $Id:
+ * 
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            drivers/bus/serial/legacy.c
+ * PURPOSE:         Legacy serial port enumeration
+ * 
+ * PROGRAMMERS:     HervÚ Poussineau (poussine@freesurf.fr)
+ */
+
+#define NDEBUG
+#include "serial.h"
+
+static BOOLEAN
+SerialDoesPortExist(PUCHAR BaseAddress)
+{
+	BOOLEAN Found;
+	BYTE Mcr;
+	BYTE Msr;
+	
+	Found = FALSE;
+	
+	/* save Modem Control Register (MCR) */
+	Mcr = READ_PORT_UCHAR(SER_MCR(BaseAddress));
+	
+	/* enable loop mode (set Bit 4 of the MCR) */
+	WRITE_PORT_UCHAR(SER_MCR(BaseAddress), 0x10);
+	
+	/* clear all modem output bits */
+	WRITE_PORT_UCHAR(SER_MCR(BaseAddress), 0x10);
+	
+	/* read the Modem Status Register */
+	Msr = READ_PORT_UCHAR(SER_MSR(BaseAddress));
+	
+	/*
+	 * the upper nibble of the MSR (modem output bits) must be
+	 * equal to the lower nibble of the MCR (modem input bits)
+	 */
+	if ((Msr & 0xf0) == 0x00)
+	{
+		/* set all modem output bits */
+		WRITE_PORT_UCHAR(SER_MCR(BaseAddress), 0x1f);
+		
+		/* read the Modem Status Register */
+		Msr = READ_PORT_UCHAR(SER_MSR(BaseAddress));
+		
+		/*
+		 * the upper nibble of the MSR (modem output bits) must be
+		 * equal to the lower nibble of the MCR (modem input bits)
+		 */
+		if ((Msr & 0xf0) == 0xf0)
+		{
+			/*
+			 * setup a resonable state for the port:
+			 * enable fifo and clear recieve/transmit buffers
+			 */
+			WRITE_PORT_UCHAR(SER_FCR(BaseAddress),
+				(SR_FCR_ENABLE_FIFO | SR_FCR_CLEAR_RCVR | SR_FCR_CLEAR_XMIT));
+			WRITE_PORT_UCHAR(SER_FCR(BaseAddress), 0);
+			READ_PORT_UCHAR(SER_RBR(BaseAddress));
+			WRITE_PORT_UCHAR(SER_IER(BaseAddress), 0);
+			Found = TRUE;
+		}
+	}
+	
+	/* restore MCR */
+	WRITE_PORT_UCHAR(SER_MCR(BaseAddress), Mcr);
+	
+	return Found;
+}
+
+NTSTATUS
+DetectLegacyDevice(
+	IN PDRIVER_OBJECT DriverObject,
+	IN ULONG ComPortBase,
+	IN ULONG Irq)
+{
+	ULONG ResourceListSize;
+	PCM_RESOURCE_LIST ResourceList;
+	BOOLEAN ConflictDetected, FoundPort;
+	NTSTATUS Status;
+	
+	/* Create resource list */
+	ResourceListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
+	ResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(NonPagedPool, ResourceListSize, SERIAL_TAG);
+	if (!ResourceList)
+		return STATUS_INSUFFICIENT_RESOURCES;
+	ResourceList->Count = 1;
+	ResourceList->List[0].InterfaceType = Isa;
+	ResourceList->List[0].BusNumber = -1; /* FIXME */
+	ResourceList->List[0].PartialResourceList.Version = 1;
+	ResourceList->List[0].PartialResourceList.Revision = 1;
+	ResourceList->List[0].PartialResourceList.Count = 2;
+	ResourceList->List[0].PartialResourceList.PartialDescriptors[0].Type = CmResourceTypePort;
+	ResourceList->List[0].PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareDriverExclusive;
+	ResourceList->List[0].PartialResourceList.PartialDescriptors[0].Flags = CM_RESOURCE_PORT_IO;
+	// FIXME ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Start = ComPortBase;
+	ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Length = 8;
+	
+	ResourceList->List[0].PartialResourceList.PartialDescriptors[1].Type = CmResourceTypeInterrupt;
+	ResourceList->List[0].PartialResourceList.PartialDescriptors[1].ShareDisposition = CmResourceShareDriverExclusive;
+	ResourceList->List[0].PartialResourceList.PartialDescriptors[1].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+	/* FIXME: ResourceList->List[0].PartialResourceList.PartialDescriptors[1].u.Interrupt.Level = ;
+	ResourceList->List[0].PartialResourceList.PartialDescriptors[1].u.Interrupt.Vector = ;
+	ResourceList->List[0].PartialResourceList.PartialDescriptors[1].u.Interrupt.Affinity = ;*/
+	
+	/* Report resource list */
+	Status = IoReportResourceForDetection(
+		DriverObject, ResourceList, ResourceListSize,
+		NULL, NULL, 0,
+		&ConflictDetected);
+	if (ConflictDetected)
+		return STATUS_DEVICE_NOT_CONNECTED;
+	if (!NT_SUCCESS(Status))
+		return Status;
+	
+	/* Test if port exists */
+	FoundPort = SerialDoesPortExist((PUCHAR)ComPortBase);
+	
+	/* Report device if detected... */
+	if (FoundPort)
+	{
+		Status = IoReportDetectedDevice(
+			DriverObject,
+			ResourceList->List[0].InterfaceType, ResourceList->List[0].BusNumber, -1/*FIXME*/,
+			ResourceList, NULL,
+			TRUE,
+			NULL);
+	}
+	else
+	{
+		/* Release resources */
+		Status = IoReportResourceForDetection(
+			DriverObject, NULL, 0,
+			NULL, NULL, 0,
+			&ConflictDetected);
+		Status = STATUS_DEVICE_NOT_CONNECTED;
+	}
+	return Status;
+}
+
+NTSTATUS
+DetectLegacyDevices(
+	IN PDRIVER_OBJECT DriverObject)
+{
+	ULONG ComPortBase[] = { 0x3f8, 0x2f8 };
+	ULONG Irq[] = { 4, 3 };
+	ULONG i;
+	NTSTATUS Status;
+	
+	for (i = 0; i < sizeof(ComPortBase)/sizeof(ComPortBase[0]); i++)
+	{
+		Status = DetectLegacyDevice(DriverObject, ComPortBase[i], Irq[i]);
+		DPRINT("Serial: Legacy device at 0x%x (IRQ %lu): status = 0x%08x\n", ComPortBase[i], Irq[i], Status);
+		if (Status == STATUS_DEVICE_NOT_CONNECTED)
+			Status = STATUS_SUCCESS;
+		else if (!NT_SUCCESS(Status))
+			break;
+	}
+	
+	return Status;
+}

Modified: trunk/reactos/drivers/dd/serial/makefile
--- trunk/reactos/drivers/dd/serial/makefile	2005-03-18 13:52:21 UTC (rev 14176)
+++ trunk/reactos/drivers/dd/serial/makefile	2005-03-18 16:01:35 UTC (rev 14177)
@@ -7,11 +7,13 @@
 TARGET_NAME = serial
 
 TARGET_OBJECTS = \
+	circularbuffer.o \
 	cleanup.o \
 	close.o \
 	create.o \
 	devctrl.o \
 	info.o \
+	legacy.o \
 	misc.o \
 	pnp.o \
 	power.o \

Modified: trunk/reactos/drivers/dd/serial/misc.c
--- trunk/reactos/drivers/dd/serial/misc.c	2005-03-18 13:52:21 UTC (rev 14176)
+++ trunk/reactos/drivers/dd/serial/misc.c	2005-03-18 16:01:35 UTC (rev 14177)
@@ -7,11 +7,12 @@
  * 
  * PROGRAMMERS:     HervÚ Poussineau (poussine@freesurf.fr)
  */
+/* FIXME: call IoAcquireRemoveLock/IoReleaseRemoveLock around each I/O operation */
 
 #define NDEBUG
 #include "serial.h"
 
-NTSTATUS
+NTSTATUS STDCALL
 ForwardIrpAndWaitCompletion(
 	IN PDEVICE_OBJECT DeviceObject,
 	IN PIRP Irp,
@@ -48,6 +49,17 @@
 	return Status;
 }
 
+NTSTATUS STDCALL
+ForwardIrpAndForget(
+	IN PDEVICE_OBJECT DeviceObject,
+	IN PIRP Irp)
+{
+	PDEVICE_OBJECT LowerDevice = ((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
+	
+	IoSkipCurrentIrpStackLocation(Irp);
+	return IoCallDriver(LowerDevice, Irp);
+}
+
 BOOLEAN STDCALL
 SerialInterruptService(
 	IN PKINTERRUPT Interrupt,
@@ -55,29 +67,23 @@
 {
 	PDEVICE_OBJECT DeviceObject;
 	PSERIAL_DEVICE_EXTENSION DeviceExtension;
+	UCHAR Byte;
 	PUCHAR ComPortBase;
 	UCHAR Iir;
+	NTSTATUS Status;
 	
 	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);
+	if ((Iir & SR_IIR_SELF) != 0) { return FALSE; }
 	
+	/* FIXME: sometimes, update DeviceExtension->IER */
+	/* FIXME: sometimes, update DeviceExtension->MCR */
 	switch (Iir)
 	{
 		case SR_IIR_MSR_CHANGE:
@@ -85,46 +91,60 @@
 			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;
+			return TRUE;
 		}
 		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 );*/
+			DPRINT("Serial: SR_IIR_THR_EMPTY\n");
+			/* FIXME: lock OutputBuffer */
+			while (!IsCircularBufferEmpty(&DeviceExtension->OutputBuffer)
+				&& READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_TBE)
+			{
+				Status = PopCircularBufferEntry(&DeviceExtension->OutputBuffer, &Byte);
+				if (!NT_SUCCESS(Status))
+					break;
+				WRITE_PORT_UCHAR(SER_THR(ComPortBase), Byte);
+				DeviceExtension->SerialPerfStats.TransmittedCount++;
+			}	
+			/* FIXME: unlock OutputBuffer */
+			return TRUE;
 		}
 		case SR_IIR_DATA_RECEIVED:
 		{
 			DPRINT1("Serial: SR_IIR_DATA_RECEIVED\n");
-			if (READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_DR)
+			while (READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_DR)
 			{
-				DPRINT1("Serial: Byte received: 0x%x\n", READ_PORT_UCHAR(SER_RBR(ComPortBase)));
+				Byte = READ_PORT_UCHAR(SER_RBR(ComPortBase));
+				DPRINT1("Serial: Byte received: 0x%02x (%c)\n", Byte, Byte);
+				/* FIXME: lock InputBuffer */
+				Status = PushCircularBufferEntry(&DeviceExtension->InputBuffer, Byte);
+				if (!NT_SUCCESS(Status))
+				{
+					/* FIXME: count buffer overflow */
+					break;
+				}
+				DPRINT1("Serial: push to buffer done\n");
+				/* FIXME: unlock InputBuffer */
 				DeviceExtension->SerialPerfStats.ReceivedCount++;
-				return TRUE;
 			}
+			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:
 		{
+			/* FIXME: what to do? */
 			DPRINT1("Serial: SR_IIR_ERROR\n");
 			break;
 			/*Error = READ_PORT_UCHAR( Self->Port + UART_LSR );
 			if( Error & LSR_OVERRUN )
 			    Self->WaitingReadBytes.PushBack( SerialFifo::OVERRUN );
+			    DeviceExtension->SerialPerfStats.SerialOverrunErrorCount++;
 			if( Error & LSR_PARITY_ERROR )
 			    Self->WaitingReadBytes.PushBack( SerialFifo::PARITY );
+			    DeviceExtension->SerialPerfStats.ParityErrorCount++;
 			if( Error & LSR_FRAMING_ERROR )
 			    Self->WaitingReadBytes.PushBack( SerialFifo::FRAMING );
+			    DeviceExtension->SerialPerfStats.FrameErrorCount++;
 			if( Error & LSR_BREAK )
 			    Self->WaitingReadBytes.PushBack( SerialFifo::BREAK );
 			if( Error & LSR_TIMEOUT )
@@ -133,44 +153,4 @@
 		}
 	}
 	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
 }

Modified: trunk/reactos/drivers/dd/serial/pnp.c
--- trunk/reactos/drivers/dd/serial/pnp.c	2005-03-18 13:52:21 UTC (rev 14176)
+++ trunk/reactos/drivers/dd/serial/pnp.c	2005-03-18 16:01:35 UTC (rev 14177)
@@ -9,6 +9,7 @@
  */
 /* FIXME: call IoAcquireRemoveLock/IoReleaseRemoveLock around each I/O operation */
 
+#define INITGUID
 #define NDEBUG
 #include "serial.h"
 
@@ -17,11 +18,12 @@
 	IN PDRIVER_OBJECT DriverObject,
 	IN PDEVICE_OBJECT Pdo)
 {
-	PDEVICE_OBJECT Fdo;
+	PDEVICE_OBJECT Fdo = NULL;
 	PSERIAL_DEVICE_EXTENSION DeviceExtension;
 	NTSTATUS Status;
 	WCHAR DeviceNameBuffer[32];
 	UNICODE_STRING DeviceName;
+	//UNICODE_STRING SymbolicLinkName;
 	static ULONG DeviceNumber = 0;
 
 	DPRINT("Serial: SerialAddDevice called\n");
@@ -39,29 +41,57 @@
 	if (!NT_SUCCESS(Status))
 	{
 		DPRINT("Serial: IoCreateDevice() failed with status 0x%08x\n", Status);
-		return Status;
+		Fdo = NULL;
+		goto ByeBye;
 	}
+	DeviceExtension = (PSERIAL_DEVICE_EXTENSION)Fdo->DeviceExtension;
+	RtlZeroMemory(DeviceExtension, sizeof(SERIAL_DEVICE_EXTENSION));
 	
 	/* Register device interface */
-	/* FIXME */
-	
-	DeviceExtension = (PSERIAL_DEVICE_EXTENSION)Fdo->DeviceExtension;
-	RtlZeroMemory(DeviceExtension, sizeof(SERIAL_DEVICE_EXTENSION));
+#if 0 /* FIXME: activate */
+	Status = IoRegisterDeviceInterface(Pdo, &GUID_DEVINTERFACE_COMPORT, NULL, &SymbolicLinkName);
+	if (!NT_SUCCESS(Status))
+	{
+		DPRINT("Serial: IoRegisterDeviceInterface() failed with status 0x%08x\n", Status);
+		goto ByeBye;
+	}
+	DPRINT1("Serial: IoRegisterDeviceInterface() returned '%wZ'\n", &SymbolicLinkName);
+	Status = IoSetDeviceInterfaceState(&SymbolicLinkName, TRUE);
+	if (!NT_SUCCESS(Status))
+	{
+		DPRINT("Serial: IoSetDeviceInterfaceState() failed with status 0x%08x\n", Status);
+		goto ByeBye;
+	}
+	RtlFreeUnicodeString(&SymbolicLinkName);
+#endif
+
 	DeviceExtension->SerialPortNumber = DeviceNumber++;
 	DeviceExtension->Pdo = Pdo;
 	DeviceExtension->PnpState = dsStopped;
+	Status = InitializeCircularBuffer(&DeviceExtension->InputBuffer, 16);
+	if (!NT_SUCCESS(Status)) goto ByeBye;
+	Status = InitializeCircularBuffer(&DeviceExtension->OutputBuffer, 16);
+	if (!NT_SUCCESS(Status)) goto ByeBye;
 	IoInitializeRemoveLock(&DeviceExtension->RemoveLock, SERIAL_TAG, 0, 0);
 	//Fdo->Flags |= DO_POWER_PAGEABLE (or DO_POWER_INRUSH?)
 	Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
 	if (!NT_SUCCESS(Status))
 	{
 		DPRINT("Serial: IoAttachDeviceToDeviceStackSafe() failed with status 0x%08x\n", Status);
-		IoDeleteDevice(Fdo);
-		return Status;
+		goto ByeBye;
 	}
 	Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
+	
+	return STATUS_SUCCESS;
 
-	return STATUS_SUCCESS;
+ByeBye:
+	if (Fdo)
+	{
+		FreeCircularBuffer(&DeviceExtension->InputBuffer);
+		FreeCircularBuffer(&DeviceExtension->OutputBuffer);
+		IoDeleteDevice(Fdo);
+	}
+	return Status;
 }
 
 NTSTATUS STDCALL
@@ -70,20 +100,24 @@
 	IN PIRP Irp)
 {
 	PIO_STACK_LOCATION Stack;
-	PCM_RESOURCE_LIST ResourceList;
+	//PCM_RESOURCE_LIST ResourceList;
 	PSERIAL_DEVICE_EXTENSION DeviceExtension;
 	WCHAR DeviceNameBuffer[32];
 	UNICODE_STRING DeviceName;
 	WCHAR LinkNameBuffer[32];
 	UNICODE_STRING LinkName;
+	WCHAR ComPortBuffer[32];
+	UNICODE_STRING ComPort;
 	ULONG Vector;
+	//ULONG i, j;
 	KIRQL Dirql;
 	KAFFINITY Affinity;
+	OBJECT_ATTRIBUTES objectAttributes;
+	UNICODE_STRING KeyName;
+	HANDLE hKey;
 	NTSTATUS Status;
 	
 	Stack = IoGetCurrentIrpStackLocation(Irp);
-	
-	ResourceList = Stack->Parameters.StartDevice.AllocatedResources/*Translated*/;
 	DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
 	
 	/* FIXME: actually, IRP_MN_START_DEVICE is sent twice to each serial device:
@@ -94,77 +128,75 @@
 	 */
 	if (DeviceExtension->PnpState == dsStarted) return STATUS_SUCCESS;
 	
-	if (ResourceList == NULL)
+#if 1
+	/* FIXME: PnP isn't correctly implemented and doesn't give us a list
+	 * of our own resources. Use default values instead.
+	 */
+	switch (DeviceExtension->SerialPortNumber)
 	{
-		/* FIXME: PnP isn't correctly implemented and doesn't give us a list
-		 * of our own resources. Use default values instead.
-		 */
-		switch (DeviceExtension->SerialPortNumber)
-		{
-			case 0:
-				DPRINT("Serial: creating COM1:\n");
-				DeviceExtension->ComPort = 3;
-				DeviceExtension->BaudRate = 19200 | SERIAL_BAUD_USER;
-				DeviceExtension->BaseAddress = 0x3F8;
-				DeviceExtension->Irq = 4;
-				break;
-			case 1:
-				DPRINT("Serial: creating COM2:\n");
-				DeviceExtension->ComPort = 4;
-				DeviceExtension->BaudRate = 19200 | SERIAL_BAUD_USER;
-				DeviceExtension->BaseAddress = 0x2F8;
-				DeviceExtension->Irq = 3;
-				break;
-			default:
-				DPRINT1("Serial: unknown port?\n");
-				return STATUS_INSUFFICIENT_RESOURCES;
-		}
+		case 0:
+			DPRINT("Serial: creating COM1:\n");
+			DeviceExtension->ComPort = 1;
+			DeviceExtension->BaudRate = 19200 | SERIAL_BAUD_USER;
+			DeviceExtension->BaseAddress = 0x3F8;
+			DeviceExtension->Irq = 4;
+			break;
+		case 1:
+			DPRINT("Serial: creating COM2:\n");
+			DeviceExtension->ComPort = 2;
+			DeviceExtension->BaudRate = 19200 | SERIAL_BAUD_USER;
+			DeviceExtension->BaseAddress = 0x2F8;
+			DeviceExtension->Irq = 3;
+			break;
+		default:
+			DPRINT1("Serial: too much ports detected. Forgetting this one...\n");
+			return STATUS_INSUFFICIENT_RESOURCES;
 	}
-#if 0
-	else
+#else
+	DPRINT1("Serial: ResourceList %p, ResourceListTranslated %p\n",
+		Stack->Parameters.StartDevice.AllocatedResources,
+		Stack->Parameters.StartDevice.AllocatedResourcesTranslated);
+	ResourceList = Stack->Parameters.StartDevice.AllocatedResourcesTranslated;
+	for (i = 0; i < ResourceList->Count; i++)
 	{
-		DPRINT1("ResourceList %p, ResourceListTranslated %p\n", Stack->Parameters.StartDevice.AllocatedResources, Stack->Parameters.StartDevice.AllocatedResourcesTranslated);
-		for (i = 0; i < ResourceList->Count; i++)
+		DPRINT1("Serial: Interface type = 0x%x\n", ResourceList->List[i].InterfaceType);
+		DPRINT1("Serial: Bus number = 0x%x\n", ResourceList->List[i].BusNumber);
+		for (j = 0; i < ResourceList->List[i].PartialResourceList.Count; j++)
 		{
-			DPRINT1("Interface type = 0x%x\n", ResourceList->List[i].InterfaceType);
-			DPRINT1("Bus number = 0x%x\n", ResourceList->List[i].BusNumber);
-			for (j = 0; i < ResourceList->List[i].PartialResourceList.Count; j++)
+			PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor = &ResourceList->List[i].PartialResourceList.PartialDescriptors[j];
+			DPRINT1("Serial: Type 0x%x, Share disposition 0x%x, Flags 0x%x\n",
+				PartialDescriptor->Type,
+				PartialDescriptor->ShareDisposition,
+				PartialDescriptor->Flags);
+			switch (PartialDescriptor->Type)
 			{
-				PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor = &ResourceList->List[i].PartialResourceList.PartialDescriptors[j];
-				DPRINT1("Type 0x%x, Share disposition 0x%x, Flags 0x%x\n",
-					PartialDescriptor->Type,
-					PartialDescriptor->ShareDisposition,
-					PartialDescriptor->Flags);
-				switch (PartialDescriptor->Type)
-				{
-					case CmResourceTypePort:
-						DeviceExtension->BaseAddress = PartialDescriptor->u.Port.Start.u.LowPart;
-						break;
-					case CmResourceTypeInterrupt:
-						/* FIXME: Detect if interrupt is shareable and/or latched */
-						/* FIXME: use also ->u.Interrupt.Vector and ->u.Interrupt.Affinity
-						 * to remove call to HalGetInterruptVector(...) */
-						DeviceExtension->Irq = PartialDescriptor->u.Interrupt.Level;
-						break;
-				}
+				case CmResourceTypePort:
+					DeviceExtension->BaseAddress = PartialDescriptor->u.Port.Start.u.LowPart;
+					DPRINT1("Serial: CmResourceTypePort = %lu\n", DeviceExtension->BaseAddress);
+					break;
+				case CmResourceTypeInterrupt:
+					/* FIXME: Detect if interrupt is shareable and/or latched */
+					/* FIXME: use also ->u.Interrupt.Vector and ->u.Interrupt.Affinity
+					 * to remove call to HalGetInterruptVector(...) */
+					DeviceExtension->Irq = PartialDescriptor->u.Interrupt.Level;
+					DPRINT1("Serial: Irq = %lu\n", DeviceExtension->Irq);
+					break;
 			}
 		}
-		/* FIXME: use polling if no interrupt was found? */
-		DeviceExtension->ComPort = 5; /* FIXME: use incremental value, or find it in resource list*/
 	}
+	DeviceExtension->BaudRate = 19200 | SERIAL_BAUD_USER;
+	/* FIXME: use polling if no interrupt was found? */
+	DeviceExtension->ComPort = 5; /* FIXME: use incremental value, or find it in resource list */
 #endif
 	
 	/* Get current settings */
 	DeviceExtension->IER = READ_PORT_UCHAR(SER_IER((PUCHAR)DeviceExtension->BaseAddress));
 	DeviceExtension->MCR = READ_PORT_UCHAR(SER_MCR((PUCHAR)DeviceExtension->BaseAddress));
 	DeviceExtension->MSR = READ_PORT_UCHAR(SER_MSR((PUCHAR)DeviceExtension->BaseAddress));
-	DeviceExtension->SerialLineControl.StopBits = STOP_BIT_1;
-	DeviceExtension->SerialLineControl.Parity = NO_PARITY;
-	DeviceExtension->SerialLineControl.WordLength = 8;
 	DeviceExtension->WaitMask = 0;
 	
 	/* Set baud rate */
-	Status = SerialSetBaudRate(DeviceExtension, 19200 | SERIAL_BAUD_USER); /* FIXME: real default value? */
+	Status = SerialSetBaudRate(DeviceExtension, DeviceExtension->BaudRate);
 	if (!NT_SUCCESS(Status))
 	{
 		DPRINT("Serial: SerialSetBaudRate() failed with status 0x%08x\n", Status);
@@ -172,6 +204,9 @@
 	}
 	
 	/* Set line control */
+	DeviceExtension->SerialLineControl.StopBits = STOP_BIT_1;
+	DeviceExtension->SerialLineControl.Parity = NO_PARITY;
+	DeviceExtension->SerialLineControl.WordLength = 8;
 	Status = SerialSetLineControl(DeviceExtension, &DeviceExtension->SerialLineControl);
 	if (!NT_SUCCESS(Status))
 	{
@@ -181,9 +216,11 @@
 	
 	/* Create link \DosDevices\COMX -> \Device\SerialX */
 	swprintf(DeviceNameBuffer, L"\\Device\\Serial%lu", DeviceExtension->SerialPortNumber);
+	swprintf(LinkNameBuffer, L"\\DosDevices\\COM%lu", DeviceExtension->ComPort);
+	swprintf(ComPortBuffer, L"COM%lu", DeviceExtension->ComPort);
 	RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
-	swprintf(LinkNameBuffer, L"\\DosDevices\\COM%lu", DeviceExtension->ComPort);
 	RtlInitUnicodeString(&LinkName, LinkNameBuffer);
+	RtlInitUnicodeString(&ComPort, ComPortBuffer);
 	Status = IoCreateSymbolicLink(&LinkName, &DeviceName);
 	if (!NT_SUCCESS(Status))
 	{
@@ -204,12 +241,29 @@
 		IoDeleteSymbolicLink(&LinkName);
 		return Status;
 	}
-	DeviceExtension->IER |= 0x1; /* Activate interrupt mode */
-	WRITE_PORT_UCHAR(SER_IER((PUCHAR)DeviceExtension->BaseAddress), DeviceExtension->IER);
 	
+	/* Write an entry value under HKLM\HARDWARE\DeviceMap\SERIALCOMM */
+	/* This step is not mandatory, so don't exit in case of error */
+	RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\HARDWARE\\DeviceMap\\SERIALCOMM");
+	InitializeObjectAttributes(&objectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
+	Status = ZwCreateKey(&hKey, KEY_SET_VALUE, &objectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
+	if (NT_SUCCESS(Status))
+	{
+		/* Key = \Device\Serialx, Value = COMx */
+		ZwSetValueKey(hKey, &DeviceName, 0, REG_SZ, &ComPortBuffer, ComPort.Length + sizeof(WCHAR));
+		ZwClose(hKey);
+	}
+	
 	DeviceExtension->PnpState = dsStarted;
 	
-	return Status;
+	DeviceExtension->IER |= 0x1f; /* Activate interrupt mode */
+	DeviceExtension->IER &= ~1; /* FIXME: Disable receive byte interrupt */
+	WRITE_PORT_UCHAR(SER_IER((PUCHAR)DeviceExtension->BaseAddress), DeviceExtension->IER);
+	
+	DeviceExtension->MCR |= 0x03; /* Activate DTR, RTS */
+	WRITE_PORT_UCHAR(SER_MCR((PUCHAR)DeviceExtension->BaseAddress), DeviceExtension->MCR);
+	
+	return STATUS_SUCCESS;
 }
 
 NTSTATUS STDCALL
@@ -220,12 +274,10 @@
 	ULONG MinorFunction;
 	PIO_STACK_LOCATION Stack;
 	ULONG Information = 0;
-	PDEVICE_OBJECT LowerDevice;
 	NTSTATUS Status;
 	
 	Stack = IoGetCurrentIrpStackLocation(Irp);
 	MinorFunction = Stack->MinorFunction;
-	LowerDevice = ((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
 	
 	switch (MinorFunction)
 	{
@@ -264,9 +316,7 @@
 		default:
 		{
 			DPRINT1("Serial: unknown minor function 0x%x\n", MinorFunction);
-			IoSkipCurrentIrpStackLocation(Irp);
-			Status = IoCallDriver(LowerDevice, Irp);
-			break;
[truncated at 1000 lines; 358 more skipped]