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