Add legacy detection of COM3 and COM4 Be ready for PnP serial ports Don't hardcode base addresses and irq twice Modified: trunk/reactos/drivers/dd/serial/legacy.c Modified: trunk/reactos/drivers/dd/serial/pnp.c Modified: trunk/reactos/drivers/dd/serial/serial.h _____
Modified: trunk/reactos/drivers/dd/serial/legacy.c --- trunk/reactos/drivers/dd/serial/legacy.c 2005-03-20 12:15:33 UTC (rev 14215) +++ trunk/reactos/drivers/dd/serial/legacy.c 2005-03-20 12:15:51 UTC (rev 14216) @@ -77,7 +77,11 @@
{ ULONG ResourceListSize; PCM_RESOURCE_LIST ResourceList; + PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor; BOOLEAN ConflictDetected, FoundPort; + PDEVICE_OBJECT Pdo = NULL; + PDEVICE_OBJECT Fdo; + KIRQL Dirql; NTSTATUS Status; /* Create resource list */ @@ -91,18 +95,23 @@ ResourceList->List[0].PartialResourceList.Version = 1; ResourceList->List[0].PartialResourceList.Revision = 1; ResourceList->List[0].PartialResourceList.Count = 2; - ResourceList->List[0].PartialResourceList.PartialDescriptors[0].Type = CmResourceTypePort; - ResourceList->List[0].PartialResourceList.PartialDescriptors[0].ShareDis position = CmResourceShareDriverExclusive; - ResourceList->List[0].PartialResourceList.PartialDescriptors[0].Flags = CM_RESOURCE_PORT_IO; - // FIXME ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.S tart = ComPortBase; - ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.L ength = 8; + ResourceDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[0]; + ResourceDescriptor->Type = CmResourceTypePort; + ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive; + ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO; + ResourceDescriptor->u.Port.Start.u.HighPart = 0; + ResourceDescriptor->u.Port.Start.u.LowPart = ComPortBase; + ResourceDescriptor->u.Port.Length = 8; - ResourceList->List[0].PartialResourceList.PartialDescriptors[1].Type = CmResourceTypeInterrupt; - ResourceList->List[0].PartialResourceList.PartialDescriptors[1].ShareDis position = CmResourceShareDriverExclusive; - ResourceList->List[0].PartialResourceList.PartialDescriptors[1].Flags = CM_RESOURCE_INTERRUPT_LATCHED; - /* FIXME: ResourceList->List[0].PartialResourceList.PartialDescriptors[1].u.Interr upt.Level = ; - ResourceList->List[0].PartialResourceList.PartialDescriptors[1].u.Interr upt.Vector = ; - ResourceList->List[0].PartialResourceList.PartialDescriptors[1].u.Interr upt.Affinity = ;*/ + ResourceDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[1]; + ResourceDescriptor->Type = CmResourceTypeInterrupt; + ResourceDescriptor->ShareDisposition = CmResourceShareShared; + ResourceDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; + ResourceDescriptor->u.Interrupt.Vector = HalGetInterruptVector( + Internal, 0, 0, Irq, + &Dirql, + &ResourceDescriptor->u.Interrupt.Affinity); + ResourceDescriptor->u.Interrupt.Level = (ULONG)Dirql; /* Report resource list */ Status = IoReportResourceForDetection( @@ -125,7 +134,15 @@ ResourceList->List[0].InterfaceType, ResourceList->List[0].BusNumber, -1/*FIXME*/, ResourceList, NULL, TRUE, - NULL); + &Pdo); + if (NT_SUCCESS(Status)) + { + Status = SerialAddDeviceInternal(DriverObject, Pdo, &Fdo); + if (NT_SUCCESS(Status)) + { + Status = SerialPnpStartDevice(Fdo, ResourceList); + } + } } else { @@ -143,20 +160,19 @@ DetectLegacyDevices( IN PDRIVER_OBJECT DriverObject) { - ULONG ComPortBase[] = { 0x3f8, 0x2f8 }; - ULONG Irq[] = { 4, 3 }; + ULONG ComPortBase[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; + ULONG Irq[] = { 4, 3, 4, 3 }; ULONG i; NTSTATUS Status; + NTSTATUS ReturnedStatus = STATUS_SUCCESS; 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; + if (!NT_SUCCESS(Status) && Status != STATUS_DEVICE_NOT_CONNECTED) + ReturnedStatus = Status; + DPRINT("Serial: Legacy device at 0x%x (IRQ %lu): status = 0x%08lx\n", ComPortBase[i], Irq[i], Status); } - return Status; + return ReturnedStatus; } _____
Modified: trunk/reactos/drivers/dd/serial/pnp.c --- trunk/reactos/drivers/dd/serial/pnp.c 2005-03-20 12:15:33 UTC (rev 14215) +++ trunk/reactos/drivers/dd/serial/pnp.c 2005-03-20 12:15:51 UTC (rev 14216) @@ -14,9 +14,10 @@
#include "serial.h"
NTSTATUS STDCALL -SerialAddDevice( +SerialAddDeviceInternal( IN PDRIVER_OBJECT DriverObject, - IN PDEVICE_OBJECT Pdo) + IN PDEVICE_OBJECT Pdo, + OUT PDEVICE_OBJECT* pFdo OPTIONAL) { PDEVICE_OBJECT Fdo = NULL; PSERIAL_DEVICE_EXTENSION DeviceExtension = NULL; @@ -26,7 +27,7 @@ //UNICODE_STRING SymbolicLinkName; static ULONG DeviceNumber = 0;
- DPRINT("Serial: SerialAddDevice called\n"); + DPRINT("Serial: SerialAddDeviceInternal called\n");
/* Create new device object */ swprintf(DeviceNameBuffer, L"\Device\Serial%lu", DeviceNumber); @@ -81,6 +82,10 @@ goto ByeBye; } Fdo->Flags &= ~DO_DEVICE_INITIALIZING; + if (pFdo) + { + *pFdo = Fdo; + } return STATUS_SUCCESS;
@@ -95,12 +100,34 @@ }
NTSTATUS STDCALL +SerialAddDevice( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT Pdo) +{ + /* Serial.sys is a legacy driver. AddDevice is called once + * with a NULL Pdo just after the driver initialization. + * Detect this case and return success. + */ + if (Pdo == NULL) + return STATUS_SUCCESS; + + /* We have here a PDO that does not correspond to a legacy + * serial port. So call the internal AddDevice function. + */ + DPRINT1("Serial: SerialAddDevice() called. Pdo 0x%p (should be NULL)\n", Pdo); + /* FIXME: due to a bug, previously described AddDevice is + * not called with a NULL Pdo. Block this call (blocks + * unfortunately all the other PnP serial ports devices). + */ + //return SerialAddDeviceInternal(DriverObject, Pdo, NULL); + return STATUS_UNSUCCESSFUL; +} + +NTSTATUS STDCALL SerialPnpStartDevice( IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) + IN PCM_RESOURCE_LIST ResourceList) { - PIO_STACK_LOCATION Stack; - //PCM_RESOURCE_LIST ResourceList; PSERIAL_DEVICE_EXTENSION DeviceExtension; WCHAR DeviceNameBuffer[32]; UNICODE_STRING DeviceName; @@ -108,16 +135,17 @@ UNICODE_STRING LinkName; WCHAR ComPortBuffer[32]; UNICODE_STRING ComPort; - ULONG Vector; - //ULONG i, j; + ULONG Vector = 0; + ULONG i, j; KIRQL Dirql; KAFFINITY Affinity; + KINTERRUPT_MODE InterruptMode = Latched; + BOOLEAN ShareInterrupt = TRUE; OBJECT_ATTRIBUTES objectAttributes; UNICODE_STRING KeyName; HANDLE hKey; NTSTATUS Status; - Stack = IoGetCurrentIrpStackLocation(Irp); DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; /* FIXME: actually, IRP_MN_START_DEVICE is sent twice to each serial device: @@ -128,66 +156,47 @@ */ if (DeviceExtension->PnpState == dsStarted) return STATUS_SUCCESS; -#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) - { - 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; - } -#else - DPRINT1("Serial: ResourceList %p, ResourceListTranslated %p\n", - Stack->Parameters.StartDevice.AllocatedResources, - Stack->Parameters.StartDevice.AllocatedResourcesTranslated); - ResourceList = Stack->Parameters.StartDevice.AllocatedResourcesTranslated; + DeviceExtension->ComPort = DeviceExtension->SerialPortNumber + 1; + DeviceExtension->BaudRate = 19200 | SERIAL_BAUD_USER; + DeviceExtension->BaseAddress = 0; + Dirql = 0; 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++) + for (j = 0; j < 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) { case CmResourceTypePort: + if (PartialDescriptor->u.Port.Length < 8) + return STATUS_INSUFFICIENT_RESOURCES; + if (DeviceExtension->BaseAddress != 0) + return STATUS_UNSUCCESSFUL; 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); + if (Dirql != 0) + return STATUS_UNSUCCESSFUL; + Dirql = (KIRQL)PartialDescriptor->u.Interrupt.Level; + Vector = PartialDescriptor->u.Interrupt.Vector; + Affinity = PartialDescriptor->u.Interrupt.Affinity; + if (PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) + InterruptMode = Latched; + else + InterruptMode = LevelSensitive; + ShareInterrupt = (PartialDescriptor->ShareDisposition == CmResourceShareShared); break; } } } - 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 + DPRINT("Serial: New COM port. Base = 0x%lx, Irql = %u\n", + 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; /* Get current settings */ DeviceExtension->IER = READ_PORT_UCHAR(SER_IER((PUCHAR)DeviceExtension->BaseAddress)); @@ -229,11 +238,11 @@ } /* Connect interrupt and enable them */ - Vector = HalGetInterruptVector(Internal, 0, 0, DeviceExtension->Irq, &Dirql, &Affinity); Status = IoConnectInterrupt( &DeviceExtension->Interrupt, SerialInterruptService, - DeviceObject, NULL, Vector, Dirql, Dirql, Latched, - FALSE /* FIXME: or TRUE to share interrupt on PCI bus? */, + DeviceObject, NULL, + Vector, Dirql, Dirql, + InterruptMode, ShareInterrupt, Affinity, FALSE); if (!NT_SUCCESS(Status)) { @@ -288,7 +297,9 @@ /* Call lower driver */ Status = ForwardIrpAndWait(DeviceObject, Irp); if (NT_SUCCESS(Status)) - Status = SerialPnpStartDevice(DeviceObject, Irp); + Status = SerialPnpStartDevice( + DeviceObject, + Stack->Parameters.StartDevice.AllocatedResources); break; } /* IRP_MN_QUERY_STOP_DEVICE (FIXME: required) */ _____
Modified: trunk/reactos/drivers/dd/serial/serial.h --- trunk/reactos/drivers/dd/serial/serial.h 2005-03-20 12:15:33 UTC (rev 14215) +++ trunk/reactos/drivers/dd/serial/serial.h 2005-03-20 12:15:51 UTC (rev 14216) @@ -70,7 +70,6 @@
ULONG ComPort; ULONG BaudRate; ULONG BaseAddress; - ULONG Irq; PKINTERRUPT Interrupt; SERIAL_LINE_CONTROL SerialLineControl; @@ -235,11 +234,22 @@ /************************************ pnp.c */
NTSTATUS STDCALL +SerialAddDeviceInternal( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT Pdo, + OUT PDEVICE_OBJECT* pFdo OPTIONAL); + +NTSTATUS STDCALL SerialAddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT Pdo);
NTSTATUS STDCALL +SerialPnpStartDevice( + IN PDEVICE_OBJECT DeviceObject, + IN PCM_RESOURCE_LIST ResourceList); + +NTSTATUS STDCALL SerialPnp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);