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