Home | History | Annotate | Line # | Download | only in cim
      1 /*
      2  * Copyright (c) 2006 Advanced Micro Devices, Inc.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     20  * DEALINGS IN THE SOFTWARE.
     21  *
     22  * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
     23  * contributors may be used to endorse or promote products derived from this
     24  * software without specific prior written permission.
     25  */
     26 
     27  /*
     28   * Cimarron graphics processor routines.  These routines program the graphics
     29   * hardware using the graphics command buffer.
     30   */
     31 
     32 /*---------------------*/
     33 /* CIMARRON GP GLOBALS */
     34 /*---------------------*/
     35 
     36 CIMARRON_STATIC unsigned long gp3_bpp = 0;
     37 CIMARRON_STATIC unsigned long gp3_ch3_bpp = 0;
     38 CIMARRON_STATIC unsigned long gp3_pat_origin = 0;
     39 CIMARRON_STATIC unsigned long gp3_buffer_lead = 0;
     40 CIMARRON_STATIC unsigned long gp3_cmd_header;
     41 CIMARRON_STATIC unsigned long gp3_cmd_top;
     42 CIMARRON_STATIC unsigned long gp3_cmd_bottom;
     43 CIMARRON_STATIC unsigned long gp3_cmd_current;
     44 CIMARRON_STATIC unsigned long gp3_cmd_next;
     45 CIMARRON_STATIC unsigned long gp3_blt_mode;
     46 CIMARRON_STATIC unsigned long gp3_vec_mode;
     47 CIMARRON_STATIC unsigned long gp3_raster_mode;
     48 CIMARRON_STATIC unsigned long gp3_pix_shift;
     49 CIMARRON_STATIC unsigned long gp3_ch3_pat;
     50 CIMARRON_STATIC unsigned long gp3_blt;
     51 CIMARRON_STATIC unsigned long gp3_blt_flags;
     52 CIMARRON_STATIC unsigned long gp3_src_stride;
     53 CIMARRON_STATIC unsigned long gp3_dst_stride;
     54 CIMARRON_STATIC unsigned long gp3_src_format;
     55 CIMARRON_STATIC unsigned long gp3_src_pix_shift;
     56 CIMARRON_STATIC unsigned long gp3_pat_format;
     57 CIMARRON_STATIC unsigned long gp3_pat_pix_shift;
     58 CIMARRON_STATIC unsigned long gp3_fb_base;
     59 CIMARRON_STATIC unsigned long gp3_vector_pattern_color;
     60 CIMARRON_STATIC unsigned long gp3_scratch_base;
     61 CIMARRON_STATIC unsigned long gp3_base_register;
     62 CIMARRON_STATIC unsigned long gp3_vec_pat;
     63 
     64 /*---------------------------------------------------------------------------
     65  * gp_set_limit_on_buffer_lead
     66  *
     67  * This routine is used to specify the maximum number of bytes in the command
     68  * buffer by which software can lead the graphics processor.  When declaring
     69  * a BLT with the CIMGP_BLTFLAGS_LIMITBUFFER flag set, Cimarron will wait
     70  * until the command buffer read and write pointers differ by no more than
     71  * 'lead' bytes.  This can be useful to limit the time lag possible when
     72  * creating a command buffer full of simple BLT commands.
     73  *-------------------------------------------------------------------------*/
     74 
     75 void
     76 gp_set_limit_on_buffer_lead(unsigned long lead)
     77 {
     78     gp3_buffer_lead = lead;
     79 }
     80 
     81 /*---------------------------------------------------------------------------
     82  * gp_set_command_buffer_base
     83  *
     84  * This routine is used to program the command buffer region in physical
     85  * memory.  The command buffer start address must be 1MB aligned. start and
     86  * stop refer to endpoints within the associated 16MB region.  Command buffers
     87  * larger than 16MB are not supported.
     88  *-------------------------------------------------------------------------*/
     89 
     90 void
     91 gp_set_command_buffer_base(unsigned long address, unsigned long start,
     92                            unsigned long stop)
     93 {
     94     Q_WORD msr_value;
     95 
     96     /* WAIT FOR IDLE */
     97     /* Obviously, we cannot change the command buffer pointer while the GP */
     98     /* is currently fetching commands.                                     */
     99 
    100     gp_wait_until_idle();
    101 
    102     /* WRITE THE COMMAND BUFFER BASE */
    103 
    104     msr_read64(MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value);
    105     msr_value.low &= 0xF000FFFF;
    106     msr_value.low |= (address >> 4) & 0x0FFF0000;
    107     msr_write64(MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value);
    108 
    109     /* WRITE THE BASE OFFSETS */
    110     /* We also reset the write and read pointers.  The hardware will */
    111     /* automatically update the write pointer when the read pointer  */
    112     /* is updated to prevent the hardware from getting confused when */
    113     /* initializing a new command buffer.                            */
    114 
    115     WRITE_GP32(GP3_CMD_TOP, start);
    116     WRITE_GP32(GP3_CMD_BOT, stop);
    117     WRITE_GP32(GP3_CMD_READ, start);
    118 
    119     /* SAVE THE BASE ADDRESSES */
    120     /* These are used to determine the appropriate wrap point. */
    121 
    122     gp3_cmd_current = gp3_cmd_top = start;
    123     gp3_cmd_bottom = stop;
    124 }
    125 
    126 /*---------------------------------------------------------------------------
    127  * gp_set_frame_buffer_base
    128  *
    129  * This routine is used to program the base address of the frame buffer in
    130  * physical memory.  The frame buffer address must be 16MB aligned.  Cimarron
    131  * tracks the base address because the maximum frame buffer size may exceed
    132  * 16MB. Any primitive will thus program the corresponding 16MB region into
    133  * all base offset registers as well as program the offset into the 16MB
    134  * region.  The size parameter is provided to allow Cimarron to claim the
    135  * last 1MB of space to be used as a scratch area for workarounds or
    136  * expanded functionality.
    137  *-------------------------------------------------------------------------*/
    138 
    139 void
    140 gp_set_frame_buffer_base(unsigned long address, unsigned long size)
    141 {
    142     gp3_scratch_base = size - GP3_SCRATCH_BUFFER_SIZE;
    143     gp3_fb_base = address >> 24;
    144     gp3_base_register =
    145         (gp3_fb_base << 24) | (gp3_fb_base << 14) | (gp3_fb_base << 4);
    146     WRITE_GP32(GP3_BASE_OFFSET, gp3_base_register);
    147 }
    148 
    149 /*---------------------------------------------------------------------------
    150  * gp_set_bpp
    151  *
    152  * This routine sets the output BPP of the GP.  The BPP used by the GP does
    153  * not have to match the display BPP, but that is usually the case.  The
    154  * supported BPP values are as follows:
    155  *
    156  *    8  - palettized 8BPP
    157  *    12 - 4:4:4:4
    158  *    15 - 1:5:5:5
    159  *    16 - 0:5:6:5
    160  *    32 - 8:8:8:8
    161  *-------------------------------------------------------------------------*/
    162 
    163 void
    164 gp_set_bpp(int bpp)
    165 {
    166     /* STORE BPP */
    167     /* The bpp is not updated until the next call to gp_set_raster_mode. */
    168     /* This allows the gp_set_bpp call to happen outside of a BLT.  It   */
    169     /* also implies that no registers need be written in this routine.   */
    170 
    171     switch (bpp) {
    172     case 8:
    173         gp3_bpp = GP3_RM_BPPFMT_332;
    174         gp3_ch3_bpp = GP3_CH3_SRC_3_3_2;
    175         gp3_pix_shift = 0;
    176         break;
    177     case 12:
    178         gp3_bpp = GP3_RM_BPPFMT_4444;
    179         gp3_ch3_bpp = GP3_CH3_SRC_4_4_4_4;
    180         gp3_pix_shift = 1;
    181         break;
    182     case 15:
    183         gp3_bpp = GP3_RM_BPPFMT_1555;
    184         gp3_ch3_bpp = GP3_CH3_SRC_1_5_5_5;
    185         gp3_pix_shift = 1;
    186         break;
    187     case 16:
    188         gp3_bpp = GP3_RM_BPPFMT_565;
    189         gp3_ch3_bpp = GP3_CH3_SRC_0_5_6_5;
    190         gp3_pix_shift = 1;
    191         break;
    192     case 24:
    193     case 32:
    194         gp3_bpp = GP3_RM_BPPFMT_8888;
    195         gp3_ch3_bpp = GP3_CH3_SRC_8_8_8_8;
    196         gp3_pix_shift = 2;
    197         break;
    198     default:
    199         gp3_bpp = GP3_RM_BPPFMT_332;
    200         gp3_ch3_bpp = GP3_CH3_SRC_3_3_2;
    201         gp3_pix_shift = 0;
    202         break;
    203     }
    204 }
    205 
    206 /*---------------------------------------------------------------------------
    207  * gp_declare_blt
    208  *
    209  * This routine is used to prepare for a 2D BLT.  Its primary function
    210  * is to verify that enough room is available in the command buffer
    211  * to hold a BLT command.  This command can be called multiple times if
    212  * necessary.  For example, if a function calls this routine on entry, but
    213  * later realizes that a LUT load command must be executed before the BLT,
    214  * the application could call gp_set_color_pattern and then call
    215  * gp_declare_blt to declare the BLT.  This is possible because the hardware
    216  * buffer pointer is not updated until a new BLT is actually executed.  An
    217  * application must take care not to call any routines that perform a buffer
    218  * command, (such as gp_set_color_pattern) between gp_declare_blt and the
    219  * routines used to program the BLT parameters.  In addition to checking for
    220  * available space, this routine also performs the following actions:
    221  *    - Sets the wrap bit if this BLT will pass close to the end of the
    222  *		buffer.
    223  *    - Writes the command header.
    224  *
    225  * The available flags are defined as follows:
    226  *   0x01 - Preserve the LUT
    227  *   0x02 - Preserve the color pattern.
    228  *   0x04 - Enable prefetch.
    229  *-------------------------------------------------------------------------*/
    230 
    231 void
    232 gp_declare_blt(unsigned long flags)
    233 {
    234     unsigned long temp;
    235 
    236     gp3_blt = 1;
    237     gp3_blt_flags = flags;
    238 
    239     /* SET ADDRESS OF NEXT COMMAND */
    240     /* A summary of the command buffer logic is as follows:           */
    241     /*  - If after a basic BLT we will not have room for the largest  */
    242     /*    command (a full line of host source data), we set the wrap  */
    243     /*    bit.  This will waste up to a whopping 8K of command buffer */
    244     /*    space, but it simplifies the logic for all commands.        */
    245     /* -  If we are wrapping, we have extra logic to ensure that we   */
    246     /*    don't skip over the current GP read pointer.                */
    247 
    248     gp3_cmd_next = gp3_cmd_current + GP3_BLT_COMMAND_SIZE;
    249 
    250     /* CHECK WRAP CONDITION */
    251 
    252     if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
    253         gp3_cmd_next = gp3_cmd_top;
    254         gp3_cmd_header = GP3_BLT_HDR_TYPE | GP3_BLT_HDR_WRAP;
    255 
    256         /* WAIT FOR HARDWARE */
    257         /* When wrapping, we must take steps to ensure that we do not    */
    258         /* wrap over the current hardware read pointer.  We do this by   */
    259         /* verifying that the hardware is not between us and the end of  */
    260         /* the command buffer.  We also have a special case to make sure */
    261         /* that the hardware is not currently reading the top of the     */
    262         /* command buffer.                                               */
    263 
    264         GP3_WAIT_WRAP(temp);
    265     }
    266     else {
    267         gp3_cmd_header = GP3_BLT_HDR_TYPE;
    268 
    269         /* WAIT FOR AVAILABLE SPACE */
    270 
    271         GP3_WAIT_PRIMITIVE(temp);
    272     }
    273 
    274     if (flags & CIMGP_BLTFLAGS_LIMITBUFFER) {
    275         while (1) {
    276             temp = READ_GP32(GP3_CMD_READ);
    277             if (((gp3_cmd_current >= temp)
    278                  && ((gp3_cmd_current - temp) <= gp3_buffer_lead))
    279                 || ((gp3_cmd_current < temp)
    280                     && ((gp3_cmd_current + (gp3_cmd_bottom - temp)) <=
    281                         gp3_buffer_lead))) {
    282                 break;
    283             }
    284         }
    285     }
    286 
    287     /* SET THE CURRENT BUFFER POINTER */
    288     /* We initialize a pointer to the current buffer base to avoid an */
    289     /* extra addition for every buffer write.                         */
    290 
    291     cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
    292 
    293     /* SET THE HAZARD BIT */
    294 
    295     if (flags & CIMGP_BLTFLAGS_HAZARD)
    296         gp3_cmd_header |= GP3_BLT_HDR_HAZARD_ENABLE;
    297 }
    298 
    299 /*---------------------------------------------------------------------------
    300  * gp_declare_vector
    301  *
    302  * This routine is used to prepare for a 2D vector.  It has no other function
    303  * except to verify that enough room is available in the command buffer
    304  * to hold a vector command.  The same rules that apply to BLTs apply to
    305  * vectors. (See the documentation for gp_declare_blt).
    306  *-------------------------------------------------------------------------*/
    307 
    308 void
    309 gp_declare_vector(unsigned long flags)
    310 {
    311     unsigned long temp;
    312 
    313     gp3_blt = 0;
    314     gp3_blt_flags = flags;
    315 
    316     /* SET ADDRESS OF NEXT COMMAND                            */
    317     /* The logic to force a wrap during a vector is identical */
    318     /* to the BLT logic.                                      */
    319 
    320     /* ALLOCATE SPACE FOR AN ADDITIONAL VECTOR TO CLEAR THE BYTE ENABLES */
    321 
    322     gp3_cmd_next = gp3_cmd_current + GP3_VECTOR_COMMAND_SIZE +
    323         GP3_VECTOR_COMMAND_SIZE + 32;
    324 
    325     /* CHECK WRAP CONDITION */
    326 
    327     if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
    328         gp3_cmd_next = gp3_cmd_top;
    329         gp3_cmd_header = GP3_VEC_HDR_TYPE | GP3_VEC_HDR_WRAP;
    330 
    331         /* CHECK WRAP CONDITION */
    332 
    333         GP3_WAIT_WRAP(temp);
    334     }
    335     else {
    336         gp3_cmd_header = GP3_VEC_HDR_TYPE;
    337 
    338         /* WAIT FOR AVAILABLE SPACE */
    339 
    340         GP3_WAIT_PRIMITIVE(temp);
    341 
    342         gp3_cmd_next -= GP3_VECTOR_COMMAND_SIZE + 32;
    343     }
    344 
    345     if (flags & CIMGP_BLTFLAGS_LIMITBUFFER) {
    346         while (1) {
    347             temp = READ_GP32(GP3_CMD_READ);
    348             if (((gp3_cmd_current >= temp)
    349                  && ((gp3_cmd_current - temp) <= gp3_buffer_lead))
    350                 || ((gp3_cmd_current < temp)
    351                     && ((gp3_cmd_current + (gp3_cmd_bottom - temp)) <=
    352                         gp3_buffer_lead))) {
    353                 break;
    354             }
    355         }
    356     }
    357 
    358     cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
    359 
    360     /* SET THE HAZARD BIT */
    361 
    362     if (flags & CIMGP_BLTFLAGS_HAZARD)
    363         gp3_cmd_header |= GP3_VEC_HDR_HAZARD_ENABLE;
    364 }
    365 
    366 /*---------------------------------------------------------------------------
    367  * gp_write_parameters
    368  *
    369  * This routine is called to write all recent parameters to the hardware.
    370  * This routine is necessary for any implementation that performs the setup
    371  * for a BLT separate from the actual BLT.  An example would be a driver
    372  * that prepares for multiple pattern fills by programming the ROP,
    373  * pattern color and destination stride.  The driver might then perform
    374  * repeated pattern fills with minimal effort.
    375  *-------------------------------------------------------------------------*/
    376 
    377 void
    378 gp_write_parameters(void)
    379 {
    380     /* WRITE THE COMMAND HEADER */
    381     /* Command header is at offset 0 for BLTs and vectors */
    382 
    383     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
    384 
    385     /* INCREMENT THE CURRENT WRITE POINTER */
    386 
    387     gp3_cmd_current = gp3_cmd_next;
    388 
    389     /* UPDATE THE GP WRITE POINTER */
    390 
    391     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_current);
    392 }
    393 
    394 /*---------------------------------------------------------------------------
    395  * gp_set_raster_operation
    396  *
    397  * This is generally the first routine called when programming a BLT.  This
    398  * routine performs the following functions:
    399  *   - Sets the initial value of the GP3_RASTER_MODE register in the buffer.
    400  *   - Clears any 8x8 pattern if the ROP does not involve pattern data.
    401  *-------------------------------------------------------------------------*/
    402 
    403 void
    404 gp_set_raster_operation(unsigned char ROP)
    405 {
    406     gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE;
    407 
    408     /* WRITE THE RASTER MODE REGISTER                                   */
    409     /* This register is in the same location in BLT and vector commands */
    410 
    411     gp3_raster_mode = gp3_bpp | (unsigned long) ROP;
    412     WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode);
    413 
    414     /* CHECK IF DESTINATION IS REQUIRED */
    415 
    416     if ((ROP & 0x55) ^ ((ROP >> 1) & 0x55)) {
    417         gp3_blt_mode = GP3_BM_DST_REQ;
    418         gp3_vec_mode = GP3_VM_DST_REQ;
    419     }
    420     else {
    421         gp3_blt_mode = gp3_vec_mode = 0;
    422     }
    423 }
    424 
    425 /*----------------------------------------------------------------------------
    426  * gp_set_alpha_operation
    427  *
    428  * BLTs are generally one of two types, a ROPed BLT or a BLT composited using
    429  * alpha blending.  For the latter, this routine is used to configure the
    430  * mathematical function used to create the blended output.  This routine
    431  * should generally be called first when programming a BLT.  The available
    432  * parameters mirror the hardware and are described as follows:
    433  *
    434  * alpha_operation =
    435  *   0 - alpha * A
    436  *   1 - (1 - alpha) * B
    437  *   2 - A + (1 - alpha)*B
    438  *   3 - alpha*A + (1 - alpha)*B
    439  *
    440  * alpha_type =
    441  *   0 - alpha component of channel A
    442  *   1 - alpha component of channel B
    443  *   2 - Constant alpha
    444  *   3 - Constant 1
    445  *   4 - The color components of channel A
    446  *   5 - The color components of channel B
    447  *   6 - Alpha comes from the alpha channel of the source before the source
    448  *		 undergoes color conversion.
    449  *
    450  * channel =
    451  *   0 - Channel A = source, channel B = destination
    452  *   1 - Channel B = source, channel A = destination
    453  *
    454  * apply_alpha =
    455  *   1 - Apply alpha blend to only the RGB portion of the pixel.  This must be
    456  *       set when the source or destination format do not include an alpha
    457  *		 channel.
    458  *   2 - Apply alpha blend only to the alpha portion of the pixel.  This
    459  *		 implies that both destination and source include an alpha channel.
    460  *   3 - Apply alpha blend to both the RGB and alpha portions of the pixel.
    461  *
    462  * Alpha-blended vectors are not currently supported.
    463  *-------------------------------------------------------------------------*/
    464 
    465 void
    466 gp_set_alpha_operation(int alpha_operation, int alpha_type, int channel,
    467                        int apply_alpha, unsigned char alpha)
    468 {
    469     gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE;
    470 
    471     /* THE AVAILABLE ALPHA DEFINITIONS FOLLOW THE HARDWARE       */
    472     /* This allows us to avoid giant switch structures, but it   */
    473     /* also implies that there is no mechanism to detect invalid */
    474     /* parameters.                                               */
    475 
    476     gp3_raster_mode = gp3_bpp | (unsigned long) alpha |
    477         ((unsigned long) apply_alpha << 22) |
    478         ((unsigned long) alpha_operation << 20) |
    479         ((unsigned long) alpha_type << 17) | ((unsigned long) channel << 16);
    480 
    481     WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode);
    482 
    483     /* CHECK IF DESTINATION IS REQUIRED */
    484 
    485     if ((alpha_operation == CIMGP_ALPHA_TIMES_A &&
    486          channel == CIMGP_CHANNEL_A_SOURCE &&
    487          alpha_type != CIMGP_CHANNEL_B_ALPHA &&
    488          alpha_type != CIMGP_ALPHA_FROM_RGB_B) ||
    489         (alpha_operation == CIMGP_BETA_TIMES_B &&
    490          channel == CIMGP_CHANNEL_A_DEST &&
    491          alpha_type != CIMGP_CHANNEL_A_ALPHA &&
    492          alpha_type != CIMGP_ALPHA_FROM_RGB_A)) {
    493         gp3_blt_mode = 0;
    494     }
    495     else
    496         gp3_blt_mode = GP3_BM_DST_REQ;
    497 }
    498 
    499 /*---------------------------------------------------------------------------
    500  * gp_set_solid_pattern
    501  *
    502  * This routine is called to program the hardware for a solid pattern.  It
    503  * need not be called for any other reason.  As a side effect, this routine
    504  * will clear any 8x8 pattern data.
    505  *-------------------------------------------------------------------------*/
    506 
    507 void
    508 gp_set_solid_pattern(unsigned long color)
    509 {
    510     /* CHANNEL 3 IS NOT NEEDED FOR SOLID PATTERNS */
    511 
    512     gp3_ch3_pat = 0;
    513 
    514     /* SET SOLID PATTERN IN COMMAND BUFFER */
    515     /* We are assuming that only one pattern type is ever set for a */
    516     /* BLT.  We are also assuming that gp_set_raster_operation will */
    517     /* be called before this routine.  With these assumptions, we   */
    518     /* will thus never have to change the raster mode register for  */
    519     /* solid patterns.                                              */
    520 
    521     if (gp3_blt) {
    522         gp3_cmd_header |= GP3_BLT_HDR_PAT_CLR0_ENABLE;
    523 
    524         WRITE_COMMAND32(GP3_BLT_PAT_COLOR_0, color);
    525     }
    526     else {
    527         gp3_cmd_header |= GP3_VEC_HDR_PAT_CLR0_ENABLE;
    528 
    529         WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_0, color);
    530     }
    531 }
    532 
    533 /*---------------------------------------------------------------------------
    534  * gp_set_mono_pattern
    535  *
    536  * This routine is called to program the hardware for a monochrome pattern.
    537  * As a side effect, this routine will clear any 8x8 pattern data.
    538  *-------------------------------------------------------------------------*/
    539 
    540 void
    541 gp_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor,
    542                     unsigned long data0, unsigned long data1, int transparent,
    543                     int x, int y)
    544 {
    545     /* CHANNEL 3 IS NOT NEEDED FOR MONOCHROME PATTERNS */
    546 
    547     gp3_ch3_pat = 0;
    548 
    549     /* UPDATE RASTER MODE REGISTER */
    550 
    551     if (transparent)
    552         gp3_raster_mode |= GP3_RM_PAT_MONO | GP3_RM_PAT_TRANS;
    553     else
    554         gp3_raster_mode |= GP3_RM_PAT_MONO;
    555 
    556     gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE;
    557 
    558     WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode);
    559 
    560     /* SET MONOCHROME PATTERN DATA AND COLORS */
    561 
    562     if (gp3_blt) {
    563         gp3_cmd_header |=
    564             (GP3_BLT_HDR_PAT_CLR0_ENABLE | GP3_BLT_HDR_PAT_CLR1_ENABLE |
    565              GP3_BLT_HDR_PAT_DATA0_ENABLE | GP3_BLT_HDR_PAT_DATA1_ENABLE);
    566 
    567         WRITE_COMMAND32(GP3_BLT_PAT_COLOR_0, bgcolor);
    568         WRITE_COMMAND32(GP3_BLT_PAT_COLOR_1, fgcolor);
    569         WRITE_COMMAND32(GP3_BLT_PAT_DATA_0, data0);
    570         WRITE_COMMAND32(GP3_BLT_PAT_DATA_1, data1);
    571     }
    572     else {
    573         gp3_cmd_header |=
    574             (GP3_VEC_HDR_PAT_CLR0_ENABLE | GP3_VEC_HDR_PAT_CLR1_ENABLE |
    575              GP3_VEC_HDR_PAT_DATA0_ENABLE | GP3_VEC_HDR_PAT_DATA1_ENABLE);
    576 
    577         WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_0, bgcolor);
    578         WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_1, fgcolor);
    579         WRITE_COMMAND32(GP3_VECTOR_PAT_DATA_0, data0);
    580         WRITE_COMMAND32(GP3_VECTOR_PAT_DATA_1, data1);
    581     }
    582 
    583     /* SAVE PATTERN ORIGIN */
    584 
    585     gp3_pat_origin = ((unsigned long) y << 29) |
    586         (((unsigned long) x & 7) << 26);
    587 }
    588 
    589 /*---------------------------------------------------------------------------
    590  * gp_set_pattern_origin
    591  *
    592  * This routine overrides the pattern origins set in gp_set_mono_pattern or
    593  * gp_set_color_pattern.  It is generally used to override the original
    594  * pattern origin due to a change in clipping.
    595  *-------------------------------------------------------------------------*/
    596 
    597 void
    598 gp_set_pattern_origin(int x, int y)
    599 {
    600     /* SAVE PATTERN ORIGIN */
    601 
    602     gp3_pat_origin = ((unsigned long) y << 29) |
    603         (((unsigned long) x & 7) << 26);
    604 }
    605 
    606 /*---------------------------------------------------------------------------
    607  * gp_set_color_pattern
    608  *
    609  * This routine is called to program a 8x8 color pattern into the LUT
    610  * hardware.  Unlike the other pattern routines, this routine must be called
    611  * before any gp_declare_xxxx routines.  The pattern that is programmed into
    612  * the hardware will stay persistent for all subsequent primitives until one
    613  * of the following conditions happens.
    614  *   - Another pattern type is programmed.
    615  *   - A color-conversion BLT rotation BLT.
    616  *-------------------------------------------------------------------------*/
    617 
    618 void
    619 gp_set_color_pattern(unsigned long *pattern, int format, int x, int y)
    620 {
    621     unsigned long size_dwords, temp;
    622 
    623     gp3_ch3_pat = 1;
    624 
    625     /* SAVE COLOR PATTERN SOURCE INFO
    626      * Color patterns can be in a format different than the primary display.
    627      * 4BPP patterns are not supported.
    628      */
    629 
    630     gp3_pat_pix_shift = (unsigned long) ((format >> 2) & 3);
    631     gp3_pat_format = (((unsigned long) format & 0xF) << 24) |
    632         (((unsigned long) format & 0x10) << 17) |
    633         GP3_CH3_COLOR_PAT_ENABLE | GP3_CH3_C3EN;
    634 
    635     size_dwords = (64 << gp3_pat_pix_shift) >> 2;
    636 
    637     /* CHECK FOR WRAP AFTER LUT LOAD                 */
    638     /* Primitive size is 12 plus the amount of data. */
    639 
    640     gp3_cmd_next = gp3_cmd_current + (size_dwords << 2) + 12;
    641 
    642     if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
    643         gp3_cmd_next = gp3_cmd_top;
    644         gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP |
    645             GP3_LUT_HDR_DATA_ENABLE;
    646 
    647         /* WAIT FOR HARDWARE           */
    648         /* Same logic as BLT wrapping. */
    649 
    650         GP3_WAIT_WRAP(temp);
    651     }
    652     else {
    653         gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE;
    654 
    655         /* WAIT FOR AVAILABLE SPACE */
    656 
    657         GP3_WAIT_PRIMITIVE(temp);
    658     }
    659 
    660     /* SAVE CURRENT BUFFER POINTER */
    661 
    662     cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
    663 
    664     /* PREPARE FOR COMMAND BUFFER DATA WRITES                 */
    665     /* Pattern data is contiguous DWORDs at LUT address 0x100 */
    666 
    667     WRITE_COMMAND32(0, gp3_cmd_header);
    668     WRITE_COMMAND32(4, 0x100);
    669     WRITE_COMMAND32(8, size_dwords | GP3_LUT_DATA_TYPE);
    670 
    671     /* WRITE ALL DATA */
    672 
    673     WRITE_COMMAND_STRING32(12, pattern, 0, size_dwords);
    674 
    675     /* START OPERATION */
    676 
    677     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
    678     gp3_cmd_current = gp3_cmd_next;
    679 
    680     /* SAVE PATTERN ORIGIN */
    681 
    682     gp3_pat_origin = ((unsigned long) y << 29) |
    683         (((unsigned long) x & 7) << 26);
    684 }
    685 
    686 /*---------------------------------------------------------------------------
    687  * gp_set_mono_source
    688  *
    689  * This routine is called to program the colors for monochrome source data.
    690  *-------------------------------------------------------------------------*/
    691 
    692 void
    693 gp_set_mono_source(unsigned long bgcolor, unsigned long fgcolor,
    694                    int transparent)
    695 {
    696     /* UPDATE RASTER MODE REGISTER IF TRANSPARENT */
    697 
    698     if (transparent) {
    699         gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE;
    700         gp3_raster_mode |= GP3_RM_SRC_TRANS;
    701 
    702         WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode);
    703     }
    704 
    705     /* SET MONOCHROME SOURCE COLORS */
    706     /* Note that this routine only sets the colors.  The actual */
    707     /* source type is determined by the final output routine    */
    708     /* (gp_mono_bitmap_xxx, gp_color_bitmap_xxx, etc.)          */
    709 
    710     gp3_cmd_header |= GP3_BLT_HDR_SRC_FG_ENABLE | GP3_BLT_HDR_SRC_BG_ENABLE;
    711 
    712     WRITE_COMMAND32(GP3_BLT_SRC_COLOR_FG, fgcolor);
    713     WRITE_COMMAND32(GP3_BLT_SRC_COLOR_BG, bgcolor);
    714 }
    715 
    716 /*---------------------------------------------------------------------------
    717  * gp_set_solid_source
    718  *
    719  * This routine is called to program a solid source color.  A solid source
    720  * color is used primarily for vectors or antialiased text.
    721  *-------------------------------------------------------------------------*/
    722 
    723 void
    724 gp_set_solid_source(unsigned long color)
    725 {
    726     /* SET SOLID SOURCE COLOR */
    727     /* The solid source register is in the same place for both BLTs and */
    728     /* vectors.                                                         */
    729 
    730     gp3_cmd_header |= GP3_BLT_HDR_SRC_FG_ENABLE;
    731 
    732     WRITE_COMMAND32(GP3_BLT_SRC_COLOR_FG, color);
    733 }
    734 
    735 /*---------------------------------------------------------------------------
    736  * gp_set_source_transparency
    737  *
    738  * This routine sets the source transparency and mask to be used in future
    739  * rendering operations.  Transparency is cleared by gp_set_raster_operation,
    740  * so this routine should never be called first.
    741  *-------------------------------------------------------------------------*/
    742 
    743 void
    744 gp_set_source_transparency(unsigned long color, unsigned long mask)
    745 {
    746     gp3_raster_mode |= GP3_RM_SRC_TRANS;
    747     gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_SRC_FG_ENABLE |
    748         GP3_BLT_HDR_SRC_BG_ENABLE;
    749 
    750     WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode);
    751     WRITE_COMMAND32(GP3_BLT_SRC_COLOR_FG, color);
    752     WRITE_COMMAND32(GP3_BLT_SRC_COLOR_BG, mask);
    753 }
    754 
    755 /*---------------------------------------------------------------------------
    756  * gp_program_lut
    757  *
    758  * This routine is called to program the hardware LUT with color-conversion
    759  * information.  This routine should be called before any gp_declare_xxxx
    760  * routines.
    761  *
    762  * colors   - Pointer to an array of DWORDs for color expansion.
    763  *
    764  * full_lut - Selector between 4BPP and 8BPP expansion. The hardware is
    765  *            initialized with 16 dwords for 4BPP expansion and 256 dwords
    766  *            for 8BPP expansion.
    767  *-------------------------------------------------------------------------*/
    768 
    769 void
    770 gp_program_lut(unsigned long *colors, int full_lut)
    771 {
    772     unsigned long size_dwords, temp;
    773 
    774     /* SIZE IS EITHER 16 DWORDS (4BPP) or 256 DWORDS (8BPP) */
    775 
    776     if (full_lut)
    777         size_dwords = 256;
    778     else
    779         size_dwords = 16;
    780 
    781     /* CHECK FOR WRAP AFTER LUT LOAD                 */
    782     /* Primitive size is 12 plus the amount of data. */
    783 
    784     gp3_cmd_next = gp3_cmd_current + (size_dwords << 2) + 12;
    785 
    786     if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
    787         gp3_cmd_next = gp3_cmd_top;
    788         gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP |
    789             GP3_LUT_HDR_DATA_ENABLE;
    790 
    791         /* WAIT FOR HARDWARE           */
    792         /* Same logic as BLT wrapping. */
    793 
    794         GP3_WAIT_WRAP(temp);
    795     }
    796     else {
    797         gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE;
    798 
    799         /* WAIT FOR AVAILABLE SPACE */
    800 
    801         GP3_WAIT_PRIMITIVE(temp);
    802     }
    803 
    804     /* SAVE CURRENT BUFFER POINTER */
    805 
    806     cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
    807 
    808     /* PREPARE FOR COMMAND BUFFER DATA WRITES             */
    809     /* Pattern data is contiguous DWORDs at LUT address 0 */
    810 
    811     WRITE_COMMAND32(0, gp3_cmd_header);
    812     WRITE_COMMAND32(4, 0);
    813     WRITE_COMMAND32(8, (size_dwords | GP3_LUT_DATA_TYPE));
    814 
    815     /* WRITE ALL DATA */
    816 
    817     WRITE_COMMAND_STRING32(12, colors, 0, size_dwords);
    818 
    819     /* START OPERATION */
    820 
    821     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
    822     gp3_cmd_current = gp3_cmd_next;
    823 }
    824 
    825 /*---------------------------------------------------------------------------
    826  * gp_set_vector_pattern
    827  *
    828  * This routine is called to program the hardware LUT with a vector pattern.
    829  * A vector pattern is programmed as a 32-bit mask that specifies a
    830  * transparency pattern.  A length parameter is used to specify patterns
    831  * smaller than 32.  Note that vectors in Geode LX do not continue across
    832  * corners.  The beginning of each vector will always begin with bit 0 of the
    833  * vector pattern.  It is the responsibility of the caller to update the
    834  * pattern if an alternate behavior is desired.
    835  *
    836  * This routine faces the same restrictions of all routines that program
    837  * the LUT, in that it must be called before any gp_declare_xxxx routines,
    838  * it cannot be combined with an 8x8 color pattern, color conversion or
    839  * rotation.
    840  *-------------------------------------------------------------------------*/
    841 
    842 void
    843 gp_set_vector_pattern(unsigned long pattern, unsigned long color, int length)
    844 {
    845     unsigned long temp, mask;
    846 
    847     gp3_ch3_pat = 1;
    848     gp3_vector_pattern_color = color;
    849 
    850     /* CREATE SUITABLE PATTERN MASK */
    851     /* The GP requires a minimum of four pixels in a vector pattern.  We */
    852     /* can get around this restriction by doubling any patterns smaller  */
    853     /* than 4 pixels.                                                    */
    854 
    855     while (length < 4) {
    856         mask = 0xFFFFFFFF >> (32 - length);
    857         pattern = (pattern << length) | (pattern & mask);
    858         length <<= 1;
    859     }
    860     mask = 0xFFFFFFFF >> (32 - length);
    861 
    862     gp3_vec_pat = pattern;
    863 
    864     /* CHECK FOR WRAP AFTER LUT LOAD */
    865 
    866     gp3_cmd_next = gp3_cmd_current + GP3_VECTOR_PATTERN_COMMAND_SIZE;
    867 
    868     if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
    869         gp3_cmd_next = gp3_cmd_top;
    870         gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP |
    871             GP3_LUT_HDR_DATA_ENABLE;
    872 
    873         /* WAIT FOR HARDWARE           */
    874         /* Same logic as BLT wrapping. */
    875 
    876         GP3_WAIT_WRAP(temp);
    877     }
    878     else {
    879         gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE;
    880 
    881         /* WAIT FOR AVAILABLE SPACE */
    882 
    883         GP3_WAIT_PRIMITIVE(temp);
    884     }
    885 
    886     /* SAVE CURRENT BUFFER POINTER */
    887 
    888     cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
    889 
    890     /* PREPARE FOR COMMAND BUFFER DATA WRITES      */
    891     /* Pattern data is 2 DWORDs at 0x100 and 0x101 */
    892 
    893     WRITE_COMMAND32(0, gp3_cmd_header);
    894     WRITE_COMMAND32(4, 0x100);
    895     WRITE_COMMAND32(8, (2 | GP3_LUT_DATA_TYPE));
    896     WRITE_COMMAND32(12, pattern);
    897     WRITE_COMMAND32(16, mask);
    898 
    899     /* START OPERATION */
    900 
    901     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
    902     gp3_cmd_current = gp3_cmd_next;
    903 }
    904 
    905 /*---------------------------------------------------------------------------
    906  * gp_set_strides
    907  *
    908  * This routine is called to program the pitch between successive lines of
    909  * data in the frame buffer.  The strides should be DWORD aligned and less
    910  * than 64K.  These restrictions are not checked by the API.
    911  *-------------------------------------------------------------------------*/
    912 
    913 void
    914 gp_set_strides(unsigned long dst_stride, unsigned long src_stride)
    915 {
    916     /* SAVE STRIDES */
    917     /* The source stride may be needed later for channel 3 source data and */
    918     /* we may need to use these strides in calculations.                   */
    919 
    920     gp3_src_stride = src_stride;
    921     gp3_dst_stride = dst_stride;
    922 
    923     /* ENABLE STRIDES */
    924     /* The stride register is in the same place for BLTs and vectors */
    925 
    926     gp3_cmd_header |= GP3_BLT_HDR_STRIDE_ENABLE;
    927 
    928     WRITE_COMMAND32(GP3_BLT_STRIDE, ((src_stride << 16) | dst_stride));
    929 }
    930 
    931 /*---------------------------------------------------------------------------
    932  * gp_set_source_format
    933  *
    934  * This routine is used to program the format of source data used in
    935  * subsequent color-conversion or rotation operations.  Note that 4BPP
    936  * indexed and 8BPP indexed source formats cannot be used when rotating, as
    937  * the LUT will be destroyed.  These formats also cannot be combined with an
    938  * 8x8 color pattern.  The supported formats mirror the hardware and are
    939  * described as follows:
    940  *
    941  * 0  - 8BPP 3:3:2
    942  * 1  - 8BPP indexed
    943  * 4  - 16BPP 4:4:4:4
    944  * 5  - 16BPP 1:5:5:5
    945  * 6  - 16BPP 5:6:5
    946  * 7  - 16BPP YUV
    947  * 8  - 32BPP 8:8:8:8
    948  * 13 - 4BPP indexed
    949  * 20 - 16BPP 4:4:4:4 BGR
    950  * 21 - 16BPP 1:5:5:5 BGR
    951  * 22 - 16BPP 0:5:6:5 BGR
    952  * 24 - 32BPP 8:8:8:8 BGR
    953  *-------------------------------------------------------------------------*/
    954 
    955 void
    956 gp_set_source_format(int format)
    957 {
    958     /* SAVE FORMAT */
    959     /* We will combine the source format later when doing color conversion. */
    960     /* We also save the pixel size for host source calculations.            */
    961     /* Conveniently, the source formats are organized such that the upper   */
    962     /* two bits of the nibble represent the pixel shift, with a pixel shift */
    963     /* of 3 being a special case for 4BPP data.  Clever, yes?  Even more    */
    964     /* clever, bit 4 indicates BGR ordering.                                */
    965 
    966     gp3_src_pix_shift = (unsigned long) ((format >> 2) & 3);
    967     gp3_src_format = (((unsigned long) format & 0xF) << 24) |
    968         (((unsigned long) format & 0x10) << 18);
    969 }
    970 
    971 /*---------------------------------------------------------------------------
    972  * gp_pattern_fill
    973  *
    974  * This routine is called to perform a simple pattern fill.  The pattern
    975  * can be solid, monochrome or a preprogrammed 8x8 color pattern.  If
    976  * the ROP involves source data, that source data will be constant.
    977  *-------------------------------------------------------------------------*/
    978 
    979 void
    980 gp_pattern_fill(unsigned long dstoffset, unsigned long width,
    981                 unsigned long height)
    982 {
    983     unsigned long base_register;
    984 
    985     base_register = (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK) |
    986         ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000));
    987 
    988     /* ENABLE RELEVANT REGISTERS */
    989     /* Note that we always enable and write the channel 3 mode, if only */
    990     /* to turn it off.   Cimarron also always writes the base offset    */
    991     /* register to allow operation with frame buffers larger than 16MB. */
    992 
    993     gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE |
    994         GP3_BLT_HDR_WIDHI_ENABLE |
    995         GP3_BLT_HDR_BASE_OFFSET_ENABLE |
    996         GP3_BLT_HDR_CH3_STR_ENABLE |
    997         GP3_BLT_HDR_CH3_WIDHI_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
    998 
    999     /* WRITE THE REGISTERS COMMON TO ALL PATTERN TYPES */
   1000     /* The destination base is the frame buffer base plus whatever */
   1001     /* 4MB segment we happen to be BLTing to.                      */
   1002 
   1003     WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, ((width << 16) | height));
   1004     WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base_register);
   1005 
   1006     /* CHECK 8X8 COLOR PATTERN CASE */
   1007 
   1008     if (gp3_ch3_pat) {
   1009         /* SET CHANNEL 3 PATTERN ORIGINS */
   1010 
   1011         gp3_cmd_header |= GP3_BLT_HDR_CH3_OFF_ENABLE;
   1012 
   1013         /* INITIALIZE CHANNEL 3 PARAMETERS */
   1014 
   1015         WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, ((width << 16) | height));
   1016         WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin);
   1017         WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset & 0x3FFFFF);
   1018         WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format);
   1019     }
   1020     else {
   1021         /* DISABLE CHANNEL 3 AND USE NORMAL PATTERN ORIGINS */
   1022 
   1023         WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0);
   1024         WRITE_COMMAND32(GP3_BLT_DST_OFFSET,
   1025                         ((dstoffset & 0x3FFFFF) | gp3_pat_origin));
   1026     }
   1027 
   1028     /* START THE BLT */
   1029 
   1030     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   1031     WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode);
   1032     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   1033     gp3_cmd_current = gp3_cmd_next;
   1034 }
   1035 
   1036 /*---------------------------------------------------------------------------
   1037  * gp_screen_to_screen_blt
   1038  *
   1039  * This routine is called to perform a BLT from one location inside video
   1040  * memory to another location inside video memory.  The source and destination
   1041  * formats are assumed to be the current BPP.  Whenever possible, this routine
   1042  * tries to use channel 3 to fetch source data.  The BLT flags can affect this
   1043  * behavior in the following ways:
   1044  *   CIMGP_BLTFLAGS_PRES_COLOR_PAT
   1045  *      A color pattern is being stored in the channel 3 buffer.  It is either
   1046  *      being stored for a later BLT or being combined with the current source
   1047  *      data.  Channel 3 cannot be used to fetch source data or the pattern
   1048  *      will be overwritten.
   1049  *   CIMGP_BLTFLAGS_PRES_LUT
   1050  *      If the first flag is not set, this flag will limit the use of the
   1051  *      channel 3 buffer to 1K.
   1052  *-------------------------------------------------------------------------*/
   1053 
   1054 void
   1055 gp_screen_to_screen_blt(unsigned long dstoffset, unsigned long srcoffset,
   1056                         unsigned long width, unsigned long height, int flags)
   1057 {
   1058     unsigned long base;
   1059     unsigned long ch3_flags = 0;
   1060     unsigned long blt_mode = gp3_blt_mode;
   1061     unsigned long size = ((width << 16) | height);
   1062     unsigned long dstbase, srcbase;
   1063 
   1064     /* CALCULATE BASE OFFSETS                                             */
   1065     /* We need to set the 4MB aligned base offsets before we add offsets  */
   1066     /* for negative BLTs.                                                 */
   1067 
   1068     srcbase = srcoffset & 0xFFC00000;
   1069     dstbase = dstoffset & 0xFFC00000;
   1070     srcoffset &= 0x3FFFFF;
   1071     dstoffset &= 0x3FFFFF;
   1072 
   1073     /* ADJUST OFFSETS BASED ON FLAGS */
   1074     /* We adjust the source and destination offsets to point to the first */
   1075     /* byte of the first pixel of the BLT.  This routine assumes that the */
   1076     /* source and destination regions do not wrap past the end of a 16MB  */
   1077     /* region.                                                            */
   1078 
   1079     if (flags & CIMGP_NEGXDIR) {
   1080         srcoffset += (width << gp3_pix_shift) - 1;
   1081         dstoffset += (width << gp3_pix_shift) - 1;
   1082         blt_mode |= GP3_BM_NEG_XDIR;
   1083         ch3_flags |= GP3_CH3_NEG_XDIR;
   1084     }
   1085     if (flags & CIMGP_NEGYDIR) {
   1086         srcoffset += (height - 1) * gp3_src_stride;
   1087         dstoffset += (height - 1) * gp3_dst_stride;
   1088         blt_mode |= GP3_BM_NEG_YDIR;
   1089         ch3_flags |= GP3_CH3_NEG_YDIR;
   1090     }
   1091 
   1092     /* BRANCH BASED ON CHANNEL 3                                     */
   1093     /* If a color pattern is not being saved or used, channel 3 will */
   1094     /* be used to fetch source for maximum throughput.   Channel 3   */
   1095     /* is not used if transparency or alpha blending is enabled.     */
   1096 
   1097     if (!(gp3_blt_flags & CIMGP_BLTFLAGS_PRES_COLOR_PAT) &&
   1098         !(gp3_raster_mode & GP3_RM_SRC_TRANS) && !(flags & CIMGP_NEGYDIR)) {
   1099         base = ((gp3_fb_base << 24) + dstbase) |
   1100             ((gp3_fb_base << 4) + (srcbase >> 20)) |
   1101             (gp3_base_register & GP3_BASE_OFFSET_SRCMASK);
   1102 
   1103         gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE |
   1104             GP3_BLT_HDR_WIDHI_ENABLE |
   1105             GP3_BLT_HDR_CH3_STR_ENABLE |
   1106             GP3_BLT_HDR_CH3_WIDHI_ENABLE |
   1107             GP3_BLT_HDR_CH3_OFF_ENABLE |
   1108             GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
   1109 
   1110         WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset | gp3_pat_origin));
   1111         WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, srcoffset);
   1112         WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
   1113         WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size);
   1114         WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
   1115         WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR,
   1116                         GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE |
   1117                         gp3_ch3_bpp | gp3_src_stride | ch3_flags |
   1118                         ((gp3_blt_flags & CIMGP_ENABLE_PREFETCH) << 17) |
   1119                         ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20));
   1120     }
   1121     else {
   1122         /* CALCULATE BASE OFFSET REGISTER */
   1123 
   1124         base = ((gp3_fb_base << 24) + dstbase) |
   1125             ((gp3_fb_base << 14) + (srcbase >> 10)) |
   1126             (gp3_base_register & GP3_BASE_OFFSET_CH3MASK);
   1127 
   1128         /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS                */
   1129         /* We assume that a color pattern is being ROPed with source  */
   1130         /* data if the pattern type is color and the preserve pattern */
   1131         /* was set.                                                   */
   1132 
   1133         blt_mode |= GP3_BM_SRC_FB;
   1134 
   1135         gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
   1136             GP3_BLT_HDR_DST_OFF_ENABLE |
   1137             GP3_BLT_HDR_WIDHI_ENABLE |
   1138             GP3_BLT_HDR_CH3_WIDHI_ENABLE |
   1139             GP3_BLT_HDR_CH3_STR_ENABLE |
   1140             GP3_BLT_HDR_CH3_OFF_ENABLE |
   1141             GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
   1142 
   1143         if (gp3_ch3_pat) {
   1144             WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin);
   1145             WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset);
   1146             WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format | ch3_flags);
   1147             WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size);
   1148         }
   1149         else {
   1150             WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset | gp3_pat_origin);
   1151             WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0);
   1152         }
   1153 
   1154         WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, srcoffset);
   1155         WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
   1156         WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
   1157     }
   1158 
   1159     /* START THE BLT */
   1160 
   1161     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   1162     WRITE_COMMAND32(GP3_BLT_MODE, blt_mode);
   1163     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   1164     gp3_cmd_current = gp3_cmd_next;
   1165 }
   1166 
   1167 /*---------------------------------------------------------------------------
   1168  * gp_screen_to_screen_convert
   1169  *
   1170  * This routine is called to color-convert a rectangular region of the frame
   1171  * buffer into the current BPP. The format of the source region is programmed
   1172  * by gp_set_source_format.
   1173  *-------------------------------------------------------------------------*/
   1174 
   1175 void
   1176 gp_screen_to_screen_convert(unsigned long dstoffset, unsigned long srcoffset,
   1177                             unsigned long width, unsigned long height,
   1178                             int nibble)
   1179 {
   1180     unsigned long size = ((width << 16) | height);
   1181     unsigned long ch3_offset = srcoffset & 0x3FFFFF;
   1182     unsigned long ch3_size, base;
   1183 
   1184     base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
   1185         ((gp3_fb_base << 4) + ((srcoffset & 0xFFC00000) >> 20)) |
   1186         (gp3_base_register & GP3_BASE_OFFSET_SRCMASK);
   1187 
   1188     /* SET NIBBLE FOR 4BPP */
   1189     /* 4BPP is a special case in that it requires subpixel addressing.  The */
   1190     /* user must supply this information via the nibble parameter.  This    */
   1191     /* parameter is ignored for every other source format.                  */
   1192 
   1193     ch3_size = size;
   1194     if (gp3_src_pix_shift == 3)
   1195         ch3_offset |= ((nibble & 1) << 25);
   1196     else if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED)
   1197         ch3_size = ((((width * 3) + 3) >> 2) << 16) | height;
   1198 
   1199     /* SET APPROPRIATE ENABLES */
   1200 
   1201     gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE |
   1202         GP3_BLT_HDR_WIDHI_ENABLE |
   1203         GP3_BLT_HDR_CH3_OFF_ENABLE |
   1204         GP3_BLT_HDR_CH3_STR_ENABLE |
   1205         GP3_BLT_HDR_CH3_WIDHI_ENABLE |
   1206         GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
   1207 
   1208     /* WRITE ALL BLT REGISTERS */
   1209 
   1210     WRITE_COMMAND32(GP3_BLT_DST_OFFSET,
   1211                     (dstoffset & 0x3FFFFF) | gp3_pat_origin);
   1212     WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
   1213     WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, ch3_size);
   1214     WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset);
   1215     WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR,
   1216                     GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | gp3_src_format |
   1217                     ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20) |
   1218                     ((gp3_blt_flags & CIMGP_ENABLE_PREFETCH) << 17) |
   1219                     gp3_src_stride);
   1220     WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
   1221 
   1222     /* START THE BLT */
   1223 
   1224     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   1225     WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode);
   1226     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   1227     gp3_cmd_current = gp3_cmd_next;
   1228 }
   1229 
   1230 /*---------------------------------------------------------------------------
   1231  * gp_color_bitmap_to_screen_blt
   1232  *
   1233  * This routine is called to BLT data from system memory into the frame
   1234  * buffer.  'srcy' is deliberately omitted to prevent extra calculations for
   1235  * simple applications that have no source indexes.
   1236  *-------------------------------------------------------------------------*/
   1237 
   1238 void
   1239 gp_color_bitmap_to_screen_blt(unsigned long dstoffset, unsigned long srcx,
   1240                               unsigned long width, unsigned long height,
   1241                               unsigned char *data, long pitch)
   1242 {
   1243     unsigned long indent, temp;
   1244     unsigned long total_dwords, size_dwords;
   1245     unsigned long dword_count, byte_count;
   1246     unsigned long size = ((width << 16) | height);
   1247     unsigned long srcoffset;
   1248 
   1249     /* ASSUME BITMAPS ARE DWORD ALIGNED */
   1250     /* We will offset into the source data in DWORD increments.  We */
   1251     /* set the source index to the remaining byte offset and        */
   1252     /* increment the size of each line to account for the dont-care */
   1253     /* pixel(s).                                                    */
   1254 
   1255     indent = srcx << gp3_pix_shift;
   1256     srcoffset = (indent & ~3L);
   1257     indent &= 3;
   1258 
   1259     /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS                */
   1260     /* We assume that a color pattern is being ROPed with source  */
   1261     /* data if the pattern type is color and the preserve pattern */
   1262     /* was set.                                                   */
   1263 
   1264     gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
   1265         GP3_BLT_HDR_DST_OFF_ENABLE |
   1266         GP3_BLT_HDR_WIDHI_ENABLE |
   1267         GP3_BLT_HDR_CH3_STR_ENABLE |
   1268         GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
   1269 
   1270     if (gp3_ch3_pat) {
   1271         gp3_cmd_header |= GP3_BLT_HDR_CH3_OFF_ENABLE |
   1272             GP3_BLT_HDR_CH3_WIDHI_ENABLE;
   1273 
   1274         WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin);
   1275         WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
   1276         WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format);
   1277         WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size);
   1278     }
   1279     else {
   1280         WRITE_COMMAND32(GP3_BLT_DST_OFFSET,
   1281                         ((dstoffset & 0x3FFFFF) | gp3_pat_origin));
   1282         WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0);
   1283     }
   1284 
   1285     WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, indent);
   1286     WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
   1287     WRITE_COMMAND32(GP3_BLT_BASE_OFFSET,
   1288                     ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)));
   1289     WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode | GP3_BM_SRC_HOST);
   1290 
   1291     /* START THE BLT */
   1292 
   1293     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   1294     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   1295     gp3_cmd_current = gp3_cmd_next;
   1296 
   1297     /* CALCULATE THE SIZE OF ONE LINE */
   1298 
   1299     size = (width << gp3_pix_shift) + indent;
   1300     total_dwords = (size + 3) >> 2;
   1301     size_dwords = (total_dwords << 2) + 8;
   1302     dword_count = (size >> 2);
   1303     byte_count = (size & 3);
   1304 
   1305     /* CHECK FOR SMALL BLT CASE */
   1306 
   1307     if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE &&
   1308         (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) {
   1309         /* UPDATE THE COMMAND POINTER */
   1310 
   1311         cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
   1312 
   1313         /* CHECK IF A WRAP WILL BE NEEDED */
   1314 
   1315         gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8;
   1316 
   1317         if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
   1318             gp3_cmd_next = gp3_cmd_top;
   1319 
   1320             GP3_WAIT_WRAP(temp);
   1321             WRITE_COMMAND32(0,
   1322                             GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
   1323                             GP3_DATA_LOAD_HDR_ENABLE);
   1324         }
   1325         else {
   1326             GP3_WAIT_PRIMITIVE(temp);
   1327             WRITE_COMMAND32(0,
   1328                             GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
   1329         }
   1330 
   1331         /* WRITE DWORD COUNT */
   1332 
   1333         WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | (total_dwords * height));
   1334 
   1335         while (height--) {
   1336             /* WRITE DATA */
   1337 
   1338             WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
   1339             WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
   1340                                   srcoffset + (dword_count << 2), byte_count);
   1341 
   1342             srcoffset += pitch;
   1343             cim_cmd_ptr += total_dwords << 2;
   1344         }
   1345 
   1346         WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   1347         gp3_cmd_current = gp3_cmd_next;
   1348     }
   1349     else {
   1350         /*
   1351          * Each line will be created as a separate command buffer entry to
   1352          * allow line-by-line wrapping and to allow simultaneous rendering
   1353          * by the HW.
   1354          */
   1355 
   1356         while (height--) {
   1357             /* UPDATE THE COMMAND POINTER
   1358              * The WRITE_COMMANDXX macros use a pointer to the current buffer
   1359              * space.  This is created by adding gp3_cmd_current to the base
   1360              * pointer.
   1361              */
   1362 
   1363             cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
   1364 
   1365             /* CHECK IF A WRAP WILL BE NEEDED */
   1366 
   1367             gp3_cmd_next = gp3_cmd_current + size_dwords;
   1368             if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
   1369                 gp3_cmd_next = gp3_cmd_top;
   1370 
   1371                 /* WAIT FOR HARDWARE */
   1372 
   1373                 GP3_WAIT_WRAP(temp);
   1374                 WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE |
   1375                                 GP3_DATA_LOAD_HDR_WRAP |
   1376                                 GP3_DATA_LOAD_HDR_ENABLE);
   1377             }
   1378             else {
   1379                 /* WAIT FOR AVAILABLE SPACE */
   1380 
   1381                 GP3_WAIT_PRIMITIVE(temp);
   1382                 WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE |
   1383                                 GP3_DATA_LOAD_HDR_ENABLE);
   1384             }
   1385 
   1386             /* WRITE DWORD COUNT */
   1387 
   1388             WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | total_dwords);
   1389 
   1390             /* WRITE DATA */
   1391 
   1392             WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
   1393             WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
   1394                                   srcoffset + (dword_count << 2), byte_count);
   1395 
   1396             /* UPDATE POINTERS */
   1397 
   1398             srcoffset += pitch;
   1399             WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   1400             gp3_cmd_current = gp3_cmd_next;
   1401         }
   1402     }
   1403 }
   1404 
   1405 /*---------------------------------------------------------------------------
   1406  * gp_color_convert_blt
   1407  *
   1408  * This routine is called to convert data that is stored in system memory
   1409  * into the current graphics BPP.  The source format is programmed in
   1410  * gp_set_source_format.
   1411  *-------------------------------------------------------------------------*/
   1412 
   1413 void
   1414 gp_color_convert_blt(unsigned long dstoffset, unsigned long srcx,
   1415                      unsigned long width, unsigned long height,
   1416                      unsigned char *data, long pitch)
   1417 {
   1418     unsigned long indent, temp;
   1419     unsigned long total_dwords, size_dwords;
   1420     unsigned long dword_count, byte_count;
   1421     unsigned long size = ((width << 16) | height);
   1422     unsigned long ch3_size;
   1423     unsigned long ch3_offset, srcoffset;
   1424     unsigned long base;
   1425 
   1426     /* ASSUME BITMAPS ARE DWORD ALIGNED */
   1427     /* We will offset into the source data in DWORD increments.  We  */
   1428     /* set the source index to the remaining byte offset and         */
   1429     /* increment the size of each line to account for the dont-care  */
   1430     /* pixel(s).   For 4BPP source data, we also set the appropriate */
   1431     /* nibble index.                                                 */
   1432 
   1433     /* CALCULATE THE SIZE OF ONE LINE */
   1434 
   1435     if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED) {
   1436         /* HANDLE 24BPP
   1437          * Note that we do not do anything to guarantee that the source data
   1438          * is DWORD aligned.  The logic here is that the source data will be
   1439          * cacheable, in which case Geode LX will not lose any clocks for
   1440          * unaligned moves.  Also note that the channel 3 width is
   1441          * programmed as the number of dwords, while the normal width is
   1442          * programmed as the number of pixels.
   1443          */
   1444 
   1445         srcoffset = srcx * 3;
   1446         ch3_offset = 0;
   1447         temp = width * 3;
   1448         ch3_size = (((temp + 3) >> 2) << 16) | height;
   1449     }
   1450     else {
   1451         ch3_size = size;
   1452 
   1453         if (gp3_src_pix_shift == 3) {
   1454             /* CALCULATE INDENT AND SOURCE OFFSET */
   1455 
   1456             indent = (srcx >> 1);
   1457             srcoffset = (indent & ~3L);
   1458             indent &= 3;
   1459             ch3_offset = indent | ((srcx & 1) << 25);
   1460 
   1461             temp = ((width + (srcx & 1) + 1) >> 1) + indent;
   1462         }
   1463         else {
   1464             indent = (srcx << gp3_src_pix_shift);
   1465             srcoffset = (indent & ~3L);
   1466             indent &= 3;
   1467             ch3_offset = indent;
   1468 
   1469             temp = (width << gp3_src_pix_shift) + indent;
   1470         }
   1471     }
   1472 
   1473     total_dwords = (temp + 3) >> 2;
   1474     size_dwords = (total_dwords << 2) + 8;
   1475     dword_count = (temp >> 2);
   1476     byte_count = (temp & 3);
   1477 
   1478     base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
   1479         (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
   1480 
   1481     /* SET APPROPRIATE ENABLES */
   1482 
   1483     gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE |
   1484         GP3_BLT_HDR_WIDHI_ENABLE |
   1485         GP3_BLT_HDR_CH3_STR_ENABLE |
   1486         GP3_BLT_HDR_CH3_OFF_ENABLE |
   1487         GP3_BLT_HDR_CH3_WIDHI_ENABLE |
   1488         GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
   1489 
   1490     WRITE_COMMAND32(GP3_BLT_DST_OFFSET,
   1491                     (dstoffset & 0x3FFFFF) | gp3_pat_origin);
   1492     WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset);
   1493     WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
   1494     WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, ch3_size);
   1495     WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
   1496     WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN |
   1497                     GP3_CH3_REPLACE_SOURCE | GP3_CH3_HST_SRC_ENABLE |
   1498                     gp3_src_format | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT)
   1499                                       << 20));
   1500     WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode);
   1501 
   1502     /* START THE BLT */
   1503 
   1504     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   1505     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   1506     gp3_cmd_current = gp3_cmd_next;
   1507 
   1508     if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE &&
   1509         (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) {
   1510         /* UPDATE THE COMMAND POINTER */
   1511 
   1512         cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
   1513 
   1514         /* CHECK IF A WRAP WILL BE NEEDED */
   1515 
   1516         gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8;
   1517 
   1518         if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
   1519             gp3_cmd_next = gp3_cmd_top;
   1520 
   1521             GP3_WAIT_WRAP(temp);
   1522             WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE |
   1523                             GP3_DATA_LOAD_HDR_WRAP | GP3_DATA_LOAD_HDR_ENABLE);
   1524         }
   1525         else {
   1526             GP3_WAIT_PRIMITIVE(temp);
   1527             WRITE_COMMAND32(0,
   1528                             GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
   1529         }
   1530 
   1531         /* WRITE DWORD COUNT */
   1532 
   1533         WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | (total_dwords * height));
   1534 
   1535         while (height--) {
   1536             /* WRITE DATA */
   1537 
   1538             WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
   1539             WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
   1540                                   srcoffset + (dword_count << 2), byte_count);
   1541 
   1542             srcoffset += pitch;
   1543             cim_cmd_ptr += total_dwords << 2;
   1544         }
   1545 
   1546         WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   1547         gp3_cmd_current = gp3_cmd_next;
   1548     }
   1549     else {
   1550         /* WRITE DATA LINE BY LINE
   1551          * Each line will be created as a separate command buffer entry to
   1552          * allow line-by-line wrapping and to allow simultaneous rendering
   1553          * by the HW.
   1554          */
   1555 
   1556         while (height--) {
   1557             /* UPDATE THE COMMAND POINTER
   1558              * The WRITE_COMMANDXX macros use a pointer to the current buffer
   1559              * space. This is created by adding gp3_cmd_current to the base
   1560              * pointer.
   1561              */
   1562 
   1563             cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
   1564 
   1565             /* CHECK IF A WRAP WILL BE NEEDED */
   1566 
   1567             gp3_cmd_next = gp3_cmd_current + size_dwords;
   1568             if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
   1569                 gp3_cmd_next = gp3_cmd_top;
   1570 
   1571                 /* WAIT FOR HARDWARE */
   1572 
   1573                 GP3_WAIT_WRAP(temp);
   1574                 WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE |
   1575                                 GP3_DATA_LOAD_HDR_WRAP |
   1576                                 GP3_DATA_LOAD_HDR_ENABLE);
   1577             }
   1578             else {
   1579                 /* WAIT FOR AVAILABLE SPACE */
   1580 
   1581                 GP3_WAIT_PRIMITIVE(temp);
   1582                 WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE |
   1583                                 GP3_DATA_LOAD_HDR_ENABLE);
   1584             }
   1585 
   1586             /* WRITE DWORD COUNT */
   1587 
   1588             WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
   1589 
   1590             /* WRITE DATA */
   1591 
   1592             WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
   1593             WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
   1594                                   srcoffset + (dword_count << 2), byte_count);
   1595 
   1596             /* UPDATE POINTERS */
   1597 
   1598             srcoffset += pitch;
   1599             WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   1600             gp3_cmd_current = gp3_cmd_next;
   1601         }
   1602     }
   1603 }
   1604 
   1605 /*---------------------------------------------------------------------------
   1606  * gp_custom_convert_blt
   1607  *
   1608  * This routine is identical to gp_color_convert_blt, except that the macro
   1609  * to write data to the frame buffer has been replaced with a new macro.  This
   1610  * allows a user to implement custom behavior when sending data, such as
   1611  * manually converting 24BPP to 32BPP, converting 2BPP to 4BPP or
   1612  * premultiplying alpha data.
   1613  *-------------------------------------------------------------------------*/
   1614 
   1615 void
   1616 gp_custom_convert_blt(unsigned long dstoffset, unsigned long srcx,
   1617                       unsigned long width, unsigned long height,
   1618                       unsigned char *data, long pitch)
   1619 {
   1620     unsigned long indent, temp;
   1621     unsigned long total_dwords, size_dwords;
   1622     unsigned long dword_count, byte_count;
   1623     unsigned long size = ((width << 16) | height);
   1624     unsigned long ch3_offset, srcoffset;
   1625     unsigned long ch3_size, base;
   1626 
   1627     /* ASSUME BITMAPS ARE DWORD ALIGNED */
   1628     /* We will offset into the source data in DWORD increments.  We  */
   1629     /* set the source index to the remaining byte offset and         */
   1630     /* increment the size of each line to account for the dont-care  */
   1631     /* pixel(s).   For 4BPP source data, we also set the appropriate */
   1632     /* nibble index.                                                 */
   1633 
   1634     /* CALCULATE THE SIZE OF ONE LINE */
   1635 
   1636     if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED) {
   1637         /* HANDLE 24BPP
   1638          * Note that we do not do anything to guarantee that the source data
   1639          * is DWORD aligned.  The logic here is that the source data will be
   1640          * cacheable, in which case Geode LX will not lose any clocks for
   1641          * unaligned moves.  Also note that the channel 3 width is programmed
   1642          * as the number of dwords, while the normal width is programmed as
   1643          * the number of pixels.
   1644          */
   1645 
   1646         srcoffset = srcx * 3;
   1647         ch3_offset = 0;
   1648         temp = width * 3;
   1649         ch3_size = (((temp + 3) >> 2) << 16) | height;
   1650     }
   1651     else {
   1652         ch3_size = size;
   1653 
   1654         if (gp3_src_pix_shift == 3) {
   1655             /* CALCULATE INDENT AND SOURCE OFFSET */
   1656 
   1657             indent = (srcx >> 1);
   1658             srcoffset = (indent & ~3L);
   1659             indent &= 3;
   1660             ch3_offset = indent | ((srcx & 1) << 25);
   1661 
   1662             temp = ((width + (srcx & 1) + 1) >> 1) + indent;
   1663         }
   1664         else {
   1665             indent = (srcx << gp3_src_pix_shift);
   1666             srcoffset = (indent & ~3L);
   1667             indent &= 3;
   1668             ch3_offset = indent;
   1669 
   1670             temp = (width << gp3_src_pix_shift) + indent;
   1671         }
   1672     }
   1673 
   1674     total_dwords = (temp + 3) >> 2;
   1675     size_dwords = (total_dwords << 2) + 8;
   1676     dword_count = (temp >> 2);
   1677     byte_count = (temp & 3);
   1678 
   1679     base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
   1680         (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
   1681 
   1682     /* SET APPROPRIATE ENABLES */
   1683 
   1684     gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE |
   1685         GP3_BLT_HDR_WIDHI_ENABLE |
   1686         GP3_BLT_HDR_CH3_STR_ENABLE |
   1687         GP3_BLT_HDR_CH3_OFF_ENABLE |
   1688         GP3_BLT_HDR_CH3_WIDHI_ENABLE |
   1689         GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
   1690 
   1691     WRITE_COMMAND32(GP3_BLT_DST_OFFSET,
   1692                     (dstoffset & 0x3FFFFF) | gp3_pat_origin);
   1693     WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset);
   1694     WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
   1695     WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, ch3_size);
   1696     WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
   1697     WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN |
   1698                     GP3_CH3_REPLACE_SOURCE | GP3_CH3_HST_SRC_ENABLE |
   1699                     gp3_src_format | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT)
   1700                                       << 20));
   1701     WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode);
   1702 
   1703     /* START THE BLT */
   1704 
   1705     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   1706     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   1707     gp3_cmd_current = gp3_cmd_next;
   1708 
   1709     if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE &&
   1710         (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) {
   1711         /* UPDATE THE COMMAND POINTER */
   1712 
   1713         cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
   1714 
   1715         /* CHECK IF A WRAP WILL BE NEEDED */
   1716 
   1717         gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8;
   1718 
   1719         if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
   1720             gp3_cmd_next = gp3_cmd_top;
   1721 
   1722             GP3_WAIT_WRAP(temp);
   1723             WRITE_COMMAND32(0,
   1724                             GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
   1725                             GP3_DATA_LOAD_HDR_ENABLE);
   1726         }
   1727         else {
   1728             GP3_WAIT_PRIMITIVE(temp);
   1729             WRITE_COMMAND32(0,
   1730                             GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
   1731         }
   1732 
   1733         /* WRITE DWORD COUNT */
   1734 
   1735         WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | (total_dwords * height));
   1736 
   1737         while (height--) {
   1738             /* WRITE DATA */
   1739 
   1740             WRITE_CUSTOM_COMMAND_STRING32(8, data, srcoffset, dword_count);
   1741             WRITE_CUSTOM_COMMAND_STRING8(8 + (dword_count << 2), data,
   1742                                          srcoffset + (dword_count << 2),
   1743                                          byte_count);
   1744 
   1745             srcoffset += pitch;
   1746             cim_cmd_ptr += total_dwords << 2;
   1747         }
   1748 
   1749         WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   1750         gp3_cmd_current = gp3_cmd_next;
   1751     }
   1752     else {
   1753         /* WRITE DATA LINE BY LINE
   1754          * Each line will be created as a separate command buffer entry to
   1755          * allow line-by-line wrapping and to allow simultaneous rendering
   1756          * by the HW.
   1757          */
   1758 
   1759         while (height--) {
   1760             /* UPDATE THE COMMAND POINTER
   1761              * The WRITE_COMMANDXX macros use a pointer to the current buffer
   1762              * space. This is created by adding gp3_cmd_current to the base
   1763              * pointer.
   1764              */
   1765 
   1766             cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
   1767 
   1768             /* CHECK IF A WRAP WILL BE NEEDED */
   1769 
   1770             gp3_cmd_next = gp3_cmd_current + size_dwords;
   1771             if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
   1772                 gp3_cmd_next = gp3_cmd_top;
   1773 
   1774                 /* WAIT FOR HARDWARE */
   1775 
   1776                 GP3_WAIT_WRAP(temp);
   1777                 WRITE_COMMAND32(0,
   1778                                 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP
   1779                                 | GP3_DATA_LOAD_HDR_ENABLE);
   1780             }
   1781             else {
   1782                 /* WAIT FOR AVAILABLE SPACE */
   1783 
   1784                 GP3_WAIT_PRIMITIVE(temp);
   1785                 WRITE_COMMAND32(0,
   1786                                 GP3_DATA_LOAD_HDR_TYPE |
   1787                                 GP3_DATA_LOAD_HDR_ENABLE);
   1788             }
   1789 
   1790             /* WRITE DWORD COUNT */
   1791 
   1792             WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
   1793 
   1794             /* WRITE DATA */
   1795 
   1796             WRITE_CUSTOM_COMMAND_STRING32(8, data, srcoffset, dword_count);
   1797             WRITE_CUSTOM_COMMAND_STRING8(8 + (dword_count << 2), data,
   1798                                          srcoffset + (dword_count << 2),
   1799                                          byte_count);
   1800 
   1801             /* UPDATE POINTERS */
   1802 
   1803             srcoffset += pitch;
   1804             WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   1805             gp3_cmd_current = gp3_cmd_next;
   1806         }
   1807     }
   1808 }
   1809 
   1810 /*---------------------------------------------------------------------------
   1811  * gp_rotate_blt
   1812  *
   1813  * This routine is called to rotate a rectangular area of video memory.  The
   1814  * data may be color converted during the rotation.  'Degrees' must be a
   1815  * multiple of 90 and indicates a clockwise rotation.  Width and height
   1816  * refer to the width and the height of the source.  The output
   1817  * destinations will be equal to the rotated dimensions.
   1818  *-------------------------------------------------------------------------*/
   1819 
   1820 void
   1821 gp_rotate_blt(unsigned long dstoffset, unsigned long srcoffset,
   1822               unsigned long width, unsigned long height, int degrees)
   1823 {
   1824     unsigned long sizein, sizeout;
   1825     unsigned long ch3_flags;
   1826     unsigned long base;
   1827 
   1828     base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
   1829         ((gp3_fb_base << 4) + ((srcoffset & 0xFFC00000) >> 20)) |
   1830         (gp3_base_register & GP3_BASE_OFFSET_SRCMASK);
   1831 
   1832     srcoffset &= 0x3FFFFF;
   1833     dstoffset &= 0x3FFFFF;
   1834 
   1835     /* SET ROTATION PARAMETERS */
   1836 
   1837     switch (degrees) {
   1838     case 90:
   1839         srcoffset += (height - 1) * gp3_src_stride;
   1840         sizein = ((width << 16) | height);
   1841         sizeout = ((height << 16) | width);
   1842         ch3_flags = GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE |
   1843             GP3_CH3_ROTATE_ENABLE | GP3_CH3_NEG_YDIR;
   1844         break;
   1845 
   1846     case 180:
   1847         srcoffset += (height - 1) * gp3_src_stride;
   1848         srcoffset += (width << gp3_src_pix_shift) - 1;
   1849         sizein = sizeout = ((width << 16) | height);
   1850         ch3_flags = GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE |
   1851             GP3_CH3_NEG_YDIR | GP3_CH3_NEG_XDIR;
   1852         break;
   1853 
   1854     case 270:
   1855         srcoffset += (width << gp3_src_pix_shift) - 1;
   1856         sizein = ((width << 16) | height);
   1857         sizeout = ((height << 16) | width);
   1858         ch3_flags = GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE |
   1859             GP3_CH3_ROTATE_ENABLE | GP3_CH3_NEG_XDIR;
   1860         break;
   1861 
   1862     default:
   1863         sizein = sizeout = ((width << 16) | height);
   1864         ch3_flags = GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE;
   1865         break;
   1866     }
   1867 
   1868     /* SET APPROPRIATE ENABLES                           */
   1869     /* We override the raster mode setting with a source */
   1870     /* copy ROP.                                         */
   1871 
   1872     gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE |
   1873         GP3_BLT_HDR_DST_OFF_ENABLE |
   1874         GP3_BLT_HDR_WIDHI_ENABLE |
   1875         GP3_BLT_HDR_CH3_OFF_ENABLE |
   1876         GP3_BLT_HDR_CH3_STR_ENABLE |
   1877         GP3_BLT_HDR_CH3_WIDHI_ENABLE |
   1878         GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
   1879 
   1880     /* WRITE ALL BLT REGISTERS */
   1881 
   1882     WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_bpp | 0xCC);
   1883     WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset);
   1884     WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, sizeout);
   1885     WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, sizein);
   1886     WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, srcoffset);
   1887     WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, ch3_flags | gp3_src_format |
   1888                     ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20) |
   1889                     ((gp3_blt_flags & CIMGP_ENABLE_PREFETCH) << 17) |
   1890                     gp3_src_stride);
   1891     WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
   1892 
   1893     /* START THE BLT */
   1894 
   1895     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   1896     WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode);
   1897     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   1898     gp3_cmd_current = gp3_cmd_next;
   1899 }
   1900 
   1901 /*---------------------------------------------------------------------------
   1902  * gp_mono_bitmap_to_screen_blt
   1903  *
   1904  * This routine expands and BLTs a monchrome bitmap that is stored in system
   1905  * memory into the framebuffer.  'data' points to an array of monochrome data.
   1906  * 'stride' indicates the pitch between successive lines of monochrome data.
   1907  * 'srcx' indicates the x coordinate within each line of blend data
   1908  * corresponding to the first pixel.  A y coordinate for the source is
   1909  * deliberately omitted to avoid extra calculation for simple cases that have
   1910  * no y index.  The calling program must adjust the data pointer accordingly.
   1911  *-------------------------------------------------------------------------*/
   1912 
   1913 void
   1914 gp_mono_bitmap_to_screen_blt(unsigned long dstoffset, unsigned long srcx,
   1915                              unsigned long width, unsigned long height,
   1916                              unsigned char *data, long stride)
   1917 {
   1918     unsigned long indent, temp;
   1919     unsigned long total_dwords, size_dwords;
   1920     unsigned long dword_count, byte_count;
   1921     unsigned long size = ((width << 16) | height);
   1922     unsigned long srcoffset, src_value;
   1923 
   1924     /* ASSUME BITMAPS ARE DWORD ALIGNED */
   1925     /* We will offset into the source data in DWORD increments.  We */
   1926     /* set the source index to the remaining byte offset and        */
   1927     /* increment the size of each line to account for the dont-care */
   1928     /* pixel(s).                                                    */
   1929 
   1930     indent = (srcx >> 3);
   1931     srcoffset = (indent & ~3L);
   1932     indent &= 3;
   1933     src_value = (indent | ((srcx & 7) << 26));
   1934 
   1935     /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS                */
   1936     /* We assume that a color pattern is being ROPed with source  */
   1937     /* data if the pattern type is color and the preserve pattern */
   1938     /* was set.                                                   */
   1939 
   1940     gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
   1941         GP3_BLT_HDR_DST_OFF_ENABLE |
   1942         GP3_BLT_HDR_WIDHI_ENABLE |
   1943         GP3_BLT_HDR_CH3_STR_ENABLE |
   1944         GP3_BLT_HDR_BASE_OFFSET_ENABLE |
   1945         GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
   1946 
   1947     if (gp3_ch3_pat) {
   1948         gp3_cmd_header |=
   1949             GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE;
   1950 
   1951         WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin);
   1952         WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
   1953         WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format);
   1954         WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size);
   1955     }
   1956     else {
   1957         WRITE_COMMAND32(GP3_BLT_DST_OFFSET,
   1958                         ((dstoffset & 0x3FFFFF) | gp3_pat_origin));
   1959         WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0);
   1960     }
   1961     if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO) {
   1962         WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
   1963                         gp3_raster_mode | GP3_RM_SOURCE_INVERT);
   1964     }
   1965     else {
   1966         WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
   1967                         gp3_raster_mode & ~GP3_RM_SOURCE_INVERT);
   1968     }
   1969     WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, src_value);
   1970     WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
   1971     WRITE_COMMAND32(GP3_BLT_BASE_OFFSET,
   1972                     ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)));
   1973     WRITE_COMMAND32(GP3_BLT_MODE,
   1974                     gp3_blt_mode | GP3_BM_SRC_HOST | GP3_BM_SRC_MONO);
   1975 
   1976     /* START THE BLT */
   1977 
   1978     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   1979     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   1980     gp3_cmd_current = gp3_cmd_next;
   1981 
   1982     /* CALCULATE THE SIZE OF ONE LINE */
   1983 
   1984     size = ((width + (srcx & 7) + 7) >> 3) + indent;
   1985     total_dwords = (size + 3) >> 2;
   1986     size_dwords = (total_dwords << 2) + 8;
   1987     dword_count = (size >> 2);
   1988     byte_count = (size & 3);
   1989 
   1990     /* CHECK FOR SMALL BLT CASE */
   1991     /* If the total amount of monochrome data is less than 50K and we have */
   1992     /* room in the command buffer, we will do all data writes in a single  */
   1993     /* data packet.                                                        */
   1994 
   1995     if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE &&
   1996         (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) {
   1997         /* UPDATE THE COMMAND POINTER */
   1998 
   1999         cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
   2000 
   2001         /* CHECK IF A WRAP WILL BE NEEDED */
   2002 
   2003         gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8;
   2004 
   2005         if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
   2006             gp3_cmd_next = gp3_cmd_top;
   2007 
   2008             GP3_WAIT_WRAP(temp);
   2009             WRITE_COMMAND32(0,
   2010                             GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
   2011                             GP3_DATA_LOAD_HDR_ENABLE);
   2012         }
   2013         else {
   2014             GP3_WAIT_PRIMITIVE(temp);
   2015             WRITE_COMMAND32(0,
   2016                             GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
   2017         }
   2018 
   2019         /* WRITE DWORD COUNT */
   2020 
   2021         WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | (total_dwords * height));
   2022 
   2023         while (height--) {
   2024             /* WRITE DATA */
   2025 
   2026             WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
   2027             WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
   2028                                   srcoffset + (dword_count << 2), byte_count);
   2029 
   2030             srcoffset += stride;
   2031             cim_cmd_ptr += total_dwords << 2;
   2032         }
   2033 
   2034         WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2035         gp3_cmd_current = gp3_cmd_next;
   2036     }
   2037     else {
   2038         /* WRITE DATA LINE BY LINE
   2039          * Each line will be created as a separate command buffer entry to
   2040          * allow line-by-line wrapping and to allow simultaneous rendering
   2041          * by the HW.
   2042          */
   2043 
   2044         while (height--) {
   2045             /* UPDATE THE COMMAND POINTER
   2046              * The WRITE_COMMANDXX macros use a pointer to the current buffer
   2047              * space.  This is created by adding gp3_cmd_current to the base
   2048              * pointer.
   2049              */
   2050 
   2051             cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
   2052 
   2053             /* CHECK IF A WRAP WILL BE NEEDED */
   2054 
   2055             gp3_cmd_next = gp3_cmd_current + size_dwords;
   2056             if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
   2057                 gp3_cmd_next = gp3_cmd_top;
   2058 
   2059                 /* WAIT FOR HARDWARE */
   2060 
   2061                 GP3_WAIT_WRAP(temp);
   2062                 WRITE_COMMAND32(0,
   2063                                 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP
   2064                                 | GP3_DATA_LOAD_HDR_ENABLE);
   2065             }
   2066             else {
   2067                 /* WAIT FOR AVAILABLE SPACE */
   2068 
   2069                 GP3_WAIT_PRIMITIVE(temp);
   2070                 WRITE_COMMAND32(0,
   2071                                 GP3_DATA_LOAD_HDR_TYPE |
   2072                                 GP3_DATA_LOAD_HDR_ENABLE);
   2073             }
   2074 
   2075             /* WRITE DWORD COUNT */
   2076 
   2077             WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | total_dwords);
   2078 
   2079             /* WRITE DATA */
   2080 
   2081             WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
   2082             WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
   2083                                   srcoffset + (dword_count << 2), byte_count);
   2084 
   2085             /* UPDATE POINTERS */
   2086 
   2087             srcoffset += stride;
   2088             WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2089             gp3_cmd_current = gp3_cmd_next;
   2090         }
   2091     }
   2092 }
   2093 
   2094 /*---------------------------------------------------------------------------
   2095  * gp_text_blt
   2096  *
   2097  * This routine expands and BLTs byte-packed monochrome data to the screen.
   2098  * There is assumed to be no x clipping involved in the BLT.
   2099  *-------------------------------------------------------------------------*/
   2100 
   2101 void
   2102 gp_text_blt(unsigned long dstoffset, unsigned long width,
   2103             unsigned long height, unsigned char *data)
   2104 {
   2105     unsigned long temp, dwords_total;
   2106     unsigned long dword_count, byte_count;
   2107     unsigned long size = ((width << 16) | height);
   2108     unsigned long srcoffset = 0;
   2109 
   2110     /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS                */
   2111     /* We assume that a color pattern is being ROPed with source  */
   2112     /* data if the pattern type is color and the preserve pattern */
   2113     /* was set.                                                   */
   2114 
   2115     gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
   2116         GP3_BLT_HDR_DST_OFF_ENABLE |
   2117         GP3_BLT_HDR_WIDHI_ENABLE |
   2118         GP3_BLT_HDR_CH3_STR_ENABLE |
   2119         GP3_BLT_HDR_BASE_OFFSET_ENABLE |
   2120         GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
   2121 
   2122     if (gp3_ch3_pat) {
   2123         gp3_cmd_header |=
   2124             GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE;
   2125 
   2126         WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin);
   2127         WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
   2128         WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format);
   2129         WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size);
   2130     }
   2131     else {
   2132         WRITE_COMMAND32(GP3_BLT_DST_OFFSET,
   2133                         ((dstoffset & 0x3FFFFF) | gp3_pat_origin));
   2134         WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0);
   2135     }
   2136     if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO) {
   2137         WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
   2138                         gp3_raster_mode | GP3_RM_SOURCE_INVERT);
   2139     }
   2140     else {
   2141         WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
   2142                         gp3_raster_mode & ~GP3_RM_SOURCE_INVERT);
   2143     }
   2144 
   2145     WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, 0);
   2146     WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
   2147     WRITE_COMMAND32(GP3_BLT_BASE_OFFSET,
   2148                     ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)));
   2149     WRITE_COMMAND32(GP3_BLT_MODE,
   2150                     gp3_blt_mode | GP3_BM_SRC_HOST | GP3_BM_SRC_BP_MONO);
   2151 
   2152     /* START THE BLT */
   2153 
   2154     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   2155     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2156     gp3_cmd_current = gp3_cmd_next;
   2157 
   2158     /* CALCULATE THE TOTAL NUMBER OF BYTES */
   2159 
   2160     size = ((width + 7) >> 3) * height;
   2161 
   2162     /* WRITE ALL DATA IN CHUNKS */
   2163 
   2164     do {
   2165         /* UPDATE THE COMMAND POINTER */
   2166 
   2167         cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
   2168 
   2169         if (size > 8192) {
   2170             dword_count = 2048;
   2171             byte_count = 0;
   2172             dwords_total = 2048;
   2173             size -= 8192;
   2174         }
   2175         else {
   2176             dword_count = (size >> 2);
   2177             byte_count = (size & 3);
   2178             dwords_total = (size + 3) >> 2;
   2179             size = 0;
   2180         }
   2181         gp3_cmd_next = gp3_cmd_current + (dwords_total << 2) + 8;
   2182 
   2183         /* CHECK IF A WRAP WILL BE NEEDED */
   2184 
   2185         if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
   2186             gp3_cmd_next = gp3_cmd_top;
   2187 
   2188             /* WAIT FOR HARDWARE */
   2189 
   2190             GP3_WAIT_WRAP(temp);
   2191             WRITE_COMMAND32(0,
   2192                             GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
   2193                             GP3_DATA_LOAD_HDR_ENABLE);
   2194         }
   2195         else {
   2196             /* WAIT FOR AVAILABLE SPACE */
   2197 
   2198             GP3_WAIT_PRIMITIVE(temp);
   2199             WRITE_COMMAND32(0,
   2200                             GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
   2201         }
   2202 
   2203         /* WRITE DWORD COUNT */
   2204 
   2205         WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | dwords_total);
   2206 
   2207         /* WRITE DATA */
   2208 
   2209         WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
   2210         WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
   2211                               srcoffset + (dword_count << 2), byte_count);
   2212 
   2213         WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2214         gp3_cmd_current = gp3_cmd_next;
   2215 
   2216         /* UPDATE THE SOURCE OFFSET */
   2217         /* We add a constant value because the code will loop only if the */
   2218         /* data exceeds 8192 bytes.                                       */
   2219 
   2220         srcoffset += 8192;
   2221 
   2222     } while (size);
   2223 }
   2224 
   2225 /*---------------------------------------------------------------------------
   2226  * gp_mono_expand_blt
   2227  *
   2228  * This routine expands monochrome data that is stored in video memory into
   2229  * the current BPP.  The source and destination regions are assumed not to
   2230  * overlap.  The pitch of the source data is specified in gp_set_strides.
   2231  * 'srcy' is deliberately omitted to prevent extra calculations for simple
   2232  * applications that have no source indexes.
   2233  *-------------------------------------------------------------------------*/
   2234 
   2235 void
   2236 gp_mono_expand_blt(unsigned long dstoffset, unsigned long srcoffset,
   2237                    unsigned long srcx, unsigned long width,
   2238                    unsigned long height, int byte_packed)
   2239 {
   2240     unsigned long base;
   2241     unsigned long blt_mode;
   2242     unsigned long size = ((width << 16) | height);
   2243 
   2244     /* ADJUST SOURCE OFFSET */
   2245 
   2246     srcoffset += (srcx >> 3);
   2247     srcx &= 7;
   2248 
   2249     /* CALCULATE BASE OFFSET REGISTER */
   2250 
   2251     base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
   2252         ((gp3_fb_base << 14) + ((srcoffset & 0xFFC00000) >> 10)) |
   2253         (gp3_base_register & GP3_BASE_OFFSET_CH3MASK);
   2254 
   2255     /* SET THE SOURCE TYPE */
   2256 
   2257     if (byte_packed)
   2258         blt_mode = gp3_blt_mode | GP3_BM_SRC_FB | GP3_BM_SRC_BP_MONO;
   2259     else
   2260         blt_mode = gp3_blt_mode | GP3_BM_SRC_FB | GP3_BM_SRC_MONO;
   2261 
   2262     /* SET HEADER ENABLES */
   2263 
   2264     gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
   2265         GP3_BLT_HDR_DST_OFF_ENABLE |
   2266         GP3_BLT_HDR_WIDHI_ENABLE |
   2267         GP3_BLT_HDR_CH3_STR_ENABLE |
   2268         GP3_BLT_HDR_BASE_OFFSET_ENABLE |
   2269         GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
   2270 
   2271     /* ENABLE COLOR PATTERN IF APPLICABLE */
   2272 
   2273     if (gp3_ch3_pat) {
   2274         gp3_cmd_header |=
   2275             GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE;
   2276 
   2277         WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin);
   2278         WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
   2279         WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format);
   2280         WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size);
   2281     }
   2282     else {
   2283         WRITE_COMMAND32(GP3_BLT_DST_OFFSET,
   2284                         ((dstoffset & 0x3FFFFF) | gp3_pat_origin));
   2285         WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0);
   2286     }
   2287     if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO) {
   2288         WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
   2289                         gp3_raster_mode | GP3_RM_SOURCE_INVERT);
   2290     }
   2291     else {
   2292         WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
   2293                         gp3_raster_mode & ~GP3_RM_SOURCE_INVERT);
   2294     }
   2295 
   2296     WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
   2297     WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, (srcoffset & 0x3FFFFF) | (srcx << 26));
   2298     WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
   2299 
   2300     /* WORKAROUND FOR SIBZ #3744
   2301      * Under extremely rare conditions, very narrow byte-packed mono BLTs
   2302      * can hang the GP.  Even under the rare case, the bad condition will
   2303      * only happen once every 16 lines.  The workaround is to break the
   2304      * offending BLT into a series of safer BLTs.  This method is preferred
   2305      * over a two-pass approach because it does not require saving and
   2306      * restoring any GP state, such as the ROP or mono colors.
   2307      */
   2308 
   2309     if ((gp3_blt_mode & GP3_BM_DST_REQ) && byte_packed && (gp3_pix_shift < 2)
   2310         && (width < 5) && ((srcoffset & 0x1F) == 0x1F)
   2311         && ((srcx + width) > 8)) {
   2312         unsigned long dstoff1, size1, org1;
   2313         unsigned long dstoff2, size2, org2;
   2314         unsigned long tempheight;
   2315 
   2316         size1 = ((8 - srcx) << 16) | 1;
   2317         size2 = ((width + srcx - 8) << 16) | 1;
   2318         org1 = gp3_pat_origin;
   2319         org2 = (org1 & 0xE0000000) | ((org1 + ((8 - srcx) << 26)) & 0x1C000000);
   2320         dstoff1 = dstoffset & 0x3FFFFF;
   2321         dstoff2 = (dstoff1 + 8 - srcx) << gp3_pix_shift;
   2322 
   2323         while (height) {
   2324             /* DIVIDE THE FIRST LINE INTO TWO SINGLE LINE BLTS */
   2325 
   2326             WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size1);
   2327             WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size1);
   2328             WRITE_COMMAND32(GP3_BLT_SRC_OFFSET,
   2329                             (srcoffset & 0x3FFFFF) | (srcx << 26));
   2330             WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoff1 | org1);
   2331             WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, org1);
   2332             WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   2333             WRITE_COMMAND32(GP3_BLT_MODE, blt_mode);
   2334             WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2335             gp3_cmd_current = gp3_cmd_next;
   2336             gp_wait_until_idle();
   2337 
   2338             gp_declare_blt(gp3_blt_flags);
   2339             gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
   2340                 GP3_BLT_HDR_DST_OFF_ENABLE |
   2341                 GP3_BLT_HDR_WIDHI_ENABLE |
   2342                 GP3_BLT_HDR_BLT_MODE_ENABLE |
   2343                 GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE;
   2344             WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size2);
   2345             WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size2);
   2346             WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, ((srcoffset + 1) & 0x3FFFFF));
   2347             WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoff2 | org2);
   2348             WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, org2);
   2349             WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   2350             WRITE_COMMAND32(GP3_BLT_MODE, blt_mode);
   2351             WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2352             gp3_cmd_current = gp3_cmd_next;
   2353             gp_wait_until_idle();
   2354 
   2355             if (--height) {
   2356                 org1 += 0x20000000;
   2357                 org2 += 0x20000000;
   2358                 dstoff1 += gp3_dst_stride;
   2359                 dstoff2 += gp3_dst_stride;
   2360                 srcoffset += 2;
   2361 
   2362                 /* THE NEXT 15 LINES ARE NOW 'SAFE' - THEY DO NOT SHOW THE
   2363                  * PROBLEM */
   2364 
   2365                 tempheight = 15;
   2366                 if (tempheight > height)
   2367                     tempheight = height;
   2368 
   2369                 gp_declare_blt(gp3_blt_flags);
   2370                 gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
   2371                     GP3_BLT_HDR_DST_OFF_ENABLE |
   2372                     GP3_BLT_HDR_WIDHI_ENABLE |
   2373                     GP3_BLT_HDR_BLT_MODE_ENABLE |
   2374                     GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE;
   2375                 WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (width << 16) | tempheight);
   2376                 WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (width << 16) | tempheight);
   2377                 WRITE_COMMAND32(GP3_BLT_SRC_OFFSET,
   2378                                 (srcoffset & 0x3FFFFF) | (srcx << 26));
   2379                 WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoff1 | org1);
   2380                 WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, org1);
   2381                 WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   2382                 WRITE_COMMAND32(GP3_BLT_MODE, blt_mode);
   2383                 WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2384                 gp3_cmd_current = gp3_cmd_next;
   2385                 gp_wait_until_idle();
   2386 
   2387                 height -= tempheight;
   2388 
   2389                 if (height) {
   2390                     gp_declare_blt(gp3_blt_flags);
   2391                     gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
   2392                         GP3_BLT_HDR_DST_OFF_ENABLE |
   2393                         GP3_BLT_HDR_WIDHI_ENABLE |
   2394                         GP3_BLT_HDR_BLT_MODE_ENABLE |
   2395                         GP3_BLT_HDR_CH3_OFF_ENABLE |
   2396                         GP3_BLT_HDR_CH3_WIDHI_ENABLE;
   2397 
   2398                     /* ADJUST ORIGIN */
   2399                     /* If we get here, we added a full 15 lines which is
   2400                      * equivalent to subtracting one from the pattern y origin
   2401                      * (adding 15). */
   2402 
   2403                     org1 -= 0x20000000;
   2404                     org2 -= 0x20000000;
   2405                     dstoff1 += (gp3_dst_stride * 15);
   2406                     dstoff2 += (gp3_dst_stride * 15);
   2407                     srcoffset += 30;
   2408                 }
   2409             }
   2410         }
   2411         return;
   2412     }
   2413 
   2414     /* START THE BLT */
   2415 
   2416     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   2417     WRITE_COMMAND32(GP3_BLT_MODE, blt_mode);
   2418     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2419     gp3_cmd_current = gp3_cmd_next;
   2420 }
   2421 
   2422 /*---------------------------------------------------------------------------
   2423  * gp_antialiased_text
   2424  *
   2425  * This routine implements alpha blending between a constant source color and
   2426  * a destination region.  The degree of the blend is controlled by an array
   2427  * of 4BPP/8BPP values specified in 'data'.  'stride' indicates the pitch
   2428  * between successive lines of blend data.  'srcx' indicates the x
   2429  * coordinate within each line of blend data corresponding to the first
   2430  * pixel.  A y coordinate for the source is deliberately omitted to avoid
   2431  * extra calculation for simple cases that have no y index.  The calling
   2432  * program must adjust the data pointer accordingly.  'fourbpp' selects
   2433  * between 4BPP and 8BPP alpha.
   2434  *-------------------------------------------------------------------------*/
   2435 
   2436 void
   2437 gp_antialiased_text(unsigned long dstoffset, unsigned long srcx,
   2438                     unsigned long width, unsigned long height,
   2439                     unsigned char *data, long stride, int fourbpp)
   2440 {
   2441     unsigned long indent, temp;
   2442     unsigned long total_dwords, size_dwords;
   2443     unsigned long dword_count, byte_count;
   2444     unsigned long size = ((width << 16) | height);
   2445     unsigned long ch3_offset, srcoffset;
   2446     unsigned long base, depth_flag;
   2447 
   2448     base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
   2449         (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
   2450 
   2451     /* ENABLE ALL RELEVANT REGISTERS */
   2452     /* We override the raster mode register to force the */
   2453     /* correct alpha blend                               */
   2454 
   2455     gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE |
   2456         GP3_BLT_HDR_DST_OFF_ENABLE |
   2457         GP3_BLT_HDR_WIDHI_ENABLE |
   2458         GP3_BLT_HDR_CH3_OFF_ENABLE |
   2459         GP3_BLT_HDR_CH3_STR_ENABLE |
   2460         GP3_BLT_HDR_CH3_WIDHI_ENABLE |
   2461         GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
   2462 
   2463     /* CALCULATIONS BASED ON ALPHA DEPTH */
   2464     /* Although most antialiased text is 4BPP, the hardware supports */
   2465     /* a full 8BPP.  Either case is supported by this routine.       */
   2466 
   2467     if (fourbpp) {
   2468         depth_flag = GP3_CH3_SRC_4BPP_ALPHA;
   2469         indent = (srcx >> 1);
   2470         srcoffset = (indent & ~3L);
   2471         indent &= 3;
   2472         ch3_offset = indent | ((srcx & 1) << 25);
   2473 
   2474         temp = ((width + (srcx & 1) + 1) >> 1) + indent;
   2475     }
   2476     else {
   2477         depth_flag = GP3_CH3_SRC_8BPP_ALPHA;
   2478         indent = srcx;
   2479         srcoffset = (indent & ~3L);
   2480         indent &= 3;
   2481         ch3_offset = indent;
   2482 
   2483         temp = width + indent;
   2484     }
   2485 
   2486     total_dwords = (temp + 3) >> 2;
   2487     size_dwords = (total_dwords << 2) + 8;
   2488     dword_count = (temp >> 2);
   2489     byte_count = (temp & 3);
   2490 
   2491     /* SET RASTER MODE REGISTER */
   2492     /* Alpha blending will only apply to RGB when no alpha component is present. */
   2493     /* As 8BPP is not supported for this routine, the only alpha-less mode is    */
   2494     /* 5:6:5.                                                                    */
   2495 
   2496     if (gp3_bpp == GP3_RM_BPPFMT_565) {
   2497         WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
   2498                         gp3_bpp |
   2499                         GP3_RM_ALPHA_TO_RGB |
   2500                         GP3_RM_ALPHA_A_PLUS_BETA_B |
   2501                         GP3_RM_SELECT_ALPHA_CHAN_3);
   2502     }
   2503     else {
   2504         WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
   2505                         gp3_bpp |
   2506                         GP3_RM_ALPHA_ALL |
   2507                         GP3_RM_ALPHA_A_PLUS_BETA_B |
   2508                         GP3_RM_SELECT_ALPHA_CHAN_3);
   2509     }
   2510 
   2511     /* WRITE ALL REMAINING REGISTERS */
   2512 
   2513     WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
   2514     WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset);
   2515     WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
   2516     WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size);
   2517     WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
   2518     WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN |
   2519                     GP3_CH3_HST_SRC_ENABLE |
   2520                     depth_flag | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) <<
   2521                                   20));
   2522     WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode | GP3_BM_DST_REQ);
   2523 
   2524     /* START THE BLT */
   2525 
   2526     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   2527     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2528     gp3_cmd_current = gp3_cmd_next;
   2529 
   2530     /* WRITE DATA LINE BY LINE
   2531      * Each line will be created as a separate command buffer entry to allow
   2532      * line-by-line wrapping and to allow simultaneous rendering by the HW.
   2533      */
   2534 
   2535     if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE &&
   2536         (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) {
   2537         /* UPDATE THE COMMAND POINTER */
   2538 
   2539         cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
   2540 
   2541         /* CHECK IF A WRAP WILL BE NEEDED */
   2542 
   2543         gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8;
   2544 
   2545         if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
   2546             gp3_cmd_next = gp3_cmd_top;
   2547 
   2548             GP3_WAIT_WRAP(temp);
   2549             WRITE_COMMAND32(0,
   2550                             GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
   2551                             GP3_DATA_LOAD_HDR_ENABLE);
   2552         }
   2553         else {
   2554             GP3_WAIT_PRIMITIVE(temp);
   2555             WRITE_COMMAND32(0,
   2556                             GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
   2557         }
   2558 
   2559         /* WRITE DWORD COUNT */
   2560 
   2561         WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | (total_dwords * height));
   2562 
   2563         while (height--) {
   2564             /* WRITE DATA */
   2565 
   2566             WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
   2567             WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
   2568                                   srcoffset + (dword_count << 2), byte_count);
   2569 
   2570             srcoffset += stride;
   2571             cim_cmd_ptr += total_dwords << 2;
   2572         }
   2573 
   2574         WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2575         gp3_cmd_current = gp3_cmd_next;
   2576     }
   2577     else {
   2578         while (height--) {
   2579             /* UPDATE THE COMMAND POINTER
   2580              * The WRITE_COMMANDXX macros use a pointer to the current buffer
   2581              * space.  This is created by adding gp3_cmd_current to the base
   2582              * pointer.
   2583              */
   2584 
   2585             cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
   2586 
   2587             /* CHECK IF A WRAP WILL BE NEEDED */
   2588 
   2589             gp3_cmd_next = gp3_cmd_current + size_dwords;
   2590             if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
   2591                 gp3_cmd_next = gp3_cmd_top;
   2592 
   2593                 /* WAIT FOR HARDWARE */
   2594 
   2595                 GP3_WAIT_WRAP(temp);
   2596                 WRITE_COMMAND32(0,
   2597                                 GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP
   2598                                 | GP3_DATA_LOAD_HDR_ENABLE);
   2599             }
   2600             else {
   2601                 /* WAIT FOR AVAILABLE SPACE */
   2602 
   2603                 GP3_WAIT_PRIMITIVE(temp);
   2604                 WRITE_COMMAND32(0,
   2605                                 GP3_DATA_LOAD_HDR_TYPE |
   2606                                 GP3_DATA_LOAD_HDR_ENABLE);
   2607             }
   2608 
   2609             /* WRITE DWORD COUNT */
   2610 
   2611             WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
   2612 
   2613             /* WRITE DATA */
   2614 
   2615             WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
   2616             WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
   2617                                   srcoffset + (dword_count << 2), byte_count);
   2618 
   2619             /* UPDATE POINTERS */
   2620 
   2621             srcoffset += stride;
   2622             WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2623             gp3_cmd_current = gp3_cmd_next;
   2624         }
   2625     }
   2626 }
   2627 
   2628 /*---------------------------------------------------------------------------
   2629  * gp_masked_blt
   2630  *
   2631  * This routine copies source data to the screen.  A monochrome mask is used
   2632  * to specify source transparency.
   2633  *-------------------------------------------------------------------------*/
   2634 
   2635 void
   2636 gp_masked_blt(unsigned long dstoffset, unsigned long width,
   2637               unsigned long height, unsigned long mono_srcx,
   2638               unsigned long color_srcx, unsigned char *mono_mask,
   2639               unsigned char *color_data, long mono_pitch, long color_pitch)
   2640 {
   2641     unsigned long indent, temp;
   2642     unsigned long total_dwords, size_dwords;
   2643     unsigned long dword_count, byte_count;
   2644     unsigned long srcoffset, size;
   2645     unsigned long i, ch3_offset, base;
   2646     unsigned long flags = 0;
   2647 
   2648     if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO)
   2649         flags = GP3_RM_SOURCE_INVERT;
   2650 
   2651     /* MONO CALCULATIONS */
   2652 
   2653     indent = (mono_srcx >> 3);
   2654     srcoffset = (indent & ~3L);
   2655     indent &= 3;
   2656 
   2657     size = ((width + (mono_srcx & 7) + 7) >> 3) + indent;
   2658     total_dwords = (size + 3) >> 2;
   2659     size_dwords = (total_dwords << 2) + 8;
   2660     dword_count = (size >> 2);
   2661     byte_count = (size & 3);
   2662 
   2663     base = ((gp3_fb_base << 24) + (gp3_scratch_base & 0xFFC00000)) |
   2664         (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
   2665 
   2666     gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE |
   2667         GP3_BLT_HDR_STRIDE_ENABLE | GP3_BLT_HDR_DST_OFF_ENABLE |
   2668         GP3_BLT_HDR_WIDHI_ENABLE | GP3_BLT_HDR_CH3_STR_ENABLE |
   2669         GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE |
   2670         GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
   2671 
   2672     WRITE_COMMAND32(GP3_BLT_RASTER_MODE, GP3_RM_BPPFMT_8888 | 0xCC);
   2673     WRITE_COMMAND32(GP3_BLT_STRIDE, (total_dwords << 2));
   2674     WRITE_COMMAND32(GP3_BLT_DST_OFFSET, gp3_scratch_base & 0x3FFFFF);
   2675     WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (total_dwords << 16) | height);
   2676     WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (total_dwords << 16) | height);
   2677     WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, 0);
   2678     WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
   2679     WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN |
   2680                     GP3_CH3_REPLACE_SOURCE | GP3_CH3_HST_SRC_ENABLE |
   2681                     GP3_CH3_SRC_8_8_8_8 |
   2682                     ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20));
   2683     WRITE_COMMAND32(GP3_BLT_MODE, 0);
   2684     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   2685 
   2686     /* START THE BLT */
   2687 
   2688     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2689     gp3_cmd_current = gp3_cmd_next;
   2690 
   2691     for (i = 0; i < height; i++) {
   2692         /* UPDATE THE COMMAND POINTER
   2693          * The WRITE_COMMANDXX macros use a pointer to the current buffer
   2694          * space.  This is created by adding gp3_cmd_current to the base
   2695          * pointer.
   2696          */
   2697 
   2698         cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
   2699 
   2700         /* CHECK IF A WRAP WILL BE NEEDED */
   2701 
   2702         gp3_cmd_next = gp3_cmd_current + size_dwords;
   2703         if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
   2704             gp3_cmd_next = gp3_cmd_top;
   2705 
   2706             /* WAIT FOR HARDWARE */
   2707 
   2708             GP3_WAIT_WRAP(temp);
   2709             WRITE_COMMAND32(0,
   2710                             GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
   2711                             GP3_DATA_LOAD_HDR_ENABLE);
   2712         }
   2713         else {
   2714             /* WAIT FOR AVAILABLE SPACE */
   2715 
   2716             GP3_WAIT_PRIMITIVE(temp);
   2717             WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE |
   2718                             GP3_DATA_LOAD_HDR_ENABLE);
   2719         }
   2720 
   2721         /* WRITE DWORD COUNT */
   2722 
   2723         WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
   2724 
   2725         /* WRITE DATA */
   2726 
   2727         WRITE_COMMAND_STRING32(8, mono_mask, srcoffset, dword_count);
   2728         WRITE_COMMAND_STRING8(8 + (dword_count << 2), mono_mask,
   2729                               srcoffset + (dword_count << 2), byte_count);
   2730 
   2731         /* UPDATE POINTERS */
   2732 
   2733         srcoffset += mono_pitch;
   2734         WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2735         gp3_cmd_current = gp3_cmd_next;
   2736     }
   2737 
   2738     /* SECOND BLT */
   2739 
   2740     gp_declare_blt(gp3_blt_flags | CIMGP_BLTFLAGS_HAZARD);
   2741 
   2742     base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
   2743         ((gp3_fb_base << 14) + (((gp3_scratch_base +
   2744                                   indent) & 0xFFC00000) >> 10)) |
   2745         (gp3_base_register & GP3_BASE_OFFSET_CH3MASK);
   2746 
   2747     gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE |
   2748         GP3_BLT_HDR_STRIDE_ENABLE | GP3_BLT_HDR_DST_OFF_ENABLE |
   2749         GP3_BLT_HDR_SRC_OFF_ENABLE | GP3_BLT_HDR_WIDHI_ENABLE |
   2750         GP3_BLT_HDR_CH3_STR_ENABLE |
   2751         GP3_BLT_HDR_CH3_WIDHI_ENABLE |
   2752         GP3_BLT_HDR_BASE_OFFSET_ENABLE |
   2753         GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
   2754 
   2755     /* ENABLE TRANSPARENCY AND PATTERN COPY ROP
   2756      * The monochrome data is used as a mask but is otherwise not involved in
   2757      * the BLT.  The color data is routed through the pattern channel.
   2758      */
   2759 
   2760     WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
   2761                     gp3_bpp | 0xF0 | GP3_RM_SRC_TRANS | flags);
   2762     WRITE_COMMAND32(GP3_BLT_STRIDE, (total_dwords << 18) | gp3_dst_stride);
   2763     WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset & 0x3FFFFF);
   2764     WRITE_COMMAND32(GP3_BLT_SRC_OFFSET,
   2765                     ((gp3_scratch_base +
   2766                       indent) & 0x3FFFFF) | ((mono_srcx & 7) << 26));
   2767     WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (width << 16) | height);
   2768     WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (width << 16) | height);
   2769     WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
   2770 
   2771     /* PROGRAM PARAMETERS FOR COLOR SOURCE DATA        */
   2772     /* Data may be color converted along the way.      */
   2773 
   2774     if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED) {
   2775         srcoffset = color_srcx * 3;
   2776         ch3_offset = 0;
   2777         size = width * 3;
   2778 
   2779         WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (((size + 3) >> 2) << 16) | height);
   2780     }
   2781     else if (gp3_src_pix_shift == 3) {
   2782         /* CALCULATE INDENT AND SOURCE OFFSET */
   2783 
   2784         indent = (color_srcx >> 1);
   2785         srcoffset = (indent & ~3L);
   2786         indent &= 3;
   2787         ch3_offset = indent | ((color_srcx & 1) << 25);
   2788 
   2789         size = ((width + (color_srcx & 1) + 1) >> 1) + indent;
   2790     }
   2791     else {
   2792         indent = (color_srcx << gp3_src_pix_shift);
   2793         srcoffset = (indent & ~3L);
   2794         indent &= 3;
   2795         ch3_offset = indent;
   2796 
   2797         size = (width << gp3_src_pix_shift) + indent;
   2798     }
   2799 
   2800     total_dwords = (size + 3) >> 2;
   2801     size_dwords = (total_dwords << 2) + 8;
   2802     dword_count = (size >> 2);
   2803     byte_count = (size & 3);
   2804 
   2805     WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset);
   2806     WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN |
   2807                     GP3_CH3_HST_SRC_ENABLE |
   2808                     gp3_src_format | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT)
   2809                                       << 20));
   2810     WRITE_COMMAND32(GP3_BLT_MODE,
   2811                     gp3_blt_mode | GP3_BM_SRC_MONO | GP3_BM_SRC_FB);
   2812 
   2813     /* START THE BLT */
   2814 
   2815     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   2816     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2817     gp3_cmd_current = gp3_cmd_next;
   2818 
   2819     /* WRITE DATA LINE BY LINE */
   2820 
   2821     while (height--) {
   2822         /* UPDATE THE COMMAND POINTER */
   2823 
   2824         cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
   2825 
   2826         /* CHECK IF A WRAP WILL BE NEEDED */
   2827 
   2828         gp3_cmd_next = gp3_cmd_current + size_dwords;
   2829         if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
   2830             gp3_cmd_next = gp3_cmd_top;
   2831 
   2832             GP3_WAIT_WRAP(temp);
   2833             WRITE_COMMAND32(0,
   2834                             GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
   2835                             GP3_DATA_LOAD_HDR_ENABLE);
   2836         }
   2837         else {
   2838             GP3_WAIT_PRIMITIVE(temp);
   2839             WRITE_COMMAND32(0,
   2840                             GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
   2841         }
   2842 
   2843         /* WRITE DWORD COUNT */
   2844 
   2845         WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
   2846 
   2847         /* WRITE COLOR DATA TO THE COMMAND BUFFER */
   2848 
   2849         WRITE_COMMAND_STRING32(8, color_data, srcoffset, dword_count);
   2850         WRITE_COMMAND_STRING8(8 + (dword_count << 2), color_data,
   2851                               srcoffset + (dword_count << 2), byte_count);
   2852 
   2853         /* UPDATE COMMAND BUFFER POINTERS */
   2854         /* We do this before writing the monochrome data because otherwise */
   2855         /* the GP could throttle the writes to the host source register    */
   2856         /* waiting for color data.  If the command buffer has not been     */
   2857         /* updated to load the color data...                               */
   2858 
   2859         srcoffset += color_pitch;
   2860         WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2861         gp3_cmd_current = gp3_cmd_next;
   2862     }
   2863 }
   2864 
   2865 /*---------------------------------------------------------------------------
   2866  * gp_screen_to_screen_masked
   2867  *
   2868  * This routine performs a screen to screen BLT, using a monochrome mask to
   2869  * specify source transparency.  The source data is assumed to be in the
   2870  * current destination format and to not overlap the destination.
   2871  *-------------------------------------------------------------------------*/
   2872 
   2873 void
   2874 gp_screen_to_screen_masked(unsigned long dstoffset, unsigned long srcoffset,
   2875                            unsigned long width, unsigned long height,
   2876                            unsigned long mono_srcx, unsigned char *mono_mask,
   2877                            long mono_pitch)
   2878 {
   2879     unsigned long indent, temp;
   2880     unsigned long total_dwords, size_dwords;
   2881     unsigned long dword_count, byte_count;
   2882     unsigned long srcoff, size;
   2883     unsigned long i, base;
   2884     unsigned long flags = 0;
   2885 
   2886     if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO)
   2887         flags = GP3_RM_SOURCE_INVERT;
   2888 
   2889     /* MONO CALCULATIONS */
   2890 
   2891     indent = (mono_srcx >> 3);
   2892     srcoff = (indent & ~3L);
   2893     indent &= 3;
   2894 
   2895     size = ((width + (mono_srcx & 7) + 7) >> 3) + indent;
   2896     total_dwords = (size + 3) >> 2;
   2897     size_dwords = (total_dwords << 2) + 8;
   2898     dword_count = (size >> 2);
   2899     byte_count = (size & 3);
   2900 
   2901     base = ((gp3_fb_base << 24) + (gp3_scratch_base & 0xFFC00000)) |
   2902         (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
   2903 
   2904     gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_STRIDE_ENABLE |
   2905         GP3_BLT_HDR_DST_OFF_ENABLE | GP3_BLT_HDR_WIDHI_ENABLE |
   2906         GP3_BLT_HDR_CH3_STR_ENABLE | GP3_BLT_HDR_CH3_OFF_ENABLE |
   2907         GP3_BLT_HDR_CH3_WIDHI_ENABLE |
   2908         GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
   2909 
   2910     WRITE_COMMAND32(GP3_BLT_RASTER_MODE, GP3_RM_BPPFMT_8888 | 0xCC);
   2911     WRITE_COMMAND32(GP3_BLT_STRIDE, (total_dwords << 2));
   2912     WRITE_COMMAND32(GP3_BLT_DST_OFFSET, gp3_scratch_base & 0x3FFFFF);
   2913     WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (total_dwords << 16) | height);
   2914     WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (total_dwords << 16) | height);
   2915     WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, 0);
   2916     WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
   2917     WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN |
   2918                     GP3_CH3_REPLACE_SOURCE | GP3_CH3_HST_SRC_ENABLE |
   2919                     GP3_CH3_SRC_8_8_8_8 |
   2920                     ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20));
   2921     WRITE_COMMAND32(GP3_BLT_MODE, 0);
   2922     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   2923 
   2924     /* START THE BLT */
   2925 
   2926     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2927     gp3_cmd_current = gp3_cmd_next;
   2928 
   2929     for (i = 0; i < height; i++) {
   2930         /* UPDATE THE COMMAND POINTER
   2931          * The WRITE_COMMANDXX macros use a pointer to the current buffer
   2932          * space. This is created by adding gp3_cmd_current to the base
   2933          * pointer.
   2934          */
   2935 
   2936         cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
   2937 
   2938         /* CHECK IF A WRAP WILL BE NEEDED */
   2939 
   2940         gp3_cmd_next = gp3_cmd_current + size_dwords;
   2941         if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
   2942             gp3_cmd_next = gp3_cmd_top;
   2943 
   2944             /* WAIT FOR HARDWARE */
   2945 
   2946             GP3_WAIT_WRAP(temp);
   2947             WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE |
   2948                             GP3_DATA_LOAD_HDR_WRAP | GP3_DATA_LOAD_HDR_ENABLE);
   2949         }
   2950         else {
   2951             /* WAIT FOR AVAILABLE SPACE */
   2952 
   2953             GP3_WAIT_PRIMITIVE(temp);
   2954             WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE |
   2955                             GP3_DATA_LOAD_HDR_ENABLE);
   2956         }
   2957 
   2958         /* WRITE DWORD COUNT */
   2959 
   2960         WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
   2961 
   2962         /* WRITE DATA */
   2963 
   2964         WRITE_COMMAND_STRING32(8, mono_mask, srcoff, dword_count);
   2965         WRITE_COMMAND_STRING8(8 + (dword_count << 2), mono_mask,
   2966                               srcoff + (dword_count << 2), byte_count);
   2967 
   2968         /* UPDATE POINTERS */
   2969 
   2970         srcoff += mono_pitch;
   2971         WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   2972         gp3_cmd_current = gp3_cmd_next;
   2973     }
   2974 
   2975     /* SECOND BLT */
   2976 
   2977     gp_declare_blt(gp3_blt_flags | CIMGP_BLTFLAGS_HAZARD);
   2978 
   2979     base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
   2980         ((gp3_fb_base << 14) + (((gp3_scratch_base +
   2981                                   indent) & 0xFFC00000) >> 10)) | ((gp3_fb_base
   2982                                                                     << 4) +
   2983                                                                    ((srcoffset &
   2984                                                                      0xFFC00000)
   2985                                                                     >> 20));
   2986 
   2987     gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE |
   2988         GP3_BLT_HDR_STRIDE_ENABLE | GP3_BLT_HDR_DST_OFF_ENABLE |
   2989         GP3_BLT_HDR_SRC_OFF_ENABLE | GP3_BLT_HDR_WIDHI_ENABLE |
   2990         GP3_BLT_HDR_CH3_STR_ENABLE |
   2991         GP3_BLT_HDR_CH3_WIDHI_ENABLE |
   2992         GP3_BLT_HDR_BASE_OFFSET_ENABLE |
   2993         GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
   2994 
   2995     /* ENABLE TRANSPARENCY AND PATTERN COPY ROP
   2996      * The monochrome data is used as a mask but is otherwise not involved
   2997      * in the BLT.  The color data is routed through the pattern channel.
   2998      */
   2999 
   3000     WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
   3001                     gp3_bpp | 0xF0 | GP3_RM_SRC_TRANS | flags);
   3002     WRITE_COMMAND32(GP3_BLT_STRIDE, (total_dwords << 18) | gp3_dst_stride);
   3003     WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset & 0x3FFFFF);
   3004     WRITE_COMMAND32(GP3_BLT_SRC_OFFSET,
   3005                     ((gp3_scratch_base +
   3006                       indent) & 0x3FFFFF) | ((mono_srcx & 7) << 26));
   3007     WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (width << 16) | height);
   3008     WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (width << 16) | height);
   3009     WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
   3010 
   3011     /* PROGRAM PARAMETERS FOR COLOR SOURCE DATA  */
   3012 
   3013     WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, srcoffset & 0x3FFFFF);
   3014     WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | gp3_ch3_bpp |
   3015                     gp3_src_stride | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT)
   3016                                       << 20));
   3017     WRITE_COMMAND32(GP3_BLT_MODE,
   3018                     gp3_blt_mode | GP3_BM_SRC_MONO | GP3_BM_SRC_FB);
   3019 
   3020     /* START THE BLT */
   3021 
   3022     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   3023     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   3024     gp3_cmd_current = gp3_cmd_next;
   3025 }
   3026 
   3027 /*---------------------------------------------------------------------------
   3028  * gp_bresenham_line
   3029  *
   3030  * This routine draws a vector using the specified Bresenham parameters.
   3031  * Currently this file does not support a routine that accepts the two
   3032  * endpoints of a vector and calculates the Bresenham parameters.  If it
   3033  * ever does, this routine is still required for vectors that have been
   3034  * clipped.
   3035  *-------------------------------------------------------------------------*/
   3036 
   3037 void
   3038 gp_bresenham_line(unsigned long dstoffset, unsigned short length,
   3039                   unsigned short initerr, unsigned short axialerr,
   3040                   unsigned short diagerr, unsigned long flags)
   3041 {
   3042     unsigned long base;
   3043     long offset;
   3044 
   3045     /* HANDLE NEGATIVE VECTORS */
   3046     /* We have to be very careful with vectors that increment negatively   */
   3047     /* Our framebuffer scheme tries to align the destination of every      */
   3048     /* BLT or vector to the nearest 4MB-aligned boundary.  This is         */
   3049     /* necessary because the GP only supports offsets up to 16MB, but the  */
   3050     /* framebuffer can be over 128MB.  To solve this problem, the GP       */
   3051     /* base address registers are alignable to 4MB regions.  However, we   */
   3052     /* cannot simply align the dest offset when the vector goes negative.  */
   3053     /* The vector offset could underflow, causing the offset to jump from  */
   3054     /* near 0 to 16MB.  As we cannot accurately determine the last address */
   3055     /* that will be written in a vector short of walking the algorithm in  */
   3056     /* software, we do a worst case approximation.                         */
   3057 
   3058     offset = dstoffset;
   3059     if (!(flags & CIMGP_POSMAJOR)) {
   3060         if (flags & CIMGP_YMAJOR)
   3061             offset -= length * gp3_dst_stride;
   3062         else
   3063             offset -= (length << gp3_pix_shift);
   3064 
   3065         if (offset < 0)
   3066             offset = 0;
   3067     }
   3068     if (!(flags & CIMGP_POSMINOR)) {
   3069         if (flags & CIMGP_YMAJOR)
   3070             offset -= (length << gp3_pix_shift);
   3071         else
   3072             offset -= length * gp3_dst_stride;
   3073 
   3074         if (offset < 0)
   3075             offset = 0;
   3076     }
   3077 
   3078     offset &= 0xFFC00000;
   3079     dstoffset -= offset;
   3080 
   3081     base = ((gp3_fb_base << 24) + offset) |
   3082         (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
   3083 
   3084     /* ENABLE RELEVANT REGISTERS */
   3085     /* Note that we always enable and write the channel 3 mode, if only */
   3086     /* to turn it off.   Cimarron also always writes the base offset    */
   3087     /* register to allow operation with frame buffers larger than 16MB. */
   3088 
   3089     gp3_cmd_header |= GP3_VEC_HDR_DST_OFF_ENABLE |
   3090         GP3_VEC_HDR_VEC_ERR_ENABLE |
   3091         GP3_VEC_HDR_VEC_LEN_ENABLE |
   3092         GP3_VEC_HDR_BASE_OFFSET_ENABLE |
   3093         GP3_VEC_HDR_CH3_STR_ENABLE | GP3_VEC_HDR_VEC_MODE_ENABLE;
   3094 
   3095     /* WRITE THE REGISTERS COMMON TO ALL PATTERN TYPES */
   3096     /* The destination base is the frame buffer base plus whatever */
   3097     /* 4MB segment we happen to be drawing to.                     */
   3098 
   3099     WRITE_COMMAND32(GP3_VECTOR_VEC_ERR,
   3100                     (((unsigned long) axialerr << 16) | (unsigned long)
   3101                      diagerr));
   3102     WRITE_COMMAND32(GP3_VECTOR_VEC_LEN,
   3103                     (((unsigned long) length << 16) | (unsigned long) initerr));
   3104     WRITE_COMMAND32(GP3_VECTOR_BASE_OFFSET, base);
   3105 
   3106     /* CHECK VECTOR PATTERN CASE */
   3107 
   3108     if (gp3_ch3_pat) {
   3109         /* SET THE SOLID COLOR */
   3110         /* The color for vector patterns from channel 3 comes from */
   3111         /* the regular pattern registers.                          */
   3112 
   3113         gp3_cmd_header |= GP3_VEC_HDR_PAT_CLR0_ENABLE;
   3114 
   3115         WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_0, gp3_vector_pattern_color);
   3116 
   3117         /* INITIALIZE CHANNEL 3 PARAMETERS
   3118          * We route the channel 3 output to the old source channel.  If the
   3119          * user sets a ROP that involves source, they will get unexpected
   3120          * results.
   3121          */
   3122 
   3123         WRITE_COMMAND32(GP3_VECTOR_DST_OFFSET, dstoffset);
   3124         WRITE_COMMAND32(GP3_VECTOR_CH3_MODE_STR,
   3125                         GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE |
   3126                         GP3_CH3_COLOR_PAT_ENABLE | GP3_CH3_SRC_8_8_8_8);
   3127     }
   3128     else {
   3129         /* DISABLE CHANNEL 3 AND USE NORMAL PATTERN ORIGINS */
   3130 
   3131         WRITE_COMMAND32(GP3_VECTOR_CH3_MODE_STR, 0);
   3132         WRITE_COMMAND32(GP3_VECTOR_DST_OFFSET, (dstoffset | gp3_pat_origin));
   3133     }
   3134 
   3135     /* START THE VECTOR */
   3136 
   3137     WRITE_COMMAND32(GP3_VEC_CMD_HEADER, gp3_cmd_header);
   3138     WRITE_COMMAND32(GP3_VECTOR_MODE, (gp3_vec_mode | flags));
   3139     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   3140 
   3141     gp3_cmd_current = gp3_cmd_next;
   3142 
   3143     /* ADD A SECOND VECTOR TO CLEAR THE BYTE ENABLES            */
   3144     /* We set a transparent pattern to clear the byte enables.  */
   3145     /* We then restore the previous pattern. (SiBZ #4001)       */
   3146 
   3147     if (gp3_ch3_pat) {
   3148         cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
   3149 
   3150         WRITE_COMMAND32(0, GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE);
   3151         WRITE_COMMAND32(4, 0x100);
   3152         WRITE_COMMAND32(8, (1 | GP3_LUT_DATA_TYPE));
   3153         WRITE_COMMAND32(12, 0);
   3154 
   3155         /* DUMMY VECTOR */
   3156         /* We shouldn't need to write anything but vector mode and the length
   3157          */
   3158 
   3159         WRITE_COMMAND32(16, GP3_VEC_HDR_TYPE | GP3_VEC_HDR_VEC_MODE_ENABLE |
   3160                         GP3_VEC_HDR_VEC_LEN_ENABLE);
   3161         WRITE_COMMAND32(16 + GP3_VECTOR_MODE, (gp3_vec_mode | flags));
   3162         WRITE_COMMAND32(16 + GP3_VECTOR_VEC_LEN,
   3163                         (1 << 16) | (unsigned long) initerr);
   3164 
   3165         WRITE_COMMAND32(16 + GP3_VECTOR_COMMAND_SIZE,
   3166                         GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE);
   3167         WRITE_COMMAND32(20 + GP3_VECTOR_COMMAND_SIZE, 0x100);
   3168         WRITE_COMMAND32(24 + GP3_VECTOR_COMMAND_SIZE, (1 | GP3_LUT_DATA_TYPE));
   3169         WRITE_COMMAND32(28 + GP3_VECTOR_COMMAND_SIZE, gp3_vec_pat);
   3170 
   3171         gp3_cmd_current += 32 + GP3_VECTOR_COMMAND_SIZE;
   3172     }
   3173 }
   3174 
   3175 /*---------------------------------------------------------------------------
   3176  * gp_line_from_endpoints
   3177  *
   3178  * This routine draws a vector from a set of rectangular coordinates.  The
   3179  * rectangle is assumed to use the currently specified destination stride.
   3180  *-------------------------------------------------------------------------*/
   3181 
   3182 void
   3183 gp_line_from_endpoints(unsigned long dstoffset, unsigned long x0,
   3184                        unsigned long y0, unsigned long x1, unsigned long y1,
   3185                        int inclusive)
   3186 {
   3187     unsigned long base;
   3188     unsigned long length;
   3189     unsigned long flags;
   3190     unsigned short initerr, axialerr, diagerr;
   3191     long dx, dy, dmaj, dmin;
   3192     long offset;
   3193 
   3194     /* ADJUST DESTINATION OFFSET BASED ON STARTING COORDINATE */
   3195 
   3196     dstoffset += (x0 << gp3_pix_shift) + (y0 * gp3_dst_stride);
   3197 
   3198     /* CALCULATE BRESENHAM TERMS */
   3199 
   3200     dx = (long) x1 - (long) x0;
   3201     dy = (long) y1 - (long) y0;
   3202     if (dx < 0)
   3203         dx = -dx;
   3204     if (dy < 0)
   3205         dy = -dy;
   3206 
   3207     if (dx >= dy) {
   3208         dmaj = dx;
   3209         dmin = dy;
   3210         flags = 0;
   3211         if (x1 > x0)
   3212             flags |= CIMGP_POSMAJOR;
   3213         if (y1 > y0)
   3214             flags |= CIMGP_POSMINOR;
   3215     }
   3216     else {
   3217         dmaj = dy;
   3218         dmin = dx;
   3219         flags = CIMGP_YMAJOR;
   3220         if (x1 > x0)
   3221             flags |= CIMGP_POSMINOR;
   3222         if (y1 > y0)
   3223             flags |= CIMGP_POSMAJOR;
   3224     }
   3225 
   3226     axialerr = (unsigned short) (dmin << 1);
   3227     diagerr = (unsigned short) ((dmin - dmaj) << 1);
   3228     initerr = (unsigned short) ((dmin << 1) - dmaj);
   3229     if (!(flags & CIMGP_POSMINOR))
   3230         initerr--;
   3231 
   3232     /* CHECK FOR NO WORK */
   3233 
   3234     if (!dmaj)
   3235         return;
   3236 
   3237     /* CHECK INCLUSIVE OR EXCLUSIVE */
   3238     /* An inclusive line can be accomplished by simply adding 1 to the */
   3239     /* line length.                                                    */
   3240 
   3241     length = dmaj;
   3242     if (inclusive)
   3243         length++;
   3244 
   3245     /* HANDLE NEGATIVE VECTORS */
   3246 
   3247     offset = dstoffset;
   3248     if (!(flags & CIMGP_POSMAJOR)) {
   3249         if (flags & CIMGP_YMAJOR)
   3250             offset -= length * gp3_dst_stride;
   3251         else
   3252             offset -= (length << gp3_pix_shift);
   3253 
   3254         if (offset < 0)
   3255             offset = 0;
   3256     }
   3257     if (!(flags & CIMGP_POSMINOR)) {
   3258         if (flags & CIMGP_YMAJOR)
   3259             offset -= (length << gp3_pix_shift);
   3260         else
   3261             offset -= length * gp3_dst_stride;
   3262 
   3263         if (offset < 0)
   3264             offset = 0;
   3265     }
   3266 
   3267     offset &= 0xFFC00000;
   3268     dstoffset -= offset;
   3269 
   3270     base = ((gp3_fb_base << 24) + offset) |
   3271         (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
   3272 
   3273     /* ENABLE RELEVANT REGISTERS */
   3274     /* Note that we always enable and write the channel 3 mode, if only */
   3275     /* to turn it off.   Cimarron also always writes the base offset    */
   3276     /* register to allow operation with frame buffers larger than 16MB. */
   3277 
   3278     gp3_cmd_header |= GP3_VEC_HDR_DST_OFF_ENABLE |
   3279         GP3_VEC_HDR_VEC_ERR_ENABLE |
   3280         GP3_VEC_HDR_VEC_LEN_ENABLE |
   3281         GP3_VEC_HDR_BASE_OFFSET_ENABLE |
   3282         GP3_VEC_HDR_CH3_STR_ENABLE | GP3_VEC_HDR_VEC_MODE_ENABLE;
   3283 
   3284     /* WRITE THE REGISTERS COMMON TO ALL PATTERN TYPES */
   3285     /* The destination base is the frame buffer base plus whatever */
   3286     /* 4MB segment we happen to be drawing to.                     */
   3287 
   3288     WRITE_COMMAND32(GP3_VECTOR_VEC_ERR,
   3289                     (((unsigned long) axialerr << 16) | (unsigned long)
   3290                      diagerr));
   3291     WRITE_COMMAND32(GP3_VECTOR_VEC_LEN,
   3292                     (((unsigned long) length << 16) | (unsigned long) initerr));
   3293     WRITE_COMMAND32(GP3_VECTOR_BASE_OFFSET, base);
   3294 
   3295     /* CHECK VECTOR PATTERN CASE */
   3296 
   3297     if (gp3_ch3_pat) {
   3298         /* SET THE SOLID COLOR */
   3299         /* The color for vector patterns from channel 3 comes from */
   3300         /* the regular pattern registers.                          */
   3301 
   3302         gp3_cmd_header |= GP3_VEC_HDR_PAT_CLR0_ENABLE;
   3303 
   3304         WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_0, gp3_vector_pattern_color);
   3305 
   3306         /* INITIALIZE CHANNEL 3 PARAMETERS */
   3307         /* We route the channel 3 output to the old source channel.  If the
   3308          * user sets a ROP that involves source, they will get unexpected
   3309          * results.
   3310          */
   3311 
   3312         WRITE_COMMAND32(GP3_VECTOR_DST_OFFSET, dstoffset);
   3313         WRITE_COMMAND32(GP3_VECTOR_CH3_MODE_STR,
   3314                         GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE |
   3315                         GP3_CH3_COLOR_PAT_ENABLE | GP3_CH3_SRC_8_8_8_8);
   3316     }
   3317     else {
   3318         /* DISABLE CHANNEL 3 AND USE NORMAL PATTERN ORIGINS */
   3319 
   3320         WRITE_COMMAND32(GP3_VECTOR_CH3_MODE_STR, 0);
   3321         WRITE_COMMAND32(GP3_VECTOR_DST_OFFSET, (dstoffset | gp3_pat_origin));
   3322     }
   3323 
   3324     /* START THE VECTOR */
   3325 
   3326     WRITE_COMMAND32(GP3_VEC_CMD_HEADER, gp3_cmd_header);
   3327     WRITE_COMMAND32(GP3_VECTOR_MODE, (gp3_vec_mode | flags));
   3328     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   3329     gp3_cmd_current = gp3_cmd_next;
   3330 
   3331     /* ADD A SECOND VECTOR TO CLEAR THE BYTE ENABLES            */
   3332     /* We set a transparent pattern to clear the byte enables.  */
   3333     /* We then restore the previous pattern.  (SiBZ #4001)      */
   3334 
   3335     if (gp3_ch3_pat) {
   3336         cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
   3337 
   3338         WRITE_COMMAND32(0, GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE);
   3339         WRITE_COMMAND32(4, 0x100);
   3340         WRITE_COMMAND32(8, (1 | GP3_LUT_DATA_TYPE));
   3341         WRITE_COMMAND32(12, 0);
   3342 
   3343         /* DUMMY VECTOR */
   3344         /* We shouldn't need to write anything but vector mode and the length
   3345          */
   3346 
   3347         WRITE_COMMAND32(16, GP3_VEC_HDR_TYPE | GP3_VEC_HDR_VEC_MODE_ENABLE |
   3348                         GP3_VEC_HDR_VEC_LEN_ENABLE);
   3349         WRITE_COMMAND32(16 + GP3_VECTOR_MODE, (gp3_vec_mode | flags));
   3350         WRITE_COMMAND32(16 + GP3_VECTOR_VEC_LEN,
   3351                         (1 << 16) | (unsigned long) initerr);
   3352 
   3353         WRITE_COMMAND32(16 + GP3_VECTOR_COMMAND_SIZE,
   3354                         GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE);
   3355         WRITE_COMMAND32(20 + GP3_VECTOR_COMMAND_SIZE, 0x100);
   3356         WRITE_COMMAND32(24 + GP3_VECTOR_COMMAND_SIZE, (1 | GP3_LUT_DATA_TYPE));
   3357         WRITE_COMMAND32(28 + GP3_VECTOR_COMMAND_SIZE, gp3_vec_pat);
   3358 
   3359         gp3_cmd_current += 32 + GP3_VECTOR_COMMAND_SIZE;
   3360     }
   3361 }
   3362 
   3363 /*---------------------------------------------------------------------------
   3364  * gp_wait_until_idle
   3365  *
   3366  * This routine stalls execution until the GP is no longer actively rendering.
   3367  *-------------------------------------------------------------------------*/
   3368 
   3369 void
   3370 gp_wait_until_idle(void)
   3371 {
   3372     unsigned long temp;
   3373 
   3374     while (((temp = READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_BUSY) ||
   3375            !(temp & GP3_BS_CB_EMPTY)) {
   3376         ;
   3377     }
   3378 }
   3379 
   3380 /*---------------------------------------------------------------------------
   3381  * gp_test_blt_busy
   3382  *-------------------------------------------------------------------------*/
   3383 
   3384 int
   3385 gp_test_blt_busy(void)
   3386 {
   3387     unsigned long temp;
   3388 
   3389     if (((temp = READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_BUSY) ||
   3390         !(temp & GP3_BS_CB_EMPTY))
   3391         return 1;
   3392 
   3393     return 0;
   3394 }
   3395 
   3396 /*---------------------------------------------------------------------------
   3397  * gp_test_blt_pending
   3398  *-------------------------------------------------------------------------*/
   3399 
   3400 int
   3401 gp_test_blt_pending(void)
   3402 {
   3403     if ((READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_PENDING)
   3404         return 1;
   3405 
   3406     return 0;
   3407 }
   3408 
   3409 /*---------------------------------------------------------------------------
   3410  * gp_wait_blt_pending
   3411  *-------------------------------------------------------------------------*/
   3412 
   3413 void
   3414 gp_wait_blt_pending(void)
   3415 {
   3416     while ((READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_PENDING);
   3417 }
   3418 
   3419 /*---------------------------------------------------------------------------
   3420  * gp_save_state
   3421  *
   3422  * This routine saves all persistent GP information.
   3423  *-------------------------------------------------------------------------*/
   3424 
   3425 void
   3426 gp_save_state(GP_SAVE_RESTORE * gp_state)
   3427 {
   3428     Q_WORD msr_value;
   3429 
   3430     gp_wait_until_idle();
   3431 
   3432     msr_read64(MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value);
   3433     gp_state->cmd_bottom = READ_GP32(GP3_CMD_BOT) & 0xFFFFFF;
   3434     gp_state->cmd_top = READ_GP32(GP3_CMD_TOP) & 0xFFFFFF;
   3435     gp_state->cmd_base = (msr_value.low << 4) & 0xFFF00000;
   3436     gp_state->base_offset = READ_GP32(GP3_BASE_OFFSET);
   3437 
   3438     /* RESET THE READ POINTER */
   3439 
   3440     gp_set_command_buffer_base(gp_state->cmd_base, gp_state->cmd_top,
   3441                                gp_state->cmd_bottom);
   3442 }
   3443 
   3444 /*---------------------------------------------------------------------------
   3445  * gp_restore_state
   3446  *
   3447  * This routine restores all persistent GP information.
   3448  *-------------------------------------------------------------------------*/
   3449 
   3450 void
   3451 gp_restore_state(GP_SAVE_RESTORE * gp_state)
   3452 {
   3453     gp_wait_until_idle();
   3454 
   3455     WRITE_GP32(GP3_BASE_OFFSET, gp_state->base_offset);
   3456 
   3457     gp_set_command_buffer_base(gp_state->cmd_base, gp_state->cmd_top,
   3458                                gp_state->cmd_bottom);
   3459 }
   3460 
   3461 /* This is identical to gp_antialiased_text, except we support all one
   3462    pass alpha operations similar to gp_set_alpha_operation */
   3463 
   3464 void
   3465 gp_blend_mask_blt(unsigned long dstoffset, unsigned long srcx,
   3466                   unsigned long width, unsigned long height,
   3467                   unsigned long dataoffset, long stride, int operation,
   3468                   int fourbpp)
   3469 {
   3470     unsigned long indent;
   3471     unsigned long size = ((width << 16) | height);
   3472     unsigned long base, depth_flag;
   3473 
   3474     base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
   3475         ((gp3_fb_base << 4) + (dataoffset >> 20)) |
   3476         (gp3_base_register & GP3_BASE_OFFSET_SRCMASK);
   3477 
   3478     /* ENABLE ALL RELEVANT REGISTERS */
   3479     /* We override the raster mode register to force the */
   3480     /* correct alpha blend                               */
   3481 
   3482     gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE |
   3483         GP3_BLT_HDR_DST_OFF_ENABLE |
   3484         GP3_BLT_HDR_WIDHI_ENABLE |
   3485         GP3_BLT_HDR_CH3_OFF_ENABLE |
   3486         GP3_BLT_HDR_CH3_STR_ENABLE |
   3487         GP3_BLT_HDR_CH3_WIDHI_ENABLE |
   3488         GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
   3489 
   3490     /* CALCULATIONS BASED ON ALPHA DEPTH */
   3491     /* Although most antialiased text is 4BPP, the hardware supports */
   3492     /* a full 8BPP.  Either case is supported by this routine.       */
   3493 
   3494     if (fourbpp) {
   3495         depth_flag = GP3_CH3_SRC_4BPP_ALPHA;
   3496         indent = (srcx >> 1) & 3;
   3497         dataoffset += indent | ((srcx & 1) << 25);
   3498     }
   3499     else {
   3500         depth_flag = GP3_CH3_SRC_8BPP_ALPHA;
   3501         indent = srcx & 3;
   3502         dataoffset += indent;
   3503     }
   3504 
   3505     /* SET RASTER MODE REGISTER */
   3506     /* Alpha blending will only apply to RGB when no alpha component is present. */
   3507     /* As 8BPP is not supported for this routine, the only alpha-less mode is    */
   3508     /* 5:6:5.                                                                    */
   3509 
   3510     if (gp3_bpp == GP3_RM_BPPFMT_565) {
   3511         WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
   3512                         gp3_bpp |
   3513                         GP3_RM_ALPHA_TO_RGB |
   3514                         ((unsigned long) (operation << 20)) |
   3515                         GP3_RM_SELECT_ALPHA_CHAN_3);
   3516     }
   3517     else {
   3518         WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
   3519                         gp3_bpp |
   3520                         GP3_RM_ALPHA_ALL | ((unsigned long) (operation << 20)) |
   3521                         GP3_RM_SELECT_ALPHA_CHAN_3);
   3522     }
   3523 
   3524     /* WRITE ALL REMAINING REGISTERS */
   3525 
   3526     WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
   3527 
   3528     /* Set the offset of the CH3 data in memory */
   3529     WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, dataoffset & 0x3FFFFF);
   3530 
   3531     WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
   3532     WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size);
   3533     WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
   3534 
   3535     WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | (stride & 0xFFFF) |
   3536                     depth_flag | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) <<
   3537                                   20));
   3538 
   3539     WRITE_COMMAND32(GP3_BLT_MODE, GP3_BM_DST_REQ);
   3540 
   3541     /* START THE BLT */
   3542 
   3543     WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
   3544     WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
   3545     gp3_cmd_current = gp3_cmd_next;
   3546 }
   3547