Allow ACPI detection and legacy detection for serial ports Detect serial debug port and prevent its management by serial driver Activate serial driver in registry Modified: trunk/reactos/bootdata/hivesys.inf Modified: trunk/reactos/drivers/dd/serial/legacy.c Modified: trunk/reactos/drivers/dd/serial/pnp.c Modified: trunk/reactos/drivers/dd/serial/serial.c Modified: trunk/reactos/drivers/dd/serial/serial.h Modified: trunk/reactos/ntoskrnl/io/pnpreport.c _____
Modified: trunk/reactos/bootdata/hivesys.inf --- trunk/reactos/bootdata/hivesys.inf 2005-04-04 22:48:51 UTC (rev 14490) +++ trunk/reactos/bootdata/hivesys.inf 2005-04-04 23:00:52 UTC (rev 14491) @@ -674,13 +674,14 @@
HKLM,"SYSTEM\CurrentControlSet\Services\Serial","ErrorControl",0x0001000 1,0x00000000
HKLM,"SYSTEM\CurrentControlSet\Services\Serial","Group",0x00000000,"Base "
HKLM,"SYSTEM\CurrentControlSet\Services\Serial","ImagePath",0x00020000," system32\drivers\serial.sys" -HKLM,"SYSTEM\CurrentControlSet\Services\Serial","Start",0x00010001,0x00 000004 +HKLM,"SYSTEM\CurrentControlSet\Services\Serial","Start",0x00010001,0x00 000001
HKLM,"SYSTEM\CurrentControlSet\Services\Serial","Type",0x00010001,0x0000 0001 ;hard coded values
HKLM,"SYSTEM\CurrentControlSet\Services\Serial\Enum","0",0x00000000,"ACP I\PNP0501"
HKLM,"SYSTEM\CurrentControlSet\Services\Serial\Enum","Count",0x00010001, 0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\Serial\Enum","NextInstance",0x00 010001,0x00000001 -HKLM,"SYSTEM\CurrentControlSet\Enum\ACPI\PNP0501\0000","Service",0x0000 0000,"serial" +HKLM,"SYSTEM\CurrentControlSet\Enum\ACPI\PNP0501\1","Service",0x0000000 0,"serial" +HKLM,"SYSTEM\CurrentControlSet\Enum\ACPI\PNP0501\2","Service",0x0000000 0,"serial"
; Packet driver
HKLM,"SYSTEM\CurrentControlSet\Services\Packet","ErrorControl",0x0001000 1,0x00000001 _____
Modified: trunk/reactos/drivers/dd/serial/legacy.c --- trunk/reactos/drivers/dd/serial/legacy.c 2005-04-04 22:48:51 UTC (rev 14490) +++ trunk/reactos/drivers/dd/serial/legacy.c 2005-04-04 23:00:52 UTC (rev 14491) @@ -74,11 +74,12 @@
return Uart16550A; }
-NTSTATUS +static NTSTATUS DetectLegacyDevice( IN PDRIVER_OBJECT DriverObject, IN ULONG ComPortBase, - IN ULONG Irq) + IN ULONG Irq, + IN PULONG pComPortNumber OPTIONAL) { ULONG ResourceListSize; PCM_RESOURCE_LIST ResourceList; @@ -125,9 +126,16 @@ NULL, NULL, 0, &ConflictDetected); if (Status == STATUS_CONFLICTING_ADDRESSES) + { + DPRINT("Serial: conflict detected for serial port at 0x%lx (Irq %lu)\n", ComPortBase, Irq); + ExFreePoolWithTag(ResourceList, SERIAL_TAG); return STATUS_DEVICE_NOT_CONNECTED; + } if (!NT_SUCCESS(Status)) + { + ExFreePoolWithTag(ResourceList, SERIAL_TAG); return Status; + } /* Test if port exists */ UartType = SerialDetectUartType((PUCHAR)ComPortBase); @@ -143,7 +151,7 @@ &Pdo); if (NT_SUCCESS(Status)) { - Status = SerialAddDeviceInternal(DriverObject, Pdo, UartType, &Fdo); + Status = SerialAddDeviceInternal(DriverObject, Pdo, UartType, pComPortNumber, &Fdo); if (NT_SUCCESS(Status)) { Status = SerialPnpStartDevice(Fdo, ResourceList); @@ -159,6 +167,7 @@ &ConflictDetected); Status = STATUS_DEVICE_NOT_CONNECTED; } + ExFreePoolWithTag(ResourceList, SERIAL_TAG); return Status; }
@@ -168,13 +177,14 @@ { ULONG ComPortBase[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; ULONG Irq[] = { 4, 3, 4, 3 }; + ULONG ComPortNumber[] = { 1, 2, 3, 4 }; 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]); + Status = DetectLegacyDevice(DriverObject, ComPortBase[i], Irq[i], &ComPortNumber[i]); 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); _____
Modified: trunk/reactos/drivers/dd/serial/pnp.c --- trunk/reactos/drivers/dd/serial/pnp.c 2005-04-04 22:48:51 UTC (rev 14490) +++ trunk/reactos/drivers/dd/serial/pnp.c 2005-04-04 23:00:52 UTC (rev 14491) @@ -18,6 +18,7 @@
IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT Pdo, IN UART_TYPE UartType, + IN PULONG pComPortNumber OPTIONAL, OUT PDEVICE_OBJECT* pFdo OPTIONAL) { PDEVICE_OBJECT Fdo = NULL; @@ -27,6 +28,7 @@ UNICODE_STRING DeviceName; //UNICODE_STRING SymbolicLinkName; static ULONG DeviceNumber = 0; + static ULONG ComPortNumber = 1;
DPRINT("Serial: SerialAddDeviceInternal called\n");
@@ -68,6 +70,10 @@ #endif
DeviceExtension->SerialPortNumber = DeviceNumber++; + if (pComPortNumber == NULL) + DeviceExtension->ComPort = ComPortNumber++; + else + DeviceExtension->ComPort = *pComPortNumber; DeviceExtension->Pdo = Pdo; DeviceExtension->PnpState = dsStopped; DeviceExtension->UartType = UartType; @@ -122,13 +128,9 @@ /* 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, UartUnknown, NULL); - //return STATUS_UNSUCCESSFUL; + return SerialAddDeviceInternal(DriverObject, Pdo, UartUnknown, NULL, NULL); + + }
NTSTATUS STDCALL @@ -160,7 +162,6 @@ ASSERT(DeviceExtension->PnpState == dsStopped); - DeviceExtension->ComPort = DeviceExtension->SerialPortNumber + 1; DeviceExtension->BaudRate = 19200 | SERIAL_BAUD_USER; DeviceExtension->BaseAddress = 0; Dirql = 0; @@ -330,15 +331,16 @@ KIRQL Dirql; ULONG ComPortBase; ULONG Irq; + BOOLEAN ConflictDetected; DPRINT1("Serial: no allocated resources for this device! Creating fake list\n"); - switch (((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->SerialPortNu mber) + switch (((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ComPort) { - case 0: + case 1: ComPortBase = 0x3f8; Irq = 4; break; - case 1: + case 2: ComPortBase = 0x2f8; Irq = 3; break; @@ -350,10 +352,15 @@ ResourceListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); ResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(PagedPool, ResourceListSize, SERIAL_TAG); if (!ResourceList) + { + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_INSUFFICIENT_RESOURCES; + } ResourceList->Count = 1; - ResourceList->List[0].InterfaceType = Isa; - ResourceList->List[0].BusNumber = -1; /* FIXME */ + ResourceList->List[0].InterfaceType = InterfaceTypeUndefined; + ResourceList->List[0].BusNumber = -1; /* unknown */
ResourceList->List[0].PartialResourceList.Version = 1;
ResourceList->List[0].PartialResourceList.Revision = 1;
ResourceList->List[0].PartialResourceList.Count = 2; @@ -375,6 +382,19 @@
&ResourceDescriptor->u.Interrupt.Affinity); ResourceDescriptor->u.Interrupt.Level = (ULONG)Dirql; + /* Verify that this COM port is not the serial debug port */ + Status = IoReportResourceForDetection( + DeviceObject->DriverObject, ResourceList, 0, + NULL, NULL, 0, + &ConflictDetected); + if (!NT_SUCCESS(Status)) + { + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; + } +
Stack->Parameters.StartDevice.AllocatedResources =
Stack->Parameters.StartDevice.AllocatedResourcesTranslated = ResourceList; _____
Modified: trunk/reactos/drivers/dd/serial/serial.c --- trunk/reactos/drivers/dd/serial/serial.c 2005-04-04 22:48:51 UTC (rev 14490) +++ trunk/reactos/drivers/dd/serial/serial.c 2005-04-04 23:00:52 UTC (rev 14491) @@ -41,6 +41,18 @@
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = SerialQueryInformation; DriverObject->MajorFunction[IRP_MJ_PNP] = SerialPnp; DriverObject->MajorFunction[IRP_MJ_POWER] = SerialPower; - - return DetectLegacyDevices(DriverObject); + + /* FIXME: It seems that DriverEntry function may be called more + * than once. Do only legacy detection the first time. */ + static BOOLEAN FirstTime = TRUE; + if (FirstTime) + { + FirstTime = FALSE; + return DetectLegacyDevices(DriverObject); + } + else + { + DPRINT1("Serial: DriverEntry called for the second time!\n"); + return STATUS_SUCCESS; + } } _____
Modified: trunk/reactos/drivers/dd/serial/serial.h --- trunk/reactos/drivers/dd/serial/serial.h 2005-04-04 22:48:51 UTC (rev 14490) +++ trunk/reactos/drivers/dd/serial/serial.h 2005-04-04 23:00:52 UTC (rev 14491) @@ -313,6 +313,7 @@
IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT Pdo, IN UART_TYPE UartType, + IN PULONG pComPortNumber OPTIONAL, OUT PDEVICE_OBJECT* pFdo OPTIONAL);
NTSTATUS STDCALL _____
Modified: trunk/reactos/ntoskrnl/io/pnpreport.c --- trunk/reactos/ntoskrnl/io/pnpreport.c 2005-04-04 22:48:51 UTC (rev 14490) +++ trunk/reactos/ntoskrnl/io/pnpreport.c 2005-04-04 23:00:52 UTC (rev 14491) @@ -80,8 +80,49 @@
IN ULONG DeviceListSize OPTIONAL, OUT PBOOLEAN ConflictDetected) { - DPRINT1("IoReportResourceForDetection UNIMPLEMENTED but returns success.\n"); *ConflictDetected = FALSE; + DPRINT1("IoReportResourceForDetection unimplemented\n"); + + if (PopSystemPowerDeviceNode != NULL && DriverListSize > 0) + { + /* We hope serial ports will be enumerated by ACPI */ + *ConflictDetected = TRUE; + return STATUS_CONFLICTING_ADDRESSES; + } + + /* HACK: check if serial debug output is enabled. If yes, + * prevent serial port driver to detect this serial port + * by indicating a conflict + */ + if ((KdDebugState & KD_DEBUG_SERIAL) && DriverList != NULL) + { + ULONG ComPortBase = 0; + ULONG i; + PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor; + + switch (LogPortInfo.ComPort) + { + case 1: ComPortBase = 0x3f8; break; + case 2: ComPortBase = 0x2f8; break; + case 3: ComPortBase = 0x3e8; break; + case 4: ComPortBase = 0x2e8; break; + } + + /* search for this port address in DriverList */ + for (i = 0; i < DriverList->List[0].PartialResourceList.Count; i++) + { + ResourceDescriptor = &DriverList->List[0].PartialResourceList.PartialDescriptors[i]; + if (ResourceDescriptor->Type == CmResourceTypePort) + { + if (ResourceDescriptor->u.Port.Start.u.LowPart <= ComPortBase + && ResourceDescriptor->u.Port.Start.u.LowPart + ResourceDescriptor->u.Port.Length > ComPortBase) + { + *ConflictDetected = TRUE; + return STATUS_CONFLICTING_ADDRESSES; + } + } + } + } return STATUS_SUCCESS; }