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