1 /* $NetBSD: stic.c,v 1.8 2001/03/04 13:32:25 ad Exp $ */ 2 3 /*- 4 * Copyright (c) 1999, 2000, 2001 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/vmparam.h> 93 #include <machine/bus.h> 94 #include <machine/intr.h> 95 96 #include <dev/wscons/wsconsio.h> 97 #include <dev/wscons/wsdisplayvar.h> 98 99 #include <dev/wsfont/wsfont.h> 100 101 #include <dev/ic/bt459reg.h> 102 103 #include <dev/tc/tcvar.h> 104 #include <dev/tc/sticreg.h> 105 #include <dev/tc/sticvar.h> 106 107 #define DUPBYTE0(x) ((((x)&0xff)<<16) | (((x)&0xff)<<8) | ((x)&0xff)) 108 #define DUPBYTE1(x) ((((x)<<8)&0xff0000) | ((x)&0xff00) | (((x)>>8)&0xff)) 109 #define DUPBYTE2(x) (((x)&0xff0000) | (((x)>>8)&0xff00) | (((x)>>16)&0xff)) 110 111 #define PACK(p, o) ((p)[(o)] | ((p)[(o)+1] << 16)) 112 113 #if defined(pmax) 114 #define machine_btop(x) mips_btop(x) 115 #elif defined(alpha) 116 #define machine_btop(x) alpha_btop(x) 117 #endif 118 119 /* 120 * N.B., Bt459 registers are 8bit width. Some of TC framebuffers have 121 * obscure register layout such as 2nd and 3rd Bt459 registers are 122 * adjacent each other in a word, i.e., 123 * struct bt459triplet { 124 * struct { 125 * u_int8_t u0; 126 * u_int8_t u1; 127 * u_int8_t u2; 128 * unsigned :8; 129 * } bt_lo; 130 * struct { 131 * 132 * Although HX has single Bt459, 32bit R/W can be done w/o any trouble. 133 * struct bt459reg { 134 * u_int32_t bt_lo; 135 * u_int32_t bt_hi; 136 * u_int32_t bt_reg; 137 * u_int32_t bt_cmap; 138 * }; 139 * 140 */ 141 142 /* Bt459 hardware registers */ 143 #define bt_lo 0 144 #define bt_hi 1 145 #define bt_reg 2 146 #define bt_cmap 3 147 148 #define REG(base, index) *((u_int32_t *)(base) + (index)) 149 #define SELECT(vdac, regno) do { \ 150 REG(vdac, bt_lo) = DUPBYTE0(regno); \ 151 REG(vdac, bt_hi) = DUPBYTE1(regno); \ 152 tc_wmb(); \ 153 } while (0) 154 155 static int sticioctl(void *, u_long, caddr_t, int, struct proc *); 156 static paddr_t sticmmap(void *, off_t, int); 157 static int stic_alloc_screen(void *, const struct wsscreen_descr *, 158 void **, int *, int *, long *); 159 static void stic_free_screen(void *, void *); 160 static int stic_show_screen(void *, void *, int, 161 void (*) (void *, int, int), void *); 162 static void stic_do_switch(void *); 163 static void stic_setup_backing(struct stic_info *, struct stic_screen *); 164 static void stic_setup_vdac(struct stic_info *si); 165 166 static int stic_get_cmap(struct stic_info *, struct wsdisplay_cmap *); 167 static int stic_set_cmap(struct stic_info *, struct wsdisplay_cmap *); 168 static int stic_set_cursor(struct stic_info *, struct wsdisplay_cursor *); 169 static int stic_get_cursor(struct stic_info *, struct wsdisplay_cursor *); 170 static void stic_set_curpos(struct stic_info *, struct wsdisplay_curpos *); 171 static void stic_set_hwcurpos(struct stic_info *); 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 WSSCREEN_WSCOLORS | WSSCREEN_HILIT 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_wmb(); 297 298 /* Now reset the VDAC. */ 299 *si->si_vdac_reset = 0; 300 tc_wmb(); 301 tc_syncbus(); 302 DELAY(1000); 303 304 /* Finish the initalization. */ 305 SELECT(vdac, BT459_IREG_COMMAND_1); 306 REG(vdac, bt_reg) = 0x00000000; tc_wmb(); 307 REG(vdac, bt_reg) = 0x00c2c2c2; tc_wmb(); 308 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb(); 309 310 for (i = 0; i < 7; i++) { 311 REG(vdac, bt_reg) = 0x00000000; 312 tc_wmb(); 313 } 314 315 /* Set cursor colormap. */ 316 SELECT(vdac, BT459_IREG_CCOLOR_1); 317 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb(); 318 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb(); 319 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb(); 320 REG(vdac, bt_reg) = 0x00000000; tc_wmb(); 321 REG(vdac, bt_reg) = 0x00000000; tc_wmb(); 322 REG(vdac, bt_reg) = 0x00000000; tc_wmb(); 323 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb(); 324 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb(); 325 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb(); 326 327 /* Get a font and set up screen metrics. */ 328 wsfont_init(); 329 cookie = wsfont_find(NULL, 0, 0, 0); 330 331 if (wsfont_lock(cookie, &si->si_font, 332 WSDISPLAY_FONTORDER_R2L, WSDISPLAY_FONTORDER_L2R) <= 0) 333 panic("stic_init: couldn't lock font\n"); 334 335 si->si_fontw = si->si_font->fontwidth; 336 si->si_fonth = si->si_font->fontheight; 337 si->si_consw = (1280 / si->si_fontw) & ~1; 338 si->si_consh = 1024 / si->si_fonth; 339 stic_stdscreen.ncols = si->si_consw; 340 stic_stdscreen.nrows = si->si_consh; 341 342 #ifdef DIAGNOSTIC 343 if ((u_int)si->si_fonth > 32 || (u_int)si->si_fontw > 16) 344 panic("stic_init: unusable font"); 345 #endif 346 347 stic_setup_vdac(si); 348 } 349 350 void 351 stic_reset(struct stic_info *si) 352 { 353 int modtype, xconfig, yconfig, config; 354 volatile struct stic_regs *sr; 355 356 sr = si->si_stic; 357 358 /* 359 * Initialize the interface chip registers. 360 */ 361 sr->sr_sticsr = 0x00000030; /* Get the STIC's attention. */ 362 tc_wmb(); 363 tc_syncbus(); 364 DELAY(4000); /* wait 4ms for STIC to respond. */ 365 sr->sr_sticsr = 0x00000000; /* Hit the STIC's csr again... */ 366 tc_wmb(); 367 sr->sr_buscsr = 0xffffffff; /* and bash its bus-acess csr. */ 368 tc_wmb(); 369 tc_syncbus(); /* Blam! */ 370 DELAY(20000); /* wait until the stic recovers... */ 371 372 modtype = sr->sr_modcl; 373 xconfig = (modtype & 0x800) >> 11; 374 yconfig = (modtype & 0x600) >> 9; 375 config = (yconfig << 1) | xconfig; 376 si->si_stampw = (xconfig ? 5 : 4); 377 si->si_stamph = (1 << yconfig); 378 #ifdef notyet 379 si->si_option = (char)((modtype >> 12) & 3); 380 #endif 381 382 /* First PixelStamp */ 383 si->si_stamp[0x000b0] = config; 384 si->si_stamp[0x000b4] = 0x0; 385 386 /* Second PixelStamp */ 387 if (yconfig > 0) { 388 si->si_stamp[0x100b0] = config | 8; 389 si->si_stamp[0x100b4] = 0; 390 } 391 392 /* 393 * Initialize STIC video registers. 394 */ 395 sr->sr_vblank = (1024 << 16) | 1063; 396 sr->sr_vsync = (1027 << 16) | 1030; 397 sr->sr_hblank = (255 << 16) | 340; 398 sr->sr_hsync2 = 245; 399 sr->sr_hsync = (261 << 16) | 293; 400 sr->sr_ipdvint = STIC_INT_CLR | STIC_INT_WE | STIC_INT_P; 401 sr->sr_sticsr = 8; 402 tc_wmb(); 403 tc_syncbus(); 404 } 405 406 void 407 stic_attach(struct device *self, struct stic_info *si, int console) 408 { 409 struct wsemuldisplaydev_attach_args waa; 410 411 callout_init(&si->si_switch_callout); 412 413 /* 414 * Allocate backing for the console. We could trawl back through 415 * msgbuf and and fill the backing, but it's not worth the hassle. 416 * We could also grab backing using pmap_steal_memory() early on, 417 * but that's a little ugly. 418 */ 419 if (console) 420 stic_setup_backing(si, &stic_consscr); 421 422 waa.console = console; 423 waa.scrdata = &stic_screenlist; 424 waa.accessops = &stic_accessops; 425 waa.accesscookie = si; 426 config_found(self, &waa, wsemuldisplaydevprint); 427 } 428 429 void 430 stic_cnattach(struct stic_info *si) 431 { 432 struct stic_screen *ss; 433 long defattr; 434 435 ss = &stic_consscr; 436 si->si_curscreen = ss; 437 ss->ss_flags = SS_ALLOCED | SS_ACTIVE | SS_CURENB; 438 ss->ss_si = si; 439 440 si->si_flags |= SI_CURENB_CHANGED; 441 stic_flush(si); 442 443 stic_alloc_attr(ss, 0, 0, 0, &defattr); 444 stic_eraserows(ss, 0, si->si_consh, 0); 445 wsdisplay_cnattach(&stic_stdscreen, ss, 0, 0, defattr); 446 } 447 448 static void 449 stic_setup_vdac(struct stic_info *si) 450 { 451 u_int8_t *ip, *mp; 452 int r, c, o, b, i; 453 454 ip = (u_int8_t *)si->si_cursor.cc_image; 455 mp = ip + (sizeof(si->si_cursor.cc_image) >> 1); 456 memset(ip, 0, sizeof(si->si_cursor.cc_image)); 457 458 for (r = 0; r < si->si_fonth; r++) { 459 for (c = 0; c < si->si_fontw; c++) { 460 o = c >> 3; 461 b = 1 << (c & 7); 462 ip[o] |= b; 463 mp[o] |= b; 464 } 465 466 ip += 16; 467 mp += 16; 468 } 469 470 si->si_cursor.cc_size.x = 64; 471 si->si_cursor.cc_size.y = si->si_fonth; 472 si->si_cursor.cc_hot.x = 0; 473 si->si_cursor.cc_hot.y = 0; 474 475 si->si_cursor.cc_color[0] = 0xff; 476 si->si_cursor.cc_color[2] = 0xff; 477 si->si_cursor.cc_color[4] = 0xff; 478 si->si_cursor.cc_color[1] = 0x00; 479 si->si_cursor.cc_color[3] = 0x00; 480 si->si_cursor.cc_color[5] = 0x00; 481 482 memset(&si->si_cmap, 0, sizeof(si->si_cmap)); 483 for (i = 0; i < 16; i++) { 484 si->si_cmap.r[i] = stic_cmap[i*3 + 0]; 485 si->si_cmap.g[i] = stic_cmap[i*3 + 1]; 486 si->si_cmap.b[i] = stic_cmap[i*3 + 2]; 487 } 488 489 si->si_flags |= SI_CMAP_CHANGED | SI_CURSHAPE_CHANGED | 490 SI_CURCMAP_CHANGED; 491 } 492 493 static int 494 sticioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 495 { 496 struct stic_info *si; 497 struct stic_xinfo *sxi; 498 499 si = v; 500 501 switch (cmd) { 502 case WSDISPLAYIO_GTYPE: 503 *(u_int *)data = si->si_disptype; 504 return (0); 505 506 case WSDISPLAYIO_GINFO: 507 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 508 wsd_fbip->height = 1024; 509 wsd_fbip->width = 1280; 510 wsd_fbip->depth = si->si_depth == 8 ? 8 : 32; 511 wsd_fbip->cmsize = CMAP_SIZE; 512 #undef fbt 513 return (0); 514 515 case WSDISPLAYIO_GETCMAP: 516 return (stic_get_cmap(si, (struct wsdisplay_cmap *)data)); 517 518 case WSDISPLAYIO_PUTCMAP: 519 return (stic_set_cmap(si, (struct wsdisplay_cmap *)data)); 520 521 case WSDISPLAYIO_SVIDEO: 522 #if 0 /* XXX later */ 523 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF; 524 if ((si->si_blanked == 0) ^ turnoff) 525 si->si_blanked = turnoff; 526 #endif 527 return (0); 528 529 case WSDISPLAYIO_GVIDEO: 530 #if 0 /* XXX later */ 531 *(u_int *)data = si->si_blanked ? 532 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 533 #endif 534 return (0); 535 536 case WSDISPLAYIO_GCURPOS: 537 *(struct wsdisplay_curpos *)data = si->si_cursor.cc_pos; 538 return (0); 539 540 case WSDISPLAYIO_SCURPOS: 541 stic_set_curpos(si, (struct wsdisplay_curpos *)data); 542 return (0); 543 544 case WSDISPLAYIO_GCURMAX: 545 ((struct wsdisplay_curpos *)data)->x = 546 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE; 547 return (0); 548 549 case WSDISPLAYIO_GCURSOR: 550 return (stic_get_cursor(si, (struct wsdisplay_cursor *)data)); 551 552 case WSDISPLAYIO_SCURSOR: 553 return (stic_set_cursor(si, (struct wsdisplay_cursor *)data)); 554 555 case WSDISPLAYIO_SMODE: 556 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) { 557 stic_setup_vdac(si); 558 stic_flush(si); 559 stic_do_switch(si->si_curscreen); 560 } 561 return (0); 562 563 case STICIO_RESET: 564 stic_reset(si); 565 return (0); 566 567 case STICIO_GXINFO: 568 sxi = (struct stic_xinfo *)data; 569 sxi->sxi_stampw = si->si_stampw; 570 sxi->sxi_stamph = si->si_stamph; 571 sxi->sxi_buf_size = si->si_buf_size; 572 sxi->sxi_buf_phys = (u_long)si->si_buf_phys; 573 return (0); 574 } 575 576 if (si->si_ioctl != NULL) 577 return ((*si->si_ioctl)(si, cmd, data, flag, p)); 578 579 return (ENOTTY); 580 } 581 582 static paddr_t 583 sticmmap(void *v, off_t offset, int prot) 584 { 585 struct stic_info *si; 586 struct stic_xmap sxm; 587 paddr_t pa; 588 589 si = v; 590 591 if (offset < 0) 592 return ((paddr_t)-1L); 593 594 if (offset < sizeof(sxm.sxm_stic)) { 595 pa = STIC_KSEG_TO_PHYS(si->si_stic); 596 return (machine_btop(pa + offset)); 597 } 598 offset -= sizeof(sxm.sxm_stic); 599 600 if (offset < sizeof(sxm.sxm_poll)) { 601 pa = STIC_KSEG_TO_PHYS(si->si_slotbase); 602 return (machine_btop(pa + offset)); 603 } 604 offset -= sizeof(sxm.sxm_poll); 605 606 if (offset < si->si_buf_size) 607 return (machine_btop(si->si_buf_phys + offset)); 608 609 return ((paddr_t)-1L); 610 } 611 612 static void 613 stic_setup_backing(struct stic_info *si, struct stic_screen *ss) 614 { 615 int size; 616 617 size = si->si_consw * si->si_consh * sizeof(*ss->ss_backing); 618 ss->ss_backing = malloc(size, M_DEVBUF, M_NOWAIT); 619 memset(ss->ss_backing, 0, size); 620 } 621 622 static int 623 stic_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 624 int *curxp, int *curyp, long *attrp) 625 { 626 struct stic_info *si; 627 struct stic_screen *ss; 628 629 si = (struct stic_info *)v; 630 631 if ((stic_consscr.ss_flags & SS_ALLOCED) == 0) 632 ss = &stic_consscr; 633 else { 634 ss = malloc(sizeof(*ss), M_DEVBUF, M_WAITOK); 635 memset(ss, 0, sizeof(*ss)); 636 } 637 stic_setup_backing(si, ss); 638 639 ss->ss_si = si; 640 ss->ss_flags = SS_ALLOCED | SS_CURENB; 641 642 *cookiep = ss; 643 *curxp = 0; 644 *curyp = 0; 645 646 stic_alloc_attr(ss, 0, 0, 0, attrp); 647 return (0); 648 } 649 650 static void 651 stic_free_screen(void *v, void *cookie) 652 { 653 struct stic_screen *ss; 654 655 ss = cookie; 656 657 #ifdef DIAGNOSTIC 658 if (ss == &stic_consscr) 659 panic("stic_free_screen: console"); 660 if (ss == ((struct stic_info *)v)->si_curscreen) 661 panic("stic_free_screen: freeing current screen"); 662 #endif 663 664 free(ss->ss_backing, M_DEVBUF); 665 free(ss, M_DEVBUF); 666 } 667 668 static int 669 stic_show_screen(void *v, void *cookie, int waitok, 670 void (*cb)(void *, int, int), void *cbarg) 671 { 672 struct stic_info *si; 673 674 si = (struct stic_info *)v; 675 if (si->si_switchcbarg != NULL) 676 return (EAGAIN); 677 si->si_switchcb = cb; 678 si->si_switchcbarg = cbarg; 679 680 if (cb != NULL) { 681 callout_reset(&si->si_switch_callout, 0, stic_do_switch, 682 cookie); 683 return (EAGAIN); 684 } 685 686 stic_do_switch(cookie); 687 return (0); 688 } 689 690 static void 691 stic_do_switch(void *cookie) 692 { 693 struct stic_screen *ss; 694 struct stic_info *si; 695 u_int r, c, nr, nc; 696 u_int16_t *p, *sp; 697 698 ss = cookie; 699 si = ss->ss_si; 700 701 #ifdef DIAGNOSTIC 702 if (ss->ss_backing == NULL) 703 panic("stic_do_switch: screen not backed"); 704 #endif 705 706 /* Swap in the new screen, and temporarily disable its backing. */ 707 si->si_curscreen->ss_flags ^= SS_ACTIVE; 708 si->si_curscreen = ss; 709 ss->ss_flags |= SS_ACTIVE; 710 sp = ss->ss_backing; 711 ss->ss_backing = NULL; 712 713 /* 714 * We assume that most of the screen is blank and blast it with 715 * eraserows(), because eraserows() is cheap. 716 */ 717 nr = si->si_consh; 718 stic_eraserows(ss, 0, nr, 0); 719 720 nc = si->si_consw; 721 p = sp; 722 for (r = 0; r < nr; r++) 723 for (c = 0; c < nc; c += 2, p += 2) { 724 if ((p[0] & 0xfff0) != 0) 725 stic_putchar(ss, r, c, p[0] >> 8, 726 p[0] & 0x00ff); 727 if ((p[1] & 0xfff0) != 0) 728 stic_putchar(ss, r, c + 1, p[1] >> 8, 729 p[1] & 0x00ff); 730 } 731 732 /* 733 * Re-enable the screen's backing, and move the cursor to the 734 * correct spot. 735 */ 736 ss->ss_backing = sp; 737 si->si_cursor.cc_pos.x = ss->ss_curx; 738 si->si_cursor.cc_pos.y = ss->ss_cury; 739 stic_set_hwcurpos(si); 740 si->si_flags |= SI_CURENB_CHANGED; 741 742 /* 743 * XXX Since we don't yet receive vblank interrupts from the 744 * PXG, we must flush immediatley. 745 */ 746 if (si->si_disptype == WSDISPLAY_TYPE_PXG) 747 stic_flush(si); 748 749 /* Tell wscons that we're done. */ 750 if (si->si_switchcbarg != NULL) { 751 cookie = si->si_switchcbarg; 752 si->si_switchcbarg = NULL; 753 (*si->si_switchcb)(cookie, 0, 0); 754 } 755 } 756 757 static int 758 stic_alloc_attr(void *cookie, int fg, int bg, int flags, long *attr) 759 { 760 long tmp; 761 762 if ((flags & (WSATTR_BLINK | WSATTR_UNDERLINE)) != 0) 763 return (EINVAL); 764 765 if ((flags & WSATTR_WSCOLORS) == 0) { 766 fg = 7; 767 bg = 0; 768 } 769 770 if ((flags & WSATTR_HILIT) != 0) 771 fg += 8; 772 773 tmp = fg | (bg << 4); 774 *attr = tmp | (tmp << 16); 775 return (0); 776 } 777 778 static void 779 stic_erasecols(void *cookie, int row, int col, int num, long attr) 780 { 781 struct stic_info *si; 782 struct stic_screen *ss; 783 u_int32_t *pb; 784 u_int i, linewidth; 785 u_int16_t *p; 786 787 ss = cookie; 788 si = ss->ss_si; 789 790 if (ss->ss_backing != NULL) { 791 p = ss->ss_backing + row * si->si_consw + col; 792 for (i = num; i != 0; i--) 793 *p++ = (u_int16_t)attr; 794 } 795 if ((ss->ss_flags & SS_ACTIVE) == 0) 796 return; 797 798 col = (col * si->si_fontw) << 19; 799 num = (num * si->si_fontw) << 19; 800 row = row * si->si_fonth; 801 attr = (attr & 0xf0) >> 4; 802 linewidth = (si->si_fonth << 2) - 1; 803 row = (row << 3) + linewidth; 804 805 pb = (*si->si_pbuf_get)(si); 806 807 pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET; 808 pb[1] = 0x01ffffff; 809 pb[2] = 0; 810 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY; 811 pb[4] = linewidth; 812 pb[5] = DUPBYTE0(attr); 813 pb[6] = col | row; 814 pb[7] = (col + num) | row; 815 816 (*si->si_pbuf_post)(si, pb); 817 } 818 819 static void 820 stic_eraserows(void *cookie, int row, int num, long attr) 821 { 822 struct stic_info *si; 823 struct stic_screen *ss; 824 u_int linewidth, i; 825 u_int32_t *pb; 826 827 ss = cookie; 828 si = ss->ss_si; 829 830 if (ss->ss_backing != NULL) { 831 pb = (u_int32_t *)(ss->ss_backing + row * si->si_consw); 832 for (i = si->si_consw * num; i > 0; i -= 2) 833 *pb++ = (u_int32_t)attr; 834 } 835 if ((ss->ss_flags & SS_ACTIVE) == 0) 836 return; 837 838 row *= si->si_fonth; 839 num *= si->si_fonth; 840 attr = (attr & 0xf0) >> 4; 841 linewidth = (num << 2) - 1; 842 row = (row << 3) + linewidth; 843 844 pb = (*si->si_pbuf_get)(si); 845 846 pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET; 847 pb[1] = 0x01ffffff; 848 pb[2] = 0; 849 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY; 850 pb[4] = linewidth; 851 pb[5] = DUPBYTE0(attr); 852 pb[6] = row; 853 pb[7] = (1280 << 19) | row; 854 855 (*si->si_pbuf_post)(si, pb); 856 } 857 858 static void 859 stic_copyrows(void *cookie, int src, int dst, int height) 860 { 861 struct stic_info *si; 862 struct stic_screen *ss; 863 u_int32_t *pb, *pbs; 864 u_int num, inc, adj; 865 866 ss = cookie; 867 si = ss->ss_si; 868 869 if (ss->ss_backing != NULL) 870 bcopy(ss->ss_backing + src * si->si_consw, 871 ss->ss_backing + dst * si->si_consw, 872 si->si_consw * sizeof(*ss->ss_backing) * height); 873 if ((ss->ss_flags & SS_ACTIVE) == 0) 874 return; 875 876 /* 877 * We need to do this in reverse if the destination row is below 878 * the source. 879 */ 880 if (dst > src) { 881 src += height; 882 dst += height; 883 inc = -8; 884 adj = -1; 885 } else { 886 inc = 8; 887 adj = 0; 888 } 889 890 src = (src * si->si_fonth + adj) << 3; 891 dst = (dst * si->si_fonth + adj) << 3; 892 height *= si->si_fonth; 893 894 while (height > 0) { 895 num = (height < 255 ? height : 255); 896 height -= num; 897 898 pbs = (*si->si_pbuf_get)(si); 899 pb = pbs; 900 901 pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET; 902 pb[1] = (num << 24) | 0xffffff; 903 pb[2] = 0x0; 904 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN | 905 STAMP_COPYSPAN_ALIGNED; 906 pb[4] = 1; /* linewidth */ 907 908 for (; num != 0; num--, src += inc, dst += inc, pb += 3) { 909 pb[5] = 1280 << 3; 910 pb[6] = src; 911 pb[7] = dst; 912 } 913 914 (*si->si_pbuf_post)(si, pbs); 915 } 916 } 917 918 static void 919 stic_copycols(void *cookie, int row, int src, int dst, int num) 920 { 921 struct stic_info *si; 922 struct stic_screen *ss; 923 u_int height, updword; 924 u_int32_t *pb, *pbs; 925 926 ss = cookie; 927 si = ss->ss_si; 928 929 if (ss->ss_backing != NULL) 930 bcopy(ss->ss_backing + row * si->si_consw + src, 931 ss->ss_backing + row * si->si_consw + dst, 932 num * sizeof(*ss->ss_backing)); 933 if ((ss->ss_flags & SS_ACTIVE) == 0) 934 return; 935 936 /* 937 * The stamp reads and writes left -> right only, so we need to 938 * buffer the span if the source and destination regions overlap 939 * and the source is left of the destination. 940 */ 941 updword = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN; 942 943 if (src < dst && src + num > dst) 944 updword |= STAMP_HALF_BUFF; 945 946 row = (row * si->si_fonth) << 3; 947 num = (num * si->si_fontw) << 3; 948 src = row | ((src * si->si_fontw) << 19); 949 dst = row | ((dst * si->si_fontw) << 19); 950 height = si->si_fonth; 951 952 pbs = (*si->si_pbuf_get)(si); 953 pb = pbs; 954 955 pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET; 956 pb[1] = (height << 24) | 0xffffff; 957 pb[2] = 0x0; 958 pb[3] = updword; 959 pb[4] = 1; /* linewidth */ 960 961 for ( ; height != 0; height--, src += 8, dst += 8, pb += 3) { 962 pb[5] = num; 963 pb[6] = src; 964 pb[7] = dst; 965 } 966 967 (*si->si_pbuf_post)(si, pbs); 968 } 969 970 static void 971 stic_putchar(void *cookie, int r, int c, u_int uc, long attr) 972 { 973 struct wsdisplay_font *font; 974 struct stic_screen *ss; 975 struct stic_info *si; 976 u_int i, bgcolor, fgcolor; 977 u_int *pb, v1, v2, xya; 978 u_short *fr; 979 980 ss = cookie; 981 si = ss->ss_si; 982 983 /* It's cheaper to use erasecols() to blit blanks. */ 984 if (uc == 0) { 985 stic_erasecols(cookie, r, c, 1, attr); 986 return; 987 } 988 989 if (ss->ss_backing != NULL) 990 ss->ss_backing[r * si->si_consw + c] = 991 (u_short)((attr & 0xff) | (uc << 8)); 992 if ((ss->ss_flags & SS_ACTIVE) == 0) 993 return; 994 995 font = si->si_font; 996 pb = (*si->si_pbuf_get)(si); 997 998 /* 999 * Create a mask from the glyph. Squeeze the foreground color 1000 * through the mask, and then squeeze the background color through 1001 * the inverted mask. We may well read outside the glyph when 1002 * creating the mask, but it's bounded by the hardware so it 1003 * shouldn't matter a great deal... 1004 */ 1005 pb[0] = STAMP_CMD_LINES | STAMP_RGB_FLAT | STAMP_XY_PERPRIMATIVE | 1006 STAMP_LW_PERPRIMATIVE; 1007 pb[1] = font->fontheight > 16 ? 0x04ffffff : 0x02ffffff; 1008 pb[2] = 0x0; 1009 pb[3] = STAMP_UPDATE_ENABLE | STAMP_WE_XYMASK | STAMP_METHOD_COPY; 1010 1011 r *= font->fontheight; 1012 c *= font->fontwidth; 1013 uc = (uc - font->firstchar) * font->stride * font->fontheight; 1014 fr = (u_short *)((caddr_t)font->data + uc); 1015 bgcolor = DUPBYTE0((attr & 0xf0) >> 4); 1016 fgcolor = DUPBYTE0(attr & 0x0f); 1017 1018 i = ((font->fontheight > 16 ? 16 : font->fontheight) << 2) - 1; 1019 v1 = (c << 19) | ((r << 3) + i); 1020 v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff); 1021 xya = XYMASKADDR(si->si_stampw, si->si_stamph, c, r, 0, 0); 1022 1023 pb[4] = PACK(fr, 0); 1024 pb[5] = PACK(fr, 2); 1025 pb[6] = PACK(fr, 4); 1026 pb[7] = PACK(fr, 6); 1027 pb[8] = PACK(fr, 8); 1028 pb[9] = PACK(fr, 10); 1029 pb[10] = PACK(fr, 12); 1030 pb[11] = PACK(fr, 14); 1031 pb[12] = xya; 1032 pb[13] = v1; 1033 pb[14] = v2; 1034 pb[15] = i; 1035 pb[16] = fgcolor; 1036 1037 pb[17] = ~pb[4]; 1038 pb[18] = ~pb[5]; 1039 pb[19] = ~pb[6]; 1040 pb[20] = ~pb[7]; 1041 pb[21] = ~pb[8]; 1042 pb[22] = ~pb[9]; 1043 pb[23] = ~pb[10]; 1044 pb[24] = ~pb[11]; 1045 pb[25] = xya; 1046 pb[26] = v1; 1047 pb[27] = v2; 1048 pb[28] = i; 1049 pb[29] = bgcolor; 1050 1051 /* Two more squeezes for the lower part of the character. */ 1052 if (font->fontheight > 16) { 1053 i = ((font->fontheight - 16) << 2) - 1; 1054 r += 16; 1055 v1 = (c << 19) | ((r << 3) + i); 1056 v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff); 1057 1058 pb[30] = PACK(fr, 16); 1059 pb[31] = PACK(fr, 18); 1060 pb[32] = PACK(fr, 20); 1061 pb[33] = PACK(fr, 22); 1062 pb[34] = PACK(fr, 24); 1063 pb[35] = PACK(fr, 26); 1064 pb[36] = PACK(fr, 28); 1065 pb[37] = PACK(fr, 30); 1066 pb[38] = xya; 1067 pb[39] = v1; 1068 pb[40] = v2; 1069 pb[41] = i; 1070 pb[42] = fgcolor; 1071 1072 pb[43] = ~pb[30]; 1073 pb[44] = ~pb[31]; 1074 pb[45] = ~pb[32]; 1075 pb[46] = ~pb[33]; 1076 pb[47] = ~pb[34]; 1077 pb[48] = ~pb[35]; 1078 pb[49] = ~pb[36]; 1079 pb[50] = ~pb[37]; 1080 pb[51] = xya; 1081 pb[52] = v1; 1082 pb[53] = v2; 1083 pb[54] = i; 1084 pb[55] = bgcolor; 1085 } 1086 1087 (*si->si_pbuf_post)(si, pb); 1088 } 1089 1090 static int 1091 stic_mapchar(void *cookie, int c, u_int *cp) 1092 { 1093 struct stic_info *si; 1094 1095 si = ((struct stic_screen *)cookie)->ss_si; 1096 1097 if (c < si->si_font->firstchar || c == ' ') { 1098 *cp = 0; 1099 return (0); 1100 } 1101 1102 if (c - si->si_font->firstchar >= si->si_font->numchars) { 1103 *cp = 0; 1104 return (0); 1105 } 1106 1107 *cp = c; 1108 return (5); 1109 } 1110 1111 static void 1112 stic_cursor(void *cookie, int on, int row, int col) 1113 { 1114 struct stic_screen *ss; 1115 struct stic_info *si; 1116 1117 ss = cookie; 1118 si = ss->ss_si; 1119 1120 ss->ss_curx = col * si->si_fontw; 1121 ss->ss_cury = row * si->si_fonth; 1122 1123 if (on) 1124 ss->ss_flags |= SS_CURENB; 1125 else 1126 ss->ss_flags &= ~SS_CURENB; 1127 1128 if ((ss->ss_flags & SS_ACTIVE) != 0) { 1129 si->si_cursor.cc_pos.x = ss->ss_curx; 1130 si->si_cursor.cc_pos.y = ss->ss_cury; 1131 si->si_flags |= SI_CURENB_CHANGED; 1132 stic_set_hwcurpos(si); 1133 1134 /* 1135 * XXX Since we don't yet receive vblank interrupts from the 1136 * PXG, we must flush immediatley. 1137 */ 1138 if (si->si_disptype == WSDISPLAY_TYPE_PXG) 1139 stic_flush(si); 1140 } 1141 } 1142 1143 void 1144 stic_flush(struct stic_info *si) 1145 { 1146 volatile u_int32_t *vdac; 1147 int v; 1148 1149 if ((si->si_flags & SI_ALL_CHANGED) == 0) 1150 return; 1151 1152 vdac = si->si_vdac; 1153 v = si->si_flags; 1154 si->si_flags &= ~SI_ALL_CHANGED; 1155 1156 if ((v & SI_CURENB_CHANGED) != 0) { 1157 SELECT(vdac, BT459_IREG_CCR); 1158 if ((si->si_curscreen->ss_flags & SS_CURENB) != 0) 1159 REG(vdac, bt_reg) = 0x00c0c0c0; 1160 else 1161 REG(vdac, bt_reg) = 0x00000000; 1162 tc_wmb(); 1163 } 1164 1165 if ((v & SI_CURCMAP_CHANGED) != 0) { 1166 u_int8_t *cp; 1167 1168 cp = si->si_cursor.cc_color; 1169 1170 SELECT(vdac, BT459_IREG_CCOLOR_2); 1171 REG(vdac, bt_reg) = DUPBYTE0(cp[1]); tc_wmb(); 1172 REG(vdac, bt_reg) = DUPBYTE0(cp[3]); tc_wmb(); 1173 REG(vdac, bt_reg) = DUPBYTE0(cp[5]); tc_wmb(); 1174 REG(vdac, bt_reg) = DUPBYTE0(cp[0]); tc_wmb(); 1175 REG(vdac, bt_reg) = DUPBYTE0(cp[2]); tc_wmb(); 1176 REG(vdac, bt_reg) = DUPBYTE0(cp[4]); tc_wmb(); 1177 } 1178 1179 if ((v & SI_CURSHAPE_CHANGED) != 0) { 1180 u_int8_t *ip, *mp, img, msk; 1181 u_int8_t u; 1182 int bcnt; 1183 1184 ip = (u_int8_t *)si->si_cursor.cc_image; 1185 mp = (u_int8_t *)(si->si_cursor.cc_image + CURSOR_MAX_SIZE); 1186 1187 bcnt = 0; 1188 SELECT(vdac, BT459_IREG_CRAM_BASE+0); 1189 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 1190 while (bcnt < si->si_cursor.cc_size.y * 16) { 1191 /* pad right half 32 pixel when smaller than 33 */ 1192 if ((bcnt & 0x8) && si->si_cursor.cc_size.x < 33) { 1193 REG(vdac, bt_reg) = 0; tc_wmb(); 1194 REG(vdac, bt_reg) = 0; tc_wmb(); 1195 } else { 1196 img = *ip++; 1197 msk = *mp++; 1198 img &= msk; /* cookie off image */ 1199 u = (msk & 0x0f) << 4 | (img & 0x0f); 1200 REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]); 1201 tc_wmb(); 1202 u = (msk & 0xf0) | (img & 0xf0) >> 4; 1203 REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]); 1204 tc_wmb(); 1205 } 1206 bcnt += 2; 1207 } 1208 /* pad unoccupied scan lines */ 1209 while (bcnt < CURSOR_MAX_SIZE * 16) { 1210 REG(vdac, bt_reg) = 0; tc_wmb(); 1211 REG(vdac, bt_reg) = 0; tc_wmb(); 1212 bcnt += 2; 1213 } 1214 } 1215 1216 if ((v & SI_CMAP_CHANGED) != 0) { 1217 struct stic_hwcmap256 *cm; 1218 int index; 1219 1220 cm = &si->si_cmap; 1221 1222 SELECT(vdac, 0); 1223 SELECT(vdac, 0); 1224 for (index = 0; index < CMAP_SIZE; index++) { 1225 REG(vdac, bt_cmap) = DUPBYTE0(cm->r[index]); 1226 tc_wmb(); 1227 REG(vdac, bt_cmap) = DUPBYTE0(cm->g[index]); 1228 tc_wmb(); 1229 REG(vdac, bt_cmap) = DUPBYTE0(cm->b[index]); 1230 tc_wmb(); 1231 } 1232 } 1233 } 1234 1235 static int 1236 stic_get_cmap(struct stic_info *si, struct wsdisplay_cmap *p) 1237 { 1238 u_int index, count; 1239 1240 index = p->index; 1241 count = p->count; 1242 1243 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 1244 return (EINVAL); 1245 1246 if (!uvm_useracc(p->red, count, B_WRITE) || 1247 !uvm_useracc(p->green, count, B_WRITE) || 1248 !uvm_useracc(p->blue, count, B_WRITE)) 1249 return (EFAULT); 1250 1251 copyout(&si->si_cmap.r[index], p->red, count); 1252 copyout(&si->si_cmap.g[index], p->green, count); 1253 copyout(&si->si_cmap.b[index], p->blue, count); 1254 return (0); 1255 } 1256 1257 static int 1258 stic_set_cmap(struct stic_info *si, struct wsdisplay_cmap *p) 1259 { 1260 u_int index, count; 1261 1262 index = p->index; 1263 count = p->count; 1264 1265 if ((index + count) > CMAP_SIZE) 1266 return (EINVAL); 1267 1268 if (!uvm_useracc(p->red, count, B_READ) || 1269 !uvm_useracc(p->green, count, B_READ) || 1270 !uvm_useracc(p->blue, count, B_READ)) 1271 return (EFAULT); 1272 1273 copyin(p->red, &si->si_cmap.r[index], count); 1274 copyin(p->green, &si->si_cmap.g[index], count); 1275 copyin(p->blue, &si->si_cmap.b[index], count); 1276 1277 si->si_flags |= SI_CMAP_CHANGED; 1278 1279 /* 1280 * XXX Since we don't yet receive vblank interrupts from the PXG, we 1281 * must flush immediatley. 1282 */ 1283 if (si->si_disptype == WSDISPLAY_TYPE_PXG) 1284 stic_flush(si); 1285 1286 return (0); 1287 } 1288 1289 static int 1290 stic_set_cursor(struct stic_info *si, struct wsdisplay_cursor *p) 1291 { 1292 #define cc (&si->si_cursor) 1293 int v, index, count, icount; 1294 struct stic_screen *ss; 1295 1296 v = p->which; 1297 ss = si->si_curscreen; 1298 1299 if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) { 1300 index = p->cmap.index; 1301 count = p->cmap.count; 1302 if (index >= 2 || (index + count) > 2) 1303 return (EINVAL); 1304 if (!uvm_useracc(p->cmap.red, count, B_READ) || 1305 !uvm_useracc(p->cmap.green, count, B_READ) || 1306 !uvm_useracc(p->cmap.blue, count, B_READ)) 1307 return (EFAULT); 1308 } 1309 1310 if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) { 1311 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE) 1312 return (EINVAL); 1313 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y; 1314 if (!uvm_useracc(p->image, icount, B_READ) || 1315 !uvm_useracc(p->mask, icount, B_READ)) 1316 return (EFAULT); 1317 } 1318 1319 if ((v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) != 0) { 1320 if (v & WSDISPLAY_CURSOR_DOCUR) 1321 cc->cc_hot = p->hot; 1322 if (v & WSDISPLAY_CURSOR_DOPOS) 1323 stic_set_curpos(si, &p->pos); 1324 } 1325 1326 if ((v & WSDISPLAY_CURSOR_DOCUR) != 0) { 1327 if (p->enable) 1328 ss->ss_flags |= SS_CURENB; 1329 else 1330 ss->ss_flags &= ~SS_CURENB; 1331 si->si_flags |= SI_CURENB_CHANGED; 1332 } 1333 1334 if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) { 1335 copyin(p->cmap.red, &cc->cc_color[index], count); 1336 copyin(p->cmap.green, &cc->cc_color[index + 2], count); 1337 copyin(p->cmap.blue, &cc->cc_color[index + 4], count); 1338 si->si_flags |= SI_CURCMAP_CHANGED; 1339 } 1340 1341 if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) { 1342 cc->cc_size = p->size; 1343 memset(cc->cc_image, 0, sizeof cc->cc_image); 1344 copyin(p->image, cc->cc_image, icount); 1345 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount); 1346 si->si_flags |= SI_CURSHAPE_CHANGED; 1347 } 1348 1349 /* 1350 * XXX Since we don't yet receive vblank interrupts from the PXG, we 1351 * must flush immediatley. 1352 */ 1353 if (si->si_disptype == WSDISPLAY_TYPE_PXG) 1354 stic_flush(si); 1355 1356 return (0); 1357 #undef cc 1358 } 1359 1360 static int 1361 stic_get_cursor(struct stic_info *si, struct wsdisplay_cursor *p) 1362 { 1363 1364 /* XXX */ 1365 return (ENOTTY); 1366 } 1367 1368 static void 1369 stic_set_curpos(struct stic_info *si, struct wsdisplay_curpos *curpos) 1370 { 1371 int x, y; 1372 1373 x = curpos->x; 1374 y = curpos->y; 1375 1376 if (y < 0) 1377 y = 0; 1378 else if (y > 1023) 1379 y = 1023; 1380 if (x < 0) 1381 x = 0; 1382 else if (x > 1279) 1383 x = 1279; 1384 1385 si->si_cursor.cc_pos.x = x; 1386 si->si_cursor.cc_pos.y = y; 1387 stic_set_hwcurpos(si); 1388 } 1389 1390 static void 1391 stic_set_hwcurpos(struct stic_info *si) 1392 { 1393 volatile u_int32_t *vdac; 1394 int x, y, s; 1395 1396 vdac = si->si_vdac; 1397 1398 x = si->si_cursor.cc_pos.x - si->si_cursor.cc_hot.x; 1399 y = si->si_cursor.cc_pos.y - si->si_cursor.cc_hot.y; 1400 x += STIC_MAGIC_X; 1401 y += STIC_MAGIC_Y; 1402 1403 s = spltty(); 1404 SELECT(vdac, BT459_IREG_CURSOR_X_LOW); 1405 REG(vdac, bt_reg) = DUPBYTE0(x); tc_wmb(); 1406 REG(vdac, bt_reg) = DUPBYTE1(x); tc_wmb(); 1407 REG(vdac, bt_reg) = DUPBYTE0(y); tc_wmb(); 1408 REG(vdac, bt_reg) = DUPBYTE1(y); tc_wmb(); 1409 splx(s); 1410 } 1411