/************************************************************************/ /* */ /* INIT_M.C */ /* */ /* Sep 27 1993 (c) 1993, ATI Technologies Incorporated. */ /************************************************************************/ /********************** PolyTron RCS Utilities $Revision: 1.16 $ $Date: 15 May 1996 16:35:42 $ $Author: RWolff $ $Log: S:/source/wnt/ms11/miniport/archive/init_m.c_v $ * * Rev 1.16 15 May 1996 16:35:42 RWolff * Waits for idle after setting accelerator mode. * * Rev 1.15 17 Apr 1996 13:09:26 RWolff * Backed out Alpha LFB mapping as dense. * * Rev 1.14 11 Apr 1996 15:12:40 RWolff * Now maps framebuffer as dense on DEC Alpha with PCI graphics card. * * Rev 1.13 31 Mar 1995 11:53:46 RWOLFF * Changed from all-or-nothing debug print statements to thresholds * depending on importance of the message. * * Rev 1.12 14 Feb 1995 15:41:20 RWOLFF * Changed conditional compile that uses or fakes failure of * VideoPortMapBankedMemory() to look for IOCTL_VIDEO_SHARE_VIDEO_MEMORY * instead of the routine itself. Looking for the routine always failed, * and since the routine is supplied in order to allow DCI to be used * on systems without a linear framebuffer, it should be available on * any DDK version that supports the IOCTL. If it isn't, a compile-time * error will be generated (unresolved external reference). * * Rev 1.11 03 Feb 1995 15:17:00 RWOLFF * Added support for DCI, removed dead code. * * Rev 1.10 23 Dec 1994 10:47:18 ASHANMUG * ALPHA/Chrontel-DAC * * Rev 1.9 22 Jul 1994 17:48:50 RWOLFF * Merged with Richard's non-x86 code stream. * * Rev 1.8 27 Jun 1994 16:30:12 RWOLFF * Now reports all hardware default mode tables as noninterlaced to * avoid confusing the display applet. * * Rev 1.7 15 Jun 1994 11:07:08 RWOLFF * Now uses VideoPortZeroDeviceMemory() to clear 24BPP screens on NT builds * where this function is available. * * Rev 1.6 12 May 1994 11:05:32 RWOLFF * Reports the refresh rate from the mode table, rather than always * reporting "Use hardware default". * * Rev 1.5 31 Mar 1994 15:02:00 RWOLFF * Added SetPowerManagement_m() function to implement DPMS handling. * * Rev 1.4 14 Mar 1994 16:31:36 RWOLFF * XMillimeter field of mode information structure now set properly. * * Rev 1.3 03 Mar 1994 12:37:54 ASHANMUG * Pageable * * Rev 1.1 31 Jan 1994 16:27:06 RWOLFF * Now fills in Frequency and VideoMemoryBitmap[Width|Height] fields of * mode information structure. Sets Number[Red|Green|Blue]Bits fields * for palette modes to 6 (assumes VGA-compatible DAC) instead of 0 * to allow Windows NT to set the palette colours to the best match * for the colours to be displayed. * * Rev 1.0 31 Jan 1994 11:10:40 RWOLFF * Initial revision. * * Rev 1.6 24 Jan 1994 18:04:28 RWOLFF * Now puts DAC in known state before setting video mode. This is to * accomodate the Graphics Wonder (1M DRAM Mach 32 with BT48x DAC). * * Rev 1.5 14 Jan 1994 15:21:22 RWOLFF * SetCurrentMode_m() and (new routine) ResetDevice_m() now initialize * and deinitialize the bank manager. * * Rev 1.4 15 Dec 1993 15:26:48 RWOLFF * Added note to clean up before sending to Microsoft. * * Rev 1.3 30 Nov 1993 18:16:34 RWOLFF * MapVideoMemory_m() now sets memoryInformation->FrameBufferLength to * aperture size rather than amount of video memory present. * * Rev 1.2 05 Nov 1993 13:25:24 RWOLFF * Switched to defined values for memory type, 1280x1024 DAC initialization is * now done in the same manner as for other resolutions. * * Rev 1.0 08 Oct 1993 11:20:34 RWOLFF * Initial revision. End of PolyTron RCS section *****************/ #ifdef DOC INIT_M.C - Highest-level card-dependent routines for miniport. DESCRIPTION This file contains initialization and packet handling routines for 8514/A-compatible ATI accelerators. Routines in this module are called only by routines in ATIMP.C, which is card-independent. OTHER FILES #endif #include "dderror.h" #include "miniport.h" #include "ntddvdeo.h" #include "video.h" #include "stdtyp.h" #include "amach.h" #include "amach1.h" #include "atimp.h" #include "atint.h" #define INCLUDE_INIT_M #include "init_m.h" #include "modes_m.h" #include "services.h" #include "setup_m.h" /* * Prototypes for static functions. */ static void QuerySingleMode_m(PVIDEO_MODE_INFORMATION ModeInformation, struct query_structure *QueryPtr, ULONG ModeIndex); /* * Allow miniport to be swapped out when not needed. */ #if defined (ALLOC_PRAGMA) #pragma alloc_text(PAGE_M, AlphaInit_m) #pragma alloc_text(PAGE_M, Initialize_m) #pragma alloc_text(PAGE_M, MapVideoMemory_m) #pragma alloc_text(PAGE_M, QueryPublicAccessRanges_m) #pragma alloc_text(PAGE_M, QueryCurrentMode_m) #pragma alloc_text(PAGE_M, QueryAvailModes_m) #pragma alloc_text(PAGE_M, QuerySingleMode_m) #pragma alloc_text(PAGE_M, SetCurrentMode_m) #pragma alloc_text(PAGE_M, ResetDevice_m) #pragma alloc_text(PAGE_M, SetPowerManagement_m) #pragma alloc_text(PAGE_M, ShareVideoMemory_m) /* BankMap_m() can't be made pageable */ #endif /*************************************************************************** * * void AlphaInit_m(void); * * DESCRIPTION: * Perform the initialization that would normally be done by the ROM * BIOS on x86 machines. * * GLOBALS CHANGED: * none * * CALLED BY: * ATIMPFindAdapter() * * AUTHOR: * Robert Wolff * * CHANGE HISTORY: * * TEST HISTORY: * ***************************************************************************/ void AlphaInit_m(void) { OUTPW(MEM_CFG, 0); DEC_DELAY OUTPW(MISC_OPTIONS, 0xb0a9); DEC_DELAY OUTPW(MEM_BNDRY, 0); DEC_DELAY #if 0 OUTPW(CONFIG_STATUS_1, 0x1410); DEC_DELAY OUTPW(SCRATCH_PAD_1, 0); DEC_DELAY OUTPW(SCRATCH_PAD_0, 0); DEC_DELAY #endif OUTPW(CLOCK_SEL, 0x250); DEC_DELAY OUTPW(DAC_W_INDEX, 0x40); DEC_DELAY OUTPW(MISC_CNTL, 0xC00); DEC_DELAY OUTPW(LOCAL_CONTROL, 0x1402); #if defined (MIPS) || defined (_MIPS_) DEC_DELAY OUTPW(OVERSCAN_COLOR_8, 0); //RKE: to eliminate left overscan on MIPS #endif DEC_DELAY return; } /* AlphaInit_m() */ /*************************************************************************** * * void Initialize_m(void); * * DESCRIPTION: * This routine is the 8514/A-compatible hardware initialization routine * for the miniport driver. It is called once an adapter has been found * and all the required data structures for it have been created. * * GLOBALS CHANGED: * none * * CALLED BY: * ATIMPInitialize() * * AUTHOR: * Robert Wolff * * CHANGE HISTORY: * * TEST HISTORY: * ***************************************************************************/ void Initialize_m(void) { /* * Make sure we have enough available FIFO entries * to initialize the card. */ CheckFIFOSpace_m(SIXTEEN_WORDS); /* * On the 68800, set the memory boundary to shared VGA memory. * On all cards, set the screen and drawing engine to start * at the beginning of accelerator memory and MEM_CNTL * to linear. */ if (phwDeviceExtension->ModelNumber == MACH32_ULTRA) OUTP (MEM_BNDRY,0); OUTPW(CRT_OFFSET_LO, 0); OUTPW(GE_OFFSET_LO, 0); OUTPW(CRT_OFFSET_HI, 0); OUTPW(GE_OFFSET_HI, 0); OUTPW(MEM_CNTL,0x5006); /* * Reset the engine and FIFO, then return to normal operation. */ OUTPW(SUBSYS_CNTL,0x9000); OUTPW(SUBSYS_CNTL,0x5000); /* * The hardware cursor is available only for Mach 32 cards. * disable the cursor and initialize it to display quadrant I - 0 */ if (phwDeviceExtension->ModelNumber == MACH32_ULTRA) { OUTPW(CURSOR_OFFSET_HI,0); OUTPW(HORZ_CURSOR_OFFSET,0); OUTP(VERT_CURSOR_OFFSET,0); OUTPW(CURSOR_COLOR_0, 0x0FF00); /* Colour 0 black, colour 1 white */ OUTPW(EXT_CURSOR_COLOR_0,0); // black OUTPW(EXT_CURSOR_COLOR_1,0xffff); // white } return; } /* Initialize_m() */ /************************************************************************** * * VP_STATUS MapVideoMemory_m(RequestPacket, QueryPtr); * * PVIDEO_REQUEST_PACKET RequestPacket; Request packet with input and output buffers * struct query_structure *QueryPtr; Query information for the card * * DESCRIPTION: * Map the card's video memory into system memory and store the mapped * address and size in OutputBuffer. * * RETURN VALUE: * NO_ERROR if successful * error code if failed * * GLOBALS CHANGED: * FrameLength and PhysicalFrameAddress fields of phwDeviceExtension * if Mach 32 card without linear framebuffer. * * CALLED BY: * IOCTL_VIDEO_MAP_VIDEO_MEMORY packet of ATIMPStartIO() * * AUTHOR: * Robert Wolff * * CHANGE HISTORY: * * TEST HISTORY: * ***************************************************************************/ VP_STATUS MapVideoMemory_m(PVIDEO_REQUEST_PACKET RequestPacket, struct query_structure *QueryPtr) { PVIDEO_MEMORY_INFORMATION memoryInformation; ULONG inIoSpace; /* Scratch variable used by VideoPortMapMemory() */ VP_STATUS status; /* Error code obtained from O/S calls */ memoryInformation = RequestPacket->OutputBuffer; memoryInformation->VideoRamBase = ((PVIDEO_MEMORY) (RequestPacket->InputBuffer))->RequestedVirtualAddress; /* * The VideoRamLength field contains the amount of video memory * on the card. The FrameBufferLength field contains the * size of the aperture in bytes * * Initially assume that the linear aperture is available. * For our 8514/A-compatible cards, we always enable a 4M aperture * if the LFB is available, so map the full 4M even if the * aperture size is greater than the amount of video memory. */ memoryInformation->VideoRamLength = phwDeviceExtension->VideoRamSize; memoryInformation->FrameBufferLength = 4 * ONE_MEG; /* * If the linear aperture is not available (==0), and we are * dealing with a card which can use the VGA 64k aperture, * map it in. */ if (QueryPtr->q_aperture_cfg == 0) { if ((phwDeviceExtension->ModelNumber == MACH32_ULTRA) && (QueryPtr->q_VGA_type == 1)) { phwDeviceExtension->FrameLength = 0x10000; phwDeviceExtension->PhysicalFrameAddress.LowPart = 0x0A0000; memoryInformation->FrameBufferLength = phwDeviceExtension->FrameLength; } else{ /* * This card can't use either linear or VGA aperture. * Set frame buffer size to zero and return. */ memoryInformation->VideoRamBase = 0; memoryInformation->FrameBufferLength = 0; memoryInformation->FrameBufferBase = 0; return NO_ERROR; } } inIoSpace = 0; #if 0 /* defined(ALPHA) if display driver can handle dense LFB */ if (QueryPtr->q_bus_type == BUS_PCI) inIoSpace = 4; #endif status = VideoPortMapMemory(phwDeviceExtension, phwDeviceExtension->PhysicalFrameAddress, &(memoryInformation->FrameBufferLength), &inIoSpace, &(memoryInformation->VideoRamBase)); memoryInformation->FrameBufferBase = memoryInformation->VideoRamBase; return status; } /* MapVideoMemory_m() */ /************************************************************************** * * VP_STATUS QueryPublicAccessRanges_m(RequestPacket); * * PVIDEO_REQUEST_PACKET RequestPacket; Request packet with input and output buffers * * DESCRIPTION: * Map and return information on the video card's public access ranges. * * RETURN VALUE: * NO_ERROR if successful * error code if failed * * GLOBALS CHANGED: * none * * CALLED BY: * IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES packet of ATIMPStartIO() * * AUTHOR: * Robert Wolff * * CHANGE HISTORY: * * TEST HISTORY: * ***************************************************************************/ VP_STATUS QueryPublicAccessRanges_m(PVIDEO_REQUEST_PACKET RequestPacket) { PVIDEO_PUBLIC_ACCESS_RANGES portAccess; PHYSICAL_ADDRESS physicalPortBase; ULONG physicalPortLength; if ( RequestPacket->OutputBufferLength < (RequestPacket->StatusBlock->Information = sizeof(VIDEO_PUBLIC_ACCESS_RANGES)) ) { return ERROR_INSUFFICIENT_BUFFER; } portAccess = RequestPacket->OutputBuffer; portAccess->VirtualAddress = (PVOID) NULL; // Requested VA portAccess->InIoSpace = 1; // In IO space portAccess->MappedInIoSpace = portAccess->InIoSpace; physicalPortBase.HighPart = 0x00000000; physicalPortBase.LowPart = 0x00000000; // physicalPortLength = LINEDRAW+2 - physicalPortBase.LowPart; physicalPortLength = 0x10000; // *SANITIZE* If MM available, give MM ports instead. return VideoPortMapMemory(phwDeviceExtension, physicalPortBase, &physicalPortLength, &(portAccess->MappedInIoSpace), &(portAccess->VirtualAddress)); } /* QueryPublicAccessRanges_m() */ /************************************************************************** * * VP_STATUS QueryCurrentMode_m(RequestPacket, QueryPtr); * * PVIDEO_REQUEST_PACKET RequestPacket; Request packet with input and output buffers * struct query_structure *QueryPtr; Query information for the card * * DESCRIPTION: * Get screen information and colour masks for the current video mode. * * RETURN VALUE: * NO_ERROR if successful * error code if failed * * GLOBALS CHANGED: * none * * CALLED BY: * IOCTL_VIDEO_QUERY_CURRENT_MODE packet of ATIMPStartIO() * * AUTHOR: * Robert Wolff * * CHANGE HISTORY: * * TEST HISTORY: * ***************************************************************************/ VP_STATUS QueryCurrentMode_m(PVIDEO_REQUEST_PACKET RequestPacket, struct query_structure *QueryPtr) { PVIDEO_MODE_INFORMATION ModeInformation; /* * If the output buffer is too small to hold the information we need * to put in it, return with the appropriate error code. */ if (RequestPacket->OutputBufferLength < (RequestPacket->StatusBlock->Information = sizeof(VIDEO_MODE_INFORMATION)) ) { return ERROR_INSUFFICIENT_BUFFER; } /* * Fill in the mode information structure. */ ModeInformation = RequestPacket->OutputBuffer; QuerySingleMode_m(ModeInformation, QueryPtr, phwDeviceExtension->ModeIndex); return NO_ERROR; } /* QueryCurrentMode_m() */ /************************************************************************** * * VP_STATUS QueryAvailModes_m(RequestPacket, QueryPtr); * * PVIDEO_REQUEST_PACKET RequestPacket; Request packet with input and output buffers * struct query_structure *QueryPtr; Query information for the card * * DESCRIPTION: * Get screen information and colour masks for all available video modes. * * RETURN VALUE: * NO_ERROR if successful * error code if failed * * GLOBALS CHANGED: * none * * CALLED BY: * IOCTL_VIDEO_QUERY_AVAIL_MODES packet of ATIMPStartIO() * * AUTHOR: * Robert Wolff * * CHANGE HISTORY: * * TEST HISTORY: * ***************************************************************************/ VP_STATUS QueryAvailModes_m(PVIDEO_REQUEST_PACKET RequestPacket, struct query_structure *QueryPtr) { PVIDEO_MODE_INFORMATION ModeInformation; ULONG CurrentMode; /* * If the output buffer is too small to hold the information we need * to put in it, return with the appropriate error code. */ if (RequestPacket->OutputBufferLength < (RequestPacket->StatusBlock->Information = QueryPtr->q_number_modes * sizeof(VIDEO_MODE_INFORMATION)) ) { return ERROR_INSUFFICIENT_BUFFER; } /* * Fill in the mode information structure. */ ModeInformation = RequestPacket->OutputBuffer; /* * For each mode supported by the card, store the mode characteristics * in the output buffer. */ for (CurrentMode = 0; CurrentMode < QueryPtr->q_number_modes; CurrentMode++, ModeInformation++) QuerySingleMode_m(ModeInformation, QueryPtr, CurrentMode); return NO_ERROR; } /* QueryCurrentMode_m() */ /************************************************************************** * * static void QuerySingleMode_m(ModeInformation, QueryPtr, ModeIndex); * * PVIDEO_MODE_INFORMATION ModeInformation; Table to be filled in * struct query_structure *QueryPtr; Query information for the card * ULONG ModeIndex; Index of mode table to use * * DESCRIPTION: * Fill in a single Windows NT mode information table using data from * one of our CRT parameter tables. * * GLOBALS CHANGED: * none * * CALLED BY: * QueryCurrentMode_m() and QueryAvailModes_m() * * AUTHOR: * Robert Wolff * * CHANGE HISTORY: * * TEST HISTORY: * ***************************************************************************/ static void QuerySingleMode_m(PVIDEO_MODE_INFORMATION ModeInformation, struct query_structure *QueryPtr, ULONG ModeIndex) { struct st_mode_table *CrtTable; /* Pointer to current mode table */ CrtTable = (struct st_mode_table *)QueryPtr; ((struct query_structure *)CrtTable)++; CrtTable += ModeIndex; ModeInformation->Length = sizeof(VIDEO_MODE_INFORMATION); ModeInformation->ModeIndex = ModeIndex; ModeInformation->VisScreenWidth = CrtTable->m_x_size; ModeInformation->VisScreenHeight = CrtTable->m_y_size; // * Bytes per line = ((pixels/line) * (bits/pixel)) / (bits/byte)) ModeInformation->ScreenStride = (CrtTable->m_screen_pitch * CrtTable->m_pixel_depth) / 8; ModeInformation->NumberOfPlanes = 1; ModeInformation->BitsPerPlane = (USHORT) CrtTable->m_pixel_depth; ModeInformation->Frequency = CrtTable->Refresh; /* * Driver can't measure the screen size, * so take reasonable values (16" diagonal). */ ModeInformation->XMillimeter = 320; ModeInformation->YMillimeter = 240; switch(ModeInformation->BitsPerPlane) { case 16: ModeInformation->RedMask = 0x0000f800; ModeInformation->GreenMask = 0x000007e0; ModeInformation->BlueMask = 0x0000001f; ModeInformation->NumberRedBits = 5; ModeInformation->NumberGreenBits = 6; ModeInformation->NumberBlueBits = 5; CrtTable->ColourDepthInfo = PIX_WIDTH_16BPP | ORDER_16BPP_565; break; case 24: /* * Windows NT uses RGB as the standard 24BPP mode, * so use this ordering for all DACs except the * Brooktree 48x which only supports BGR. */ if (QueryPtr->q_DAC_type != DAC_BT48x) { ModeInformation->RedMask = 0x00ff0000; ModeInformation->GreenMask = 0x0000ff00; ModeInformation->BlueMask = 0x000000ff; CrtTable->ColourDepthInfo = PIX_WIDTH_24BPP | ORDER_24BPP_RGB; } else{ ModeInformation->RedMask = 0x000000ff; ModeInformation->GreenMask = 0x0000ff00; ModeInformation->BlueMask = 0x00ff0000; CrtTable->ColourDepthInfo = PIX_WIDTH_24BPP | ORDER_24BPP_BGR; } ModeInformation->NumberRedBits = 8; ModeInformation->NumberGreenBits = 8; ModeInformation->NumberBlueBits = 8; break; case 32: /* * Only the Brooktree 481 requires BGR, * and it doesn't support 32BPP. */ ModeInformation->RedMask = 0xff000000; ModeInformation->GreenMask = 0x00ff0000; ModeInformation->BlueMask = 0x0000ff00; ModeInformation->NumberRedBits = 8; ModeInformation->NumberGreenBits = 8; ModeInformation->NumberBlueBits = 8; CrtTable->ColourDepthInfo = PIX_WIDTH_24BPP | ORDER_24BPP_RGBx; break; default: ModeInformation->RedMask = 0x00000000; ModeInformation->GreenMask = 0x00000000; ModeInformation->BlueMask = 0x00000000; ModeInformation->NumberRedBits = 6; ModeInformation->NumberGreenBits = 6; ModeInformation->NumberBlueBits = 6; CrtTable->ColourDepthInfo = PIX_WIDTH_8BPP; break; } ModeInformation->AttributeFlags = VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS; if (CrtTable->m_pixel_depth <= 8) { ModeInformation->AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE; } /* * Bit 4 of the m_disp_cntl field is set for interlaced and * cleared for noninterlaced. * * The display applet gets confused if some of the "Use hardware * default" modes are interlaced and some are noninterlaced * (two "Use hardware default" entries are shown in the refresh * rate list). To avoid this, report all mode tables stored in * the EEPROM as noninterlaced, even if they are interlaced. * "Canned" mode tables give true reports. */ if ((CrtTable->m_disp_cntl & 0x010) && (ModeInformation->Frequency != DEFAULT_REFRESH)) ModeInformation->AttributeFlags |= VIDEO_MODE_INTERLACED; else ModeInformation->AttributeFlags &= ~VIDEO_MODE_INTERLACED; /* * Fill in the video memory bitmap width and height fields. * The descriptions are somewhat ambiguous - assume that * "bitmap width" is the same as ScreenStride (bytes from * start of one scanline to start of the next) and "bitmap * height" refers to the number of complete scanlines which * will fit into video memory. */ ModeInformation->VideoMemoryBitmapWidth = ModeInformation->ScreenStride; ModeInformation->VideoMemoryBitmapHeight = (QueryPtr->q_memory_size * QUARTER_MEG) / ModeInformation->VideoMemoryBitmapWidth; return; } /* QuerySingleMode_m() */ // // When coming back from hibernate, mach32s can lock up and blackscreen. // This is because the card itself has to be reinitialized. // This initialization include at least the frame buffer initialization // and the initialization of the use of memory mapped registers. // VOID EnableMach32FrameBufferAndMemMappedRegisters( PHW_DEVICE_EXTENSION pHwDeviceExtension ) { USHORT temp, temp1; // // enable the framebuffer. // temp = INPW(MEM_CFG) & 0x0fffc; /* Preserve bits 2-15 */ temp |= 0x0002; /* 4M aperture */ OUTPW(MEM_CFG, temp); // // enable memory mapped register use. // save SRC_X ??? OUTPW(SRC_X, 0x0AAAA); temp = INPW(R_SRC_X); if (temp != 0x02AA) VideoDebugPrint((DEBUG_NORMAL, "Can't use memory mapped ranges, read %x\n", temp)); temp1 = INPW(LOCAL_CONTROL); temp1 |= 0x0020; // Enable memory mapped registers OUTPW(LOCAL_CONTROL, temp1); //restore SRC_X???: OUTPW(SRC_X, temp); } /************************************************************************** * * void SetCurrentMode_m(QueryPtr, CrtTable); * * struct query_structure *QueryPtr; Query information for the card * struct st_mode_table *CrtTable; CRT parameter table for desired mode * * DESCRIPTION: * Switch into the specified video mode. * * GLOBALS CHANGED: * none * * CALLED BY: * IOCTL_VIDEO_SET_CURRENT_MODE packet of ATIMPStartIO() * * AUTHOR: * Robert Wolff * * CHANGE HISTORY: * 1994 01 13 Added initialization of bank manager * * TEST HISTORY: * ***************************************************************************/ void SetCurrentMode_m(struct query_structure *QueryPtr, struct st_mode_table *CrtTable) { WORD MiscOptions; /* Contents of MISC_OPTIONS register */ USHORT Scratch, USTemp; /* Temporary variable */ // // When coming back from hibernate, mach32s can lock up and blackscreen. // This is because the card itself has to be reinitialized. // This initialization include at least the frame buffer initialization // and the initialization of the use of memory mapped registers. // if (phwDeviceExtension->ModelNumber == MACH32_ULTRA) { // enable the framebuffer. Scratch = INPW(MEM_CFG) & 0x0fffc; /* Preserve bits 2-15 */ Scratch |= 0x0002; /* 4M aperture */ OUTPW(MEM_CFG, Scratch); // enable memory mapped register use. // save SRC_X ??? OUTPW(SRC_X, 0x0AAAA); Scratch = INPW(R_SRC_X); if (Scratch != 0x02AA) VideoDebugPrint((DEBUG_NORMAL, "Can't use memory mapped ranges, read %x\n", Scratch)); USTemp = INPW(LOCAL_CONTROL); USTemp |= 0x0020; // Enable memory mapped registers OUTPW(LOCAL_CONTROL, USTemp); //restore SRC_X???: OUTPW(SRC_X, Scratch); } /* * Put the DAC in a known state before we start. */ UninitTiDac_m(); Passth8514_m(SHOW_ACCEL); // turn vga pass through off /* * On cards with the "MISC_OPTIONS doesn't report video memory size * correctly" bug, reset MISC_OPTIONS to show the true amount of * video memory. This is done here rather than when we determine * how much memory is present in order to avoid trashing the "blue * screen" (no adverse effects on operation, but would generate * large numbers of user complaints). */ if (((QueryPtr->q_asic_rev == CI_68800_6) || (QueryPtr->q_asic_rev == CI_68800_AX)) && (QueryPtr->q_VGA_type == 1) && ((QueryPtr->q_memory_type == VMEM_DRAM_256Kx4) || (QueryPtr->q_memory_type == VMEM_DRAM_256Kx16) || (QueryPtr->q_memory_type == VMEM_DRAM_256Kx4_GRAP))) { MiscOptions = INPW(MISC_OPTIONS) & MEM_SIZE_STRIPPED; switch (QueryPtr->q_memory_size) { case VRAM_512k: MiscOptions |= MEM_SIZE_512K; break; case VRAM_1mb: MiscOptions |= MEM_SIZE_1M; break; case VRAM_2mb: MiscOptions |= MEM_SIZE_2M; break; case VRAM_4mb: MiscOptions |= MEM_SIZE_4M; break; } OUTPW(MISC_OPTIONS, MiscOptions); } setmode_m(CrtTable, (ULONG_PTR) &(phwDeviceExtension->RomBaseRange), (ULONG) phwDeviceExtension->ModelNumber); /* * On a Mach 8 card, 1280x1024 can only be done in split * pixel mode. If we are running on a Mach 8, and this * resolution was selected, go into split pixel mode. * * Bit 4 of EXT_GE_CONFIG is set for split pixel mode and * clear for normal mode. Bit 3 must be set, since clearing * it accesses EEPROM read/write mode. */ if ((phwDeviceExtension->ModelNumber == _8514_ULTRA) || (phwDeviceExtension->ModelNumber == GRAPHICS_ULTRA)) { if (QueryPtr->q_desire_x == 1280) OUTPW(EXT_GE_CONFIG, 0x0018); else OUTPW(EXT_GE_CONFIG, 0x0008); } /* * Default to 8 bits per pixel. Modes which require a different * setting will change this in the init_ti__m() function. */ OUTP(DAC_MASK, 0xff); if (phwDeviceExtension->ModelNumber == MACH32_ULTRA) { switch (CrtTable->m_pixel_depth) // program the DAC for the { // other resolutions case 4: case 8: InitTi_8_m((WORD)(CrtTable->ColourDepthInfo | 0x0a)); break; case 16: InitTi_16_m((WORD)(CrtTable->ColourDepthInfo | 0x0a), (ULONG_PTR) &(phwDeviceExtension->RomBaseRange)); /* 16 bit 565 */ break; case 24: case 32: /* * RGB/BGR and 24/32 bit mode information is * stored in CrtTable->ColourDepthInfo. */ InitTi_24_m((WORD)(CrtTable->ColourDepthInfo | 0x0a), (ULONG_PTR) &(phwDeviceExtension->RomBaseRange)); break; } } /* * If we are going to be using the VGA aperture on a Mach 32, * initialize the bank manager by saving the ATI extended register * values and putting the VGA controller into packed pixel mode. * * We can't identify this case by looking at * phwDeviceExtension->FrameLength because it is set to 0x10000 * when the VGA aperture is being used in the * IOCTL_VIDEO_MAP_VIDEO_MEMORY packet which may or may not * have been called by the time we reach this point. */ if ((phwDeviceExtension->ModelNumber == MACH32_ULTRA) && (QueryPtr->q_aperture_cfg == 0) && (QueryPtr->q_VGA_type == 1)) { for (Scratch = 0; Scratch <= 2; Scratch++) { OUTP(reg1CE, (BYTE)(SavedExtRegs[Scratch] & 0x00FF)); SavedExtRegs[Scratch] = (SavedExtRegs[Scratch] & 0x00FF) | (INP(reg1CF) << 8); } OUTPW(HI_SEQ_ADDR, 0x0F02); OUTPW(HI_SEQ_ADDR, 0x0A04); OUTPW(reg3CE, 0x1000); OUTPW(reg3CE, 0x0001); OUTPW(reg3CE, 0x0002); OUTPW(reg3CE, 0x0003); OUTPW(reg3CE, 0x0004); OUTPW(reg3CE, 0x0005); OUTPW(reg3CE, 0x0506); OUTPW(reg3CE, 0x0F07); OUTPW(reg3CE, 0xFF08); OUTPW(reg1CE, 0x28B0); /* Enable 256 colour, 1M video RAM */ OUTPW(reg1CE, 0x04B6); /* Select linear addressing */ OUTP(reg1CE, 0xBE); OUTPW(reg1CE, (WORD)(((INP(reg1CF) & 0xF7) << 8) | 0xBE)); } /* * phwDeviceExtension->ReInitializing becomes TRUE in * IOCTL_VIDEO_SET_COLOR_REGISTERS packet of ATIMPStartIO(). * * If this is not the first time we are switching into graphics * mode, set the palette to the last set of colours that was * selected while in graphics mode. */ if (phwDeviceExtension->ReInitializing) { SetPalette_m(phwDeviceExtension->Clut, phwDeviceExtension->FirstEntry, phwDeviceExtension->NumEntries); } /* * Clear visible screen. * * 24 and 32 BPP would require a q_desire_y value beyond the * maximum allowable clipping value (1535) if we clear the screen * using a normal blit. Since these pixel depths are only supported * up to 800x600, we can fake it by doing a 16BPP blit of double the * screen height, clipping the special case of 640x480 24BPP on * a 1M card (this is the only true colour mode that will fit in * 1M, so if we hit this case on a 1M card, we know which mode * we're dealing with) to avoid running off the end of video memory. */ if (CrtTable->m_pixel_depth >= 24) { /* * Save the colour depth configuration and switch into 16BPP */ Scratch = INPW(R_EXT_GE_CONFIG); OUTPD(EXT_GE_CONFIG, (Scratch & 0xFFCF) | PIX_WIDTH_16BPP); CheckFIFOSpace_m(SIXTEEN_WORDS); OUTPW(DP_CONFIG, 0x2011); OUTPW(ALU_FG_FN, 0x7); // Paint OUTPW(FRGD_COLOR, 0); // Black OUTPW(CUR_X, 0); OUTPW(CUR_Y, 0); OUTPW(DEST_X_START, 0); OUTPW(DEST_X_END, QueryPtr->q_desire_x); if (QueryPtr->q_memory_size == VRAM_1mb) OUTPW(DEST_Y_END, 720); /* Only 640x480 24BPP will fit in 1M */ else OUTPW(DEST_Y_END, (WORD)(2*(QueryPtr->q_desire_y))); /* * Let the blit finish then restore the colour depth configuration */ WaitForIdle_m(); OUTPD(EXT_GE_CONFIG, Scratch); } else{ /* * Other colour depths can be handled by a normal blit, and the * LFB may not be available, so use a blit to clear the screen. */ CheckFIFOSpace_m(SIXTEEN_WORDS); OUTPW(DP_CONFIG, 0x2011); OUTPW(ALU_FG_FN, 0x7); // Paint OUTPW(FRGD_COLOR, 0); // Black OUTPW(CUR_X, 0); OUTPW(CUR_Y, 0); OUTPW(DEST_X_START, 0); OUTPW(DEST_X_END, QueryPtr->q_desire_x); OUTPW(DEST_Y_END, QueryPtr->q_desire_y); } #if 0 /* * In 800x600 24BPP, set the offset to start 1 pixel into video * memory to avoid screen tearing. The MAP_VIDEO_MEMORY packet * must adjust the framebuffer base to compensate for this. */ if ((QueryPtr->q_desire_x == 800) && (QueryPtr->q_pix_depth == 24)) { OUTPW(CRT_OFFSET_LO, 3); } else { OUTPW(CRT_OFFSET_HI, 0); } #endif WaitForIdle_m(); return; } /* SetCurrentMode_m() */ /************************************************************************** * * void ResetDevice_m(void); * * DESCRIPTION: * Reset the accelerator to allow the VGA miniport to switch * into a VGA mode. * * GLOBALS CHANGED: * none * * CALLED BY: * IOCTL_VIDEO_RESET_DEVICE packet of ATIMPStartIO() * * AUTHOR: * Robert Wolff * * CHANGE HISTORY: * * TEST HISTORY: * ***************************************************************************/ void ResetDevice_m(void) { VIDEO_X86_BIOS_ARGUMENTS Registers; /* Used in VideoPortInt10() calls */ /* * If we are using the VGA aperture on a Mach 32, put its * VGA controller into planar mode. */ if (phwDeviceExtension->FrameLength == 0x10000) { OUTPW(reg1CE, SavedExtRegs[0]); OUTPW(reg1CE, SavedExtRegs[1]); OUTPW(reg1CE, SavedExtRegs[2]); OUTP(reg1CE, 0xBE); OUTPW(reg1CE, (WORD)(((INP(reg1CF) & 0xF7) << 8) | 0xBE)); } UninitTiDac_m(); Passth8514_m(SHOW_VGA); VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); Registers.Eax = 0x0003; // set text mode 3 VideoPortInt10(phwDeviceExtension, &Registers); } /* ResetDevice_m() */ /************************************************************************** * * VP_STATUS SetPowerManagement_m(QueryPtr, DpmsState); * * struct query_structure *QueryPtr; Query information for the card * DWORD DpmsState; Desired DPMS state * (VIDEO_POWER_STATE enumeration) * * DESCRIPTION: * Switch into the desired DPMS state. * * RETURN VALUE: * NO_ERROR if successful * ERROR_INVALID_PARAMETER if invalid state requested. * * GLOBALS CHANGED: * none * * CALLED BY: * IOCTL_VIDEO_SET_POWER_MANAGEMENT packet of ATIMPStartIO() * * AUTHOR: * Robert Wolff * * CHANGE HISTORY: * * TEST HISTORY: * ***************************************************************************/ VP_STATUS SetPowerManagement_m(struct query_structure *QueryPtr, DWORD DpmsState) { struct st_mode_table *CrtTable; /* Mode table, used to obtain sync values */ /* * Only accept valid states. */ if ((DpmsState < VideoPowerOn) || (DpmsState > VideoPowerOff)) return ERROR_INVALID_PARAMETER; /* * Set CrtTable to point to the mode table associated with the * selected mode. * * When a pointer to a structure is incremented by an integer, * the integer represents the number of structure-sized blocks * to skip over, not the number of bytes to skip over. */ CrtTable = (struct st_mode_table *)QueryPtr; ((struct query_structure *)CrtTable)++; CrtTable += phwDeviceExtension->ModeIndex; SavedDPMSState = DpmsState; /* * Mach 32 rev. 6 and later supports turning the sync signals on and off * through the HORZ_OVERSCAN registers, but some chips that report as * rev. 6 don't have this implemented. Also, Mach 32 rev. 3 and Mach 8 * don't support this mechanism. * * Disabling the sync by setting it to start after the total will work * for all chips. Most chips will de-synchronize if the sync is set * to 1 more than the total, but some need higher values. To be sure * of de-synchronizing, set the disabled sync signal to start at * the highest possible value. */ switch (DpmsState) { case VideoPowerOn: OUTP(H_SYNC_STRT, CrtTable->m_h_sync_strt); OUTPW(V_SYNC_STRT, CrtTable->m_v_sync_strt); break; case VideoPowerStandBy: OUTP(H_SYNC_STRT, 0xFF); OUTPW(V_SYNC_STRT, CrtTable->m_v_sync_strt); break; case VideoPowerSuspend: OUTP(H_SYNC_STRT, CrtTable->m_h_sync_strt); OUTPW(V_SYNC_STRT, 0x0FFF); break; case VideoPowerOff: OUTP(H_SYNC_STRT, 0xFF); OUTPW(V_SYNC_STRT, 0x0FFF); break; /* * This case should never happen, because the initial * acceptance of only valid states should have already * rejected anything that will appear here. */ default: break; } return NO_ERROR; } /* SetPowerManagement_m() */ DWORD GetPowerManagement_m(PHW_DEVICE_EXTENSION phwDeviceExtension) /* * DESCRIPTION: * Report which DPMS state we are in. * * PARAMETERS: * phwDeviceExtension Points to per-adapter device extension. * * RETURN VALUE: * Current DPMS state (VIDEO_POWER_STATE enumeration). */ { ASSERT(phwDeviceExtension != NULL); /* * On the Mach 8, the sync start registers are write-only, so * we can't check which state we are in. For this reason, we * have saved the state we switched into using SetPowerManagement_m(). * On the Mach 32, we can either use this saved state or read * the sync start registers, but using the same method as for * the Mach 8 reduces complexity. */ return SavedDPMSState; } /* GetPowerManagement_m() */ /************************************************************************** * * VP_STATUS ShareVideoMemory_m(RequestPacket, QueryPtr); * * PVIDEO_REQUEST_PACKET RequestPacket; Request packet with input and output buffers * struct query_structure *QueryPtr; Query information for the card * * DESCRIPTION: * Allow applications to do direct screen access through DCI. * * RETURN VALUE: * NO_ERROR if successful * error code if failed * * CALLED BY: * IOCTL_VIDEO_SHARE_VIDEO_MEMORY packet of ATIMPStartIO() * * AUTHOR: * Robert Wolff * * CHANGE HISTORY: * * TEST HISTORY: * ***************************************************************************/ VP_STATUS ShareVideoMemory_m(PVIDEO_REQUEST_PACKET RequestPacket, struct query_structure *QueryPtr) { PVIDEO_SHARE_MEMORY InputPtr; /* Pointer to input structure */ PVIDEO_SHARE_MEMORY_INFORMATION OutputPtr; /* Pointer to output structure */ PHYSICAL_ADDRESS ShareAddress; /* Physical address of video memory */ PVOID VirtualAddress; /* Virtual address to map video memory at */ ULONG SharedViewSize; /* Size of block to share */ ULONG SpaceType; /* Sparse or dense space? */ VP_STATUS Status; /* Status to return */ /* * We can only share the aperture with application programs if there * is an aperture available. If both the LFB and the on-board VGA * and therefore the VGA aperture) are disabled, report that we * can't share the aperture. */ if ((QueryPtr->q_aperture_cfg == 0) && (QueryPtr->q_VGA_type == 0)) return ERROR_INVALID_FUNCTION; InputPtr = RequestPacket->InputBuffer; if ((InputPtr->ViewOffset > phwDeviceExtension->VideoRamSize) || ((InputPtr->ViewOffset + InputPtr->ViewSize) > phwDeviceExtension->VideoRamSize)) { VideoDebugPrint((DEBUG_ERROR, "ShareVideoMemory_m() - access beyond video memory\n")); return ERROR_INVALID_PARAMETER; } RequestPacket->StatusBlock->Information = sizeof(VIDEO_SHARE_MEMORY_INFORMATION); /* * Beware: the input buffer and the output buffer are the same buffer, * and therefore data should not be copied from one to the other. */ VirtualAddress = InputPtr->ProcessHandle; SharedViewSize = InputPtr->ViewSize; SpaceType = 0; #if defined(_ALPHA_) /* * Use dense space mapping whenever we can, because that will * allow us to support DCI and direct GDI access. * * Dense space is extremely slow with ISA cards on the newer Alphas, * because any byte- or word-write requires a read/modify/write * operation, and the ALpha can only ever do 64-bit reads when in * dense mode. As a result, these operations would always require * 4 reads and 2 writes on the ISA bus. Also, some older Alphas * don't support dense space mapping. * * Any Alpha that supports PCI can support dense space mapping, and * because the bus is wider and faster, the read/modify/write has * less of an impact on performance. */ if (QueryPtr->q_bus_type == BUS_PCI) SpaceType = 4; #endif /* * NOTE: we are ignoring ViewOffset */ ShareAddress.QuadPart = phwDeviceExtension->PhysicalFrameAddress.QuadPart; /* * If the LFB is enabled, use ordinary mapping. If we have only * the paged aperture, we must map to banked memory. Since the * LFB is always aligned on a 1M boundary (4M boundary for 4M * aperture), this check for the paged aperture will never falsely * detect a LFB as paged. */ if (phwDeviceExtension->PhysicalFrameAddress.LowPart == 0x0A0000) { /* * On some versions of the DDK, VideoPortMapBankedMemory() is * not available. If this is the case, force an error. * This routine should be available in all versions of * the DDK which support DCI, since it is used for DCI * support on cards with banked apertures. */ #if defined(IOCTL_VIDEO_SHARE_VIDEO_MEMORY) Status = VideoPortMapBankedMemory( phwDeviceExtension, ShareAddress, &SharedViewSize, &SpaceType, &VirtualAddress, 0x10000, /* 64k VGA aperture */ FALSE, /* No separate read/write banks */ BankMap_m, /* Our bank-mapping routine */ (PVOID) phwDeviceExtension); #else Status = ERROR_INVALID_FUNCTION; #endif } else /* LFB */ { Status = VideoPortMapMemory(phwDeviceExtension, ShareAddress, &SharedViewSize, &SpaceType, &VirtualAddress); } OutputPtr = RequestPacket->OutputBuffer; OutputPtr->SharedViewOffset = InputPtr->ViewOffset; OutputPtr->VirtualAddress = VirtualAddress; OutputPtr->SharedViewSize = SharedViewSize; return Status; } /* ShareVideoMemory_m() */ /************************************************************************** * * void BankMap_m(BankRead, BankWrite, Context); * * ULONG BankRead; Bank to read * ULONG BankWrite; Bank to write * PVOID Context; Pointer to hardware-specific information * * DESCRIPTION: * Map the selected bank of video memory into the 64k VGA aperture. * We don't support separate read and write banks, so we use BankWrite * to set the read/write bank, and ignore BankRead. * * CALLED BY: * This is an entry point, rather than being called * by other miniport functions. * * NOTE: * This function is called directly by the memory manager during page * fault handling, and so cannot be made pageable. * * AUTHOR: * Robert Wolff * * CHANGE HISTORY: * * TEST HISTORY: * ***************************************************************************/ void BankMap_m(ULONG BankRead, ULONG BankWrite, PVOID Context) { OUTPW( reg1CE, (USHORT)(((BankWrite & 0x0f) << 9) | 0xb2)); OUTPW( reg1CE, (USHORT)(((BankWrite & 0x30) << 4) | 0xae)); return; } /* BankMap_m() */