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