Merge 13159:13510 from trunk
[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$
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 if (DriverExtension->InitializationData.HwResetHw != NULL)
53 {
54 if (DriverExtension->InitializationData.HwResetHw(
55 &ResetDisplayParametersDeviceExtension->MiniPortDeviceExtension,
56 Columns, Rows))
57 {
58 ResetDisplayParametersDeviceExtension = NULL;
59 return TRUE;
60 }
61 }
62
63 ResetDisplayParametersDeviceExtension = NULL;
64 return FALSE;
65 }
66
67 NTSTATUS STDCALL
68 IntVideoPortAddDevice(
69 IN PDRIVER_OBJECT DriverObject,
70 IN PDEVICE_OBJECT PhysicalDeviceObject)
71 {
72 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
73
74 /*
75 * Get the initialization data we saved in VideoPortInitialize.
76 */
77
78 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
79
80 /*
81 * Create adapter device object.
82 */
83
84 return IntVideoPortCreateAdapterDeviceObject(
85 DriverObject,
86 DriverExtension,
87 PhysicalDeviceObject,
88 NULL);
89 }
90
91 /*
92 * IntVideoPortDispatchOpen
93 *
94 * Answer requests for Open calls.
95 *
96 * Run Level
97 * PASSIVE_LEVEL
98 */
99
100 NTSTATUS STDCALL
101 IntVideoPortDispatchOpen(
102 IN PDEVICE_OBJECT DeviceObject,
103 IN PIRP Irp)
104 {
105 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
106 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
107
108 DPRINT("IntVideoPortDispatchOpen\n");
109
110 if (CsrssInitialized == FALSE)
111 {
112 /*
113 * We know the first open call will be from the CSRSS process
114 * to let us know its handle.
115 */
116
117 DPRINT("Referencing CSRSS\n");
118 Csrss = PsGetCurrentProcess();
119 DPRINT("Csrss %p\n", Csrss);
120
121 CsrssInitialized = TRUE;
122
123 Irp->IoStatus.Information = FILE_OPENED;
124 IoCompleteRequest(Irp, IO_NO_INCREMENT);
125
126 return STATUS_SUCCESS;
127 }
128
129 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
130 DriverExtension = DeviceExtension->DriverExtension;
131
132 if (DriverExtension->InitializationData.HwInitialize(&DeviceExtension->MiniPortDeviceExtension))
133 {
134 Irp->IoStatus.Status = STATUS_SUCCESS;
135
136 InterlockedIncrement((PLONG)&DeviceExtension->DeviceOpened);
137
138 /*
139 * Storing the device extension pointer in a static variable is an
140 * ugly hack. Unfortunately, we need it in VideoPortResetDisplayParameters
141 * and HalAcquireDisplayOwnership doesn't allow us to pass a userdata
142 * parameter. On the bright side, the DISPLAY device is opened
143 * exclusively, so there can be only one device extension active at
144 * any point in time.
145 */
146
147 ResetDisplayParametersDeviceExtension = DeviceExtension;
148 HalAcquireDisplayOwnership(IntVideoPortResetDisplayParameters);
149 }
150 else
151 {
152 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
153 }
154
155 Irp->IoStatus.Information = FILE_OPENED;
156 IoCompleteRequest(Irp, IO_NO_INCREMENT);
157
158 return STATUS_SUCCESS;
159 }
160
161 /*
162 * IntVideoPortDispatchClose
163 *
164 * Answer requests for Close calls.
165 *
166 * Run Level
167 * PASSIVE_LEVEL
168 */
169
170 NTSTATUS STDCALL
171 IntVideoPortDispatchClose(
172 IN PDEVICE_OBJECT DeviceObject,
173 IN PIRP Irp)
174 {
175 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
176
177 DPRINT("IntVideoPortDispatchClose\n");
178
179 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
180 if (DeviceExtension->DeviceOpened >= 1 &&
181 InterlockedDecrement((PLONG)&DeviceExtension->DeviceOpened) == 0)
182 {
183 ResetDisplayParametersDeviceExtension = DeviceExtension;
184 HalReleaseDisplayOwnership();
185 }
186
187 Irp->IoStatus.Status = STATUS_SUCCESS;
188 IoCompleteRequest(Irp, IO_NO_INCREMENT);
189
190 return STATUS_SUCCESS;
191 }
192
193 /*
194 * IntVideoPortDispatchDeviceControl
195 *
196 * Answer requests for device control calls.
197 *
198 * Run Level
199 * PASSIVE_LEVEL
200 */
201
202 NTSTATUS STDCALL
203 IntVideoPortDispatchDeviceControl(
204 IN PDEVICE_OBJECT DeviceObject,
205 IN PIRP Irp)
206 {
207 PIO_STACK_LOCATION IrpStack;
208 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
209 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
210 PVIDEO_REQUEST_PACKET vrp;
211 NTSTATUS Status;
212
213 DPRINT("IntVideoPortDispatchDeviceControl\n");
214
215 IrpStack = IoGetCurrentIrpStackLocation(Irp);
216 DeviceExtension = DeviceObject->DeviceExtension;
217 DriverExtension = DeviceExtension->DriverExtension;
218
219 /* Translate the IRP to a VRP */
220 vrp = ExAllocatePool(NonPagedPool, sizeof(VIDEO_REQUEST_PACKET));
221 if (NULL == vrp)
222 {
223 return STATUS_NO_MEMORY;
224 }
225
226 vrp->StatusBlock = (PSTATUS_BLOCK)&(Irp->IoStatus);
227 vrp->IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
228
229 DPRINT("- IoControlCode: %x\n", vrp->IoControlCode);
230
231 /* We're assuming METHOD_BUFFERED */
232 vrp->InputBuffer = Irp->AssociatedIrp.SystemBuffer;
233 vrp->InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
234 vrp->OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
235 vrp->OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
236
237 /* Call the Miniport Driver with the VRP */
238 DriverExtension->InitializationData.HwStartIO(
239 &DeviceExtension->MiniPortDeviceExtension,
240 vrp);
241
242 /* Free the VRP */
243 ExFreePool(vrp);
244
245 DPRINT("- Returned status: %x\n", Irp->IoStatus.Status);
246
247 if (Irp->IoStatus.Status != STATUS_SUCCESS)
248 {
249 /* Map from win32 error codes to NT status values. */
250 switch (Irp->IoStatus.Status)
251 {
252 case ERROR_NOT_ENOUGH_MEMORY: Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; break;
253 case ERROR_MORE_DATA: Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; break;
254 case ERROR_INVALID_FUNCTION: Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; break;
255 case ERROR_INVALID_PARAMETER: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; break;
256 case ERROR_INSUFFICIENT_BUFFER: Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; break;
257 case ERROR_DEV_NOT_EXIST: Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST; break;
258 case ERROR_IO_PENDING: Irp->IoStatus.Status = STATUS_PENDING; break;
259 }
260 }
261
262 Status = Irp->IoStatus.Status;
263 IoCompleteRequest(Irp, IO_NO_INCREMENT);
264
265 return Status;
266 }
267
268 NTSTATUS STDCALL
269 IntVideoPortPnPStartDevice(
270 IN PDEVICE_OBJECT DeviceObject,
271 IN PIRP Irp)
272 {
273 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
274 PDRIVER_OBJECT DriverObject;
275 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
276 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
277 PCM_RESOURCE_LIST AllocatedResources;
278
279 /*
280 * Get the initialization data we saved in VideoPortInitialize.
281 */
282
283 DriverObject = DeviceObject->DriverObject;
284 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
285 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
286
287 /*
288 * Store some resources in the DeviceExtension.
289 */
290
291 AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources;
292 if (AllocatedResources != NULL)
293 {
294 CM_FULL_RESOURCE_DESCRIPTOR *FullList;
295 CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
296 ULONG ResourceCount;
297 ULONG ResourceListSize;
298
299 /* Save the resource list */
300 ResourceCount = AllocatedResources->List[0].PartialResourceList.Count;
301 ResourceListSize =
302 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
303 PartialDescriptors[ResourceCount]);
304 DeviceExtension->AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize);
305 if (DeviceExtension->AllocatedResources == NULL)
306 {
307 return STATUS_INSUFFICIENT_RESOURCES;
308 }
309
310 RtlCopyMemory(DeviceExtension->AllocatedResources,
311 AllocatedResources,
312 ResourceListSize);
313
314 /* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
315 for (FullList = AllocatedResources->List;
316 FullList < AllocatedResources->List + AllocatedResources->Count;
317 FullList++)
318 {
319 /* FIXME: Is this ASSERT ok for resources from the PNP manager? */
320 ASSERT(FullList->InterfaceType == PCIBus &&
321 FullList->BusNumber == DeviceExtension->SystemIoBusNumber &&
322 1 == FullList->PartialResourceList.Version &&
323 1 == FullList->PartialResourceList.Revision);
324 for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
325 Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
326 Descriptor++)
327 {
328 if (Descriptor->Type == CmResourceTypeInterrupt)
329 {
330 DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
331 DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
332 }
333 }
334 }
335 }
336 DPRINT("Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
337 DeviceExtension->InterruptLevel,
338 DeviceExtension->InterruptVector);
339
340 /*
341 * Create adapter device object.
342 */
343
344 return IntVideoPortFindAdapter(
345 DriverObject,
346 DriverExtension,
347 DeviceObject);
348 }
349
350
351 NTSTATUS
352 STDCALL
353 IntVideoPortForwardIrpAndWaitCompletionRoutine(
354 PDEVICE_OBJECT Fdo,
355 PIRP Irp,
356 PVOID Context)
357 {
358 PKEVENT Event = Context;
359
360 if (Irp->PendingReturned)
361 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
362
363 return STATUS_MORE_PROCESSING_REQUIRED;
364 }
365
366
367 NTSTATUS
368 STDCALL
369 IntVideoPortForwardIrpAndWait(PDEVICE_OBJECT DeviceObject, PIRP Irp)
370 {
371 KEVENT Event;
372 NTSTATUS Status;
373 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension =
374 (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
375
376 KeInitializeEvent(&Event, NotificationEvent, FALSE);
377 IoCopyCurrentIrpStackLocationToNext(Irp);
378 IoSetCompletionRoutine(Irp, IntVideoPortForwardIrpAndWaitCompletionRoutine,
379 &Event, TRUE, TRUE, TRUE);
380 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
381 if (Status == STATUS_PENDING)
382 {
383 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
384 Status = Irp->IoStatus.Status;
385 }
386 return Status;
387 }
388
389
390 NTSTATUS STDCALL
391 IntVideoPortDispatchPnp(
392 IN PDEVICE_OBJECT DeviceObject,
393 IN PIRP Irp)
394 {
395 PIO_STACK_LOCATION IrpSp;
396 NTSTATUS Status;
397
398 IrpSp = IoGetCurrentIrpStackLocation(Irp);
399
400 switch (IrpSp->MinorFunction)
401 {
402 case IRP_MN_START_DEVICE:
403 Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
404 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
405 Status = IntVideoPortPnPStartDevice(DeviceObject, Irp);
406 Irp->IoStatus.Status = Status;
407 Irp->IoStatus.Information = 0;
408 IoCompleteRequest(Irp, IO_NO_INCREMENT);
409 break;
410
411
412 case IRP_MN_REMOVE_DEVICE:
413 case IRP_MN_QUERY_REMOVE_DEVICE:
414 case IRP_MN_CANCEL_REMOVE_DEVICE:
415 case IRP_MN_SURPRISE_REMOVAL:
416
417 case IRP_MN_STOP_DEVICE:
418 Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
419 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
420 Status = STATUS_SUCCESS;
421 Irp->IoStatus.Status = Status;
422 Irp->IoStatus.Information = 0;
423 IoCompleteRequest(Irp, IO_NO_INCREMENT);
424 break;
425
426 case IRP_MN_QUERY_STOP_DEVICE:
427 case IRP_MN_CANCEL_STOP_DEVICE:
428 Status = STATUS_SUCCESS;
429 Irp->IoStatus.Status = STATUS_SUCCESS;
430 Irp->IoStatus.Information = 0;
431 IoCompleteRequest(Irp, IO_NO_INCREMENT);
432 break;
433
434 default:
435 return STATUS_NOT_IMPLEMENTED;
436 break;
437 }
438
439 return Status;
440 }
441
442 NTSTATUS STDCALL
443 IntVideoPortDispatchCleanup(
444 IN PDEVICE_OBJECT DeviceObject,
445 IN PIRP Irp)
446 {
447 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
448
449 DeviceExtension = DeviceObject->DeviceExtension;
450 RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
451
452 Irp->IoStatus.Status = STATUS_SUCCESS;
453 Irp->IoStatus.Information = 0;
454 IoCompleteRequest(Irp, IO_NO_INCREMENT);
455
456 return STATUS_SUCCESS;
457 }
458
459 NTSTATUS STDCALL
460 IntVideoPortDispatchPower(
461 IN PDEVICE_OBJECT DeviceObject,
462 IN PIRP Irp)
463 {
464 return STATUS_NOT_IMPLEMENTED;
465 }
466
467 VOID STDCALL
468 IntVideoPortUnload(PDRIVER_OBJECT DriverObject)
469 {
470 }