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