- Implemented VideoPortQueryPerformanceCounter and all video port spinlock functions.
[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.17 2004/03/09 17:28:49 navaraf Exp $
22 */
23
24 #include "videoprt.h"
25
26 BOOLEAN CsrssInitialized = FALSE;
27 PEPROCESS Csrss = NULL;
28 PVIDEO_PORT_DEVICE_EXTENSION ResetDisplayParametersDeviceExtension = NULL;
29 static PVOID RomImageBuffer = NULL;
30
31 VOID STDCALL STATIC
32 VideoPortDeferredRoutine(
33 IN PKDPC Dpc,
34 IN PVOID DeferredContext,
35 IN PVOID SystemArgument1,
36 IN PVOID SystemArgument2
37 );
38 PVOID STDCALL
39 VideoPortGetProcAddress(IN PVOID HwDeviceExtension,
40 IN PUCHAR FunctionName);
41
42 // ------------------------------------------------------- Public Interface
43
44 // DriverEntry
45 //
46 // DESCRIPTION:
47 // This function initializes the driver.
48 //
49 // RUN LEVEL:
50 // PASSIVE_LEVEL
51 //
52 // ARGUMENTS:
53 // IN PDRIVER_OBJECT DriverObject System allocated Driver Object
54 // for this driver
55 // IN PUNICODE_STRING RegistryPath Name of registry driver service
56 // key
57 //
58 // RETURNS:
59 // NTSTATUS
60
61 NTSTATUS STDCALL
62 DriverEntry(IN PDRIVER_OBJECT DriverObject,
63 IN PUNICODE_STRING RegistryPath)
64 {
65 DPRINT("DriverEntry()\n");
66 return(STATUS_SUCCESS);
67 }
68
69 /*
70 * @implemented
71 */
72 VOID
73 VideoPortDebugPrint(IN VIDEO_DEBUG_LEVEL DebugPrintLevel,
74 IN PCHAR DebugMessage, ...)
75 {
76 char Buffer[256];
77 va_list ap;
78
79 /*
80 if (DebugPrintLevel > InternalDebugLevel)
81 return;
82 */
83 va_start (ap, DebugMessage);
84 vsprintf (Buffer, DebugMessage, ap);
85 va_end (ap);
86
87 DbgPrint (Buffer);
88 }
89
90
91 /*
92 * @implemented
93 */
94 VOID
95 STDCALL
96 VideoPortFreeDeviceBase(IN PVOID HwDeviceExtension,
97 IN PVOID MappedAddress)
98 {
99 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
100
101 DPRINT("VideoPortFreeDeviceBase\n");
102
103 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
104 VIDEO_PORT_DEVICE_EXTENSION,
105 MiniPortDeviceExtension);
106
107 InternalUnmapMemory(DeviceExtension, MappedAddress);
108 }
109
110
111 /*
112 * @implemented
113 */
114 ULONG
115 STDCALL
116 VideoPortGetBusData(IN PVOID HwDeviceExtension,
117 IN BUS_DATA_TYPE BusDataType,
118 IN ULONG SlotNumber,
119 OUT PVOID Buffer,
120 IN ULONG Offset,
121 IN ULONG Length)
122 {
123 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
124
125 DPRINT("VideoPortGetBusData\n");
126
127 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
128 VIDEO_PORT_DEVICE_EXTENSION,
129 MiniPortDeviceExtension);
130
131 return HalGetBusDataByOffset(BusDataType,
132 DeviceExtension->SystemIoBusNumber,
133 SlotNumber,
134 Buffer,
135 Offset,
136 Length);
137 }
138
139
140 /*
141 * @implemented
142 */
143 UCHAR
144 STDCALL
145 VideoPortGetCurrentIrql(VOID)
146 {
147 return KeGetCurrentIrql();
148 }
149
150
151 /*
152 * @implemented
153 */
154 PVOID
155 STDCALL
156 VideoPortGetDeviceBase(IN PVOID HwDeviceExtension,
157 IN PHYSICAL_ADDRESS IoAddress,
158 IN ULONG NumberOfUchars,
159 IN UCHAR InIoSpace)
160 {
161 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
162
163 DPRINT("VideoPortGetDeviceBase\n");
164
165 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
166 VIDEO_PORT_DEVICE_EXTENSION,
167 MiniPortDeviceExtension);
168
169 return InternalMapMemory(DeviceExtension, IoAddress, NumberOfUchars, InIoSpace, NULL);
170 }
171
172
173 /*
174 * @unimplemented
175 */
176 VP_STATUS
177 STDCALL
178 VideoPortGetDeviceData(IN PVOID HwDeviceExtension,
179 IN VIDEO_DEVICE_DATA_TYPE DeviceDataType,
180 IN PMINIPORT_QUERY_DEVICE_ROUTINE CallbackRoutine,
181 IN PVOID Context)
182 {
183 DPRINT("VideoPortGetDeviceData\n");
184 UNIMPLEMENTED;
185 return STATUS_NOT_IMPLEMENTED;
186 }
187
188
189 /*
190 * @implemented
191 */
192 VP_STATUS
193 STDCALL
194 VideoPortGetAccessRanges(IN PVOID HwDeviceExtension,
195 IN ULONG NumRequestedResources,
196 IN PIO_RESOURCE_DESCRIPTOR RequestedResources OPTIONAL,
197 IN ULONG NumAccessRanges,
198 IN PVIDEO_ACCESS_RANGE AccessRanges,
199 IN PVOID VendorId,
200 IN PVOID DeviceId,
201 IN PULONG Slot)
202 {
203 PCI_SLOT_NUMBER PciSlotNumber;
204 ULONG FunctionNumber;
205 PCI_COMMON_CONFIG Config;
206 PCM_RESOURCE_LIST AllocatedResources;
207 NTSTATUS Status;
208 UINT AssignedCount;
209 CM_FULL_RESOURCE_DESCRIPTOR *FullList;
210 CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
211 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
212 USHORT VendorIdToFind;
213 USHORT DeviceIdToFind;
214 ULONG SlotIdToFind;
215
216 DPRINT("VideoPortGetAccessRanges\n");
217
218 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
219 VIDEO_PORT_DEVICE_EXTENSION,
220 MiniPortDeviceExtension);
221
222 if (0 == NumRequestedResources &&
223 PCIBus == DeviceExtension->AdapterInterfaceType)
224 {
225 VendorIdToFind = VendorId != NULL ? *(PUSHORT)VendorId : 0;
226 DeviceIdToFind = DeviceId != NULL ? *(PUSHORT)DeviceId : 0;
227 SlotIdToFind = Slot != NULL ? *Slot : 0;
228
229 DPRINT("Looking for VendorId 0x%04x DeviceId 0x%04x SlotId 0x%04x\n",
230 VendorIdToFind, DeviceIdToFind, SlotIdToFind);
231
232 PciSlotNumber.u.AsULONG = SlotIdToFind;
233
234 /*
235 Search for the device id and vendor id on this bus.
236 */
237 for (FunctionNumber = 0; FunctionNumber < 8; FunctionNumber++)
238 {
239 ULONG ReturnedLength;
240 DPRINT("- Function number: %d\n", FunctionNumber);
241 PciSlotNumber.u.bits.FunctionNumber = FunctionNumber;
242 ReturnedLength = HalGetBusData(PCIConfiguration,
243 DeviceExtension->SystemIoBusNumber,
244 PciSlotNumber.u.AsULONG,
245 &Config,
246 sizeof(PCI_COMMON_CONFIG));
247 DPRINT("- Length of data: %x\n", ReturnedLength);
248 if (sizeof(PCI_COMMON_CONFIG) == ReturnedLength)
249 {
250 DPRINT("- Slot 0x%02x (Device %d Function %d) VendorId 0x%04x "
251 "DeviceId 0x%04x\n",
252 PciSlotNumber.u.AsULONG,
253 PciSlotNumber.u.bits.DeviceNumber,
254 PciSlotNumber.u.bits.FunctionNumber,
255 Config.VendorID,
256 Config.DeviceID);
257
258 if ((VendorIdToFind == 0 || Config.VendorID == VendorIdToFind) &&
259 (DeviceIdToFind == 0 || Config.DeviceID == DeviceIdToFind))
260 {
261 break;
262 }
263 }
264 }
265 if (FunctionNumber == 8)
266 {
267 DPRINT("Didn't find device.\n");
268 return STATUS_UNSUCCESSFUL;
269 }
270
271 Status = HalAssignSlotResources(NULL, NULL, NULL, NULL,
272 DeviceExtension->AdapterInterfaceType,
273 DeviceExtension->SystemIoBusNumber,
274 PciSlotNumber.u.AsULONG,
275 &AllocatedResources);
276 if (! NT_SUCCESS(Status))
277 {
278 return Status;
279 }
280 AssignedCount = 0;
281 for (FullList = AllocatedResources->List;
282 FullList < AllocatedResources->List + AllocatedResources->Count;
283 FullList++)
284 {
285 assert(FullList->InterfaceType == PCIBus &&
286 FullList->BusNumber == DeviceExtension->SystemIoBusNumber &&
287 1 == FullList->PartialResourceList.Version &&
288 1 == FullList->PartialResourceList.Revision);
289 for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
290 Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
291 Descriptor++)
292 {
293 if ((CmResourceTypeMemory == Descriptor->Type
294 || CmResourceTypePort == Descriptor->Type)
295 && NumAccessRanges <= AssignedCount)
296 {
297 DPRINT1("Too many access ranges found\n");
298 ExFreePool(AllocatedResources);
299 return STATUS_UNSUCCESSFUL;
300 }
301 if (CmResourceTypeMemory == Descriptor->Type)
302 {
303 if (NumAccessRanges <= AssignedCount)
304 {
305 DPRINT1("Too many access ranges found\n");
306 ExFreePool(AllocatedResources);
307 return STATUS_UNSUCCESSFUL;
308 }
309 DPRINT("Memory range starting at 0x%08x length 0x%08x\n",
310 Descriptor->u.Memory.Start.u.LowPart, Descriptor->u.Memory.Length);
311 AccessRanges[AssignedCount].RangeStart = Descriptor->u.Memory.Start;
312 AccessRanges[AssignedCount].RangeLength = Descriptor->u.Memory.Length;
313 AccessRanges[AssignedCount].RangeInIoSpace = 0;
314 AccessRanges[AssignedCount].RangeVisible = 0; /* FIXME: Just guessing */
315 AccessRanges[AssignedCount].RangeShareable =
316 (CmResourceShareShared == Descriptor->ShareDisposition);
317 AssignedCount++;
318 }
319 else if (CmResourceTypePort == Descriptor->Type)
320 {
321 DPRINT("Port range starting at 0x%04x length %d\n",
322 Descriptor->u.Memory.Start.u.LowPart, Descriptor->u.Memory.Length);
323 AccessRanges[AssignedCount].RangeStart = Descriptor->u.Port.Start;
324 AccessRanges[AssignedCount].RangeLength = Descriptor->u.Port.Length;
325 AccessRanges[AssignedCount].RangeInIoSpace = 1;
326 AccessRanges[AssignedCount].RangeVisible = 0; /* FIXME: Just guessing */
327 AccessRanges[AssignedCount].RangeShareable = 0;
328 AssignedCount++;
329 }
330 else if (CmResourceTypeInterrupt == Descriptor->Type)
331 {
332 DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
333 DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
334 }
335 }
336 }
337 ExFreePool(AllocatedResources);
338 }
339 else
340 {
341 UNIMPLEMENTED
342 }
343
344 return STATUS_SUCCESS;
345 }
346
347 typedef struct QueryRegistryCallbackContext
348 {
349 PVOID HwDeviceExtension;
350 PVOID HwContext;
351 PMINIPORT_GET_REGISTRY_ROUTINE HwGetRegistryRoutine;
352 } QUERY_REGISTRY_CALLBACK_CONTEXT, *PQUERY_REGISTRY_CALLBACK_CONTEXT;
353
354 static NTSTATUS STDCALL
355 QueryRegistryCallback(IN PWSTR ValueName,
356 IN ULONG ValueType,
357 IN PVOID ValueData,
358 IN ULONG ValueLength,
359 IN PVOID Context,
360 IN PVOID EntryContext)
361 {
362 PQUERY_REGISTRY_CALLBACK_CONTEXT CallbackContext = (PQUERY_REGISTRY_CALLBACK_CONTEXT) Context;
363
364 DPRINT("Found registry value for name %S: type %d, length %d\n",
365 ValueName, ValueType, ValueLength);
366 return (*(CallbackContext->HwGetRegistryRoutine))(CallbackContext->HwDeviceExtension,
367 CallbackContext->HwContext,
368 ValueName,
369 ValueData,
370 ValueLength);
371 }
372
373 /*
374 * @unimplemented
375 */
376 VP_STATUS
377 STDCALL
378 VideoPortGetRegistryParameters(IN PVOID HwDeviceExtension,
379 IN PWSTR ParameterName,
380 IN UCHAR IsParameterFileName,
381 IN PMINIPORT_GET_REGISTRY_ROUTINE GetRegistryRoutine,
382 IN PVOID HwContext)
383 {
384 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
385 QUERY_REGISTRY_CALLBACK_CONTEXT Context;
386 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
387
388 DPRINT("VideoPortGetRegistryParameters ParameterName %S\n", ParameterName);
389
390 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
391 VIDEO_PORT_DEVICE_EXTENSION,
392 MiniPortDeviceExtension);
393
394 if (IsParameterFileName)
395 {
396 UNIMPLEMENTED;
397 }
398
399 Context.HwDeviceExtension = HwDeviceExtension;
400 Context.HwContext = HwContext;
401 Context.HwGetRegistryRoutine = GetRegistryRoutine;
402
403 QueryTable[0].QueryRoutine = QueryRegistryCallback;
404 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
405 QueryTable[0].Name = ParameterName;
406 QueryTable[0].EntryContext = NULL;
407 QueryTable[0].DefaultType = REG_NONE;
408 QueryTable[0].DefaultData = NULL;
409 QueryTable[0].DefaultLength = 0;
410
411 QueryTable[1].QueryRoutine = NULL;
412 QueryTable[1].Name = NULL;
413
414 return NT_SUCCESS(RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
415 DeviceExtension->RegistryPath.Buffer,
416 QueryTable, &Context, NULL))
417 ? ERROR_SUCCESS : ERROR_INVALID_PARAMETER;
418 }
419
420
421 /*
422 * @implemented
423 */
424 VP_STATUS
425 STDCALL
426 VideoPortGetVgaStatus(IN PVOID HwDeviceExtension,
427 OUT PULONG VgaStatus)
428 {
429 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
430
431 DPRINT1("VideoPortGetVgaStatus = %S \n", VgaStatus);
432
433 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
434 VIDEO_PORT_DEVICE_EXTENSION,
435 MiniPortDeviceExtension);
436
437 if(KeGetCurrentIrql() == PASSIVE_LEVEL)
438 {
439 DPRINT1("VideoPortGetVgaStatus1 = %S \n", VgaStatus);
440
441 if ( PCIBus == DeviceExtension->AdapterInterfaceType)
442 {
443 /*
444 VgaStatus 0 == VGA not enabled, 1 == VGA enabled.
445 */
446 DPRINT1("VideoPortGetVgaStatus2 = %S \n", VgaStatus);
447
448 /* Assumed for now */
449
450 VgaStatus = (PULONG) 1;
451
452 return STATUS_SUCCESS;
453 }
454 }
455 DPRINT1("VideoPortGetVgaStatus3 = %S \n", VgaStatus);
456
457 return ERROR_INVALID_FUNCTION;
458 }
459
460 static BOOLEAN
461 VPInterruptRoutine(IN struct _KINTERRUPT *Interrupt,
462 IN PVOID ServiceContext)
463 {
464 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
465
466 DeviceExtension = ServiceContext;
467 assert(NULL != DeviceExtension->HwInterrupt);
468
469 return DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension);
470 }
471
472 static VOID STDCALL
473 VPTimerRoutine(IN PDEVICE_OBJECT DeviceObject,
474 IN PVOID Context)
475 {
476 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
477
478 DeviceExtension = Context;
479 assert(DeviceExtension == DeviceObject->DeviceExtension
480 && NULL != DeviceExtension->HwTimer);
481
482 DeviceExtension->HwTimer(&DeviceExtension->MiniPortDeviceExtension);
483 }
484
485 /*
486 * @implemented
487 */
488 ULONG STDCALL
489 VideoPortInitialize(IN PVOID Context1,
490 IN PVOID Context2,
491 IN PVIDEO_HW_INITIALIZATION_DATA HwInitializationData,
492 IN PVOID HwContext)
493 {
494 PUNICODE_STRING RegistryPath;
495 UCHAR Again = FALSE;
496 WCHAR DeviceBuffer[20];
497 WCHAR SymlinkBuffer[20];
498 WCHAR DeviceVideoBuffer[20];
499 NTSTATUS Status;
500 PDRIVER_OBJECT MPDriverObject = (PDRIVER_OBJECT) Context1;
501 PDEVICE_OBJECT MPDeviceObject;
502 VIDEO_PORT_CONFIG_INFO ConfigInfo;
503 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
504 ULONG DisplayNumber;
505 UNICODE_STRING DeviceName;
506 UNICODE_STRING SymlinkName;
507 ULONG MaxBus;
508 ULONG MaxLen;
509 KIRQL IRQL;
510 KAFFINITY Affinity;
511 ULONG InterruptVector;
512 OBJECT_ATTRIBUTES Obj;
513 HANDLE ObjHandle;
514
515 DPRINT("VideoPortInitialize\n");
516
517 RegistryPath = (PUNICODE_STRING) Context2;
518
519 /* Build Dispatch table from passed data */
520 MPDriverObject->DriverStartIo = (PDRIVER_STARTIO) HwInitializationData->HwStartIO;
521
522 /* Find the first free device number */
523 for (DisplayNumber = 0;;)
524 {
525 swprintf(SymlinkBuffer, L"\\??\\DISPLAY%lu", DisplayNumber + 1);
526 RtlInitUnicodeString(&SymlinkName, SymlinkBuffer);
527 InitializeObjectAttributes(&Obj, &SymlinkName, 0, NULL, NULL);
528 Status = ZwOpenSymbolicLinkObject(&ObjHandle, GENERIC_READ, &Obj);
529 if (NT_SUCCESS(Status))
530 {
531 ZwClose(ObjHandle);
532 DisplayNumber++;
533 continue;
534 }
535 else if (Status == STATUS_NOT_FOUND || Status == STATUS_UNSUCCESSFUL)
536 {
537 break;
538 }
539 else
540 {
541 return Status;
542 }
543 }
544
545 DPRINT("- DisplayNumber: %d\n", DisplayNumber);
546
547 Again = FALSE;
548
549 do
550 {
551 /* Create a unicode device name. */
552 swprintf(DeviceBuffer, L"\\Device\\Video%lu", DisplayNumber);
553 RtlInitUnicodeString(&DeviceName, DeviceBuffer);
554
555 /* Create the device. */
556 Status = IoCreateDevice(
557 MPDriverObject,
558 HwInitializationData->HwDeviceExtensionSize +
559 sizeof(VIDEO_PORT_DEVICE_EXTENSION),
560 &DeviceName,
561 FILE_DEVICE_VIDEO,
562 0,
563 TRUE,
564 &MPDeviceObject);
565 if (!NT_SUCCESS(Status))
566 {
567 DPRINT("IoCreateDevice call failed with status 0x%08x\n", Status);
568 return Status;
569 }
570
571 MPDriverObject->DeviceObject = MPDeviceObject;
572
573 /* Initialize the miniport drivers dispatch table */
574 MPDriverObject->MajorFunction[IRP_MJ_CREATE] = VidDispatchOpen;
575 MPDriverObject->MajorFunction[IRP_MJ_CLOSE] = VidDispatchClose;
576 MPDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VidDispatchDeviceControl;
577
578 /* Initialize our device extension */
579 DeviceExtension =
580 (PVIDEO_PORT_DEVICE_EXTENSION) MPDeviceObject->DeviceExtension;
581 DeviceExtension->DeviceObject = MPDeviceObject;
582 DeviceExtension->HwInitialize = HwInitializationData->HwInitialize;
583 DeviceExtension->HwResetHw = HwInitializationData->HwResetHw;
584 DeviceExtension->AdapterInterfaceType = HwInitializationData->AdapterInterfaceType;
585 DeviceExtension->SystemIoBusNumber = 0;
586 KeInitializeDpc(&DeviceExtension->DpcObject, VideoPortDeferredRoutine,
587 (PVOID)DeviceExtension);
588 MaxLen = (wcslen(RegistryPath->Buffer) + 10) * sizeof(WCHAR);
589 DeviceExtension->RegistryPath.MaximumLength = MaxLen;
590 DeviceExtension->RegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
591 MaxLen,
592 TAG_VIDEO_PORT);
593 swprintf(DeviceExtension->RegistryPath.Buffer, L"%s\\Device0",
594 RegistryPath->Buffer);
595 DeviceExtension->RegistryPath.Length = wcslen(DeviceExtension->RegistryPath.Buffer) *
596 sizeof(WCHAR);
597
598 MaxBus = (DeviceExtension->AdapterInterfaceType == PCIBus) ? 8 : 1;
599 DPRINT("MaxBus: %lu\n", MaxBus);
600 InitializeListHead(&DeviceExtension->AddressMappingListHead);
601
602 /* Set the buffering strategy here... */
603 /* If you change this, remember to change VidDispatchDeviceControl too */
604 MPDeviceObject->Flags |= DO_BUFFERED_IO;
605
606 do
607 {
608 RtlZeroMemory(&DeviceExtension->MiniPortDeviceExtension,
609 HwInitializationData->HwDeviceExtensionSize);
610 DPRINT("Searching on bus %d\n", DeviceExtension->SystemIoBusNumber);
611 /* Setup configuration info */
612 RtlZeroMemory(&ConfigInfo, sizeof(VIDEO_PORT_CONFIG_INFO));
613 ConfigInfo.Length = sizeof(VIDEO_PORT_CONFIG_INFO);
614 ConfigInfo.AdapterInterfaceType = DeviceExtension->AdapterInterfaceType;
615 ConfigInfo.SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
616 ConfigInfo.InterruptMode = (PCIBus == DeviceExtension->AdapterInterfaceType) ?
617 LevelSensitive : Latched;
618 ConfigInfo.DriverRegistryPath = RegistryPath->Buffer;
619 ConfigInfo.VideoPortGetProcAddress = VideoPortGetProcAddress;
620
621 /* Call HwFindAdapter entry point */
622 /* FIXME: Need to figure out what string to pass as param 3 */
623 DPRINT("FindAdapter %X\n", HwInitializationData->HwFindAdapter);
624 Status = HwInitializationData->HwFindAdapter(&DeviceExtension->MiniPortDeviceExtension,
625 Context2,
626 NULL,
627 &ConfigInfo,
628 &Again);
629 if (NO_ERROR != Status)
630 {
631 DPRINT("HwFindAdapter call failed with error %X\n", Status);
632 DeviceExtension->SystemIoBusNumber++;
633 }
634 }
635 while (NO_ERROR != Status && DeviceExtension->SystemIoBusNumber < MaxBus);
636
637 if (NO_ERROR != Status)
638 {
639 RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
640 IoDeleteDevice(MPDeviceObject);
641
642 return Status;
643 }
644 DPRINT("Found adapter\n");
645
646 /* create symbolic link "\??\DISPLAYx" */
647 swprintf(SymlinkBuffer, L"\\??\\DISPLAY%lu", DisplayNumber + 1);
648 RtlInitUnicodeString (&SymlinkName,
649 SymlinkBuffer);
650 IoCreateSymbolicLink (&SymlinkName,
651 &DeviceName);
652
653 /* Add entry to DEVICEMAP\VIDEO key in registry */
654 swprintf(DeviceVideoBuffer, L"\\Device\\Video%d", DisplayNumber);
655 RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP,
656 L"VIDEO",
657 DeviceVideoBuffer,
658 REG_SZ,
659 DeviceExtension->RegistryPath.Buffer,
660 DeviceExtension->RegistryPath.Length + sizeof(WCHAR));
661
662 /* FIXME: Allocate hardware resources for device */
663
664 /* Allocate interrupt for device */
665 DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
666 if (0 == ConfigInfo.BusInterruptVector)
667 {
668 ConfigInfo.BusInterruptVector = DeviceExtension->InterruptVector;
669 }
670 if (0 == ConfigInfo.BusInterruptLevel)
671 {
672 ConfigInfo.BusInterruptLevel = DeviceExtension->InterruptLevel;
673 }
674 if (NULL != HwInitializationData->HwInterrupt)
675 {
676 InterruptVector =
677 HalGetInterruptVector(ConfigInfo.AdapterInterfaceType,
678 ConfigInfo.SystemIoBusNumber,
679 ConfigInfo.BusInterruptLevel,
680 ConfigInfo.BusInterruptVector,
681 &IRQL,
682 &Affinity);
683 if (0 == InterruptVector)
684 {
685 DPRINT1("HalGetInterruptVector failed\n");
686 IoDeleteDevice(MPDeviceObject);
687
688 return STATUS_INSUFFICIENT_RESOURCES;
689 }
690 KeInitializeSpinLock(&DeviceExtension->InterruptSpinLock);
691 Status = IoConnectInterrupt(&DeviceExtension->InterruptObject,
692 VPInterruptRoutine,
693 DeviceExtension,
694 &DeviceExtension->InterruptSpinLock,
695 InterruptVector,
696 IRQL,
697 IRQL,
698 ConfigInfo.InterruptMode,
699 FALSE,
700 Affinity,
701 FALSE);
702 if (!NT_SUCCESS(Status))
703 {
704 DPRINT1("IoConnectInterrupt failed with status 0x%08x\n", Status);
705 IoDeleteDevice(MPDeviceObject);
706
707 return Status;
708 }
709 }
710 DisplayNumber++;
711 }
712 while (Again);
713
714 DeviceExtension->HwTimer = HwInitializationData->HwTimer;
715 if (HwInitializationData->HwTimer != NULL)
716 {
717 DPRINT("Initializing timer\n");
718 Status = IoInitializeTimer(MPDeviceObject,
719 VPTimerRoutine,
720 DeviceExtension);
721 if (!NT_SUCCESS(Status))
722 {
723 DPRINT("IoInitializeTimer failed with status 0x%08x\n", Status);
724
725 if (HwInitializationData->HwInterrupt != NULL)
726 {
727 IoDisconnectInterrupt(DeviceExtension->InterruptObject);
728 }
729 IoDeleteDevice(MPDeviceObject);
730
731 return Status;
732 }
733 }
734
735 return STATUS_SUCCESS;
736 }
737
738 /*
739 * @unimplemented
740 */
741 VOID
742 STDCALL
743 VideoPortLogError(IN PVOID HwDeviceExtension,
744 IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL,
745 IN VP_STATUS ErrorCode,
746 IN ULONG UniqueId)
747 {
748 DPRINT1("VideoPortLogError ErrorCode %d (0x%x) UniqueId %lu (0x%lx)\n",
749 ErrorCode, ErrorCode, UniqueId, UniqueId);
750 if (NULL != Vrp)
751 {
752 DPRINT1("Vrp->IoControlCode %lu (0x%lx)\n", Vrp->IoControlCode, Vrp->IoControlCode);
753 }
754 }
755
756
757 /*
758 * @unimplemented
759 */
760 VP_STATUS
761 STDCALL
762 VideoPortMapBankedMemory(IN PVOID HwDeviceExtension,
763 IN PHYSICAL_ADDRESS PhysicalAddress,
764 IN PULONG Length,
765 IN PULONG InIoSpace,
766 OUT PVOID *VirtualAddress,
767 IN ULONG BankLength,
768 IN UCHAR ReadWriteBank,
769 IN PBANKED_SECTION_ROUTINE BankRoutine,
770 IN PVOID Context)
771 {
772 DPRINT("VideoPortMapBankedMemory\n");
773 UNIMPLEMENTED;
774 return STATUS_NOT_IMPLEMENTED;
775 }
776
777
778 /*
779 * @implemented
780 */
781 VP_STATUS
782 STDCALL
783 VideoPortMapMemory(IN PVOID HwDeviceExtension,
784 IN PHYSICAL_ADDRESS PhysicalAddress,
785 IN PULONG Length,
786 IN PULONG InIoSpace,
787 OUT PVOID *VirtualAddress)
788 {
789 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
790 NTSTATUS Status;
791
792 DPRINT("VideoPortMapMemory\n");
793
794 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
795 VIDEO_PORT_DEVICE_EXTENSION,
796 MiniPortDeviceExtension);
797 *VirtualAddress = InternalMapMemory(DeviceExtension, PhysicalAddress,
798 *Length, *InIoSpace, &Status);
799
800 return Status;
801 }
802
803
804 /*
805 * @implemented
806 */
807 BOOLEAN
808 STDCALL
809 VideoPortScanRom(IN PVOID HwDeviceExtension,
810 IN PUCHAR RomBase,
811 IN ULONG RomLength,
812 IN PUCHAR String)
813 {
814 ULONG StringLength;
815 BOOLEAN Found;
816 PUCHAR SearchLocation;
817
818 DPRINT("VideoPortScanRom RomBase %p RomLength 0x%x String %s\n", RomBase, RomLength, String);
819
820 StringLength = strlen(String);
821 Found = FALSE;
822 SearchLocation = RomBase;
823 for (SearchLocation = RomBase;
824 ! Found && SearchLocation < RomBase + RomLength - StringLength;
825 SearchLocation++)
826 {
827 Found = (RtlCompareMemory(SearchLocation, String, StringLength) == StringLength);
828 if (Found)
829 {
830 DPRINT("Match found at %p\n", SearchLocation);
831 }
832 }
833
834 return Found;
835 }
836
837
838 /*
839 * @implemented
840 */
841 ULONG
842 STDCALL
843 VideoPortSetBusData(IN PVOID HwDeviceExtension,
844 IN BUS_DATA_TYPE BusDataType,
845 IN ULONG SlotNumber,
846 IN PVOID Buffer,
847 IN ULONG Offset,
848 IN ULONG Length)
849 {
850 DPRINT("VideoPortSetBusData\n");
851 return HalSetBusDataByOffset(BusDataType,
852 0,
853 SlotNumber,
854 Buffer,
855 Offset,
856 Length);
857 }
858
859
860 /*
861 * @implemented
862 */
863 VP_STATUS
864 STDCALL
865 VideoPortSetRegistryParameters(IN PVOID HwDeviceExtension,
866 IN PWSTR ValueName,
867 IN PVOID ValueData,
868 IN ULONG ValueLength)
869 {
870 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
871
872 DPRINT("VideoSetRegistryParameters\n");
873
874 assert_irql(PASSIVE_LEVEL);
875
876 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
877 VIDEO_PORT_DEVICE_EXTENSION,
878 MiniPortDeviceExtension);
879 return RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
880 DeviceExtension->RegistryPath.Buffer,
881 ValueName,
882 REG_BINARY,
883 ValueData,
884 ValueLength);
885 }
886
887
888 /*
889 * @unimplemented
890 */
891 VP_STATUS
892 STDCALL
893 VideoPortSetTrappedEmulatorPorts(IN PVOID HwDeviceExtension,
894 IN ULONG NumAccessRanges,
895 IN PVIDEO_ACCESS_RANGE AccessRange)
896 {
897 DPRINT("VideoPortSetTrappedEmulatorPorts\n");
898 /* Should store the ranges in the device extension for use by ntvdm. */
899 return STATUS_SUCCESS;
900 }
901
902
903 /*
904 * @implemented
905 */
906 VOID
907 STDCALL
908 VideoPortStartTimer(IN PVOID HwDeviceExtension)
909 {
910 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
911
912 DPRINT("VideoPortStartTimer\n");
913
914 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
915 VIDEO_PORT_DEVICE_EXTENSION,
916 MiniPortDeviceExtension);
917 IoStartTimer(DeviceExtension->DeviceObject);
918 }
919
920
921 /*
922 * @implemented
923 */
924 VOID
925 STDCALL
926 VideoPortStopTimer(IN PVOID HwDeviceExtension)
927 {
928 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
929
930 DPRINT("VideoPortStopTimer\n");
931
932 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
933 VIDEO_PORT_DEVICE_EXTENSION,
934 MiniPortDeviceExtension);
935 IoStopTimer(DeviceExtension->DeviceObject);
936 }
937
938
939 /*
940 * @implemented
941 */
942 BOOLEAN
943 STDCALL
944 VideoPortSynchronizeExecution(IN PVOID HwDeviceExtension,
945 IN VIDEO_SYNCHRONIZE_PRIORITY Priority,
946 IN PMINIPORT_SYNCHRONIZE_ROUTINE SynchronizeRoutine,
947 OUT PVOID Context)
948 {
949 BOOLEAN Ret;
950 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
951 KIRQL OldIrql;
952
953 switch(Priority)
954 {
955 case VpLowPriority:
956 Ret = (*SynchronizeRoutine)(Context);
957 break;
958 case VpMediumPriority:
959 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
960 VIDEO_PORT_DEVICE_EXTENSION,
961 MiniPortDeviceExtension);
962 if (NULL == DeviceExtension->InterruptObject)
963 {
964 Ret = (*SynchronizeRoutine)(Context);
965 }
966 else
967 {
968 Ret = KeSynchronizeExecution(DeviceExtension->InterruptObject,
969 SynchronizeRoutine,
970 Context);
971 }
972 break;
973 case VpHighPriority:
974 OldIrql = KeGetCurrentIrql();
975 if (OldIrql < SYNCH_LEVEL)
976 {
977 OldIrql = KfRaiseIrql(SYNCH_LEVEL);
978 }
979 Ret = (*SynchronizeRoutine)(Context);
980 if (OldIrql < SYNCH_LEVEL)
981 {
982 KfLowerIrql(OldIrql);
983 }
984 break;
985 default:
986 Ret = FALSE;
987 }
988
989 return Ret;
990 }
991
992
993 /*
994 * @implemented
995 */
996 VP_STATUS
997 STDCALL
998 VideoPortUnmapMemory(IN PVOID HwDeviceExtension,
999 IN PVOID VirtualAddress,
1000 IN HANDLE ProcessHandle)
1001 {
1002 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1003
1004 DPRINT("VideoPortFreeDeviceBase\n");
1005
1006 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
1007 VIDEO_PORT_DEVICE_EXTENSION,
1008 MiniPortDeviceExtension);
1009
1010 InternalUnmapMemory(DeviceExtension, VirtualAddress);
1011
1012 return STATUS_SUCCESS;
1013 }
1014
1015
1016 /*
1017 * @unimplemented
1018 */
1019 VP_STATUS
1020 STDCALL
1021 VideoPortVerifyAccessRanges(IN PVOID HwDeviceExtension,
1022 IN ULONG NumAccessRanges,
1023 IN PVIDEO_ACCESS_RANGE AccessRanges)
1024 {
1025 DPRINT1("VideoPortVerifyAccessRanges not implemented\n");
1026 return NO_ERROR;
1027 }
1028
1029
1030 /*
1031 * Reset display to blue screen
1032 */
1033 static BOOLEAN STDCALL
1034 VideoPortResetDisplayParameters(Columns, Rows)
1035 {
1036 if (NULL == ResetDisplayParametersDeviceExtension)
1037 {
1038 return(FALSE);
1039 }
1040 if (NULL == ResetDisplayParametersDeviceExtension->HwResetHw)
1041 {
1042 return(FALSE);
1043 }
1044 if (!ResetDisplayParametersDeviceExtension->HwResetHw(&ResetDisplayParametersDeviceExtension->MiniPortDeviceExtension,
1045 Columns, Rows))
1046 {
1047 return(FALSE);
1048 }
1049
1050 ResetDisplayParametersDeviceExtension = NULL;
1051
1052 return TRUE;
1053 }
1054
1055 /*
1056 * @implemented
1057 */
1058
1059 PVOID
1060 STDCALL
1061 VideoPortAllocatePool(
1062 IN PVOID HwDeviceExtension,
1063 IN VP_POOL_TYPE PoolType,
1064 IN SIZE_T NumberOfBytes,
1065 IN ULONG Tag)
1066 {
1067 return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
1068 }
1069
1070 /*
1071 * @implemented
1072 */
1073
1074 VOID
1075 STDCALL
1076 VideoPortFreePool(
1077 IN PVOID HwDeviceExtension,
1078 IN PVOID Ptr)
1079 {
1080 ExFreePool(Ptr);
1081 }
1082
1083 // VidDispatchOpen
1084 //
1085 // DESCRIPTION:
1086 // Answer requests for Open calls
1087 //
1088 // RUN LEVEL:
1089 // PASSIVE_LEVEL
1090 //
1091 // ARGUMENTS:
1092 // Standard dispatch arguments
1093 //
1094 // RETURNS:
1095 // NTSTATUS
1096 //
1097
1098 NTSTATUS STDCALL
1099 VidDispatchOpen(IN PDEVICE_OBJECT pDO,
1100 IN PIRP Irp)
1101 {
1102 PIO_STACK_LOCATION IrpStack;
1103 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1104
1105 DPRINT("VidDispatchOpen() called\n");
1106
1107 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1108
1109 if (! CsrssInitialized)
1110 {
1111 DPRINT("Referencing CSRSS\n");
1112 Csrss = PsGetCurrentProcess();
1113 DPRINT("Csrss %p\n", Csrss);
1114 }
1115 else
1116 {
1117 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION) pDO->DeviceExtension;
1118 if (DeviceExtension->HwInitialize(&DeviceExtension->MiniPortDeviceExtension))
1119 {
1120 Irp->IoStatus.Status = STATUS_SUCCESS;
1121 /* Storing the device extension pointer in a static variable is an ugly
1122 * hack. Unfortunately, we need it in VideoPortResetDisplayParameters
1123 * and HalAcquireDisplayOwnership doesn't allow us to pass a userdata
1124 * parameter. On the bright side, the DISPLAY device is opened
1125 * exclusively, so there can be only one device extension active at
1126 * any point in time. */
1127 ResetDisplayParametersDeviceExtension = DeviceExtension;
1128 HalAcquireDisplayOwnership(VideoPortResetDisplayParameters);
1129 }
1130 else
1131 {
1132 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1133 }
1134 }
1135
1136 Irp->IoStatus.Information = FILE_OPENED;
1137 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1138
1139 return STATUS_SUCCESS;
1140 }
1141
1142 // VidDispatchClose
1143 //
1144 // DESCRIPTION:
1145 // Answer requests for Close calls
1146 //
1147 // RUN LEVEL:
1148 // PASSIVE_LEVEL
1149 //
1150 // ARGUMENTS:
1151 // Standard dispatch arguments
1152 //
1153 // RETURNS:
1154 // NTSTATUS
1155 //
1156
1157 NTSTATUS STDCALL
1158 VidDispatchClose(IN PDEVICE_OBJECT pDO,
1159 IN PIRP Irp)
1160 {
1161 PIO_STACK_LOCATION IrpStack;
1162
1163 DPRINT("VidDispatchClose() called\n");
1164
1165 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1166
1167 if (! CsrssInitialized)
1168 {
1169 CsrssInitialized = TRUE;
1170 }
1171 else
1172 {
1173 HalReleaseDisplayOwnership();
1174 }
1175
1176 Irp->IoStatus.Status = STATUS_SUCCESS;
1177 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1178
1179 return STATUS_SUCCESS;
1180 }
1181
1182 // VidDispatchDeviceControl
1183 //
1184 // DESCRIPTION:
1185 // Answer requests for device control calls
1186 //
1187 // RUN LEVEL:
1188 // PASSIVE_LEVEL
1189 //
1190 // ARGUMENTS:
1191 // Standard dispatch arguments
1192 //
1193 // RETURNS:
1194 // NTSTATUS
1195 //
1196
1197 NTSTATUS STDCALL
1198 VidDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,
1199 IN PIRP Irp)
1200 {
1201 PIO_STACK_LOCATION IrpStack;
1202 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1203 PVIDEO_REQUEST_PACKET vrp;
1204
1205 DPRINT("VidDispatchDeviceControl\n");
1206 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1207 DeviceExtension = DeviceObject->DeviceExtension;
1208
1209 /* Translate the IRP to a VRP */
1210 vrp = ExAllocatePool(NonPagedPool, sizeof(VIDEO_REQUEST_PACKET));
1211 if (NULL == vrp)
1212 {
1213 return STATUS_NO_MEMORY;
1214 }
1215 vrp->StatusBlock = (PSTATUS_BLOCK) &(Irp->IoStatus);
1216 vrp->IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
1217
1218 DPRINT("- IoControlCode: %x\n", vrp->IoControlCode);
1219
1220 /* We're assuming METHOD_BUFFERED */
1221 vrp->InputBuffer = Irp->AssociatedIrp.SystemBuffer;
1222 vrp->InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
1223 vrp->OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
1224 vrp->OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
1225
1226 /* Call the Miniport Driver with the VRP */
1227 ((PDRIVER_STARTIO)DeviceObject->DriverObject->DriverStartIo)((PVOID) &DeviceExtension->MiniPortDeviceExtension, (PIRP)vrp);
1228
1229 /* Free the VRP */
1230 ExFreePool(vrp);
1231
1232 DPRINT("- Returned status: %x\n", Irp->IoStatus.Status);
1233
1234 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1235
1236 return STATUS_SUCCESS;
1237 }
1238
1239 PVOID STDCALL
1240 InternalMapMemory(IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,
1241 IN PHYSICAL_ADDRESS IoAddress,
1242 IN ULONG NumberOfUchars,
1243 IN UCHAR InIoSpace,
1244 OUT NTSTATUS *Status)
1245 {
1246 PHYSICAL_ADDRESS TranslatedAddress;
1247 PVIDEO_PORT_ADDRESS_MAPPING AddressMapping;
1248 ULONG AddressSpace;
1249 PVOID MappedAddress;
1250 PLIST_ENTRY Entry;
1251
1252 DPRINT("- IoAddress: %lx\n", IoAddress.u.LowPart);
1253 DPRINT("- NumberOfUchars: %lx\n", NumberOfUchars);
1254 DPRINT("- InIoSpace: %x\n", InIoSpace);
1255 InIoSpace &= ~VIDEO_MEMORY_SPACE_DENSE;
1256 if (0 != (InIoSpace & VIDEO_MEMORY_SPACE_P6CACHE))
1257 {
1258 DPRINT("VIDEO_MEMORY_SPACE_P6CACHE not supported, turning off\n");
1259 InIoSpace &= ~VIDEO_MEMORY_SPACE_P6CACHE;
1260 }
1261 if (! IsListEmpty(&DeviceExtension->AddressMappingListHead))
1262 {
1263 Entry = DeviceExtension->AddressMappingListHead.Flink;
1264 while (Entry != &DeviceExtension->AddressMappingListHead)
1265 {
1266 AddressMapping = CONTAINING_RECORD(Entry,
1267 VIDEO_PORT_ADDRESS_MAPPING,
1268 List);
1269 if (IoAddress.QuadPart == AddressMapping->IoAddress.QuadPart &&
1270 NumberOfUchars <= AddressMapping->NumberOfUchars)
1271 {
1272 AddressMapping->MappingCount++;
1273 if (Status)
1274 {
1275 *Status = STATUS_SUCCESS;
1276 }
1277 return AddressMapping->MappedAddress;
1278 }
1279 Entry = Entry->Flink;
1280 }
1281 }
1282
1283 AddressSpace = (ULONG)InIoSpace;
1284 if (HalTranslateBusAddress(DeviceExtension->AdapterInterfaceType,
1285 DeviceExtension->SystemIoBusNumber,
1286 IoAddress,
1287 &AddressSpace,
1288 &TranslatedAddress) == FALSE)
1289 {
1290 if (Status)
1291 {
1292 *Status = STATUS_NO_MEMORY;
1293 }
1294 return NULL;
1295 }
1296
1297 /* i/o space */
1298 if (AddressSpace != 0)
1299 {
1300 assert(0 == TranslatedAddress.u.HighPart);
1301 if (Status)
1302 {
1303 *Status = STATUS_SUCCESS;
1304 }
1305 return (PVOID) TranslatedAddress.u.LowPart;
1306 }
1307
1308 MappedAddress = MmMapIoSpace(TranslatedAddress,
1309 NumberOfUchars,
1310 FALSE);
1311
1312 if (MappedAddress)
1313 {
1314 if (Status)
1315 {
1316 *Status = STATUS_SUCCESS;
1317 }
1318
1319 AddressMapping = ExAllocatePoolWithTag(PagedPool,
1320 sizeof(VIDEO_PORT_ADDRESS_MAPPING),
1321 TAG_VIDEO_PORT);
1322 if (AddressMapping == NULL)
1323 return MappedAddress;
1324
1325 AddressMapping->MappedAddress = MappedAddress;
1326 AddressMapping->NumberOfUchars = NumberOfUchars;
1327 AddressMapping->IoAddress = IoAddress;
1328 AddressMapping->SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
1329 AddressMapping->MappingCount = 1;
1330
1331 InsertHeadList(&DeviceExtension->AddressMappingListHead,
1332 &AddressMapping->List);
1333
1334 return MappedAddress;
1335 }
1336 else
1337 {
1338 if (Status)
1339 {
1340 *Status = STATUS_NO_MEMORY;
1341 }
1342
1343 return NULL;
1344 }
1345 }
1346
1347 VOID STDCALL
1348 InternalUnmapMemory(IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,
1349 IN PVOID MappedAddress)
1350 {
1351 PVIDEO_PORT_ADDRESS_MAPPING AddressMapping;
1352 PLIST_ENTRY Entry;
1353
1354 Entry = DeviceExtension->AddressMappingListHead.Flink;
1355 while (Entry != &DeviceExtension->AddressMappingListHead)
1356 {
1357 AddressMapping = CONTAINING_RECORD(Entry,
1358 VIDEO_PORT_ADDRESS_MAPPING,
1359 List);
1360 if (AddressMapping->MappedAddress == MappedAddress)
1361 {
1362 assert(0 <= AddressMapping->MappingCount);
1363 AddressMapping->MappingCount--;
1364 if (0 == AddressMapping->MappingCount)
1365 {
1366 MmUnmapIoSpace(AddressMapping->MappedAddress,
1367 AddressMapping->NumberOfUchars);
1368 RemoveEntryList(Entry);
1369 ExFreePool(AddressMapping);
1370
1371 return;
1372 }
1373 }
1374
1375 Entry = Entry->Flink;
1376 }
1377 }
1378
1379 BOOLEAN STDCALL
1380 VideoPortDDCMonitorHelper(
1381 PVOID HwDeviceExtension,
1382 /*PI2C_FNC_TABLE*/PVOID I2CFunctions,
1383 PUCHAR pEdidBuffer,
1384 ULONG EdidBufferSize
1385 )
1386 {
1387 DPRINT1("VideoPortDDCMonitorHelper() - Unimplemented.\n");
1388 return FALSE;
1389 }
1390
1391 /*
1392 * @implemented
1393 */
1394 VP_STATUS
1395 STDCALL
1396 VideoPortAllocateBuffer(IN PVOID HwDeviceExtension,
1397 IN ULONG Size,
1398 OUT PVOID *Buffer)
1399 {
1400 DPRINT("VideoPortAllocateBuffer()\n");
1401
1402 Buffer = ExAllocatePool(PagedPool, Size);
1403 return STATUS_SUCCESS;
1404
1405 }
1406
1407 /*
1408 * @implemented
1409 */
1410 VOID
1411 STDCALL
1412 VideoPortReleaseBuffer( IN PVOID HwDeviceExtension,
1413 IN PVOID Ptr)
1414 {
1415 DPRINT("VideoPortReleaseBuffer()\n");
1416
1417 ExFreePool(Ptr);
1418 }
1419
1420
1421 VP_STATUS
1422 STDCALL
1423 VideoPortEnumerateChildren ( IN PVOID HwDeviceExtension,
1424 IN PVOID Reserved )
1425 {
1426 DPRINT1("VideoPortEnumerateChildren(): Unimplemented.\n");
1427 return STATUS_SUCCESS;
1428 }
1429
1430 PVOID
1431 STDCALL
1432 VideoPortGetRomImage ( IN PVOID HwDeviceExtension,
1433 IN PVOID Unused1,
1434 IN ULONG Unused2,
1435 IN ULONG Length )
1436 {
1437 DPRINT("VideoPortGetRomImage(HwDeviceExtension 0x%X Length 0x%X)\n",
1438 HwDeviceExtension, Length);
1439
1440 /* If the length is zero then free the existing buffer. */
1441 if (Length == 0)
1442 {
1443 if (RomImageBuffer != NULL)
1444 {
1445 ExFreePool(RomImageBuffer);
1446 RomImageBuffer = NULL;
1447 }
1448 return NULL;
1449 }
1450 else
1451 {
1452 PEPROCESS CallingProcess, PrevAttachedProcess;
1453
1454 /*
1455 The DDK says we shouldn't use the legacy C000 method but get the
1456 rom base address from the corresponding pci or acpi register but
1457 lets ignore that and use C000 anyway. CSRSS has already mapped the
1458 bios area into memory so we'll copy from there.
1459 */
1460 CallingProcess = PsGetCurrentProcess();
1461 if (CallingProcess != Csrss)
1462 {
1463 if (NULL != PsGetCurrentThread()->OldProcess)
1464 {
1465 PrevAttachedProcess = CallingProcess;
1466 KeDetachProcess();
1467 }
1468 else
1469 {
1470 PrevAttachedProcess = NULL;
1471 }
1472 KeAttachProcess(Csrss);
1473 }
1474
1475 /*
1476 Copy the bios.
1477 */
1478 Length = min(Length, 0x10000);
1479 if (RomImageBuffer != NULL)
1480 {
1481 ExFreePool(RomImageBuffer);
1482 }
1483 RomImageBuffer = ExAllocatePool(PagedPool, Length);
1484 if (RomImageBuffer == NULL)
1485 {
1486 return(NULL);
1487 }
1488 RtlCopyMemory(RomImageBuffer, (PUCHAR)0xC0000, Length);
1489
1490 /*
1491 Detach from csrss if we attached.
1492 */
1493 if (CallingProcess != Csrss)
1494 {
1495 KeDetachProcess();
1496 if (NULL != PrevAttachedProcess)
1497 {
1498 KeAttachProcess(PrevAttachedProcess);
1499 }
1500 }
1501
1502 return(RomImageBuffer);
1503 }
1504 }
1505
1506 VOID
1507 STDCALL
1508 STATIC
1509 VideoPortDeferredRoutine ( IN PKDPC Dpc,
1510 IN PVOID DeferredContext,
1511 IN PVOID SystemArgument1,
1512 IN PVOID SystemArgument2 )
1513 {
1514 PVOID HwDeviceExtension =
1515 ((PVIDEO_PORT_DEVICE_EXTENSION)DeferredContext)->MiniPortDeviceExtension;
1516 ((PMINIPORT_DPC_ROUTINE)SystemArgument1)(HwDeviceExtension, SystemArgument2);
1517 }
1518
1519 BOOLEAN
1520 STDCALL
1521 VideoPortQueueDpc ( IN PVOID HwDeviceExtension,
1522 IN PMINIPORT_DPC_ROUTINE CallbackRoutine,
1523 IN PVOID Context )
1524 {
1525 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1526
1527 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
1528 VIDEO_PORT_DEVICE_EXTENSION,
1529 MiniPortDeviceExtension);
1530 return KeInsertQueueDpc(&DeviceExtension->DpcObject,
1531 (PVOID)CallbackRoutine,
1532 (PVOID)Context);
1533 }
1534
1535 PVOID
1536 STDCALL
1537 VideoPortGetAssociatedDeviceExtension ( IN PVOID DeviceObject )
1538 {
1539 DPRINT1("VideoPortGetAssociatedDeviceExtension(): Unimplemented.\n");
1540 return(NULL);
1541 }
1542
1543 PVOID
1544 STDCALL
1545 VideoPortAllocateCommonBuffer ( IN PVOID HwDeviceExtension,
1546 IN PVP_DMA_ADAPTER VpDmaAdapter,
1547 IN ULONG DesiredLength,
1548 OUT PPHYSICAL_ADDRESS LogicalAddress,
1549 IN BOOLEAN CacheEnabled,
1550 PVOID Reserved )
1551 {
1552 return HalAllocateCommonBuffer((PADAPTER_OBJECT)VpDmaAdapter,
1553 DesiredLength,
1554 LogicalAddress,
1555 CacheEnabled);
1556 }
1557
1558 VOID
1559 STDCALL
1560 VideoPortReleaseCommonBuffer ( IN PVOID HwDeviceExtension,
1561 IN PVP_DMA_ADAPTER VpDmaAdapter,
1562 IN ULONG Length,
1563 IN PHYSICAL_ADDRESS LogicalAddress,
1564 IN PVOID VirtualAddress,
1565 IN BOOLEAN CacheEnabled )
1566 {
1567 HalFreeCommonBuffer((PADAPTER_OBJECT)VpDmaAdapter,
1568 Length,
1569 LogicalAddress,
1570 VirtualAddress,
1571 CacheEnabled);
1572 }
1573
1574 VP_STATUS
1575 STDCALL
1576 VideoPortCreateSecondaryDisplay ( IN PVOID HwDeviceExtension,
1577 IN OUT PVOID *SecondaryDeviceExtension,
1578 IN ULONG Flag )
1579 {
1580 DPRINT1("VideoPortCreateSecondaryDisplay(): Unimplemented.\n");
1581 return STATUS_UNSUCCESSFUL;
1582 }
1583
1584 VOID
1585 STDCALL
1586 VideoPortPutDmaAdapter ( IN PVOID HwDeviceExtension,
1587 IN PVP_DMA_ADAPTER VpDmaAdapter )
1588 {
1589 DPRINT("VideoPortPutDmaAdapter(): Unimplemented.\n");
1590 }
1591
1592 PVP_DMA_ADAPTER
1593 STDCALL
1594 VideoPortGetDmaAdapter ( IN PVOID HwDeviceExtension,
1595 IN PVP_DEVICE_DESCRIPTION VpDeviceExtension )
1596 {
1597 DEVICE_DESCRIPTION DeviceDescription;
1598 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1599 ULONG NumberOfMapRegisters;
1600 PVP_DMA_ADAPTER Adapter;
1601
1602 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
1603 VIDEO_PORT_DEVICE_EXTENSION,
1604 MiniPortDeviceExtension);
1605
1606 DPRINT("VideoPortGetDmaAdapter()\n");
1607
1608 DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
1609 DeviceDescription.Master = TRUE /* ?? */;
1610 DeviceDescription.ScatterGather = VpDeviceExtension->ScatterGather;
1611 DeviceDescription.DemandMode = FALSE /* ?? */;
1612 DeviceDescription.AutoInitialize = FALSE /* ?? */;
1613 DeviceDescription.Dma32BitAddresses = VpDeviceExtension->Dma32BitAddresses;
1614 DeviceDescription.IgnoreCount = FALSE /* ?? */;
1615 DeviceDescription.Reserved1 = FALSE;
1616 DeviceDescription.BusNumber = DeviceExtension->SystemIoBusNumber;
1617 DeviceDescription.DmaChannel = 0 /* ?? */;
1618 DeviceDescription.InterfaceType = DeviceExtension->AdapterInterfaceType;
1619 DeviceDescription.DmaWidth = Width8Bits;
1620 DeviceDescription.DmaSpeed = Compatible;
1621 DeviceDescription.MaximumLength = VpDeviceExtension->MaximumLength;
1622 DeviceDescription.DmaPort = 0;
1623
1624 Adapter =
1625 (PVP_DMA_ADAPTER)HalGetAdapter(&DeviceDescription, &NumberOfMapRegisters);
1626 DPRINT("Adapter %X\n", Adapter);
1627 return(Adapter);
1628 }
1629
1630
1631 /*
1632 * @implemented
1633 */
1634 VP_STATUS
1635 STDCALL
1636 VideoPortGetVersion ( IN PVOID HwDeviceExtension,
1637 IN OUT PVPOSVERSIONINFO VpOsVersionInfo )
1638 {
1639 RTL_OSVERSIONINFOEXW Version;
1640
1641 Version.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
1642 if (VpOsVersionInfo->Size >= sizeof(VPOSVERSIONINFO))
1643 {
1644 #if 1
1645 if (NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&Version)))
1646 {
1647 VpOsVersionInfo->MajorVersion = Version.dwMajorVersion;
1648 VpOsVersionInfo->MinorVersion = Version.dwMinorVersion;
1649 VpOsVersionInfo->BuildNumber = Version.dwBuildNumber;
1650 VpOsVersionInfo->ServicePackMajor = Version.wServicePackMajor;
1651 VpOsVersionInfo->ServicePackMinor = Version.wServicePackMinor;
1652 return STATUS_SUCCESS;
1653 }
1654 return STATUS_UNSUCCESSFUL;
1655 #else
1656 VpOsVersionInfo->MajorVersion = 5;
1657 VpOsVersionInfo->MinorVersion = 0;
1658 VpOsVersionInfo->BuildNumber = 2195;
1659 VpOsVersionInfo->ServicePackMajor = 4;
1660 VpOsVersionInfo->ServicePackMinor = 0;
1661 return(STATUS_SUCCESS);
1662 #endif
1663 }
1664
1665 return ERROR_INVALID_PARAMETER;
1666 }
1667
1668 PVOID
1669 STDCALL
1670 VideoPortLockBuffer ( IN PVOID HwDeviceExtension,
1671 IN PVOID BaseAddress,
1672 IN ULONG Length,
1673 IN VP_LOCK_OPERATION Operation )
1674 {
1675 DPRINT1("VideoPortLockBuffer(): Unimplemented.\n");
1676 return NULL;
1677 }
1678
1679 VOID
1680 STDCALL
1681 VideoPortUnlockBuffer ( IN PVOID HwDeviceExtension,
1682 IN PVOID Mdl )
1683 {
1684 DPRINT1("VideoPortUnlockBuffer(): Unimplemented.\n");
1685 }
1686
1687 VP_STATUS
1688 STDCALL
1689 VideoPortCreateEvent ( IN PVOID HwDeviceExtension,
1690 IN ULONG EventFlag,
1691 IN PVOID Unused,
1692 OUT PEVENT *Event)
1693 {
1694 EVENT_TYPE Type;
1695 (*Event) = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT),
1696 TAG_VIDEO_PORT);
1697 if ((*Event) == NULL)
1698 {
1699 return STATUS_NO_MEMORY;
1700 }
1701 if (EventFlag & NOTIFICATION_EVENT)
1702 {
1703 Type = NotificationEvent;
1704 }
1705 else
1706 {
1707 Type = SynchronizationEvent;
1708 }
1709 KeInitializeEvent((PKEVENT)*Event, Type, EventFlag & INITIAL_EVENT_SIGNALED);
1710 return STATUS_SUCCESS;
1711 }
1712
1713 VP_STATUS
1714 STDCALL
1715 VideoPortDeleteEvent ( IN PVOID HwDeviceExtension,
1716 IN PEVENT Event)
1717 {
1718 ExFreePool(Event);
1719 return STATUS_SUCCESS;
1720 }
1721
1722 LONG
1723 STDCALL
1724 VideoPortSetEvent ( IN PVOID HwDeviceExtension,
1725 IN PEVENT Event )
1726 {
1727 return KeSetEvent((PKEVENT)Event, IO_NO_INCREMENT, FALSE);
1728 }
1729
1730 VOID
1731 STDCALL
1732 VideoPortClearEvent ( IN PVOID HwDeviceExtension,
1733 IN PEVENT Event )
1734 {
1735 KeClearEvent((PKEVENT)Event);
1736 }
1737
1738 VP_STATUS
1739 STDCALL
1740 VideoPortWaitForSingleObject ( IN PVOID HwDeviceExtension,
1741 IN PVOID Object,
1742 IN PLARGE_INTEGER Timeout OPTIONAL )
1743 {
1744 return KeWaitForSingleObject(Object,
1745 Executive,
1746 KernelMode,
1747 FALSE,
1748 Timeout);
1749 }
1750
1751 BOOLEAN
1752 STDCALL
1753 VideoPortCheckForDeviceExistence ( IN PVOID HwDeviceExtension,
1754 IN USHORT VendorId,
1755 IN USHORT DeviceId,
1756 IN UCHAR RevisionId,
1757 IN USHORT SubVendorId,
1758 IN USHORT SubSystemId,
1759 IN ULONG Flags )
1760 {
1761 DPRINT1("VideoPortCheckForDeviceExistence(): Unimplemented.\n");
1762 return TRUE;
1763 }
1764
1765 VP_STATUS
1766 STDCALL
1767 VideoPortRegisterBugcheckCallback ( IN PVOID HwDeviceExtension,
1768 IN ULONG BugcheckCode,
1769 IN PVOID Callback,
1770 IN ULONG BugcheckDataSize )
1771 {
1772 DPRINT1("VideoPortRegisterBugcheckCallback(): Unimplemented.\n");
1773 return STATUS_UNSUCCESSFUL;
1774 }
1775
1776 PVOID
1777 STDCALL
1778 VideoPortImageDirectoryEntryToData ( PVOID BaseAddress,
1779 ULONG Directory )
1780 {
1781 PIMAGE_NT_HEADERS NtHeader;
1782 ULONG Va;
1783
1784 NtHeader = RtlImageNtHeader (BaseAddress);
1785 if (NtHeader == NULL)
1786 return NULL;
1787
1788 if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes)
1789 return NULL;
1790
1791 Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress;
1792 if (Va == 0)
1793 return NULL;
1794
1795 return (PVOID)(BaseAddress + Va);
1796 }
1797
1798 PVOID STDCALL
1799 VideoPortGetProcAddress(IN PVOID HwDeviceExtension,
1800 IN PUCHAR FunctionName)
1801 {
1802 SYSTEM_LOAD_IMAGE GdiDriverInfo;
1803 PVOID BaseAddress;
1804 PIMAGE_EXPORT_DIRECTORY ExportDir;
1805 PUSHORT OrdinalPtr;
1806 PULONG NamePtr;
1807 PULONG AddressPtr;
1808 ULONG i = 0;
1809 NTSTATUS Status;
1810
1811 DPRINT("VideoPortGetProcAddress(%s)\n", FunctionName);
1812
1813 RtlInitUnicodeString(&GdiDriverInfo.ModuleName, L"videoprt");
1814 Status = ZwSetSystemInformation(SystemLoadImage, &GdiDriverInfo,
1815 sizeof(SYSTEM_LOAD_IMAGE));
1816 if (!NT_SUCCESS(Status))
1817 {
1818 DPRINT("Couldn't get our own module handle?\n");
1819 return NULL;
1820 }
1821
1822 BaseAddress = GdiDriverInfo.ModuleBase;
1823
1824 /* Get the pointer to the export directory */
1825 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1826 VideoPortImageDirectoryEntryToData (BaseAddress,
1827 IMAGE_DIRECTORY_ENTRY_EXPORT);
1828
1829 /* search by name */
1830 AddressPtr = (PULONG)
1831 ((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfFunctions);
1832 OrdinalPtr = (PUSHORT)
1833 ((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfNameOrdinals);
1834 NamePtr = (PULONG)
1835 ((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfNames);
1836 for (i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++)
1837 {
1838 if (!_strnicmp(FunctionName, (char*)(BaseAddress + *NamePtr),
1839 strlen(FunctionName)))
1840 {
1841 return (PVOID)((ULONG_PTR)BaseAddress +
1842 (ULONG_PTR)AddressPtr[*OrdinalPtr]);
1843 }
1844 }
1845 DPRINT("VideoPortGetProcAddress: Can't resolve symbol %s\n", FunctionName);
1846 return(NULL);
1847 }
1848
1849 LONGLONG STDCALL
1850 VideoPortQueryPerformanceCounter(
1851 IN PVOID HwDeviceExtension,
1852 OUT PLONGLONG PerformanceFrequency OPTIONAL)
1853 {
1854 LARGE_INTEGER Result;
1855
1856 DPRINT("VideoPortQueryPerformanceCounter\n");
1857 Result = KeQueryPerformanceCounter((PLARGE_INTEGER)PerformanceFrequency);
1858 return Result.QuadPart;
1859 }
1860