mfb.c revision 1.12 1 /* $NetBSD: mfb.c,v 1.12 1999/06/23 01:58:22 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.12 1999/06/23 01:58:22 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 hwcursor64 {
136 struct wsdisplay_curpos cc_pos;
137 struct wsdisplay_curpos cc_hot;
138 struct wsdisplay_curpos cc_size;
139 struct wsdisplay_curpos cc_magic;
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 hwcursor64 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 };
158
159 #define MX_MAGIC_X 360
160 #define MX_MAGIC_Y 36
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 = 8;
314 dc->dc_rowbytes = 2048;
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
370 sc->sc_cursor.cc_magic.x = MX_MAGIC_X;
371 sc->sc_cursor.cc_magic.y = MX_MAGIC_Y;
372
373 tc_intr_establish(parent, ta->ta_cookie, TC_IPL_TTY, mfbintr, sc);
374
375 mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
376 *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET) = 0;
377 junk = *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET);
378 *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET) = 1;
379
380 waa.console = console;
381 waa.scrdata = &mfb_screenlist;
382 waa.accessops = &mfb_accessops;
383 waa.accesscookie = sc;
384
385 config_found(self, &waa, wsemuldisplaydevprint);
386 }
387
388 int
389 mfbioctl(v, cmd, data, flag, p)
390 void *v;
391 u_long cmd;
392 caddr_t data;
393 int flag;
394 struct proc *p;
395 {
396 struct mfb_softc *sc = v;
397 struct fb_devconfig *dc = sc->sc_dc;
398 int turnoff;
399
400 switch (cmd) {
401 case WSDISPLAYIO_GTYPE:
402 *(u_int *)data = WSDISPLAY_TYPE_MFB;
403 return (0);
404
405 case WSDISPLAYIO_GINFO:
406 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
407 wsd_fbip->height = sc->sc_dc->dc_ht;
408 wsd_fbip->width = sc->sc_dc->dc_wid;
409 wsd_fbip->depth = sc->sc_dc->dc_depth;
410 wsd_fbip->cmsize = 0;
411 #undef fbt
412 return (0);
413
414 case WSDISPLAYIO_GETCMAP:
415 case WSDISPLAYIO_PUTCMAP:
416 return (ENOTTY);
417
418 case WSDISPLAYIO_SVIDEO:
419 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
420 if ((dc->dc_blanked == 0) ^ turnoff) {
421 dc->dc_blanked = turnoff;
422 /* XXX later XXX */
423 }
424 return (0);
425
426 case WSDISPLAYIO_GVIDEO:
427 *(u_int *)data = dc->dc_blanked ?
428 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
429 return (0);
430
431 case WSDISPLAYIO_GCURPOS:
432 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
433 return (0);
434
435 case WSDISPLAYIO_SCURPOS:
436 set_curpos(sc, (struct wsdisplay_curpos *)data);
437 bt431_set_curpos(sc);
438 return (0);
439
440 case WSDISPLAYIO_GCURMAX:
441 ((struct wsdisplay_curpos *)data)->x =
442 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
443 return (0);
444
445 case WSDISPLAYIO_GCURSOR:
446 return get_cursor(sc, (struct wsdisplay_cursor *)data);
447
448 case WSDISPLAYIO_SCURSOR:
449 return set_cursor(sc, (struct wsdisplay_cursor *)data);
450 }
451 return (ENOTTY);
452 }
453
454 int
455 mfbmmap(v, offset, prot)
456 void *v;
457 off_t offset;
458 int prot;
459 {
460 struct mfb_softc *sc = v;
461
462 if (offset >= MX_FB_SIZE || offset < 0)
463 return (-1);
464 return machine_btop(sc->sc_dc->dc_paddr + offset);
465 }
466
467 int
468 mfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
469 void *v;
470 const struct wsscreen_descr *type;
471 void **cookiep;
472 int *curxp, *curyp;
473 long *attrp;
474 {
475 struct mfb_softc *sc = v;
476 long defattr;
477
478 if (sc->nscreens > 0)
479 return (ENOMEM);
480
481 *cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
482 *curxp = 0;
483 *curyp = 0;
484 rcons_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
485 *attrp = defattr;
486 sc->nscreens++;
487 return (0);
488 }
489
490 void
491 mfb_free_screen(v, cookie)
492 void *v;
493 void *cookie;
494 {
495 struct mfb_softc *sc = v;
496
497 if (sc->sc_dc == &mfb_console_dc)
498 panic("mfb_free_screen: console");
499
500 sc->nscreens--;
501 }
502
503 void
504 mfb_show_screen(v, cookie)
505 void *v;
506 void *cookie;
507 {
508 }
509
510 int
511 mfb_cnattach(addr)
512 tc_addr_t addr;
513 {
514 struct fb_devconfig *dcp = &mfb_console_dc;
515 long defattr;
516
517 mfb_getdevconfig(addr, dcp);
518
519 rcons_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
520
521 wsdisplay_cnattach(&mfb_stdscreen, &dcp->dc_rcons,
522 0, 0, defattr);
523 mfb_consaddr = addr;
524 return (0);
525 }
526
527
528 int
529 mfbintr(arg)
530 void *arg;
531 {
532 struct mfb_softc *sc = arg;
533 caddr_t mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
534 struct bt455reg *vdac;
535 struct bt431reg *curs;
536 int v;
537 volatile register int junk;
538
539 junk = *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET);
540 /* *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET) = 1; */
541
542 if (sc->sc_changed == 0)
543 return (1);
544
545 vdac = (void *)(mfbbase + MX_BT455_OFFSET);
546 curs = (void *)(mfbbase + MX_BT431_OFFSET);
547
548 v = sc->sc_changed;
549 sc->sc_changed = 0;
550 if (v & DATA_ENB_CHANGED) {
551 BT431_SELECT(curs, BT431_REG_COMMAND);
552 curs->bt_ctl = (sc->sc_curenb) ? 0x4444 : 0x0404;
553 }
554 if (v & DATA_CURSHAPE_CHANGED) {
555 u_int8_t *ip, *mp, img, msk;
556 int bcnt;
557
558 ip = (u_int8_t *)sc->sc_cursor.cc_image;
559 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
560
561 bcnt = 0;
562 BT431_SELECT(curs, BT431_REG_CRAM_BASE+0);
563 /* 64 pixel scan line is consisted with 16 byte cursor ram */
564 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
565 /* pad right half 32 pixel when smaller than 33 */
566 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
567 curs->bt_ram = 0;
568 tc_wmb();
569 }
570 else {
571 img = *ip++;
572 msk = *mp++;
573 img &= msk; /* cookie off image */
574 curs->bt_ram = (flip[msk] << 8) | flip[img];
575 tc_wmb();
576 }
577 bcnt += 2;
578 }
579 /* pad unoccupied scan lines */
580 while (bcnt < CURSOR_MAX_SIZE * 16) {
581 curs->bt_ram = 0;
582 tc_wmb();
583 bcnt += 2;
584 }
585 }
586 return (1);
587 }
588
589 void
590 mfbinit(dc)
591 struct fb_devconfig *dc;
592 {
593 caddr_t mfbbase = (caddr_t)dc->dc_vaddr;
594 struct bt431reg *curs = (void *)(mfbbase + MX_BT431_OFFSET);
595 struct bt455reg *vdac = (void *)(mfbbase + MX_BT455_OFFSET);
596 int i;
597
598 BT431_SELECT(curs, BT431_REG_COMMAND);
599 curs->bt_ctl = 0x0404; 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 curs->bt_ctl = 0; tc_wmb();
612
613 BT455_SELECT(vdac, 0);
614 for (i = 0; i < 16; i++) {
615 vdac->bt_cmap = 0; tc_wmb();
616 vdac->bt_cmap = 0; tc_wmb();
617 vdac->bt_cmap = 0; tc_wmb();
618 }
619
620 BT455_SELECT(vdac, 1);
621 vdac->bt_cmap = 0; tc_wmb();
622 vdac->bt_cmap = 0xff; tc_wmb();
623 vdac->bt_cmap = 0; tc_wmb();
624
625 BT455_SELECT(vdac, 8);
626 vdac->bt_cmap = 0; tc_wmb();
627 vdac->bt_cmap = 0xff; tc_wmb();
628 vdac->bt_cmap = 0; tc_wmb();
629
630 vdac->bt_ovly = 0; tc_wmb();
631 vdac->bt_ovly = 0xff; tc_wmb();
632 vdac->bt_ovly = 0; tc_wmb();
633 }
634
635 static int
636 set_cursor(sc, p)
637 struct mfb_softc *sc;
638 struct wsdisplay_cursor *p;
639 {
640 #define cc (&sc->sc_cursor)
641 int v, count;
642
643 v = p->which;
644 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
645 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
646 return (EINVAL);
647 count = ((p->size.x < 33) ? 4 : 8) * p->size.y;
648 if (!uvm_useracc(p->image, count, B_READ) ||
649 !uvm_useracc(p->mask, count, B_READ))
650 return (EFAULT);
651 }
652 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
653 if (v & WSDISPLAY_CURSOR_DOCUR)
654 cc->cc_hot = p->hot;
655 if (v & WSDISPLAY_CURSOR_DOPOS)
656 set_curpos(sc, &p->pos);
657 bt431_set_curpos(sc);
658 }
659
660 sc->sc_changed = 0;
661 if (v & WSDISPLAY_CURSOR_DOCUR) {
662 sc->sc_curenb = p->enable;
663 sc->sc_changed |= DATA_ENB_CHANGED;
664 }
665 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
666 cc->cc_size = p->size;
667 memset(cc->cc_image, 0, sizeof cc->cc_image);
668 copyin(p->image, cc->cc_image, count);
669 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, count);
670 sc->sc_changed |= DATA_CURSHAPE_CHANGED;
671 }
672
673 return (0);
674 #undef cc
675 }
676
677 static int
678 get_cursor(sc, p)
679 struct mfb_softc *sc;
680 struct wsdisplay_cursor *p;
681 {
682 return (ENOTTY); /* XXX */
683 }
684
685 static void
686 set_curpos(sc, curpos)
687 struct mfb_softc *sc;
688 struct wsdisplay_curpos *curpos;
689 {
690 struct fb_devconfig *dc = sc->sc_dc;
691 int x = curpos->x, y = curpos->y;
692
693 if (y < 0)
694 y = 0;
695 else if (y > dc->dc_ht)
696 y = dc->dc_ht;
697 if (x < 0)
698 x = 0;
699 else if (x > dc->dc_wid)
700 x = dc->dc_wid;
701 sc->sc_cursor.cc_pos.x = x;
702 sc->sc_cursor.cc_pos.y = y;
703 }
704
705 void
706 bt431_set_curpos(sc)
707 struct mfb_softc *sc;
708 {
709 caddr_t mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
710 struct bt431reg *curs = (void *)(mfbbase + MX_BT431_OFFSET);
711 u_int16_t twin;
712 int x, y, s;
713
714 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
715 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
716
717 x += sc->sc_cursor.cc_magic.x;
718 y += sc->sc_cursor.cc_magic.y;
719
720 s = spltty();
721
722 BT431_SELECT(curs, BT431_REG_CURSOR_X_LOW);
723 curs->bt_ctl = TWIN_LO(x); tc_wmb();
724 curs->bt_ctl = TWIN_HI(x); tc_wmb();
725 curs->bt_ctl = TWIN_LO(y); tc_wmb();
726 curs->bt_ctl = TWIN_HI(y); tc_wmb();
727
728 splx(s);
729 }
730