diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2003-04-06 17:02:33 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2003-04-06 17:02:33 +0000 |
commit | 7189e491adb5025608cce49cefa1c511bca038db (patch) | |
tree | a21d49d47543993bd353faa43b0a2a75c488bd6d | |
parent | 43cca2bab54cf98899acf891792e39889ccdd80f (diff) |
Run the console in the overlay plane, or in low-depth mode, as appropriate,
and do not switch to high-depth mode until the appropriate ioctls are
issued. This lets us benefit from true color X11, with a faster text console.
-rw-r--r-- | sys/arch/sparc/dev/cgfourteen.c | 190 | ||||
-rw-r--r-- | sys/arch/sparc/dev/cgtwelve.c | 350 | ||||
-rw-r--r-- | sys/arch/sparc/dev/tcx.c | 241 |
3 files changed, 365 insertions, 416 deletions
diff --git a/sys/arch/sparc/dev/cgfourteen.c b/sys/arch/sparc/dev/cgfourteen.c index 49616018d5c..3c1615dbf56 100644 --- a/sys/arch/sparc/dev/cgfourteen.c +++ b/sys/arch/sparc/dev/cgfourteen.c @@ -1,8 +1,8 @@ -/* $OpenBSD: cgfourteen.c,v 1.22 2003/04/06 17:00:35 miod Exp $ */ +/* $OpenBSD: cgfourteen.c,v 1.23 2003/04/06 17:02:32 miod Exp $ */ /* $NetBSD: cgfourteen.c,v 1.7 1997/05/24 20:16:08 pk Exp $ */ /* - * Copyright (c) 2002 Miodrag Vallat. All rights reserved. + * Copyright (c) 2002, 2003 Miodrag Vallat. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -78,8 +78,6 @@ /* * Driver for Campus-II on-board mbus-based video (cgfourteen). - * Provides minimum emulation of a Sun cgthree 8-bit framebuffer to - * allow X to run. * * Does not handle interrupts, even though they can occur. * @@ -133,6 +131,9 @@ struct cgfourteen_softc { struct cg14clut *sc_clut3; u_int *sc_clutincr; + int sc_32; /* can do 32bit at this resolution */ + size_t sc_vramsize; /* total video memory size */ + int sc_nscreens; }; @@ -156,7 +157,7 @@ void cgfourteen_free_screen(void *, void *); int cgfourteen_show_screen(void *, void *, int, void (*cb)(void *, int, int), void *); paddr_t cgfourteen_mmap(void *, off_t, int); -void cgfourteen_reset(struct cgfourteen_softc *); +void cgfourteen_reset(struct cgfourteen_softc *, int); void cgfourteen_burner(void *, u_int, u_int); void cgfourteen_prom(void *); @@ -234,7 +235,7 @@ cgfourteenattach(parent, self, args) struct cgfourteen_softc *sc = (struct cgfourteen_softc *)self; struct confargs *ca = args; struct wsemuldisplaydev_attach_args waa; - int fb_depth, node, i; + int node, i; u_int32_t *lut; int isconsole = 0; char *nam; @@ -253,14 +254,14 @@ cgfourteenattach(parent, self, args) * Sanity checks */ if (ca->ca_ra.ra_len < 0x10000) { - printf("\n"); - panic("cgfourteen: expected %x bytes of control " - "registers, got %x", 0x10000, ca->ca_ra.ra_len); + printf("\n%s: expected %x bytes of control registers, got %x\n", + self->dv_xname, 0x10000, ca->ca_ra.ra_len); + return; } if (ca->ca_ra.ra_nreg < CG14_NREG) { - printf("\n"); - panic("cgfourteen: expected %d registers, got %d", - CG14_NREG, ca->ca_ra.ra_nreg); + printf("\n%s: expected %d registers, got %d", + self->dv_xname, CG14_NREG, ca->ca_ra.ra_nreg); + return; } printf(", %dMB", ca->ca_ra.ra_reg[CG14_REG_VRAM].rr_len >> 20); @@ -291,39 +292,29 @@ cgfourteenattach(parent, self, args) */ sc->sc_phys = ca->ca_ra.ra_reg[CG14_REG_VRAM]; - if (ISSET(sc->sc_sunfb.sf_flags, FB_FORCELOW)) - fb_depth = 8; - else - fb_depth = 32; - - fb_setsize(&sc->sc_sunfb, fb_depth, 1152, 900, node, ca->ca_bustype); + fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype); /* - * The prom will report depth == 8, since this is the mode - * it will get initialized in. - * Try to compensate and enable 32 bit mode, unless it would - * not fit in the video memory. Note that, in this case, the + * The prom will report depth == 8, since this is the mode it will + * get initialized in. + * Check if we will be able to use 32 bit mode later (i.e. if it will + * fit in the video memory. Note that, if this is not the case, the * VSIMM will usually not appear in the OBP device tree! */ - if (fb_depth == 32 && sc->sc_sunfb.sf_depth == 8 && - sc->sc_sunfb.sf_fbsize * 4 <= - ca->ca_ra.ra_reg[CG14_REG_VRAM].rr_len) { - sc->sc_sunfb.sf_depth = 32; - sc->sc_sunfb.sf_linebytes *= 4; - sc->sc_sunfb.sf_fbsize *= 4; - } + sc->sc_vramsize = ca->ca_ra.ra_reg[CG14_REG_VRAM].rr_len; + sc->sc_32 = sc->sc_sunfb.sf_fbsize * 4 <= sc->sc_vramsize; sc->sc_sunfb.sf_ro.ri_bits = mapiodev(&ca->ca_ra.ra_reg[CG14_REG_VRAM], 0, /* CHUNKY_XBGR */ - round_page(sc->sc_sunfb.sf_fbsize)); + sc->sc_vramsize); - printf(", %dx%d, depth %d\n", sc->sc_sunfb.sf_width, - sc->sc_sunfb.sf_height, sc->sc_sunfb.sf_depth); + printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); /* * Reset frame buffer controls */ - cgfourteen_reset(sc); + sc->sc_sunfb.sf_depth = 0; /* force action */ + cgfourteen_reset(sc, 8); /* * Grab the initial colormap @@ -348,8 +339,7 @@ cgfourteenattach(parent, self, args) if (isconsole) { fbwscons_console_init(&sc->sc_sunfb, &cgfourteen_stdscreen, - sc->sc_sunfb.sf_depth == 8 ? -1 : 0, - cgfourteen_burner); + -1, cgfourteen_burner); shutdownhook_establish(cgfourteen_prom, sc); } @@ -373,48 +363,59 @@ cgfourteen_ioctl(dev, cmd, data, flags, p) struct wsdisplay_fbinfo *wdf; int error; + /* + * Note that, although the emulation (text) mode is running in a + * 8-bit plane, we advertize the frame buffer as 32-bit if it can + * support this mode. + */ switch (cmd) { case WSDISPLAYIO_GTYPE: - *(u_int *)data = WSDISPLAY_TYPE_SUN24; + if (sc->sc_32) + *(u_int *)data = WSDISPLAY_TYPE_SUN24; + else + *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN; break; case WSDISPLAYIO_GINFO: wdf = (struct wsdisplay_fbinfo *)data; wdf->height = sc->sc_sunfb.sf_height; wdf->width = sc->sc_sunfb.sf_width; - wdf->depth = sc->sc_sunfb.sf_depth; - wdf->cmsize = (sc->sc_sunfb.sf_depth == 8) ? 256 : 0; + wdf->depth = sc->sc_32 ? 32 : 8; + wdf->cmsize = sc->sc_32 ? 0 : 256; break; case WSDISPLAYIO_LINEBYTES: - *(u_int *)data = sc->sc_sunfb.sf_linebytes; + if (sc->sc_32) + *(u_int *)data = sc->sc_sunfb.sf_linebytes * 4; + else + *(u_int *)data = sc->sc_sunfb.sf_linebytes; break; case WSDISPLAYIO_GETCMAP: - if (sc->sc_sunfb.sf_depth == 8) { - cm = (struct wsdisplay_cmap *)data; - error = cgfourteen_getcmap(&sc->sc_cmap, cm); - if (error) - return (error); - } + cm = (struct wsdisplay_cmap *)data; + error = cgfourteen_getcmap(&sc->sc_cmap, cm); + if (error) + return (error); break; case WSDISPLAYIO_PUTCMAP: - if (sc->sc_sunfb.sf_depth == 8) { - cm = (struct wsdisplay_cmap *)data; - error = cgfourteen_putcmap(&sc->sc_cmap, cm); - if (error) - return (error); - /* XXX should use retrace interrupt */ - cgfourteen_loadcmap(sc, cm->index, cm->count); + cm = (struct wsdisplay_cmap *)data; + error = cgfourteen_putcmap(&sc->sc_cmap, cm); + if (error) + return (error); + /* XXX should use retrace interrupt */ + cgfourteen_loadcmap(sc, cm->index, cm->count); + break; + + case WSDISPLAYIO_SMODE: + if (*(int *)data == WSDISPLAYIO_MODE_EMUL) { + /* Back from X11 to text mode */ + cgfourteen_reset(sc, 8); + } else { + /* Starting X11, try to switch to 32 bit mode */ + if (sc->sc_32) + cgfourteen_reset(sc, 32); } break; - case WSDISPLAYIO_SVIDEO: - case WSDISPLAYIO_GVIDEO: - case WSDISPLAYIO_GCURPOS: - case WSDISPLAYIO_SCURPOS: - case WSDISPLAYIO_GCURMAX: - case WSDISPLAYIO_GCURSOR: - case WSDISPLAYIO_SCURSOR: default: return (-1); /* not supported yet */ } @@ -437,12 +438,8 @@ cgfourteen_alloc_screen(v, type, cookiep, curxp, curyp, attrp) *cookiep = &sc->sc_sunfb.sf_ro; *curyp = 0; *curxp = 0; - if (sc->sc_sunfb.sf_depth == 8) - sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro, - WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp); - else - sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro, - 0, 0, 0, attrp); + sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro, + WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp); sc->sc_nscreens++; return (0); } @@ -484,7 +481,7 @@ cgfourteen_mmap(v, offset, prot) return (-1); /* Allow mapping as a dumb framebuffer from offset 0 */ - if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) { + if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize * 4) { return (REG2PHYS(&sc->sc_phys, offset) | PMAP_NC); } @@ -493,36 +490,42 @@ cgfourteen_mmap(v, offset, prot) /* Initialize the framebuffer, storing away useful state for later reset */ void -cgfourteen_reset(sc) +cgfourteen_reset(sc, depth) struct cgfourteen_softc *sc; + int depth; { - if (sc->sc_sunfb.sf_depth == 8) { - /* - * Enable the video and put it in 8 bit mode - */ - sc->sc_ctl->ctl_mctl = CG14_MCTL_ENABLEVID | - CG14_MCTL_PIXMODE_8 | CG14_MCTL_POWERCTL; - } else { - /* - * Enable the video, and put in 32 bit mode. - */ - sc->sc_ctl->ctl_mctl = CG14_MCTL_ENABLEVID | - CG14_MCTL_PIXMODE_32 | CG14_MCTL_POWERCTL; - - /* - * Clear the screen to white - */ - memset(sc->sc_sunfb.sf_ro.ri_bits, 0xff, - round_page(sc->sc_sunfb.sf_fbsize)); - - /* - * Zero the xlut to enable direct-color mode - */ - bzero(sc->sc_xlut, CG14_CLUT_SIZE); - - shutdownhook_establish(cgfourteen_prom, sc); + if (sc->sc_sunfb.sf_depth != depth) { + if (depth == 8) { + /* + * Enable the video and put it in 8 bit mode + */ + sc->sc_ctl->ctl_mctl = CG14_MCTL_ENABLEVID | + CG14_MCTL_PIXMODE_8 | CG14_MCTL_POWERCTL; + + fbwscons_setcolormap(&sc->sc_sunfb, + cgfourteen_setcolor); + } else { + /* + * Clear the screen to black + */ + bzero(sc->sc_sunfb.sf_ro.ri_bits, + sc->sc_sunfb.sf_fbsize); + + /* + * Enable the video, and put in 32 bit mode. + */ + sc->sc_ctl->ctl_mctl = CG14_MCTL_ENABLEVID | + CG14_MCTL_PIXMODE_32 | CG14_MCTL_POWERCTL; + + /* + * Zero the xlut to enable direct-color mode + */ + bzero(sc->sc_xlut, CG14_CLUT_SIZE); + } } + + sc->sc_sunfb.sf_depth = depth; } void @@ -536,8 +539,7 @@ cgfourteen_prom(v) /* * Go back to 8-bit mode. */ - sc->sc_ctl->ctl_mctl = CG14_MCTL_ENABLEVID | - CG14_MCTL_PIXMODE_8 | CG14_MCTL_POWERCTL; + cgfourteen_reset(sc, 8); /* * Go back to prom output for the last few messages, so they diff --git a/sys/arch/sparc/dev/cgtwelve.c b/sys/arch/sparc/dev/cgtwelve.c index af9a07e53fd..ed201fa3520 100644 --- a/sys/arch/sparc/dev/cgtwelve.c +++ b/sys/arch/sparc/dev/cgtwelve.c @@ -1,7 +1,7 @@ -/* $OpenBSD: cgtwelve.c,v 1.5 2002/11/06 21:06:20 miod Exp $ */ +/* $OpenBSD: cgtwelve.c,v 1.6 2003/04/06 17:02:32 miod Exp $ */ /* - * Copyright (c) 2002 Miodrag Vallat. All rights reserved. + * Copyright (c) 2002, 2003 Miodrag Vallat. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -36,12 +36,12 @@ * SPARCstation 1, 1+, 2 and 5, or in an xbox SBUS extension (untested). * * It is a 24-bit 3D accelerated framebuffer made by Matrox, featuring 4MB - * (regular model) or 8MB (high-res model) of video memory, a complex windowing - * engine, double buffering modes, three video planes (overlay, 8 bit and 24 bit - * color), and a lot of colormap combinations. + * (regular model) or 8MB (high-res model) of video memory, a complex + * windowing engine, double buffering modes, three video planes (overlay, + * 8 bit and 24 bit color), and a lot of colormap combinations. * - * All of this is driven by a set of three Bt462 ramdacs, and a couple of - * Matrox-specific chips. + * All of this is driven by a set of three Bt462 ramdacs (latched unless + * explicitely programmed), and a couple of other Matrox-specific chips. * * XXX The high res card is untested. */ @@ -110,14 +110,11 @@ void cgtwelve_free_screen(void *, void *); int cgtwelve_show_screen(void *, void *, int, void (*cb)(void *, int, int), void *); paddr_t cgtwelve_mmap(void *, off_t, int); -void cgtwelve_reset(struct cgtwelve_softc *); -void cgtwelve_burner(void *, u_int, u_int); +void cgtwelve_reset(struct cgtwelve_softc *, int); void cgtwelve_prom(void *); static __inline__ void cgtwelve_ramdac_wraddr(struct cgtwelve_softc *sc, u_int32_t addr); -void cgtwelve_initcmap(struct cgtwelve_softc *); -void cgtwelve_darkcmap(struct cgtwelve_softc *); struct wsdisplay_accessops cgtwelve_accessops = { cgtwelve_ioctl, @@ -128,7 +125,7 @@ struct wsdisplay_accessops cgtwelve_accessops = { NULL, /* load_font */ NULL, /* scrollback */ NULL, /* getchar */ - cgtwelve_burner + NULL, /* burner */ }; int cgtwelvematch(struct device *, void *, void *); @@ -155,13 +152,10 @@ cgtwelvematch(parent, vcf, aux) struct confargs *ca = aux; struct romaux *ra = &ca->ca_ra; - if (strcmp(cf->cf_driver->cd_name, ra->ra_name)) + if (strcmp(cf->cf_driver->cd_name, ra->ra_name) != 0) return (0); - if (ca->ca_bustype == BUS_SBUS) - return (1); - - return (0); + return (1); } /* @@ -175,7 +169,7 @@ cgtwelveattach(parent, self, args) struct cgtwelve_softc *sc = (struct cgtwelve_softc *)self; struct confargs *ca = args; struct wsemuldisplaydev_attach_args waa; - int fb_depth, node; + int node; int isconsole = 0; char *ps; @@ -203,23 +197,15 @@ cgtwelveattach(parent, self, args) CG12_OFF_DAC, sizeof(struct cgtwelve_dac)); /* - * Compute framebuffer size + * The console is using the 1-bit overlay plane, while the prom + * will correctly report 32 bit depth. */ - if (ISSET(sc->sc_sunfb.sf_flags, FB_FORCELOW)) - fb_depth = 1; - else - fb_depth = 32; - - fb_setsize(&sc->sc_sunfb, fb_depth, CG12_WIDTH, CG12_HEIGHT, + fb_setsize(&sc->sc_sunfb, 1, CG12_WIDTH, CG12_HEIGHT, node, ca->ca_bustype); - - if (fb_depth == 1 && sc->sc_sunfb.sf_depth == 32) { - /* the prom will report depth == 32, so compensate */ - sc->sc_sunfb.sf_depth = 1; - sc->sc_sunfb.sf_linebytes = sc->sc_sunfb.sf_width / 8; - sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height * - sc->sc_sunfb.sf_linebytes; - } + sc->sc_sunfb.sf_depth = 1; + sc->sc_sunfb.sf_linebytes = sc->sc_sunfb.sf_width / 8; + sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height * + sc->sc_sunfb.sf_linebytes; sc->sc_highres = sc->sc_sunfb.sf_width == CG12_WIDTH_HR; @@ -230,25 +216,16 @@ cgtwelveattach(parent, self, args) sc->sc_highres ? CG12_OFF_OVERLAY0_HR : CG12_OFF_OVERLAY0, round_page(sc->sc_highres ? CG12_SIZE_OVERLAY_HR : CG12_SIZE_OVERLAY)); - if (sc->sc_sunfb.sf_depth != 1) - sc->sc_inten = mapiodev(ca->ca_ra.ra_reg, - sc->sc_highres ? CG12_OFF_INTEN_HR : CG12_OFF_INTEN, - round_page(sc->sc_highres ? CG12_SIZE_COLOR24_HR : - CG12_SIZE_COLOR24)); + sc->sc_inten = mapiodev(ca->ca_ra.ra_reg, + sc->sc_highres ? CG12_OFF_INTEN_HR : CG12_OFF_INTEN, + round_page(sc->sc_highres ? CG12_SIZE_COLOR24_HR : + CG12_SIZE_COLOR24)); /* reset cursor & frame buffer controls */ - cgtwelve_reset(sc); - - if (sc->sc_sunfb.sf_depth != 1) { - /* enable video */ - cgtwelve_burner(sc, 1, 0); - } - - if (sc->sc_sunfb.sf_depth == 1) - sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_overlay; - else - sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_inten; + sc->sc_sunfb.sf_depth = 0; /* force action */ + cgtwelve_reset(sc, 1); + sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_overlay; sc->sc_sunfb.sf_ro.ri_hw = sc; fbwscons_init(&sc->sc_sunfb, isconsole); @@ -258,17 +235,8 @@ cgtwelveattach(parent, self, args) cgtwelve_stdscreen.textops = &sc->sc_sunfb.sf_ro.ri_ops; if (isconsole) { - if (sc->sc_sunfb.sf_depth == 1) { - fbwscons_console_init(&sc->sc_sunfb, - &cgtwelve_stdscreen, -1, NULL); - } else { - /* - * Since the screen has been cleared, restart at the - * top of the screen. - */ - fbwscons_console_init(&sc->sc_sunfb, - &cgtwelve_stdscreen, 0, cgtwelve_burner); - } + fbwscons_console_init(&sc->sc_sunfb, + &cgtwelve_stdscreen, -1, NULL); shutdownhook_establish(cgtwelve_prom, sc); } @@ -299,35 +267,40 @@ cgtwelve_ioctl(dev, cmd, data, flags, p) struct cgtwelve_softc *sc = dev; struct wsdisplay_fbinfo *wdf; + /* + * Note that, although the emulation (text) mode is running in the + * overlay plane, we advertize the frame buffer as the full-blown + * 32-bit beast it is. + */ switch (cmd) { case WSDISPLAYIO_GTYPE: - if (sc->sc_sunfb.sf_depth == 1) - *(u_int *)data = WSDISPLAY_TYPE_SUNBW; - else - *(u_int *)data = WSDISPLAY_TYPE_SUN24; + *(u_int *)data = WSDISPLAY_TYPE_SUN24; break; case WSDISPLAYIO_GINFO: wdf = (struct wsdisplay_fbinfo *)data; wdf->height = sc->sc_sunfb.sf_height; wdf->width = sc->sc_sunfb.sf_width; - wdf->depth = sc->sc_sunfb.sf_depth; + wdf->depth = 32; wdf->cmsize = 0; break; case WSDISPLAYIO_LINEBYTES: - *(u_int *)data = sc->sc_sunfb.sf_linebytes; + *(u_int *)data = sc->sc_sunfb.sf_linebytes * 32; break; case WSDISPLAYIO_GETCMAP: case WSDISPLAYIO_PUTCMAP: break; - case WSDISPLAYIO_SVIDEO: - case WSDISPLAYIO_GVIDEO: - case WSDISPLAYIO_GCURPOS: - case WSDISPLAYIO_SCURPOS: - case WSDISPLAYIO_GCURMAX: - case WSDISPLAYIO_GCURSOR: - case WSDISPLAYIO_SCURSOR: + case WSDISPLAYIO_SMODE: + if (*(int *)data == WSDISPLAYIO_MODE_EMUL) { + /* Back from X11 to text mode */ + cgtwelve_reset(sc, 1); + } else { + /* Starting X11, switch to 32 bit mode */ + cgtwelve_reset(sc, 32); + } + break; + default: return (-1); /* not supported yet */ } @@ -339,58 +312,104 @@ cgtwelve_ioctl(dev, cmd, data, flags, p) * Clean up hardware state (e.g., after bootup or after X crashes). */ void -cgtwelve_reset(sc) +cgtwelve_reset(sc, depth) struct cgtwelve_softc *sc; + int depth; { - if (sc->sc_sunfb.sf_depth == 1) - return; + u_int32_t c; - /* - * Select the overlay plane as sc_overlay. - */ - sc->sc_apu->hpage = - sc->sc_highres ? CG12_HPAGE_OVERLAY_HR : CG12_HPAGE_OVERLAY; - sc->sc_apu->haccess = CG12_HACCESS_OVERLAY; - sc->sc_dpu->pln_sl_host = CG12_PLN_SL_OVERLAY; - sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_OVERLAY; - sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_OVERLAY; + if (sc->sc_sunfb.sf_depth != depth) { + if (depth == 1) { + /* + * Select the enable plane as sc_overlay, and fill it. + */ + sc->sc_apu->hpage = sc->sc_highres ? + CG12_HPAGE_ENABLE_HR : CG12_HPAGE_ENABLE; + sc->sc_apu->haccess = CG12_HACCESS_ENABLE; + sc->sc_dpu->pln_sl_host = CG12_PLN_SL_ENABLE; + sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_ENABLE; + sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_ENABLE; - /* - * Do not attempt to somewhat preserve screen contents - reading the - * overlay plane and writing to the color plane at the same time is not - * reliable, and allocating memory to save a copy of the overlay plane - * would be awful. - */ - bzero((void *)sc->sc_overlay, - sc->sc_highres ? CG12_SIZE_OVERLAY_HR : CG12_SIZE_OVERLAY); + memset((void *)sc->sc_overlay, 0xff, sc->sc_highres ? + CG12_SIZE_ENABLE_HR : CG12_SIZE_ENABLE); - /* - * Select the enable plane as sc_overlay, and clear it. - */ - sc->sc_apu->hpage = - sc->sc_highres ? CG12_HPAGE_ENABLE_HR : CG12_HPAGE_ENABLE; - sc->sc_apu->haccess = CG12_HACCESS_ENABLE; - sc->sc_dpu->pln_sl_host = CG12_PLN_SL_ENABLE; - sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_ENABLE; - sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_ENABLE; + /* + * Select the overlay plane as sc_overlay. + */ + sc->sc_apu->hpage = sc->sc_highres ? + CG12_HPAGE_OVERLAY_HR : CG12_HPAGE_OVERLAY; + sc->sc_apu->haccess = CG12_HACCESS_OVERLAY; + sc->sc_dpu->pln_sl_host = CG12_PLN_SL_OVERLAY; + sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_OVERLAY; + sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_OVERLAY; + + /* + * Upload a strict mono colormap, or the text + * upon returning from 32 bit mode would appear + * as (slightly dark) white on white. + */ + cgtwelve_ramdac_wraddr(sc, 0); + sc->sc_ramdac->color = 0x00000000; + for (c = 1; c < 256; c++) + sc->sc_ramdac->color = 0x00ffffff; + } else { + /* + * Select the overlay plane as sc_overlay. + */ + sc->sc_apu->hpage = sc->sc_highres ? + CG12_HPAGE_OVERLAY_HR : CG12_HPAGE_OVERLAY; + sc->sc_apu->haccess = CG12_HACCESS_OVERLAY; + sc->sc_dpu->pln_sl_host = CG12_PLN_SL_OVERLAY; + sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_OVERLAY; + sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_OVERLAY; - bzero((void *)sc->sc_overlay, - sc->sc_highres ? CG12_SIZE_ENABLE_HR : CG12_SIZE_ENABLE); + /* + * Do not attempt to somewhat preserve screen + * contents - reading the overlay plane and writing + * to the color plane at the same time is not + * reliable, and allocating memory to save a copy + * of the overlay plane would be awful. + */ + bzero((void *)sc->sc_overlay, sc->sc_highres ? + CG12_SIZE_OVERLAY_HR : CG12_SIZE_OVERLAY); - /* - * Select the intensity (color) plane, and clear it. - */ - sc->sc_apu->hpage = - sc->sc_highres ? CG12_HPAGE_24BIT_HR : CG12_HPAGE_24BIT; - sc->sc_apu->haccess = CG12_HACCESS_24BIT; - sc->sc_dpu->pln_sl_host = CG12_PLN_SL_24BIT; - sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_24BIT; - sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_24BIT; + /* + * Select the enable plane as sc_overlay, and clear it. + */ + sc->sc_apu->hpage = sc->sc_highres ? + CG12_HPAGE_ENABLE_HR : CG12_HPAGE_ENABLE; + sc->sc_apu->haccess = CG12_HACCESS_ENABLE; + sc->sc_dpu->pln_sl_host = CG12_PLN_SL_ENABLE; + sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_ENABLE; + sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_ENABLE; - memset((void *)sc->sc_inten, 0x00ffffff, - sc->sc_highres ? CG12_SIZE_COLOR24_HR : CG12_SIZE_COLOR24); + bzero((void *)sc->sc_overlay, sc->sc_highres ? + CG12_SIZE_ENABLE_HR : CG12_SIZE_ENABLE); - shutdownhook_establish(cgtwelve_prom, sc); + /* + * Select the intensity (color) plane, and clear it. + */ + sc->sc_apu->hpage = sc->sc_highres ? + CG12_HPAGE_24BIT_HR : CG12_HPAGE_24BIT; + sc->sc_apu->haccess = CG12_HACCESS_24BIT; + sc->sc_dpu->pln_sl_host = CG12_PLN_SL_24BIT; + sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_24BIT; + sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_24BIT; + + memset((void *)sc->sc_inten, 0x00ffffff, + sc->sc_highres ? + CG12_SIZE_COLOR24_HR : CG12_SIZE_COLOR24); + + /* + * Use a direct colormap (ramp) + */ + cgtwelve_ramdac_wraddr(sc, 0); + for (c = 0; c < 256; c++) + sc->sc_ramdac->color = c | (c << 8) | (c << 16); + } + } + + sc->sc_sunfb.sf_depth = depth; } /* @@ -405,20 +424,17 @@ cgtwelve_mmap(v, offset, prot) { struct cgtwelve_softc *sc = v; - if (offset & PGOFSET) + if (offset & PGOFSET || offset < 0) return (-1); - /* Allow mapping as a dumb framebuffer from offset 0 */ - if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) { - if (sc->sc_sunfb.sf_depth == 1) { - return (REG2PHYS(&sc->sc_phys, - (sc->sc_highres ? CG12_OFF_OVERLAY0_HR : - CG12_OFF_OVERLAY0) + offset) | PMAP_NC); - } else { - return (REG2PHYS(&sc->sc_phys, - (sc->sc_highres ? CG12_OFF_INTEN_HR : - CG12_OFF_INTEN) + offset) | PMAP_NC); - } + /* + * Note that mmap() will invoke this function only if we are NOT + * in emulation mode, so we can assume 32 bit mode safely here. + */ + if (offset < sc->sc_sunfb.sf_fbsize * 32) { + return (REG2PHYS(&sc->sc_phys, + (sc->sc_highres ? CG12_OFF_INTEN_HR : + CG12_OFF_INTEN) + offset) | PMAP_NC); } return (-1); /* not a user-map offset */ @@ -478,50 +494,6 @@ cgtwelve_ramdac_wraddr(struct cgtwelve_softc *sc, u_int32_t addr) sc->sc_ramdac->addr_hi = ((addr >> 8) & 0xff); } -void -cgtwelve_initcmap(sc) - struct cgtwelve_softc *sc; -{ - u_int32_t c; - - /* - * Since we are using the framebuffer in true color mode, there is - * theoretically no ramdac initialisation to do. - * In practice, we have to load a ramp on each ramdac first. - * Fortunately they are latched on each other at this point, so by - * loading one single ramp, all of them get initialized. - */ - cgtwelve_ramdac_wraddr(sc, 0); - for (c = 0; c < 256; c++) - sc->sc_ramdac->color = c | (c << 8) | (c << 16); -} - -void -cgtwelve_darkcmap(sc) - struct cgtwelve_softc *sc; -{ - u_int32_t c; - - cgtwelve_ramdac_wraddr(sc, 0); - for (c = 0; c < 256; c++) - sc->sc_ramdac->color = 0; -} - -void cgtwelve_burner(v, on, flags) - void *v; - u_int on, flags; -{ - struct cgtwelve_softc *sc = v; - - if (sc->sc_sunfb.sf_depth == 1) - return; - - if (on) - cgtwelve_initcmap(sc); - else - cgtwelve_darkcmap(sc); -} - /* * Shutdown hook used to restore PROM-compatible video mode on shutdown, * so that the PROM prompt is visible again. @@ -531,33 +503,15 @@ cgtwelve_prom(v) void *v; { struct cgtwelve_softc *sc = v; - int c; extern struct consdev consdev_prom; - /* - * Select the overlay plane. - */ - sc->sc_apu->hpage = - sc->sc_highres ? CG12_HPAGE_OVERLAY_HR : CG12_HPAGE_OVERLAY; - sc->sc_apu->haccess = CG12_HACCESS_OVERLAY; - sc->sc_dpu->pln_sl_host = CG12_PLN_SL_OVERLAY; - sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_OVERLAY; - sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_OVERLAY; - - /* - * Do not touch enable and intensity planes, so that kernel - * messages can still be read when back to the prom. - * However, we need to fix the colormap, or the prompt will come - * back as white on white. - */ - cgtwelve_ramdac_wraddr(sc, 0); - sc->sc_ramdac->color = 0x00ffffff; - for (c = 1; c < 256; c++) - sc->sc_ramdac->color = 0x00000000; + if (sc->sc_sunfb.sf_depth != 1) { + cgtwelve_reset(sc, 1); - /* - * Go back to prom output for the last few messages, so they - * will be displayed correctly. - */ - cn_tab = &consdev_prom; + /* + * Go back to prom output for the last few messages, so they + * will be displayed correctly. + */ + cn_tab = &consdev_prom; + } } diff --git a/sys/arch/sparc/dev/tcx.c b/sys/arch/sparc/dev/tcx.c index 85a4a7717dd..2e444346c8a 100644 --- a/sys/arch/sparc/dev/tcx.c +++ b/sys/arch/sparc/dev/tcx.c @@ -1,8 +1,8 @@ -/* $OpenBSD: tcx.c,v 1.15 2002/12/10 20:32:57 miod Exp $ */ +/* $OpenBSD: tcx.c,v 1.16 2003/04/06 17:02:32 miod Exp $ */ /* $NetBSD: tcx.c,v 1.8 1997/07/29 09:58:14 fair Exp $ */ /* - * Copyright (c) 2002 Miodrag Vallat. All rights reserved. + * Copyright (c) 2002, 2003 Miodrag Vallat. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -105,6 +105,8 @@ struct tcx_softc { struct rom_reg sc_phys[TCX_NREG]; /* phys addr of h/w */ volatile struct bt_regs *sc_bt; /* Brooktree registers */ volatile struct tcx_thc *sc_thc; /* THC registers */ + volatile u_int8_t *sc_dfb8; /* 8 bit plane */ + volatile u_int32_t *sc_dfb24; /* S24 24 bit plane */ volatile u_int32_t *sc_cplane; /* S24 control plane */ union bt_cmap sc_cmap; /* Brooktree color map */ struct intrhand sc_ih; @@ -117,7 +119,6 @@ struct wsscreen_descr tcx_stdscreen = { const struct wsscreen_descr *tcx_scrlist[] = { &tcx_stdscreen, - /* XXX other formats? */ }; struct wsscreen_list tcx_screenlist = { @@ -131,7 +132,7 @@ void tcx_free_screen(void *, void *); int tcx_show_screen(void *, void *, int, void (*cb)(void *, int, int), void *); paddr_t tcx_mmap(void *, off_t, int); -void tcx_reset(struct tcx_softc *); +void tcx_reset(struct tcx_softc *, int); void tcx_burner(void *, u_int, u_int); void tcx_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t); static __inline__ void tcx_loadcmap_deferred(struct tcx_softc *, u_int, u_int); @@ -190,13 +191,10 @@ tcxmatch(parent, vcf, aux) struct confargs *ca = aux; struct romaux *ra = &ca->ca_ra; - if (strcmp(ra->ra_name, "SUNW,tcx")) + if (strcmp(ra->ra_name, "SUNW,tcx") != 0) return (0); - if (ca->ca_bustype == BUS_SBUS) - return (1); - - return (0); + return (1); } /* @@ -210,16 +208,22 @@ tcxattach(parent, self, args) struct tcx_softc *sc = (struct tcx_softc *)self; struct confargs *ca = args; struct wsemuldisplaydev_attach_args waa; - int fb_depth, node = 0, i; + int node = 0, i; volatile struct bt_regs *bt; int isconsole = 0; char *nam = NULL; sc->sc_sunfb.sf_flags = self->dv_cfdata->cf_flags & FB_USERMASK; - if (ca->ca_ra.ra_nreg < TCX_NREG) - panic("tcx: expected %d registers, got %d", TCX_NREG, - ca->ca_ra.ra_nreg); + node = ca->ca_ra.ra_node; + nam = getpropstring(node, "model"); + printf(": %s\n", nam); + + if (ca->ca_ra.ra_nreg < TCX_NREG) { + printf("\n%s: expected %d registers, got %d\n", + self->dv_xname, TCX_NREG, ca->ca_ra.ra_nreg); + return; + } /* Copy register address spaces */ for (i = 0; i < TCX_NREG; i++) @@ -231,40 +235,28 @@ tcxattach(parent, self, args) mapiodev(&ca->ca_ra.ra_reg[TCX_REG_THC], 0x1000, sizeof *sc->sc_thc); - switch (ca->ca_bustype) { - case BUS_SBUS: - node = ca->ca_ra.ra_node; - nam = getpropstring(node, "model"); - break; - - default: - printf("TCX on bus 0x%x?\n", ca->ca_bustype); - return; - } - - printf(": %s\n", nam); - isconsole = node == fbnode; - if (ISSET(sc->sc_sunfb.sf_flags, FB_FORCELOW)) - fb_depth = 8; - else - fb_depth = node_has_property(node, "tcx-8-bit") ? 8 : 32; - - fb_setsize(&sc->sc_sunfb, fb_depth, 1152, 900, node, ca->ca_bustype); - - sc->sc_sunfb.sf_ro.ri_bits = mapiodev(&ca->ca_ra.ra_reg[ - sc->sc_sunfb.sf_depth == 8 ? TCX_REG_DFB8 : TCX_REG_DFB24], - 0, round_page(sc->sc_sunfb.sf_fbsize)); - - /* map the control plane for S24 framebuffers */ - if (sc->sc_sunfb.sf_depth != 8) { - sc->sc_cplane = mapiodev(&ca->ca_ra.ra_reg[TCX_REG_RDFB32], - 0, round_page(sc->sc_sunfb.sf_fbsize)); + fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype); + if (node_has_property(node, "tcx-8-bit")) { + sc->sc_dfb8 = mapiodev(&ca->ca_ra.ra_reg[TCX_REG_DFB8], 0, + round_page(sc->sc_sunfb.sf_fbsize)); + sc->sc_dfb24 = NULL; + sc->sc_cplane = NULL; + } else { + sc->sc_dfb8 = mapiodev(&ca->ca_ra.ra_reg[TCX_REG_DFB8], 0, + round_page(sc->sc_sunfb.sf_fbsize)); + + /* map the 24 bit and control planes for S24 framebuffers */ + sc->sc_dfb24 = mapiodev(&ca->ca_ra.ra_reg[TCX_REG_DFB24], 0, + round_page(sc->sc_sunfb.sf_fbsize * 4)); + sc->sc_cplane = mapiodev(&ca->ca_ra.ra_reg[TCX_REG_RDFB32], 0, + round_page(sc->sc_sunfb.sf_fbsize * 4)); } /* reset cursor & frame buffer controls */ - tcx_reset(sc); + sc->sc_sunfb.sf_depth = 0; /* force action */ + tcx_reset(sc, 8); /* grab initial (current) color map */ bt->bt_addr = 0; @@ -275,6 +267,7 @@ tcxattach(parent, self, args) tcx_burner(sc, 1, 0); sc->sc_sunfb.sf_ro.ri_hw = sc; + sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_dfb8; fbwscons_init(&sc->sc_sunfb, isconsole); fbwscons_setcolormap(&sc->sc_sunfb, tcx_setcolor); @@ -325,51 +318,62 @@ tcx_ioctl(dev, cmd, data, flags, p) struct wsdisplay_fbinfo *wdf; int error; + /* + * Note that, although the emulation (text) mode is running in 8-bit + * mode, if the frame buffer is able to run in 24-bit mode, it will + * be advertized as such. + */ switch (cmd) { case WSDISPLAYIO_GTYPE: - *(u_int *)data = WSDISPLAY_TYPE_SUN24; + if (sc->sc_cplane == NULL) + *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN; + else + *(u_int *)data = WSDISPLAY_TYPE_SUN24; break; case WSDISPLAYIO_GINFO: wdf = (struct wsdisplay_fbinfo *)data; wdf->height = sc->sc_sunfb.sf_height; wdf->width = sc->sc_sunfb.sf_width; wdf->depth = sc->sc_sunfb.sf_depth; - wdf->cmsize = (sc->sc_sunfb.sf_depth == 8) ? 256 : 0; + wdf->cmsize = sc->sc_cplane == NULL ? 256 : 0; break; case WSDISPLAYIO_LINEBYTES: - *(u_int *)data = sc->sc_sunfb.sf_linebytes; + if (sc->sc_cplane == NULL) + *(u_int *)data = sc->sc_sunfb.sf_linebytes; + else + *(u_int *)data = sc->sc_sunfb.sf_linebytes * 4; break; case WSDISPLAYIO_GETCMAP: - if (sc->sc_sunfb.sf_depth == 8) { - cm = (struct wsdisplay_cmap *)data; - error = bt_getcmap(&sc->sc_cmap, cm); - if (error) - return (error); - } + cm = (struct wsdisplay_cmap *)data; + error = bt_getcmap(&sc->sc_cmap, cm); + if (error) + return (error); break; case WSDISPLAYIO_PUTCMAP: - if (sc->sc_sunfb.sf_depth == 8) { - cm = (struct wsdisplay_cmap *)data; - error = bt_putcmap(&sc->sc_cmap, cm); - if (error) - return (error); - if (ISSET(sc->sc_sunfb.sf_flags, TCX_INTR)) { - tcx_loadcmap_deferred(sc, cm->index, cm->count); - } else { - bt_loadcmap(&sc->sc_cmap, sc->sc_bt, - cm->index, cm->count, 1); - } + cm = (struct wsdisplay_cmap *)data; + error = bt_putcmap(&sc->sc_cmap, cm); + if (error) + return (error); + if (ISSET(sc->sc_sunfb.sf_flags, TCX_INTR)) { + tcx_loadcmap_deferred(sc, cm->index, cm->count); + } else { + bt_loadcmap(&sc->sc_cmap, sc->sc_bt, + cm->index, cm->count, 1); + } + break; + + case WSDISPLAYIO_SMODE: + if (*(int *)data == WSDISPLAYIO_MODE_EMUL) { + /* Back from X11 to text mode */ + tcx_reset(sc, 8); + } else { + /* Starting X11, try to switch to 24 bit mode */ + if (sc->sc_cplane != NULL) + tcx_reset(sc, 32); } break; - case WSDISPLAYIO_SVIDEO: - case WSDISPLAYIO_GVIDEO: - case WSDISPLAYIO_GCURPOS: - case WSDISPLAYIO_SCURPOS: - case WSDISPLAYIO_GCURMAX: - case WSDISPLAYIO_GCURSOR: - case WSDISPLAYIO_SCURSOR: default: return (-1); /* not supported yet */ } @@ -381,8 +385,9 @@ tcx_ioctl(dev, cmd, data, flags, p) * Clean up hardware state (e.g., after bootup or after X crashes). */ void -tcx_reset(sc) +tcx_reset(sc, depth) struct tcx_softc *sc; + int depth; { volatile struct bt_regs *bt; @@ -395,31 +400,34 @@ tcx_reset(sc) bt->bt_ctrl |= 0x03 << 24; /* - * Select 24-bit mode if appropriate. + * Change mode if appropriate */ - if (sc->sc_sunfb.sf_depth != 8) { - volatile u_int32_t *cptr; - u_int32_t pixel; - int ramsize; - - ramsize = sc->sc_sunfb.sf_fbsize / sizeof(u_int32_t); - cptr = sc->sc_cplane; - - /* - * Since the prom output so far has only been white (0) - * or black (255), we can promote the 8 bit plane contents - * to full color. - * Of course, the 24 bit plane uses 0 for black, so a - * reversal is necessary. Blame Sun. - */ - while (ramsize-- != 0) { - pixel = 255 - ((*cptr & TCX_CTL_PIXELMASK) & 0xff); - pixel = (pixel << 16) | (pixel << 8) | pixel; - *cptr++ = pixel | TCX_CTL_24_LEVEL; + if (sc->sc_sunfb.sf_depth != depth) { + if (sc->sc_cplane != NULL) { + volatile u_int32_t *cptr; + u_int32_t pixel; + int ramsize; + + cptr = sc->sc_cplane; + ramsize = sc->sc_sunfb.sf_fbsize; + + if (depth == 8) { + while (ramsize-- != 0) { + pixel = (*cptr & TCX_CTL_PIXELMASK); + *cptr++ = pixel | TCX_CTL_8_MAPPED; + } + } else { + while (ramsize-- != 0) { + *cptr++ = TCX_CTL_24_LEVEL; + } + } } - shutdownhook_establish(tcx_prom, sc); + if (depth == 8) + fbwscons_setcolormap(&sc->sc_sunfb, tcx_setcolor); } + + sc->sc_sunfb.sf_depth = depth; } void @@ -429,28 +437,18 @@ tcx_prom(v) struct tcx_softc *sc = v; extern struct consdev consdev_prom; - /* - * Select 8-bit mode. - */ if (sc->sc_sunfb.sf_depth != 8) { - volatile u_int32_t *cptr; - u_int32_t pixel; - int ramsize; - - ramsize = sc->sc_sunfb.sf_fbsize / sizeof(u_int32_t); - cptr = sc->sc_cplane; + /* + * Select 8-bit mode. + */ + tcx_reset(sc, 8); - while (ramsize-- != 0) { - pixel = (*cptr & TCX_CTL_PIXELMASK); - *cptr++ = pixel | TCX_CTL_8_MAPPED; - } + /* + * Go back to prom output for the last few messages, so they + * will be displayed correctly. + */ + cn_tab = &consdev_prom; } - - /* - * Go back to prom output for the last few messages, so they - * will be displayed correctly. - */ - cn_tab = &consdev_prom; } void @@ -487,17 +485,17 @@ tcx_mmap(v, offset, prot) int prot; { struct tcx_softc *sc = v; - int reg; - if (offset & PGOFSET) + if (offset & PGOFSET || offset < 0) return (-1); /* Allow mapping as a dumb framebuffer from offset 0 */ - if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) { - reg = (sc->sc_sunfb.sf_depth == 8) ? - TCX_REG_DFB8 : TCX_REG_DFB24; - return (REG2PHYS(&sc->sc_phys[reg], offset) | PMAP_NC); - } + if (sc->sc_sunfb.sf_depth == 8 && offset < sc->sc_sunfb.sf_fbsize) + return (REG2PHYS(&sc->sc_phys[TCX_REG_DFB8], offset) | PMAP_NC); + else if (sc->sc_sunfb.sf_depth != 8 && + offset < sc->sc_sunfb.sf_fbsize * 4) + return (REG2PHYS(&sc->sc_phys[TCX_REG_DFB24], offset) | + PMAP_NC); return (-1); /* not a user-map offset */ } @@ -529,13 +527,8 @@ tcx_alloc_screen(v, type, cookiep, curxp, curyp, attrp) *cookiep = &sc->sc_sunfb.sf_ro; *curyp = 0; *curxp = 0; - if (sc->sc_sunfb.sf_depth == 8) { - sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro, - WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp); - } else { - sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro, - 0, 0, 0, attrp); - } + sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro, + WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp); sc->sc_nscreens++; return (0); } |