Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / tc / mfb.c
blobebd27b505f10a9a3e12af761d8d6af7d918c6255
1 /* $NetBSD: mfb.c,v 1.53 2008/12/17 20:51:35 cegger Exp $ */
3 /*-
4 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tohru Nishimura.
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.
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.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: mfb.c,v 1.53 2008/12/17 20:51:35 cegger Exp $");
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>
43 #include <sys/bus.h>
44 #include <sys/intr.h>
46 #include <dev/wscons/wsconsio.h>
47 #include <dev/wscons/wsdisplayvar.h>
49 #include <dev/rasops/rasops.h>
50 #include <dev/wsfont/wsfont.h>
52 #include <dev/tc/tcvar.h>
53 #include <dev/ic/bt431reg.h>
55 #include <uvm/uvm_extern.h>
57 #if defined(pmax)
58 #define machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x))
59 #endif
61 #if defined(alpha)
62 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x))
63 #endif
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
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
77 #define REGWRITE32(p,i,v) do { \
78 *(volatile uint32_t *)((p) + (i)) = (v); tc_wmb(); \
79 } while (0)
81 #define SELECT455(p,r) do { \
82 REGWRITE32((p), bt_reg, (r)); \
83 REGWRITE32((p), bt_clr, 0); \
84 } while (0)
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)
90 #define SELECT431(p,r) do { \
91 REGWRITE32((p), bt_lo, TWIN(r)); \
92 REGWRITE32((p), bt_hi, 0); \
93 } while (0)
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];
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;
117 #define MX_MAGIC_X 360
118 #define MX_MAGIC_Y 36
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 */
126 static int mfbmatch(device_t, cfdata_t, void *);
127 static void mfbattach(device_t, device_t, void *);
129 CFATTACH_DECL_NEW(mfb, sizeof(struct mfb_softc),
130 mfbmatch, mfbattach, NULL, NULL);
132 static void mfb_common_init(struct rasops_info *);
133 static struct rasops_info mfb_console_ri;
134 static tc_addr_t mfb_consaddr;
136 static struct wsscreen_descr mfb_stdscreen = {
137 "std", 0, 0,
138 0, /* textops */
139 0, 0,
140 WSSCREEN_REVERSE
143 static const struct wsscreen_descr *_mfb_scrlist[] = {
144 &mfb_stdscreen,
147 static const struct wsscreen_list mfb_screenlist = {
148 sizeof(_mfb_scrlist) / sizeof(struct wsscreen_descr *), _mfb_scrlist
151 static int mfbioctl(void *, void *, u_long, void *, int, struct lwp *);
152 static paddr_t mfbmmap(void *, void *, off_t, int);
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 *);
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 */
169 int mfb_cnattach(tc_addr_t);
170 static int mfbintr(void *);
171 static void mfbhwinit(void *);
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 *);
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,
213 static int
214 mfbmatch(device_t parent, cfdata_t match, void *aux)
216 struct tc_attach_args *ta = aux;
218 if (strncmp("PMAG-AA ", ta->ta_modname, TC_ROM_LLEN) != 0)
219 return (0);
221 return (1);
224 static void
225 mfbattach(device_t parent, device_t self, void *aux)
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;
234 console = (ta->ta_addr == mfb_consaddr);
235 if (console) {
236 sc->sc_ri = ri = &mfb_console_ri;
237 sc->nscreens = 1;
239 else {
240 ri = malloc(sizeof(struct rasops_info),
241 M_DEVBUF, M_NOWAIT);
242 if (ri == NULL) {
243 printf(": can't alloc memory\n");
244 return;
246 memset(ri, 0, sizeof(struct rasops_info));
248 ri->ri_hw = (void *)ta->ta_addr;
249 mfb_common_init(ri);
250 sc->sc_ri = ri;
252 printf(": %dx%d, 1bpp\n", ri->ri_width, ri->ri_height);
254 sc->sc_vaddr = ta->ta_addr;
255 sc->sc_cursor.cc_magic.x = MX_MAGIC_X;
256 sc->sc_cursor.cc_magic.y = MX_MAGIC_Y;
257 sc->sc_blanked = sc->sc_curenb = 0;
259 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, mfbintr, sc);
261 /* clear any pending interrupts */
262 *(uint8_t *)((char *)ri->ri_hw + MX_IREQ_OFFSET) = 0;
263 junk = *(uint8_t *)((char *)ri->ri_hw + MX_IREQ_OFFSET);
264 *(uint8_t *)((char *)ri->ri_hw + MX_IREQ_OFFSET) = 1;
266 waa.console = console;
267 waa.scrdata = &mfb_screenlist;
268 waa.accessops = &mfb_accessops;
269 waa.accesscookie = sc;
271 config_found(self, &waa, wsemuldisplaydevprint);
274 static void
275 mfb_common_init(struct rasops_info *ri)
277 char *base;
278 int cookie;
280 base = (void *)ri->ri_hw;
282 /* initialize colormap and cursor hardware */
283 mfbhwinit(base);
285 ri->ri_flg = RI_CENTER | RI_FORCEMONO;
286 ri->ri_depth = 8; /* !! watch out !! */
287 ri->ri_width = 1280;
288 ri->ri_height = 1024;
289 ri->ri_stride = 2048;
290 ri->ri_bits = base + MX_FB_OFFSET;
292 /* clear the screen */
293 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
295 wsfont_init();
296 /* prefer 12 pixel wide font */
297 cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_L2R,
298 WSDISPLAY_FONTORDER_L2R);
299 if (cookie <= 0)
300 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R,
301 WSDISPLAY_FONTORDER_L2R);
302 if (cookie <= 0) {
303 printf("mfb: font table is empty\n");
304 return;
307 if (wsfont_lock(cookie, &ri->ri_font)) {
308 printf("mfb: couldn't lock font\n");
309 return;
311 ri->ri_wsfcookie = cookie;
313 rasops_init(ri, 34, 80);
315 /* XXX shouldn't be global */
316 mfb_stdscreen.nrows = ri->ri_rows;
317 mfb_stdscreen.ncols = ri->ri_cols;
318 mfb_stdscreen.textops = &ri->ri_ops;
319 mfb_stdscreen.capabilities = ri->ri_caps;
322 static int
323 mfbioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
325 struct mfb_softc *sc = v;
326 struct rasops_info *ri = sc->sc_ri;
327 int turnoff, s;
329 switch (cmd) {
330 case WSDISPLAYIO_GTYPE:
331 *(u_int *)data = WSDISPLAY_TYPE_MFB;
332 return (0);
334 case WSDISPLAYIO_GINFO:
335 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
336 wsd_fbip->height = ri->ri_height;
337 wsd_fbip->width = ri->ri_width;
338 wsd_fbip->depth = ri->ri_depth;
339 wsd_fbip->cmsize = 0;
340 #undef fbt
341 return (0);
343 case WSDISPLAYIO_GETCMAP:
344 case WSDISPLAYIO_PUTCMAP:
345 return (EPASSTHROUGH);
347 case WSDISPLAYIO_SVIDEO:
348 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
349 if (sc->sc_blanked != turnoff) {
350 sc->sc_blanked = turnoff;
351 #if 0 /* XXX later XXX */
352 To turn off,
353 - assign Bt455 cmap[1].green with value 0 (black),
354 - assign Bt431 register #0 with value 0x04 to hide sprite cursor.
355 #endif /* XXX XXX XXX */
357 return (0);
359 case WSDISPLAYIO_GVIDEO:
360 *(u_int *)data = sc->sc_blanked ?
361 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
362 return (0);
364 case WSDISPLAYIO_GCURPOS:
365 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
366 return (0);
368 case WSDISPLAYIO_SCURPOS:
369 s = spltty();
370 set_curpos(sc, (struct wsdisplay_curpos *)data);
371 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS;
372 splx(s);
373 return (0);
375 case WSDISPLAYIO_GCURMAX:
376 ((struct wsdisplay_curpos *)data)->x =
377 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
378 return (0);
380 case WSDISPLAYIO_GCURSOR:
381 return get_cursor(sc, (struct wsdisplay_cursor *)data);
383 case WSDISPLAYIO_SCURSOR:
384 return set_cursor(sc, (struct wsdisplay_cursor *)data);
386 case WSDISPLAYIO_SMODE:
387 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
388 s = spltty();
389 sc->sc_curenb = 0;
390 sc->sc_blanked = 0;
391 sc->sc_changed |= WSDISPLAY_CURSOR_DOCUR;
392 splx(s);
394 return (0);
396 return (EPASSTHROUGH);
399 static paddr_t
400 mfbmmap(void *v, void *vs, off_t offset, int prot)
402 struct mfb_softc *sc = v;
404 if (offset >= MX_FB_SIZE || offset < 0)
405 return (-1);
406 return machine_btop(sc->sc_vaddr + MX_FB_OFFSET + offset);
409 static int
410 mfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
411 int *curxp, int *curyp, long *attrp)
413 struct mfb_softc *sc = v;
414 struct rasops_info *ri = sc->sc_ri;
415 long defattr;
417 if (sc->nscreens > 0)
418 return (ENOMEM);
420 *cookiep = ri; /* one and only for now */
421 *curxp = 0;
422 *curyp = 0;
423 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
424 *attrp = defattr;
425 sc->nscreens++;
426 return (0);
429 static void
430 mfb_free_screen(void *v, void *cookie)
432 struct mfb_softc *sc = v;
434 if (sc->sc_ri == &mfb_console_ri)
435 panic("mfb_free_screen: console");
437 sc->nscreens--;
440 static int
441 mfb_show_screen(void *v, void *cookie, int waitok,
442 void (*cb)(void *, int, int), void *cbarg)
445 return (0);
448 /* EXPORT */ int
449 mfb_cnattach(tc_addr_t addr)
451 struct rasops_info *ri;
452 long defattr;
454 ri = &mfb_console_ri;
455 ri->ri_hw = (void *)addr;
456 mfb_common_init(ri);
457 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
458 wsdisplay_cnattach(&mfb_stdscreen, ri, 0, 0, defattr);
459 mfb_consaddr = addr;
460 return (0);
463 static int
464 mfbintr(void *arg)
466 struct mfb_softc *sc = arg;
467 char *base, *vdac, *curs;
468 int v;
469 volatile register int junk;
471 base = (void *)sc->sc_ri->ri_hw;
472 junk = *(uint8_t *)(base + MX_IREQ_OFFSET);
473 #if 0
474 *(uint8_t *)(base + MX_IREQ_OFFSET) = 0;
475 #endif
476 if (sc->sc_changed == 0)
477 return (1);
479 vdac = base + MX_BT455_OFFSET;
480 curs = base + MX_BT431_OFFSET;
481 v = sc->sc_changed;
482 if (v & WSDISPLAY_CURSOR_DOCUR) {
483 int onoff;
485 onoff = (sc->sc_curenb) ? 0x4444 : 0x0404;
486 SELECT431(curs, BT431_REG_COMMAND);
487 REGWRITE32(curs, bt_ctl, onoff);
489 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
490 int x, y;
491 uint32_t twin;
493 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
494 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
496 x += sc->sc_cursor.cc_magic.x;
497 y += sc->sc_cursor.cc_magic.y;
499 SELECT431(curs, BT431_REG_CURSOR_X_LOW);
500 REGWRITE32(curs, bt_ctl, TWIN_LO(x));
501 REGWRITE32(curs, bt_ctl, TWIN_HI(x));
502 REGWRITE32(curs, bt_ctl, TWIN_LO(y));
503 REGWRITE32(curs, bt_ctl, TWIN_HI(y));
505 if (v & WSDISPLAY_CURSOR_DOCMAP) {
506 uint8_t *cp = sc->sc_cursor.cc_color;
508 SELECT455(vdac, 8);
509 REGWRITE32(vdac, bt_cmap, 0);
510 REGWRITE32(vdac, bt_cmap, cp[1]);
511 REGWRITE32(vdac, bt_cmap, 0);
513 REGWRITE32(vdac, bt_cmap, 0);
514 REGWRITE32(vdac, bt_cmap, cp[1]);
515 REGWRITE32(vdac, bt_cmap, 0);
517 REGWRITE32(vdac, bt_ovly, 0);
518 REGWRITE32(vdac, bt_ovly, cp[0]);
519 REGWRITE32(vdac, bt_ovly, 0);
521 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
522 uint8_t *ip, *mp, img, msk;
523 int bcnt;
525 ip = (uint8_t *)sc->sc_cursor.cc_image;
526 mp = (uint8_t *)sc->sc_cursor.cc_mask;
527 bcnt = 0;
528 SELECT431(curs, BT431_REG_CRAM_BASE);
530 /* 64 pixel scan line is consisted with 16 byte cursor ram */
531 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
532 /* pad right half 32 pixel when smaller than 33 */
533 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
534 REGWRITE32(curs, bt_ram, 0);
536 else {
537 int half;
539 img = *ip++;
540 msk = *mp++;
541 img &= msk; /* cookie off image */
542 half = (flip[msk] << 8) | flip[img];
543 REGWRITE32(curs, bt_ram, half);
545 bcnt += 2;
547 /* pad unoccupied scan lines */
548 while (bcnt < CURSOR_MAX_SIZE * 16) {
549 REGWRITE32(curs, bt_ram, 0);
550 bcnt += 2;
553 sc->sc_changed = 0;
554 return (1);
557 static void
558 mfbhwinit(void *mfbbase)
560 char *vdac, *curs;
561 int i;
563 vdac = (char *)mfbbase + MX_BT455_OFFSET;
564 curs = (char *)mfbbase + MX_BT431_OFFSET;
565 SELECT431(curs, BT431_REG_COMMAND);
566 REGWRITE32(curs, bt_ctl, 0x0404);
567 REGWRITE32(curs, bt_ctl, 0); /* XLO */
568 REGWRITE32(curs, bt_ctl, 0); /* XHI */
569 REGWRITE32(curs, bt_ctl, 0); /* YLO */
570 REGWRITE32(curs, bt_ctl, 0); /* YHI */
571 REGWRITE32(curs, bt_ctl, 0); /* XWLO */
572 REGWRITE32(curs, bt_ctl, 0); /* XWHI */
573 REGWRITE32(curs, bt_ctl, 0); /* WYLO */
574 REGWRITE32(curs, bt_ctl, 0); /* WYLO */
575 REGWRITE32(curs, bt_ctl, 0); /* WWLO */
576 REGWRITE32(curs, bt_ctl, 0); /* WWHI */
577 REGWRITE32(curs, bt_ctl, 0); /* WHLO */
578 REGWRITE32(curs, bt_ctl, 0); /* WHHI */
580 /* 0: black, 1: white, 8,9: cursor mask, ovly: cursor image */
581 SELECT455(vdac, 0);
582 REGWRITE32(vdac, bt_cmap, 0);
583 REGWRITE32(vdac, bt_cmap, 0);
584 REGWRITE32(vdac, bt_cmap, 0);
585 REGWRITE32(vdac, bt_cmap, 0);
586 REGWRITE32(vdac, bt_cmap, 0xff);
587 REGWRITE32(vdac, bt_cmap, 0);
588 for (i = 2; i < 16; i++) {
589 REGWRITE32(vdac, bt_cmap, 0);
590 REGWRITE32(vdac, bt_cmap, 0);
591 REGWRITE32(vdac, bt_cmap, 0);
593 REGWRITE32(vdac, bt_ovly, 0);
594 REGWRITE32(vdac, bt_ovly, 0xff);
595 REGWRITE32(vdac, bt_ovly, 0);
597 SELECT431(curs, BT431_REG_CRAM_BASE);
598 for (i = 0; i < 512; i++) {
599 REGWRITE32(curs, bt_ram, 0);
603 static int
604 set_cursor(struct mfb_softc *sc, struct wsdisplay_cursor *p)
606 #define cc (&sc->sc_cursor)
607 u_int v, count = 0, icount = 0, index = 0;
608 uint64_t image[CURSOR_MAX_SIZE];
609 uint64_t mask[CURSOR_MAX_SIZE];
610 uint8_t color[6];
611 int error, s;
613 v = p->which;
614 if (v & WSDISPLAY_CURSOR_DOCMAP) {
615 index = p->cmap.index;
616 count = p->cmap.count;
617 if (index >= 2 || (index + count) > 2)
618 return (EINVAL);
619 error = copyin(p->cmap.red, &color[index], count);
620 if (error)
621 return error;
623 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
624 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
625 return (EINVAL);
626 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
627 error = copyin(p->image, image, icount);
628 if (error)
629 return error;
630 error = copyin(p->mask, mask, icount);
631 if (error)
632 return error;
635 s = spltty();
636 if (v & WSDISPLAY_CURSOR_DOCUR)
637 sc->sc_curenb = p->enable;
638 if (v & WSDISPLAY_CURSOR_DOPOS)
639 set_curpos(sc, &p->pos);
640 if (v & WSDISPLAY_CURSOR_DOHOT)
641 cc->cc_hot = p->hot;
642 if (v & WSDISPLAY_CURSOR_DOCMAP)
643 memcpy(&cc->cc_color[index], &color[index], count);
644 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
645 cc->cc_size = p->size;
646 memset(cc->cc_image, 0, sizeof cc->cc_image);
647 memcpy(cc->cc_image, image, icount);
648 memset(cc->cc_mask, 0, sizeof cc->cc_mask);
649 memcpy(cc->cc_mask, mask, icount);
651 sc->sc_changed |= v;
652 splx(s);
654 return (0);
655 #undef cc
658 static int
659 get_cursor(struct mfb_softc *sc, struct wsdisplay_cursor *p)
661 return (EPASSTHROUGH); /* XXX */
664 static void
665 set_curpos(struct mfb_softc *sc, struct wsdisplay_curpos *curpos)
667 struct rasops_info *ri = sc->sc_ri;
668 int x = curpos->x, y = curpos->y;
670 if (y < 0)
671 y = 0;
672 else if (y > ri->ri_height)
673 y = ri->ri_height;
674 if (x < 0)
675 x = 0;
676 else if (x > ri->ri_width)
677 x = ri->ri_width;
678 sc->sc_cursor.cc_pos.x = x;
679 sc->sc_cursor.cc_pos.y = y;