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;
}