update for HEAD-2003050101
[reactos.git] / drivers / dd / videoprt / videoprt.c
1 /* $Id$
2  *
3  * VideoPort driver
4  *   Written by Rex Jolliff
5  *
6  */
7
8 #include <errors.h>
9 #include <ddk/ntddk.h>
10 #include <ddk/ntddvid.h>
11
12 #include "../../../ntoskrnl/include/internal/v86m.h"
13
14 #define NDEBUG
15 #include <debug.h>
16
17 #define VERSION "0.0.0"
18
19 #define TAG_VIDEO_PORT  TAG('V', 'I', 'D', 'P')
20
21 typedef struct _VIDEO_PORT_ADDRESS_MAPPING
22 {
23   LIST_ENTRY List;
24
25   PVOID MappedAddress;
26   ULONG NumberOfUchars;
27   PHYSICAL_ADDRESS IoAddress;
28   ULONG SystemIoBusNumber;
29   UINT MappingCount;
30 } VIDEO_PORT_ADDRESS_MAPPING, *PVIDEO_PORT_ADDRESS_MAPPING;
31
32 typedef struct _VIDEO_PORT_DEVICE_EXTENSTION
33 {
34   PDEVICE_OBJECT  DeviceObject;
35   PKINTERRUPT  InterruptObject;
36   KSPIN_LOCK  InterruptSpinLock;
37   ULONG  InterruptLevel;
38   KIRQL  IRQL;
39   KAFFINITY  Affinity;
40   PVIDEO_HW_INITIALIZE HwInitialize;
41   LIST_ENTRY AddressMappingListHead;
42   INTERFACE_TYPE AdapterInterfaceType;
43   ULONG SystemIoBusNumber;
44   UNICODE_STRING RegistryPath;
45
46   UCHAR MiniPortDeviceExtension[1]; /* must be the last entry */
47 } VIDEO_PORT_DEVICE_EXTENSION, *PVIDEO_PORT_DEVICE_EXTENSION;
48
49
50 static VOID STDCALL VidStartIo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
51 static NTSTATUS STDCALL VidDispatchOpenClose(IN PDEVICE_OBJECT pDO, IN PIRP Irp);
52 static NTSTATUS STDCALL VidDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
53 static PVOID STDCALL InternalMapMemory(IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,
54                                        IN PHYSICAL_ADDRESS  IoAddress,
55                                        IN ULONG NumberOfUchars,
56                                        IN UCHAR InIoSpace);
57 static VOID STDCALL InternalUnmapMemory(IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,
58                                         IN PVOID MappedAddress);
59
60 static BOOLEAN CsrssInitialized = FALSE;
61 static HANDLE CsrssHandle = 0;
62 static struct _EPROCESS* Csrss = NULL;
63
64 PBYTE ReturnCsrssAddress(void)
65 {
66   DPRINT("ReturnCsrssAddress()\n");
67   return (PBYTE)Csrss;
68 }
69
70 //  -------------------------------------------------------  Public Interface
71
72 //    DriverEntry
73 //
74 //  DESCRIPTION:
75 //    This function initializes the driver.
76 //
77 //  RUN LEVEL:
78 //    PASSIVE_LEVEL
79 //
80 //  ARGUMENTS:
81 //    IN  PDRIVER_OBJECT   DriverObject  System allocated Driver Object
82 //                                       for this driver
83 //    IN  PUNICODE_STRING  RegistryPath  Name of registry driver service 
84 //                                       key
85 //
86 //  RETURNS:
87 //    NTSTATUS  
88
89 STDCALL NTSTATUS
90 DriverEntry(IN PDRIVER_OBJECT DriverObject,
91             IN PUNICODE_STRING RegistryPath)
92 {
93   DPRINT("DriverEntry()\n");
94   return(STATUS_SUCCESS);
95 }
96
97 VOID
98 VideoPortDebugPrint(IN ULONG DebugPrintLevel,
99                     IN PCHAR DebugMessage, ...)
100 {
101         char Buffer[256];
102         va_list ap;
103
104 /*
105         if (DebugPrintLevel > InternalDebugLevel)
106                 return;
107 */
108         va_start (ap, DebugMessage);
109         vsprintf (Buffer, DebugMessage, ap);
110         va_end (ap);
111
112         DbgPrint (Buffer);
113 }
114
115 VP_STATUS 
116 STDCALL
117 VideoPortDisableInterrupt(IN PVOID  HwDeviceExtension)
118 {
119   DPRINT("VideoPortDisableInterrupt\n");
120   UNIMPLEMENTED;
121 }
122
123 VP_STATUS 
124 STDCALL
125 VideoPortEnableInterrupt(IN PVOID  HwDeviceExtension)
126 {
127   DPRINT("VideoPortEnableInterrupt\n");
128   UNIMPLEMENTED;
129 }
130
131 VOID 
132 STDCALL
133 VideoPortFreeDeviceBase(IN PVOID  HwDeviceExtension, 
134                         IN PVOID  MappedAddress)
135 {
136   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
137
138   DPRINT("VideoPortFreeDeviceBase\n");
139
140   DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
141                                       VIDEO_PORT_DEVICE_EXTENSION,
142                                       MiniPortDeviceExtension);
143
144   InternalUnmapMemory(DeviceExtension, MappedAddress);
145 }
146
147 ULONG 
148 STDCALL
149 VideoPortGetBusData(IN PVOID  HwDeviceExtension,
150                     IN BUS_DATA_TYPE  BusDataType,
151                     IN ULONG  SlotNumber,
152                     OUT PVOID  Buffer,
153                     IN ULONG  Offset,
154                     IN ULONG  Length)
155 {
156   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
157
158   DPRINT("VideoPortGetBusData\n");
159
160   DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
161                                       VIDEO_PORT_DEVICE_EXTENSION,
162                                       MiniPortDeviceExtension);
163
164   return HalGetBusDataByOffset(BusDataType, 
165                                DeviceExtension->SystemIoBusNumber, 
166                                SlotNumber, 
167                                Buffer, 
168                                Offset, 
169                                Length);
170 }
171
172 UCHAR 
173 STDCALL
174 VideoPortGetCurrentIrql(VOID)
175 {
176   DPRINT("VideoPortGetCurrentIrql\n");
177   return KeGetCurrentIrql();
178 }
179
180 PVOID 
181 STDCALL
182 VideoPortGetDeviceBase(IN PVOID  HwDeviceExtension,
183                        IN PHYSICAL_ADDRESS  IoAddress,
184                        IN ULONG  NumberOfUchars,
185                        IN UCHAR  InIoSpace)
186 {
187   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
188
189   DPRINT("VideoPortGetDeviceBase\n");
190
191   DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
192                                       VIDEO_PORT_DEVICE_EXTENSION,
193                                       MiniPortDeviceExtension);
194
195   return InternalMapMemory(DeviceExtension, IoAddress, NumberOfUchars, InIoSpace);
196 }
197
198 VP_STATUS 
199 STDCALL
200 VideoPortGetDeviceData(IN PVOID  HwDeviceExtension,
201                        IN VIDEO_DEVICE_DATA_TYPE  DeviceDataType,
202                        IN PMINIPORT_QUERY_DEVICE_ROUTINE  CallbackRoutine,
203                        IN PVOID Context)
204 {
205   DPRINT("VideoPortGetDeviceData\n");
206   UNIMPLEMENTED;
207 }
208
209 VP_STATUS 
210 STDCALL
211 VideoPortGetAccessRanges(IN PVOID  HwDeviceExtension,
212                          IN ULONG  NumRequestedResources,
213                          IN PIO_RESOURCE_DESCRIPTOR  RequestedResources OPTIONAL,
214                          IN ULONG  NumAccessRanges,
215                          IN PVIDEO_ACCESS_RANGE  AccessRanges,
216                          IN PVOID  VendorId,
217                          IN PVOID  DeviceId,
218                          IN PULONG  Slot)
219 {
220   PCI_SLOT_NUMBER PciSlotNumber;
221   BOOLEAN FoundDevice;
222   ULONG FunctionNumber;
223   PCI_COMMON_CONFIG Config;
224   PCM_RESOURCE_LIST AllocatedResources;
225   NTSTATUS Status;
226   UINT AssignedCount;
227   CM_FULL_RESOURCE_DESCRIPTOR *FullList;
228   CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
229   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
230
231   DPRINT("VideoPortGetAccessRanges\n");
232
233   DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
234                                       VIDEO_PORT_DEVICE_EXTENSION,
235                                       MiniPortDeviceExtension);
236
237   if (0 == NumRequestedResources && PCIBus == DeviceExtension->AdapterInterfaceType)
238     {
239       DPRINT("Looking for VendorId 0x%04x DeviceId 0x%04x\n", (int)*((USHORT *) VendorId),
240              (int)*((USHORT *) DeviceId));
241       FoundDevice = FALSE;
242       PciSlotNumber.u.AsULONG = *Slot;
243       for (FunctionNumber = 0; ! FoundDevice && FunctionNumber < 8; FunctionNumber++)
244         {
245           PciSlotNumber.u.bits.FunctionNumber = FunctionNumber;
246           if (sizeof(PCI_COMMON_CONFIG) ==
247               HalGetBusDataByOffset(PCIConfiguration, DeviceExtension->SystemIoBusNumber,
248                                     PciSlotNumber.u.AsULONG,&Config, 0,
249                                     sizeof(PCI_COMMON_CONFIG)))
250             {
251               DPRINT("Slot 0x%02x (Device %d Function %d) VendorId 0x%04x DeviceId 0x%04x\n",
252                      PciSlotNumber.u.AsULONG, PciSlotNumber.u.bits.DeviceNumber,
253                      PciSlotNumber.u.bits.FunctionNumber, Config.VendorID, Config.DeviceID);
254               FoundDevice = (Config.VendorID == *((USHORT *) VendorId) &&
255                              Config.DeviceID == *((USHORT *) DeviceId));
256             }
257         }
258       if (! FoundDevice)
259         {
260           return STATUS_UNSUCCESSFUL;
261         }
262       Status = HalAssignSlotResources(NULL, NULL, NULL, NULL,
263                                       DeviceExtension->AdapterInterfaceType,
264                                       DeviceExtension->SystemIoBusNumber,
265                                       PciSlotNumber.u.AsULONG, &AllocatedResources);
266       if (! NT_SUCCESS(Status))
267         {
268           return Status;
269         }
270       AssignedCount = 0;
271       for (FullList = AllocatedResources->List;
272            FullList < AllocatedResources->List + AllocatedResources->Count &&
273            AssignedCount < NumAccessRanges;
274            FullList++)
275         {
276           assert(FullList->InterfaceType == PCIBus &&
277                  FullList->BusNumber == DeviceExtension->SystemIoBusNumber &&
278                  1 == FullList->PartialResourceList.Version &&
279                  1 == FullList->PartialResourceList.Revision);
280           for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
281                Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count &&
282                AssignedCount < NumAccessRanges;
283                Descriptor++)
284             {
285               if (CmResourceTypeMemory == Descriptor->Type)
286                 {
287                   DPRINT("Memory range starting at 0x%08x length 0x%08x\n",
288                          Descriptor->u.Memory.Start.u.LowPart, Descriptor->u.Memory.Length);
289                   AccessRanges[AssignedCount].RangeStart = Descriptor->u.Memory.Start;
290                   AccessRanges[AssignedCount].RangeLength = Descriptor->u.Memory.Length;
291                   AccessRanges[AssignedCount].RangeInIoSpace = 0;
292                   AccessRanges[AssignedCount].RangeVisible = 0; /* FIXME: Just guessing */
293                   AccessRanges[AssignedCount].RangeShareable =
294                     (CmResourceShareShared == Descriptor->ShareDisposition);
295                 }
296               else if (CmResourceTypePort == Descriptor->Type)
297                 {
298                   DPRINT("Port range starting at 0x%04x length %d\n",
299                          Descriptor->u.Memory.Start.u.LowPart, Descriptor->u.Memory.Length);
300                   AccessRanges[AssignedCount].RangeStart = Descriptor->u.Port.Start;
301                   AccessRanges[AssignedCount].RangeLength = Descriptor->u.Port.Length;
302                   AccessRanges[AssignedCount].RangeInIoSpace = 1;
303                   AccessRanges[AssignedCount].RangeVisible = 0; /* FIXME: Just guessing */
304                   AccessRanges[AssignedCount].RangeShareable = 0;
305                 }
306               else
307                 {
308                   ExFreePool(AllocatedResources);
309                   return STATUS_UNSUCCESSFUL;
310                 }
311               AssignedCount++;
312             }
313         }
314       ExFreePool(AllocatedResources);
315     }
316   else
317     {
318     UNIMPLEMENTED
319     }
320
321   return STATUS_SUCCESS;
322 }
323
324 VP_STATUS 
325 STDCALL
326 VideoPortGetRegistryParameters(IN PVOID  HwDeviceExtension,
327                                IN PWSTR  ParameterName,
328                                IN UCHAR  IsParameterFileName,
329                                IN PMINIPORT_GET_REGISTRY_ROUTINE  GetRegistryRoutine,
330                                IN PVOID  Context)
331 {
332   DPRINT("VideoPortGetRegistryParameters\n");
333   DPRINT("ParameterName %S\n", ParameterName);
334   return STATUS_OBJECT_NAME_NOT_FOUND;
335 /*
336   return NO_ERROR;
337 */
338 }
339
340 ULONG STDCALL
341 VideoPortInitialize(IN PVOID  Context1,
342                     IN PVOID  Context2,
343                     IN PVIDEO_HW_INITIALIZATION_DATA  HwInitializationData,
344                     IN PVOID  HwContext)
345 {
346   PUNICODE_STRING RegistryPath;
347   UCHAR  Again;
348   WCHAR  DeviceBuffer[20];
349   WCHAR  SymlinkBuffer[20];
350   WCHAR  DeviceVideoBuffer[20];
351   NTSTATUS  Status;
352   PDRIVER_OBJECT  MPDriverObject = (PDRIVER_OBJECT) Context1;
353   PDEVICE_OBJECT  MPDeviceObject;
354   VIDEO_PORT_CONFIG_INFO  ConfigInfo;
355   PVIDEO_PORT_DEVICE_EXTENSION  DeviceExtension;
356   ULONG DeviceNumber = 0;
357   UNICODE_STRING DeviceName;
358   UNICODE_STRING SymlinkName;
359   ULONG MaxBus;
360   ULONG MaxLen;
361
362   DPRINT("VideoPortInitialize\n");
363
364   RegistryPath = (PUNICODE_STRING) Context2;
365
366   /*  Build Dispatch table from passed data  */
367   MPDriverObject->DriverStartIo = (PDRIVER_STARTIO) HwInitializationData->HwStartIO;
368
369   /*  Create a unicode device name  */
370   Again = FALSE;
371   do
372     {
373       swprintf(DeviceBuffer, L"\\Device\\Video%lu", DeviceNumber);
374       RtlInitUnicodeString(&DeviceName, DeviceBuffer);
375
376       /*  Create the device  */
377       Status = IoCreateDevice(MPDriverObject,
378                               HwInitializationData->HwDeviceExtensionSize +
379                                 sizeof(VIDEO_PORT_DEVICE_EXTENSION),
380                               &DeviceName,
381                               FILE_DEVICE_VIDEO,
382                               0,
383                               TRUE,
384                               &MPDeviceObject);
385       if (!NT_SUCCESS(Status))
386         {
387           DPRINT("IoCreateDevice call failed with status 0x%08x\n", Status);
388           return Status;
389         }
390
391       MPDriverObject->DeviceObject = MPDeviceObject;
392
393       /* Initialize the miniport drivers dispatch table */
394       MPDriverObject->MajorFunction[IRP_MJ_CREATE] = VidDispatchOpenClose;
395       MPDriverObject->MajorFunction[IRP_MJ_CLOSE] = VidDispatchOpenClose;
396       MPDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VidDispatchDeviceControl;
397
398       /* Initialize our device extension */
399       DeviceExtension = 
400         (PVIDEO_PORT_DEVICE_EXTENSION) MPDeviceObject->DeviceExtension;
401       DeviceExtension->DeviceObject = MPDeviceObject;
402       DeviceExtension->HwInitialize = HwInitializationData->HwInitialize;
403       DeviceExtension->AdapterInterfaceType = HwInitializationData->AdapterInterfaceType;
404       DeviceExtension->SystemIoBusNumber = 0;
405       MaxLen = (wcslen(RegistryPath->Buffer) + 10) * sizeof(WCHAR);
406       DeviceExtension->RegistryPath.MaximumLength = MaxLen;
407       DeviceExtension->RegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
408                                                                    MaxLen,
409                                                                    TAG_VIDEO_PORT);
410       swprintf(DeviceExtension->RegistryPath.Buffer, L"%s\\Device%d",
411                RegistryPath->Buffer, DeviceNumber);
412       DeviceExtension->RegistryPath.Length = wcslen(DeviceExtension->RegistryPath.Buffer) *
413                                              sizeof(WCHAR);
414
415       MaxBus = (DeviceExtension->AdapterInterfaceType == PCIBus) ? 8 : 1;
416       DPRINT("MaxBus: %lu\n", MaxBus);
417       InitializeListHead(&DeviceExtension->AddressMappingListHead);
418       
419       /*  Set the buffering strategy here...  */
420       /*  If you change this, remember to change VidDispatchDeviceControl too */
421       MPDeviceObject->Flags |= DO_BUFFERED_IO;
422
423       do
424         {
425           RtlZeroMemory(&DeviceExtension->MiniPortDeviceExtension, 
426                         HwInitializationData->HwDeviceExtensionSize);
427           DPRINT("Searching on bus %d\n", DeviceExtension->SystemIoBusNumber);
428           /* Setup configuration info */
429           RtlZeroMemory(&ConfigInfo, sizeof(VIDEO_PORT_CONFIG_INFO));
430           ConfigInfo.Length = sizeof(VIDEO_PORT_CONFIG_INFO);
431           ConfigInfo.AdapterInterfaceType = DeviceExtension->AdapterInterfaceType;
432           ConfigInfo.SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
433           ConfigInfo.InterruptMode = (PCIBus == DeviceExtension->AdapterInterfaceType) ?
434                                       LevelSensitive : Latched;
435
436           /*  Call HwFindAdapter entry point  */
437           /* FIXME: Need to figure out what string to pass as param 3  */
438           Status = HwInitializationData->HwFindAdapter(&DeviceExtension->MiniPortDeviceExtension,
439                                                        Context2,
440                                                        NULL,
441                                                        &ConfigInfo,
442                                                        &Again);
443           if (NO_ERROR != Status)
444             {
445               DPRINT("HwFindAdapter call failed with error %d\n", Status);
446               DeviceExtension->SystemIoBusNumber++;
447             }
448         }
449       while (NO_ERROR != Status && DeviceExtension->SystemIoBusNumber < MaxBus);
450
451       if (NO_ERROR != Status)
452         {
453           RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
454           IoDeleteDevice(MPDeviceObject);
455
456           return  Status;
457         }
458       DPRINT("Found adapter\n");
459
460       /* create symbolic link "\??\DISPLAYx" */
461       swprintf(SymlinkBuffer, L"\\??\\DISPLAY%lu", DeviceNumber+1);
462       RtlInitUnicodeString (&SymlinkName,
463                             SymlinkBuffer);
464       IoCreateSymbolicLink (&SymlinkName,
465                             &DeviceName);
466
467       /* Add entry to DEVICEMAP\VIDEO key in registry */
468       swprintf(DeviceVideoBuffer, L"\\Device\\Video%d", DeviceNumber);
469       RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP,
470                             L"VIDEO",
471                             DeviceVideoBuffer,
472                             REG_SZ,
473                             DeviceExtension->RegistryPath.Buffer,
474                             DeviceExtension->RegistryPath.Length + sizeof(WCHAR));
475
476       /* FIXME: Allocate hardware resources for device  */
477
478       /*  Allocate interrupt for device  */
479       if (HwInitializationData->HwInterrupt != NULL &&
480           !(ConfigInfo.BusInterruptLevel == 0 &&
481             ConfigInfo.BusInterruptVector == 0))
482         {
483 #if 0
484           DeviceExtension->IRQL = ConfigInfo.BusInterruptLevel;
485           DeviceExtension->InterruptLevel = 
486             HalGetInterruptVector(ConfigInfo.AdapterInterfaceType,
487                                   ConfigInfo.SystemIoBusNumber,
488                                   ConfigInfo.BusInterruptLevel,
489                                   ConfigInfo.BusInterruptVector,
490                                   &DeviceExtension->IRQL,
491                                   &DeviceExtension->Affinity);
492           KeInitializeSpinLock(&DeviceExtension->InterruptSpinLock);
493           Status = IoConnectInterrupt(&DeviceExtension->InterruptObject,
494                                       (PKSERVICE_ROUTINE)
495                                         HwInitializationData->HwInterrupt,
496                                       &DeviceExtension->MiniPortDeviceExtension,
497                                       &DeviceExtension->InterruptSpinLock,
498                                       DeviceExtension->InterruptLevel,
499                                       DeviceExtension->IRQL,
500                                       DeviceExtension->IRQL,
501                                       ConfigInfo.InterruptMode,
502                                       FALSE,
503                                       DeviceExtension->Affinity,
504                                       FALSE);
505           if (!NT_SUCCESS(Status))
506             {
507               DPRINT("IoConnectInterrupt failed with status 0x%08x\n", Status);
508               IoDeleteDevice(MPDeviceObject);
509               
510               return Status;
511             }
512 #endif
513         }
514       DeviceNumber++;
515     }
516   while (Again);
517
518   /* FIXME: initialize timer routine for MP Driver  */
519   if (HwInitializationData->HwTimer != NULL)
520     {
521       Status = IoInitializeTimer(MPDeviceObject,
522                                  (PIO_TIMER_ROUTINE)
523                                    HwInitializationData->HwTimer,
524                                  &DeviceExtension->MiniPortDeviceExtension);
525       if (!NT_SUCCESS(Status))
526         {
527           DPRINT("IoInitializeTimer failed with status 0x%08x\n", Status);
528           
529           if (HwInitializationData->HwInterrupt != NULL)
530             {
531               IoDisconnectInterrupt(DeviceExtension->InterruptObject);
532             }
533           IoDeleteDevice(MPDeviceObject);
534           
535           return Status;
536         }
537     }
538
539   return  STATUS_SUCCESS;
540 }
541
542 VP_STATUS STDCALL
543 VideoPortInt10(IN PVOID  HwDeviceExtension,
544                IN PVIDEO_X86_BIOS_ARGUMENTS  BiosArguments)
545 {
546   KV86M_REGISTERS Regs;
547   NTSTATUS Status;
548
549   DPRINT("VideoPortInt10\n");
550   KeAttachProcess(Csrss);
551
552   memset(&Regs, 0, sizeof(Regs));
553   Regs.Eax = BiosArguments->Eax;
554   Regs.Ebx = BiosArguments->Ebx;
555   Regs.Ecx = BiosArguments->Ecx;
556   Regs.Edx = BiosArguments->Edx;
557   Regs.Esi = BiosArguments->Esi;
558   Regs.Edi = BiosArguments->Edi;
559   Regs.Ebp = BiosArguments->Ebp;
560   Status = Ke386CallBios(0x10, &Regs);
561
562   KeDetachProcess();
563
564   return(Status);
565 }
566
567 VOID 
568 STDCALL
569 VideoPortLogError(IN PVOID  HwDeviceExtension,
570                   IN PVIDEO_REQUEST_PACKET  Vrp OPTIONAL,
571                   IN VP_STATUS  ErrorCode,
572                   IN ULONG  UniqueId)
573 {
574   DPRINT("VideoPortLogError\n");
575   UNIMPLEMENTED;
576 }
577
578 VP_STATUS 
579 STDCALL
580 VideoPortMapBankedMemory(IN PVOID  HwDeviceExtension,
581                          IN PHYSICAL_ADDRESS  PhysicalAddress,
582                          IN PULONG  Length,
583                          IN PULONG  InIoSpace,
584                          OUT PVOID  *VirtualAddress,
585                          IN ULONG  BankLength,
586                          IN UCHAR  ReadWriteBank,
587                          IN PBANKED_SECTION_ROUTINE  BankRoutine,
588                          IN PVOID  Context)
589 {
590   DPRINT("VideoPortMapBankedMemory\n");
591   UNIMPLEMENTED;
592 }
593
594 VP_STATUS 
595 STDCALL
596 VideoPortMapMemory(IN PVOID  HwDeviceExtension,
597                    IN PHYSICAL_ADDRESS  PhysicalAddress,
598                    IN PULONG  Length,
599                    IN PULONG  InIoSpace,
600                    OUT PVOID  *VirtualAddress)
601 {
602   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
603   PVIDEO_PORT_ADDRESS_MAPPING AddressMapping;
604   PLIST_ENTRY Entry;
605
606   DPRINT("VideoPortMapMemory\n");
607
608   DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
609                                       VIDEO_PORT_DEVICE_EXTENSION,
610                                       MiniPortDeviceExtension);
611   *VirtualAddress = InternalMapMemory(DeviceExtension, PhysicalAddress,
612                                       *Length, *InIoSpace);
613
614   return NULL == *VirtualAddress ? STATUS_NO_MEMORY : STATUS_SUCCESS;
615 }
616
617 UCHAR 
618 STDCALL
619 VideoPortReadPortUchar(IN PUCHAR  Port)
620 {
621   DPRINT("VideoPortReadPortUchar\n");
622   return  READ_PORT_UCHAR(Port);
623 }
624
625 USHORT 
626 STDCALL
627 VideoPortReadPortUshort(IN PUSHORT Port)
628 {
629   DPRINT("VideoPortReadPortUshort\n");
630   return  READ_PORT_USHORT(Port);
631 }
632
633 ULONG 
634 STDCALL
635 VideoPortReadPortUlong(IN PULONG Port)
636 {
637   DPRINT("VideoPortReadPortUlong\n");
638   return  READ_PORT_ULONG(Port);
639 }
640
641 VOID 
642 STDCALL
643 VideoPortReadPortBufferUchar(IN PUCHAR  Port, 
644                              OUT PUCHAR  Buffer, 
645                              IN ULONG  Count)
646 {
647   DPRINT("VideoPortReadPortBufferUchar\n");
648   READ_PORT_BUFFER_UCHAR(Port, Buffer, Count);
649 }
650
651 VOID 
652 STDCALL
653 VideoPortReadPortBufferUshort(IN PUSHORT Port, 
654                               OUT PUSHORT Buffer, 
655                               IN ULONG Count)
656 {
657   DPRINT("VideoPortReadPortBufferUshort\n");
658   READ_PORT_BUFFER_USHORT(Port, Buffer, Count);
659 }
660
661 VOID 
662 STDCALL
663 VideoPortReadPortBufferUlong(IN PULONG Port, 
664                              OUT PULONG Buffer, 
665                              IN ULONG Count)
666 {
667   DPRINT("VideoPortReadPortBufferUlong\n");
668   READ_PORT_BUFFER_ULONG(Port, Buffer, Count);
669 }
670
671 UCHAR 
672 STDCALL
673 VideoPortReadRegisterUchar(IN PUCHAR Register)
674 {
675   DPRINT("VideoPortReadPortRegisterUchar\n");
676   return  READ_REGISTER_UCHAR(Register);
677 }
678
679 USHORT 
680 STDCALL
681 VideoPortReadRegisterUshort(IN PUSHORT Register)
682 {
683   DPRINT("VideoPortReadPortRegisterUshort\n");
684   return  READ_REGISTER_USHORT(Register);
685 }
686
687 ULONG 
688 STDCALL
689 VideoPortReadRegisterUlong(IN PULONG Register)
690 {
691   DPRINT("VideoPortReadPortRegisterUlong\n");
692   return  READ_REGISTER_ULONG(Register);
693 }
694
695 VOID 
696 STDCALL
697 VideoPortReadRegisterBufferUchar(IN PUCHAR  Register, 
698                                  OUT PUCHAR  Buffer, 
699                                  IN ULONG  Count)
700 {
701   DPRINT("VideoPortReadPortRegisterBufferUchar\n");
702   READ_REGISTER_BUFFER_UCHAR(Register, Buffer, Count);
703 }
704
705 VOID 
706 STDCALL
707 VideoPortReadRegisterBufferUshort(IN PUSHORT  Register, 
708                                   OUT PUSHORT  Buffer, 
709                                   IN ULONG  Count)
710 {
711   DPRINT("VideoPortReadPortRegisterBufferUshort\n");
712   READ_REGISTER_BUFFER_USHORT(Register, Buffer, Count);
713 }
714
715 VOID 
716 STDCALL
717 VideoPortReadRegisterBufferUlong(IN PULONG  Register, 
718                                  OUT PULONG  Buffer, 
719                                  IN ULONG  Count)
720 {
721   DPRINT("VideoPortReadPortRegisterBufferUlong\n");
722   READ_REGISTER_BUFFER_ULONG(Register, Buffer, Count);
723 }
724
725 BOOLEAN 
726 STDCALL
727 VideoPortScanRom(IN PVOID  HwDeviceExtension, 
728                  IN PUCHAR  RomBase,
729                  IN ULONG  RomLength,
730                  IN PUCHAR  String)
731 {
732   DPRINT("VideoPortScanRom\n");
733   UNIMPLEMENTED;
734 }
735
736 ULONG 
737 STDCALL
738 VideoPortSetBusData(IN PVOID  HwDeviceExtension,
739                     IN BUS_DATA_TYPE  BusDataType,
740                     IN ULONG  SlotNumber,
741                     IN PVOID  Buffer,
742                     IN ULONG  Offset,
743                     IN ULONG  Length)
744 {
745   DPRINT("VideoPortSetBusData\n");
746   return  HalSetBusDataByOffset(BusDataType,
747                                 0,
748                                 SlotNumber,
749                                 Buffer,
750                                 Offset,
751                                 Length);
752 }
753
754 VP_STATUS 
755 STDCALL
756 VideoPortSetRegistryParameters(IN PVOID  HwDeviceExtension,
757                                IN PWSTR  ValueName,
758                                IN PVOID  ValueData,
759                                IN ULONG  ValueLength)
760 {
761   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
762
763   DPRINT("VideoSetRegistryParameters\n");
764
765   assert_irql(PASSIVE_LEVEL);
766
767   DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
768                                       VIDEO_PORT_DEVICE_EXTENSION,
769                                       MiniPortDeviceExtension);
770   return RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
771                                DeviceExtension->RegistryPath.Buffer,
772                                ValueName,
773                                REG_BINARY,
774                                ValueData,
775                                ValueLength);
776 }
777
778 VP_STATUS 
779 STDCALL
780 VideoPortSetTrappedEmulatorPorts(IN PVOID  HwDeviceExtension,
781                                  IN ULONG  NumAccessRanges,
782                                  IN PVIDEO_ACCESS_RANGE  AccessRange)
783 {
784   DPRINT("VideoPortSetTrappedEmulatorPorts\n");
785   UNIMPLEMENTED;
786 }
787
788 VOID 
789 STDCALL
790 VideoPortStartTimer(IN PVOID  HwDeviceExtension)
791 {
792   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
793
794   DPRINT("VideoPortStartTimer\n");
795
796   DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
797                                       VIDEO_PORT_DEVICE_EXTENSION,
798                                       MiniPortDeviceExtension);
799   IoStartTimer(DeviceExtension->DeviceObject);
800 }
801
802 VOID 
803 STDCALL
804 VideoPortStopTimer(IN PVOID  HwDeviceExtension)
805 {
806   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
807
808   DPRINT("VideoPortStopTimer\n");
809
810   DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
811                                       VIDEO_PORT_DEVICE_EXTENSION,
812                                       MiniPortDeviceExtension);
813   IoStopTimer(DeviceExtension->DeviceObject);
814 }
815
816 BOOLEAN 
817 STDCALL
818 VideoPortSynchronizeExecution(IN PVOID  HwDeviceExtension,
819                               IN VIDEO_SYNCHRONIZE_PRIORITY  Priority,
820                               IN PMINIPORT_SYNCHRONIZE_ROUTINE  SynchronizeRoutine,
821                               OUT PVOID  Context)
822 {
823   DPRINT("VideoPortSynchronizeExecution\n");
824   UNIMPLEMENTED;
825 }
826
827 VP_STATUS 
828 STDCALL
829 VideoPortUnmapMemory(IN PVOID  HwDeviceExtension,
830                      IN PVOID  VirtualAddress,
831                      IN HANDLE  ProcessHandle)
832 {
833   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
834
835   DPRINT("VideoPortFreeDeviceBase\n");
836
837   DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
838                                       VIDEO_PORT_DEVICE_EXTENSION,
839                                       MiniPortDeviceExtension);
840
841   InternalUnmapMemory(DeviceExtension, VirtualAddress);
842
843   return STATUS_SUCCESS;
844 }
845
846 VP_STATUS 
847 STDCALL
848 VideoPortVerifyAccessRanges(IN PVOID  HwDeviceExtension,
849                             IN ULONG  NumAccessRanges,
850                             IN PVIDEO_ACCESS_RANGE  AccessRanges)
851 {
852   DPRINT1("VideoPortVerifyAccessRanges not implemented\n");
853   return NO_ERROR;
854 }
855
856 VOID 
857 STDCALL
858 VideoPortWritePortUchar(IN PUCHAR  Port, 
859                         IN UCHAR  Value)
860 {
861   DPRINT("VideoPortWritePortUchar\n");
862   WRITE_PORT_UCHAR(Port, Value);
863 }
864
865 VOID 
866 STDCALL
867 VideoPortWritePortUshort(IN PUSHORT  Port, 
868                          IN USHORT  Value)
869 {
870   DPRINT("VideoPortWritePortUshort\n");
871   WRITE_PORT_USHORT(Port, Value);
872 }
873
874 VOID 
875 STDCALL
876 VideoPortWritePortUlong(IN PULONG Port, 
877                         IN ULONG Value)
878 {
879   DPRINT("VideoPortWritePortUlong\n");
880   WRITE_PORT_ULONG(Port, Value);
881 }
882
883 VOID 
884 STDCALL
885 VideoPortWritePortBufferUchar(IN PUCHAR  Port, 
886                               IN PUCHAR  Buffer, 
887                               IN ULONG  Count)
888 {
889   DPRINT("VideoPortWritePortBufferUchar\n");
890   WRITE_PORT_BUFFER_UCHAR(Port, Buffer, Count);
891 }
892
893 VOID 
894 STDCALL
895 VideoPortWritePortBufferUshort(IN PUSHORT  Port, 
896                                IN PUSHORT  Buffer, 
897                                IN ULONG  Count)
898 {
899   DPRINT("VideoPortWritePortBufferUshort\n");
900   WRITE_PORT_BUFFER_USHORT(Port, Buffer, Count);
901 }
902
903 VOID 
904 STDCALL
905 VideoPortWritePortBufferUlong(IN PULONG  Port, 
906                               IN PULONG  Buffer, 
907                               IN ULONG  Count)
908 {
909   DPRINT("VideoPortWritePortBufferUlong\n");
910   WRITE_PORT_BUFFER_ULONG(Port, Buffer, Count);
911 }
912
913 VOID 
914 STDCALL
915 VideoPortWriteRegisterUchar(IN PUCHAR  Register, 
916                             IN UCHAR  Value)
917 {
918   DPRINT("VideoPortWriteRegisterUchar\n");
919   WRITE_REGISTER_UCHAR(Register, Value);
920 }
921
922 VOID 
923 STDCALL
924 VideoPortWriteRegisterUshort(IN PUSHORT  Register, 
925                              IN USHORT  Value)
926 {
927   DPRINT("VideoPortWriteRegisterUshort\n");
928   WRITE_REGISTER_USHORT(Register, Value);
929 }
930
931 VOID 
932 STDCALL
933 VideoPortWriteRegisterUlong(IN PULONG  Register, 
934                             IN ULONG  Value)
935 {
936   DPRINT("VideoPortWriteRegisterUlong\n");
937   WRITE_REGISTER_ULONG(Register, Value);
938 }
939
940 VOID 
941 STDCALL
942 VideoPortWriteRegisterBufferUchar(IN PUCHAR  Register, 
943                                   IN PUCHAR  Buffer, 
944                                   IN ULONG  Count)
945 {
946   DPRINT("VideoPortWriteRegisterBufferUchar\n");
947   WRITE_REGISTER_BUFFER_UCHAR(Register, Buffer, Count);
948 }
949
950 VOID STDCALL
951 VideoPortWriteRegisterBufferUshort(IN PUSHORT  Register,
952                                    IN PUSHORT  Buffer,
953                                    IN ULONG  Count)
954 {
955   DPRINT("VideoPortWriteRegisterBufferUshort\n");
956   WRITE_REGISTER_BUFFER_USHORT(Register, Buffer, Count);
957 }
958
959 VOID STDCALL
960 VideoPortWriteRegisterBufferUlong(IN PULONG  Register,
961                                   IN PULONG  Buffer,
962                                   IN ULONG  Count)
963 {
964   DPRINT("VideoPortWriteRegisterBufferUlong\n");
965   WRITE_REGISTER_BUFFER_ULONG(Register, Buffer, Count);
966 }
967
968 VOID STDCALL
969 VideoPortZeroDeviceMemory(OUT PVOID  Destination,
970                           IN ULONG  Length)
971 {
972   DPRINT("VideoPortZeroDeviceMemory\n");
973   RtlZeroMemory(Destination, Length);
974 }
975
976
977 //  -------------------------------------------  Nondiscardable statics
978
979 //    VidDispatchOpenClose
980 //
981 //  DESCRIPTION:
982 //    Answer requests for Open/Close calls: a null operation
983 //
984 //  RUN LEVEL:
985 //    PASSIVE_LEVEL
986 //
987 //  ARGUMENTS:
988 //    Standard dispatch arguments
989 //
990 //  RETURNS:
991 //    NTSTATUS
992 //
993
994 static NTSTATUS STDCALL
995 VidDispatchOpenClose(IN PDEVICE_OBJECT pDO,
996                      IN PIRP Irp)
997 {
998   PIO_STACK_LOCATION IrpStack;
999   PVIDEO_PORT_DEVICE_EXTENSION  DeviceExtension;
1000
1001   DPRINT("VidDispatchOpenClose() called\n");
1002
1003   IrpStack = IoGetCurrentIrpStackLocation(Irp);
1004
1005   if (IrpStack->MajorFunction == IRP_MJ_CREATE &&
1006       CsrssInitialized == FALSE)
1007     {
1008       DPRINT("Referencing CSRSS\n");
1009       Csrss = PsGetCurrentProcess();
1010       CsrssInitialized = TRUE;
1011       DPRINT("Csrss %p\n", Csrss);
1012       DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION) pDO->DeviceExtension;
1013       if (DeviceExtension->HwInitialize(&DeviceExtension->MiniPortDeviceExtension))
1014         {
1015           Irp->IoStatus.Status = STATUS_SUCCESS;
1016         }
1017       else
1018         {
1019           Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1020         }
1021     }
1022   else
1023     {
1024     Irp->IoStatus.Status = STATUS_SUCCESS;
1025     }
1026
1027   Irp->IoStatus.Information = FILE_OPENED;
1028   IoCompleteRequest(Irp, IO_NO_INCREMENT);
1029
1030   return STATUS_SUCCESS;
1031 }
1032
1033 //    VidStartIo
1034 //
1035 //  DESCRIPTION:
1036 //    Get the next requested I/O packet started
1037 //
1038 //  RUN LEVEL:
1039 //    DISPATCH_LEVEL
1040 //
1041 //  ARGUMENTS:
1042 //    Dispatch routine standard arguments
1043 //
1044 //  RETURNS:
1045 //    NTSTATUS
1046 //
1047
1048 static VOID STDCALL
1049 VidStartIo(IN PDEVICE_OBJECT DeviceObject,
1050            IN PIRP Irp)
1051 {
1052   DPRINT("VidStartIo\n");
1053   UNIMPLEMENTED;
1054 }
1055
1056 //    VidDispatchDeviceControl
1057 //
1058 //  DESCRIPTION:
1059 //    Answer requests for device control calls
1060 //
1061 //  RUN LEVEL:
1062 //    PASSIVE_LEVEL
1063 //
1064 //  ARGUMENTS:
1065 //    Standard dispatch arguments
1066 //
1067 //  RETURNS:
1068 //    NTSTATUS
1069 //
1070
1071 static NTSTATUS STDCALL
1072 VidDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,
1073                          IN PIRP Irp)
1074 {
1075   PIO_STACK_LOCATION IrpStack;
1076   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1077   PVIDEO_REQUEST_PACKET vrp;
1078
1079   DPRINT("VidDispatchDeviceControl\n");
1080   IrpStack = IoGetCurrentIrpStackLocation(Irp);
1081   DeviceExtension = DeviceObject->DeviceExtension;
1082
1083   /* Translate the IRP to a VRP */
1084   vrp = ExAllocatePool(PagedPool, sizeof(VIDEO_REQUEST_PACKET));
1085   if (NULL == vrp)
1086     {
1087     return STATUS_NO_MEMORY;
1088     }
1089   vrp->StatusBlock        = (PSTATUS_BLOCK) &(Irp->IoStatus);
1090   vrp->IoControlCode      = IrpStack->Parameters.DeviceIoControl.IoControlCode;
1091
1092   /* We're assuming METHOD_BUFFERED */
1093   vrp->InputBuffer        = Irp->AssociatedIrp.SystemBuffer;
1094   vrp->InputBufferLength  = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
1095   vrp->OutputBuffer       = Irp->AssociatedIrp.SystemBuffer;
1096   vrp->OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
1097
1098   /* Call the Miniport Driver with the VRP */
1099   DeviceObject->DriverObject->DriverStartIo((PVOID) &DeviceExtension->MiniPortDeviceExtension, (PIRP)vrp);
1100
1101   /* Free the VRP */
1102   ExFreePool(vrp);
1103
1104   IoCompleteRequest(Irp, IO_NO_INCREMENT);
1105
1106   return STATUS_SUCCESS;
1107 }
1108
1109 static PVOID STDCALL
1110 InternalMapMemory(IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,
1111                   IN PHYSICAL_ADDRESS IoAddress,
1112                   IN ULONG NumberOfUchars,
1113                   IN UCHAR InIoSpace)
1114 {
1115   PHYSICAL_ADDRESS TranslatedAddress;
1116   PVIDEO_PORT_ADDRESS_MAPPING AddressMapping;
1117   ULONG AddressSpace;
1118   PVOID MappedAddress;
1119   PLIST_ENTRY Entry;
1120
1121   if (0 != (InIoSpace & VIDEO_MEMORY_SPACE_P6CACHE))
1122     {
1123       DPRINT("VIDEO_MEMORY_SPACE_P6CACHE not supported, turning off\n");
1124       InIoSpace &= ~VIDEO_MEMORY_SPACE_P6CACHE;
1125     }
1126   if (! IsListEmpty(&DeviceExtension->AddressMappingListHead))
1127     {
1128       Entry = DeviceExtension->AddressMappingListHead.Flink;
1129       while (Entry != &DeviceExtension->AddressMappingListHead)
1130         {
1131           AddressMapping = CONTAINING_RECORD(Entry,
1132                                              VIDEO_PORT_ADDRESS_MAPPING,
1133                                              List);
1134           if (IoAddress.QuadPart == AddressMapping->IoAddress.QuadPart &&
1135               NumberOfUchars <= AddressMapping->NumberOfUchars)
1136             {
1137               AddressMapping->MappingCount++;
1138               return AddressMapping->MappedAddress;
1139             }
1140           Entry = Entry->Flink;
1141         }
1142     }
1143
1144   AddressSpace = (ULONG)InIoSpace;
1145   if (HalTranslateBusAddress(DeviceExtension->AdapterInterfaceType,
1146                              DeviceExtension->SystemIoBusNumber,
1147                              IoAddress,
1148                              &AddressSpace,
1149                              &TranslatedAddress) == FALSE)
1150     return NULL;
1151
1152   /* i/o space */
1153   if (AddressSpace != 0)
1154     {
1155     assert(0 == TranslatedAddress.u.HighPart);
1156     return (PVOID) TranslatedAddress.u.LowPart;
1157     }
1158
1159   MappedAddress = MmMapIoSpace(TranslatedAddress,
1160                                NumberOfUchars,
1161                                FALSE);
1162
1163   AddressMapping = ExAllocatePoolWithTag(PagedPool,
1164                                          sizeof(VIDEO_PORT_ADDRESS_MAPPING),
1165                                          TAG_VIDEO_PORT);
1166   if (AddressMapping == NULL)
1167     return MappedAddress;
1168
1169   AddressMapping->MappedAddress = MappedAddress;
1170   AddressMapping->NumberOfUchars = NumberOfUchars;
1171   AddressMapping->IoAddress = IoAddress;
1172   AddressMapping->SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
1173   AddressMapping->MappingCount = 1;
1174
1175   InsertHeadList(&DeviceExtension->AddressMappingListHead,
1176                  &AddressMapping->List);
1177
1178   return MappedAddress;
1179 }
1180
1181 static VOID STDCALL
1182 InternalUnmapMemory(IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,
1183                     IN PVOID MappedAddress)
1184 {
1185   PVIDEO_PORT_ADDRESS_MAPPING AddressMapping;
1186   PLIST_ENTRY Entry;
1187
1188   Entry = DeviceExtension->AddressMappingListHead.Flink;
1189   while (Entry != &DeviceExtension->AddressMappingListHead)
1190     {
1191       AddressMapping = CONTAINING_RECORD(Entry,
1192                                          VIDEO_PORT_ADDRESS_MAPPING,
1193                                          List);
1194       if (AddressMapping->MappedAddress == MappedAddress)
1195         {
1196           assert(0 <= AddressMapping->MappingCount);
1197           AddressMapping->MappingCount--;
1198           if (0 == AddressMapping->MappingCount)
1199             {
1200 #ifdef TODO
1201               MmUnmapIoSpace(AddressMapping->MappedAddress,
1202                              AddressMapping->NumberOfUchars);
1203 #else
1204 DPRINT("MmUnmapIoSpace(0x%08x, 0x%08x)\n", AddressMapping->MappedAddress, AddressMapping->NumberOfUchars);
1205 #endif
1206               RemoveEntryList(Entry);
1207               ExFreePool(AddressMapping);
1208
1209               return;
1210             }
1211         }
1212
1213       Entry = Entry->Flink;
1214     }
1215 }