Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* VGAGOP 1.2: GOP branch for the user-supplied original VGA miniport.
- * Reuses the BSE4 0.4.2.1 reserved-system-PTE mapping workaround, with runtime
- * geometry, generic PCI identity, a checked CSM35 record, and physical-width
- * checks. This is experimental XP x86 kernel code; hardware test required.
- * The legacy VGA code remains in vga.c/modeset.c/vesa.c/vgadata.c.
- */
- #if defined(VGAGOP_HOST_TEST)
- # define __stdcall __attribute__((stdcall))
- # define __cdecl __attribute__((cdecl))
- # define __declspec(x)
- #endif
- typedef unsigned char UCHAR;
- typedef unsigned char BOOLEAN;
- typedef unsigned short USHORT;
- #if defined(_MSC_VER)
- typedef unsigned __int64 ULONGLONG;
- typedef __int64 LONGLONG;
- #else
- typedef unsigned long long ULONGLONG;
- typedef long long LONGLONG;
- #endif
- typedef unsigned long ULONG;
- typedef signed long LONG;
- typedef signed short CSHORT;
- typedef unsigned long ULONG_PTR;
- typedef unsigned long SIZE_T;
- typedef void VOID;
- typedef void *PVOID;
- typedef unsigned char *PUCHAR;
- typedef unsigned long *PULONG;
- typedef unsigned short *PWSTR;
- typedef void *HANDLE;
- typedef LONG VP_STATUS;
- typedef unsigned long INTERFACE_TYPE;
- typedef int MEMORY_CACHING_TYPE;
- #ifndef NULL
- #define NULL ((void*)0)
- #endif
- #define TRUE 1
- #define FALSE 0
- #define NO_ERROR 0L
- #define ERROR_INVALID_FUNCTION 1L
- #define ERROR_INVALID_PARAMETER 87L
- #define ERROR_INSUFFICIENT_BUFFER 122L
- /* INTERFACE_TYPE::Internal */
- #define Internal 0
- #define PCIBus 5
- /* video.h */
- #define VIDEO_MEMORY_SPACE_MEMORY 0x00
- #define VIDEO_MEMORY_SPACE_P6CACHE 0x08
- /* ntddvdeo.h IOCTLs */
- #define FILE_DEVICE_VIDEO 0x00000023
- #define METHOD_BUFFERED 0
- #define FILE_ANY_ACCESS 0
- #define CTL_CODE(DeviceType, Function, Method, Access) \
- (((DeviceType)<<16) | ((Access)<<14) | ((Function)<<2) | (Method))
- #define IOCTL_VIDEO_QUERY_AVAIL_MODES CTL_CODE(FILE_DEVICE_VIDEO,0x100,METHOD_BUFFERED,FILE_ANY_ACCESS)
- #define IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES CTL_CODE(FILE_DEVICE_VIDEO,0x101,METHOD_BUFFERED,FILE_ANY_ACCESS)
- #define IOCTL_VIDEO_QUERY_CURRENT_MODE CTL_CODE(FILE_DEVICE_VIDEO,0x102,METHOD_BUFFERED,FILE_ANY_ACCESS)
- #define IOCTL_VIDEO_SET_CURRENT_MODE CTL_CODE(FILE_DEVICE_VIDEO,0x103,METHOD_BUFFERED,FILE_ANY_ACCESS)
- #define IOCTL_VIDEO_RESET_DEVICE CTL_CODE(FILE_DEVICE_VIDEO,0x104,METHOD_BUFFERED,FILE_ANY_ACCESS)
- #define IOCTL_VIDEO_MAP_VIDEO_MEMORY CTL_CODE(FILE_DEVICE_VIDEO,0x116,METHOD_BUFFERED,FILE_ANY_ACCESS)
- #define IOCTL_VIDEO_UNMAP_VIDEO_MEMORY CTL_CODE(FILE_DEVICE_VIDEO,0x117,METHOD_BUFFERED,FILE_ANY_ACCESS)
- /* VIDEO_MODE_INFORMATION flags. Deliberately match generic NT/ReactOS fb. */
- #define VIDEO_MODE_COLOR 0x0001
- #define VIDEO_MODE_GRAPHICS 0x0002
- #define VIDEO_MODE_NO_OFF_SCREEN 0x0020
- /* Exactly one firmware-established graphics mode is exposed. */
- #define BSE_MODECOUNT 1UL
- #include "gop35_record.h"
- #include "gop36_record.h"
- #include "gop35_diag.h"
- #include "gop35_screen.h"
- /* MmMapIoSpace cache types used by NT5. */
- #define MmNonCached 0
- #define MmWriteCombined 2
- #pragma pack(push,8)
- typedef union _PHYSICAL_ADDRESS {
- struct { ULONG LowPart; LONG HighPart; } u;
- LONGLONG QuadPart;
- } PHYSICAL_ADDRESS;
- #pragma pack(pop)
- #define PAGE_SHIFT 12
- #define PAGE_SIZE 4096UL
- #define NonPagedPool 0UL
- /* XP x86 PAE self-map verified by WinDbg: PTE(VA)=0xC0000000+(VA>>12)*8. */
- #define VGAGOP_PTE_BASE 0xC0000000UL
- #define VGAGOP_PDE_BASE 0xC0600000UL
- /* P|RW|PWT|PCD|Global. Do not use XP's 26-bit PageFrameNumber bitfield. */
- #define VGAGOP_PTE_UC_FLAGS 0x000000000000011BULL
- #define VGAGOP_PTE_PHYS_MASK 0x000FFFFFFFFFF000ULL
- #define VGAGOP_MAP_TAG 0x504F4756UL /* 'VGOP' little endian */
- #define VGAGOP_SAVE_TAG 0x50534542UL /* 'BESP' */
- typedef struct _STATUS_BLOCK {
- union { VP_STATUS Status; PVOID Pointer; } u;
- ULONG_PTR Information;
- } STATUS_BLOCK, *PSTATUS_BLOCK;
- typedef struct _VIDEO_REQUEST_PACKET {
- ULONG IoControlCode;
- PSTATUS_BLOCK StatusBlock;
- PVOID InputBuffer;
- ULONG InputBufferLength;
- PVOID OutputBuffer;
- ULONG OutputBufferLength;
- } VIDEO_REQUEST_PACKET, *PVIDEO_REQUEST_PACKET;
- typedef struct _VIDEO_MEMORY {
- PVOID RequestedVirtualAddress;
- } VIDEO_MEMORY, *PVIDEO_MEMORY;
- typedef struct _VIDEO_MEMORY_INFORMATION {
- PVOID VideoRamBase;
- ULONG VideoRamLength;
- PVOID FrameBufferBase;
- ULONG FrameBufferLength;
- } VIDEO_MEMORY_INFORMATION, *PVIDEO_MEMORY_INFORMATION;
- typedef struct _VIDEO_MODE {
- ULONG RequestedMode;
- } VIDEO_MODE, *PVIDEO_MODE;
- typedef struct _VIDEO_NUM_MODES {
- ULONG NumModes;
- ULONG ModeInformationLength;
- } VIDEO_NUM_MODES, *PVIDEO_NUM_MODES;
- typedef struct _VIDEO_MODE_INFORMATION {
- ULONG Length;
- ULONG ModeIndex;
- ULONG VisScreenWidth;
- ULONG VisScreenHeight;
- ULONG ScreenStride;
- ULONG NumberOfPlanes;
- ULONG BitsPerPlane;
- ULONG Frequency;
- ULONG XMillimeter;
- ULONG YMillimeter;
- ULONG NumberRedBits;
- ULONG NumberGreenBits;
- ULONG NumberBlueBits;
- ULONG RedMask;
- ULONG GreenMask;
- ULONG BlueMask;
- ULONG AttributeFlags;
- ULONG VideoMemoryBitmapWidth;
- ULONG VideoMemoryBitmapHeight;
- ULONG DriverSpecificAttributeFlags;
- } VIDEO_MODE_INFORMATION, *PVIDEO_MODE_INFORMATION;
- /* Only the prefix actually accessed. Layout matches XP x86 video.h. */
- typedef struct _VIDEO_PORT_CONFIG_INFO_MIN {
- ULONG Length;
- ULONG SystemIoBusNumber;
- INTERFACE_TYPE AdapterInterfaceType;
- ULONG BusInterruptLevel;
- ULONG BusInterruptVector;
- } VIDEO_PORT_CONFIG_INFO_MIN, *PVIDEO_PORT_CONFIG_INFO;
- typedef struct _VIDEO_POWER_MANAGEMENT {
- ULONG Length, DPMSVersion, PowerState;
- } VIDEO_POWER_MANAGEMENT;
- typedef struct _VIDEO_CHILD_ENUM_INFO {
- ULONG Size, ChildDescriptorSize, ChildIndex, ACPIHwId;
- PVOID ChildHwDeviceExtension;
- } VIDEO_CHILD_ENUM_INFO;
- typedef VP_STATUS (__stdcall *VG_POWER)(PVOID,ULONG,VIDEO_POWER_MANAGEMENT*);
- typedef VP_STATUS (__stdcall *VG_CHILD)(PVOID,VIDEO_CHILD_ENUM_INFO*,PULONG,PUCHAR,PULONG,PULONG);
- typedef VP_STATUS (__stdcall *PVIDEO_HW_FIND_ADAPTER)(PVOID,PVOID,PWSTR,PVIDEO_PORT_CONFIG_INFO,PUCHAR);
- typedef BOOLEAN (__stdcall *PVIDEO_HW_INITIALIZE)(PVOID);
- typedef BOOLEAN (__stdcall *PVIDEO_HW_INTERRUPT)(PVOID);
- typedef BOOLEAN (__stdcall *PVIDEO_HW_START_IO)(PVOID,PVIDEO_REQUEST_PACKET);
- typedef BOOLEAN (__stdcall *PVIDEO_HW_RESET_HW)(PVOID,ULONG,ULONG);
- typedef struct _VIDEO_HW_INITIALIZATION_DATA {
- ULONG HwInitDataSize;
- INTERFACE_TYPE AdapterInterfaceType;
- PVIDEO_HW_FIND_ADAPTER HwFindAdapter;
- PVIDEO_HW_INITIALIZE HwInitialize;
- PVIDEO_HW_INTERRUPT HwInterrupt;
- PVIDEO_HW_START_IO HwStartIO;
- ULONG HwDeviceExtensionSize;
- ULONG StartingDeviceNumber;
- PVIDEO_HW_RESET_HW HwResetHw;
- PVOID HwTimer;
- PVOID HwStartDma;
- VG_POWER HwSetPowerState;
- VG_POWER HwGetPowerState;
- VG_CHILD HwGetVideoChildDescriptor;
- PVOID HwQueryInterface;
- ULONG HwChildDeviceExtensionSize;
- PVOID HwLegacyResourceList;
- ULONG HwLegacyResourceCount;
- PVOID HwGetLegacyResources;
- BOOLEAN AllowEarlyEnumeration;
- UCHAR _pad[3];
- ULONG Reserved;
- } VIDEO_HW_INITIALIZATION_DATA, *PVIDEO_HW_INITIALIZATION_DATA;
- /* Compile-time ABI guards for XP x86 / x64. */
- typedef char bse_assert_mode_info_80[(sizeof(VIDEO_MODE_INFORMATION)==80)?1:-1];
- typedef char bse_assert_num_modes_8[(sizeof(VIDEO_NUM_MODES)==8)?1:-1];
- #if defined(_WIN64)
- typedef char bse_assert_hw_init_144[(sizeof(VIDEO_HW_INITIALIZATION_DATA)==144)?1:-1];
- typedef char bse_assert_mem_info_32[(sizeof(VIDEO_MEMORY_INFORMATION)==32)?1:-1];
- #else
- typedef char bse_assert_hw_init_84[(sizeof(VIDEO_HW_INITIALIZATION_DATA)==84)?1:-1];
- typedef char bse_assert_mem_info_16[(sizeof(VIDEO_MEMORY_INFORMATION)==16)?1:-1];
- #endif
- typedef char vg_assert_config_prefix_20[(sizeof(VIDEO_PORT_CONFIG_INFO_MIN)==20)?1:-1];
- typedef char vg_assert_power_12[(sizeof(VIDEO_POWER_MANAGEMENT)==12)?1:-1];
- #if defined(_WIN64)
- typedef char vg_assert_child_24[(sizeof(VIDEO_CHILD_ENUM_INFO)==24)?1:-1];
- #else
- typedef char vg_assert_child_20[(sizeof(VIDEO_CHILD_ENUM_INFO)==20)?1:-1];
- #endif
- /* VGAGOP target and status definitions. */
- #define ERROR_DEV_NOT_EXIST 55L
- #define ERROR_BUSY 170L
- #define ERROR_IO_DEVICE 1117L
- #define VGAGOP_PATTERN_A 0xAA55AA55UL
- #define VGAGOP_PATTERN_B 0x55AA55AAUL
- #define VGAGOP_POLL_US 10UL
- #define VGAGOP_MAX_WAITS 100UL
- typedef struct _VIDEO_ACCESS_RANGE {
- PHYSICAL_ADDRESS RangeStart;
- ULONG RangeLength;
- UCHAR RangeInIoSpace, RangeVisible, RangeShareable, RangePassive;
- } VIDEO_ACCESS_RANGE;
- typedef struct _VGAGOP_EXTENSION {
- ULONG Claimed;
- ULONG GopValid;
- ULONG CurrentMode;
- G35_RECORD Record;
- ULONG MapUsers;
- ULONG PixelTestDone,Cr4,PhysicalBits;
- G35_PIXEL_RESULT Pixels;
- ULONGLONG FbPhysical;
- ULONG FbLength;
- PVOID MappingAddress;
- ULONGLONG *SavedPtes;
- ULONG MapPages;
- ULONG MapLength;
- PVOID MappedBase;
- volatile LONG Busy;
- } VGAGOP_EXTENSION;
- __declspec(dllimport) ULONG __stdcall VideoPortInitialize(PVOID,PVOID,PVIDEO_HW_INITIALIZATION_DATA,PVOID);
- __declspec(dllimport) VP_STATUS __stdcall VideoPortVerifyAccessRanges(PVOID,ULONG,VIDEO_ACCESS_RANGE*);
- __declspec(dllimport) VP_STATUS __stdcall VideoPortGetAccessRanges(PVOID,ULONG,PVOID,ULONG,VIDEO_ACCESS_RANGE*,PVOID,PVOID,PULONG);
- __declspec(dllimport) VOID __stdcall VideoPortStallExecution(ULONG);
- __declspec(dllimport) ULONG __stdcall HalGetBusDataByOffset(ULONG,ULONG,ULONG,PVOID,ULONG,ULONG);
- __declspec(dllimport) PVOID __stdcall MmMapIoSpace(PHYSICAL_ADDRESS,SIZE_T,MEMORY_CACHING_TYPE);
- __declspec(dllimport) VOID __stdcall MmUnmapIoSpace(PVOID,SIZE_T);
- __declspec(dllimport) PVOID __stdcall MmAllocateMappingAddress(SIZE_T,ULONG);
- __declspec(dllimport) VOID __stdcall MmFreeMappingAddress(PVOID,ULONG);
- __declspec(dllimport) PVOID __stdcall ExAllocatePoolWithTag(ULONG,SIZE_T,ULONG);
- __declspec(dllimport) VOID __stdcall ExFreePool(PVOID);
- __declspec(dllimport) VOID __stdcall KeFlushEntireTb(BOOLEAN,BOOLEAN);
- __declspec(dllimport) ULONG __cdecl DbgPrint(const char*,...);
- #if defined(_MSC_VER)
- LONG __cdecl _InterlockedCompareExchange(volatile LONG*,LONG,LONG);
- #pragma intrinsic(_InterlockedCompareExchange)
- #if defined(_M_AMD64) || defined(_M_X64)
- unsigned __int64 __readcr4(void);
- #pragma intrinsic(__readcr4)
- void __cpuid(int cpuInfo[4], int function_id);
- #pragma intrinsic(__cpuid)
- #endif
- #endif
- /* Stable, exported diagnostic ABI: dd vgagop!VgaGopDiag L40 (hex length). */
- enum {
- D_MAGIC, D_VERSION, D_BYTES, D_STAGE, D_ERROR, D_IOCTL, D_STATUS,
- D_ENTRY_STATUS, D_BAR_OLD_LO, D_BAR_OLD_HI, D_BAR_NOW_LO, D_BAR_NOW_HI,
- D_CMD_OLD, D_CMD_NOW, D_SUBSYS, D_TOLUD, D_CLAIM_STATUS,
- D_FB_PHYSICAL, D_FB_LENGTH, D_FB_VIRTUAL, D_MAP_COUNT, D_UNMAP_COUNT,
- D_SET_COUNT, D_TEST_COUNT, D_TEST_A, D_TEST_B, D_SAVED_PIXEL,
- D_RELOCATIONS, D_FAILURES, D_CONFLICT_BDF, D_CONFLICT_BASE,
- D_GOP_RECORD, D_GOP_FLAGS, D_GOP_FB_LO, D_GOP_FB_HI, D_MODE,
- D_EXTENSION, D_LOCK, D_ROLLBACK, D_MAP_STATUS, D_HISTORY_NEXT,
- D_HISTORY, /* 16 DWORDs: indices 41..56; new fields begin at 57. */
- D_FIRST_A = 57, D_FIRST_B, D_WAITS_A, D_WAITS_B,
- D_PRIME_READ, D_PRIME_WAITS, D_PROBE_STATE
- };
- enum {
- E_NONE, E_PCI_READ, E_GPU, E_BOARD, E_BAR, E_RAM, E_GOP, E_CLAIM,
- E_CONFLICT, E_COMMAND, E_PCI_WRITE, E_READBACK, E_ROLLBACK,
- E_MAP, E_PIXEL_TEST, E_LOCK, E_ARGUMENT, E_BRIDGE
- };
- __declspec(dllexport) volatile ULONG VgaGopDiag[64] = {0x504F4756UL,0x00010000UL,256UL};
- /* Separate diagnostic ABI; old VgaGopDiag offsets are unchanged.
- * 0 magic,1 version,2 bytes,3 path (1 legacy high,2 PCI/PnP low),
- * 4 bus,5 interface,6 slot,7 GetAccessRanges result,8 matched index,
- * 9 error (1 config,2 bus,3 API,4 slot,5 containment,6 identity),
- * 10/11 framebuffer,12 length,13 matching range low,14 high,15 length.
- */
- __declspec(dllexport) volatile ULONG VgaGopPciDiag[16] = {0x49435056UL,0x00010200UL,64UL};
- static volatile LONG VgaGopFenceWord;
- #if defined(_WIN64)
- typedef char check_pointer_64[(sizeof(PVOID)==8)?1:-1];
- /* BankSwitch is x86-only (i386\banking.asm). Export dummy symbols to satisfy vga.obj on AMD64. */
- UCHAR BankSwitchStart = 0;
- UCHAR BankSwitchEnd = 0;
- #else
- typedef char check_pointer_32[(sizeof(PVOID)==4)?1:-1];
- #endif
- typedef char check_access_range[(sizeof(VIDEO_ACCESS_RANGE)==16)?1:-1];
- typedef char check_ulong_32[(sizeof(ULONG)==4)?1:-1];
- typedef char check_physical_address_8[(sizeof(PHYSICAL_ADDRESS)==8)?1:-1];
- typedef char check_diag_64[(D_PROBE_STATE==63)?1:-1];
- static LONG vgagop_cas(volatile LONG *p, LONG n, LONG old)
- {
- #if defined(__GNUC__)
- return __sync_val_compare_and_swap(p,old,n);
- #else
- return _InterlockedCompareExchange(p,n,old);
- #endif
- }
- static void vgagop_fence(void) { (void)vgagop_cas(&VgaGopFenceWord,0,0); }
- static void vgagop_stall(G35_U32 us){VideoPortStallExecution(us);}
- static void bse_zero(PVOID p, ULONG n)
- {
- UCHAR *q=(UCHAR*)p;
- while(n--) *q++=0;
- }
- static ULONG rd32(const UCHAR *p)
- {
- return (ULONG)p[0]|((ULONG)p[1]<<8)|((ULONG)p[2]<<16)|((ULONG)p[3]<<24);
- }
- static USHORT rd16(const UCHAR *p) { return (USHORT)(p[0]|((USHORT)p[1]<<8)); }
- static VP_STATUS fail(ULONG e, VP_STATUS status)
- {
- VgaGopDiag[D_ERROR]=e; ++VgaGopDiag[D_FAILURES];
- DbgPrint("VGAGOP: fail=%lu stage=%lu ioctl=%08lx status=%lu\n",
- e,VgaGopDiag[D_STAGE],VgaGopDiag[D_IOCTL],(ULONG)status);
- return status;
- }
- /* The dispatcher only falls back to the original VGA driver when NO CSM
- * graphics handoff is present. An invalid/old CSM handoff never triggers
- * legacy VGA port accesses on a Class 3 machine. */
- static G35_RECORD VgaGopRecord;
- static G36_RECORD VgaGopBridgeRecord;
- static int VgaGopRecordReady;
- static int read_handoff(void)
- {
- PHYSICAL_ADDRESS pa;
- UCHAR *p;
- ULONG i,j,count=0,invalid=0,old=0;
- G35_RECORD r;
- pa.QuadPart=0x80000;
- p=(UCHAR*)MmMapIoSpace(pa,0x20000,1);
- if(!p)return -1;
- for(i=0;i<=0x20000-8;i+=8) {
- if(g35_equal(p+i,"GOP23V1\0",8))old=1;
- if(i>0x20000-sizeof(r)||!g35_equal(p+i,G35_SIGNATURE,8))continue;
- for(j=0;j<sizeof(r);j++)((UCHAR*)&r)[j]=p[i+j];
- if(g35_validate(&r)){invalid=1;continue;}
- if(r.Flags&G35_BRIDGE_VALID) {
- if(i+sizeof(r)+sizeof(VgaGopBridgeRecord)>0x20000){invalid=1;continue;}
- for(j=0;j<sizeof(VgaGopBridgeRecord);j++)
- ((UCHAR*)&VgaGopBridgeRecord)[j]=p[i+sizeof(r)+j];
- if(g36_validate(&VgaGopBridgeRecord,&r)){invalid=1;continue;}
- }
- ++count;
- VgaGopRecord=r;
- VgaGopDiag[D_GOP_RECORD]=0x80000+i;
- }
- MmUnmapIoSpace(p,0x20000);
- if(count==1&&!invalid)return 1;
- return (count||invalid||old)?-1:0;
- }
- static VP_STATUS identify(VGAGOP_EXTENSION *e,UCHAR *cfg)
- {
- ULONG slot,i;
- const G35_RECORD *r=&e->Record;
- slot=r->Device|(r->Function<<5);
- if(HalGetBusDataByOffset(4,r->Bus,slot,cfg,0,64)!=64)
- return fail(E_PCI_READ,ERROR_IO_DEVICE);
- if(rd32(cfg)!=r->PciId||rd32(cfg+8)!=r->ClassRevision||
- rd32(cfg+0x2c)!=r->Subsystem||(cfg[0x0e]&0x7f)!=0)
- return fail(E_GPU,ERROR_DEV_NOT_EXIST);
- for(i=0;i<6;i++) if(rd32(cfg+0x10+i*4)!=r->Bars[i]) {
- VgaGopDiag[D_BAR_OLD_LO]=r->Bars[i];
- VgaGopDiag[D_BAR_NOW_LO]=rd32(cfg+0x10+i*4);
- VgaGopDiag[D_CONFLICT_BDF]=i;
- return fail(E_BAR,ERROR_INVALID_PARAMETER);
- }
- VgaGopDiag[D_CMD_OLD]=r->Command;
- VgaGopDiag[D_CMD_NOW]=rd16(cfg+4);
- if(!(rd16(cfg+4)&2))return fail(E_COMMAND,ERROR_DEV_NOT_EXIST);
- VgaGopDiag[D_SUBSYS]=r->Subsystem;
- return NO_ERROR;
- }
- #include "gop36_xp.h"
- static ULONG mask_bits(ULONG m)
- {
- ULONG n=0;
- while(m){n+=m&1;m>>=1;}
- return n;
- }
- static void fill_mode(VGAGOP_EXTENSION *e,VIDEO_MODE_INFORMATION *m,ULONG i)
- {
- const G35_GOP *g=&e->Record.Gop;
- bse_zero(m,sizeof(*m));
- m->Length=sizeof(*m);m->ModeIndex=i;
- m->VisScreenWidth=g->Width;m->VisScreenHeight=g->Height;
- m->ScreenStride=g->PixelsPerScanLine*4;m->NumberOfPlanes=1;m->BitsPerPlane=32;
- /* GOP does not expose refresh or physical monitor size. 60 Hz is the
- * XP display-mode descriptor value, never a hardware mode-set request. */
- m->Frequency=60;m->XMillimeter=0;m->YMillimeter=0;
- m->NumberRedBits=mask_bits(g->RedMask);m->NumberGreenBits=mask_bits(g->GreenMask);
- m->NumberBlueBits=mask_bits(g->BlueMask);
- m->RedMask=g->RedMask;m->GreenMask=g->GreenMask;m->BlueMask=g->BlueMask;
- m->AttributeFlags=VIDEO_MODE_COLOR|VIDEO_MODE_GRAPHICS|VIDEO_MODE_NO_OFF_SCREEN;
- m->VideoMemoryBitmapWidth=g->PixelsPerScanLine;m->VideoMemoryBitmapHeight=g->Height;
- }
- /* Write ONCE, then read until two successive samples agree with the pattern.
- * Each sample after the first follows a 10-us stall and a CPU memory barrier.
- * A barrier alone did not make BSE2's readback reliable on the target.
- * No unbounded loop and no repeated writes that could hide a stuck readback.
- * Maximum requested stall time: 100 * 10 us per pattern, 3 ms per MAP.
- * That limit is a test-build policy, not a measured hardware latency bound.
- */
- static int write_and_wait(volatile ULONG *pixel,ULONG expected,
- volatile ULONG *first,volatile ULONG *last,
- volatile ULONG *waits)
- {
- ULONG i,value,matching=0;
- *pixel=expected;
- vgagop_fence();
- for(i=0;i<=VGAGOP_MAX_WAITS;i++) {
- value=*pixel;
- if(i==0 && first) *first=value;
- *last=value;
- *waits=i;
- if(value==expected) {
- ++matching;
- if(matching==2) return 1;
- } else {
- matching=0;
- }
- if(i==VGAGOP_MAX_WAITS) break;
- VideoPortStallExecution(VGAGOP_POLL_US);
- vgagop_fence();
- }
- return 0;
- }
- static int probe_and_prime(volatile ULONG *pixel)
- {
- ULONG old,i;
- old=*pixel;
- VgaGopDiag[D_SAVED_PIXEL]=old;
- VgaGopDiag[D_TEST_A]=0;
- VgaGopDiag[D_TEST_B]=0;
- for(i=D_FIRST_A;i<=D_PROBE_STATE;i++) VgaGopDiag[i]=0;
- ++VgaGopDiag[D_TEST_COUNT];
- VgaGopDiag[D_PROBE_STATE]=1;
- if(!write_and_wait(pixel,VGAGOP_PATTERN_A,&VgaGopDiag[D_FIRST_A],
- &VgaGopDiag[D_TEST_A],&VgaGopDiag[D_WAITS_A])) goto failed;
- VgaGopDiag[D_PROBE_STATE]=2;
- if(!write_and_wait(pixel,VGAGOP_PATTERN_B,&VgaGopDiag[D_FIRST_B],
- &VgaGopDiag[D_TEST_B],&VgaGopDiag[D_WAITS_B])) goto failed;
- /* The supplied framebuf bInitSURF writes AA55AA55 and immediately compares
- * it. A miniport delay before returning cannot delay that later CMP.
- * Instead, establish and confirm its expected starting value here AFTER
- * testing a real A -> B transition. Do NOT restore the old pixel on success:
- * that would recreate the observed delayed-read failure in framebuf.dll.
- * The A -> B -> A checks must all pass; no unconditional success branch.
- * Only the first 32-bit pixel changes. No framebuf code or flags are patched.
- */
- VgaGopDiag[D_PROBE_STATE]=3;
- if(!write_and_wait(pixel,VGAGOP_PATTERN_A,NULL,
- &VgaGopDiag[D_PRIME_READ],&VgaGopDiag[D_PRIME_WAITS])) goto failed;
- VgaGopDiag[D_PROBE_STATE]=4;
- DbgPrint("VGAGOP: probe OK; waits A/B/prime=%lu/%lu/%lu; framebuf seed=%08lx\n",
- VgaGopDiag[D_WAITS_A],VgaGopDiag[D_WAITS_B],
- VgaGopDiag[D_PRIME_WAITS],VgaGopDiag[D_PRIME_READ]);
- return 1;
- failed:
- VgaGopDiag[D_PROBE_STATE]|=0x80UL;
- *pixel=old; /* Best-effort restoration on failure, not claimed as verified. */
- vgagop_fence();
- return 0;
- }
- static ULONGLONG vgagop_load_pte(volatile ULONG *p)
- {
- return ((ULONGLONG)p[1]<<32)|(ULONGLONG)p[0];
- }
- /* Present bit is published last, matching the already-proven GOP8 PAE writer. */
- static void vgagop_store_pte(volatile ULONG *p,ULONGLONG v)
- {
- p[0]=0;
- vgagop_fence();
- p[1]=(ULONG)(v>>32);
- vgagop_fence();
- p[0]=(ULONG)v;
- }
- #if defined(VGAGOP_HOST_TEST)
- extern volatile ULONG *test_pte_for_va(PVOID);
- extern volatile ULONG *test_pde_for_va(PVOID);
- extern ULONG test_read_cr4(void);
- extern ULONG test_phys_bits(void);
- #define vgagop_pte_for_va test_pte_for_va
- #define vgagop_pde_for_va test_pde_for_va
- #define vgagop_read_cr4 test_read_cr4
- #define vgagop_phys_bits test_phys_bits
- #else
- static volatile ULONG *vgagop_pte_for_va(PVOID va)
- {
- return (volatile ULONG*)(VGAGOP_PTE_BASE+(((ULONG_PTR)va>>PAGE_SHIFT)<<3));
- }
- static volatile ULONG *vgagop_pde_for_va(PVOID va)
- {
- return (volatile ULONG*)(VGAGOP_PDE_BASE+(((ULONG_PTR)va>>21)<<3));
- }
- static ULONG vgagop_read_cr4(void)
- {
- ULONG value;
- #if defined(__GNUC__)
- __asm__ __volatile__("mov %%cr4, %0" : "=r"(value));
- #elif defined(_M_AMD64) || defined(_M_X64)
- value = (ULONG)__readcr4();
- #else
- __asm {
- xor eax,eax
- _emit 0x0f
- _emit 0x20
- _emit 0xe0
- mov value,eax
- }
- #endif
- return value;
- }
- static ULONG vgagop_cpuid_eax(ULONG leaf)
- {
- ULONG a;
- #if defined(__GNUC__)
- ULONG b,c,d;
- __asm__ __volatile__("cpuid":"=a"(a),"=b"(b),"=c"(c),"=d"(d):"a"(leaf),"c"(0));
- #elif defined(_M_AMD64) || defined(_M_X64)
- int cpuInfo[4];
- __cpuid(cpuInfo, (int)leaf);
- a = (ULONG)cpuInfo[0];
- #else
- __asm {
- mov eax,leaf
- xor ecx,ecx
- cpuid
- mov a,eax
- }
- #endif
- return a;
- }
- static ULONG vgagop_phys_bits(void)
- {
- ULONG bits;
- if(vgagop_cpuid_eax(0x80000000UL)<0x80000008UL)return 36;
- bits=vgagop_cpuid_eax(0x80000008UL)&255;
- return (bits>=32&&bits<=52)?bits:0;
- }
- #endif
- /*
- * XP SP3 PAE's documented/internal MDL/MMIO mapper on this kernel truncates
- * the PFN with 0x03FFFFFF. For framebuffer 0xA000800000 that produces PFN
- * 0x02000800 -> physical 0x2000800000, which WinDbg proved is wrong.
- *
- * 0.4.1 incorrectly replaced the RAM PTEs of a nonpaged-pool allocation.
- * MiFreePoolPages can inspect an adjacent allocation's PFN while coalescing
- * free pool pages. A device PFN has no ordinary RAM/pool PFN metadata there.
- * Restoring those RAM PTEs only when UNMAP arrives is too late.
- *
- * 0.4.2 reserves VA/system PTEs with MmAllocateMappingAddress instead. This
- * allocation is not pool RAM. Save the INVALID reserved PTEs, and change
- * only the requested range; allocator metadata outside that range is left
- * untouched. Restore the invalid PTEs and flush all CPUs before releasing
- * the reservation with MmFreeMappingAddress. ExFreePool is used only for
- * the separate saved-PTE array, whose RAM mapping is never modified.
- *
- * Called by HwVidStartIO (pageable context); mapping reservation/free require
- * IRQL <= APC_LEVEL. The direct PTE writes remain an XP-x86-PAE-specific
- * experimental workaround, not the documented reserved-MDL mapping path.
- */
- static void unmap_high_fb(VGAGOP_EXTENSION *e);
- static int map_high_fb(VGAGOP_EXTENSION *e)
- {
- ULONGLONG phys,base,newpte,oldpte,pde,last;
- ULONG off,total,pages,i,bits;
- UCHAR *reserve;
- ULONGLONG *saved;
- volatile ULONG *pte;
- if(e->MappedBase) return 1;
- VgaGopDiag[D_STAGE]=6;
- e->Cr4=vgagop_read_cr4();
- if(!(e->Cr4&0x20UL)) {
- DbgPrint("VGAGOP: map rejected: CR4.PAE is not set\n");
- return 0;
- }
- bits=vgagop_phys_bits();e->PhysicalBits=bits;
- if(bits<32||bits>52)return 0;
- phys=e->FbPhysical;
- off=(ULONG)(phys & (PAGE_SIZE-1));
- base=phys-(ULONGLONG)off;
- if(!e->FbLength || e->FbLength>0xFFFFFFFFUL-off-(PAGE_SIZE-1)) return 0;
- total=(e->FbLength+off+PAGE_SIZE-1)&~(PAGE_SIZE-1);
- if(!total || total<e->FbLength) return 0;
- pages=total>>PAGE_SHIFT;
- if(!pages || pages>0x4000UL) return 0;
- last=base+((ULONGLONG)(pages-1)<<PAGE_SHIFT);
- if(last<base || (base&~VGAGOP_PTE_PHYS_MASK) || (last&~VGAGOP_PTE_PHYS_MASK)) return 0;
- if(last>=((ULONGLONG)1<<bits))return 0;
- reserve=(UCHAR*)MmAllocateMappingAddress(total,VGAGOP_MAP_TAG);
- if(!reserve) {
- DbgPrint("VGAGOP: MmAllocateMappingAddress failed for %08lx bytes\n",total);
- return 0;
- }
- /* The mapping reservation must start on a page boundary. */
- if(((ULONG_PTR)reserve & (PAGE_SIZE-1))!=0) {
- MmFreeMappingAddress(reserve,VGAGOP_MAP_TAG);
- return 0;
- }
- VgaGopDiag[D_STAGE]=7;
- saved=(ULONGLONG*)ExAllocatePoolWithTag(NonPagedPool,pages*sizeof(ULONGLONG),VGAGOP_SAVE_TAG);
- if(!saved) {
- MmFreeMappingAddress(reserve,VGAGOP_MAP_TAG);
- return 0;
- }
- /* Verify the entire reservation before changing ANY PTE. Check the PDE
- * before dereferencing its PTE page; reject absent/large-page mappings. */
- for(i=0;i<pages;i++) {
- pde=vgagop_load_pte(vgagop_pde_for_va(reserve+(i<<PAGE_SHIFT)));
- if(!(pde&1ULL) || (pde&0x80ULL)) {
- DbgPrint("VGAGOP: reserved VA has unsuitable PDE at page %lu\n",i);
- ExFreePool(saved);
- MmFreeMappingAddress(reserve,VGAGOP_MAP_TAG);
- return 0;
- }
- pte=vgagop_pte_for_va(reserve+(i<<PAGE_SHIFT));
- oldpte=vgagop_load_pte(pte);
- if(oldpte&1ULL) {
- DbgPrint("VGAGOP: reserved PTE unexpectedly present at page %lu\n",i);
- ExFreePool(saved);
- MmFreeMappingAddress(reserve,VGAGOP_MAP_TAG);
- return 0;
- }
- saved[i]=oldpte;
- }
- e->MappingAddress=reserve;
- e->SavedPtes=saved;
- e->MapPages=pages;
- e->MapLength=total;
- for(i=0;i<pages;i++) {
- pte=vgagop_pte_for_va(reserve+(i<<PAGE_SHIFT));
- newpte=((base+((ULONGLONG)i<<PAGE_SHIFT))&VGAGOP_PTE_PHYS_MASK)|VGAGOP_PTE_UC_FLAGS;
- vgagop_store_pte(pte,newpte);
- }
- /* Verify every raw 64-bit value before exposing the VA to GDI. */
- for(i=0;i<pages;i++) {
- newpte=(base+((ULONGLONG)i<<PAGE_SHIFT))|VGAGOP_PTE_UC_FLAGS;
- if(vgagop_load_pte(vgagop_pte_for_va(reserve+(i<<PAGE_SHIFT)))!=newpte) {
- unmap_high_fb(e);return 0;
- }
- }
- KeFlushEntireTb(TRUE,TRUE);
- e->MappedBase=reserve+off;
- pte=vgagop_pte_for_va(reserve);
- newpte=vgagop_load_pte(pte);
- DbgPrint("VGAGOP 1.0: reserved system VA=%08lx bytes=%08lx PTE=%08lx raw=%08lx%08lx\n",
- (ULONG_PTR)e->MappedBase,total,(ULONG_PTR)pte,
- (ULONG)(newpte>>32),(ULONG)newpte);
- return 1;
- }
- static void unmap_high_fb(VGAGOP_EXTENSION *e)
- {
- ULONG i;
- UCHAR *reserve=(UCHAR*)e->MappingAddress;
- if(reserve && e->SavedPtes && e->MapPages) {
- for(i=0;i<e->MapPages;i++)
- vgagop_store_pte(vgagop_pte_for_va(reserve+(i<<PAGE_SHIFT)),e->SavedPtes[i]);
- KeFlushEntireTb(TRUE,TRUE);
- }
- e->MappedBase=NULL;
- e->PixelTestDone=0;
- e->MapLength=0;
- e->MapPages=0;
- if(e->SavedPtes) ExFreePool(e->SavedPtes);
- e->SavedPtes=NULL;
- if(e->MappingAddress) MmFreeMappingAddress(e->MappingAddress,VGAGOP_MAP_TAG);
- e->MappingAddress=NULL;
- }
- static void vgagop_draw_screen(VGAGOP_EXTENSION *e) {
- G35_SCREEN s;ULONGLONG pte=vgagop_load_pte(vgagop_pte_for_va(e->MappingAddress));
- g35_begin(&s,(volatile G35_U32*)e->MappedBase,&e->Record.Gop,"VGAGOP 1.0 / XP DRIVER TESTS");
- g35_common(&s,&e->Record,&e->Pixels);
- g35_text(&s,"XP CR4 ");g35_hex(&s,e->Cr4,8);g35_text(&s," PAE ");g35_text(&s,e->Cr4&0x20?"PASS":"FAIL");
- g35_text(&s," PHYSICAL BITS ");g35_num(&s,e->PhysicalBits);g35_char(&s,'\n');
- g35_text(&s,"SYSTEM VA ");g35_hex(&s,(ULONG_PTR)e->MappedBase,8);g35_text(&s," PAGES ");g35_num(&s,e->MapPages);g35_char(&s,'\n');
- g35_text(&s,"FIRST RAW PTE 0X");g35_hex(&s,pte,16);g35_char(&s,'\n');
- g35_text(&s,"PCI ID / ALL SIX BARS / MEMORY DECODE: PASS\n");
- g35_text(&s,"VIDEOPORT RESOURCE CLAIM STATUS ");g35_num(&s,VgaGopDiag[D_CLAIM_STATUS]);g35_char(&s,'\n');
- g35_text(&s,"RESERVED SYSTEM PTE CHECKS / 64 BIT ADDRESS: PASS\n");
- g35_text(&s,"GDI DESKTOP: NOT YET CONFIRMED\n");
- g35_text(&s,"THIS PAGE MAY BE REPLACED BY XP. RUN GOPDIAG.EXE\n");
- }
- static void vgagop_snapshot(VGAGOP_EXTENSION *e,G35_DIAG_PACKET *p) {
- ULONG i;ULONGLONG raw=0;
- bse_zero(p,sizeof(*p));p->Magic=G35_DIAG_MAGIC;p->Size=sizeof(*p);p->Version=G35_VERSION;
- p->Cr4=e->Cr4;p->PhysicalBits=e->PhysicalBits;p->PixelTestDone=e->PixelTestDone;p->MapUsers=e->MapUsers;
- if(e->MappingAddress)raw=vgagop_load_pte(vgagop_pte_for_va(e->MappingAddress));
- p->RawPteLow=(G35_U32)raw;p->RawPteHigh=(G35_U32)(raw>>32);
- for(i=0;i<64;i++)p->Diag[i]=VgaGopDiag[i];p->Record=e->Record;p->Pixels=e->Pixels;
- }
- static void vgagop_seed_note(VGAGOP_EXTENSION *e,int ok) {
- G35_SCREEN s;
- if(e->MapUsers||!e->PixelTestDone)return;
- s.G=&e->Record.Gop;s.Fb=(volatile G35_U32*)e->MappedBase;
- s.Scale=s.G->Width>=1000&&s.G->Height>=720?2:1;
- s.X=18;s.Y=s.G->Height-120;s.Ink=g35_color(&s,ok?0x64e3ff:0xffdd77);
- g35_rect(&s,18,s.Y,s.G->Width-36,20,g35_color(&s,0x081727));
- g35_text(&s,ok?"GDI SEED PASS A ":"GDI SEED FAIL A ");g35_hex(&s,VgaGopDiag[D_TEST_A],8);
- g35_text(&s," B ");g35_hex(&s,VgaGopDiag[D_TEST_B],8);
- g35_text(&s," FINAL ");g35_hex(&s,VgaGopDiag[D_PRIME_READ],8);vgagop_fence();
- }
- static VP_STATUS map_fb(VGAGOP_EXTENSION *e,VIDEO_REQUEST_PACKET *r)
- {
- VIDEO_MEMORY_INFORMATION *mi;
- volatile ULONG *pixel;
- UCHAR cfg[64];
- VP_STATUS identity_status;
- if(r->InputBufferLength<sizeof(VIDEO_MEMORY) || !r->InputBuffer ||
- r->OutputBufferLength<sizeof(VIDEO_MEMORY_INFORMATION) || !r->OutputBuffer)
- return fail(E_ARGUMENT,ERROR_INSUFFICIENT_BUFFER);
- /* This version supports the system-space mapping requested by framebuf.dll. */
- if(((VIDEO_MEMORY*)r->InputBuffer)->RequestedVirtualAddress)
- return fail(E_ARGUMENT,ERROR_INVALID_PARAMETER);
- bse_zero(r->OutputBuffer,sizeof(VIDEO_MEMORY_INFORMATION));
- if(e->MapUsers==0xffffffffUL)return fail(E_ARGUMENT,ERROR_BUSY);
- if(!e->MappedBase) {
- identity_status=identify(e,cfg);
- if(identity_status)return identity_status;
- VgaGopDiag[D_STAGE]=6;
- identity_status=vgagop_restore_bridges(e);
- if(identity_status)return identity_status;
- identity_status=identify(e,cfg);
- if(identity_status)return identity_status;
- if(!map_high_fb(e)) return fail(E_MAP,ERROR_IO_DEVICE);
- ++VgaGopDiag[D_MAP_COUNT];
- }
- VgaGopDiag[D_STAGE]=8;
- VgaGopDiag[D_FB_VIRTUAL]=(ULONG_PTR)e->MappedBase;
- pixel=(volatile ULONG*)e->MappedBase;
- if(!e->PixelTestDone) {
- if(!g35_pixel_test(&e->Record.Gop,(volatile G35_U32*)pixel,vgagop_fence,vgagop_stall,&e->Pixels)) {
- VgaGopDiag[D_MAP_STATUS]=ERROR_IO_DEVICE;
- if(!e->MapUsers){unmap_high_fb(e);VgaGopDiag[D_FB_VIRTUAL]=0;}
- return fail(E_PIXEL_TEST,ERROR_IO_DEVICE);
- }
- e->PixelTestDone=1;
- vgagop_draw_screen(e);
- }
- if(!probe_and_prime(pixel)) {
- VgaGopDiag[D_MAP_STATUS]=ERROR_IO_DEVICE;
- vgagop_seed_note(e,0);
- if(!e->MapUsers) {unmap_high_fb(e);VgaGopDiag[D_FB_VIRTUAL]=0;}
- return fail(E_PIXEL_TEST,ERROR_IO_DEVICE);
- }
- vgagop_seed_note(e,1);
- VgaGopDiag[D_STAGE]=9; VgaGopDiag[D_MAP_STATUS]=NO_ERROR;
- mi=(VIDEO_MEMORY_INFORMATION*)r->OutputBuffer;
- mi->VideoRamBase=mi->FrameBufferBase=e->MappedBase;
- mi->VideoRamLength=mi->FrameBufferLength=e->FbLength;
- ++e->MapUsers;
- r->StatusBlock->Information=sizeof(*mi);
- return NO_ERROR;
- }
- /* Use the resources of the PnP device, not a second Internal-bus claim.
- * A successful API result alone is insufficient: validate bus/slot,
- * framebuffer containment and unchanged live PCI identity/BARs.
- */
- static VP_STATUS claim_pnp(VGAGOP_EXTENSION *e,PVIDEO_PORT_CONFIG_INFO ci)
- {
- VIDEO_ACCESS_RANGE ranges[16];
- ULONG slot=0xffffffffUL,i;
- ULONGLONG base,delta;
- UCHAR cfg[64];
- VP_STATUS st;
- VgaGopPciDiag[3]=2;VgaGopPciDiag[8]=0xffffffffUL;VgaGopPciDiag[9]=0;
- VgaGopPciDiag[10]=(ULONG)e->FbPhysical;
- VgaGopPciDiag[11]=(ULONG)(e->FbPhysical>>32);
- VgaGopPciDiag[12]=e->FbLength;
- if(!ci||ci->Length<sizeof(*ci)) {VgaGopPciDiag[9]=1;return ERROR_INVALID_PARAMETER;}
- VgaGopPciDiag[4]=ci->SystemIoBusNumber;VgaGopPciDiag[5]=ci->AdapterInterfaceType;
- if(ci->AdapterInterfaceType!=PCIBus||ci->SystemIoBusNumber!=e->Record.Bus) {
- VgaGopPciDiag[9]=2;return ERROR_DEV_NOT_EXIST;
- }
- bse_zero(ranges,sizeof(ranges));
- st=VideoPortGetAccessRanges(e,0,NULL,16,ranges,NULL,NULL,&slot);
- ci->BusInterruptLevel=0;ci->BusInterruptVector=0;
- VgaGopPciDiag[6]=slot;VgaGopPciDiag[7]=(ULONG)st;
- DbgPrint("VGAGOP 1.2: PCI/PnP bus=%lu slot=%08lx GetAccessRanges=%lu FB=%08lx%08lx bytes=%08lx\n",
- ci->SystemIoBusNumber,slot,(ULONG)st,(ULONG)(e->FbPhysical>>32),(ULONG)e->FbPhysical,e->FbLength);
- if(st) {VgaGopPciDiag[9]=3;return st;}
- if(slot!=(e->Record.Device|(e->Record.Function<<5))) {
- VgaGopPciDiag[9]=4;return ERROR_DEV_NOT_EXIST;
- }
- for(i=0;i<16;i++) {
- if(ranges[i].RangeInIoSpace||!ranges[i].RangeLength)continue;
- base=(ULONGLONG)ranges[i].RangeStart.QuadPart;
- if(e->FbPhysical<base)continue;
- delta=e->FbPhysical-base;
- if(delta>ranges[i].RangeLength||e->FbLength>ranges[i].RangeLength-delta)continue;
- VgaGopPciDiag[8]=i;VgaGopPciDiag[13]=(ULONG)base;
- VgaGopPciDiag[14]=(ULONG)(base>>32);VgaGopPciDiag[15]=ranges[i].RangeLength;
- st=identify(e,cfg);
- if(st) {VgaGopPciDiag[9]=6;return st;}
- DbgPrint("VGAGOP 1.2: framebuffer is inside this PCI device's assigned memory range %lu\n",i);
- return NO_ERROR;
- }
- VgaGopPciDiag[9]=5;return ERROR_INVALID_PARAMETER;
- }
- static VP_STATUS __stdcall VgaGopFindAdapter(PVOID hw,PVOID context,PWSTR args,
- PVIDEO_PORT_CONFIG_INFO ci,PUCHAR again)
- {
- VGAGOP_EXTENSION *e=(VGAGOP_EXTENSION*)hw;
- UCHAR cfg[64];
- VIDEO_ACCESS_RANGE range;
- VP_STATUS st;
- (void)context; (void)args;
- *again=FALSE; bse_zero(e,sizeof(*e));
- VgaGopDiag[D_STAGE]=2; VgaGopDiag[D_EXTENSION]=(ULONG_PTR)e;
- if(!VgaGopRecordReady)return fail(E_GOP,ERROR_DEV_NOT_EXIST);
- e->Record=VgaGopRecord;
- if(g35_validate(&e->Record))return fail(E_GOP,ERROR_INVALID_PARAMETER);
- st=identify(e,cfg); if(st)return st;
- e->GopValid=1;
- e->FbPhysical=e->Record.Gop.FrameBufferBase;
- e->FbLength=e->Record.Gop.PixelsPerScanLine*4*e->Record.Gop.Height;
- VgaGopDiag[D_GOP_FLAGS]=e->Record.Gop.Flags;
- VgaGopDiag[D_GOP_FB_LO]=(ULONG)e->FbPhysical;
- VgaGopDiag[D_GOP_FB_HI]=(ULONG)(e->FbPhysical>>32);
- bse_zero(&range,sizeof(range));
- range.RangeStart.QuadPart=e->FbPhysical;range.RangeLength=e->FbLength;
- range.RangeVisible=1;
- VgaGopDiag[D_STAGE]=4;
- if((e->FbPhysical>>32)==0)st=claim_pnp(e,ci);
- else {
- VgaGopPciDiag[3]=1;
- st=VideoPortVerifyAccessRanges(hw,1,&range);
- }
- VgaGopDiag[D_CLAIM_STATUS]=(ULONG)st;
- /* Retain the BSE4 high-MMIO workaround ONLY after the checksummed CSM
- * record, PCI owner, all six live BAR DWORDs and memory decode match.
- * With a low physical range a claim failure is a hard stop. */
- if(st && (e->FbPhysical>>32)==0) {
- DbgPrint("VGAGOP 1.2: PnP resource validation rejected, detail=%lu\n",VgaGopPciDiag[9]);
- /* Relinquish a successfully obtained claim when later validation
- * rejects this adapter. Never release on a failed retrieval. */
- if(VgaGopPciDiag[7]==0 && VgaGopPciDiag[9]>=4)
- VideoPortVerifyAccessRanges(hw,0,NULL);
- return fail(E_CLAIM,st);
- }
- if(st)DbgPrint("VGAGOP: high resource claim=%lu; verified firmware owner and unchanged BARs\n",(ULONG)st);
- e->Claimed=1;
- VgaGopDiag[D_FB_PHYSICAL]=(ULONG)e->FbPhysical;VgaGopDiag[D_FB_LENGTH]=e->FbLength;
- DbgPrint("VGAGOP: PCI %lu:%lu.%lu ID=%08lx mode=%lux%lu pitch=%lu FB=%08lx%08lx\n",
- e->Record.Bus,e->Record.Device,e->Record.Function,e->Record.PciId,
- e->Record.Gop.Width,e->Record.Gop.Height,e->Record.Gop.PixelsPerScanLine*4,
- (ULONG)(e->FbPhysical>>32),(ULONG)e->FbPhysical);
- return NO_ERROR;
- }
- static BOOLEAN __stdcall VgaGopInitialize(PVOID hw)
- {
- VGAGOP_EXTENSION *e=(VGAGOP_EXTENSION*)hw;
- VgaGopDiag[D_STAGE]=5;
- return (BOOLEAN)(e->Claimed && e->GopValid);
- }
- static BOOLEAN __stdcall VgaGopResetHw(PVOID hw,ULONG columns,ULONG rows)
- {
- (void)hw; (void)columns; (void)rows;
- return TRUE; /* Preserve firmware scanout; no VGA or INT10 transition. */
- }
- /* This firmware-scanout driver cannot restore GPU state after sleep.
- * Advertise only On and Shutdown. No fake successful D3/resume operation. */
- static VP_STATUS __stdcall VgaGopPower(PVOID hw,ULONG id,VIDEO_POWER_MANAGEMENT *p)
- {
- (void)hw;
- if(!p||p->Length<sizeof(*p))return ERROR_INVALID_PARAMETER;
- if(id!=0xffffffffUL&&id!=1)return ERROR_INVALID_PARAMETER;
- return (p->PowerState==1||p->PowerState==6)?NO_ERROR:ERROR_INVALID_FUNCTION;
- }
- static VP_STATUS __stdcall VgaGopChild(PVOID hw,VIDEO_CHILD_ENUM_INFO *info,
- PULONG type,PUCHAR descriptor,PULONG uid,PULONG unused)
- {
- (void)hw;(void)descriptor;
- if(unused)*unused=0;
- if(!info||info->Size<sizeof(*info)||!type||!uid||!unused)return 1248L;
- if(info->ChildIndex==0xffffffffUL) {*type=3;*uid=0xffffffffUL;return 1246L;}
- if(info->ChildIndex==1) {*type=1;*uid=1;return 1246L;}
- return 1248L; /* One firmware-selected monitor; no fabricated EDID. */
- }
- static BOOLEAN __stdcall VgaGopStartIO(PVOID hw,PVIDEO_REQUEST_PACKET r)
- {
- VGAGOP_EXTENSION *e=(VGAGOP_EXTENSION*)hw;
- VP_STATUS st=ERROR_INVALID_FUNCTION;
- ULONG i,mode,need;
- PVOID requested;
- VIDEO_NUM_MODES *n;
- if(!r || !r->StatusBlock) return FALSE;
- r->StatusBlock->Information=0;
- /* A diagnostic read must not overwrite the last operational error. */
- if(r->IoControlCode==G35_IOCTL_DIAG) {
- if(!r->OutputBuffer||r->OutputBufferLength<sizeof(G35_DIAG_PACKET))st=ERROR_INSUFFICIENT_BUFFER;
- else if(vgagop_cas(&e->Busy,1,0))st=ERROR_BUSY;
- else {
- vgagop_snapshot(e,(G35_DIAG_PACKET*)r->OutputBuffer);
- r->StatusBlock->Information=sizeof(G35_DIAG_PACKET);st=NO_ERROR;
- vgagop_fence();(void)vgagop_cas(&e->Busy,0,1);
- }
- r->StatusBlock->u.Status=st;return TRUE;
- }
- VgaGopDiag[D_IOCTL]=r->IoControlCode;
- i=VgaGopDiag[D_HISTORY_NEXT]++ & 15;
- VgaGopDiag[D_HISTORY+i]=r->IoControlCode;
- if(vgagop_cas(&e->Busy,1,0)) {
- r->StatusBlock->u.Status=fail(E_LOCK,ERROR_BUSY); return TRUE;
- }
- VgaGopDiag[D_LOCK]=1;
- switch(r->IoControlCode) {
- case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
- if(!r->OutputBuffer || r->OutputBufferLength<sizeof(VIDEO_NUM_MODES)) {st=ERROR_INSUFFICIENT_BUFFER; break;}
- n=(VIDEO_NUM_MODES*)r->OutputBuffer;
- n->NumModes=BSE_MODECOUNT; n->ModeInformationLength=sizeof(VIDEO_MODE_INFORMATION);
- r->StatusBlock->Information=sizeof(*n); st=NO_ERROR; break;
- case IOCTL_VIDEO_QUERY_AVAIL_MODES:
- need=BSE_MODECOUNT*sizeof(VIDEO_MODE_INFORMATION);
- if(!r->OutputBuffer || r->OutputBufferLength<need) {st=ERROR_INSUFFICIENT_BUFFER; break;}
- for(i=0;i<BSE_MODECOUNT;i++) fill_mode(e,(VIDEO_MODE_INFORMATION*)r->OutputBuffer+i,i);
- r->StatusBlock->Information=need; st=NO_ERROR; break;
- case IOCTL_VIDEO_QUERY_CURRENT_MODE:
- if(!r->OutputBuffer || r->OutputBufferLength<sizeof(VIDEO_MODE_INFORMATION)) {st=ERROR_INSUFFICIENT_BUFFER; break;}
- fill_mode(e,(VIDEO_MODE_INFORMATION*)r->OutputBuffer,e->CurrentMode);
- r->StatusBlock->Information=sizeof(VIDEO_MODE_INFORMATION); st=NO_ERROR; break;
- case IOCTL_VIDEO_SET_CURRENT_MODE:
- if(!r->InputBuffer || r->InputBufferLength<sizeof(VIDEO_MODE)) {st=ERROR_INSUFFICIENT_BUFFER; break;}
- mode=((VIDEO_MODE*)r->InputBuffer)->RequestedMode&0x3FFFFFFFUL;
- if(mode>=BSE_MODECOUNT) {st=ERROR_INVALID_PARAMETER; break;}
- ++VgaGopDiag[D_SET_COUNT]; st=NO_ERROR;
- e->CurrentMode=mode; VgaGopDiag[D_MODE]=mode;
- break;
- case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
- st=map_fb(e,r); break;
- case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
- if(!r->InputBuffer || r->InputBufferLength<sizeof(VIDEO_MEMORY)) {st=ERROR_INSUFFICIENT_BUFFER; break;}
- requested=((VIDEO_MEMORY*)r->InputBuffer)->RequestedVirtualAddress;
- if(requested && requested!=e->MappedBase) {st=ERROR_INVALID_PARAMETER; break;}
- if(!e->MapUsers){st=ERROR_INVALID_PARAMETER;break;}
- --e->MapUsers;
- if(!e->MapUsers && e->MappedBase) {unmap_high_fb(e); ++VgaGopDiag[D_UNMAP_COUNT];VgaGopDiag[D_FB_VIRTUAL]=0;}
- st=NO_ERROR; break;
- case IOCTL_VIDEO_RESET_DEVICE:
- st=NO_ERROR; break;
- default:
- break; /* Optional pointer/color IOCTLs: framebuf uses software/defaults. */
- }
- r->StatusBlock->u.Status=st; VgaGopDiag[D_STATUS]=(ULONG)st;
- VgaGopDiag[D_LOCK]=0; vgagop_fence(); (void)vgagop_cas(&e->Busy,0,1);
- return TRUE;
- }
- static ULONG __stdcall VgaGopStart(PVOID context1,PVOID context2)
- {
- VIDEO_HW_INITIALIZATION_DATA init;
- ULONG status;
- bse_zero(&init,sizeof(init));
- VgaGopDiag[D_STAGE]=1;
- init.HwInitDataSize=sizeof(init); init.AdapterInterfaceType=Internal;
- init.HwFindAdapter=VgaGopFindAdapter; init.HwInitialize=VgaGopInitialize;
- init.HwStartIO=VgaGopStartIO; init.HwResetHw=VgaGopResetHw;
- init.HwDeviceExtensionSize=sizeof(VGAGOP_EXTENSION);
- /* Keep the high-address workaround's entry path; low MMIO uses PnP.
- * XP recognizes PnP miniports through these three callbacks. */
- if((VgaGopRecord.Gop.FrameBufferBase>>32)==0) {
- init.AdapterInterfaceType=PCIBus;
- init.HwSetPowerState=VgaGopPower;init.HwGetPowerState=VgaGopPower;
- init.HwGetVideoChildDescriptor=VgaGopChild;
- VgaGopPciDiag[3]=2;
- } else VgaGopPciDiag[3]=1;
- DbgPrint("VGAGOP 1.2 / CSM36: resource path=%lu (1=legacy high, 2=PCI/PnP low)\n",VgaGopPciDiag[3]);
- status=VideoPortInitialize(context1,context2,&init,NULL);
- VgaGopDiag[D_ENTRY_STATUS]=status;
- if(status) DbgPrint("VGAGOP: VideoPortInitialize failed, NTSTATUS=%08lx\n",status);
- return status;
- }
- /* DriverEntry in the ORIGINAL vga.c calls this before its legacy code. */
- int __stdcall VgaGopTryStart(PVOID context1,PVOID context2,PULONG status)
- {
- int found;
- VgaGopRecordReady=0;
- found=read_handoff();
- if(!found)return 0;
- if(found<0){
- VgaGopDiag[D_ERROR]=E_GOP;
- DbgPrint("VGAGOP: invalid, ambiguous or old CSM handoff. Need matching csm35/csm36 handoff. Legacy VGA path blocked.\n");
- *status=0xc000000dUL;return 1;
- }
- VgaGopRecordReady=1;
- *status=VgaGopStart(context1,context2);
- return 1;
- }
Advertisement
Add Comment
Please, Sign In to add comment