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