stic.c revision 1.8 1 /* $NetBSD: stic.c,v 1.8 2001/03/04 13:32:25 ad Exp $ */
2
3 /*-
4 * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Copyright (c) 1998, 1999 Tohru Nishimura. All rights reserved.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement:
52 * This product includes software developed by Tohru Nishimura
53 * for the NetBSD Project.
54 * 4. The name of the author may not be used to endorse or promote products
55 * derived from this software without specific prior written permission
56 *
57 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
58 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
59 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
60 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
61 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
62 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
63 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
64 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
65 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
66 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67 */
68
69 /*
70 * Driver for the DEC PixelStamp interface chip (STIC).
71 *
72 * XXX The bt459 interface shouldn't be replicated here.
73 */
74
75 #include <sys/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/vmparam.h>
93 #include <machine/bus.h>
94 #include <machine/intr.h>
95
96 #include <dev/wscons/wsconsio.h>
97 #include <dev/wscons/wsdisplayvar.h>
98
99 #include <dev/wsfont/wsfont.h>
100
101 #include <dev/ic/bt459reg.h>
102
103 #include <dev/tc/tcvar.h>
104 #include <dev/tc/sticreg.h>
105 #include <dev/tc/sticvar.h>
106
107 #define DUPBYTE0(x) ((((x)&0xff)<<16) | (((x)&0xff)<<8) | ((x)&0xff))
108 #define DUPBYTE1(x) ((((x)<<8)&0xff0000) | ((x)&0xff00) | (((x)>>8)&0xff))
109 #define DUPBYTE2(x) (((x)&0xff0000) | (((x)>>8)&0xff00) | (((x)>>16)&0xff))
110
111 #define PACK(p, o) ((p)[(o)] | ((p)[(o)+1] << 16))
112
113 #if defined(pmax)
114 #define machine_btop(x) mips_btop(x)
115 #elif defined(alpha)
116 #define machine_btop(x) alpha_btop(x)
117 #endif
118
119 /*
120 * N.B., Bt459 registers are 8bit width. Some of TC framebuffers have
121 * obscure register layout such as 2nd and 3rd Bt459 registers are
122 * adjacent each other in a word, i.e.,
123 * struct bt459triplet {
124 * struct {
125 * u_int8_t u0;
126 * u_int8_t u1;
127 * u_int8_t u2;
128 * unsigned :8;
129 * } bt_lo;
130 * struct {
131 *
132 * Although HX has single Bt459, 32bit R/W can be done w/o any trouble.
133 * struct bt459reg {
134 * u_int32_t bt_lo;
135 * u_int32_t bt_hi;
136 * u_int32_t bt_reg;
137 * u_int32_t bt_cmap;
138 * };
139 *
140 */
141
142 /* Bt459 hardware registers */
143 #define bt_lo 0
144 #define bt_hi 1
145 #define bt_reg 2
146 #define bt_cmap 3
147
148 #define REG(base, index) *((u_int32_t *)(base) + (index))
149 #define SELECT(vdac, regno) do { \
150 REG(vdac, bt_lo) = DUPBYTE0(regno); \
151 REG(vdac, bt_hi) = DUPBYTE1(regno); \
152 tc_wmb(); \
153 } while (0)
154
155 static int sticioctl(void *, u_long, caddr_t, int, struct proc *);
156 static paddr_t sticmmap(void *, off_t, int);
157 static int stic_alloc_screen(void *, const struct wsscreen_descr *,
158 void **, int *, int *, long *);
159 static void stic_free_screen(void *, void *);
160 static int stic_show_screen(void *, void *, int,
161 void (*) (void *, int, int), void *);
162 static void stic_do_switch(void *);
163 static void stic_setup_backing(struct stic_info *, struct stic_screen *);
164 static void stic_setup_vdac(struct stic_info *si);
165
166 static int stic_get_cmap(struct stic_info *, struct wsdisplay_cmap *);
167 static int stic_set_cmap(struct stic_info *, struct wsdisplay_cmap *);
168 static int stic_set_cursor(struct stic_info *, struct wsdisplay_cursor *);
169 static int stic_get_cursor(struct stic_info *, struct wsdisplay_cursor *);
170 static void stic_set_curpos(struct stic_info *, struct wsdisplay_curpos *);
171 static void stic_set_hwcurpos(struct stic_info *);
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 WSSCREEN_WSCOLORS | WSSCREEN_HILIT
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_wmb();
297
298 /* Now reset the VDAC. */
299 *si->si_vdac_reset = 0;
300 tc_wmb();
301 tc_syncbus();
302 DELAY(1000);
303
304 /* Finish the initalization. */
305 SELECT(vdac, BT459_IREG_COMMAND_1);
306 REG(vdac, bt_reg) = 0x00000000; tc_wmb();
307 REG(vdac, bt_reg) = 0x00c2c2c2; tc_wmb();
308 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
309
310 for (i = 0; i < 7; i++) {
311 REG(vdac, bt_reg) = 0x00000000;
312 tc_wmb();
313 }
314
315 /* Set cursor colormap. */
316 SELECT(vdac, BT459_IREG_CCOLOR_1);
317 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
318 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
319 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
320 REG(vdac, bt_reg) = 0x00000000; tc_wmb();
321 REG(vdac, bt_reg) = 0x00000000; tc_wmb();
322 REG(vdac, bt_reg) = 0x00000000; tc_wmb();
323 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
324 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
325 REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
326
327 /* Get a font and set up screen metrics. */
328 wsfont_init();
329 cookie = wsfont_find(NULL, 0, 0, 0);
330
331 if (wsfont_lock(cookie, &si->si_font,
332 WSDISPLAY_FONTORDER_R2L, WSDISPLAY_FONTORDER_L2R) <= 0)
333 panic("stic_init: couldn't lock font\n");
334
335 si->si_fontw = si->si_font->fontwidth;
336 si->si_fonth = si->si_font->fontheight;
337 si->si_consw = (1280 / si->si_fontw) & ~1;
338 si->si_consh = 1024 / si->si_fonth;
339 stic_stdscreen.ncols = si->si_consw;
340 stic_stdscreen.nrows = si->si_consh;
341
342 #ifdef DIAGNOSTIC
343 if ((u_int)si->si_fonth > 32 || (u_int)si->si_fontw > 16)
344 panic("stic_init: unusable font");
345 #endif
346
347 stic_setup_vdac(si);
348 }
349
350 void
351 stic_reset(struct stic_info *si)
352 {
353 int modtype, xconfig, yconfig, config;
354 volatile struct stic_regs *sr;
355
356 sr = si->si_stic;
357
358 /*
359 * Initialize the interface chip registers.
360 */
361 sr->sr_sticsr = 0x00000030; /* Get the STIC's attention. */
362 tc_wmb();
363 tc_syncbus();
364 DELAY(4000); /* wait 4ms for STIC to respond. */
365 sr->sr_sticsr = 0x00000000; /* Hit the STIC's csr again... */
366 tc_wmb();
367 sr->sr_buscsr = 0xffffffff; /* and bash its bus-acess csr. */
368 tc_wmb();
369 tc_syncbus(); /* Blam! */
370 DELAY(20000); /* wait until the stic recovers... */
371
372 modtype = sr->sr_modcl;
373 xconfig = (modtype & 0x800) >> 11;
374 yconfig = (modtype & 0x600) >> 9;
375 config = (yconfig << 1) | xconfig;
376 si->si_stampw = (xconfig ? 5 : 4);
377 si->si_stamph = (1 << yconfig);
378 #ifdef notyet
379 si->si_option = (char)((modtype >> 12) & 3);
380 #endif
381
382 /* First PixelStamp */
383 si->si_stamp[0x000b0] = config;
384 si->si_stamp[0x000b4] = 0x0;
385
386 /* Second PixelStamp */
387 if (yconfig > 0) {
388 si->si_stamp[0x100b0] = config | 8;
389 si->si_stamp[0x100b4] = 0;
390 }
391
392 /*
393 * Initialize STIC video registers.
394 */
395 sr->sr_vblank = (1024 << 16) | 1063;
396 sr->sr_vsync = (1027 << 16) | 1030;
397 sr->sr_hblank = (255 << 16) | 340;
398 sr->sr_hsync2 = 245;
399 sr->sr_hsync = (261 << 16) | 293;
400 sr->sr_ipdvint = STIC_INT_CLR | STIC_INT_WE | STIC_INT_P;
401 sr->sr_sticsr = 8;
402 tc_wmb();
403 tc_syncbus();
404 }
405
406 void
407 stic_attach(struct device *self, struct stic_info *si, int console)
408 {
409 struct wsemuldisplaydev_attach_args waa;
410
411 callout_init(&si->si_switch_callout);
412
413 /*
414 * Allocate backing for the console. We could trawl back through
415 * msgbuf and and fill the backing, but it's not worth the hassle.
416 * We could also grab backing using pmap_steal_memory() early on,
417 * but that's a little ugly.
418 */
419 if (console)
420 stic_setup_backing(si, &stic_consscr);
421
422 waa.console = console;
423 waa.scrdata = &stic_screenlist;
424 waa.accessops = &stic_accessops;
425 waa.accesscookie = si;
426 config_found(self, &waa, wsemuldisplaydevprint);
427 }
428
429 void
430 stic_cnattach(struct stic_info *si)
431 {
432 struct stic_screen *ss;
433 long defattr;
434
435 ss = &stic_consscr;
436 si->si_curscreen = ss;
437 ss->ss_flags = SS_ALLOCED | SS_ACTIVE | SS_CURENB;
438 ss->ss_si = si;
439
440 si->si_flags |= SI_CURENB_CHANGED;
441 stic_flush(si);
442
443 stic_alloc_attr(ss, 0, 0, 0, &defattr);
444 stic_eraserows(ss, 0, si->si_consh, 0);
445 wsdisplay_cnattach(&stic_stdscreen, ss, 0, 0, defattr);
446 }
447
448 static void
449 stic_setup_vdac(struct stic_info *si)
450 {
451 u_int8_t *ip, *mp;
452 int r, c, o, b, i;
453
454 ip = (u_int8_t *)si->si_cursor.cc_image;
455 mp = ip + (sizeof(si->si_cursor.cc_image) >> 1);
456 memset(ip, 0, sizeof(si->si_cursor.cc_image));
457
458 for (r = 0; r < si->si_fonth; r++) {
459 for (c = 0; c < si->si_fontw; c++) {
460 o = c >> 3;
461 b = 1 << (c & 7);
462 ip[o] |= b;
463 mp[o] |= b;
464 }
465
466 ip += 16;
467 mp += 16;
468 }
469
470 si->si_cursor.cc_size.x = 64;
471 si->si_cursor.cc_size.y = si->si_fonth;
472 si->si_cursor.cc_hot.x = 0;
473 si->si_cursor.cc_hot.y = 0;
474
475 si->si_cursor.cc_color[0] = 0xff;
476 si->si_cursor.cc_color[2] = 0xff;
477 si->si_cursor.cc_color[4] = 0xff;
478 si->si_cursor.cc_color[1] = 0x00;
479 si->si_cursor.cc_color[3] = 0x00;
480 si->si_cursor.cc_color[5] = 0x00;
481
482 memset(&si->si_cmap, 0, sizeof(si->si_cmap));
483 for (i = 0; i < 16; i++) {
484 si->si_cmap.r[i] = stic_cmap[i*3 + 0];
485 si->si_cmap.g[i] = stic_cmap[i*3 + 1];
486 si->si_cmap.b[i] = stic_cmap[i*3 + 2];
487 }
488
489 si->si_flags |= SI_CMAP_CHANGED | SI_CURSHAPE_CHANGED |
490 SI_CURCMAP_CHANGED;
491 }
492
493 static int
494 sticioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
495 {
496 struct stic_info *si;
497 struct stic_xinfo *sxi;
498
499 si = v;
500
501 switch (cmd) {
502 case WSDISPLAYIO_GTYPE:
503 *(u_int *)data = si->si_disptype;
504 return (0);
505
506 case WSDISPLAYIO_GINFO:
507 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
508 wsd_fbip->height = 1024;
509 wsd_fbip->width = 1280;
510 wsd_fbip->depth = si->si_depth == 8 ? 8 : 32;
511 wsd_fbip->cmsize = CMAP_SIZE;
512 #undef fbt
513 return (0);
514
515 case WSDISPLAYIO_GETCMAP:
516 return (stic_get_cmap(si, (struct wsdisplay_cmap *)data));
517
518 case WSDISPLAYIO_PUTCMAP:
519 return (stic_set_cmap(si, (struct wsdisplay_cmap *)data));
520
521 case WSDISPLAYIO_SVIDEO:
522 #if 0 /* XXX later */
523 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
524 if ((si->si_blanked == 0) ^ turnoff)
525 si->si_blanked = turnoff;
526 #endif
527 return (0);
528
529 case WSDISPLAYIO_GVIDEO:
530 #if 0 /* XXX later */
531 *(u_int *)data = si->si_blanked ?
532 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
533 #endif
534 return (0);
535
536 case WSDISPLAYIO_GCURPOS:
537 *(struct wsdisplay_curpos *)data = si->si_cursor.cc_pos;
538 return (0);
539
540 case WSDISPLAYIO_SCURPOS:
541 stic_set_curpos(si, (struct wsdisplay_curpos *)data);
542 return (0);
543
544 case WSDISPLAYIO_GCURMAX:
545 ((struct wsdisplay_curpos *)data)->x =
546 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
547 return (0);
548
549 case WSDISPLAYIO_GCURSOR:
550 return (stic_get_cursor(si, (struct wsdisplay_cursor *)data));
551
552 case WSDISPLAYIO_SCURSOR:
553 return (stic_set_cursor(si, (struct wsdisplay_cursor *)data));
554
555 case WSDISPLAYIO_SMODE:
556 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
557 stic_setup_vdac(si);
558 stic_flush(si);
559 stic_do_switch(si->si_curscreen);
560 }
561 return (0);
562
563 case STICIO_RESET:
564 stic_reset(si);
565 return (0);
566
567 case STICIO_GXINFO:
568 sxi = (struct stic_xinfo *)data;
569 sxi->sxi_stampw = si->si_stampw;
570 sxi->sxi_stamph = si->si_stamph;
571 sxi->sxi_buf_size = si->si_buf_size;
572 sxi->sxi_buf_phys = (u_long)si->si_buf_phys;
573 return (0);
574 }
575
576 if (si->si_ioctl != NULL)
577 return ((*si->si_ioctl)(si, cmd, data, flag, p));
578
579 return (ENOTTY);
580 }
581
582 static paddr_t
583 sticmmap(void *v, off_t offset, int prot)
584 {
585 struct stic_info *si;
586 struct stic_xmap sxm;
587 paddr_t pa;
588
589 si = v;
590
591 if (offset < 0)
592 return ((paddr_t)-1L);
593
594 if (offset < sizeof(sxm.sxm_stic)) {
595 pa = STIC_KSEG_TO_PHYS(si->si_stic);
596 return (machine_btop(pa + offset));
597 }
598 offset -= sizeof(sxm.sxm_stic);
599
600 if (offset < sizeof(sxm.sxm_poll)) {
601 pa = STIC_KSEG_TO_PHYS(si->si_slotbase);
602 return (machine_btop(pa + offset));
603 }
604 offset -= sizeof(sxm.sxm_poll);
605
606 if (offset < si->si_buf_size)
607 return (machine_btop(si->si_buf_phys + offset));
608
609 return ((paddr_t)-1L);
610 }
611
612 static void
613 stic_setup_backing(struct stic_info *si, struct stic_screen *ss)
614 {
615 int size;
616
617 size = si->si_consw * si->si_consh * sizeof(*ss->ss_backing);
618 ss->ss_backing = malloc(size, M_DEVBUF, M_NOWAIT);
619 memset(ss->ss_backing, 0, size);
620 }
621
622 static int
623 stic_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
624 int *curxp, int *curyp, long *attrp)
625 {
626 struct stic_info *si;
627 struct stic_screen *ss;
628
629 si = (struct stic_info *)v;
630
631 if ((stic_consscr.ss_flags & SS_ALLOCED) == 0)
632 ss = &stic_consscr;
633 else {
634 ss = malloc(sizeof(*ss), M_DEVBUF, M_WAITOK);
635 memset(ss, 0, sizeof(*ss));
636 }
637 stic_setup_backing(si, ss);
638
639 ss->ss_si = si;
640 ss->ss_flags = SS_ALLOCED | SS_CURENB;
641
642 *cookiep = ss;
643 *curxp = 0;
644 *curyp = 0;
645
646 stic_alloc_attr(ss, 0, 0, 0, attrp);
647 return (0);
648 }
649
650 static void
651 stic_free_screen(void *v, void *cookie)
652 {
653 struct stic_screen *ss;
654
655 ss = cookie;
656
657 #ifdef DIAGNOSTIC
658 if (ss == &stic_consscr)
659 panic("stic_free_screen: console");
660 if (ss == ((struct stic_info *)v)->si_curscreen)
661 panic("stic_free_screen: freeing current screen");
662 #endif
663
664 free(ss->ss_backing, M_DEVBUF);
665 free(ss, M_DEVBUF);
666 }
667
668 static int
669 stic_show_screen(void *v, void *cookie, int waitok,
670 void (*cb)(void *, int, int), void *cbarg)
671 {
672 struct stic_info *si;
673
674 si = (struct stic_info *)v;
675 if (si->si_switchcbarg != NULL)
676 return (EAGAIN);
677 si->si_switchcb = cb;
678 si->si_switchcbarg = cbarg;
679
680 if (cb != NULL) {
681 callout_reset(&si->si_switch_callout, 0, stic_do_switch,
682 cookie);
683 return (EAGAIN);
684 }
685
686 stic_do_switch(cookie);
687 return (0);
688 }
689
690 static void
691 stic_do_switch(void *cookie)
692 {
693 struct stic_screen *ss;
694 struct stic_info *si;
695 u_int r, c, nr, nc;
696 u_int16_t *p, *sp;
697
698 ss = cookie;
699 si = ss->ss_si;
700
701 #ifdef DIAGNOSTIC
702 if (ss->ss_backing == NULL)
703 panic("stic_do_switch: screen not backed");
704 #endif
705
706 /* Swap in the new screen, and temporarily disable its backing. */
707 si->si_curscreen->ss_flags ^= SS_ACTIVE;
708 si->si_curscreen = ss;
709 ss->ss_flags |= SS_ACTIVE;
710 sp = ss->ss_backing;
711 ss->ss_backing = NULL;
712
713 /*
714 * We assume that most of the screen is blank and blast it with
715 * eraserows(), because eraserows() is cheap.
716 */
717 nr = si->si_consh;
718 stic_eraserows(ss, 0, nr, 0);
719
720 nc = si->si_consw;
721 p = sp;
722 for (r = 0; r < nr; r++)
723 for (c = 0; c < nc; c += 2, p += 2) {
724 if ((p[0] & 0xfff0) != 0)
725 stic_putchar(ss, r, c, p[0] >> 8,
726 p[0] & 0x00ff);
727 if ((p[1] & 0xfff0) != 0)
728 stic_putchar(ss, r, c + 1, p[1] >> 8,
729 p[1] & 0x00ff);
730 }
731
732 /*
733 * Re-enable the screen's backing, and move the cursor to the
734 * correct spot.
735 */
736 ss->ss_backing = sp;
737 si->si_cursor.cc_pos.x = ss->ss_curx;
738 si->si_cursor.cc_pos.y = ss->ss_cury;
739 stic_set_hwcurpos(si);
740 si->si_flags |= SI_CURENB_CHANGED;
741
742 /*
743 * XXX Since we don't yet receive vblank interrupts from the
744 * PXG, we must flush immediatley.
745 */
746 if (si->si_disptype == WSDISPLAY_TYPE_PXG)
747 stic_flush(si);
748
749 /* Tell wscons that we're done. */
750 if (si->si_switchcbarg != NULL) {
751 cookie = si->si_switchcbarg;
752 si->si_switchcbarg = NULL;
753 (*si->si_switchcb)(cookie, 0, 0);
754 }
755 }
756
757 static int
758 stic_alloc_attr(void *cookie, int fg, int bg, int flags, long *attr)
759 {
760 long tmp;
761
762 if ((flags & (WSATTR_BLINK | WSATTR_UNDERLINE)) != 0)
763 return (EINVAL);
764
765 if ((flags & WSATTR_WSCOLORS) == 0) {
766 fg = 7;
767 bg = 0;
768 }
769
770 if ((flags & WSATTR_HILIT) != 0)
771 fg += 8;
772
773 tmp = fg | (bg << 4);
774 *attr = tmp | (tmp << 16);
775 return (0);
776 }
777
778 static void
779 stic_erasecols(void *cookie, int row, int col, int num, long attr)
780 {
781 struct stic_info *si;
782 struct stic_screen *ss;
783 u_int32_t *pb;
784 u_int i, linewidth;
785 u_int16_t *p;
786
787 ss = cookie;
788 si = ss->ss_si;
789
790 if (ss->ss_backing != NULL) {
791 p = ss->ss_backing + row * si->si_consw + col;
792 for (i = num; i != 0; i--)
793 *p++ = (u_int16_t)attr;
794 }
795 if ((ss->ss_flags & SS_ACTIVE) == 0)
796 return;
797
798 col = (col * si->si_fontw) << 19;
799 num = (num * si->si_fontw) << 19;
800 row = row * si->si_fonth;
801 attr = (attr & 0xf0) >> 4;
802 linewidth = (si->si_fonth << 2) - 1;
803 row = (row << 3) + linewidth;
804
805 pb = (*si->si_pbuf_get)(si);
806
807 pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET;
808 pb[1] = 0x01ffffff;
809 pb[2] = 0;
810 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY;
811 pb[4] = linewidth;
812 pb[5] = DUPBYTE0(attr);
813 pb[6] = col | row;
814 pb[7] = (col + num) | row;
815
816 (*si->si_pbuf_post)(si, pb);
817 }
818
819 static void
820 stic_eraserows(void *cookie, int row, int num, long attr)
821 {
822 struct stic_info *si;
823 struct stic_screen *ss;
824 u_int linewidth, i;
825 u_int32_t *pb;
826
827 ss = cookie;
828 si = ss->ss_si;
829
830 if (ss->ss_backing != NULL) {
831 pb = (u_int32_t *)(ss->ss_backing + row * si->si_consw);
832 for (i = si->si_consw * num; i > 0; i -= 2)
833 *pb++ = (u_int32_t)attr;
834 }
835 if ((ss->ss_flags & SS_ACTIVE) == 0)
836 return;
837
838 row *= si->si_fonth;
839 num *= si->si_fonth;
840 attr = (attr & 0xf0) >> 4;
841 linewidth = (num << 2) - 1;
842 row = (row << 3) + linewidth;
843
844 pb = (*si->si_pbuf_get)(si);
845
846 pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET;
847 pb[1] = 0x01ffffff;
848 pb[2] = 0;
849 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY;
850 pb[4] = linewidth;
851 pb[5] = DUPBYTE0(attr);
852 pb[6] = row;
853 pb[7] = (1280 << 19) | row;
854
855 (*si->si_pbuf_post)(si, pb);
856 }
857
858 static void
859 stic_copyrows(void *cookie, int src, int dst, int height)
860 {
861 struct stic_info *si;
862 struct stic_screen *ss;
863 u_int32_t *pb, *pbs;
864 u_int num, inc, adj;
865
866 ss = cookie;
867 si = ss->ss_si;
868
869 if (ss->ss_backing != NULL)
870 bcopy(ss->ss_backing + src * si->si_consw,
871 ss->ss_backing + dst * si->si_consw,
872 si->si_consw * sizeof(*ss->ss_backing) * height);
873 if ((ss->ss_flags & SS_ACTIVE) == 0)
874 return;
875
876 /*
877 * We need to do this in reverse if the destination row is below
878 * the source.
879 */
880 if (dst > src) {
881 src += height;
882 dst += height;
883 inc = -8;
884 adj = -1;
885 } else {
886 inc = 8;
887 adj = 0;
888 }
889
890 src = (src * si->si_fonth + adj) << 3;
891 dst = (dst * si->si_fonth + adj) << 3;
892 height *= si->si_fonth;
893
894 while (height > 0) {
895 num = (height < 255 ? height : 255);
896 height -= num;
897
898 pbs = (*si->si_pbuf_get)(si);
899 pb = pbs;
900
901 pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET;
902 pb[1] = (num << 24) | 0xffffff;
903 pb[2] = 0x0;
904 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN |
905 STAMP_COPYSPAN_ALIGNED;
906 pb[4] = 1; /* linewidth */
907
908 for (; num != 0; num--, src += inc, dst += inc, pb += 3) {
909 pb[5] = 1280 << 3;
910 pb[6] = src;
911 pb[7] = dst;
912 }
913
914 (*si->si_pbuf_post)(si, pbs);
915 }
916 }
917
918 static void
919 stic_copycols(void *cookie, int row, int src, int dst, int num)
920 {
921 struct stic_info *si;
922 struct stic_screen *ss;
923 u_int height, updword;
924 u_int32_t *pb, *pbs;
925
926 ss = cookie;
927 si = ss->ss_si;
928
929 if (ss->ss_backing != NULL)
930 bcopy(ss->ss_backing + row * si->si_consw + src,
931 ss->ss_backing + row * si->si_consw + dst,
932 num * sizeof(*ss->ss_backing));
933 if ((ss->ss_flags & SS_ACTIVE) == 0)
934 return;
935
936 /*
937 * The stamp reads and writes left -> right only, so we need to
938 * buffer the span if the source and destination regions overlap
939 * and the source is left of the destination.
940 */
941 updword = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN;
942
943 if (src < dst && src + num > dst)
944 updword |= STAMP_HALF_BUFF;
945
946 row = (row * si->si_fonth) << 3;
947 num = (num * si->si_fontw) << 3;
948 src = row | ((src * si->si_fontw) << 19);
949 dst = row | ((dst * si->si_fontw) << 19);
950 height = si->si_fonth;
951
952 pbs = (*si->si_pbuf_get)(si);
953 pb = pbs;
954
955 pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET;
956 pb[1] = (height << 24) | 0xffffff;
957 pb[2] = 0x0;
958 pb[3] = updword;
959 pb[4] = 1; /* linewidth */
960
961 for ( ; height != 0; height--, src += 8, dst += 8, pb += 3) {
962 pb[5] = num;
963 pb[6] = src;
964 pb[7] = dst;
965 }
966
967 (*si->si_pbuf_post)(si, pbs);
968 }
969
970 static void
971 stic_putchar(void *cookie, int r, int c, u_int uc, long attr)
972 {
973 struct wsdisplay_font *font;
974 struct stic_screen *ss;
975 struct stic_info *si;
976 u_int i, bgcolor, fgcolor;
977 u_int *pb, v1, v2, xya;
978 u_short *fr;
979
980 ss = cookie;
981 si = ss->ss_si;
982
983 /* It's cheaper to use erasecols() to blit blanks. */
984 if (uc == 0) {
985 stic_erasecols(cookie, r, c, 1, attr);
986 return;
987 }
988
989 if (ss->ss_backing != NULL)
990 ss->ss_backing[r * si->si_consw + c] =
991 (u_short)((attr & 0xff) | (uc << 8));
992 if ((ss->ss_flags & SS_ACTIVE) == 0)
993 return;
994
995 font = si->si_font;
996 pb = (*si->si_pbuf_get)(si);
997
998 /*
999 * Create a mask from the glyph. Squeeze the foreground color
1000 * through the mask, and then squeeze the background color through
1001 * the inverted mask. We may well read outside the glyph when
1002 * creating the mask, but it's bounded by the hardware so it
1003 * shouldn't matter a great deal...
1004 */
1005 pb[0] = STAMP_CMD_LINES | STAMP_RGB_FLAT | STAMP_XY_PERPRIMATIVE |
1006 STAMP_LW_PERPRIMATIVE;
1007 pb[1] = font->fontheight > 16 ? 0x04ffffff : 0x02ffffff;
1008 pb[2] = 0x0;
1009 pb[3] = STAMP_UPDATE_ENABLE | STAMP_WE_XYMASK | STAMP_METHOD_COPY;
1010
1011 r *= font->fontheight;
1012 c *= font->fontwidth;
1013 uc = (uc - font->firstchar) * font->stride * font->fontheight;
1014 fr = (u_short *)((caddr_t)font->data + uc);
1015 bgcolor = DUPBYTE0((attr & 0xf0) >> 4);
1016 fgcolor = DUPBYTE0(attr & 0x0f);
1017
1018 i = ((font->fontheight > 16 ? 16 : font->fontheight) << 2) - 1;
1019 v1 = (c << 19) | ((r << 3) + i);
1020 v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff);
1021 xya = XYMASKADDR(si->si_stampw, si->si_stamph, c, r, 0, 0);
1022
1023 pb[4] = PACK(fr, 0);
1024 pb[5] = PACK(fr, 2);
1025 pb[6] = PACK(fr, 4);
1026 pb[7] = PACK(fr, 6);
1027 pb[8] = PACK(fr, 8);
1028 pb[9] = PACK(fr, 10);
1029 pb[10] = PACK(fr, 12);
1030 pb[11] = PACK(fr, 14);
1031 pb[12] = xya;
1032 pb[13] = v1;
1033 pb[14] = v2;
1034 pb[15] = i;
1035 pb[16] = fgcolor;
1036
1037 pb[17] = ~pb[4];
1038 pb[18] = ~pb[5];
1039 pb[19] = ~pb[6];
1040 pb[20] = ~pb[7];
1041 pb[21] = ~pb[8];
1042 pb[22] = ~pb[9];
1043 pb[23] = ~pb[10];
1044 pb[24] = ~pb[11];
1045 pb[25] = xya;
1046 pb[26] = v1;
1047 pb[27] = v2;
1048 pb[28] = i;
1049 pb[29] = bgcolor;
1050
1051 /* Two more squeezes for the lower part of the character. */
1052 if (font->fontheight > 16) {
1053 i = ((font->fontheight - 16) << 2) - 1;
1054 r += 16;
1055 v1 = (c << 19) | ((r << 3) + i);
1056 v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff);
1057
1058 pb[30] = PACK(fr, 16);
1059 pb[31] = PACK(fr, 18);
1060 pb[32] = PACK(fr, 20);
1061 pb[33] = PACK(fr, 22);
1062 pb[34] = PACK(fr, 24);
1063 pb[35] = PACK(fr, 26);
1064 pb[36] = PACK(fr, 28);
1065 pb[37] = PACK(fr, 30);
1066 pb[38] = xya;
1067 pb[39] = v1;
1068 pb[40] = v2;
1069 pb[41] = i;
1070 pb[42] = fgcolor;
1071
1072 pb[43] = ~pb[30];
1073 pb[44] = ~pb[31];
1074 pb[45] = ~pb[32];
1075 pb[46] = ~pb[33];
1076 pb[47] = ~pb[34];
1077 pb[48] = ~pb[35];
1078 pb[49] = ~pb[36];
1079 pb[50] = ~pb[37];
1080 pb[51] = xya;
1081 pb[52] = v1;
1082 pb[53] = v2;
1083 pb[54] = i;
1084 pb[55] = bgcolor;
1085 }
1086
1087 (*si->si_pbuf_post)(si, pb);
1088 }
1089
1090 static int
1091 stic_mapchar(void *cookie, int c, u_int *cp)
1092 {
1093 struct stic_info *si;
1094
1095 si = ((struct stic_screen *)cookie)->ss_si;
1096
1097 if (c < si->si_font->firstchar || c == ' ') {
1098 *cp = 0;
1099 return (0);
1100 }
1101
1102 if (c - si->si_font->firstchar >= si->si_font->numchars) {
1103 *cp = 0;
1104 return (0);
1105 }
1106
1107 *cp = c;
1108 return (5);
1109 }
1110
1111 static void
1112 stic_cursor(void *cookie, int on, int row, int col)
1113 {
1114 struct stic_screen *ss;
1115 struct stic_info *si;
1116
1117 ss = cookie;
1118 si = ss->ss_si;
1119
1120 ss->ss_curx = col * si->si_fontw;
1121 ss->ss_cury = row * si->si_fonth;
1122
1123 if (on)
1124 ss->ss_flags |= SS_CURENB;
1125 else
1126 ss->ss_flags &= ~SS_CURENB;
1127
1128 if ((ss->ss_flags & SS_ACTIVE) != 0) {
1129 si->si_cursor.cc_pos.x = ss->ss_curx;
1130 si->si_cursor.cc_pos.y = ss->ss_cury;
1131 si->si_flags |= SI_CURENB_CHANGED;
1132 stic_set_hwcurpos(si);
1133
1134 /*
1135 * XXX Since we don't yet receive vblank interrupts from the
1136 * PXG, we must flush immediatley.
1137 */
1138 if (si->si_disptype == WSDISPLAY_TYPE_PXG)
1139 stic_flush(si);
1140 }
1141 }
1142
1143 void
1144 stic_flush(struct stic_info *si)
1145 {
1146 volatile u_int32_t *vdac;
1147 int v;
1148
1149 if ((si->si_flags & SI_ALL_CHANGED) == 0)
1150 return;
1151
1152 vdac = si->si_vdac;
1153 v = si->si_flags;
1154 si->si_flags &= ~SI_ALL_CHANGED;
1155
1156 if ((v & SI_CURENB_CHANGED) != 0) {
1157 SELECT(vdac, BT459_IREG_CCR);
1158 if ((si->si_curscreen->ss_flags & SS_CURENB) != 0)
1159 REG(vdac, bt_reg) = 0x00c0c0c0;
1160 else
1161 REG(vdac, bt_reg) = 0x00000000;
1162 tc_wmb();
1163 }
1164
1165 if ((v & SI_CURCMAP_CHANGED) != 0) {
1166 u_int8_t *cp;
1167
1168 cp = si->si_cursor.cc_color;
1169
1170 SELECT(vdac, BT459_IREG_CCOLOR_2);
1171 REG(vdac, bt_reg) = DUPBYTE0(cp[1]); tc_wmb();
1172 REG(vdac, bt_reg) = DUPBYTE0(cp[3]); tc_wmb();
1173 REG(vdac, bt_reg) = DUPBYTE0(cp[5]); tc_wmb();
1174 REG(vdac, bt_reg) = DUPBYTE0(cp[0]); tc_wmb();
1175 REG(vdac, bt_reg) = DUPBYTE0(cp[2]); tc_wmb();
1176 REG(vdac, bt_reg) = DUPBYTE0(cp[4]); tc_wmb();
1177 }
1178
1179 if ((v & SI_CURSHAPE_CHANGED) != 0) {
1180 u_int8_t *ip, *mp, img, msk;
1181 u_int8_t u;
1182 int bcnt;
1183
1184 ip = (u_int8_t *)si->si_cursor.cc_image;
1185 mp = (u_int8_t *)(si->si_cursor.cc_image + CURSOR_MAX_SIZE);
1186
1187 bcnt = 0;
1188 SELECT(vdac, BT459_IREG_CRAM_BASE+0);
1189 /* 64 pixel scan line is consisted with 16 byte cursor ram */
1190 while (bcnt < si->si_cursor.cc_size.y * 16) {
1191 /* pad right half 32 pixel when smaller than 33 */
1192 if ((bcnt & 0x8) && si->si_cursor.cc_size.x < 33) {
1193 REG(vdac, bt_reg) = 0; tc_wmb();
1194 REG(vdac, bt_reg) = 0; tc_wmb();
1195 } else {
1196 img = *ip++;
1197 msk = *mp++;
1198 img &= msk; /* cookie off image */
1199 u = (msk & 0x0f) << 4 | (img & 0x0f);
1200 REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]);
1201 tc_wmb();
1202 u = (msk & 0xf0) | (img & 0xf0) >> 4;
1203 REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]);
1204 tc_wmb();
1205 }
1206 bcnt += 2;
1207 }
1208 /* pad unoccupied scan lines */
1209 while (bcnt < CURSOR_MAX_SIZE * 16) {
1210 REG(vdac, bt_reg) = 0; tc_wmb();
1211 REG(vdac, bt_reg) = 0; tc_wmb();
1212 bcnt += 2;
1213 }
1214 }
1215
1216 if ((v & SI_CMAP_CHANGED) != 0) {
1217 struct stic_hwcmap256 *cm;
1218 int index;
1219
1220 cm = &si->si_cmap;
1221
1222 SELECT(vdac, 0);
1223 SELECT(vdac, 0);
1224 for (index = 0; index < CMAP_SIZE; index++) {
1225 REG(vdac, bt_cmap) = DUPBYTE0(cm->r[index]);
1226 tc_wmb();
1227 REG(vdac, bt_cmap) = DUPBYTE0(cm->g[index]);
1228 tc_wmb();
1229 REG(vdac, bt_cmap) = DUPBYTE0(cm->b[index]);
1230 tc_wmb();
1231 }
1232 }
1233 }
1234
1235 static int
1236 stic_get_cmap(struct stic_info *si, struct wsdisplay_cmap *p)
1237 {
1238 u_int index, count;
1239
1240 index = p->index;
1241 count = p->count;
1242
1243 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
1244 return (EINVAL);
1245
1246 if (!uvm_useracc(p->red, count, B_WRITE) ||
1247 !uvm_useracc(p->green, count, B_WRITE) ||
1248 !uvm_useracc(p->blue, count, B_WRITE))
1249 return (EFAULT);
1250
1251 copyout(&si->si_cmap.r[index], p->red, count);
1252 copyout(&si->si_cmap.g[index], p->green, count);
1253 copyout(&si->si_cmap.b[index], p->blue, count);
1254 return (0);
1255 }
1256
1257 static int
1258 stic_set_cmap(struct stic_info *si, struct wsdisplay_cmap *p)
1259 {
1260 u_int index, count;
1261
1262 index = p->index;
1263 count = p->count;
1264
1265 if ((index + count) > CMAP_SIZE)
1266 return (EINVAL);
1267
1268 if (!uvm_useracc(p->red, count, B_READ) ||
1269 !uvm_useracc(p->green, count, B_READ) ||
1270 !uvm_useracc(p->blue, count, B_READ))
1271 return (EFAULT);
1272
1273 copyin(p->red, &si->si_cmap.r[index], count);
1274 copyin(p->green, &si->si_cmap.g[index], count);
1275 copyin(p->blue, &si->si_cmap.b[index], count);
1276
1277 si->si_flags |= SI_CMAP_CHANGED;
1278
1279 /*
1280 * XXX Since we don't yet receive vblank interrupts from the PXG, we
1281 * must flush immediatley.
1282 */
1283 if (si->si_disptype == WSDISPLAY_TYPE_PXG)
1284 stic_flush(si);
1285
1286 return (0);
1287 }
1288
1289 static int
1290 stic_set_cursor(struct stic_info *si, struct wsdisplay_cursor *p)
1291 {
1292 #define cc (&si->si_cursor)
1293 int v, index, count, icount;
1294 struct stic_screen *ss;
1295
1296 v = p->which;
1297 ss = si->si_curscreen;
1298
1299 if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
1300 index = p->cmap.index;
1301 count = p->cmap.count;
1302 if (index >= 2 || (index + count) > 2)
1303 return (EINVAL);
1304 if (!uvm_useracc(p->cmap.red, count, B_READ) ||
1305 !uvm_useracc(p->cmap.green, count, B_READ) ||
1306 !uvm_useracc(p->cmap.blue, count, B_READ))
1307 return (EFAULT);
1308 }
1309
1310 if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
1311 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
1312 return (EINVAL);
1313 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
1314 if (!uvm_useracc(p->image, icount, B_READ) ||
1315 !uvm_useracc(p->mask, icount, B_READ))
1316 return (EFAULT);
1317 }
1318
1319 if ((v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) != 0) {
1320 if (v & WSDISPLAY_CURSOR_DOCUR)
1321 cc->cc_hot = p->hot;
1322 if (v & WSDISPLAY_CURSOR_DOPOS)
1323 stic_set_curpos(si, &p->pos);
1324 }
1325
1326 if ((v & WSDISPLAY_CURSOR_DOCUR) != 0) {
1327 if (p->enable)
1328 ss->ss_flags |= SS_CURENB;
1329 else
1330 ss->ss_flags &= ~SS_CURENB;
1331 si->si_flags |= SI_CURENB_CHANGED;
1332 }
1333
1334 if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
1335 copyin(p->cmap.red, &cc->cc_color[index], count);
1336 copyin(p->cmap.green, &cc->cc_color[index + 2], count);
1337 copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
1338 si->si_flags |= SI_CURCMAP_CHANGED;
1339 }
1340
1341 if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
1342 cc->cc_size = p->size;
1343 memset(cc->cc_image, 0, sizeof cc->cc_image);
1344 copyin(p->image, cc->cc_image, icount);
1345 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
1346 si->si_flags |= SI_CURSHAPE_CHANGED;
1347 }
1348
1349 /*
1350 * XXX Since we don't yet receive vblank interrupts from the PXG, we
1351 * must flush immediatley.
1352 */
1353 if (si->si_disptype == WSDISPLAY_TYPE_PXG)
1354 stic_flush(si);
1355
1356 return (0);
1357 #undef cc
1358 }
1359
1360 static int
1361 stic_get_cursor(struct stic_info *si, struct wsdisplay_cursor *p)
1362 {
1363
1364 /* XXX */
1365 return (ENOTTY);
1366 }
1367
1368 static void
1369 stic_set_curpos(struct stic_info *si, struct wsdisplay_curpos *curpos)
1370 {
1371 int x, y;
1372
1373 x = curpos->x;
1374 y = curpos->y;
1375
1376 if (y < 0)
1377 y = 0;
1378 else if (y > 1023)
1379 y = 1023;
1380 if (x < 0)
1381 x = 0;
1382 else if (x > 1279)
1383 x = 1279;
1384
1385 si->si_cursor.cc_pos.x = x;
1386 si->si_cursor.cc_pos.y = y;
1387 stic_set_hwcurpos(si);
1388 }
1389
1390 static void
1391 stic_set_hwcurpos(struct stic_info *si)
1392 {
1393 volatile u_int32_t *vdac;
1394 int x, y, s;
1395
1396 vdac = si->si_vdac;
1397
1398 x = si->si_cursor.cc_pos.x - si->si_cursor.cc_hot.x;
1399 y = si->si_cursor.cc_pos.y - si->si_cursor.cc_hot.y;
1400 x += STIC_MAGIC_X;
1401 y += STIC_MAGIC_Y;
1402
1403 s = spltty();
1404 SELECT(vdac, BT459_IREG_CURSOR_X_LOW);
1405 REG(vdac, bt_reg) = DUPBYTE0(x); tc_wmb();
1406 REG(vdac, bt_reg) = DUPBYTE1(x); tc_wmb();
1407 REG(vdac, bt_reg) = DUPBYTE0(y); tc_wmb();
1408 REG(vdac, bt_reg) = DUPBYTE1(y); tc_wmb();
1409 splx(s);
1410 }
1411