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