mfb.c revision 1.4 1 /* $NetBSD: mfb.c,v 1.4 1998/11/18 12:26:32 nisimura Exp $ */
2
3 /*
4 * Copyright (c) 1998 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.4 1998/11/18 12:26:32 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 #include <vm/vm.h>
45
46 #include <machine/bus.h>
47 #include <machine/intr.h>
48
49 #include <dev/rcons/raster.h>
50 #include <dev/wscons/wsconsio.h>
51 #include <dev/wscons/wscons_raster.h>
52 #include <dev/wscons/wsdisplayvar.h>
53 #include <machine/autoconf.h>
54
55 #include <dev/tc/tcvar.h>
56 #include <dev/ic/bt431reg.h>
57
58 #include "opt_uvm.h"
59 #if defined(UVM)
60 #include <uvm/uvm_extern.h>
61 #define useracc uvm_useracc
62 #endif
63
64 /* XXX BUS'IFYING XXX */
65
66 #if defined(__pmax__)
67 #define machine_btop(x) mips_btop(x)
68 #define MACHINE_KSEG0_TO_PHYS(x) MIPS_KSEG0_TO_PHYS(x)
69
70 struct bt455reg {
71 u_int8_t bt_reg;
72 unsigned : 24;
73 u_int8_t bt_cmap;
74 unsigned : 24;
75 u_int8_t bt_clr;
76 unsigned : 24;
77 u_int8_t bt_ovly;
78 };
79
80 /*
81 * N.B. a paif of Bt431s are located adjascently.
82 * struct bt431twin {
83 * struct {
84 * u_int8_t u0; for sprite image
85 * u_int8_t u1; for sprite mask
86 * unsigned :16;
87 * } bt_lo;
88 * ...
89 */
90 struct bt431reg {
91 u_int16_t bt_lo;
92 unsigned : 16;
93 u_int16_t bt_hi;
94 unsigned : 16;
95 u_int16_t bt_ram;
96 unsigned : 16;
97 u_int16_t bt_ctl;
98 };
99
100 #endif
101
102 #if defined(__alpha__) || defined(alpha)
103 /*
104 * Digital UNIX never supports PMAG-AA
105 */
106 #define machine_btop(x) alpha_btop(x)
107 #define MACHINE_KSEG0_TO_PHYS(x) ALPHA_K0SEG_TO_PHYS(x)
108
109 struct bt455reg {
110 u_int32_t bt_reg;
111 u_int32_t bt_cmap;
112 u_int32_t bt_clr;
113 u_int32_t bt_ovly;
114 };
115
116 struct bt431reg {
117 u_int32_t bt_lo;
118 u_int32_t bt_hi;
119 u_int32_t bt_ram;
120 u_int32_t bt_ctl;
121 };
122 #endif
123
124 /* XXX XXX XXX */
125
126 struct fb_devconfig {
127 vaddr_t dc_vaddr; /* memory space virtual base address */
128 paddr_t dc_paddr; /* memory space physical base address */
129 vsize_t dc_size; /* size of slot memory */
130 int dc_wid; /* width of frame buffer */
131 int dc_ht; /* height of frame buffer */
132 int dc_depth; /* depth, bits per pixel */
133 int dc_rowbytes; /* bytes in a FB scan line */
134 vaddr_t dc_videobase; /* base of flat frame buffer */
135 struct raster dc_raster; /* raster description */
136 struct rcons dc_rcons; /* raster blitter control info */
137 int dc_blanked; /* currently has video disabled */
138 };
139
140 struct hwcursor {
141 struct wsdisplay_curpos cc_pos;
142 struct wsdisplay_curpos cc_hot;
143 struct wsdisplay_curpos cc_size;
144 #define CURSOR_MAX_SIZE 64
145 u_int8_t cc_color[6];
146 u_int64_t cc_image[64 + 64];
147 };
148
149 struct mfb_softc {
150 struct device sc_dev;
151 struct fb_devconfig *sc_dc; /* device configuration */
152 struct hwcursor sc_cursor; /* software copy of cursor */
153 int sc_curenb; /* cursor sprite enabled */
154 int sc_changed; /* need update of colormap */
155 #define DATA_ENB_CHANGED 0x01 /* cursor enable changed */
156 #define DATA_CURCMAP_CHANGED 0x02 /* cursor colormap changed */
157 #define DATA_CURSHAPE_CHANGED 0x04 /* cursor size, image, mask changed */
158 #define DATA_CMAP_CHANGED 0x08 /* colormap changed */
159 #define DATA_ALL_CHANGED 0x0f
160 int nscreens;
161 short magic_x, magic_y; /* MX cursor location offset */
162 #define MX_MAGIC_X 360
163 #define MX_MAGIC_Y 36
164 };
165
166 #define MX_FB_OFFSET 0x200000
167 #define MX_FB_SIZE 0x40000
168 #define MX_BT455_OFFSET 0x100000
169 #define MX_BT431_OFFSET 0x180000
170 #define MX_IREQ_OFFSET 0x080000 /* Interrupt req. control */
171
172 int mfbmatch __P((struct device *, struct cfdata *, void *));
173 void mfbattach __P((struct device *, struct device *, void *));
174
175 struct cfattach mfb_ca = {
176 sizeof(struct mfb_softc), mfbmatch, mfbattach,
177 };
178
179 void mfb_getdevconfig __P((tc_addr_t, struct fb_devconfig *));
180 struct fb_devconfig mfb_console_dc;
181 tc_addr_t mfb_consaddr;
182
183 struct wsdisplay_emulops mfb_emulops = {
184 rcons_cursor, /* could use hardware cursor; punt */
185 rcons_mapchar,
186 rcons_putchar,
187 rcons_copycols,
188 rcons_erasecols,
189 rcons_copyrows,
190 rcons_eraserows,
191 rcons_alloc_attr
192 };
193
194 struct wsscreen_descr mfb_stdscreen = {
195 "std", 0, 0,
196 &mfb_emulops,
197 0, 0,
198 0
199 };
200
201 const struct wsscreen_descr *_mfb_scrlist[] = {
202 &mfb_stdscreen,
203 };
204
205 struct wsscreen_list mfb_screenlist = {
206 sizeof(_mfb_scrlist) / sizeof(struct wsscreen_descr *), _mfb_scrlist
207 };
208
209 int mfbioctl __P((void *, u_long, caddr_t, int, struct proc *));
210 int mfbmmap __P((void *, off_t, int));
211
212 int mfb_alloc_screen __P((void *, const struct wsscreen_descr *,
213 void **, int *, int *, long *));
214 void mfb_free_screen __P((void *, void *));
215 void mfb_show_screen __P((void *, void *));
216 int mfb_load_font __P((void *, void *, int, int, int, void *));
217
218 struct wsdisplay_accessops mfb_accessops = {
219 mfbioctl,
220 mfbmmap,
221 mfb_alloc_screen,
222 mfb_free_screen,
223 mfb_show_screen,
224 mfb_load_font
225 };
226
227 int mfb_cnattach __P((tc_addr_t));
228 int mfbintr __P((void *));
229 void mfbinit __P((struct fb_devconfig *));
230
231 static int set_cursor __P((struct mfb_softc *, struct wsdisplay_cursor *));
232 static int get_cursor __P((struct mfb_softc *, struct wsdisplay_cursor *));
233 static void set_curpos __P((struct mfb_softc *, struct wsdisplay_curpos *));
234 void bt431_set_curpos __P((struct mfb_softc *));
235
236 #define TWIN_LO(x) (twin = (x) & 0x00ff, twin << 8 | twin)
237 #define TWIN_HI(x) (twin = (x) & 0xff00, twin | twin >> 8)
238
239 /* XXX XXX XXX */
240 #define BT431_SELECT(curs, regno) do { \
241 u_int16_t twin; \
242 curs->bt_lo = TWIN_LO(regno); \
243 curs->bt_hi = TWIN_HI(regno); \
244 tc_wmb(); \
245 } while (0)
246
247 #define BT455_SELECT(vdac, index) do { \
248 vdac->bt_reg = index; \
249 vdac->bt_clr = 0; \
250 tc_wmb(); \
251 } while (0)
252 /* XXX XXX XXX */
253
254 /* bit order reverse */
255 const static u_int8_t flip[256] = {
256 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
257 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
258 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
259 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
260 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
261 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
262 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
263 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
264 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
265 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
266 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
267 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
268 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
269 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
270 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
271 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
272 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
273 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
274 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
275 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
276 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
277 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
278 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
279 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
280 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
281 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
282 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
283 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
284 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
285 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
286 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
287 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
288 };
289
290 int
291 mfbmatch(parent, match, aux)
292 struct device *parent;
293 struct cfdata *match;
294 void *aux;
295 {
296 struct tc_attach_args *ta = aux;
297
298 if (strncmp("PMAG-AA ", ta->ta_modname, TC_ROM_LLEN) != 0)
299 return (0);
300
301 return (1);
302 }
303
304 void
305 mfb_getdevconfig(dense_addr, dc)
306 tc_addr_t dense_addr;
307 struct fb_devconfig *dc;
308 {
309 struct raster *rap;
310 struct rcons *rcp;
311 int i;
312
313 dc->dc_vaddr = dense_addr;
314 dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr + MX_FB_OFFSET);
315
316 dc->dc_wid = 1280;
317 dc->dc_ht = 1024;
318 dc->dc_depth = 1;
319 dc->dc_rowbytes = 2048 / 8;
320 dc->dc_videobase = dc->dc_vaddr + MX_FB_OFFSET;
321 dc->dc_blanked = 0;
322
323 /* initialize colormap and cursor resource */
324 mfbinit(dc);
325
326 /* clear the screen */
327 for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
328 *(u_int32_t *)(dc->dc_videobase + i) = 0;
329
330 /* initialize the raster */
331 rap = &dc->dc_raster;
332 rap->width = dc->dc_wid;
333 rap->height = dc->dc_ht;
334 rap->depth = dc->dc_depth;
335 rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
336 rap->pixels = (u_int32_t *)dc->dc_videobase;
337
338 /* initialize the raster console blitter */
339 rcp = &dc->dc_rcons;
340 rcp->rc_sp = rap;
341 rcp->rc_crow = rcp->rc_ccol = -1;
342 rcp->rc_crowp = &rcp->rc_crow;
343 rcp->rc_ccolp = &rcp->rc_ccol;
344 rcons_init(rcp, 34, 80);
345
346 mfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
347 mfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
348 }
349
350 void
351 mfbattach(parent, self, aux)
352 struct device *parent, *self;
353 void *aux;
354 {
355 struct mfb_softc *sc = (struct mfb_softc *)self;
356 struct tc_attach_args *ta = aux;
357 struct wsemuldisplaydev_attach_args waa;
358 caddr_t mfbbase;
359 int console;
360 volatile register int junk;
361
362 console = (ta->ta_addr == mfb_consaddr);
363 if (console) {
364 sc->sc_dc = &mfb_console_dc;
365 sc->nscreens = 1;
366 }
367 else {
368 sc->sc_dc = (struct fb_devconfig *)
369 malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
370 mfb_getdevconfig(ta->ta_addr, sc->sc_dc);
371 }
372 printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
373 sc->sc_dc->dc_depth);
374 sc->magic_x = MX_MAGIC_X;
375 sc->magic_y = MX_MAGIC_Y;
376
377 tc_intr_establish(parent, ta->ta_cookie, TC_IPL_TTY, mfbintr, sc);
378
379 mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
380 *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET) = 0;
381 junk = *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET);
382 *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET) = 1;
383
384 waa.console = console;
385 waa.scrdata = &mfb_screenlist;
386 waa.accessops = &mfb_accessops;
387 waa.accesscookie = sc;
388
389 config_found(self, &waa, wsemuldisplaydevprint);
390 }
391
392 int
393 mfbioctl(v, cmd, data, flag, p)
394 void *v;
395 u_long cmd;
396 caddr_t data;
397 int flag;
398 struct proc *p;
399 {
400 struct mfb_softc *sc = v;
401 struct fb_devconfig *dc = sc->sc_dc;
402 int turnoff;
403
404 switch (cmd) {
405 case WSDISPLAYIO_GTYPE:
406 *(u_int *)data = WSDISPLAY_TYPE_MFB;
407 return (0);
408
409 case WSDISPLAYIO_GINFO:
410 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
411 wsd_fbip->height = sc->sc_dc->dc_ht;
412 wsd_fbip->width = sc->sc_dc->dc_wid;
413 wsd_fbip->depth = sc->sc_dc->dc_depth;
414 wsd_fbip->cmsize = 0;
415 #undef fbt
416 return (0);
417
418 case WSDISPLAYIO_GETCMAP:
419 case WSDISPLAYIO_PUTCMAP:
420 return (ENOTTY);
421
422 case WSDISPLAYIO_SVIDEO:
423 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
424 if ((dc->dc_blanked == 0) ^ turnoff) {
425 dc->dc_blanked = turnoff;
426 /* XXX later XXX */
427 }
428 return (0);
429
430 case WSDISPLAYIO_GVIDEO:
431 *(u_int *)data = dc->dc_blanked ?
432 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
433 return (0);
434
435 case WSDISPLAYIO_GCURPOS:
436 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
437 return (0);
438
439 case WSDISPLAYIO_SCURPOS:
440 set_curpos(sc, (struct wsdisplay_curpos *)data);
441 bt431_set_curpos(sc);
442 return (0);
443
444 case WSDISPLAYIO_GCURMAX:
445 ((struct wsdisplay_curpos *)data)->x =
446 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
447 return (0);
448
449 case WSDISPLAYIO_GCURSOR:
450 return get_cursor(sc, (struct wsdisplay_cursor *)data);
451
452 case WSDISPLAYIO_SCURSOR:
453 return set_cursor(sc, (struct wsdisplay_cursor *)data);
454 }
455 return ENOTTY;
456 }
457
458 int
459 mfbmmap(v, offset, prot)
460 void *v;
461 off_t offset;
462 int prot;
463 {
464 struct mfb_softc *sc = v;
465
466 if (offset > MX_FB_SIZE)
467 return (-1);
468 return machine_btop(sc->sc_dc->dc_paddr + offset);
469 }
470
471 int
472 mfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
473 void *v;
474 const struct wsscreen_descr *type;
475 void **cookiep;
476 int *curxp, *curyp;
477 long *attrp;
478 {
479 struct mfb_softc *sc = v;
480 long defattr;
481
482 if (sc->nscreens > 0)
483 return (ENOMEM);
484
485 *cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
486 *curxp = 0;
487 *curyp = 0;
488 rcons_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
489 *attrp = defattr;
490 sc->nscreens++;
491 return (0);
492 }
493
494 void
495 mfb_free_screen(v, cookie)
496 void *v;
497 void *cookie;
498 {
499 struct mfb_softc *sc = v;
500
501 if (sc->sc_dc == &mfb_console_dc)
502 panic("mfb_free_screen: console");
503
504 sc->nscreens--;
505 }
506
507 void
508 mfb_show_screen(v, cookie)
509 void *v;
510 void *cookie;
511 {
512 }
513
514 int
515 mfb_load_font(v, cookie, first, num, stride, data)
516 void *v;
517 void *cookie;
518 int first, num, stride;
519 void *data;
520 {
521 return (EINVAL);
522 }
523
524 int
525 mfb_cnattach(addr)
526 tc_addr_t addr;
527 {
528 struct fb_devconfig *dcp = &mfb_console_dc;
529 long defattr;
530
531 mfb_getdevconfig(addr, dcp);
532
533 rcons_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
534
535 wsdisplay_cnattach(&mfb_stdscreen, &dcp->dc_rcons,
536 0, 0, defattr);
537 mfb_consaddr = addr;
538 return(0);
539 }
540
541
542 int
543 mfbintr(arg)
544 void *arg;
545 {
546 struct mfb_softc *sc = arg;
547 caddr_t mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
548 struct bt455reg *vdac;
549 struct bt431reg *curs;
550 int v;
551 volatile register int junk;
552
553 junk = *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET);
554 /* *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET) = 1; */
555
556 if (sc->sc_changed == 0)
557 return (1);
558
559 vdac = (void *)(mfbbase + MX_BT455_OFFSET);
560 curs = (void *)(mfbbase + MX_BT431_OFFSET);
561
562 v = sc->sc_changed;
563 sc->sc_changed = 0;
564 if (v & DATA_ENB_CHANGED) {
565 BT431_SELECT(curs, BT431_REG_COMMAND);
566 curs->bt_ctl = (sc->sc_curenb) ? 0x4444 : 0x0404;
567 }
568 if (v & DATA_CURSHAPE_CHANGED) {
569 u_int8_t *ip, *mp, img, msk;
570 int bcnt;
571
572 ip = (u_int8_t *)sc->sc_cursor.cc_image;
573 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
574
575 bcnt = 0;
576 BT431_SELECT(curs, BT431_REG_CRAM_BASE+0);
577 /* 64 pixel scan line is consisted with 16 byte cursor ram */
578 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
579 /* pad right half 32 pixel when smaller than 33 */
580 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
581 curs->bt_ram = 0;
582 tc_wmb();
583 }
584 else {
585 img = *ip++;
586 msk = *mp++;
587 img &= msk; /* cookie off image */
588 curs->bt_ram = (flip[msk] << 8) | flip[img];
589 tc_wmb();
590 }
591 bcnt += 2;
592 }
593 /* pad unoccupied scan lines */
594 while (bcnt < CURSOR_MAX_SIZE * 16) {
595 curs->bt_ram = 0;
596 tc_wmb();
597 bcnt += 2;
598 }
599 }
600 return (1);
601 }
602
603 void
604 mfbinit(dc)
605 struct fb_devconfig *dc;
606 {
607 caddr_t mfbbase = (caddr_t)dc->dc_vaddr;
608 struct bt431reg *curs = (void *)(mfbbase + MX_BT431_OFFSET);
609 struct bt455reg *vdac = (void *)(mfbbase + MX_BT455_OFFSET);
610 int i;
611
612 BT431_SELECT(curs, BT431_REG_COMMAND);
613 curs->bt_ctl = 0x0404; tc_wmb();
614 curs->bt_ctl = 0; tc_wmb();
615 curs->bt_ctl = 0; tc_wmb();
616 curs->bt_ctl = 0; tc_wmb();
617 curs->bt_ctl = 0; tc_wmb();
618 curs->bt_ctl = 0; tc_wmb();
619 curs->bt_ctl = 0; tc_wmb();
620 curs->bt_ctl = 0; tc_wmb();
621 curs->bt_ctl = 0; tc_wmb();
622 curs->bt_ctl = 0; tc_wmb();
623 curs->bt_ctl = 0; tc_wmb();
624 curs->bt_ctl = 0; tc_wmb();
625 curs->bt_ctl = 0; tc_wmb();
626
627 BT455_SELECT(vdac, 0);
628 for (i = 0; i < 16; i++) {
629 vdac->bt_cmap = 0; tc_wmb();
630 vdac->bt_cmap = 0; tc_wmb();
631 vdac->bt_cmap = 0; tc_wmb();
632 }
633
634 BT455_SELECT(vdac, 1);
635 vdac->bt_cmap = 0; tc_wmb();
636 vdac->bt_cmap = 0xff; tc_wmb();
637 vdac->bt_cmap = 0; tc_wmb();
638
639 BT455_SELECT(vdac, 8);
640 vdac->bt_cmap = 0; tc_wmb();
641 vdac->bt_cmap = 0xff; tc_wmb();
642 vdac->bt_cmap = 0; tc_wmb();
643
644 vdac->bt_ovly = 0; tc_wmb();
645 vdac->bt_ovly = 0xff; tc_wmb();
646 vdac->bt_ovly = 0; tc_wmb();
647 }
648
649 static int
650 set_cursor(sc, p)
651 struct mfb_softc *sc;
652 struct wsdisplay_cursor *p;
653 {
654 #define cc (&sc->sc_cursor)
655 int v, count;
656
657 v = p->which;
658 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
659 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
660 return (EINVAL);
661 count = ((p->size.x < 33) ? 4 : 8) * p->size.y;
662 if (!useracc(p->image, count, B_READ) ||
663 !useracc(p->mask, count, B_READ))
664 return (EFAULT);
665 }
666 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
667 if (v & WSDISPLAY_CURSOR_DOCUR)
668 cc->cc_hot = p->hot;
669 if (v & WSDISPLAY_CURSOR_DOPOS)
670 set_curpos(sc, &p->pos);
671 bt431_set_curpos(sc);
672 }
673
674 sc->sc_changed = 0;
675 if (v & WSDISPLAY_CURSOR_DOCUR) {
676 sc->sc_curenb = p->enable;
677 sc->sc_changed |= DATA_ENB_CHANGED;
678 }
679 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
680 cc->cc_size = p->size;
681 memset(cc->cc_image, 0, sizeof cc->cc_image);
682 copyin(p->image, cc->cc_image, count);
683 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, count);
684 sc->sc_changed |= DATA_CURSHAPE_CHANGED;
685 }
686
687 return (0);
688 #undef cc
689 }
690
691 static int
692 get_cursor(sc, p)
693 struct mfb_softc *sc;
694 struct wsdisplay_cursor *p;
695 {
696 return (ENOTTY); /* XXX */
697 }
698
699 static void
700 set_curpos(sc, curpos)
701 struct mfb_softc *sc;
702 struct wsdisplay_curpos *curpos;
703 {
704 struct fb_devconfig *dc = sc->sc_dc;
705 int x = curpos->x, y = curpos->y;
706
707 if (y < 0)
708 y = 0;
709 else if (y > dc->dc_ht)
710 y = dc->dc_ht;
711 if (x < 0)
712 x = 0;
713 else if (x > dc->dc_wid)
714 x = dc->dc_wid;
715 sc->sc_cursor.cc_pos.x = x;
716 sc->sc_cursor.cc_pos.y = y;
717 }
718
719 void
720 bt431_set_curpos(sc)
721 struct mfb_softc *sc;
722 {
723 caddr_t mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
724 struct bt431reg *curs = (void *)(mfbbase + MX_BT431_OFFSET);
725 u_int16_t twin;
726 int x, y, s;
727
728 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
729 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
730 x += sc->magic_x; y += sc->magic_y; /* magic offset of MX coordinate */
731
732 s = spltty();
733
734 BT431_SELECT(curs, BT431_REG_CURSOR_X_LOW);
735 curs->bt_ctl = TWIN_LO(x); tc_wmb();
736 curs->bt_ctl = TWIN_HI(x); tc_wmb();
737 curs->bt_ctl = TWIN_LO(y); tc_wmb();
738 curs->bt_ctl = TWIN_HI(y); tc_wmb();
739
740 splx(s);
741 }
742