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