diff options
Diffstat (limited to 'sys/arch/hp300/dev/diofb.c')
-rw-r--r-- | sys/arch/hp300/dev/diofb.c | 430 |
1 files changed, 221 insertions, 209 deletions
diff --git a/sys/arch/hp300/dev/diofb.c b/sys/arch/hp300/dev/diofb.c index 1c825b51dfa..1e6595b4172 100644 --- a/sys/arch/hp300/dev/diofb.c +++ b/sys/arch/hp300/dev/diofb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: diofb.c,v 1.5 2005/01/18 21:53:23 miod Exp $ */ +/* $OpenBSD: diofb.c,v 1.6 2005/01/24 21:36:39 miod Exp $ */ /* * Copyright (c) 2005, Miodrag Vallat @@ -72,40 +72,18 @@ #include <hp300/dev/dioreg.h> #include <hp300/dev/diovar.h> +#include <dev/wscons/wsconsio.h> #include <dev/wscons/wsdisplayvar.h> +#include <dev/rasops/rasops.h> #include <hp300/dev/diofbreg.h> #include <hp300/dev/diofbvar.h> -/* - * X and Y location of character 'c' in the framebuffer, in pixels. - */ -#define charX(fb,c) \ - (((c) % (fb)->cpl) * (fb)->ftscale + (fb)->fontx) -#define charY(fb,c) \ - (((c) / (fb)->cpl) * (fb)->ftheight + (fb)->fonty) - -void diofb_fontcopy(struct diofb *, char *, char *); - -int diofb_mapchar(void *, int, unsigned int *); -void diofb_cursor(void *, int, int, int); -void diofb_putchar(void *, int, int, u_int, long); void diofb_copycols(void *, int, int, int, int); void diofb_erasecols(void *, int, int, int, long); void diofb_copyrows(void *, int, int, int); void diofb_eraserows(void *, int, int, long); -const struct wsdisplay_emulops diofb_emulops = { - diofb_cursor, - diofb_mapchar, - diofb_putchar, - diofb_copycols, - diofb_erasecols, - diofb_copyrows, - diofb_eraserows, - diofb_alloc_attr -}; - /* * Frame buffer geometry initialization */ @@ -126,26 +104,25 @@ diofb_fbinquire(struct diofb *fb, int scode, struct diofbreg *fbr) } fb->fbsize = fb->fbwidth * fb->fbheight; + fb->regkva = (caddr_t)fbr; fboff = (fbr->fbomsb << 8) | fbr->fbolsb; fb->fbaddr = (caddr_t) (*((u_char *)fbr + fboff) << 16); if (fb->regaddr >= (caddr_t)DIOII_BASE) { /* - * For DIO II space the fbaddr just computed is + * For DIO-II space the fbaddr just computed is * the offset from the select code base (regaddr) * of the framebuffer. Hence it is also implicitly * the size of the set. */ regsize = (int)fb->fbaddr; fb->fbaddr += (int)fb->regaddr; - fb->regkva = (caddr_t)fbr; fb->fbkva = (caddr_t)fbr + regsize; } else { /* - * For DIO space we need to map the separate + * For internal or DIO-I space we need to map the separate * framebuffer. */ - fb->regkva = (caddr_t)fbr; fb->fbkva = iomap(fb->fbaddr, fb->fbsize); if (fb->fbkva == NULL) return (ENOMEM); @@ -164,136 +141,153 @@ diofb_fbinquire(struct diofb *fb, int scode, struct diofbreg *fbr) if (fb->dheight > fb->fbheight) fb->dheight = fb->fbheight; + fb->planes = fbr->num_planes; + if (fb->planes > 8) + fb->planes = 8; + fb->planemask = (1 << fb->planes) - 1; + + fb->mapmode = WSDISPLAYIO_MODE_DUMBFB; + return (0); } /* - * PROM font setup + * Frame buffer rasops and colormap setup */ void diofb_fbsetup(struct diofb *fb) { - u_long fontaddr = getword(fb, getword(fb, FONTROM) + FONTADDR); + struct rasops_info *ri = &fb->ri; /* - * Get font metrics. + * Pretend we are an 8bpp frame buffer, unless ri_depth is already + * initialized, since this is how it is supposed to be addressed. + * (Hyperion forces 1bpp because it is really 1bpp addressed). */ - fb->ftheight = getbyte(fb, fontaddr + FONTHEIGHT); - fb->ftwidth = getbyte(fb, fontaddr + FONTWIDTH); - fb->ftscale = fb->ftwidth; - fb->rows = fb->dheight / fb->ftheight; - fb->cols = fb->dwidth / fb->ftwidth; + if (ri->ri_depth == 0) + ri->ri_depth = 8; + ri->ri_stride = (fb->fbwidth * ri->ri_depth) / 8; - /* - * Decide where to put the font in off-screen memory. - */ - if (fb->fbwidth > fb->dwidth) { - /* Unpacked font will be to the right of the display */ - fb->fontx = fb->dwidth; - fb->fonty = 0; - fb->cpl = (fb->fbwidth - fb->dwidth) / fb->ftwidth; - fb->cblankx = fb->dwidth; - } else { - /* Unpacked font will be below the display */ - fb->fontx = 0; - fb->fonty = fb->dheight; - fb->cpl = fb->fbwidth / fb->ftwidth; - fb->cblankx = 0; - } - fb->cblanky = fb->fonty + ((FONTMAXCHAR / fb->cpl) + 1) * fb->ftheight; + ri->ri_flg = RI_CENTER | RI_FULLCLEAR; + ri->ri_bits = fb->fbkva; + ri->ri_width = fb->dwidth; + ri->ri_height = fb->dheight; + ri->ri_hw = fb; /* - * Clear display + * Ask for an unholy big display, rasops will trim this to more + * reasonable values. */ - (*fb->bmv)(fb, 0, 0, 0, 0, fb->fbwidth, fb->fbheight, RR_CLEAR); - fb->curvisible = 0; + rasops_init(ri, 160, 160); - /* - * Setup inverted cursor. - */ - (*fb->bmv)(fb, charX(fb, ' '), charY(fb, ' '), - fb->cblankx, fb->cblanky, fb->ftwidth, fb->ftheight, - RR_COPYINVERTED); + diofb_resetcmap(fb); - /* - * Default colormap - */ - bzero(&fb->cmap, sizeof(fb->cmap)); - fb->cmap.r[1] = 0xff; - fb->cmap.g[1] = 0xff; - fb->cmap.b[1] = 0xff; - fb->cmap.r[(1 << fb->planes) - 1] = 0xff; - fb->cmap.g[(1 << fb->planes) - 1] = 0xff; - fb->cmap.b[(1 << fb->planes) - 1] = 0xff; + if (fb->planes <= 4) + ri->ri_caps &= ~WSSCREEN_HILIT; + if (fb->planes < 4) + ri->ri_caps &= ~WSSCREEN_WSCOLORS; + + ri->ri_ops.copycols = diofb_copycols; + ri->ri_ops.copyrows = diofb_copyrows; + ri->ri_ops.erasecols = diofb_erasecols; + ri->ri_ops.eraserows = diofb_eraserows; + + /* Clear entire display, including non visible areas */ + (*fb->bmv)(fb, 0, 0, 0, 0, fb->fbwidth, fb->fbheight, RR_CLEAR); strlcpy(fb->wsd.name, "std", sizeof(fb->wsd.name)); - fb->wsd.ncols = fb->cols; - fb->wsd.nrows = fb->rows; - fb->wsd.textops = &diofb_emulops; - fb->wsd.fontwidth = fb->ftwidth; - fb->wsd.fontheight = fb->ftheight; - fb->wsd.capabilities = WSSCREEN_REVERSE; + fb->wsd.ncols = ri->ri_cols; + fb->wsd.nrows = ri->ri_rows; + fb->wsd.textops = &ri->ri_ops; + fb->wsd.fontwidth = ri->ri_font->fontwidth; + fb->wsd.fontheight = ri->ri_font->fontheight; + fb->wsd.capabilities = ri->ri_caps; } +/* + * Setup default emulation mode colormap + */ void -diofb_fontunpack(struct diofb *fb) +diofb_resetcmap(struct diofb *fb) { - char fontbuf[500]; /* XXX malloc not initialized yet */ - char *dp, *fbmem; - int bytewidth, glyphsize; - int c, i, romp; + const u_char *color; + u_int i; + + /* start with the rasops colormap */ + color = (const u_char *)rasops_cmap; + for (i = 0; i < 256; i++) { + fb->cmap.r[i] = *color++; + fb->cmap.g[i] = *color++; + fb->cmap.b[i] = *color++; + } /* - * Unpack PROM font to the off-screen location. + * Tweak colormap + * + * Due to the way rasops cursor work, we need to provide + * copies of the 8 or 16 basic colors at extra locations + * in 4bpp and 6bpp mode. This is because missing planes + * accept writes but read back as zero. + * + * So, in 6bpp mode: + * 00 gets inverted to ff, read back as 3f + * 3f gets inverted to c0, read back as 00 + * and in 4bpp mode: + * 00 gets inverted to ff, read back as 0f + * 0f gets inverted to f0, read back as 00 */ - bytewidth = (((fb->ftwidth - 1) / 8) + 1); - glyphsize = bytewidth * fb->ftheight; - romp = getword(fb, getword(fb, FONTROM) + FONTADDR) + FONTDATA; - for (c = 0; c < FONTMAXCHAR; c++) { - fbmem = (char *)(FBBASE(fb) + - (fb->fonty + (c / fb->cpl) * fb->ftheight) * fb->fbwidth + - (fb->fontx + (c % fb->cpl) * fb->ftwidth)); - dp = fontbuf; - for (i = 0; i < glyphsize; i++) { - *dp++ = getbyte(fb, romp); - romp += 2; - } - diofb_fontcopy(fb, fbmem, fontbuf); + + switch (fb->planes) { + case 6: + /* + * 00-0f normal colors + * 30-3f inverted colors + * c0-cf normal colors + * f0-ff inverted colors + */ + bcopy(fb->cmap.r + 0x00, fb->cmap.r + 0xc0, 0x10); + bcopy(fb->cmap.g + 0x00, fb->cmap.g + 0xc0, 0x10); + bcopy(fb->cmap.b + 0x00, fb->cmap.b + 0xc0, 0x10); + bcopy(fb->cmap.r + 0xf0, fb->cmap.r + 0x30, 0x10); + bcopy(fb->cmap.g + 0xf0, fb->cmap.g + 0x30, 0x10); + bcopy(fb->cmap.b + 0xf0, fb->cmap.b + 0x30, 0x10); + break; + case 4: + /* + * 00-07 normal colors + * 08-0f inverted colors + * highlighted colors are not available. + */ + bcopy(fb->cmap.r + 0xf8, fb->cmap.r + 0x08, 0x08); + bcopy(fb->cmap.g + 0xf8, fb->cmap.g + 0x08, 0x08); + bcopy(fb->cmap.b + 0xf8, fb->cmap.b + 0x08, 0x08); + break; } } +/* + * Attachment helpers + */ + void -diofb_fontcopy(struct diofb *fb, char *fbmem, char *glyphp) +diofb_cnattach(struct diofb *fb) { - int bn; - int l, b; - - for (l = 0; l < fb->ftheight; l++) { - bn = 7; - for (b = 0; b < fb->ftwidth; b++) { - if ((1 << bn) & *glyphp) - *fbmem++ = 1; - else - *fbmem++ = 0; - if (--bn < 0) { - bn = 7; - glyphp++; - } - } - if (bn < 7) - glyphp++; - fbmem -= fb->ftwidth; - fbmem += fb->fbwidth; - } + long defattr; + struct rasops_info *ri; + + ri = &fb->ri; + if (ri->ri_caps & WSSCREEN_WSCOLORS) + ri->ri_ops.alloc_attr(ri, WSCOL_WHITE, WSCOL_BLACK, + WSATTR_WSCOLORS, &defattr); + else + ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr); + wsdisplay_cnattach(&fb->wsd, ri, 0, 0, defattr); } -/* - * Attachment helper - */ void diofb_end_attach(void *sc, struct wsdisplay_accessops *accessops, - struct diofb *fb, int console, int planes, const char *descr) + struct diofb *fb, int console, const char *descr) { struct wsemuldisplaydev_attach_args waa; struct wsscreen_descr *scrlist[1]; @@ -301,12 +295,10 @@ diofb_end_attach(void *sc, struct wsdisplay_accessops *accessops, printf(": %dx%d", fb->dwidth, fb->dheight); - if (planes == 0) - planes = fb->planes; - if (planes == 1) + if (fb->planes == 1) printf(" monochrome"); else - printf("x%d", planes); + printf("x%d", fb->planes); if (descr != NULL) printf(" %s", descr); @@ -328,107 +320,93 @@ diofb_end_attach(void *sc, struct wsdisplay_accessops *accessops, * Common wsdisplay emulops for DIO frame buffers */ -/* the cursor is just an inverted space */ -#define flip_cursor(fb) \ -do { \ - (*fb->bmv)((fb), (fb)->cblankx, (fb)->cblanky, \ - (fb)->cursorx * (fb)->ftwidth, \ - (fb)->cursory * (fb)->ftheight, \ - (fb)->ftwidth, (fb)->ftheight, RR_XOR); \ -} while (0) - -int -diofb_alloc_attr(void *cookie, int fg, int bg, int flag, long *attrp) -{ - *attrp = flag & WSATTR_REVERSE; - return (0); -} - -int -diofb_mapchar(void *cookie, int c, unsigned int *cp) -{ - if (c < (int)' ' || c >= FONTMAXCHAR) { - *cp = ' '; - return (0); - } - - *cp = c; - return (5); -} - void -diofb_cursor(void *cookie, int on, int row, int col) +diofb_copycols(void *cookie, int row, int src, int dst, int n) { - struct diofb *fb = cookie; - - /* Turn old cursor off if necessary */ - if (fb->curvisible != 0) - flip_cursor(fb); + struct rasops_info *ri = cookie; + struct diofb *fb = ri->ri_hw; - fb->cursorx = col; - fb->cursory = row; + n *= ri->ri_font->fontwidth; + src *= ri->ri_font->fontwidth; + dst *= ri->ri_font->fontwidth; + row *= ri->ri_font->fontheight; - if ((fb->curvisible = on) != 0) - flip_cursor(fb); + (*fb->bmv)(fb, ri->ri_xorigin + src, ri->ri_yorigin + row, + ri->ri_xorigin + dst, ri->ri_yorigin + row, + n, ri->ri_font->fontheight, RR_COPY); } void -diofb_putchar(void *cookie, int row, int col, u_int uc, long attr) +diofb_copyrows(void *cookie, int src, int dst, int n) { - struct diofb *fb = cookie; - int wmrr; + struct rasops_info *ri = cookie; + struct diofb *fb = ri->ri_hw; - wmrr = (attr & WSATTR_REVERSE) ? RR_COPYINVERTED : RR_COPY; + n *= ri->ri_font->fontheight; + src *= ri->ri_font->fontheight; + dst *= ri->ri_font->fontheight; - (*fb->bmv)(fb, charX(fb, uc), charY(fb, uc), - col * fb->ftwidth, row * fb->ftheight, - fb->ftwidth, fb->ftheight, wmrr); + (*fb->bmv)(fb, ri->ri_xorigin, ri->ri_yorigin + src, + ri->ri_xorigin, ri->ri_yorigin + dst, + ri->ri_emuwidth, n, RR_COPY); } void -diofb_copycols(void *cookie, int row, int src, int dst, int n) +diofb_erasecols(void *cookie, int row, int col, int num, long attr) { - struct diofb *fb = cookie; + struct rasops_info *ri = cookie; + struct diofb *fb = ri->ri_hw; + int fg, bg, uline; - n *= fb->ftwidth; - src *= fb->ftwidth; - dst *= fb->ftwidth; - row *= fb->ftheight; + rasops_unpack_attr(attr, &fg, &bg, &uline); - (*fb->bmv)(fb, src, row, dst, row, n, fb->ftheight, RR_COPY); -} - -void -diofb_copyrows(void *cookie, int src, int dst, int n) -{ - struct diofb *fb = cookie; + /* + * If the background color is not black, this is a bit too tricky + * for the simple raster ops engine, so pass the fun to rasops. + */ + if (ri->ri_devcmap[bg] != 0) { + rasops_erasecols(cookie, row, col, num, attr); + return; + } - n *= fb->ftheight; - src *= fb->ftheight; - dst *= fb->ftheight; + num *= ri->ri_font->fontwidth; + col *= ri->ri_font->fontwidth; + row *= ri->ri_font->fontheight; - (*fb->bmv)(fb, 0, src, 0, dst, fb->dwidth, n, RR_COPY); + (*fb->bmv)(fb, ri->ri_xorigin + col, ri->ri_yorigin + row, + ri->ri_xorigin + col, ri->ri_yorigin + row, + num, ri->ri_font->fontheight, RR_CLEAR); } void -diofb_erasecols(void *cookie, int row, int col, int num, long attr) +diofb_eraserows(void *cookie, int row, int num, long attr) { - struct diofb *fb = cookie; + struct rasops_info *ri = cookie; + struct diofb *fb = ri->ri_hw; + int fg, bg, uline; - num *= fb->ftwidth; - col *= fb->ftwidth; - row *= fb->ftheight; - (*fb->bmv)(fb, col, row, col, row, num, fb->ftheight, RR_CLEAR); -} + rasops_unpack_attr(attr, &fg, &bg, &uline); -void -diofb_eraserows(void *cookie, int row, int num, long attr) -{ - struct diofb *fb = cookie; + /* + * If the background color is not black, this is a bit too tricky + * for the simple raster ops engine, so pass the fun to rasops. + */ + if (ri->ri_devcmap[bg] != 0) { + rasops_eraserows(cookie, row, num, attr); + return; + } - row *= fb->ftheight; - num *= fb->ftheight; - (*fb->bmv)(fb, 0, row, 0, row, fb->dwidth, num, RR_CLEAR); + /* As an exception, hunt the mouse all over the screen if necessary */ + if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR)) { + (*fb->bmv)(fb, 0, 0, 0, 0, + ri->ri_width, ri->ri_height, RR_CLEAR); + } else { + row *= ri->ri_font->fontheight; + num *= ri->ri_font->fontheight; + (*fb->bmv)(fb, ri->ri_xorigin, ri->ri_yorigin + row, + ri->ri_xorigin, ri->ri_yorigin + row, + ri->ri_emuwidth, num, RR_CLEAR); + } } /* @@ -440,13 +418,18 @@ diofb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, int *curxp, int *curyp, long *attrp) { struct diofb *fb = v; + struct rasops_info *ri = &fb->ri; if (fb->nscreens > 0) return (ENOMEM); - *cookiep = fb; + *cookiep = ri; *curxp = *curyp = 0; - diofb_alloc_attr(fb, 0, 0, 0, attrp); + if (ri->ri_caps & WSSCREEN_WSCOLORS) + ri->ri_ops.alloc_attr(ri, WSCOL_WHITE, WSCOL_BLACK, + WSATTR_WSCOLORS, attrp); + else + ri->ri_ops.alloc_attr(ri, 0, 0, 0, attrp); fb->nscreens++; return (0); @@ -472,11 +455,40 @@ diofb_mmap(void * v, off_t offset, int prot) { struct diofb *fb = v; - if (offset & PGOFSET) + if ((offset & PAGE_MASK) != 0) return (-1); - if (offset < 0 || offset >= fb->fbsize) - return (-1); + switch (fb->mapmode) { + case WSDISPLAYIO_MODE_MAPPED: + if (offset >= 0 && offset < DIOFB_REGSPACE) + return (((paddr_t)fb->regaddr + offset) >> PGSHIFT); + offset -= DIOFB_REGSPACE; + /* FALLTHROUGH */ + case WSDISPLAYIO_MODE_DUMBFB: + if (offset >= 0 && offset < fb->fbsize) + return (((paddr_t)fb->fbaddr + offset) >> PGSHIFT); + break; + } + + return (-1); +} + +int +diofb_getcmap(struct diofb *fb, struct wsdisplay_cmap *cm) +{ + u_int index = cm->index, count = cm->count; + u_int colcount = 1 << fb->planes; + int error; + + if (index >= colcount || count > colcount - index) + return (EINVAL); - return (((paddr_t)fb->fbaddr + offset) >> PGSHIFT); + if ((error = copyout(fb->cmap.r + index, cm->red, count)) != 0) + return (error); + if ((error = copyout(fb->cmap.g + index, cm->green, count)) != 0) + return (error); + if ((error = copyout(fb->cmap.b + index, cm->blue, count)) != 0) + return (error); + + return (0); } |