1 /* $NetBSD: cg2.c,v 1.31 2014/07/25 08:10:35 dholland 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.31 2014/07/25 08:10:35 dholland 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/malloc.h> 60 #include <sys/mman.h> 61 #include <sys/proc.h> 62 #include <sys/tty.h> 63 64 #include <uvm/uvm_extern.h> 65 66 #include <dev/sun/fbio.h> 67 #include <machine/autoconf.h> 68 #include <machine/pmap.h> 69 #include <machine/cg2reg.h> 70 71 #include "ioconf.h" 72 #include "fbvar.h" 73 74 #define CMSIZE 256 75 76 /* offset to and size of mapped part of frame buffer */ 77 #define PLANEMAP_SIZE 0x100000 78 #define PIXELMAP_SIZE 0x100000 79 #define ROWOPMAP_SIZE 0x100000 80 81 #define CTLREGS_OFF 0x300000 82 #define CTLREGS_SIZE 0x10600 83 84 #define CG2_MAPPED_OFFSET (PLANEMAP_SIZE + PIXELMAP_SIZE) 85 #define CG2_MAPPED_SIZE (CTLREGS_OFF + CTLREGS_SIZE) 86 87 /* per-display variables */ 88 struct cg2_softc { 89 device_t sc_dev; /* base device */ 90 struct fbdevice sc_fb; /* frame buffer device */ 91 int sc_phys; /* display RAM (phys addr) */ 92 int sc_pmtype; /* pmap type bits */ 93 struct cg2fb *sc_ctlreg; /* control registers */ 94 }; 95 96 /* autoconfiguration driver */ 97 static int cg2match(device_t, cfdata_t, void *); 98 static void cg2attach(device_t, device_t, void *); 99 100 CFATTACH_DECL_NEW(cgtwo, sizeof(struct cg2_softc), 101 cg2match, cg2attach, NULL, NULL); 102 103 dev_type_open(cg2open); 104 dev_type_ioctl(cg2ioctl); 105 dev_type_mmap(cg2mmap); 106 107 const struct cdevsw cgtwo_cdevsw = { 108 .d_open = cg2open, 109 .d_close = nullclose, 110 .d_read = noread, 111 .d_write = nowrite, 112 .d_ioctl = cg2ioctl, 113 .d_stop = nostop, 114 .d_tty = notty, 115 .d_poll = nopoll, 116 .d_mmap = cg2mmap, 117 .d_kqfilter = nokqfilter, 118 .d_discard = nodiscard, 119 .d_flag = 0 120 }; 121 122 static int cg2gattr(struct fbdevice *, void *); 123 static int cg2gvideo(struct fbdevice *, void *); 124 static int cg2svideo(struct fbdevice *, void *); 125 static int cg2getcmap(struct fbdevice *, void *); 126 static int cg2putcmap(struct fbdevice *, void *); 127 128 static struct fbdriver cg2fbdriver = { 129 cg2open, nullclose, cg2mmap, nokqfilter, cg2gattr, 130 cg2gvideo, cg2svideo, 131 cg2getcmap, cg2putcmap }; 132 133 static int cg2intr(void *); 134 135 /* 136 * Match a cg2. 137 */ 138 static int 139 cg2match(device_t parent, cfdata_t cf, void *aux) 140 { 141 struct confargs *ca = aux; 142 int probe_addr; 143 144 /* No default VME address. */ 145 if (ca->ca_paddr == -1) 146 return 0; 147 148 /* Make sure something is there... */ 149 probe_addr = ca->ca_paddr + CTLREGS_OFF; 150 if (bus_peek(ca->ca_bustype, probe_addr, 1) == -1) 151 return 0; 152 153 /* XXX: look at the ID reg? */ 154 /* aprint_debug("cg2: id=0x%x\n", x); */ 155 156 /* Default interrupt priority. */ 157 if (ca->ca_intpri == -1) 158 ca->ca_intpri = 4; 159 160 return 1; 161 } 162 163 /* 164 * Attach a display. We need to notice if it is the console, too. 165 */ 166 static void 167 cg2attach(device_t parent, device_t self, void *args) 168 { 169 struct cg2_softc *sc = device_private(self); 170 struct fbdevice *fb = &sc->sc_fb; 171 struct confargs *ca = args; 172 struct fbtype *fbt; 173 174 sc->sc_dev = self; 175 sc->sc_phys = ca->ca_paddr; 176 sc->sc_pmtype = PMAP_NC | PMAP_VME16; 177 178 sc->sc_ctlreg = (struct cg2fb *)bus_mapin(ca->ca_bustype, 179 ca->ca_paddr + CTLREGS_OFF, CTLREGS_SIZE); 180 181 isr_add_vectored(cg2intr, sc, ca->ca_intpri, ca->ca_intvec); 182 183 /* 184 * XXX - Initialize? Determine type? 185 */ 186 sc->sc_ctlreg->intrptvec.reg = ca->ca_intvec; 187 sc->sc_ctlreg->status.word = 1; 188 189 fb->fb_driver = &cg2fbdriver; 190 fb->fb_private = sc; 191 fb->fb_name = device_xname(self); 192 193 fbt = &fb->fb_fbtype; 194 fbt->fb_type = FBTYPE_SUN2COLOR; 195 fbt->fb_depth = 8; 196 fbt->fb_cmsize = CMSIZE; 197 198 fbt->fb_width = 1152; 199 fbt->fb_height = 900; 200 fbt->fb_size = CG2_MAPPED_SIZE; 201 202 aprint_normal(" (%dx%d)\n", fbt->fb_width, fbt->fb_height); 203 fb_attach(fb, 2); 204 } 205 206 int 207 cg2open(dev_t dev, int flags, int mode, struct lwp *l) 208 { 209 struct cg2_softc *sc; 210 int unit = minor(dev); 211 212 sc = device_lookup_private(&cgtwo_cd, unit); 213 if (sc == NULL) 214 return ENXIO; 215 return 0; 216 } 217 218 int 219 cg2ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 220 { 221 struct cg2_softc *sc = device_lookup_private(&cgtwo_cd, minor(dev)); 222 223 return fbioctlfb(&sc->sc_fb, cmd, data); 224 } 225 226 /* 227 * Return the address that would map the given device at the given 228 * offset, allowing for the given protection, or return -1 for error. 229 */ 230 paddr_t 231 cg2mmap(dev_t dev, off_t off, int prot) 232 { 233 struct cg2_softc *sc = device_lookup_private(&cgtwo_cd, minor(dev)); 234 235 if (off & PGOFSET) 236 panic("%s: bad offset", __func__); 237 238 if (off >= CG2_MAPPED_SIZE) 239 return -1; 240 241 /* 242 * I turned on PMAP_NC here to disable the cache as I was 243 * getting horribly broken behaviour with it on. 244 */ 245 return (sc->sc_phys + off) | sc->sc_pmtype; 246 } 247 248 /* 249 * Internal ioctl functions. 250 */ 251 252 /* FBIOGATTR: */ 253 static int 254 cg2gattr(struct fbdevice *fb, void *data) 255 { 256 struct fbgattr *fba = data; 257 258 fba->real_type = fb->fb_fbtype.fb_type; 259 fba->owner = 0; /* XXX - TIOCCONS stuff? */ 260 fba->fbtype = fb->fb_fbtype; 261 fba->sattr.flags = 0; 262 fba->sattr.emu_type = fb->fb_fbtype.fb_type; 263 fba->sattr.dev_specific[0] = -1; 264 fba->emu_types[0] = fb->fb_fbtype.fb_type; 265 fba->emu_types[1] = -1; 266 return 0; 267 } 268 269 /* FBIOGVIDEO: */ 270 static int 271 cg2gvideo(struct fbdevice *fb, void *data) 272 { 273 int *on = data; 274 struct cg2_softc *sc = fb->fb_private; 275 276 *on = sc->sc_ctlreg->status.reg.video_enab; 277 return 0; 278 } 279 280 /* FBIOSVIDEO: */ 281 static int 282 cg2svideo(struct fbdevice *fb, void *data) 283 { 284 int *on = data; 285 struct cg2_softc *sc = fb->fb_private; 286 287 sc->sc_ctlreg->status.reg.video_enab = (*on) & 1; 288 289 return 0; 290 } 291 292 /* FBIOGETCMAP: */ 293 static int 294 cg2getcmap(struct fbdevice *fb, void *data) 295 { 296 struct fbcmap *cmap = data; 297 struct cg2_softc *sc = fb->fb_private; 298 uint8_t red[CMSIZE], green[CMSIZE], blue[CMSIZE]; 299 int error, start, count, ecount; 300 u_int i; 301 uint16_t *p; 302 303 start = cmap->index; 304 count = cmap->count; 305 ecount = start + count; 306 if (start >= CMSIZE || count > CMSIZE - start) 307 return EINVAL; 308 309 /* XXX - Wait for retrace? */ 310 311 /* Copy hardware to local arrays. */ 312 p = &sc->sc_ctlreg->redmap[start]; 313 for (i = start; i < ecount; i++) 314 red[i] = *p++; 315 p = &sc->sc_ctlreg->greenmap[start]; 316 for (i = start; i < ecount; i++) 317 green[i] = *p++; 318 p = &sc->sc_ctlreg->bluemap[start]; 319 for (i = start; i < ecount; i++) 320 blue[i] = *p++; 321 322 /* Copy local arrays to user space. */ 323 if ((error = copyout(red + start, cmap->red, count)) != 0) 324 return error; 325 if ((error = copyout(green + start, cmap->green, count)) != 0) 326 return error; 327 if ((error = copyout(blue + start, cmap->blue, count)) != 0) 328 return error; 329 330 return 0; 331 } 332 333 /* FBIOPUTCMAP: */ 334 static int 335 cg2putcmap(struct fbdevice *fb, void *data) 336 { 337 struct fbcmap *cmap = data; 338 struct cg2_softc *sc = fb->fb_private; 339 uint8_t red[CMSIZE], green[CMSIZE], blue[CMSIZE]; 340 int error; 341 u_int start, count, ecount; 342 u_int i; 343 uint16_t *p; 344 345 start = cmap->index; 346 count = cmap->count; 347 ecount = start + count; 348 if (start >= CMSIZE || count > CMSIZE - start) 349 return EINVAL; 350 351 /* Copy from user space to local arrays. */ 352 if ((error = copyin(cmap->red, red + start, count)) != 0) 353 return error; 354 if ((error = copyin(cmap->green, green + start, count)) != 0) 355 return error; 356 if ((error = copyin(cmap->blue, blue + start, count)) != 0) 357 return error; 358 359 /* XXX - Wait for retrace? */ 360 361 /* Copy from local arrays to hardware. */ 362 p = &sc->sc_ctlreg->redmap[start]; 363 for (i = start; i < ecount; i++) 364 *p++ = red[i]; 365 p = &sc->sc_ctlreg->greenmap[start]; 366 for (i = start; i < ecount; i++) 367 *p++ = green[i]; 368 p = &sc->sc_ctlreg->bluemap[start]; 369 for (i = start; i < ecount; i++) 370 *p++ = blue[i]; 371 372 return 0; 373 374 } 375 376 static int 377 cg2intr(void *vsc) 378 { 379 struct cg2_softc *sc = vsc; 380 381 /* XXX - Just disable interrupts for now. */ 382 sc->sc_ctlreg->status.reg.inten = 0; 383 384 printf("cg2intr\n"); 385 return 1; 386 } 387