1/* $NetBSD: bw2.c,v 1.37 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 * @(#)bwtwo.c 8.1 (Berkeley) 6/11/93 41 */ 42 43/* 44 * black&white display (bw2) driver. 45 * 46 * Does not handle interrupts, even though they can occur. 47 */ 48 49#include <sys/cdefs.h> 50__KERNEL_RCSID(0, "$NetBSD: bw2.c,v 1.37 2023/12/20 05:18:00 thorpej Exp $"); 51 52#include <sys/param.h> 53#include <sys/systm.h> 54#include <sys/conf.h> 55#include <sys/device.h> 56#include <sys/ioctl.h> 57#include <sys/mman.h> 58#include <sys/proc.h> 59#include <sys/tty.h> 60 61#include <uvm/uvm_extern.h> 62 63#include <machine/autoconf.h> 64#include <machine/cpu.h> 65#include <dev/sun/fbio.h> 66#include <machine/idprom.h> 67#include <machine/pmap.h> 68 69#include <sun3/dev/fbvar.h> 70#include <sun3/dev/bw2reg.h> 71#include <sun3/dev/p4reg.h> 72 73#include "ioconf.h" 74 75/* per-display variables */ 76struct bw2_softc { 77 device_t sc_dev; /* base device */ 78 struct fbdevice sc_fb; /* frame buffer device */ 79 int sc_phys; /* display RAM (phys addr) */ 80 /* If using overlay plane of something, it is... */ 81 int sc_ovtype; /* ... this type. */ 82 int sc_video_on; 83}; 84 85/* autoconfiguration driver */ 86static int bw2match(device_t, cfdata_t, void *); 87static void bw2attach(device_t, device_t, void *); 88 89CFATTACH_DECL_NEW(bwtwo, sizeof(struct bw2_softc), 90 bw2match, bw2attach, NULL, NULL); 91 92dev_type_open(bw2open); 93dev_type_ioctl(bw2ioctl); 94dev_type_mmap(bw2mmap); 95 96const struct cdevsw bwtwo_cdevsw = { 97 .d_open = bw2open, 98 .d_close = nullclose, 99 .d_read = noread, 100 .d_write = nowrite, 101 .d_ioctl = bw2ioctl, 102 .d_stop = nostop, 103 .d_tty = notty, 104 .d_poll = nopoll, 105 .d_mmap = bw2mmap, 106 .d_kqfilter = nokqfilter, 107 .d_discard = nodiscard, 108 .d_flag = 0 109}; 110 111/* XXX we do not handle frame buffer interrupts */ 112 113static int bw2gvideo(struct fbdevice *, void *); 114static int bw2svideo(struct fbdevice *, void *); 115 116static struct fbdriver bw2fbdriver = { 117 bw2open, nullclose, bw2mmap, nokqfilter, 118 fb_noioctl, 119 bw2gvideo, bw2svideo, 120 fb_noioctl, fb_noioctl, }; 121 122static int 123bw2match(device_t parent, cfdata_t cf, void *args) 124{ 125 struct confargs *ca = args; 126 int mid, p4id, peekval; 127 void *p4reg; 128 129 /* No default address support. */ 130 if (ca->ca_paddr == -1) 131 return 0; 132 133 /* 134 * Slight hack here: The low four bits of the 135 * config flags, if set, restrict the match to 136 * that machine "implementation" only. 137 */ 138 mid = cf->cf_flags & IDM_IMPL_MASK; 139 if (mid != 0 && (mid != (cpu_machine_id & IDM_IMPL_MASK))) 140 return 0; 141 142 /* 143 * Make sure something is there, and if so, 144 * see if it looks like a P4 register. 145 */ 146 p4reg = bus_tmapin(ca->ca_bustype, ca->ca_paddr); 147 peekval = peek_long(p4reg); 148 p4id = (peekval == -1) ? P4_NOTFOUND : fb_pfour_id(p4reg); 149 bus_tmapout(p4reg); 150 if (peekval == -1) 151 return 0; 152 153 /* 154 * The config flag 0x40 if set means we should match 155 * only on a CG? overlay plane. We can use only the 156 * CG4 and CG8, which both have a P4 register. 157 */ 158 if (cf->cf_flags & 0x40) { 159 switch (p4id) { 160 case P4_ID_COLOR8P1: 161 case P4_ID_COLOR24: 162 return 1; 163 case P4_NOTFOUND: 164 default: 165 return 0; 166 } 167 } 168 169 /* 170 * OK, we are expecting a plain old BW2, and 171 * there may or may not be a P4 register. 172 */ 173 switch (p4id) { 174 case P4_ID_BW: 175 case P4_NOTFOUND: 176 return 1; 177 default: 178#ifdef DEBUG 179 aprint_debug("bwtwo at 0x%lx match p4id=0x%x fails\n", 180 ca->ca_paddr, p4id & 0xFF); 181#endif 182 break; 183 } 184 185 return 0; 186} 187 188/* 189 * Attach a display. We need to notice if it is the console, too. 190 */ 191static void 192bw2attach(device_t parent, device_t self, void *args) 193{ 194 struct bw2_softc *sc = device_private(self); 195 struct fbdevice *fb = &sc->sc_fb; 196 struct confargs *ca = args; 197 struct fbtype *fbt; 198 void *p4reg; 199 int p4id, tmp; 200 int pixeloffset; /* offset to framebuffer */ 201 202 sc->sc_dev = self; 203 204 fbt = &fb->fb_fbtype; 205 fbt->fb_type = FBTYPE_SUN2BW; 206 fbt->fb_width = 1152; /* default - see below */ 207 fbt->fb_height = 900; /* default - see below */ 208 fbt->fb_depth = 1; 209 fbt->fb_cmsize = 0; 210 fbt->fb_size = BW2_FBSIZE; /* default - see below */ 211 fb->fb_driver = &bw2fbdriver; 212 fb->fb_private = sc; 213 fb->fb_name = device_xname(self); 214 fb->fb_flags = device_cfdata(self)->cf_flags; 215 216 /* Set up default pixel offset. May be changed below. */ 217 pixeloffset = 0; 218 219 /* Does it have a P4 register? */ 220 p4reg = bus_mapin(ca->ca_bustype, ca->ca_paddr, 4); 221 p4id = fb_pfour_id(p4reg); 222 if (p4id != P4_NOTFOUND) 223 fb->fb_pfour = p4reg; 224 else 225 bus_mapout(p4reg, 4); 226 227 switch (p4id) { 228 case P4_NOTFOUND: 229 pixeloffset = 0; 230 break; 231 232 case P4_ID_BW: 233 pixeloffset = P4_BW_OFF; 234 break; 235 236 default: 237 aprint_error("%s: bad p4id=0x%x\n", fb->fb_name, p4id); 238 /* Must be some kinda color... */ 239 /* FALLTHROUGH */ 240 case P4_ID_COLOR8P1: 241 case P4_ID_COLOR24: 242 sc->sc_ovtype = p4id; 243 pixeloffset = P4_COLOR_OFF_OVERLAY; 244 break; 245 } 246 sc->sc_phys = ca->ca_paddr + pixeloffset; 247 248 /* 249 * Determine width and height as follows: 250 * If it has a P4 register, use that; 251 * else if unit==0, use the EEPROM size, 252 * else make our best guess. 253 */ 254 if (fb->fb_pfour) 255 fb_pfour_setsize(fb); 256 /* XXX device_unit() abuse */ 257 else if (device_unit(self) == 0) 258 fb_eeprom_setsize(fb); 259 else { 260 /* Guess based on machine ID. */ 261 switch (cpu_machine_id) { 262#ifdef _SUN3_ 263 case ID_SUN3_60: 264 /* 265 * Only the model 60 can have hi-res. 266 * Look at the "resolution" jumper. 267 */ 268 tmp = bus_peek(BUS_OBMEM, BW2_CR_PADDR, 1); 269 if ((tmp != -1) && (tmp & 0x80) == 0) 270 goto high_res; 271 break; 272 273 case ID_SUN3_260: 274 /* The Sun3/260 is ALWAYS high-resolution! */ 275 /* fall through */ 276 high_res: 277 fbt->fb_width = 1600; 278 fbt->fb_height = 1280; 279 fbt->fb_size = BW2_FBSIZE_HIRES; 280 break; 281#endif /* SUN3 */ 282 283 default: 284 /* Leave the defaults set above. */ 285 break; 286 } 287 } 288 aprint_normal(" (%dx%d)\n", fbt->fb_width, fbt->fb_height); 289 290 /* Make sure video is on. */ 291 tmp = 1; 292 bw2svideo(fb, &tmp); 293 294 /* Let /dev/fb know we are here. */ 295 fb_attach(fb, 1); 296} 297 298int 299bw2open(dev_t dev, int flags, int mode, struct lwp *l) 300{ 301 struct bw2_softc *sc; 302 int unit = minor(dev); 303 304 sc = device_lookup_private(&bwtwo_cd, unit); 305 if (sc == NULL) 306 return ENXIO; 307 return 0; 308} 309 310int 311bw2ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 312{ 313 struct bw2_softc *sc = device_lookup_private(&bwtwo_cd, minor(dev)); 314 315 return fbioctlfb(&sc->sc_fb, cmd, data); 316} 317 318/* 319 * Return the address that would map the given device at the given 320 * offset, allowing for the given protection, or return -1 for error. 321 */ 322paddr_t 323bw2mmap(dev_t dev, off_t off, int prot) 324{ 325 struct bw2_softc *sc = device_lookup_private(&bwtwo_cd, minor(dev)); 326 int size = sc->sc_fb.fb_fbtype.fb_size; 327 328 if (off & PGOFSET) 329 panic("%s: bad offset", __func__); 330 331 if ((off < 0) || (off >= size)) 332 return -1; 333 334 /* 335 * I turned on PMAP_NC here to disable the cache as I was 336 * getting horribly broken behaviour without it. 337 */ 338 return (sc->sc_phys + off) | PMAP_NC; 339} 340 341/* FBIOGVIDEO: */ 342static int 343bw2gvideo(struct fbdevice *fb, void *data) 344{ 345 struct bw2_softc *sc = fb->fb_private; 346 int *on = data; 347 348 *on = sc->sc_video_on; 349 return 0; 350} 351 352/* FBIOSVIDEO: */ 353static int 354bw2svideo(struct fbdevice *fb, void *data) 355{ 356 struct bw2_softc *sc = fb->fb_private; 357 int *on = data; 358 359 if (sc->sc_video_on == *on) 360 return 0; 361 sc->sc_video_on = *on; 362 363 if (fb->fb_pfour) 364 fb_pfour_set_video(fb, sc->sc_video_on); 365 else 366 enable_video(sc->sc_video_on); 367 368 return 0; 369} 370