- Fixed bug in VideoPortSetBusData.
[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.18 2004/03/10 16:10:13 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 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
851
852 DPRINT("VideoPortSetBusData\n");
853
854 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
855 VIDEO_PORT_DEVICE_EXTENSION,
856 MiniPortDeviceExtension);
857
858 return HalSetBusDataByOffset(BusDataType,
859 DeviceExtension->SystemIoBusNumber,
860 SlotNumber,
861 Buffer,
862 Offset,
863 Length);
864 }
865
866
867 /*
868 * @implemented
869 */
870 VP_STATUS
871 STDCALL
872 VideoPortSetRegistryParameters(IN PVOID HwDeviceExtension,
873 IN PWSTR ValueName,
874 IN PVOID ValueData,
875 IN ULONG ValueLength)
876 {
877 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
878
879 DPRINT("VideoSetRegistryParameters\n");
880
881 assert_irql(PASSIVE_LEVEL);
882
883 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
884 VIDEO_PORT_DEVICE_EXTENSION,
885 MiniPortDeviceExtension);
886 return RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
887 DeviceExtension->RegistryPath.Buffer,
888 ValueName,
889 REG_BINARY,
890 ValueData,
891 ValueLength);
892 }
893
894
895 /*
896 * @unimplemented
897 */
898 VP_STATUS
899 STDCALL
900 VideoPortSetTrappedEmulatorPorts(IN PVOID HwDeviceExtension,
901 IN ULONG NumAccessRanges,
902 IN PVIDEO_ACCESS_RANGE AccessRange)
903 {
904 DPRINT("VideoPortSetTrappedEmulatorPorts\n");
905 /* Should store the ranges in the device extension for use by ntvdm. */
906 return STATUS_SUCCESS;
907 }
908
909
910 /*
911 * @implemented
912 */
913 VOID
914 STDCALL
915 VideoPortStartTimer(IN PVOID HwDeviceExtension)
916 {
917 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
918
919 DPRINT("VideoPortStartTimer\n");
920
921 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
922 VIDEO_PORT_DEVICE_EXTENSION,
923 MiniPortDeviceExtension);
924 IoStartTimer(DeviceExtension->DeviceObject);
925 }
926
927
928 /*
929 * @implemented
930 */
931 VOID
932 STDCALL
933 VideoPortStopTimer(IN PVOID HwDeviceExtension)
934 {
935 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
936
937 DPRINT("VideoPortStopTimer\n");
938
939 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
940 VIDEO_PORT_DEVICE_EXTENSION,
941 MiniPortDeviceExtension);
942 IoStopTimer(DeviceExtension->DeviceObject);
943 }
944
945
946 /*
947 * @implemented
948 */
949 BOOLEAN
950 STDCALL
951 VideoPortSynchronizeExecution(IN PVOID HwDeviceExtension,
952 IN VIDEO_SYNCHRONIZE_PRIORITY Priority,
953 IN PMINIPORT_SYNCHRONIZE_ROUTINE SynchronizeRoutine,
954 OUT PVOID Context)
955 {
956 BOOLEAN Ret;
957 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
958 KIRQL OldIrql;
959
960 switch(Priority)
961 {
962 case VpLowPriority:
963 Ret = (*SynchronizeRoutine)(Context);
964 break;
965 case VpMediumPriority:
966 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
967 VIDEO_PORT_DEVICE_EXTENSION,
968 MiniPortDeviceExtension);
969 if (NULL == DeviceExtension->InterruptObject)
970 {
971 Ret = (*SynchronizeRoutine)(Context);
972 }
973 else
974 {
975 Ret = KeSynchronizeExecution(DeviceExtension->InterruptObject,
976 SynchronizeRoutine,
977 Context);
978 }
979 break;
980 case VpHighPriority:
981 OldIrql = KeGetCurrentIrql();
982 if (OldIrql < SYNCH_LEVEL)
983 {
984 OldIrql = KfRaiseIrql(SYNCH_LEVEL);
985 }
986 Ret = (*SynchronizeRoutine)(Context);
987 if (OldIrql < SYNCH_LEVEL)
988 {
989 KfLowerIrql(OldIrql);
990 }
991 break;
992 default:
993 Ret = FALSE;
994 }
995
996 return Ret;
997 }
998
999
1000 /*
1001 * @implemented
1002 */
1003 VP_STATUS
1004 STDCALL
1005 VideoPortUnmapMemory(IN PVOID HwDeviceExtension,
1006 IN PVOID VirtualAddress,
1007 IN HANDLE ProcessHandle)
1008 {
1009 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1010
1011 DPRINT("VideoPortFreeDeviceBase\n");
1012
1013 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
1014 VIDEO_PORT_DEVICE_EXTENSION,
1015 MiniPortDeviceExtension);
1016
1017 InternalUnmapMemory(DeviceExtension, VirtualAddress);
1018
1019 return STATUS_SUCCESS;
1020 }
1021
1022
1023 /*
1024 * @unimplemented
1025 */
1026 VP_STATUS
1027 STDCALL
1028 VideoPortVerifyAccessRanges(IN PVOID HwDeviceExtension,
1029 IN ULONG NumAccessRanges,
1030 IN PVIDEO_ACCESS_RANGE AccessRanges)
1031 {
1032 DPRINT1("VideoPortVerifyAccessRanges not implemented\n");
1033 return NO_ERROR;
1034 }
1035
1036
1037 /*
1038 * Reset display to blue screen
1039 */
1040 static BOOLEAN STDCALL
1041 VideoPortResetDisplayParameters(Columns, Rows)
1042 {
1043 if (NULL == ResetDisplayParametersDeviceExtension)
1044 {
1045 return(FALSE);
1046 }
1047 if (NULL == ResetDisplayParametersDeviceExtension->HwResetHw)
1048 {
1049 return(FALSE);
1050 }
1051 if (!ResetDisplayParametersDeviceExtension->HwResetHw(&ResetDisplayParametersDeviceExtension->MiniPortDeviceExtension,
1052 Columns, Rows))
1053 {
1054 return(FALSE);
1055 }
1056
1057 ResetDisplayParametersDeviceExtension = NULL;
1058
1059 return TRUE;
1060 }
1061
1062 /*
1063 * @implemented
1064 */
1065
1066 PVOID
1067 STDCALL
1068 VideoPortAllocatePool(
1069 IN PVOID HwDeviceExtension,
1070 IN VP_POOL_TYPE PoolType,
1071 IN SIZE_T NumberOfBytes,
1072 IN ULONG Tag)
1073 {
1074 return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
1075 }
1076
1077 /*
1078 * @implemented
1079 */
1080
1081 VOID
1082 STDCALL
1083 VideoPortFreePool(
1084 IN PVOID HwDeviceExtension,
1085 IN PVOID Ptr)
1086 {
1087 ExFreePool(Ptr);
1088 }
1089
1090 // VidDispatchOpen
1091 //
1092 // DESCRIPTION:
1093 // Answer requests for Open calls
1094 //
1095 // RUN LEVEL:
1096 // PASSIVE_LEVEL
1097 //
1098 // ARGUMENTS:
1099 // Standard dispatch arguments
1100 //
1101 // RETURNS:
1102 // NTSTATUS
1103 //
1104
1105 NTSTATUS STDCALL
1106 VidDispatchOpen(IN PDEVICE_OBJECT pDO,
1107 IN PIRP Irp)
1108 {
1109 PIO_STACK_LOCATION IrpStack;
1110 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1111
1112 DPRINT("VidDispatchOpen() called\n");
1113
1114 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1115
1116 if (! CsrssInitialized)
1117 {
1118 DPRINT("Referencing CSRSS\n");
1119 Csrss = PsGetCurrentProcess();
1120 DPRINT("Csrss %p\n", Csrss);
1121 }
1122 else
1123 {
1124 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION) pDO->DeviceExtension;
1125 if (DeviceExtension->HwInitialize(&DeviceExtension->MiniPortDeviceExtension))
1126 {
1127 Irp->IoStatus.Status = STATUS_SUCCESS;
1128 /* Storing the device extension pointer in a static variable is an ugly
1129 * hack. Unfortunately, we need it in VideoPortResetDisplayParameters
1130 * and HalAcquireDisplayOwnership doesn't allow us to pass a userdata
1131 * parameter. On the bright side, the DISPLAY device is opened
1132 * exclusively, so there can be only one device extension active at
1133 * any point in time. */
1134 ResetDisplayParametersDeviceExtension = DeviceExtension;
1135 HalAcquireDisplayOwnership(VideoPortResetDisplayParameters);
1136 }
1137 else
1138 {
1139 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1140 }
1141 }
1142
1143 Irp->IoStatus.Information = FILE_OPENED;
1144 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1145
1146 return STATUS_SUCCESS;
1147 }
1148
1149 // VidDispatchClose
1150 //
1151 // DESCRIPTION:
1152 // Answer requests for Close calls
1153 //
1154 // RUN LEVEL:
1155 // PASSIVE_LEVEL
1156 //
1157 // ARGUMENTS:
1158 // Standard dispatch arguments
1159 //
1160 // RETURNS:
1161 // NTSTATUS
1162 //
1163
1164 NTSTATUS STDCALL
1165 VidDispatchClose(IN PDEVICE_OBJECT pDO,
1166 IN PIRP Irp)
1167 {
1168 PIO_STACK_LOCATION IrpStack;
1169
1170 DPRINT("VidDispatchClose() called\n");
1171
1172 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1173
1174 if (! CsrssInitialized)
1175 {
1176 CsrssInitialized = TRUE;
1177 }
1178 else
1179 {
1180 HalReleaseDisplayOwnership();
1181 }
1182
1183 Irp->IoStatus.Status = STATUS_SUCCESS;
1184 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1185
1186 return STATUS_SUCCESS;
1187 }
1188
1189 // VidDispatchDeviceControl
1190 //
1191 // DESCRIPTION:
1192 // Answer requests for device control calls
1193 //
1194 // RUN LEVEL:
1195 // PASSIVE_LEVEL
1196 //
1197 // ARGUMENTS:
1198 // Standard dispatch arguments
1199 //
1200 // RETURNS:
1201 // NTSTATUS
1202 //
1203
1204 NTSTATUS STDCALL
1205 VidDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,
1206 IN PIRP Irp)
1207 {
1208 PIO_STACK_LOCATION IrpStack;
1209 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1210 PVIDEO_REQUEST_PACKET vrp;
1211
1212 DPRINT("VidDispatchDeviceControl\n");
1213 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1214 DeviceExtension = DeviceObject->DeviceExtension;
1215
1216 /* Translate the IRP to a VRP */
1217 vrp = ExAllocatePool(NonPagedPool, sizeof(VIDEO_REQUEST_PACKET));
1218 if (NULL == vrp)
1219 {
1220 return STATUS_NO_MEMORY;
1221 }
1222 vrp->StatusBlock = (PSTATUS_BLOCK) &(Irp->IoStatus);
1223 vrp->IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
1224
1225 DPRINT("- IoControlCode: %x\n", vrp->IoControlCode);
1226
1227 /* We're assuming METHOD_BUFFERED */
1228 vrp->InputBuffer = Irp->AssociatedIrp.SystemBuffer;
1229 vrp->InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
1230 vrp->OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
1231 vrp->OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
1232
1233 /* Call the Miniport Driver with the VRP */
1234 ((PDRIVER_STARTIO)DeviceObject->DriverObject->DriverStartIo)((PVOID) &DeviceExtension->MiniPortDeviceExtension, (PIRP)vrp);
1235
1236 /* Free the VRP */
1237 ExFreePool(vrp);
1238
1239 DPRINT("- Returned status: %x\n", Irp->IoStatus.Status);
1240
1241 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1242
1243 return STATUS_SUCCESS;
1244 }
1245
1246 PVOID STDCALL
1247 InternalMapMemory(IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,
1248 IN PHYSICAL_ADDRESS IoAddress,
1249 IN ULONG NumberOfUchars,
1250 IN UCHAR InIoSpace,
1251 OUT NTSTATUS *Status)
1252 {
1253 PHYSICAL_ADDRESS TranslatedAddress;
1254 PVIDEO_PORT_ADDRESS_MAPPING AddressMapping;
1255 ULONG AddressSpace;
1256 PVOID MappedAddress;
1257 PLIST_ENTRY Entry;
1258
1259 DPRINT("- IoAddress: %lx\n", IoAddress.u.LowPart);
1260 DPRINT("- NumberOfUchars: %lx\n", NumberOfUchars);
1261 DPRINT("- InIoSpace: %x\n", InIoSpace);
1262 InIoSpace &= ~VIDEO_MEMORY_SPACE_DENSE;
1263 if (0 != (InIoSpace & VIDEO_MEMORY_SPACE_P6CACHE))
1264 {
1265 DPRINT("VIDEO_MEMORY_SPACE_P6CACHE not supported, turning off\n");
1266 InIoSpace &= ~VIDEO_MEMORY_SPACE_P6CACHE;
1267 }
1268 if (! IsListEmpty(&DeviceExtension->AddressMappingListHead))
1269 {
1270 Entry = DeviceExtension->AddressMappingListHead.Flink;
1271 while (Entry != &DeviceExtension->AddressMappingListHead)
1272 {
1273 AddressMapping = CONTAINING_RECORD(Entry,
1274 VIDEO_PORT_ADDRESS_MAPPING,
1275 List);
1276 if (IoAddress.QuadPart == AddressMapping->IoAddress.QuadPart &&
1277 NumberOfUchars <= AddressMapping->NumberOfUchars)
1278 {
1279 AddressMapping->MappingCount++;
1280 if (Status)
1281 {
1282 *Status = STATUS_SUCCESS;
1283 }
1284 return AddressMapping->MappedAddress;
1285 }
1286 Entry = Entry->Flink;
1287 }
1288 }
1289
1290 AddressSpace = (ULONG)InIoSpace;
1291 if (HalTranslateBusAddress(DeviceExtension->AdapterInterfaceType,
1292 DeviceExtension->SystemIoBusNumber,
1293 IoAddress,
1294 &AddressSpace,
1295 &TranslatedAddress) == FALSE)
1296 {
1297 if (Status)
1298 {
1299 *Status = STATUS_NO_MEMORY;
1300 }
1301 return NULL;
1302 }
1303
1304 /* i/o space */
1305 if (AddressSpace != 0)
1306 {
1307 assert(0 == TranslatedAddress.u.HighPart);
1308 if (Status)
1309 {
1310 *Status = STATUS_SUCCESS;
1311 }
1312 return (PVOID) TranslatedAddress.u.LowPart;
1313 }
1314
1315 MappedAddress = MmMapIoSpace(TranslatedAddress,
1316 NumberOfUchars,
1317 FALSE);
1318
1319 if (MappedAddress)
1320 {
1321 if (Status)
1322 {
1323 *Status = STATUS_SUCCESS;
1324 }
1325
1326 AddressMapping = ExAllocatePoolWithTag(PagedPool,
1327 sizeof(VIDEO_PORT_ADDRESS_MAPPING),
1328 TAG_VIDEO_PORT);
1329 if (AddressMapping == NULL)
1330 return MappedAddress;
1331
1332 AddressMapping->MappedAddress = MappedAddress;
1333 AddressMapping->NumberOfUchars = NumberOfUchars;
1334 AddressMapping->IoAddress = IoAddress;
1335 AddressMapping->SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
1336 AddressMapping->MappingCount = 1;
1337
1338 InsertHeadList(&DeviceExtension->AddressMappingListHead,
1339 &AddressMapping->List);
1340
1341 return MappedAddress;
1342 }
1343 else
1344 {
1345 if (Status)
1346 {
1347 *Status = STATUS_NO_MEMORY;
1348 }
1349
1350 return NULL;
1351 }
1352 }
1353
1354 VOID STDCALL
1355 InternalUnmapMemory(IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,
1356 IN PVOID MappedAddress)
1357 {
1358 PVIDEO_PORT_ADDRESS_MAPPING AddressMapping;
1359 PLIST_ENTRY Entry;
1360
1361 Entry = DeviceExtension->AddressMappingListHead.Flink;
1362 while (Entry != &DeviceExtension->AddressMappingListHead)
1363 {
1364 AddressMapping = CONTAINING_RECORD(Entry,
1365 VIDEO_PORT_ADDRESS_MAPPING,
1366 List);
1367 if (AddressMapping->MappedAddress == MappedAddress)
1368 {
1369 assert(0 <= AddressMapping->MappingCount);
1370 AddressMapping->MappingCount--;
1371 if (0 == AddressMapping->MappingCount)
1372 {
1373 MmUnmapIoSpace(AddressMapping->MappedAddress,
1374 AddressMapping->NumberOfUchars);
1375 RemoveEntryList(Entry);
1376 ExFreePool(AddressMapping);
1377
1378 return;
1379 }
1380 }
1381
1382 Entry = Entry->Flink;
1383 }
1384 }
1385
1386 BOOLEAN STDCALL
1387 VideoPortDDCMonitorHelper(
1388 PVOID HwDeviceExtension,
1389 /*PI2C_FNC_TABLE*/PVOID I2CFunctions,
1390 PUCHAR pEdidBuffer,
1391 ULONG EdidBufferSize
1392 )
1393 {
1394 DPRINT1("VideoPortDDCMonitorHelper() - Unimplemented.\n");
1395 return FALSE;
1396 }
1397
1398 /*
1399 * @implemented
1400 */
1401 VP_STATUS
1402 STDCALL
1403 VideoPortAllocateBuffer(IN PVOID HwDeviceExtension,
1404 IN ULONG Size,
1405 OUT PVOID *Buffer)
1406 {
1407 DPRINT("VideoPortAllocateBuffer()\n");
1408
1409 Buffer = ExAllocatePool(PagedPool, Size);
1410 return STATUS_SUCCESS;
1411
1412 }
1413
1414 /*
1415 * @implemented
1416 */
1417 VOID
1418 STDCALL
1419 VideoPortReleaseBuffer( IN PVOID HwDeviceExtension,
1420 IN PVOID Ptr)
1421 {
1422 DPRINT("VideoPortReleaseBuffer()\n");
1423
1424 ExFreePool(Ptr);
1425 }
1426
1427
1428 VP_STATUS
1429 STDCALL
1430 VideoPortEnumerateChildren ( IN PVOID HwDeviceExtension,
1431 IN PVOID Reserved )
1432 {
1433 DPRINT1("VideoPortEnumerateChildren(): Unimplemented.\n");
1434 return STATUS_SUCCESS;
1435 }
1436
1437 PVOID
1438 STDCALL
1439 VideoPortGetRomImage ( IN PVOID HwDeviceExtension,
1440 IN PVOID Unused1,
1441 IN ULONG Unused2,
1442 IN ULONG Length )
1443 {
1444 DPRINT("VideoPortGetRomImage(HwDeviceExtension 0x%X Length 0x%X)\n",
1445 HwDeviceExtension, Length);
1446
1447 /* If the length is zero then free the existing buffer. */
1448 if (Length == 0)
1449 {
1450 if (RomImageBuffer != NULL)
1451 {
1452 ExFreePool(RomImageBuffer);
1453 RomImageBuffer = NULL;
1454 }
1455 return NULL;
1456 }
1457 else
1458 {
1459 PEPROCESS CallingProcess, PrevAttachedProcess;
1460
1461 /*
1462 The DDK says we shouldn't use the legacy C000 method but get the
1463 rom base address from the corresponding pci or acpi register but
1464 lets ignore that and use C000 anyway. CSRSS has already mapped the
1465 bios area into memory so we'll copy from there.
1466 */
1467 CallingProcess = PsGetCurrentProcess();
1468 if (CallingProcess != Csrss)
1469 {
1470 if (NULL != PsGetCurrentThread()->OldProcess)
1471 {
1472 PrevAttachedProcess = CallingProcess;
1473 KeDetachProcess();
1474 }
1475 else
1476 {
1477 PrevAttachedProcess = NULL;
1478 }
1479 KeAttachProcess(Csrss);
1480 }
1481
1482 /*
1483 Copy the bios.
1484 */
1485 Length = min(Length, 0x10000);
1486 if (RomImageBuffer != NULL)
1487 {
1488 ExFreePool(RomImageBuffer);
1489 }
1490 RomImageBuffer = ExAllocatePool(PagedPool, Length);
1491 if (RomImageBuffer == NULL)
1492 {
1493 return(NULL);
1494 }
1495 RtlCopyMemory(RomImageBuffer, (PUCHAR)0xC0000, Length);
1496
1497 /*
1498 Detach from csrss if we attached.
1499 */
1500 if (CallingProcess != Csrss)
1501 {
1502 KeDetachProcess();
1503 if (NULL != PrevAttachedProcess)
1504 {
1505 KeAttachProcess(PrevAttachedProcess);
1506 }
1507 }
1508
1509 return(RomImageBuffer);
1510 }
1511 }
1512
1513 VOID
1514 STDCALL
1515 STATIC
1516 VideoPortDeferredRoutine ( IN PKDPC Dpc,
1517 IN PVOID DeferredContext,
1518 IN PVOID SystemArgument1,
1519 IN PVOID SystemArgument2 )
1520 {
1521 PVOID HwDeviceExtension =
1522 ((PVIDEO_PORT_DEVICE_EXTENSION)DeferredContext)->MiniPortDeviceExtension;
1523 ((PMINIPORT_DPC_ROUTINE)SystemArgument1)(HwDeviceExtension, SystemArgument2);
1524 }
1525
1526 BOOLEAN
1527 STDCALL
1528 VideoPortQueueDpc ( IN PVOID HwDeviceExtension,
1529 IN PMINIPORT_DPC_ROUTINE CallbackRoutine,
1530 IN PVOID Context )
1531 {
1532 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1533
1534 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
1535 VIDEO_PORT_DEVICE_EXTENSION,
1536 MiniPortDeviceExtension);
1537 return KeInsertQueueDpc(&DeviceExtension->DpcObject,
1538 (PVOID)CallbackRoutine,
1539 (PVOID)Context);
1540 }
1541
1542 PVOID
1543 STDCALL
1544 VideoPortGetAssociatedDeviceExtension ( IN PVOID DeviceObject )
1545 {
1546 DPRINT1("VideoPortGetAssociatedDeviceExtension(): Unimplemented.\n");
1547 return(NULL);
1548 }
1549
1550 PVOID
1551 STDCALL
1552 VideoPortAllocateCommonBuffer ( IN PVOID HwDeviceExtension,
1553 IN PVP_DMA_ADAPTER VpDmaAdapter,
1554 IN ULONG DesiredLength,
1555 OUT PPHYSICAL_ADDRESS LogicalAddress,
1556 IN BOOLEAN CacheEnabled,
1557 PVOID Reserved )
1558 {
1559 return HalAllocateCommonBuffer((PADAPTER_OBJECT)VpDmaAdapter,
1560 DesiredLength,
1561 LogicalAddress,
1562 CacheEnabled);
1563 }
1564
1565 VOID
1566 STDCALL
1567 VideoPortReleaseCommonBuffer ( IN PVOID HwDeviceExtension,
1568 IN PVP_DMA_ADAPTER VpDmaAdapter,
1569 IN ULONG Length,
1570 IN PHYSICAL_ADDRESS LogicalAddress,
1571 IN PVOID VirtualAddress,
1572 IN BOOLEAN CacheEnabled )
1573 {
1574 HalFreeCommonBuffer((PADAPTER_OBJECT)VpDmaAdapter,
1575 Length,
1576 LogicalAddress,
1577 VirtualAddress,
1578 CacheEnabled);
1579 }
1580
1581 VP_STATUS
1582 STDCALL
1583 VideoPortCreateSecondaryDisplay ( IN PVOID HwDeviceExtension,
1584 IN OUT PVOID *SecondaryDeviceExtension,
1585 IN ULONG Flag )
1586 {
1587 DPRINT1("VideoPortCreateSecondaryDisplay(): Unimplemented.\n");
1588 return STATUS_UNSUCCESSFUL;
1589 }
1590
1591 VOID
1592 STDCALL
1593 VideoPortPutDmaAdapter ( IN PVOID HwDeviceExtension,
1594 IN PVP_DMA_ADAPTER VpDmaAdapter )
1595 {
1596 DPRINT("VideoPortPutDmaAdapter(): Unimplemented.\n");
1597 }
1598
1599 PVP_DMA_ADAPTER
1600 STDCALL
1601 VideoPortGetDmaAdapter ( IN PVOID HwDeviceExtension,
1602 IN PVP_DEVICE_DESCRIPTION VpDeviceExtension )
1603 {
1604 DEVICE_DESCRIPTION DeviceDescription;
1605 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1606 ULONG NumberOfMapRegisters;
1607 PVP_DMA_ADAPTER Adapter;
1608
1609 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
1610 VIDEO_PORT_DEVICE_EXTENSION,
1611 MiniPortDeviceExtension);
1612
1613 DPRINT("VideoPortGetDmaAdapter()\n");
1614
1615 DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
1616 DeviceDescription.Master = TRUE /* ?? */;
1617 DeviceDescription.ScatterGather = VpDeviceExtension->ScatterGather;
1618 DeviceDescription.DemandMode = FALSE /* ?? */;
1619 DeviceDescription.AutoInitialize = FALSE /* ?? */;
1620 DeviceDescription.Dma32BitAddresses = VpDeviceExtension->Dma32BitAddresses;
1621 DeviceDescription.IgnoreCount = FALSE /* ?? */;
1622 DeviceDescription.Reserved1 = FALSE;
1623 DeviceDescription.BusNumber = DeviceExtension->SystemIoBusNumber;
1624 DeviceDescription.DmaChannel = 0 /* ?? */;
1625 DeviceDescription.InterfaceType = DeviceExtension->AdapterInterfaceType;
1626 DeviceDescription.DmaWidth = Width8Bits;
1627 DeviceDescription.DmaSpeed = Compatible;
1628 DeviceDescription.MaximumLength = VpDeviceExtension->MaximumLength;
1629 DeviceDescription.DmaPort = 0;
1630
1631 Adapter =
1632 (PVP_DMA_ADAPTER)HalGetAdapter(&DeviceDescription, &NumberOfMapRegisters);
1633 DPRINT("Adapter %X\n", Adapter);
1634 return(Adapter);
1635 }
1636
1637
1638 /*
1639 * @implemented
1640 */
1641 VP_STATUS
1642 STDCALL
1643 VideoPortGetVersion ( IN PVOID HwDeviceExtension,
1644 IN OUT PVPOSVERSIONINFO VpOsVersionInfo )
1645 {
1646 RTL_OSVERSIONINFOEXW Version;
1647
1648 Version.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
1649 if (VpOsVersionInfo->Size >= sizeof(VPOSVERSIONINFO))
1650 {
1651 #if 1
1652 if (NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&Version)))
1653 {
1654 VpOsVersionInfo->MajorVersion = Version.dwMajorVersion;
1655 VpOsVersionInfo->MinorVersion = Version.dwMinorVersion;
1656 VpOsVersionInfo->BuildNumber = Version.dwBuildNumber;
1657 VpOsVersionInfo->ServicePackMajor = Version.wServicePackMajor;
1658 VpOsVersionInfo->ServicePackMinor = Version.wServicePackMinor;
1659 return STATUS_SUCCESS;
1660 }
1661 return STATUS_UNSUCCESSFUL;
1662 #else
1663 VpOsVersionInfo->MajorVersion = 5;
1664 VpOsVersionInfo->MinorVersion = 0;
1665 VpOsVersionInfo->BuildNumber = 2195;
1666 VpOsVersionInfo->ServicePackMajor = 4;
1667 VpOsVersionInfo->ServicePackMinor = 0;
1668 return(STATUS_SUCCESS);
1669 #endif
1670 }
1671
1672 return ERROR_INVALID_PARAMETER;
1673 }
1674
1675 PVOID
1676 STDCALL
1677 VideoPortLockBuffer ( IN PVOID HwDeviceExtension,
1678 IN PVOID BaseAddress,
1679 IN ULONG Length,
1680 IN VP_LOCK_OPERATION Operation )
1681 {
1682 DPRINT1("VideoPortLockBuffer(): Unimplemented.\n");
1683 return NULL;
1684 }
1685
1686 VOID
1687 STDCALL
1688 VideoPortUnlockBuffer ( IN PVOID HwDeviceExtension,
1689 IN PVOID Mdl )
1690 {
1691 DPRINT1("VideoPortUnlockBuffer(): Unimplemented.\n");
1692 }
1693
1694 VP_STATUS
1695 STDCALL
1696 VideoPortCreateEvent ( IN PVOID HwDeviceExtension,
1697 IN ULONG EventFlag,
1698 IN PVOID Unused,
1699 OUT PEVENT *Event)
1700 {
1701 EVENT_TYPE Type;
1702 (*Event) = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT),
1703 TAG_VIDEO_PORT);
1704 if ((*Event) == NULL)
1705 {
1706 return STATUS_NO_MEMORY;
1707 }
1708 if (EventFlag & NOTIFICATION_EVENT)
1709 {
1710 Type = NotificationEvent;
1711 }
1712 else
1713 {
1714 Type = SynchronizationEvent;
1715 }
1716 KeInitializeEvent((PKEVENT)*Event, Type, EventFlag & INITIAL_EVENT_SIGNALED);
1717 return STATUS_SUCCESS;
1718 }
1719
1720 VP_STATUS
1721 STDCALL
1722 VideoPortDeleteEvent ( IN PVOID HwDeviceExtension,
1723 IN PEVENT Event)
1724 {
1725 ExFreePool(Event);
1726 return STATUS_SUCCESS;
1727 }
1728
1729 LONG
1730 STDCALL
1731 VideoPortSetEvent ( IN PVOID HwDeviceExtension,
1732 IN PEVENT Event )
1733 {
1734 return KeSetEvent((PKEVENT)Event, IO_NO_INCREMENT, FALSE);
1735 }
1736
1737 VOID
1738 STDCALL
1739 VideoPortClearEvent ( IN PVOID HwDeviceExtension,
1740 IN PEVENT Event )
1741 {
1742 KeClearEvent((PKEVENT)Event);
1743 }
1744
1745 VP_STATUS
1746 STDCALL
1747 VideoPortWaitForSingleObject ( IN PVOID HwDeviceExtension,
1748 IN PVOID Object,
1749 IN PLARGE_INTEGER Timeout OPTIONAL )
1750 {
1751 return KeWaitForSingleObject(Object,
1752 Executive,
1753 KernelMode,
1754 FALSE,
1755 Timeout);
1756 }
1757
1758 BOOLEAN
1759 STDCALL
1760 VideoPortCheckForDeviceExistence ( IN PVOID HwDeviceExtension,
1761 IN USHORT VendorId,
1762 IN USHORT DeviceId,
1763 IN UCHAR RevisionId,
1764 IN USHORT SubVendorId,
1765 IN USHORT SubSystemId,
1766 IN ULONG Flags )
1767 {
1768 DPRINT1("VideoPortCheckForDeviceExistence(): Unimplemented.\n");
1769 return TRUE;
1770 }
1771
1772 VP_STATUS
1773 STDCALL
1774 VideoPortRegisterBugcheckCallback ( IN PVOID HwDeviceExtension,
1775 IN ULONG BugcheckCode,
1776 IN PVOID Callback,
1777 IN ULONG BugcheckDataSize )
1778 {
1779 DPRINT1("VideoPortRegisterBugcheckCallback(): Unimplemented.\n");
1780 return STATUS_UNSUCCESSFUL;
1781 }
1782
1783 PVOID
1784 STDCALL
1785 VideoPortImageDirectoryEntryToData ( PVOID BaseAddress,
1786 ULONG Directory )
1787 {
1788 PIMAGE_NT_HEADERS NtHeader;
1789 ULONG Va;
1790
1791 NtHeader = RtlImageNtHeader (BaseAddress);
1792 if (NtHeader == NULL)
1793 return NULL;
1794
1795 if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes)
1796 return NULL;
1797
1798 Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress;
1799 if (Va == 0)
1800 return NULL;
1801
1802 return (PVOID)(BaseAddress + Va);
1803 }
1804
1805 PVOID STDCALL
1806 VideoPortGetProcAddress(IN PVOID HwDeviceExtension,
1807 IN PUCHAR FunctionName)
1808 {
1809 SYSTEM_LOAD_IMAGE GdiDriverInfo;
1810 PVOID BaseAddress;
1811 PIMAGE_EXPORT_DIRECTORY ExportDir;
1812 PUSHORT OrdinalPtr;
1813 PULONG NamePtr;
1814 PULONG AddressPtr;
1815 ULONG i = 0;
1816 NTSTATUS Status;
1817
1818 DPRINT("VideoPortGetProcAddress(%s)\n", FunctionName);
1819
1820 RtlInitUnicodeString(&GdiDriverInfo.ModuleName, L"videoprt");
1821 Status = ZwSetSystemInformation(SystemLoadImage, &GdiDriverInfo,
1822 sizeof(SYSTEM_LOAD_IMAGE));
1823 if (!NT_SUCCESS(Status))
1824 {
1825 DPRINT("Couldn't get our own module handle?\n");
1826 return NULL;
1827 }
1828
1829 BaseAddress = GdiDriverInfo.ModuleBase;
1830
1831 /* Get the pointer to the export directory */
1832 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1833 VideoPortImageDirectoryEntryToData (BaseAddress,
1834 IMAGE_DIRECTORY_ENTRY_EXPORT);
1835
1836 /* search by name */
1837 AddressPtr = (PULONG)
1838 ((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfFunctions);
1839 OrdinalPtr = (PUSHORT)
1840 ((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfNameOrdinals);
1841 NamePtr = (PULONG)
1842 ((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfNames);
1843 for (i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++)
1844 {
1845 if (!_strnicmp(FunctionName, (char*)(BaseAddress + *NamePtr),
1846 strlen(FunctionName)))
1847 {
1848 return (PVOID)((ULONG_PTR)BaseAddress +
1849 (ULONG_PTR)AddressPtr[*OrdinalPtr]);
1850 }
1851 }
1852 DPRINT("VideoPortGetProcAddress: Can't resolve symbol %s\n", FunctionName);
1853 return(NULL);
1854 }
1855
1856 LONGLONG STDCALL
1857 VideoPortQueryPerformanceCounter(
1858 IN PVOID HwDeviceExtension,
1859 OUT PLONGLONG PerformanceFrequency OPTIONAL)
1860 {
1861 LARGE_INTEGER Result;
1862
1863 DPRINT("VideoPortQueryPerformanceCounter\n");
1864 Result = KeQueryPerformanceCounter((PLARGE_INTEGER)PerformanceFrequency);
1865 return Result.QuadPart;
1866 }
1867