stic.c revision 1.7 1 /* $NetBSD: stic.c,v 1.7 2001/01/09 16:04:03 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 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 /* Get a font and set up screen metrics. */
327 wsfont_init();
328 cookie = wsfont_find(NULL, 0, 0, 0);
329
330 if (wsfont_lock(cookie, &si->si_font,
331 WSDISPLAY_FONTORDER_R2L, WSDISPLAY_FONTORDER_L2R) <= 0)
332 panic("stic_init: couldn't lock font\n");
333
334 si->si_fontw = si->si_font->fontwidth;
335 si->si_fonth = si->si_font->fontheight;
336 si->si_consw = (1280 / si->si_fontw) & ~1;
337 si->si_consh = 1024 / si->si_fonth;
338 stic_stdscreen.ncols = si->si_consw;
339 stic_stdscreen.nrows = si->si_consh;
340
341 #ifdef DIAGNOSTIC
342 if ((u_int)si->si_fonth > 32 || (u_int)si->si_fontw > 16)
343 panic("stic_init: unusable font");
344 #endif
345
346 stic_setup_vdac(si);
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;
434 ss->ss_si = si;
435
436 si->si_flags |= SI_CURENB | SI_CURENB_CHANGED;
437 stic_flush(si);
438
439 stic_alloc_attr(ss, WSCOL_WHITE, 0, 0, &defattr);
440 stic_eraserows(ss, 0, si->si_consh, 0);
441 wsdisplay_cnattach(&stic_stdscreen, ss, 0, 0, defattr);
442 }
443
444 static void
445 stic_setup_vdac(struct stic_info *si)
446 {
447 u_int8_t *ip, *mp;
448 int r, c, o, b;
449
450 ip = (u_int8_t *)si->si_cursor.cc_image;
451 mp = ip + (sizeof(si->si_cursor.cc_image) >> 1);
452 memset(ip, 0, sizeof(si->si_cursor.cc_image));
453
454 for (r = 0; r < si->si_fonth; r++) {
455 for (c = 0; c < si->si_fontw; c++) {
456 o = c >> 3;
457 b = 1 << (c & 7);
458 ip[o] |= b;
459 mp[o] |= b;
460 }
461
462 ip += 16;
463 mp += 16;
464 }
465
466 si->si_cursor.cc_size.x = 64;
467 si->si_cursor.cc_size.y = si->si_fonth;
468 si->si_cursor.cc_hot.x = 0;
469 si->si_cursor.cc_hot.y = 0;
470
471 si->si_cursor.cc_color[0] = 0xff;
472 si->si_cursor.cc_color[2] = 0xff;
473 si->si_cursor.cc_color[4] = 0xff;
474 si->si_cursor.cc_color[1] = 0x00;
475 si->si_cursor.cc_color[3] = 0x00;
476 si->si_cursor.cc_color[5] = 0x00;
477
478 memset(&si->si_cmap, 0, sizeof(si->si_cmap));
479 for (i = 0; i < 16; i++) {
480 si->si_cmap.r[i] = stic_cmap[i*3 + 0];
481 si->si_cmap.g[i] = stic_cmap[i*3 + 1];
482 si->si_cmap.b[i] = stic_cmap[i*3 + 2];
483 }
484
485 si->si_flags |= SI_CMAP_CHANGED | SI_CURSHAPE_CHANGED |
486 SI_CURCMAP_CHANGED;
487 }
488
489 static int
490 sticioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
491 {
492 struct stic_info *si;
493 struct stic_xinfo *sxi;
494
495 si = v;
496
497 switch (cmd) {
498 case WSDISPLAYIO_GTYPE:
499 *(u_int *)data = si->si_disptype;
500 return (0);
501
502 case WSDISPLAYIO_GINFO:
503 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
504 wsd_fbip->height = 1024;
505 wsd_fbip->width = 1280;
506 wsd_fbip->depth = si->si_depth == 8 ? 8 : 32;
507 wsd_fbip->cmsize = CMAP_SIZE;
508 #undef fbt
509 return (0);
510
511 case WSDISPLAYIO_GETCMAP:
512 return (stic_get_cmap(si, (struct wsdisplay_cmap *)data));
513
514 case WSDISPLAYIO_PUTCMAP:
515 return (stic_set_cmap(si, (struct wsdisplay_cmap *)data));
516
517 case WSDISPLAYIO_SVIDEO:
518 #if 0 /* XXX later */
519 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
520 if ((si->si_blanked == 0) ^ turnoff)
521 si->si_blanked = turnoff;
522 #endif
523 return (0);
524
525 case WSDISPLAYIO_GVIDEO:
526 #if 0 /* XXX later */
527 *(u_int *)data = si->si_blanked ?
528 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
529 #endif
530 return (0);
531
532 case WSDISPLAYIO_GCURPOS:
533 *(struct wsdisplay_curpos *)data = si->si_cursor.cc_pos;
534 return (0);
535
536 case WSDISPLAYIO_SCURPOS:
537 stic_set_curpos(si, (struct wsdisplay_curpos *)data);
538 return (0);
539
540 case WSDISPLAYIO_GCURMAX:
541 ((struct wsdisplay_curpos *)data)->x =
542 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
543 return (0);
544
545 case WSDISPLAYIO_GCURSOR:
546 return (stic_get_cursor(si, (struct wsdisplay_cursor *)data));
547
548 case WSDISPLAYIO_SCURSOR:
549 return (stic_set_cursor(si, (struct wsdisplay_cursor *)data));
550
551 case STICIO_RESET:
552 stic_reset(si);
553 return (0);
554
555 case STICIO_RESTORE:
556 stic_setup_vdac(si);
557 stic_flush(si);
558 stic_do_switch(si->si_curscreen);
559 return (0);
560
561 case STICIO_GXINFO:
562 sxi = (struct stic_xinfo *)data;
563 sxi->sxi_stampw = si->si_stampw;
564 sxi->sxi_stamph = si->si_stamph;
565 sxi->sxi_buf_size = si->si_buf_size;
566 sxi->sxi_buf_phys = (u_long)si->si_buf_phys;
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 int
618 stic_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
619 int *curxp, int *curyp, long *attrp)
620 {
621 struct stic_info *si;
622 struct stic_screen *ss;
623
624 si = (struct stic_info *)v;
625
626 if ((stic_consscr.ss_flags & SS_ALLOCED) == 0)
627 ss = &stic_consscr;
628 else {
629 ss = malloc(sizeof(*ss), M_DEVBUF, M_WAITOK);
630 memset(ss, 0, sizeof(*ss));
631 }
632 stic_setup_backing(si, ss);
633
634 ss->ss_si = si;
635 ss->ss_flags = SS_ALLOCED;
636
637 *cookiep = ss;
638 *curxp = 0;
639 *curyp = 0;
640
641 stic_alloc_attr(ss, WSCOL_WHITE, 0, 0, attrp);
642 return (0);
643 }
644
645 static void
646 stic_free_screen(void *v, void *cookie)
647 {
648 struct stic_screen *ss;
649
650 ss = cookie;
651
652 #ifdef DIAGNOSTIC
653 if (ss == &stic_consscr)
654 panic("stic_free_screen: console");
655 if (ss == ((struct stic_info *)v)->si_curscreen)
656 panic("stic_free_screen: freeing current screen");
657 #endif
658
659 free(ss->ss_backing, M_DEVBUF);
660 free(ss, M_DEVBUF);
661 }
662
663 static int
664 stic_show_screen(void *v, void *cookie, int waitok,
665 void (*cb)(void *, int, int), void *cbarg)
666 {
667 struct stic_info *si;
668
669 si = (struct stic_info *)v;
670 if (si->si_switchcbarg != NULL)
671 return (EAGAIN);
672 si->si_switchcb = cb;
673 si->si_switchcbarg = cbarg;
674
675 if (cb != NULL) {
676 callout_reset(&si->si_switch_callout, 0, stic_do_switch,
677 cookie);
678 return (EAGAIN);
679 }
680
681 stic_do_switch(cookie);
682 return (0);
683 }
684
685 static void
686 stic_do_switch(void *cookie)
687 {
688 struct stic_screen *ss;
689 struct stic_info *si;
690 u_int r, c, nr, nc;
691 u_int16_t *p, *sp;
692
693 ss = cookie;
694 si = ss->ss_si;
695
696 #ifdef DIAGNOSTIC
697 if (ss->ss_backing == NULL)
698 panic("stic_do_switch: screen not backed");
699 #endif
700
701 /* Swap in the new screen, and temporarily disable its backing. */
702 si->si_curscreen->ss_flags ^= SS_ACTIVE;
703 si->si_curscreen = ss;
704 ss->ss_flags |= SS_ACTIVE;
705 sp = ss->ss_backing;
706 ss->ss_backing = NULL;
707
708 /*
709 * We assume that most of the screen is blank and blast it with
710 * eraserows(), because eraserows() is cheap.
711 */
712 nr = si->si_consh;
713 stic_eraserows(ss, 0, nr, 0);
714
715 nc = si->si_consw;
716 p = sp;
717 for (r = 0; r < nr; r++)
718 for (c = 0; c < nc; c += 2, p += 2) {
719 if ((p[0] & 0xfff0) != 0)
720 stic_putchar(ss, r, c, p[0] >> 8,
721 p[0] & 0x00ff);
722 if ((p[1] & 0xfff0) != 0)
723 stic_putchar(ss, r, c + 1, p[1] >> 8,
724 p[1] & 0x00ff);
725 }
726
727 /*
728 * Re-enable the screen's backing, and move the cursor to the
729 * correct spot.
730 */
731 ss->ss_backing = sp;
732 si->si_cursor.cc_pos.x = ss->ss_curx;
733 si->si_cursor.cc_pos.y = ss->ss_cury;
734 stic_set_hwcurpos(si);
735
736 /* Tell wscons that we're done. */
737 if (si->si_switchcbarg != NULL) {
738 cookie = si->si_switchcbarg;
739 si->si_switchcbarg = NULL;
740 (*si->si_switchcb)(cookie, 0, 0);
741 }
742 }
743
744 static int
745 stic_alloc_attr(void *cookie, int fg, int bg, int flags, long *attr)
746 {
747 long tmp;
748 int swap;
749
750 if ((flags & (WSATTR_BLINK | WSATTR_UNDERLINE)) != 0)
751 return (EINVAL);
752
753 if ((flags & WSATTR_HILIT) != 0)
754 fg += 8;
755
756 if ((flags & WSATTR_REVERSE) != 0) {
757 swap = fg;
758 fg = bg;
759 bg = swap;
760 }
761
762 tmp = fg | (bg << 4);
763 *attr = tmp | (tmp << 16);
764 return (0);
765 }
766
767 static void
768 stic_erasecols(void *cookie, int row, int col, int num, long attr)
769 {
770 struct stic_info *si;
771 struct stic_screen *ss;
772 u_int32_t *pb;
773 u_int i, linewidth;
774 u_int16_t *p;
775
776 ss = cookie;
777 si = ss->ss_si;
778
779 if (ss->ss_backing != NULL) {
780 p = ss->ss_backing + row * si->si_consw + col;
781 for (i = num; i != 0; i--)
782 *p++ = (u_int16_t)attr;
783 }
784 if ((ss->ss_flags & SS_ACTIVE) == 0)
785 return;
786
787 si = (struct stic_info *)cookie;
788 col = (col * si->si_fontw) << 19;
789 num = (num * si->si_fontw) << 19;
790 row = row * si->si_fonth;
791 attr = (attr & 0xf0) >> 4;
792
793 pb = (*si->si_pbuf_get)(si);
794
795 linewidth = (si->si_fonth << 2) - 1;
796 row = (row << 3) + linewidth;
797
798 pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET;
799 pb[1] = 0x01ffffff;
800 pb[2] = 0;
801 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY;
802 pb[4] = linewidth;
803 pb[5] = DUPBYTE0(attr);
804 pb[6] = col | row;
805 pb[7] = (col + num) | row;
806
807 (*si->si_pbuf_post)(si, pb);
808 }
809
810 static void
811 stic_eraserows(void *cookie, int row, int num, long attr)
812 {
813 struct stic_info *si;
814 struct stic_screen *ss;
815 u_int linewidth, i;
816 u_int32_t *pb;
817
818 ss = cookie;
819 si = ss->ss_si;
820
821 if (ss->ss_backing != NULL) {
822 pb = (u_int32_t *)(ss->ss_backing + row * si->si_consw);
823 for (i = si->si_consw * num; i > 0; i -= 2)
824 *pb++ = (u_int32_t)attr;
825 }
826 if ((ss->ss_flags & SS_ACTIVE) == 0)
827 return;
828
829 row *= si->si_fonth;
830 num *= si->si_fonth;
831 attr = (attr & 0xf0) >> 4;
832
833 pb = (*si->si_pbuf_get)(si);
834
835 linewidth = (num << 2) - 1;
836 row = (row << 3) + linewidth;
837
838 pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET;
839 pb[1] = 0x01ffffff;
840 pb[2] = 0;
841 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY;
842 pb[4] = linewidth;
843 pb[5] = DUPBYTE0(attr);
844 pb[6] = row;
845 pb[7] = (1280 << 19) | row;
846
847 (*si->si_pbuf_post)(si, pb);
848 }
849
850 static void
851 stic_copyrows(void *cookie, int src, int dst, int height)
852 {
853 struct stic_info *si;
854 struct stic_screen *ss;
855 u_int32_t *pb, *pbs;
856 u_int num, inc, adj;
857
858 ss = cookie;
859 si = ss->ss_si;
860
861 if (ss->ss_backing != NULL)
862 bcopy(ss->ss_backing + src * si->si_consw,
863 ss->ss_backing + dst * si->si_consw,
864 si->si_consw * sizeof(*ss->ss_backing) * height);
865 if ((ss->ss_flags & SS_ACTIVE) == 0)
866 return;
867
868 /*
869 * We need to do this in reverse if the destination row is below
870 * the source.
871 */
872 if (dst > src) {
873 src += height;
874 dst += height;
875 inc = -8;
876 adj = -1;
877 } else {
878 inc = 8;
879 adj = 0;
880 }
881
882 src = (src * si->si_fonth + adj) << 3;
883 dst = (dst * si->si_fonth + adj) << 3;
884 height *= si->si_fonth;
885
886 while (height > 0) {
887 num = (height < 255 ? height : 255);
888 height -= num;
889
890 pbs = (*si->si_pbuf_get)(si);
891 pb = pbs;
892
893 pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET;
894 pb[1] = (num << 24) | 0xffffff;
895 pb[2] = 0x0;
896 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN |
897 STAMP_COPYSPAN_ALIGNED;
898 pb[4] = 1; /* linewidth */
899
900 for (; num != 0; num--, src += inc, dst += inc, pb += 3) {
901 pb[5] = 1280 << 3;
902 pb[6] = src;
903 pb[7] = dst;
904 }
905
906 (*si->si_pbuf_post)(si, pbs);
907 }
908 }
909
910 static void
911 stic_copycols(void *cookie, int row, int src, int dst, int num)
912 {
913 struct stic_info *si;
914 struct stic_screen *ss;
915 u_int height, updword;
916 u_int32_t *pb, *pbs;
917
918 ss = cookie;
919 si = ss->ss_si;
920
921 if (ss->ss_backing != NULL)
922 bcopy(ss->ss_backing + row * si->si_consw + src,
923 ss->ss_backing + row * si->si_consw + dst,
924 num * sizeof(*ss->ss_backing));
925 if ((ss->ss_flags & SS_ACTIVE) == 0)
926 return;
927
928 /*
929 * The stamp reads and writes left -> right only, so we need to
930 * buffer the span if the source and destination regions overlap
931 * and the source is left of the destination.
932 */
933 updword = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN;
934
935 if (src < dst && src + num > dst)
936 updword |= STAMP_HALF_BUFF;
937
938 row = (row * si->si_fonth) << 3;
939 num = (num * si->si_fontw) << 3;
940 src = row | ((src * si->si_fontw) << 19);
941 dst = row | ((dst * si->si_fontw) << 19);
942 height = si->si_fonth;
943
944 pbs = (*si->si_pbuf_get)(si);
945 pb = pbs;
946
947 pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET;
948 pb[1] = (height << 24) | 0xffffff;
949 pb[2] = 0x0;
950 pb[3] = updword;
951 pb[4] = 1; /* linewidth */
952
953 for ( ; height != 0; height--, src += 8, dst += 8, pb += 3) {
954 pb[5] = num;
955 pb[6] = src;
956 pb[7] = dst;
957 }
958
959 (*si->si_pbuf_post)(si, pbs);
960 }
961
962 static void
963 stic_putchar(void *cookie, int r, int c, u_int uc, long attr)
964 {
965 struct wsdisplay_font *font;
966 struct stic_screen *ss;
967 struct stic_info *si;
968 u_int i, bgcolor, fgcolor;
969 u_int *pb, v1, v2, xya;
970 u_short *fr;
971
972 ss = cookie;
973 si = ss->ss_si;
974
975 /* It's cheaper to use erasecols() to blit blanks. */
976 if (uc == 0) {
977 stic_erasecols(cookie, r, c, 1, attr);
978 return;
979 }
980
981 if (ss->ss_backing != NULL)
982 ss->ss_backing[r * si->si_consw + c] =
983 (u_int16_t)((attr & 0xff) | (uc << 8));
984 if ((ss->ss_flags & SS_ACTIVE) == 0)
985 return;
986
987 font = si->si_font;
988 pb = (*si->si_pbuf_get)(si);
989
990 /*
991 * Create a mask from the glyph. Squeeze the foreground color
992 * through the mask, and then squeeze the background color through
993 * the inverted mask. We may well read outside the glyph when
994 * creating the mask, but it's bounded by the hardware so it
995 * shouldn't matter a great deal...
996 */
997 pb[0] = STAMP_CMD_LINES | STAMP_RGB_FLAT | STAMP_XY_PERPRIMATIVE |
998 STAMP_LW_PERPRIMATIVE;
999 pb[1] = font->fontheight > 16 ? 0x04ffffff : 0x02ffffff;
1000 pb[2] = 0x0;
1001 pb[3] = STAMP_UPDATE_ENABLE | STAMP_WE_XYMASK | STAMP_METHOD_COPY;
1002
1003 r *= font->fontheight;
1004 c *= font->fontwidth;
1005 uc = (uc - font->firstchar) * font->stride * font->fontheight;
1006 fr = (u_short *)((caddr_t)font->data + uc);
1007 bgcolor = DUPBYTE1((attr & 0xf0) >> 4);
1008 fgcolor = DUPBYTE0(attr & 0x0f);
1009
1010 i = ((font->fontheight > 16 ? 16 : font->fontheight) << 2) - 1;
1011 v1 = (c << 19) | ((r << 3) + i);
1012 v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff);
1013 xya = XYMASKADDR(si->si_stampw, si->si_stamph, c, r, 0, 0);
1014
1015 pb[4] = PACK(fr, 0);
1016 pb[5] = PACK(fr, 2);
1017 pb[6] = PACK(fr, 4);
1018 pb[7] = PACK(fr, 6);
1019 pb[8] = PACK(fr, 8);
1020 pb[9] = PACK(fr, 10);
1021 pb[10] = PACK(fr, 12);
1022 pb[11] = PACK(fr, 14);
1023 pb[12] = xya;
1024 pb[13] = v1;
1025 pb[14] = v2;
1026 pb[15] = i;
1027 pb[16] = fgcolor;
1028
1029 pb[17] = ~pb[4];
1030 pb[18] = ~pb[5];
1031 pb[19] = ~pb[6];
1032 pb[20] = ~pb[7];
1033 pb[21] = ~pb[8];
1034 pb[22] = ~pb[9];
1035 pb[23] = ~pb[10];
1036 pb[24] = ~pb[11];
1037 pb[25] = xya;
1038 pb[26] = v1;
1039 pb[27] = v2;
1040 pb[28] = i;
1041 pb[29] = bgcolor;
1042
1043 /* Two more squeezes for the lower part of the character. */
1044 if (font->fontheight > 16) {
1045 i = ((font->fontheight - 16) << 2) - 1;
1046 r += 16;
1047 v1 = (c << 19) | ((r << 3) + i);
1048 v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff);
1049
1050 pb[30] = PACK(fr, 16);
1051 pb[31] = PACK(fr, 18);
1052 pb[32] = PACK(fr, 20);
1053 pb[33] = PACK(fr, 22);
1054 pb[34] = PACK(fr, 24);
1055 pb[35] = PACK(fr, 26);
1056 pb[36] = PACK(fr, 28);
1057 pb[37] = PACK(fr, 30);
1058 pb[38] = xya;
1059 pb[39] = v1;
1060 pb[40] = v2;
1061 pb[41] = i;
1062 pb[42] = fgcolor;
1063
1064 pb[43] = ~pb[30];
1065 pb[44] = ~pb[31];
1066 pb[45] = ~pb[32];
1067 pb[46] = ~pb[33];
1068 pb[47] = ~pb[34];
1069 pb[48] = ~pb[35];
1070 pb[49] = ~pb[36];
1071 pb[50] = ~pb[37];
1072 pb[51] = xya;
1073 pb[52] = v1;
1074 pb[53] = v2;
1075 pb[54] = i;
1076 pb[55] = bgcolor;
1077 }
1078
1079 (*si->si_pbuf_post)(si, pb);
1080 }
1081
1082 static int
1083 stic_mapchar(void *cookie, int c, u_int *cp)
1084 {
1085 struct stic_info *si;
1086
1087 si = ((struct stic_screen *)cookie)->ss_si;
1088
1089 if (c < si->si_font->firstchar || c == ' ') {
1090 *cp = 0;
1091 return (0);
1092 }
1093
1094 if (c - si->si_font->firstchar >= si->si_font->numchars) {
1095 *cp = 0;
1096 return (0);
1097 }
1098
1099 *cp = c;
1100 return (5);
1101 }
1102
1103 static void
1104 stic_cursor(void *cookie, int on, int row, int col)
1105 {
1106 struct stic_screen *ss;
1107 struct stic_info *si;
1108
1109 ss = cookie;
1110 si = ss->ss_si;
1111
1112 ss->ss_curx = col * si->si_fontw;
1113 ss->ss_cury = row * si->si_fonth;
1114
1115 if ((ss->ss_flags & SS_ACTIVE) != 0) {
1116 /* XXX We should do cursor on/off. */
1117 si->si_cursor.cc_pos.x = ss->ss_curx;
1118 si->si_cursor.cc_pos.y = ss->ss_cury;
1119 stic_set_hwcurpos(si);
1120 }
1121 }
1122
1123 void
1124 stic_flush(struct stic_info *si)
1125 {
1126 volatile u_int32_t *vdac;
1127 int v;
1128
1129 if ((si->si_flags & SI_ALL_CHANGED) == 0)
1130 return;
1131
1132 vdac = si->si_vdac;
1133 v = si->si_flags;
1134 si->si_flags &= ~SI_ALL_CHANGED;
1135
1136 if ((v & SI_CURENB_CHANGED) != 0) {
1137 SELECT(vdac, BT459_IREG_CCR);
1138 if ((v & SI_CURENB) != 0)
1139 REG(vdac, bt_reg) = 0x00c0c0c0;
1140 else
1141 REG(vdac, bt_reg) = 0x00000000;
1142 tc_wmb();
1143 }
1144
1145 if ((v & SI_CURCMAP_CHANGED) != 0) {
1146 u_int8_t *cp;
1147
1148 cp = si->si_cursor.cc_color;
1149
1150 SELECT(vdac, BT459_IREG_CCOLOR_2);
1151 REG(vdac, bt_reg) = DUPBYTE0(cp[1]); tc_wmb();
1152 REG(vdac, bt_reg) = DUPBYTE0(cp[3]); tc_wmb();
1153 REG(vdac, bt_reg) = DUPBYTE0(cp[5]); tc_wmb();
1154 REG(vdac, bt_reg) = DUPBYTE0(cp[0]); tc_wmb();
1155 REG(vdac, bt_reg) = DUPBYTE0(cp[2]); tc_wmb();
1156 REG(vdac, bt_reg) = DUPBYTE0(cp[4]); tc_wmb();
1157 }
1158
1159 if ((v & SI_CURSHAPE_CHANGED) != 0) {
1160 u_int8_t *ip, *mp, img, msk;
1161 u_int8_t u;
1162 int bcnt;
1163
1164 ip = (u_int8_t *)si->si_cursor.cc_image;
1165 mp = (u_int8_t *)(si->si_cursor.cc_image + CURSOR_MAX_SIZE);
1166
1167 bcnt = 0;
1168 SELECT(vdac, BT459_IREG_CRAM_BASE+0);
1169 /* 64 pixel scan line is consisted with 16 byte cursor ram */
1170 while (bcnt < si->si_cursor.cc_size.y * 16) {
1171 /* pad right half 32 pixel when smaller than 33 */
1172 if ((bcnt & 0x8) && si->si_cursor.cc_size.x < 33) {
1173 REG(vdac, bt_reg) = 0; tc_wmb();
1174 REG(vdac, bt_reg) = 0; tc_wmb();
1175 } else {
1176 img = *ip++;
1177 msk = *mp++;
1178 img &= msk; /* cookie off image */
1179 u = (msk & 0x0f) << 4 | (img & 0x0f);
1180 REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]);
1181 tc_wmb();
1182 u = (msk & 0xf0) | (img & 0xf0) >> 4;
1183 REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]);
1184 tc_wmb();
1185 }
1186 bcnt += 2;
1187 }
1188 /* pad unoccupied scan lines */
1189 while (bcnt < CURSOR_MAX_SIZE * 16) {
1190 REG(vdac, bt_reg) = 0; tc_wmb();
1191 REG(vdac, bt_reg) = 0; tc_wmb();
1192 bcnt += 2;
1193 }
1194 }
1195
1196 if ((v & SI_CMAP_CHANGED) != 0) {
1197 struct stic_hwcmap256 *cm;
1198 int index;
1199
1200 cm = &si->si_cmap;
1201
1202 SELECT(vdac, 0);
1203 SELECT(vdac, 0);
1204 for (index = 0; index < CMAP_SIZE; index++) {
1205 REG(vdac, bt_cmap) = DUPBYTE0(cm->r[index]);
1206 tc_wmb();
1207 REG(vdac, bt_cmap) = DUPBYTE0(cm->g[index]);
1208 tc_wmb();
1209 REG(vdac, bt_cmap) = DUPBYTE0(cm->b[index]);
1210 tc_wmb();
1211 }
1212 }
1213 }
1214
1215 static int
1216 stic_get_cmap(struct stic_info *si, struct wsdisplay_cmap *p)
1217 {
1218 u_int index, count;
1219
1220 index = p->index;
1221 count = p->count;
1222
1223 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
1224 return (EINVAL);
1225
1226 if (!uvm_useracc(p->red, count, B_WRITE) ||
1227 !uvm_useracc(p->green, count, B_WRITE) ||
1228 !uvm_useracc(p->blue, count, B_WRITE))
1229 return (EFAULT);
1230
1231 copyout(&si->si_cmap.r[index], p->red, count);
1232 copyout(&si->si_cmap.g[index], p->green, count);
1233 copyout(&si->si_cmap.b[index], p->blue, count);
1234 return (0);
1235 }
1236
1237 static int
1238 stic_set_cmap(struct stic_info *si, struct wsdisplay_cmap *p)
1239 {
1240 u_int index, count;
1241
1242 index = p->index;
1243 count = p->count;
1244
1245 if ((index + count) > CMAP_SIZE)
1246 return (EINVAL);
1247
1248 if (!uvm_useracc(p->red, count, B_READ) ||
1249 !uvm_useracc(p->green, count, B_READ) ||
1250 !uvm_useracc(p->blue, count, B_READ))
1251 return (EFAULT);
1252
1253 copyin(p->red, &si->si_cmap.r[index], count);
1254 copyin(p->green, &si->si_cmap.g[index], count);
1255 copyin(p->blue, &si->si_cmap.b[index], count);
1256
1257 si->si_flags |= SI_CMAP_CHANGED;
1258
1259 /*
1260 * XXX Since we don't yet receive vblank interrupts from the PXG, we
1261 * must flush immediatley.
1262 */
1263 if (si->si_disptype == WSDISPLAY_TYPE_PXG)
1264 stic_flush(si);
1265
1266 return (0);
1267 }
1268
1269 static int
1270 stic_set_cursor(struct stic_info *si, struct wsdisplay_cursor *p)
1271 {
1272 #define cc (&si->si_cursor)
1273 int v, index, count, icount;
1274
1275 v = p->which;
1276
1277 if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
1278 index = p->cmap.index;
1279 count = p->cmap.count;
1280 if (index >= 2 || (index + count) > 2)
1281 return (EINVAL);
1282 if (!uvm_useracc(p->cmap.red, count, B_READ) ||
1283 !uvm_useracc(p->cmap.green, count, B_READ) ||
1284 !uvm_useracc(p->cmap.blue, count, B_READ))
1285 return (EFAULT);
1286 }
1287
1288 if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
1289 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
1290 return (EINVAL);
1291 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
1292 if (!uvm_useracc(p->image, icount, B_READ) ||
1293 !uvm_useracc(p->mask, icount, B_READ))
1294 return (EFAULT);
1295 }
1296
1297 if ((v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) != 0) {
1298 if (v & WSDISPLAY_CURSOR_DOCUR)
1299 cc->cc_hot = p->hot;
1300 if (v & WSDISPLAY_CURSOR_DOPOS)
1301 stic_set_curpos(si, &p->pos);
1302 }
1303
1304 if ((v & WSDISPLAY_CURSOR_DOCUR) != 0) {
1305 if (p->enable)
1306 si->si_flags |= SI_CURENB;
1307 else
1308 si->si_flags &= ~SI_CURENB;
1309 si->si_flags |= SI_CURENB_CHANGED;
1310 }
1311
1312 if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
1313 copyin(p->cmap.red, &cc->cc_color[index], count);
1314 copyin(p->cmap.green, &cc->cc_color[index + 2], count);
1315 copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
1316 si->si_flags |= SI_CURCMAP_CHANGED;
1317 }
1318
1319 if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
1320 cc->cc_size = p->size;
1321 memset(cc->cc_image, 0, sizeof cc->cc_image);
1322 copyin(p->image, cc->cc_image, icount);
1323 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
1324 si->si_flags |= SI_CURSHAPE_CHANGED;
1325 }
1326
1327 /*
1328 * XXX Since we don't yet receive vblank interrupts from the PXG, we
1329 * must flush immediatley.
1330 */
1331 if (si->si_disptype == WSDISPLAY_TYPE_PXG)
1332 stic_flush(si);
1333
1334 return (0);
1335 #undef cc
1336 }
1337
1338 static int
1339 stic_get_cursor(struct stic_info *si, struct wsdisplay_cursor *p)
1340 {
1341
1342 /* XXX */
1343 return (ENOTTY);
1344 }
1345
1346 static void
1347 stic_set_curpos(struct stic_info *si, struct wsdisplay_curpos *curpos)
1348 {
1349 int x, y;
1350
1351 x = curpos->x;
1352 y = curpos->y;
1353
1354 if (y < 0)
1355 y = 0;
1356 else if (y > 1023)
1357 y = 1023;
1358 if (x < 0)
1359 x = 0;
1360 else if (x > 1279)
1361 x = 1279;
1362
1363 si->si_cursor.cc_pos.x = x;
1364 si->si_cursor.cc_pos.y = y;
1365 stic_set_hwcurpos(si);
1366 }
1367
1368 static void
1369 stic_set_hwcurpos(struct stic_info *si)
1370 {
1371 volatile u_int32_t *vdac;
1372 int x, y, s;
1373
1374 vdac = si->si_vdac;
1375
1376 x = si->si_cursor.cc_pos.x - si->si_cursor.cc_hot.x;
1377 y = si->si_cursor.cc_pos.y - si->si_cursor.cc_hot.y;
1378 x += STIC_MAGIC_X;
1379 y += STIC_MAGIC_Y;
1380
1381 s = spltty();
1382 SELECT(vdac, BT459_IREG_CURSOR_X_LOW);
1383 REG(vdac, bt_reg) = DUPBYTE0(x); tc_wmb();
1384 REG(vdac, bt_reg) = DUPBYTE1(x); tc_wmb();
1385 REG(vdac, bt_reg) = DUPBYTE0(y); tc_wmb();
1386 REG(vdac, bt_reg) = DUPBYTE1(y); tc_wmb();
1387 splx(s);
1388 }
1389