-/* $Id:
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
+ * PROJECT: Serial port driver
* FILE: drivers/dd/serial/pnp.c
* PURPOSE: Serial IRP_MJ_PNP operations
- *
- * PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
+ *
+ * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com)
*/
/* FIXME: call IoAcquireRemoveLock/IoReleaseRemoveLock around each I/O operation */
NTSTATUS Status;
WCHAR DeviceNameBuffer[32];
UNICODE_STRING DeviceName;
- //UNICODE_STRING SymbolicLinkName;
static ULONG DeviceNumber = 0;
static ULONG ComPortNumber = 1;
DPRINT("Serial: SerialAddDeviceInternal called\n");
-
+
+ ASSERT(DriverObject);
+ ASSERT(Pdo);
+
/* Create new device object */
swprintf(DeviceNameBuffer, L"\\Device\\Serial%lu", DeviceNumber);
RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
}
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)Fdo->DeviceExtension;
RtlZeroMemory(DeviceExtension, sizeof(SERIAL_DEVICE_EXTENSION));
-
+
/* Register device interface */
-#if 0 /* FIXME: activate */
- Status = IoRegisterDeviceInterface(Pdo, &GUID_DEVINTERFACE_COMPORT, NULL, &SymbolicLinkName);
+ Status = IoRegisterDeviceInterface(Pdo, &GUID_DEVINTERFACE_COMPORT, NULL, &DeviceExtension->SerialInterfaceName);
if (!NT_SUCCESS(Status))
{
DPRINT("Serial: IoRegisterDeviceInterface() failed with status 0x%08x\n", Status);
goto ByeBye;
}
- DPRINT1("Serial: IoRegisterDeviceInterface() returned '%wZ'\n", &SymbolicLinkName);
- Status = IoSetDeviceInterfaceState(&SymbolicLinkName, TRUE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Serial: IoSetDeviceInterfaceState() failed with status 0x%08x\n", Status);
- goto ByeBye;
- }
- RtlFreeUnicodeString(&SymbolicLinkName);
-#endif
DeviceExtension->SerialPortNumber = DeviceNumber++;
if (pComPortNumber == NULL)
{
*pFdo = Fdo;
}
-
+
return STATUS_SUCCESS;
ByeBye:
*/
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.
+
+ /* We have here a PDO not null. It represents a real serial
+ * port. So call the internal AddDevice function.
*/
return SerialAddDeviceInternal(DriverObject, Pdo, UartUnknown, NULL, NULL);
-
-
}
NTSTATUS STDCALL
SerialPnpStartDevice(
IN PDEVICE_OBJECT DeviceObject,
- IN PCM_RESOURCE_LIST ResourceList)
+ IN PCM_RESOURCE_LIST ResourceList,
+ IN PCM_RESOURCE_LIST ResourceListTranslated)
{
PSERIAL_DEVICE_EXTENSION DeviceExtension;
WCHAR DeviceNameBuffer[32];
UNICODE_STRING KeyName;
HANDLE hKey;
NTSTATUS Status;
-
+
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
+
+ ASSERT(ResourceList);
+ ASSERT(DeviceExtension);
ASSERT(DeviceExtension->PnpState == dsStopped);
-
- DeviceExtension->BaudRate = 19200 | SERIAL_BAUD_USER;
+
+ DeviceExtension->BaudRate = 19200;
DeviceExtension->BaseAddress = 0;
Dirql = 0;
for (i = 0; i < ResourceList->Count; i++)
for (j = 0; j < ResourceList->List[i].PartialResourceList.Count; j++)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor = &ResourceList->List[i].PartialResourceList.PartialDescriptors[j];
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptorTranslated = &ResourceListTranslated->List[i].PartialResourceList.PartialDescriptors[j];
switch (PartialDescriptor->Type)
{
case CmResourceTypePort:
DeviceExtension->BaseAddress = PartialDescriptor->u.Port.Start.u.LowPart;
break;
case CmResourceTypeInterrupt:
- 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)
+ Dirql = (KIRQL)PartialDescriptorTranslated->u.Interrupt.Level;
+ Vector = PartialDescriptorTranslated->u.Interrupt.Vector;
+ Affinity = PartialDescriptorTranslated->u.Interrupt.Affinity;
+ if (PartialDescriptorTranslated->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
InterruptMode = Latched;
else
InterruptMode = LevelSensitive;
- ShareInterrupt = (PartialDescriptor->ShareDisposition == CmResourceShareShared);
+ ShareInterrupt = (PartialDescriptorTranslated->ShareDisposition == CmResourceShareShared);
break;
}
}
if (!Dirql)
return STATUS_INSUFFICIENT_RESOURCES;
ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
-
+
if (DeviceExtension->UartType == UartUnknown)
DeviceExtension->UartType = SerialDetectUartType(ComPortBase);
-
+
/* Get current settings */
DeviceExtension->MCR = READ_PORT_UCHAR(SER_MCR(ComPortBase));
DeviceExtension->MSR = READ_PORT_UCHAR(SER_MSR(ComPortBase));
DeviceExtension->WaitMask = 0;
-
+
/* Set baud rate */
Status = SerialSetBaudRate(DeviceExtension, DeviceExtension->BaudRate);
if (!NT_SUCCESS(Status))
DPRINT("Serial: SerialSetBaudRate() failed with status 0x%08x\n", Status);
return Status;
}
-
+
/* Set line control */
DeviceExtension->SerialLineControl.StopBits = STOP_BIT_1;
DeviceExtension->SerialLineControl.Parity = NO_PARITY;
DPRINT("Serial: SerialSetLineControl() failed with status 0x%08x\n", Status);
return Status;
}
-
+
/* Clear receive/transmit buffers */
if (DeviceExtension->UartType >= Uart16550A)
{
WRITE_PORT_UCHAR(SER_FCR(ComPortBase),
SR_FCR_CLEAR_RCVR | SR_FCR_CLEAR_XMIT);
}
-
+
/* Create link \DosDevices\COMX -> \Device\SerialX */
swprintf(DeviceNameBuffer, L"\\Device\\Serial%lu", DeviceExtension->SerialPortNumber);
swprintf(LinkNameBuffer, L"\\DosDevices\\COM%lu", DeviceExtension->ComPort);
DPRINT("Serial: IoCreateSymbolicLink() failed with status 0x%08x\n", Status);
return Status;
}
-
+
/* Connect interrupt and enable them */
Status = IoConnectInterrupt(
&DeviceExtension->Interrupt, SerialInterruptService,
if (!NT_SUCCESS(Status))
{
DPRINT("Serial: IoConnectInterrupt() failed with status 0x%08x\n", Status);
+ IoSetDeviceInterfaceState(&DeviceExtension->SerialInterfaceName, FALSE);
IoDeleteSymbolicLink(&LinkName);
return Status;
}
-
+
/* Write an entry value under HKLM\HARDWARE\DeviceMap\SERIALCOMM */
/* This step is not mandatory, so don't exit in case of error */
RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\HARDWARE\\DeviceMap\\SERIALCOMM");
if (NT_SUCCESS(Status))
{
/* Key = \Device\Serialx, Value = COMx */
- ZwSetValueKey(hKey, &DeviceName, 0, REG_SZ, &ComPortBuffer, ComPort.Length + sizeof(WCHAR));
+ ZwSetValueKey(hKey, &DeviceName, 0, REG_SZ, ComPortBuffer, ComPort.Length + sizeof(WCHAR));
ZwClose(hKey);
}
-
+
DeviceExtension->PnpState = dsStarted;
-
+
/* Activate interrupt modes */
IER = READ_PORT_UCHAR(SER_IER(ComPortBase));
IER |= SR_IER_DATA_RECEIVED | SR_IER_THR_EMPTY | SR_IER_LSR_CHANGE | SR_IER_MSR_CHANGE;
WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER);
-
+
/* Activate DTR, RTS */
DeviceExtension->MCR |= SR_MCR_DTR | SR_MCR_RTS;
WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
-
+
+ /* Activate serial interface */
+ IoSetDeviceInterfaceState(&DeviceExtension->SerialInterfaceName, TRUE);
+ /* We don't really care if the call succeeded or not... */
+
return STATUS_SUCCESS;
}
PIO_STACK_LOCATION Stack;
ULONG_PTR Information = 0;
NTSTATUS Status;
-
+
Stack = IoGetCurrentIrpStackLocation(Irp);
MinorFunction = Stack->MinorFunction;
-
+
switch (MinorFunction)
{
- case IRP_MN_START_DEVICE:
+ /* FIXME: do all these minor functions
+ IRP_MN_QUERY_REMOVE_DEVICE 0x1
+ IRP_MN_REMOVE_DEVICE 0x2
+ {
+ DPRINT("Serial: IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
+ IoAcquireRemoveLock
+ IoReleaseRemoveLockAndWait
+ pass request to DeviceExtension-LowerDriver
+ disable interface
+ IoDeleteDevice(Fdo) and/or IoDetachDevice
+ break;
+ }
+ IRP_MN_CANCEL_REMOVE_DEVICE 0x3
+ IRP_MN_STOP_DEVICE 0x4
+ IRP_MN_QUERY_STOP_DEVICE 0x5
+ IRP_MN_CANCEL_STOP_DEVICE 0x6
+ IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations (optional) 0x7
+ IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations (optional) 0x7
+ IRP_MN_QUERY_INTERFACE (optional) 0x8
+ IRP_MN_QUERY_CAPABILITIES (optional) 0x9
+ IRP_MN_FILTER_RESOURCE_REQUIREMENTS (optional) 0xd
+ IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14
+ IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16
+ IRP_MN_SURPRISE_REMOVAL 0x17
+ */
+ case IRP_MN_START_DEVICE: /* 0x0 */
{
BOOLEAN ConflictDetected;
DPRINT("Serial: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
-
- /* FIXME: first HACK: PnP manager can send multiple
- * IRP_MN_START_DEVICE for one device
- */
- if (((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->PnpState != dsStopped)
- {
- DPRINT1("Serial: device already started. Ignoring this irp!\n");
- Status = STATUS_SUCCESS;
- break;
- }
- /* FIXME: second HACK: verify that we have some allocated resources.
+
+ ASSERT(((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->PnpState == dsStopped);
+
+ /* FIXME: HACK: verify that we have some allocated resources.
* It seems not to be always the case on some hardware
*/
if (Stack->Parameters.StartDevice.AllocatedResources == NULL)
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
- /* FIXME: third HACK: verify that we don't have resource conflict,
+ /* FIXME: HACK: verify that we don't have resource conflict,
* because PnP manager doesn't do it automatically
*/
Status = IoReportResourceForDetection(
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
-
+
/* Call lower driver */
Status = ForwardIrpAndWait(DeviceObject, Irp);
if (NT_SUCCESS(Status))
Status = SerialPnpStartDevice(
DeviceObject,
- Stack->Parameters.StartDevice.AllocatedResources);
+ Stack->Parameters.StartDevice.AllocatedResources,
+ Stack->Parameters.StartDevice.AllocatedResourcesTranslated);
break;
}
- /* IRP_MN_QUERY_STOP_DEVICE (FIXME: required) */
- /* IRP_MN_STOP_DEVICE (FIXME: required) */
- /* IRP_MN_CANCEL_STOP_DEVICE (FIXME: required) */
- /* IRP_MN_QUERY_REMOVE_DEVICE (FIXME: required) */
- /* case IRP_MN_REMOVE_DEVICE (FIXME: required) */
- /*{
- DPRINT("Serial: IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
- IoAcquireRemoveLock
- IoReleaseRemoveLockAndWait
- pass request to DeviceExtension-LowerDriver
- IoDeleteDevice(Fdo) and/or IoDetachDevice
+ case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x7 */
+ {
+ switch (Stack->Parameters.QueryDeviceRelations.Type)
+ {
+ case BusRelations:
+ {
+ DPRINT("Serial: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
+ return ForwardIrpAndForget(DeviceObject, Irp);
+ }
+ case RemovalRelations:
+ {
+ DPRINT("Serial: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
+ return ForwardIrpAndForget(DeviceObject, Irp);
+ }
+ default:
+ DPRINT1("Serial: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
+ Stack->Parameters.QueryDeviceRelations.Type);
+ return ForwardIrpAndForget(DeviceObject, Irp);
+ }
break;
- }*/
- /* IRP_MN_CANCEL_REMOVE_DEVICE (FIXME: required) */
- /* IRP_MN_SURPRISE_REMOVAL (FIXME: required) */
- /* IRP_MN_QUERY_CAPABILITIES (optional) */
- /* IRP_MN_QUERY_PNP_DEVICE_STATE (optional) */
- /* IRP_MN_FILTER_RESOURCE_REQUIREMENTS (optional) */
- /* IRP_MN_DEVICE_USAGE_NOTIFICATION (FIXME: required or optional ???) */
- /* IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations (optional) */
- /* IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations (optional) */
- /* IRP_MN_QUERY_INTERFACE (optional) */
+ }
default:
{
DPRINT1("Serial: unknown minor function 0x%x\n", MinorFunction);
return ForwardIrpAndForget(DeviceObject, Irp);
}
}
-
+
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);