1 /* $NetBSD: stic.c,v 1.5 2000/12/17 14:46:43 ad Exp $ */ 2 3 /*- 4 * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Copyright (c) 1998, 1999 Tohru Nishimura. All rights reserved. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. All advertising materials mentioning features or use of this software 51 * must display the following acknowledgement: 52 * This product includes software developed by Tohru Nishimura 53 * for the NetBSD Project. 54 * 4. The name of the author may not be used to endorse or promote products 55 * derived from this software without specific prior written permission 56 * 57 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 58 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 59 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 60 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 61 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 62 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 63 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 64 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 65 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 66 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 67 */ 68 69 /* 70 * Driver for the DEC PixelStamp interface chip (STIC). 71 * 72 * XXX The bt459 interface shouldn't be replicated here. 73 */ 74 75 #include <sys/param.h> 76 #include <sys/systm.h> 77 #include <sys/kernel.h> 78 #include <sys/device.h> 79 #include <sys/malloc.h> 80 #include <sys/buf.h> 81 #include <sys/ioctl.h> 82 #include <sys/callout.h> 83 84 #include <uvm/uvm_extern.h> 85 86 #if defined(pmax) 87 #include <mips/cpuregs.h> 88 #elif defined(alpha) 89 #include <alpha/alpha_cpu.h> 90 #endif 91 92 #include <machine/bus.h> 93 #include <machine/intr.h> 94 95 #include <dev/wscons/wsconsio.h> 96 #include <dev/wscons/wsdisplayvar.h> 97 98 #include <dev/wsfont/wsfont.h> 99 100 #include <dev/ic/bt459reg.h> 101 102 #include <dev/tc/tcvar.h> 103 #include <dev/tc/sticreg.h> 104 #include <dev/tc/sticvar.h> 105 106 #define DUPBYTE0(x) ((((x)&0xff)<<16) | (((x)&0xff)<<8) | ((x)&0xff)) 107 #define DUPBYTE1(x) ((((x)<<8)&0xff0000) | ((x)&0xff00) | (((x)>>8)&0xff)) 108 #define DUPBYTE2(x) (((x)&0xff0000) | (((x)>>8)&0xff00) | (((x)>>16)&0xff)) 109 110 #define PACK(p, o) ((p)[(o)] | ((p)[(o)+1] << 16)) 111 112 #if defined(pmax) 113 #define machine_btop(x) mips_btop(x) 114 #elif defined(alpha) 115 #define machine_btop(x) alpha_btop(x) 116 #endif 117 118 /* 119 * N.B., Bt459 registers are 8bit width. Some of TC framebuffers have 120 * obscure register layout such as 2nd and 3rd Bt459 registers are 121 * adjacent each other in a word, i.e., 122 * struct bt459triplet { 123 * struct { 124 * u_int8_t u0; 125 * u_int8_t u1; 126 * u_int8_t u2; 127 * unsigned :8; 128 * } bt_lo; 129 * struct { 130 * 131 * Although HX has single Bt459, 32bit R/W can be done w/o any trouble. 132 * struct bt459reg { 133 * u_int32_t bt_lo; 134 * u_int32_t bt_hi; 135 * u_int32_t bt_reg; 136 * u_int32_t bt_cmap; 137 * }; 138 * 139 */ 140 141 /* Bt459 hardware registers */ 142 #define bt_lo 0 143 #define bt_hi 1 144 #define bt_reg 2 145 #define bt_cmap 3 146 147 #define REG(base, index) *((u_int32_t *)(base) + (index)) 148 #define SELECT(vdac, regno) do { \ 149 REG(vdac, bt_lo) = DUPBYTE0(regno); \ 150 REG(vdac, bt_hi) = DUPBYTE1(regno); \ 151 tc_wmb(); \ 152 } while (0) 153 154 static int sticioctl(void *, u_long, caddr_t, int, struct proc *); 155 static paddr_t sticmmap(void *, off_t, int); 156 static int stic_alloc_screen(void *, const struct wsscreen_descr *, 157 void **, int *, int *, long *); 158 static void stic_free_screen(void *, void *); 159 static int stic_show_screen(void *, void *, int, 160 void (*) (void *, int, int), void *); 161 static void stic_do_switch(void *); 162 static int stic_setup_backing(struct stic_info *, struct stic_screen *, int); 163 static void stic_setup_cmap(struct stic_screen *); 164 static void stic_setup_cursor(struct stic_info *, struct stic_screen *); 165 166 static int stic_get_cmap(struct stic_screen *, struct wsdisplay_cmap *); 167 static int stic_set_cmap(struct stic_screen *, struct wsdisplay_cmap *); 168 static int stic_set_cursor(struct stic_screen *, struct wsdisplay_cursor *); 169 static int stic_get_cursor(struct stic_screen *, struct wsdisplay_cursor *); 170 static void stic_set_curpos(struct stic_screen *, struct wsdisplay_curpos *); 171 static void stic_set_hwcurpos(struct stic_screen *); 172 173 static void stic_cursor(void *, int, int, int); 174 static void stic_copycols(void *, int, int, int, int); 175 static void stic_copyrows(void *, int, int, int); 176 static void stic_erasecols(void *, int, int, int, long); 177 static void stic_eraserows(void *, int, int, long); 178 static int stic_mapchar(void *, int, u_int *); 179 static void stic_putchar(void *, int, int, u_int, long); 180 static int stic_alloc_attr(void *, int, int, int, long *); 181 182 /* Colormap for wscons, matching WSCOL_*. Upper 8 are high-intensity. */ 183 static const u_int8_t stic_cmap[16*3] = { 184 0x00, 0x00, 0x00, /* black */ 185 0x7f, 0x00, 0x00, /* red */ 186 0x00, 0x7f, 0x00, /* green */ 187 0x7f, 0x7f, 0x00, /* brown */ 188 0x00, 0x00, 0x7f, /* blue */ 189 0x7f, 0x00, 0x7f, /* magenta */ 190 0x00, 0x7f, 0x7f, /* cyan */ 191 0xc7, 0xc7, 0xc7, /* white */ 192 193 0x7f, 0x7f, 0x7f, /* black */ 194 0xff, 0x00, 0x00, /* red */ 195 0x00, 0xff, 0x00, /* green */ 196 0xff, 0xff, 0x00, /* brown */ 197 0x00, 0x00, 0xff, /* blue */ 198 0xff, 0x00, 0xff, /* magenta */ 199 0x00, 0xff, 0xff, /* cyan */ 200 0xff, 0xff, 0xff, /* white */ 201 }; 202 203 /* 204 * Compose 2 bit/pixel cursor image. Bit order will be reversed. 205 * M M M M I I I I M I M I M I M I 206 * [ before ] [ after ] 207 * 3 2 1 0 3 2 1 0 0 0 1 1 2 2 3 3 208 * 7 6 5 4 7 6 5 4 4 4 5 5 6 6 7 7 209 */ 210 static const u_int8_t shuffle[256] = { 211 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54, 212 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55, 213 0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4, 214 0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5, 215 0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74, 216 0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75, 217 0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4, 218 0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5, 219 0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c, 220 0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d, 221 0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc, 222 0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd, 223 0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c, 224 0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d, 225 0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc, 226 0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd, 227 0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56, 228 0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57, 229 0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6, 230 0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7, 231 0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76, 232 0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77, 233 0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6, 234 0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7, 235 0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e, 236 0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f, 237 0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde, 238 0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf, 239 0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e, 240 0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f, 241 0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe, 242 0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff, 243 }; 244 245 static const struct wsdisplay_accessops stic_accessops = { 246 sticioctl, 247 sticmmap, 248 stic_alloc_screen, 249 stic_free_screen, 250 stic_show_screen, 251 0 /* load_font */ 252 }; 253 254 static const struct wsdisplay_emulops stic_emulops = { 255 stic_cursor, 256 stic_mapchar, 257 stic_putchar, 258 stic_copycols, 259 stic_erasecols, 260 stic_copyrows, 261 stic_eraserows, 262 stic_alloc_attr 263 }; 264 265 static struct wsscreen_descr stic_stdscreen = { 266 "std", 267 0, 0, 268 &stic_emulops, 269 0, 0, 270 WSATTR_REVERSE | WSATTR_HILIT | WSATTR_WSCOLORS 271 }; 272 273 static const struct wsscreen_descr *_stic_scrlist[] = { 274 &stic_stdscreen, 275 }; 276 277 static const struct wsscreen_list stic_screenlist = { 278 sizeof(_stic_scrlist) / sizeof(struct wsscreen_descr *), _stic_scrlist 279 }; 280 281 struct stic_info stic_consinfo; 282 static struct stic_screen stic_consscr; 283 284 void 285 stic_init(struct stic_info *si) 286 { 287 volatile u_int32_t *vdac; 288 int i, cookie; 289 290 /* Reset the STIC & stamp(s). */ 291 stic_reset(si); 292 vdac = si->si_vdac; 293 294 /* Hit it... */ 295 SELECT(vdac, BT459_IREG_COMMAND_0); 296 REG(vdac, bt_reg) = 0x00c0c0c0; tc_syncbus(); 297 298 /* Now reset the VDAC. */ 299 *si->si_vdac_reset = 0; 300 tc_syncbus(); 301 DELAY(1000); 302 303 /* Finish the initalization. */ 304 SELECT(vdac, BT459_IREG_COMMAND_1); 305 REG(vdac, bt_reg) = 0x00000000; tc_wmb(); 306 REG(vdac, bt_reg) = 0x00c2c2c2; tc_wmb(); 307 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb(); 308 309 for (i = 0; i < 7; i++) { 310 REG(vdac, bt_reg) = 0x00000000; 311 tc_wmb(); 312 } 313 314 /* Set cursor colormap. */ 315 SELECT(vdac, BT459_IREG_CCOLOR_1); 316 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb(); 317 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb(); 318 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb(); 319 REG(vdac, bt_reg) = 0x00000000; tc_wmb(); 320 REG(vdac, bt_reg) = 0x00000000; tc_wmb(); 321 REG(vdac, bt_reg) = 0x00000000; tc_wmb(); 322 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb(); 323 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb(); 324 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb(); 325 326 si->si_vdacctl = STIC_VDAC_BLINK; 327 328 /* Get a font and set up screen metrics. */ 329 wsfont_init(); 330 cookie = wsfont_find(NULL, 0, 0, 0); 331 332 if (wsfont_lock(cookie, &si->si_font, 333 WSDISPLAY_FONTORDER_R2L, WSDISPLAY_FONTORDER_L2R) <= 0) 334 panic("stic_init: couldn't lock font\n"); 335 336 si->si_fonth = si->si_font->fontheight; 337 si->si_fontw = si->si_font->fontwidth; 338 si->si_consh = 1024 / si->si_fonth; 339 si->si_consw = (1280 / si->si_fontw) & ~1; 340 stic_stdscreen.nrows = si->si_consh; 341 stic_stdscreen.ncols = si->si_consw; 342 343 #ifdef DIAGNOSTIC 344 if ((u_int)si->si_fonth > 32 || (u_int)si->si_fontw > 16) 345 panic("stic_init: unusable font"); 346 #endif 347 } 348 349 void 350 stic_reset(struct stic_info *si) 351 { 352 int modtype, xconfig, yconfig, config; 353 volatile struct stic_regs *sr; 354 355 sr = si->si_stic; 356 357 /* 358 * Initialize the interface chip registers. 359 */ 360 sr->sr_sticsr = 0x00000030; /* Get the STIC's attention. */ 361 tc_syncbus(); 362 DELAY(4000); /* wait 4ms for STIC to respond. */ 363 sr->sr_sticsr = 0x00000000; /* Hit the STIC's csr again... */ 364 tc_syncbus(); 365 sr->sr_buscsr = 0xffffffff; /* and bash its bus-acess csr. */ 366 tc_syncbus(); /* Blam! */ 367 DELAY(20000); /* wait until the stic recovers... */ 368 369 modtype = sr->sr_modcl; 370 xconfig = (modtype & 0x800) >> 11; 371 yconfig = (modtype & 0x600) >> 9; 372 config = (yconfig << 1) | xconfig; 373 si->si_stampw = (xconfig ? 5 : 4); 374 si->si_stamph = (1 << yconfig); 375 #ifdef notyet 376 si->si_option = (char)((modtype >> 12) & 3); 377 #endif 378 379 /* First PixelStamp */ 380 si->si_stamp[0x000b0] = config; 381 si->si_stamp[0x000b4] = 0x0; 382 383 /* Second PixelStamp */ 384 if (yconfig > 0) { 385 si->si_stamp[0x100b0] = config | 8; 386 si->si_stamp[0x100b4] = 0; 387 } 388 389 /* 390 * Initialize STIC video registers. 391 */ 392 sr->sr_vblank = (1024 << 16) | 1063; 393 sr->sr_vsync = (1027 << 16) | 1030; 394 sr->sr_hblank = (255 << 16) | 340; 395 sr->sr_hsync2 = 245; 396 sr->sr_hsync = (261 << 16) | 293; 397 sr->sr_ipdvint = STIC_INT_CLR | STIC_INT_WE; 398 sr->sr_sticsr = 8; 399 tc_wmb(); 400 } 401 402 void 403 stic_attach(struct device *self, struct stic_info *si, int console) 404 { 405 struct wsemuldisplaydev_attach_args waa; 406 407 callout_init(&si->si_switch_callout); 408 409 /* 410 * Allocate backing for the console. We could trawl back through 411 * msgbuf and and fill the backing, but it's not worth the hassle. 412 * We could also grab backing using pmap_steal_memory() early on, 413 * but that's a little ugly. 414 */ 415 if (console) 416 stic_setup_backing(si, &stic_consscr, M_NOWAIT); 417 418 waa.console = console; 419 waa.scrdata = &stic_screenlist; 420 waa.accessops = &stic_accessops; 421 waa.accesscookie = si; 422 config_found(self, &waa, wsemuldisplaydevprint); 423 } 424 425 void 426 stic_cnattach(struct stic_info *si) 427 { 428 struct stic_screen *ss; 429 long defattr; 430 int i; 431 432 ss = &stic_consscr; 433 si->si_curscreen = ss; 434 ss->ss_flags = SS_ALLOCED | SS_ACTIVE | SS_CURENB | SS_CURENB_CHANGED; 435 ss->ss_si = si; 436 437 stic_setup_cursor(si, ss); 438 stic_setup_cmap(ss); 439 stic_flush(si); 440 stic_eraserows(ss, 0, si->si_consh, 0); 441 442 stic_alloc_attr(ss, 0, 0, 0, &defattr); 443 wsdisplay_cnattach(&stic_stdscreen, ss, 0, 0, defattr); 444 } 445 446 static void 447 stic_setup_cursor(struct stic_info *si, struct stic_screen *ss) 448 { 449 u_int8_t *ip, *mp; 450 int r, c, o, b; 451 452 ip = (u_int8_t *)ss->ss_cursor.cc_image; 453 mp = ip + (sizeof(ss->ss_cursor.cc_image) >> 1); 454 memset(ip, 0, sizeof(ss->ss_cursor.cc_image)); 455 456 for (r = 0; r < si->si_fonth; r++) { 457 for (c = 0; c < si->si_fontw; c++) { 458 o = c >> 3; 459 b = 1 << (c & 7); 460 ip[o] |= b; 461 mp[o] |= b; 462 } 463 464 ip += 16; 465 mp += 16; 466 } 467 468 ss->ss_cursor.cc_size.x = 64; 469 ss->ss_cursor.cc_size.y = si->si_fonth; 470 ss->ss_cursor.cc_hot.x = 0; 471 ss->ss_cursor.cc_hot.y = 0; 472 473 ss->ss_cursor.cc_color[0] = 0xff; 474 ss->ss_cursor.cc_color[2] = 0xff; 475 ss->ss_cursor.cc_color[4] = 0xff; 476 ss->ss_cursor.cc_color[1] = 0x00; 477 ss->ss_cursor.cc_color[3] = 0x00; 478 ss->ss_cursor.cc_color[5] = 0x00; 479 480 ss->ss_flags |= SS_CURSHAPE_CHANGED | SS_CURCMAP_CHANGED; 481 } 482 483 static int 484 sticioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 485 { 486 struct stic_info *si; 487 struct stic_screen *ss; 488 struct stic_xinfo *sxi; 489 490 ss = (struct stic_screen *)v; 491 si = ss->ss_si; 492 493 switch (cmd) { 494 case WSDISPLAYIO_GTYPE: 495 *(u_int *)data = si->si_disptype; 496 return (0); 497 498 case WSDISPLAYIO_GINFO: 499 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 500 wsd_fbip->height = 1024; 501 wsd_fbip->width = 1280; 502 wsd_fbip->depth = si->si_depth; 503 wsd_fbip->cmsize = CMAP_SIZE; 504 #undef fbt 505 return (0); 506 507 case WSDISPLAYIO_GETCMAP: 508 return (stic_get_cmap(ss, (struct wsdisplay_cmap *)data)); 509 510 case WSDISPLAYIO_PUTCMAP: 511 return (stic_set_cmap(ss, (struct wsdisplay_cmap *)data)); 512 513 case WSDISPLAYIO_SVIDEO: 514 #if 0 /* XXX later */ 515 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF; 516 if ((si->si_blanked == 0) ^ turnoff) 517 si->si_blanked = turnoff; 518 #endif 519 return (0); 520 521 case WSDISPLAYIO_GVIDEO: 522 #if 0 /* XXX later */ 523 *(u_int *)data = si->si_blanked ? 524 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 525 #endif 526 return (0); 527 528 case WSDISPLAYIO_GCURPOS: 529 *(struct wsdisplay_curpos *)data = ss->ss_cursor.cc_pos; 530 return (0); 531 532 case WSDISPLAYIO_SCURPOS: 533 stic_set_curpos(ss, (struct wsdisplay_curpos *)data); 534 stic_set_hwcurpos(ss); 535 return (0); 536 537 case WSDISPLAYIO_GCURMAX: 538 ((struct wsdisplay_curpos *)data)->x = 539 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE; 540 return (0); 541 542 case WSDISPLAYIO_GCURSOR: 543 return (stic_get_cursor(ss, (struct wsdisplay_cursor *)data)); 544 545 case WSDISPLAYIO_SCURSOR: 546 return (stic_set_cursor(ss, (struct wsdisplay_cursor *)data)); 547 548 case STICIO_GXINFO: 549 sxi = (struct stic_xinfo *)data; 550 sxi->sxi_stampw = si->si_stampw; 551 sxi->sxi_stamph = si->si_stamph; 552 sxi->sxi_buf_size = si->si_buf_size; 553 sxi->sxi_buf_phys = (u_long)si->si_buf_phys; 554 break; 555 556 case STICIO_SBLINK: 557 if ((int *)data != 0) 558 si->si_vdacctl |= STIC_VDAC_BLINK; 559 else 560 si->si_vdacctl &= ~STIC_VDAC_BLINK; 561 break; 562 563 case STICIO_S24BIT: 564 if ((int *)data != 0) 565 si->si_vdacctl |= STIC_VDAC_24BIT; 566 else 567 si->si_vdacctl &= ~STIC_VDAC_24BIT; 568 break; 569 } 570 571 return (ENOTTY); 572 } 573 574 static paddr_t 575 sticmmap(void *v, off_t offset, int prot) 576 { 577 struct stic_softc *sc; 578 struct stic_xmap sxm; 579 paddr_t pa; 580 581 sc = v; 582 583 if (offset < 0) 584 return ((paddr_t)-1L); 585 586 if (offset < sizeof(sxm.sxm_stic)) { 587 pa = STIC_KSEG_TO_PHYS(si->si_stic); 588 return (machine_btop(pa + pffset)); 589 } 590 offset -= sizeof(sxm.sxm_stic); 591 592 if (offset < sizeof(sxm.sxm_poll)) { 593 pa = STIC_KSEG_TO_PHYS(si->si_poll); 594 return (machine_btop(pa + pffset)); 595 } 596 offset -= sizeof(sxm.sxm_poll); 597 598 if (offset < si->si_buf_size) { 599 pa = STIC_KSEG_TO_PHYS(si->si_buf_phys); 600 return (machine_btop(pa + pffset)); 601 } 602 603 return ((paddr_t)-1L); 604 } 605 606 static int 607 stic_setup_backing(struct stic_info *si, struct stic_screen *ss, int mflag) 608 { 609 int size; 610 611 size = si->si_consw * si->si_consh * sizeof(*ss->ss_backing); 612 if ((ss->ss_backing = malloc(size, M_DEVBUF, mflag)) == NULL) { 613 free(ss, M_DEVBUF); 614 return (ENOMEM); 615 } 616 memset(ss->ss_backing, 0, size); 617 return (0); 618 } 619 620 static void 621 stic_setup_cmap(struct stic_screen *ss) 622 { 623 int i; 624 625 memset(&ss->ss_cmap, 0, sizeof(ss->ss_cmap)); 626 for (i = 0; i < 16; i++) { 627 ss->ss_cmap.r[i] = stic_cmap[i*3 + 0]; 628 ss->ss_cmap.g[i] = stic_cmap[i*3 + 1]; 629 ss->ss_cmap.b[i] = stic_cmap[i*3 + 2]; 630 } 631 632 ss->ss_flags |= SS_CMAP_CHANGED; 633 } 634 635 static int 636 stic_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 637 int *curxp, int *curyp, long *attrp) 638 { 639 struct stic_info *si; 640 struct stic_screen *ss; 641 int i; 642 643 si = (struct stic_info *)v; 644 645 if ((stic_consscr.ss_flags & SS_ALLOCED) == 0) { 646 ss = &stic_consscr; 647 648 if (stic_setup_backing(si, ss, M_WAITOK) != 0) 649 return (ENOMEM); 650 } else { 651 if ((ss = malloc(sizeof(*ss), M_DEVBUF, M_WAITOK)) == NULL) 652 return (ENOMEM); 653 memset(ss, 0, sizeof(*ss)); 654 655 if (stic_setup_backing(si, ss, M_WAITOK) != 0) { 656 free(ss, M_DEVBUF); 657 return (ENOMEM); 658 } 659 } 660 661 ss->ss_si = si; 662 ss->ss_flags |= SS_ALLOCED | SS_CURENB; 663 664 *cookiep = ss; 665 *curxp = 0; 666 *curyp = 0; 667 668 stic_alloc_attr(ss, 0, 0, 0, attrp); 669 stic_setup_cursor(si, ss); 670 stic_setup_cmap(ss); 671 672 return (0); 673 } 674 675 static void 676 stic_free_screen(void *v, void *cookie) 677 { 678 struct stic_screen *ss; 679 680 ss = cookie; 681 682 #ifdef DIAGNOSTIC 683 if (ss == &stic_consscr) 684 panic("stic_free_screen: console"); 685 if (ss == ((struct stic_info *)v)->si_curscreen) 686 panic("stic_free_screen: freeing current screen"); 687 #endif 688 689 free(ss->ss_backing, M_DEVBUF); 690 free(ss, M_DEVBUF); 691 } 692 693 static int 694 stic_show_screen(void *v, void *cookie, int waitok, 695 void (*cb)(void *, int, int), void *cbarg) 696 { 697 struct stic_info *si; 698 699 si = (struct stic_info *)v; 700 if (si->si_switchcbarg != NULL) 701 return (EAGAIN); 702 si->si_switchcb = cb; 703 si->si_switchcbarg = cbarg; 704 705 if (cb != NULL) { 706 callout_reset(&si->si_switch_callout, 0, stic_do_switch, 707 cookie); 708 return (EAGAIN); 709 } 710 711 stic_do_switch(cookie); 712 return (0); 713 } 714 715 static void 716 stic_do_switch(void *cookie) 717 { 718 struct stic_screen *ss; 719 struct stic_info *si; 720 u_int r, c, nr, nc; 721 u_int16_t *p, *sp; 722 723 ss = cookie; 724 si = ss->ss_si; 725 726 if (ss == si->si_curscreen) { 727 si->si_switchcbarg = NULL; 728 return; 729 } 730 731 #ifdef DIAGNOSTIC 732 if (ss->ss_backing == NULL) 733 panic("stic_do_switch: screen not backed"); 734 #endif 735 736 /* Swap in the new screen, and temporarily disable its backing. */ 737 si->si_curscreen->ss_flags ^= SS_ACTIVE; 738 si->si_curscreen = ss; 739 ss->ss_flags |= SS_ACTIVE; 740 sp = ss->ss_backing; 741 ss->ss_backing = NULL; 742 743 /* 744 * We assume that most of the screen is blank and blast it with 745 * eraserows(), because eraserows() is cheap. 746 */ 747 nr = si->si_consh; 748 stic_eraserows(ss, 0, nr, 0); 749 750 nc = si->si_consw; 751 p = sp; 752 for (r = 0; r < nr; r++) 753 for (c = 0; c < nc; c += 2, p += 2) { 754 if ((p[0] & 0xfff0) != 0) 755 stic_putchar(ss, r, c, p[0] >> 8, 756 p[0] & 0x00ff); 757 if ((p[1] & 0xfff0) != 0) 758 stic_putchar(ss, r, c, p[1] >> 8, 759 p[1] & 0x00ff); 760 } 761 762 /* Re-enable the screen's backing and flush out the new VDAC state. */ 763 ss->ss_backing = sp; 764 ss->ss_flags |= SS_ALL_CHANGED; 765 stic_flush(si); 766 767 /* Move the cursor to the correct spot. */ 768 stic_set_hwcurpos(ss); 769 770 /* Tell wscons that we're done. */ 771 if (si->si_switchcbarg != NULL) { 772 cookie = si->si_switchcbarg; 773 si->si_switchcbarg = NULL; 774 (*si->si_switchcb)(cookie, 0, 0); 775 } 776 } 777 778 static int 779 stic_alloc_attr(void *cookie, int fg, int bg, int flags, long *attr) 780 { 781 long tmp; 782 int swap; 783 784 if ((flags & (WSATTR_BLINK | WSATTR_UNDERLINE)) != 0) 785 return (EINVAL); 786 787 if ((flags & WSATTR_HILIT) != 0) 788 fg += 8; 789 790 if ((flags & WSATTR_REVERSE) != 0) { 791 swap = fg; 792 fg = bg; 793 bg = swap; 794 } 795 796 tmp = fg | (bg << 4); 797 *attr = tmp | (tmp << 16); 798 return (0); 799 } 800 801 static void 802 stic_erasecols(void *cookie, int row, int col, int num, long attr) 803 { 804 struct stic_info *si; 805 struct stic_screen *ss; 806 u_int32_t *pb; 807 u_int i, linewidth; 808 u_int16_t *p; 809 810 ss = cookie; 811 si = ss->ss_si; 812 813 if (ss->ss_backing != NULL) { 814 p = ss->ss_backing + row * si->si_consw + col; 815 for (i = num; i != 0; i--) 816 *p++ = (u_int16_t)attr; 817 } 818 if ((ss->ss_flags & SS_ACTIVE) == 0) 819 return; 820 821 si = (struct stic_info *)cookie; 822 col = (col * si->si_fontw) << 19; 823 num = (num * si->si_fontw) << 19; 824 row = row * si->si_fonth; 825 attr = (attr & 0xf0) >> 4; 826 827 pb = (*si->si_pbuf_get)(si); 828 829 linewidth = (si->si_fonth << 2) - 1; 830 row = (row << 3) + linewidth; 831 832 pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET; 833 pb[1] = 0x01ffffff; 834 pb[2] = 0; 835 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY; 836 pb[4] = linewidth; 837 pb[5] = DUPBYTE0(attr); 838 pb[6] = col | row; 839 pb[7] = (col + num) | row; 840 841 (*si->si_pbuf_post)(si, pb); 842 } 843 844 static void 845 stic_eraserows(void *cookie, int row, int num, long attr) 846 { 847 struct stic_info *si; 848 struct stic_screen *ss; 849 u_int linewidth, i; 850 u_int32_t *pb; 851 852 ss = cookie; 853 si = ss->ss_si; 854 855 if (ss->ss_backing != NULL) { 856 pb = (u_int32_t *)(ss->ss_backing + row * si->si_consw); 857 for (i = si->si_consw * num; i != 0; i -= 2) 858 *pb++ = (u_int32_t)attr; 859 } 860 if ((ss->ss_flags & SS_ACTIVE) == 0) 861 return; 862 863 row *= si->si_fonth; 864 num *= si->si_fonth; 865 attr = (attr & 0xf0) >> 4; 866 867 pb = (*si->si_pbuf_get)(si); 868 869 linewidth = (num << 2) - 1; 870 row = (row << 3) + linewidth; 871 872 pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET; 873 pb[1] = 0x01ffffff; 874 pb[2] = 0; 875 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY; 876 pb[4] = linewidth; 877 pb[5] = DUPBYTE0(attr); 878 pb[6] = row; 879 pb[7] = (1280 << 19) | row; 880 881 (*si->si_pbuf_post)(si, pb); 882 } 883 884 static void 885 stic_copyrows(void *cookie, int src, int dst, int height) 886 { 887 struct stic_info *si; 888 struct stic_screen *ss; 889 u_int32_t *pb, *pbs; 890 u_int num, inc, adj; 891 892 ss = cookie; 893 si = ss->ss_si; 894 895 if (ss->ss_backing != NULL) 896 bcopy(ss->ss_backing + src * si->si_consw, 897 ss->ss_backing + dst * si->si_consw, 898 si->si_consw * sizeof(*ss->ss_backing) * height); 899 if ((ss->ss_flags & SS_ACTIVE) == 0) 900 return; 901 902 /* 903 * We need to do this in reverse if the destination row is below 904 * the source. 905 */ 906 if (dst > src) { 907 src += height; 908 dst += height; 909 inc = -8; 910 adj = -1; 911 } else { 912 inc = 8; 913 adj = 0; 914 } 915 916 src = (src * si->si_fonth + adj) << 3; 917 dst = (dst * si->si_fonth + adj) << 3; 918 height *= si->si_fonth; 919 920 while (height > 0) { 921 num = (height < 255 ? height : 255); 922 height -= num; 923 924 pbs = (*si->si_pbuf_get)(si); 925 pb = pbs; 926 927 pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET; 928 pb[1] = (num << 24) | 0xffffff; 929 pb[2] = 0x0; 930 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN | 931 STAMP_COPYSPAN_ALIGNED; 932 pb[4] = 1; /* linewidth */ 933 934 for (; num != 0; num--, src += inc, dst += inc, pb += 3) { 935 pb[5] = 1280 << 3; 936 pb[6] = src; 937 pb[7] = dst; 938 } 939 940 (*si->si_pbuf_post)(si, pbs); 941 } 942 } 943 944 static void 945 stic_copycols(void *cookie, int row, int src, int dst, int num) 946 { 947 struct stic_info *si; 948 struct stic_screen *ss; 949 u_int height, updword; 950 u_int32_t *pb, *pbs; 951 952 ss = cookie; 953 si = ss->ss_si; 954 955 if (ss->ss_backing != NULL) 956 bcopy(ss->ss_backing + row * si->si_consw + src, 957 ss->ss_backing + row * si->si_consw + dst, 958 num * sizeof(*ss->ss_backing)); 959 if ((ss->ss_flags & SS_ACTIVE) == 0) 960 return; 961 962 /* 963 * The stamp reads and writes left -> right only, so we need to 964 * buffer the span if the source and destination regions overlap 965 * and the source is left of the destination. 966 */ 967 updword = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN; 968 969 if (src < dst && src + num > dst) 970 updword |= STAMP_HALF_BUFF; 971 972 row = (row * si->si_fonth) << 3; 973 num = (num * si->si_fontw) << 3; 974 src = row | ((src * si->si_fontw) << 19); 975 dst = row | ((dst * si->si_fontw) << 19); 976 height = si->si_fonth; 977 978 pbs = (*si->si_pbuf_get)(si); 979 pb = pbs; 980 981 pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET; 982 pb[1] = (height << 24) | 0xffffff; 983 pb[2] = 0x0; 984 pb[3] = updword; 985 pb[4] = 1; /* linewidth */ 986 987 for ( ; height != 0; height--, src += 8, dst += 8, pb += 3) { 988 pb[5] = num; 989 pb[6] = src; 990 pb[7] = dst; 991 } 992 993 (*si->si_pbuf_post)(si, pbs); 994 } 995 996 static void 997 stic_putchar(void *cookie, int r, int c, u_int uc, long attr) 998 { 999 struct wsdisplay_font *font; 1000 struct stic_screen *ss; 1001 struct stic_info *si; 1002 u_int i, bgcolor, fgcolor; 1003 u_int *pb, v1, v2, xya; 1004 u_short *fr; 1005 1006 ss = cookie; 1007 si = ss->ss_si; 1008 1009 /* It's cheaper to use erasecols() to blit blanks. */ 1010 if (uc == 0) { 1011 stic_erasecols(cookie, r, c, 1, attr); 1012 return; 1013 } 1014 1015 if (ss->ss_backing != NULL) 1016 ss->ss_backing[r * si->si_consw + c] = 1017 (u_int16_t)((attr & 0xff) | (uc << 8)); 1018 if ((ss->ss_flags & SS_ACTIVE) == 0) 1019 return; 1020 1021 font = si->si_font; 1022 pb = (*si->si_pbuf_get)(si); 1023 1024 /* 1025 * Create a mask from the glyph. Squeeze the foreground color 1026 * through the mask, and then squeeze the background color through 1027 * the inverted mask. We may well read outside the glyph when 1028 * creating the mask, but it's bounded by the hardware so it 1029 * shouldn't matter a great deal... 1030 */ 1031 pb[0] = STAMP_CMD_LINES | STAMP_RGB_FLAT | STAMP_XY_PERPRIMATIVE | 1032 STAMP_LW_PERPRIMATIVE; 1033 pb[1] = font->fontheight > 16 ? 0x04ffffff : 0x02ffffff; 1034 pb[2] = 0x0; 1035 pb[3] = STAMP_UPDATE_ENABLE | STAMP_WE_XYMASK | STAMP_METHOD_COPY; 1036 1037 r *= font->fontheight; 1038 c *= font->fontwidth; 1039 uc = (uc - font->firstchar) * font->stride * font->fontheight; 1040 fr = (u_short *)((caddr_t)font->data + uc); 1041 bgcolor = DUPBYTE1((attr & 0x40) >> 4); 1042 fgcolor = DUPBYTE0(attr & 0x0f); 1043 1044 i = ((font->fontheight > 16 ? 16 : font->fontheight) << 2) - 1; 1045 v1 = (c << 19) | ((r << 3) + i); 1046 v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff); 1047 xya = XYMASKADDR(si->si_stampw, si->si_stamph, c, r, 0, 0); 1048 1049 pb[4] = PACK(fr, 0); 1050 pb[5] = PACK(fr, 2); 1051 pb[6] = PACK(fr, 4); 1052 pb[7] = PACK(fr, 6); 1053 pb[8] = PACK(fr, 8); 1054 pb[9] = PACK(fr, 10); 1055 pb[10] = PACK(fr, 12); 1056 pb[11] = PACK(fr, 14); 1057 pb[12] = xya; 1058 pb[13] = v1; 1059 pb[14] = v2; 1060 pb[15] = i; 1061 pb[16] = fgcolor; 1062 1063 pb[17] = ~pb[4]; 1064 pb[18] = ~pb[5]; 1065 pb[19] = ~pb[6]; 1066 pb[20] = ~pb[7]; 1067 pb[21] = ~pb[8]; 1068 pb[22] = ~pb[9]; 1069 pb[23] = ~pb[10]; 1070 pb[24] = ~pb[11]; 1071 pb[25] = xya; 1072 pb[26] = v1; 1073 pb[27] = v2; 1074 pb[28] = i; 1075 pb[29] = bgcolor; 1076 1077 /* Two more squeezes for the lower part of the character. */ 1078 if (font->fontheight > 16) { 1079 i = ((font->fontheight - 16) << 2) - 1; 1080 r += 16; 1081 v1 = (c << 19) | ((r << 3) + i); 1082 v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff); 1083 1084 pb[30] = PACK(fr, 16); 1085 pb[31] = PACK(fr, 18); 1086 pb[32] = PACK(fr, 20); 1087 pb[33] = PACK(fr, 22); 1088 pb[34] = PACK(fr, 24); 1089 pb[35] = PACK(fr, 26); 1090 pb[36] = PACK(fr, 28); 1091 pb[37] = PACK(fr, 30); 1092 pb[38] = xya; 1093 pb[39] = v1; 1094 pb[40] = v2; 1095 pb[41] = i; 1096 pb[42] = fgcolor; 1097 1098 pb[43] = ~pb[30]; 1099 pb[44] = ~pb[31]; 1100 pb[45] = ~pb[32]; 1101 pb[46] = ~pb[33]; 1102 pb[47] = ~pb[34]; 1103 pb[48] = ~pb[35]; 1104 pb[49] = ~pb[36]; 1105 pb[50] = ~pb[37]; 1106 pb[51] = xya; 1107 pb[52] = v1; 1108 pb[53] = v2; 1109 pb[54] = i; 1110 pb[55] = bgcolor; 1111 } 1112 1113 (*si->si_pbuf_post)(si, pb); 1114 } 1115 1116 static int 1117 stic_mapchar(void *cookie, int c, u_int *cp) 1118 { 1119 struct stic_info *si; 1120 1121 si = ((struct stic_screen *)cookie)->ss_si; 1122 1123 if (c < si->si_font->firstchar || c == ' ') { 1124 *cp = 0; 1125 return (0); 1126 } 1127 1128 if (c - si->si_font->firstchar >= si->si_font->numchars) { 1129 *cp = 0; 1130 return (0); 1131 } 1132 1133 *cp = c; 1134 return (5); 1135 } 1136 1137 static void 1138 stic_cursor(void *cookie, int on, int row, int col) 1139 { 1140 struct stic_screen *ss; 1141 1142 ss = cookie; 1143 1144 /* XXX We should do cursor on/off. */ 1145 ss->ss_cursor.cc_pos.x = col * ss->ss_si->si_fontw; 1146 ss->ss_cursor.cc_pos.y = row * ss->ss_si->si_fonth; 1147 stic_set_hwcurpos(ss); 1148 } 1149 1150 void 1151 stic_flush(struct stic_info *si) 1152 { 1153 struct stic_screen *ss; 1154 volatile u_int32_t *vdac; 1155 int v; 1156 1157 ss = si->si_curscreen; 1158 if ((ss->ss_flags & SS_ALL_CHANGED) == 0) 1159 return; 1160 1161 vdac = si->si_vdac; 1162 v = ss->ss_flags; 1163 ss->ss_flags &= ~SS_ALL_CHANGED; 1164 1165 if ((v & SS_CURENB_CHANGED) != 0) { 1166 SELECT(vdac, BT459_IREG_CCR); 1167 if ((v & SS_CURENB) != 0) { 1168 if ((si->si_vdacctl & STIC_VDAC_BLINK) != 0) 1169 REG(vdac, bt_reg) = 0x00c1c1c1; 1170 else 1171 REG(vdac, bt_reg) = 0x00c0c0c0; 1172 } else 1173 REG(vdac, bt_reg) = 0x00000000; 1174 tc_wmb(); 1175 } 1176 1177 if ((v & SS_CURCMAP_CHANGED) != 0) { 1178 u_int8_t *cp; 1179 1180 cp = ss->ss_cursor.cc_color; 1181 1182 SELECT(vdac, BT459_IREG_CCOLOR_2); 1183 if ((si->si_vdacctl & STIC_VDAC_24BIT) != 0) { 1184 REG(vdac, bt_reg) = cp[1]; tc_wmb(); 1185 REG(vdac, bt_reg) = cp[3] << 8; tc_wmb(); 1186 REG(vdac, bt_reg) = cp[5] << 16; tc_wmb(); 1187 REG(vdac, bt_reg) = cp[0]; tc_wmb(); 1188 REG(vdac, bt_reg) = cp[2] << 8; tc_wmb(); 1189 REG(vdac, bt_reg) = cp[4] << 16; tc_wmb(); 1190 } else { 1191 REG(vdac, bt_reg) = DUPBYTE0(cp[1]); tc_wmb(); 1192 REG(vdac, bt_reg) = DUPBYTE0(cp[3]); tc_wmb(); 1193 REG(vdac, bt_reg) = DUPBYTE0(cp[5]); tc_wmb(); 1194 REG(vdac, bt_reg) = DUPBYTE0(cp[0]); tc_wmb(); 1195 REG(vdac, bt_reg) = DUPBYTE0(cp[2]); tc_wmb(); 1196 REG(vdac, bt_reg) = DUPBYTE0(cp[4]); tc_wmb(); 1197 } 1198 } 1199 1200 if ((v & SS_CURSHAPE_CHANGED) != 0) { 1201 u_int8_t *ip, *mp, img, msk; 1202 u_int8_t u; 1203 int bcnt; 1204 1205 ip = (u_int8_t *)ss->ss_cursor.cc_image; 1206 mp = (u_int8_t *)(ss->ss_cursor.cc_image + CURSOR_MAX_SIZE); 1207 1208 bcnt = 0; 1209 SELECT(vdac, BT459_IREG_CRAM_BASE+0); 1210 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 1211 while (bcnt < ss->ss_cursor.cc_size.y * 16) { 1212 /* pad right half 32 pixel when smaller than 33 */ 1213 if ((bcnt & 0x8) && ss->ss_cursor.cc_size.x < 33) { 1214 REG(vdac, bt_reg) = 0; tc_wmb(); 1215 REG(vdac, bt_reg) = 0; tc_wmb(); 1216 } else { 1217 img = *ip++; 1218 msk = *mp++; 1219 img &= msk; /* cookie off image */ 1220 u = (msk & 0x0f) << 4 | (img & 0x0f); 1221 REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]); 1222 tc_wmb(); 1223 u = (msk & 0xf0) | (img & 0xf0) >> 4; 1224 REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]); 1225 tc_wmb(); 1226 } 1227 bcnt += 2; 1228 } 1229 /* pad unoccupied scan lines */ 1230 while (bcnt < CURSOR_MAX_SIZE * 16) { 1231 REG(vdac, bt_reg) = 0; tc_wmb(); 1232 REG(vdac, bt_reg) = 0; tc_wmb(); 1233 bcnt += 2; 1234 } 1235 } 1236 1237 if ((v & SS_CMAP_CHANGED) != 0) { 1238 struct stic_hwcmap256 *cm; 1239 int index; 1240 1241 cm = &ss->ss_cmap; 1242 1243 SELECT(vdac, 0); 1244 SELECT(vdac, 0); 1245 if ((si->si_vdacctl & STIC_VDAC_24BIT) != 0) { 1246 for (index = 0; index < CMAP_SIZE; index++) { 1247 REG(vdac, bt_cmap) = DUPBYTE0(cm->r[index]); 1248 tc_wmb(); 1249 REG(vdac, bt_cmap) = DUPBYTE0(cm->g[index]); 1250 tc_wmb(); 1251 REG(vdac, bt_cmap) = DUPBYTE0(cm->b[index]); 1252 tc_wmb(); 1253 } 1254 } else { 1255 for (index = 0; index < CMAP_SIZE; index++) { 1256 REG(vdac, bt_cmap) = cm->r[index]; 1257 tc_wmb(); 1258 REG(vdac, bt_cmap) = cm->g[index] << 8; 1259 tc_wmb(); 1260 REG(vdac, bt_cmap) = cm->b[index] << 16; 1261 tc_wmb(); 1262 } 1263 } 1264 } 1265 } 1266 1267 static int 1268 stic_get_cmap(struct stic_screen *ss, struct wsdisplay_cmap *p) 1269 { 1270 u_int index, count; 1271 1272 index = p->index; 1273 count = p->count; 1274 1275 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 1276 return (EINVAL); 1277 1278 if (!uvm_useracc(p->red, count, B_WRITE) || 1279 !uvm_useracc(p->green, count, B_WRITE) || 1280 !uvm_useracc(p->blue, count, B_WRITE)) 1281 return (EFAULT); 1282 1283 copyout(&ss->ss_cmap.r[index], p->red, count); 1284 copyout(&ss->ss_cmap.g[index], p->green, count); 1285 copyout(&ss->ss_cmap.b[index], p->blue, count); 1286 return (0); 1287 } 1288 1289 static int 1290 stic_set_cmap(struct stic_screen *ss, struct wsdisplay_cmap *p) 1291 { 1292 u_int index, count; 1293 1294 index = p->index; 1295 count = p->count; 1296 1297 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 1298 return (EINVAL); 1299 1300 if (!uvm_useracc(p->red, count, B_READ) || 1301 !uvm_useracc(p->green, count, B_READ) || 1302 !uvm_useracc(p->blue, count, B_READ)) 1303 return (EFAULT); 1304 1305 copyin(p->red, &ss->ss_cmap.r[index], count); 1306 copyin(p->green, &ss->ss_cmap.g[index], count); 1307 copyin(p->blue, &ss->ss_cmap.b[index], count); 1308 1309 ss->ss_flags |= SS_CMAP_CHANGED; 1310 1311 /* 1312 * XXX Since we don't yet receive vblank interrupts from the PXG, we 1313 * must flush immediatley. 1314 */ 1315 if (ss->ss_si->si_disptype == WSDISPLAY_TYPE_PXG) 1316 stic_flush(ss->ss_si); 1317 1318 return (0); 1319 } 1320 1321 static int 1322 stic_set_cursor(struct stic_screen *ss, struct wsdisplay_cursor *p) 1323 { 1324 #define cc (&ss->ss_cursor) 1325 int v, index, count, icount; 1326 1327 v = p->which; 1328 1329 if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) { 1330 index = p->cmap.index; 1331 count = p->cmap.count; 1332 if (index >= 2 || (index + count) > 2) 1333 return (EINVAL); 1334 if (!uvm_useracc(p->cmap.red, count, B_READ) || 1335 !uvm_useracc(p->cmap.green, count, B_READ) || 1336 !uvm_useracc(p->cmap.blue, count, B_READ)) 1337 return (EFAULT); 1338 } 1339 1340 if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) { 1341 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE) 1342 return (EINVAL); 1343 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y; 1344 if (!uvm_useracc(p->image, icount, B_READ) || 1345 !uvm_useracc(p->mask, icount, B_READ)) 1346 return (EFAULT); 1347 } 1348 1349 if ((v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) != 0) { 1350 if (v & WSDISPLAY_CURSOR_DOCUR) 1351 cc->cc_hot = p->hot; 1352 if (v & WSDISPLAY_CURSOR_DOPOS) 1353 stic_set_curpos(ss, &p->pos); 1354 stic_set_hwcurpos(ss); 1355 } 1356 1357 ss->ss_flags &= ~SS_ALL_CHANGED; 1358 1359 if ((v & WSDISPLAY_CURSOR_DOCUR) != 0) { 1360 if (p->enable) 1361 ss->ss_flags |= SS_CURENB; 1362 else 1363 ss->ss_flags &= ~SS_CURENB; 1364 ss->ss_flags |= SS_CURENB_CHANGED; 1365 } 1366 1367 if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) { 1368 copyin(p->cmap.red, &cc->cc_color[index], count); 1369 copyin(p->cmap.green, &cc->cc_color[index + 2], count); 1370 copyin(p->cmap.blue, &cc->cc_color[index + 4], count); 1371 ss->ss_flags |= SS_CURCMAP_CHANGED; 1372 } 1373 1374 if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) { 1375 cc->cc_size = p->size; 1376 memset(cc->cc_image, 0, sizeof cc->cc_image); 1377 copyin(p->image, cc->cc_image, icount); 1378 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount); 1379 ss->ss_flags |= SS_CURSHAPE_CHANGED; 1380 } 1381 1382 /* 1383 * XXX Since we don't yet receive vblank interrupts from the PXG, we 1384 * must flush immediatley. 1385 */ 1386 if (ss->ss_si->si_disptype == WSDISPLAY_TYPE_PXG) 1387 stic_flush(ss->ss_si); 1388 1389 return (0); 1390 #undef cc 1391 } 1392 1393 static int 1394 stic_get_cursor(struct stic_screen *ss, struct wsdisplay_cursor *p) 1395 { 1396 1397 /* XXX No X support yet. */ 1398 return (ENOTTY); 1399 } 1400 1401 static void 1402 stic_set_curpos(struct stic_screen *ss, struct wsdisplay_curpos *curpos) 1403 { 1404 int x, y; 1405 1406 x = curpos->x; 1407 y = curpos->y; 1408 1409 if (y < 0) 1410 y = 0; 1411 else if (y > 1023) 1412 y = 1023; 1413 if (x < 0) 1414 x = 0; 1415 else if (x > 1279) 1416 x = 1279; 1417 1418 ss->ss_cursor.cc_pos.x = x; 1419 ss->ss_cursor.cc_pos.y = y; 1420 stic_set_hwcurpos(ss); 1421 } 1422 1423 static void 1424 stic_set_hwcurpos(struct stic_screen *ss) 1425 { 1426 struct stic_info *si; 1427 volatile u_int32_t *vdac; 1428 int x, y, s; 1429 1430 si = ss->ss_si; 1431 vdac = si->si_vdac; 1432 1433 x = ss->ss_cursor.cc_pos.x - ss->ss_cursor.cc_hot.x; 1434 y = ss->ss_cursor.cc_pos.y - ss->ss_cursor.cc_hot.y; 1435 x += STIC_MAGIC_X; 1436 y += STIC_MAGIC_Y; 1437 1438 s = spltty(); 1439 SELECT(vdac, BT459_IREG_CURSOR_X_LOW); 1440 REG(vdac, bt_reg) = DUPBYTE0(x); tc_wmb(); 1441 REG(vdac, bt_reg) = DUPBYTE1(x); tc_wmb(); 1442 REG(vdac, bt_reg) = DUPBYTE0(y); tc_wmb(); 1443 REG(vdac, bt_reg) = DUPBYTE1(y); tc_wmb(); 1444 splx(s); 1445 } 1446