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