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