1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nsc/gfx/rndr_gu1.c,v 1.2 2003/01/14 09:34:34 alanh Exp $ */
2/*
3 * $Workfile: rndr_gu1.c $
4 *
5 * This file contains routines to program the 2D acceleration hardware for
6 * the first generation graphics unit (GXLV, SC1200).
7 *
8 *    gfx_set_bpp
9 *    gfx_set_solid_pattern
10 *    gfx_set_mono_pattern
11 *    gfx_set_color_pattern
12 *    gfx_set_solid_source
13 *    gfx_set_mono_source
14 *    gfx_set_raster_operation
15 *    gfx_pattern_fill
16 *    gfx_screen_to_screen_blt
17 *    gfx_screen_to_screen_xblt
18 *    gfx_color_bitmap_to_screen_blt
19 *    gfx_color_bitmap_to_screen_xblt
20 *    gfx_mono_bitmap_to_screen_blt
21 *    gfx_bresenham_line
22 *    gfx_wait_until_idle
23 *
24 * NSC_LIC_ALTERNATIVE_PREAMBLE
25 *
26 * Revision 1.0
27 *
28 * National Semiconductor Alternative GPL-BSD License
29 *
30 * National Semiconductor Corporation licenses this software
31 * ("Software"):
32 *
33 *      Durango
34 *
35 * under one of the two following licenses, depending on how the
36 * Software is received by the Licensee.
37 *
38 * If this Software is received as part of the Linux Framebuffer or
39 * other GPL licensed software, then the GPL license designated
40 * NSC_LIC_GPL applies to this Software; in all other circumstances
41 * then the BSD-style license designated NSC_LIC_BSD shall apply.
42 *
43 * END_NSC_LIC_ALTERNATIVE_PREAMBLE */
44
45/* NSC_LIC_BSD
46 *
47 * National Semiconductor Corporation Open Source License for Durango
48 *
49 * (BSD License with Export Notice)
50 *
51 * Copyright (c) 1999-2001
52 * National Semiconductor Corporation.
53 * All rights reserved.
54 *
55 * Redistribution and use in source and binary forms, with or without
56 * modification, are permitted provided that the following conditions
57 * are met:
58 *
59 *   * Redistributions of source code must retain the above copyright
60 *     notice, this list of conditions and the following disclaimer.
61 *
62 *   * Redistributions in binary form must reproduce the above
63 *     copyright notice, this list of conditions and the following
64 *     disclaimer in the documentation and/or other materials provided
65 *     with the distribution.
66 *
67 *   * Neither the name of the National Semiconductor Corporation nor
68 *     the names of its contributors may be used to endorse or promote
69 *     products derived from this software without specific prior
70 *     written permission.
71 *
72 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
73 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
74 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
75 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
76 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
77 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
78 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
79 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
80 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
81 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
82 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
83 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
84 * OF SUCH DAMAGE.
85 *
86 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
87 * YOUR JURISDICTION. It is licensee's responsibility to comply with
88 * any export regulations applicable in licensee's jurisdiction. Under
89 * CURRENT (2001) U.S. export regulations this software
90 * is eligible for export from the U.S. and can be downloaded by or
91 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
92 * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
93 * Syria, Sudan, Afghanistan and any other country to which the U.S.
94 * has embargoed goods and services.
95 *
96 * END_NSC_LIC_BSD */
97
98/* NSC_LIC_GPL
99 *
100 * National Semiconductor Corporation Gnu General Public License for Durango
101 *
102 * (GPL License with Export Notice)
103 *
104 * Copyright (c) 1999-2001
105 * National Semiconductor Corporation.
106 * All rights reserved.
107 *
108 * Redistribution and use in source and binary forms, with or without
109 * modification, are permitted under the terms of the GNU General
110 * Public License as published by the Free Software Foundation; either
111 * version 2 of the License, or (at your option) any later version
112 *
113 * In addition to the terms of the GNU General Public License, neither
114 * the name of the National Semiconductor Corporation nor the names of
115 * its contributors may be used to endorse or promote products derived
116 * from this software without specific prior written permission.
117 *
118 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
119 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
120 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
121 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
122 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
123 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
124 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
125 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
126 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
127 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
128 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
129 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
130 * OF SUCH DAMAGE. See the GNU General Public License for more details.
131 *
132 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
133 * YOUR JURISDICTION. It is licensee's responsibility to comply with
134 * any export regulations applicable in licensee's jurisdiction. Under
135 * CURRENT (2001) U.S. export regulations this software
136 * is eligible for export from the U.S. and can be downloaded by or
137 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
138 * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
139 * Syria, Sudan, Afghanistan and any other country to which the U.S.
140 * has embargoed goods and services.
141 *
142 * You should have received a copy of the GNU General Public License
143 * along with this file; if not, write to the Free Software Foundation,
144 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
145 *
146 * END_NSC_LIC_GPL */
147
148void gu1_set_bpp(unsigned short bpp);
149void gu1_set_solid_pattern(unsigned long color);
150void gu1_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor,
151			  unsigned long data0, unsigned long data1,
152			  unsigned char transparency);
153void gu1_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor,
154			   unsigned long data0, unsigned long data1,
155			   unsigned long data2, unsigned long data3,
156			   unsigned char transparency);
157void gu1_load_color_pattern_line(short y, unsigned long *pattern_8x8);
158void gu1_set_solid_source(unsigned long color);
159void gu1_set_mono_source(unsigned long bgcolor, unsigned long fgcolor,
160			 unsigned short transparent);
161void gu1_set_pattern_flags(unsigned short flags);
162void gu1_set_raster_operation(unsigned char rop);
163void gu1_pattern_fill(unsigned short x, unsigned short y,
164		      unsigned short width, unsigned short height);
165void gu1_color_pattern_fill(unsigned short x, unsigned short y,
166			    unsigned short width, unsigned short height,
167			    unsigned long *pattern);
168void gu1_screen_to_screen_blt(unsigned short srcx, unsigned short srcy,
169			      unsigned short dstx, unsigned short dsty,
170			      unsigned short width, unsigned short height);
171void gu1_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy,
172			       unsigned short dstx, unsigned short dsty,
173			       unsigned short width, unsigned short height,
174			       unsigned long color);
175void gu1_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
176				    unsigned short dstx, unsigned short dsty,
177				    unsigned short width,
178				    unsigned short height,
179				    unsigned char *data, long pitch);
180void gu1_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy,
181				     unsigned short dstx, unsigned short dsty,
182				     unsigned short width,
183				     unsigned short height,
184				     unsigned char *data, long pitch,
185				     unsigned long color);
186void gu1_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
187				   unsigned short dstx, unsigned short dsty,
188				   unsigned short width,
189				   unsigned short height, unsigned char *data,
190				   short pitch);
191void gu1_text_blt(unsigned short dstx, unsigned short dsty,
192		  unsigned short width, unsigned short height,
193		  unsigned char *data);
194void gu1_bresenham_line(unsigned short x, unsigned short y,
195			unsigned short length, unsigned short initerr,
196			unsigned short axialerr, unsigned short diagerr,
197			unsigned short flags);
198void gu1_wait_until_idle(void);
199
200#if GFX_NO_IO_IN_WAIT_MACROS
201#define GFX_WAIT_PENDING while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING) { ; }
202#define GFX_WAIT_BUSY while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_BUSY) { ; }
203#define GFX_WAIT_PIPELINE while (READ_REG16(GP_BLIT_STATUS) & BS_PIPELINE_BUSY) { ; }
204#else
205#define GFX_WAIT_PENDING while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING) { INB (0x80); }
206#define GFX_WAIT_BUSY while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_BUSY) { INB (0x80); }
207#define GFX_WAIT_PIPELINE while (READ_REG16(GP_BLIT_STATUS) & BS_PIPELINE_BUSY) { INB (0x80); }
208#endif
209
210void gu1_detect_blt_buffer_base(void);
211int gu1_test_blt_pending(void);
212void gu1_solid_fill(unsigned short x, unsigned short y,
213		    unsigned short width, unsigned short height,
214		    unsigned long color);
215
216/*---------------------------------------------------------------------------
217 * GFX_SET_BPP
218 *
219 * This routine sets the bits per pixel value in the graphics engine.
220 * It is also stored in a static variable to use in the future calls to
221 * the rendering routines.
222 *---------------------------------------------------------------------------
223 */
224#if GFX_2DACCEL_DYNAMIC
225void
226gu1_set_bpp(unsigned short bpp)
227#else
228void
229gfx_set_bpp(unsigned short bpp)
230#endif
231{
232   int control = 0;
233   unsigned short pitch = gfx_get_display_pitch();
234
235   GFXbpp = bpp;
236
237   /* DETECT BASE ADDRESSES FOR BLT BUFFERS */
238   /* Different for 2K or 3K of scratchpad.  Also need to calculate */
239   /* the number of pixels that can fit in a BLT buffer - need to */
240   /* subtract 16 for alignment considerations.  The 2K case, for */
241   /* example, is 816 bytes wide, allowing 800 pixels in 8 BPP, which */
242   /* means rendering operations won't be split for 800x600. */
243
244   gu1_detect_blt_buffer_base();
245   GFXbufferWidthPixels = GFXbb1Base - GFXbb0Base - 16;
246   if (bpp > 8) {
247      /* If 16bpp, divide GFXbufferWidthPixels by 2 */
248      GFXbufferWidthPixels >>= 1;
249   }
250
251   /* SET THE GRAPHICS CONTROLLER BPP AND PITCH */
252   if (bpp > 8) {
253      /* Set the 16bpp bit if necessary */
254      control = BC_16BPP;
255   }
256   if ((gfx_cpu_version == GFX_CPU_PYRAMID) && (pitch > 2048)) {
257      control |= BC_FB_WIDTH_4096;
258   } else if (pitch > 1024) {
259      control |= BC_FB_WIDTH_2048;
260   }
261   GFX_WAIT_BUSY;
262   WRITE_REG32(GP_BLIT_STATUS, control);
263}
264
265/*
266//---------------------------------------------------------------------------
267// GFX_SET_SOLID_SOURCE
268//
269// This routine is used to specify a solid source color.  For the Xfree96
270// display driver, the source color is used to specify a planemask and the
271// ROP is adjusted accordingly.
272//---------------------------------------------------------------------------
273*/
274#if GFX_2DACCEL_DYNAMIC
275void
276gu1_set_solid_source(unsigned long color)
277#else
278void
279gfx_set_solid_source(unsigned long color)
280#endif
281{
282   /* CLEAR TRANSPARENCY FLAG */
283
284   GFXsourceFlags = 0;
285
286   /* FORMAT 8 BPP COLOR */
287   /* GX requires 8BPP color data be duplicated into bits [15:8]. */
288
289   if (GFXbpp == 8) {
290      color &= 0x00FF;
291      color |= (color << 8);
292   }
293
294   /* POLL UNTIL ABLE TO WRITE THE SOURCE COLOR */
295
296   GFX_WAIT_PENDING;
297   WRITE_REG16(GP_SRC_COLOR_0, (unsigned short)color);
298   WRITE_REG16(GP_SRC_COLOR_1, (unsigned short)color);
299}
300
301/*
302//---------------------------------------------------------------------------
303// GFX_SET_MONO_SOURCE
304//
305// This routine is used to specify the monochrome source colors.
306// It must be called *after* loading any pattern data (those routines
307// clear the source flags).
308//---------------------------------------------------------------------------
309*/
310#if GFX_2DACCEL_DYNAMIC
311void
312gu1_set_mono_source(unsigned long bgcolor, unsigned long fgcolor,
313		    unsigned short transparent)
314#else
315void
316gfx_set_mono_source(unsigned long bgcolor, unsigned long fgcolor,
317		    unsigned short transparent)
318#endif
319{
320   /* SET TRANSPARENCY FLAG */
321
322   GFXsourceFlags = transparent ? RM_SRC_TRANSPARENT : 0;
323
324   /* FORMAT 8 BPP COLOR */
325   /* GX requires 8BPP color data be duplicated into bits [15:8]. */
326
327   if (GFXbpp == 8) {
328      bgcolor &= 0x00FF;
329      bgcolor |= (bgcolor << 8);
330      fgcolor &= 0x00FF;
331      fgcolor |= (fgcolor << 8);
332   }
333
334   /* POLL UNTIL ABLE TO WRITE THE SOURCE COLOR */
335
336   GFX_WAIT_PENDING;
337   WRITE_REG16(GP_SRC_COLOR_0, (unsigned short)bgcolor);
338   WRITE_REG16(GP_SRC_COLOR_1, (unsigned short)fgcolor);
339}
340
341/*
342//---------------------------------------------------------------------------
343// GFX_SET_SOLID_PATTERN
344//
345// This routine is used to specify a solid pattern color.  It is called
346// before performing solid rectangle fills or more complicated BLTs that
347// use a solid pattern color.
348//
349// The driver should always call "gfx_load_raster_operation" after a call
350// to this routine to make sure that the pattern flags are set appropriately.
351//---------------------------------------------------------------------------
352*/
353#if GFX_2DACCEL_DYNAMIC
354void
355gu1_set_solid_pattern(unsigned long color)
356#else
357void
358gfx_set_solid_pattern(unsigned long color)
359#endif
360{
361   /* CLEAR TRANSPARENCY FLAG */
362
363   GFXsourceFlags = 0;
364
365   /* SET PATTERN FLAGS */
366
367   GFXpatternFlags = 0;
368
369   /* FORMAT 8 BPP COLOR */
370   /* GX requires 8BPP color data be duplicated into bits [15:8]. */
371
372   if (GFXbpp == 8) {
373      color &= 0x00FF;
374      color |= (color << 8);
375   }
376
377   /* SAVE THE REFORMATTED COLOR FOR LATER */
378   /* Used to call the "GFX_solid_fill" routine for special cases. */
379
380   GFXsavedColor = color;
381
382   /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */
383
384   GFX_WAIT_PENDING;
385   WRITE_REG16(GP_PAT_COLOR_0, (unsigned short)color);
386}
387
388/*
389//---------------------------------------------------------------------------
390// GFX_SET_MONO_PATTERN
391//
392// This routine is used to specify a monochrome pattern.
393//---------------------------------------------------------------------------
394*/
395#if GFX_2DACCEL_DYNAMIC
396void
397gu1_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor,
398		     unsigned long data0, unsigned long data1,
399		     unsigned char transparent)
400#else
401void
402gfx_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor,
403		     unsigned long data0, unsigned long data1,
404		     unsigned char transparent)
405#endif
406{
407   /* CLEAR TRANSPARENCY FLAG */
408
409   GFXsourceFlags = 0;
410
411   /* SET PATTERN FLAGS */
412
413   GFXpatternFlags = transparent ? RM_PAT_MONO | RM_PAT_TRANSPARENT :
414	 RM_PAT_MONO;
415
416   /* FORMAT 8 BPP COLOR */
417   /* GXm requires 8BPP color data be duplicated into bits [15:8]. */
418
419   if (GFXbpp == 8) {
420      bgcolor &= 0x00FF;
421      bgcolor |= (bgcolor << 8);
422      fgcolor &= 0x00FF;
423      fgcolor |= (fgcolor << 8);
424   }
425
426   /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */
427
428   GFX_WAIT_PENDING;
429   WRITE_REG16(GP_PAT_COLOR_0, (unsigned short)bgcolor);
430   WRITE_REG16(GP_PAT_COLOR_1, (unsigned short)fgcolor);
431   WRITE_REG32(GP_PAT_DATA_0, data0);
432   WRITE_REG32(GP_PAT_DATA_1, data1);
433}
434
435/*
436//---------------------------------------------------------------------------
437// GFX_SET_COLOR_PATTERN
438//
439// This routine is used to specify a color pattern.
440//---------------------------------------------------------------------------
441*/
442#if GFX_2DACCEL_DYNAMIC
443void
444gu1_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor,
445		      unsigned long data0, unsigned long data1,
446		      unsigned long data2, unsigned long data3,
447		      unsigned char transparent)
448#else
449void
450gfx_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor,
451		      unsigned long data0, unsigned long data1,
452		      unsigned long data2, unsigned long data3,
453		      unsigned char transparent)
454#endif
455{
456   /* CLEAR TRANSPARENCY FLAG */
457
458   GFXsourceFlags = 0;
459
460   /* SET PATTERN FLAGS */
461
462   GFXpatternFlags = transparent ? RM_PAT_MONO | RM_PAT_TRANSPARENT :
463	 RM_PAT_MONO;
464
465   GFXpatternFlags |= RM_PAT_COLOR;
466   /* FORMAT 8 BPP COLOR */
467   /* GXm requires 8BPP color data be duplicated into bits [15:8]. */
468
469   if (GFXbpp == 8) {
470      bgcolor &= 0x00FF;
471      bgcolor |= (bgcolor << 8);
472      fgcolor &= 0x00FF;
473      fgcolor |= (fgcolor << 8);
474   }
475
476   /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */
477
478   GFX_WAIT_PENDING;
479   WRITE_REG16(GP_PAT_COLOR_0, (unsigned short)bgcolor);
480   WRITE_REG16(GP_PAT_COLOR_1, (unsigned short)fgcolor);
481   WRITE_REG32(GP_PAT_DATA_0, data0);
482   WRITE_REG32(GP_PAT_DATA_1, data1);
483   if (GFXbpp > 8) {
484      WRITE_REG32(GP_PAT_DATA_2, data2);
485      WRITE_REG32(GP_PAT_DATA_3, data3);
486   }
487}
488
489/*
490//---------------------------------------------------------------------------
491// GFX_LOAD_COLOR_PATTERN_LINE
492//
493// This routine is used to load a single line of a 8x8 color pattern.
494//---------------------------------------------------------------------------
495*/
496#if GFX_2DACCEL_DYNAMIC
497void
498gu1_load_color_pattern_line(short y, unsigned long *pattern_8x8)
499#else
500void
501gfx_load_color_pattern_line(short y, unsigned long *pattern_8x8)
502#endif
503{
504   /* CLEAR TRANSPARENCY FLAG */
505
506   GFXsourceFlags = 0;
507
508   /* SET PATTERN FLAGS */
509
510   GFXpatternFlags = RM_PAT_COLOR;
511
512   y &= 7;
513
514   if (GFXbpp > 8)
515      pattern_8x8 += (y << 2);
516   else
517      pattern_8x8 += (y << 1);
518
519   /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */
520
521   GFX_WAIT_PENDING;
522   WRITE_REG32(GP_PAT_DATA_0, pattern_8x8[0]);
523   WRITE_REG32(GP_PAT_DATA_1, pattern_8x8[1]);
524   if (GFXbpp > 8) {
525      WRITE_REG32(GP_PAT_DATA_2, pattern_8x8[2]);
526      WRITE_REG32(GP_PAT_DATA_3, pattern_8x8[3]);
527   }
528}
529
530/*
531//---------------------------------------------------------------------------
532// GFX_SET_RASTER_OPERATION
533//
534// This routine loads the specified raster operation.  It sets the pattern
535// flags appropriately.
536//---------------------------------------------------------------------------
537*/
538#if GFX_2DACCEL_DYNAMIC
539void
540gu1_set_raster_operation(unsigned char rop)
541#else
542void
543gfx_set_raster_operation(unsigned char rop)
544#endif
545{
546   unsigned short rop16;
547
548   /* GENERATE 16-BIT VERSION OF ROP WITH PATTERN FLAGS */
549
550   rop16 = (unsigned short)rop | GFXpatternFlags;
551   if ((rop & 0x33) ^ ((rop >> 2) & 0x33))
552      rop16 |= GFXsourceFlags;
553
554   /* SAVE ROP FOR LATER COMPARISONS */
555   /* Need to have the pattern flags included */
556
557   GFXsavedRop = rop16;
558
559   /* SET FLAG INDICATING ROP REQUIRES DESTINATION DATA */
560   /* True if even bits (0:2:4:6) do not equal the correspinding */
561   /* even bits (1:3:5:7). */
562
563   GFXusesDstData = ((rop & 0x55) ^ ((rop >> 1) & 0x55));
564
565   /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */
566   /* Only one operation can be pending at a time. */
567
568   GFX_WAIT_PENDING;
569   WRITE_REG16(GP_RASTER_MODE, rop16);
570}
571
572/*
573//---------------------------------------------------------------------------
574// GFX_SOLID_FILL
575//
576// This routine MUST be used when performing a solid rectangle fill with
577// the ROPs of PATCOPY (0xF0), BLACKNESS (0x00), WHITENESS (0xFF), or
578// PATINVERT (0x0F).  There is a bug in GXm for these cases that requires a
579// workaround.
580//
581// For BLACKNESS (ROP = 0x00), set the color to 0x0000.
582// For WHITENESS (ROP = 0xFF), set the color to 0xFFFF.
583// For PATINVERT (ROP = 0x0F), invert the desired color.
584//
585//      X               screen X position (left)
586//      Y               screen Y position (top)
587//      WIDTH           width of rectangle, in pixels
588//      HEIGHT          height of rectangle, in scanlines
589//      COLOR           fill color
590//
591// THIS ROUTINE SHOULD NOT BE DIRECTLY CALLED FROM THE DRIVER.  The driver
592// should always use GFX_pattern_fill and let that routine call this one
593// when approipriate.  This is to hide quirks specific to MediaGX hardware.
594//---------------------------------------------------------------------------
595*/
596void
597gu1_solid_fill(unsigned short x, unsigned short y,
598	       unsigned short width, unsigned short height,
599	       unsigned long color)
600{
601   unsigned short section;
602
603   /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
604   /* Only one operation can be pending at a time. */
605
606   GFX_WAIT_PENDING;
607
608   /* SET REGISTERS TO DRAW RECTANGLE */
609
610   WRITE_REG16(GP_DST_XCOOR, x);
611   WRITE_REG16(GP_DST_YCOOR, y);
612   WRITE_REG16(GP_HEIGHT, height);
613   WRITE_REG16(GP_RASTER_MODE, 0x00F0);	/* PATCOPY */
614   WRITE_REG16(GP_PAT_COLOR_0, (unsigned short)color);
615
616   /* CHECK WIDTH FOR GX BUG WORKAROUND */
617
618   if (width <= 16) {
619      /* OK TO DRAW SMALL RECTANGLE IN ONE PASS */
620
621      WRITE_REG16(GP_WIDTH, width);
622      WRITE_REG16(GP_BLIT_MODE, 0);
623   } else {
624      /* DRAW FIRST PART OF RECTANGLE */
625      /* Get to a 16 pixel boundary. */
626
627      section = 0x10 - (x & 0x0F);
628      WRITE_REG16(GP_WIDTH, section);
629      WRITE_REG16(GP_BLIT_MODE, 0);
630
631      /* POLL UNTIL ABLE TO LOAD THE SECOND RECTANGLE */
632
633      GFX_WAIT_PENDING;
634      WRITE_REG16(GP_DST_XCOOR, x + section);
635      WRITE_REG16(GP_DST_YCOOR, y);
636      WRITE_REG16(GP_WIDTH, width - section);
637      WRITE_REG16(GP_BLIT_MODE, 0);
638   }
639}
640
641/*
642//----------------------------------------------------------------------------
643// GFX_PATTERN_FILL
644//
645// This routine is used to fill a rectangular region.  The pattern must
646// be previously loaded using one of GFX_load_*_pattern routines.  Also, the
647// raster operation must be previously specified using the
648// "GFX_load_raster_operation" routine.
649//
650//      X               screen X position (left)
651//      Y               screen Y position (top)
652//      WIDTH           width of rectangle, in pixels
653//      HEIGHT          height of rectangle, in scanlines
654//----------------------------------------------------------------------------
655*/
656#if GFX_2DACCEL_DYNAMIC
657void
658gu1_pattern_fill(unsigned short x, unsigned short y,
659		 unsigned short width, unsigned short height)
660#else
661void
662gfx_pattern_fill(unsigned short x, unsigned short y,
663		 unsigned short width, unsigned short height)
664#endif
665{
666   unsigned short section, buffer_width, blit_mode;
667
668   /* CHECK IF OPTIMIZED SOLID CASES */
669   /* Check all 16 bits of the ROP to include solid pattern flags. */
670
671   switch (GFXsavedRop) {
672      /* CHECK FOR SPECIAL CASES WITHOUT DESTINATION DATA */
673      /* Need hardware workaround for fast "burst write" cases. */
674
675   case 0x00F0:
676      gu1_solid_fill(x, y, width, height, (unsigned short)GFXsavedColor);
677      break;
678   case 0x000F:
679      gu1_solid_fill(x, y, width, height, (unsigned short)~GFXsavedColor);
680      break;
681   case 0x0000:
682      gu1_solid_fill(x, y, width, height, 0x0000);
683      break;
684   case 0x00FF:
685      gu1_solid_fill(x, y, width, height, 0xFFFF);
686      break;
687
688      /* REMAINING CASES REQUIRE DESTINATION DATA OR NOT SOLID COLOR */
689
690   default:
691
692      /* DETERMINE BLT MODE VALUE */
693      /* Still here for non-solid patterns without destination data. */
694
695      blit_mode = GFXusesDstData ? BM_READ_DST_FB0 : 0;
696
697      /* SET SOURCE EXPANSION MODE */
698      /* If the ROP requires source data, then the source data is all 1's */
699      /* and then expanded into the desired color in GP_SRC_COLOR_1. */
700
701      blit_mode |= BM_SOURCE_EXPAND;
702
703      /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
704      /* Write the registers that do not change for each section. */
705
706      GFX_WAIT_PENDING;
707      WRITE_REG16(GP_HEIGHT, height);
708
709      /* SINCE ONLY DESTINATION DATA, WE CAN USE BOTH BB0 AND BB1. */
710      /* Therefore, width available = BLT buffer width * 2. */
711
712      buffer_width = GFXbufferWidthPixels << 1;
713
714      /* REPEAT UNTIL FINISHED WITH RECTANGLE */
715      /* Perform BLT in vertical sections, as wide as the BLT buffer */
716      /* allows.  Hardware does not split the operations, so */
717      /* software must do it to avoid large scanlines that would */
718      /* overflow the BLT buffers. */
719
720      while (width > 0) {
721	 /* DETERMINE WIDTH OF SECTION */
722
723	 if (width > buffer_width)
724	    section = buffer_width;
725	 else
726	    section = width;
727
728	 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
729
730	 GFX_WAIT_PENDING;
731	 WRITE_REG16(GP_DST_XCOOR, x);
732	 WRITE_REG16(GP_DST_YCOOR, y);
733	 WRITE_REG16(GP_WIDTH, section);
734	 WRITE_REG16(GP_BLIT_MODE, blit_mode);
735
736	 /* ADJUST PARAMETERS FOR NEXT SECTION */
737
738	 width -= section;
739	 x += section;
740      }
741      break;
742   }
743}
744
745/*
746//----------------------------------------------------------------------------
747// GFX_COLOR_PATTERN_FILL
748//
749// This routine is used to render a rectangle using the current raster
750// operation and the specified color pattern.  It allows an 8x8 color
751// pattern to be rendered without multiple calls to the gfx_set_color_pattern
752// and gfx_pattern_fill routines.
753//
754//      X               screen X position (left)
755//      Y               screen Y position (top)
756//      WIDTH           width of rectangle, in pixels
757//      HEIGHT          height of rectangle, in scanlines
758//      *PATTERN		pointer to 8x8 color pattern data
759//----------------------------------------------------------------------------
760*/
761#if GFX_2DACCEL_DYNAMIC
762void
763gu1_color_pattern_fill(unsigned short x, unsigned short y,
764		       unsigned short width, unsigned short height,
765		       unsigned long *pattern)
766#else
767void
768gfx_color_pattern_fill(unsigned short x, unsigned short y,
769		       unsigned short width, unsigned short height,
770		       unsigned long *pattern)
771#endif
772{
773   unsigned short blit_mode, passes, cur_y, pat_y, i;
774   unsigned short buffer_width, line_width;
775   unsigned short bpp_shift, section, cur_x;
776
777   /* SET APPROPRIATE INCREMENT */
778
779   bpp_shift = (GFXbpp > 8) ? 2 : 1;
780
781   /* SET DESTINATION REQUIRED */
782
783   blit_mode = GFXusesDstData ? BM_READ_DST_FB0 : 0;
784
785   /* SET SOURCE EXPANSION */
786
787   blit_mode |= BM_SOURCE_EXPAND;
788
789   /* OVERRIDE RASTER MODE TO FORCE A COLOR PATTERN */
790
791   GFX_WAIT_PENDING;
792   WRITE_REG16(GP_RASTER_MODE,
793	       (GFXsavedRop & ~RM_PAT_MASK & ~RM_PAT_TRANSPARENT) |
794	       RM_PAT_COLOR);
795
796   /* WRITE THE REGISTERS THAT DO NOT CHANGE         */
797   /* If destination data is required, the width and */
798   /* x position will be overwritten.                */
799
800   WRITE_REG16(GP_HEIGHT, 1);
801   WRITE_REG16(GP_WIDTH, width);
802   WRITE_REG16(GP_DST_XCOOR, x);
803
804   /* THE ENTIRE PATTERN WILL NOT BE DRAWN IF THE HEIGHT IS LESS THAN 8 */
805
806   passes = (height < 8) ? height : 8;
807
808   /* SINCE ONLY DESTINATION DATA, WE CAN USE BOTH BB0 AND BB1. */
809   /* Therefore, width available = BLT buffer width * 2. */
810
811   buffer_width = GFXbufferWidthPixels << 1;
812
813   for (i = 0; i < passes; i++) {
814      pat_y = ((y + i) & 7) << bpp_shift;
815      cur_y = y + i;
816
817      /* WRITE THE PATTERN DATA FOR THE ACTIVE LINE */
818
819      GFX_WAIT_PENDING;
820      WRITE_REG32(GP_PAT_DATA_0, pattern[pat_y]);
821      WRITE_REG32(GP_PAT_DATA_1, pattern[pat_y + 1]);
822
823      if (GFXbpp > 8) {
824	 WRITE_REG32(GP_PAT_DATA_2, pattern[pat_y + 2]);
825	 WRITE_REG32(GP_PAT_DATA_3, pattern[pat_y + 3]);
826      }
827
828      /* SPLIT BLT LINE INTO SECTIONS IF REQUIRED              */
829      /* If no destination data is required, we can ignore     */
830      /* the BLT buffers.  Otherwise, we must separate the BLT */
831      /* so as not to overflow the buffers                     */
832
833      if (blit_mode & BM_READ_DST_BB0) {
834	 line_width = width;
835	 cur_x = x;
836
837	 while (line_width) {
838	    section = (line_width > buffer_width) ? buffer_width : line_width;
839	    cur_y = y + i;
840
841	    GFX_WAIT_PENDING;
842	    WRITE_REG16(GP_DST_XCOOR, cur_x);
843	    WRITE_REG16(GP_WIDTH, section);
844
845	    while (cur_y < y + height) {
846	       GFX_WAIT_PENDING;
847	       WRITE_REG16(GP_DST_YCOOR, cur_y);
848	       WRITE_REG16(GP_BLIT_MODE, blit_mode);
849	       cur_y += 8;
850	    }
851
852	    cur_x += section;
853	    line_width -= section;
854	 }
855
856      } else {
857	 while (cur_y < y + height) {
858	    GFX_WAIT_PENDING;
859	    WRITE_REG16(GP_DST_YCOOR, cur_y);
860	    WRITE_REG16(GP_BLIT_MODE, blit_mode);
861	    cur_y += 8;
862	 }
863      }
864
865   }
866
867   /* RESTORE ORIGINAL ROP AND FLAGS */
868
869   GFX_WAIT_PENDING;
870   WRITE_REG16(GP_RASTER_MODE, GFXsavedRop);
871
872}
873
874/*
875//----------------------------------------------------------------------------
876// SCREEN TO SCREEN BLT
877//
878// This routine should be used to perform a screen to screen BLT when the
879// ROP does not require destination data.
880//
881//      SRCX            screen X position to copy from
882//      SRCY            screen Y position to copy from
883//      DSTX            screen X position to copy to
884//      DSTY            screen Y position to copy to
885//      WIDTH           width of rectangle, in pixels
886//      HEIGHT          height of rectangle, in scanlines
887//----------------------------------------------------------------------------
888*/
889#if GFX_2DACCEL_DYNAMIC
890void
891gu1_screen_to_screen_blt(unsigned short srcx, unsigned short srcy,
892			 unsigned short dstx, unsigned short dsty,
893			 unsigned short width, unsigned short height)
894#else
895void
896gfx_screen_to_screen_blt(unsigned short srcx, unsigned short srcy,
897			 unsigned short dstx, unsigned short dsty,
898			 unsigned short width, unsigned short height)
899#endif
900{
901   unsigned short section, buffer_width;
902   unsigned short blit_mode;
903
904   /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA */
905
906   blit_mode = GFXusesDstData ? BM_READ_DST_FB1 | BM_READ_SRC_FB :
907	 BM_READ_SRC_FB;
908
909   /* CHECK Y DIRECTION */
910   /* Hardware has support for negative Y direction. */
911
912   if (dsty > srcy) {
913      blit_mode |= BM_REVERSE_Y;
914      srcy += height - 1;
915      dsty += height - 1;
916   }
917
918   /* CHECK X DIRECTION */
919   /* Hardware does not support negative X direction since at the time */
920   /* of development all supported resolutions could fit a scanline of */
921   /* data at once into the BLT buffers (using both BB0 and BB1).  This */
922   /* code is more generic to allow for any size BLT buffer. */
923
924   if (dstx > srcx) {
925      srcx += width;
926      dstx += width;
927   }
928
929   /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
930   /* Write the registers that do not change for each section. */
931
932   GFX_WAIT_PENDING;
933   WRITE_REG16(GP_HEIGHT, height);
934
935   /* CHECK AVAILABLE BLT BUFFER SIZE */
936   /* Can use both BLT buffers if no destination data is required. */
937
938   buffer_width = GFXusesDstData ? GFXbufferWidthPixels :
939	 GFXbufferWidthPixels << 1;
940
941   /* REPEAT UNTIL FINISHED WITH RECTANGLE */
942   /* Perform BLT in vertical sections, as wide as the BLT buffer allows. */
943   /* Hardware does not split the operations, so software must do it to */
944   /* avoid large scanlines that would overflow the BLT buffers. */
945
946   while (width > 0) {
947      /* CHECK WIDTH OF CURRENT SECTION */
948
949      if (width > buffer_width)
950	 section = buffer_width;
951      else
952	 section = width;
953
954      /* PROGRAM REGISTERS THAT ARE THE SAME FOR EITHER X DIRECTION */
955
956      GFX_WAIT_PENDING;
957      WRITE_REG16(GP_SRC_YCOOR, srcy);
958      WRITE_REG16(GP_DST_YCOOR, dsty);
959      WRITE_REG16(GP_WIDTH, section);
960
961      /* CHECK X DIRECTION */
962
963      if (dstx > srcx) {
964	 /* NEGATIVE X DIRECTION */
965	 /* Still positive X direction within the section. */
966
967	 srcx -= section;
968	 dstx -= section;
969	 WRITE_REG16(GP_SRC_XCOOR, srcx);
970	 WRITE_REG16(GP_DST_XCOOR, dstx);
971	 WRITE_REG16(GP_BLIT_MODE, blit_mode);
972      } else {
973	 /* POSITIVE X DIRECTION */
974
975	 WRITE_REG16(GP_SRC_XCOOR, srcx);
976	 WRITE_REG16(GP_DST_XCOOR, dstx);
977	 WRITE_REG16(GP_BLIT_MODE, blit_mode);
978	 dstx += section;
979	 srcx += section;
980      }
981      width -= section;
982   }
983}
984
985/*
986//----------------------------------------------------------------------------
987// SCREEN TO SCREEN TRANSPARENT BLT
988//
989// This routine should be used to perform a screen to screen BLT when a
990// specified color should by transparent.  The only supported ROP is SRCCOPY.
991//
992//      SRCX            screen X position to copy from
993//      SRCY            screen Y position to copy from
994//      DSTX            screen X position to copy to
995//      DSTY            screen Y position to copy to
996//      WIDTH           width of rectangle, in pixels
997//      HEIGHT          height of rectangle, in scanlines
998//      COLOR           transparent color
999//----------------------------------------------------------------------------
1000*/
1001#if GFX_2DACCEL_DYNAMIC
1002void
1003gu1_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy,
1004			  unsigned short dstx, unsigned short dsty,
1005			  unsigned short width, unsigned short height,
1006			  unsigned long color)
1007#else
1008void
1009gfx_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy,
1010			  unsigned short dstx, unsigned short dsty,
1011			  unsigned short width, unsigned short height,
1012			  unsigned long color)
1013#endif
1014{
1015   unsigned short section, buffer_width;
1016   unsigned short blit_mode = BM_READ_SRC_FB;
1017
1018   /* CHECK Y DIRECTION */
1019   /* Hardware has support for negative Y direction. */
1020
1021   if (dsty > srcy) {
1022      blit_mode |= BM_REVERSE_Y;
1023      srcy += height - 1;
1024      dsty += height - 1;
1025   }
1026
1027   /* CHECK X DIRECTION */
1028   /* Hardware does not support negative X direction since at the time */
1029   /* of development all supported resolutions could fit a scanline of */
1030   /* data at once into the BLT buffers (using both BB0 and BB1).  This */
1031   /* code is more generic to allow for any size BLT buffer. */
1032
1033   if (dstx > srcx) {
1034      srcx += width;
1035      dstx += width;
1036   }
1037
1038   /* CALCULATE BLT BUFFER SIZE */
1039   /* Need to use BB1 to store the BLT buffer data. */
1040
1041   buffer_width = GFXbufferWidthPixels;
1042
1043   /* WRITE TRANSPARENCY COLOR TO BLT BUFFER 1 */
1044
1045   if (GFXbpp == 8) {
1046      color &= 0x00FF;
1047      color |= (color << 8);
1048   }
1049   color = (color & 0x0000FFFF) | (color << 16);
1050
1051   /* WAIT UNTIL PIPELINE IS NOT BUSY BEFORE LOADING DATA INTO BB1 */
1052   /* Need to make sure any previous BLT using BB1 is complete. */
1053   /* Only need to load 32 bits of BB1 for the 1 pixel BLT that follows. */
1054
1055   GFX_WAIT_BUSY;
1056   WRITE_SCRATCH32(GFXbb1Base, color);
1057
1058   /* DO BOGUS BLT TO LATCH DATA FROM BB1 */
1059   /* Already know graphics pipeline is idle. */
1060   /* Only need to latch data into the holding registers for the current */
1061   /* data from BB1.  A 1 pixel wide BLT will suffice. */
1062
1063   WRITE_REG32(GP_DST_XCOOR, 0);
1064   WRITE_REG32(GP_SRC_XCOOR, 0);
1065   WRITE_REG32(GP_WIDTH, 0x00010001);
1066   WRITE_REG16(GP_RASTER_MODE, 0x00CC);
1067   WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_FB | BM_READ_DST_BB1);
1068
1069   /* WRITE REGISTERS FOR REAL SCREEN TO SCREEN BLT */
1070
1071   GFX_WAIT_PENDING;
1072   WRITE_REG16(GP_HEIGHT, height);
1073   WRITE_REG16(GP_RASTER_MODE, 0x10C6);
1074   WRITE_REG32(GP_PAT_COLOR_0, 0xFFFFFFFF);
1075
1076   /* REPEAT UNTIL FINISHED WITH RECTANGLE */
1077   /* Perform BLT in vertical sections, as wide as the BLT buffer allows. */
1078   /* Hardware does not split the operations, so software must do it to */
1079   /* avoid large scanlines that would overflow the BLT buffers. */
1080
1081   while (width > 0) {
1082      /* CHECK WIDTH OF CURRENT SECTION */
1083
1084      if (width > buffer_width)
1085	 section = buffer_width;
1086      else
1087	 section = width;
1088
1089      /* PROGRAM REGISTERS THAT ARE THE SAME FOR EITHER X DIRECTION */
1090
1091      GFX_WAIT_PENDING;
1092      WRITE_REG16(GP_SRC_YCOOR, srcy);
1093      WRITE_REG16(GP_DST_YCOOR, dsty);
1094      WRITE_REG16(GP_WIDTH, section);
1095
1096      /* CHECK X DIRECTION */
1097      /* Again, this must be done in software, and can be removed if the */
1098      /* display driver knows that the BLT buffers will always be large  */
1099      /* enough to contain an entire scanline of a screen to screen BLT. */
1100
1101      if (dstx > srcx) {
1102	 /* NEGATIVE X DIRECTION */
1103	 /* Still positive X direction within the section. */
1104
1105	 srcx -= section;
1106	 dstx -= section;
1107	 WRITE_REG16(GP_SRC_XCOOR, srcx);
1108	 WRITE_REG16(GP_DST_XCOOR, dstx);
1109	 WRITE_REG16(GP_BLIT_MODE, blit_mode);
1110      } else {
1111	 /* POSITIVE X DIRECTION */
1112
1113	 WRITE_REG16(GP_SRC_XCOOR, srcx);
1114	 WRITE_REG16(GP_DST_XCOOR, dstx);
1115	 WRITE_REG16(GP_BLIT_MODE, blit_mode);
1116	 dstx += section;
1117	 srcx += section;
1118      }
1119      width -= section;
1120   }
1121}
1122
1123/*
1124//----------------------------------------------------------------------------
1125// COLOR BITMAP TO SCREEN BLT
1126//
1127// This routine transfers color bitmap data to the screen.  For most cases,
1128// when the ROP is SRCCOPY, it may be faster to write a separate routine that
1129// copies the data to the frame buffer directly.  This routine should be
1130// used when the ROP requires destination data.
1131//
1132// Transparency is handled by another routine.
1133//
1134//      SRCX            X offset within source bitmap
1135//      SRCY            Y offset within source bitmap
1136//      DSTX            screen X position to render data
1137//      DSTY            screen Y position to render data
1138//      WIDTH           width of rectangle, in pixels
1139//      HEIGHT          height of rectangle, in scanlines
1140//      *DATA           pointer to bitmap data
1141//      PITCH           pitch of bitmap data (bytes between scanlines)
1142//----------------------------------------------------------------------------
1143*/
1144
1145#if GFX_2DACCEL_DYNAMIC
1146void
1147gu1_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
1148			       unsigned short dstx, unsigned short dsty,
1149			       unsigned short width, unsigned short height,
1150			       unsigned char *data, long pitch)
1151#else
1152void
1153gfx_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
1154			       unsigned short dstx, unsigned short dsty,
1155			       unsigned short width, unsigned short height,
1156			       unsigned char *data, long pitch)
1157#endif
1158{
1159   unsigned short section, buffer_width;
1160   unsigned short blit_mode = BM_READ_SRC_BB0;
1161   unsigned short temp_height;
1162   unsigned long dword_bytes_needed, bytes_extra;
1163   unsigned long bpp_shift;
1164   long array_offset;
1165
1166   /* CHECK SIZE OF BLT BUFFER */
1167
1168   buffer_width = GFXbufferWidthPixels;
1169
1170   /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA */
1171   /* If no destination data, we have twice the room for  */
1172   /* source data.                                        */
1173
1174   if (GFXusesDstData)
1175      blit_mode |= BM_READ_DST_FB1;
1176   else
1177      buffer_width <<= 1;
1178
1179   /* SET THE SCRATCHPAD BASE */
1180
1181   SET_SCRATCH_BASE(GFXbb0Base);
1182
1183   /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS                */
1184   /* Write the registers that do not change for each section. */
1185
1186   GFX_WAIT_PENDING;
1187   WRITE_REG16(GP_HEIGHT, 1);
1188
1189   bpp_shift = (GFXbpp + 7) >> 4;
1190
1191   while (width > 0) {
1192      if (width > buffer_width)
1193	 section = buffer_width;
1194      else
1195	 section = width;
1196
1197      dword_bytes_needed = (section << bpp_shift) & ~3l;
1198      bytes_extra = (section << bpp_shift) & 3l;
1199
1200      temp_height = height;
1201
1202      /* WRITE THE REGISTERS FOR EACH SECTION                          */
1203      /* The GX hardware will auto-increment the Y coordinate, meaning */
1204      /* that we don't have to.                                        */
1205
1206      WRITE_REG16(GP_WIDTH, section);
1207      WRITE_REG16(GP_DST_XCOOR, dstx);
1208      WRITE_REG16(GP_DST_YCOOR, dsty);
1209
1210      /* CALCULATE THE BITMAP OFFSET */
1211
1212      array_offset =
1213	    (unsigned long)srcy *(long)pitch + ((long)srcx << bpp_shift);
1214
1215      while (temp_height--) {
1216	 GFX_WAIT_PIPELINE;
1217
1218	 /* WRITE ALL DATA TO THE BLT BUFFERS */
1219	 /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */
1220	 /* scratchpad offset set by the SET_SCRATCH_BASE macro.               */
1221
1222	 WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data,
1223			      array_offset);
1224	 WRITE_REG16(GP_BLIT_MODE, blit_mode);
1225
1226	 array_offset += pitch;
1227      }
1228
1229      width -= section;
1230      srcx += section;
1231      dstx += section;
1232   }
1233}
1234
1235/*
1236//----------------------------------------------------------------------------
1237// COLOR BITMAP TO SCREEN TRANSPARENT BLT
1238//
1239// This routine transfers color bitmap data to the screen with transparency.
1240// The transparent color is specified.  The only supported ROP is SRCCOPY,
1241// meaning that transparency cannot be applied if the ROP requires
1242// destination data (this is a hardware restriction).
1243//
1244//      SRCX            X offset within source bitmap
1245//      SRCY            Y offset within source bitmap
1246//      DSTX            screen X position to render data
1247//      DSTY            screen Y position to render data
1248//      WIDTH           width of rectangle, in pixels
1249//      HEIGHT          height of rectangle, in scanlines
1250//      *DATA           pointer to bitmap data
1251//      PITCH           pitch of bitmap data (bytes between scanlines)
1252//      COLOR           transparent color
1253//----------------------------------------------------------------------------
1254*/
1255#if GFX_2DACCEL_DYNAMIC
1256void
1257gu1_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy,
1258				unsigned short dstx, unsigned short dsty,
1259				unsigned short width, unsigned short height,
1260				unsigned char *data, long pitch,
1261				unsigned long color)
1262#else
1263void
1264gfx_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy,
1265				unsigned short dstx, unsigned short dsty,
1266				unsigned short width, unsigned short height,
1267				unsigned char *data, long pitch,
1268				unsigned long color)
1269#endif
1270{
1271   unsigned short section, buffer_width;
1272   unsigned short temp_height;
1273   unsigned long dword_bytes_needed, bytes_extra;
1274   unsigned long bpp_shift;
1275   long array_offset;
1276
1277   /* CHECK SIZE OF BLT BUFFER */
1278
1279   buffer_width = GFXbufferWidthPixels;
1280
1281   /* WRITE TRANSPARENCY COLOR TO BLT BUFFER 1 */
1282
1283   if (GFXbpp == 8) {
1284      color &= 0x00FF;
1285      color |= (color << 8);
1286   }
1287   color = (color & 0x0000FFFF) | (color << 16);
1288
1289   /* WAIT UNTIL PIPELINE IS NOT BUSY BEFORE LOADING DATA INTO BB1 */
1290   /* Need to make sure any previous BLT using BB1 is complete. */
1291   /* Only need to load 32 bits of BB1 for the 1 pixel BLT that follows. */
1292
1293   GFX_WAIT_PIPELINE;
1294   GFX_WAIT_PENDING;
1295   WRITE_SCRATCH32(GFXbb1Base, color);
1296
1297   /* DO BOGUS BLT TO LATCH DATA FROM BB1 */
1298   /* Already know graphics pipeline is idle. */
1299   /* Only need to latch data into the holding registers for the current */
1300   /* data from BB1.  A 1 pixel wide BLT will suffice. */
1301
1302   WRITE_REG32(GP_DST_XCOOR, 0);
1303   WRITE_REG32(GP_SRC_XCOOR, 0);
1304   WRITE_REG32(GP_WIDTH, 0x00010001);
1305   WRITE_REG16(GP_RASTER_MODE, 0x00CC);
1306   WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_FB | BM_READ_DST_BB1);
1307
1308   /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
1309   /* Write the registers that do not change for each section. */
1310
1311   GFX_WAIT_PENDING;
1312   WRITE_REG16(GP_HEIGHT, 1);
1313   WRITE_REG16(GP_RASTER_MODE, 0x10C6);
1314   WRITE_REG32(GP_PAT_COLOR_0, 0xFFFFFFFF);
1315
1316   bpp_shift = (GFXbpp + 7) >> 4;
1317
1318   /* SET THE SCRATCHPAD BASE */
1319
1320   SET_SCRATCH_BASE(GFXbb0Base);
1321
1322   while (width > 0) {
1323      if (width > buffer_width)
1324	 section = buffer_width;
1325      else
1326	 section = width;
1327
1328      dword_bytes_needed = (section << bpp_shift) & ~3l;
1329      bytes_extra = (section << bpp_shift) & 3l;
1330
1331      temp_height = height;
1332
1333      /* WRITE THE REGISTERS FOR EACH SECTION                          */
1334      /* The GX hardware will auto-increment the Y coordinate, meaning */
1335      /* that we don't have to.                                        */
1336
1337      WRITE_REG16(GP_WIDTH, section);
1338      WRITE_REG16(GP_DST_XCOOR, dstx);
1339      WRITE_REG16(GP_DST_YCOOR, dsty);
1340
1341      /* CALCULATE THE BITMAP OFFSET */
1342
1343      array_offset =
1344	    (unsigned long)srcy *(long)pitch + ((long)srcx << bpp_shift);
1345
1346      while (temp_height--) {
1347	 GFX_WAIT_PIPELINE;
1348
1349	 /* WRITE ALL DATA TO THE BLT BUFFERS */
1350	 /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */
1351	 /* scratchpad offset set by the SET_SCRATCH_BASE macro.               */
1352
1353	 WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data,
1354			      array_offset);
1355	 WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_BB0);
1356
1357	 array_offset += pitch;
1358      }
1359
1360      width -= section;
1361      srcx += section;
1362      dstx += section;
1363   }
1364}
1365
1366/*
1367//----------------------------------------------------------------------------
1368// MONOCHROME BITMAP TO SCREEN BLT
1369//
1370// This routine transfers monochrome bitmap data to the screen.
1371//
1372//      SRCX            X offset within source bitmap
1373//      SRCY            Y offset within source bitmap
1374//      DSTX            screen X position to render data
1375//      DSTY            screen Y position to render data
1376//      WIDTH           width of rectangle, in pixels
1377//      HEIGHT          height of rectangle, in scanlines
1378//      *DATA           pointer to bitmap data
1379//      PITCH           pitch of bitmap data (bytes between scanlines)
1380//----------------------------------------------------------------------------
1381*/
1382#if GFX_2DACCEL_DYNAMIC
1383void
1384gu1_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
1385			      unsigned short dstx, unsigned short dsty,
1386			      unsigned short width, unsigned short height,
1387			      unsigned char *data, short pitch)
1388#else
1389void
1390gfx_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
1391			      unsigned short dstx, unsigned short dsty,
1392			      unsigned short width, unsigned short height,
1393			      unsigned char *data, short pitch)
1394#endif
1395{
1396   unsigned short section, buffer_width;
1397   unsigned short blit_mode = BM_READ_SRC_BB0 | BM_SOURCE_EXPAND;
1398   unsigned short temp_height;
1399   unsigned long dword_bytes_needed, bytes_extra;
1400   long array_offset;
1401
1402   /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA        */
1403   /* If no destination data, the source data will always fit.   */
1404   /* So, in that event we will set the buffer width to a        */
1405   /* fictitiously large value such that the BLT is never split. */
1406
1407   if (GFXusesDstData) {
1408      buffer_width = GFXbufferWidthPixels;
1409      blit_mode |= BM_READ_DST_FB1;
1410   } else
1411      buffer_width = 3200;
1412
1413   /* CHECK IF DATA ALREADY IN BLIT BUFFER */
1414   /* If the pointer is NULL, data for the full BLT is already there */
1415   /* WARNING: This could cause problems if destination data is */
1416   /* involved and it overflows the BLT buffer.  Need to remove */
1417   /* this option and change the drivers to use a temporary buffer. */
1418
1419   if (!data) {
1420      GFX_WAIT_PENDING;
1421      WRITE_REG16(GP_SRC_XCOOR, srcx & 7);
1422      WRITE_REG16(GP_DST_XCOOR, dstx);
1423      WRITE_REG16(GP_DST_YCOOR, dsty);
1424      WRITE_REG16(GP_WIDTH, width);
1425      WRITE_REG16(GP_HEIGHT, height);
1426      WRITE_REG16(GP_BLIT_MODE, blit_mode);
1427      return;
1428   }
1429
1430   /* SET THE SCRATCHPAD BASE */
1431
1432   SET_SCRATCH_BASE(GFXbb0Base);
1433
1434   /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
1435   /* Write the registers that do not change for each section. */
1436
1437   GFX_WAIT_PENDING;
1438   WRITE_REG16(GP_HEIGHT, 1);
1439
1440   while (width > 0) {
1441      if (width > buffer_width)
1442	 section = buffer_width;
1443      else
1444	 section = width;
1445
1446      /* CALCULATE BYTES NEEDED */
1447      /* Add 1 for possible alignment issues. */
1448
1449      dword_bytes_needed = ((section + 7 + (srcx & 7)) >> 3) & ~3l;
1450      bytes_extra = ((section + 7 + (srcx & 7)) >> 3) & 3l;
1451
1452      temp_height = height;
1453
1454      /* WRITE THE REGISTERS FOR EACH SECTION                          */
1455      /* The GX hardware will auto-increment the Y coordinate, meaning */
1456      /* that we don't have to.                                        */
1457
1458      WRITE_REG16(GP_WIDTH, section);
1459      WRITE_REG16(GP_DST_XCOOR, dstx);
1460      WRITE_REG16(GP_DST_YCOOR, dsty);
1461      WRITE_REG16(GP_SRC_XCOOR, srcx & 7);
1462
1463      /* CALCULATE THE BITMAP OFFSET */
1464
1465      array_offset = (unsigned long)srcy *(long)pitch + ((long)srcx >> 3);
1466
1467      while (temp_height--) {
1468	 GFX_WAIT_PIPELINE;
1469
1470	 /* WRITE ALL DATA TO THE BLT BUFFERS */
1471	 /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */
1472	 /* scratchpad offset set by the SET_SCRATCH_BASE macro.               */
1473
1474	 WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data,
1475			      array_offset);
1476	 WRITE_REG16(GP_BLIT_MODE, blit_mode);
1477
1478	 array_offset += pitch;
1479      }
1480
1481      width -= section;
1482      srcx += section;
1483      dstx += section;
1484   }
1485}
1486
1487/*
1488//----------------------------------------------------------------------------
1489// MONOCHROME TEXT BLT
1490//
1491// This routine transfers contiguous monochrome text data to the screen.
1492//
1493//      DSTX            screen X position to render data
1494//      DSTY            screen Y position to render data
1495//      WIDTH           width of rectangle, in pixels
1496//      HEIGHT          height of rectangle, in scanlines
1497//      *DATA           pointer to bitmap data
1498//----------------------------------------------------------------------------
1499*/
1500#if GFX_2DACCEL_DYNAMIC
1501void
1502gu1_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width,
1503	     unsigned short height, unsigned char *data)
1504#else
1505void
1506gfx_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width,
1507	     unsigned short height, unsigned char *data)
1508#endif
1509{
1510   unsigned long dword_bytes_needed, bytes_extra;
1511   long pitch, buffer_bytes, data_bytes;
1512
1513   /* CALCULATE DATA SIZE */
1514
1515   pitch = (width + 7) >> 3;
1516   data_bytes = (long)height *pitch;
1517
1518   /* CHECK FOR SIMPLE CASE */
1519   /* This routine is designed to render a source copy text glyph.  If destination */
1520   /* data is required or the source data will not fit, we will punt the operation */
1521   /* to the more versatile (and slow) mono bitmap routine.                        */
1522
1523   if (GFXbpp > 8)
1524      buffer_bytes = GFXbufferWidthPixels << 1;
1525   else
1526      buffer_bytes = GFXbufferWidthPixels;
1527
1528   if (GFXusesDstData || data_bytes > buffer_bytes) {
1529      gfx_mono_bitmap_to_screen_blt(0, 0, dstx, dsty, width, height, data,
1530				    (short)pitch);
1531      return;
1532   }
1533
1534   /* SET THE SCRATCHPAD BASE */
1535
1536   SET_SCRATCH_BASE(GFXbb0Base);
1537
1538   /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
1539
1540   dword_bytes_needed = data_bytes & ~3l;
1541   bytes_extra = data_bytes & 3l;
1542
1543   GFX_WAIT_PENDING;
1544   WRITE_REG16(GP_HEIGHT, height);
1545   WRITE_REG16(GP_WIDTH, width);
1546   WRITE_REG16(GP_DST_XCOOR, dstx);
1547   WRITE_REG16(GP_DST_YCOOR, dsty);
1548   WRITE_REG16(GP_SRC_XCOOR, 0);
1549
1550   /* WRITE ALL DATA TO THE BLT BUFFERS */
1551   /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */
1552   /* scratchpad offset set by the SET_SCRATCH_BASE macro.               */
1553
1554   GFX_WAIT_PIPELINE;
1555
1556   WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data, 0);
1557   WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_BB0 | BM_SOURCE_TEXT);
1558}
1559
1560/*
1561//----------------------------------------------------------------------------
1562// BRESENHAM LINE
1563//
1564// This routine draws a vector using the specified Bresenham parameters.
1565// Currently this file does not support a routine that accepts the two
1566// endpoints of a vector and calculates the Bresenham parameters.  If it
1567// ever does, this routine is still required for vectors that have been
1568// clipped.
1569//
1570//      X               screen X position to start vector
1571//      Y               screen Y position to start vector
1572//      LENGTH          length of the vector, in pixels
1573//      INITERR         Bresenham initial error term
1574//      AXIALERR        Bresenham axial error term
1575//      DIAGERR         Bresenham diagonal error term
1576//      FLAGS           VM_YMAJOR, VM_MAJOR_INC, VM_MINOR_INC
1577//----------------------------------------------------------------------------
1578*/
1579#if GFX_2DACCEL_DYNAMIC
1580void
1581gu1_bresenham_line(unsigned short x, unsigned short y,
1582		   unsigned short length, unsigned short initerr,
1583		   unsigned short axialerr, unsigned short diagerr,
1584		   unsigned short flags)
1585#else
1586void
1587gfx_bresenham_line(unsigned short x, unsigned short y,
1588		   unsigned short length, unsigned short initerr,
1589		   unsigned short axialerr, unsigned short diagerr,
1590		   unsigned short flags)
1591#endif
1592{
1593   unsigned short vector_mode = flags;
1594
1595   if (GFXusesDstData)
1596      vector_mode |= VM_READ_DST_FB;
1597
1598   /* CHECK NULL LENGTH */
1599
1600   if (!length)
1601      return;
1602
1603   /* LOAD THE REGISTERS FOR THE VECTOR */
1604
1605   GFX_WAIT_PENDING;
1606   WRITE_REG16(GP_DST_XCOOR, x);
1607   WRITE_REG16(GP_DST_YCOOR, y);
1608   WRITE_REG16(GP_VECTOR_LENGTH, length);
1609   WRITE_REG16(GP_INIT_ERROR, initerr);
1610   WRITE_REG16(GP_AXIAL_ERROR, axialerr);
1611   WRITE_REG16(GP_DIAG_ERROR, diagerr);
1612   WRITE_REG16(GP_VECTOR_MODE, vector_mode);
1613}
1614
1615/*---------------------------------------------------------------------------
1616 * GFX_WAIT_UNTIL_IDLE
1617 *
1618 * This routine waits until the graphics engine is idle.  This is required
1619 * before allowing direct access to the frame buffer.
1620 *---------------------------------------------------------------------------
1621 */
1622#if GFX_2DACCEL_DYNAMIC
1623void
1624gu1_wait_until_idle(void)
1625#else
1626void
1627gfx_wait_until_idle(void)
1628#endif
1629{
1630   GFX_WAIT_BUSY;
1631}
1632
1633/*---------------------------------------------------------------------------
1634 * GFX_TEST_BLT_PENDING
1635 *
1636 * This routine returns 1 if a BLT is pending, meaning that a call to
1637 * perform a rendering operation would stall.  Otherwise it returns 0.
1638 * It is used by Darwin during random testing to only start a BLT
1639 * operation when it knows the Durango routines won't spin on graphics
1640 * (so Darwin can continue to do frame buffer reads and writes).
1641 *---------------------------------------------------------------------------
1642 */
1643#if GFX_2DACCEL_DYNAMIC
1644int
1645gu1_test_blt_pending(void)
1646#else
1647int
1648gfx_test_blt_pending(void)
1649#endif
1650{
1651   if (READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING)
1652      return (1);
1653   else
1654      return (0);
1655}
1656
1657/*---------------------------------------------------------------------------
1658 * BLT BUFFERS!!!!!
1659 *---------------------------------------------------------------------------
1660 */
1661
1662/* THE BOOT CODE MUST SET THE BLT BUFFER BASES USING THE "CPU_WRITE" */
1663/* INSTRUCTION TO ONE OF THE FOLLOWING VALUES: */
1664
1665#define BB0_BASE_2K		0x800
1666#define BB1_BASE_2K		0xB30
1667#define BB0_BASE_3K		0x400
1668#define BB1_BASE_3K		0x930
1669
1670/*---------------------------------------------------------------------------
1671 * gu1_detect_blt_buffer_base
1672 *
1673 * This detection is hidden from the driver by being called from the
1674 * "gfx_set_bpp" routine.
1675 *
1676 * This is fairly ugly for the following reasons:
1677 *
1678 * - It is the boot code that must set the BLT buffer bases to the
1679 *   appropriate values and load the scratchpad tags.
1680 * - The old drivers would also set the base address values to what they
1681 *   knew they should be for the 2K or 3K scratchpad configuration.
1682 * - Unfortunately, to set the base addresses requires the use of the
1683 *   CPU_WRITE instruction, an instruction specific to GX.
1684 * - Using the CPU_WRITE instruction requires the use of assembly to
1685 *   produce the appropriate op codes.
1686 * - Assembly is something that is avoided in Durango because it is not
1687 *   platform independent.  Some compilers do not support inline assembly.
1688 * - Therefore Durango cannot use the CPU_WRITE instruction.
1689 * - Therefore drivers using Durango must rely on the boot code to set
1690 *   the appropriate values.  Durango uses this routine to check where
1691 *   the base addresses have been set.
1692 * - Unfortunately, it is not as simple as using IO to check for 2K or 3K
1693 *   scratchpad size.  In VSA1, even though the boot code may set it for
1694 *   3K, SoftVGA comes along and resets it to 2K for it's use in text
1695 *   redraws.  It used to be that the display driver would set it back
1696 *   to 3K.
1697 * - So, the Durango code was changed to just always use 2K.
1698 * - But, the XpressROM code sets it for 3K, and the newer versions of
1699 *   SoftVGA do not interfere with that, so then Durango needs to use
1700 *   the 3K values to work properly.
1701 * - Therefore, Durango does somewhat of a kludge by writing to directly
1702 *   to the scratchpad at both the 2K and 3K locations, then performing
1703 *   a unobtrusive BLT that loads data into BB0 (the graphics engine
1704 *   always knows the true base).  After the BLT, Durango looks to see
1705 *   which location changed to know where the base address is.
1706 * - This is a relatively simple way to allow Durango to work on old
1707 *   and new platforms without using theCPU_WRITE instructions.
1708 *
1709 * To summarize, the BLT buffers are one of the most painful aspects of
1710 * the GX graphics unit design, and have been removed from future designs
1711 * (the graphics unit has its own dedicated RAM).  Durango has tried to
1712 * hide the BLT buffer use from the drivers.
1713 *---------------------------------------------------------------------------
1714 */
1715void
1716gu1_detect_blt_buffer_base(void)
1717{
1718   /* ASSUME 2K */
1719
1720   GFXbb0Base = BB0_BASE_2K;
1721   GFXbb1Base = BB1_BASE_2K;
1722
1723   /* CHECK IF SCRATCHPAD IS SET TO 3K OR 4K */
1724   /* Boot code should still set 3K values for 4K. */
1725
1726   if (gfx_gxm_config_read(GXM_CONFIG_GCR) & 0x08) {
1727      /* WRITE DATA TO 3K LOCATION */
1728
1729      GFX_WAIT_BUSY;
1730      WRITE_SCRATCH32(BB0_BASE_3K, 0xFEEDFACE);
1731
1732      /* HAVE THE GRAPHICS UNIT STORE SOMETHING IN BB0 */
1733
1734      WRITE_REG32(GP_DST_XCOOR, 0x00000000);	/* AT (0,0) */
1735      WRITE_REG32(GP_WIDTH, 0x00010004);	/* 4x1 BLT */
1736      WRITE_REG16(GP_RASTER_MODE, 0x00AA);	/* KEEP DST */
1737      WRITE_REG16(GP_BLIT_MODE, BM_READ_DST_FB0);	/* STORE IN BB0 */
1738
1739      /* CHECK 3K LOCATION */
1740      /* Breaks if data happened to be 0xFEEDFACE - unlikely. */
1741
1742      GFX_WAIT_BUSY;
1743      if (READ_SCRATCH32(BB0_BASE_3K) != 0xFEEDFACE) {
1744	 GFXbb0Base = BB0_BASE_3K;
1745	 GFXbb1Base = BB1_BASE_3K;
1746      }
1747   }
1748}
1749
1750/* END OF FILE */
1751