Copy w32api 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 if (Descriptor->ShareDisposition == CmResourceShareShared)
333 DeviceExtension->InterruptShared = TRUE;
334 else
335 DeviceExtension->InterruptShared = FALSE;
336 }
337 }
338 }
339 }
340 DPRINT("Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
341 DeviceExtension->InterruptLevel,
342 DeviceExtension->InterruptVector);
343
344 /*
345 * Create adapter device object.
346 */
347
348 return IntVideoPortFindAdapter(
349 DriverObject,
350 DriverExtension,
351 DeviceObject);
352 }
353
354
355 NTSTATUS
356 STDCALL
357 IntVideoPortForwardIrpAndWaitCompletionRoutine(
358 PDEVICE_OBJECT Fdo,
359 PIRP Irp,
360 PVOID Context)
361 {
362 PKEVENT Event = Context;
363
364 if (Irp->PendingReturned)
365 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
366
367 return STATUS_MORE_PROCESSING_REQUIRED;
368 }
369
370
371 NTSTATUS
372 STDCALL
373 IntVideoPortForwardIrpAndWait(PDEVICE_OBJECT DeviceObject, PIRP Irp)
374 {
375 KEVENT Event;
376 NTSTATUS Status;
377 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension =
378 (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
379
380 KeInitializeEvent(&Event, NotificationEvent, FALSE);
381 IoCopyCurrentIrpStackLocationToNext(Irp);
382 IoSetCompletionRoutine(Irp, IntVideoPortForwardIrpAndWaitCompletionRoutine,
383 &Event, TRUE, TRUE, TRUE);
384 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
385 if (Status == STATUS_PENDING)
386 {
387 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
388 Status = Irp->IoStatus.Status;
389 }
390 return Status;
391 }
392
393
394 NTSTATUS STDCALL
395 IntVideoPortDispatchPnp(
396 IN PDEVICE_OBJECT DeviceObject,
397 IN PIRP Irp)
398 {
399 PIO_STACK_LOCATION IrpSp;
400 NTSTATUS Status;
401
402 IrpSp = IoGetCurrentIrpStackLocation(Irp);
403
404 switch (IrpSp->MinorFunction)
405 {
406 case IRP_MN_START_DEVICE:
407 Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
408 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
409 Status = IntVideoPortPnPStartDevice(DeviceObject, Irp);
410 Irp->IoStatus.Status = Status;
411 Irp->IoStatus.Information = 0;
412 IoCompleteRequest(Irp, IO_NO_INCREMENT);
413 break;
414
415
416 case IRP_MN_REMOVE_DEVICE:
417 case IRP_MN_QUERY_REMOVE_DEVICE:
418 case IRP_MN_CANCEL_REMOVE_DEVICE:
419 case IRP_MN_SURPRISE_REMOVAL:
420
421 case IRP_MN_STOP_DEVICE:
422 Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
423 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
424 Status = STATUS_SUCCESS;
425 Irp->IoStatus.Status = Status;
426 Irp->IoStatus.Information = 0;
427 IoCompleteRequest(Irp, IO_NO_INCREMENT);
428 break;
429
430 case IRP_MN_QUERY_STOP_DEVICE:
431 case IRP_MN_CANCEL_STOP_DEVICE:
432 Status = STATUS_SUCCESS;
433 Irp->IoStatus.Status = STATUS_SUCCESS;
434 Irp->IoStatus.Information = 0;
435 IoCompleteRequest(Irp, IO_NO_INCREMENT);
436 break;
437
438 default:
439 return STATUS_NOT_IMPLEMENTED;
440 break;
441 }
442
443 return Status;
444 }
445
446 NTSTATUS STDCALL
447 IntVideoPortDispatchCleanup(
448 IN PDEVICE_OBJECT DeviceObject,
449 IN PIRP Irp)
450 {
451 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
452
453 DeviceExtension = DeviceObject->DeviceExtension;
454 RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
455
456 Irp->IoStatus.Status = STATUS_SUCCESS;
457 Irp->IoStatus.Information = 0;
458 IoCompleteRequest(Irp, IO_NO_INCREMENT);
459
460 return STATUS_SUCCESS;
461 }
462
463 NTSTATUS STDCALL
464 IntVideoPortDispatchPower(
465 IN PDEVICE_OBJECT DeviceObject,
466 IN PIRP Irp)
467 {
468 return STATUS_NOT_IMPLEMENTED;
469 }
470
471 VOID STDCALL
472 IntVideoPortUnload(PDRIVER_OBJECT DriverObject)
473 {
474 }