Modified: trunk/reactos/drivers/dd/serial/misc.c
Modified: trunk/reactos/drivers/dd/serial/pnp.c
Modified: trunk/reactos/drivers/dd/serial/rw.c
Modified: trunk/reactos/drivers/dd/serial/serial.h
--- trunk/reactos/drivers/dd/serial/misc.c 2005-04-03 21:31:41 UTC (rev 14484)
+++ trunk/reactos/drivers/dd/serial/misc.c 2005-04-03 21:36:15 UTC (rev 14485)
@@ -64,29 +64,37 @@
SerialReceiveByte(
IN PKDPC Dpc,
IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION
- IN PVOID pByte, // real type UCHAR
- IN PVOID Unused)
+ IN PVOID Unused1,
+ IN PVOID Unused2)
{
PSERIAL_DEVICE_EXTENSION DeviceExtension;
+ PUCHAR ComPortBase;
UCHAR Byte;
KIRQL Irql;
+ UCHAR IER;
NTSTATUS Status;
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)pDeviceExtension;
- Byte = (UCHAR)(ULONG_PTR)pByte;
- DPRINT1("Serial: received byte on COM%lu: 0x%02x (%c)\n",
- DeviceExtension->ComPort, Byte, Byte);
+ ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
- Status = PushCircularBufferEntry(&DeviceExtension->InputBuffer, Byte);
- if (!NT_SUCCESS(Status))
+ while (READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_DR)
{
- /* FIXME: count buffer overflow */
- return;
+ Byte = READ_PORT_UCHAR(SER_RBR(ComPortBase));
+ DPRINT("Serial: Byte received on COM%lu: 0x%02x\n",
+ DeviceExtension->ComPort, Byte);
+ Status = PushCircularBufferEntry(&DeviceExtension->InputBuffer, Byte);
+ if (NT_SUCCESS(Status))
+ DeviceExtension->SerialPerfStats.ReceivedCount++;
+ else
+ DeviceExtension->SerialPerfStats.BufferOverrunErrorCount++;
}
- DPRINT1("Serial: push to buffer done\n");
+ KeSetEvent(&DeviceExtension->InputBufferNotEmpty, 0, FALSE);
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
- InterlockedIncrement(&DeviceExtension->SerialPerfStats.ReceivedCount);
+
+ /* allow new interrupts */
+ IER = READ_PORT_UCHAR(SER_IER(ComPortBase));
+ WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER | SR_IER_DATA_RECEIVED);
}
VOID STDCALL
@@ -100,6 +108,7 @@
PUCHAR ComPortBase;
UCHAR Byte;
KIRQL Irql;
+ UCHAR IER;
NTSTATUS Status;
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)pDeviceExtension;
@@ -113,9 +122,15 @@
if (!NT_SUCCESS(Status))
break;
WRITE_PORT_UCHAR(SER_THR(ComPortBase), Byte);
+ DPRINT("Serial: Byte sent to COM%lu: 0x%02x\n",
+ DeviceExtension->ComPort, Byte);
DeviceExtension->SerialPerfStats.TransmittedCount++;
- }
+ }
KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
+
+ /* allow new interrupts */
+ IER = READ_PORT_UCHAR(SER_IER(ComPortBase));
+ WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER | SR_IER_THR_EMPTY);
}
BOOLEAN STDCALL
@@ -125,7 +140,6 @@
{
PDEVICE_OBJECT DeviceObject;
PSERIAL_DEVICE_EXTENSION DeviceExtension;
- UCHAR Byte;
PUCHAR ComPortBase;
UCHAR Iir;
@@ -139,32 +153,32 @@
Iir &= SR_IIR_ID_MASK;
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:
{
+ UCHAR IER;
DPRINT1("Serial: SR_IIR_MSR_CHANGE\n");
+
DeviceExtension->MSR = READ_PORT_UCHAR(SER_MSR(ComPortBase));
/* FIXME: what to do? */
+ IER = READ_PORT_UCHAR(SER_IER(ComPortBase));
+ WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER | SR_IER_MSR_CHANGE);
return TRUE;
}
case SR_IIR_THR_EMPTY:
{
DPRINT("Serial: SR_IIR_THR_EMPTY\n");
- return KeInsertQueueDpc(&DeviceExtension->SendByteDpc, NULL, NULL);
+
+ KeInsertQueueDpc(&DeviceExtension->SendByteDpc, NULL, NULL);
+ return TRUE;
}
case SR_IIR_DATA_RECEIVED:
{
- DPRINT1("Serial: SR_IIR_DATA_RECEIVED\n");
- while (READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_DR)
- {
- Byte = READ_PORT_UCHAR(SER_RBR(ComPortBase));
- DPRINT1("Serial: Byte received: 0x%02x (%c)\n", Byte, Byte);
- if (!KeInsertQueueDpc(&DeviceExtension->ReceivedByteDpc, (PVOID)(ULONG_PTR)Byte, NULL))
- break;
- }
+ DPRINT("Serial: SR_IIR_DATA_RECEIVED\n");
+
+ KeInsertQueueDpc(&DeviceExtension->ReceivedByteDpc, NULL, NULL);
return TRUE;
}
case SR_IIR_ERROR:
--- trunk/reactos/drivers/dd/serial/pnp.c 2005-04-03 21:31:41 UTC (rev 14484)
+++ trunk/reactos/drivers/dd/serial/pnp.c 2005-04-03 21:36:15 UTC (rev 14485)
@@ -78,6 +78,7 @@
IoInitializeRemoveLock(&DeviceExtension->RemoveLock, SERIAL_TAG, 0, 0);
KeInitializeSpinLock(&DeviceExtension->InputBufferLock);
KeInitializeSpinLock(&DeviceExtension->OutputBufferLock);
+ KeInitializeEvent(&DeviceExtension->InputBufferNotEmpty, NotificationEvent, FALSE);
KeInitializeDpc(&DeviceExtension->ReceivedByteDpc, SerialReceiveByte, DeviceExtension);
KeInitializeDpc(&DeviceExtension->SendByteDpc, SerialSendByte, DeviceExtension);
Fdo->Flags |= DO_POWER_PAGABLE;
@@ -144,6 +145,7 @@
UNICODE_STRING ComPort;
ULONG Vector = 0;
ULONG i, j;
+ UCHAR IER;
KIRQL Dirql;
KAFFINITY Affinity = 0;
KINTERRUPT_MODE InterruptMode = Latched;
@@ -195,8 +197,6 @@
DeviceExtension->BaseAddress, Dirql);
if (!DeviceExtension->BaseAddress)
return STATUS_INSUFFICIENT_RESOURCES;
- /* FIXME: we should be able to continue and use polling method
- * for read/write if we don't have an interrupt */
if (!Dirql)
return STATUS_INSUFFICIENT_RESOURCES;
ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
@@ -205,7 +205,6 @@
DeviceExtension->UartType = SerialDetectUartType(ComPortBase);
/* Get current settings */
- DeviceExtension->IER = READ_PORT_UCHAR(SER_IER(ComPortBase));
DeviceExtension->MCR = READ_PORT_UCHAR(SER_MCR(ComPortBase));
DeviceExtension->MSR = READ_PORT_UCHAR(SER_MSR(ComPortBase));
DeviceExtension->WaitMask = 0;
@@ -279,11 +278,13 @@
DeviceExtension->PnpState = dsStarted;
- DeviceExtension->IER |= 0x1f; /* Activate interrupt mode */
- DeviceExtension->IER &= ~1; /* FIXME: Disable receive byte interrupt */
- WRITE_PORT_UCHAR(SER_IER(ComPortBase), DeviceExtension->IER);
+ /* Activate interrupt modes */
+ IER = READ_PORT_UCHAR(SER_IER(ComPortBase));
+ IER |= SR_IER_DATA_RECEIVED | SR_IER_THR_EMPTY | SR_IER_LSR_CHANGE | SR_IER_MSR_CHANGE;
+ WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER);
- DeviceExtension->MCR |= 0x03; /* Activate DTR, RTS */
+ /* Activate DTR, RTS */
+ DeviceExtension->MCR |= SR_MCR_DTR | SR_MCR_RTS;
WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
return STATUS_SUCCESS;
@@ -331,11 +332,19 @@
ULONG Irq;
DPRINT1("Serial: no allocated resources for this device! Creating fake list\n");
- /* These values are resources of the ONLY serial
- * port that will be managed by this driver
- * (default is COM2) */
- ComPortBase = 0x2f8;
- Irq = 3;
+ switch (((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->SerialPortNumber)
+ {
+ case 0:
+ ComPortBase = 0x3f8;
+ Irq = 4;
+ break;
+ case 1:
+ ComPortBase = 0x2f8;
+ Irq = 3;
+ break;
+ default:
+ ComPortBase = Irq = 0;
+ }
/* Create resource list */
ResourceListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
--- trunk/reactos/drivers/dd/serial/rw.c 2005-04-03 21:31:41 UTC (rev 14484)
+++ trunk/reactos/drivers/dd/serial/rw.c 2005-04-03 21:36:15 UTC (rev 14485)
@@ -7,7 +7,6 @@
*
* PROGRAMMERS: HervÚ Poussineau (poussine@freesurf.fr)
*/
-/* FIXME: call IoAcquireRemoveLock/IoReleaseRemoveLock around each I/O operation */
#define NDEBUG
#include "serial.h"
@@ -30,84 +29,81 @@
PUCHAR ComPortBase;
ULONG Length;
PUCHAR Buffer;
- ULONG Information = 0;
- LARGE_INTEGER SystemTime, ByteTimeoutTime;
UCHAR ReceivedByte;
- BOOLEAN IsByteReceived;
- //KIRQL Irql;
+ KTIMER TotalTimeoutTimer;
+ KIRQL Irql;
+ ULONG ObjectCount;
+ PVOID ObjectsArray[2];
+ ULONG Information = 0;
+ NTSTATUS Status;
- DPRINT("Serial: ReadBytes() called\n");
-
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
Length = IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length;
Buffer = SerialGetUserBuffer(Irp);
- /* FIXME: remove disabling interrupts */
- WRITE_PORT_UCHAR(SER_IER(ComPortBase), DeviceExtension->IER & ~1);
+ DPRINT("Serial: UseIntervalTimeout = %s, IntervalTimeout = %lu\n",
+ WorkItemData->UseIntervalTimeout ? "YES" : "NO",
+ WorkItemData->UseIntervalTimeout ? WorkItemData->IntervalTimeout.QuadPart : 0);
+ DPRINT("Serial: UseTotalTimeout = %s\n",
+ WorkItemData->UseTotalTimeout ? "YES" : "NO");
+
+ ObjectCount = 1;
+ ObjectsArray[0] = &DeviceExtension->InputBufferNotEmpty;
+ if (WorkItemData->UseTotalTimeout)
+ {
+ KeInitializeTimer(&TotalTimeoutTimer);
+ KeSetTimer(&TotalTimeoutTimer, WorkItemData->TotalTimeoutTime, NULL);
+ ObjectsArray[ObjectCount] = &TotalTimeoutTimer;
+ ObjectCount++;
+ }
+
+ /* while buffer is not fully filled */
while (Length > 0)
{
- /* Calculate dead line to receive the next byte */
- KeQuerySystemTime(&SystemTime);
- ByteTimeoutTime.QuadPart = SystemTime.QuadPart +
- WorkItemData->IntervalTimeout * 10000;
+ /* read already received bytes from buffer */
+ KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
+ while (!IsCircularBufferEmpty(&DeviceExtension->InputBuffer)
+ && Length > 0)
+ {
+ PopCircularBufferEntry(&DeviceExtension->InputBuffer, &ReceivedByte);
+ DPRINT("Serial: reading byte from buffer: 0x%02x\n", ReceivedByte);
+
+ Buffer[Information++] = ReceivedByte;
+ Length--;
+ }
+ KeClearEvent(&DeviceExtension->InputBufferNotEmpty);
+ KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
- IsByteReceived = FALSE;
- while (TRUE)
+ if (WorkItemData->DontWait
+ && !(WorkItemData->ReadAtLeastOneByte && Information == 0))
{
-#if 1
- if ((READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_DR) != 0)
- {
- ReceivedByte = READ_PORT_UCHAR(ComPortBase);
- DPRINT("Serial: received byte 0x%02x (%c)\n", ReceivedByte, ReceivedByte);
- IsByteReceived = TRUE;
- break;
- }
- else if (WorkItemData->DontWait &&
- !(WorkItemData->ReadAtLeastOneByte && Information == 0))
- {
- DPRINT("Serial: read buffer empty\n");
- break;
- }
-#else
- KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
- if (!IsCircularBufferEmpty(&DeviceExtension->InputBuffer))
- {
- CHECKPOINT1;
- PopCircularBufferEntry(&DeviceExtension->InputBuffer, &ReceivedByte);
- KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
- DPRINT("Serial: reading byte from buffer 0x%02x (%c)\n", ReceivedByte, ReceivedByte);
- IsByteReceived = TRUE;
- break;
- }
- else if (WorkItemData->DontWait &&
- !(WorkItemData->ReadAtLeastOneByte && Information == 0))
- {
- DPRINT("Serial: read buffer empty\n");
- break;
- }
- KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
-#endif
- if (IsByteReceived) break;
- KeQuerySystemTime(&SystemTime);
- if (WorkItemData->UseIntervalTimeout && Information > 0)
- {
- if (SystemTime.QuadPart >= ByteTimeoutTime.QuadPart)
- break;
- }
- if (WorkItemData->UseTotalTimeout)
- {
- if (SystemTime.QuadPart >= WorkItemData->TotalTimeoutTime.QuadPart)
- break;
- }
+ DPRINT("Serial: buffer empty. Don't wait more bytes\n");
+ break;
}
- if (!IsByteReceived) break;
- Buffer[Information++] = ReceivedByte;
- Length--;
+
+ Status = KeWaitForMultipleObjects(
+ ObjectCount,
+ ObjectsArray,
+ WaitAny,
+ Executive,
+ KernelMode,
+ FALSE,
+ (WorkItemData->UseIntervalTimeout && Information > 0) ? &WorkItemData->IntervalTimeout : NULL,
+ NULL);
+
+ if (Status == STATUS_TIMEOUT /* interval timeout */
+ || Status == STATUS_WAIT_1) /* total timeout */
+ {
+ DPRINT("Serial: timeout when reading bytes. Status = 0x%08lx\n", Status);
+ break;
+ }
}
- /* FIXME: remove enabling interrupts */
- WRITE_PORT_UCHAR(SER_IER(ComPortBase), DeviceExtension->IER);
+ /* stop total timeout timer */
+ if (WorkItemData->UseTotalTimeout)
+ KeCancelTimer(&TotalTimeoutTimer);
+
Irp->IoStatus.Information = Information;
if (Information == 0)
Irp->IoStatus.Status = STATUS_TIMEOUT;
@@ -148,8 +144,6 @@
DPRINT("Serial: IRP_MJ_READ\n");
- /* FIXME: pend operation if possible */
-
Stack = IoGetCurrentIrpStackLocation(Irp);
Length = Stack->Parameters.Read.Length;
Buffer = SerialGetUserBuffer(Irp);
@@ -200,7 +194,7 @@
if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout != 0)
{
WorkItemData->UseIntervalTimeout = TRUE;
- WorkItemData->IntervalTimeout = DeviceExtension->SerialTimeOuts.ReadIntervalTimeout;
+ WorkItemData->IntervalTimeout.QuadPart = DeviceExtension->SerialTimeOuts.ReadIntervalTimeout;
}
if (DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier != 0 ||
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant != 0)
--- trunk/reactos/drivers/dd/serial/serial.h 2005-04-03 21:31:41 UTC (rev 14484)
+++ trunk/reactos/drivers/dd/serial/serial.h 2005-04-03 21:36:15 UTC (rev 14485)
@@ -54,10 +54,12 @@
typedef enum
{
UartUnknown,
- Uart8250,
- Uart16450,
- Uart16550,
- Uart16550A
+ Uart8250, /* initial version */
+ Uart16450, /* + 38.4 Kbps */
+ Uart16550, /* + 115 Kbps */
+ Uart16550A,/* + FIFO 16 bytes */
+ Uart16650, /* + FIFO 32 bytes, 230 Kbps, power management, auto-flow */
+ Uart16750 /* + FIFO 64 bytes, 460 Kbps */
} UART_TYPE;
typedef struct _CIRCULAR_BUFFER
@@ -90,14 +92,14 @@
SERIALPERF_STATS SerialPerfStats;
SERIAL_TIMEOUTS SerialTimeOuts;
- BOOLEAN IsOpened;
+ BOOLEAN IsOpened;
+ KEVENT InputBufferNotEmpty;
CIRCULAR_BUFFER InputBuffer;
KSPIN_LOCK InputBufferLock;
CIRCULAR_BUFFER OutputBuffer;
KSPIN_LOCK OutputBufferLock;
/* Current values */
- UCHAR IER; /* Base+1, Interrupt Enable Register */
UCHAR MCR; /* Base+4, Modem Control Register */
UCHAR MSR; /* Base+6, Modem Status Register */
} SERIAL_DEVICE_EXTENSION, *PSERIAL_DEVICE_EXTENSION;
@@ -108,7 +110,7 @@
BOOLEAN UseIntervalTimeout;
BOOLEAN UseTotalTimeout;
- ULONG IntervalTimeout;
+ LARGE_INTEGER IntervalTimeout;
LARGE_INTEGER TotalTimeoutTime;
BOOLEAN DontWait;
BOOLEAN ReadAtLeastOneByte;
@@ -120,22 +122,28 @@
/* Baud master clock */
#define BAUD_CLOCK 1843200
-#define CLOCKS_PER_BIT 16
+#define CLOCKS_PER_BIT 16
/* UART registers and bits */
-#define SER_RBR(x) ((x)+0)
-#define SER_THR(x) ((x)+0)
-#define SER_DLL(x) ((x)+0)
-#define SER_IER(x) ((x)+1)
-#define SER_DLM(x) ((x)+1)
-#define SER_IIR(x) ((x)+2)
+#define SER_RBR(x) ((x)+0) /* Receive Register */
+#define SER_THR(x) ((x)+0) /* Transmit Register */
+#define SER_DLL(x) ((x)+0) /* Baud Rate Divisor LSB */
+#define SER_IER(x) ((x)+1) /* Interrupt Enable Register */
+#define SR_IER_DATA_RECEIVED 0x01
+#define SR_IER_THR_EMPTY 0x02
+#define SR_IER_LSR_CHANGE 0x04
+#define SR_IER_MSR_CHANGE 0x08
+#define SR_IER_SLEEP_MODE 0x10 /* Uart >= 16750 */
+#define SR_IER_LOW_POWER 0x20 /* Uart >= 16750 */
+#define SER_DLM(x) ((x)+1) /* Baud Rate Divisor MSB */
+#define SER_IIR(x) ((x)+2) /* Interrupt Identification Register */
#define SR_IIR_SELF 0x00
#define SR_IIR_ID_MASK 0x07
#define SR_IIR_MSR_CHANGE SR_IIR_SELF
#define SR_IIR_THR_EMPTY (SR_IIR_SELF | 2)
#define SR_IIR_DATA_RECEIVED (SR_IIR_SELF | 4)
#define SR_IIR_ERROR (SR_IIR_SELF | 6)
-#define SER_FCR(x) ((x)+2)
+#define SER_FCR(x) ((x)+2) /* FIFO Control Register (Uart >= 16550A) */
#define SR_FCR_ENABLE_FIFO 0x01
#define SR_FCR_CLEAR_RCVR (0x02 | SR_FCR_ENABLE_FIFO)
#define SR_FCR_CLEAR_XMIT (0x04 | SR_FCR_ENABLE_FIFO)
@@ -143,7 +151,7 @@
#define SR_FCR_4_BYTES (0x40 | SR_FCR_ENABLE_FIFO)
#define SR_FCR_8_BYTES (0x80 | SR_FCR_ENABLE_FIFO)
#define SR_FCR_14_BYTES (0xC0 | SR_FCR_ENABLE_FIFO)
-#define SER_LCR(x) ((x)+3)
+#define SER_LCR(x) ((x)+3) /* Line Control Register */
#define SR_LCR_CS5 0x00
#define SR_LCR_CS6 0x01
#define SR_LCR_CS7 0x02
@@ -157,16 +165,16 @@
#define SR_LCR_PSP 0x38
#define SR_LCR_BRK 0x40
#define SR_LCR_DLAB 0x80
-#define SER_MCR(x) ((x)+4)
+#define SER_MCR(x) ((x)+4) /* Modem Control Register */
#define SR_MCR_DTR 0x01
#define SR_MCR_RTS 0x02
-#define SER_LSR(x) ((x)+5)
+#define SER_LSR(x) ((x)+5) /* Line Status Register */
#define SR_LSR_DR 0x01
#define SR_LSR_TBE 0x20
-#define SER_MSR(x) ((x)+6)
+#define SER_MSR(x) ((x)+6) /* Modem Status Register */
#define SR_MSR_CTS 0x10
#define SR_MSR_DSR 0x20
-#define SER_SCR(x) ((x)+7)
+#define SER_SCR(x) ((x)+7) /* Scratch Pad Register */
/************************************ circularbuffer.c */