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
--- 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;
+}
--- 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;
}
--- 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:
--- 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;
}
--- 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;
+}
--- 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 \
--- 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
}
--- 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]