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