Home | History | Annotate | Line # | Download | only in tc
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