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(a)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(a)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].ShareDis
position = CmResourceShareDriverExclusive;
+
ResourceList->List[0].PartialResourceList.PartialDescriptors[0].Flags =
CM_RESOURCE_PORT_IO;
+ // FIXME
ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.S
tart = ComPortBase;
+
ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.L
ength = 8;
+
+
ResourceList->List[0].PartialResourceList.PartialDescriptors[1].Type =
CmResourceTypeInterrupt;
+
ResourceList->List[0].PartialResourceList.PartialDescriptors[1].ShareDis
position = CmResourceShareDriverExclusive;
+
ResourceList->List[0].PartialResourceList.PartialDescriptors[1].Flags =
CM_RESOURCE_INTERRUPT_LATCHED;
+ /* FIXME:
ResourceList->List[0].PartialResourceList.PartialDescriptors[1].u.Interr
upt.Level = ;
+
ResourceList->List[0].PartialResourceList.PartialDescriptors[1].u.Interr
upt.Vector = ;
+
ResourceList->List[0].PartialResourceList.PartialDescriptors[1].u.Interr
upt.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(a)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]