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 Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 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 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; see the file COPYING.LIB.
18 * If not, write to the Free Software Foundation,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 /* EXTERNAL FUNCTIONS *********************************************************/
27 VOID NTAPI
HalAcquireDisplayOwnership(IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
);
28 VOID NTAPI
HalReleaseDisplayOwnership();
30 /* GLOBAL VARIABLES ***********************************************************/
32 PVIDEO_PORT_DEVICE_EXTENSION ResetDisplayParametersDeviceExtension
= NULL
;
34 /* PRIVATE FUNCTIONS **********************************************************/
37 * Reset display to blue screen
41 IntVideoPortResetDisplayParameters(ULONG Columns
, ULONG Rows
)
43 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
;
45 if (ResetDisplayParametersDeviceExtension
== NULL
)
48 DriverExtension
= ResetDisplayParametersDeviceExtension
->DriverExtension
;
50 if (DriverExtension
->InitializationData
.HwResetHw
!= NULL
)
52 if (DriverExtension
->InitializationData
.HwResetHw(
53 &ResetDisplayParametersDeviceExtension
->MiniPortDeviceExtension
,
56 ResetDisplayParametersDeviceExtension
= NULL
;
61 ResetDisplayParametersDeviceExtension
= NULL
;
66 IntVideoPortAddDevice(
67 IN PDRIVER_OBJECT DriverObject
,
68 IN PDEVICE_OBJECT PhysicalDeviceObject
)
70 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
;
71 PDEVICE_OBJECT DeviceObject
;
75 * Get the initialization data we saved in VideoPortInitialize.
78 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
81 * Create adapter device object.
84 Status
= IntVideoPortCreateAdapterDeviceObject(
89 if (!NT_SUCCESS(Status
))
92 if (PhysicalDeviceObject
== NULL
)
94 /* We will never have a IRP_MJ_PNP/IRP_MN_START_DEVICE Irp */
95 Status
= IntVideoPortFindAdapter(DriverObject
, DriverExtension
, DeviceObject
);
101 * IntVideoPortDispatchOpen
103 * Answer requests for Open calls.
110 IntVideoPortDispatchOpen(
111 IN PDEVICE_OBJECT DeviceObject
,
114 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
115 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
;
117 DPRINT("IntVideoPortDispatchOpen\n");
119 if (CsrssInitialized
== FALSE
)
122 * We know the first open call will be from the CSRSS process
123 * to let us know its handle.
126 DPRINT("Referencing CSRSS\n");
127 Csrss
= (PKPROCESS
)PsGetCurrentProcess();
128 DPRINT("Csrss %p\n", Csrss
);
130 CsrssInitialized
= TRUE
;
132 Irp
->IoStatus
.Information
= FILE_OPENED
;
133 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
135 return STATUS_SUCCESS
;
138 DeviceExtension
= (PVIDEO_PORT_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
139 DriverExtension
= DeviceExtension
->DriverExtension
;
141 if (DriverExtension
->InitializationData
.HwInitialize(&DeviceExtension
->MiniPortDeviceExtension
))
143 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
145 InterlockedIncrement((PLONG
)&DeviceExtension
->DeviceOpened
);
149 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
152 Irp
->IoStatus
.Information
= FILE_OPENED
;
153 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
155 return STATUS_SUCCESS
;
159 * IntVideoPortDispatchClose
161 * Answer requests for Close calls.
168 IntVideoPortDispatchClose(
169 IN PDEVICE_OBJECT DeviceObject
,
172 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
174 DPRINT("IntVideoPortDispatchClose\n");
176 DeviceExtension
= (PVIDEO_PORT_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
177 if (DeviceExtension
->DeviceOpened
>= 1 &&
178 InterlockedDecrement((PLONG
)&DeviceExtension
->DeviceOpened
) == 0)
180 ResetDisplayParametersDeviceExtension
= DeviceExtension
;
181 HalReleaseDisplayOwnership();
184 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
185 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
187 return STATUS_SUCCESS
;
191 * IntVideoPortDispatchDeviceControl
193 * Answer requests for device control calls.
200 IntVideoPortDispatchDeviceControl(
201 IN PDEVICE_OBJECT DeviceObject
,
204 PIO_STACK_LOCATION IrpStack
;
205 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
;
206 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
207 PVIDEO_REQUEST_PACKET vrp
;
210 DPRINT("IntVideoPortDispatchDeviceControl\n");
212 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
213 DeviceExtension
= DeviceObject
->DeviceExtension
;
214 DriverExtension
= DeviceExtension
->DriverExtension
;
216 /* Translate the IRP to a VRP */
217 vrp
= ExAllocatePool(NonPagedPool
, sizeof(VIDEO_REQUEST_PACKET
));
220 return STATUS_NO_MEMORY
;
223 vrp
->StatusBlock
= (PSTATUS_BLOCK
)&(Irp
->IoStatus
);
224 vrp
->IoControlCode
= IrpStack
->Parameters
.DeviceIoControl
.IoControlCode
;
226 DPRINT("- IoControlCode: %x\n", vrp
->IoControlCode
);
228 /* We're assuming METHOD_BUFFERED */
229 vrp
->InputBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
230 vrp
->InputBufferLength
= IrpStack
->Parameters
.DeviceIoControl
.InputBufferLength
;
231 vrp
->OutputBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
232 vrp
->OutputBufferLength
= IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
234 /* Call the Miniport Driver with the VRP */
235 DriverExtension
->InitializationData
.HwStartIO(
236 &DeviceExtension
->MiniPortDeviceExtension
,
242 DPRINT("- Returned status: %x\n", Irp
->IoStatus
.Status
);
244 if (Irp
->IoStatus
.Status
!= STATUS_SUCCESS
)
246 /* Map from win32 error codes to NT status values. */
247 switch (Irp
->IoStatus
.Status
)
249 case ERROR_NOT_ENOUGH_MEMORY
: Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
; break;
250 case ERROR_MORE_DATA
: Irp
->IoStatus
.Status
= STATUS_BUFFER_OVERFLOW
; break;
251 case ERROR_INVALID_FUNCTION
: Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
; break;
252 case ERROR_INVALID_PARAMETER
: Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
; break;
253 case ERROR_INSUFFICIENT_BUFFER
: Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
; break;
254 case ERROR_DEV_NOT_EXIST
: Irp
->IoStatus
.Status
= STATUS_DEVICE_DOES_NOT_EXIST
; break;
255 case ERROR_IO_PENDING
: Irp
->IoStatus
.Status
= STATUS_PENDING
; break;
259 Status
= Irp
->IoStatus
.Status
;
260 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
268 * This is a bit of a hack. We want to take ownership of the display as late
269 * as possible, just before the switch to graphics mode. Win32k knows when
270 * this happens, we don't. So we need Win32k to inform us. This could be done
271 * using an IOCTL, but there's no way of knowing which IOCTL codes are unused
272 * in the communication between GDI driver and miniport driver. So we use
273 * IRP_MJ_WRITE as the signal that win32k is ready to switch to graphics mode,
274 * since we know for certain that there is no read/write activity going on
275 * between GDI and miniport drivers.
276 * We don't actually need the data that is passed, we just trigger on the fact
277 * that an IRP_MJ_WRITE was sent.
284 IntVideoPortDispatchWrite(
285 IN PDEVICE_OBJECT DeviceObject
,
288 PIO_STACK_LOCATION piosStack
= IoGetCurrentIrpStackLocation(Irp
);
289 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
292 DeviceExtension
= (PVIDEO_PORT_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
295 * Storing the device extension pointer in a static variable is an
296 * ugly hack. Unfortunately, we need it in VideoPortResetDisplayParameters
297 * and HalAcquireDisplayOwnership doesn't allow us to pass a userdata
298 * parameter. On the bright side, the DISPLAY device is opened
299 * exclusively, so there can be only one device extension active at
303 ResetDisplayParametersDeviceExtension
= DeviceExtension
;
304 HalAcquireDisplayOwnership(IntVideoPortResetDisplayParameters
);
306 nErrCode
= STATUS_SUCCESS
;
307 Irp
->IoStatus
.Information
= piosStack
->Parameters
.Write
.Length
;
308 Irp
->IoStatus
.Status
= nErrCode
;
309 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
316 IntVideoPortPnPStartDevice(
317 IN PDEVICE_OBJECT DeviceObject
,
320 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
321 PDRIVER_OBJECT DriverObject
;
322 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
;
323 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
324 PCM_RESOURCE_LIST AllocatedResources
;
327 * Get the initialization data we saved in VideoPortInitialize.
330 DriverObject
= DeviceObject
->DriverObject
;
331 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
332 DeviceExtension
= (PVIDEO_PORT_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
335 * Store some resources in the DeviceExtension.
338 AllocatedResources
= Stack
->Parameters
.StartDevice
.AllocatedResources
;
339 if (AllocatedResources
!= NULL
)
341 CM_FULL_RESOURCE_DESCRIPTOR
*FullList
;
342 CM_PARTIAL_RESOURCE_DESCRIPTOR
*Descriptor
;
344 ULONG ResourceListSize
;
346 /* Save the resource list */
347 ResourceCount
= AllocatedResources
->List
[0].PartialResourceList
.Count
;
349 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
350 PartialDescriptors
[ResourceCount
]);
351 DeviceExtension
->AllocatedResources
= ExAllocatePool(PagedPool
, ResourceListSize
);
352 if (DeviceExtension
->AllocatedResources
== NULL
)
354 return STATUS_INSUFFICIENT_RESOURCES
;
357 RtlCopyMemory(DeviceExtension
->AllocatedResources
,
361 /* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
362 for (FullList
= AllocatedResources
->List
;
363 FullList
< AllocatedResources
->List
+ AllocatedResources
->Count
;
366 /* FIXME: Is this ASSERT ok for resources from the PNP manager? */
367 ASSERT(FullList
->InterfaceType
== PCIBus
&&
368 FullList
->BusNumber
== DeviceExtension
->SystemIoBusNumber
&&
369 1 == FullList
->PartialResourceList
.Version
&&
370 1 == FullList
->PartialResourceList
.Revision
);
371 for (Descriptor
= FullList
->PartialResourceList
.PartialDescriptors
;
372 Descriptor
< FullList
->PartialResourceList
.PartialDescriptors
+ FullList
->PartialResourceList
.Count
;
375 if (Descriptor
->Type
== CmResourceTypeInterrupt
)
377 DeviceExtension
->InterruptLevel
= Descriptor
->u
.Interrupt
.Level
;
378 DeviceExtension
->InterruptVector
= Descriptor
->u
.Interrupt
.Vector
;
379 if (Descriptor
->ShareDisposition
== CmResourceShareShared
)
380 DeviceExtension
->InterruptShared
= TRUE
;
382 DeviceExtension
->InterruptShared
= FALSE
;
387 DPRINT("Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
388 DeviceExtension
->InterruptLevel
,
389 DeviceExtension
->InterruptVector
);
392 * Create adapter device object.
395 return IntVideoPortFindAdapter(
404 IntVideoPortForwardIrpAndWaitCompletionRoutine(
409 PKEVENT Event
= Context
;
411 if (Irp
->PendingReturned
)
412 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
414 return STATUS_MORE_PROCESSING_REQUIRED
;
420 IntVideoPortForwardIrpAndWait(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
424 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
=
425 (PVIDEO_PORT_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
427 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
428 IoCopyCurrentIrpStackLocationToNext(Irp
);
429 IoSetCompletionRoutine(Irp
, IntVideoPortForwardIrpAndWaitCompletionRoutine
,
430 &Event
, TRUE
, TRUE
, TRUE
);
431 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
432 if (Status
== STATUS_PENDING
)
434 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
435 Status
= Irp
->IoStatus
.Status
;
442 IntVideoPortDispatchPnp(
443 IN PDEVICE_OBJECT DeviceObject
,
446 PIO_STACK_LOCATION IrpSp
;
449 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
451 switch (IrpSp
->MinorFunction
)
453 case IRP_MN_START_DEVICE
:
454 Status
= IntVideoPortForwardIrpAndWait(DeviceObject
, Irp
);
455 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
456 Status
= IntVideoPortPnPStartDevice(DeviceObject
, Irp
);
457 Irp
->IoStatus
.Status
= Status
;
458 Irp
->IoStatus
.Information
= 0;
459 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
463 case IRP_MN_REMOVE_DEVICE
:
464 case IRP_MN_QUERY_REMOVE_DEVICE
:
465 case IRP_MN_CANCEL_REMOVE_DEVICE
:
466 case IRP_MN_SURPRISE_REMOVAL
:
468 case IRP_MN_STOP_DEVICE
:
469 Status
= IntVideoPortForwardIrpAndWait(DeviceObject
, Irp
);
470 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
471 Status
= STATUS_SUCCESS
;
472 Irp
->IoStatus
.Status
= Status
;
473 Irp
->IoStatus
.Information
= 0;
474 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
477 case IRP_MN_QUERY_STOP_DEVICE
:
478 case IRP_MN_CANCEL_STOP_DEVICE
:
479 Status
= STATUS_SUCCESS
;
480 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
481 Irp
->IoStatus
.Information
= 0;
482 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
486 return STATUS_NOT_IMPLEMENTED
;
494 IntVideoPortDispatchCleanup(
495 IN PDEVICE_OBJECT DeviceObject
,
498 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
500 DeviceExtension
= DeviceObject
->DeviceExtension
;
501 RtlFreeUnicodeString(&DeviceExtension
->RegistryPath
);
503 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
504 Irp
->IoStatus
.Information
= 0;
505 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
507 return STATUS_SUCCESS
;
511 IntVideoPortDispatchPower(
512 IN PDEVICE_OBJECT DeviceObject
,
515 return STATUS_NOT_IMPLEMENTED
;
519 IntVideoPortUnload(PDRIVER_OBJECT DriverObject
)