Fix sublanguage IDs in .rc files:
[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 */
22
23 #include "videoprt.h"
24
25 /* EXTERNAL FUNCTIONS *********************************************************/
26
27 VOID NTAPI HalAcquireDisplayOwnership(IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters);
28 VOID NTAPI HalReleaseDisplayOwnership();
29
30 /* GLOBAL VARIABLES ***********************************************************/
31
32 PVIDEO_PORT_DEVICE_EXTENSION ResetDisplayParametersDeviceExtension = NULL;
33
34 /* PRIVATE FUNCTIONS **********************************************************/
35
36 /*
37 * Reset display to blue screen
38 */
39
40 BOOLEAN NTAPI
41 IntVideoPortResetDisplayParameters(ULONG Columns, ULONG Rows)
42 {
43 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
44
45 if (ResetDisplayParametersDeviceExtension == NULL)
46 return FALSE;
47
48 DriverExtension = ResetDisplayParametersDeviceExtension->DriverExtension;
49
50 if (DriverExtension->InitializationData.HwResetHw != NULL)
51 {
52 if (DriverExtension->InitializationData.HwResetHw(
53 &ResetDisplayParametersDeviceExtension->MiniPortDeviceExtension,
54 Columns, Rows))
55 {
56 ResetDisplayParametersDeviceExtension = NULL;
57 return TRUE;
58 }
59 }
60
61 ResetDisplayParametersDeviceExtension = NULL;
62 return FALSE;
63 }
64
65 NTSTATUS NTAPI
66 IntVideoPortAddDevice(
67 IN PDRIVER_OBJECT DriverObject,
68 IN PDEVICE_OBJECT PhysicalDeviceObject)
69 {
70 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
71 PDEVICE_OBJECT DeviceObject;
72 NTSTATUS Status;
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 Status = IntVideoPortCreateAdapterDeviceObject(
85 DriverObject,
86 DriverExtension,
87 PhysicalDeviceObject,
88 &DeviceObject);
89 if (!NT_SUCCESS(Status))
90 return Status;
91
92 if (PhysicalDeviceObject == NULL)
93 {
94 /* We will never have a IRP_MJ_PNP/IRP_MN_START_DEVICE Irp */
95 Status = IntVideoPortFindAdapter(DriverObject, DriverExtension, DeviceObject);
96 }
97 return Status;
98 }
99
100 /*
101 * IntVideoPortDispatchOpen
102 *
103 * Answer requests for Open calls.
104 *
105 * Run Level
106 * PASSIVE_LEVEL
107 */
108
109 NTSTATUS NTAPI
110 IntVideoPortDispatchOpen(
111 IN PDEVICE_OBJECT DeviceObject,
112 IN PIRP Irp)
113 {
114 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
115 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
116
117 DPRINT("IntVideoPortDispatchOpen\n");
118
119 if (CsrssInitialized == FALSE)
120 {
121 /*
122 * We know the first open call will be from the CSRSS process
123 * to let us know its handle.
124 */
125
126 DPRINT("Referencing CSRSS\n");
127 Csrss = (PKPROCESS)PsGetCurrentProcess();
128 DPRINT("Csrss %p\n", Csrss);
129
130 CsrssInitialized = TRUE;
131
132 Irp->IoStatus.Information = FILE_OPENED;
133 IoCompleteRequest(Irp, IO_NO_INCREMENT);
134
135 return STATUS_SUCCESS;
136 }
137
138 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
139 DriverExtension = DeviceExtension->DriverExtension;
140
141 if (DriverExtension->InitializationData.HwInitialize(&DeviceExtension->MiniPortDeviceExtension))
142 {
143 Irp->IoStatus.Status = STATUS_SUCCESS;
144
145 InterlockedIncrement((PLONG)&DeviceExtension->DeviceOpened);
146 }
147 else
148 {
149 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
150 }
151
152 Irp->IoStatus.Information = FILE_OPENED;
153 IoCompleteRequest(Irp, IO_NO_INCREMENT);
154
155 return STATUS_SUCCESS;
156 }
157
158 /*
159 * IntVideoPortDispatchClose
160 *
161 * Answer requests for Close calls.
162 *
163 * Run Level
164 * PASSIVE_LEVEL
165 */
166
167 NTSTATUS NTAPI
168 IntVideoPortDispatchClose(
169 IN PDEVICE_OBJECT DeviceObject,
170 IN PIRP Irp)
171 {
172 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
173
174 DPRINT("IntVideoPortDispatchClose\n");
175
176 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
177 if (DeviceExtension->DeviceOpened >= 1 &&
178 InterlockedDecrement((PLONG)&DeviceExtension->DeviceOpened) == 0)
179 {
180 ResetDisplayParametersDeviceExtension = DeviceExtension;
181 HalReleaseDisplayOwnership();
182 }
183
184 Irp->IoStatus.Status = STATUS_SUCCESS;
185 IoCompleteRequest(Irp, IO_NO_INCREMENT);
186
187 return STATUS_SUCCESS;
188 }
189
190 /*
191 * IntVideoPortDispatchDeviceControl
192 *
193 * Answer requests for device control calls.
194 *
195 * Run Level
196 * PASSIVE_LEVEL
197 */
198
199 NTSTATUS NTAPI
200 IntVideoPortDispatchDeviceControl(
201 IN PDEVICE_OBJECT DeviceObject,
202 IN PIRP Irp)
203 {
204 PIO_STACK_LOCATION IrpStack;
205 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
206 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
207 PVIDEO_REQUEST_PACKET vrp;
208 NTSTATUS Status;
209
210 DPRINT("IntVideoPortDispatchDeviceControl\n");
211
212 IrpStack = IoGetCurrentIrpStackLocation(Irp);
213 DeviceExtension = DeviceObject->DeviceExtension;
214 DriverExtension = DeviceExtension->DriverExtension;
215
216 /* Translate the IRP to a VRP */
217 vrp = ExAllocatePool(NonPagedPool, sizeof(VIDEO_REQUEST_PACKET));
218 if (NULL == vrp)
219 {
220 return STATUS_NO_MEMORY;
221 }
222
223 vrp->StatusBlock = (PSTATUS_BLOCK)&(Irp->IoStatus);
224 vrp->IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
225
226 DPRINT("- IoControlCode: %x\n", vrp->IoControlCode);
227
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;
233
234 /* Call the Miniport Driver with the VRP */
235 DriverExtension->InitializationData.HwStartIO(
236 &DeviceExtension->MiniPortDeviceExtension,
237 vrp);
238
239 /* Free the VRP */
240 ExFreePool(vrp);
241
242 DPRINT("- Returned status: %x\n", Irp->IoStatus.Status);
243
244 if (Irp->IoStatus.Status != STATUS_SUCCESS)
245 {
246 /* Map from win32 error codes to NT status values. */
247 switch (Irp->IoStatus.Status)
248 {
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;
256 }
257 }
258
259 Status = Irp->IoStatus.Status;
260 IoCompleteRequest(Irp, IO_NO_INCREMENT);
261
262 return Status;
263 }
264
265 /*
266 * IntVideoPortWrite
267 *
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.
278 *
279 * Run Level
280 * PASSIVE_LEVEL
281 */
282
283 NTSTATUS NTAPI
284 IntVideoPortDispatchWrite(
285 IN PDEVICE_OBJECT DeviceObject,
286 IN PIRP Irp)
287 {
288 PIO_STACK_LOCATION piosStack = IoGetCurrentIrpStackLocation(Irp);
289 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
290 NTSTATUS nErrCode;
291
292 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
293
294 /*
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
300 * any point in time.
301 */
302
303 ResetDisplayParametersDeviceExtension = DeviceExtension;
304 HalAcquireDisplayOwnership(IntVideoPortResetDisplayParameters);
305
306 nErrCode = STATUS_SUCCESS;
307 Irp->IoStatus.Information = piosStack->Parameters.Write.Length;
308 Irp->IoStatus.Status = nErrCode;
309 IoCompleteRequest(Irp, IO_NO_INCREMENT);
310
311 return nErrCode;
312 }
313
314
315 NTSTATUS NTAPI
316 IntVideoPortPnPStartDevice(
317 IN PDEVICE_OBJECT DeviceObject,
318 IN PIRP Irp)
319 {
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;
325
326 /*
327 * Get the initialization data we saved in VideoPortInitialize.
328 */
329
330 DriverObject = DeviceObject->DriverObject;
331 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
332 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
333
334 /*
335 * Store some resources in the DeviceExtension.
336 */
337
338 AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources;
339 if (AllocatedResources != NULL)
340 {
341 CM_FULL_RESOURCE_DESCRIPTOR *FullList;
342 CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
343 ULONG ResourceCount;
344 ULONG ResourceListSize;
345
346 /* Save the resource list */
347 ResourceCount = AllocatedResources->List[0].PartialResourceList.Count;
348 ResourceListSize =
349 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
350 PartialDescriptors[ResourceCount]);
351 DeviceExtension->AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize);
352 if (DeviceExtension->AllocatedResources == NULL)
353 {
354 return STATUS_INSUFFICIENT_RESOURCES;
355 }
356
357 RtlCopyMemory(DeviceExtension->AllocatedResources,
358 AllocatedResources,
359 ResourceListSize);
360
361 /* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
362 for (FullList = AllocatedResources->List;
363 FullList < AllocatedResources->List + AllocatedResources->Count;
364 FullList++)
365 {
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;
373 Descriptor++)
374 {
375 if (Descriptor->Type == CmResourceTypeInterrupt)
376 {
377 DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
378 DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
379 if (Descriptor->ShareDisposition == CmResourceShareShared)
380 DeviceExtension->InterruptShared = TRUE;
381 else
382 DeviceExtension->InterruptShared = FALSE;
383 }
384 }
385 }
386 }
387 DPRINT("Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
388 DeviceExtension->InterruptLevel,
389 DeviceExtension->InterruptVector);
390
391 /*
392 * Create adapter device object.
393 */
394
395 return IntVideoPortFindAdapter(
396 DriverObject,
397 DriverExtension,
398 DeviceObject);
399 }
400
401
402 NTSTATUS
403 NTAPI
404 IntVideoPortForwardIrpAndWaitCompletionRoutine(
405 PDEVICE_OBJECT Fdo,
406 PIRP Irp,
407 PVOID Context)
408 {
409 PKEVENT Event = Context;
410
411 if (Irp->PendingReturned)
412 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
413
414 return STATUS_MORE_PROCESSING_REQUIRED;
415 }
416
417
418 NTSTATUS
419 NTAPI
420 IntVideoPortForwardIrpAndWait(PDEVICE_OBJECT DeviceObject, PIRP Irp)
421 {
422 KEVENT Event;
423 NTSTATUS Status;
424 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension =
425 (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
426
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)
433 {
434 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
435 Status = Irp->IoStatus.Status;
436 }
437 return Status;
438 }
439
440
441 NTSTATUS NTAPI
442 IntVideoPortDispatchPnp(
443 IN PDEVICE_OBJECT DeviceObject,
444 IN PIRP Irp)
445 {
446 PIO_STACK_LOCATION IrpSp;
447 NTSTATUS Status;
448
449 IrpSp = IoGetCurrentIrpStackLocation(Irp);
450
451 switch (IrpSp->MinorFunction)
452 {
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);
460 break;
461
462
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:
467
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);
475 break;
476
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);
483 break;
484
485 default:
486 return STATUS_NOT_IMPLEMENTED;
487 break;
488 }
489
490 return Status;
491 }
492
493 NTSTATUS NTAPI
494 IntVideoPortDispatchCleanup(
495 IN PDEVICE_OBJECT DeviceObject,
496 IN PIRP Irp)
497 {
498 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
499
500 DeviceExtension = DeviceObject->DeviceExtension;
501 RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
502
503 Irp->IoStatus.Status = STATUS_SUCCESS;
504 Irp->IoStatus.Information = 0;
505 IoCompleteRequest(Irp, IO_NO_INCREMENT);
506
507 return STATUS_SUCCESS;
508 }
509
510 NTSTATUS NTAPI
511 IntVideoPortDispatchPower(
512 IN PDEVICE_OBJECT DeviceObject,
513 IN PIRP Irp)
514 {
515 return STATUS_NOT_IMPLEMENTED;
516 }
517
518 VOID NTAPI
519 IntVideoPortUnload(PDRIVER_OBJECT DriverObject)
520 {
521 }