VP_STATUS NTAPI VbeSetColorLookup(IN PHW_DEVICE_EXTENSION VgaExtension, IN PVIDEO_CLUT ClutBuffer) { PVBE_COLOR_REGISTER VesaClut; INT10_BIOS_ARGUMENTS BiosArguments; PVOID Context; ULONG Entries; ULONG BufferSize = 4 * 1024; USHORT TrampolineMemorySegment, TrampolineMemoryOffset; VP_STATUS Status; USHORT i; Entries = ClutBuffer->NumEntries; /* Allocate INT10 context/buffer */ VesaClut = VideoPortAllocatePool(VgaExtension, 1, sizeof(ULONG) * Entries, 0x20616756u); if (!VesaClut) return ERROR_INVALID_PARAMETER; if (!VgaExtension->Int10Interface.Size) return ERROR_INVALID_PARAMETER; Context = VgaExtension->Int10Interface.Context; Status = VgaExtension->Int10Interface.Int10AllocateBuffer(Context, &TrampolineMemorySegment, &TrampolineMemoryOffset, &BufferSize); if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER; /* VESA has color registers backward! */ for (i = 0; i < Entries; i++) { VesaClut[i].Blue = ClutBuffer->LookupTable[i].RgbArray.Blue; VesaClut[i].Green = ClutBuffer->LookupTable[i].RgbArray.Green; VesaClut[i].Red = ClutBuffer->LookupTable[i].RgbArray.Red; VesaClut[i].Pad = 0; } Status = VgaExtension->Int10Interface.Int10WriteMemory(Context, TrampolineMemorySegment, TrampolineMemoryOffset, VesaClut, Entries * sizeof(ULONG)); if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER; /* Write new palette */ BiosArguments.Ebx = 0; BiosArguments.Ecx = Entries; BiosArguments.Edx = ClutBuffer->FirstEntry; BiosArguments.Edi = TrampolineMemoryOffset; BiosArguments.SegEs = TrampolineMemorySegment; BiosArguments.Eax = VBE_SET_GET_PALETTE_DATA; Status = VgaExtension->Int10Interface.Int10CallBios(Context, &BiosArguments); if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER; VideoPortFreePool(VgaExtension, VesaClut); VideoPortDebugPrint(Error, "VBE Status: %lx\n", BiosArguments.Eax); if (BiosArguments.Eax == VBE_SUCCESS) return NO_ERROR; return ERROR_INVALID_PARAMETER; }
BOOLEAN NTAPI VBEInitialize(PVOID HwDeviceExtension) { INT10_BIOS_ARGUMENTS BiosRegisters; VP_STATUS Status; PVBE_DEVICE_EXTENSION VBEDeviceExtension = (PVBE_DEVICE_EXTENSION)HwDeviceExtension; ULONG Length; ULONG ModeCount; ULONG SuitableModeCount; USHORT ModeTemp; ULONG CurrentMode; PVBE_MODEINFO VbeModeInfo; /* * Get the Int 10 interface that we will use for allocating real * mode memory and calling the video BIOS. */ VBEDeviceExtension->Int10Interface.Version = VIDEO_PORT_INT10_INTERFACE_VERSION_1; VBEDeviceExtension->Int10Interface.Size = sizeof(VIDEO_PORT_INT10_INTERFACE); Status = VideoPortQueryServices( HwDeviceExtension, VideoPortServicesInt10, (PINTERFACE)&VBEDeviceExtension->Int10Interface); if (Status != NO_ERROR) { VideoPortDebugPrint(Error, "Failed to get Int 10 service functions (Status %x)\n", Status); return FALSE; } /* * Allocate a bit of memory that will be later used for VBE transport * buffer. This memory must be accessible from V86 mode so it must fit * in the first megabyte of physical memory. */ Length = 0x400; Status = VBEDeviceExtension->Int10Interface.Int10AllocateBuffer( VBEDeviceExtension->Int10Interface.Context, &VBEDeviceExtension->TrampolineMemorySegment, &VBEDeviceExtension->TrampolineMemoryOffset, &Length); if (Status != NO_ERROR) { VideoPortDebugPrint(Error, "Failed to allocate virtual memory (Status %x)\n", Status); return FALSE; } /* * Get the VBE general information. */ VBEDeviceExtension->Int10Interface.Int10WriteMemory( VBEDeviceExtension->Int10Interface.Context, VBEDeviceExtension->TrampolineMemorySegment, VBEDeviceExtension->TrampolineMemoryOffset, "VBE2", 4); VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); BiosRegisters.Eax = VBE_GET_CONTROLLER_INFORMATION; BiosRegisters.Edi = VBEDeviceExtension->TrampolineMemoryOffset; BiosRegisters.SegEs = VBEDeviceExtension->TrampolineMemorySegment; VBEDeviceExtension->Int10Interface.Int10CallBios( VBEDeviceExtension->Int10Interface.Context, &BiosRegisters); if (VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS) { VBEDeviceExtension->Int10Interface.Int10ReadMemory( VBEDeviceExtension->Int10Interface.Context, VBEDeviceExtension->TrampolineMemorySegment, VBEDeviceExtension->TrampolineMemoryOffset, &VBEDeviceExtension->VbeInfo, sizeof(VBEDeviceExtension->VbeInfo)); /* Verify the VBE signature. */ if (VideoPortCompareMemory(VBEDeviceExtension->VbeInfo.Signature, "VESA", 4) != 4) { VideoPortDebugPrint(Error, "No VBE BIOS present\n"); return FALSE; } VideoPortDebugPrint(Trace, "VBE BIOS Present (%d.%d, %8ld Kb)\n", VBEDeviceExtension->VbeInfo.Version / 0x100, VBEDeviceExtension->VbeInfo.Version & 0xFF, VBEDeviceExtension->VbeInfo.TotalMemory * 64); #ifdef VBE12_SUPPORT if (VBEDeviceExtension->VbeInfo.Version < 0x102) #else if (VBEDeviceExtension->VbeInfo.Version < 0x200) #endif { VideoPortDebugPrint(Error, "VBE BIOS present, but incompatible version %d.%d\n", VBEDeviceExtension->VbeInfo.Version / 0x100, VBEDeviceExtension->VbeInfo.Version & 0xFF); return FALSE; } } else { VideoPortDebugPrint(Error, "No VBE BIOS found.\n"); return FALSE; } /* * Build a mode list here that can be later used by * IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES and IOCTL_VIDEO_QUERY_AVAIL_MODES * calls. */ /* * Get the number of supported video modes. * * No need to be map the memory. It's either in the video BIOS memory or * in our trampoline memory. In either case the memory is already mapped. */ for (ModeCount = 0; ; ModeCount++) { /* Read the VBE mode number. */ VBEDeviceExtension->Int10Interface.Int10ReadMemory( VBEDeviceExtension->Int10Interface.Context, HIWORD(VBEDeviceExtension->VbeInfo.VideoModePtr), LOWORD(VBEDeviceExtension->VbeInfo.VideoModePtr) + (ModeCount << 1), &ModeTemp, sizeof(ModeTemp)); /* End of list? */ if (ModeTemp == 0xFFFF || ModeTemp == 0) break; } /* * Allocate space for video modes information. */ VBEDeviceExtension->ModeInfo = VideoPortAllocatePool(HwDeviceExtension, VpPagedPool, ModeCount * sizeof(VBE_MODEINFO), TAG_VBE); VBEDeviceExtension->ModeNumbers = VideoPortAllocatePool(HwDeviceExtension, VpPagedPool, ModeCount * sizeof(USHORT), TAG_VBE); /* * Get the actual mode infos. */ for (CurrentMode = 0, SuitableModeCount = 0; CurrentMode < ModeCount; CurrentMode++) { /* Read the VBE mode number. */ VBEDeviceExtension->Int10Interface.Int10ReadMemory( VBEDeviceExtension->Int10Interface.Context, HIWORD(VBEDeviceExtension->VbeInfo.VideoModePtr), LOWORD(VBEDeviceExtension->VbeInfo.VideoModePtr) + (CurrentMode << 1), &ModeTemp, sizeof(ModeTemp)); /* Call VBE BIOS to read the mode info. */ VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); BiosRegisters.Eax = VBE_GET_MODE_INFORMATION; BiosRegisters.Ecx = ModeTemp; BiosRegisters.Edi = VBEDeviceExtension->TrampolineMemoryOffset + 0x200; BiosRegisters.SegEs = VBEDeviceExtension->TrampolineMemorySegment; VBEDeviceExtension->Int10Interface.Int10CallBios( VBEDeviceExtension->Int10Interface.Context, &BiosRegisters); /* Read the VBE mode info. */ VBEDeviceExtension->Int10Interface.Int10ReadMemory( VBEDeviceExtension->Int10Interface.Context, VBEDeviceExtension->TrampolineMemorySegment, VBEDeviceExtension->TrampolineMemoryOffset + 0x200, VBEDeviceExtension->ModeInfo + SuitableModeCount, sizeof(VBE_MODEINFO)); VbeModeInfo = VBEDeviceExtension->ModeInfo + SuitableModeCount; /* Is this mode acceptable? */ if (VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS && VbeModeInfo->XResolution >= 640 && VbeModeInfo->YResolution >= 480 && (VbeModeInfo->MemoryModel == VBE_MEMORYMODEL_PACKEDPIXEL || VbeModeInfo->MemoryModel == VBE_MEMORYMODEL_DIRECTCOLOR) && VbeModeInfo->PhysBasePtr != 0) { if (VbeModeInfo->ModeAttributes & VBE_MODEATTR_LINEAR) { /* Bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 */ // if (ModeTemp & 0x4000) //{ VBEDeviceExtension->ModeNumbers[SuitableModeCount] = ModeTemp | 0x4000; SuitableModeCount++; //} } #ifdef VBE12_SUPPORT else { VBEDeviceExtension->ModeNumbers[SuitableModeCount] = ModeTemp; SuitableModeCount++; } #endif } } if (SuitableModeCount == 0) { VideoPortDebugPrint(Warn, "VBEMP: No video modes supported\n"); return FALSE; } VBEDeviceExtension->ModeCount = SuitableModeCount; /* * Sort the video mode list according to resolution and bits per pixel. */ VBESortModes(VBEDeviceExtension); /* * Print the supported video modes. */ for (CurrentMode = 0; CurrentMode < SuitableModeCount; CurrentMode++) { VideoPortDebugPrint(Trace, "%dx%dx%d\n", VBEDeviceExtension->ModeInfo[CurrentMode].XResolution, VBEDeviceExtension->ModeInfo[CurrentMode].YResolution, VBEDeviceExtension->ModeInfo[CurrentMode].BitsPerPixel); } /* * Enumerate our children. */ VideoPortEnumerateChildren(HwDeviceExtension, NULL); return TRUE; }
VP_STATUS NTAPI VbeSetColorLookup(IN PHW_DEVICE_EXTENSION VgaExtension, IN PVIDEO_CLUT ClutBuffer) { PVBE_COLOR_REGISTER VesaClut; INT10_BIOS_ARGUMENTS BiosArguments; PVOID Context; ULONG Entries; ULONG BufferSize = 4 * 1024; USHORT TrampolineMemorySegment, TrampolineMemoryOffset; VP_STATUS Status; USHORT i; PVIDEOMODE CurrentMode = VgaExtension->CurrentMode; Entries = ClutBuffer->NumEntries; VideoDebugPrint((0, "Setting %lu entries.\n", Entries)); /* * For Vga compatible modes, write them directly. * Otherwise, the LGPL VGABIOS (used in bochs) fails! * It is also said that this way is faster. */ if(!CurrentMode->NonVgaMode) { for (i=ClutBuffer->FirstEntry; i<ClutBuffer->FirstEntry + Entries; i++) { VideoPortWritePortUchar((PUCHAR)0x03c8, i); VideoPortWritePortUchar((PUCHAR)0x03c9, ClutBuffer->LookupTable[i].RgbArray.Red); VideoPortWritePortUchar((PUCHAR)0x03c9, ClutBuffer->LookupTable[i].RgbArray.Green); VideoPortWritePortUchar((PUCHAR)0x03c9, ClutBuffer->LookupTable[i].RgbArray.Blue); } return NO_ERROR; } /* Allocate INT10 context/buffer */ VesaClut = VideoPortAllocatePool(VgaExtension, 1, sizeof(ULONG) * Entries, ' agV'); if (!VesaClut) return ERROR_INVALID_PARAMETER; if (!VgaExtension->Int10Interface.Size) return ERROR_INVALID_PARAMETER; Context = VgaExtension->Int10Interface.Context; Status = VgaExtension->Int10Interface.Int10AllocateBuffer(Context, &TrampolineMemorySegment, &TrampolineMemoryOffset, &BufferSize); if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER; /* VESA has color registers backward! */ for (i = 0; i < Entries; i++) { VesaClut[i].Blue = ClutBuffer->LookupTable[i].RgbArray.Blue; VesaClut[i].Green = ClutBuffer->LookupTable[i].RgbArray.Green; VesaClut[i].Red = ClutBuffer->LookupTable[i].RgbArray.Red; VesaClut[i].Pad = 0; } Status = VgaExtension->Int10Interface.Int10WriteMemory(Context, TrampolineMemorySegment, TrampolineMemoryOffset, VesaClut, Entries * sizeof(ULONG)); if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER; /* Write the palette */ VideoPortZeroMemory(&BiosArguments, sizeof(BiosArguments)); BiosArguments.Ebx = 0; BiosArguments.Ecx = Entries; BiosArguments.Edx = ClutBuffer->FirstEntry; BiosArguments.Edi = TrampolineMemoryOffset; BiosArguments.SegEs = TrampolineMemorySegment; BiosArguments.Eax = VBE_SET_GET_PALETTE_DATA; Status = VgaExtension->Int10Interface.Int10CallBios(Context, &BiosArguments); if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER; VideoPortFreePool(VgaExtension, VesaClut); VideoDebugPrint((Error, "VBE Status: %lx\n", BiosArguments.Eax)); if (VBE_GETRETURNCODE(BiosArguments.Eax) == VBE_SUCCESS) return NO_ERROR; return ERROR_INVALID_PARAMETER; }