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