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