mfb.c revision 1.29 1 /* $NetBSD: mfb.c,v 1.29 2001/11/13 06:26:10 lukem 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.29 2001/11/13 06:26:10 lukem 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;
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 if ((cookie = wsfont_find(NULL, 12, 0, 0)) <= 0)
310 cookie = wsfont_find(NULL, 0, 0, 0);
311 if (cookie <= 0) {
312 printf("mfb: font table is empty\n");
313 return;
314 }
315
316 if (wsfont_lock(cookie, &ri->ri_font,
317 WSDISPLAY_FONTORDER_L2R, WSDISPLAY_FONTORDER_L2R) <= 0) {
318 printf("mfb: couldn't lock font\n");
319 return;
320 }
321 ri->ri_wsfcookie = cookie;
322
323 rasops_init(ri, 34, 80);
324
325 /* XXX shouldn't be global */
326 mfb_stdscreen.nrows = ri->ri_rows;
327 mfb_stdscreen.ncols = ri->ri_cols;
328 mfb_stdscreen.textops = &ri->ri_ops;
329 mfb_stdscreen.capabilities = ri->ri_caps;
330 }
331
332 static int
333 mfbioctl(v, cmd, data, flag, p)
334 void *v;
335 u_long cmd;
336 caddr_t data;
337 int flag;
338 struct proc *p;
339 {
340 struct mfb_softc *sc = v;
341 struct rasops_info *ri = sc->sc_ri;
342 int turnoff;
343
344 switch (cmd) {
345 case WSDISPLAYIO_GTYPE:
346 *(u_int *)data = WSDISPLAY_TYPE_MFB;
347 return (0);
348
349 case WSDISPLAYIO_GINFO:
350 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
351 wsd_fbip->height = ri->ri_height;
352 wsd_fbip->width = ri->ri_width;
353 wsd_fbip->depth = ri->ri_depth;
354 wsd_fbip->cmsize = 0;
355 #undef fbt
356 return (0);
357
358 case WSDISPLAYIO_GETCMAP:
359 case WSDISPLAYIO_PUTCMAP:
360 return (ENOTTY);
361
362 case WSDISPLAYIO_SVIDEO:
363 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
364 if ((sc->sc_blanked == 0) ^ turnoff) {
365 sc->sc_blanked = turnoff;
366 #if 0 /* XXX later XXX */
367 To turn off,
368 - assign Bt455 cmap[1].green with value 0 (black),
369 - assign Bt431 register #0 with value 0x04 to hide sprite cursor.
370 #endif /* XXX XXX XXX */
371 }
372 return (0);
373
374 case WSDISPLAYIO_GVIDEO:
375 *(u_int *)data = sc->sc_blanked ?
376 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
377 return (0);
378
379 case WSDISPLAYIO_GCURPOS:
380 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
381 return (0);
382
383 case WSDISPLAYIO_SCURPOS:
384 set_curpos(sc, (struct wsdisplay_curpos *)data);
385 sc->sc_changed = WSDISPLAY_CURSOR_DOPOS;
386 return (0);
387
388 case WSDISPLAYIO_GCURMAX:
389 ((struct wsdisplay_curpos *)data)->x =
390 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
391 return (0);
392
393 case WSDISPLAYIO_GCURSOR:
394 return get_cursor(sc, (struct wsdisplay_cursor *)data);
395
396 case WSDISPLAYIO_SCURSOR:
397 return set_cursor(sc, (struct wsdisplay_cursor *)data);
398 }
399 return (ENOTTY);
400 }
401
402 static paddr_t
403 mfbmmap(v, offset, prot)
404 void *v;
405 off_t offset;
406 int prot;
407 {
408 struct mfb_softc *sc = v;
409
410 if (offset >= MX_FB_SIZE || offset < 0)
411 return (-1);
412 return machine_btop(sc->sc_vaddr + MX_FB_OFFSET + offset);
413 }
414
415 static int
416 mfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
417 void *v;
418 const struct wsscreen_descr *type;
419 void **cookiep;
420 int *curxp, *curyp;
421 long *attrp;
422 {
423 struct mfb_softc *sc = v;
424 struct rasops_info *ri = sc->sc_ri;
425 long defattr;
426
427 if (sc->nscreens > 0)
428 return (ENOMEM);
429
430 *cookiep = ri; /* one and only for now */
431 *curxp = 0;
432 *curyp = 0;
433 (*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr);
434 *attrp = defattr;
435 sc->nscreens++;
436 return (0);
437 }
438
439 static void
440 mfb_free_screen(v, cookie)
441 void *v;
442 void *cookie;
443 {
444 struct mfb_softc *sc = v;
445
446 if (sc->sc_ri == &mfb_console_ri)
447 panic("mfb_free_screen: console");
448
449 sc->nscreens--;
450 }
451
452 static int
453 mfb_show_screen(v, cookie, waitok, cb, cbarg)
454 void *v;
455 void *cookie;
456 int waitok;
457 void (*cb) __P((void *, int, int));
458 void *cbarg;
459 {
460
461 return (0);
462 }
463
464 /* EXPORT */ int
465 mfb_cnattach(addr)
466 tc_addr_t addr;
467 {
468 struct rasops_info *ri;
469 long defattr;
470
471 ri = &mfb_console_ri;
472 ri->ri_hw = (void *)addr;
473 mfb_common_init(ri);
474 (*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr);
475 wsdisplay_cnattach(&mfb_stdscreen, ri, 0, 0, defattr);
476 mfb_consaddr = addr;
477 return (0);
478 }
479
480 static int
481 mfbintr(arg)
482 void *arg;
483 {
484 struct mfb_softc *sc = arg;
485 caddr_t base, vdac, curs;
486 int v;
487 volatile register int junk;
488
489 base = (caddr_t)sc->sc_ri->ri_hw;
490 junk = *(u_int8_t *)(base + MX_IREQ_OFFSET);
491 #if 0
492 *(u_int8_t *)(base + MX_IREQ_OFFSET) = 0;
493 #endif
494 if (sc->sc_changed == 0)
495 goto done;
496
497 vdac = base + MX_BT455_OFFSET;
498 curs = base + MX_BT431_OFFSET;
499 v = sc->sc_changed;
500 if (v & WSDISPLAY_CURSOR_DOCUR) {
501 SELECT431(curs, BT431_REG_COMMAND);
502 HALF(curs, bt_ctl) = (sc->sc_curenb) ? 0x4444 : 0x0404;
503 }
504 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
505 int x, y;
506 u_int16_t twin;
507
508 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
509 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
510
511 x += sc->sc_cursor.cc_magic.x;
512 y += sc->sc_cursor.cc_magic.y;
513
514 SELECT431(curs, BT431_REG_CURSOR_X_LOW);
515 HALF(curs, bt_ctl) = TWIN_LO(x); tc_wmb();
516 HALF(curs, bt_ctl) = TWIN_HI(x); tc_wmb();
517 HALF(curs, bt_ctl) = TWIN_LO(y); tc_wmb();
518 HALF(curs, bt_ctl) = TWIN_HI(y); tc_wmb();
519 }
520 if (v & WSDISPLAY_CURSOR_DOCMAP) {
521 u_int8_t *cp = sc->sc_cursor.cc_color;
522
523 SELECT455(vdac, 8);
524 BYTE(vdac, bt_cmap) = 0; tc_wmb();
525 BYTE(vdac, bt_cmap) = cp[1]; tc_wmb();
526 BYTE(vdac, bt_cmap) = 0; tc_wmb();
527
528 BYTE(vdac, bt_cmap) = 0; tc_wmb();
529 BYTE(vdac, bt_cmap) = cp[1]; tc_wmb();
530 BYTE(vdac, bt_cmap) = 0; tc_wmb();
531
532 BYTE(vdac, bt_ovly) = 0; tc_wmb();
533 BYTE(vdac, bt_ovly) = cp[0]; tc_wmb();
534 BYTE(vdac, bt_ovly) = 0; tc_wmb();
535 }
536 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
537 u_int8_t *ip, *mp, img, msk;
538 int bcnt;
539
540 ip = (u_int8_t *)sc->sc_cursor.cc_image;
541 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
542 bcnt = 0;
543 SELECT431(curs, BT431_REG_CRAM_BASE);
544
545 /* 64 pixel scan line is consisted with 16 byte cursor ram */
546 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
547 /* pad right half 32 pixel when smaller than 33 */
548 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
549 HALF(curs, bt_ram) = 0;
550 tc_wmb();
551 }
552 else {
553 img = *ip++;
554 msk = *mp++;
555 img &= msk; /* cookie off image */
556 HALF(curs, bt_ram)
557 = (flip[msk] << 8) | flip[img];
558 tc_wmb();
559 }
560 bcnt += 2;
561 }
562 /* pad unoccupied scan lines */
563 while (bcnt < CURSOR_MAX_SIZE * 16) {
564 HALF(curs, bt_ram) = 0;
565 tc_wmb();
566 bcnt += 2;
567 }
568 }
569 sc->sc_changed = 0;
570 done:
571 return (1);
572 }
573
574 static void
575 mfbhwinit(mfbbase)
576 caddr_t mfbbase;
577 {
578 caddr_t vdac, curs;
579 int i;
580
581 vdac = mfbbase + MX_BT455_OFFSET;
582 curs = mfbbase + MX_BT431_OFFSET;
583 SELECT431(curs, BT431_REG_COMMAND);
584 HALF(curs, bt_ctl) = 0x0404; tc_wmb();
585 HALF(curs, bt_ctl) = 0; /* XLO */ tc_wmb();
586 HALF(curs, bt_ctl) = 0; /* XHI */ tc_wmb();
587 HALF(curs, bt_ctl) = 0; /* YLO */ tc_wmb();
588 HALF(curs, bt_ctl) = 0; /* YHI */ tc_wmb();
589 HALF(curs, bt_ctl) = 0; /* XWLO */ tc_wmb();
590 HALF(curs, bt_ctl) = 0; /* XWHI */ tc_wmb();
591 HALF(curs, bt_ctl) = 0; /* WYLO */ tc_wmb();
592 HALF(curs, bt_ctl) = 0; /* WYLO */ tc_wmb();
593 HALF(curs, bt_ctl) = 0; /* WWLO */ tc_wmb();
594 HALF(curs, bt_ctl) = 0; /* WWHI */ tc_wmb();
595 HALF(curs, bt_ctl) = 0; /* WHLO */ tc_wmb();
596 HALF(curs, bt_ctl) = 0; /* WHHI */ tc_wmb();
597
598 /* 0: black, 1: white, 8,9: cursor mask, ovly: cursor image */
599 SELECT455(vdac, 0);
600 BYTE(vdac, bt_cmap) = 0; tc_wmb();
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) = 0xff; tc_wmb();
605 BYTE(vdac, bt_cmap) = 0; tc_wmb();
606 for (i = 2; i < 16; i++) {
607 BYTE(vdac, bt_cmap) = 0; tc_wmb();
608 BYTE(vdac, bt_cmap) = 0; tc_wmb();
609 BYTE(vdac, bt_cmap) = 0; tc_wmb();
610 }
611 BYTE(vdac, bt_ovly) = 0; tc_wmb();
612 BYTE(vdac, bt_ovly) = 0xff; tc_wmb();
613 BYTE(vdac, bt_ovly) = 0; tc_wmb();
614
615 SELECT431(curs, BT431_REG_CRAM_BASE);
616 for (i = 0; i < 512; i++) {
617 HALF(curs, bt_ram) = 0; tc_wmb();
618 }
619 }
620
621 static int
622 set_cursor(sc, p)
623 struct mfb_softc *sc;
624 struct wsdisplay_cursor *p;
625 {
626 #define cc (&sc->sc_cursor)
627 u_int v, count, index;
628
629 v = p->which;
630 if (v & WSDISPLAY_CURSOR_DOCMAP) {
631 index = p->cmap.index;
632 count = p->cmap.count;
633 if (index >= 2 || (index + count) > 2)
634 return (EINVAL);
635 if (!uvm_useracc(p->cmap.red, count, B_READ))
636 return (EFAULT);
637 }
638 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
639 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
640 return (EINVAL);
641 count = ((p->size.x < 33) ? 4 : 8) * p->size.y;
642 if (!uvm_useracc(p->image, count, B_READ) ||
643 !uvm_useracc(p->mask, count, B_READ))
644 return (EFAULT);
645 }
646
647 if (v & WSDISPLAY_CURSOR_DOCUR)
648 sc->sc_curenb = p->enable;
649 if (v & WSDISPLAY_CURSOR_DOPOS)
650 set_curpos(sc, &p->pos);
651 if (v & WSDISPLAY_CURSOR_DOHOT)
652 cc->cc_hot = p->hot;
653 if (v & WSDISPLAY_CURSOR_DOCMAP)
654 copyin(p->cmap.red, &cc->cc_color[index], count);
655 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
656 cc->cc_size = p->size;
657 memset(cc->cc_image, 0, sizeof cc->cc_image);
658 copyin(p->image, cc->cc_image, count);
659 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, count);
660 }
661 sc->sc_changed = v;
662
663 return (0);
664 #undef cc
665 }
666
667 static int
668 get_cursor(sc, p)
669 struct mfb_softc *sc;
670 struct wsdisplay_cursor *p;
671 {
672 return (ENOTTY); /* XXX */
673 }
674
675 static void
676 set_curpos(sc, curpos)
677 struct mfb_softc *sc;
678 struct wsdisplay_curpos *curpos;
679 {
680 struct rasops_info *ri = sc->sc_ri;
681 int x = curpos->x, y = curpos->y;
682
683 if (y < 0)
684 y = 0;
685 else if (y > ri->ri_height)
686 y = ri->ri_height;
687 if (x < 0)
688 x = 0;
689 else if (x > ri->ri_width)
690 x = ri->ri_width;
691 sc->sc_cursor.cc_pos.x = x;
692 sc->sc_cursor.cc_pos.y = y;
693 }
694