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