Add hardware acceleration features for use with the RASTERCONSOLE option.

Code posted on port-sparc by `der Mouse'; it was slightly re-arranged to
fit the layout of this driver.
This commit is contained in:
pk 2000-03-30 13:57:50 +00:00
parent 4b30d9885e
commit a41d265271
5 changed files with 396 additions and 22 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cgsix.c,v 1.46 2000/03/19 15:38:45 pk Exp $ */
/* $NetBSD: cgsix.c,v 1.47 2000/03/30 13:57:51 pk Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -121,6 +121,9 @@
#include <sparc/dev/cgsixvar.h>
#include <sparc/dev/pfourreg.h>
#include <dev/rasops/rasops.h>
#include <dev/wscons/wsconsio.h>
static void cg6_unblank __P((struct device *));
/* cdevsw prototypes */
@ -139,6 +142,8 @@ static struct fbdriver cg6_fbdriver = {
* on anyway.
*
* Actually, the new rasops stuff is a LOT faster! --thorpej
*
* Especially with the cg6 accelerated blits :-) --Mouse
*/
#ifdef RASTERCONSOLE
int cgsix_use_rasterconsole = 1;
@ -150,6 +155,298 @@ static void cg6_loadomap __P((struct cgsix_softc *));
static void cg6_setcursor __P((struct cgsix_softc *));/* set position */
static void cg6_loadcursor __P((struct cgsix_softc *));/* set shape */
/*
* cg6 accelerated console routines.
*
* Note that buried in this code in several places is the assumption
* that pixels are exactly one byte wide. Since this is cg6-specific
* code, this seems safe. This assumption resides in things like the
* use of ri_emuwidth without messing around with ri_pelbytes, or the
* assumption that ri_font->fontwidth is the right thing to multiply
* character-cell counts by to get byte counts.
*/
/*
* Magic values for blitter
*/
/* Value for the alu register for screen-to-screen copies */
#define CG6_ALU_COPY ( \
0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \
| 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \
| 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \
| 0x00000000 /* GX_RAST_BOOL (function unknown) */ \
| 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \
| 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \
| 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \
| 0x0000cccc /* ALU = src */ \
)
/* Value for the alu register for region fills */
#define CG6_ALU_FILL ( \
0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \
| 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \
| 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \
| 0x00000000 /* GX_RAST_BOOL (function unknown) */ \
| 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \
| 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \
| 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \
| 0x0000ff00 /* ALU = fg color */ \
)
/* Value for the alu register for toggling an area */
#define CG6_ALU_FLIP ( \
0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \
| 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \
| 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \
| 0x00000000 /* GX_RAST_BOOL (function unknown) */ \
| 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \
| 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \
| 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \
| 0x00005555 /* ALU = ~dst */ \
)
/*
* Wait for a blit to finish.
* 0x8000000 bit: function unknown; 0x20000000 bit: GX_BLT_INPROGRESS
*/
#define CG6_BLIT_WAIT(fbc) do { \
while (((fbc)->fbc_blit & 0xa0000000) == 0xa0000000) \
/*EMPTY*/; \
} while (0)
/*
* Wait for a drawing operation to finish, or at least get queued.
* 0x8000000 bit: function unknown; 0x20000000 bit: GX_FULL
*/
#define CG6_DRAW_WAIT(fbc) do { \
while (((fbc)->fbc_draw & 0xa0000000) == 0xa0000000) \
/*EMPTY*/; \
} while (0)
/*
* Wait for the whole engine to go idle. This may not matter in our case;
* I'm not sure whether blits are actually queued or not. It more likely
* is intended for lines and such that do get queued.
* 0x10000000 bit: GX_INPROGRESS
*/
#define CG6_DRAIN(fbc) do { \
while ((fbc)->fbc_s & 0x10000000) \
/*EMPTY*/; \
} while (0)
static void
cg6_ras_copyrows(void *cookie, int src, int dst, int n)
{
struct rasops_info *ri;
volatile struct cg6_fbc *fbc;
ri = cookie;
if (dst == src)
return;
if (src < 0) {
n += src;
src = 0;
}
if (src+n > ri->ri_rows)
n = ri->ri_rows - src;
if (dst < 0) {
n += dst;
dst = 0;
}
if (dst+n > ri->ri_rows)
n = ri->ri_rows - dst;
if (n <= 0)
return;
n *= ri->ri_font->fontheight;
src *= ri->ri_font->fontheight;
dst *= ri->ri_font->fontheight;
fbc = ((struct cgsix_softc *)ri->ri_hw)->sc_fbc;
fbc->fbc_clip = 0;
fbc->fbc_s = 0;
fbc->fbc_offx = 0;
fbc->fbc_offy = 0;
fbc->fbc_clipminx = 0;
fbc->fbc_clipminy = 0;
fbc->fbc_clipmaxx = ri->ri_width - 1;
fbc->fbc_clipmaxy = ri->ri_height - 1;
fbc->fbc_alu = CG6_ALU_COPY;
fbc->fbc_x0 = ri->ri_xorigin;
fbc->fbc_y0 = ri->ri_yorigin + src;
fbc->fbc_x1 = ri->ri_xorigin + ri->ri_emuwidth - 1;
fbc->fbc_y1 = ri->ri_yorigin + src + n - 1;
fbc->fbc_x2 = ri->ri_xorigin;
fbc->fbc_y2 = ri->ri_yorigin + dst;
fbc->fbc_x3 = ri->ri_xorigin + ri->ri_emuwidth - 1;
fbc->fbc_y3 = ri->ri_yorigin + dst + n - 1;
CG6_BLIT_WAIT(fbc);
CG6_DRAIN(fbc);
}
static void
cg6_ras_copycols(void *cookie, int row, int src, int dst, int n)
{
struct rasops_info *ri;
volatile struct cg6_fbc *fbc;
ri = cookie;
if (dst == src)
return;
if ((row < 0) || (row >= ri->ri_rows))
return;
if (src < 0) {
n += src;
src = 0;
}
if (src+n > ri->ri_cols)
n = ri->ri_cols - src;
if (dst < 0) {
n += dst;
dst = 0;
}
if (dst+n > ri->ri_cols)
n = ri->ri_cols - dst;
if (n <= 0)
return;
n *= ri->ri_font->fontwidth;
src *= ri->ri_font->fontwidth;
dst *= ri->ri_font->fontwidth;
row *= ri->ri_font->fontheight;
fbc = ((struct cgsix_softc *)ri->ri_hw)->sc_fbc;
fbc->fbc_clip = 0;
fbc->fbc_s = 0;
fbc->fbc_offx = 0;
fbc->fbc_offy = 0;
fbc->fbc_clipminx = 0;
fbc->fbc_clipminy = 0;
fbc->fbc_clipmaxx = ri->ri_width - 1;
fbc->fbc_clipmaxy = ri->ri_height - 1;
fbc->fbc_alu = CG6_ALU_COPY;
fbc->fbc_x0 = ri->ri_xorigin + src;
fbc->fbc_y0 = ri->ri_yorigin + row;
fbc->fbc_x1 = ri->ri_xorigin + src + n - 1;
fbc->fbc_y1 = ri->ri_yorigin + row + ri->ri_font->fontheight - 1;
fbc->fbc_x2 = ri->ri_xorigin + dst;
fbc->fbc_y2 = ri->ri_yorigin + row;
fbc->fbc_x3 = ri->ri_xorigin + dst + n - 1;
fbc->fbc_y3 = ri->ri_yorigin + row + ri->ri_font->fontheight - 1;
CG6_BLIT_WAIT(fbc);
CG6_DRAIN(fbc);
}
static void
cg6_ras_erasecols(void *cookie, int row, int col, int n, long int attr)
{
struct rasops_info *ri;
volatile struct cg6_fbc *fbc;
ri = cookie;
if ((row < 0) || (row >= ri->ri_rows))
return;
if (col < 0) {
n += col;
col = 0;
}
if (col+n > ri->ri_cols)
n = ri->ri_cols - col;
if (n <= 0)
return;
n *= ri->ri_font->fontwidth;
col *= ri->ri_font->fontwidth;
row *= ri->ri_font->fontheight;
fbc = ((struct cgsix_softc *)ri->ri_hw)->sc_fbc;
fbc->fbc_clip = 0;
fbc->fbc_s = 0;
fbc->fbc_offx = 0;
fbc->fbc_offy = 0;
fbc->fbc_clipminx = 0;
fbc->fbc_clipminy = 0;
fbc->fbc_clipmaxx = ri->ri_width - 1;
fbc->fbc_clipmaxy = ri->ri_height - 1;
fbc->fbc_alu = CG6_ALU_FILL;
fbc->fbc_fg = ri->ri_devcmap[0/*(attr>>16)&15*/];
fbc->fbc_arecty = ri->ri_yorigin + row;
fbc->fbc_arectx = ri->ri_xorigin + col;
fbc->fbc_arecty = ri->ri_yorigin + row + ri->ri_font->fontheight - 1;
fbc->fbc_arectx = ri->ri_xorigin + col + n - 1;
CG6_DRAW_WAIT(fbc);
CG6_DRAIN(fbc);
}
static void
cg6_ras_eraserows(void *cookie, int row, int n, long int attr)
{
struct rasops_info *ri;
volatile struct cg6_fbc *fbc;
ri = cookie;
if (row < 0) {
n += row;
row = 0;
}
if (row+n > ri->ri_rows)
n = ri->ri_rows - row;
if (n <= 0)
return;
fbc = ((struct cgsix_softc *)ri->ri_hw)->sc_fbc;
fbc->fbc_clip = 0;
fbc->fbc_s = 0;
fbc->fbc_offx = 0;
fbc->fbc_offy = 0;
fbc->fbc_clipminx = 0;
fbc->fbc_clipminy = 0;
fbc->fbc_clipmaxx = ri->ri_width - 1;
fbc->fbc_clipmaxy = ri->ri_height - 1;
fbc->fbc_alu = CG6_ALU_FILL;
fbc->fbc_fg = ri->ri_devcmap[0/*(attr>>16)&15*/];
if ((n == ri->ri_rows) && (ri->ri_flg & RI_FULLCLEAR)) {
fbc->fbc_arecty = 0;
fbc->fbc_arectx = 0;
fbc->fbc_arecty = ri->ri_height - 1;
fbc->fbc_arectx = ri->ri_width - 1;
} else {
row *= ri->ri_font->fontheight;
fbc->fbc_arecty = ri->ri_yorigin + row;
fbc->fbc_arectx = ri->ri_xorigin;
fbc->fbc_arecty = ri->ri_yorigin + row + (n * ri->ri_font->fontheight) - 1;
fbc->fbc_arectx = ri->ri_xorigin + ri->ri_emuwidth - 1;
}
CG6_DRAW_WAIT(fbc);
CG6_DRAIN(fbc);
}
/*
* Really want something more like fg^bg here, but that would be more
* or less impossible to migrate to colors. So we hope there's
* something not too inappropriate in the colormap...besides, it's what
* the non-accelerated code did. :-)
*/
static void
cg6_ras_do_cursor(struct rasops_info *ri)
{
volatile struct cg6_fbc *fbc;
int row;
int col;
row = ri->ri_crow * ri->ri_font->fontheight;
col = ri->ri_ccol * ri->ri_font->fontwidth;
fbc = ((struct cgsix_softc *)ri->ri_hw)->sc_fbc;
fbc->fbc_clip = 0;
fbc->fbc_s = 0;
fbc->fbc_offx = 0;
fbc->fbc_offy = 0;
fbc->fbc_clipminx = 0;
fbc->fbc_clipminy = 0;
fbc->fbc_clipmaxx = ri->ri_width - 1;
fbc->fbc_clipmaxy = ri->ri_height - 1;
fbc->fbc_alu = CG6_ALU_FLIP;
fbc->fbc_arecty = ri->ri_yorigin + row;
fbc->fbc_arectx = ri->ri_xorigin + col;
fbc->fbc_arecty = ri->ri_yorigin + row + ri->ri_font->fontheight - 1;
fbc->fbc_arectx = ri->ri_xorigin + col + ri->ri_font->fontwidth - 1;
CG6_DRAW_WAIT(fbc);
CG6_DRAIN(fbc);
}
void
cg6attach(sc, name, isconsole)
@ -187,8 +484,15 @@ cg6attach(sc, name, isconsole)
if (isconsole) {
printf(" (console)");
#ifdef RASTERCONSOLE
if (cgsix_use_rasterconsole)
if (cgsix_use_rasterconsole) {
fbrcons_init(&sc->sc_fb);
sc->sc_fb.fb_rinfo.ri_hw = sc;
sc->sc_fb.fb_rinfo.ri_ops.copyrows = cg6_ras_copyrows;
sc->sc_fb.fb_rinfo.ri_ops.copycols = cg6_ras_copycols;
sc->sc_fb.fb_rinfo.ri_ops.erasecols = cg6_ras_erasecols;
sc->sc_fb.fb_rinfo.ri_ops.eraserows = cg6_ras_eraserows;
sc->sc_fb.fb_rinfo.ri_do_cursor = cg6_ras_do_cursor;
}
#endif
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: cgsix_obio.c,v 1.4 2000/03/19 15:38:45 pk Exp $ */
/* $NetBSD: cgsix_obio.c,v 1.5 2000/03/30 13:57:50 pk Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -192,6 +192,16 @@ cgsixattach(parent, self, aux)
}
sc->sc_tec = (struct cg6_tec_xxx *)bh;
if (bus_space_map2(oba->oba_bustag, 0,
oba->oba_paddr + CGSIX_FBC_OFFSET,
sizeof(*sc->sc_fbc),
BUS_SPACE_MAP_LINEAR,
0, &bh) != 0) {
printf("%s: cannot map FBC registers\n", self->dv_xname);
return;
}
sc->sc_fbc = (struct cg6_fbc *)bh;
if (fb_pfour_id((void *)sc->sc_fhc) == PFOUR_ID_FASTCOLOR) {
fb->fb_flags |= FB_PFOUR;

View File

@ -1,4 +1,4 @@
/* $NetBSD: cgsix_sbus.c,v 1.2 2000/03/19 15:38:45 pk Exp $ */
/* $NetBSD: cgsix_sbus.c,v 1.3 2000/03/30 13:57:50 pk Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -171,6 +171,16 @@ cgsixattach(parent, self, aux)
}
sc->sc_tec = (struct cg6_tec_xxx *)bh;
if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
sa->sa_offset + CGSIX_FBC_OFFSET,
sizeof(*sc->sc_fbc),
BUS_SPACE_MAP_LINEAR,
0, &bh) != 0) {
printf("%s: cannot map FBC registers\n", self->dv_xname);
return;
}
sc->sc_fbc = (struct cg6_fbc *)bh;
sbus_establish(&sc->sc_sd, &sc->sc_dev);
name = getpropstring(node, "model");

View File

@ -1,4 +1,4 @@
/* $NetBSD: cgsixreg.h,v 1.5 1998/03/21 19:45:45 pk Exp $ */
/* $NetBSD: cgsixreg.h,v 1.6 2000/03/30 13:57:51 pk Exp $ */
/*
* Copyright (c) 1993
@ -71,7 +71,7 @@
* we have only seen rev 1 & 2.
*/
/* offsets */
/* Control register banks offsets */
#define CGSIX_ROM_OFFSET 0x000000
#define CGSIX_BT_OFFSET 0x200000
#define CGSIX_DHC_OFFSET 0x240000
@ -114,18 +114,18 @@
* The layout of the THC.
*/
struct cg6_thc {
u_int thc_xxx0[512]; /* ??? */
u_int thc_hsync1; /* horizontal sync timing */
u_int thc_hsync2; /* more hsync timing */
u_int thc_hsync3; /* yet more hsync timing */
u_int thc_vsync1; /* vertical sync timing */
u_int thc_vsync2; /* only two of these */
u_int thc_refresh; /* refresh counter */
u_int thc_misc; /* miscellaneous control & status */
u_int thc_xxx1[56]; /* ??? */
u_int thc_cursxy; /* cursor x,y position (16 bits each) */
u_int thc_cursmask[32]; /* cursor mask bits */
u_int thc_cursbits[32]; /* what to show where mask enabled */
u_int32_t thc_xxx0[512]; /* ??? */
u_int32_t thc_hsync1; /* horizontal sync timing */
u_int32_t thc_hsync2; /* more hsync timing */
u_int32_t thc_hsync3; /* yet more hsync timing */
u_int32_t thc_vsync1; /* vertical sync timing */
u_int32_t thc_vsync2; /* only two of these */
u_int32_t thc_refresh; /* refresh counter */
u_int32_t thc_misc; /* miscellaneous control & status */
u_int32_t thc_xxx1[56]; /* ??? */
u_int32_t thc_cursxy; /* cursor x,y position (16 bits each) */
u_int32_t thc_cursmask[32];/* cursor mask bits */
u_int32_t thc_cursbits[32];/* what to show where mask enabled */
};
/* bits in thc_misc */
@ -151,11 +151,59 @@ struct cg6_thc {
* Partial description of TEC (needed to get around FHC rev 1 bugs).
*/
struct cg6_tec_xxx {
u_int tec_mv; /* matrix stuff */
u_int tec_clip; /* clipping stuff */
u_int tec_vdc; /* ??? */
u_int32_t tec_mv; /* matrix stuff */
u_int32_t tec_clip; /* clipping stuff */
u_int32_t tec_vdc; /* ??? */
};
/*
* Partial description of FBC
*
* Most of this we don't care about; here are only the portions
* we need, most notably the blitter. Comments are merely my
* best guesses as to register functions, based largely on the
* X11R6.4 sunGX code. Some of these are here only so we can
* stuff canned values in them (eg, offx).
*/
struct cg6_fbc {
u_int32_t fbc_pad1[2];
u_int32_t fbc_clip; /* function unknown */
u_int32_t fbc_pad2[1];
u_int32_t fbc_s; /* global status */
u_int32_t fbc_draw; /* drawing pipeline status */
u_int32_t fbc_blit; /* blitter status */
u_int32_t fbc_pad3[25];
u_int32_t fbc_x0; /* blitter, src llx */
u_int32_t fbc_y0; /* blitter, src lly */
u_int32_t fbc_pad4[2];
u_int32_t fbc_x1; /* blitter, src urx */
u_int32_t fbc_y1; /* blitter, src ury */
u_int32_t fbc_pad5[2];
u_int32_t fbc_x2; /* blitter, dst llx */
u_int32_t fbc_y2; /* blitter, dst lly */
u_int32_t fbc_pad6[2];
u_int32_t fbc_x3; /* blitter, dst urx */
u_int32_t fbc_y3; /* blitter, dst ury */
u_int32_t fbc_pad7[2];
u_int32_t fbc_offx; /* x offset for drawing */
u_int32_t fbc_offy; /* y offset for drawing */
u_int32_t fbc_pad8[6];
u_int32_t fbc_clipminx; /* clip rectangle llx */
u_int32_t fbc_clipminy; /* clip rectangle lly */
u_int32_t fbc_pad9[2];
u_int32_t fbc_clipmaxx; /* clip rectangle urx */
u_int32_t fbc_clipmaxy; /* clip rectangle ury */
u_int32_t fbc_pad10[2];
u_int32_t fbc_fg; /* fg value for rop */
u_int32_t fbc_pad11[1];
u_int32_t fbc_alu; /* operation to be performed */
u_int32_t fbc_pad12[509];
u_int32_t fbc_arectx; /* rectangle drawing, x coord */
u_int32_t fbc_arecty; /* rectangle drawing, y coord */
/* actually much more, but nothing more we need */
};
#if _CG6_LAYOUT_NOT_USED_ANYMORE
/*
* This structure exists only to compute the layout of the CG6
* hardware. Each of the individual substructures lives on a
@ -214,3 +262,4 @@ struct cg6_layout {
/* Video RAM at 0x800000 */
char cg6_ram[1024 * 1024]; /* approx.? */
};
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: cgsixvar.h,v 1.2 2000/03/19 15:38:45 pk Exp $ */
/* $NetBSD: cgsixvar.h,v 1.3 2000/03/30 13:57:51 pk Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -67,6 +67,7 @@ struct cgsix_softc {
volatile int *sc_fhc; /* FHC register */
volatile struct cg6_thc *sc_thc; /* THC registers */
volatile struct cg6_tec_xxx *sc_tec; /* TEC registers */
volatile struct cg6_fbc *sc_fbc; /* FBC registers */
short sc_fhcrev; /* hardware rev */
short sc_blanked; /* true if blanked */
struct cg6_cursor sc_cursor; /* software cursor info */