mfb.c revision 1.56 1 /* $NetBSD: mfb.c,v 1.56 2010/05/15 08:53:27 tsutsui Exp $ */
2
3 /*-
4 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tohru Nishimura.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: mfb.c,v 1.56 2010/05/15 08:53:27 tsutsui Exp $");
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/device.h>
39 #include <sys/malloc.h>
40 #include <sys/buf.h>
41 #include <sys/ioctl.h>
42
43 #include <sys/bus.h>
44 #include <sys/intr.h>
45
46 #include <dev/wscons/wsconsio.h>
47 #include <dev/wscons/wsdisplayvar.h>
48
49 #include <dev/rasops/rasops.h>
50 #include <dev/wsfont/wsfont.h>
51
52 #include <dev/tc/tcvar.h>
53 #include <dev/ic/bt431reg.h>
54
55 #include <uvm/uvm_extern.h>
56
57 #if defined(pmax)
58 #define machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x))
59 #endif
60
61 #if defined(alpha)
62 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x))
63 #endif
64
65 /* Bt455 hardware registers, memory-mapped in 32bit stride */
66 #define bt_reg 0x0
67 #define bt_cmap 0x4
68 #define bt_clr 0x8
69 #define bt_ovly 0xc
70
71 /* Bt431 hardware registers, memory-mapped in 32bit stride */
72 #define bt_lo 0x0
73 #define bt_hi 0x4
74 #define bt_ram 0x8
75 #define bt_ctl 0xc
76
77 #define REGWRITE32(p,i,v) do { \
78 *(volatile uint32_t *)((p) + (i)) = (v); tc_wmb(); \
79 } while (0)
80
81 #define SELECT455(p,r) do { \
82 REGWRITE32((p), bt_reg, (r)); \
83 REGWRITE32((p), bt_clr, 0); \
84 } while (0)
85
86 #define TWIN(x) ((x)|((x) << 8))
87 #define TWIN_LO(x) (twin = (x) & 0x00ff, twin << 8 | twin)
88 #define TWIN_HI(x) (twin = (x) & 0xff00, twin | twin >> 8)
89
90 #define SELECT431(p,r) do { \
91 REGWRITE32((p), bt_lo, TWIN(r)); \
92 REGWRITE32((p), bt_hi, 0); \
93 } while (0)
94
95 struct hwcursor64 {
96 struct wsdisplay_curpos cc_pos;
97 struct wsdisplay_curpos cc_hot;
98 struct wsdisplay_curpos cc_size;
99 struct wsdisplay_curpos cc_magic;
100 #define CURSOR_MAX_SIZE 64
101 uint8_t cc_color[6];
102 uint64_t cc_image[CURSOR_MAX_SIZE];
103 uint64_t cc_mask[CURSOR_MAX_SIZE];
104 };
105
106 struct mfb_softc {
107 vaddr_t sc_vaddr;
108 size_t sc_size;
109 struct rasops_info *sc_ri;
110 struct hwcursor64 sc_cursor; /* software copy of cursor */
111 int sc_blanked;
112 int sc_curenb; /* cursor sprite enabled */
113 int sc_changed; /* need update of hardware */
114 int nscreens;
115 };
116
117 #define MX_MAGIC_X 360
118 #define MX_MAGIC_Y 36
119
120 #define MX_FB_OFFSET 0x200000
121 #define MX_FB_SIZE 0x200000
122 #define MX_BT455_OFFSET 0x100000
123 #define MX_BT431_OFFSET 0x180000
124 #define MX_IREQ_OFFSET 0x080000 /* Interrupt req. control */
125
126 static int mfbmatch(device_t, cfdata_t, void *);
127 static void mfbattach(device_t, device_t, void *);
128
129 CFATTACH_DECL_NEW(mfb, sizeof(struct mfb_softc),
130 mfbmatch, mfbattach, NULL, NULL);
131
132 static void mfb_common_init(struct rasops_info *);
133 static struct rasops_info mfb_console_ri;
134 static tc_addr_t mfb_consaddr;
135
136 static struct wsscreen_descr mfb_stdscreen = {
137 "std", 0, 0,
138 0, /* textops */
139 0, 0,
140 WSSCREEN_REVERSE
141 };
142
143 static const struct wsscreen_descr *_mfb_scrlist[] = {
144 &mfb_stdscreen,
145 };
146
147 static const struct wsscreen_list mfb_screenlist = {
148 sizeof(_mfb_scrlist) / sizeof(struct wsscreen_descr *), _mfb_scrlist
149 };
150
151 static int mfbioctl(void *, void *, u_long, void *, int, struct lwp *);
152 static paddr_t mfbmmap(void *, void *, off_t, int);
153
154 static int mfb_alloc_screen(void *, const struct wsscreen_descr *,
155 void **, int *, int *, long *);
156 static void mfb_free_screen(void *, void *);
157 static int mfb_show_screen(void *, void *, int,
158 void (*) (void *, int, int), void *);
159
160 static const struct wsdisplay_accessops mfb_accessops = {
161 mfbioctl,
162 mfbmmap,
163 mfb_alloc_screen,
164 mfb_free_screen,
165 mfb_show_screen,
166 0 /* load_font */
167 };
168
169 int mfb_cnattach(tc_addr_t);
170 static int mfbintr(void *);
171 static void mfbhwinit(void *);
172
173 static int set_cursor(struct mfb_softc *, struct wsdisplay_cursor *);
174 static int get_cursor(struct mfb_softc *, struct wsdisplay_cursor *);
175 static void set_curpos(struct mfb_softc *, struct wsdisplay_curpos *);
176
177 /* bit order reverse */
178 static const uint8_t flip[256] = {
179 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
180 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
181 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
182 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
183 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
184 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
185 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
186 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
187 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
188 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
189 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
190 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
191 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
192 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
193 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
194 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
195 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
196 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
197 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
198 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
199 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
200 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
201 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
202 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
203 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
204 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
205 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
206 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
207 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
208 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
209 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
210 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
211 };
212
213 static int
214 mfbmatch(device_t parent, cfdata_t match, void *aux)
215 {
216 struct tc_attach_args *ta = aux;
217
218 if (strncmp("PMAG-AA ", ta->ta_modname, TC_ROM_LLEN) != 0)
219 return (0);
220
221 return (1);
222 }
223
224 static void
225 mfbattach(device_t parent, device_t self, void *aux)
226 {
227 struct mfb_softc *sc = device_private(self);
228 struct tc_attach_args *ta = aux;
229 struct rasops_info *ri;
230 struct wsemuldisplaydev_attach_args waa;
231 int console;
232 volatile register int junk;
233
234 console = (ta->ta_addr == mfb_consaddr);
235 if (console) {
236 sc->sc_ri = ri = &mfb_console_ri;
237 ri->ri_flg &= ~RI_NO_AUTO;
238 sc->nscreens = 1;
239 }
240 else {
241 ri = malloc(sizeof(struct rasops_info),
242 M_DEVBUF, M_NOWAIT);
243 if (ri == NULL) {
244 printf(": can't alloc memory\n");
245 return;
246 }
247 memset(ri, 0, sizeof(struct rasops_info));
248
249 ri->ri_hw = (void *)ta->ta_addr;
250 mfb_common_init(ri);
251 sc->sc_ri = ri;
252 }
253 printf(": %dx%d, 1bpp\n", ri->ri_width, ri->ri_height);
254
255 sc->sc_vaddr = ta->ta_addr;
256 sc->sc_cursor.cc_magic.x = MX_MAGIC_X;
257 sc->sc_cursor.cc_magic.y = MX_MAGIC_Y;
258 sc->sc_blanked = sc->sc_curenb = 0;
259
260 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, mfbintr, sc);
261
262 /* clear any pending interrupts */
263 *(uint8_t *)((char *)ri->ri_hw + MX_IREQ_OFFSET) = 0;
264 junk = *(uint8_t *)((char *)ri->ri_hw + MX_IREQ_OFFSET);
265 *(uint8_t *)((char *)ri->ri_hw + MX_IREQ_OFFSET) = 1;
266
267 waa.console = console;
268 waa.scrdata = &mfb_screenlist;
269 waa.accessops = &mfb_accessops;
270 waa.accesscookie = sc;
271
272 config_found(self, &waa, wsemuldisplaydevprint);
273 }
274
275 static void
276 mfb_common_init(struct rasops_info *ri)
277 {
278 char *base;
279 int cookie;
280
281 base = (void *)ri->ri_hw;
282
283 /* initialize colormap and cursor hardware */
284 mfbhwinit(base);
285
286 ri->ri_flg = RI_CENTER | RI_FORCEMONO;
287 if (ri == &mfb_console_ri)
288 ri->ri_flg |= RI_NO_AUTO;
289 ri->ri_depth = 8; /* !! watch out !! */
290 ri->ri_width = 1280;
291 ri->ri_height = 1024;
292 ri->ri_stride = 2048;
293 ri->ri_bits = base + MX_FB_OFFSET;
294
295 /* clear the screen */
296 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
297
298 wsfont_init();
299 /* prefer 12 pixel wide font */
300 cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_L2R,
301 WSDISPLAY_FONTORDER_L2R);
302 if (cookie <= 0)
303 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R,
304 WSDISPLAY_FONTORDER_L2R);
305 if (cookie <= 0) {
306 printf("mfb: font table is empty\n");
307 return;
308 }
309
310 if (wsfont_lock(cookie, &ri->ri_font)) {
311 printf("mfb: couldn't lock font\n");
312 return;
313 }
314 ri->ri_wsfcookie = cookie;
315
316 rasops_init(ri, 34, 80);
317
318 /* XXX shouldn't be global */
319 mfb_stdscreen.nrows = ri->ri_rows;
320 mfb_stdscreen.ncols = ri->ri_cols;
321 mfb_stdscreen.textops = &ri->ri_ops;
322 mfb_stdscreen.capabilities = ri->ri_caps;
323 }
324
325 static int
326 mfbioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
327 {
328 struct mfb_softc *sc = v;
329 struct rasops_info *ri = sc->sc_ri;
330 int turnoff, s;
331
332 switch (cmd) {
333 case WSDISPLAYIO_GTYPE:
334 *(u_int *)data = WSDISPLAY_TYPE_MFB;
335 return (0);
336
337 case WSDISPLAYIO_GINFO:
338 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
339 wsd_fbip->height = ri->ri_height;
340 wsd_fbip->width = ri->ri_width;
341 wsd_fbip->depth = ri->ri_depth;
342 wsd_fbip->cmsize = 0;
343 #undef fbt
344 return (0);
345
346 case WSDISPLAYIO_GETCMAP:
347 case WSDISPLAYIO_PUTCMAP:
348 return (EPASSTHROUGH);
349
350 case WSDISPLAYIO_SVIDEO:
351 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
352 if (sc->sc_blanked != turnoff) {
353 sc->sc_blanked = turnoff;
354 #if 0 /* XXX later XXX */
355 To turn off,
356 - assign Bt455 cmap[1].green with value 0 (black),
357 - assign Bt431 register #0 with value 0x04 to hide sprite cursor.
358 #endif /* XXX XXX XXX */
359 }
360 return (0);
361
362 case WSDISPLAYIO_GVIDEO:
363 *(u_int *)data = sc->sc_blanked ?
364 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
365 return (0);
366
367 case WSDISPLAYIO_GCURPOS:
368 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
369 return (0);
370
371 case WSDISPLAYIO_SCURPOS:
372 s = spltty();
373 set_curpos(sc, (struct wsdisplay_curpos *)data);
374 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS;
375 splx(s);
376 return (0);
377
378 case WSDISPLAYIO_GCURMAX:
379 ((struct wsdisplay_curpos *)data)->x =
380 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
381 return (0);
382
383 case WSDISPLAYIO_GCURSOR:
384 return get_cursor(sc, (struct wsdisplay_cursor *)data);
385
386 case WSDISPLAYIO_SCURSOR:
387 return set_cursor(sc, (struct wsdisplay_cursor *)data);
388
389 case WSDISPLAYIO_SMODE:
390 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
391 s = spltty();
392 sc->sc_curenb = 0;
393 sc->sc_blanked = 0;
394 sc->sc_changed |= WSDISPLAY_CURSOR_DOCUR;
395 splx(s);
396 }
397 return (0);
398 }
399 return (EPASSTHROUGH);
400 }
401
402 static paddr_t
403 mfbmmap(void *v, void *vs, off_t offset, int prot)
404 {
405 struct mfb_softc *sc = v;
406
407 if (offset >= MX_FB_SIZE || offset < 0)
408 return (-1);
409 return machine_btop(sc->sc_vaddr + MX_FB_OFFSET + offset);
410 }
411
412 static int
413 mfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
414 int *curxp, int *curyp, long *attrp)
415 {
416 struct mfb_softc *sc = v;
417 struct rasops_info *ri = sc->sc_ri;
418 long defattr;
419
420 if (sc->nscreens > 0)
421 return (ENOMEM);
422
423 *cookiep = ri; /* one and only for now */
424 *curxp = 0;
425 *curyp = 0;
426 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
427 *attrp = defattr;
428 sc->nscreens++;
429 return (0);
430 }
431
432 static void
433 mfb_free_screen(void *v, void *cookie)
434 {
435 struct mfb_softc *sc = v;
436
437 if (sc->sc_ri == &mfb_console_ri)
438 panic("mfb_free_screen: console");
439
440 sc->nscreens--;
441 }
442
443 static int
444 mfb_show_screen(void *v, void *cookie, int waitok,
445 void (*cb)(void *, int, int), void *cbarg)
446 {
447
448 return (0);
449 }
450
451 /* EXPORT */ int
452 mfb_cnattach(tc_addr_t addr)
453 {
454 struct rasops_info *ri;
455 long defattr;
456
457 ri = &mfb_console_ri;
458 ri->ri_hw = (void *)addr;
459 mfb_common_init(ri);
460 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
461 wsdisplay_cnattach(&mfb_stdscreen, ri, 0, 0, defattr);
462 mfb_consaddr = addr;
463 return (0);
464 }
465
466 static int
467 mfbintr(void *arg)
468 {
469 struct mfb_softc *sc = arg;
470 char *base, *vdac, *curs;
471 int v;
472 volatile register int junk;
473
474 base = (void *)sc->sc_ri->ri_hw;
475 junk = *(uint8_t *)(base + MX_IREQ_OFFSET);
476 #if 0
477 *(uint8_t *)(base + MX_IREQ_OFFSET) = 0;
478 #endif
479 if (sc->sc_changed == 0)
480 return (1);
481
482 vdac = base + MX_BT455_OFFSET;
483 curs = base + MX_BT431_OFFSET;
484 v = sc->sc_changed;
485 if (v & WSDISPLAY_CURSOR_DOCUR) {
486 int onoff;
487
488 onoff = (sc->sc_curenb) ? 0x4444 : 0x0404;
489 SELECT431(curs, BT431_REG_COMMAND);
490 REGWRITE32(curs, bt_ctl, onoff);
491 }
492 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
493 int x, y;
494 uint32_t twin;
495
496 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
497 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
498
499 x += sc->sc_cursor.cc_magic.x;
500 y += sc->sc_cursor.cc_magic.y;
501
502 SELECT431(curs, BT431_REG_CURSOR_X_LOW);
503 REGWRITE32(curs, bt_ctl, TWIN_LO(x));
504 REGWRITE32(curs, bt_ctl, TWIN_HI(x));
505 REGWRITE32(curs, bt_ctl, TWIN_LO(y));
506 REGWRITE32(curs, bt_ctl, TWIN_HI(y));
507 }
508 if (v & WSDISPLAY_CURSOR_DOCMAP) {
509 uint8_t *cp = sc->sc_cursor.cc_color;
510
511 SELECT455(vdac, 8);
512 REGWRITE32(vdac, bt_cmap, 0);
513 REGWRITE32(vdac, bt_cmap, cp[1]);
514 REGWRITE32(vdac, bt_cmap, 0);
515
516 REGWRITE32(vdac, bt_cmap, 0);
517 REGWRITE32(vdac, bt_cmap, cp[1]);
518 REGWRITE32(vdac, bt_cmap, 0);
519
520 REGWRITE32(vdac, bt_ovly, 0);
521 REGWRITE32(vdac, bt_ovly, cp[0]);
522 REGWRITE32(vdac, bt_ovly, 0);
523 }
524 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
525 uint8_t *ip, *mp, img, msk;
526 int bcnt;
527
528 ip = (uint8_t *)sc->sc_cursor.cc_image;
529 mp = (uint8_t *)sc->sc_cursor.cc_mask;
530 bcnt = 0;
531 SELECT431(curs, BT431_REG_CRAM_BASE);
532
533 /* 64 pixel scan line is consisted with 16 byte cursor ram */
534 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
535 /* pad right half 32 pixel when smaller than 33 */
536 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
537 REGWRITE32(curs, bt_ram, 0);
538 }
539 else {
540 int half;
541
542 img = *ip++;
543 msk = *mp++;
544 img &= msk; /* cookie off image */
545 half = (flip[msk] << 8) | flip[img];
546 REGWRITE32(curs, bt_ram, half);
547 }
548 bcnt += 2;
549 }
550 /* pad unoccupied scan lines */
551 while (bcnt < CURSOR_MAX_SIZE * 16) {
552 REGWRITE32(curs, bt_ram, 0);
553 bcnt += 2;
554 }
555 }
556 sc->sc_changed = 0;
557 return (1);
558 }
559
560 static void
561 mfbhwinit(void *mfbbase)
562 {
563 char *vdac, *curs;
564 int i;
565
566 vdac = (char *)mfbbase + MX_BT455_OFFSET;
567 curs = (char *)mfbbase + MX_BT431_OFFSET;
568 SELECT431(curs, BT431_REG_COMMAND);
569 REGWRITE32(curs, bt_ctl, 0x0404);
570 REGWRITE32(curs, bt_ctl, 0); /* XLO */
571 REGWRITE32(curs, bt_ctl, 0); /* XHI */
572 REGWRITE32(curs, bt_ctl, 0); /* YLO */
573 REGWRITE32(curs, bt_ctl, 0); /* YHI */
574 REGWRITE32(curs, bt_ctl, 0); /* XWLO */
575 REGWRITE32(curs, bt_ctl, 0); /* XWHI */
576 REGWRITE32(curs, bt_ctl, 0); /* WYLO */
577 REGWRITE32(curs, bt_ctl, 0); /* WYLO */
578 REGWRITE32(curs, bt_ctl, 0); /* WWLO */
579 REGWRITE32(curs, bt_ctl, 0); /* WWHI */
580 REGWRITE32(curs, bt_ctl, 0); /* WHLO */
581 REGWRITE32(curs, bt_ctl, 0); /* WHHI */
582
583 /* 0: black, 1: white, 8,9: cursor mask, ovly: cursor image */
584 SELECT455(vdac, 0);
585 REGWRITE32(vdac, bt_cmap, 0);
586 REGWRITE32(vdac, bt_cmap, 0);
587 REGWRITE32(vdac, bt_cmap, 0);
588 REGWRITE32(vdac, bt_cmap, 0);
589 REGWRITE32(vdac, bt_cmap, 0xff);
590 REGWRITE32(vdac, bt_cmap, 0);
591 for (i = 2; i < 16; i++) {
592 REGWRITE32(vdac, bt_cmap, 0);
593 REGWRITE32(vdac, bt_cmap, 0);
594 REGWRITE32(vdac, bt_cmap, 0);
595 }
596 REGWRITE32(vdac, bt_ovly, 0);
597 REGWRITE32(vdac, bt_ovly, 0xff);
598 REGWRITE32(vdac, bt_ovly, 0);
599
600 SELECT431(curs, BT431_REG_CRAM_BASE);
601 for (i = 0; i < 512; i++) {
602 REGWRITE32(curs, bt_ram, 0);
603 }
604 }
605
606 static int
607 set_cursor(struct mfb_softc *sc, struct wsdisplay_cursor *p)
608 {
609 #define cc (&sc->sc_cursor)
610 u_int v, count = 0, icount = 0, index = 0;
611 uint64_t image[CURSOR_MAX_SIZE];
612 uint64_t mask[CURSOR_MAX_SIZE];
613 uint8_t color[6];
614 int error, s;
615
616 v = p->which;
617 if (v & WSDISPLAY_CURSOR_DOCMAP) {
618 index = p->cmap.index;
619 count = p->cmap.count;
620 if (index >= 2 || (index + count) > 2)
621 return (EINVAL);
622 error = copyin(p->cmap.red, &color[index], count);
623 if (error)
624 return error;
625 }
626 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
627 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
628 return (EINVAL);
629 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
630 error = copyin(p->image, image, icount);
631 if (error)
632 return error;
633 error = copyin(p->mask, mask, icount);
634 if (error)
635 return error;
636 }
637
638 s = spltty();
639 if (v & WSDISPLAY_CURSOR_DOCUR)
640 sc->sc_curenb = p->enable;
641 if (v & WSDISPLAY_CURSOR_DOPOS)
642 set_curpos(sc, &p->pos);
643 if (v & WSDISPLAY_CURSOR_DOHOT)
644 cc->cc_hot = p->hot;
645 if (v & WSDISPLAY_CURSOR_DOCMAP)
646 memcpy(&cc->cc_color[index], &color[index], count);
647 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
648 cc->cc_size = p->size;
649 memset(cc->cc_image, 0, sizeof cc->cc_image);
650 memcpy(cc->cc_image, image, icount);
651 memset(cc->cc_mask, 0, sizeof cc->cc_mask);
652 memcpy(cc->cc_mask, mask, icount);
653 }
654 sc->sc_changed |= v;
655 splx(s);
656
657 return (0);
658 #undef cc
659 }
660
661 static int
662 get_cursor(struct mfb_softc *sc, struct wsdisplay_cursor *p)
663 {
664 return (EPASSTHROUGH); /* XXX */
665 }
666
667 static void
668 set_curpos(struct mfb_softc *sc, struct wsdisplay_curpos *curpos)
669 {
670 struct rasops_info *ri = sc->sc_ri;
671 int x = curpos->x, y = curpos->y;
672
673 if (y < 0)
674 y = 0;
675 else if (y > ri->ri_height)
676 y = ri->ri_height;
677 if (x < 0)
678 x = 0;
679 else if (x > ri->ri_width)
680 x = ri->ri_width;
681 sc->sc_cursor.cc_pos.x = x;
682 sc->sc_cursor.cc_pos.y = y;
683 }
684