1/* $NetBSD: cg2.c,v 1.32 2023/12/20 05:18:00 thorpej Exp $ */ 2 3/* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This software was developed by the Computer Systems Engineering group 8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 * contributed to Berkeley. 10 * 11 * All advertising materials mentioning features or use of this software 12 * must display the following acknowledgement: 13 * This product includes software developed by the University of 14 * California, Lawrence Berkeley Laboratory. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * from: @(#)cgthree.c 8.2 (Berkeley) 10/30/93 41 */ 42 43/* 44 * color display (cg2) driver. 45 * 46 * Does not handle interrupts, even though they can occur. 47 * 48 * XXX should defer colormap updates to vertical retrace interrupts 49 */ 50 51#include <sys/cdefs.h> 52__KERNEL_RCSID(0, "$NetBSD: cg2.c,v 1.32 2023/12/20 05:18:00 thorpej Exp $"); 53 54#include <sys/param.h> 55#include <sys/systm.h> 56#include <sys/conf.h> 57#include <sys/device.h> 58#include <sys/ioctl.h> 59#include <sys/mman.h> 60#include <sys/proc.h> 61#include <sys/tty.h> 62 63#include <uvm/uvm_extern.h> 64 65#include <dev/sun/fbio.h> 66#include <machine/autoconf.h> 67#include <machine/pmap.h> 68#include <machine/cg2reg.h> 69 70#include "ioconf.h" 71#include "fbvar.h" 72 73#define CMSIZE 256 74 75/* offset to and size of mapped part of frame buffer */ 76#define PLANEMAP_SIZE 0x100000 77#define PIXELMAP_SIZE 0x100000 78#define ROWOPMAP_SIZE 0x100000 79 80#define CTLREGS_OFF 0x300000 81#define CTLREGS_SIZE 0x10600 82 83#define CG2_MAPPED_OFFSET (PLANEMAP_SIZE + PIXELMAP_SIZE) 84#define CG2_MAPPED_SIZE (CTLREGS_OFF + CTLREGS_SIZE) 85 86/* per-display variables */ 87struct cg2_softc { 88 device_t sc_dev; /* base device */ 89 struct fbdevice sc_fb; /* frame buffer device */ 90 int sc_phys; /* display RAM (phys addr) */ 91 int sc_pmtype; /* pmap type bits */ 92 struct cg2fb *sc_ctlreg; /* control registers */ 93}; 94 95/* autoconfiguration driver */ 96static int cg2match(device_t, cfdata_t, void *); 97static void cg2attach(device_t, device_t, void *); 98 99CFATTACH_DECL_NEW(cgtwo, sizeof(struct cg2_softc), 100 cg2match, cg2attach, NULL, NULL); 101 102dev_type_open(cg2open); 103dev_type_ioctl(cg2ioctl); 104dev_type_mmap(cg2mmap); 105 106const struct cdevsw cgtwo_cdevsw = { 107 .d_open = cg2open, 108 .d_close = nullclose, 109 .d_read = noread, 110 .d_write = nowrite, 111 .d_ioctl = cg2ioctl, 112 .d_stop = nostop, 113 .d_tty = notty, 114 .d_poll = nopoll, 115 .d_mmap = cg2mmap, 116 .d_kqfilter = nokqfilter, 117 .d_discard = nodiscard, 118 .d_flag = 0 119}; 120 121static int cg2gattr(struct fbdevice *, void *); 122static int cg2gvideo(struct fbdevice *, void *); 123static int cg2svideo(struct fbdevice *, void *); 124static int cg2getcmap(struct fbdevice *, void *); 125static int cg2putcmap(struct fbdevice *, void *); 126 127static struct fbdriver cg2fbdriver = { 128 cg2open, nullclose, cg2mmap, nokqfilter, cg2gattr, 129 cg2gvideo, cg2svideo, 130 cg2getcmap, cg2putcmap }; 131 132static int cg2intr(void *); 133 134/* 135 * Match a cg2. 136 */ 137static int 138cg2match(device_t parent, cfdata_t cf, void *aux) 139{ 140 struct confargs *ca = aux; 141 int probe_addr; 142 143 /* No default VME address. */ 144 if (ca->ca_paddr == -1) 145 return 0; 146 147 /* Make sure something is there... */ 148 probe_addr = ca->ca_paddr + CTLREGS_OFF; 149 if (bus_peek(ca->ca_bustype, probe_addr, 1) == -1) 150 return 0; 151 152 /* XXX: look at the ID reg? */ 153 /* aprint_debug("cg2: id=0x%x\n", x); */ 154 155 /* Default interrupt priority. */ 156 if (ca->ca_intpri == -1) 157 ca->ca_intpri = 4; 158 159 return 1; 160} 161 162/* 163 * Attach a display. We need to notice if it is the console, too. 164 */ 165static void 166cg2attach(device_t parent, device_t self, void *args) 167{ 168 struct cg2_softc *sc = device_private(self); 169 struct fbdevice *fb = &sc->sc_fb; 170 struct confargs *ca = args; 171 struct fbtype *fbt; 172 173 sc->sc_dev = self; 174 sc->sc_phys = ca->ca_paddr; 175 sc->sc_pmtype = PMAP_NC | PMAP_VME16; 176 177 sc->sc_ctlreg = (struct cg2fb *)bus_mapin(ca->ca_bustype, 178 ca->ca_paddr + CTLREGS_OFF, CTLREGS_SIZE); 179 180 isr_add_vectored(cg2intr, sc, ca->ca_intpri, ca->ca_intvec); 181 182 /* 183 * XXX - Initialize? Determine type? 184 */ 185 sc->sc_ctlreg->intrptvec.reg = ca->ca_intvec; 186 sc->sc_ctlreg->status.word = 1; 187 188 fb->fb_driver = &cg2fbdriver; 189 fb->fb_private = sc; 190 fb->fb_name = device_xname(self); 191 192 fbt = &fb->fb_fbtype; 193 fbt->fb_type = FBTYPE_SUN2COLOR; 194 fbt->fb_depth = 8; 195 fbt->fb_cmsize = CMSIZE; 196 197 fbt->fb_width = 1152; 198 fbt->fb_height = 900; 199 fbt->fb_size = CG2_MAPPED_SIZE; 200 201 aprint_normal(" (%dx%d)\n", fbt->fb_width, fbt->fb_height); 202 fb_attach(fb, 2); 203} 204 205int 206cg2open(dev_t dev, int flags, int mode, struct lwp *l) 207{ 208 struct cg2_softc *sc; 209 int unit = minor(dev); 210 211 sc = device_lookup_private(&cgtwo_cd, unit); 212 if (sc == NULL) 213 return ENXIO; 214 return 0; 215} 216 217int 218cg2ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 219{ 220 struct cg2_softc *sc = device_lookup_private(&cgtwo_cd, minor(dev)); 221 222 return fbioctlfb(&sc->sc_fb, cmd, data); 223} 224 225/* 226 * Return the address that would map the given device at the given 227 * offset, allowing for the given protection, or return -1 for error. 228 */ 229paddr_t 230cg2mmap(dev_t dev, off_t off, int prot) 231{ 232 struct cg2_softc *sc = device_lookup_private(&cgtwo_cd, minor(dev)); 233 234 if (off & PGOFSET) 235 panic("%s: bad offset", __func__); 236 237 if (off >= CG2_MAPPED_SIZE) 238 return -1; 239 240 /* 241 * I turned on PMAP_NC here to disable the cache as I was 242 * getting horribly broken behaviour with it on. 243 */ 244 return (sc->sc_phys + off) | sc->sc_pmtype; 245} 246 247/* 248 * Internal ioctl functions. 249 */ 250 251/* FBIOGATTR: */ 252static int 253cg2gattr(struct fbdevice *fb, void *data) 254{ 255 struct fbgattr *fba = data; 256 257 fba->real_type = fb->fb_fbtype.fb_type; 258 fba->owner = 0; /* XXX - TIOCCONS stuff? */ 259 fba->fbtype = fb->fb_fbtype; 260 fba->sattr.flags = 0; 261 fba->sattr.emu_type = fb->fb_fbtype.fb_type; 262 fba->sattr.dev_specific[0] = -1; 263 fba->emu_types[0] = fb->fb_fbtype.fb_type; 264 fba->emu_types[1] = -1; 265 return 0; 266} 267 268/* FBIOGVIDEO: */ 269static int 270cg2gvideo(struct fbdevice *fb, void *data) 271{ 272 int *on = data; 273 struct cg2_softc *sc = fb->fb_private; 274 275 *on = sc->sc_ctlreg->status.reg.video_enab; 276 return 0; 277} 278 279/* FBIOSVIDEO: */ 280static int 281cg2svideo(struct fbdevice *fb, void *data) 282{ 283 int *on = data; 284 struct cg2_softc *sc = fb->fb_private; 285 286 sc->sc_ctlreg->status.reg.video_enab = (*on) & 1; 287 288 return 0; 289} 290 291/* FBIOGETCMAP: */ 292static int 293cg2getcmap(struct fbdevice *fb, void *data) 294{ 295 struct fbcmap *cmap = data; 296 struct cg2_softc *sc = fb->fb_private; 297 uint8_t red[CMSIZE], green[CMSIZE], blue[CMSIZE]; 298 int error, start, count, ecount; 299 u_int i; 300 uint16_t *p; 301 302 start = cmap->index; 303 count = cmap->count; 304 ecount = start + count; 305 if (start >= CMSIZE || count > CMSIZE - start) 306 return EINVAL; 307 308 /* XXX - Wait for retrace? */ 309 310 /* Copy hardware to local arrays. */ 311 p = &sc->sc_ctlreg->redmap[start]; 312 for (i = start; i < ecount; i++) 313 red[i] = *p++; 314 p = &sc->sc_ctlreg->greenmap[start]; 315 for (i = start; i < ecount; i++) 316 green[i] = *p++; 317 p = &sc->sc_ctlreg->bluemap[start]; 318 for (i = start; i < ecount; i++) 319 blue[i] = *p++; 320 321 /* Copy local arrays to user space. */ 322 if ((error = copyout(red + start, cmap->red, count)) != 0) 323 return error; 324 if ((error = copyout(green + start, cmap->green, count)) != 0) 325 return error; 326 if ((error = copyout(blue + start, cmap->blue, count)) != 0) 327 return error; 328 329 return 0; 330} 331 332/* FBIOPUTCMAP: */ 333static int 334cg2putcmap(struct fbdevice *fb, void *data) 335{ 336 struct fbcmap *cmap = data; 337 struct cg2_softc *sc = fb->fb_private; 338 uint8_t red[CMSIZE], green[CMSIZE], blue[CMSIZE]; 339 int error; 340 u_int start, count, ecount; 341 u_int i; 342 uint16_t *p; 343 344 start = cmap->index; 345 count = cmap->count; 346 ecount = start + count; 347 if (start >= CMSIZE || count > CMSIZE - start) 348 return EINVAL; 349 350 /* Copy from user space to local arrays. */ 351 if ((error = copyin(cmap->red, red + start, count)) != 0) 352 return error; 353 if ((error = copyin(cmap->green, green + start, count)) != 0) 354 return error; 355 if ((error = copyin(cmap->blue, blue + start, count)) != 0) 356 return error; 357 358 /* XXX - Wait for retrace? */ 359 360 /* Copy from local arrays to hardware. */ 361 p = &sc->sc_ctlreg->redmap[start]; 362 for (i = start; i < ecount; i++) 363 *p++ = red[i]; 364 p = &sc->sc_ctlreg->greenmap[start]; 365 for (i = start; i < ecount; i++) 366 *p++ = green[i]; 367 p = &sc->sc_ctlreg->bluemap[start]; 368 for (i = start; i < ecount; i++) 369 *p++ = blue[i]; 370 371 return 0; 372 373} 374 375static int 376cg2intr(void *vsc) 377{ 378 struct cg2_softc *sc = vsc; 379 380 /* XXX - Just disable interrupts for now. */ 381 sc->sc_ctlreg->status.reg.inten = 0; 382 383 printf("cg2intr\n"); 384 return 1; 385} 386