stic.c revision 1.26 1 /* $NetBSD: stic.c,v 1.26 2003/11/13 03:09:29 chs 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.26 2003/11/13 03:09:29 chs 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, nokqfilter,
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");
354
355 if (wsfont_lock(cookie, &si->si_font))
356 panic("stic_init: couldn't lock font");
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 = (u_int8_t *)si->si_cursor.cc_mask;
494 memset(ip, 0, sizeof(si->si_cursor.cc_image));
495 memset(mp, 0, sizeof(si->si_cursor.cc_mask));
496
497 for (r = 0; r < si->si_fonth; r++) {
498 for (c = r & 1; c < si->si_fontw; c += 2) {
499 o = c >> 3;
500 b = 1 << (c & 7);
501 ip[o] |= b;
502 mp[o] |= b;
503 }
504
505 ip += 8;
506 mp += 8;
507 }
508
509 si->si_cursor.cc_size.x = 64;
510 si->si_cursor.cc_size.y = si->si_fonth;
511 si->si_cursor.cc_hot.x = 0;
512 si->si_cursor.cc_hot.y = 0;
513
514 si->si_cursor.cc_color[0] = 0xff;
515 si->si_cursor.cc_color[2] = 0xff;
516 si->si_cursor.cc_color[4] = 0xff;
517 si->si_cursor.cc_color[1] = 0x00;
518 si->si_cursor.cc_color[3] = 0x00;
519 si->si_cursor.cc_color[5] = 0x00;
520
521 memset(&si->si_cmap, 0, sizeof(si->si_cmap));
522 for (i = 0; i < 16; i++) {
523 si->si_cmap.r[i] = stic_cmap[i*3 + 0];
524 si->si_cmap.g[i] = stic_cmap[i*3 + 1];
525 si->si_cmap.b[i] = stic_cmap[i*3 + 2];
526 }
527
528 si->si_flags |= SI_CMAP_CHANGED | SI_CURSHAPE_CHANGED |
529 SI_CURCMAP_CHANGED;
530
531 splx(s);
532 }
533
534 void
535 stic_clear_screen(struct stic_info *si)
536 {
537 u_int32_t *pb;
538 int i;
539
540 /*
541 * Do this twice, since the first packet after a reset may be
542 * silently ignored.
543 */
544 for (i = 0; i < 2; i++) {
545 pb = (*si->si_pbuf_get)(si);
546
547 pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET;
548 pb[1] = 0x01ffffff;
549 pb[2] = 0;
550 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY;
551 pb[4] = (1024 << 2) - 1;
552 pb[5] = 0;
553 pb[6] = 0;
554 pb[7] = (1280 << 19) | ((1024 << 3) + pb[4]);
555
556 (*si->si_pbuf_post)(si, pb);
557 }
558 }
559
560 int
561 sticioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
562 {
563 struct stic_info *si;
564
565 si = v;
566
567 switch (cmd) {
568 case WSDISPLAYIO_GTYPE:
569 *(u_int *)data = si->si_disptype;
570 return (0);
571
572 case WSDISPLAYIO_GINFO:
573 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
574 wsd_fbip->height = 1024;
575 wsd_fbip->width = 1280;
576 wsd_fbip->depth = si->si_depth == 8 ? 8 : 32;
577 wsd_fbip->cmsize = CMAP_SIZE;
578 #undef fbt
579 return (0);
580
581 case WSDISPLAYIO_GETCMAP:
582 return (stic_get_cmap(si, (struct wsdisplay_cmap *)data));
583
584 case WSDISPLAYIO_PUTCMAP:
585 return (stic_set_cmap(si, (struct wsdisplay_cmap *)data));
586
587 case WSDISPLAYIO_SVIDEO:
588 #if 0 /* XXX later */
589 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
590 if ((si->si_blanked == 0) ^ turnoff)
591 si->si_blanked = turnoff;
592 #endif
593 return (0);
594
595 case WSDISPLAYIO_GVIDEO:
596 #if 0 /* XXX later */
597 *(u_int *)data = si->si_blanked ?
598 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
599 #endif
600 return (0);
601
602 case WSDISPLAYIO_GCURPOS:
603 *(struct wsdisplay_curpos *)data = si->si_cursor.cc_pos;
604 return (0);
605
606 case WSDISPLAYIO_SCURPOS:
607 stic_set_curpos(si, (struct wsdisplay_curpos *)data);
608 return (0);
609
610 case WSDISPLAYIO_GCURMAX:
611 ((struct wsdisplay_curpos *)data)->x =
612 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
613 return (0);
614
615 case WSDISPLAYIO_GCURSOR:
616 return (stic_get_cursor(si, (struct wsdisplay_cursor *)data));
617
618 case WSDISPLAYIO_SCURSOR:
619 return (stic_set_cursor(si, (struct wsdisplay_cursor *)data));
620
621 case WSDISPLAYIO_SMODE:
622 si->si_dispmode = *(int *)data;
623 if (si->si_dispmode == WSDISPLAYIO_MODE_EMUL) {
624 (*si->si_ioctl)(si, STICIO_STOPQ, NULL, flag, p);
625 stic_setup_vdac(si);
626 stic_flush(si);
627 stic_clear_screen(si);
628 stic_do_switch(si->si_curscreen);
629 }
630 return (0);
631
632 case STICIO_RESET:
633 stic_reset(si);
634 return (0);
635 }
636
637 if (si->si_ioctl != NULL)
638 return ((*si->si_ioctl)(si, cmd, data, flag, p));
639
640 return (EPASSTHROUGH);
641 }
642
643 void
644 stic_setup_backing(struct stic_info *si, struct stic_screen *ss)
645 {
646 int size;
647
648 size = si->si_consw * si->si_consh * sizeof(*ss->ss_backing);
649 ss->ss_backing = malloc(size, M_DEVBUF, M_NOWAIT|M_ZERO);
650 }
651
652 int
653 stic_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
654 int *curxp, int *curyp, long *attrp)
655 {
656 struct stic_info *si;
657 struct stic_screen *ss;
658
659 si = (struct stic_info *)v;
660
661 if ((stic_consscr.ss_flags & SS_ALLOCED) == 0)
662 ss = &stic_consscr;
663 else {
664 ss = malloc(sizeof(*ss), M_DEVBUF, M_WAITOK|M_ZERO);
665 }
666 stic_setup_backing(si, ss);
667
668 ss->ss_si = si;
669 ss->ss_flags = SS_ALLOCED | SS_CURENB;
670
671 *cookiep = ss;
672 *curxp = 0;
673 *curyp = 0;
674
675 stic_allocattr(ss, 0, 0, 0, attrp);
676 return (0);
677 }
678
679 void
680 stic_free_screen(void *v, void *cookie)
681 {
682 struct stic_screen *ss;
683
684 ss = cookie;
685
686 #ifdef DIAGNOSTIC
687 if (ss == &stic_consscr)
688 panic("stic_free_screen: console");
689 if (ss == ((struct stic_info *)v)->si_curscreen)
690 panic("stic_free_screen: freeing current screen");
691 #endif
692
693 free(ss->ss_backing, M_DEVBUF);
694 free(ss, M_DEVBUF);
695 }
696
697 int
698 stic_show_screen(void *v, void *cookie, int waitok,
699 void (*cb)(void *, int, int), void *cbarg)
700 {
701 struct stic_info *si;
702
703 si = (struct stic_info *)v;
704 if (si->si_switchcbarg != NULL)
705 return (EAGAIN);
706 si->si_switchcb = cb;
707 si->si_switchcbarg = cbarg;
708
709 if (cb != NULL) {
710 callout_reset(&si->si_switch_callout, 0, stic_do_switch,
711 cookie);
712 return (EAGAIN);
713 }
714
715 stic_do_switch(cookie);
716 return (0);
717 }
718
719 void
720 stic_do_switch(void *cookie)
721 {
722 struct stic_screen *ss;
723 struct stic_info *si;
724 u_int r, c, nr, nc;
725 u_int16_t *p, *sp;
726
727 ss = cookie;
728 si = ss->ss_si;
729
730 #ifdef DIAGNOSTIC
731 if (ss->ss_backing == NULL)
732 panic("stic_do_switch: screen not backed");
733 #endif
734
735 /* Swap in the new screen, and temporarily disable its backing. */
736 if (si->si_curscreen != NULL)
737 si->si_curscreen->ss_flags ^= SS_ACTIVE;
738 si->si_curscreen = ss;
739 ss->ss_flags |= SS_ACTIVE;
740 sp = ss->ss_backing;
741 ss->ss_backing = NULL;
742
743 /*
744 * We assume that most of the screen is blank and blast it with
745 * eraserows(), because eraserows() is cheap.
746 */
747 nr = si->si_consh;
748 stic_eraserows(ss, 0, nr, 0);
749
750 nc = si->si_consw;
751 p = sp;
752 for (r = 0; r < nr; r++)
753 for (c = 0; c < nc; c += 2, p += 2) {
754 if ((p[0] & 0xfff0) != 0)
755 stic_putchar(ss, r, c, p[0] >> 8,
756 p[0] & 0x00ff);
757 if ((p[1] & 0xfff0) != 0)
758 stic_putchar(ss, r, c + 1, p[1] >> 8,
759 p[1] & 0x00ff);
760 }
761
762 /*
763 * Re-enable the screen's backing, and move the cursor to the
764 * correct spot.
765 */
766 ss->ss_backing = sp;
767 si->si_cursor.cc_pos.x = ss->ss_curx;
768 si->si_cursor.cc_pos.y = ss->ss_cury;
769 stic_set_hwcurpos(si);
770 si->si_flags |= SI_CURENB_CHANGED;
771
772 /*
773 * XXX Since we don't yet receive vblank interrupts from the
774 * PXG, we must flush immediatley.
775 */
776 if (si->si_disptype == WSDISPLAY_TYPE_PXG)
777 stic_flush(si);
778
779 /* Tell wscons that we're done. */
780 if (si->si_switchcbarg != NULL) {
781 cookie = si->si_switchcbarg;
782 si->si_switchcbarg = NULL;
783 (*si->si_switchcb)(cookie, 0, 0);
784 }
785 }
786
787 int
788 stic_allocattr(void *cookie, int fg, int bg, int flags, long *attr)
789 {
790 long tmp;
791
792 if ((flags & (WSATTR_BLINK | WSATTR_UNDERLINE)) != 0)
793 return (EINVAL);
794
795 if ((flags & WSATTR_WSCOLORS) == 0) {
796 fg = 7;
797 bg = 0;
798 }
799
800 if ((flags & WSATTR_HILIT) != 0)
801 fg += 8;
802
803 tmp = fg | (bg << 4);
804 *attr = tmp | (tmp << 16);
805 return (0);
806 }
807
808 void
809 stic_erasecols(void *cookie, int row, int col, int num, long attr)
810 {
811 struct stic_info *si;
812 struct stic_screen *ss;
813 u_int32_t *pb;
814 u_int i, linewidth;
815 u_int16_t *p;
816
817 ss = cookie;
818 si = ss->ss_si;
819
820 if (ss->ss_backing != NULL) {
821 p = ss->ss_backing + row * si->si_consw + col;
822 for (i = num; i != 0; i--)
823 *p++ = (u_int16_t)attr;
824 }
825 if ((ss->ss_flags & SS_ACTIVE) == 0)
826 return;
827
828 col = (col * si->si_fontw) << 19;
829 num = (num * si->si_fontw) << 19;
830 row = row * si->si_fonth;
831 attr = (attr & 0xf0) >> 4;
832 linewidth = (si->si_fonth << 2) - 1;
833 row = (row << 3) + linewidth;
834
835 pb = (*si->si_pbuf_get)(si);
836
837 pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET;
838 pb[1] = 0x01ffffff;
839 pb[2] = 0;
840 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY;
841 pb[4] = linewidth;
842 pb[5] = DUPBYTE0(attr);
843 pb[6] = col | row;
844 pb[7] = (col + num) | row;
845
846 (*si->si_pbuf_post)(si, pb);
847 }
848
849 void
850 stic_eraserows(void *cookie, int row, int num, long attr)
851 {
852 struct stic_info *si;
853 struct stic_screen *ss;
854 u_int linewidth, i;
855 u_int32_t *pb;
856
857 ss = cookie;
858 si = ss->ss_si;
859
860 if (ss->ss_backing != NULL) {
861 pb = (u_int32_t *)(ss->ss_backing + row * si->si_consw);
862 for (i = si->si_consw * num; i > 0; i -= 2)
863 *pb++ = (u_int32_t)attr;
864 }
865 if ((ss->ss_flags & SS_ACTIVE) == 0)
866 return;
867
868 row *= si->si_fonth;
869 num *= si->si_fonth;
870 attr = (attr & 0xf0) >> 4;
871 linewidth = (num << 2) - 1;
872 row = (row << 3) + linewidth;
873
874 pb = (*si->si_pbuf_get)(si);
875
876 pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET;
877 pb[1] = 0x01ffffff;
878 pb[2] = 0;
879 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY;
880 pb[4] = linewidth;
881 pb[5] = DUPBYTE0(attr);
882 pb[6] = row;
883 pb[7] = (1280 << 19) | row;
884
885 (*si->si_pbuf_post)(si, pb);
886 }
887
888 void
889 stic_copyrows(void *cookie, int src, int dst, int height)
890 {
891 struct stic_info *si;
892 struct stic_screen *ss;
893 u_int32_t *pb, *pbs;
894 u_int num, inc, adj;
895
896 ss = cookie;
897 si = ss->ss_si;
898
899 if (ss->ss_backing != NULL)
900 bcopy(ss->ss_backing + src * si->si_consw,
901 ss->ss_backing + dst * si->si_consw,
902 si->si_consw * sizeof(*ss->ss_backing) * height);
903 if ((ss->ss_flags & SS_ACTIVE) == 0)
904 return;
905
906 /*
907 * We need to do this in reverse if the destination row is below
908 * the source.
909 */
910 if (dst > src) {
911 src += height;
912 dst += height;
913 inc = -8;
914 adj = -1;
915 } else {
916 inc = 8;
917 adj = 0;
918 }
919
920 src = (src * si->si_fonth + adj) << 3;
921 dst = (dst * si->si_fonth + adj) << 3;
922 height *= si->si_fonth;
923
924 while (height > 0) {
925 num = (height < 255 ? height : 255);
926 height -= num;
927
928 pbs = (*si->si_pbuf_get)(si);
929 pb = pbs;
930
931 pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET;
932 pb[1] = (num << 24) | 0xffffff;
933 pb[2] = 0x0;
934 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN |
935 STAMP_COPYSPAN_ALIGNED;
936 pb[4] = 1; /* linewidth */
937
938 for (; num != 0; num--, src += inc, dst += inc, pb += 3) {
939 pb[5] = 1280 << 3;
940 pb[6] = src;
941 pb[7] = dst;
942 }
943
944 (*si->si_pbuf_post)(si, pbs);
945 }
946 }
947
948 void
949 stic_copycols(void *cookie, int row, int src, int dst, int num)
950 {
951 struct stic_info *si;
952 struct stic_screen *ss;
953 u_int height, updword;
954 u_int32_t *pb, *pbs;
955
956 ss = cookie;
957 si = ss->ss_si;
958
959 if (ss->ss_backing != NULL)
960 bcopy(ss->ss_backing + row * si->si_consw + src,
961 ss->ss_backing + row * si->si_consw + dst,
962 num * sizeof(*ss->ss_backing));
963 if ((ss->ss_flags & SS_ACTIVE) == 0)
964 return;
965
966 /*
967 * The stamp reads and writes left -> right only, so we need to
968 * buffer the span if the source and destination regions overlap
969 * and the source is left of the destination.
970 */
971 updword = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN;
972
973 if (src < dst && src + num > dst)
974 updword |= STAMP_HALF_BUFF;
975
976 row = (row * si->si_fonth) << 3;
977 num = (num * si->si_fontw) << 3;
978 src = row | ((src * si->si_fontw) << 19);
979 dst = row | ((dst * si->si_fontw) << 19);
980 height = si->si_fonth;
981
982 pbs = (*si->si_pbuf_get)(si);
983 pb = pbs;
984
985 pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET;
986 pb[1] = (height << 24) | 0xffffff;
987 pb[2] = 0x0;
988 pb[3] = updword;
989 pb[4] = 1; /* linewidth */
990
991 for ( ; height != 0; height--, src += 8, dst += 8, pb += 3) {
992 pb[5] = num;
993 pb[6] = src;
994 pb[7] = dst;
995 }
996
997 (*si->si_pbuf_post)(si, pbs);
998 }
999
1000 void
1001 stic_putchar(void *cookie, int r, int c, u_int uc, long attr)
1002 {
1003 struct wsdisplay_font *font;
1004 struct stic_screen *ss;
1005 struct stic_info *si;
1006 u_int i, bgcolor, fgcolor;
1007 u_int *pb, v1, v2, xya;
1008 u_short *fr;
1009
1010 ss = cookie;
1011 si = ss->ss_si;
1012
1013 /* It's cheaper to use erasecols() to blit blanks. */
1014 if (uc == 0) {
1015 stic_erasecols(cookie, r, c, 1, attr);
1016 return;
1017 }
1018
1019 if (ss->ss_backing != NULL)
1020 ss->ss_backing[r * si->si_consw + c] =
1021 (u_short)((attr & 0xff) | (uc << 8));
1022 if ((ss->ss_flags & SS_ACTIVE) == 0)
1023 return;
1024
1025 font = si->si_font;
1026 pb = (*si->si_pbuf_get)(si);
1027
1028 /*
1029 * Create a mask from the glyph. Squeeze the foreground color
1030 * through the mask, and then squeeze the background color through
1031 * the inverted mask. We may well read outside the glyph when
1032 * creating the mask, but it's bounded by the hardware so it
1033 * shouldn't matter a great deal...
1034 */
1035 pb[0] = STAMP_CMD_LINES | STAMP_RGB_FLAT | STAMP_XY_PERPRIMATIVE |
1036 STAMP_LW_PERPRIMATIVE;
1037 pb[1] = font->fontheight > 16 ? 0x04ffffff : 0x02ffffff;
1038 pb[2] = 0x0;
1039 pb[3] = STAMP_UPDATE_ENABLE | STAMP_WE_XYMASK | STAMP_METHOD_COPY;
1040
1041 r *= font->fontheight;
1042 c *= font->fontwidth;
1043 uc = (uc - font->firstchar) * font->stride * font->fontheight;
1044 fr = (u_short *)((caddr_t)font->data + uc);
1045 bgcolor = DUPBYTE0((attr & 0xf0) >> 4);
1046 fgcolor = DUPBYTE0(attr & 0x0f);
1047
1048 i = ((font->fontheight > 16 ? 16 : font->fontheight) << 2) - 1;
1049 v1 = (c << 19) | ((r << 3) + i);
1050 v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff);
1051 xya = XYMASKADDR(si->si_stampw, si->si_stamphm, c, r, 0, 0);
1052
1053 pb[4] = PACK(fr, 0);
1054 pb[5] = PACK(fr, 2);
1055 pb[6] = PACK(fr, 4);
1056 pb[7] = PACK(fr, 6);
1057 pb[8] = PACK(fr, 8);
1058 pb[9] = PACK(fr, 10);
1059 pb[10] = PACK(fr, 12);
1060 pb[11] = PACK(fr, 14);
1061 pb[12] = xya;
1062 pb[13] = v1;
1063 pb[14] = v2;
1064 pb[15] = i;
1065 pb[16] = fgcolor;
1066
1067 pb[17] = ~pb[4];
1068 pb[18] = ~pb[5];
1069 pb[19] = ~pb[6];
1070 pb[20] = ~pb[7];
1071 pb[21] = ~pb[8];
1072 pb[22] = ~pb[9];
1073 pb[23] = ~pb[10];
1074 pb[24] = ~pb[11];
1075 pb[25] = xya;
1076 pb[26] = v1;
1077 pb[27] = v2;
1078 pb[28] = i;
1079 pb[29] = bgcolor;
1080
1081 /* Two more squeezes for the lower part of the character. */
1082 if (font->fontheight > 16) {
1083 i = ((font->fontheight - 16) << 2) - 1;
1084 r += 16;
1085 v1 = (c << 19) | ((r << 3) + i);
1086 v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff);
1087
1088 pb[30] = PACK(fr, 16);
1089 pb[31] = PACK(fr, 18);
1090 pb[32] = PACK(fr, 20);
1091 pb[33] = PACK(fr, 22);
1092 pb[34] = PACK(fr, 24);
1093 pb[35] = PACK(fr, 26);
1094 pb[36] = PACK(fr, 28);
1095 pb[37] = PACK(fr, 30);
1096 pb[38] = xya;
1097 pb[39] = v1;
1098 pb[40] = v2;
1099 pb[41] = i;
1100 pb[42] = fgcolor;
1101
1102 pb[43] = ~pb[30];
1103 pb[44] = ~pb[31];
1104 pb[45] = ~pb[32];
1105 pb[46] = ~pb[33];
1106 pb[47] = ~pb[34];
1107 pb[48] = ~pb[35];
1108 pb[49] = ~pb[36];
1109 pb[50] = ~pb[37];
1110 pb[51] = xya;
1111 pb[52] = v1;
1112 pb[53] = v2;
1113 pb[54] = i;
1114 pb[55] = bgcolor;
1115 }
1116
1117 (*si->si_pbuf_post)(si, pb);
1118 }
1119
1120 int
1121 stic_mapchar(void *cookie, int c, u_int *cp)
1122 {
1123 struct stic_info *si;
1124
1125 si = ((struct stic_screen *)cookie)->ss_si;
1126
1127 if (c < si->si_font->firstchar || c == ' ') {
1128 *cp = 0;
1129 return (0);
1130 }
1131
1132 if (c - si->si_font->firstchar >= si->si_font->numchars) {
1133 *cp = 0;
1134 return (0);
1135 }
1136
1137 *cp = c;
1138 return (5);
1139 }
1140
1141 void
1142 stic_cursor(void *cookie, int on, int row, int col)
1143 {
1144 struct stic_screen *ss;
1145 struct stic_info *si;
1146 int s;
1147
1148 ss = cookie;
1149 si = ss->ss_si;
1150
1151 ss->ss_curx = col * si->si_fontw;
1152 ss->ss_cury = row * si->si_fonth;
1153
1154 s = spltty();
1155
1156 if (on)
1157 ss->ss_flags |= SS_CURENB;
1158 else
1159 ss->ss_flags &= ~SS_CURENB;
1160
1161 if ((ss->ss_flags & SS_ACTIVE) != 0) {
1162 si->si_cursor.cc_pos.x = ss->ss_curx;
1163 si->si_cursor.cc_pos.y = ss->ss_cury;
1164 si->si_flags |= SI_CURENB_CHANGED;
1165 stic_set_hwcurpos(si);
1166
1167 /*
1168 * XXX Since we don't yet receive vblank interrupts from the
1169 * PXG, we must flush immediatley.
1170 */
1171 if (si->si_disptype == WSDISPLAY_TYPE_PXG)
1172 stic_flush(si);
1173 }
1174
1175 splx(s);
1176 }
1177
1178 void
1179 stic_flush(struct stic_info *si)
1180 {
1181 volatile u_int32_t *vdac;
1182 int v;
1183
1184 if ((si->si_flags & SI_ALL_CHANGED) == 0)
1185 return;
1186
1187 vdac = si->si_vdac;
1188 v = si->si_flags;
1189 si->si_flags &= ~SI_ALL_CHANGED;
1190
1191 if ((v & SI_CURENB_CHANGED) != 0) {
1192 SELECT(vdac, BT459_IREG_CCR);
1193 if ((si->si_curscreen->ss_flags & SS_CURENB) != 0)
1194 REG(vdac, bt_reg) = 0x00c0c0c0;
1195 else
1196 REG(vdac, bt_reg) = 0x00000000;
1197 tc_wmb();
1198 }
1199
1200 if ((v & SI_CURCMAP_CHANGED) != 0) {
1201 u_int8_t *cp;
1202
1203 cp = si->si_cursor.cc_color;
1204
1205 SELECT(vdac, BT459_IREG_CCOLOR_2);
1206 REG(vdac, bt_reg) = DUPBYTE0(cp[1]); tc_wmb();
1207 REG(vdac, bt_reg) = DUPBYTE0(cp[3]); tc_wmb();
1208 REG(vdac, bt_reg) = DUPBYTE0(cp[5]); tc_wmb();
1209 REG(vdac, bt_reg) = DUPBYTE0(cp[0]); tc_wmb();
1210 REG(vdac, bt_reg) = DUPBYTE0(cp[2]); tc_wmb();
1211 REG(vdac, bt_reg) = DUPBYTE0(cp[4]); tc_wmb();
1212 }
1213
1214 if ((v & SI_CURSHAPE_CHANGED) != 0) {
1215 u_int8_t *ip, *mp, img, msk;
1216 u_int8_t u;
1217 int bcnt;
1218
1219 ip = (u_int8_t *)si->si_cursor.cc_image;
1220 mp = (u_int8_t *)si->si_cursor.cc_mask;
1221
1222 bcnt = 0;
1223 SELECT(vdac, BT459_IREG_CRAM_BASE);
1224 /* 64 pixel scan line is consisted with 16 byte cursor ram */
1225 while (bcnt < CURSOR_MAX_SIZE * 16) {
1226 img = *ip++;
1227 msk = *mp++;
1228 img &= msk; /* cookie off image */
1229 u = (msk & 0x0f) << 4 | (img & 0x0f);
1230 REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]);
1231 tc_wmb();
1232 u = (msk & 0xf0) | (img & 0xf0) >> 4;
1233 REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]);
1234 tc_wmb();
1235 bcnt += 2;
1236 }
1237 }
1238
1239 if ((v & SI_CMAP_CHANGED) != 0) {
1240 struct stic_hwcmap256 *cm;
1241 int index;
1242
1243 cm = &si->si_cmap;
1244
1245 SELECT(vdac, 0);
1246 SELECT(vdac, 0);
1247 for (index = 0; index < CMAP_SIZE; index++) {
1248 REG(vdac, bt_cmap) = DUPBYTE0(cm->r[index]);
1249 tc_wmb();
1250 REG(vdac, bt_cmap) = DUPBYTE0(cm->g[index]);
1251 tc_wmb();
1252 REG(vdac, bt_cmap) = DUPBYTE0(cm->b[index]);
1253 tc_wmb();
1254 }
1255 }
1256 }
1257
1258 int
1259 stic_get_cmap(struct stic_info *si, struct wsdisplay_cmap *p)
1260 {
1261 u_int index = p->index, count = p->count;
1262 int error;
1263
1264 if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
1265 return (EINVAL);
1266
1267 error = copyout(&si->si_cmap.r[index], p->red, count);
1268 if (error)
1269 return error;
1270 error = copyout(&si->si_cmap.g[index], p->green, count);
1271 if (error)
1272 return error;
1273 error = copyout(&si->si_cmap.b[index], p->blue, count);
1274 return error;
1275 }
1276
1277 int
1278 stic_set_cmap(struct stic_info *si, struct wsdisplay_cmap *p)
1279 {
1280 struct stic_hwcmap256 cmap;
1281 u_int index, count;
1282 int s, error;
1283
1284 index = p->index;
1285 count = p->count;
1286
1287 if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
1288 return (EINVAL);
1289
1290 error = copyin(p->red, &cmap.r[index], count);
1291 if (error)
1292 return error;
1293 error = copyin(p->green, &cmap.g[index], count);
1294 if (error)
1295 return error;
1296 error = copyin(p->blue, &cmap.b[index], count);
1297 if (error)
1298 return error;
1299
1300 s = spltty();
1301 memcpy(&si->si_cmap.r[index], &cmap.r[index], count);
1302 memcpy(&si->si_cmap.g[index], &cmap.g[index], count);
1303 memcpy(&si->si_cmap.b[index], &cmap.b[index], count);
1304 si->si_flags |= SI_CMAP_CHANGED;
1305 splx(s);
1306
1307 /*
1308 * XXX Since we don't yet receive vblank interrupts from the PXG, we
1309 * must flush immediatley.
1310 */
1311 if (si->si_disptype == WSDISPLAY_TYPE_PXG)
1312 stic_flush(si);
1313
1314 return (0);
1315 }
1316
1317 int
1318 stic_set_cursor(struct stic_info *si, struct wsdisplay_cursor *p)
1319 {
1320 #define cc (&si->si_cursor)
1321 u_int v, index = 0, count = 0, icount = 0;
1322 struct stic_screen *ss;
1323 uint8_t r[2], g[2], b[2], image[512], mask[512];
1324 int s, error;
1325
1326 v = p->which;
1327 ss = si->si_curscreen;
1328 if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
1329 index = p->cmap.index;
1330 count = p->cmap.count;
1331 if (index >= 2 || (index + count) > 2)
1332 return (EINVAL);
1333 error = copyin(p->cmap.red, &r[index], count);
1334 if (error)
1335 return error;
1336 error = copyin(p->cmap.green, &g[index], count);
1337 if (error)
1338 return error;
1339 error = copyin(p->cmap.blue, &b[index], count);
1340 if (error)
1341 return error;
1342 }
1343 if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
1344 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
1345 return (EINVAL);
1346 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
1347 error = copyin(p->image, image, icount);
1348 if (error)
1349 return error;
1350 error = copyin(p->mask, mask, icount);
1351 if (error)
1352 return error;
1353 }
1354 if ((v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) != 0) {
1355 if (v & WSDISPLAY_CURSOR_DOCUR)
1356 cc->cc_hot = p->hot;
1357 if (v & WSDISPLAY_CURSOR_DOPOS)
1358 stic_set_curpos(si, &p->pos);
1359 }
1360
1361 s = spltty();
1362 if ((v & WSDISPLAY_CURSOR_DOCUR) != 0) {
1363 if (p->enable)
1364 ss->ss_flags |= SS_CURENB;
1365 else
1366 ss->ss_flags &= ~SS_CURENB;
1367 si->si_flags |= SI_CURENB_CHANGED;
1368 }
1369 if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
1370 memcpy(&cc->cc_color[index], &r[index], count);
1371 memcpy(&cc->cc_color[index + 2], &g[index], count);
1372 memcpy(&cc->cc_color[index + 4], &b[index], count);
1373 si->si_flags |= SI_CURCMAP_CHANGED;
1374 }
1375 if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
1376 memset(cc->cc_image, 0, sizeof cc->cc_image);
1377 memcpy(cc->cc_image, image, icount);
1378 memset(cc->cc_mask, 0, sizeof cc->cc_mask);
1379 memcpy(cc->cc_mask, mask, icount);
1380 si->si_flags |= SI_CURSHAPE_CHANGED;
1381 }
1382 splx(s);
1383
1384 /*
1385 * XXX Since we don't yet receive vblank interrupts from the PXG, we
1386 * must flush immediatley.
1387 */
1388 if (si->si_disptype == WSDISPLAY_TYPE_PXG)
1389 stic_flush(si);
1390
1391 return (0);
1392 #undef cc
1393 }
1394
1395 int
1396 stic_get_cursor(struct stic_info *si, struct wsdisplay_cursor *p)
1397 {
1398
1399 /* XXX */
1400 return (EPASSTHROUGH);
1401 }
1402
1403 void
1404 stic_set_curpos(struct stic_info *si, struct wsdisplay_curpos *curpos)
1405 {
1406 int x, y;
1407
1408 x = curpos->x;
1409 y = curpos->y;
1410
1411 if (y < 0)
1412 y = 0;
1413 else if (y > 1023)
1414 y = 1023;
1415 if (x < 0)
1416 x = 0;
1417 else if (x > 1279)
1418 x = 1279;
1419
1420 si->si_cursor.cc_pos.x = x;
1421 si->si_cursor.cc_pos.y = y;
1422 stic_set_hwcurpos(si);
1423 }
1424
1425 void
1426 stic_set_hwcurpos(struct stic_info *si)
1427 {
1428 volatile u_int32_t *vdac;
1429 int x, y, s;
1430
1431 vdac = si->si_vdac;
1432
1433 x = si->si_cursor.cc_pos.x - si->si_cursor.cc_hot.x;
1434 y = si->si_cursor.cc_pos.y - si->si_cursor.cc_hot.y;
1435 x += STIC_MAGIC_X;
1436 y += STIC_MAGIC_Y;
1437
1438 s = spltty();
1439 SELECT(vdac, BT459_IREG_CURSOR_X_LOW);
1440 REG(vdac, bt_reg) = DUPBYTE0(x); tc_wmb();
1441 REG(vdac, bt_reg) = DUPBYTE1(x); tc_wmb();
1442 REG(vdac, bt_reg) = DUPBYTE0(y); tc_wmb();
1443 REG(vdac, bt_reg) = DUPBYTE1(y); tc_wmb();
1444 splx(s);
1445 }
1446
1447 /*
1448 * STIC control inteface. We have a separate device for mapping the board,
1449 * because access to the DMA engine means that it's possible to circumvent
1450 * the securelevel mechanism. Given the way devices work in the BSD kernel,
1451 * and given the unfortunate design of the mmap() call it's near impossible
1452 * to protect against this using a shared device (i.e. wsdisplay).
1453 *
1454 * This is a gross hack... Hopefully not too many other devices will need
1455 * it.
1456 */
1457 int
1458 sticopen(dev_t dev, int flag, int mode, struct proc *p)
1459 {
1460 struct stic_info *si;
1461 int s;
1462
1463 if (securelevel > 0)
1464 return (EPERM);
1465 if (minor(dev) >= STIC_MAXDV)
1466 return (ENXIO);
1467 if ((si = stic_info[minor(dev)]) == NULL)
1468 return (ENXIO);
1469
1470 s = spltty();
1471 if ((si->si_flags & SI_DVOPEN) != 0) {
1472 splx(s);
1473 return (EBUSY);
1474 }
1475 si->si_flags |= SI_DVOPEN;
1476 splx(s);
1477
1478 return (0);
1479 }
1480
1481 int
1482 sticclose(dev_t dev, int flag, int mode, struct proc *p)
1483 {
1484 struct stic_info *si;
1485 int s;
1486
1487 si = stic_info[minor(dev)];
1488 s = spltty();
1489 si->si_flags &= ~SI_DVOPEN;
1490 splx(s);
1491
1492 return (0);
1493 }
1494
1495 paddr_t
1496 sticmmap(dev_t dev, off_t offset, int prot)
1497 {
1498 struct stic_info *si;
1499 struct stic_xmap *sxm;
1500 paddr_t pa;
1501
1502 si = stic_info[minor(dev)];
1503 sxm = NULL;
1504
1505 if (securelevel > 0)
1506 return (-1L);
1507 if (si->si_dispmode != WSDISPLAYIO_MODE_MAPPED)
1508 return (-1L);
1509
1510 if (offset < 0)
1511 return ((paddr_t)-1L);
1512
1513 if (offset < sizeof(sxm->sxm_stic)) {
1514 pa = STIC_KSEG_TO_PHYS(si->si_stic);
1515 return (machine_btop(pa + offset));
1516 }
1517 offset -= sizeof(sxm->sxm_stic);
1518
1519 if (offset < sizeof(sxm->sxm_poll)) {
1520 pa = STIC_KSEG_TO_PHYS(si->si_slotbase);
1521 return (machine_btop(pa + offset));
1522 }
1523 offset -= sizeof(sxm->sxm_poll);
1524
1525 if (offset < si->si_buf_size)
1526 return (machine_btop(si->si_buf_phys + offset));
1527
1528 return ((paddr_t)-1L);
1529 }
1530