1 /* $NetBSD: cgtwelve.c,v 1.10 2026/09/22 16:48:56 macallan Exp $ */ 2 3 /*- 4 * Copyright (c) 2010 Michael Lorenz 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* a console driver for the Sun CG12 / Matrox SG3 graphics board */ 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: cgtwelve.c,v 1.10 2026/09/22 16:48:56 macallan Exp $"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/buf.h> 37 #include <sys/device.h> 38 #include <sys/ioctl.h> 39 #include <sys/conf.h> 40 #include <sys/kmem.h> 41 42 #include <sys/bus.h> 43 #include <machine/autoconf.h> 44 45 #include <dev/sbus/sbusvar.h> 46 #include <dev/sun/fbio.h> 47 #include <dev/sun/fbvar.h> 48 49 #include <dev/wscons/wsdisplayvar.h> 50 #include <dev/wscons/wsconsio.h> 51 #include <dev/wsfont/wsfont.h> 52 #include <dev/rasops/rasops.h> 53 54 #include <dev/wscons/wsdisplay_vconsvar.h> 55 56 #include <dev/sbus/cgtwelvereg.h> 57 //#include <dev/ic/bt462reg.h> 58 59 #include "opt_wsemul.h" 60 #include "opt_cgtwelve.h" 61 62 63 struct cgtwelve_softc { 64 device_t sc_dev; 65 bus_space_tag_t sc_tag; 66 bus_space_handle_t sc_regh; 67 bus_addr_t sc_paddr; 68 void *sc_fbaddr; 69 void *sc_shadow; 70 uint8_t *sc_wids; 71 void *sc_int; 72 int sc_width; 73 int sc_height; 74 int sc_stride; 75 int sc_fbsize; 76 int sc_mode; 77 int sc_video; 78 int sc_depth; 79 /* colour map */ 80 uint8_t sc_r[256], sc_g[256], sc_b[256]; 81 uint32_t sc_cursor_mask[32]; 82 uint32_t sc_cursor_image[32]; 83 int sc_cursor_wi, sc_cursor_he; /* real size of sprite */ 84 int sc_cursor_x, sc_cursor_y; 85 int sc_hot_x, sc_hot_y; 86 int sc_cursor_on; 87 struct vcons_data vd; 88 }; 89 90 static int cgtwelve_match(device_t, cfdata_t, void *); 91 static void cgtwelve_attach(device_t, device_t, void *); 92 static int cgtwelve_ioctl(void *, void *, u_long, void *, int, 93 struct lwp*); 94 static paddr_t cgtwelve_mmap(void *, void *, off_t, int); 95 static void cgtwelve_init_screen(void *, struct vcons_screen *, int, 96 long *); 97 static void cgtwelve_write_wid(struct cgtwelve_softc *, int, uint8_t); 98 static void cgtwelve_select_ovl(struct cgtwelve_softc *, int); 99 #define CG12_SEL_OVL 0 100 #define CG12_SEL_ENABLE 1 101 #define CG12_SEL_8BIT 2 102 #define CG12_SEL_24BIT 3 103 #define CG12_SEL_WID 4 104 static void cgtwelve_write_dac(struct cgtwelve_softc *, int, int, int, int); 105 static void cgtwelve_setup(struct cgtwelve_softc *, int); 106 static void cgtwelve_set_video(struct cgtwelve_softc *, int); 107 static int cgtwelve_putcmap(struct cgtwelve_softc *, struct wsdisplay_cmap *); 108 static int cgtwelve_getcmap(struct cgtwelve_softc *, struct wsdisplay_cmap *); 109 static void cgtwelve_move_cursor(struct cgtwelve_softc *, int, int); 110 static int cgtwelve_do_cursor(struct cgtwelve_softc *, 111 struct wsdisplay_cursor *); 112 113 CFATTACH_DECL_NEW(cgtwelve, sizeof(struct cgtwelve_softc), 114 cgtwelve_match, cgtwelve_attach, NULL, NULL); 115 116 struct wsscreen_descr cgtwelve_defscreendesc = { 117 "default", 118 0, 0, 119 NULL, 120 8, 16, 121 0, 122 }; 123 124 static struct vcons_screen cgtwelve_console_screen; 125 126 const struct wsscreen_descr *_cgtwelve_scrlist[] = { 127 &cgtwelve_defscreendesc, 128 /* XXX other formats, graphics screen? */ 129 }; 130 131 struct wsscreen_list cgtwelve_screenlist = { 132 sizeof(_cgtwelve_scrlist) / sizeof(struct wsscreen_descr *), 133 _cgtwelve_scrlist 134 }; 135 136 struct wsdisplay_accessops cgtwelve_accessops = { 137 cgtwelve_ioctl, 138 cgtwelve_mmap, 139 NULL, /* vcons_alloc_screen */ 140 NULL, /* vcons_free_screen */ 141 NULL, /* vcons_show_screen */ 142 NULL, /* load_font */ 143 NULL, /* polls */ 144 NULL, /* scroll */ 145 }; 146 147 extern const u_char rasops_cmap[768]; 148 149 static int 150 cgtwelve_match(device_t parent, cfdata_t cf, void *aux) 151 { 152 struct sbus_attach_args *sa = aux; 153 154 if (strcmp("cgtwelve", sa->sa_name) == 0) 155 return 100; 156 return 0; 157 } 158 159 /* 160 * Attach a display. We need to notice if it is the console, too. 161 */ 162 static void 163 cgtwelve_attach(device_t parent, device_t self, void *args) 164 { 165 struct cgtwelve_softc *sc = device_private(self); 166 struct sbus_attach_args *sa = args; 167 struct wsemuldisplaydev_attach_args aa; 168 struct rasops_info *ri; 169 unsigned long defattr; 170 bus_space_handle_t bh; 171 int node = sa->sa_node; 172 int isconsole; 173 174 aprint_normal("\n"); 175 sc->sc_dev = self; 176 sc->sc_tag = sa->sa_bustag; 177 178 sc->sc_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_slot, sa->sa_offset); 179 180 /* read geometry information from the device tree */ 181 sc->sc_width = prom_getpropint(sa->sa_node, "width", 1152); 182 sc->sc_height = prom_getpropint(sa->sa_node, "height", 900); 183 #ifdef CG12_COLOR 184 sc->sc_stride = sc->sc_width; 185 #else 186 sc->sc_stride = (sc->sc_width + 7) >> 3; 187 #endif 188 sc->sc_fbsize = sc->sc_height * sc->sc_stride; 189 190 sc->sc_fbaddr = (void *)prom_getpropint(sa->sa_node, "address", 0); 191 if (sc->sc_fbaddr == NULL) { 192 if (sbus_bus_map(sa->sa_bustag, 193 sa->sa_slot, 194 sa->sa_offset + CG12_FB_MONO, 195 sc->sc_fbsize, 196 BUS_SPACE_MAP_LINEAR, &bh) != 0) { 197 aprint_error_dev(self, "cannot map framebuffer\n"); 198 return; 199 } 200 sc->sc_fbaddr = bus_space_vaddr(sa->sa_bustag, bh); 201 } 202 203 aprint_normal_dev(self, "%d x %d\n", sc->sc_width, sc->sc_height); 204 205 if (sbus_bus_map(sa->sa_bustag, 206 sa->sa_slot, 207 sa->sa_offset + CG12_OFF_REGISTERS, 208 0xc0000, 0, &sc->sc_regh) != 0) { 209 aprint_error("%s: couldn't map registers\n", 210 device_xname(sc->sc_dev)); 211 return; 212 } 213 214 if (sbus_bus_map(sa->sa_bustag, 215 sa->sa_slot, 216 sa->sa_offset + CG12_OFF_WID, 0x100000, 217 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE, 218 &bh) != 0) { 219 aprint_error("%s: couldn't map WID\n", 220 device_xname(sc->sc_dev)); 221 return; 222 } 223 sc->sc_wids = bus_space_vaddr(sa->sa_bustag, bh); 224 225 if (sbus_bus_map(sa->sa_bustag, 226 sa->sa_slot, 227 sa->sa_offset + CG12_OFF_INTEN, 0x400000, 228 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE, 229 &bh) != 0) { 230 aprint_error("%s: couldn't map colour fb\n", 231 device_xname(sc->sc_dev)); 232 return; 233 } 234 sc->sc_int = bus_space_vaddr(sa->sa_bustag, bh); 235 sc->sc_video = WSDISPLAYIO_VIDEO_ON; 236 sc->sc_depth = 32; 237 #ifdef CG12_COLOR 238 cgtwelve_setup(sc, 8); 239 #else 240 cgtwelve_setup(sc, 1); 241 #endif 242 #ifdef CG12_SHADOW 243 sc->sc_shadow = kmem_alloc(sc->sc_fbsize, KM_SLEEP); 244 #else 245 sc->sc_shadow = NULL; 246 #endif 247 248 isconsole = fb_is_console(node); 249 250 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 251 wsfont_init(); 252 253 vcons_init(&sc->vd, sc, &cgtwelve_defscreendesc, &cgtwelve_accessops); 254 sc->vd.init_screen = cgtwelve_init_screen; 255 256 vcons_init_screen(&sc->vd, &cgtwelve_console_screen, 1, &defattr); 257 cgtwelve_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 258 259 ri = &cgtwelve_console_screen.scr_ri; 260 261 cgtwelve_defscreendesc.nrows = ri->ri_rows; 262 cgtwelve_defscreendesc.ncols = ri->ri_cols; 263 cgtwelve_defscreendesc.textops = &ri->ri_ops; 264 cgtwelve_defscreendesc.capabilities = ri->ri_caps; 265 266 if(isconsole) { 267 wsdisplay_cnattach(&cgtwelve_defscreendesc, ri, 0, 0, defattr); 268 vcons_replay_msgbuf(&cgtwelve_console_screen); 269 } 270 271 aa.console = isconsole; 272 aa.scrdata = &cgtwelve_screenlist; 273 aa.accessops = &cgtwelve_accessops; 274 aa.accesscookie = &sc->vd; 275 276 config_found(self, &aa, wsemuldisplaydevprint, CFARGS_NONE); 277 #ifdef CG12_DEBUG 278 { 279 int i; 280 for (i = 0; i < 0x10; i++) { 281 bus_space_write_4(sc->sc_tag, sc->sc_regh, 282 CG12DAC_ADDR0, (i << 16) | (i << 8) | i); 283 bus_space_write_4(sc->sc_tag, sc->sc_regh, 284 CG12DAC_ADDR1, 0x010101); 285 printf("%02x: %08x\n", i, bus_space_read_4(sc->sc_tag, 286 sc->sc_regh, CG12DAC_CTRL)); 287 } 288 } 289 #endif 290 } 291 292 /* 0 - overlay plane, 1 - enable plane, 2 - 8bit fb, 3 - 24bit fb, 4 - WIDs */ 293 static void 294 cgtwelve_select_ovl(struct cgtwelve_softc *sc, int which) 295 { 296 switch(which) { 297 case 0: 298 bus_space_write_4(sc->sc_tag, sc->sc_regh, 299 CG12DPU_PLN_RDMSK_HOST, CG12_PLN_RD_OVERLAY); 300 bus_space_write_4(sc->sc_tag, sc->sc_regh, 301 CG12DPU_PLN_WRMSK_HOST, CG12_PLN_WR_OVERLAY); 302 bus_space_write_4(sc->sc_tag, sc->sc_regh, 303 CG12DPU_PLN_SL_HOST, CG12_PLN_SL_OVERLAY); 304 bus_space_write_4(sc->sc_tag, sc->sc_regh, 305 CG12APU_HPAGE, CG12_HPAGE_OVERLAY); 306 bus_space_write_4(sc->sc_tag, sc->sc_regh, 307 CG12APU_HACCESS, CG12_HACCESS_OVERLAY); 308 break; 309 case 1: 310 bus_space_write_4(sc->sc_tag, sc->sc_regh, 311 CG12DPU_PLN_RDMSK_HOST, CG12_PLN_RD_ENABLE); 312 bus_space_write_4(sc->sc_tag, sc->sc_regh, 313 CG12DPU_PLN_WRMSK_HOST, CG12_PLN_WR_ENABLE); 314 bus_space_write_4(sc->sc_tag, sc->sc_regh, 315 CG12DPU_PLN_SL_HOST, CG12_PLN_SL_ENABLE); 316 bus_space_write_4(sc->sc_tag, sc->sc_regh, 317 CG12APU_HPAGE, CG12_HPAGE_ENABLE); 318 bus_space_write_4(sc->sc_tag, sc->sc_regh, 319 CG12APU_HACCESS, CG12_HACCESS_ENABLE); 320 break; 321 case 2: 322 bus_space_write_4(sc->sc_tag, sc->sc_regh, 323 CG12DPU_PLN_RDMSK_HOST, CG12_PLN_RD_8BIT); 324 bus_space_write_4(sc->sc_tag, sc->sc_regh, 325 CG12DPU_PLN_WRMSK_HOST, CG12_PLN_WR_8BIT); 326 bus_space_write_4(sc->sc_tag, sc->sc_regh, 327 CG12DPU_PLN_SL_HOST, CG12_PLN_SL_8BIT); 328 bus_space_write_4(sc->sc_tag, sc->sc_regh, 329 CG12APU_HPAGE, CG12_HPAGE_8BIT); 330 bus_space_write_4(sc->sc_tag, sc->sc_regh, 331 CG12APU_HACCESS, CG12_HACCESS_8BIT); 332 break; 333 case 3: 334 bus_space_write_4(sc->sc_tag, sc->sc_regh, 335 CG12DPU_PLN_RDMSK_HOST, CG12_PLN_RD_24BIT); 336 bus_space_write_4(sc->sc_tag, sc->sc_regh, 337 CG12DPU_PLN_WRMSK_HOST, CG12_PLN_WR_24BIT); 338 bus_space_write_4(sc->sc_tag, sc->sc_regh, 339 CG12DPU_PLN_SL_HOST, CG12_PLN_SL_24BIT); 340 bus_space_write_4(sc->sc_tag, sc->sc_regh, 341 CG12APU_HPAGE, CG12_HPAGE_24BIT); 342 bus_space_write_4(sc->sc_tag, sc->sc_regh, 343 CG12APU_HACCESS, CG12_HACCESS_24BIT); 344 break; 345 case 4: 346 bus_space_write_4(sc->sc_tag, sc->sc_regh, 347 CG12DPU_PLN_RDMSK_HOST, CG12_PLN_RD_WID); 348 bus_space_write_4(sc->sc_tag, sc->sc_regh, 349 CG12DPU_PLN_WRMSK_HOST, CG12_PLN_WR_WID); 350 bus_space_write_4(sc->sc_tag, sc->sc_regh, 351 CG12DPU_PLN_SL_HOST, CG12_PLN_SL_WID); 352 bus_space_write_4(sc->sc_tag, sc->sc_regh, 353 CG12APU_HPAGE, CG12_HPAGE_WID); 354 bus_space_write_4(sc->sc_tag, sc->sc_regh, 355 CG12APU_HACCESS, CG12_HACCESS_WID); 356 break; 357 } 358 } 359 360 static void 361 cgtwelve_write_wid(struct cgtwelve_softc *sc, int idx, uint8_t wid) 362 { 363 bus_space_write_4(sc->sc_tag, sc->sc_regh, CG12_WSC_ADDR, idx << 16); 364 bus_space_write_4(sc->sc_tag, sc->sc_regh, CG12_WSC_DATA, 365 ((uint32_t)wid) << 16); 366 } 367 368 static void 369 cgtwelve_write_dac(struct cgtwelve_softc *sc, int idx, int r, int g, int b) 370 { 371 uint32_t lo = (idx & 0xff); 372 uint32_t hi = (idx >> 8) & 0xff; 373 int use_alt = idx & 0x10000; 374 375 lo |= lo << 8 | lo << 16; 376 hi |= hi << 8 | hi << 16; 377 bus_space_write_4(sc->sc_tag, sc->sc_regh, CG12DAC_ADDR0, lo); 378 bus_space_write_4(sc->sc_tag, sc->sc_regh, CG12DAC_ADDR1, hi); 379 bus_space_write_4(sc->sc_tag, sc->sc_regh, 380 use_alt ? CG12DAC_CTRL : CG12DAC_DATA, 381 b << 16 | g << 8 | r); 382 } 383 384 static int 385 cgtwelve_putcmap(struct cgtwelve_softc *sc, struct wsdisplay_cmap *cm) 386 { 387 u_int index = cm->index; 388 u_int count = cm->count; 389 int i, error; 390 391 if (cm->index >= 256 || cm->count > 256 || 392 (cm->index + cm->count) > 256) 393 return EINVAL; 394 error = copyin(cm->red, &sc->sc_r[index], count); 395 if (error) 396 return error; 397 error = copyin(cm->green, &sc->sc_g[index], count); 398 if (error) 399 return error; 400 error = copyin(cm->blue, &sc->sc_b[index], count); 401 if (error) 402 return error; 403 404 if (sc->sc_depth == 8) { 405 for (i = index; i < index + count; i++) { 406 cgtwelve_write_dac(sc, i, sc->sc_r[i], sc->sc_g[i], sc->sc_b[i]); 407 } 408 } 409 return 0; 410 } 411 412 static int 413 cgtwelve_getcmap(struct cgtwelve_softc *sc, struct wsdisplay_cmap *cm) 414 { 415 u_int index = cm->index; 416 u_int count = cm->count; 417 int error; 418 419 if (index >= 255 || count > 256 || index + count > 256) 420 return EINVAL; 421 422 423 error = copyout(&sc->sc_r[index], cm->red, count); 424 if (error) 425 return error; 426 error = copyout(&sc->sc_g[index], cm->green, count); 427 if (error) 428 return error; 429 error = copyout(&sc->sc_b[index], cm->blue, count); 430 if (error) 431 return error; 432 433 return 0; 434 } 435 436 static void 437 cgtwelve_setup(struct cgtwelve_softc *sc, int depth) 438 { 439 int i, j; 440 441 /* first let's put some stuff into the WID table */ 442 cgtwelve_write_wid(sc, 0, CG12_WID_8_BIT); 443 cgtwelve_write_wid(sc, 1, CG12_WID_24_BIT); 444 445 /* a linear ramp for the gamma table */ 446 for (i = 0; i < 256; i++) 447 cgtwelve_write_dac(sc, i + 0x100, i, i, i); 448 449 j = 0; 450 /* rasops' ANSI colour map */ 451 for (i = 0; i < 256; i++) { 452 sc->sc_r[i] = rasops_cmap[j]; 453 sc->sc_g[i] = rasops_cmap[j + 1]; 454 sc->sc_g[i] = rasops_cmap[j + 2]; 455 cgtwelve_write_dac(sc, i, 456 rasops_cmap[j], 457 rasops_cmap[j + 1], 458 rasops_cmap[j + 2]); 459 j += 3; 460 } 461 462 switch(depth) { 463 case 1: 464 /* setup the console */ 465 466 /* first, make the overlay all opaque */ 467 cgtwelve_select_ovl(sc, CG12_SEL_ENABLE); 468 memset(sc->sc_fbaddr, 0xff, 0x20000); 469 470 /* now write the right thing into the WID plane */ 471 cgtwelve_select_ovl(sc, CG12_SEL_WID); 472 memset(sc->sc_wids, 0, 0x100000); 473 474 /* now clean the plane */ 475 cgtwelve_select_ovl(sc, CG12_SEL_OVL); 476 memset(sc->sc_fbaddr, 0, 0x20000); 477 break; 478 case 8: 479 /* setup the 8bit fb */ 480 /* 481 * first clean the 8bit fb - for aesthetic reasons do it while 482 * it's still not visible ( we hope... ) 483 */ 484 cgtwelve_select_ovl(sc, CG12_SEL_8BIT); 485 memset(sc->sc_int, 0x00, 0x100000); 486 487 /* now write the right thing into the WID plane */ 488 cgtwelve_select_ovl(sc, CG12_SEL_WID); 489 memset(sc->sc_wids, 0, 0x100000); 490 491 /* hide the overlay */ 492 cgtwelve_select_ovl(sc, CG12_SEL_ENABLE); 493 memset(sc->sc_fbaddr, 0, 0x20000); 494 495 /* now clean the plane */ 496 cgtwelve_select_ovl(sc, CG12_SEL_OVL); 497 memset(sc->sc_fbaddr, 0, 0x20000); 498 499 /* and make sure we can write the 8bit fb */ 500 cgtwelve_select_ovl(sc, CG12_SEL_8BIT); 501 break; 502 case 24: 503 case 32: 504 /* setup the 24bit fb for X */ 505 /* 506 * first clean the 24bit fb - for aesthetic reasons do it while 507 * it's still not visible ( we hope... ) 508 */ 509 cgtwelve_select_ovl(sc, CG12_SEL_24BIT); 510 memset(sc->sc_int, 0x80, 0x400000); 511 512 /* now write the right thing into the WID plane */ 513 cgtwelve_select_ovl(sc, CG12_SEL_WID); 514 memset(sc->sc_wids, 1, 0x100000); 515 516 /* hide the overlay */ 517 cgtwelve_select_ovl(sc, CG12_SEL_ENABLE); 518 memset(sc->sc_fbaddr, 0, 0x20000); 519 520 /* now clean the plane */ 521 cgtwelve_select_ovl(sc, CG12_SEL_OVL); 522 memset(sc->sc_fbaddr, 0, 0x20000); 523 524 /* and make sure we can write the 24bit fb */ 525 cgtwelve_select_ovl(sc, CG12_SEL_24BIT); 526 break; 527 } 528 } 529 530 static void 531 cgtwelve_set_video(struct cgtwelve_softc *sc, int on) 532 { 533 uint32_t reg; 534 if (on == sc->sc_video) return; 535 on = on == 0 ? WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 536 reg = bus_space_read_4(sc->sc_tag, sc->sc_regh, CG12APU_VSG_CTL); 537 reg &= ~CG12APU_VIDEO_ENABLE; 538 if (on) reg |= CG12APU_VIDEO_ENABLE; 539 bus_space_write_4(sc->sc_tag, sc->sc_regh, CG12APU_VSG_CTL, reg); 540 sc->sc_video = on; 541 } 542 543 static void 544 cgtwelve_init_screen(void *cookie, struct vcons_screen *scr, 545 int existing, long *defattr) 546 { 547 struct cgtwelve_softc *sc = cookie; 548 struct rasops_info *ri = &scr->scr_ri; 549 550 #ifdef CG12_COLOR 551 ri->ri_depth = 8; 552 #else 553 ri->ri_depth = 1; 554 #endif 555 ri->ri_width = sc->sc_width; 556 ri->ri_height = sc->sc_height; 557 ri->ri_stride = sc->sc_stride; 558 ri->ri_flg = RI_CENTER; 559 560 if (sc->sc_shadow == NULL) { 561 #ifdef CG12_COLOR 562 ri->ri_bits = sc->sc_int; 563 #else 564 ri->ri_bits = sc->sc_fbaddr; 565 #endif 566 scr->scr_flags |= VCONS_DONT_READ; 567 } else { 568 #ifdef CG12_COLOR 569 ri->ri_hwbits = sc->sc_int; 570 #else 571 ri->ri_hwbits = sc->sc_fbaddr; 572 #endif 573 ri->ri_bits = sc->sc_shadow; 574 } 575 576 rasops_init(ri, 0, 0); 577 #ifdef CG12_COLOR 578 ri->ri_caps = WSSCREEN_REVERSE | WSSCREEN_WSCOLORS; 579 #else 580 ri->ri_caps = WSSCREEN_REVERSE; 581 #endif 582 rasops_reconfig(ri, ri->ri_height / ri->ri_font->fontheight, 583 ri->ri_width / ri->ri_font->fontwidth); 584 } 585 586 static int 587 cgtwelve_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 588 struct lwp *l) 589 { 590 struct vcons_data *vd = v; 591 struct cgtwelve_softc *sc = vd->cookie; 592 struct wsdisplay_fbinfo *wdf; 593 struct vcons_screen *ms = vd->active; 594 595 switch (cmd) { 596 case WSDISPLAYIO_GTYPE: 597 *(u_int *)data = WSDISPLAY_TYPE_SUNCG12; 598 return 0; 599 600 case WSDISPLAYIO_GINFO: 601 wdf = (void *)data; 602 wdf->height = sc->sc_height; 603 wdf->width = sc->sc_width; 604 wdf->depth = sc->sc_depth; 605 wdf->cmsize = 256; 606 return 0; 607 608 case FBIOGVIDEO: 609 case WSDISPLAYIO_GVIDEO: 610 *(int *)data = sc->sc_video; 611 return 0; 612 613 case WSDISPLAYIO_SVIDEO: 614 case FBIOSVIDEO: 615 cgtwelve_set_video(sc, *(int *)data); 616 return 0; 617 618 case WSDISPLAYIO_GETCMAP: 619 return cgtwelve_getcmap(sc, 620 (struct wsdisplay_cmap *)data); 621 622 case WSDISPLAYIO_PUTCMAP: 623 return cgtwelve_putcmap(sc, 624 (struct wsdisplay_cmap *)data); 625 626 case WSDISPLAYIO_LINEBYTES: 627 { 628 int *ret = (int *)data; 629 if (sc->sc_depth == 32) { 630 *ret = sc->sc_width << 2; 631 } else 632 *ret = sc->sc_width; 633 } 634 return 0; 635 636 case WSDISPLAYIO_SMODE: 637 { 638 int new_mode = *(int*)data; 639 if (new_mode != sc->sc_mode) 640 { 641 sc->sc_mode = new_mode; 642 if (new_mode == WSDISPLAYIO_MODE_EMUL) 643 { 644 #ifdef CG12_COLOR 645 cgtwelve_setup(sc, 8); 646 #else 647 cgtwelve_setup(sc, 1); 648 #endif 649 vcons_redraw_screen(ms); 650 } else { 651 cgtwelve_setup(sc, sc->sc_depth); 652 } 653 } 654 } 655 return 0; 656 657 case WSDISPLAYIO_GCURPOS: 658 { 659 struct wsdisplay_curpos *cp = (void *)data; 660 661 cp->x = sc->sc_cursor_x; 662 cp->y = sc->sc_cursor_y; 663 } 664 return 0; 665 666 case WSDISPLAYIO_SCURPOS: 667 { 668 struct wsdisplay_curpos *cp = (void *)data; 669 670 cgtwelve_move_cursor(sc, cp->x, cp->y); 671 } 672 return 0; 673 674 case WSDISPLAYIO_GCURMAX: 675 { 676 struct wsdisplay_curpos *cp = (void *)data; 677 678 cp->x = 32; 679 cp->y = 32; 680 } 681 return 0; 682 683 case WSDISPLAYIO_SCURSOR: 684 { 685 struct wsdisplay_cursor *cursor = (void *)data; 686 687 return cgtwelve_do_cursor(sc, cursor); 688 } 689 690 case WSDISPLAYIO_SET_DEPTH: 691 { 692 int new_depth = *(int*)data; 693 694 if ((new_depth == 8) || (new_depth == 32)) { 695 sc->sc_depth = new_depth; 696 return 0; 697 } 698 return EINVAL; 699 } 700 701 case WSDISPLAYIO_GET_FBINFO: 702 { 703 struct wsdisplayio_fbinfo *fbi = data; 704 705 if (sc->sc_depth == 8) { 706 fbi->fbi_stride = sc->sc_width; 707 fbi->fbi_fbsize = 1024 * 1024; 708 fbi->fbi_bitsperpixel = 8; 709 fbi->fbi_pixeltype = WSFB_CI; 710 } else { 711 fbi->fbi_stride = sc->sc_width * 4; 712 fbi->fbi_fbsize = 4 * 1024 * 1024; 713 fbi->fbi_bitsperpixel = 32; 714 fbi->fbi_pixeltype = WSFB_RGB; 715 } 716 fbi->fbi_width = sc->sc_width; 717 fbi->fbi_height = sc->sc_height; 718 fbi->fbi_subtype.fbi_rgbmasks.red_offset = 0; 719 fbi->fbi_subtype.fbi_rgbmasks.red_size = 8; 720 fbi->fbi_subtype.fbi_rgbmasks.green_offset = 8; 721 fbi->fbi_subtype.fbi_rgbmasks.green_size = 8; 722 fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 16; 723 fbi->fbi_subtype.fbi_rgbmasks.blue_size = 8; 724 fbi->fbi_subtype.fbi_rgbmasks.alpha_offset = 0; 725 fbi->fbi_subtype.fbi_rgbmasks.alpha_size = 0; 726 return 0; 727 } 728 } 729 730 return EPASSTHROUGH; 731 } 732 733 static paddr_t 734 cgtwelve_mmap(void *v, void *vs, off_t offset, int prot) 735 { 736 struct vcons_data *vd = v; 737 struct cgtwelve_softc *sc = vd->cookie; 738 739 /* regular fb mapping at 0 */ 740 if ((offset >= 0) && (offset < 0x400000)) { 741 return bus_space_mmap(sc->sc_tag, sc->sc_paddr + CG12_OFF_INTEN, 742 offset, prot, BUS_SPACE_MAP_LINEAR); 743 } 744 745 return -1; 746 } 747 748 static void 749 cgtwelve_move_cursor(struct cgtwelve_softc *sc, int x, int y) 750 { 751 int start, end, wi, he; 752 uint8_t *saddr; 753 uint32_t *addr; 754 int monostride = sc->sc_width >> 5; 755 int shift, i; 756 757 /* first we clear the old image */ 758 start = sc->sc_cursor_x & ~0x1f; 759 end = (sc->sc_cursor_x + sc->sc_cursor_wi - 1) & ~0x1f; 760 /* if start == end the whole thing fits in one 32bit word */ 761 cgtwelve_select_ovl(sc, CG12_SEL_ENABLE); 762 wi = sc->sc_width - sc->sc_cursor_x - 1; 763 if (wi > sc->sc_cursor_wi) wi = sc->sc_cursor_wi; 764 if (wi < 1) goto skip; 765 he = sc->sc_height - sc->sc_cursor_y - 1; 766 if (he > sc->sc_cursor_he) he = sc->sc_cursor_he; 767 if (he < 1) goto skip; 768 saddr = (uint8_t *)sc->sc_fbaddr + (start >> 3); 769 if (start == end) { 770 addr = (uint32_t *)saddr + monostride * sc->sc_cursor_y; 771 for (i = 0; i < he; i++) { 772 *addr = 0; 773 addr += monostride; 774 } 775 } else { 776 addr = (uint32_t *)saddr + monostride * sc->sc_cursor_y; 777 for (i = 0; i < he; i++) { 778 addr[0] = 0; 779 addr[1] = 0; 780 addr += monostride; 781 } 782 } 783 /* clear it in the image plane as well */ 784 cgtwelve_select_ovl(sc, CG12_SEL_OVL); 785 if (start == end) { 786 addr = (uint32_t *)saddr + monostride * sc->sc_cursor_y; 787 for (i = 0; i < he; i++) { 788 *addr = 0; 789 addr += monostride; 790 } 791 } else { 792 addr = (uint32_t *)saddr + monostride * sc->sc_cursor_y; 793 for (i = 0; i < he; i++) { 794 addr[0] = 0; 795 addr[1] = 0; 796 addr += monostride; 797 } 798 } 799 skip: 800 /* now draw the cursor at the new position, mask first */ 801 cgtwelve_select_ovl(sc, CG12_SEL_ENABLE); 802 wi = sc->sc_width - x - 1; 803 if (wi > sc->sc_cursor_wi) wi = sc->sc_cursor_wi; 804 if (wi < 1) goto out; 805 he = sc->sc_height - y - 1; 806 if (he > sc->sc_cursor_he) he = sc->sc_cursor_he; 807 if (he < 1) goto out; 808 809 start = x & ~0x1f; 810 end = (x + wi - 1) & ~0x1f; 811 saddr = (uint8_t *)sc->sc_fbaddr + (start >> 3); 812 shift = x & 0x1f; 813 if ((shift + wi) < 32) { 814 /* fits in a single 32bit word */ 815 addr = (uint32_t *)saddr + monostride * y; 816 for (i = 0; i < he; i++) { 817 *addr = sc->sc_cursor_mask[i] >> shift; 818 addr += monostride; 819 } 820 } else { 821 /* split into two 32bit words */ 822 addr = (uint32_t *)saddr + monostride * y; 823 for (i = 0; i < he; i++) { 824 addr[0] = sc->sc_cursor_mask[i] >> shift; 825 addr[1] = sc->sc_cursor_mask[i] << (32 - shift); 826 addr += monostride; 827 } 828 } 829 /* ... and now the image */ 830 cgtwelve_select_ovl(sc, CG12_SEL_OVL); 831 if ((shift + wi) < 32) { 832 /* fits in a single 32bit word */ 833 addr = (uint32_t *)saddr + monostride * y; 834 for (i = 0; i < he; i++) { 835 *addr = sc->sc_cursor_image[i] >> shift; 836 addr += monostride; 837 } 838 } else { 839 /* split into two 32bit words */ 840 addr = (uint32_t *)saddr + monostride * y; 841 for (i = 0; i < he; i++) { 842 addr[0] = sc->sc_cursor_image[i] >> shift; 843 addr[1] = sc->sc_cursor_image[i] << (32 - shift); 844 addr += monostride; 845 } 846 } 847 out: 848 sc->sc_cursor_x = x; 849 sc->sc_cursor_y = y; 850 cgtwelve_select_ovl(sc, sc->sc_depth == 8 ? CG12_SEL_8BIT : CG12_SEL_24BIT); 851 } 852 853 static int 854 cgtwelve_do_cursor(struct cgtwelve_softc *sc, 855 struct wsdisplay_cursor *cur) 856 { 857 if (cur->which & WSDISPLAY_CURSOR_DOCUR) { 858 859 if (cur->enable != sc->sc_cursor_on) { 860 /* clear or draw as needed */ 861 sc->sc_cursor_on = cur->enable; 862 } 863 } 864 if (cur->which & WSDISPLAY_CURSOR_DOHOT) { 865 866 sc->sc_hot_x = cur->hot.x; 867 sc->sc_hot_y = cur->hot.y; 868 cur->which |= WSDISPLAY_CURSOR_DOPOS; 869 } 870 if (cur->which & WSDISPLAY_CURSOR_DOPOS) { 871 872 cgtwelve_move_cursor(sc, cur->pos.x, cur->pos.y); 873 } 874 if (cur->which & WSDISPLAY_CURSOR_DOCMAP) { 875 int i; 876 877 if ((cur->cmap.index > 1) || (cur->cmap.count > 2) || 878 (cur->cmap.index + cur->cmap.count > 2)) 879 return EINVAL; 880 881 for (i = 0; i < uimin(cur->cmap.count, 2); i++) { 882 /* overlay colours live in alt space at 0x100 */ 883 cgtwelve_write_dac(sc, ((i << 1) + cur->cmap.index + 1) | 0x10100, cur->cmap.red[i], 884 cur->cmap.green[i], cur->cmap.blue[i]); 885 } 886 } 887 if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) { 888 uint32_t buffer[32], latch, tmp; 889 int i, s; 890 891 sc->sc_cursor_wi = 0; 892 sc->sc_cursor_he = 0; 893 copyin(cur->mask, buffer, 128); 894 for (i = 0; i < 32; i++) { 895 latch = 0; 896 tmp = buffer[i] & 0x80808080; 897 latch |= tmp >> 7; 898 tmp = buffer[i] & 0x40404040; 899 latch |= tmp >> 5; 900 tmp = buffer[i] & 0x20202020; 901 latch |= tmp >> 3; 902 tmp = buffer[i] & 0x10101010; 903 latch |= tmp >> 1; 904 tmp = buffer[i] & 0x08080808; 905 latch |= tmp << 1; 906 tmp = buffer[i] & 0x04040404; 907 latch |= tmp << 3; 908 tmp = buffer[i] & 0x02020202; 909 latch |= tmp << 5; 910 tmp = buffer[i] & 0x01010101; 911 latch |= tmp << 7; 912 sc->sc_cursor_mask[i] = latch; 913 /* measure sprite size to optimize drawing */ 914 if (latch != 0) { 915 sc->sc_cursor_he = i + 1; 916 s = ffs(latch); 917 s = 33 - s; 918 if (s > sc->sc_cursor_wi) sc->sc_cursor_wi = s; 919 } 920 } 921 922 copyin(cur->image, buffer, 128); 923 for (i = 0; i < 32; i++) { 924 latch = 0; 925 tmp = buffer[i] & 0x80808080; 926 latch |= tmp >> 7; 927 tmp = buffer[i] & 0x40404040; 928 latch |= tmp >> 5; 929 tmp = buffer[i] & 0x20202020; 930 latch |= tmp >> 3; 931 tmp = buffer[i] & 0x10101010; 932 latch |= tmp >> 1; 933 tmp = buffer[i] & 0x08080808; 934 latch |= tmp << 1; 935 tmp = buffer[i] & 0x04040404; 936 latch |= tmp << 3; 937 tmp = buffer[i] & 0x02020202; 938 latch |= tmp << 5; 939 tmp = buffer[i] & 0x01010101; 940 latch |= tmp << 7; 941 sc->sc_cursor_image[i] = latch; 942 } 943 } 944 return 0; 945 } 946 947