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