summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2003-06-13 06:44:56 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2003-06-13 06:44:56 +0000
commit16d9708c1dee1d6015b459765ebc9603f9be8587 (patch)
treebb69769a5c421d783cc0b223307eef576d5bebc8 /sys/arch
parent4070211ffd94f929b7558872d538bd9d7e649abb (diff)
Accelerated text console routines, using the Power 9100 drawing engine.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/sparc/dev/p9100.c433
1 files changed, 377 insertions, 56 deletions
diff --git a/sys/arch/sparc/dev/p9100.c b/sys/arch/sparc/dev/p9100.c
index 994400c28f9..d073262fe29 100644
--- a/sys/arch/sparc/dev/p9100.c
+++ b/sys/arch/sparc/dev/p9100.c
@@ -1,6 +1,7 @@
-/* $OpenBSD: p9100.c,v 1.18 2003/06/12 19:09:43 miod Exp $ */
+/* $OpenBSD: p9100.c,v 1.19 2003/06/13 06:44:55 miod Exp $ */
/*
+ * Copyright (c) 2003, Miodrag Vallat.
* Copyright (c) 1999 Jason L. Wright (jason@thought.net)
* All rights reserved.
*
@@ -115,6 +116,13 @@ struct wsdisplay_accessops p9100_accessops = {
p9100_burner,
};
+void p9100_ras_init(struct p9100_softc *);
+void p9100_ras_copycols(void *, int, int, int, int);
+void p9100_ras_copyrows(void *, int, int, int);
+void p9100_ras_do_cursor(struct rasops_info *);
+void p9100_ras_erasecols(void *, int, int, int, long int);
+void p9100_ras_eraserows(void *, int, int, long int);
+
int p9100match(struct device *, void *, void *);
void p9100attach(struct device *, struct device *, void *);
@@ -141,7 +149,7 @@ struct cfdriver pnozz_cd = {
struct p9100_ctl {
/* System control registers: 0x0000 - 0x00ff */
struct p9100_scr {
- volatile u_int32_t unused0;
+ volatile u_int32_t :32;
volatile u_int32_t scr; /* system config reg */
#define SCR_ID_MASK 0x00000007
#define SCR_PIXEL_ID_MASK 0x00000007
@@ -167,7 +175,7 @@ struct p9100_ctl {
/* Video control registers: 0x0100 - 0x017f */
struct p9100_vcr {
- volatile u_int32_t unused0;
+ volatile u_int32_t :32;
volatile u_int32_t hcr; /* horizontal cntr */
volatile u_int32_t htr; /* horizontal total */
volatile u_int32_t hsre; /* horiz sync rising */
@@ -182,6 +190,7 @@ struct p9100_ctl {
volatile u_int32_t vcp; /* vert cntr preload */
volatile u_int32_t sra; /* scrn repaint addr */
volatile u_int32_t srtc1; /* scrn rpnt time 1 */
+#define SRTC1_VIDEN 0x00000020
volatile u_int32_t qsf; /* qsf counter */
volatile u_int32_t srtc2; /* scrn rpnt time 2 */
volatile u_int32_t unused1[15];
@@ -189,7 +198,7 @@ struct p9100_ctl {
/* VRAM control registers: 0x0180 - 0x1ff */
struct p9100_vram {
- volatile u_int32_t unused0;
+ volatile u_int32_t :32;
volatile u_int32_t mc; /* memory config */
volatile u_int32_t rp; /* refresh period */
volatile u_int32_t rc; /* refresh count */
@@ -216,19 +225,149 @@ struct p9100_ctl {
volatile u_int32_t ctl_vci[768];
};
-#define SRTC1_VIDEN 0x00000020
+/*
+ * Power 9100 Drawing engine
+ */
+
+struct p9100_coord {
+ volatile u_int32_t :32;
+ volatile u_int32_t :32;
+ volatile u_int32_t abs_x32;
+ volatile u_int32_t :32;
+ volatile u_int32_t abs_y32;
+ volatile u_int32_t :32;
+ volatile u_int32_t abs_x16y16;
+ volatile u_int32_t :32;
+ volatile u_int32_t :32;
+ volatile u_int32_t :32;
+ volatile u_int32_t rel_x32;
+ volatile u_int32_t :32;
+ volatile u_int32_t rel_y32;
+ volatile u_int32_t :32;
+ volatile u_int32_t rel_x16y16;
+ volatile u_int32_t :32;
+};
+
+/* How to encode a x16y16 value */
+#define P9100_COORDS(col,row) ((((col) & 0x0fff) << 16) | ((row) & 0x0fff))
+
+struct p9100_cmd {
+ /* Parameter engine 0x2000-0x217f */
+ struct cmd_pe {
+ volatile u_int32_t status; /* status register */
+#define STATUS_QUAD_BUSY 0x80000000
+#define STATUS_BLIT_BUSY 0x40000000
+#define STATUS_PICK_DETECTED 0x00000080
+#define STATUS_PIXEL_ERROR 0x00000040
+#define STATUS_BLIT_ERROR 0x00000020
+#define STATUS_QUAD_ERROR 0x00000010
+#define STATUS_QUAD_CONCAVE 0x00000008
+#define STATUS_QUAD_OUTSIDE 0x00000004
+#define STATUS_QUAD_INSIDE 0x00000002
+#define STATUS_QUAD_STRADDLE 0x00000001
+ volatile u_int32_t blit; /* blit command */
+ volatile u_int32_t quad; /* quad command */
+ volatile u_int32_t pixel8; /* P9000 pixel8 command */
+ volatile u_int32_t :32;
+ volatile u_int32_t nextpixels; /* next_pixels command */
+ volatile u_int32_t unused1[(0x80 - 0x18) / 4];
+ volatile u_int32_t pixel1[32]; /* pixel1 command */
+ volatile u_int32_t unused2[(0x180 - 0x100) / 4];
+
+ /* Parameter engine registers 0x2180-0x21ff */
+ volatile u_int32_t :32;
+ volatile u_int32_t oor; /* out of range register */
+ volatile u_int32_t :32;
+ volatile u_int32_t cindex; /* index register */
+ volatile u_int32_t winoffset; /* window offset (16+16) */
+ volatile u_int32_t winmin; /* window minimum */
+ volatile u_int32_t winmax; /* window maximum */
+ volatile u_int32_t :32;
+ volatile u_int32_t yclip;
+ volatile u_int32_t xclip;
+ volatile u_int32_t xedgeless;
+ volatile u_int32_t xedgegreater;
+ volatile u_int32_t yedgeless;
+ volatile u_int32_t yedgegreater;
+ volatile u_int32_t unused3[(0x200 - 0x1b8) / 4];
+ } pe;
+
+ /* Drawing engine 0x2200-0x2fff */
+ struct cmd_de {
+ volatile u_int32_t color0; /* fg color */
+ volatile u_int32_t color1; /* bg color */
+ volatile u_int32_t planemask; /* 8-bit plane mask */
+ volatile u_int32_t drawmode;
+#define DM_PICK_CONTROL 0x00000008
+#define DM_PICK_ENABLE 0x00000004
+#define DM_BUFFER_CONTROL 0x00000002
+#define DM_BUFFER_ENABLE0 0x00000000
+#define DM_BUFFER_ENABLE1 0x00000001
+ volatile u_int32_t patternx; /* Quad 16x16 pattern origin */
+ volatile u_int32_t patterny; /* (4-bit) */
+ volatile u_int32_t raster;
+ volatile u_int32_t pixel8; /* Pixel8 extra storage */
+ volatile u_int32_t winmin; /* window min, same as above */
+ volatile u_int32_t winmax; /* window max, same as above */
+ volatile u_int32_t unused1[(0x38 - 0x28) / 4];
+ volatile u_int32_t color2;
+ volatile u_int32_t color3;
+ volatile u_int32_t unused2[(0x80 - 0x40) / 4];
+ volatile u_int32_t pattern[4]; /* pattern for quad fill */
+ volatile u_int32_t user[4]; /* user defined registers */
+ volatile u_int32_t bwinmin; /* byte window minimum */
+ volatile u_int32_t bwinmax; /* byte window maximum */
+ volatile u_int32_t unused3[(0x3000 - 0x22a8) / 4];
+ } de;
+
+ /* Device coordinates 0x3000-0x31ff */
+ struct cmd_dc {
+ struct p9100_coord coord[4];
+ volatile u_int32_t unused[(0x200 - 0x100) / 4];
+ } dc;
+
+ /* Load coordinates 0x3200-0x33ff */
+ struct cmd_lc {
+ struct p9100_coord point;
+ struct p9100_coord line;
+ struct p9100_coord tri;
+ struct p9100_coord quad;
+ struct p9100_coord rect;
+ } lc;
+};
+/* How to encode a color in 8 bit mode, for the drawing engine */
+#define P9100_COLOR8(col) ((col) | ((col) << 8) | ((col) << 16))
+
+/* P9100 minterms for the raster register */
+#define P9100_RASTER_SRC 0x00cc
+#define P9100_RASTER_DST 0x00aa
+#define P9100_RASTER_PATTERN 0x00f0
+#define P9100_RASTER_MASK 0x00ff
/*
- * Select the appropriate register group within the control registers
- * (must be done before any write to a register within the group, but
- * subsequent writes to the same group do not need to reselect).
+ * On the tadpole, the first write to a register group is ignored until
+ * the proper group address is latched, which can be done by reading from the
+ * register group first.
+ *
+ * Register groups are 0x80 bytes long (i.e. it is necessary to force a read
+ * when writing to an adress which upper 25 bit differ from the previous
+ * read or write operation).
+ *
+ * This is specific to the Tadpole design, and not a limitation of the
+ * Power 9100 hardware.
*/
#define P9100_SELECT_SCR(sc) ((sc)->sc_junk = (sc)->sc_ctl->ctl_scr.scr)
#define P9100_SELECT_VCR(sc) ((sc)->sc_junk = (sc)->sc_ctl->ctl_vcr.hcr)
#define P9100_SELECT_VRAM(sc) ((sc)->sc_junk = (sc)->sc_ctl->ctl_vram.mc)
#define P9100_SELECT_DAC(sc) ((sc)->sc_junk = (sc)->sc_ctl->ctl_dac.pwraddr)
#define P9100_SELECT_VCI(sc) ((sc)->sc_junk = (sc)->sc_ctl->ctl_vci[0])
+#define P9100_SELECT_DE_LOW(sc) ((sc)->sc_junk = (sc)->sc_cmd->de.color0)
+#define P9100_SELECT_DE_HIGH(sc) \
+ ((sc)->sc_junk = (sc)->sc_cmd->de.bwinmax)
+#define P9100_SELECT_PE(sc) ((sc)->sc_junk = (sc)->sc_cmd->pe.cindex)
+#define P9100_SELECT_COORD(sc,field) \
+ ((sc)->sc_junk = (sc)->sc_cmd->##field##.abs_x32)
/*
* For some reason, every write to a DAC register needs to be followed by a
@@ -241,17 +380,8 @@ struct p9100_ctl {
(sc)->sc_junk = (sc)->sc_ctl->ctl_vram.dacfifo; \
} while (0)
-/*
- * Drawing engine
- */
-struct p9100_cmd {
- volatile u_int32_t cmd_regs[0x800];
-};
-
int
-p9100match(parent, vcf, aux)
- struct device *parent;
- void *vcf, *aux;
+p9100match(struct device *parent, void *vcf, void *aux)
{
struct confargs *ca = aux;
struct romaux *ra = &ca->ca_ra;
@@ -266,9 +396,7 @@ p9100match(parent, vcf, aux)
* Attach a display.
*/
void
-p9100attach(parent, self, args)
- struct device *parent, *self;
- void *args;
+p9100attach(struct device *parent, struct device *self, void *args)
{
struct p9100_softc *sc = (struct p9100_softc *)self;
struct confargs *ca = args;
@@ -347,6 +475,18 @@ p9100attach(parent, self, args)
isconsole && (sc->sc_sunfb.sf_width != 800));
fbwscons_setcolormap(&sc->sc_sunfb, p9100_setcolor);
+ /*
+ * Plug-in accelerated console operations if we can.
+ */
+ if (sc->sc_sunfb.sf_depth == 8) {
+ sc->sc_sunfb.sf_ro.ri_ops.copycols = p9100_ras_copycols;
+ sc->sc_sunfb.sf_ro.ri_ops.copyrows = p9100_ras_copyrows;
+ sc->sc_sunfb.sf_ro.ri_ops.erasecols = p9100_ras_erasecols;
+ sc->sc_sunfb.sf_ro.ri_ops.eraserows = p9100_ras_eraserows;
+ sc->sc_sunfb.sf_ro.ri_do_cursor = p9100_ras_do_cursor;
+ p9100_ras_init(sc);
+ }
+
p9100_stdscreen.capabilities = sc->sc_sunfb.sf_ro.ri_caps;
p9100_stdscreen.nrows = sc->sc_sunfb.sf_ro.ri_rows;
p9100_stdscreen.ncols = sc->sc_sunfb.sf_ro.ri_cols;
@@ -375,12 +515,7 @@ p9100attach(parent, self, args)
}
int
-p9100_ioctl(v, cmd, data, flags, p)
- void *v;
- u_long cmd;
- caddr_t data;
- int flags;
- struct proc *p;
+p9100_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
{
struct p9100_softc *sc = v;
struct wsdisplay_fbinfo *wdf;
@@ -396,6 +531,14 @@ p9100_ioctl(v, cmd, data, flags, p)
*(u_int *)data = WSDISPLAY_TYPE_SB_P9100;
break;
+ case WSDISPLAYIO_SMODE:
+ /* Restore proper acceleration state upon leaving X11 */
+ if (*(u_int *)data == WSDISPLAYIO_MODE_EMUL &&
+ sc->sc_sunfb.sf_depth == 8) {
+ p9100_ras_init(sc);
+ }
+ break;
+
case WSDISPLAYIO_GINFO:
wdf = (struct wsdisplay_fbinfo *)data;
wdf->height = sc->sc_sunfb.sf_height;
@@ -474,12 +617,8 @@ p9100_ioctl(v, cmd, data, flags, p)
}
int
-p9100_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
- void *v;
- const struct wsscreen_descr *type;
- void **cookiep;
- int *curxp, *curyp;
- long *attrp;
+p9100_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
+ int *curxp, int *curyp, long *attrp)
{
struct p9100_softc *sc = v;
@@ -501,9 +640,7 @@ p9100_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
}
void
-p9100_free_screen(v, cookie)
- void *v;
- void *cookie;
+p9100_free_screen(void *v, void *cookie)
{
struct p9100_softc *sc = v;
@@ -511,12 +648,8 @@ p9100_free_screen(v, cookie)
}
int
-p9100_show_screen(v, cookie, waitok, cb, cbarg)
- void *v;
- void *cookie;
- int waitok;
- void (*cb)(void *, int, int);
- void *cbarg;
+p9100_show_screen(void *v, void *cookie, int waitok,
+ void (*cb)(void *, int, int), void *cbarg)
{
return (0);
}
@@ -526,10 +659,7 @@ p9100_show_screen(v, cookie, waitok, cb, cbarg)
* offset, allowing for the given protection, or return -1 for error.
*/
paddr_t
-p9100_mmap(v, offset, prot)
- void *v;
- off_t offset;
- int prot;
+p9100_mmap(void *v, off_t offset, int prot)
{
struct p9100_softc *sc = v;
@@ -544,10 +674,7 @@ p9100_mmap(v, offset, prot)
}
void
-p9100_setcolor(v, index, r, g, b)
- void *v;
- u_int index;
- u_int8_t r, g, b;
+p9100_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
{
struct p9100_softc *sc = v;
union bt_cmap *bcm = &sc->sc_cmap;
@@ -559,9 +686,7 @@ p9100_setcolor(v, index, r, g, b)
}
void
-p9100_loadcmap_immediate(sc, start, ncolors)
- struct p9100_softc *sc;
- u_int start, ncolors;
+p9100_loadcmap_immediate(struct p9100_softc *sc, u_int start, u_int ncolors)
{
u_char *p;
@@ -587,9 +712,7 @@ p9100_loadcmap_deferred(struct p9100_softc *sc, u_int start, u_int ncolors)
}
void
-p9100_burner(v, on, flags)
- void *v;
- u_int on, flags;
+p9100_burner(void *v, u_int on, u_int flags)
{
struct p9100_softc *sc = v;
u_int32_t vcr;
@@ -627,3 +750,201 @@ p9100_intr(void *v)
return (0);
}
+
+/*
+ * Accelerated text console code
+ */
+
+static __inline__ void p9100_drain(struct p9100_softc *);
+
+static __inline__ void
+p9100_drain(struct p9100_softc *sc)
+{
+ while (sc->sc_cmd->pe.status & (STATUS_QUAD_BUSY | STATUS_BLIT_BUSY));
+}
+
+void
+p9100_ras_init(struct p9100_softc *sc)
+{
+
+ /*
+ * Setup safe defaults for the parameter and drawing engine, in
+ * order to minimize the operations to do for ri_ops.
+ */
+
+ P9100_SELECT_DE_LOW(sc);
+ sc->sc_cmd->de.drawmode = DM_PICK_CONTROL | 0 |
+ DM_BUFFER_CONTROL | DM_BUFFER_ENABLE0;
+
+ sc->sc_cmd->de.patternx = 0;
+ sc->sc_cmd->de.patterny = 0;
+ sc->sc_cmd->de.planemask = 0xffffffff; /* enable all planes */
+
+ /* Unclip */
+ sc->sc_cmd->de.winmin = 0;
+ sc->sc_cmd->de.winmax =
+ P9100_COORDS(sc->sc_sunfb.sf_width - 1, sc->sc_sunfb.sf_height);
+
+ P9100_SELECT_DE_HIGH(sc);
+ sc->sc_cmd->de.bwinmin = 0;
+ sc->sc_cmd->de.bwinmax =
+ P9100_COORDS(sc->sc_sunfb.sf_width - 1, sc->sc_sunfb.sf_height);
+
+ P9100_SELECT_PE(sc);
+ sc->sc_cmd->pe.winoffset = 0;
+}
+
+void
+p9100_ras_copycols(void *v, int row, int src, int dst, int n)
+{
+ struct rasops_info *ri = v;
+ struct p9100_softc *sc = ri->ri_hw;
+
+ n *= ri->ri_font->fontwidth;
+ n--;
+ src *= ri->ri_font->fontwidth;
+ src += ri->ri_xorigin;
+ dst *= ri->ri_font->fontwidth;
+ dst += ri->ri_xorigin;
+ row *= ri->ri_font->fontheight;
+ row += ri->ri_yorigin;
+
+ p9100_drain(sc);
+ P9100_SELECT_DE_LOW(sc);
+ sc->sc_cmd->de.raster = P9100_RASTER_SRC & P9100_RASTER_MASK;
+
+ P9100_SELECT_COORD(sc,dc.coord[0]);
+ sc->sc_cmd->dc.coord[0].abs_x16y16 = P9100_COORDS(src, row);
+ sc->sc_cmd->dc.coord[1].abs_x16y16 =
+ P9100_COORDS(src + n, row + ri->ri_font->fontheight - 1);
+ P9100_SELECT_COORD(sc,dc.coord[2]);
+ sc->sc_cmd->dc.coord[2].abs_x16y16 = P9100_COORDS(dst, row);
+ sc->sc_cmd->dc.coord[3].abs_x16y16 =
+ P9100_COORDS(dst + n, row + ri->ri_font->fontheight - 1);
+
+ sc->sc_junk = sc->sc_cmd->pe.blit;
+
+ p9100_drain(sc);
+}
+
+void
+p9100_ras_copyrows(void *v, int src, int dst, int n)
+{
+ struct rasops_info *ri = v;
+ struct p9100_softc *sc = ri->ri_hw;
+
+ n *= ri->ri_font->fontheight;
+ n--;
+ src *= ri->ri_font->fontheight;
+ src += ri->ri_yorigin;
+ dst *= ri->ri_font->fontheight;
+ dst += ri->ri_yorigin;
+
+ p9100_drain(sc);
+ P9100_SELECT_DE_LOW(sc);
+ sc->sc_cmd->de.raster = P9100_RASTER_SRC & P9100_RASTER_MASK;
+
+ P9100_SELECT_COORD(sc,dc.coord[0]);
+ sc->sc_cmd->dc.coord[0].abs_x16y16 = P9100_COORDS(ri->ri_xorigin, src);
+ sc->sc_cmd->dc.coord[1].abs_x16y16 =
+ P9100_COORDS(ri->ri_xorigin + ri->ri_emuwidth - 1, src + n);
+ P9100_SELECT_COORD(sc,dc.coord[2]);
+ sc->sc_cmd->dc.coord[2].abs_x16y16 = P9100_COORDS(ri->ri_xorigin, dst);
+ sc->sc_cmd->dc.coord[3].abs_x16y16 =
+ P9100_COORDS(ri->ri_xorigin + ri->ri_emuwidth - 1, dst + n);
+
+ sc->sc_junk = sc->sc_cmd->pe.blit;
+
+ p9100_drain(sc);
+}
+
+void
+p9100_ras_erasecols(void *v, int row, int col, int n, long int attr)
+{
+ struct rasops_info *ri = v;
+ struct p9100_softc *sc = ri->ri_hw;
+ int fg, bg;
+
+ rasops_unpack_attr(attr, &fg, &bg, NULL);
+
+ n *= ri->ri_font->fontwidth;
+ n--;
+ col *= ri->ri_font->fontwidth;
+ col += ri->ri_xorigin;
+ row *= ri->ri_font->fontheight;
+ row += ri->ri_yorigin;
+
+ p9100_drain(sc);
+ P9100_SELECT_DE_LOW(sc);
+ sc->sc_cmd->de.raster = P9100_RASTER_PATTERN & P9100_RASTER_MASK;
+ sc->sc_cmd->de.color0 = P9100_COLOR8(bg);
+
+ P9100_SELECT_COORD(sc,lc.rect);
+ sc->sc_cmd->lc.rect.abs_x16y16 = P9100_COORDS(col, row);
+ sc->sc_cmd->lc.rect.abs_x16y16 =
+ P9100_COORDS(col + n, row + ri->ri_font->fontheight - 1);
+
+ sc->sc_junk = sc->sc_cmd->pe.quad;
+
+ p9100_drain(sc);
+}
+
+void
+p9100_ras_eraserows(void *v, int row, int n, long int attr)
+{
+ struct rasops_info *ri = v;
+ struct p9100_softc *sc = ri->ri_hw;
+ int fg, bg;
+
+ rasops_unpack_attr(attr, &fg, &bg, NULL);
+
+ p9100_drain(sc);
+ P9100_SELECT_DE_LOW(sc);
+ sc->sc_cmd->de.raster = P9100_RASTER_PATTERN & P9100_RASTER_MASK;
+ sc->sc_cmd->de.color0 = P9100_COLOR8(bg);
+
+ if (n == ri->ri_rows && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
+ sc->sc_cmd->lc.rect.abs_x16y16 = P9100_COORDS(0, 0);
+ sc->sc_cmd->lc.rect.abs_x16y16 =
+ P9100_COORDS(ri->ri_width - 1, ri->ri_height - 1);
+ } else {
+ n *= ri->ri_font->fontheight;
+ n--;
+ row *= ri->ri_font->fontheight;
+ row += ri->ri_yorigin;
+
+ sc->sc_cmd->lc.rect.abs_x16y16 =
+ P9100_COORDS(ri->ri_xorigin, row);
+ sc->sc_cmd->lc.rect.abs_x16y16 =
+ P9100_COORDS(ri->ri_xorigin + ri->ri_emuwidth - 1, row + n);
+ }
+
+ sc->sc_junk = sc->sc_cmd->pe.quad;
+
+ p9100_drain(sc);
+}
+
+void
+p9100_ras_do_cursor(struct rasops_info *ri)
+{
+ struct p9100_softc *sc = ri->ri_hw;
+ int row, col;
+
+ row = ri->ri_crow * ri->ri_font->fontheight + ri->ri_yorigin;
+ col = ri->ri_ccol * ri->ri_font->fontwidth + ri->ri_xorigin;
+
+ p9100_drain(sc);
+
+ P9100_SELECT_DE_LOW(sc);
+ sc->sc_cmd->de.raster = (~P9100_RASTER_DST) & P9100_RASTER_MASK;
+
+ P9100_SELECT_COORD(sc,lc.rect);
+ sc->sc_cmd->lc.rect.abs_x16y16 = P9100_COORDS(col, row);
+ sc->sc_cmd->lc.rect.abs_x16y16 =
+ P9100_COORDS(col + ri->ri_font->fontwidth,
+ row + ri->ri_font->fontheight);
+
+ sc->sc_junk = sc->sc_cmd->pe.quad;
+
+ p9100_drain(sc);
+}