Start of the serial driver: Handle write support and some IOCTL codes First serial port is mapped to COM3 and second serial port is mapped to COM4. This prevents conflicts with existing code. Added: trunk/reactos/drivers/dd/serial/cleanup.c Added: trunk/reactos/drivers/dd/serial/close.c Added: trunk/reactos/drivers/dd/serial/create.c Added: trunk/reactos/drivers/dd/serial/devctrl.c Added: trunk/reactos/drivers/dd/serial/info.c Modified: trunk/reactos/drivers/dd/serial/makefile Added: trunk/reactos/drivers/dd/serial/misc.c Added: trunk/reactos/drivers/dd/serial/pnp.c Added: trunk/reactos/drivers/dd/serial/power.c Added: trunk/reactos/drivers/dd/serial/rw.c Modified: trunk/reactos/drivers/dd/serial/serial.c Added: trunk/reactos/drivers/dd/serial/serial.h _____
Added: trunk/reactos/drivers/dd/serial/cleanup.c --- trunk/reactos/drivers/dd/serial/cleanup.c 2005-03-14 20:38:32 UTC (rev 14073) +++ trunk/reactos/drivers/dd/serial/cleanup.c 2005-03-14 20:59:50 UTC (rev 14074) @@ -0,0 +1,22 @@
+/* $Id: + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: drivers/dd/serial/cleanup.c + * PURPOSE: Serial IRP_MJ_CLEANUP operations + * + * PROGRAMMERS: HervÚ Poussineau (poussine@freesurf.fr) + */ + +#define NDEBUG +#include "serial.h" + +NTSTATUS STDCALL +SerialCleanup( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT("Serial: IRP_MJ_CLEANUP\n"); + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} _____
Added: trunk/reactos/drivers/dd/serial/close.c --- trunk/reactos/drivers/dd/serial/close.c 2005-03-14 20:38:32 UTC (rev 14073) +++ trunk/reactos/drivers/dd/serial/close.c 2005-03-14 20:59:50 UTC (rev 14074) @@ -0,0 +1,22 @@
+/* $Id: + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: drivers/dd/serial/close.c + * PURPOSE: Serial IRP_MJ_CLOSE operations + * + * PROGRAMMERS: HervÚ Poussineau (poussine@freesurf.fr) + */ + +#define NDEBUG +#include "serial.h" + +NTSTATUS STDCALL +SerialClose( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT("Serial: IRP_MJ_CLOSE\n"); + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} _____
Added: trunk/reactos/drivers/dd/serial/create.c --- trunk/reactos/drivers/dd/serial/create.c 2005-03-14 20:38:32 UTC (rev 14073) +++ trunk/reactos/drivers/dd/serial/create.c 2005-03-14 20:59:50 UTC (rev 14074) @@ -0,0 +1,52 @@
+/* $Id: + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: drivers/dd/serial/create.c + * PURPOSE: Serial IRP_MJ_CREATE operations + * + * PROGRAMMERS: HervÚ Poussineau (poussine@freesurf.fr) + */ + +#define NDEBUG +#include "serial.h" + +NTSTATUS STDCALL +SerialCreate( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + PSERIAL_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + + DPRINT("Serial: IRP_MJ_CREATE\n"); + Stack = IoGetCurrentIrpStackLocation(Irp); + FileObject = Stack->FileObject; + DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (Stack->Parameters.Create.Options & FILE_DIRECTORY_FILE) + { + CHECKPOINT; + Status = STATUS_NOT_A_DIRECTORY; + goto ByeBye; + } + + if (FileObject->FileName.Length != 0 || + FileObject->RelatedFileObject != NULL) + { + CHECKPOINT; + Status = STATUS_ACCESS_DENIED; + goto ByeBye; + } + + DPRINT("Serial: open COM%lu: successfull\n", DeviceExtension->ComPort); + Status = STATUS_SUCCESS; + +ByeBye: + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; +} _____
Added: trunk/reactos/drivers/dd/serial/devctrl.c --- trunk/reactos/drivers/dd/serial/devctrl.c 2005-03-14 20:38:32 UTC (rev 14073) +++ trunk/reactos/drivers/dd/serial/devctrl.c 2005-03-14 20:59:50 UTC (rev 14074) @@ -0,0 +1,551 @@
+/* $Id: + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: drivers/dd/serial/devctrl.c + * PURPOSE: Serial IRP_MJ_DEVICE_CONTROL operations + * + * PROGRAMMERS: HervÚ Poussineau (poussine@freesurf.fr) + */ +/* FIXME: call IoAcquireRemoveLock/IoReleaseRemoveLock around each I/O operation */ + +#define NDEBUG +#include "serial.h" + +NTSTATUS STDCALL +SerialSetBaudRate( + IN PSERIAL_DEVICE_EXTENSION DeviceExtension, + IN ULONG NewBaudRate) +{ + USHORT divisor; + PUCHAR ComPortBase = (PUCHAR)DeviceExtension->BaseAddress; + NTSTATUS Status = STATUS_SUCCESS; + + if (NewBaudRate & SERIAL_BAUD_USER) + { + divisor = (USHORT)(BAUD_CLOCK / (CLOCKS_PER_BIT * (NewBaudRate & ~SERIAL_BAUD_USER))); + } + 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; + default: Status = STATUS_INVALID_PARAMETER; + } + } + + if (NT_SUCCESS(Status)) + { + Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort); + if (NT_SUCCESS(Status)) + { + UCHAR Lcr; + DPRINT("Serial: SerialSetBaudRate(COM%lu, %lu Bauds)\n", DeviceExtension->ComPort, BAUD_CLOCK / (CLOCKS_PER_BIT * divisor)); + /* FIXME: update DeviceExtension->LowerDevice when modifying LCR? */ + /* Set Bit 7 of LCR to expose baud registers */ + Lcr = READ_PORT_UCHAR(SER_LCR(ComPortBase)); + Lcr |= SR_LCR_DLAB; + WRITE_PORT_UCHAR(SER_LCR(ComPortBase), Lcr); + /* Write the baud rate */ + WRITE_PORT_UCHAR(SER_DLL(ComPortBase), divisor & 0xff); + WRITE_PORT_UCHAR(SER_DLM(ComPortBase), divisor
8);
+ /* Switch back to normal registers */ + Lcr ^= SR_LCR_DLAB; + WRITE_PORT_UCHAR(SER_LCR(ComPortBase), Lcr); + + IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort); + } + } + + if (NT_SUCCESS(Status)) + DeviceExtension->BaudRate = NewBaudRate; + return Status; +} + +NTSTATUS STDCALL +SerialSetLineControl( + IN PSERIAL_DEVICE_EXTENSION DeviceExtension, + IN PSERIAL_LINE_CONTROL NewSettings) +{ + UCHAR Lcr = 0; + NTSTATUS Status; + + DPRINT("Serial: SerialSetLineControl(COM%lu, Settings { %lu %lu %lu })\n", + DeviceExtension->ComPort, NewSettings->StopBits, NewSettings->Parity, NewSettings->WordLength); + + /* Verify parameters */ + switch (NewSettings->WordLength) + { + case 5: Lcr |= SR_LCR_CS5; break; + case 6: Lcr |= SR_LCR_CS6; break; + case 7: Lcr |= SR_LCR_CS7; break; + case 8: Lcr |= SR_LCR_CS8; break; + default: return STATUS_INVALID_PARAMETER; + } + + if (NewSettings->WordLength < 5 || NewSettings->WordLength > 8) + return STATUS_INVALID_PARAMETER; + + switch (NewSettings->Parity) + { + case NO_PARITY: Lcr |= SR_LCR_PNO; break; + case ODD_PARITY: Lcr |= SR_LCR_POD; break; + case EVEN_PARITY: Lcr |= SR_LCR_PEV; break; + case MARK_PARITY: Lcr |= SR_LCR_PMK; break; + case SPACE_PARITY: Lcr |= SR_LCR_PSP; break; + default: return STATUS_INVALID_PARAMETER; + } + + switch (NewSettings->StopBits) + { + case STOP_BIT_1: + Lcr |= SR_LCR_ST1; + break; + case STOP_BITS_1_5: + if (NewSettings->WordLength != 5) + return STATUS_INVALID_PARAMETER; + Lcr |= SR_LCR_ST2; + break; + case STOP_BITS_2: + if (NewSettings->WordLength < 6 || NewSettings->WordLength > 8) + return STATUS_INVALID_PARAMETER; + Lcr |= SR_LCR_ST2; + break; + default: + return STATUS_INVALID_PARAMETER; + } + + /* Update current parameters */ + Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort); + if (!NT_SUCCESS(Status)) + return Status; + WRITE_PORT_UCHAR(SER_LCR((PUCHAR)DeviceExtension->BaseAddress), Lcr); + IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort); + + if (NT_SUCCESS(Status)) + DeviceExtension->SerialLineControl = *NewSettings; + + return Status; +} + +NTSTATUS STDCALL +SerialDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + PSERIAL_DEVICE_EXTENSION DeviceExtension; + ULONG LengthIn, LengthOut; + ULONG Information = 0; + PUCHAR Buffer; + PUCHAR ComPortBase; + NTSTATUS Status; + + DPRINT("Serial: IRP_MJ_DEVICE_CONTROL dispatch\n"); + + /* FIXME: pend operation if possible */ + + Stack = IoGetCurrentIrpStackLocation(Irp); + LengthIn = Stack->Parameters.DeviceIoControl.InputBufferLength; + LengthOut = Stack->Parameters.DeviceIoControl.OutputBufferLength; + Buffer = Irp->AssociatedIrp.SystemBuffer; + DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + ComPortBase = (PUCHAR)DeviceExtension->BaseAddress; + + /* FIXME: need to probe buffers */ + /* FIXME: see http://www.osronline.com/ddkx/serial/serref_61bm.htm */ + switch (Stack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_SERIAL_CLEAR_STATS: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_CLEAR_STATS not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_CLR_DTR: + { + DPRINT("Serial: IOCTL_SERIAL_CLR_DTR\n"); + /* FIXME: If the handshake flow control of the device is configured to + * automatically use DTR, return STATUS_INVALID_PARAMETER */ + DeviceExtension->MCR &= ~SR_MCR_DTR; + WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR); + Status = STATUS_SUCCESS; + break; + } + case IOCTL_SERIAL_CLR_RTS: + { + DPRINT("Serial: IOCTL_SERIAL_CLR_RTS\n"); + /* FIXME: If the handshake flow control of the device is configured to + * automatically use RTS, return STATUS_INVALID_PARAMETER */ + DeviceExtension->MCR &= ~SR_MCR_RTS; + WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR); + Status = STATUS_SUCCESS; + break; + } + case IOCTL_SERIAL_CONFIG_SIZE: + { + /* Obsolete on Microsoft Windows 2000+ */ + PULONG pConfigSize; + DPRINT("Serial: IOCTL_SERIAL_CONFIG_SIZE\n"); + if (LengthOut != sizeof(ULONG) || Buffer == NULL) + Status = STATUS_INVALID_PARAMETER; + else + { + pConfigSize = (PULONG)Buffer; + *pConfigSize = 0; + Status = STATUS_SUCCESS; + } + break; + } + case IOCTL_SERIAL_GET_BAUD_RATE: + { + DPRINT("Serial: IOCTL_SERIAL_GET_BAUD_RATE\n"); + if (LengthOut < sizeof(SERIAL_BAUD_RATE)) + Status = STATUS_BUFFER_TOO_SMALL; + else if (Buffer == NULL) + Status = STATUS_INVALID_PARAMETER; + else + { + ((PSERIAL_BAUD_RATE)Buffer)->BaudRate = DeviceExtension->BaudRate; + Information = sizeof(SERIAL_BAUD_RATE); + Status = STATUS_SUCCESS; + } + } + case IOCTL_SERIAL_GET_CHARS: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_GET_CHARS not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_GET_COMMSTATUS: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_GET_COMMSTATUS not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_GET_DTRRTS: + { + PULONG pDtrRts; + DPRINT("Serial: IOCTL_SERIAL_GET_DTRRTS\n"); + if (LengthOut != sizeof(ULONG) || Buffer == NULL) + Status = STATUS_INVALID_PARAMETER; + else + { + pDtrRts = (PULONG)Buffer; + *pDtrRts = 0; + if (DeviceExtension->MCR & SR_MCR_DTR) + *pDtrRts |= SERIAL_DTR_STATE; + if (DeviceExtension->MCR & SR_MCR_RTS) + *pDtrRts |= SERIAL_RTS_STATE; + Status = STATUS_SUCCESS; + } + break; + } + case IOCTL_SERIAL_GET_HANDFLOW: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_GET_HANDFLOW not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_GET_LINE_CONTROL: + { + DPRINT("Serial: IOCTL_SERIAL_GET_LINE_CONTROL\n"); + if (LengthOut < sizeof(SERIAL_LINE_CONTROL)) + Status = STATUS_BUFFER_TOO_SMALL; + else if (Buffer == NULL) + Status = STATUS_INVALID_PARAMETER; + else + { + *((PSERIAL_LINE_CONTROL)Buffer) = DeviceExtension->SerialLineControl; + Information = sizeof(SERIAL_LINE_CONTROL); + Status = STATUS_SUCCESS; + } + break; + } + case IOCTL_SERIAL_GET_MODEM_CONTROL: + { + PULONG pMCR; + DPRINT("Serial: IOCTL_SERIAL_GET_MODEM_CONTROL\n"); + if (LengthOut != sizeof(ULONG) || Buffer == NULL) + Status = STATUS_INVALID_PARAMETER; + else + { + pMCR = (PULONG)Buffer; + *pMCR = DeviceExtension->MCR; + Status = STATUS_SUCCESS; + } + break; + } + case IOCTL_SERIAL_GET_MODEMSTATUS: + { + PULONG pMSR; + DPRINT("Serial: IOCTL_SERIAL_GET_MODEMSTATUS\n"); + if (LengthOut != sizeof(ULONG) || Buffer == NULL) + Status = STATUS_INVALID_PARAMETER; + else + { + pMSR = (PULONG)Buffer; + *pMSR = DeviceExtension->MSR; + Status = STATUS_SUCCESS; + } + break; + } + case IOCTL_SERIAL_GET_PROPERTIES: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_GET_PROPERTIES not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_GET_STATS: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_GET_STATS not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_GET_TIMEOUTS: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_GET_TIMEOUTS not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_GET_WAIT_MASK: + { + PULONG pWaitMask; + DPRINT("Serial: IOCTL_SERIAL_GET_WAIT_MASK\n"); + if (LengthOut != sizeof(ULONG) || Buffer == NULL) + Status = STATUS_INVALID_PARAMETER; + else + { + pWaitMask = (PULONG)Buffer; + *pWaitMask = DeviceExtension->WaitMask; + Status = STATUS_SUCCESS; + } + break; + } + case IOCTL_SERIAL_IMMEDIATE_CHAR: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_IMMEDIATE_CHAR not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_LSRMST_INSERT: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_LSRMST_INSERT not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_PURGE: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_PURGE not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_RESET_DEVICE: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_RESET_DEVICE not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_SET_BAUD_RATE: + { + PULONG pNewBaudRate; + DPRINT("Serial: IOCTL_SERIAL_SET_BAUD_RATE\n"); + if (LengthIn != sizeof(ULONG) || Buffer == NULL) + Status = STATUS_INVALID_PARAMETER; + else + { + pNewBaudRate = (PULONG)Buffer; + Status = SerialSetBaudRate(DeviceExtension, *pNewBaudRate); + } + break; + } + case IOCTL_SERIAL_SET_BREAK_OFF: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_SET_BREAK_OFF not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_SET_BREAK_ON: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_SET_BREAK_ON not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_SET_CHARS: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_SET_CHARS not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_SET_DTR: + { + /* FIXME: If the handshake flow control of the device is configured to + * automatically use DTR, return STATUS_INVALID_PARAMETER */ + DPRINT("Serial: IOCTL_SERIAL_SET_DTR\n"); + if (!(DeviceExtension->MCR & SR_MCR_DTR)) + { + DeviceExtension->MCR |= SR_MCR_DTR; + WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR); + } + Status = STATUS_SUCCESS; + break; + } + case IOCTL_SERIAL_SET_FIFO_CONTROL: + { + DPRINT("Serial: IOCTL_SERIAL_SET_FIFO_CONTROL\n"); + if (LengthIn != sizeof(ULONG) || Buffer == NULL) + Status = STATUS_INVALID_PARAMETER; + else + { + WRITE_PORT_UCHAR(SER_FCR(ComPortBase), (UCHAR)((*(PULONG)Buffer) & 0xff)); + Status = STATUS_SUCCESS; + } + break; + } + case IOCTL_SERIAL_SET_HANDFLOW: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_SET_HANDFLOW not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_SET_LINE_CONTROL: + { + DPRINT("Serial: IOCTL_SERIAL_SET_LINE_CONTROL\n"); + if (LengthIn < sizeof(SERIAL_LINE_CONTROL)) + Status = STATUS_BUFFER_TOO_SMALL; + else if (Buffer == NULL) + Status = STATUS_INVALID_PARAMETER; + else + Status = SerialSetLineControl(DeviceExtension, (PSERIAL_LINE_CONTROL)Buffer); + break; + } + case IOCTL_SERIAL_SET_MODEM_CONTROL: + { + PULONG pMCR; + DPRINT("Serial: IOCTL_SERIAL_SET_MODEM_CONTROL\n"); + if (LengthIn != sizeof(ULONG) || Buffer == NULL) + Status = STATUS_INVALID_PARAMETER; + else + { + pMCR = (PULONG)Buffer; + DeviceExtension->MCR = (UCHAR)(*pMCR & 0xff); + WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR); + Status = STATUS_SUCCESS; + } + break; + } + case IOCTL_SERIAL_SET_QUEUE_SIZE: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_SET_QUEUE_SIZE not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_SET_RTS: + { + /* FIXME: If the handshake flow control of the device is configured to + * automatically use DTR, return STATUS_INVALID_PARAMETER */ + DPRINT("Serial: IOCTL_SERIAL_SET_RTS\n"); + if (!(DeviceExtension->MCR & SR_MCR_RTS)) + { + DeviceExtension->MCR |= SR_MCR_RTS; + WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR); + } + Status = STATUS_SUCCESS; + break; + } + case IOCTL_SERIAL_SET_TIMEOUTS: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_SET_TIMEOUTS not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_SET_WAIT_MASK: + { + PULONG pWaitMask; + DPRINT("Serial: IOCTL_SERIAL_SET_WAIT_MASK\n"); + if (LengthIn != sizeof(ULONG) || Buffer == NULL) + Status = STATUS_INVALID_PARAMETER; + else + { + pWaitMask = (PULONG)Buffer; + DeviceExtension->WaitMask = *pWaitMask; + Status = STATUS_SUCCESS; + } + break; + } + case IOCTL_SERIAL_SET_XOFF: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_SET_XOFF not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_SET_XON: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_SET_XON not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_WAIT_ON_MASK: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_WAIT_ON_MASK not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_SERIAL_XOFF_COUNTER: + { + /* FIXME */ + DPRINT1("Serial: IOCTL_SERIAL_XOFF_COUNTER not implemented.\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + default: + { + /* Pass Irp to lower driver */ + DPRINT("Serial: Unknown IOCTL code 0x%x\n", Stack->Parameters.DeviceIoControl.IoControlCode); + IoSkipCurrentIrpStackLocation(Irp); + return IoCallDriver(DeviceExtension->LowerDevice, Irp); + } + } + + Irp->IoStatus.Information = Information; + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; +} _____
Added: trunk/reactos/drivers/dd/serial/info.c --- trunk/reactos/drivers/dd/serial/info.c 2005-03-14 20:38:32 UTC (rev 14073) +++ trunk/reactos/drivers/dd/serial/info.c 2005-03-14 20:59:50 UTC (rev 14074) @@ -0,0 +1,79 @@
+/* $Id: + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: drivers/dd/serial/info.c + * PURPOSE: Serial IRP_MJ_QUERY_INFORMATION operations + * + * PROGRAMMERS: HervÚ Poussineau (poussine@freesurf.fr) + */ + +#define NDEBUG2 +#include "serial.h" + +NTSTATUS STDCALL +SerialQueryInformation( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PSERIAL_DEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION Stack; + PVOID SystemBuffer; + ULONG BufferLength; + NTSTATUS Status; + + DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + Stack = IoGetCurrentIrpStackLocation(Irp); + SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + BufferLength = Stack->Parameters.QueryFile.Length; + + switch (Stack->Parameters.QueryFile.FileInformationClass) + { + case FileStandardInformation: + { + PFILE_STANDARD_INFORMATION StandardInfo = (PFILE_STANDARD_INFORMATION)SystemBuffer; + + DPRINT("Serial: IRP_MJ_QUERY_INFORMATION / FileStandardInformation\n"); + if (BufferLength < sizeof(FILE_STANDARD_INFORMATION)) + Status = STATUS_BUFFER_OVERFLOW; + else + { + StandardInfo->AllocationSize.QuadPart = 0; + StandardInfo->EndOfFile.QuadPart = 0; + StandardInfo->Directory = FALSE; + StandardInfo->NumberOfLinks = 0; + 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: + { + PFILE_POSITION_INFORMATION PositionInfo = (PFILE_POSITION_INFORMATION)SystemBuffer; + + DPRINT("Serial: IRP_MJ_QUERY_INFORMATION / FilePositionInformation\n"); + if (BufferLength < sizeof(PFILE_POSITION_INFORMATION)) + Status = STATUS_BUFFER_OVERFLOW; + else + { + 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 Status; +} _____
Modified: trunk/reactos/drivers/dd/serial/makefile --- trunk/reactos/drivers/dd/serial/makefile 2005-03-14 20:38:32 UTC (rev 14073) +++ trunk/reactos/drivers/dd/serial/makefile 2005-03-14 20:59:50 UTC (rev 14074) @@ -6,7 +6,17 @@
TARGET_NAME = serial
-TARGET_OBJECTS = serial.o +TARGET_OBJECTS = \ + cleanup.o \ + close.o \ + create.o \ + devctrl.o \ + info.o \ + misc.o \ + pnp.o \ + power.o \ + rw.o \ + serial.o
TARGET_CFLAGS = -Wall -Werror -D__USE_W32API
_____
Added: trunk/reactos/drivers/dd/serial/misc.c --- trunk/reactos/drivers/dd/serial/misc.c 2005-03-14 20:38:32 UTC (rev 14073) +++ trunk/reactos/drivers/dd/serial/misc.c 2005-03-14 20:59:50 UTC (rev 14074) @@ -0,0 +1,175 @@
+/* $Id: + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: drivers/dd/serial/misc.c + * PURPOSE: Misceallenous operations + * + * PROGRAMMERS: HervÚ Poussineau (poussine@freesurf.fr) + */ + +#define NDEBUG +#include "serial.h" + +NTSTATUS +ForwardIrpAndWaitCompletion( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context) +{ + if (Irp->PendingReturned) + KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE); + return STATUS_MORE_PROCESSING_REQUIRED; +} + +NTSTATUS +ForwardIrpAndWait( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PDEVICE_OBJECT LowerDevice = ((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice; + KEVENT Event; + NTSTATUS Status; + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + IoCopyCurrentIrpStackLocationToNext(Irp); + + DPRINT("Serial: Calling lower device %p [%wZ]\n", LowerDevice, &LowerDevice->DriverObject->DriverName); + IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE); + + Status = IoCallDriver(LowerDevice, Irp); + if (Status == STATUS_PENDING) + { + Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); + if (NT_SUCCESS(Status)) + Status = Irp->IoStatus.Status; + } + + return Status; +} + +BOOLEAN STDCALL +SerialInterruptService( + IN PKINTERRUPT Interrupt, + IN OUT PVOID ServiceContext) +{ + PDEVICE_OBJECT DeviceObject; + PSERIAL_DEVICE_EXTENSION DeviceExtension; + PUCHAR ComPortBase; + UCHAR Iir; + + 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); + + switch (Iir) + { + case SR_IIR_MSR_CHANGE: + { + 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; + } + 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 );*/ + } + case SR_IIR_DATA_RECEIVED: + { + DPRINT1("Serial: SR_IIR_DATA_RECEIVED\n"); + if (READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_DR) + { + DPRINT1("Serial: Byte received: 0x%x\n", READ_PORT_UCHAR(SER_RBR(ComPortBase))); + 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: + { + DPRINT1("Serial: SR_IIR_ERROR\n"); + break; + /*Error = READ_PORT_UCHAR( Self->Port + UART_LSR ); + if( Error & LSR_OVERRUN ) + Self->WaitingReadBytes.PushBack( SerialFifo::OVERRUN ); + if( Error & LSR_PARITY_ERROR ) + Self->WaitingReadBytes.PushBack( SerialFifo::PARITY ); + if( Error & LSR_FRAMING_ERROR ) + Self->WaitingReadBytes.PushBack( SerialFifo::FRAMING ); + if( Error & LSR_BREAK ) + Self->WaitingReadBytes.PushBack( SerialFifo::BREAK ); + if( Error & LSR_TIMEOUT ) + Self->WaitingReadBytes.PushBack( SerialFifo::TIMEOUT ); + return KeInsertQueueDpc( &Self->DataInDpc, Self, 0 );*/ + } + } + 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 +} _____
Added: trunk/reactos/drivers/dd/serial/pnp.c --- trunk/reactos/drivers/dd/serial/pnp.c 2005-03-14 20:38:32 UTC (rev 14073) +++ trunk/reactos/drivers/dd/serial/pnp.c 2005-03-14 20:59:50 UTC (rev 14074) @@ -0,0 +1,275 @@
+/* $Id: + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: drivers/dd/serial/pnp.c + * PURPOSE: Serial IRP_MJ_PNP operations + * + * PROGRAMMERS: HervÚ Poussineau (poussine@freesurf.fr) + */ +/* FIXME: call IoAcquireRemoveLock/IoReleaseRemoveLock around each I/O operation */ + +#define NDEBUG +#include "serial.h" + +NTSTATUS STDCALL +SerialAddDevice( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT Pdo) +{ + PDEVICE_OBJECT Fdo; + PSERIAL_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + WCHAR DeviceNameBuffer[32]; + UNICODE_STRING DeviceName; + static ULONG DeviceNumber = 0; + + DPRINT("Serial: SerialAddDevice called\n"); + + /* Create new device object */ + swprintf(DeviceNameBuffer, L"\Device\Serial%lu", DeviceNumber); + RtlInitUnicodeString(&DeviceName, DeviceNameBuffer); + Status = IoCreateDevice(DriverObject, + sizeof(SERIAL_DEVICE_EXTENSION), + &DeviceName, + FILE_DEVICE_SERIAL_PORT, + FILE_DEVICE_SECURE_OPEN, + FALSE, + &Fdo); + if (!NT_SUCCESS(Status)) + { + DPRINT("Serial: IoCreateDevice() failed with status 0x%08x\n", Status); [truncated at 1000 lines; 773 more skipped]