bwtwo.c revision 1.5
1/* $OpenBSD: bwtwo.c,v 1.5 2002/09/10 03:18:59 jason Exp $ */ 2 3/* 4 * Copyright (c) 2002 Jason L. Wright (jason@thought.net) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Jason L. Wright 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 * 33 * Effort sponsored in part by the Defense Advanced Research Projects 34 * Agency (DARPA) and Air Force Research Laboratory, Air Force 35 * Materiel Command, USAF, under agreement number F30602-01-2-0537. 36 * 37 */ 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/kernel.h> 42#include <sys/errno.h> 43#include <sys/device.h> 44#include <sys/ioctl.h> 45#include <sys/malloc.h> 46 47#include <machine/bus.h> 48#include <machine/intr.h> 49#include <machine/autoconf.h> 50#include <machine/openfirm.h> 51 52#include <dev/sbus/sbusvar.h> 53#include <dev/wscons/wsconsio.h> 54#include <dev/wscons/wsdisplayvar.h> 55#include <dev/wscons/wscons_raster.h> 56#include <dev/rasops/rasops.h> 57 58#define BWTWO_CTRL_OFFSET 0x400000 59#define BWTWO_CTRL_SIZE (sizeof(u_int32_t) * 8) 60#define BWTWO_VID_OFFSET 0x800000 61#define BWTWO_VID_SIZE (1024 * 1024) 62 63union bt_cmap { 64 u_int8_t cm_map[256][3]; /* 256 r/b/g entries */ 65 u_int32_t cm_chip[256 * 3 / 4]; /* the way the chip is loaded */ 66}; 67 68#define BT_ADDR 0x00 /* map address register */ 69#define BT_CMAP 0x04 /* colormap data register */ 70#define BT_CTRL 0x08 /* control register */ 71#define BT_OMAP 0x0c /* overlay (cursor) map register */ 72#define FBC_CTRL 0x10 /* control */ 73#define FBC_STAT 0x11 /* status */ 74#define FBC_START 0x12 /* cursor start */ 75#define FBC_END 0x13 /* cursor end */ 76#define FBC_VCTRL 0x14 /* 12 bytes of timing goo */ 77 78#define BT_WRITE(sc, reg, val) \ 79 bus_space_write_4((sc)->sc_bustag, (sc)->sc_ctrl_regs, (reg), (val)) 80#define BT_READ(sc, reg) \ 81 bus_space_read_4((sc)->sc_bustag, (sc)->sc_ctrl_regs, (reg)) 82#define BT_BARRIER(sc,reg,flags) \ 83 bus_space_barrier((sc)->sc_bustag, (sc)->sc_ctrl_regs, (reg), \ 84 sizeof(u_int32_t), (flags)) 85 86#define BT_D4M3(x) ((((x) >> 2) << 1) + ((x) >> 2)) /* (x / 4) * 3 */ 87#define BT_D4M4(x) ((x) & ~3) /* (x / 4) * 4 */ 88 89#define FBC_CTRL_IENAB 0x80 /* interrupt enable */ 90#define FBC_CTRL_VENAB 0x40 /* video enable */ 91#define FBC_CTRL_TIME 0x20 /* timing enable */ 92#define FBC_CTRL_CURS 0x10 /* cursor compare enable */ 93#define FBC_CTRL_XTAL 0x0c /* xtal select (0,1,2,test): */ 94#define FBC_CTRL_XTAL_0 0x00 /* 0 */ 95#define FBC_CTRL_XTAL_1 0x04 /* 0 */ 96#define FBC_CTRL_XTAL_2 0x08 /* 0 */ 97#define FBC_CTRL_XTAL_TEST 0x0c /* 0 */ 98#define FBC_CTRL_DIV 0x03 /* divisor (1,2,3,4): */ 99#define FBC_CTRL_DIV_1 0x00 /* / 1 */ 100#define FBC_CTRL_DIV_2 0x01 /* / 2 */ 101#define FBC_CTRL_DIV_3 0x02 /* / 3 */ 102#define FBC_CTRL_DIV_4 0x03 /* / 4 */ 103 104#define FBC_STAT_INTR 0x80 /* interrupt pending */ 105#define FBC_STAT_RES 0x70 /* monitor sense: */ 106#define FBC_STAT_RES_1024 0x10 /* 1024x768 */ 107#define FBC_STAT_RES_1280 0x40 /* 1280x1024 */ 108#define FBC_STAT_RES_1152 0x30 /* 1152x900 */ 109#define FBC_STAT_RES_1152A 0x40 /* 1152x900x76, A */ 110#define FBC_STAT_RES_1600 0x50 /* 1600x1200 */ 111#define FBC_STAT_RES_1152B 0x60 /* 1152x900x86, B */ 112#define FBC_STAT_ID 0x0f /* id mask: */ 113#define FBC_STAT_ID_COLOR 0x01 /* color */ 114#define FBC_STAT_ID_MONO 0x02 /* monochrome */ 115#define FBC_STAT_ID_MONOECL 0x03 /* monochrome, ecl */ 116 117#define FBC_READ(sc, reg) \ 118 bus_space_read_1((sc)->sc_bustag, (sc)->sc_ctrl_regs, (reg)) 119#define FBC_WRITE(sc, reg, val) \ 120 bus_space_write_1((sc)->sc_bustag, (sc)->sc_ctrl_regs, (reg), (val)) 121 122struct bwtwo_softc { 123 struct device sc_dev; 124 struct sbusdev sc_sd; 125 bus_space_tag_t sc_bustag; 126 bus_addr_t sc_paddr; 127 bus_space_handle_t sc_ctrl_regs; 128 bus_space_handle_t sc_vid_regs; 129 int sc_nscreens; 130 int sc_width, sc_height, sc_depth, sc_linebytes; 131 union bt_cmap sc_cmap; 132 struct rasops_info sc_rasops; 133 int *sc_crowp, *sc_ccolp; 134}; 135 136struct wsscreen_descr bwtwo_stdscreen = { 137 "std", 138 0, 0, /* will be filled in -- XXX shouldn't, it's global. */ 139 0, 140 0, 0, 141 WSSCREEN_UNDERLINE | WSSCREEN_REVERSE 142}; 143 144const struct wsscreen_descr *bwtwo_scrlist[] = { 145 &bwtwo_stdscreen, 146 /* XXX other formats? */ 147}; 148 149struct wsscreen_list bwtwo_screenlist = { 150 sizeof(bwtwo_scrlist) / sizeof(struct wsscreen_descr *), bwtwo_scrlist 151}; 152 153int bwtwo_ioctl(void *, u_long, caddr_t, int, struct proc *); 154int bwtwo_alloc_screen(void *, const struct wsscreen_descr *, void **, 155 int *, int *, long *); 156void bwtwo_free_screen(void *, void *); 157int bwtwo_show_screen(void *, void *, int, void (*cb)(void *, int, int), 158 void *); 159paddr_t bwtwo_mmap(void *, off_t, int); 160int bwtwo_is_console(int); 161void bwtwo_burner(void *, u_int, u_int); 162void bwtwo_updatecursor(struct rasops_info *); 163static int a2int(char *, int); 164 165struct wsdisplay_accessops bwtwo_accessops = { 166 bwtwo_ioctl, 167 bwtwo_mmap, 168 bwtwo_alloc_screen, 169 bwtwo_free_screen, 170 bwtwo_show_screen, 171 NULL, /* load_font */ 172 NULL, /* scrollback */ 173 NULL, /* getchar */ 174 bwtwo_burner, 175}; 176 177int bwtwomatch(struct device *, void *, void *); 178void bwtwoattach(struct device *, struct device *, void *); 179 180struct cfattach bwtwo_ca = { 181 sizeof (struct bwtwo_softc), bwtwomatch, bwtwoattach 182}; 183 184struct cfdriver bwtwo_cd = { 185 NULL, "bwtwo", DV_DULL 186}; 187 188int 189bwtwomatch(parent, vcf, aux) 190 struct device *parent; 191 void *vcf, *aux; 192{ 193 struct cfdata *cf = vcf; 194 struct sbus_attach_args *sa = aux; 195 196 return (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0); 197} 198 199void 200bwtwoattach(parent, self, aux) 201 struct device *parent, *self; 202 void *aux; 203{ 204 struct bwtwo_softc *sc = (struct bwtwo_softc *)self; 205 struct sbus_attach_args *sa = aux; 206 struct wsemuldisplaydev_attach_args waa; 207 int console; 208 long defattr; 209 210 sc->sc_bustag = sa->sa_bustag; 211 sc->sc_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_slot, sa->sa_offset); 212 213 if (sa->sa_nreg != 1) { 214 printf(": expected %d registers, got %d\n", 1, sa->sa_nreg); 215 goto fail; 216 } 217 218 /* 219 * Map just CTRL and video RAM. 220 */ 221 if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, 222 sa->sa_reg[0].sbr_offset + BWTWO_CTRL_OFFSET, 223 BWTWO_CTRL_SIZE, BUS_SPACE_MAP_LINEAR, 224 0, &sc->sc_ctrl_regs) != 0) { 225 printf(": cannot map ctrl registers\n"); 226 goto fail_ctrl; 227 } 228 229 if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, 230 sa->sa_reg[0].sbr_offset + BWTWO_VID_OFFSET, 231 BWTWO_VID_SIZE, BUS_SPACE_MAP_LINEAR, 232 0, &sc->sc_vid_regs) != 0) { 233 printf(": cannot map vid registers\n"); 234 goto fail_vid; 235 } 236 237 console = bwtwo_is_console(sa->sa_node); 238 239 sc->sc_depth = getpropint(sa->sa_node, "depth", 1); 240 sc->sc_linebytes = getpropint(sa->sa_node, "linebytes", 1152); 241 sc->sc_height = getpropint(sa->sa_node, "height", 900); 242 sc->sc_width = getpropint(sa->sa_node, "width", 1152); 243 244 sbus_establish(&sc->sc_sd, &sc->sc_dev); 245 246 bwtwo_burner(sc, 1, 0); 247 248 sc->sc_rasops.ri_depth = sc->sc_depth; 249 sc->sc_rasops.ri_stride = sc->sc_linebytes; 250 sc->sc_rasops.ri_flg = RI_CENTER | 251 (console ? 0 : RI_CLEAR); 252 sc->sc_rasops.ri_bits = (void *)bus_space_vaddr(sc->sc_bustag, 253 sc->sc_vid_regs); 254 sc->sc_rasops.ri_width = sc->sc_width; 255 sc->sc_rasops.ri_height = sc->sc_height; 256 sc->sc_rasops.ri_hw = sc; 257 258 rasops_init(&sc->sc_rasops, 259 a2int(getpropstring(optionsnode, "screen-#rows"), 34), 260 a2int(getpropstring(optionsnode, "screen-#columns"), 80)); 261 262 bwtwo_stdscreen.nrows = sc->sc_rasops.ri_rows; 263 bwtwo_stdscreen.ncols = sc->sc_rasops.ri_cols; 264 bwtwo_stdscreen.textops = &sc->sc_rasops.ri_ops; 265 sc->sc_rasops.ri_ops.alloc_attr(&sc->sc_rasops, 0, 0, 0, &defattr); 266 267 printf("\n"); 268 269 if (console) { 270 if (romgetcursoraddr(&sc->sc_crowp, &sc->sc_ccolp)) 271 sc->sc_ccolp = sc->sc_crowp = NULL; 272 if (sc->sc_ccolp != NULL) 273 sc->sc_rasops.ri_ccol = *sc->sc_ccolp; 274 if (sc->sc_crowp != NULL) 275 sc->sc_rasops.ri_crow = *sc->sc_crowp; 276 sc->sc_rasops.ri_updatecursor = bwtwo_updatecursor; 277 278 wsdisplay_cnattach(&bwtwo_stdscreen, &sc->sc_rasops, 279 sc->sc_rasops.ri_ccol, sc->sc_rasops.ri_crow, defattr); 280 } 281 282 waa.console = console; 283 waa.scrdata = &bwtwo_screenlist; 284 waa.accessops = &bwtwo_accessops; 285 waa.accesscookie = sc; 286 config_found(self, &waa, wsemuldisplaydevprint); 287 288 return; 289 290fail_vid: 291 bus_space_unmap(sa->sa_bustag, sc->sc_ctrl_regs, BWTWO_CTRL_SIZE); 292fail_ctrl: 293fail: 294} 295 296int 297bwtwo_ioctl(v, cmd, data, flags, p) 298 void *v; 299 u_long cmd; 300 caddr_t data; 301 int flags; 302 struct proc *p; 303{ 304 struct bwtwo_softc *sc = v; 305 struct wsdisplay_fbinfo *wdf; 306 307 switch (cmd) { 308 case WSDISPLAYIO_GTYPE: 309 *(u_int *)data = WSDISPLAY_TYPE_SUNBW; 310 break; 311 case WSDISPLAYIO_GINFO: 312 wdf = (void *)data; 313 wdf->height = sc->sc_height; 314 wdf->width = sc->sc_width; 315 wdf->depth = sc->sc_depth; 316 wdf->cmsize = 0; 317 break; 318 case WSDISPLAYIO_LINEBYTES: 319 *(u_int *)data = sc->sc_linebytes; 320 break; 321 322 case WSDISPLAYIO_GETCMAP: 323 case WSDISPLAYIO_PUTCMAP: 324 break; 325 326 case WSDISPLAYIO_SVIDEO: 327 case WSDISPLAYIO_GVIDEO: 328 case WSDISPLAYIO_GCURPOS: 329 case WSDISPLAYIO_SCURPOS: 330 case WSDISPLAYIO_GCURMAX: 331 case WSDISPLAYIO_GCURSOR: 332 case WSDISPLAYIO_SCURSOR: 333 default: 334 return -1; /* not supported yet */ 335 } 336 337 return (0); 338} 339 340int 341bwtwo_alloc_screen(v, type, cookiep, curxp, curyp, attrp) 342 void *v; 343 const struct wsscreen_descr *type; 344 void **cookiep; 345 int *curxp, *curyp; 346 long *attrp; 347{ 348 struct bwtwo_softc *sc = v; 349 350 if (sc->sc_nscreens > 0) 351 return (ENOMEM); 352 353 *cookiep = &sc->sc_rasops; 354 *curyp = 0; 355 *curxp = 0; 356 sc->sc_rasops.ri_ops.alloc_attr(&sc->sc_rasops, 0, 0, 0, attrp); 357 sc->sc_nscreens++; 358 return (0); 359} 360 361void 362bwtwo_free_screen(v, cookie) 363 void *v; 364 void *cookie; 365{ 366 struct bwtwo_softc *sc = v; 367 368 sc->sc_nscreens--; 369} 370 371int 372bwtwo_show_screen(v, cookie, waitok, cb, cbarg) 373 void *v; 374 void *cookie; 375 int waitok; 376 void (*cb)(void *, int, int); 377 void *cbarg; 378{ 379 return (0); 380} 381 382#define START (128 * 1024 + 128 * 1024) 383#define NOOVERLAY (0x04000000) 384 385paddr_t 386bwtwo_mmap(v, offset, prot) 387 void *v; 388 off_t offset; 389 int prot; 390{ 391 struct bwtwo_softc *sc = v; 392 393 if (offset & PGOFSET) 394 return (-1); 395 396 if (offset >= 0 && offset < (sc->sc_linebytes * sc->sc_height)) 397 return (bus_space_mmap(sc->sc_bustag, sc->sc_paddr, 398 BWTWO_VID_OFFSET + offset, prot, BUS_SPACE_MAP_LINEAR)); 399 400 return (-1); 401} 402 403static int 404a2int(char *cp, int deflt) 405{ 406 int i = 0; 407 408 if (*cp == '\0') 409 return (deflt); 410 while (*cp != '\0') 411 i = i * 10 + *cp++ - '0'; 412 return (i); 413} 414 415int 416bwtwo_is_console(node) 417 int node; 418{ 419 extern int fbnode; 420 421 return (fbnode == node); 422} 423 424void 425bwtwo_burner(vsc, on, flags) 426 void *vsc; 427 u_int on, flags; 428{ 429 struct bwtwo_softc *sc = vsc; 430 int s; 431 u_int8_t fbc; 432 433 s = splhigh(); 434 fbc = FBC_READ(sc, FBC_CTRL); 435 if (on) 436 fbc |= FBC_CTRL_VENAB | FBC_CTRL_TIME; 437 else { 438 fbc &= ~FBC_CTRL_VENAB; 439 if (flags & WSDISPLAY_BURN_VBLANK) 440 fbc &= ~FBC_CTRL_TIME; 441 } 442 FBC_WRITE(sc, FBC_CTRL, fbc); 443 splx(s); 444} 445 446void 447bwtwo_updatecursor(ri) 448 struct rasops_info *ri; 449{ 450 struct bwtwo_softc *sc = ri->ri_hw; 451 452 if (sc->sc_crowp != NULL) 453 *sc->sc_crowp = ri->ri_crow; 454 if (sc->sc_ccolp != NULL) 455 *sc->sc_ccolp = ri->ri_ccol; 456} 457