- Add synchronization on input and output buffers

- Respect timeouts on IRP_MJ_READ
- Get right buffer in read/write routines

svn path=/trunk/; revision=14297
This commit is contained in:
Hervé Poussineau 2005-03-24 07:50:41 +00:00
parent 974ee62e85
commit 632a47580b
5 changed files with 209 additions and 79 deletions

View file

@ -215,14 +215,23 @@ SerialGetCommStatus(
OUT PSERIAL_STATUS pSerialStatus, OUT PSERIAL_STATUS pSerialStatus,
IN PSERIAL_DEVICE_EXTENSION DeviceExtension) IN PSERIAL_DEVICE_EXTENSION DeviceExtension)
{ {
KIRQL Irql;
RtlZeroMemory(pSerialStatus, sizeof(SERIAL_STATUS)); RtlZeroMemory(pSerialStatus, sizeof(SERIAL_STATUS));
pSerialStatus->Errors = 0; /* FIXME */ pSerialStatus->Errors = 0; /* FIXME */
pSerialStatus->HoldReasons = 0; /* FIXME */ pSerialStatus->HoldReasons = 0; /* FIXME */
KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
pSerialStatus->AmountInInQueue = (DeviceExtension->InputBuffer.WritePosition + DeviceExtension->InputBuffer.Length pSerialStatus->AmountInInQueue = (DeviceExtension->InputBuffer.WritePosition + DeviceExtension->InputBuffer.Length
- DeviceExtension->InputBuffer.ReadPosition) % DeviceExtension->InputBuffer.Length; - DeviceExtension->InputBuffer.ReadPosition) % DeviceExtension->InputBuffer.Length;
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
pSerialStatus->AmountInOutQueue = (DeviceExtension->OutputBuffer.WritePosition + DeviceExtension->OutputBuffer.Length pSerialStatus->AmountInOutQueue = (DeviceExtension->OutputBuffer.WritePosition + DeviceExtension->OutputBuffer.Length
- DeviceExtension->OutputBuffer.ReadPosition) % DeviceExtension->OutputBuffer.Length; - DeviceExtension->OutputBuffer.ReadPosition) % DeviceExtension->OutputBuffer.Length;
KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
pSerialStatus->EofReceived = FALSE; /* FIXME */ pSerialStatus->EofReceived = FALSE; /* FIXME */
pSerialStatus->WaitForImmediate = FALSE; /* FIXME */ pSerialStatus->WaitForImmediate = FALSE; /* FIXME */
@ -497,8 +506,10 @@ SerialDeviceControl(
} }
case IOCTL_SERIAL_PURGE: case IOCTL_SERIAL_PURGE:
{ {
KIRQL Irql1, Irql2;
DPRINT("Serial: IOCTL_SERIAL_PURGE\n"); DPRINT("Serial: IOCTL_SERIAL_PURGE\n");
/* FIXME: lock input and output queues */ KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql1);
KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql2);
DeviceExtension->InputBuffer.ReadPosition = DeviceExtension->InputBuffer.WritePosition = 0; DeviceExtension->InputBuffer.ReadPosition = DeviceExtension->InputBuffer.WritePosition = 0;
DeviceExtension->OutputBuffer.ReadPosition = DeviceExtension->OutputBuffer.WritePosition = 0; DeviceExtension->OutputBuffer.ReadPosition = DeviceExtension->OutputBuffer.WritePosition = 0;
/* Clear receive/transmit buffers */ /* Clear receive/transmit buffers */
@ -507,7 +518,8 @@ SerialDeviceControl(
WRITE_PORT_UCHAR(SER_FCR(ComPortBase), WRITE_PORT_UCHAR(SER_FCR(ComPortBase),
SR_FCR_CLEAR_RCVR | SR_FCR_CLEAR_XMIT); SR_FCR_CLEAR_RCVR | SR_FCR_CLEAR_XMIT);
} }
/* FIXME: unlock input and output queues */ KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql2);
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql1);
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
break; break;
} }
@ -618,18 +630,19 @@ SerialDeviceControl(
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
else else
{ {
KIRQL Irql;
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
if (((PSERIAL_QUEUE_SIZE)Buffer)->InSize > DeviceExtension->InputBuffer.Length) if (((PSERIAL_QUEUE_SIZE)Buffer)->InSize > DeviceExtension->InputBuffer.Length)
{ {
/* FIXME: lock input queue */ KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
Status = IncreaseCircularBufferSize(&DeviceExtension->InputBuffer, ((PSERIAL_QUEUE_SIZE)Buffer)->InSize); Status = IncreaseCircularBufferSize(&DeviceExtension->InputBuffer, ((PSERIAL_QUEUE_SIZE)Buffer)->InSize);
/* FIXME: unlock input queue */ KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
} }
if (NT_SUCCESS(Status) && ((PSERIAL_QUEUE_SIZE)Buffer)->OutSize > DeviceExtension->OutputBuffer.Length) if (NT_SUCCESS(Status) && ((PSERIAL_QUEUE_SIZE)Buffer)->OutSize > DeviceExtension->OutputBuffer.Length)
{ {
/* FIXME: lock output queue */ KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
Status = IncreaseCircularBufferSize(&DeviceExtension->OutputBuffer, ((PSERIAL_QUEUE_SIZE)Buffer)->OutSize); Status = IncreaseCircularBufferSize(&DeviceExtension->OutputBuffer, ((PSERIAL_QUEUE_SIZE)Buffer)->OutSize);
/* FIXME: unlock output queue */ KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
} }
} }
break; break;

View file

@ -60,6 +60,67 @@ ForwardIrpAndForget(
return IoCallDriver(LowerDevice, Irp); return IoCallDriver(LowerDevice, Irp);
} }
VOID STDCALL
SerialReceiveByte(
IN PKDPC Dpc,
IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION
IN PVOID pByte, // real type UCHAR
IN PVOID Unused)
{
PSERIAL_DEVICE_EXTENSION DeviceExtension;
UCHAR Byte;
KIRQL Irql;
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);
KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
Status = PushCircularBufferEntry(&DeviceExtension->InputBuffer, Byte);
if (!NT_SUCCESS(Status))
{
/* FIXME: count buffer overflow */
return;
}
DPRINT1("Serial: push to buffer done\n");
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
InterlockedIncrement(&DeviceExtension->SerialPerfStats.ReceivedCount);
}
VOID STDCALL
SerialSendByte(
IN PKDPC Dpc,
IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION
IN PVOID Unused1,
IN PVOID Unused2)
{
PSERIAL_DEVICE_EXTENSION DeviceExtension;
PUCHAR ComPortBase;
UCHAR Byte;
KIRQL Irql;
NTSTATUS Status;
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)pDeviceExtension;
ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
DPRINT1("Serial: sending bytes (if any) on COM%lu\n",
DeviceExtension->ComPort);
KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
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++;
}
KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
}
BOOLEAN STDCALL BOOLEAN STDCALL
SerialInterruptService( SerialInterruptService(
IN PKINTERRUPT Interrupt, IN PKINTERRUPT Interrupt,
@ -70,7 +131,6 @@ SerialInterruptService(
UCHAR Byte; UCHAR Byte;
PUCHAR ComPortBase; PUCHAR ComPortBase;
UCHAR Iir; UCHAR Iir;
NTSTATUS Status;
DeviceObject = (PDEVICE_OBJECT)ServiceContext; DeviceObject = (PDEVICE_OBJECT)ServiceContext;
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
@ -96,18 +156,7 @@ SerialInterruptService(
case SR_IIR_THR_EMPTY: case SR_IIR_THR_EMPTY:
{ {
DPRINT("Serial: SR_IIR_THR_EMPTY\n"); DPRINT("Serial: SR_IIR_THR_EMPTY\n");
/* FIXME: lock OutputBuffer */ return KeInsertQueueDpc(&DeviceExtension->SendByteDpc, NULL, NULL);
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: case SR_IIR_DATA_RECEIVED:
{ {
@ -116,19 +165,10 @@ SerialInterruptService(
{ {
Byte = READ_PORT_UCHAR(SER_RBR(ComPortBase)); Byte = READ_PORT_UCHAR(SER_RBR(ComPortBase));
DPRINT1("Serial: Byte received: 0x%02x (%c)\n", Byte, Byte); DPRINT1("Serial: Byte received: 0x%02x (%c)\n", Byte, Byte);
/* FIXME: lock InputBuffer */ if (!KeInsertQueueDpc(&DeviceExtension->ReceivedByteDpc, (PVOID)(ULONG_PTR)Byte, NULL))
Status = PushCircularBufferEntry(&DeviceExtension->InputBuffer, Byte);
if (!NT_SUCCESS(Status))
{
/* FIXME: count buffer overflow */
break; break;
}
DPRINT1("Serial: push to buffer done\n");
/* FIXME: unlock InputBuffer */
DeviceExtension->SerialPerfStats.ReceivedCount++;
} }
return TRUE; return TRUE;
break;
} }
case SR_IIR_ERROR: case SR_IIR_ERROR:
{ {

View file

@ -76,6 +76,10 @@ SerialAddDeviceInternal(
Status = InitializeCircularBuffer(&DeviceExtension->OutputBuffer, 16); Status = InitializeCircularBuffer(&DeviceExtension->OutputBuffer, 16);
if (!NT_SUCCESS(Status)) goto ByeBye; if (!NT_SUCCESS(Status)) goto ByeBye;
IoInitializeRemoveLock(&DeviceExtension->RemoveLock, SERIAL_TAG, 0, 0); IoInitializeRemoveLock(&DeviceExtension->RemoveLock, SERIAL_TAG, 0, 0);
KeInitializeSpinLock(&DeviceExtension->InputBufferLock);
KeInitializeSpinLock(&DeviceExtension->OutputBufferLock);
KeInitializeDpc(&DeviceExtension->ReceivedByteDpc, SerialReceiveByte, DeviceExtension);
KeInitializeDpc(&DeviceExtension->SendByteDpc, SerialSendByte, DeviceExtension);
//Fdo->Flags |= DO_POWER_PAGEABLE (or DO_POWER_INRUSH?) //Fdo->Flags |= DO_POWER_PAGEABLE (or DO_POWER_INRUSH?)
Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice); Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -152,13 +156,7 @@ SerialPnpStartDevice(
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* FIXME: actually, IRP_MN_START_DEVICE is sent twice to each serial device: ASSERT(DeviceExtension->PnpState == dsStopped);
* - one when loading serial.sys
* - one when loading attached upper filter serenum.sys
* This behaviour MUST NOT exist.
* As PnP handling isn't right anyway, I didn't search how to correct this.
*/
if (DeviceExtension->PnpState == dsStarted) return STATUS_SUCCESS;
DeviceExtension->ComPort = DeviceExtension->SerialPortNumber + 1; DeviceExtension->ComPort = DeviceExtension->SerialPortNumber + 1;
DeviceExtension->BaudRate = 19200 | SERIAL_BAUD_USER; DeviceExtension->BaudRate = 19200 | SERIAL_BAUD_USER;

View file

@ -16,12 +16,8 @@ static PVOID
SerialGetUserBuffer(IN PIRP Irp) SerialGetUserBuffer(IN PIRP Irp)
{ {
ASSERT(Irp); ASSERT(Irp);
if (Irp->MdlAddress) return Irp->AssociatedIrp.SystemBuffer;
return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
else
/* FIXME: try buffer */
return Irp->UserBuffer;
} }
NTSTATUS STDCALL NTSTATUS STDCALL
@ -36,6 +32,7 @@ SerialRead(
PUCHAR Buffer; PUCHAR Buffer;
PUCHAR ComPortBase; PUCHAR ComPortBase;
UCHAR ReceivedByte; UCHAR ReceivedByte;
KIRQL Irql;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
DPRINT("Serial: IRP_MJ_READ\n"); DPRINT("Serial: IRP_MJ_READ\n");
@ -64,8 +61,8 @@ SerialRead(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
goto ByeBye; goto ByeBye;
/* FIXME: lock InputBuffer */ KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
while (Length-- > 0 && !IsCircularBufferEmpty(&DeviceExtension->InputBuffer)) while (Length-- > 0)
{ {
Status = PopCircularBufferEntry(&DeviceExtension->InputBuffer, &ReceivedByte); Status = PopCircularBufferEntry(&DeviceExtension->InputBuffer, &ReceivedByte);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -73,54 +70,117 @@ SerialRead(
DPRINT("Serial: read from buffer 0x%x (%c)\n", ReceivedByte, ReceivedByte); DPRINT("Serial: read from buffer 0x%x (%c)\n", ReceivedByte, ReceivedByte);
Buffer[Information++] = ReceivedByte; Buffer[Information++] = ReceivedByte;
} }
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
if (Length > 0 && if (Length > 0 &&
!(DeviceExtension->SerialTimeOuts.ReadIntervalTimeout == INFINITE && !(DeviceExtension->SerialTimeOuts.ReadIntervalTimeout == INFINITE &&
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant == 0 && DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant == 0 &&
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier == 0)) DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier == 0))
{ {
if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout == 0 ULONG IntervalTimeout;
|| DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier == 0) ULONG TotalTimeout;
BOOLEAN UseIntervalTimeout = FALSE;
BOOLEAN UseTotalTimeout = FALSE;
ULONG ThisByteTimeout;
BOOLEAN IsByteReceived;
ULONG i;
/* Extract timeouts informations */
if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout == INFINITE &&
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier == INFINITE &&
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant > 0 &&
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant < INFINITE)
{ {
DPRINT("Serial: we must wait for %lu characters!\n", Length); if (Information > 0)
#if 1
/* Disable interrupts */
WRITE_PORT_UCHAR(SER_IER((PUCHAR)DeviceExtension->BaseAddress), DeviceExtension->IER & ~1);
/* Polling code */
while (Length > 0)
{ {
while ((READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_DR) == 0) /* don't read mode bytes */
; Length = 0;
ReceivedByte = READ_PORT_UCHAR(SER_RBR(ComPortBase));
Buffer[Information++] = ReceivedByte;
Length--;
} }
/* Enable interrupts */ else
WRITE_PORT_UCHAR(SER_IER((PUCHAR)DeviceExtension->BaseAddress), DeviceExtension->IER);
#else
while (Length > 0)
{ {
if (!IsCircularBufferEmpty(&DeviceExtension->InputBuffer)) /* read only one byte */
{ UseTotalTimeout = TRUE;
Status = PopCircularBufferEntry(&DeviceExtension->InputBuffer, &ReceivedByte); TotalTimeout = DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant;
if (!NT_SUCCESS(Status)) Length = 1;
break;
DPRINT1("Serial: read from buffer 0x%x (%c)\n", ReceivedByte, ReceivedByte);
Buffer[Information++] = ReceivedByte;
Length--;
}
} }
#endif
} }
else else
{ {
/* FIXME: use ReadTotalTimeoutMultiplier and ReadTotalTimeoutConstant */ if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout != 0)
DPRINT1("Serial: we must wait for %lu characters at maximum within %lu milliseconds! UNIMPLEMENTED\n", {
Length, UseIntervalTimeout = TRUE;
Stack->Parameters.Read.Length * DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier + DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant); IntervalTimeout = DeviceExtension->SerialTimeOuts.ReadIntervalTimeout;
}
if (DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant != 0 ||
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier != 0)
{
UseTotalTimeout = TRUE;
TotalTimeout = DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant +
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier * Length;
}
} }
DPRINT("Serial: UseIntervalTimeout = %ws, IntervalTimeout = %lu\n",
UseIntervalTimeout ? L"YES" : L"NO",
UseIntervalTimeout ? IntervalTimeout : 0);
DPRINT("Serial: UseTotalTimeout = %ws, TotalTimeout = %lu\n",
UseTotalTimeout ? L"YES" : L"NO",
UseTotalTimeout ? TotalTimeout : 0);
/* FIXME: it should be better to use input buffer instead of
* disabling interrupts, and try to directly read for port! */
/* FIXME: NtQueryPerformanceCounter gives a more accurate
* timer, but it is not available on all computers. First try
* NtQueryPerformanceCounter, and current method if it is not
* implemented. */
/* FIXME: remove disabling interrupts */
WRITE_PORT_UCHAR(SER_IER(ComPortBase), DeviceExtension->IER & ~1);
while (Length > 0)
{
ThisByteTimeout = IntervalTimeout;
IsByteReceived = FALSE;
while (TRUE)
{
for (i = 0; i < 1000; i++)
{
#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
KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
if (!IsCircularBufferEmpty(&DeviceExtension->InputBuffer))
{
PopCircularBufferEntry(&DeviceExtension->InputBuffer, &ReceivedByte);
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
DPRINT("Serial: reading byte from buffer 0x%02x (%c)\n", ReceivedByte, ReceivedByte);
IsByteReceived = TRUE;
break;
}
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
#endif
KeStallExecutionProcessor(1);
}
if (IsByteReceived) break;
if (UseIntervalTimeout)
{
if (ThisByteTimeout == 0) break; else ThisByteTimeout--;
}
if (UseTotalTimeout)
{
if (TotalTimeout == 0) break; else TotalTimeout--;
}
}
if (!IsByteReceived) break;
Buffer[Information++] = ReceivedByte;
Length--;
}
/* FIXME: remove enabling interrupts */
WRITE_PORT_UCHAR(SER_IER(ComPortBase), DeviceExtension->IER);
} }
/* FIXME: unlock InputBuffer */
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
@ -143,6 +203,7 @@ SerialWrite(
ULONG Information = 0; ULONG Information = 0;
PUCHAR Buffer; PUCHAR Buffer;
PUCHAR ComPortBase; PUCHAR ComPortBase;
KIRQL Irql;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
DPRINT("Serial: IRP_MJ_WRITE\n"); DPRINT("Serial: IRP_MJ_WRITE\n");
@ -166,7 +227,7 @@ SerialWrite(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
goto ByeBye; goto ByeBye;
/* FIXME: lock OutputBuffer */ KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
if (IsCircularBufferEmpty(&DeviceExtension->OutputBuffer)) if (IsCircularBufferEmpty(&DeviceExtension->OutputBuffer))
{ {
/* Put the maximum amount of data in UART output buffer */ /* Put the maximum amount of data in UART output buffer */
@ -197,7 +258,7 @@ SerialWrite(
DPRINT1("Serial: write to buffer 0x%02x\n", Buffer[Information]); DPRINT1("Serial: write to buffer 0x%02x\n", Buffer[Information]);
Information++; Information++;
} }
/* FIXME: unlock OutputBuffer */ KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
ByeBye: ByeBye:

View file

@ -81,6 +81,8 @@ typedef struct _SERIAL_DEVICE_EXTENSION
ULONG BaudRate; ULONG BaudRate;
ULONG BaseAddress; ULONG BaseAddress;
PKINTERRUPT Interrupt; PKINTERRUPT Interrupt;
KDPC ReceivedByteDpc;
KDPC SendByteDpc;
SERIAL_LINE_CONTROL SerialLineControl; SERIAL_LINE_CONTROL SerialLineControl;
UART_TYPE UartType; UART_TYPE UartType;
@ -90,7 +92,9 @@ typedef struct _SERIAL_DEVICE_EXTENSION
SERIAL_TIMEOUTS SerialTimeOuts; SERIAL_TIMEOUTS SerialTimeOuts;
BOOLEAN IsOpened; BOOLEAN IsOpened;
CIRCULAR_BUFFER InputBuffer; CIRCULAR_BUFFER InputBuffer;
KSPIN_LOCK InputBufferLock;
CIRCULAR_BUFFER OutputBuffer; CIRCULAR_BUFFER OutputBuffer;
KSPIN_LOCK OutputBufferLock;
/* Current values */ /* Current values */
UCHAR IER; /* Base+1, Interrupt Enable Register */ UCHAR IER; /* Base+1, Interrupt Enable Register */
@ -250,6 +254,20 @@ ForwardIrpAndForget(
IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp); IN PIRP Irp);
VOID STDCALL
SerialReceiveByte(
IN PKDPC Dpc,
IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION
IN PVOID pByte, // real type UCHAR
IN PVOID Unused);
VOID STDCALL
SerialSendByte(
IN PKDPC Dpc,
IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION
IN PVOID Unused1,
IN PVOID Unused2);
BOOLEAN STDCALL BOOLEAN STDCALL
SerialInterruptService( SerialInterruptService(
IN PKINTERRUPT Interrupt, IN PKINTERRUPT Interrupt,