/* #pragma comment(exestr, "@(#) NEC(MIPS) jxdisp.c 1.2 95/10/17 01:18:22" ) */ /*++ Copyright (c) 1995 NEC Corporation Copyright (c) 1991-1993 Microsoft Corporation Module Name: jxdisp.c Abstract: This module implements the HAL display initialization and output routines for a R4400 R94A system. History: --*/ /* * New Code for 3.51 * * M001 kuriyama@oa2.kb.nec.co.jp Fri Jul 14 11:46:06 JST 1995 * -change textmode 80x50 * * M002 kuriyama@oa2.kb.nec.co.jp Tue Jul 18 15:36:23 JST 1995 * -change for fw interface * * M003 kuriyama@oa2.kb.nec.co.jp Fri Jul 21 14:14:54 JST 1995 * -add call HalpResetDisplayParameters * for bug fix DPI board panic message * * M004 kuriyama@oa2.kb.nec.co.jp Wed Aug 2 14:28:28 JST 1995 * -add ESM critical error logging * * S005 kuriyama@oa2.kb.nec.co.jp Wed Aug 23 23:42:59 JST 1995 * -change for scroll bug fix * * S006 nishi@oa2.kb.nec.co.jp Mon Sep 4 18:42:00 JST 1995 * -change for GLINT new revision board * R01=00,R02=02 * M007 nishi@oa2.kb.nec.co.jp Mon Sep 18 18:42:00 JST 1995 * - Add Software Power Off, when system panic is occured * * M008 nishi@oa2.kb.nec.co.jp Mon Sep 18 18:42:00 JST 1995 * - Change Logic for resume fixed TLB for DMA * * M009 kuriyama@oa2.kbnes.nec.co.jp Mon Sep 18 19:58:22 JST 1995 * - bug fix for tga 800x600 72Hz * * M010 v-akitk@microsoft.com * - Change for Software Power Supply(R96B) * */ #include "halp.h" #include "jazzvdeo.h" #include "jzvxl484.h" #include #include "cirrus.h" #include "modeset.h" #include "mode542x.h" #include #include #include #include "string.h" #include "pci.h" /* START M007 */ #define HEADER_FILE #include "kxmips.h" /* START M007 */ // // Put all code for HAL initialization in the INIT section. It will be // deallocated by memory management when phase 1 initialization is // completed. // #if defined(ALLOC_PRAGMA) #pragma alloc_text(INIT, HalpInitializeDisplay0) #pragma alloc_text(INIT, HalpInitializeDisplay1) #endif // // for x86bios emulate // PCHAR K351UseBios=NULL; VOID HalpCopyROMs(VOID); PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters; // M003 typedef VOID (*PHALP_CONTROLLER_SETUP) ( VOID ); typedef VOID (*PHALP_DISPLAY_CHARACTER) ( UCHAR ); typedef VOID (*PHALP_SCROLL_SCREEN) ( UCHAR ); #define TAB_SIZE 4 #define TEXT_ATTR 0x1F // // Define forward referenced procedure prototypes. // VOID HalpDisplayINT10Setup ( VOID); VOID HalpOutputCharacterINT10 ( IN UCHAR Character ); VOID HalpScrollINT10 ( IN UCHAR line ); VOID HalpDisplayCharacterVGA ( IN UCHAR Character ); BOOLEAN HalpInitializeX86DisplayAdapter( VOID ); PHALP_DISPLAY_CHARACTER HalpDisplayCharacter = NULL; // // Define forward referenced procedure prototypes. // VOID HalpDisplayCharacterOld ( IN UCHAR Character ); VOID HalpOutputCharacterOld( IN PUCHAR Glyph ); VOID HalpDisplayCirrusSetup ( VOID ); BOOLEAN HalpCirrusInterpretCmdStream ( PUSHORT pusCmdStream ); VOID HalpDisplayTgaSetup ( VOID ); /* VOID RGB525_WRITE( ULONG dac, ULONG offset, UCHAR data); VOID RGB525_SET_REG( ULONG dac, ULONG index, UCHAR data); */ VOID HalpDisplayGlintSetup( VOID ); VOID Write_Dbg_Uchar( PUCHAR, UCHAR ); // // Must use 32Bit transfer. RtlMoveMemory() uses 64Bit transfer. // VOID HalpMoveMemory32 ( PUCHAR Destination, PUCHAR Source, ULONG Length ); /* Start M007 */ VOID HalpMrcModeChange( UCHAR Mode ); /*End M007 */ // // Define virtual address of the video memory and control registers. // #define VIDEO_MEMORY_BASE 0x40000000 // // Define memory access constants for VXL // #define CIRRUS_BASE ((PJAGUAR_REGISTERS)0x403ff000) #define CIRRUS_OFFSET ((PUSHORT)0x3b0) #define TGA_REGISTER_BASE ((ULONG)0x403ff000) #define R94A_PCI_ADDR_REG ((PULONG)(0x80000518 | 0xffffc000)) #define R94A_PCI_DATA_REG ((PULONG)(0x80000520 | 0xffffc000)) #define GLINT_CONTROL_REGISTER_BASE ((ULONG)0x403ff000) // M021 #define GLINT_VIDEO_REGISTER_BASE ((ULONG)0x403fe000) #define RGB525_REGISTER_BASE ((ULONG)0x403fd000) // // Define controller setup routine type. // typedef VOID (*PHALP_CONTROLLER_SETUP) ( VOID ); // // Define OEM font variables. // ULONG HalpBytesPerRow; ULONG HalpCharacterHeight; ULONG HalpCharacterWidth; ULONG HalpColumn; ULONG HalpDisplayText; ULONG HalpDisplayWidth; POEM_FONT_FILE_HEADER HalpFontHeader; ULONG HalpRow; ULONG HalpScrollLength; ULONG HalpScrollLine; ULONG HalpGlintRevisionId; // S006 // // Define display variables. // BOOLEAN HalpDisplayOwnedByHal; ENTRYLO HalpDisplayPte; ULONG HalpDisplayControlBase = 0; ULONG HalpDisplayMemoryBase = 0; // M021 ULONG HalpDisplayResetRegisterBase = 0; ULONG HalpDisplayVxlClockRegisterBase = 0; ULONG HalpDisplayVxlBt484RegisterBase = 0; ULONG HalpDisplayVxlJaguarRegisterBase = 0; PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL; MONITOR_CONFIGURATION_DATA HalpMonitorConfigurationData; BOOLEAN HalpDisplayTypeUnknown = FALSE; ULONG HalpG364Type = 0; LARGE_INTEGER HalpCirrusPhigicalVideo = {0,0}; LARGE_INTEGER HalpTgaPhigicalVideo = {0,0}; LARGE_INTEGER HalpTgaPhigicalVideoCont = {0,0}; LARGE_INTEGER HalpGlintPhygicalVideo = {0,0}; LARGE_INTEGER HalpGlintPhygicalVideoCont = {0,0}; ULONG HalpDisplayPCIDevice = FALSE; ULONG HalpDisplayType16BPP = FALSE; PVOID HalpMrcControlBase = NULL; // M007 BOOLEAN HalpMrcControlMapped = FALSE; // M007 typedef struct _R94A_PCI_CONFIGURATION_ADDRESS_REG{ ULONG Reserved2: 2; ULONG RegisterNumber: 6; ULONG FunctionNumber: 3; ULONG DeviceNumber: 5; ULONG BusNumber: 8; ULONG Reserved1: 7; ULONG ConfigEnable: 1; } R94A_PCI_CONFIGURATION_ADDRESS_REG, *PR94A_PCI_CONFIGURATION_ADDRESS_REG; VOID HalpReadPCIConfigUlongByOffset ( IN PCI_SLOT_NUMBER Slot, IN PULONG Buffer, IN ULONG Offset ); BOOLEAN HalpCheckPCIDevice ( IN PCI_SLOT_NUMBER Slot ); BOOLEAN HalpInitializeDisplay0 ( IN PLOADER_PARAMETER_BLOCK LoaderBlock ) /*++ Routine Description: This routine maps the video memory and control registers into the user part of the idle process address space, initializes the video control registers, and clears the video screen. Arguments: LoaderBlock - Supplies a pointer to the loader parameter block. Return Value: If the initialization is successfully completed, than a value of TRUE is returned. Otherwise, a value of FALSE is returned. --*/ { PCONFIGURATION_COMPONENT_DATA Child; PCONFIGURATION_COMPONENT_DATA ConfigurationEntry; POEM_FONT_FILE_HEADER FontHeader; ULONG Index; ULONG MatchKey; PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor; PLIST_ENTRY NextEntry; PENTRYLO PageFrame; ENTRYLO Pte; ULONG StartingPfn; PCI_SLOT_NUMBER Slot; ULONG ReadValue; PCHAR Options; // // Set the address of the font file header and compute display variables. // // N.B. The font information suppled by the OS Loader is used during phase // 0 initialization. During phase 1 initialization, a pool buffer is // allocated and the font information is copied from the OS Loader // heap into pool. // FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile; HalpFontHeader = FontHeader; HalpBytesPerRow = (FontHeader->PixelWidth + 7) / 8; HalpCharacterHeight = FontHeader->PixelHeight; HalpCharacterWidth = FontHeader->PixelWidth; #if defined(_X86_DBG_) DbgPrint("\n DISP 0\n"); //DBGDBG #endif // _X86_DBG_ // // Find the configuration entry for the first display controller. // MatchKey = 0; ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot, ControllerClass, DisplayController, &MatchKey); if (ConfigurationEntry == NULL) { MatchKey = 1; ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot, ControllerClass, DisplayController, &MatchKey); if (ConfigurationEntry == NULL) { return FALSE; } } // // Determine which video controller is present in the system. // Copy the display controller and monitor parameters in case they are // needed later to reinitialize the display to output a message. // if (LoaderBlock->LoadOptions != NULL) { Options = LoaderBlock->LoadOptions; _strupr(Options); K351UseBios = strstr(Options, "USEBIOS"); } if(K351UseBios!=NULL){ DbgPrint("\nUSEBIOS---\n"); HalpDisplayControllerSetup = HalpDisplayINT10Setup; HalpDisplayCharacter = HalpDisplayCharacterVGA; HalpDisplayControlBase = 0x90000000; }else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier, "necvdfrb")) { HalpDisplayControllerSetup = HalpDisplayCirrusSetup; HalpDisplayCharacter = HalpDisplayCharacterOld; HalpDisplayControlBase = 0x90000000; } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"10110004")) { // // for DEC21030 PCI // HalpDisplayControllerSetup = HalpDisplayTgaSetup; HalpDisplayCharacter = HalpDisplayCharacterOld; HalpDisplayPCIDevice = TRUE; Slot.u.bits.FunctionNumber = 0; for (Slot.u.bits.DeviceNumber = 3; Slot.u.bits.DeviceNumber < 6; Slot.u.bits.DeviceNumber++){ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0); if (ReadValue == 0x00041011){ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x4); if ((ReadValue & 0x00000002) == 0x2){ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10); HalpDisplayControlBase = (ReadValue & 0xfffffff0) + TGA_REG_SPC_OFFSET; } else { return FALSE; } } } } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"3D3D0001")) { // // for GLINT 300SX PCI // HalpDisplayControllerSetup = HalpDisplayGlintSetup; HalpDisplayCharacter = HalpDisplayCharacterOld; HalpDisplayPCIDevice = TRUE; HalpDisplayType16BPP = TRUE; // // FunctionNumber always zero // Slot.u.bits.FunctionNumber = 0; for (Slot.u.bits.DeviceNumber = 3; Slot.u.bits.DeviceNumber < 6; Slot.u.bits.DeviceNumber++){ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0); if (ReadValue == 0x00013d3d){ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x4); // // GLINT 300SX has no I/O space regions // if (ReadValue & 0x2){ // // Control Registers // HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10); HalpDisplayControlBase = (ReadValue & 0xfffffff0); // // Framebuffer // HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x18); HalpDisplayMemoryBase = (ReadValue & 0xfffffff0); // // Revision ID // HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x08); // S006 HalpGlintRevisionId = (ReadValue & 0x000000ff); } else { return FALSE; } } } } else { // M002 +++ HalpDisplayControllerSetup = HalpDisplayINT10Setup; HalpDisplayCharacter = HalpDisplayCharacterVGA; HalpDisplayControlBase = 0x90000000; HalpDisplayTypeUnknown = TRUE; // M002 --- } Child = ConfigurationEntry->Child; RtlMoveMemory((PVOID)&HalpMonitorConfigurationData, Child->ConfigurationData, Child->ComponentEntry.ConfigurationDataLength); // // Compute character output display parameters. // HalpDisplayText = HalpMonitorConfigurationData.VerticalResolution / HalpCharacterHeight; if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){ HalpScrollLine = 1024 * HalpCharacterHeight; } else if (HalpDisplayType16BPP) { HalpScrollLine = HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight * sizeof(USHORT); } else { HalpScrollLine = HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight; } HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1); if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){ HalpDisplayWidth = 1024 / HalpCharacterWidth; }else{ HalpDisplayWidth = HalpMonitorConfigurationData.HorizontalResolution / HalpCharacterWidth; } // // Scan the memory allocation descriptors and allocate a free page // to map the video memory and control registers, and initialize the // PDE entry. // NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink; while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) { MemoryDescriptor = CONTAINING_RECORD(NextEntry, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry); if ((MemoryDescriptor->MemoryType == LoaderFree) && (MemoryDescriptor->PageCount > 1)) { StartingPfn = MemoryDescriptor->BasePage; MemoryDescriptor->BasePage += 1; MemoryDescriptor->PageCount -= 1; break; } NextEntry = NextEntry->Flink; } ASSERT(NextEntry != &LoaderBlock->MemoryDescriptorListHead); Pte.X1 = 0; Pte.PFN = StartingPfn; Pte.G = 0; Pte.V = 1; Pte.D = 1; #if defined(R3000) Pte.N = 1; #endif #if defined(R4000) Pte.C = UNCACHED_POLICY; #endif // // Save the page table page PTE for use in displaying information and // map the appropriate PTE in the current page directory page to address // the display controller page table page. // HalpDisplayPte = Pte; *((PENTRYLO)(PDE_BASE | ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = Pte; // // Initialize the page table page. // PageFrame = (PENTRYLO)(PTE_BASE | (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT))); if (HalpDisplayControllerSetup == HalpDisplayINT10Setup) { HalpCirrusPhigicalVideo.HighPart = 1; HalpCirrusPhigicalVideo.LowPart = 0; Pte.PFN = (HalpCirrusPhigicalVideo.HighPart >> PAGE_SHIFT) & (0x7fffffff >> PAGE_SHIFT-1) | HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT); }else if (HalpDisplayControllerSetup == HalpDisplayCirrusSetup) { HalpCirrusPhigicalVideo.HighPart = 1; HalpCirrusPhigicalVideo.LowPart = MEM_VGA; Pte.PFN = (HalpCirrusPhigicalVideo.LowPart >> PAGE_SHIFT) & (0x7fffffff >> PAGE_SHIFT-1) | HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT); } else if (HalpDisplayControllerSetup == HalpDisplayTgaSetup) { HalpTgaPhigicalVideo.HighPart = 1; HalpTgaPhigicalVideo.LowPart = HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET; Pte.PFN = (HalpTgaPhigicalVideo.LowPart >> PAGE_SHIFT) & (0x7fffffff >> PAGE_SHIFT-1) | HalpTgaPhigicalVideo.HighPart << (32 - PAGE_SHIFT); } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) { // M021 HalpGlintPhygicalVideo.HighPart = 1; HalpGlintPhygicalVideo.LowPart = HalpDisplayMemoryBase; Pte.PFN = (HalpGlintPhygicalVideo.LowPart >> PAGE_SHIFT) & (0x7fffffff >> PAGE_SHIFT-1) | HalpGlintPhygicalVideo.HighPart << (32 - PAGE_SHIFT); } Pte.G = 0; Pte.V = 1; Pte.D = 1; #if defined(R3000) Pte.N = 1; #endif #if defined(R4000) Pte.C = UNCACHED_POLICY; #endif // // Page table entries of the video memory. // for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) { *PageFrame++ = Pte; Pte.PFN += 1; } if (HalpDisplayControllerSetup == HalpDisplayTgaSetup) { HalpTgaPhigicalVideoCont.HighPart = 1; HalpTgaPhigicalVideoCont.LowPart = HalpDisplayControlBase; Pte.PFN = (HalpTgaPhigicalVideoCont.LowPart >> PAGE_SHIFT) & (0x7fffffff >> PAGE_SHIFT-1) | HalpTgaPhigicalVideoCont.HighPart << (32 - PAGE_SHIFT); *PageFrame = Pte; } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) { HalpGlintPhygicalVideoCont.HighPart = 1; HalpGlintPhygicalVideoCont.LowPart = HalpDisplayControlBase; // // IBM RGB525 // Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x4000) >> PAGE_SHIFT) & (0x7fffffff >> PAGE_SHIFT-1) | HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT); *(PageFrame - 2) = Pte; // // GLINT 300SX Internal Video Registers // Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x3000) >> PAGE_SHIFT) & (0x7fffffff >> PAGE_SHIFT-1) | HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT); *(PageFrame - 1) = Pte; // // GLINT 300SX Control Status Registers // Pte.PFN = (HalpGlintPhygicalVideoCont.LowPart >> PAGE_SHIFT) & (0x7fffffff >> PAGE_SHIFT-1) | HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT); *PageFrame = Pte; } else if (HalpDisplayControllerSetup == HalpDisplayINT10Setup){ #if defined(_X86_DBG_) DbgPrint("Map x86 and cirrus control register\n"); #endif // _X86_DBG_ Pte.PFN = ((ULONG)HalpDisplayControlBase + 0xffff) >> PAGE_SHIFT; for (Index = 0; Index < (0x10000 / PAGE_SIZE ); Index++) { *PageFrame-- = Pte; #if defined(_X86_DBG_) DbgPrint("Map index %x pfn %x\n",Index,Pte.PFN); #endif // _X86_DBG_ Pte.PFN -= 1; } } else { // // If we have a 'NEC-cirrus GD5428' // use the page before last to map the reset register. // // // Page table for the video registers. // Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT; *PageFrame = Pte; } // // M004 // ESM critical error logging setup. // HalpInitDisplayStringIntoNvram(); // // Initialize the display controller. // #if defined(_X86_DBG_) DbgPrint("\n x86adp init GOOO\n"); //DBGDBG #endif // _X86_DBG if(HalpDisplayControllerSetup == HalpDisplayINT10Setup){ if (HalpInitializeX86DisplayAdapter()) { #if defined(_X86_DBG_) DbgPrint("\n x86adp init OK\n"); //DBGDBG #endif // _X86_DBG // HalpDisplayControllerSetup(); // initialize twice bugbug }else{ return FALSE; } } HalpDisplayControllerSetup(); return TRUE; } BOOLEAN HalpInitializeDisplay1 ( IN PLOADER_PARAMETER_BLOCK LoaderBlock ) /*++ Routine Description: This routine allocates pool for the OEM font file and copies the font information from the OS Loader heap into the allocated pool. Arguments: LoaderBlock - Supplies a pointer to the loader parameter block. Return Value: If the initialization is successfully completed, than a value of TRUE is returned. Otherwise, a value of FALSE is returned. --*/ { PVOID FontHeader; // // Allocate a pool block and copy the OEM font information from the // OS Loader heap into the pool block. // FontHeader = ExAllocatePool(NonPagedPool, HalpFontHeader->FileSize); if (FontHeader == NULL) { return FALSE; } RtlMoveMemory(FontHeader, HalpFontHeader, HalpFontHeader->FileSize); HalpFontHeader = (POEM_FONT_FILE_HEADER)FontHeader; return TRUE; } VOID HalAcquireDisplayOwnership ( IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters ) /*++ Routine Description: This routine switches ownership of the display away from the HAL to the system display driver. It is called when the system has reached a point during bootstrap where it is self supporting and can output its own messages. Once ownership has passed to the system display driver any attempts to output messages using HalDisplayString must result in ownership of the display reverting to the HAL and the display hardware reinitialized for use by the HAL. Arguments: ResetDisplayParameters - if non-NULL the address of a function the hal can call to reset the video card. The function returns TRUE if the display was reset. Return Value: None. --*/ { // // Set HAL ownership of the display to false. // HalpResetDisplayParameters=ResetDisplayParameters;// M003 HalpDisplayOwnedByHal = FALSE; // // M010 // Set for Software Power supply control // #if defined (_MRCPOWER_) HalpMrcModeChange((UCHAR)0x1); // M007 #endif // _MRCPOWER_ // // M006 // ESM critical logging success set success startup. // HalpSuccessOsStartUp(); return; } VOID HalpDisplayCirrusSetup( VOID ) /*++ Routine Description: This routine initializes the Cirrus VGA display controlleer. Arguments: None Return Value: None --*/ { PULONG Buffer; LONG Limit; LONG Index; ULONG dac_address, dac_reg; ULONG verticalFrequency; ULONG horizontalTotal; ULONG verticalTotal; // // Calculate vertical frequency. // horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime +HalpMonitorConfigurationData.HorizontalBackPorch +HalpMonitorConfigurationData.HorizontalFrontPorch +HalpMonitorConfigurationData.HorizontalSync ); verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution +HalpMonitorConfigurationData.VerticalBackPorch +HalpMonitorConfigurationData.VerticalFrontPorch +HalpMonitorConfigurationData.VerticalSync ); verticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal); switch (HalpMonitorConfigurationData.HorizontalResolution) { case 640: if( verticalFrequency < 66 ) { HalpCirrusInterpretCmdStream(CL542x_640x480_256_60); HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); } else { HalpCirrusInterpretCmdStream(CL542x_640x480_256_72); HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); } break; case 800: if( verticalFrequency < 58 ) { HalpCirrusInterpretCmdStream(CL542x_800x600_256_56); HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); } else if( verticalFrequency < 66 ) { HalpCirrusInterpretCmdStream(CL542x_800x600_256_60); HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); } else { HalpCirrusInterpretCmdStream(CL542x_800x600_256_72); HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); } break; case 1024: if( verticalFrequency < 47 ) { HalpCirrusInterpretCmdStream(CL542x_1024x768_256_87); HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); } else if ( verticalFrequency < 65) { HalpCirrusInterpretCmdStream(CL542x_1024x768_256_60); HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); } else { HalpCirrusInterpretCmdStream(CL542x_1024x768_256_70); HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); } break; default: HalpCirrusInterpretCmdStream(CL542x_640x480_256_60); HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); return; } // // Initialize color pallete. // dac_address = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_ADDRESS_WRITE_PORT; dac_reg = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_DATA_REG_PORT; Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x0); Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f); Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f); Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f); Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x1); Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00); Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00); Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)(0x90 >> 2)); // // Set the video memory to address color one. // Buffer = (PULONG)VIDEO_MEMORY_BASE; Limit = (1024 * HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG); for (Index = 0; Index < Limit; Index += 1) { *Buffer++ = 0x01010101; } // // Initialize the current display column, row, and ownership values. // HalpColumn = 0; HalpRow = 0; HalpDisplayOwnedByHal = TRUE; return; } BOOLEAN HalpCirrusInterpretCmdStream( PUSHORT pusCmdStream ) /*++ Routine Description: Interprets the appropriate command array to set up VGA registers for the requested mode. Typically used to set the VGA into a particular mode by programming all of the registers Arguments: pusCmdStream - array of commands to be interpreted. Return Value: The status of the operation (can only fail on a bad command); TRUE for success, FALSE for failure. Revision History: --*/ { ULONG ulCmd; ULONG ulPort; UCHAR jValue; USHORT usValue; ULONG culCount; ULONG ulIndex; ULONG ulBase; if (pusCmdStream == NULL) { return TRUE; } ulBase = (ULONG)CIRRUS_BASE+0x3b0; // // Now set the adapter to the desired mode. // while ((ulCmd = *pusCmdStream++) != EOD) { // // Determine major command type // switch (ulCmd & 0xF0) { // // Basic input/output command // case INOUT: // // Determine type of inout instruction // if (!(ulCmd & IO)) { // // Out instruction. Single or multiple outs? // if (!(ulCmd & MULTI)) { // // Single out. Byte or word out? // if (!(ulCmd & BW)) { // // Single byte out // ulPort = *pusCmdStream++; jValue = (UCHAR) *pusCmdStream++; Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort), jValue); } else { // // Single word out // ulPort = *pusCmdStream++; usValue = *pusCmdStream++; Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort), (UCHAR)(usValue & 0x00ff)); Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort+1 ), (UCHAR)(usValue >> 8)); } } else { // // Output a string of values // Byte or word outs? // if (!(ulCmd & BW)) { // // String byte outs. Do in a loop; can't use // VideoPortWritePortBufferUchar because the data // is in USHORT form // ulPort = ulBase + *pusCmdStream++; culCount = *pusCmdStream++; while (culCount--) { jValue = (UCHAR) *pusCmdStream++; Write_Dbg_Uchar((PUCHAR)ulPort, jValue); } } else { // // String word outs // ulPort = *pusCmdStream++; culCount = *pusCmdStream++; // // Buffering out is not use on the Miniport Driver for R96 machine. // while(culCount--) { usValue = *pusCmdStream++; Write_Dbg_Uchar((PUCHAR) (ulBase + ulPort), (UCHAR) (usValue & 0x00ff)); Write_Dbg_Uchar((PUCHAR) (ulBase + ulPort+1), (UCHAR) (usValue >> 8)); } } } } else { // In instruction // // Currently, string in instructions aren't supported; all // in instructions are handled as single-byte ins // // Byte or word in? // if (!(ulCmd & BW)) { // // Single byte in // ulPort = *pusCmdStream++; jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort); } else { // // Single word in // ulPort = *pusCmdStream++; usValue = READ_REGISTER_USHORT((PUSHORT) (ulBase+ulPort)); } } break; // // Higher-level input/output commands // case METAOUT: // // Determine type of metaout command, based on minor // command field // switch (ulCmd & 0x0F) { // // Indexed outs // case INDXOUT: ulPort = ulBase + *pusCmdStream++; culCount = *pusCmdStream++; ulIndex = *pusCmdStream++; while (culCount--) { usValue = (USHORT) (ulIndex + (((ULONG)(*pusCmdStream++)) << 8)); Write_Dbg_Uchar((PUCHAR)ulPort, (UCHAR) (usValue & 0x00ff)); Write_Dbg_Uchar((PUCHAR)ulPort+1, (UCHAR) (usValue >> 8)); ulIndex++; } break; // // Masked out (read, AND, XOR, write) // case MASKOUT: ulPort = *pusCmdStream++; jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort); jValue &= *pusCmdStream++; jValue ^= *pusCmdStream++; Write_Dbg_Uchar((PUCHAR)ulBase + ulPort, jValue); break; // // Attribute Controller out // case ATCOUT: ulPort = ulBase + *pusCmdStream++; culCount = *pusCmdStream++; ulIndex = *pusCmdStream++; while (culCount--) { // Write Attribute Controller index Write_Dbg_Uchar((PUCHAR)ulPort, (UCHAR)ulIndex); // Write Attribute Controller data jValue = (UCHAR) *pusCmdStream++; Write_Dbg_Uchar((PUCHAR)ulPort, jValue); ulIndex++; } break; // // None of the above; error // default: return FALSE; } break; // // NOP // case NCMD: break; // // Unknown command; error // default: return FALSE; } } return TRUE; } // end HalpCirrusInterpretCmdStream() VOID HalpDisplayTgaSetup( VOID ) /*++ Routine Description: This routine initializes the Tga(DEC21030) Graphics accelerator. Arguments: None Return Value: None --*/ { PUCHAR PLLbits; ULONG i, j; ULONG PLLdata; ULONG ColorData; PULONG Buffer; LONG Limit; LONG Index; ULONG VerticalFrequency; ULONG horizontalTotal; ULONG verticalTotal; // M019+++ // // support for nec dec-ga(tga) board. // parameter change. // #if 0 const UCHAR PLLbits640x480_72[7] = { 0x80, 0x08, 0x80, 0x24, 0xb0, 0x20, 0xc8 }; const UCHAR PLLbits640x480_60[7] = { 0x80, 0x08, 0x80, 0x24, 0x88, 0x80, 0x78 }; const UCHAR PLLbits800x600_72[7] = { 0x80, 0x00, 0x80, 0x24, 0x88, 0x80, 0x78 }; const UCHAR PLLbits800x600_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x70, 0xa0, 0x84 }; const UCHAR PLLbits1024x768_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x48, 0x20, 0x98 }; #else const UCHAR PLLbits640x480_72[7] = { 0x80, 0x04, 0x80, 0xa4, 0x51, 0x80, 0x70 }; const UCHAR PLLbits640x480_60[7] = { 0x80, 0x04, 0x80, 0xa5, 0xc4, 0x10, 0x78 }; const UCHAR PLLbits800x600_72[7] = { 0x80, 0x08, 0x80, 0x24, 0xf1, 0x60, 0x38 }; // S007 const UCHAR PLLbits800x600_60[7] = { 0x80, 0x04, 0x80, 0xa5, 0x78, 0x20, 0x08 }; const UCHAR PLLbits1024x768_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x48, 0x20, 0x98 }; #endif // _NECDEC_ // M019 --- const UCHAR Vga_Ini_ColorTable[48] = // { VGA_INI_PALETTE_WHITE_R, VGA_INI_PALETTE_WHITE_G, VGA_INI_PALETTE_WHITE_B, { VGA_INI_PALETTE_HI_WHITE_R, VGA_INI_PALETTE_HI_WHITE_G, VGA_INI_PALETTE_HI_WHITE_B, // M010 VGA_INI_PALETTE_BLUE_R, VGA_INI_PALETTE_BLUE_G, VGA_INI_PALETTE_BLUE_B, VGA_INI_PALETTE_GREEN_R, VGA_INI_PALETTE_GREEN_B, VGA_INI_PALETTE_GREEN_G, VGA_INI_PALETTE_YELLOW_R, VGA_INI_PALETTE_YELLOW_G, VGA_INI_PALETTE_YELLOW_B, VGA_INI_PALETTE_RED_R, VGA_INI_PALETTE_RED_G, VGA_INI_PALETTE_RED_B, VGA_INI_PALETTE_MAGENTA_R, VGA_INI_PALETTE_MAGENTA_G, VGA_INI_PALETTE_MAGENTA_B, VGA_INI_PALETTE_CYAN_R, VGA_INI_PALETTE_CYAN_G, VGA_INI_PALETTE_CYAN_B, VGA_INI_PALETTE_BLACK_R, VGA_INI_PALETTE_BLACK_G, VGA_INI_PALETTE_BLACK_B, // VGA_INI_PALETTE_HI_WHITE_R, VGA_INI_PALETTE_HI_WHITE_G, VGA_INI_PALETTE_HI_WHITE_B, VGA_INI_PALETTE_WHITE_R, VGA_INI_PALETTE_WHITE_G, VGA_INI_PALETTE_WHITE_B, // M010 VGA_INI_PALETTE_HI_BLUE_R, VGA_INI_PALETTE_HI_BLUE_G, VGA_INI_PALETTE_HI_BLUE_B, VGA_INI_PALETTE_HI_GREEN_R, VGA_INI_PALETTE_HI_GREEN_G, VGA_INI_PALETTE_HI_GREEN_B, VGA_INI_PALETTE_HI_YELLOW_R, VGA_INI_PALETTE_HI_YELLOW_G, VGA_INI_PALETTE_HI_YELLOW_B, VGA_INI_PALETTE_HI_RED_R, VGA_INI_PALETTE_HI_RED_G, VGA_INI_PALETTE_HI_RED_B, VGA_INI_PALETTE_HI_MAGENTA_R, VGA_INI_PALETTE_HI_MAGENTA_G, VGA_INI_PALETTE_HI_MAGENTA_B, VGA_INI_PALETTE_HI_CYAN_R, VGA_INI_PALETTE_HI_CYAN_G, VGA_INI_PALETTE_HI_CYAN_B, VGA_INI_PALETTE_HI_BLACK_R, VGA_INI_PALETTE_HI_BLACK_G, VGA_INI_PALETTE_HI_BLACK_B }; // // Calculate vertical frequency. // horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime +HalpMonitorConfigurationData.HorizontalBackPorch +HalpMonitorConfigurationData.HorizontalFrontPorch +HalpMonitorConfigurationData.HorizontalSync ); verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution +HalpMonitorConfigurationData.VerticalBackPorch +HalpMonitorConfigurationData.VerticalFrontPorch +HalpMonitorConfigurationData.VerticalSync ); VerticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal); // // Write the PLL // // Select PLL Data if( HalpMonitorConfigurationData.HorizontalResolution == 640 && HalpMonitorConfigurationData.VerticalResolution == 480 ){ if( VerticalFrequency > 66 ){ PLLbits = (PVOID)PLLbits640x480_72; // S012 } else { PLLbits = (PVOID)PLLbits640x480_60; // S012 } } else if( HalpMonitorConfigurationData.HorizontalResolution == 800 && HalpMonitorConfigurationData.VerticalResolution == 600 ){ if( VerticalFrequency > 66 ){ PLLbits = (PVOID)PLLbits800x600_72; // S012 } else { PLLbits = (PVOID)PLLbits800x600_60; // S012 } } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024 && HalpMonitorConfigurationData.VerticalResolution == 768 ){ PLLbits = (PVOID)PLLbits1024x768_60; // S012 } else { PLLbits = (PVOID)PLLbits640x480_60; // S012 } // Set PLL Data for( i = 0; i <= 6; i++ ){ for( j = 0; j <= 7; j++ ){ PLLdata = (PLLbits[i] >> (7-j)) & 1; if( i == 6 && j == 7 ) PLLdata |= 2; // Set ~HOLD bit on last write WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + CLOCK), PLLdata); } } // Verify 21030 is idle ( check busy bit on Command Status Register ) while( (READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ) & 1) == 1 ){ } // Set to Deep Register WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + DEEP), 0x00014000 ); // Verify 21030 is idle ( check busy bit on Command Status Register ) while( (READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ) & 1) == 1 ){ } // Set to Video Base Address Register WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + VIDEO_BASE), 0x00000000 ); // Set to Plane Mask Register WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + PLANE_MASK), 0xffffffff ); // Set to Pixel Mask Register WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + ONE_SHOT_PIXEL_MASK), 0xffffffff ); // Set to Raster Operation WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RASTER_OP), 0x03 ); // Set to Mode Register WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + MODE), 0x0000200d ); // Set to Block Color Register 0 WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + BLK_COLOR_R0), 0x12345678 ); // Set to Block Color Register 1 WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + BLK_COLOR_R1), 0x12345678 ); // // Init. video timing registers for each resolution // if( HalpMonitorConfigurationData.HorizontalResolution == 640 && HalpMonitorConfigurationData.VerticalResolution == 480 ){ if( VerticalFrequency > 66 ){ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x03c294a0 ); // M023 WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x070349e0 ); } else { WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x00e64ca0 ); // M023 WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x064211e0 ); } } else if( HalpMonitorConfigurationData.HorizontalResolution == 800 && HalpMonitorConfigurationData.VerticalResolution == 600 ){ if( VerticalFrequency > 66 ){ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x01a7a4c8 ); // M023 WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x05c6fa58 ); } else { WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x02681cc8 ); // M023 WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x05c40a58 ); } } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024 && HalpMonitorConfigurationData.VerticalResolution == 768 ){ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x04889300 ); // M023 WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x07461b00 ); } else { WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x00e64ca0 ); // M023 WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x064211e0 ); } // Set to Raster Operation Register WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RASTER_OP), 0x03 ); // Set to Mode Register WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + MODE), 0x00002000 ); // M019 +++ // // wait for 10 msec for nec dec-ga support // KeStallExecutionProcessor(10000L); // M019 --- // Set to Palette and DAC Setup & Data Register WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x0c ); WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x0ca2 ); WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x10 ); WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1040 ); WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x12 ); WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1220 ); WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x00 ); WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x01 ); WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x14 ); WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1410 ); // // set pass thru on off & on again to verify operation // // EEPROM Write Register WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + EEPROM_WRITE), 0x00000001 ); // // Fill palette // // Set to Palette and DAC Setup & Data Register WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x00 ); WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x00 ); WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x02 ); for( i = 0; i < 48; i++ ){ ColorData = Vga_Ini_ColorTable[i]; ColorData |= 0x200; WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), ColorData ); } for( i = 48; i < 768; i++ ){ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x200 ); } // Set to Video Valid Register WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + VIDEO_VALID), 0x01 ); // // Set Video Memory to address color one. // Buffer = (PULONG)VIDEO_MEMORY_BASE; Limit = (HalpMonitorConfigurationData.HorizontalResolution * HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG); for (Index = 0; Index < Limit; Index += 1) { *Buffer++ = 0x01010101; } // // Initialize the current display column, row, and ownership values. // HalpColumn = 0; HalpRow = 0; HalpDisplayOwnedByHal = TRUE; return; } VOID HalDisplayString ( PUCHAR String ) /*++ Routine Description: This routine displays a character string on the display screen. Arguments: String - Supplies a pointer to the characters that are to be displayed. Return Value: None. --*/ { KIRQL OldIrql; ENTRYLO SavedPte; /* Start D001 */ ULONG NowDisplayControlBase; ULONG NowDisplayMemoryBase; // M021 PENTRYLO PageFrame; ENTRYLO Pte; LONG Index; /* End D001 */ PCI_SLOT_NUMBER Slot; // M014 ULONG ReadValue; // M014 // // Raise IRQL to the highest level, acquire the display adapter spin lock, // flush the TB, and map the display frame buffer into the address space // of the current process. // KeRaiseIrql(HIGH_LEVEL, &OldIrql); #if defined(_DUO_) KiAcquireSpinLock(&HalpDisplayAdapterLock); #endif SavedPte = *((PENTRYLO)(PDE_BASE | ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))); KeFlushCurrentTb(); *((PENTRYLO)(PDE_BASE | ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = HalpDisplayPte; if (HalpDisplayPCIDevice == TRUE){ // // the display type is PCI // check physical address and reinitialize PTE // we assume that the device has no function // Slot.u.bits.FunctionNumber = 0; for (Slot.u.bits.DeviceNumber = 3; Slot.u.bits.DeviceNumber < 6; Slot.u.bits.DeviceNumber++){ HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0); if (HalpDisplayControllerSetup == HalpDisplayTgaSetup && ReadValue == 0x00041011){ // // DEC21030 // HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10); NowDisplayControlBase = (ReadValue & 0xfffffff0)+ TGA_REG_SPC_OFFSET; NowDisplayMemoryBase = 0; } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup && ReadValue == 0x00013d3d){ // // GLINT 300SX // HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10); NowDisplayControlBase = (ReadValue & 0xfffffff0); HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x18); NowDisplayMemoryBase = (ReadValue & 0xfffffff0); } } // // check to see if address has been changed // if (HalpDisplayControlBase != NowDisplayControlBase || HalpDisplayMemoryBase != NowDisplayMemoryBase){ // Called by OS, so reinitialize PTE HalpDisplayControlBase = NowDisplayControlBase; HalpDisplayMemoryBase = NowDisplayMemoryBase; Pte.G = 0; Pte.V = 1; Pte.D = 1; #if defined(R3000) Pte.N = 1; #endif #if defined(R4000) Pte.C = UNCACHED_POLICY; #endif // // Initialize the page table page. // PageFrame = (PENTRYLO)(PTE_BASE | (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT))); if (HalpDisplayControllerSetup == HalpDisplayTgaSetup){ HalpTgaPhigicalVideoCont.HighPart = 1; HalpTgaPhigicalVideoCont.LowPart = HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET; Pte.PFN = (HalpTgaPhigicalVideoCont.LowPart >> PAGE_SHIFT) & (0x7fffffff >> PAGE_SHIFT-1) | HalpTgaPhigicalVideoCont.HighPart << (32 - PAGE_SHIFT); } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) { // M021 HalpGlintPhygicalVideo.HighPart = 1; HalpGlintPhygicalVideo.LowPart = HalpDisplayMemoryBase; Pte.PFN = (HalpGlintPhygicalVideo.LowPart >> PAGE_SHIFT) & (0x7fffffff >> PAGE_SHIFT-1) | HalpGlintPhygicalVideo.HighPart << (32 - PAGE_SHIFT); } // // Page table entries of the video memory. // for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) { *PageFrame++ = Pte; Pte.PFN += 1; } if (HalpDisplayControllerSetup == HalpDisplayTgaSetup){ HalpTgaPhigicalVideoCont.HighPart = 1; HalpTgaPhigicalVideoCont.LowPart = HalpDisplayControlBase; Pte.PFN = (HalpTgaPhigicalVideoCont.LowPart >> PAGE_SHIFT) & (0x7fffffff >> PAGE_SHIFT-1) | HalpTgaPhigicalVideoCont.HighPart << (32 - PAGE_SHIFT); *PageFrame = Pte; } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) { // M021 HalpGlintPhygicalVideoCont.HighPart = 1; HalpGlintPhygicalVideoCont.LowPart = HalpDisplayControlBase; // // IBM RGB525 // Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x4000) >> PAGE_SHIFT) & (0x7fffffff >> PAGE_SHIFT-1) | HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT); *(PageFrame - 2) = Pte; // // GLINT 300SX Internal Video Registers // Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x3000) >> PAGE_SHIFT) & (0x7fffffff >> PAGE_SHIFT-1) | HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT); *(PageFrame - 1) = Pte; // // GLINT 300SX Control Status Registers // Pte.PFN = (HalpGlintPhygicalVideoCont.LowPart >> PAGE_SHIFT) & (0x7fffffff >> PAGE_SHIFT-1) | HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT); *PageFrame = Pte; } } } // // If ownership of the display has been switched to the system display // driver, then reinitialize the display controller and revert ownership // to the HAL. // if (HalpDisplayOwnedByHal == FALSE) { // M003 +++ if (HalpResetDisplayParameters && HalpDisplayControllerSetup == HalpDisplayINT10Setup) { // // Video work-around. The video driver has a reset function, // call it before resetting the system in case the bios doesn't // know how to reset the displays video mode. // if (HalpResetDisplayParameters(80, 50)) { } // M003--- } // // M010 // for Software controlled power suply. // #if defined(_MRCPOWER_) HalpMrcModeChange((UCHAR)0); // M007 #endif // _MRCPOWER_ HalpDisplayControllerSetup(); // HalpResetX86DisplayAdapter(); // // M004 // re-initialize critical message // HalpInitDisplayStringIntoNvram(); } // // M004 // ESM critical error logging start (set colomn,row) // HalStringIntoBufferStart( HalpColumn, HalpRow ); // // Display characters until a null byte is encountered. // while (*String != 0) { HalpDisplayCharacter(*String++); } // M004 // ESM critical error logging(strings) // HalpStringBufferCopyToNvram(); // // Restore the previous mapping for the current process, flush the TB, // release the display adapter spin lock, and lower IRQL to its previous // level. // KeFlushCurrentTb(); *((PENTRYLO)(PDE_BASE | ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = SavedPte; #if defined(_DUO_) KiReleaseSpinLock(&HalpDisplayAdapterLock); #endif KeLowerIrql(OldIrql); return; } VOID HalpDisplayCharacterOld ( IN UCHAR Character ) /*++ Routine Description: This routine displays a character at the current x and y positions in the frame buffer. If a newline is encounter, then the frame buffer is scrolled. If characters extend below the end of line, then they are not displayed. Arguments: Character - Supplies a character to be displayed. Return Value: None. --*/ { PUCHAR Destination; PUSHORT DestinationShort; // M021 ULONG Index; // // If the character is a newline, then scroll the screen up, blank the // bottom line, and reset the x position. // if (Character == '\n') { HalpColumn = 0; if (HalpRow < (HalpDisplayText - 1)) { HalpRow += 1; } else { HalpMoveMemory32((PUCHAR)VIDEO_MEMORY_BASE, (PUCHAR)(VIDEO_MEMORY_BASE + HalpScrollLine), HalpScrollLength); // /* START M002 */ // RtlMoveMemory((PUCHAR)VIDEO_MEMORY_BASE, // S013 // (PUCHAR)(VIDEO_MEMORY_BASE + HalpScrollLine), // HalpScrollLength); // /* END M002 */ if (HalpDisplayType16BPP) { DestinationShort = (PUSHORT)(VIDEO_MEMORY_BASE + HalpScrollLength); } else { Destination = (PUCHAR)VIDEO_MEMORY_BASE + HalpScrollLength; } if (HalpDisplayType16BPP) { for (Index = 0; Index < HalpScrollLine/2; Index += 1) { *DestinationShort++ = (USHORT)0x000f; } } else { for (Index = 0; Index < HalpScrollLine; Index += 1) { *Destination++ = 1; } } } // // M006 // ESM critical logging re-print(column, row) // HalpStringBufferCopyToNvram(); HalStringIntoBufferStart( HalpColumn, HalpRow ); } else if (Character == '\r') { HalpColumn = 0; // // M006 // ESM critical logging re-print(column,row) // HalpStringBufferCopyToNvram(); HalStringIntoBufferStart( HalpColumn, HalpRow ); } else { // // M006 // ESM critical logging put character. // HalStringIntoBuffer( Character ); if ((Character < HalpFontHeader->FirstCharacter) || (Character > HalpFontHeader->LastCharacter)) { Character = HalpFontHeader->DefaultCharacter; } Character -= HalpFontHeader->FirstCharacter; HalpOutputCharacterOld((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset); } return; } //351 VOID HalpDisplayCharacterVGA ( IN UCHAR Character ) /*++ Routine Description: This routine displays a character at the current x and y positions in the frame buffer. If a newline is encounter, then the frame buffer is scrolled. If characters extend below the end of line, then they are not displayed. Arguments: Character - Supplies a character to be displayed. Return Value: None. --*/ { // // If the character is a newline, then scroll the screen up, blank the // bottom line, and reset the x position. // if (Character == '\n') { HalpColumn = 0; if (HalpRow < (HalpDisplayText - 1)) { HalpRow += 1; } else { // need to scroll up the screen HalpScrollINT10(1); } // // M006 // ESM critical logging re-print(column, row) // HalpStringBufferCopyToNvram(); HalStringIntoBufferStart( HalpColumn, HalpRow ); } //========================================================================= // // IBMBJB added tab processing // else if( Character == '\t' ) // tab? { HalpColumn += TAB_SIZE; HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE; if( HalpColumn >= 80 ) // tab beyond end of screen? { HalpColumn = 0; // next tab stop is 1st column of next line if( HalpRow >= (HalpDisplayText - 1) ) HalpScrollINT10( 1 ); // scroll the screen up else ++HalpRow; } } //========================================================================= else if (Character == '\r') { // // M006 // ESM critical logging re-print(column,row) // HalpStringBufferCopyToNvram(); HalStringIntoBufferStart( HalpColumn, HalpRow ); HalpColumn = 0; } else if (Character == 0x7f) { /* DEL character */ if (HalpColumn != 0) { HalpColumn -= 1; HalpOutputCharacterINT10(0); HalpColumn -= 1; } else /* do nothing */ ; } else if (Character >= 0x20) { // // M006 // ESM critical logging put character. // HalStringIntoBuffer( Character ); // Auto wrap for 80 columns per line if (HalpColumn >= 80) { HalpColumn = 0; if (HalpRow < (HalpDisplayText - 1)) { HalpRow += 1; } else { // need to scroll up the screen HalpScrollINT10(1); } } HalpOutputCharacterINT10(Character); } else /* skip the nonprintable character */ ; return; } /* end of HalpDisplayCharacterVGA() */ VOID HalQueryDisplayParameters ( OUT PULONG WidthInCharacters, OUT PULONG HeightInLines, OUT PULONG CursorColumn, OUT PULONG CursorRow ) /*++ Routine Description: This routine return information about the display area and current cursor position. Arguments: WidthInCharacter - Supplies a pointer to a varible that receives the width of the display area in characters. HeightInLines - Supplies a pointer to a variable that receives the height of the display area in lines. CursorColumn - Supplies a pointer to a variable that receives the current display column position. CursorRow - Supplies a pointer to a variable that receives the current display row position. Return Value: None. --*/ { // // Set the display parameter values and return. // *WidthInCharacters = HalpDisplayWidth; *HeightInLines = HalpDisplayText; *CursorColumn = HalpColumn; *CursorRow = HalpRow; return; } VOID HalSetDisplayParameters ( IN ULONG CursorColumn, IN ULONG CursorRow ) /*++ Routine Description: This routine set the current cursor position on the display area. Arguments: CursorColumn - Supplies the new display column position. CursorRow - Supplies a the new display row position. Return Value: None. --*/ { // // Set the display parameter values and return. // if (CursorColumn > HalpDisplayWidth) { CursorColumn = HalpDisplayWidth; } if (CursorRow > HalpDisplayText) { CursorRow = HalpDisplayText; } HalpColumn = CursorColumn; HalpRow = CursorRow; return; } VOID HalpOutputCharacterOld( IN PUCHAR Glyph ) /*++ Routine Description: This routine insert a set of pixels into the display at the current x cursor position. If the current x cursor position is at the end of the line, then a newline is displayed before the specified character. Arguments: Character - Supplies a character to be displayed. Return Value: None. --*/ { PUCHAR Destination; PUSHORT DestinationShort; // M021 ULONG FontValue; ULONG I; ULONG J; // // If the current x cursor position is at the end of the line, then // output a line feed before displaying the character. // if (HalpColumn == HalpDisplayWidth) { HalpDisplayCharacter('\n'); } // // Output the specified character and update the x cursor position. // if (HalpDisplayType16BPP) { DestinationShort = (PUSHORT)(VIDEO_MEMORY_BASE + (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth * sizeof(USHORT))); } else { Destination = (PUCHAR)(VIDEO_MEMORY_BASE + (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth)); } for (I = 0; I < HalpCharacterHeight; I += 1) { FontValue = 0; for (J = 0; J < HalpBytesPerRow; J += 1) { FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8)); } Glyph += 1; for (J = 0; J < HalpCharacterWidth ; J += 1) { if (HalpDisplayType16BPP) { if (FontValue >> 31) *DestinationShort++ = (USHORT)0xffff; else *DestinationShort++ = (USHORT)0x000f; }else{ *Destination++ = (UCHAR) (FontValue >> 31) ^ 1; /* M008 */ } FontValue <<= 1; } if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){ Destination += (1024 - HalpCharacterWidth); } else if (HalpDisplayType16BPP){ DestinationShort += (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth); } else { Destination += (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth); } } HalpColumn += 1; return; } VOID Write_Dbg_Uchar( PUCHAR Ioadress, UCHAR Moji ) { #if defined (R96DBG) DbgPrint("Disply I/O Adress %x Char %x \n",Ioadress,Moji); #endif WRITE_PORT_UCHAR(Ioadress,Moji); } VOID HalpMoveMemory32 ( PUCHAR Destination, PUCHAR Source, ULONG Length ) /*++ Routine Description: This function moves blocks of memory. Arguments: Destination - Supplies a pointer to the destination address of the move operation. Source - Supplies a pointer to the source address of the move operation. Length - Supplies the length, in bytes, of the memory to be moved. Return Value: None. --*/ { UCHAR Remainder; PUCHAR Dstend; PUCHAR Srcend; if ( (Source == Destination) || (Length == 0) ) { return; } if ((Source < Destination)&((Source + Length) > Destination)) { if((Destination - Source) > 4){ Remainder = (UCHAR) Length &0x03; Length = Length / 4; Dstend = Destination + Length - 4 ; Srcend = Source + Length -4; for (; Length > 0; Length--) { *(PULONG)(Dstend) = *(PULONG)(Srcend); Dstend -= 4; Srcend -= 4; } for (; Remainder > 0; Remainder--) { *Dstend = *Srcend; Dstend--; Srcend--; } return; } for (; Length > 0; Length--) { *Dstend = *Srcend; Dstend--; Srcend--; } return; } else { if( (Source - Destination) > 4 ){ Remainder = (UCHAR) Length &0x03; Length = Length / 4; for (; Length > 0; Length--) { *(PULONG)(Destination) = *(PULONG)(Source); Destination += 4; Source += 4; } for (; Remainder > 0; Remainder--) { *Destination = *Source; Destination++; Source++; } return; } for (; Length > 0; Length--) { *Destination = *Source; Destination++; Source++; } } } VOID HalpOutputCharacterINT10 ( IN UCHAR Character ) { ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp; Eax = 2 << 8; // AH = 2 Ebx = 0; // BH = page number Edx = (HalpRow << 8) + HalpColumn; HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); Eax = (0x0A << 8) + Character; // AH = 0xA AL = character Ebx = 0; Ecx = 1; HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); HalpColumn += 1; } VOID HalpScrollINT10 ( IN UCHAR LinesToScroll ) { ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp; Eax = 6 << 8; // AH = 6 (scroll up) Eax |= LinesToScroll; // AL = lines to scroll Ebx = TEXT_ATTR << 8; // BH = attribute to fill blank line(s) Ecx = 0; // CH,CL = upper left Edx = ((HalpDisplayText - 1) << 8) + (HalpDisplayWidth - 1); // DH,DL = lower right // M001,S005 HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); } VOID HalpDisplayINT10Setup ( VOID ) { ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp; HalpColumn = 0; HalpRow = 0; HalpDisplayWidth = 80; HalpDisplayText = 50; // M001 HalpScrollLine = 160; HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1); HalpDisplayOwnedByHal = TRUE; HalpResetX86DisplayAdapter(); // for compaq q-vision reset // M001 +++ // // Load 8x8 font 80x50 on VGA // Eax = 0x1112; // AH = 11 AL=12 Ebx = 0; HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); // M001 --- // // Set cursor to (0,0) // Eax = 0x02 << 8; // AH = 2 Ebx = 0; // BH = page Number Edx = 0; // DH = row DL = column HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); // // Make screen white on blue by scrolling entire screen // Eax = 0x06 << 8; // AH = 6 AL = 0 Ebx = TEXT_ATTR << 8; // BH = attribute Ecx = 0; // (x,y) upper left Edx = ((HalpDisplayText-1) << 8); // (x,y) lower right Edx += HalpScrollLine/2; HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); } // start M014 VOID HalpReadPCIConfigUlongByOffset ( IN PCI_SLOT_NUMBER Slot, IN PULONG Buffer, IN ULONG Offset ) /*++ Routine Description: This function returns PCI configuration data. Arguments: Slot - Supplies a PCI slot number and function number. Buffer - Supplies a pointer to a configuration data is returned. Offset - Offset in the PCI configuration header. Return Value: None. --*/ { R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; USHORT StatusValue; KIRQL OldIrql; // // check to see if specified slot is valid // if (!HalpCheckPCIDevice(Slot)) { // // Invalid SlotID return no data // *Buffer = 0xffffffff; return ; } *((PULONG) &ConfigAddressValue) = 0x0; ConfigAddressValue.ConfigEnable = 1; ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber; ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber; ConfigAddressValue.RegisterNumber = Offset >> 2; // // Synchronize with PCI configuration // // KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017 // KiAcquireSpinLock(&HalpPCIConfigLock); WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue)); *Buffer = READ_REGISTER_ULONG(R94A_PCI_DATA_REG); // // Release spinlock // // KiReleaseSpinLock(&HalpPCIConfigLock); // KeLowerIrql(OldIrql); return; } BOOLEAN HalpCheckPCIDevice ( IN PCI_SLOT_NUMBER Slot ) /*++ Routine Description: This function checks if spcified PCI slot is valid. Arguments: Slot - Supplies a PCI slot number and function number. Return Value: TRUE - specified slot is valid FALSE - specified slot is invalid --*/ { R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; BOOLEAN ReturnValue; ULONG OrigData; ULONG IdValue; KIRQL OldIrql; // // Disable PCI-MasterAbort interrupt during configration read. // OrigData = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable); WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData & 0xffffff7f); // // read VendorID and DeviceID of the specified slot // *((PULONG) &ConfigAddressValue) = 0x0; ConfigAddressValue.ConfigEnable = 1; ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber; ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber; // // Synchronize with PCI configuration // // KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017 // KiAcquireSpinLock(&HalpPCIConfigLock); WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue)); IdValue = READ_REGISTER_ULONG(R94A_PCI_DATA_REG); // // Release spinlock // // KiReleaseSpinLock(&HalpPCIConfigLock); // KeLowerIrql(OldIrql); if ((USHORT)(IdValue & 0xffff) == 0xffff){ // // waiting until ReceivedMasterAbort bit is set // while(!(READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus) & 0x2000)) ; // // clear the ReceivedMasterAbort bit // WRITE_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus, 0x2000) // // M018 // Clear memory address error registers. // { LARGE_INTEGER registerLarge; READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, ®isterLarge); } ReturnValue = FALSE; } else { ReturnValue = TRUE; } // // Restore the PCIInterruptEnable register. // WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData); return ReturnValue; } // end M014 #if defined(_R94A_) VOID HalpDisplayGlintSetup( VOID ) /*++ Routine Description: This routine initializes the GLINT 300SX Graphics accelerator. Arguments: None Return Value: None --*/ { ULONG VerticalFrequency; ULONG horizontalTotal; ULONG verticalTotal; __VIDEO __Video; VIDEO Video = &__Video; long ClockDivider; // for initialize ramdac ULONG Dac = RGB525_REGISTER_BASE; UCHAR ByteVal; // for initialize timing ULONG Glint = GLINT_VIDEO_REGISTER_BASE - 0x3000; // for initialize control ULONG SerialClk; ULONG Temp; ULONG Data; ULONG Mask; // for initialize RampLut ULONG Index; // for clear the screen PULONG DestinationUlong; ULONG Length; /* check revision id R01 or R02. assume 40MHz(R01) or 50MHz(R02) reference clock for now */ if ( HalpGlintRevisionId == 0){ Video->RefDivCount = RGB525_PLL_REFCLK_40_MHz; } else { Video->RefDivCount = RGB525_PLL_REFCLK_50_MHz; // S006 } // // Calculate vertical frequency. // #if defined(_GLINT60HZ_) VerticalFrequency = 60; #else horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime +HalpMonitorConfigurationData.HorizontalBackPorch +HalpMonitorConfigurationData.HorizontalFrontPorch +HalpMonitorConfigurationData.HorizontalSync ); verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution +HalpMonitorConfigurationData.VerticalBackPorch +HalpMonitorConfigurationData.VerticalFrontPorch +HalpMonitorConfigurationData.VerticalSync ); VerticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal); #endif // _GLINT60HZ_ // // Initialize video data // /* get timing values for named resolution */ if ( HalpMonitorConfigurationData.HorizontalResolution == 1280 && HalpMonitorConfigurationData.VerticalResolution == 1024 && VerticalFrequency == 75) { Video->ImageWidth = 1280; Video->ImageHeight = 1024; Video->HLimit = 8 * 211; Video->HSyncStart = 8 * 2; Video->HSyncEnd = 8 * 20; Video->HBlankEnd = 8 * 51; Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; Video->VLimit = 1066; Video->VSyncStart = 2; Video->VSyncEnd = 5; Video->VBlankEnd = 42; Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; /* 134 MHz */ Video->PixelClock = RGB525_DF(3) | RGB525_VCO_DIV_COUNT(2); } else if ( HalpMonitorConfigurationData.HorizontalResolution == 1024 && HalpMonitorConfigurationData.VerticalResolution == 768 && VerticalFrequency == 75) { Video->ImageWidth = 1024; Video->ImageHeight = 768; Video->HLimit = 8 * 164; Video->HSyncStart = 8 * 2; Video->HSyncEnd = 8 * 14; Video->HBlankEnd = 8 * 36; Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH; Video->VLimit = 800; Video->VSyncStart = 2; Video->VSyncEnd = 5; Video->VBlankEnd = 32; Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH; /* 79 MHz */ Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(14); } else if ( HalpMonitorConfigurationData.HorizontalResolution == 1024 && HalpMonitorConfigurationData.VerticalResolution == 768 && VerticalFrequency == 60) { Video->ImageWidth = 1024; Video->ImageHeight = 768; Video->HLimit = 8 * 168; Video->HSyncStart = 8 * 3; Video->HSyncEnd = 8 * 20; Video->HBlankEnd = 8 * 40; Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; Video->VLimit = 806; Video->VSyncStart = 4; Video->VSyncEnd = 10; Video->VBlankEnd = 38; Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; /* 65 MHz */ Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(0); } else if ( HalpMonitorConfigurationData.HorizontalResolution == 800 && HalpMonitorConfigurationData.VerticalResolution == 600 && VerticalFrequency == 75) { Video->ImageWidth = 800; Video->ImageHeight = 600; Video->HLimit = 8 * 132; Video->HSyncStart = 8 * 2; Video->HSyncEnd = 8 * 12; Video->HBlankEnd = 8 * 32; Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH; Video->VLimit = 625; Video->VSyncStart = 2; Video->VSyncEnd = 5; Video->VBlankEnd = 25; Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_HIGH; /* 49.5 MHz */ Video->PixelClock = RGB525_DF(1) | RGB525_VCO_DIV_COUNT(34); } else if ( HalpMonitorConfigurationData.HorizontalResolution == 800 && HalpMonitorConfigurationData.VerticalResolution == 600 && VerticalFrequency == 60) { Video->ImageWidth = 800; Video->ImageHeight = 600; Video->HLimit = 8 * 132; Video->HSyncStart = 8 * 5; Video->HSyncEnd = 8 * 21; Video->HBlankEnd = 8 * 32; Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH; Video->VLimit = 628; Video->VSyncStart = 2; Video->VSyncEnd = 6; Video->VBlankEnd = 28; Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_HIGH; /* 40 MHz */ Video->PixelClock = RGB525_DF(1) | RGB525_VCO_DIV_COUNT(15); } else if ( HalpMonitorConfigurationData.HorizontalResolution == 640 // add 4/5/1995 && HalpMonitorConfigurationData.VerticalResolution == 480 && VerticalFrequency == 60) { Video->ImageWidth = 640; Video->ImageHeight = 480; Video->HLimit = 8 * 100; Video->HSyncStart = 8 * 2; Video->HSyncEnd = 8 * 14; Video->HBlankEnd = 8 * 20; Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; Video->VLimit = 525; Video->VSyncStart = 12; Video->VSyncEnd = 13; Video->VBlankEnd = 45; Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_LOW; /* 31.5 MHz */ Video->PixelClock = RGB525_DF(0) | RGB525_VCO_DIV_COUNT(36); } else if ( HalpMonitorConfigurationData.HorizontalResolution == 640 && HalpMonitorConfigurationData.VerticalResolution == 480 && VerticalFrequency == 75) { Video->ImageWidth = 640; Video->ImageHeight = 480; Video->HLimit = 8 * 105; Video->HSyncStart = 8 * 2; Video->HSyncEnd = 8 * 10; Video->HBlankEnd = 8 * 25; Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; Video->VLimit = 500; Video->VSyncStart = 2; Video->VSyncEnd = 5; Video->VBlankEnd = 20; Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_LOW; /* 31.5 MHz */ Video->PixelClock = RGB525_DF(0) | RGB525_VCO_DIV_COUNT(61); } else if ( HalpMonitorConfigurationData.HorizontalResolution == 1280 && HalpMonitorConfigurationData.VerticalResolution == 1024 && VerticalFrequency == 57) { Video->ImageWidth = 1280; Video->ImageHeight = 1024; Video->HLimit = 8 * 211; Video->HSyncStart = 8 * 2; Video->HSyncEnd = 8 * 20; Video->HBlankEnd = 8 * 51; Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; Video->VLimit = 1066; Video->VSyncStart = 2; Video->VSyncEnd = 5; Video->VBlankEnd = 42; Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; /* 103 MHz */ Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(38); } else { // // force to set the resolution. 1024x768(60MHz) // Video->ImageWidth = 1024; Video->ImageHeight = 768; Video->HLimit = 8 * 168; Video->HSyncStart = 8 * 3; Video->HSyncEnd = 8 * 20; Video->HBlankEnd = 8 * 40; Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; Video->VLimit = 806; Video->VSyncStart = 4; Video->VSyncEnd = 10; Video->VBlankEnd = 38; Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; /* 65 MHz */ Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(0); #if DBG DbgBreakPoint(); #endif } /* record image depth */ Video->ImageDepth = 16; /* determine video clock divider and pixel format */ ClockDivider = 4; Video->PixelFormat = RGB525_PIXEL_FORMAT_16_BPP; /* adjust horizontal timings */ Video->HLimit /= ClockDivider; Video->HSyncStart /= ClockDivider; Video->HSyncEnd /= ClockDivider; Video->HBlankEnd /= ClockDivider; // // Initialize ramdac data // RGB525_WRITE(Dac, __RGB525_PixelMask, 0xff); /* set MiscControlOne register */ ByteVal = RGB525_MISR_CNTL_OFF | RGB525_VMSK_CNTL_OFF | RGB525_PADR_RFMT_READ_ADDR | RGB525_SENS_DSAB_DISABLE | RGB525_VRAM_SIZE_64; RGB525_SET_REG(Dac, __RGB525_MiscControlOne, ByteVal); /* set MiscControlTwo register */ ByteVal = RGB525_PCLK_SEL_PLL | RGB525_INTL_MODE_DISABLE | RGB525_BLANK_CNTL_NORMAL | RGB525_COL_RES_8_BIT | RGB525_PORT_SEL_VRAM; RGB525_SET_REG(Dac, __RGB525_MiscControlTwo, ByteVal); /* set MiscControlThree register */ ByteVal = RGB525_SWAP_RB_DISABLE | RGB525_SWAP_WORD_31_00_FIRST | RGB525_SWAP_NIB_07_04_FIRST; RGB525_SET_REG(Dac, __RGB525_MiscControlThree, ByteVal); /* set MiscClockControl register */ ByteVal = RGB525_DDOTCLK_DISABLE | RGB525_SCLK_ENABLE | RGB525_PLL_ENABLE; RGB525_SET_REG(Dac, __RGB525_MiscClockControl, ByteVal); /* set SyncControl register */ ByteVal = RGB525_DLY_CNTL_ADD | RGB525_VSYN_INVT_DISABLE | RGB525_HSYN_INVT_DISABLE | RGB525_VSYN_CNTL_NORMAL | RGB525_HSYN_CNTL_NORMAL; RGB525_SET_REG(Dac, __RGB525_SyncControl, ByteVal); /* set HSyncControl register */ RGB525_SET_REG(Dac, __RGB525_HSyncControl, RGB525_HSYN_POS(0)); /* set PowerManagement register */ ByteVal = RGB525_SCLK_PWR_NORMAL | RGB525_DDOT_PWR_DISABLE | RGB525_SYNC_PWR_NORMAL | RGB525_ICLK_PWR_NORMAL | RGB525_DAC_PWR_NORMAL; RGB525_SET_REG(Dac, __RGB525_PowerManagement, ByteVal); /* set DACOperation register */ ByteVal = RGB525_SOG_DISABLE | RGB525_BRB_NORMAL | RGB525_DSR_FAST | RGB525_DPE_ENABLE; /* disable? */ RGB525_SET_REG(Dac, __RGB525_DACOperation, ByteVal); /* set PaletteControl register */ ByteVal = RGB525_6BIT_LINEAR_ENABLE | RGB525_PALETTE_PARTITION(0); RGB525_SET_REG(Dac, __RGB525_PaletteControl, ByteVal); /* set PixelFormat register */ RGB525_SET_REG(Dac, __RGB525_PixelFormat, Video->PixelFormat); /* set 8BitPixelControl register */ RGB525_SET_REG(Dac, __RGB525_8BitPixelControl, RGB525_B8_DCOL_INDIRECT); /* set 16BitPixelControl register */ ByteVal = RGB525_B16_DCOL_INDIRECT | RGB525_B16_565 | RGB525_B16_ZIB | RGB525_B16_SPARSE; RGB525_SET_REG(Dac, __RGB525_16BitPixelControl, ByteVal); /* set 32BitPixelControl register */ RGB525_SET_REG(Dac, __RGB525_32BitPixelControl, RGB525_B32_DCOL_INDIRECT); /* set PLLControlOne register */ ByteVal = RGB525_REF_SRC_REFCLK | RGB525_PLL_INT_FS_DIRECT; RGB525_SET_REG(Dac, __RGB525_PLLControlOne, ByteVal); /* set PLLControlTwo register */ RGB525_SET_REG(Dac, __RGB525_PLLControlTwo, RGB525_PLL_INT_FS(0)); /* set PLLRefDivCount register */ RGB525_SET_REG(Dac, __RGB525_PLLRefDivCount, Video->RefDivCount); /* set F0 register */ RGB525_SET_REG(Dac, __RGB525_F0, Video->PixelClock); /* set CursorControl register */ RGB525_SET_REG(Dac, __RGB525_CursorControl, RGB525_CURSOR_MODE_OFF); // // Initialize timing // /* horizontal video timing values */ GLINT_WRITE(Glint, __GLINT_VTGHLimit, Video->HLimit); GLINT_WRITE(Glint, __GLINT_VTGHSyncStart, Video->HSyncStart); GLINT_WRITE(Glint, __GLINT_VTGHSyncEnd, Video->HSyncEnd); GLINT_WRITE(Glint, __GLINT_VTGHBlankEnd, Video->HBlankEnd); /* vertical video timing values */ GLINT_WRITE(Glint, __GLINT_VTGVLimit, Video->VLimit); GLINT_WRITE(Glint, __GLINT_VTGVSyncStart, Video->VSyncStart); GLINT_WRITE(Glint, __GLINT_VTGVSyncEnd, Video->VSyncEnd); GLINT_WRITE(Glint, __GLINT_VTGVBlankEnd, Video->VBlankEnd); /* horizontal clock gate values */ GLINT_WRITE(Glint, __GLINT_VTGHGateStart, Video->HBlankEnd - 2); GLINT_WRITE(Glint, __GLINT_VTGHGateEnd, Video->HLimit - 2); /* vertical clock gate values */ GLINT_WRITE(Glint, __GLINT_VTGVGateStart, Video->VBlankEnd - 1) GLINT_WRITE(Glint, __GLINT_VTGVGateEnd, Video->VBlankEnd); // // Initialize control // /* serial clock control */ SerialClk = GLINT_EXTERNAL_QSF | GLINT_SPLIT_SIZE_128_WORD | GLINT_SCLK_VCLK_DIV_2; GLINT_WRITE(Glint, __GLINT_VTGSerialClk, SerialClk); /* set sync polarities and unblank screen */ // UpdatePolarityRegister(Glint, // GLINT_CBLANK_ACTIVE_LOW // | Video->HSyncPolarity // | Video->VSyncPolarity, // GLINT_CBLANK_POLARITY_MASK // | GLINT_HSYNC_POLARITY_MASK // | GLINT_VSYNC_POLARITY_MASK); Data = GLINT_CBLANK_ACTIVE_LOW | Video->HSyncPolarity | Video->VSyncPolarity; Mask = GLINT_CBLANK_POLARITY_MASK | GLINT_HSYNC_POLARITY_MASK | GLINT_VSYNC_POLARITY_MASK; /* read video polarity control register */ GLINT_READ(Glint, __GLINT_VTGPolarity, Temp); /* replace existing polarity field */ Temp = (Temp & ~Mask) | (Data & Mask); /* write result back to polarity register */ GLINT_WRITE(Glint, __GLINT_VTGPolarity, Temp); /* set FrameRowAddr */ GLINT_WRITE(Glint, __GLINT_VTGFrameRowAddr, 0); // // Initialize RampLut // /* initialise palette address */ RGB525_WRITE(Dac, __RGB525_PalAddrWrite, 0); /* ramp colour components using auto-increment */ for (Index = 0; Index <= 0xff; Index++) { RGB525_WRITE(Dac, __RGB525_PaletteData, Index); RGB525_WRITE(Dac, __RGB525_PaletteData, Index); RGB525_WRITE(Dac, __RGB525_PaletteData, Index); } // // Clear the screen. // DestinationUlong = (PULONG)VIDEO_MEMORY_BASE; Length = (HalpMonitorConfigurationData.VerticalResolution * HalpMonitorConfigurationData.HorizontalResolution -1) * sizeof(USHORT); for (Index = 0; Index < (Length / sizeof(ULONG)); Index++) *(DestinationUlong++) = (ULONG)0x000f000f; // // Initialize the current display column, row, and ownership values. // HalpColumn = 0; HalpRow = 0; HalpDisplayOwnedByHal = TRUE; return; } #endif // _R94A_ // // M010 // for software controlled power supply. // #if defined(_MRCPOWER_) /* Start M007 */ VOID HalpMrcModeChange( UCHAR Mode ) /*++ Routine Description: This routine is change Mode bit on MRC Controller. Arguments: Mode - Parameter for setting Mode bit on MRC Return Value: None --*/ { PHYSICAL_ADDRESS physicalAddress; UCHAR ModeNow; KIRQL OldIrql; ENTRYLO Pte[2]; // // MRC Controller Mapping, when first call // if (HalpMrcControlMapped == FALSE) { physicalAddress.HighPart = 0; physicalAddress.LowPart = MRC_TEMP_PHYSICAL_BASE; HalpMrcControlBase = MmMapIoSpace(physicalAddress, PAGE_SIZE, FALSE); if (HalpMrcControlBase != NULL) { HalpMrcControlMapped = TRUE; } } if (HalpMrcControlMapped == TRUE){ ModeNow = READ_REGISTER_UCHAR( &((PMRC_REGISTERS)HalpMrcControlBase)->Mode ); // // Set MRC Mode bit // WRITE_REGISTER_UCHAR( &((PMRC_REGISTERS)HalpMrcControlBase)->Mode, ((ModeNow & 0x02) | (Mode << 7)), ); } else { KeRaiseIrql(HIGH_LEVEL, &OldIrql); Pte[0].PFN = MRC_TEMP_PHYSICAL_BASE >> PAGE_SHIFT; Pte[0].G = 1; Pte[0].V = 1; Pte[0].D = 1; // // set second page to global and not valid. // Pte[0].C = UNCACHED_POLICY; Pte[1].G = 1; Pte[1].V = 0; // // Map MRC using virtual address of DMA controller. // KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0], (PVOID)DMA_VIRTUAL_BASE, DMA_ENTRY); ModeNow = READ_REGISTER_UCHAR( &MRC_CONTROL->Mode // B028 ); // // Set MRC Mode bit // WRITE_REGISTER_UCHAR( &MRC_CONTROL->Mode, ((ModeNow & 0x02) | (Mode << 7)), ); // Start M008 // // Resume fixed TLB for DMA // Pte[0].PFN = DMA_PHYSICAL_BASE >> PAGE_SHIFT; Pte[0].G = 1; Pte[0].V = 1; Pte[0].D = 1; Pte[0].C = UNCACHED_POLICY; Pte[1].PFN = INTERRUPT_PHYSICAL_BASE >> PAGE_SHIFT; Pte[1].G = 1; Pte[1].V = 1; Pte[1].D = 1; Pte[1].C = UNCACHED_POLICY; // End M008 KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0], (PVOID)DMA_VIRTUAL_BASE, DMA_ENTRY); KeLowerIrql(OldIrql); } } /* End M007 */ #endif // _MRCPOWER_ VOID HalpWritePCIConfigUlongByOffset ( IN PCI_SLOT_NUMBER Slot, IN PULONG Buffer, IN ULONG Offset ) /*++ Routine Description: This function writes PCI configuration data. Arguments: Slot - Supplies a PCI slot number and function number. Buffer - Supplies a pointer to a configuration data to write. Offset - Offset in the PCI configuration header. Return Value: None. --*/ { R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; USHORT StatusValue; KIRQL OldIrql; // // check to see if specified slot is valid // if (!HalpCheckPCIDevice(Slot)) { // // Invalid SlotID return no data // *Buffer = 0xffffffff; return ; } *((PULONG) &ConfigAddressValue) = 0x0; ConfigAddressValue.ConfigEnable = 1; ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber; ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber; ConfigAddressValue.RegisterNumber = Offset >> 2; // // Synchronize with PCI configuration // // KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017 // KiAcquireSpinLock(&HalpPCIConfigLock); WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue)); // *Buffer = READ_REGISTER_ULONG(R94A_PCI_DATA_REG); WRITE_REGISTER_ULONG(R94A_PCI_DATA_REG, *Buffer); // // Release spinlock // // KiReleaseSpinLock(&HalpPCIConfigLock); // KeLowerIrql(OldIrql); return; } VOID HalpReadPCIConfigUshortByOffset ( IN PCI_SLOT_NUMBER Slot, IN PUSHORT Buffer, IN ULONG Offset ) /*++ Routine Description: This function returns PCI configuration data. Arguments: Slot - Supplies a PCI slot number and function number. Buffer - Supplies a pointer to a configuration data is returned. Offset - Offset in the PCI configuration header. Return Value: None. --*/ { R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; USHORT StatusValue; KIRQL OldIrql; // // check to see if specified slot is valid // if (!HalpCheckPCIDevice(Slot)) { // // Invalid SlotID return no data // *Buffer = 0xffff; return ; } *((PULONG) &ConfigAddressValue) = 0x0; ConfigAddressValue.ConfigEnable = 1; ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber; ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber; ConfigAddressValue.RegisterNumber = Offset >> 2; // // Synchronize with PCI configuration // // KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017 // KiAcquireSpinLock(&HalpPCIConfigLock); WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue)); *Buffer = READ_REGISTER_USHORT((PUCHAR)R94A_PCI_DATA_REG + (Offset % sizeof(ULONG))); // // Release spinlock // // KiReleaseSpinLock(&HalpPCIConfigLock); // KeLowerIrql(OldIrql); return; } VOID HalpWritePCIConfigUshortByOffset ( IN PCI_SLOT_NUMBER Slot, IN PUSHORT Buffer, IN ULONG Offset ) /*++ Routine Description: This function returns PCI configuration data. Arguments: Slot - Supplies a PCI slot number and function number. Buffer - Supplies a pointer to a configuration data is returned. Offset - Offset in the PCI configuration header. Return Value: None. --*/ { R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; USHORT StatusValue; KIRQL OldIrql; // // check to see if specified slot is valid // if (!HalpCheckPCIDevice(Slot)) { // // Invalid SlotID return no data // *Buffer = 0xffff; return ; } *((PULONG) &ConfigAddressValue) = 0x0; ConfigAddressValue.ConfigEnable = 1; ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber; ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber; ConfigAddressValue.RegisterNumber = Offset >> 2; // // Synchronize with PCI configuration // // KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017 // KiAcquireSpinLock(&HalpPCIConfigLock); WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue)); // *Buffer = READ_REGISTER_ULONG(R94A_PCI_DATA_REG); WRITE_REGISTER_USHORT((PUCHAR)R94A_PCI_DATA_REG + (Offset % sizeof(ULONG)),*Buffer); // // Release spinlock // // KiReleaseSpinLock(&HalpPCIConfigLock); // KeLowerIrql(OldIrql); return; } VOID HalpReadPCIConfigUcharByOffset ( IN PCI_SLOT_NUMBER Slot, IN PUCHAR Buffer, IN ULONG Offset ) /*++ Routine Description: This function returns PCI configuration data. Arguments: Slot - Supplies a PCI slot number and function number. Buffer - Supplies a pointer to a configuration data is returned. Offset - Offset in the PCI configuration header. Return Value: None. --*/ { R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; USHORT StatusValue; KIRQL OldIrql; // // check to see if specified slot is valid // if (!HalpCheckPCIDevice(Slot)) { // // Invalid SlotID return no data // *Buffer = 0xff; return ; } *((PULONG) &ConfigAddressValue) = 0x0; ConfigAddressValue.ConfigEnable = 1; ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber; ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber; ConfigAddressValue.RegisterNumber = Offset >> 2; // // Synchronize with PCI configuration // // KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017 // KiAcquireSpinLock(&HalpPCIConfigLock); WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue)); *Buffer = READ_REGISTER_UCHAR((PUCHAR)R94A_PCI_DATA_REG + (Offset % sizeof(ULONG))); // // Release spinlock // // KiReleaseSpinLock(&HalpPCIConfigLock); // KeLowerIrql(OldIrql); return; } VOID HalpWritePCIConfigUcharByOffset ( IN PCI_SLOT_NUMBER Slot, IN PUCHAR Buffer, IN ULONG Offset ) /*++ Routine Description: This function returns PCI configuration data. Arguments: Slot - Supplies a PCI slot number and function number. Buffer - Supplies a pointer to a configuration data is returned. Offset - Offset in the PCI configuration header. Return Value: None. --*/ { R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; USHORT StatusValue; KIRQL OldIrql; // // check to see if specified slot is valid // if (!HalpCheckPCIDevice(Slot)) { // // Invalid SlotID return no data // *Buffer = 0xff; return ; } *((PULONG) &ConfigAddressValue) = 0x0; ConfigAddressValue.ConfigEnable = 1; ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber; ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber; ConfigAddressValue.RegisterNumber = Offset >> 2; // // Synchronize with PCI configuration // // KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017 // KiAcquireSpinLock(&HalpPCIConfigLock); WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue)); // *Buffer = READ_REGISTER_ULONG(R94A_PCI_DATA_REG); WRITE_REGISTER_UCHAR((PUCHAR)R94A_PCI_DATA_REG + (Offset % sizeof(ULONG)),*Buffer); // // Release spinlock // // KiReleaseSpinLock(&HalpPCIConfigLock); // KeLowerIrql(OldIrql); return; }