1 /* $NetBSD: cg2.c,v 1.29 2008/06/28 12:13:38 tsutsui 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.29 2008/06/28 12:13:38 tsutsui 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 cg2open, nullclose, noread, nowrite, cg2ioctl, 109 nostop, notty, nopoll, cg2mmap, nokqfilter, 110 }; 111 112 static int cg2gattr(struct fbdevice *, void *); 113 static int cg2gvideo(struct fbdevice *, void *); 114 static int cg2svideo(struct fbdevice *, void *); 115 static int cg2getcmap(struct fbdevice *, void *); 116 static int cg2putcmap(struct fbdevice *, void *); 117 118 static struct fbdriver cg2fbdriver = { 119 cg2open, nullclose, cg2mmap, nokqfilter, cg2gattr, 120 cg2gvideo, cg2svideo, 121 cg2getcmap, cg2putcmap }; 122 123 static int cg2intr(void *); 124 125 /* 126 * Match a cg2. 127 */ 128 static int 129 cg2match(device_t parent, cfdata_t cf, void *aux) 130 { 131 struct confargs *ca = aux; 132 int probe_addr; 133 134 /* No default VME address. */ 135 if (ca->ca_paddr == -1) 136 return 0; 137 138 /* Make sure something is there... */ 139 probe_addr = ca->ca_paddr + CTLREGS_OFF; 140 if (bus_peek(ca->ca_bustype, probe_addr, 1) == -1) 141 return 0; 142 143 /* XXX: look at the ID reg? */ 144 /* aprint_debug("cg2: id=0x%x\n", x); */ 145 146 /* Default interrupt priority. */ 147 if (ca->ca_intpri == -1) 148 ca->ca_intpri = 4; 149 150 return 1; 151 } 152 153 /* 154 * Attach a display. We need to notice if it is the console, too. 155 */ 156 static void 157 cg2attach(device_t parent, device_t self, void *args) 158 { 159 struct cg2_softc *sc = device_private(self); 160 struct fbdevice *fb = &sc->sc_fb; 161 struct confargs *ca = args; 162 struct fbtype *fbt; 163 164 sc->sc_dev = self; 165 sc->sc_phys = ca->ca_paddr; 166 sc->sc_pmtype = PMAP_NC | PMAP_VME16; 167 168 sc->sc_ctlreg = (struct cg2fb *)bus_mapin(ca->ca_bustype, 169 ca->ca_paddr + CTLREGS_OFF, CTLREGS_SIZE); 170 171 isr_add_vectored(cg2intr, sc, ca->ca_intpri, ca->ca_intvec); 172 173 /* 174 * XXX - Initialize? Determine type? 175 */ 176 sc->sc_ctlreg->intrptvec.reg = ca->ca_intvec; 177 sc->sc_ctlreg->status.word = 1; 178 179 fb->fb_driver = &cg2fbdriver; 180 fb->fb_private = sc; 181 fb->fb_name = device_xname(self); 182 183 fbt = &fb->fb_fbtype; 184 fbt->fb_type = FBTYPE_SUN2COLOR; 185 fbt->fb_depth = 8; 186 fbt->fb_cmsize = CMSIZE; 187 188 fbt->fb_width = 1152; 189 fbt->fb_height = 900; 190 fbt->fb_size = CG2_MAPPED_SIZE; 191 192 aprint_normal(" (%dx%d)\n", fbt->fb_width, fbt->fb_height); 193 fb_attach(fb, 2); 194 } 195 196 int 197 cg2open(dev_t dev, int flags, int mode, struct lwp *l) 198 { 199 struct cg2_softc *sc; 200 int unit = minor(dev); 201 202 sc = device_lookup_private(&cgtwo_cd, unit); 203 if (sc == NULL) 204 return ENXIO; 205 return 0; 206 } 207 208 int 209 cg2ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 210 { 211 struct cg2_softc *sc = device_lookup_private(&cgtwo_cd, minor(dev)); 212 213 return fbioctlfb(&sc->sc_fb, cmd, data); 214 } 215 216 /* 217 * Return the address that would map the given device at the given 218 * offset, allowing for the given protection, or return -1 for error. 219 */ 220 paddr_t 221 cg2mmap(dev_t dev, off_t off, int prot) 222 { 223 struct cg2_softc *sc = device_lookup_private(&cgtwo_cd, minor(dev)); 224 225 if (off & PGOFSET) 226 panic("%s: bad offset", __func__); 227 228 if (off >= CG2_MAPPED_SIZE) 229 return -1; 230 231 /* 232 * I turned on PMAP_NC here to disable the cache as I was 233 * getting horribly broken behaviour with it on. 234 */ 235 return (sc->sc_phys + off) | sc->sc_pmtype; 236 } 237 238 /* 239 * Internal ioctl functions. 240 */ 241 242 /* FBIOGATTR: */ 243 static int 244 cg2gattr(struct fbdevice *fb, void *data) 245 { 246 struct fbgattr *fba = data; 247 248 fba->real_type = fb->fb_fbtype.fb_type; 249 fba->owner = 0; /* XXX - TIOCCONS stuff? */ 250 fba->fbtype = fb->fb_fbtype; 251 fba->sattr.flags = 0; 252 fba->sattr.emu_type = fb->fb_fbtype.fb_type; 253 fba->sattr.dev_specific[0] = -1; 254 fba->emu_types[0] = fb->fb_fbtype.fb_type; 255 fba->emu_types[1] = -1; 256 return 0; 257 } 258 259 /* FBIOGVIDEO: */ 260 static int 261 cg2gvideo(struct fbdevice *fb, void *data) 262 { 263 int *on = data; 264 struct cg2_softc *sc = fb->fb_private; 265 266 *on = sc->sc_ctlreg->status.reg.video_enab; 267 return 0; 268 } 269 270 /* FBIOSVIDEO: */ 271 static int 272 cg2svideo(struct fbdevice *fb, void *data) 273 { 274 int *on = data; 275 struct cg2_softc *sc = fb->fb_private; 276 277 sc->sc_ctlreg->status.reg.video_enab = (*on) & 1; 278 279 return 0; 280 } 281 282 /* FBIOGETCMAP: */ 283 static int 284 cg2getcmap(struct fbdevice *fb, void *data) 285 { 286 struct fbcmap *cmap = data; 287 struct cg2_softc *sc = fb->fb_private; 288 uint8_t red[CMSIZE], green[CMSIZE], blue[CMSIZE]; 289 int error, start, count, ecount; 290 u_int i; 291 uint16_t *p; 292 293 start = cmap->index; 294 count = cmap->count; 295 ecount = start + count; 296 if (start >= CMSIZE || count > CMSIZE - start) 297 return EINVAL; 298 299 /* XXX - Wait for retrace? */ 300 301 /* Copy hardware to local arrays. */ 302 p = &sc->sc_ctlreg->redmap[start]; 303 for (i = start; i < ecount; i++) 304 red[i] = *p++; 305 p = &sc->sc_ctlreg->greenmap[start]; 306 for (i = start; i < ecount; i++) 307 green[i] = *p++; 308 p = &sc->sc_ctlreg->bluemap[start]; 309 for (i = start; i < ecount; i++) 310 blue[i] = *p++; 311 312 /* Copy local arrays to user space. */ 313 if ((error = copyout(red + start, cmap->red, count)) != 0) 314 return error; 315 if ((error = copyout(green + start, cmap->green, count)) != 0) 316 return error; 317 if ((error = copyout(blue + start, cmap->blue, count)) != 0) 318 return error; 319 320 return 0; 321 } 322 323 /* FBIOPUTCMAP: */ 324 static int 325 cg2putcmap(struct fbdevice *fb, void *data) 326 { 327 struct fbcmap *cmap = data; 328 struct cg2_softc *sc = fb->fb_private; 329 uint8_t red[CMSIZE], green[CMSIZE], blue[CMSIZE]; 330 int error; 331 u_int start, count, ecount; 332 u_int i; 333 uint16_t *p; 334 335 start = cmap->index; 336 count = cmap->count; 337 ecount = start + count; 338 if (start >= CMSIZE || count > CMSIZE - start) 339 return EINVAL; 340 341 /* Copy from user space to local arrays. */ 342 if ((error = copyin(cmap->red, red + start, count)) != 0) 343 return error; 344 if ((error = copyin(cmap->green, green + start, count)) != 0) 345 return error; 346 if ((error = copyin(cmap->blue, blue + start, count)) != 0) 347 return error; 348 349 /* XXX - Wait for retrace? */ 350 351 /* Copy from local arrays to hardware. */ 352 p = &sc->sc_ctlreg->redmap[start]; 353 for (i = start; i < ecount; i++) 354 *p++ = red[i]; 355 p = &sc->sc_ctlreg->greenmap[start]; 356 for (i = start; i < ecount; i++) 357 *p++ = green[i]; 358 p = &sc->sc_ctlreg->bluemap[start]; 359 for (i = start; i < ecount; i++) 360 *p++ = blue[i]; 361 362 return 0; 363 364 } 365 366 static int 367 cg2intr(void *vsc) 368 { 369 struct cg2_softc *sc = vsc; 370 371 /* XXX - Just disable interrupts for now. */ 372 sc->sc_ctlreg->status.reg.inten = 0; 373 374 printf("cg2intr\n"); 375 return 1; 376 } 377