diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2003-06-13 06:44:56 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2003-06-13 06:44:56 +0000 |
commit | 16d9708c1dee1d6015b459765ebc9603f9be8587 (patch) | |
tree | bb69769a5c421d783cc0b223307eef576d5bebc8 /sys/arch | |
parent | 4070211ffd94f929b7558872d538bd9d7e649abb (diff) |
Accelerated text console routines, using the Power 9100 drawing engine.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sparc/dev/p9100.c | 433 |
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); +} |