mfb.c revision 1.7 1 /* $NetBSD: mfb.c,v 1.7 1999/01/11 21:35:55 drochner 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.7 1999/01/11 21:35:55 drochner 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 pair 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
217 struct wsdisplay_accessops mfb_accessops = {
218 mfbioctl,
219 mfbmmap,
220 mfb_alloc_screen,
221 mfb_free_screen,
222 mfb_show_screen,
223 0 /* load_font */
224 };
225
226 int mfb_cnattach __P((tc_addr_t));
227 int mfbintr __P((void *));
228 void mfbinit __P((struct fb_devconfig *));
229
230 static int set_cursor __P((struct mfb_softc *, struct wsdisplay_cursor *));
231 static int get_cursor __P((struct mfb_softc *, struct wsdisplay_cursor *));
232 static void set_curpos __P((struct mfb_softc *, struct wsdisplay_curpos *));
233 void bt431_set_curpos __P((struct mfb_softc *));
234
235 #define TWIN_LO(x) (twin = (x) & 0x00ff, twin << 8 | twin)
236 #define TWIN_HI(x) (twin = (x) & 0xff00, twin | twin >> 8)
237
238 /* XXX XXX XXX */
239 #define BT431_SELECT(curs, regno) do { \
240 u_int16_t twin; \
241 curs->bt_lo = TWIN_LO(regno); \
242 curs->bt_hi = TWIN_HI(regno); \
243 tc_wmb(); \
244 } while (0)
245
246 #define BT455_SELECT(vdac, index) do { \
247 vdac->bt_reg = index; \
248 vdac->bt_clr = 0; \
249 tc_wmb(); \
250 } while (0)
251 /* XXX XXX XXX */
252
253 /* bit order reverse */
254 const static u_int8_t flip[256] = {
255 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
256 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
257 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
258 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
259 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
260 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
261 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
262 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
263 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
264 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
265 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
266 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
267 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
268 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
269 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
270 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
271 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
272 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
273 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
274 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
275 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
276 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
277 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
278 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
279 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
280 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
281 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
282 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
283 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
284 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
285 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
286 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
287 };
288
289 int
290 mfbmatch(parent, match, aux)
291 struct device *parent;
292 struct cfdata *match;
293 void *aux;
294 {
295 struct tc_attach_args *ta = aux;
296
297 if (strncmp("PMAG-AA ", ta->ta_modname, TC_ROM_LLEN) != 0)
298 return (0);
299
300 return (1);
301 }
302
303 void
304 mfb_getdevconfig(dense_addr, dc)
305 tc_addr_t dense_addr;
306 struct fb_devconfig *dc;
307 {
308 struct raster *rap;
309 struct rcons *rcp;
310 int i;
311
312 dc->dc_vaddr = dense_addr;
313 dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr + MX_FB_OFFSET);
314
315 dc->dc_wid = 1280;
316 dc->dc_ht = 1024;
317 dc->dc_depth = 1;
318 dc->dc_rowbytes = 2048 / 8;
319 dc->dc_videobase = dc->dc_vaddr + MX_FB_OFFSET;
320 dc->dc_blanked = 0;
321
322 /* initialize colormap and cursor resource */
323 mfbinit(dc);
324
325 /* clear the screen */
326 for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
327 *(u_int32_t *)(dc->dc_videobase + i) = 0;
328
329 /* initialize the raster */
330 rap = &dc->dc_raster;
331 rap->width = dc->dc_wid;
332 rap->height = dc->dc_ht;
333 rap->depth = dc->dc_depth;
334 rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
335 rap->pixels = (u_int32_t *)dc->dc_videobase;
336
337 /* initialize the raster console blitter */
338 rcp = &dc->dc_rcons;
339 rcp->rc_sp = rap;
340 rcp->rc_crow = rcp->rc_ccol = -1;
341 rcp->rc_crowp = &rcp->rc_crow;
342 rcp->rc_ccolp = &rcp->rc_ccol;
343 rcons_init(rcp, 34, 80);
344
345 mfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
346 mfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
347 }
348
349 void
350 mfbattach(parent, self, aux)
351 struct device *parent, *self;
352 void *aux;
353 {
354 struct mfb_softc *sc = (struct mfb_softc *)self;
355 struct tc_attach_args *ta = aux;
356 struct wsemuldisplaydev_attach_args waa;
357 caddr_t mfbbase;
358 int console;
359 volatile register int junk;
360
361 console = (ta->ta_addr == mfb_consaddr);
362 if (console) {
363 sc->sc_dc = &mfb_console_dc;
364 sc->nscreens = 1;
365 }
366 else {
367 sc->sc_dc = (struct fb_devconfig *)
368 malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
369 mfb_getdevconfig(ta->ta_addr, sc->sc_dc);
370 }
371 printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
372 sc->sc_dc->dc_depth);
373 sc->magic_x = MX_MAGIC_X;
374 sc->magic_y = MX_MAGIC_Y;
375
376 tc_intr_establish(parent, ta->ta_cookie, TC_IPL_TTY, mfbintr, sc);
377
378 mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
379 *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET) = 0;
380 junk = *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET);
381 *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET) = 1;
382
383 waa.console = console;
384 waa.scrdata = &mfb_screenlist;
385 waa.accessops = &mfb_accessops;
386 waa.accesscookie = sc;
387
388 config_found(self, &waa, wsemuldisplaydevprint);
389 }
390
391 int
392 mfbioctl(v, cmd, data, flag, p)
393 void *v;
394 u_long cmd;
395 caddr_t data;
396 int flag;
397 struct proc *p;
398 {
399 struct mfb_softc *sc = v;
400 struct fb_devconfig *dc = sc->sc_dc;
401 int turnoff;
402
403 switch (cmd) {
404 case WSDISPLAYIO_GTYPE:
405 *(u_int *)data = WSDISPLAY_TYPE_MFB;
406 return (0);
407
408 case WSDISPLAYIO_GINFO:
409 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
410 wsd_fbip->height = sc->sc_dc->dc_ht;
411 wsd_fbip->width = sc->sc_dc->dc_wid;
412 wsd_fbip->depth = sc->sc_dc->dc_depth;
413 wsd_fbip->cmsize = 0;
414 #undef fbt
415 return (0);
416
417 case WSDISPLAYIO_GETCMAP:
418 case WSDISPLAYIO_PUTCMAP:
419 return (ENOTTY);
420
421 case WSDISPLAYIO_SVIDEO:
422 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
423 if ((dc->dc_blanked == 0) ^ turnoff) {
424 dc->dc_blanked = turnoff;
425 /* XXX later XXX */
426 }
427 return (0);
428
429 case WSDISPLAYIO_GVIDEO:
430 *(u_int *)data = dc->dc_blanked ?
431 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
432 return (0);
433
434 case WSDISPLAYIO_GCURPOS:
435 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
436 return (0);
437
438 case WSDISPLAYIO_SCURPOS:
439 set_curpos(sc, (struct wsdisplay_curpos *)data);
440 bt431_set_curpos(sc);
441 return (0);
442
443 case WSDISPLAYIO_GCURMAX:
444 ((struct wsdisplay_curpos *)data)->x =
445 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
446 return (0);
447
448 case WSDISPLAYIO_GCURSOR:
449 return get_cursor(sc, (struct wsdisplay_cursor *)data);
450
451 case WSDISPLAYIO_SCURSOR:
452 return set_cursor(sc, (struct wsdisplay_cursor *)data);
453 }
454 return (ENOTTY);
455 }
456
457 int
458 mfbmmap(v, offset, prot)
459 void *v;
460 off_t offset;
461 int prot;
462 {
463 struct mfb_softc *sc = v;
464
465 if (offset >= MX_FB_SIZE || offset < 0)
466 return (-1);
467 return machine_btop(sc->sc_dc->dc_paddr + offset);
468 }
469
470 int
471 mfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
472 void *v;
473 const struct wsscreen_descr *type;
474 void **cookiep;
475 int *curxp, *curyp;
476 long *attrp;
477 {
478 struct mfb_softc *sc = v;
479 long defattr;
480
481 if (sc->nscreens > 0)
482 return (ENOMEM);
483
484 *cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
485 *curxp = 0;
486 *curyp = 0;
487 rcons_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
488 *attrp = defattr;
489 sc->nscreens++;
490 return (0);
491 }
492
493 void
494 mfb_free_screen(v, cookie)
495 void *v;
496 void *cookie;
497 {
498 struct mfb_softc *sc = v;
499
500 if (sc->sc_dc == &mfb_console_dc)
501 panic("mfb_free_screen: console");
502
503 sc->nscreens--;
504 }
505
506 void
507 mfb_show_screen(v, cookie)
508 void *v;
509 void *cookie;
510 {
511 }
512
513 int
514 mfb_cnattach(addr)
515 tc_addr_t addr;
516 {
517 struct fb_devconfig *dcp = &mfb_console_dc;
518 long defattr;
519
520 mfb_getdevconfig(addr, dcp);
521
522 rcons_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
523
524 wsdisplay_cnattach(&mfb_stdscreen, &dcp->dc_rcons,
525 0, 0, defattr);
526 mfb_consaddr = addr;
527 return (0);
528 }
529
530
531 int
532 mfbintr(arg)
533 void *arg;
534 {
535 struct mfb_softc *sc = arg;
536 caddr_t mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
537 struct bt455reg *vdac;
538 struct bt431reg *curs;
539 int v;
540 volatile register int junk;
541
542 junk = *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET);
543 /* *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET) = 1; */
544
545 if (sc->sc_changed == 0)
546 return (1);
547
548 vdac = (void *)(mfbbase + MX_BT455_OFFSET);
549 curs = (void *)(mfbbase + MX_BT431_OFFSET);
550
551 v = sc->sc_changed;
552 sc->sc_changed = 0;
553 if (v & DATA_ENB_CHANGED) {
554 BT431_SELECT(curs, BT431_REG_COMMAND);
555 curs->bt_ctl = (sc->sc_curenb) ? 0x4444 : 0x0404;
556 }
557 if (v & DATA_CURSHAPE_CHANGED) {
558 u_int8_t *ip, *mp, img, msk;
559 int bcnt;
560
561 ip = (u_int8_t *)sc->sc_cursor.cc_image;
562 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
563
564 bcnt = 0;
565 BT431_SELECT(curs, BT431_REG_CRAM_BASE+0);
566 /* 64 pixel scan line is consisted with 16 byte cursor ram */
567 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
568 /* pad right half 32 pixel when smaller than 33 */
569 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
570 curs->bt_ram = 0;
571 tc_wmb();
572 }
573 else {
574 img = *ip++;
575 msk = *mp++;
576 img &= msk; /* cookie off image */
577 curs->bt_ram = (flip[msk] << 8) | flip[img];
578 tc_wmb();
579 }
580 bcnt += 2;
581 }
582 /* pad unoccupied scan lines */
583 while (bcnt < CURSOR_MAX_SIZE * 16) {
584 curs->bt_ram = 0;
585 tc_wmb();
586 bcnt += 2;
587 }
588 }
589 return (1);
590 }
591
592 void
593 mfbinit(dc)
594 struct fb_devconfig *dc;
595 {
596 caddr_t mfbbase = (caddr_t)dc->dc_vaddr;
597 struct bt431reg *curs = (void *)(mfbbase + MX_BT431_OFFSET);
598 struct bt455reg *vdac = (void *)(mfbbase + MX_BT455_OFFSET);
599 int i;
600
601 BT431_SELECT(curs, BT431_REG_COMMAND);
602 curs->bt_ctl = 0x0404; tc_wmb();
603 curs->bt_ctl = 0; tc_wmb();
604 curs->bt_ctl = 0; tc_wmb();
605 curs->bt_ctl = 0; tc_wmb();
606 curs->bt_ctl = 0; tc_wmb();
607 curs->bt_ctl = 0; tc_wmb();
608 curs->bt_ctl = 0; tc_wmb();
609 curs->bt_ctl = 0; tc_wmb();
610 curs->bt_ctl = 0; tc_wmb();
611 curs->bt_ctl = 0; tc_wmb();
612 curs->bt_ctl = 0; tc_wmb();
613 curs->bt_ctl = 0; tc_wmb();
614 curs->bt_ctl = 0; tc_wmb();
615
616 BT455_SELECT(vdac, 0);
617 for (i = 0; i < 16; i++) {
618 vdac->bt_cmap = 0; tc_wmb();
619 vdac->bt_cmap = 0; tc_wmb();
620 vdac->bt_cmap = 0; tc_wmb();
621 }
622
623 BT455_SELECT(vdac, 1);
624 vdac->bt_cmap = 0; tc_wmb();
625 vdac->bt_cmap = 0xff; tc_wmb();
626 vdac->bt_cmap = 0; tc_wmb();
627
628 BT455_SELECT(vdac, 8);
629 vdac->bt_cmap = 0; tc_wmb();
630 vdac->bt_cmap = 0xff; tc_wmb();
631 vdac->bt_cmap = 0; tc_wmb();
632
633 vdac->bt_ovly = 0; tc_wmb();
634 vdac->bt_ovly = 0xff; tc_wmb();
635 vdac->bt_ovly = 0; tc_wmb();
636 }
637
638 static int
639 set_cursor(sc, p)
640 struct mfb_softc *sc;
641 struct wsdisplay_cursor *p;
642 {
643 #define cc (&sc->sc_cursor)
644 int v, count;
645
646 v = p->which;
647 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
648 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
649 return (EINVAL);
650 count = ((p->size.x < 33) ? 4 : 8) * p->size.y;
651 if (!useracc(p->image, count, B_READ) ||
652 !useracc(p->mask, count, B_READ))
653 return (EFAULT);
654 }
655 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
656 if (v & WSDISPLAY_CURSOR_DOCUR)
657 cc->cc_hot = p->hot;
658 if (v & WSDISPLAY_CURSOR_DOPOS)
659 set_curpos(sc, &p->pos);
660 bt431_set_curpos(sc);
661 }
662
663 sc->sc_changed = 0;
664 if (v & WSDISPLAY_CURSOR_DOCUR) {
665 sc->sc_curenb = p->enable;
666 sc->sc_changed |= DATA_ENB_CHANGED;
667 }
668 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
669 cc->cc_size = p->size;
670 memset(cc->cc_image, 0, sizeof cc->cc_image);
671 copyin(p->image, cc->cc_image, count);
672 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, count);
673 sc->sc_changed |= DATA_CURSHAPE_CHANGED;
674 }
675
676 return (0);
677 #undef cc
678 }
679
680 static int
681 get_cursor(sc, p)
682 struct mfb_softc *sc;
683 struct wsdisplay_cursor *p;
684 {
685 return (ENOTTY); /* XXX */
686 }
687
688 static void
689 set_curpos(sc, curpos)
690 struct mfb_softc *sc;
691 struct wsdisplay_curpos *curpos;
692 {
693 struct fb_devconfig *dc = sc->sc_dc;
694 int x = curpos->x, y = curpos->y;
695
696 if (y < 0)
697 y = 0;
698 else if (y > dc->dc_ht)
699 y = dc->dc_ht;
700 if (x < 0)
701 x = 0;
702 else if (x > dc->dc_wid)
703 x = dc->dc_wid;
704 sc->sc_cursor.cc_pos.x = x;
705 sc->sc_cursor.cc_pos.y = y;
706 }
707
708 void
709 bt431_set_curpos(sc)
710 struct mfb_softc *sc;
711 {
712 caddr_t mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
713 struct bt431reg *curs = (void *)(mfbbase + MX_BT431_OFFSET);
714 u_int16_t twin;
715 int x, y, s;
716
717 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
718 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
719 x += sc->magic_x; y += sc->magic_y; /* magic offset of MX coordinate */
720
721 s = spltty();
722
723 BT431_SELECT(curs, BT431_REG_CURSOR_X_LOW);
724 curs->bt_ctl = TWIN_LO(x); tc_wmb();
725 curs->bt_ctl = TWIN_HI(x); tc_wmb();
726 curs->bt_ctl = TWIN_LO(y); tc_wmb();
727 curs->bt_ctl = TWIN_HI(y); tc_wmb();
728
729 splx(s);
730 }
731