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