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