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