diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2006-01-22 19:40:55 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2006-01-22 19:40:55 +0000 |
commit | f50e21120b8ebbdbc501c5e983d375c333c12d85 (patch) | |
tree | a75835a7ba5ec68d265b3a10c6df55a3c4342185 | |
parent | 1f158e584073b8dec2d5cba982d36d6d024fd0fc (diff) |
Colormap support for DAFB frame buffers (using information from Linux).
However, color can not be enabled in emulation mode if the display is the
console at this point, but 8bpp X11 works.
-rw-r--r-- | sys/arch/mac68k/dev/grf_iv.c | 51 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/macfb.c | 205 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/macfbvar.h | 7 |
3 files changed, 212 insertions, 51 deletions
diff --git a/sys/arch/mac68k/dev/grf_iv.c b/sys/arch/mac68k/dev/grf_iv.c index db29a43e28e..93dd05a3d9a 100644 --- a/sys/arch/mac68k/dev/grf_iv.c +++ b/sys/arch/mac68k/dev/grf_iv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: grf_iv.c,v 1.37 2006/01/22 18:37:56 miod Exp $ */ +/* $OpenBSD: grf_iv.c,v 1.38 2006/01/22 19:40:54 miod Exp $ */ /* $NetBSD: grf_iv.c,v 1.17 1997/02/20 00:23:27 scottr Exp $ */ /* @@ -96,11 +96,14 @@ struct cfattach macfb_obio_ca = { #define DAFB_BASE 0xf9000000 #define DAFB_CONTROL_BASE 0xf9800000 +#define DAFB_CMAP_BASE 0xf9800200 #define CIVIC_BASE 0x50100000 #define CIVIC_CONTROL_BASE 0x50036000 #define VALKYRIE_BASE 0xf9000000 #define VALKYRIE_CONTROL_BASE 0x50f2a000 +void dafb_setcolor(void *, u_int, u_int); + int macfb_obio_match(struct device *parent, void *vcf, void *aux) { @@ -204,12 +207,15 @@ macfb_obio_attach(struct device *parent, struct device *self, void *aux) { struct obio_attach_args *oa = (struct obio_attach_args *) aux; struct macfb_softc *sc = (struct macfb_softc *)self; - u_long base, length; + u_long length; u_int32_t vbase1, vbase2; struct macfb_devconfig *dc; sc->card_id = 0; + dc = malloc(sizeof(*dc), M_DEVBUF, M_WAITOK); + bzero(dc, sizeof(*dc)); + switch (current_mac_model->class) { case MACH_CLASSQ2: if (current_mac_model->machineid != MACH_MACLC575) { @@ -231,10 +237,11 @@ macfb_obio_attach(struct device *parent, struct device *self, void *aux) /* See note in grfiv_match() */ /*FALLTHROUGH*/ case MACH_CLASSQ: - base = DAFB_CONTROL_BASE; sc->sc_tag = oa->oa_tag; - if (bus_space_map(sc->sc_tag, base, 0x20, 0, &sc->sc_regh)) { + if (bus_space_map(sc->sc_tag, DAFB_CONTROL_BASE, PAGE_SIZE, 0, + &sc->sc_regh)) { printf(": failed to map DAFB register space\n"); + free(dc, M_DEVBUF); return; } @@ -270,7 +277,11 @@ macfb_obio_attach(struct device *parent, struct device *self, void *aux) printf(": DAFB, monitor sense %x\n", (bus_space_read_4(sc->sc_tag, sc->sc_regh, 0x1c) & 0x7)); - bus_space_unmap(sc->sc_tag, sc->sc_regh, 0x20); + dc->dc_cmapregs = + (vaddr_t)bus_space_vaddr(sc->sc_tag, sc->sc_regh) + + (DAFB_CMAP_BASE - DAFB_CONTROL_BASE); + dc->dc_setcolor = dafb_setcolor; + break; case MACH_CLASSAV: sc->sc_basepa = CIVIC_BASE; @@ -333,6 +344,7 @@ macfb_obio_attach(struct device *parent, struct device *self, void *aux) if (bus_space_map(sc->sc_tag, sc->sc_basepa, length, 0, &sc->sc_handle)) { printf("%s: failed to map video RAM\n", sc->sc_dev.dv_xname); + free(dc, M_DEVBUF); return; } @@ -342,9 +354,6 @@ macfb_obio_attach(struct device *parent, struct device *self, void *aux) (vaddr_t)bus_space_vaddr(sc->sc_tag, sc->sc_handle) + sc->sc_fbofs; - dc = malloc(sizeof(*dc), M_DEVBUF, M_WAITOK); - bzero(dc, sizeof(*dc)); - dc->dc_vaddr = (vaddr_t)bus_space_vaddr(sc->sc_tag, sc->sc_handle); dc->dc_paddr = sc->sc_basepa; dc->dc_offset = sc->sc_fbofs; @@ -358,3 +367,29 @@ macfb_obio_attach(struct device *parent, struct device *self, void *aux) /* Perform common video attachment. */ macfb_attach_common(sc, dc); } + +/* + * Basic indexed modes palette handling. + */ + +void +dafb_setcolor(void *v, u_int start, u_int end) +{ + struct macfb_devconfig *dc = v; + u_int i; + u_int8_t *c; + + c = dc->dc_cmap; + + /* + * DAFB can not start a colormap update at a color index different + * than zero, so we need to reprogram all slots below the requested + * range. + */ + *(volatile u_int32_t *)(dc->dc_cmapregs) = 0; + for (i = 0; i < end; i++) { + *(volatile u_int8_t *)(dc->dc_cmapregs + 0x13) = *c++; + *(volatile u_int8_t *)(dc->dc_cmapregs + 0x13) = *c++; + *(volatile u_int8_t *)(dc->dc_cmapregs + 0x13) = *c++; + } +} diff --git a/sys/arch/mac68k/dev/macfb.c b/sys/arch/mac68k/dev/macfb.c index 53bae5db404..91a68f1ce3b 100644 --- a/sys/arch/mac68k/dev/macfb.c +++ b/sys/arch/mac68k/dev/macfb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: macfb.c,v 1.8 2006/01/10 21:19:14 miod Exp $ */ +/* $OpenBSD: macfb.c,v 1.9 2006/01/22 19:40:54 miod Exp $ */ /* $NetBSD: macfb.c,v 1.11 2005/01/15 16:00:59 chs Exp $ */ /* * Copyright (c) 1998 Matt DeBergalis @@ -73,9 +73,13 @@ const struct wsdisplay_accessops macfb_accessops = { NULL /* burner */ }; -int macfb_alloc_attr(void *, int, int, int, long *); +int macfb_alloc_cattr(void *, int, int, int, long *); +int macfb_alloc_mattr(void *, int, int, int, long *); +int macfb_color_setup(struct macfb_devconfig *); +int macfb_getcmap(struct macfb_devconfig *, struct wsdisplay_cmap *); int macfb_init(struct macfb_devconfig *); int macfb_is_console(paddr_t); +int macfb_putcmap(struct macfb_devconfig *, struct wsdisplay_cmap *); paddr_t macfb_consaddr; @@ -89,6 +93,8 @@ extern u_long videosize; extern u_int32_t mac68k_vidphys; extern u_int32_t mac68k_vidlen; +extern int rasops_alloc_cattr(void *, int, int, int, long *); + int macfb_is_console(paddr_t addr) { @@ -112,14 +118,7 @@ int macfb_init(struct macfb_devconfig *dc) { struct rasops_info *ri = &dc->dc_ri; - extern int rasops_alloc_cattr(void *, int, int, int, long *); - - /* - * Clear display. We can't pass RI_CLEAR in ri_flg and have rasops - * do it for us until we know how to setup the colormap first. - */ - memset((char *)dc->dc_vaddr + dc->dc_offset, - dc->dc_depth <= 8 ? 0xff : 0, dc->dc_rowbytes * dc->dc_ht); + int bgcolor; bzero(ri, sizeof(*ri)); ri->ri_depth = dc->dc_depth; @@ -147,17 +146,14 @@ macfb_init(struct macfb_devconfig *dc) if (rasops_init(ri, 160, 160) != 0) return (-1); - if (ri->ri_depth <= 8) { - /* - * Until we know how to setup the colormap, constrain ourselves - * to mono mode. Note that we need to use our own alloc_attr - * routine to compensate for inverted black and white colors. - */ - ri->ri_ops.alloc_attr = macfb_alloc_attr; - ri->ri_caps &= ~(WSSCREEN_WSCOLORS | WSSCREEN_HILIT); - if (ri->ri_depth == 8) - ri->ri_devcmap[15] = 0xffffffff; - } + bgcolor = macfb_color_setup(dc); + + /* + * Clear display. We can't pass RI_CLEAR in ri_flg and have rasops + * do it for us until we know how to setup the colormap first. + */ + memset((char *)dc->dc_vaddr + dc->dc_offset, bgcolor, + dc->dc_rowbytes * dc->dc_ht); strlcpy(dc->wsd.name, "std", sizeof(dc->wsd.name)); dc->wsd.ncols = ri->ri_cols; @@ -171,11 +167,57 @@ macfb_init(struct macfb_devconfig *dc) } int -macfb_alloc_attr(void *cookie, int fg, int bg, int flg, long *attr) +macfb_color_setup(struct macfb_devconfig *dc) { - struct rasops_info *ri = cookie; - int swap; + extern int rasops_alloc_cattr(void *, int, int, int, long *); + struct rasops_info *ri = &dc->dc_ri; + + /* nothing to do for non-indexed modes... */ + if (ri->ri_depth > 8) + return (0); /* fill in black */ + + if (dc->dc_setcolor == NULL || + ri->ri_depth < 4 /* XXX unfair with 2bpp */) { + /* + * Until we know how to setup the colormap, constrain ourselves + * to mono mode. Note that we need to use our own alloc_attr + * routine to compensate for inverted black and white colors. + */ + ri->ri_ops.alloc_attr = macfb_alloc_mattr; + if (ri->ri_depth == 8) + ri->ri_devcmap[15] = 0xffffffff; + return (0xff); /* fill in black inherited from MacOS */ + } + + /* start from the rasops colormap */ + bcopy(rasops_cmap, dc->dc_cmap, 256 * 3); + + switch (ri->ri_depth) { + case 4: + /* + * Tweak colormap + * + * Due to the way rasops cursor work, we need to provide + * inverted copies of the 8 basic colors as the other 8 + * in 4bpp mode. + */ + bcopy(dc->dc_cmap + (256 - 8) * 3, dc->dc_cmap + 8 * 3, 8 * 3); + ri->ri_caps |= WSSCREEN_WSCOLORS; + ri->ri_ops.alloc_attr = macfb_alloc_cattr; + break; + default: + case 8: + break; + } + (*dc->dc_setcolor)(dc, 0, 1 << ri->ri_depth); + + return (WSCOL_BLACK); /* fill in our own black */ +} + +int +macfb_alloc_mattr(void *cookie, int fg, int bg, int flg, long *attr) +{ if ((flg & (WSATTR_BLINK | WSATTR_HILIT | WSATTR_WSCOLORS)) != 0) return (EINVAL); @@ -183,24 +225,27 @@ macfb_alloc_attr(void *cookie, int fg, int bg, int flg, long *attr) * Default values are white on black. However, on indexed displays, * 0 is white and all bits set is black. */ - if (ri->ri_depth <= 8) { + if ((flg & WSATTR_REVERSE) != 0) { + fg = 15; + bg = 0; + } else { fg = 0; bg = 15; - } else { - bg = WSCOL_BLACK; - fg = WSCOL_WHITE; - } - - if ((flg & WSATTR_REVERSE) != 0) { - swap = fg; - fg = bg; - bg = swap; } *attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6); return (0); } +int +macfb_alloc_cattr(void *cookie, int fg, int bg, int flg, long *attr) +{ + if ((flg & (WSATTR_BLINK | WSATTR_HILIT)) != 0) + return (EINVAL); + + return (rasops_alloc_cattr(cookie, fg, bg, flg, attr)); +} + void macfb_attach_common(struct macfb_softc *sc, struct macfb_devconfig *dc) { @@ -223,6 +268,9 @@ macfb_attach_common(struct macfb_softc *sc, struct macfb_devconfig *dc) free(dc, M_DEVBUF); dc = sc->sc_dc = &macfb_console_dc; dc->nscreens = 1; + macfb_color_setup(dc); + /* XXX at this point we should reset the emulation to have + * it pick better attributes for kernel messages. Oh well. */ } else { sc->sc_dc = dc; if (macfb_init(dc) != 0) @@ -252,19 +300,30 @@ macfb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) case WSDISPLAYIO_GTYPE: *(int *)data = WSDISPLAY_TYPE_MAC68K; break; - case WSDISPLAYIO_GINFO: wdf = (struct wsdisplay_fbinfo *)data; wdf->height = dc->dc_ri.ri_height; wdf->width = dc->dc_ri.ri_width; wdf->depth = dc->dc_ri.ri_depth; - wdf->cmsize = 0; /* until we can change it... */ + if (dc->dc_ri.ri_depth > 8) + wdf->cmsize = 0; + else + wdf->cmsize = (dc->dc_ri.ri_caps & WSSCREEN_WSCOLORS) ? + 1 << dc->dc_ri.ri_depth : 0; break; - case WSDISPLAYIO_LINEBYTES: *(u_int *)data = dc->dc_ri.ri_stride; break; - + case WSDISPLAYIO_GETCMAP: + if (dc->dc_ri.ri_depth > 8 || + (dc->dc_ri.ri_caps & WSSCREEN_WSCOLORS) == 0) + return (0); + return (macfb_getcmap(dc, (struct wsdisplay_cmap *)data)); + case WSDISPLAYIO_PUTCMAP: + if (dc->dc_ri.ri_depth > 8 || + (dc->dc_ri.ri_caps & WSSCREEN_WSCOLORS) == 0) + return (0); + return (macfb_putcmap(dc, (struct wsdisplay_cmap *)data)); case WSDISPLAYIO_GVIDEO: case WSDISPLAYIO_SVIDEO: break; @@ -303,12 +362,10 @@ macfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, *cookiep = ri; *curxp = *curyp = 0; -#ifdef notyet if ((ri->ri_caps & WSSCREEN_WSCOLORS) && ri->ri_depth <= 8) ri->ri_ops.alloc_attr(ri, WSCOL_WHITE, WSCOL_BLACK, WSATTR_WSCOLORS, defattrp); else -#endif ri->ri_ops.alloc_attr(ri, 0, 0, 0, defattrp); sc->sc_dc->nscreens++; @@ -331,6 +388,72 @@ macfb_show_screen(void *v, void *cookie, int waitok, } int +macfb_getcmap(struct macfb_devconfig *dc, struct wsdisplay_cmap *cm) +{ + u_int index = cm->index, count = cm->count; + u_int colcount = 1 << dc->dc_ri.ri_depth; + int i, error; + u_int8_t ramp[256], *c, *r; + + if (index >= colcount || count > colcount - index) + return (EINVAL); + + /* extract reds */ + c = dc->dc_cmap + 0 + index * 3; + for (i = count, r = ramp; i != 0; i--) + *r++ = *c, c += 3; + if ((error = copyout(ramp, cm->red, count)) != 0) + return (error); + + /* extract greens */ + c = dc->dc_cmap + 1 + index * 3; + for (i = count, r = ramp; i != 0; i--) + *r++ = *c, c += 3; + if ((error = copyout(ramp, cm->green, count)) != 0) + return (error); + + /* extract blues */ + c = dc->dc_cmap + 2 + index * 3; + for (i = count, r = ramp; i != 0; i--) + *r++ = *c, c += 3; + if ((error = copyout(ramp, cm->blue, count)) != 0) + return (error); + + return (0); +} + +int +macfb_putcmap(struct macfb_devconfig *dc, struct wsdisplay_cmap *cm) +{ + u_int index = cm->index, count = cm->count; + u_int colcount = 1 << dc->dc_ri.ri_depth; + int i, error; + u_int8_t r[256], g[256], b[256], *nr, *ng, *nb, *c; + + if (index >= colcount || count > colcount - index) + return (EINVAL); + + if ((error = copyin(cm->red, r, count)) != 0) + return (error); + if ((error = copyin(cm->green, g, count)) != 0) + return (error); + if ((error = copyin(cm->blue, b, count)) != 0) + return (error); + + nr = r, ng = g, nb = b; + c = dc->dc_cmap + index * 3; + for (i = count; i != 0; i--) { + *c++ = *nr++; + *c++ = *ng++; + *c++ = *nb++; + } + + (*dc->dc_setcolor)(dc, index, index + count); + + return (0); +} + +int macfb_cnattach() { struct macfb_devconfig *dc = &macfb_console_dc; @@ -352,12 +475,10 @@ macfb_cnattach() return (-1); ri = &dc->dc_ri; -#ifdef notyet if ((ri->ri_caps & WSSCREEN_WSCOLORS) && ri->ri_depth <= 8) ri->ri_ops.alloc_attr(ri, WSCOL_WHITE, WSCOL_BLACK, WSATTR_WSCOLORS, &defattr); else -#endif ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr); wsdisplay_cnattach(&dc->wsd, ri, 0, 0, defattr); diff --git a/sys/arch/mac68k/dev/macfbvar.h b/sys/arch/mac68k/dev/macfbvar.h index 6a83cb31f87..9641ed3a52a 100644 --- a/sys/arch/mac68k/dev/macfbvar.h +++ b/sys/arch/mac68k/dev/macfbvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: macfbvar.h,v 1.4 2006/01/10 21:19:14 miod Exp $ */ +/* $OpenBSD: macfbvar.h,v 1.5 2006/01/22 19:40:54 miod Exp $ */ /* $NetBSD: macfbvar.h,v 1.3 2005/01/15 16:00:59 chs Exp $ */ /* $NetBSD: grfvar.h,v 1.11 1996/08/04 06:03:58 scottr Exp $ */ /* $NetBSD: grfioctl.h,v 1.5 1995/07/02 05:26:45 briggs Exp $ */ @@ -103,6 +103,7 @@ struct macfb_devconfig { vaddr_t dc_vaddr; /* memory space virtual base address */ paddr_t dc_paddr; /* memory space physical base address */ psize_t dc_size; /* size of slot memory */ + vaddr_t dc_cmapregs; /* va of cmap registers if known */ int dc_offset; /* offset to base of flat fb */ @@ -114,6 +115,10 @@ struct macfb_devconfig { /* rasops information */ struct rasops_info dc_ri; + /* shadow colormap */ + u_int8_t dc_cmap[256 * 3]; + void (*dc_setcolor)(void *, u_int, u_int); + /* wsdisplay information */ struct wsscreen_descr wsd; int nscreens; |