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