1/* $NetBSD: gbox.c,v 1.2 2011/02/12 16:40:29 tsutsui Exp $ */ 2/* $OpenBSD: gbox.c,v 1.15 2007/01/07 15:13:52 miod Exp $ */ 3 4/* 5 * Copyright (c) 2005, Miodrag Vallat 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28/*- 29 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. 30 * All rights reserved. 31 * 32 * This code is derived from software contributed to The NetBSD Foundation 33 * by Jason R. Thorpe. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 44 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 45 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 46 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 47 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 48 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 49 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 50 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 51 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 52 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 53 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 54 * POSSIBILITY OF SUCH DAMAGE. 55 */ 56 57/* 58 * Copyright (c) 1988 University of Utah. 59 * Copyright (c) 1990, 1993 60 * The Regents of the University of California. All rights reserved. 61 * 62 * This code is derived from software contributed to Berkeley by 63 * the Systems Programming Group of the University of Utah Computer 64 * Science Department. 65 * 66 * Redistribution and use in source and binary forms, with or without 67 * modification, are permitted provided that the following conditions 68 * are met: 69 * 1. Redistributions of source code must retain the above copyright 70 * notice, this list of conditions and the following disclaimer. 71 * 2. Redistributions in binary form must reproduce the above copyright 72 * notice, this list of conditions and the following disclaimer in the 73 * documentation and/or other materials provided with the distribution. 74 * 3. Neither the name of the University nor the names of its contributors 75 * may be used to endorse or promote products derived from this software 76 * without specific prior written permission. 77 * 78 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 79 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 80 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 81 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 82 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 83 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 84 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 85 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 86 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 87 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 88 * SUCH DAMAGE. 89 * 90 * from: Utah $Hdr: grf_gb.c 1.18 93/08/13$ 91 * 92 * @(#)grf_gb.c 8.4 (Berkeley) 1/12/94 93 */ 94 95/* 96 * Graphics routines for the Gatorbox. 97 * 98 * Note: In the context of this system, "gator" and "gatorbox" both refer to 99 * HP 987x0 graphics systems. "Gator" is not used for high res mono. 100 * (as in 9837 Gator systems) 101 */ 102 103#include <sys/param.h> 104#include <sys/systm.h> 105#include <sys/conf.h> 106#include <sys/device.h> 107#include <sys/proc.h> 108#include <sys/ioctl.h> 109#include <sys/bus.h> 110#include <sys/cpu.h> 111 112#include <machine/autoconf.h> 113 114#include <hp300/dev/dioreg.h> 115#include <hp300/dev/diovar.h> 116#include <hp300/dev/diodevs.h> 117#include <hp300/dev/intiovar.h> 118 119#include <dev/wscons/wsconsio.h> 120#include <dev/wscons/wsdisplayvar.h> 121#include <dev/rasops/rasops.h> 122 123#include <hp300/dev/diofbreg.h> 124#include <hp300/dev/diofbvar.h> 125#include <hp300/dev/gboxreg.h> 126 127struct gbox_softc { 128 device_t sc_dev; 129 struct diofb *sc_fb; 130 struct diofb sc_fb_store; 131 int sc_scode; 132}; 133 134static int gbox_dio_match(device_t, cfdata_t, void *); 135static void gbox_dio_attach(device_t, device_t, void *); 136static int gbox_intio_match(device_t, cfdata_t, void *); 137static void gbox_intio_attach(device_t, device_t, void *); 138 139CFATTACH_DECL_NEW(gbox_dio, sizeof(struct gbox_softc), 140 gbox_dio_match, gbox_dio_attach, NULL, NULL); 141 142CFATTACH_DECL_NEW(gbox_intio, sizeof(struct gbox_softc), 143 gbox_intio_match, gbox_intio_attach, NULL, NULL); 144 145static int gbox_reset(struct diofb *, int, struct diofbreg *); 146static void gbox_restore(struct diofb *); 147static int gbox_setcmap(struct diofb *, struct wsdisplay_cmap *); 148static void gbox_setcolor(struct diofb *, u_int); 149static int gbox_windowmove(struct diofb *, uint16_t, uint16_t, uint16_t, 150 uint16_t, uint16_t, uint16_t, int16_t, int16_t); 151 152static int gbox_ioctl(void *, void *, u_long, void *, int, struct lwp *); 153 154static struct wsdisplay_accessops gbox_accessops = { 155 gbox_ioctl, 156 diofb_mmap, 157 diofb_alloc_screen, 158 diofb_free_screen, 159 diofb_show_screen, 160 NULL, /* load_font */ 161}; 162 163/* 164 * Attachment glue 165 */ 166int 167gbox_intio_match(device_t parent, cfdata_t cf, void *aux) 168{ 169 struct intio_attach_args *ia = aux; 170 struct diofbreg *fbr; 171 172 if (strcmp("fb", ia->ia_modname) != 0) 173 return 0; 174 175 fbr = (struct diofbreg *)ia->ia_addr; 176 177 if (badaddr((void *)fbr)) 178 return 0; 179 180 if (fbr->id == GRFHWID && fbr->fbid == GID_GATORBOX) { 181 return 1; 182 } 183 184 return 0; 185} 186 187void 188gbox_intio_attach(device_t parent, device_t self, void *aux) 189{ 190 struct gbox_softc *sc = device_private(self); 191 struct intio_attach_args *ia = aux; 192 struct diofbreg *fbr; 193 194 sc->sc_dev = self; 195 fbr = (struct diofbreg *)ia->ia_addr; 196 sc->sc_scode = CONSCODE_INTERNAL; 197 198 if (sc->sc_scode == conscode) { 199 sc->sc_fb = &diofb_cn; 200 } else { 201 sc->sc_fb = &sc->sc_fb_store; 202 gbox_reset(sc->sc_fb, sc->sc_scode, fbr); 203 } 204 205 diofb_end_attach(self, &gbox_accessops, sc->sc_fb, 206 sc->sc_scode == conscode, NULL); 207} 208 209int 210gbox_dio_match(device_t parent, cfdata_t cf, void *aux) 211{ 212 struct dio_attach_args *da = aux; 213 214 /* We can not appear in DIO-II space */ 215 if (DIO_ISDIOII(da->da_scode)) 216 return 0; 217 218 if (da->da_id == DIO_DEVICE_ID_FRAMEBUFFER && 219 da->da_secid == DIO_DEVICE_SECID_GATORBOX) 220 return 1; 221 222 return 0; 223} 224 225void 226gbox_dio_attach(device_t parent, device_t self, void *aux) 227{ 228 struct gbox_softc *sc = device_private(self); 229 struct dio_attach_args *da = aux; 230 bus_space_handle_t bsh; 231 struct diofbreg * fbr; 232 233 sc->sc_dev = self; 234 sc->sc_scode = da->da_scode; 235 if (sc->sc_scode == conscode) { 236 fbr = (struct diofbreg *)conaddr; /* already mapped */ 237 sc->sc_fb = &diofb_cn; 238 } else { 239 sc->sc_fb = &sc->sc_fb_store; 240 if (bus_space_map(da->da_bst, da->da_addr, da->da_size, 0, 241 &bsh)) { 242 aprint_error(": can't map framebuffer\n"); 243 return; 244 } 245 fbr = bus_space_vaddr(da->da_bst, bsh); 246 if (gbox_reset(sc->sc_fb, sc->sc_scode, fbr) != 0) { 247 aprint_error(": can't reset framebuffer\n"); 248 return; 249 } 250 } 251 252 diofb_end_attach(self, &gbox_accessops, sc->sc_fb, 253 sc->sc_scode == conscode, NULL); 254} 255 256/* 257 * Initialize hardware and display routines. 258 */ 259 260const uint8_t crtc_init_data[] = { 261 0x29, 0x20, 0x23, 0x04, 0x30, 0x0b, 0x30, 262 0x30, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00 263}; 264 265int 266gbox_reset(struct diofb *fb, int scode, struct diofbreg *fbr) 267{ 268 int rc; 269 u_int i; 270 271 /* XXX don't trust hardware, force defaults */ 272 fb->fbwidth = 1024; 273 fb->fbheight = 1024; 274 fb->dwidth = 1024; 275 fb->dheight = 768; 276 if ((rc = diofb_fbinquire(fb, scode, fbr)) != 0) 277 return rc; 278 279 fb->bmv = gbox_windowmove; 280 gbox_restore(fb); 281 282 /* 283 * Find out how many colors are available by determining 284 * which planes are installed. That is, write all ones to 285 * a frame buffer location, see how many ones are read back. 286 */ 287 if (1 /* fb->planes == 0 */) { 288 volatile uint8_t *fbp; 289 uint8_t save; 290 291 fbp = (uint8_t *)fb->fbkva; 292 save = *fbp; 293 *fbp = 0xff; 294 fb->planemask = *fbp; 295 *fbp = save; 296 297 for (fb->planes = 1; fb->planemask >= (1 << fb->planes); 298 fb->planes++); 299 if (fb->planes > 8) 300 fb->planes = 8; 301 fb->planemask = (1 << fb->planes) - 1; 302 } 303 304 diofb_fbsetup(fb); 305 for (i = 0; i <= fb->planemask; i++) 306 gbox_setcolor(fb, i); 307 308 return 0; 309} 310 311void 312gbox_restore(struct diofb *fb) 313{ 314 volatile struct gboxfb *gb = (struct gboxfb *)fb->regkva; 315 u_int i; 316 317 /* 318 * The minimal info here is from the Gatorbox X driver. 319 */ 320 gb->write_protect = 0x0; 321 gb->regs.interrupt = 0x4; 322 gb->rep_rule = RR_COPY; 323 gb->blink1 = 0xff; 324 gb->blink2 = 0xff; 325 326 /* 327 * Program the 6845. 328 */ 329 for (i = 0; i < sizeof(crtc_init_data); i++) { 330 gb->crtc_address = i; 331 gb->crtc_data = crtc_init_data[i]; 332 } 333 334 tile_mover_waitbusy(gb); 335 336 /* Enable display */ 337 gb->regs.sec_interrupt = 0x01; 338} 339 340int 341gbox_ioctl(void *v, void *vs, u_long cmd, void *data, int flags, struct lwp *l) 342{ 343 struct diofb *fb = v; 344 struct wsdisplay_fbinfo *wdf; 345 u_int i; 346 347 switch (cmd) { 348 case WSDISPLAYIO_GTYPE: 349 *(u_int *)data = WSDISPLAY_TYPE_GBOX; 350 return 0; 351 case WSDISPLAYIO_SMODE: 352 fb->mapmode = *(u_int *)data; 353 if (fb->mapmode == WSDISPLAYIO_MODE_EMUL) { 354 gbox_restore(fb); 355 for (i = 0; i <= fb->planemask; i++) 356 gbox_setcolor(fb, i); 357 } 358 return 0; 359 case WSDISPLAYIO_GINFO: 360 wdf = (void *)data; 361 wdf->width = fb->ri.ri_width; 362 wdf->height = fb->ri.ri_height; 363 wdf->depth = fb->ri.ri_depth; 364 wdf->cmsize = 1 << fb->planes; 365 return 0; 366 case WSDISPLAYIO_LINEBYTES: 367 *(u_int *)data = fb->ri.ri_stride; 368 return 0; 369 case WSDISPLAYIO_GETCMAP: 370 return diofb_getcmap(fb, (struct wsdisplay_cmap *)data); 371 case WSDISPLAYIO_PUTCMAP: 372 return gbox_setcmap(fb, (struct wsdisplay_cmap *)data); 373 case WSDISPLAYIO_GVIDEO: 374 case WSDISPLAYIO_SVIDEO: 375 return EPASSTHROUGH; 376 } 377 378 return EPASSTHROUGH; 379} 380 381void 382gbox_setcolor(struct diofb *fb, u_int index) 383{ 384 volatile struct gboxfb *gb = (struct gboxfb *)fb->regkva; 385 386 gb->creg_select = index; 387 gb->cmap_red = fb->cmap.r[index]; 388 gb->cmap_grn = fb->cmap.g[index]; 389 gb->cmap_blu = fb->cmap.b[index]; 390 gb->cmap_write = !!index; 391 gbcm_waitbusy(gb); 392} 393 394int 395gbox_setcmap(struct diofb *fb, struct wsdisplay_cmap *cm) 396{ 397 uint8_t r[256], g[256], b[256]; 398 u_int index = cm->index, count = cm->count; 399 u_int colcount = 1 << fb->planes; 400 int error; 401 402 if (index >= colcount || count > colcount - index) 403 return EINVAL; 404 405 if ((error = copyin(cm->red, r, count)) != 0) 406 return error; 407 if ((error = copyin(cm->green, g, count)) != 0) 408 return error; 409 if ((error = copyin(cm->blue, b, count)) != 0) 410 return error; 411 412 memcpy(fb->cmap.r + index, r, count); 413 memcpy(fb->cmap.g + index, g, count); 414 memcpy(fb->cmap.b + index, b, count); 415 416 while (count-- != 0) 417 gbox_setcolor(fb, index++); 418 419 return 0; 420} 421 422int 423gbox_windowmove(struct diofb *fb, uint16_t sx, uint16_t sy, 424 uint16_t dx, uint16_t dy, uint16_t cx, uint16_t cy, int16_t rop, 425 int16_t planemask) 426{ 427 volatile struct gboxfb *gb = (struct gboxfb *)fb->regkva; 428 int src, dest; 429 430 if (planemask != 0xff) 431 return EINVAL; 432 433 src = (sy * 1024) + sx; /* upper left corner in pixels */ 434 dest = (dy * 1024) + dx; 435 436 tile_mover_waitbusy(gb); 437 438 gb->width = -(cx / 4); 439 gb->height = -(cy / 4); 440 if (src < dest) 441 gb->rep_rule = MOVE_DOWN_RIGHT | rop; 442 else { 443 gb->rep_rule = MOVE_UP_LEFT | rop; 444 /* 445 * Adjust to top of lower right tile of the block. 446 */ 447 src = src + ((cy - 4) * 1024) + (cx - 4); 448 dest= dest + ((cy - 4) * 1024) + (cx - 4); 449 } 450 *(volatile uint8_t *)(fb->fbkva + dest) = 451 *(volatile uint8_t *)(fb->fbkva + src); 452 453 tile_mover_waitbusy(gb); 454 455 return 0; 456} 457 458/* 459 * Gatorbox console support 460 */ 461int 462gboxcnattach(bus_space_tag_t bst, bus_addr_t addr, int scode) 463{ 464 bus_space_handle_t bsh; 465 void *va; 466 struct diofbreg *fbr; 467 struct diofb *fb = &diofb_cn; 468 int size; 469 470 if (bus_space_map(bst, addr, PAGE_SIZE, 0, &bsh)) 471 return 1; 472 va = bus_space_vaddr(bst, bsh); 473 fbr = va; 474 475 if (badaddr(va) || 476 (fbr->id != GRFHWID) || (fbr->fbid != GID_GATORBOX)) { 477 bus_space_unmap(bst, bsh, PAGE_SIZE); 478 return 1; 479 } 480 481 size = DIO_SIZE(scode, va); 482 483 bus_space_unmap(bst, bsh, PAGE_SIZE); 484 if (bus_space_map(bst, addr, size, 0, &bsh)) 485 return 1; 486 va = bus_space_vaddr(bst, bsh); 487 488 /* 489 * Initialize the framebuffer hardware. 490 */ 491 conscode = scode; 492 conaddr = va; 493 gbox_reset(fb, conscode, (struct diofbreg *)conaddr); 494 495 /* 496 * Initialize the terminal emulator. 497 */ 498 diofb_cnattach(fb); 499 return 0; 500} 501