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