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