- Fixed releasing of display ownership.
[reactos.git] / reactos / drivers / video / videoprt / dispatch.c
1 /*
2 * VideoPort driver
3 *
4 * Copyright (C) 2002, 2003, 2004 ReactOS Team
5 *
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.
10 *
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.
15 *
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.
20 *
21 * $Id: dispatch.c,v 1.3 2004/04/08 09:43:55 navaraf Exp $
22 */
23
24 #include "videoprt.h"
25
26 /* EXTERNAL FUNCTIONS *********************************************************/
27
28 typedef PVOID PHAL_RESET_DISPLAY_PARAMETERS;
29 VOID STDCALL HalAcquireDisplayOwnership(IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters);
30 VOID STDCALL HalReleaseDisplayOwnership();
31
32 /* GLOBAL VARIABLES ***********************************************************/
33
34 PVIDEO_PORT_DEVICE_EXTENSION ResetDisplayParametersDeviceExtension = NULL;
35
36 /* PRIVATE FUNCTIONS **********************************************************/
37
38 /*
39 * Reset display to blue screen
40 */
41
42 BOOLEAN STDCALL
43 IntVideoPortResetDisplayParameters(ULONG Columns, ULONG Rows)
44 {
45 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
46
47 if (ResetDisplayParametersDeviceExtension == NULL)
48 return FALSE;
49
50 DriverExtension = ResetDisplayParametersDeviceExtension->DriverExtension;
51
52 ASSERT(DriverExtension->InitializationData.HwResetHw != NULL);
53
54 if (!DriverExtension->InitializationData.HwResetHw(
55 &ResetDisplayParametersDeviceExtension->MiniPortDeviceExtension,
56 Columns, Rows))
57 {
58 ResetDisplayParametersDeviceExtension = NULL;
59 return FALSE;
60 }
61
62 ResetDisplayParametersDeviceExtension = NULL;
63 return TRUE;
64 }
65
66 NTSTATUS STDCALL
67 IntVideoPortAddDevice(
68 IN PDRIVER_OBJECT DriverObject,
69 IN PDEVICE_OBJECT PhysicalDeviceObject)
70 {
71 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
72
73 /*
74 * Get the initialization data we saved in VideoPortInitialize.
75 */
76
77 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
78
79 /*
80 * Use generic routine to find the adapter and create device object.
81 */
82
83 return IntVideoPortFindAdapter(
84 DriverObject,
85 DriverExtension,
86 PhysicalDeviceObject);
87 }
88
89 /*
90 * IntVideoPortDispatchOpen
91 *
92 * Answer requests for Open calls.
93 *
94 * Run Level
95 * PASSIVE_LEVEL
96 */
97
98 NTSTATUS STDCALL
99 IntVideoPortDispatchOpen(
100 IN PDEVICE_OBJECT DeviceObject,
101 IN PIRP Irp)
102 {
103 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
104 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
105
106 DPRINT("IntVideoPortDispatchOpen\n");
107
108 if (CsrssInitialized == FALSE)
109 {
110 /*
111 * We know the first open call will be from the CSRSS process
112 * to let us know its handle.
113 */
114
115 DPRINT("Referencing CSRSS\n");
116 Csrss = PsGetCurrentProcess();
117 DPRINT("Csrss %p\n", Csrss);
118
119 CsrssInitialized = TRUE;
120
121 Irp->IoStatus.Information = FILE_OPENED;
122 IoCompleteRequest(Irp, IO_NO_INCREMENT);
123
124 return STATUS_SUCCESS;
125 }
126
127 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
128 DriverExtension = DeviceExtension->DriverExtension;
129
130 if (DriverExtension->InitializationData.HwInitialize(&DeviceExtension->MiniPortDeviceExtension))
131 {
132 Irp->IoStatus.Status = STATUS_SUCCESS;
133
134 InterlockedIncrement(&DeviceExtension->DeviceOpened);
135
136 /*
137 * Storing the device extension pointer in a static variable is an
138 * ugly hack. Unfortunately, we need it in VideoPortResetDisplayParameters
139 * and HalAcquireDisplayOwnership doesn't allow us to pass a userdata
140 * parameter. On the bright side, the DISPLAY device is opened
141 * exclusively, so there can be only one device extension active at
142 * any point in time.
143 */
144
145 ResetDisplayParametersDeviceExtension = DeviceExtension;
146 HalAcquireDisplayOwnership(IntVideoPortResetDisplayParameters);
147 }
148 else
149 {
150 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
151 }
152
153 Irp->IoStatus.Information = FILE_OPENED;
154 IoCompleteRequest(Irp, IO_NO_INCREMENT);
155
156 return STATUS_SUCCESS;
157 }
158
159 /*
160 * IntVideoPortDispatchClose
161 *
162 * Answer requests for Close calls.
163 *
164 * Run Level
165 * PASSIVE_LEVEL
166 */
167
168 NTSTATUS STDCALL
169 IntVideoPortDispatchClose(
170 IN PDEVICE_OBJECT DeviceObject,
171 IN PIRP Irp)
172 {
173 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
174
175 DPRINT("IntVideoPortDispatchClose\n");
176
177 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
178 if (DeviceExtension->DeviceOpened > 1 &&
179 InterlockedDecrement(&DeviceExtension->DeviceOpened) == 0)
180 {
181 ResetDisplayParametersDeviceExtension = DeviceExtension;
182 HalReleaseDisplayOwnership();
183 }
184
185 Irp->IoStatus.Status = STATUS_SUCCESS;
186 IoCompleteRequest(Irp, IO_NO_INCREMENT);
187
188 return STATUS_SUCCESS;
189 }
190
191 /*
192 * IntVideoPortDispatchDeviceControl
193 *
194 * Answer requests for device control calls.
195 *
196 * Run Level
197 * PASSIVE_LEVEL
198 */
199
200 NTSTATUS STDCALL
201 IntVideoPortDispatchDeviceControl(
202 IN PDEVICE_OBJECT DeviceObject,
203 IN PIRP Irp)
204 {
205 PIO_STACK_LOCATION IrpStack;
206 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
207 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
208 PVIDEO_REQUEST_PACKET vrp;
209 NTSTATUS Status;
210
211 DPRINT("IntVideoPortDispatchDeviceControl\n");
212
213 IrpStack = IoGetCurrentIrpStackLocation(Irp);
214 DeviceExtension = DeviceObject->DeviceExtension;
215 DriverExtension = DeviceExtension->DriverExtension;
216
217 /* Translate the IRP to a VRP */
218 vrp = ExAllocatePool(NonPagedPool, sizeof(VIDEO_REQUEST_PACKET));
219 if (NULL == vrp)
220 {
221 return STATUS_NO_MEMORY;
222 }
223
224 vrp->StatusBlock = (PSTATUS_BLOCK)&(Irp->IoStatus);
225 vrp->IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
226
227 DPRINT("- IoControlCode: %x\n", vrp->IoControlCode);
228
229 /* We're assuming METHOD_BUFFERED */
230 vrp->InputBuffer = Irp->AssociatedIrp.SystemBuffer;
231 vrp->InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
232 vrp->OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
233 vrp->OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
234
235 /* Call the Miniport Driver with the VRP */
236 DriverExtension->InitializationData.HwStartIO(
237 &DeviceExtension->MiniPortDeviceExtension,
238 vrp);
239
240 /* Free the VRP */
241 ExFreePool(vrp);
242
243 DPRINT("- Returned status: %x\n", Irp->IoStatus.Status);
244
245 if (Irp->IoStatus.Status != STATUS_SUCCESS)
246 {
247 /* Map from win32 error codes to NT status values. */
248 switch (Irp->IoStatus.Status)
249 {
250 case ERROR_NOT_ENOUGH_MEMORY: Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; break;
251 case ERROR_MORE_DATA: Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; break;
252 case ERROR_INVALID_FUNCTION: Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; break;
253 case ERROR_INVALID_PARAMETER: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; break;
254 case ERROR_INSUFFICIENT_BUFFER: Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; break;
255 case ERROR_DEV_NOT_EXIST: Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST; break;
256 case ERROR_IO_PENDING: Irp->IoStatus.Status = STATUS_PENDING; break;
257 }
258 }
259
260 Status = Irp->IoStatus.Status;
261 IoCompleteRequest(Irp, IO_NO_INCREMENT);
262
263 return Status;
264 }
265
266 NTSTATUS STDCALL
267 IntVideoPortDispatchPnp(
268 IN PDEVICE_OBJECT DeviceObject,
269 IN PIRP Irp)
270 {
271 PIO_STACK_LOCATION IrpSp;
272
273 IrpSp = IoGetCurrentIrpStackLocation(Irp);
274
275 switch (IrpSp->MinorFunction)
276 {
277 case IRP_MN_START_DEVICE:
278
279 case IRP_MN_REMOVE_DEVICE:
280 case IRP_MN_QUERY_REMOVE_DEVICE:
281 case IRP_MN_CANCEL_REMOVE_DEVICE:
282 case IRP_MN_SURPRISE_REMOVAL:
283
284 case IRP_MN_STOP_DEVICE:
285 case IRP_MN_QUERY_STOP_DEVICE:
286 case IRP_MN_CANCEL_STOP_DEVICE:
287 Irp->IoStatus.Status = STATUS_SUCCESS;
288 Irp->IoStatus.Information = 0;
289 IoCompleteRequest(Irp, IO_NO_INCREMENT);
290
291 return STATUS_SUCCESS;
292 }
293
294 return STATUS_NOT_IMPLEMENTED;
295 }
296
297 NTSTATUS STDCALL
298 IntVideoPortDispatchCleanup(
299 IN PDEVICE_OBJECT DeviceObject,
300 IN PIRP Irp)
301 {
302 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
303
304 DeviceExtension = DeviceObject->DeviceExtension;
305 RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
306
307 Irp->IoStatus.Status = STATUS_SUCCESS;
308 Irp->IoStatus.Information = 0;
309 IoCompleteRequest(Irp, IO_NO_INCREMENT);
310
311 return STATUS_SUCCESS;
312 }
313
314 NTSTATUS STDCALL
315 IntVideoPortDispatchPower(
316 IN PDEVICE_OBJECT DeviceObject,
317 IN PIRP Irp)
318 {
319 return STATUS_NOT_IMPLEMENTED;
320 }
321
322 VOID STDCALL
323 IntVideoPortUnload(PDRIVER_OBJECT DriverObject)
324 {
325 }