1 /* $NetBSD: stic.c,v 1.14 2002/02/11 10:44:40 wiz 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.14 2002/02/11 10:44:40 wiz 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|M_ZERO); 637 } 638 639 int 640 stic_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 641 int *curxp, int *curyp, long *attrp) 642 { 643 struct stic_info *si; 644 struct stic_screen *ss; 645 646 si = (struct stic_info *)v; 647 648 if ((stic_consscr.ss_flags & SS_ALLOCED) == 0) 649 ss = &stic_consscr; 650 else { 651 ss = malloc(sizeof(*ss), M_DEVBUF, M_WAITOK|M_ZERO); 652 } 653 stic_setup_backing(si, ss); 654 655 ss->ss_si = si; 656 ss->ss_flags = SS_ALLOCED | SS_CURENB; 657 658 *cookiep = ss; 659 *curxp = 0; 660 *curyp = 0; 661 662 stic_alloc_attr(ss, 0, 0, 0, attrp); 663 return (0); 664 } 665 666 void 667 stic_free_screen(void *v, void *cookie) 668 { 669 struct stic_screen *ss; 670 671 ss = cookie; 672 673 #ifdef DIAGNOSTIC 674 if (ss == &stic_consscr) 675 panic("stic_free_screen: console"); 676 if (ss == ((struct stic_info *)v)->si_curscreen) 677 panic("stic_free_screen: freeing current screen"); 678 #endif 679 680 free(ss->ss_backing, M_DEVBUF); 681 free(ss, M_DEVBUF); 682 } 683 684 int 685 stic_show_screen(void *v, void *cookie, int waitok, 686 void (*cb)(void *, int, int), void *cbarg) 687 { 688 struct stic_info *si; 689 690 si = (struct stic_info *)v; 691 if (si->si_switchcbarg != NULL) 692 return (EAGAIN); 693 si->si_switchcb = cb; 694 si->si_switchcbarg = cbarg; 695 696 if (cb != NULL) { 697 callout_reset(&si->si_switch_callout, 0, stic_do_switch, 698 cookie); 699 return (EAGAIN); 700 } 701 702 stic_do_switch(cookie); 703 return (0); 704 } 705 706 void 707 stic_do_switch(void *cookie) 708 { 709 struct stic_screen *ss; 710 struct stic_info *si; 711 u_int r, c, nr, nc; 712 u_int16_t *p, *sp; 713 714 ss = cookie; 715 si = ss->ss_si; 716 717 #ifdef DIAGNOSTIC 718 if (ss->ss_backing == NULL) 719 panic("stic_do_switch: screen not backed"); 720 #endif 721 722 /* Swap in the new screen, and temporarily disable its backing. */ 723 if (si->si_curscreen != NULL) 724 si->si_curscreen->ss_flags ^= SS_ACTIVE; 725 si->si_curscreen = ss; 726 ss->ss_flags |= SS_ACTIVE; 727 sp = ss->ss_backing; 728 ss->ss_backing = NULL; 729 730 /* 731 * We assume that most of the screen is blank and blast it with 732 * eraserows(), because eraserows() is cheap. 733 */ 734 nr = si->si_consh; 735 stic_eraserows(ss, 0, nr, 0); 736 737 nc = si->si_consw; 738 p = sp; 739 for (r = 0; r < nr; r++) 740 for (c = 0; c < nc; c += 2, p += 2) { 741 if ((p[0] & 0xfff0) != 0) 742 stic_putchar(ss, r, c, p[0] >> 8, 743 p[0] & 0x00ff); 744 if ((p[1] & 0xfff0) != 0) 745 stic_putchar(ss, r, c + 1, p[1] >> 8, 746 p[1] & 0x00ff); 747 } 748 749 /* 750 * Re-enable the screen's backing, and move the cursor to the 751 * correct spot. 752 */ 753 ss->ss_backing = sp; 754 si->si_cursor.cc_pos.x = ss->ss_curx; 755 si->si_cursor.cc_pos.y = ss->ss_cury; 756 stic_set_hwcurpos(si); 757 si->si_flags |= SI_CURENB_CHANGED; 758 759 /* 760 * XXX Since we don't yet receive vblank interrupts from the 761 * PXG, we must flush immediatley. 762 */ 763 if (si->si_disptype == WSDISPLAY_TYPE_PXG) 764 stic_flush(si); 765 766 /* Tell wscons that we're done. */ 767 if (si->si_switchcbarg != NULL) { 768 cookie = si->si_switchcbarg; 769 si->si_switchcbarg = NULL; 770 (*si->si_switchcb)(cookie, 0, 0); 771 } 772 } 773 774 int 775 stic_alloc_attr(void *cookie, int fg, int bg, int flags, long *attr) 776 { 777 long tmp; 778 779 if ((flags & (WSATTR_BLINK | WSATTR_UNDERLINE)) != 0) 780 return (EINVAL); 781 782 if ((flags & WSATTR_WSCOLORS) == 0) { 783 fg = 7; 784 bg = 0; 785 } 786 787 if ((flags & WSATTR_HILIT) != 0) 788 fg += 8; 789 790 tmp = fg | (bg << 4); 791 *attr = tmp | (tmp << 16); 792 return (0); 793 } 794 795 void 796 stic_erasecols(void *cookie, int row, int col, int num, long attr) 797 { 798 struct stic_info *si; 799 struct stic_screen *ss; 800 u_int32_t *pb; 801 u_int i, linewidth; 802 u_int16_t *p; 803 804 ss = cookie; 805 si = ss->ss_si; 806 807 if (ss->ss_backing != NULL) { 808 p = ss->ss_backing + row * si->si_consw + col; 809 for (i = num; i != 0; i--) 810 *p++ = (u_int16_t)attr; 811 } 812 if ((ss->ss_flags & SS_ACTIVE) == 0) 813 return; 814 815 col = (col * si->si_fontw) << 19; 816 num = (num * si->si_fontw) << 19; 817 row = row * si->si_fonth; 818 attr = (attr & 0xf0) >> 4; 819 linewidth = (si->si_fonth << 2) - 1; 820 row = (row << 3) + linewidth; 821 822 pb = (*si->si_pbuf_get)(si); 823 824 pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET; 825 pb[1] = 0x01ffffff; 826 pb[2] = 0; 827 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY; 828 pb[4] = linewidth; 829 pb[5] = DUPBYTE0(attr); 830 pb[6] = col | row; 831 pb[7] = (col + num) | row; 832 833 (*si->si_pbuf_post)(si, pb); 834 } 835 836 void 837 stic_eraserows(void *cookie, int row, int num, long attr) 838 { 839 struct stic_info *si; 840 struct stic_screen *ss; 841 u_int linewidth, i; 842 u_int32_t *pb; 843 844 ss = cookie; 845 si = ss->ss_si; 846 847 if (ss->ss_backing != NULL) { 848 pb = (u_int32_t *)(ss->ss_backing + row * si->si_consw); 849 for (i = si->si_consw * num; i > 0; i -= 2) 850 *pb++ = (u_int32_t)attr; 851 } 852 if ((ss->ss_flags & SS_ACTIVE) == 0) 853 return; 854 855 row *= si->si_fonth; 856 num *= si->si_fonth; 857 attr = (attr & 0xf0) >> 4; 858 linewidth = (num << 2) - 1; 859 row = (row << 3) + linewidth; 860 861 pb = (*si->si_pbuf_get)(si); 862 863 pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET; 864 pb[1] = 0x01ffffff; 865 pb[2] = 0; 866 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY; 867 pb[4] = linewidth; 868 pb[5] = DUPBYTE0(attr); 869 pb[6] = row; 870 pb[7] = (1280 << 19) | row; 871 872 (*si->si_pbuf_post)(si, pb); 873 } 874 875 void 876 stic_copyrows(void *cookie, int src, int dst, int height) 877 { 878 struct stic_info *si; 879 struct stic_screen *ss; 880 u_int32_t *pb, *pbs; 881 u_int num, inc, adj; 882 883 ss = cookie; 884 si = ss->ss_si; 885 886 if (ss->ss_backing != NULL) 887 bcopy(ss->ss_backing + src * si->si_consw, 888 ss->ss_backing + dst * si->si_consw, 889 si->si_consw * sizeof(*ss->ss_backing) * height); 890 if ((ss->ss_flags & SS_ACTIVE) == 0) 891 return; 892 893 /* 894 * We need to do this in reverse if the destination row is below 895 * the source. 896 */ 897 if (dst > src) { 898 src += height; 899 dst += height; 900 inc = -8; 901 adj = -1; 902 } else { 903 inc = 8; 904 adj = 0; 905 } 906 907 src = (src * si->si_fonth + adj) << 3; 908 dst = (dst * si->si_fonth + adj) << 3; 909 height *= si->si_fonth; 910 911 while (height > 0) { 912 num = (height < 255 ? height : 255); 913 height -= num; 914 915 pbs = (*si->si_pbuf_get)(si); 916 pb = pbs; 917 918 pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET; 919 pb[1] = (num << 24) | 0xffffff; 920 pb[2] = 0x0; 921 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN | 922 STAMP_COPYSPAN_ALIGNED; 923 pb[4] = 1; /* linewidth */ 924 925 for (; num != 0; num--, src += inc, dst += inc, pb += 3) { 926 pb[5] = 1280 << 3; 927 pb[6] = src; 928 pb[7] = dst; 929 } 930 931 (*si->si_pbuf_post)(si, pbs); 932 } 933 } 934 935 void 936 stic_copycols(void *cookie, int row, int src, int dst, int num) 937 { 938 struct stic_info *si; 939 struct stic_screen *ss; 940 u_int height, updword; 941 u_int32_t *pb, *pbs; 942 943 ss = cookie; 944 si = ss->ss_si; 945 946 if (ss->ss_backing != NULL) 947 bcopy(ss->ss_backing + row * si->si_consw + src, 948 ss->ss_backing + row * si->si_consw + dst, 949 num * sizeof(*ss->ss_backing)); 950 if ((ss->ss_flags & SS_ACTIVE) == 0) 951 return; 952 953 /* 954 * The stamp reads and writes left -> right only, so we need to 955 * buffer the span if the source and destination regions overlap 956 * and the source is left of the destination. 957 */ 958 updword = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN; 959 960 if (src < dst && src + num > dst) 961 updword |= STAMP_HALF_BUFF; 962 963 row = (row * si->si_fonth) << 3; 964 num = (num * si->si_fontw) << 3; 965 src = row | ((src * si->si_fontw) << 19); 966 dst = row | ((dst * si->si_fontw) << 19); 967 height = si->si_fonth; 968 969 pbs = (*si->si_pbuf_get)(si); 970 pb = pbs; 971 972 pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET; 973 pb[1] = (height << 24) | 0xffffff; 974 pb[2] = 0x0; 975 pb[3] = updword; 976 pb[4] = 1; /* linewidth */ 977 978 for ( ; height != 0; height--, src += 8, dst += 8, pb += 3) { 979 pb[5] = num; 980 pb[6] = src; 981 pb[7] = dst; 982 } 983 984 (*si->si_pbuf_post)(si, pbs); 985 } 986 987 void 988 stic_putchar(void *cookie, int r, int c, u_int uc, long attr) 989 { 990 struct wsdisplay_font *font; 991 struct stic_screen *ss; 992 struct stic_info *si; 993 u_int i, bgcolor, fgcolor; 994 u_int *pb, v1, v2, xya; 995 u_short *fr; 996 997 ss = cookie; 998 si = ss->ss_si; 999 1000 /* It's cheaper to use erasecols() to blit blanks. */ 1001 if (uc == 0) { 1002 stic_erasecols(cookie, r, c, 1, attr); 1003 return; 1004 } 1005 1006 if (ss->ss_backing != NULL) 1007 ss->ss_backing[r * si->si_consw + c] = 1008 (u_short)((attr & 0xff) | (uc << 8)); 1009 if ((ss->ss_flags & SS_ACTIVE) == 0) 1010 return; 1011 1012 font = si->si_font; 1013 pb = (*si->si_pbuf_get)(si); 1014 1015 /* 1016 * Create a mask from the glyph. Squeeze the foreground color 1017 * through the mask, and then squeeze the background color through 1018 * the inverted mask. We may well read outside the glyph when 1019 * creating the mask, but it's bounded by the hardware so it 1020 * shouldn't matter a great deal... 1021 */ 1022 pb[0] = STAMP_CMD_LINES | STAMP_RGB_FLAT | STAMP_XY_PERPRIMATIVE | 1023 STAMP_LW_PERPRIMATIVE; 1024 pb[1] = font->fontheight > 16 ? 0x04ffffff : 0x02ffffff; 1025 pb[2] = 0x0; 1026 pb[3] = STAMP_UPDATE_ENABLE | STAMP_WE_XYMASK | STAMP_METHOD_COPY; 1027 1028 r *= font->fontheight; 1029 c *= font->fontwidth; 1030 uc = (uc - font->firstchar) * font->stride * font->fontheight; 1031 fr = (u_short *)((caddr_t)font->data + uc); 1032 bgcolor = DUPBYTE0((attr & 0xf0) >> 4); 1033 fgcolor = DUPBYTE0(attr & 0x0f); 1034 1035 i = ((font->fontheight > 16 ? 16 : font->fontheight) << 2) - 1; 1036 v1 = (c << 19) | ((r << 3) + i); 1037 v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff); 1038 xya = XYMASKADDR(si->si_stampw, si->si_stamph, c, r, 0, 0); 1039 1040 pb[4] = PACK(fr, 0); 1041 pb[5] = PACK(fr, 2); 1042 pb[6] = PACK(fr, 4); 1043 pb[7] = PACK(fr, 6); 1044 pb[8] = PACK(fr, 8); 1045 pb[9] = PACK(fr, 10); 1046 pb[10] = PACK(fr, 12); 1047 pb[11] = PACK(fr, 14); 1048 pb[12] = xya; 1049 pb[13] = v1; 1050 pb[14] = v2; 1051 pb[15] = i; 1052 pb[16] = fgcolor; 1053 1054 pb[17] = ~pb[4]; 1055 pb[18] = ~pb[5]; 1056 pb[19] = ~pb[6]; 1057 pb[20] = ~pb[7]; 1058 pb[21] = ~pb[8]; 1059 pb[22] = ~pb[9]; 1060 pb[23] = ~pb[10]; 1061 pb[24] = ~pb[11]; 1062 pb[25] = xya; 1063 pb[26] = v1; 1064 pb[27] = v2; 1065 pb[28] = i; 1066 pb[29] = bgcolor; 1067 1068 /* Two more squeezes for the lower part of the character. */ 1069 if (font->fontheight > 16) { 1070 i = ((font->fontheight - 16) << 2) - 1; 1071 r += 16; 1072 v1 = (c << 19) | ((r << 3) + i); 1073 v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff); 1074 1075 pb[30] = PACK(fr, 16); 1076 pb[31] = PACK(fr, 18); 1077 pb[32] = PACK(fr, 20); 1078 pb[33] = PACK(fr, 22); 1079 pb[34] = PACK(fr, 24); 1080 pb[35] = PACK(fr, 26); 1081 pb[36] = PACK(fr, 28); 1082 pb[37] = PACK(fr, 30); 1083 pb[38] = xya; 1084 pb[39] = v1; 1085 pb[40] = v2; 1086 pb[41] = i; 1087 pb[42] = fgcolor; 1088 1089 pb[43] = ~pb[30]; 1090 pb[44] = ~pb[31]; 1091 pb[45] = ~pb[32]; 1092 pb[46] = ~pb[33]; 1093 pb[47] = ~pb[34]; 1094 pb[48] = ~pb[35]; 1095 pb[49] = ~pb[36]; 1096 pb[50] = ~pb[37]; 1097 pb[51] = xya; 1098 pb[52] = v1; 1099 pb[53] = v2; 1100 pb[54] = i; 1101 pb[55] = bgcolor; 1102 } 1103 1104 (*si->si_pbuf_post)(si, pb); 1105 } 1106 1107 int 1108 stic_mapchar(void *cookie, int c, u_int *cp) 1109 { 1110 struct stic_info *si; 1111 1112 si = ((struct stic_screen *)cookie)->ss_si; 1113 1114 if (c < si->si_font->firstchar || c == ' ') { 1115 *cp = 0; 1116 return (0); 1117 } 1118 1119 if (c - si->si_font->firstchar >= si->si_font->numchars) { 1120 *cp = 0; 1121 return (0); 1122 } 1123 1124 *cp = c; 1125 return (5); 1126 } 1127 1128 void 1129 stic_cursor(void *cookie, int on, int row, int col) 1130 { 1131 struct stic_screen *ss; 1132 struct stic_info *si; 1133 int s; 1134 1135 ss = cookie; 1136 si = ss->ss_si; 1137 1138 ss->ss_curx = col * si->si_fontw; 1139 ss->ss_cury = row * si->si_fonth; 1140 1141 s = spltty(); 1142 1143 if (on) 1144 ss->ss_flags |= SS_CURENB; 1145 else 1146 ss->ss_flags &= ~SS_CURENB; 1147 1148 if ((ss->ss_flags & SS_ACTIVE) != 0) { 1149 si->si_cursor.cc_pos.x = ss->ss_curx; 1150 si->si_cursor.cc_pos.y = ss->ss_cury; 1151 si->si_flags |= SI_CURENB_CHANGED; 1152 stic_set_hwcurpos(si); 1153 1154 /* 1155 * XXX Since we don't yet receive vblank interrupts from the 1156 * PXG, we must flush immediatley. 1157 */ 1158 if (si->si_disptype == WSDISPLAY_TYPE_PXG) 1159 stic_flush(si); 1160 } 1161 1162 splx(s); 1163 } 1164 1165 void 1166 stic_flush(struct stic_info *si) 1167 { 1168 volatile u_int32_t *vdac; 1169 int v; 1170 1171 if ((si->si_flags & SI_ALL_CHANGED) == 0) 1172 return; 1173 1174 vdac = si->si_vdac; 1175 v = si->si_flags; 1176 si->si_flags &= ~SI_ALL_CHANGED; 1177 1178 if ((v & SI_CURENB_CHANGED) != 0) { 1179 SELECT(vdac, BT459_IREG_CCR); 1180 if ((si->si_curscreen->ss_flags & SS_CURENB) != 0) 1181 REG(vdac, bt_reg) = 0x00c0c0c0; 1182 else 1183 REG(vdac, bt_reg) = 0x00000000; 1184 tc_wmb(); 1185 } 1186 1187 if ((v & SI_CURCMAP_CHANGED) != 0) { 1188 u_int8_t *cp; 1189 1190 cp = si->si_cursor.cc_color; 1191 1192 SELECT(vdac, BT459_IREG_CCOLOR_2); 1193 REG(vdac, bt_reg) = DUPBYTE0(cp[1]); tc_wmb(); 1194 REG(vdac, bt_reg) = DUPBYTE0(cp[3]); tc_wmb(); 1195 REG(vdac, bt_reg) = DUPBYTE0(cp[5]); tc_wmb(); 1196 REG(vdac, bt_reg) = DUPBYTE0(cp[0]); tc_wmb(); 1197 REG(vdac, bt_reg) = DUPBYTE0(cp[2]); tc_wmb(); 1198 REG(vdac, bt_reg) = DUPBYTE0(cp[4]); tc_wmb(); 1199 } 1200 1201 if ((v & SI_CURSHAPE_CHANGED) != 0) { 1202 u_int8_t *ip, *mp, img, msk; 1203 u_int8_t u; 1204 int bcnt; 1205 1206 ip = (u_int8_t *)si->si_cursor.cc_image; 1207 mp = (u_int8_t *)(si->si_cursor.cc_image + CURSOR_MAX_SIZE); 1208 1209 bcnt = 0; 1210 SELECT(vdac, BT459_IREG_CRAM_BASE); 1211 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 1212 while (bcnt < CURSOR_MAX_SIZE * 16) { 1213 img = *ip++; 1214 msk = *mp++; 1215 img &= msk; /* cookie off image */ 1216 u = (msk & 0x0f) << 4 | (img & 0x0f); 1217 REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]); 1218 tc_wmb(); 1219 u = (msk & 0xf0) | (img & 0xf0) >> 4; 1220 REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]); 1221 tc_wmb(); 1222 bcnt += 2; 1223 } 1224 } 1225 1226 if ((v & SI_CMAP_CHANGED) != 0) { 1227 struct stic_hwcmap256 *cm; 1228 int index; 1229 1230 cm = &si->si_cmap; 1231 1232 SELECT(vdac, 0); 1233 SELECT(vdac, 0); 1234 for (index = 0; index < CMAP_SIZE; index++) { 1235 REG(vdac, bt_cmap) = DUPBYTE0(cm->r[index]); 1236 tc_wmb(); 1237 REG(vdac, bt_cmap) = DUPBYTE0(cm->g[index]); 1238 tc_wmb(); 1239 REG(vdac, bt_cmap) = DUPBYTE0(cm->b[index]); 1240 tc_wmb(); 1241 } 1242 } 1243 } 1244 1245 int 1246 stic_get_cmap(struct stic_info *si, struct wsdisplay_cmap *p) 1247 { 1248 u_int index, count; 1249 1250 index = p->index; 1251 count = p->count; 1252 1253 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 1254 return (EINVAL); 1255 1256 if (!uvm_useracc(p->red, count, B_WRITE) || 1257 !uvm_useracc(p->green, count, B_WRITE) || 1258 !uvm_useracc(p->blue, count, B_WRITE)) 1259 return (EFAULT); 1260 1261 copyout(&si->si_cmap.r[index], p->red, count); 1262 copyout(&si->si_cmap.g[index], p->green, count); 1263 copyout(&si->si_cmap.b[index], p->blue, count); 1264 return (0); 1265 } 1266 1267 int 1268 stic_set_cmap(struct stic_info *si, struct wsdisplay_cmap *p) 1269 { 1270 u_int index, count; 1271 int s; 1272 1273 index = p->index; 1274 count = p->count; 1275 1276 if ((index + count) > CMAP_SIZE) 1277 return (EINVAL); 1278 1279 if (!uvm_useracc(p->red, count, B_READ) || 1280 !uvm_useracc(p->green, count, B_READ) || 1281 !uvm_useracc(p->blue, count, B_READ)) 1282 return (EFAULT); 1283 1284 s = spltty(); 1285 copyin(p->red, &si->si_cmap.r[index], count); 1286 copyin(p->green, &si->si_cmap.g[index], count); 1287 copyin(p->blue, &si->si_cmap.b[index], count); 1288 si->si_flags |= SI_CMAP_CHANGED; 1289 splx(s); 1290 1291 /* 1292 * XXX Since we don't yet receive vblank interrupts from the PXG, we 1293 * must flush immediatley. 1294 */ 1295 if (si->si_disptype == WSDISPLAY_TYPE_PXG) 1296 stic_flush(si); 1297 1298 return (0); 1299 } 1300 1301 int 1302 stic_set_cursor(struct stic_info *si, struct wsdisplay_cursor *p) 1303 { 1304 #define cc (&si->si_cursor) 1305 u_int v, index, count, icount; 1306 struct stic_screen *ss; 1307 int s; 1308 1309 v = p->which; 1310 ss = si->si_curscreen; 1311 1312 if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) { 1313 index = p->cmap.index; 1314 count = p->cmap.count; 1315 if (index >= 2 || (index + count) > 2) 1316 return (EINVAL); 1317 if (!uvm_useracc(p->cmap.red, count, B_READ) || 1318 !uvm_useracc(p->cmap.green, count, B_READ) || 1319 !uvm_useracc(p->cmap.blue, count, B_READ)) 1320 return (EFAULT); 1321 } 1322 1323 if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) { 1324 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE) 1325 return (EINVAL); 1326 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y; 1327 if (!uvm_useracc(p->image, icount, B_READ) || 1328 !uvm_useracc(p->mask, icount, B_READ)) 1329 return (EFAULT); 1330 } 1331 1332 if ((v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) != 0) { 1333 if (v & WSDISPLAY_CURSOR_DOCUR) 1334 cc->cc_hot = p->hot; 1335 if (v & WSDISPLAY_CURSOR_DOPOS) 1336 stic_set_curpos(si, &p->pos); 1337 } 1338 1339 s = spltty(); 1340 1341 if ((v & WSDISPLAY_CURSOR_DOCUR) != 0) { 1342 if (p->enable) 1343 ss->ss_flags |= SS_CURENB; 1344 else 1345 ss->ss_flags &= ~SS_CURENB; 1346 si->si_flags |= SI_CURENB_CHANGED; 1347 } 1348 1349 if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) { 1350 copyin(p->cmap.red, &cc->cc_color[index], count); 1351 copyin(p->cmap.green, &cc->cc_color[index + 2], count); 1352 copyin(p->cmap.blue, &cc->cc_color[index + 4], count); 1353 si->si_flags |= SI_CURCMAP_CHANGED; 1354 } 1355 1356 if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) { 1357 memset(cc->cc_image, 0, sizeof(cc->cc_image)); 1358 copyin(p->image, cc->cc_image, icount); 1359 copyin(p->mask, cc->cc_image + CURSOR_MAX_SIZE, icount); 1360 si->si_flags |= SI_CURSHAPE_CHANGED; 1361 } 1362 1363 splx(s); 1364 1365 /* 1366 * XXX Since we don't yet receive vblank interrupts from the PXG, we 1367 * must flush immediatley. 1368 */ 1369 if (si->si_disptype == WSDISPLAY_TYPE_PXG) 1370 stic_flush(si); 1371 1372 return (0); 1373 #undef cc 1374 } 1375 1376 int 1377 stic_get_cursor(struct stic_info *si, struct wsdisplay_cursor *p) 1378 { 1379 1380 /* XXX */ 1381 return (ENOTTY); 1382 } 1383 1384 void 1385 stic_set_curpos(struct stic_info *si, struct wsdisplay_curpos *curpos) 1386 { 1387 int x, y; 1388 1389 x = curpos->x; 1390 y = curpos->y; 1391 1392 if (y < 0) 1393 y = 0; 1394 else if (y > 1023) 1395 y = 1023; 1396 if (x < 0) 1397 x = 0; 1398 else if (x > 1279) 1399 x = 1279; 1400 1401 si->si_cursor.cc_pos.x = x; 1402 si->si_cursor.cc_pos.y = y; 1403 stic_set_hwcurpos(si); 1404 } 1405 1406 void 1407 stic_set_hwcurpos(struct stic_info *si) 1408 { 1409 volatile u_int32_t *vdac; 1410 int x, y, s; 1411 1412 vdac = si->si_vdac; 1413 1414 x = si->si_cursor.cc_pos.x - si->si_cursor.cc_hot.x; 1415 y = si->si_cursor.cc_pos.y - si->si_cursor.cc_hot.y; 1416 x += STIC_MAGIC_X; 1417 y += STIC_MAGIC_Y; 1418 1419 s = spltty(); 1420 SELECT(vdac, BT459_IREG_CURSOR_X_LOW); 1421 REG(vdac, bt_reg) = DUPBYTE0(x); tc_wmb(); 1422 REG(vdac, bt_reg) = DUPBYTE1(x); tc_wmb(); 1423 REG(vdac, bt_reg) = DUPBYTE0(y); tc_wmb(); 1424 REG(vdac, bt_reg) = DUPBYTE1(y); tc_wmb(); 1425 splx(s); 1426 } 1427 1428 /* 1429 * STIC control inteface. We have a separate device for mapping the board, 1430 * because access to the DMA engine means that it's possible to circumvent 1431 * the securelevel mechanism. Given the way devices work in the BSD kernel, 1432 * and given the unfortunate design of the mmap() call it's near impossible 1433 * to protect against this using a shared device (i.e. wsdisplay). 1434 * 1435 * This is a gross hack... Hopefully not too many other devices will need 1436 * it. 1437 */ 1438 int 1439 sticopen(dev_t dev, int flag, int mode, struct proc *p) 1440 { 1441 struct stic_info *si; 1442 int s; 1443 1444 if (securelevel > 0) 1445 return (EPERM); 1446 if (minor(dev) >= STIC_MAXDV) 1447 return (ENXIO); 1448 if ((si = stic_info[minor(dev)]) == NULL) 1449 return (ENXIO); 1450 1451 s = spltty(); 1452 if ((si->si_flags & SI_DVOPEN) != 0) { 1453 splx(s); 1454 return (EBUSY); 1455 } 1456 si->si_flags |= SI_DVOPEN; 1457 splx(s); 1458 1459 return (0); 1460 } 1461 1462 int 1463 sticclose(dev_t dev, int flag, int mode, struct proc *p) 1464 { 1465 struct stic_info *si; 1466 int s; 1467 1468 si = stic_info[minor(dev)]; 1469 s = spltty(); 1470 si->si_flags &= ~SI_DVOPEN; 1471 splx(s); 1472 1473 return (0); 1474 } 1475 1476 paddr_t 1477 sticmmap(dev_t dev, off_t offset, int prot) 1478 { 1479 struct stic_info *si; 1480 struct stic_xmap *sxm; 1481 paddr_t pa; 1482 1483 si = stic_info[minor(dev)]; 1484 sxm = NULL; 1485 1486 if (securelevel > 0) 1487 return (-1L); 1488 if (si->si_dispmode != WSDISPLAYIO_MODE_MAPPED) 1489 return (-1L); 1490 1491 if (offset < 0) 1492 return ((paddr_t)-1L); 1493 1494 if (offset < sizeof(sxm->sxm_stic)) { 1495 pa = STIC_KSEG_TO_PHYS(si->si_stic); 1496 return (machine_btop(pa + offset)); 1497 } 1498 offset -= sizeof(sxm->sxm_stic); 1499 1500 if (offset < sizeof(sxm->sxm_poll)) { 1501 pa = STIC_KSEG_TO_PHYS(si->si_slotbase); 1502 return (machine_btop(pa + offset)); 1503 } 1504 offset -= sizeof(sxm->sxm_poll); 1505 1506 if (offset < si->si_buf_size) 1507 return (machine_btop(si->si_buf_phys + offset)); 1508 1509 return ((paddr_t)-1L); 1510 } 1511