4 * Copyright (C) 2002, 2003, 2004 ReactOS Team
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 /* GLOBAL VARIABLES ***********************************************************/
26 PVIDEO_PORT_DEVICE_EXTENSION ResetDisplayParametersDeviceExtension
= NULL
;
28 /* PRIVATE FUNCTIONS **********************************************************/
31 * Reset display to blue screen
35 IntVideoPortResetDisplayParameters(ULONG Columns
, ULONG Rows
)
37 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
;
39 if (ResetDisplayParametersDeviceExtension
== NULL
)
42 DriverExtension
= ResetDisplayParametersDeviceExtension
->DriverExtension
;
44 if (DriverExtension
->InitializationData
.HwResetHw
!= NULL
)
46 if (DriverExtension
->InitializationData
.HwResetHw(
47 &ResetDisplayParametersDeviceExtension
->MiniPortDeviceExtension
,
50 ResetDisplayParametersDeviceExtension
= NULL
;
55 ResetDisplayParametersDeviceExtension
= NULL
;
60 IntVideoPortAddDevice(
61 IN PDRIVER_OBJECT DriverObject
,
62 IN PDEVICE_OBJECT PhysicalDeviceObject
)
64 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
;
65 PDEVICE_OBJECT DeviceObject
;
69 * Get the initialization data we saved in VideoPortInitialize.
72 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
75 * Create adapter device object.
78 Status
= IntVideoPortCreateAdapterDeviceObject(
83 if (NT_SUCCESS(Status
))
84 VideoPortDeviceNumber
++;
90 * IntVideoPortDispatchOpen
92 * Answer requests for Open calls.
99 IntVideoPortDispatchOpen(
100 IN PDEVICE_OBJECT DeviceObject
,
103 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
104 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
;
106 TRACE_(VIDEOPRT
, "IntVideoPortDispatchOpen\n");
108 if (CsrssInitialized
== FALSE
)
111 * We know the first open call will be from the CSRSS process
112 * to let us know its handle.
115 INFO_(VIDEOPRT
, "Referencing CSRSS\n");
116 Csrss
= (PKPROCESS
)PsGetCurrentProcess();
117 INFO_(VIDEOPRT
, "Csrss %p\n", Csrss
);
119 CsrssInitialized
= TRUE
;
121 Irp
->IoStatus
.Information
= FILE_OPENED
;
122 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
124 return STATUS_SUCCESS
;
127 DeviceExtension
= (PVIDEO_PORT_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
128 DriverExtension
= DeviceExtension
->DriverExtension
;
130 if (DriverExtension
->InitializationData
.HwInitialize(&DeviceExtension
->MiniPortDeviceExtension
))
132 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
134 InterlockedIncrement((PLONG
)&DeviceExtension
->DeviceOpened
);
138 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
141 Irp
->IoStatus
.Information
= FILE_OPENED
;
142 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
144 return STATUS_SUCCESS
;
148 * IntVideoPortDispatchClose
150 * Answer requests for Close calls.
157 IntVideoPortDispatchClose(
158 IN PDEVICE_OBJECT DeviceObject
,
161 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
163 TRACE_(VIDEOPRT
, "IntVideoPortDispatchClose\n");
165 DeviceExtension
= (PVIDEO_PORT_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
166 if (DeviceExtension
->DeviceOpened
>= 1 &&
167 InterlockedDecrement((PLONG
)&DeviceExtension
->DeviceOpened
) == 0)
169 ResetDisplayParametersDeviceExtension
= NULL
;
170 InbvNotifyDisplayOwnershipLost(NULL
);
171 ResetDisplayParametersDeviceExtension
= DeviceExtension
;
172 IntVideoPortResetDisplayParameters(80, 50);
175 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
176 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
178 return STATUS_SUCCESS
;
182 * IntVideoPortDispatchDeviceControl
184 * Answer requests for device control calls.
191 IntVideoPortDispatchDeviceControl(
192 IN PDEVICE_OBJECT DeviceObject
,
195 PIO_STACK_LOCATION IrpStack
;
196 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
;
197 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
198 PVIDEO_REQUEST_PACKET vrp
;
201 TRACE_(VIDEOPRT
, "IntVideoPortDispatchDeviceControl\n");
203 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
204 DeviceExtension
= DeviceObject
->DeviceExtension
;
205 DriverExtension
= DeviceExtension
->DriverExtension
;
207 /* Translate the IRP to a VRP */
208 vrp
= ExAllocatePoolWithTag(NonPagedPool
,
209 sizeof(VIDEO_REQUEST_PACKET
),
213 return STATUS_NO_MEMORY
;
216 vrp
->StatusBlock
= (PSTATUS_BLOCK
)&(Irp
->IoStatus
);
217 vrp
->IoControlCode
= IrpStack
->Parameters
.DeviceIoControl
.IoControlCode
;
219 INFO_(VIDEOPRT
, "- IoControlCode: %x\n", vrp
->IoControlCode
);
221 /* We're assuming METHOD_BUFFERED */
222 vrp
->InputBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
223 vrp
->InputBufferLength
= IrpStack
->Parameters
.DeviceIoControl
.InputBufferLength
;
224 vrp
->OutputBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
225 vrp
->OutputBufferLength
= IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
227 /* Call the Miniport Driver with the VRP */
228 DriverExtension
->InitializationData
.HwStartIO(
229 &DeviceExtension
->MiniPortDeviceExtension
,
233 ExFreePoolWithTag(vrp
, TAG_REQUEST_PACKET
);
235 INFO_(VIDEOPRT
, "- Returned status: %x\n", Irp
->IoStatus
.Status
);
237 if (Irp
->IoStatus
.Status
!= STATUS_SUCCESS
)
239 /* Map from win32 error codes to NT status values. */
240 switch (Irp
->IoStatus
.Status
)
242 case ERROR_NOT_ENOUGH_MEMORY
: Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
; break;
243 case ERROR_MORE_DATA
: Irp
->IoStatus
.Status
= STATUS_BUFFER_OVERFLOW
; break;
244 case ERROR_INVALID_FUNCTION
: Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
; break;
245 case ERROR_INVALID_PARAMETER
: Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
; break;
246 case ERROR_INSUFFICIENT_BUFFER
: Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
; break;
247 case ERROR_DEV_NOT_EXIST
: Irp
->IoStatus
.Status
= STATUS_DEVICE_DOES_NOT_EXIST
; break;
248 case ERROR_IO_PENDING
: Irp
->IoStatus
.Status
= STATUS_PENDING
; break;
252 Status
= Irp
->IoStatus
.Status
;
253 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
261 * This is a bit of a hack. We want to take ownership of the display as late
262 * as possible, just before the switch to graphics mode. Win32k knows when
263 * this happens, we don't. So we need Win32k to inform us. This could be done
264 * using an IOCTL, but there's no way of knowing which IOCTL codes are unused
265 * in the communication between GDI driver and miniport driver. So we use
266 * IRP_MJ_WRITE as the signal that win32k is ready to switch to graphics mode,
267 * since we know for certain that there is no read/write activity going on
268 * between GDI and miniport drivers.
269 * We don't actually need the data that is passed, we just trigger on the fact
270 * that an IRP_MJ_WRITE was sent.
277 IntVideoPortDispatchWrite(
278 IN PDEVICE_OBJECT DeviceObject
,
281 PIO_STACK_LOCATION piosStack
= IoGetCurrentIrpStackLocation(Irp
);
282 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
285 DeviceExtension
= (PVIDEO_PORT_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
288 * Storing the device extension pointer in a static variable is an
289 * ugly hack. Unfortunately, we need it in IntVideoPortResetDisplayParameters
290 * and InbvNotifyDisplayOwnershipLost doesn't allow us to pass a userdata
291 * parameter. On the bright side, the DISPLAY device is opened
292 * exclusively, so there can be only one device extension active at
295 * FIXME: We should process all opened display devices in
296 * IntVideoPortResetDisplayParameters.
299 ResetDisplayParametersDeviceExtension
= DeviceExtension
;
300 InbvNotifyDisplayOwnershipLost(IntVideoPortResetDisplayParameters
);
302 nErrCode
= STATUS_SUCCESS
;
303 Irp
->IoStatus
.Information
= piosStack
->Parameters
.Write
.Length
;
304 Irp
->IoStatus
.Status
= nErrCode
;
305 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
311 IntVideoPortPnPStartDevice(
312 IN PDEVICE_OBJECT DeviceObject
,
315 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
316 PDRIVER_OBJECT DriverObject
;
317 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
;
318 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
319 PCM_RESOURCE_LIST AllocatedResources
;
322 * Get the initialization data we saved in VideoPortInitialize.
325 DriverObject
= DeviceObject
->DriverObject
;
326 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
327 DeviceExtension
= (PVIDEO_PORT_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
330 * Store some resources in the DeviceExtension.
333 AllocatedResources
= Stack
->Parameters
.StartDevice
.AllocatedResources
;
334 if (AllocatedResources
!= NULL
)
336 CM_FULL_RESOURCE_DESCRIPTOR
*FullList
;
337 CM_PARTIAL_RESOURCE_DESCRIPTOR
*Descriptor
;
339 ULONG ResourceListSize
;
341 /* Save the resource list */
342 ResourceCount
= AllocatedResources
->List
[0].PartialResourceList
.Count
;
344 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
345 PartialDescriptors
[ResourceCount
]);
346 DeviceExtension
->AllocatedResources
= ExAllocatePool(PagedPool
, ResourceListSize
);
347 if (DeviceExtension
->AllocatedResources
== NULL
)
349 return STATUS_INSUFFICIENT_RESOURCES
;
352 RtlCopyMemory(DeviceExtension
->AllocatedResources
,
356 /* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
357 for (FullList
= AllocatedResources
->List
;
358 FullList
< AllocatedResources
->List
+ AllocatedResources
->Count
;
361 INFO_(VIDEOPRT
, "InterfaceType %u BusNumber List %u Device BusNumber %u Version %u Revision %u\n",
362 FullList
->InterfaceType
, FullList
->BusNumber
, DeviceExtension
->SystemIoBusNumber
, FullList
->PartialResourceList
.Version
, FullList
->PartialResourceList
.Revision
);
364 /* FIXME: Is this ASSERT ok for resources from the PNP manager? */
365 ASSERT(FullList
->InterfaceType
== PCIBus
);
366 ASSERT(FullList
->BusNumber
== DeviceExtension
->SystemIoBusNumber
);
367 ASSERT(1 == FullList
->PartialResourceList
.Version
);
368 ASSERT(1 == FullList
->PartialResourceList
.Revision
);
369 for (Descriptor
= FullList
->PartialResourceList
.PartialDescriptors
;
370 Descriptor
< FullList
->PartialResourceList
.PartialDescriptors
+ FullList
->PartialResourceList
.Count
;
373 if (Descriptor
->Type
== CmResourceTypeInterrupt
)
375 DeviceExtension
->InterruptLevel
= Descriptor
->u
.Interrupt
.Level
;
376 DeviceExtension
->InterruptVector
= Descriptor
->u
.Interrupt
.Vector
;
377 if (Descriptor
->ShareDisposition
== CmResourceShareShared
)
378 DeviceExtension
->InterruptShared
= TRUE
;
380 DeviceExtension
->InterruptShared
= FALSE
;
385 INFO_(VIDEOPRT
, "Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
386 DeviceExtension
->InterruptLevel
,
387 DeviceExtension
->InterruptVector
);
390 * Create adapter device object.
393 return IntVideoPortFindAdapter(
402 IntVideoPortForwardIrpAndWaitCompletionRoutine(
407 PKEVENT Event
= Context
;
409 if (Irp
->PendingReturned
)
410 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
412 return STATUS_MORE_PROCESSING_REQUIRED
;
417 IntVideoPortQueryBusRelations(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
419 PDEVICE_RELATIONS DeviceRelations
;
420 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
421 PVIDEO_PORT_CHILD_EXTENSION ChildExtension
;
423 PLIST_ENTRY CurrentEntry
;
425 /* Count the children */
427 CurrentEntry
= DeviceExtension
->ChildDeviceList
.Flink
;
428 while (CurrentEntry
!= &DeviceExtension
->ChildDeviceList
)
431 CurrentEntry
= CurrentEntry
->Flink
;
435 return Irp
->IoStatus
.Status
;
437 DeviceRelations
= ExAllocatePool(PagedPool
, sizeof(DEVICE_RELATIONS
) + ((i
- 1) * sizeof(PVOID
)));
438 if (!DeviceRelations
) return STATUS_NO_MEMORY
;
440 DeviceRelations
->Count
= i
;
442 /* Add the children */
444 CurrentEntry
= DeviceExtension
->ChildDeviceList
.Flink
;
445 while (CurrentEntry
!= &DeviceExtension
->ChildDeviceList
)
447 ChildExtension
= CONTAINING_RECORD(CurrentEntry
, VIDEO_PORT_CHILD_EXTENSION
, ListEntry
);
449 ObReferenceObject(ChildExtension
->PhysicalDeviceObject
);
450 DeviceRelations
->Objects
[i
] = ChildExtension
->PhysicalDeviceObject
;
453 CurrentEntry
= CurrentEntry
->Flink
;
456 INFO_(VIDEOPRT
, "Reported %d PDOs\n", i
);
457 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
459 return STATUS_SUCCESS
;
464 IntVideoPortForwardIrpAndWait(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
468 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
=
469 (PVIDEO_PORT_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
471 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
472 IoCopyCurrentIrpStackLocationToNext(Irp
);
473 IoSetCompletionRoutine(Irp
, IntVideoPortForwardIrpAndWaitCompletionRoutine
,
474 &Event
, TRUE
, TRUE
, TRUE
);
475 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
476 if (Status
== STATUS_PENDING
)
478 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
479 Status
= Irp
->IoStatus
.Status
;
485 IntVideoPortDispatchFdoPnp(
486 IN PDEVICE_OBJECT DeviceObject
,
489 PIO_STACK_LOCATION IrpSp
;
491 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
493 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
495 switch (IrpSp
->MinorFunction
)
497 case IRP_MN_START_DEVICE
:
498 Status
= IntVideoPortForwardIrpAndWait(DeviceObject
, Irp
);
499 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
500 Status
= IntVideoPortPnPStartDevice(DeviceObject
, Irp
);
501 Irp
->IoStatus
.Status
= Status
;
502 Irp
->IoStatus
.Information
= 0;
503 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
506 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
:
507 Status
= IntVideoPortForwardIrpAndWait(DeviceObject
, Irp
);
508 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
509 Status
= IntVideoPortFilterResourceRequirements(DeviceObject
, Irp
);
510 Irp
->IoStatus
.Status
= Status
;
511 Irp
->IoStatus
.Information
= 0;
512 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
515 case IRP_MN_QUERY_DEVICE_RELATIONS
:
516 if (IrpSp
->Parameters
.QueryDeviceRelations
.Type
!= BusRelations
)
518 IoSkipCurrentIrpStackLocation(Irp
);
519 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
523 Status
= IntVideoPortQueryBusRelations(DeviceObject
, Irp
);
524 Irp
->IoStatus
.Status
= Status
;
525 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
529 case IRP_MN_REMOVE_DEVICE
:
530 case IRP_MN_QUERY_REMOVE_DEVICE
:
531 case IRP_MN_CANCEL_REMOVE_DEVICE
:
532 case IRP_MN_SURPRISE_REMOVAL
:
534 case IRP_MN_STOP_DEVICE
:
535 Status
= IntVideoPortForwardIrpAndWait(DeviceObject
, Irp
);
536 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
537 Status
= STATUS_SUCCESS
;
538 Irp
->IoStatus
.Status
= Status
;
539 Irp
->IoStatus
.Information
= 0;
540 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
543 case IRP_MN_QUERY_STOP_DEVICE
:
544 case IRP_MN_CANCEL_STOP_DEVICE
:
545 Status
= STATUS_SUCCESS
;
546 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
547 Irp
->IoStatus
.Information
= 0;
548 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
552 Status
= Irp
->IoStatus
.Status
;
553 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
561 IntVideoPortDispatchPnp(
562 IN PDEVICE_OBJECT DeviceObject
,
565 PVIDEO_PORT_COMMON_EXTENSION CommonExtension
= DeviceObject
->DeviceExtension
;
567 if (CommonExtension
->Fdo
)
568 return IntVideoPortDispatchFdoPnp(DeviceObject
, Irp
);
570 return IntVideoPortDispatchPdoPnp(DeviceObject
, Irp
);
574 IntVideoPortDispatchCleanup(
575 IN PDEVICE_OBJECT DeviceObject
,
578 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
580 DeviceExtension
= DeviceObject
->DeviceExtension
;
581 RtlFreeUnicodeString(&DeviceExtension
->RegistryPath
);
583 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
584 Irp
->IoStatus
.Information
= 0;
585 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
587 return STATUS_SUCCESS
;
591 IntVideoPortDispatchPower(
592 IN PDEVICE_OBJECT DeviceObject
,
595 return STATUS_NOT_IMPLEMENTED
;
599 IntVideoPortDispatchSystemControl(
600 IN PDEVICE_OBJECT DeviceObject
,
603 return STATUS_NOT_IMPLEMENTED
;
607 IntVideoPortUnload(PDRIVER_OBJECT DriverObject
)