4 * Written by Rex Jolliff
8 #include <ddk/ntddvid.h>
10 #include "../../../ntoskrnl/include/internal/v86m.h"
17 //#define UNIMPLEMENTED do {DbgPrint("%s:%d: Function not implemented", __FILE__, __LINE__); for(;;);} while (0)
19 #define VERSION "0.0.0"
21 static VOID STDCALL VidStartIo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
22 static NTSTATUS STDCALL VidDispatchOpenClose(IN PDEVICE_OBJECT pDO, IN PIRP Irp);
23 static NTSTATUS STDCALL VidDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
25 static BOOLEAN CsrssInitialized = FALSE;
26 static HANDLE CsrssHandle = 0;
27 static struct _EPROCESS* Csrss = NULL;
29 PBYTE ReturnCsrssAddress(void)
34 // ------------------------------------------------------- Public Interface
39 // This function initializes the driver.
45 // IN PDRIVER_OBJECT DriverObject System allocated Driver Object
47 // IN PUNICODE_STRING RegistryPath Name of registry driver service
54 DriverEntry(IN PDRIVER_OBJECT DriverObject,
55 IN PUNICODE_STRING RegistryPath)
57 return(STATUS_SUCCESS);
61 VideoPortDebugPrint(IN ULONG DebugPrintLevel,
62 IN PCHAR DebugMessage, ...)
68 if (DebugPrintLevel > InternalDebugLevel)
71 va_start (ap, DebugMessage);
72 vsprintf (Buffer, DebugMessage, ap);
80 VideoPortDisableInterrupt(IN PVOID HwDeviceExtension)
87 VideoPortEnableInterrupt(IN PVOID HwDeviceExtension)
94 VideoPortFreeDeviceBase(IN PVOID HwDeviceExtension,
95 IN PVOID MappedAddress)
102 VideoPortGetBusData(IN PVOID HwDeviceExtension,
103 IN BUS_DATA_TYPE BusDataType,
109 return HalGetBusDataByOffset(BusDataType,
119 VideoPortGetCurrentIrql(VOID)
121 return KeGetCurrentIrql();
126 VideoPortGetDeviceBase(IN PVOID HwDeviceExtension,
127 IN PHYSICAL_ADDRESS IoAddress,
128 IN ULONG NumberOfUchars,
133 return MmMapIoSpace(IoAddress, NumberOfUchars, FALSE);
144 VideoPortGetDeviceData(IN PVOID HwDeviceExtension,
145 IN VIDEO_DEVICE_DATA_TYPE DeviceDataType,
146 IN PMINIPORT_QUERY_DEVICE_ROUTINE CallbackRoutine,
154 VideoPortGetAccessRanges(IN PVOID HwDeviceExtension,
155 IN ULONG NumRequestedResources,
156 IN PIO_RESOURCE_DESCRIPTOR RequestedResources OPTIONAL,
157 IN ULONG NumAccessRanges,
158 IN PVIDEO_ACCESS_RANGE AccessRanges,
168 VideoPortGetRegistryParameters(IN PVOID HwDeviceExtension,
169 IN PWSTR ParameterName,
170 IN UCHAR IsParameterFileName,
171 IN PMINIPORT_GET_REGISTRY_ROUTINE GetRegistryRoutine,
178 VideoPortInitialize(IN PVOID Context1,
180 IN PVIDEO_HW_INITIALIZATION_DATA HwInitializationData,
184 WCHAR DeviceBuffer[20];
185 WCHAR SymlinkBuffer[20];
187 PDRIVER_OBJECT MPDriverObject = (PDRIVER_OBJECT) Context1;
188 PDEVICE_OBJECT MPDeviceObject;
189 VIDEO_PORT_CONFIG_INFO ConfigInfo;
190 PVIDEOPORT_EXTENSION_DATA ExtensionData;
191 ULONG DeviceNumber = 0;
192 UNICODE_STRING DeviceName;
193 UNICODE_STRING SymlinkName;
196 /* Build Dispatch table from passed data */
197 MPDriverObject->DriverStartIo = (PDRIVER_STARTIO) HwInitializationData->HwStartIO;
199 /* Create a unicode device name */
203 swprintf(DeviceBuffer, L"\\Device\\Video%lu", DeviceNumber);
204 RtlInitUnicodeString(&DeviceName, DeviceBuffer);
206 /* Create the device */
207 Status = IoCreateDevice(MPDriverObject,
208 HwInitializationData->HwDeviceExtensionSize +
209 sizeof(VIDEOPORT_EXTENSION_DATA),
215 if (!NT_SUCCESS(Status))
217 DbgPrint("IoCreateDevice call failed\n",0);
221 MPDriverObject->DeviceObject = MPDeviceObject;
223 /* initialize the miniport drivers dispatch table */
224 MPDriverObject->MajorFunction[IRP_MJ_CREATE] = VidDispatchOpenClose;
225 MPDriverObject->MajorFunction[IRP_MJ_CLOSE] = VidDispatchOpenClose;
226 MPDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VidDispatchDeviceControl;
228 /* create symbolic link "\??\DISPLAYx" */
229 swprintf(SymlinkBuffer, L"\\??\\DISPLAY%lu", DeviceNumber+1);
230 RtlInitUnicodeString (&SymlinkName,
232 IoCreateSymbolicLink (&SymlinkName,
236 (PVIDEOPORT_EXTENSION_DATA) MPDeviceObject->DeviceExtension;
237 ExtensionData->DeviceObject = MPDeviceObject;
239 /* Set the buffering strategy here... */
240 /* If you change this, remember to change VidDispatchDeviceControl too */
241 MPDeviceObject->Flags |= DO_BUFFERED_IO;
243 /* Call HwFindAdapter entry point */
244 /* FIXME: Need to figure out what string to pass as param 3 */
245 Status = HwInitializationData->HwFindAdapter(VPExtensionToMPExtension(ExtensionData),
250 if (!NT_SUCCESS(Status))
252 DbgPrint("HwFindAdapter call failed\n");
253 IoDeleteDevice(MPDeviceObject);
258 /* FIXME: Allocate hardware resources for device */
260 /* Allocate interrupt for device */
261 if (HwInitializationData->HwInterrupt != NULL &&
262 !(ConfigInfo.BusInterruptLevel == 0 &&
263 ConfigInfo.BusInterruptVector == 0))
266 ExtensionData->IRQL = ConfigInfo.BusInterruptLevel;
267 ExtensionData->InterruptLevel =
268 HalGetInterruptVector(ConfigInfo.AdapterInterfaceType,
269 ConfigInfo.SystemIoBusNumber,
270 ConfigInfo.BusInterruptLevel,
271 ConfigInfo.BusInterruptVector,
272 &ExtensionData->IRQL,
273 &ExtensionData->Affinity);
274 KeInitializeSpinLock(&ExtensionData->InterruptSpinLock);
275 Status = IoConnectInterrupt(&ExtensionData->InterruptObject,
277 HwInitializationData->HwInterrupt,
278 VPExtensionToMPExtension(ExtensionData),
279 &ExtensionData->InterruptSpinLock,
280 ExtensionData->InterruptLevel,
283 ConfigInfo.InterruptMode,
285 ExtensionData->Affinity,
287 if (!NT_SUCCESS(Status))
289 DbgPrint("IoConnectInterrupt failed\n");
290 IoDeleteDevice(MPDeviceObject);
300 /* FIXME: initialize timer routine for MP Driver */
301 if (HwInitializationData->HwTimer != NULL)
303 Status = IoInitializeTimer(MPDeviceObject,
305 HwInitializationData->HwTimer,
306 VPExtensionToMPExtension(ExtensionData));
307 if (!NT_SUCCESS(Status))
309 DbgPrint("IoInitializeTimer failed\n");
311 if (HwInitializationData->HwInterrupt != NULL)
313 IoDisconnectInterrupt(ExtensionData->InterruptObject);
315 IoDeleteDevice(MPDeviceObject);
321 return STATUS_SUCCESS;
325 VideoPortInt10(IN PVOID HwDeviceExtension,
326 IN PVIDEO_X86_BIOS_ARGUMENTS BiosArguments)
328 KV86M_REGISTERS Regs;
331 KeAttachProcess(Csrss);
333 memset(&Regs, 0, sizeof(Regs));
334 Regs.Eax = BiosArguments->Eax;
335 Regs.Ebx = BiosArguments->Ebx;
336 Regs.Ecx = BiosArguments->Ecx;
337 Regs.Edx = BiosArguments->Edx;
338 Regs.Esi = BiosArguments->Esi;
339 Regs.Edi = BiosArguments->Edi;
340 Regs.Ebp = BiosArguments->Ebp;
341 Status = Ke386CallBios(0x10, &Regs);
350 VideoPortLogError(IN PVOID HwDeviceExtension,
351 IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL,
352 IN VP_STATUS ErrorCode,
360 VideoPortMapBankedMemory(IN PVOID HwDeviceExtension,
361 IN PHYSICAL_ADDRESS PhysicalAddress,
364 OUT PVOID *VirtualAddress,
366 IN UCHAR ReadWriteBank,
367 IN PBANKED_SECTION_ROUTINE BankRoutine,
375 VideoPortMapMemory(IN PVOID HwDeviceExtension,
376 IN PHYSICAL_ADDRESS PhysicalAddress,
379 OUT PVOID *VirtualAddress)
383 *VirtualAddress = MmMapIoSpace(PhysicalAddress, *Length, FALSE);
385 return *VirtualAddress != NULL ? STATUS_SUCCESS :
386 STATUS_INSUFFICIENT_RESOURCES;
393 return STATUS_SUCCESS;
398 VideoPortReadPortUchar(IN PUCHAR Port)
400 return READ_PORT_UCHAR(Port);
405 VideoPortReadPortUshort(IN PUSHORT Port)
407 return READ_PORT_USHORT(Port);
412 VideoPortReadPortUlong(IN PULONG Port)
414 return READ_PORT_ULONG(Port);
419 VideoPortReadPortBufferUchar(IN PUCHAR Port,
423 READ_PORT_BUFFER_UCHAR(Port, Buffer, Count);
428 VideoPortReadPortBufferUshort(IN PUSHORT Port,
432 READ_PORT_BUFFER_USHORT(Port, Buffer, Count);
437 VideoPortReadPortBufferUlong(IN PULONG Port,
441 READ_PORT_BUFFER_ULONG(Port, Buffer, Count);
446 VideoPortReadRegisterUchar(IN PUCHAR Register)
448 return READ_REGISTER_UCHAR(Register);
453 VideoPortReadRegisterUshort(IN PUSHORT Register)
455 return READ_REGISTER_USHORT(Register);
460 VideoPortReadRegisterUlong(IN PULONG Register)
462 return READ_REGISTER_ULONG(Register);
467 VideoPortReadRegisterBufferUchar(IN PUCHAR Register,
471 READ_REGISTER_BUFFER_UCHAR(Register, Buffer, Count);
476 VideoPortReadRegisterBufferUshort(IN PUSHORT Register,
480 READ_REGISTER_BUFFER_USHORT(Register, Buffer, Count);
485 VideoPortReadRegisterBufferUlong(IN PULONG Register,
489 READ_REGISTER_BUFFER_ULONG(Register, Buffer, Count);
494 VideoPortScanRom(IN PVOID HwDeviceExtension,
504 VideoPortSetBusData(IN PVOID HwDeviceExtension,
505 IN BUS_DATA_TYPE BusDataType,
511 return HalSetBusDataByOffset(BusDataType,
521 VideoPortSetRegistryParameters(IN PVOID HwDeviceExtension,
524 IN ULONG ValueLength)
531 VideoPortSetTrappedEmulatorPorts(IN PVOID HwDeviceExtension,
532 IN ULONG NumAccessRanges,
533 IN PVIDEO_ACCESS_RANGE AccessRange)
540 VideoPortStartTimer(IN PVOID HwDeviceExtension)
542 PVIDEOPORT_EXTENSION_DATA ExtensionData =
543 MPExtensionToVPExtension(HwDeviceExtension);
545 IoStartTimer(ExtensionData->DeviceObject);
550 VideoPortStopTimer(IN PVOID HwDeviceExtension)
552 PVIDEOPORT_EXTENSION_DATA ExtensionData =
553 MPExtensionToVPExtension(HwDeviceExtension);
555 IoStopTimer(ExtensionData->DeviceObject);
560 VideoPortSynchronizeExecution(IN PVOID HwDeviceExtension,
561 IN VIDEO_SYNCHRONIZE_PRIORITY Priority,
562 IN PMINIPORT_SYNCHRONIZE_ROUTINE SynchronizeRoutine,
570 VideoPortUnmapMemory(IN PVOID HwDeviceExtension,
571 IN PVOID VirtualAddress,
572 IN HANDLE ProcessHandle)
579 VideoPortVerifyAccessRanges(IN PVOID HwDeviceExtension,
580 IN ULONG NumAccessRanges,
581 IN PVIDEO_ACCESS_RANGE AccessRanges)
588 VideoPortWritePortUchar(IN PUCHAR Port,
591 WRITE_PORT_UCHAR(Port, Value);
596 VideoPortWritePortUshort(IN PUSHORT Port,
599 WRITE_PORT_USHORT(Port, Value);
604 VideoPortWritePortUlong(IN PULONG Port,
607 WRITE_PORT_ULONG(Port, Value);
612 VideoPortWritePortBufferUchar(IN PUCHAR Port,
616 WRITE_PORT_BUFFER_UCHAR(Port, Buffer, Count);
621 VideoPortWritePortBufferUshort(IN PUSHORT Port,
625 WRITE_PORT_BUFFER_USHORT(Port, Buffer, Count);
630 VideoPortWritePortBufferUlong(IN PULONG Port,
634 WRITE_PORT_BUFFER_ULONG(Port, Buffer, Count);
639 VideoPortWriteRegisterUchar(IN PUCHAR Register,
642 WRITE_REGISTER_UCHAR(Register, Value);
647 VideoPortWriteRegisterUshort(IN PUSHORT Register,
650 WRITE_REGISTER_USHORT(Register, Value);
655 VideoPortWriteRegisterUlong(IN PULONG Register,
658 WRITE_REGISTER_ULONG(Register, Value);
663 VideoPortWriteRegisterBufferUchar(IN PUCHAR Register,
667 WRITE_REGISTER_BUFFER_UCHAR(Register, Buffer, Count);
671 VideoPortWriteRegisterBufferUshort(IN PUSHORT Register,
675 WRITE_REGISTER_BUFFER_USHORT(Register, Buffer, Count);
679 VideoPortWriteRegisterBufferUlong(IN PULONG Register,
683 WRITE_REGISTER_BUFFER_ULONG(Register, Buffer, Count);
687 VideoPortZeroDeviceMemory(OUT PVOID Destination,
694 // ------------------------------------------- Nondiscardable statics
696 // VidDispatchOpenClose
699 // Answer requests for Open/Close calls: a null operation
705 // Standard dispatch arguments
711 static NTSTATUS STDCALL
712 VidDispatchOpenClose(IN PDEVICE_OBJECT pDO,
715 PIO_STACK_LOCATION IrpStack;
717 DPRINT("VidDispatchOpenClose() called\n");
719 IrpStack = IoGetCurrentIrpStackLocation(Irp);
721 if (IrpStack->MajorFunction == IRP_MJ_CREATE &&
722 CsrssInitialized == FALSE)
724 DPRINT("Referencing CSRSS\n");
725 Csrss = PsGetCurrentProcess();
726 CsrssInitialized = TRUE;
727 DPRINT("Csrss %p\n", Csrss);
730 Irp->IoStatus.Status = STATUS_SUCCESS;
731 Irp->IoStatus.Information = FILE_OPENED;
732 IoCompleteRequest(Irp, IO_NO_INCREMENT);
734 return STATUS_SUCCESS;
740 // Get the next requested I/O packet started
746 // Dispatch routine standard arguments
753 VidStartIo(IN PDEVICE_OBJECT DeviceObject,
759 // VidDispatchDeviceControl
762 // Answer requests for device control calls
768 // Standard dispatch arguments
774 static NTSTATUS STDCALL
775 VidDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,
778 PIO_STACK_LOCATION IrpStack;
779 PVIDEO_REQUEST_PACKET vrp;
781 IrpStack = IoGetCurrentIrpStackLocation(Irp);
783 // Translate the IRP to a VRP
784 vrp = ExAllocatePool(PagedPool, sizeof(VIDEO_REQUEST_PACKET));
785 vrp->StatusBlock = ExAllocatePool(PagedPool, sizeof(STATUS_BLOCK));
786 vrp->IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
788 // We're assuming METHOD_BUFFERED
789 vrp->InputBuffer = Irp->AssociatedIrp.SystemBuffer;
790 vrp->InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
791 vrp->OutputBuffer = Irp->UserBuffer;
792 vrp->OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
794 // Call the Miniport Driver with the VRP
795 DeviceObject->DriverObject->DriverStartIo(DeviceObject->DeviceExtension, (PIRP)vrp);
797 // Translate the VRP back into the IRP for OutputBuffer
798 Irp->UserBuffer = vrp->OutputBuffer;
799 IrpStack->Parameters.DeviceIoControl.OutputBufferLength = vrp->OutputBufferLength;
802 ExFreePool(vrp->StatusBlock);
805 return STATUS_SUCCESS;