1 /* $Id: vidport.c,v 1.25 2002/09/08 10:22:08 chorns Exp $
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
;