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