Allow ACPI detection and legacy detection for serial ports
authorHervé Poussineau <hpoussin@reactos.org>
Mon, 4 Apr 2005 23:00:52 +0000 (23:00 +0000)
committerHervé Poussineau <hpoussin@reactos.org>
Mon, 4 Apr 2005 23:00:52 +0000 (23:00 +0000)
Detect serial debug port and prevent its management by serial driver
Activate serial driver in registry

svn path=/trunk/; revision=14491

reactos/bootdata/hivesys.inf
reactos/drivers/dd/serial/legacy.c
reactos/drivers/dd/serial/pnp.c
reactos/drivers/dd/serial/serial.c
reactos/drivers/dd/serial/serial.h
reactos/ntoskrnl/io/pnpreport.c

index 2bb581e..e69d8b6 100644 (file)
@@ -674,13 +674,14 @@ HKLM,"SYSTEM\CurrentControlSet\Services\Null","Type",0x00010001,0x00000001
 HKLM,"SYSTEM\CurrentControlSet\Services\Serial","ErrorControl",0x00010001,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,0x00000004
+HKLM,"SYSTEM\CurrentControlSet\Services\Serial","Start",0x00010001,0x00000001
 HKLM,"SYSTEM\CurrentControlSet\Services\Serial","Type",0x00010001,0x00000001
 ;hard coded values
 HKLM,"SYSTEM\CurrentControlSet\Services\Serial\Enum","0",0x00000000,"ACPI\PNP0501"
 HKLM,"SYSTEM\CurrentControlSet\Services\Serial\Enum","Count",0x00010001,0x00000001
 HKLM,"SYSTEM\CurrentControlSet\Services\Serial\Enum","NextInstance",0x00010001,0x00000001
-HKLM,"SYSTEM\CurrentControlSet\Enum\ACPI\PNP0501\0000","Service",0x00000000,"serial"
+HKLM,"SYSTEM\CurrentControlSet\Enum\ACPI\PNP0501\1","Service",0x00000000,"serial"
+HKLM,"SYSTEM\CurrentControlSet\Enum\ACPI\PNP0501\2","Service",0x00000000,"serial"
 
 ; Packet driver
 HKLM,"SYSTEM\CurrentControlSet\Services\Packet","ErrorControl",0x00010001,0x00000001
index 41df89d..1a7886b 100644 (file)
@@ -74,11 +74,12 @@ SerialDetectUartType(
        return Uart16550A;\r
 }\r
 \r
-NTSTATUS\r
+static NTSTATUS\r
 DetectLegacyDevice(\r
        IN PDRIVER_OBJECT DriverObject,\r
        IN ULONG ComPortBase,\r
-       IN ULONG Irq)\r
+       IN ULONG Irq,\r
+       IN PULONG pComPortNumber OPTIONAL)\r
 {\r
        ULONG ResourceListSize;\r
        PCM_RESOURCE_LIST ResourceList;\r
@@ -125,9 +126,16 @@ DetectLegacyDevice(
                NULL, NULL, 0,\r
                &ConflictDetected);\r
        if (Status == STATUS_CONFLICTING_ADDRESSES)\r
+       {\r
+               DPRINT("Serial: conflict detected for serial port at 0x%lx (Irq %lu)\n", ComPortBase, Irq);\r
+               ExFreePoolWithTag(ResourceList, SERIAL_TAG);\r
                return STATUS_DEVICE_NOT_CONNECTED;\r
+       }\r
        if (!NT_SUCCESS(Status))\r
+       {\r
+               ExFreePoolWithTag(ResourceList, SERIAL_TAG);\r
                return Status;\r
+       }\r
        \r
        /* Test if port exists */\r
        UartType = SerialDetectUartType((PUCHAR)ComPortBase);\r
@@ -143,7 +151,7 @@ DetectLegacyDevice(
                        &Pdo);\r
                if (NT_SUCCESS(Status))\r
                {\r
-                       Status = SerialAddDeviceInternal(DriverObject, Pdo, UartType, &Fdo);\r
+                       Status = SerialAddDeviceInternal(DriverObject, Pdo, UartType, pComPortNumber, &Fdo);\r
                        if (NT_SUCCESS(Status))\r
                        {\r
                                Status = SerialPnpStartDevice(Fdo, ResourceList);\r
@@ -159,6 +167,7 @@ DetectLegacyDevice(
                        &ConflictDetected);\r
                Status = STATUS_DEVICE_NOT_CONNECTED;\r
        }\r
+       ExFreePoolWithTag(ResourceList, SERIAL_TAG);\r
        return Status;\r
 }\r
 \r
@@ -168,13 +177,14 @@ DetectLegacyDevices(
 {\r
        ULONG ComPortBase[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };\r
        ULONG Irq[] = { 4, 3, 4, 3 };\r
+       ULONG ComPortNumber[] = { 1, 2, 3, 4 };\r
        ULONG i;\r
        NTSTATUS Status;\r
        NTSTATUS ReturnedStatus = STATUS_SUCCESS;\r
        \r
        for (i = 0; i < sizeof(ComPortBase)/sizeof(ComPortBase[0]); i++)\r
        {\r
-               Status = DetectLegacyDevice(DriverObject, ComPortBase[i], Irq[i]);\r
+               Status = DetectLegacyDevice(DriverObject, ComPortBase[i], Irq[i], &ComPortNumber[i]);\r
                if (!NT_SUCCESS(Status) && Status != STATUS_DEVICE_NOT_CONNECTED)\r
                        ReturnedStatus = Status;\r
                DPRINT("Serial: Legacy device at 0x%x (IRQ %lu): status = 0x%08lx\n", ComPortBase[i], Irq[i], Status);\r
index 08b0e87..f07d20c 100644 (file)
@@ -18,6 +18,7 @@ SerialAddDeviceInternal(
        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 @@ SerialAddDeviceInternal(
        UNICODE_STRING DeviceName;
        //UNICODE_STRING SymbolicLinkName;
        static ULONG DeviceNumber = 0;
+       static ULONG ComPortNumber = 1;
 
        DPRINT("Serial: SerialAddDeviceInternal called\n");
    
@@ -68,6 +70,10 @@ SerialAddDeviceInternal(
 #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 @@ SerialAddDevice(
        /* 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 @@ SerialPnpStartDevice(
        
        ASSERT(DeviceExtension->PnpState == dsStopped);
        
-       DeviceExtension->ComPort = DeviceExtension->SerialPortNumber + 1;
        DeviceExtension->BaudRate = 19200 | SERIAL_BAUD_USER;
        DeviceExtension->BaseAddress = 0;
        Dirql = 0;
@@ -330,15 +331,16 @@ SerialPnp(
                                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)->SerialPortNumber)
+                               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 @@ SerialPnp(
                                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 @@ SerialPnp(
                                        &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;
index 7d41444..6fc66e5 100644 (file)
@@ -41,6 +41,18 @@ DriverEntry(
        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;
+       }
 }
index 9fb3094..95188f1 100644 (file)
@@ -313,6 +313,7 @@ SerialAddDeviceInternal(
        IN PDRIVER_OBJECT DriverObject,
        IN PDEVICE_OBJECT Pdo,
        IN UART_TYPE UartType,
+       IN PULONG pComPortNumber OPTIONAL,
        OUT PDEVICE_OBJECT* pFdo OPTIONAL);
 
 NTSTATUS STDCALL
index 0e02c38..29f7737 100644 (file)
@@ -80,8 +80,49 @@ IoReportResourceForDetection(
   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;
 }