/* Copyright (c) 2005 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * * Neither the name of the Advanced Micro Devices, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * */ /* * This header file contains the macros used to access the hardware. These * macros assume that 32-bit access is possible, which is true for most * applications. Projects using 16-bit compilers (the Windows98 display * driver) and special purpose applications (such as Darwin) need to define * their own versions of these macros, which typically call a subroutine. * */ /* ACCESS TO THE CPU REGISTERS */ #define WRITE_REG8(offset, value) \ (*(volatile unsigned char *)(gfx_virt_regptr + (offset))) = (value) #define WRITE_REG16(offset, value) \ (*(volatile unsigned short *)(gfx_virt_regptr + (offset))) = (value) #define WRITE_REG32(offset, value) \ (*(volatile unsigned long *)(gfx_virt_regptr + (offset))) = (value) #define READ_REG16(offset) \ (*(volatile unsigned short *)(gfx_virt_regptr + (offset))) #define READ_REG32(offset) \ (*(volatile unsigned long *)(gfx_virt_regptr + (offset))) /* ACCESS TO THE ACCELERATOR REGISTERS (REDCLOUD ONLY) */ #define WRITE_GP8(offset, value) \ (*(volatile unsigned char *)(gfx_virt_gpptr + (offset))) = (value) #define WRITE_GP16(offset, value) \ (*(volatile unsigned short *)(gfx_virt_gpptr + (offset))) = (value) #define WRITE_GP32(offset, value) \ (*(volatile unsigned long *)(gfx_virt_gpptr + (offset))) = (value) #define READ_GP16(offset) \ (*(volatile unsigned short *)(gfx_virt_gpptr + (offset))) #define READ_GP32(offset) \ (*(volatile unsigned long *)(gfx_virt_gpptr + (offset))) /* ACCESS TO THE FRAME BUFFER */ #define WRITE_FB32(offset, value) \ (*(volatile unsigned long *)(gfx_virt_fbptr + (offset))) = (value) #define WRITE_FB16(offset, value) \ (*(volatile unsigned short *)(gfx_virt_fbptr + (offset))) = (value) #define WRITE_FB8(offset, value) \ (*(volatile unsigned char *)(gfx_virt_fbptr + (offset))) = (value) /* ACCESS TO THE VIDEO HARDWARE */ #define READ_VID32(offset) \ (*(volatile unsigned long *)(gfx_virt_vidptr + (offset))) #define WRITE_VID32(offset, value) \ (*(volatile unsigned long *)(gfx_virt_vidptr + (offset))) = (value) /* ACCESS TO THE VIP HARDWARE */ #define READ_VIP32(offset) \ (*(volatile unsigned long *)(gfx_virt_vipptr + (offset))) #define WRITE_VIP32(offset, value) \ (*(volatile unsigned long *)(gfx_virt_vipptr + (offset))) = (value) /* ACCESS TO THE SCRATCHPAD RAM */ #define WRITE_SCRATCH32(offset, value) \ (*(volatile unsigned long *)(gfx_virt_spptr + (offset))) = (value) #define WRITE_SCRATCH16(offset, value) \ (*(volatile unsigned short *)(gfx_virt_spptr + (offset))) = (value) #define WRITE_SCRATCH8(offset, value) \ (*(volatile unsigned char *)(gfx_virt_spptr + (offset))) = (value) #define READ_SCRATCH16(offset) \ (*(volatile unsigned short *)(gfx_virt_spptr + (offset))) #define READ_SCRATCH32(offset) \ (*(volatile unsigned long *)(gfx_virt_spptr + (offset))) /* ACCESS TO MSRS */ void gfx_msr_asm_write(unsigned short msrReg, unsigned long msrAddr, unsigned long *ptrHigh, unsigned long *ptrLow); void gfx_msr_asm_read(unsigned short msrReg, unsigned long msrAddr, unsigned long *ptrHigh, unsigned long *ptrLow); #define MSR_READ( MBD_MSR_CAP, address, valueHigh_ptr, valueLow_ptr ) \ gfx_msr_asm_read( ((unsigned short)(MBD_MSR_CAP)), address, \ valueHigh_ptr, valueLow_ptr ) #define MSR_WRITE( MBD_MSR_CAP, address, valueHigh_ptr, valueLow_ptr ) \ gfx_msr_asm_write( ((unsigned short)(MBD_MSR_CAP)), address, \ valueHigh_ptr, valueLow_ptr ) /* OPTIMIZATION MACROS */ /* The following macros have been added to allow more complete optimization of * the bitmap-to-screen routines in Durango. These routines also allow * Durango to run properly within a 16-bit environment. * */ /***************************************************************************** * Macro: SET_SCRATCH_BASE * Purpose: Record the base address of the BLT buffers. The * WRITE_SCRATCH_STRINGxx macros assume that this address is used * as the base for all writes. * * Arguments: * scratch_base - offset into the GX base for the first BLT buffer byte. ****************************************************************************/ #define SET_SCRATCH_BASE(scratch_base) \ { gfx_gx1_scratch_base = (unsigned long)gfx_virt_spptr + scratch_base; } #ifdef GFX_OPTIMIZE_ASSEMBLY /***************************************************************************** * Macro: WRITE_SCRATCH_STRING * Purpose: Write multiple bytes to the scratchpad buffer * * Arguments: * dword_bytes - number of bytes to transfer. This number will always. * be a multiple of 4. It cannot be modified within the * macro (ex. bytes -= 4) * bytes_extra - number of non-DWORD aligned bytes * array - pointer to an array of unsigned characters. * array_offset - offset into the array from which to pull the first * character. ****************************************************************************/ #define WRITE_SCRATCH_STRING(dwords, bytes, array, array_offset) \ { \ _asm { mov edi, gfx_gx1_scratch_base } \ _asm { mov esi, array } \ _asm { add esi, array_offset } \ _asm { mov ecx, dwords } \ _asm { shr ecx, 2 } \ _asm { rep movsd } \ _asm { mov ecx, bytes } \ _asm { rep movsb } \ } /***************************************************************************** * Macro: WRITE_FRAME_BUFFER_STRING32 * Purpose: Write multiple dwords to the Frame buffer * * Arguments: * fboffset - offset to the beginning frame buffer location. * bytes - number of bytes to transfer. This number will always. * be a multiple of 4. It cannot be modified within the * macro (ex. bytes -= 4) * array - pointer to an array of unsigned characters. * array_offset - offset into the array from which to pull the first * character. ****************************************************************************/ #define WRITE_FRAME_BUFFER_STRING32(fboffset, bytes, array, array_offset) \ { \ _asm { mov ecx, bytes } \ _asm { shr ecx, 2 } \ _asm { cld } \ _asm { mov edi, gfx_virt_fbptr } \ _asm { add edi, fboffset } \ _asm { mov esi, array } \ _asm { add esi, array_offset } \ _asm { rep movsd } \ } #else /***************************************************************************** * Macro: WRITE_SCRATCH_STRING * Purpose: Write multiple bytes to the scratchpad buffer * * Arguments: * dword_bytes - number of bytes to transfer. This number will always. * be a multiple of 4. It cannot be modified within the * macro (ex. bytes -= 4) * bytes_extra - number of non-DWORD aligned bytes * array - pointer to an array of unsigned characters. * array_offset - offset into the array from which to pull the first * character. ****************************************************************************/ #define WRITE_SCRATCH_STRING(dword_bytes, bytes_extra, array, array_offset) \ { \ unsigned long i, j; \ unsigned long aroffset = (unsigned long)array + (array_offset); \ \ /* WRITE DWORDS */ \ \ for (i = 0; i < dword_bytes; i += 4) \ *((volatile unsigned long *)(gfx_gx1_scratch_base + i)) = \ *((unsigned long *)(aroffset + i)); \ \ /* WRITE BYTES */ \ \ j = i + bytes_extra; \ while (i < j) { \ *((volatile unsigned char *)(gfx_gx1_scratch_base + i)) = \ *((unsigned char *)(aroffset + i)); \ i++; \ } \ } /***************************************************************************** * Macro: WRITE_FRAME_BUFFER_STRING32 * Purpose: Write multiple dwords to the Frame buffer * * Arguments: * fboffset - offset to the beginning frame buffer location. * bytes - number of bytes to transfer. This number will always. * be a multiple of 4. It cannot be modified within the * macro (ex. bytes -= 4) * array - pointer to an array of unsigned characters. * array_offset - offset into the array from which to pull the first * character. ****************************************************************************/ #define WRITE_FRAME_BUFFER_STRING32(fboffset, bytes, array, array_offset) \ { \ unsigned long i; \ unsigned long aroffset = (unsigned long)array + (array_offset); \ for (i = 0; i < bytes; i += 4) \ WRITE_FB32 ((fboffset) + i, *((unsigned long *)(aroffset + i))); \ } #endif /***************************************************************************** * Macro: WRITE_FRAME_BUFFER_STRING8 * Purpose: Write multiple bytes to the frame buffer * * Arguments: * spoffset - offset to the beginning frame buffer location. * bytes - number of bytes to transfer. This number cannot be * modified within the macro (ex. bytes -= 4) * array - pointer to an array of unsigned characters. * array_offset - offset into the array from which to pull the first * character. ****************************************************************************/ #define WRITE_FRAME_BUFFER_STRING8(fboffset, bytes, array, array_offset) \ { \ unsigned long i; \ unsigned long aroffset = (unsigned long)array + (array_offset); \ for (i = 0; i < bytes; i++) \ WRITE_FB8 ((fboffset) + i, *((unsigned char *)(aroffset + i))); \ } /***************************************************************************** * Macro: WRITE_GPREG_STRING32 * Purpose: Write multiple dwords to one GP register. * * Arguments: * regoffset - Offset of the GP register to be written. * dwords - number of dwords to transfer. It cannot be modified * within the macro (ex. dwords--) * counter - name of a counter variable that can be used in a loop. * This is used to optimize macros written in C. * array - pointer to an array of unsigned characters. * array_offset - offset into the array from which to pull the first * character. * temp - name of a temporary variable that can be used for * calculations. * This argument is also used for C-only macros. ****************************************************************************/ #define WRITE_GPREG_STRING32(regoffset, dwords, counter, array, \ array_offset, temp) \ { \ temp = (unsigned long)array + (array_offset); \ for (counter = 0; counter < dwords; counter++) \ WRITE_GP32 (regoffset, *((unsigned long *)temp + counter)); \ } /***************************************************************************** * Macro: WRITE_GPREG_STRING8 * Purpose: Write 4 or less bytes to one GP register. * * Arguments: * regoffset - Offset of the GP register to be written. * bytes - number of bytes to transfer. This number will always. * be less than 4. It cannot be modified within the * macro (ex. bytes--) * shift - name of a shift variable that can be used as a shift * count. * This variable holds the initial shift value into the * GP register. * counter - name of a counter variable that can be used in a loop. * This is used to optimize macros written in C. * array - pointer to an array of unsigned characters. * array_offset - offset into the array from which to pull the first * character. * temp1 - name of a temporary variable that can be used for * calculations. * This argument is also used for C-only macros. * temp2 - name of a temporary variable that can be used for * calculations. * This argument is also used for C-only macros. ****************************************************************************/ #define WRITE_GPREG_STRING8(regoffset, bytes, shift, counter, array, \ array_offset, temp1, temp2) \ { \ if (bytes) { \ temp1 = (unsigned long)array + (array_offset); \ temp2 = 0; \ for (counter = 0; counter < bytes; counter++) { \ temp2 |= ((unsigned long)(*((unsigned char *)(temp1 + \ counter)))) << shift; \ shift += 8; \ } \ WRITE_GP32 (regoffset, temp2); \ } \ } /* END OF FILE */