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