0dc6ff6693a0930ca5f6d8fea01b25bd96f85741
[reactos.git] / reactos / drivers / video / videoprt / videoprt.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: videoprt.c,v 1.7 2004/03/06 08:39:06 jimtabor Exp $
22 */
23
24 #include "videoprt.h"
25
26 BOOLEAN CsrssInitialized = FALSE;
27 PEPROCESS Csrss = NULL;
28 PVIDEO_PORT_DEVICE_EXTENSION ResetDisplayParametersDeviceExtension = NULL;
29
30 // ------------------------------------------------------- Public Interface
31
32 // DriverEntry
33 //
34 // DESCRIPTION:
35 // This function initializes the driver.
36 //
37 // RUN LEVEL:
38 // PASSIVE_LEVEL
39 //
40 // ARGUMENTS:
41 // IN PDRIVER_OBJECT DriverObject System allocated Driver Object
42 // for this driver
43 // IN PUNICODE_STRING RegistryPath Name of registry driver service
44 // key
45 //
46 // RETURNS:
47 // NTSTATUS
48
49 NTSTATUS STDCALL
50 DriverEntry(IN PDRIVER_OBJECT DriverObject,
51 IN PUNICODE_STRING RegistryPath)
52 {
53 DPRINT("DriverEntry()\n");
54 return(STATUS_SUCCESS);
55 }
56
57 /*
58 * @implemented
59 */
60 VOID
61 VideoPortDebugPrint(IN VIDEO_DEBUG_LEVEL DebugPrintLevel,
62 IN PCHAR DebugMessage, ...)
63 {
64 char Buffer[256];
65 va_list ap;
66
67 /*
68 if (DebugPrintLevel > InternalDebugLevel)
69 return;
70 */
71 va_start (ap, DebugMessage);
72 vsprintf (Buffer, DebugMessage, ap);
73 va_end (ap);
74
75 DbgPrint (Buffer);
76 }
77
78
79 /*
80 * @implemented
81 */
82 VOID
83 STDCALL
84 VideoPortFreeDeviceBase(IN PVOID HwDeviceExtension,
85 IN PVOID MappedAddress)
86 {
87 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
88
89 DPRINT("VideoPortFreeDeviceBase\n");
90
91 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
92 VIDEO_PORT_DEVICE_EXTENSION,
93 MiniPortDeviceExtension);
94
95 InternalUnmapMemory(DeviceExtension, MappedAddress);
96 }
97
98
99 /*
100 * @implemented
101 */
102 ULONG
103 STDCALL
104 VideoPortGetBusData(IN PVOID HwDeviceExtension,
105 IN BUS_DATA_TYPE BusDataType,
106 IN ULONG SlotNumber,
107 OUT PVOID Buffer,
108 IN ULONG Offset,
109 IN ULONG Length)
110 {
111 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
112
113 DPRINT("VideoPortGetBusData\n");
114
115 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
116 VIDEO_PORT_DEVICE_EXTENSION,
117 MiniPortDeviceExtension);
118
119 return HalGetBusDataByOffset(BusDataType,
120 DeviceExtension->SystemIoBusNumber,
121 SlotNumber,
122 Buffer,
123 Offset,
124 Length);
125 }
126
127
128 /*
129 * @implemented
130 */
131 UCHAR
132 STDCALL
133 VideoPortGetCurrentIrql(VOID)
134 {
135 DPRINT("VideoPortGetCurrentIrql\n");
136 return KeGetCurrentIrql();
137 }
138
139
140 /*
141 * @implemented
142 */
143 PVOID
144 STDCALL
145 VideoPortGetDeviceBase(IN PVOID HwDeviceExtension,
146 IN PHYSICAL_ADDRESS IoAddress,
147 IN ULONG NumberOfUchars,
148 IN UCHAR InIoSpace)
149 {
150 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
151
152 DPRINT("VideoPortGetDeviceBase\n");
153
154 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
155 VIDEO_PORT_DEVICE_EXTENSION,
156 MiniPortDeviceExtension);
157
158 return InternalMapMemory(DeviceExtension, IoAddress, NumberOfUchars, InIoSpace, NULL);
159 }
160
161
162 /*
163 * @unimplemented
164 */
165 VP_STATUS
166 STDCALL
167 VideoPortGetDeviceData(IN PVOID HwDeviceExtension,
168 IN VIDEO_DEVICE_DATA_TYPE DeviceDataType,
169 IN PMINIPORT_QUERY_DEVICE_ROUTINE CallbackRoutine,
170 IN PVOID Context)
171 {
172 DPRINT("VideoPortGetDeviceData\n");
173 UNIMPLEMENTED;
174 return STATUS_NOT_IMPLEMENTED;
175 }
176
177
178 /*
179 * @implemented
180 */
181 VP_STATUS
182 STDCALL
183 VideoPortGetAccessRanges(IN PVOID HwDeviceExtension,
184 IN ULONG NumRequestedResources,
185 IN PIO_RESOURCE_DESCRIPTOR RequestedResources OPTIONAL,
186 IN ULONG NumAccessRanges,
187 IN PVIDEO_ACCESS_RANGE AccessRanges,
188 IN PVOID VendorId,
189 IN PVOID DeviceId,
190 IN PULONG Slot)
191 {
192 PCI_SLOT_NUMBER PciSlotNumber;
193 BOOLEAN FoundDevice;
194 ULONG FunctionNumber;
195 PCI_COMMON_CONFIG Config;
196 PCM_RESOURCE_LIST AllocatedResources;
197 NTSTATUS Status;
198 UINT AssignedCount;
199 CM_FULL_RESOURCE_DESCRIPTOR *FullList;
200 CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
201 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
202
203 DPRINT("VideoPortGetAccessRanges\n");
204
205 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
206 VIDEO_PORT_DEVICE_EXTENSION,
207 MiniPortDeviceExtension);
208
209 if (0 == NumRequestedResources && PCIBus == DeviceExtension->AdapterInterfaceType)
210 {
211 if (DeviceId != NULL && VendorId != NULL)
212 {
213 DPRINT("Looking for VendorId 0x%04x DeviceId 0x%04x\n", (int)*((USHORT *) VendorId),
214 (int)*((USHORT *) DeviceId));
215 }
216 FoundDevice = FALSE;
217 PciSlotNumber.u.AsULONG = *Slot;
218 for (FunctionNumber = 0; ! FoundDevice && FunctionNumber < 8; FunctionNumber++)
219 {
220 PciSlotNumber.u.bits.FunctionNumber = FunctionNumber;
221 if (sizeof(PCI_COMMON_CONFIG) ==
222 HalGetBusDataByOffset(PCIConfiguration, DeviceExtension->SystemIoBusNumber,
223 PciSlotNumber.u.AsULONG,&Config, 0,
224 sizeof(PCI_COMMON_CONFIG)))
225 {
226 if (DeviceId != NULL && VendorId != NULL)
227 {
228 DPRINT("Slot 0x%02x (Device %d Function %d) VendorId 0x%04x DeviceId 0x%04x\n",
229 PciSlotNumber.u.AsULONG, PciSlotNumber.u.bits.DeviceNumber,
230 PciSlotNumber.u.bits.FunctionNumber, Config.VendorID, Config.DeviceID);
231 }
232
233 FoundDevice = (VendorId == NULL || Config.VendorID == *((USHORT *) VendorId)) &&
234 (DeviceId == NULL || Config.DeviceID == *((USHORT *) DeviceId));
235 }
236 }
237 if (! FoundDevice)
238 {
239 return STATUS_UNSUCCESSFUL;
240 }
241 Status = HalAssignSlotResources(NULL, NULL, NULL, NULL,
242 DeviceExtension->AdapterInterfaceType,
243 DeviceExtension->SystemIoBusNumber,
244 PciSlotNumber.u.AsULONG, &AllocatedResources);
245 if (! NT_SUCCESS(Status))
246 {
247 return Status;
248 }
249 AssignedCount = 0;
250 for (FullList = AllocatedResources->List;
251 FullList < AllocatedResources->List + AllocatedResources->Count;
252 FullList++)
253 {
254 assert(FullList->InterfaceType == PCIBus &&
255 FullList->BusNumber == DeviceExtension->SystemIoBusNumber &&
256 1 == FullList->PartialResourceList.Version &&
257 1 == FullList->PartialResourceList.Revision);
258 for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
259 Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
260 Descriptor++)
261 {
262 if ((CmResourceTypeMemory == Descriptor->Type
263 || CmResourceTypePort == Descriptor->Type)
264 && NumAccessRanges <= AssignedCount)
265 {
266 DPRINT1("Too many access ranges found\n");
267 ExFreePool(AllocatedResources);
268 return STATUS_UNSUCCESSFUL;
269 }
270 if (CmResourceTypeMemory == Descriptor->Type)
271 {
272 if (NumAccessRanges <= AssignedCount)
273 {
274 DPRINT1("Too many access ranges found\n");
275 ExFreePool(AllocatedResources);
276 return STATUS_UNSUCCESSFUL;
277 }
278 DPRINT("Memory range starting at 0x%08x length 0x%08x\n",
279 Descriptor->u.Memory.Start.u.LowPart, Descriptor->u.Memory.Length);
280 AccessRanges[AssignedCount].RangeStart = Descriptor->u.Memory.Start;
281 AccessRanges[AssignedCount].RangeLength = Descriptor->u.Memory.Length;
282 AccessRanges[AssignedCount].RangeInIoSpace = 0;
283 AccessRanges[AssignedCount].RangeVisible = 0; /* FIXME: Just guessing */
284 AccessRanges[AssignedCount].RangeShareable =
285 (CmResourceShareShared == Descriptor->ShareDisposition);
286 AssignedCount++;
287 }
288 else if (CmResourceTypePort == Descriptor->Type)
289 {
290 DPRINT("Port range starting at 0x%04x length %d\n",
291 Descriptor->u.Memory.Start.u.LowPart, Descriptor->u.Memory.Length);
292 AccessRanges[AssignedCount].RangeStart = Descriptor->u.Port.Start;
293 AccessRanges[AssignedCount].RangeLength = Descriptor->u.Port.Length;
294 AccessRanges[AssignedCount].RangeInIoSpace = 1;
295 AccessRanges[AssignedCount].RangeVisible = 0; /* FIXME: Just guessing */
296 AccessRanges[AssignedCount].RangeShareable = 0;
297 AssignedCount++;
298 }
299 else if (CmResourceTypeInterrupt == Descriptor->Type)
300 {
301 DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
302 DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
303 }
304 }
305 }
306 ExFreePool(AllocatedResources);
307 }
308 else
309 {
310 UNIMPLEMENTED
311 }
312
313 return STATUS_SUCCESS;
314 }
315
316 typedef struct QueryRegistryCallbackContext
317 {
318 PVOID HwDeviceExtension;
319 PVOID HwContext;
320 PMINIPORT_GET_REGISTRY_ROUTINE HwGetRegistryRoutine;
321 } QUERY_REGISTRY_CALLBACK_CONTEXT, *PQUERY_REGISTRY_CALLBACK_CONTEXT;
322
323 static NTSTATUS STDCALL
324 QueryRegistryCallback(IN PWSTR ValueName,
325 IN ULONG ValueType,
326 IN PVOID ValueData,
327 IN ULONG ValueLength,
328 IN PVOID Context,
329 IN PVOID EntryContext)
330 {
331 PQUERY_REGISTRY_CALLBACK_CONTEXT CallbackContext = (PQUERY_REGISTRY_CALLBACK_CONTEXT) Context;
332
333 DPRINT("Found registry value for name %S: type %d, length %d\n",
334 ValueName, ValueType, ValueLength);
335 return (*(CallbackContext->HwGetRegistryRoutine))(CallbackContext->HwDeviceExtension,
336 CallbackContext->HwContext,
337 ValueName,
338 ValueData,
339 ValueLength);
340 }
341
342 /*
343 * @unimplemented
344 */
345 VP_STATUS
346 STDCALL
347 VideoPortGetRegistryParameters(IN PVOID HwDeviceExtension,
348 IN PWSTR ParameterName,
349 IN UCHAR IsParameterFileName,
350 IN PMINIPORT_GET_REGISTRY_ROUTINE GetRegistryRoutine,
351 IN PVOID HwContext)
352 {
353 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
354 QUERY_REGISTRY_CALLBACK_CONTEXT Context;
355 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
356
357 DPRINT("VideoPortGetRegistryParameters ParameterName %S\n", ParameterName);
358
359 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
360 VIDEO_PORT_DEVICE_EXTENSION,
361 MiniPortDeviceExtension);
362
363 if (IsParameterFileName)
364 {
365 UNIMPLEMENTED;
366 }
367
368 DPRINT("ParameterName %S\n", ParameterName);
369
370 Context.HwDeviceExtension = HwDeviceExtension;
371 Context.HwContext = HwContext;
372 Context.HwGetRegistryRoutine = GetRegistryRoutine;
373
374 QueryTable[0].QueryRoutine = QueryRegistryCallback;
375 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
376 QueryTable[0].Name = ParameterName;
377 QueryTable[0].EntryContext = NULL;
378 QueryTable[0].DefaultType = REG_NONE;
379 QueryTable[0].DefaultData = NULL;
380 QueryTable[0].DefaultLength = 0;
381
382 QueryTable[1].QueryRoutine = NULL;
383 QueryTable[1].Name = NULL;
384
385 return NT_SUCCESS(RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
386 DeviceExtension->RegistryPath.Buffer,
387 QueryTable, &Context, NULL))
388 ? ERROR_SUCCESS : ERROR_INVALID_PARAMETER;
389 }
390
391
392 /*
393 * @implemented
394 */
395 VP_STATUS
396 STDCALL
397 VideoPortGetVgaStatus(IN PVOID HwDeviceExtension,
398 OUT PULONG VgaStatus)
399 {
400 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
401
402 DPRINT1("VideoPortGetVgaStatus = %S \n", VgaStatus);
403
404 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
405 VIDEO_PORT_DEVICE_EXTENSION,
406 MiniPortDeviceExtension);
407
408 if(KeGetCurrentIrql() == PASSIVE_LEVEL)
409 {
410 DPRINT1("VideoPortGetVgaStatus1 = %S \n", VgaStatus);
411
412 if ( PCIBus == DeviceExtension->AdapterInterfaceType)
413 {
414 /*
415 VgaStatus 0 == VGA not enabled, 1 == VGA enabled.
416 */
417 DPRINT1("VideoPortGetVgaStatus2 = %S \n", VgaStatus);
418
419 /* Assumed for now */
420
421 VgaStatus = (PULONG) 1;
422
423 return STATUS_SUCCESS;
424 }
425 }
426 DPRINT1("VideoPortGetVgaStatus3 = %S \n", VgaStatus);
427
428 return ERROR_INVALID_FUNCTION;
429 }
430
431 static BOOLEAN
432 VPInterruptRoutine(IN struct _KINTERRUPT *Interrupt,
433 IN PVOID ServiceContext)
434 {
435 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
436
437 DeviceExtension = ServiceContext;
438 assert(NULL != DeviceExtension->HwInterrupt);
439
440 return DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension);
441 }
442
443 static VOID STDCALL
444 VPTimerRoutine(IN PDEVICE_OBJECT DeviceObject,
445 IN PVOID Context)
446 {
447 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
448
449 DeviceExtension = Context;
450 assert(DeviceExtension == DeviceObject->DeviceExtension
451 && NULL != DeviceExtension->HwTimer);
452
453 DeviceExtension->HwTimer(&DeviceExtension->MiniPortDeviceExtension);
454 }
455
456 /*
457 * @implemented
458 */
459 ULONG STDCALL
460 VideoPortInitialize(IN PVOID Context1,
461 IN PVOID Context2,
462 IN PVIDEO_HW_INITIALIZATION_DATA HwInitializationData,
463 IN PVOID HwContext)
464 {
465 PUNICODE_STRING RegistryPath;
466 UCHAR Again = FALSE;
467 WCHAR DeviceBuffer[20];
468 WCHAR SymlinkBuffer[20];
469 WCHAR DeviceVideoBuffer[20];
470 NTSTATUS Status;
471 PDRIVER_OBJECT MPDriverObject = (PDRIVER_OBJECT) Context1;
472 PDEVICE_OBJECT MPDeviceObject;
473 VIDEO_PORT_CONFIG_INFO ConfigInfo;
474 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
475 ULONG DisplayNumber;
476 UNICODE_STRING DeviceName;
477 UNICODE_STRING SymlinkName;
478 ULONG MaxBus;
479 ULONG MaxLen;
480 KIRQL IRQL;
481 KAFFINITY Affinity;
482 ULONG InterruptVector;
483 OBJECT_ATTRIBUTES Obj;
484 HANDLE ObjHandle;
485
486 DPRINT("VideoPortInitialize\n");
487
488 RegistryPath = (PUNICODE_STRING) Context2;
489
490 /* Build Dispatch table from passed data */
491 MPDriverObject->DriverStartIo = (PDRIVER_STARTIO) HwInitializationData->HwStartIO;
492
493 /* Find the first free device number */
494 for (DisplayNumber = 0;;)
495 {
496 swprintf(SymlinkBuffer, L"\\??\\DISPLAY%lu", DisplayNumber + 1);
497 RtlInitUnicodeString(&SymlinkName, SymlinkBuffer);
498 InitializeObjectAttributes(&Obj, &SymlinkName, 0, NULL, NULL);
499 Status = ZwOpenSymbolicLinkObject(&ObjHandle, GENERIC_READ, &Obj);
500 if (NT_SUCCESS(Status))
501 {
502 ZwClose(ObjHandle);
503 DisplayNumber++;
504 continue;
505 }
506 else if (Status == STATUS_NOT_FOUND || Status == STATUS_UNSUCCESSFUL)
507 {
508 break;
509 }
510 else
511 {
512 return Status;
513 }
514 }
515
516 DPRINT("- DisplayNumber: %d\n", DisplayNumber);
517
518 Again = FALSE;
519
520 do
521 {
522 /* Create a unicode device name. */
523 swprintf(DeviceBuffer, L"\\Device\\Video%lu", DisplayNumber);
524 RtlInitUnicodeString(&DeviceName, DeviceBuffer);
525
526 /* Create the device. */
527 Status = IoCreateDevice(
528 MPDriverObject,
529 HwInitializationData->HwDeviceExtensionSize +
530 sizeof(VIDEO_PORT_DEVICE_EXTENSION),
531 &DeviceName,
532 FILE_DEVICE_VIDEO,
533 0,
534 TRUE,
535 &MPDeviceObject);
536 if (!NT_SUCCESS(Status))
537 {
538 DPRINT("IoCreateDevice call failed with status 0x%08x\n", Status);
539 return Status;
540 }
541
542 MPDriverObject->DeviceObject = MPDeviceObject;
543
544 /* Initialize the miniport drivers dispatch table */
545 MPDriverObject->MajorFunction[IRP_MJ_CREATE] = VidDispatchOpen;
546 MPDriverObject->MajorFunction[IRP_MJ_CLOSE] = VidDispatchClose;
547 MPDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VidDispatchDeviceControl;
548
549 /* Initialize our device extension */
550 DeviceExtension =
551 (PVIDEO_PORT_DEVICE_EXTENSION) MPDeviceObject->DeviceExtension;
552 DeviceExtension->DeviceObject = MPDeviceObject;
553 DeviceExtension->HwInitialize = HwInitializationData->HwInitialize;
554 DeviceExtension->HwResetHw = HwInitializationData->HwResetHw;
555 DeviceExtension->AdapterInterfaceType = HwInitializationData->AdapterInterfaceType;
556 DeviceExtension->SystemIoBusNumber = 0;
557 MaxLen = (wcslen(RegistryPath->Buffer) + 10) * sizeof(WCHAR);
558 DeviceExtension->RegistryPath.MaximumLength = MaxLen;
559 DeviceExtension->RegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
560 MaxLen,
561 TAG_VIDEO_PORT);
562 swprintf(DeviceExtension->RegistryPath.Buffer, L"%s\\Device0",
563 RegistryPath->Buffer);
564 DeviceExtension->RegistryPath.Length = wcslen(DeviceExtension->RegistryPath.Buffer) *
565 sizeof(WCHAR);
566
567 MaxBus = (DeviceExtension->AdapterInterfaceType == PCIBus) ? 8 : 1;
568 DPRINT("MaxBus: %lu\n", MaxBus);
569 InitializeListHead(&DeviceExtension->AddressMappingListHead);
570
571 /* Set the buffering strategy here... */
572 /* If you change this, remember to change VidDispatchDeviceControl too */
573 MPDeviceObject->Flags |= DO_BUFFERED_IO;
574
575 do
576 {
577 RtlZeroMemory(&DeviceExtension->MiniPortDeviceExtension,
578 HwInitializationData->HwDeviceExtensionSize);
579 DPRINT("Searching on bus %d\n", DeviceExtension->SystemIoBusNumber);
580 /* Setup configuration info */
581 RtlZeroMemory(&ConfigInfo, sizeof(VIDEO_PORT_CONFIG_INFO));
582 ConfigInfo.Length = sizeof(VIDEO_PORT_CONFIG_INFO);
583 ConfigInfo.AdapterInterfaceType = DeviceExtension->AdapterInterfaceType;
584 ConfigInfo.SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
585 ConfigInfo.InterruptMode = (PCIBus == DeviceExtension->AdapterInterfaceType) ?
586 LevelSensitive : Latched;
587
588 /* Call HwFindAdapter entry point */
589 /* FIXME: Need to figure out what string to pass as param 3 */
590 Status = HwInitializationData->HwFindAdapter(&DeviceExtension->MiniPortDeviceExtension,
591 Context2,
592 NULL,
593 &ConfigInfo,
594 &Again);
595 if (NO_ERROR != Status)
596 {
597 DPRINT("HwFindAdapter call failed with error %d\n", Status);
598 DeviceExtension->SystemIoBusNumber++;
599 }
600 }
601 while (NO_ERROR != Status && DeviceExtension->SystemIoBusNumber < MaxBus);
602
603 if (NO_ERROR != Status)
604 {
605 RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
606 IoDeleteDevice(MPDeviceObject);
607
608 return Status;
609 }
610 DPRINT("Found adapter\n");
611
612 /* create symbolic link "\??\DISPLAYx" */
613 swprintf(SymlinkBuffer, L"\\??\\DISPLAY%lu", DisplayNumber + 1);
614 RtlInitUnicodeString (&SymlinkName,
615 SymlinkBuffer);
616 IoCreateSymbolicLink (&SymlinkName,
617 &DeviceName);
618
619 /* Add entry to DEVICEMAP\VIDEO key in registry */
620 swprintf(DeviceVideoBuffer, L"\\Device\\Video%d", DisplayNumber);
621 RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP,
622 L"VIDEO",
623 DeviceVideoBuffer,
624 REG_SZ,
625 DeviceExtension->RegistryPath.Buffer,
626 DeviceExtension->RegistryPath.Length + sizeof(WCHAR));
627
628 /* FIXME: Allocate hardware resources for device */
629
630 /* Allocate interrupt for device */
631 DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
632 if (0 == ConfigInfo.BusInterruptVector)
633 {
634 ConfigInfo.BusInterruptVector = DeviceExtension->InterruptVector;
635 }
636 if (0 == ConfigInfo.BusInterruptLevel)
637 {
638 ConfigInfo.BusInterruptLevel = DeviceExtension->InterruptLevel;
639 }
640 if (NULL != HwInitializationData->HwInterrupt)
641 {
642 InterruptVector =
643 HalGetInterruptVector(ConfigInfo.AdapterInterfaceType,
644 ConfigInfo.SystemIoBusNumber,
645 ConfigInfo.BusInterruptLevel,
646 ConfigInfo.BusInterruptVector,
647 &IRQL,
648 &Affinity);
649 if (0 == InterruptVector)
650 {
651 DPRINT1("HalGetInterruptVector failed\n");
652 IoDeleteDevice(MPDeviceObject);
653
654 return STATUS_INSUFFICIENT_RESOURCES;
655 }
656 KeInitializeSpinLock(&DeviceExtension->InterruptSpinLock);
657 Status = IoConnectInterrupt(&DeviceExtension->InterruptObject,
658 VPInterruptRoutine,
659 DeviceExtension,
660 &DeviceExtension->InterruptSpinLock,
661 InterruptVector,
662 IRQL,
663 IRQL,
664 ConfigInfo.InterruptMode,
665 FALSE,
666 Affinity,
667 FALSE);
668 if (!NT_SUCCESS(Status))
669 {
670 DPRINT1("IoConnectInterrupt failed with status 0x%08x\n", Status);
671 IoDeleteDevice(MPDeviceObject);
672
673 return Status;
674 }
675 }
676 DisplayNumber++;
677 }
678 while (Again);
679
680 DeviceExtension->HwTimer = HwInitializationData->HwTimer;
681 if (HwInitializationData->HwTimer != NULL)
682 {
683 DPRINT("Initializing timer\n");
684 Status = IoInitializeTimer(MPDeviceObject,
685 VPTimerRoutine,
686 DeviceExtension);
687 if (!NT_SUCCESS(Status))
688 {
689 DPRINT("IoInitializeTimer failed with status 0x%08x\n", Status);
690
691 if (HwInitializationData->HwInterrupt != NULL)
692 {
693 IoDisconnectInterrupt(DeviceExtension->InterruptObject);
694 }
695 IoDeleteDevice(MPDeviceObject);
696
697 return Status;
698 }
699 }
700
701 return STATUS_SUCCESS;
702 }
703
704 /*
705 * @unimplemented
706 */
707 VOID
708 STDCALL
709 VideoPortLogError(IN PVOID HwDeviceExtension,
710 IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL,
711 IN VP_STATUS ErrorCode,
712 IN ULONG UniqueId)
713 {
714 DPRINT1("VideoPortLogError ErrorCode %d (0x%x) UniqueId %lu (0x%lx)\n",
715 ErrorCode, ErrorCode, UniqueId, UniqueId);
716 if (NULL != Vrp)
717 {
718 DPRINT1("Vrp->IoControlCode %lu (0x%lx)\n", Vrp->IoControlCode, Vrp->IoControlCode);
719 }
720 }
721
722
723 /*
724 * @unimplemented
725 */
726 VP_STATUS
727 STDCALL
728 VideoPortMapBankedMemory(IN PVOID HwDeviceExtension,
729 IN PHYSICAL_ADDRESS PhysicalAddress,
730 IN PULONG Length,
731 IN PULONG InIoSpace,
732 OUT PVOID *VirtualAddress,
733 IN ULONG BankLength,
734 IN UCHAR ReadWriteBank,
735 IN PBANKED_SECTION_ROUTINE BankRoutine,
736 IN PVOID Context)
737 {
738 DPRINT("VideoPortMapBankedMemory\n");
739 UNIMPLEMENTED;
740 return STATUS_NOT_IMPLEMENTED;
741 }
742
743
744 /*
745 * @implemented
746 */
747 VP_STATUS
748 STDCALL
749 VideoPortMapMemory(IN PVOID HwDeviceExtension,
750 IN PHYSICAL_ADDRESS PhysicalAddress,
751 IN PULONG Length,
752 IN PULONG InIoSpace,
753 OUT PVOID *VirtualAddress)
754 {
755 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
756 NTSTATUS Status;
757
758 DPRINT("VideoPortMapMemory\n");
759
760 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
761 VIDEO_PORT_DEVICE_EXTENSION,
762 MiniPortDeviceExtension);
763 *VirtualAddress = InternalMapMemory(DeviceExtension, PhysicalAddress,
764 *Length, *InIoSpace, &Status);
765
766 return Status;
767 }
768
769
770 /*
771 * @implemented
772 */
773 BOOLEAN
774 STDCALL
775 VideoPortScanRom(IN PVOID HwDeviceExtension,
776 IN PUCHAR RomBase,
777 IN ULONG RomLength,
778 IN PUCHAR String)
779 {
780 ULONG StringLength;
781 BOOLEAN Found;
782 PUCHAR SearchLocation;
783
784 DPRINT("VideoPortScanRom RomBase %p RomLength 0x%x String %s\n", RomBase, RomLength, String);
785
786 StringLength = strlen(String);
787 Found = FALSE;
788 SearchLocation = RomBase;
789 for (SearchLocation = RomBase;
790 ! Found && SearchLocation < RomBase + RomLength - StringLength;
791 SearchLocation++)
792 {
793 Found = (RtlCompareMemory(SearchLocation, String, StringLength) == StringLength);
794 if (Found)
795 {
796 DPRINT("Match found at %p\n", SearchLocation);
797 }
798 }
799
800 return Found;
801 }
802
803
804 /*
805 * @implemented
806 */
807 ULONG
808 STDCALL
809 VideoPortSetBusData(IN PVOID HwDeviceExtension,
810 IN BUS_DATA_TYPE BusDataType,
811 IN ULONG SlotNumber,
812 IN PVOID Buffer,
813 IN ULONG Offset,
814 IN ULONG Length)
815 {
816 DPRINT("VideoPortSetBusData\n");
817 return HalSetBusDataByOffset(BusDataType,
818 0,
819 SlotNumber,
820 Buffer,
821 Offset,
822 Length);
823 }
824
825
826 /*
827 * @implemented
828 */
829 VP_STATUS
830 STDCALL
831 VideoPortSetRegistryParameters(IN PVOID HwDeviceExtension,
832 IN PWSTR ValueName,
833 IN PVOID ValueData,
834 IN ULONG ValueLength)
835 {
836 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
837
838 DPRINT("VideoSetRegistryParameters\n");
839
840 assert_irql(PASSIVE_LEVEL);
841
842 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
843 VIDEO_PORT_DEVICE_EXTENSION,
844 MiniPortDeviceExtension);
845 return RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
846 DeviceExtension->RegistryPath.Buffer,
847 ValueName,
848 REG_BINARY,
849 ValueData,
850 ValueLength);
851 }
852
853
854 /*
855 * @unimplemented
856 */
857 VP_STATUS
858 STDCALL
859 VideoPortSetTrappedEmulatorPorts(IN PVOID HwDeviceExtension,
860 IN ULONG NumAccessRanges,
861 IN PVIDEO_ACCESS_RANGE AccessRange)
862 {
863 DPRINT("VideoPortSetTrappedEmulatorPorts\n");
864 UNIMPLEMENTED;
865 return STATUS_NOT_IMPLEMENTED;
866 }
867
868
869 /*
870 * @implemented
871 */
872 VOID
873 STDCALL
874 VideoPortStartTimer(IN PVOID HwDeviceExtension)
875 {
876 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
877
878 DPRINT("VideoPortStartTimer\n");
879
880 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
881 VIDEO_PORT_DEVICE_EXTENSION,
882 MiniPortDeviceExtension);
883 IoStartTimer(DeviceExtension->DeviceObject);
884 }
885
886
887 /*
888 * @implemented
889 */
890 VOID
891 STDCALL
892 VideoPortStopTimer(IN PVOID HwDeviceExtension)
893 {
894 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
895
896 DPRINT("VideoPortStopTimer\n");
897
898 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
899 VIDEO_PORT_DEVICE_EXTENSION,
900 MiniPortDeviceExtension);
901 IoStopTimer(DeviceExtension->DeviceObject);
902 }
903
904
905 /*
906 * @implemented
907 */
908 BOOLEAN
909 STDCALL
910 VideoPortSynchronizeExecution(IN PVOID HwDeviceExtension,
911 IN VIDEO_SYNCHRONIZE_PRIORITY Priority,
912 IN PMINIPORT_SYNCHRONIZE_ROUTINE SynchronizeRoutine,
913 OUT PVOID Context)
914 {
915 BOOLEAN Ret;
916 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
917 KIRQL OldIrql;
918
919 DPRINT("VideoPortSynchronizeExecution\n");
920
921 switch(Priority)
922 {
923 case VpLowPriority:
924 Ret = (*SynchronizeRoutine)(Context);
925 break;
926 case VpMediumPriority:
927 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
928 VIDEO_PORT_DEVICE_EXTENSION,
929 MiniPortDeviceExtension);
930 if (NULL == DeviceExtension->InterruptObject)
931 {
932 Ret = (*SynchronizeRoutine)(Context);
933 }
934 else
935 {
936 Ret = KeSynchronizeExecution(DeviceExtension->InterruptObject,
937 SynchronizeRoutine,
938 Context);
939 }
940 break;
941 case VpHighPriority:
942 OldIrql = KeGetCurrentIrql();
943 if (OldIrql < SYNCH_LEVEL)
944 {
945 OldIrql = KfRaiseIrql(SYNCH_LEVEL);
946 }
947 Ret = (*SynchronizeRoutine)(Context);
948 if (OldIrql < SYNCH_LEVEL)
949 {
950 KfLowerIrql(OldIrql);
951 }
952 break;
953 default:
954 Ret = FALSE;
955 }
956
957 return Ret;
958 }
959
960
961 /*
962 * @implemented
963 */
964 VP_STATUS
965 STDCALL
966 VideoPortUnmapMemory(IN PVOID HwDeviceExtension,
967 IN PVOID VirtualAddress,
968 IN HANDLE ProcessHandle)
969 {
970 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
971
972 DPRINT("VideoPortFreeDeviceBase\n");
973
974 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
975 VIDEO_PORT_DEVICE_EXTENSION,
976 MiniPortDeviceExtension);
977
978 InternalUnmapMemory(DeviceExtension, VirtualAddress);
979
980 return STATUS_SUCCESS;
981 }
982
983
984 /*
985 * @unimplemented
986 */
987 VP_STATUS
988 STDCALL
989 VideoPortVerifyAccessRanges(IN PVOID HwDeviceExtension,
990 IN ULONG NumAccessRanges,
991 IN PVIDEO_ACCESS_RANGE AccessRanges)
992 {
993 DPRINT1("VideoPortVerifyAccessRanges not implemented\n");
994 return NO_ERROR;
995 }
996
997
998 /*
999 * Reset display to blue screen
1000 */
1001 static BOOLEAN STDCALL
1002 VideoPortResetDisplayParameters(Columns, Rows)
1003 {
1004 if (NULL == ResetDisplayParametersDeviceExtension)
1005 {
1006 return(FALSE);
1007 }
1008 if (NULL == ResetDisplayParametersDeviceExtension->HwResetHw)
1009 {
1010 return(FALSE);
1011 }
1012 if (!ResetDisplayParametersDeviceExtension->HwResetHw(&ResetDisplayParametersDeviceExtension->MiniPortDeviceExtension,
1013 Columns, Rows))
1014 {
1015 return(FALSE);
1016 }
1017
1018 ResetDisplayParametersDeviceExtension = NULL;
1019
1020 return TRUE;
1021 }
1022
1023 /*
1024 * @implemented
1025 */
1026
1027 PVOID
1028 STDCALL
1029 VideoPortAllocatePool(
1030 IN PVOID HwDeviceExtension,
1031 IN VP_POOL_TYPE PoolType,
1032 IN SIZE_T NumberOfBytes,
1033 IN ULONG Tag)
1034 {
1035 return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
1036 }
1037
1038 /*
1039 * @implemented
1040 */
1041
1042 VOID
1043 STDCALL
1044 VideoPortFreePool(
1045 IN PVOID HwDeviceExtension,
1046 IN PVOID Ptr)
1047 {
1048 ExFreePool(Ptr);
1049 }
1050
1051 // VidDispatchOpen
1052 //
1053 // DESCRIPTION:
1054 // Answer requests for Open calls
1055 //
1056 // RUN LEVEL:
1057 // PASSIVE_LEVEL
1058 //
1059 // ARGUMENTS:
1060 // Standard dispatch arguments
1061 //
1062 // RETURNS:
1063 // NTSTATUS
1064 //
1065
1066 NTSTATUS STDCALL
1067 VidDispatchOpen(IN PDEVICE_OBJECT pDO,
1068 IN PIRP Irp)
1069 {
1070 PIO_STACK_LOCATION IrpStack;
1071 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1072
1073 DPRINT("VidDispatchOpen() called\n");
1074
1075 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1076
1077 if (! CsrssInitialized)
1078 {
1079 DPRINT("Referencing CSRSS\n");
1080 Csrss = PsGetCurrentProcess();
1081 DPRINT("Csrss %p\n", Csrss);
1082 }
1083 else
1084 {
1085 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION) pDO->DeviceExtension;
1086 if (DeviceExtension->HwInitialize(&DeviceExtension->MiniPortDeviceExtension))
1087 {
1088 Irp->IoStatus.Status = STATUS_SUCCESS;
1089 /* Storing the device extension pointer in a static variable is an ugly
1090 * hack. Unfortunately, we need it in VideoPortResetDisplayParameters
1091 * and HalAcquireDisplayOwnership doesn't allow us to pass a userdata
1092 * parameter. On the bright side, the DISPLAY device is opened
1093 * exclusively, so there can be only one device extension active at
1094 * any point in time. */
1095 ResetDisplayParametersDeviceExtension = DeviceExtension;
1096 HalAcquireDisplayOwnership(VideoPortResetDisplayParameters);
1097 }
1098 else
1099 {
1100 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1101 }
1102 }
1103
1104 Irp->IoStatus.Information = FILE_OPENED;
1105 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1106
1107 return STATUS_SUCCESS;
1108 }
1109
1110 // VidDispatchClose
1111 //
1112 // DESCRIPTION:
1113 // Answer requests for Close calls
1114 //
1115 // RUN LEVEL:
1116 // PASSIVE_LEVEL
1117 //
1118 // ARGUMENTS:
1119 // Standard dispatch arguments
1120 //
1121 // RETURNS:
1122 // NTSTATUS
1123 //
1124
1125 NTSTATUS STDCALL
1126 VidDispatchClose(IN PDEVICE_OBJECT pDO,
1127 IN PIRP Irp)
1128 {
1129 PIO_STACK_LOCATION IrpStack;
1130
1131 DPRINT("VidDispatchClose() called\n");
1132
1133 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1134
1135 if (! CsrssInitialized)
1136 {
1137 CsrssInitialized = TRUE;
1138 }
1139 else
1140 {
1141 HalReleaseDisplayOwnership();
1142 }
1143
1144 Irp->IoStatus.Status = STATUS_SUCCESS;
1145 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1146
1147 return STATUS_SUCCESS;
1148 }
1149
1150 // VidDispatchDeviceControl
1151 //
1152 // DESCRIPTION:
1153 // Answer requests for device control calls
1154 //
1155 // RUN LEVEL:
1156 // PASSIVE_LEVEL
1157 //
1158 // ARGUMENTS:
1159 // Standard dispatch arguments
1160 //
1161 // RETURNS:
1162 // NTSTATUS
1163 //
1164
1165 NTSTATUS STDCALL
1166 VidDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,
1167 IN PIRP Irp)
1168 {
1169 PIO_STACK_LOCATION IrpStack;
1170 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1171 PVIDEO_REQUEST_PACKET vrp;
1172
1173 DPRINT("VidDispatchDeviceControl\n");
1174 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1175 DeviceExtension = DeviceObject->DeviceExtension;
1176
1177 /* Translate the IRP to a VRP */
1178 vrp = ExAllocatePool(NonPagedPool, sizeof(VIDEO_REQUEST_PACKET));
1179 if (NULL == vrp)
1180 {
1181 return STATUS_NO_MEMORY;
1182 }
1183 vrp->StatusBlock = (PSTATUS_BLOCK) &(Irp->IoStatus);
1184 vrp->IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
1185
1186 DPRINT("- IoControlCode: %x\n", vrp->IoControlCode);
1187
1188 /* We're assuming METHOD_BUFFERED */
1189 vrp->InputBuffer = Irp->AssociatedIrp.SystemBuffer;
1190 vrp->InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
1191 vrp->OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
1192 vrp->OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
1193
1194 /* Call the Miniport Driver with the VRP */
1195 ((PDRIVER_STARTIO)DeviceObject->DriverObject->DriverStartIo)((PVOID) &DeviceExtension->MiniPortDeviceExtension, (PIRP)vrp);
1196
1197 /* Free the VRP */
1198 ExFreePool(vrp);
1199
1200 DPRINT("- Returned status: %x\n", Irp->IoStatus.Status);
1201
1202 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1203
1204 return STATUS_SUCCESS;
1205 }
1206
1207 PVOID STDCALL
1208 InternalMapMemory(IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,
1209 IN PHYSICAL_ADDRESS IoAddress,
1210 IN ULONG NumberOfUchars,
1211 IN UCHAR InIoSpace,
1212 OUT NTSTATUS *Status)
1213 {
1214 PHYSICAL_ADDRESS TranslatedAddress;
1215 PVIDEO_PORT_ADDRESS_MAPPING AddressMapping;
1216 ULONG AddressSpace;
1217 PVOID MappedAddress;
1218 PLIST_ENTRY Entry;
1219
1220 if (0 != (InIoSpace & VIDEO_MEMORY_SPACE_P6CACHE))
1221 {
1222 DPRINT("VIDEO_MEMORY_SPACE_P6CACHE not supported, turning off\n");
1223 InIoSpace &= ~VIDEO_MEMORY_SPACE_P6CACHE;
1224 }
1225 if (! IsListEmpty(&DeviceExtension->AddressMappingListHead))
1226 {
1227 Entry = DeviceExtension->AddressMappingListHead.Flink;
1228 while (Entry != &DeviceExtension->AddressMappingListHead)
1229 {
1230 AddressMapping = CONTAINING_RECORD(Entry,
1231 VIDEO_PORT_ADDRESS_MAPPING,
1232 List);
1233 if (IoAddress.QuadPart == AddressMapping->IoAddress.QuadPart &&
1234 NumberOfUchars <= AddressMapping->NumberOfUchars)
1235 {
1236 AddressMapping->MappingCount++;
1237 if (Status)
1238 {
1239 *Status = STATUS_SUCCESS;
1240 }
1241 return AddressMapping->MappedAddress;
1242 }
1243 Entry = Entry->Flink;
1244 }
1245 }
1246
1247 AddressSpace = (ULONG)InIoSpace;
1248 if (HalTranslateBusAddress(DeviceExtension->AdapterInterfaceType,
1249 DeviceExtension->SystemIoBusNumber,
1250 IoAddress,
1251 &AddressSpace,
1252 &TranslatedAddress) == FALSE)
1253 {
1254 if (Status)
1255 {
1256 *Status = STATUS_NO_MEMORY;
1257 }
1258 return NULL;
1259 }
1260
1261 /* i/o space */
1262 if (AddressSpace != 0)
1263 {
1264 assert(0 == TranslatedAddress.u.HighPart);
1265 if (Status)
1266 {
1267 *Status = STATUS_SUCCESS;
1268 }
1269 return (PVOID) TranslatedAddress.u.LowPart;
1270 }
1271
1272 MappedAddress = MmMapIoSpace(TranslatedAddress,
1273 NumberOfUchars,
1274 FALSE);
1275
1276 if (MappedAddress)
1277 {
1278 if (Status)
1279 {
1280 *Status = STATUS_SUCCESS;
1281 }
1282
1283 AddressMapping = ExAllocatePoolWithTag(PagedPool,
1284 sizeof(VIDEO_PORT_ADDRESS_MAPPING),
1285 TAG_VIDEO_PORT);
1286 if (AddressMapping == NULL)
1287 return MappedAddress;
1288
1289 AddressMapping->MappedAddress = MappedAddress;
1290 AddressMapping->NumberOfUchars = NumberOfUchars;
1291 AddressMapping->IoAddress = IoAddress;
1292 AddressMapping->SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
1293 AddressMapping->MappingCount = 1;
1294
1295 InsertHeadList(&DeviceExtension->AddressMappingListHead,
1296 &AddressMapping->List);
1297
1298 return MappedAddress;
1299 }
1300 else
1301 {
1302 if (Status)
1303 {
1304 *Status = STATUS_NO_MEMORY;
1305 }
1306
1307 return NULL;
1308 }
1309 }
1310
1311 VOID STDCALL
1312 InternalUnmapMemory(IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,
1313 IN PVOID MappedAddress)
1314 {
1315 PVIDEO_PORT_ADDRESS_MAPPING AddressMapping;
1316 PLIST_ENTRY Entry;
1317
1318 Entry = DeviceExtension->AddressMappingListHead.Flink;
1319 while (Entry != &DeviceExtension->AddressMappingListHead)
1320 {
1321 AddressMapping = CONTAINING_RECORD(Entry,
1322 VIDEO_PORT_ADDRESS_MAPPING,
1323 List);
1324 if (AddressMapping->MappedAddress == MappedAddress)
1325 {
1326 assert(0 <= AddressMapping->MappingCount);
1327 AddressMapping->MappingCount--;
1328 if (0 == AddressMapping->MappingCount)
1329 {
1330 MmUnmapIoSpace(AddressMapping->MappedAddress,
1331 AddressMapping->NumberOfUchars);
1332 RemoveEntryList(Entry);
1333 ExFreePool(AddressMapping);
1334
1335 return;
1336 }
1337 }
1338
1339 Entry = Entry->Flink;
1340 }
1341 }
1342
1343 BOOLEAN STDCALL
1344 VideoPortDDCMonitorHelper(
1345 PVOID HwDeviceExtension,
1346 /*PI2C_FNC_TABLE*/PVOID I2CFunctions,
1347 PUCHAR pEdidBuffer,
1348 ULONG EdidBufferSize
1349 )
1350 {
1351 return FALSE;
1352 }
1353
1354
1355 VP_STATUS
1356 STDCALL
1357 VideoPortAllocateBuffer(IN PVOID HwDeviceExtension,
1358 IN ULONG Size,
1359 OUT PVOID *Buffer)
1360 {
1361 DPRINT("VideoPortAllocateBuffer\n");
1362
1363 Buffer = ExAllocatePool (PagedPool, Size) ;
1364 return STATUS_SUCCESS;
1365
1366 }
1367
1368 VOID
1369 STDCALL
1370 VideoPortReleaseBuffer( IN PVOID HwDeviceExtension,
1371 IN PVOID Ptr)
1372 {
1373 DPRINT("VideoPortReleaseBuffer\n");
1374
1375 ExFreePool(Ptr);
1376 }
1377
1378