1110603Sphk/* $NetBSD: cgtwo.c,v 1.58 2023/12/20 05:33:18 thorpej Exp $ */ 2110603Sphk 3110603Sphk/* 4110603Sphk * Copyright (c) 1992, 1993 5110603Sphk * The Regents of the University of California. All rights reserved. 6110603Sphk * 7110603Sphk * This software was developed by the Computer Systems Engineering group 8110603Sphk * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9110603Sphk * contributed to Berkeley. 10110603Sphk * 11110603Sphk * All advertising materials mentioning features or use of this software 12110603Sphk * must display the following acknowledgement: 13110603Sphk * This product includes software developed by the University of 14110603Sphk * California, Lawrence Berkeley Laboratory. 15110603Sphk * 16110603Sphk * Redistribution and use in source and binary forms, with or without 17110603Sphk * modification, are permitted provided that the following conditions 18110603Sphk * are met: 19110603Sphk * 1. Redistributions of source code must retain the above copyright 20110603Sphk * notice, this list of conditions and the following disclaimer. 21110603Sphk * 2. Redistributions in binary form must reproduce the above copyright 22110603Sphk * notice, this list of conditions and the following disclaimer in the 23110603Sphk * documentation and/or other materials provided with the distribution. 24110603Sphk * 3. Neither the name of the University nor the names of its contributors 25110603Sphk * may be used to endorse or promote products derived from this software 26110603Sphk * without specific prior written permission. 27110603Sphk * 28110603Sphk * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29110603Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30110603Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31110603Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32110603Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33110603Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34110603Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35110603Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36110603Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37110603Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38110603Sphk * SUCH DAMAGE. 39110603Sphk * 40110603Sphk * from: @(#)cgthree.c 8.2 (Berkeley) 10/30/93 41110603Sphk */ 42110603Sphk 43110603Sphk/* 44110603Sphk * color display (cgtwo) driver. 45110603Sphk * 46110603Sphk * Does not handle interrupts, even though they can occur. 47110603Sphk * 48110603Sphk * XXX should defer colormap updates to vertical retrace interrupts 49110603Sphk */ 50110603Sphk 51110603Sphk#include <sys/cdefs.h> 52110603Sphk__KERNEL_RCSID(0, "$NetBSD: cgtwo.c,v 1.58 2023/12/20 05:33:18 thorpej Exp $"); 53110603Sphk 54110603Sphk#include <sys/param.h> 55110603Sphk#include <sys/systm.h> 56110603Sphk#include <sys/buf.h> 57110603Sphk#include <sys/device.h> 58234107Sjmallett#include <sys/ioctl.h> 59242130Sjh#include <sys/mman.h> 60242130Sjh#include <sys/tty.h> 61110603Sphk#include <sys/conf.h> 62110603Sphk 63110603Sphk#include <uvm/uvm_extern.h> 64110603Sphk 65110603Sphk#include <machine/autoconf.h> 66110603Sphk 67110603Sphk#include <dev/sun/fbio.h> 68110603Sphk#include <dev/sun/fbvar.h> 69110603Sphk 70110603Sphk#include <dev/vme/vmevar.h> 71110603Sphk 72110603Sphk#include <machine/eeprom.h> 73181463Sdes#include <machine/cgtworeg.h> 74110603Sphk 75126786Sjhb 76110603Sphk/* per-display variables */ 77110603Sphkstruct cgtwo_softc { 78253249Shrs struct fbdevice sc_fb; /* frame buffer device */ 79234107Sjmallett vme_addr_t sc_paddr; 80110603Sphk vme_chipset_tag_t sc_ct; 81253249Shrs bus_space_tag_t sc_bt; 82110603Sphk volatile struct cg2statusreg *sc_reg; /* CG2 control registers */ 83110603Sphk volatile u_short *sc_cmap; 84110603Sphk#define sc_redmap(sc) ((sc)->sc_cmap) 85110603Sphk#define sc_greenmap(sc) ((sc)->sc_cmap + CG2_CMSIZE) 86110603Sphk#define sc_bluemap(sc) ((sc)->sc_cmap + 2 * CG2_CMSIZE) 87110603Sphk}; 88110603Sphk 89180369Slulf/* autoconfiguration driver */ 90242130Sjhstatic int cgtwomatch(device_t, cfdata_t, void *); 91242130Sjhstatic void cgtwoattach(device_t, device_t, void *); 92180369Slulfstatic void cgtwounblank(device_t); 93180369Slulfint cgtwogetcmap(struct cgtwo_softc *, struct fbcmap *); 94180369Slulfint cgtwoputcmap(struct cgtwo_softc *, struct fbcmap *); 95180369Slulf 96126786SjhbCFATTACH_DECL_NEW(cgtwo, sizeof(struct cgtwo_softc), 97126786Sjhb cgtwomatch, cgtwoattach, NULL, NULL); 98126786Sjhb 99126786Sjhbextern struct cfdriver cgtwo_cd; 100110603Sphk 101110603Sphkdev_type_open(cgtwoopen); 102110603Sphkdev_type_ioctl(cgtwoioctl); 103110603Sphkdev_type_mmap(cgtwommap); 104180369Slulf 105242130Sjhconst struct cdevsw cgtwo_cdevsw = { 106242130Sjh .d_open = cgtwoopen, 107180369Slulf .d_close = nullclose, 108180369Slulf .d_read = noread, 109180369Slulf .d_write = nowrite, 110180369Slulf .d_ioctl = cgtwoioctl, 111126786Sjhb .d_stop = nostop, 112126786Sjhb .d_tty = notty, 113126786Sjhb .d_poll = nopoll, 114126786Sjhb .d_mmap = cgtwommap, 115126786Sjhb .d_kqfilter = nokqfilter, 116110603Sphk .d_discard = nodiscard, 117110603Sphk .d_flag = 0 118110603Sphk}; 119126786Sjhb 120110603Sphk/* frame buffer generic driver */ 121110603Sphkstatic struct fbdriver cgtwofbdriver = { 122110603Sphk cgtwounblank, cgtwoopen, nullclose, cgtwoioctl, nopoll, cgtwommap, 123110603Sphk nokqfilter 124180369Slulf}; 125242130Sjh 126242130Sjh/* 127180369Slulf * Match a cgtwo. 128180369Slulf */ 129180369Slulfstatic int 130180369Slulfcgtwomatch(device_t parent, cfdata_t cf, void *aux) 131126786Sjhb{ 132126786Sjhb struct vme_attach_args *va = aux; 133126786Sjhb vme_chipset_tag_t ct = va->va_vct; 134126786Sjhb vme_am_t mod; 135110603Sphk 136110603Sphk /* 137110603Sphk * Mask out invalid flags from the user. 138126786Sjhb */ 139110603Sphk cf->cf_flags &= FB_USERMASK; 140110603Sphk 141110603Sphk mod = 0x3d; /* VME_AM_A24 | VME_AM_MBO | VME_AM_SUPER | VME_AM_DATA */ 142126786Sjhb if (vme_probe(ct, va->r[0].offset + CG2_CTLREG_OFF, 2, mod, VME_D16, 143110603Sphk 0, 0)) { 144110603Sphk return (0); 145110603Sphk } 146110603Sphk 147180369Slulf return (1); 148242130Sjh} 149242130Sjh 150180369Slulf/* 151180369Slulf * Attach a display. We need to notice if it is the console, too. 152180369Slulf */ 153180369Slulfstatic void 154126786Sjhbcgtwoattach(device_t parent, device_t self, void *aux) 155126786Sjhb{ 156126786Sjhb struct vme_attach_args *va = aux; 157126786Sjhb vme_chipset_tag_t ct = va->va_vct; 158126786Sjhb bus_space_tag_t bt; 159110603Sphk bus_space_handle_t bh; 160110603Sphk vme_am_t mod; 161110603Sphk vme_mapresc_t resc; 162126786Sjhb struct cgtwo_softc *sc = device_private(self); 163110603Sphk struct fbdevice *fb = &sc->sc_fb; 164110603Sphk struct eeprom *eep = (struct eeprom *)eeprom_va; 165110603Sphk int isconsole = 0; 166110603Sphk 167126786Sjhb sc->sc_ct = ct; 168110603Sphk fb->fb_driver = &cgtwofbdriver; 169110603Sphk fb->fb_device = self; 170110603Sphk fb->fb_type.fb_type = FBTYPE_SUN2COLOR; 171126786Sjhb fb->fb_flags = device_cfdata(self)->cf_flags; 172110603Sphk 173110603Sphk fb->fb_type.fb_depth = 8; 174110603Sphk fb_setsize_eeprom(fb, fb->fb_type.fb_depth, 1152, 900); 175126786Sjhb 176110603Sphk fb->fb_type.fb_cmsize = 256; 177110603Sphk fb->fb_type.fb_size = roundup(CG2_MAPPED_SIZE, PAGE_SIZE); 178110603Sphk printf(": cgtwo, %d x %d", 179126786Sjhb fb->fb_type.fb_width, fb->fb_type.fb_height); 180110603Sphk 181110603Sphk /* 182110603Sphk * When the ROM has mapped in a cgtwo display, the address 183110603Sphk * maps only the video RAM, so in any case we have to map the 184110603Sphk * registers ourselves. We only need the video RAM if we are 185110603Sphk * going to print characters via rconsole. 186110603Sphk */ 187110603Sphk sc->sc_paddr = va->r[0].offset; 188110603Sphk mod = 0x3d; /* VME_AM_A24 | VME_AM_MBO | VME_AM_SUPER | VME_AM_DATA */ 189110603Sphk 190110603Sphk if (vme_space_map(ct, sc->sc_paddr + CG2_ROPMEM_OFF + 191110603Sphk offsetof(struct cg2fb, status.reg), 192110603Sphk sizeof(struct cg2statusreg), mod, VME_D16, 0, 193242130Sjh &bt, &bh, &resc) != 0) 194242130Sjh panic("cgtwo: vme_map status"); 195242130Sjh sc->sc_bt = bt; 196242130Sjh sc->sc_reg = (volatile struct cg2statusreg *)bh; /* XXX */ 197242130Sjh 198242130Sjh if (vme_space_map(ct, sc->sc_paddr + CG2_ROPMEM_OFF + 199180369Slulf offsetof(struct cg2fb, redmap[0]), 200242130Sjh 3 * CG2_CMSIZE, mod, VME_D16, 0, 201242130Sjh &bt, &bh, &resc) != 0) 202180369Slulf panic("cgtwo: vme_map cmap"); 203180369Slulf sc->sc_cmap = (volatile u_short *)bh; /* XXX */ 204180369Slulf 205180369Slulf /* 206110603Sphk * Assume this is the console if there's no eeprom info 207110603Sphk * to be found. 208110603Sphk */ 209110603Sphk if (eep == NULL || eep->eeConsole == EE_CONS_COLOR) 210110603Sphk isconsole = fb_is_console(0); 211110603Sphk else 212110603Sphk isconsole = 0; 213126786Sjhb 214110603Sphk if (isconsole) { 215110603Sphk if (vme_space_map(ct, sc->sc_paddr + CG2_PIXMAP_OFF, 216126786Sjhb CG2_PIXMAP_SIZE, mod, VME_D16, 0, 217110603Sphk &bt, &bh, &resc) != 0) 218110603Sphk panic("cgtwo: vme_map pixels"); 219126786Sjhb 220110603Sphk fb->fb_pixels = (void *)bh; /* XXX */ 221110603Sphk printf(" (console)\n"); 222110603Sphk#ifdef RASTERCONSOLE 223110603Sphk fbrcons_init(fb); 224126786Sjhb#endif 225110603Sphk } else 226110603Sphk printf("\n"); 227110603Sphk 228110603Sphk fb_attach(fb, isconsole); 229126786Sjhb} 230110603Sphk 231110603Sphkint 232110603Sphkcgtwoopen(dev_t dev, int flags, int mode, struct lwp *l) 233126786Sjhb{ 234110603Sphk int unit = minor(dev); 235110603Sphk 236110603Sphk if (device_lookup(&cgtwo_cd, unit) == NULL) 237126786Sjhb return (ENXIO); 238110603Sphk return (0); 239110603Sphk} 240110603Sphk 241110603Sphkint 242126786Sjhbcgtwoioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 243110603Sphk{ 244110603Sphk register struct cgtwo_softc *sc = device_lookup_private(&cgtwo_cd, 245110603Sphk minor(dev)); 246202454Sdelphij register struct fbgattr *fba; 247202454Sdelphij 248202454Sdelphij switch (cmd) { 249202454Sdelphij 250202454Sdelphij case FBIOGTYPE: 251202454Sdelphij *(struct fbtype *)data = sc->sc_fb.fb_type; 252202454Sdelphij break; 253202454Sdelphij 254202454Sdelphij case FBIOGATTR: 255202454Sdelphij fba = (struct fbgattr *)data; 256110603Sphk fba->real_type = sc->sc_fb.fb_type.fb_type; 257110603Sphk fba->owner = 0; /* XXX ??? */ 258110603Sphk fba->fbtype = sc->sc_fb.fb_type; 259110603Sphk fba->sattr.flags = 0; 260110603Sphk fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; 261110603Sphk fba->sattr.dev_specific[0] = -1; 262110603Sphk fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; 263180369Slulf fba->emu_types[1] = -1; 264180369Slulf break; 265242130Sjh 266242130Sjh case FBIOGETCMAP: 267180369Slulf return cgtwogetcmap(sc, (struct fbcmap *) data); 268180369Slulf 269180369Slulf case FBIOPUTCMAP: 270180369Slulf return cgtwoputcmap(sc, (struct fbcmap *) data); 271126786Sjhb 272180369Slulf case FBIOGVIDEO: 273242130Sjh *(int *)data = sc->sc_reg->video_enab; 274242130Sjh break; 275180369Slulf 276180369Slulf case FBIOSVIDEO: 277180369Slulf sc->sc_reg->video_enab = (*(int*)data) & 1; 278180369Slulf break; 279126786Sjhb 280126786Sjhb default: 281110603Sphk return (ENOTTY); 282110603Sphk } 283110603Sphk return (0); 284110603Sphk} 285253469Sscottl 286112340Sphk/* 287253469Sscottl * Undo the effect of an FBIOSVIDEO that turns the video off. 288110603Sphk */ 289110603Sphkstatic void 290110603Sphkcgtwounblank(device_t dev) 291110603Sphk{ 292110603Sphk struct cgtwo_softc *sc = device_private(dev); 293110603Sphk sc->sc_reg->video_enab = 1; 294110603Sphk} 295110603Sphk 296110603Sphk/* 297110603Sphk */ 298110603Sphkint 299110603Sphkcgtwogetcmap(struct cgtwo_softc *sc, struct fbcmap *cmap) 300110603Sphk{ 301110603Sphk u_char red[CG2_CMSIZE], green[CG2_CMSIZE], blue[CG2_CMSIZE]; 302110603Sphk int error, start, count, ecount; 303110603Sphk register u_int i; 304110603Sphk register volatile u_short *p; 305110603Sphk 306110603Sphk start = cmap->index; 307110603Sphk count = cmap->count; 308110603Sphk ecount = start + count; 309110603Sphk if (start >= CG2_CMSIZE || count > CG2_CMSIZE - start) 310110603Sphk return (EINVAL); 311110603Sphk 312110603Sphk /* XXX - Wait for retrace? */ 313110603Sphk 314110603Sphk /* Copy hardware to local arrays. */ 315110603Sphk p = &sc_redmap(sc)[start]; 316110603Sphk for (i = start; i < ecount; i++) 317110603Sphk red[i] = *p++; 318110603Sphk p = &sc_greenmap(sc)[start]; 319110603Sphk for (i = start; i < ecount; i++) 320110603Sphk green[i] = *p++; 321110603Sphk p = &sc_bluemap(sc)[start]; 322110603Sphk for (i = start; i < ecount; i++) 323110603Sphk blue[i] = *p++; 324110603Sphk 325110603Sphk /* Copy local arrays to user space. */ 326110603Sphk if ((error = copyout(red + start, cmap->red, count)) != 0) 327110603Sphk return (error); 328110603Sphk if ((error = copyout(green + start, cmap->green, count)) != 0) 329110603Sphk return (error); 330110603Sphk if ((error = copyout(blue + start, cmap->blue, count)) != 0) 331110603Sphk return (error); 332110603Sphk 333110603Sphk return (0); 334110603Sphk} 335110603Sphk 336110603Sphk/* 337112340Sphk */ 338110603Sphkint 339234107Sjmallettcgtwoputcmap(struct cgtwo_softc *sc, struct fbcmap *cmap) 340110603Sphk{ 341234107Sjmallett u_char red[CG2_CMSIZE], green[CG2_CMSIZE], blue[CG2_CMSIZE]; 342234107Sjmallett int error; 343234107Sjmallett u_int start, count, ecount; 344110603Sphk register u_int i; 345110603Sphk register volatile u_short *p; 346110603Sphk 347110603Sphk start = cmap->index; 348110603Sphk count = cmap->count; 349110603Sphk ecount = start + count; 350110603Sphk if (start >= CG2_CMSIZE || count > CG2_CMSIZE - start) 351110603Sphk return (EINVAL); 352110603Sphk 353110603Sphk /* Copy from user space to local arrays. */ 354110603Sphk if ((error = copyin(cmap->red, red + start, count)) != 0) 355110603Sphk return (error); 356242130Sjh if ((error = copyin(cmap->green, green + start, count)) != 0) 357110603Sphk return (error); 358110603Sphk if ((error = copyin(cmap->blue, blue + start, count)) != 0) 359126786Sjhb return (error); 360110603Sphk 361213451Semaste /* XXX - Wait for retrace? */ 362213451Semaste 363110603Sphk /* Copy from local arrays to hardware. */ 364213451Semaste p = &sc_redmap(sc)[start]; 365213451Semaste for (i = start; i < ecount; i++) 366110603Sphk *p++ = red[i]; 367213451Semaste p = &sc_greenmap(sc)[start]; 368110603Sphk for (i = start; i < ecount; i++) 369242130Sjh *p++ = green[i]; 370242130Sjh p = &sc_bluemap(sc)[start]; 371110603Sphk for (i = start; i < ecount; i++) 372110603Sphk *p++ = blue[i]; 373110603Sphk 374110603Sphk return (0); 375242130Sjh} 376242130Sjh 377242130Sjh/* 378242130Sjh * Return the address that would map the given device at the given 379242130Sjh * offset, allowing for the given protection, or return -1 for error. 380242130Sjh */ 381213451Semastepaddr_t 382242130Sjhcgtwommap(dev_t dev, off_t off, int prot) 383213451Semaste{ 384242130Sjh extern int sparc_vme_mmap_cookie(vme_addr_t, vme_am_t, 385213451Semaste bus_space_handle_t *); 386234107Sjmallett 387234107Sjmallett register struct cgtwo_softc *sc = device_lookup_private(&cgtwo_cd, 388234107Sjmallett minor(dev)); 389233646Sjmallett vme_am_t mod; 390234107Sjmallett bus_space_handle_t bh; 391110603Sphk 392126786Sjhb if (off & PGOFSET) 393234107Sjmallett panic("cgtwommap"); 394234107Sjmallett 395234107Sjmallett if (off >= sc->sc_fb.fb_type.fb_size) 396234107Sjmallett return (-1); 397126786Sjhb 398234107Sjmallett /* Apparently, the pixels are in 32-bit data space */ 399234107Sjmallett mod = 0x3d; /* VME_AM_A24 | VME_AM_MBO | VME_AM_SUPER | VME_AM_DATA */ 400234107Sjmallett 401234107Sjmallett if (sparc_vme_mmap_cookie(sc->sc_paddr + off, mod, &bh) != 0) 402126786Sjhb panic("cgtwommap"); 403234107Sjmallett 404234107Sjmallett return ((paddr_t)bh); 405234107Sjmallett} 406234107Sjmallett