mfb.c revision 1.15 1 /* $NetBSD: mfb.c,v 1.15 1999/06/25 03:33:20 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.15 1999/06/25 03:33:20 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 /* Bt431 hardware registers */
66 #define bt_reg 0
67 #define bt_cmap 1
68 #define bt_clr 2
69 #define bt_ovly 3
70
71 /* Bt455 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 0x40000
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;
493 void *curs;
494 int v;
495 volatile register int junk;
496
497 junk = *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET);
498 /* *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET) = 1; */
499
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
506 v = sc->sc_changed;
507 sc->sc_changed = 0;
508 if (v & DATA_ENB_CHANGED) {
509 SELECT431(curs, BT431_REG_COMMAND);
510 HALF(curs, bt_ctl) = (sc->sc_curenb) ? 0x4444 : 0x0404;
511 }
512 if (v & DATA_CURCMAP_CHANGED) {
513 u_int8_t *cp = sc->sc_cursor.cc_color;
514
515 SELECT455(vdac, 8);
516 BYTE(vdac, bt_cmap) = 0; tc_wmb();
517 BYTE(vdac, bt_cmap) = cp[1]; tc_wmb();
518 BYTE(vdac, bt_cmap) = 0; tc_wmb();
519
520 BYTE(vdac, bt_cmap) = 0; tc_wmb();
521 BYTE(vdac, bt_cmap) = cp[1]; tc_wmb();
522 BYTE(vdac, bt_cmap) = 0; tc_wmb();
523
524 BYTE(vdac, bt_ovly) = 0; tc_wmb();
525 BYTE(vdac, bt_ovly) = cp[0]; tc_wmb();
526 BYTE(vdac, bt_ovly) = 0; tc_wmb();
527 }
528 if (v & DATA_CURSHAPE_CHANGED) {
529 u_int8_t *ip, *mp, img, msk;
530 int bcnt;
531
532 ip = (u_int8_t *)sc->sc_cursor.cc_image;
533 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
534 bcnt = 0;
535 SELECT431(curs, BT431_REG_CRAM_BASE);
536
537 /* 64 pixel scan line is consisted with 16 byte cursor ram */
538 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
539 /* pad right half 32 pixel when smaller than 33 */
540 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
541 HALF(curs, bt_ram) = 0;
542 tc_wmb();
543 }
544 else {
545 img = *ip++;
546 msk = *mp++;
547 img &= msk; /* cookie off image */
548 HALF(curs, bt_ram)
549 = (flip[msk] << 8) | flip[img];
550 tc_wmb();
551 }
552 bcnt += 2;
553 }
554 /* pad unoccupied scan lines */
555 while (bcnt < CURSOR_MAX_SIZE * 16) {
556 HALF(curs, bt_ram) = 0;
557 tc_wmb();
558 bcnt += 2;
559 }
560 }
561 return (1);
562 }
563
564 void
565 mfbinit(dc)
566 struct fb_devconfig *dc;
567 {
568 caddr_t mfbbase = (caddr_t)dc->dc_vaddr;
569 void *curs = (void *)(mfbbase + MX_BT431_OFFSET);
570 void *vdac = (void *)(mfbbase + MX_BT455_OFFSET);
571 int i;
572
573 SELECT431(curs, BT431_REG_COMMAND);
574 HALF(curs, bt_ctl) = 0x0404; tc_wmb();
575 HALF(curs, bt_ctl) = 0; /* XLO */ tc_wmb();
576 HALF(curs, bt_ctl) = 0; /* XHI */ tc_wmb();
577 HALF(curs, bt_ctl) = 0; /* YLO */ tc_wmb();
578 HALF(curs, bt_ctl) = 0; /* YHI */ tc_wmb();
579 HALF(curs, bt_ctl) = 0; /* XWLO */ tc_wmb();
580 HALF(curs, bt_ctl) = 0; /* XWHI */ tc_wmb();
581 HALF(curs, bt_ctl) = 0; /* WYLO */ tc_wmb();
582 HALF(curs, bt_ctl) = 0; /* WYLO */ tc_wmb();
583 HALF(curs, bt_ctl) = 0; /* WWLO */ tc_wmb();
584 HALF(curs, bt_ctl) = 0; /* WWHI */ tc_wmb();
585 HALF(curs, bt_ctl) = 0; /* WHLO */ tc_wmb();
586 HALF(curs, bt_ctl) = 0; /* WHHI */ tc_wmb();
587
588 /* 0: black, 1: white, 8,9: cursor mask, ovly: cursor image */
589 SELECT455(vdac, 0);
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) = 0; tc_wmb();
594 BYTE(vdac, bt_cmap) = 0xff; tc_wmb();
595 BYTE(vdac, bt_cmap) = 0; tc_wmb();
596 for (i = 2; i < 16; i++) {
597 BYTE(vdac, bt_cmap) = 0; tc_wmb();
598 BYTE(vdac, bt_cmap) = 0; tc_wmb();
599 BYTE(vdac, bt_cmap) = 0; tc_wmb();
600 }
601 BYTE(vdac, bt_ovly) = 0; tc_wmb();
602 BYTE(vdac, bt_ovly) = 0xff; tc_wmb();
603 BYTE(vdac, bt_ovly) = 0; tc_wmb();
604
605 SELECT431(curs, BT431_REG_CRAM_BASE);
606 for (i = 0; i < 512; i++) {
607 HALF(curs, bt_ram) = 0; tc_wmb();
608 }
609 }
610
611 static int
612 set_cursor(sc, p)
613 struct mfb_softc *sc;
614 struct wsdisplay_cursor *p;
615 {
616 #define cc (&sc->sc_cursor)
617 int v, count, index;
618
619 v = p->which;
620 if (v & WSDISPLAY_CURSOR_DOCMAP) {
621 index = p->cmap.index;
622 count = p->cmap.count;
623 if (index >= 2 || (index + count) > 2)
624 return (EINVAL);
625 if (!uvm_useracc(p->cmap.red, count, B_READ))
626 return (EFAULT);
627 }
628 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
629 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
630 return (EINVAL);
631 count = ((p->size.x < 33) ? 4 : 8) * p->size.y;
632 if (!uvm_useracc(p->image, count, B_READ) ||
633 !uvm_useracc(p->mask, count, B_READ))
634 return (EFAULT);
635 }
636 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
637 if (v & WSDISPLAY_CURSOR_DOCUR)
638 cc->cc_hot = p->hot;
639 if (v & WSDISPLAY_CURSOR_DOPOS)
640 set_curpos(sc, &p->pos);
641 bt431_set_curpos(sc);
642 }
643
644 sc->sc_changed = 0;
645 if (v & WSDISPLAY_CURSOR_DOCUR) {
646 sc->sc_curenb = p->enable;
647 sc->sc_changed |= DATA_ENB_CHANGED;
648 }
649 if (v & WSDISPLAY_CURSOR_DOCMAP) {
650 copyin(p->cmap.red, &cc->cc_color[index], count);
651 sc->sc_changed |= DATA_CURCMAP_CHANGED;
652 }
653 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
654 cc->cc_size = p->size;
655 memset(cc->cc_image, 0, sizeof cc->cc_image);
656 copyin(p->image, cc->cc_image, count);
657 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, count);
658 sc->sc_changed |= DATA_CURSHAPE_CHANGED;
659 }
660
661 return (0);
662 #undef cc
663 }
664
665 static int
666 get_cursor(sc, p)
667 struct mfb_softc *sc;
668 struct wsdisplay_cursor *p;
669 {
670 return (ENOTTY); /* XXX */
671 }
672
673 static void
674 set_curpos(sc, curpos)
675 struct mfb_softc *sc;
676 struct wsdisplay_curpos *curpos;
677 {
678 struct fb_devconfig *dc = sc->sc_dc;
679 int x = curpos->x, y = curpos->y;
680
681 if (y < 0)
682 y = 0;
683 else if (y > dc->dc_ht)
684 y = dc->dc_ht;
685 if (x < 0)
686 x = 0;
687 else if (x > dc->dc_wid)
688 x = dc->dc_wid;
689 sc->sc_cursor.cc_pos.x = x;
690 sc->sc_cursor.cc_pos.y = y;
691 }
692
693 void
694 bt431_set_curpos(sc)
695 struct mfb_softc *sc;
696 {
697 caddr_t mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
698 void *curs = (void *)(mfbbase + MX_BT431_OFFSET);
699 u_int16_t twin;
700 int x, y, s;
701
702 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
703 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
704
705 x += sc->sc_cursor.cc_magic.x;
706 y += sc->sc_cursor.cc_magic.y;
707
708 s = spltty();
709
710 SELECT431(curs, BT431_REG_CURSOR_X_LOW);
711 HALF(curs, bt_ctl) = TWIN_LO(x); tc_wmb();
712 HALF(curs, bt_ctl) = TWIN_HI(x); tc_wmb();
713 HALF(curs, bt_ctl) = TWIN_LO(y); tc_wmb();
714 HALF(curs, bt_ctl) = TWIN_HI(y); tc_wmb();
715
716 splx(s);
717 }
718