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