Home | History | Annotate | Line # | Download | only in tc
mfb.c revision 1.4
      1 /* $NetBSD: mfb.c,v 1.4 1998/11/18 12:26:32 nisimura 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.4 1998/11/18 12:26:32 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 #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 paif 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 int	mfb_load_font __P((void *, void *, int, int, int, void *));
    217 
    218 struct wsdisplay_accessops mfb_accessops = {
    219 	mfbioctl,
    220 	mfbmmap,
    221 	mfb_alloc_screen,
    222 	mfb_free_screen,
    223 	mfb_show_screen,
    224 	mfb_load_font
    225 };
    226 
    227 int  mfb_cnattach __P((tc_addr_t));
    228 int  mfbintr __P((void *));
    229 void mfbinit __P((struct fb_devconfig *));
    230 
    231 static int  set_cursor __P((struct mfb_softc *, struct wsdisplay_cursor *));
    232 static int  get_cursor __P((struct mfb_softc *, struct wsdisplay_cursor *));
    233 static void set_curpos __P((struct mfb_softc *, struct wsdisplay_curpos *));
    234 void bt431_set_curpos __P((struct mfb_softc *));
    235 
    236 #define	TWIN_LO(x) (twin = (x) & 0x00ff, twin << 8 | twin)
    237 #define	TWIN_HI(x) (twin = (x) & 0xff00, twin | twin >> 8)
    238 
    239 /* XXX XXX XXX */
    240 #define	BT431_SELECT(curs, regno) do {	\
    241 	u_int16_t twin;			\
    242 	curs->bt_lo = TWIN_LO(regno);	\
    243 	curs->bt_hi = TWIN_HI(regno);	\
    244 	tc_wmb();			\
    245    } while (0)
    246 
    247 #define BT455_SELECT(vdac, index) do {	\
    248 	vdac->bt_reg = index;		\
    249 	vdac->bt_clr = 0;		\
    250 	tc_wmb();			\
    251    } while (0)
    252 /* XXX XXX XXX */
    253 
    254 /* bit order reverse */
    255 const static u_int8_t flip[256] = {
    256 	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
    257 	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
    258 	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
    259 	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
    260 	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
    261 	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
    262 	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
    263 	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
    264 	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
    265 	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
    266 	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
    267 	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
    268 	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
    269 	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
    270 	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
    271 	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
    272 	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
    273 	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
    274 	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
    275 	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
    276 	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
    277 	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
    278 	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
    279 	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
    280 	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
    281 	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
    282 	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
    283 	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
    284 	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
    285 	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
    286 	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
    287 	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
    288 };
    289 
    290 int
    291 mfbmatch(parent, match, aux)
    292 	struct device *parent;
    293 	struct cfdata *match;
    294 	void *aux;
    295 {
    296 	struct tc_attach_args *ta = aux;
    297 
    298 	if (strncmp("PMAG-AA ", ta->ta_modname, TC_ROM_LLEN) != 0)
    299 		return (0);
    300 
    301 	return (1);
    302 }
    303 
    304 void
    305 mfb_getdevconfig(dense_addr, dc)
    306 	tc_addr_t dense_addr;
    307 	struct fb_devconfig *dc;
    308 {
    309 	struct raster *rap;
    310 	struct rcons *rcp;
    311 	int i;
    312 
    313 	dc->dc_vaddr = dense_addr;
    314 	dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr + MX_FB_OFFSET);
    315 
    316 	dc->dc_wid = 1280;
    317 	dc->dc_ht = 1024;
    318 	dc->dc_depth = 1;
    319 	dc->dc_rowbytes = 2048 / 8;
    320 	dc->dc_videobase = dc->dc_vaddr + MX_FB_OFFSET;
    321 	dc->dc_blanked = 0;
    322 
    323 	/* initialize colormap and cursor resource */
    324 	mfbinit(dc);
    325 
    326 	/* clear the screen */
    327 	for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
    328 		*(u_int32_t *)(dc->dc_videobase + i) = 0;
    329 
    330 	/* initialize the raster */
    331 	rap = &dc->dc_raster;
    332 	rap->width = dc->dc_wid;
    333 	rap->height = dc->dc_ht;
    334 	rap->depth = dc->dc_depth;
    335 	rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
    336 	rap->pixels = (u_int32_t *)dc->dc_videobase;
    337 
    338 	/* initialize the raster console blitter */
    339 	rcp = &dc->dc_rcons;
    340 	rcp->rc_sp = rap;
    341 	rcp->rc_crow = rcp->rc_ccol = -1;
    342 	rcp->rc_crowp = &rcp->rc_crow;
    343 	rcp->rc_ccolp = &rcp->rc_ccol;
    344 	rcons_init(rcp, 34, 80);
    345 
    346 	mfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
    347 	mfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
    348 }
    349 
    350 void
    351 mfbattach(parent, self, aux)
    352 	struct device *parent, *self;
    353 	void *aux;
    354 {
    355 	struct mfb_softc *sc = (struct mfb_softc *)self;
    356 	struct tc_attach_args *ta = aux;
    357 	struct wsemuldisplaydev_attach_args waa;
    358 	caddr_t mfbbase;
    359 	int console;
    360 	volatile register int junk;
    361 
    362 	console = (ta->ta_addr == mfb_consaddr);
    363 	if (console) {
    364 		sc->sc_dc = &mfb_console_dc;
    365 		sc->nscreens = 1;
    366 	}
    367 	else {
    368 		sc->sc_dc = (struct fb_devconfig *)
    369 		    malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
    370 		mfb_getdevconfig(ta->ta_addr, sc->sc_dc);
    371 	}
    372 	printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
    373 	    sc->sc_dc->dc_depth);
    374 	sc->magic_x = MX_MAGIC_X;
    375 	sc->magic_y = MX_MAGIC_Y;
    376 
    377         tc_intr_establish(parent, ta->ta_cookie, TC_IPL_TTY, mfbintr, sc);
    378 
    379 	mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    380 	*(u_int8_t *)(mfbbase + MX_IREQ_OFFSET) = 0;
    381 	junk = *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET);
    382 	*(u_int8_t *)(mfbbase + MX_IREQ_OFFSET) = 1;
    383 
    384 	waa.console = console;
    385 	waa.scrdata = &mfb_screenlist;
    386 	waa.accessops = &mfb_accessops;
    387 	waa.accesscookie = sc;
    388 
    389 	config_found(self, &waa, wsemuldisplaydevprint);
    390 }
    391 
    392 int
    393 mfbioctl(v, cmd, data, flag, p)
    394 	void *v;
    395 	u_long cmd;
    396 	caddr_t data;
    397 	int flag;
    398 	struct proc *p;
    399 {
    400 	struct mfb_softc *sc = v;
    401 	struct fb_devconfig *dc = sc->sc_dc;
    402 	int turnoff;
    403 
    404 	switch (cmd) {
    405 	case WSDISPLAYIO_GTYPE:
    406 		*(u_int *)data = WSDISPLAY_TYPE_MFB;
    407 		return (0);
    408 
    409 	case WSDISPLAYIO_GINFO:
    410 #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    411 		wsd_fbip->height = sc->sc_dc->dc_ht;
    412 		wsd_fbip->width = sc->sc_dc->dc_wid;
    413 		wsd_fbip->depth = sc->sc_dc->dc_depth;
    414 		wsd_fbip->cmsize = 0;
    415 #undef fbt
    416 		return (0);
    417 
    418 	case WSDISPLAYIO_GETCMAP:
    419 	case WSDISPLAYIO_PUTCMAP:
    420 		return (ENOTTY);
    421 
    422 	case WSDISPLAYIO_SVIDEO:
    423 		turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
    424 		if ((dc->dc_blanked == 0) ^ turnoff) {
    425 			dc->dc_blanked = turnoff;
    426 			/* XXX later XXX */
    427 		}
    428 		return (0);
    429 
    430 	case WSDISPLAYIO_GVIDEO:
    431 		*(u_int *)data = dc->dc_blanked ?
    432 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
    433 		return (0);
    434 
    435 	case WSDISPLAYIO_GCURPOS:
    436 		*(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
    437 		return (0);
    438 
    439 	case WSDISPLAYIO_SCURPOS:
    440 		set_curpos(sc, (struct wsdisplay_curpos *)data);
    441 		bt431_set_curpos(sc);
    442 		return (0);
    443 
    444 	case WSDISPLAYIO_GCURMAX:
    445 		((struct wsdisplay_curpos *)data)->x =
    446 		((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
    447 		return (0);
    448 
    449 	case WSDISPLAYIO_GCURSOR:
    450 		return get_cursor(sc, (struct wsdisplay_cursor *)data);
    451 
    452 	case WSDISPLAYIO_SCURSOR:
    453 		return set_cursor(sc, (struct wsdisplay_cursor *)data);
    454 	}
    455 	return ENOTTY;
    456 }
    457 
    458 int
    459 mfbmmap(v, offset, prot)
    460 	void *v;
    461 	off_t offset;
    462 	int prot;
    463 {
    464 	struct mfb_softc *sc = v;
    465 
    466 	if (offset > MX_FB_SIZE)
    467 		return (-1);
    468 	return machine_btop(sc->sc_dc->dc_paddr + offset);
    469 }
    470 
    471 int
    472 mfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
    473 	void *v;
    474 	const struct wsscreen_descr *type;
    475 	void **cookiep;
    476 	int *curxp, *curyp;
    477 	long *attrp;
    478 {
    479 	struct mfb_softc *sc = v;
    480 	long defattr;
    481 
    482 	if (sc->nscreens > 0)
    483 		return (ENOMEM);
    484 
    485 	*cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
    486 	*curxp = 0;
    487 	*curyp = 0;
    488 	rcons_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
    489 	*attrp = defattr;
    490 	sc->nscreens++;
    491 	return (0);
    492 }
    493 
    494 void
    495 mfb_free_screen(v, cookie)
    496 	void *v;
    497 	void *cookie;
    498 {
    499 	struct mfb_softc *sc = v;
    500 
    501 	if (sc->sc_dc == &mfb_console_dc)
    502 		panic("mfb_free_screen: console");
    503 
    504 	sc->nscreens--;
    505 }
    506 
    507 void
    508 mfb_show_screen(v, cookie)
    509 	void *v;
    510 	void *cookie;
    511 {
    512 }
    513 
    514 int
    515 mfb_load_font(v, cookie, first, num, stride, data)
    516 	void *v;
    517 	void *cookie;
    518 	int first, num, stride;
    519 	void *data;
    520 {
    521 	return (EINVAL);
    522 }
    523 
    524 int
    525 mfb_cnattach(addr)
    526         tc_addr_t addr;
    527 {
    528         struct fb_devconfig *dcp = &mfb_console_dc;
    529         long defattr;
    530 
    531         mfb_getdevconfig(addr, dcp);
    532 
    533         rcons_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
    534 
    535         wsdisplay_cnattach(&mfb_stdscreen, &dcp->dc_rcons,
    536                            0, 0, defattr);
    537         mfb_consaddr = addr;
    538         return(0);
    539 }
    540 
    541 
    542 int
    543 mfbintr(arg)
    544 	void *arg;
    545 {
    546 	struct mfb_softc *sc = arg;
    547 	caddr_t mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    548 	struct bt455reg *vdac;
    549 	struct bt431reg *curs;
    550 	int v;
    551 	volatile register int junk;
    552 
    553 	junk = *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET);
    554 	/* *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET) = 1; */
    555 
    556 	if (sc->sc_changed == 0)
    557 		return (1);
    558 
    559 	vdac = (void *)(mfbbase + MX_BT455_OFFSET);
    560 	curs = (void *)(mfbbase + MX_BT431_OFFSET);
    561 
    562 	v = sc->sc_changed;
    563 	sc->sc_changed = 0;
    564 	if (v & DATA_ENB_CHANGED) {
    565 		BT431_SELECT(curs, BT431_REG_COMMAND);
    566 		curs->bt_ctl = (sc->sc_curenb) ? 0x4444 : 0x0404;
    567 	}
    568 	if (v & DATA_CURSHAPE_CHANGED) {
    569 		u_int8_t *ip, *mp, img, msk;
    570 		int bcnt;
    571 
    572 		ip = (u_int8_t *)sc->sc_cursor.cc_image;
    573 		mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
    574 
    575 		bcnt = 0;
    576 		BT431_SELECT(curs, BT431_REG_CRAM_BASE+0);
    577 		/* 64 pixel scan line is consisted with 16 byte cursor ram */
    578 		while (bcnt < sc->sc_cursor.cc_size.y * 16) {
    579 			/* pad right half 32 pixel when smaller than 33 */
    580 			if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
    581 				curs->bt_ram = 0;
    582 				tc_wmb();
    583 			}
    584 			else {
    585 				img = *ip++;
    586 				msk = *mp++;
    587 				img &= msk;	/* cookie off image */
    588 				curs->bt_ram = (flip[msk] << 8) | flip[img];
    589 				tc_wmb();
    590 			}
    591 			bcnt += 2;
    592 		}
    593 		/* pad unoccupied scan lines */
    594 		while (bcnt < CURSOR_MAX_SIZE * 16) {
    595 			curs->bt_ram = 0;
    596 			tc_wmb();
    597 			bcnt += 2;
    598 		}
    599 	}
    600 	return (1);
    601 }
    602 
    603 void
    604 mfbinit(dc)
    605 	struct fb_devconfig *dc;
    606 {
    607 	caddr_t mfbbase = (caddr_t)dc->dc_vaddr;
    608 	struct bt431reg *curs = (void *)(mfbbase + MX_BT431_OFFSET);
    609 	struct bt455reg *vdac = (void *)(mfbbase + MX_BT455_OFFSET);
    610 	int i;
    611 
    612 	BT431_SELECT(curs, BT431_REG_COMMAND);
    613 	curs->bt_ctl = 0x0404;	tc_wmb();
    614 	curs->bt_ctl = 0;	tc_wmb();
    615 	curs->bt_ctl = 0;	tc_wmb();
    616 	curs->bt_ctl = 0;	tc_wmb();
    617 	curs->bt_ctl = 0;	tc_wmb();
    618 	curs->bt_ctl = 0;	tc_wmb();
    619 	curs->bt_ctl = 0;	tc_wmb();
    620 	curs->bt_ctl = 0;	tc_wmb();
    621 	curs->bt_ctl = 0;	tc_wmb();
    622 	curs->bt_ctl = 0;	tc_wmb();
    623 	curs->bt_ctl = 0;	tc_wmb();
    624 	curs->bt_ctl = 0;	tc_wmb();
    625 	curs->bt_ctl = 0;	tc_wmb();
    626 
    627 	BT455_SELECT(vdac, 0);
    628 	for (i = 0; i < 16; i++) {
    629 		vdac->bt_cmap = 0;	tc_wmb();
    630 		vdac->bt_cmap = 0;	tc_wmb();
    631 		vdac->bt_cmap = 0;	tc_wmb();
    632 	}
    633 
    634 	BT455_SELECT(vdac, 1);
    635 	vdac->bt_cmap = 0;	tc_wmb();
    636 	vdac->bt_cmap = 0xff;	tc_wmb();
    637 	vdac->bt_cmap = 0;	tc_wmb();
    638 
    639 	BT455_SELECT(vdac, 8);
    640 	vdac->bt_cmap = 0;	tc_wmb();
    641 	vdac->bt_cmap = 0xff;	tc_wmb();
    642 	vdac->bt_cmap = 0;	tc_wmb();
    643 
    644 	vdac->bt_ovly = 0;	tc_wmb();
    645 	vdac->bt_ovly = 0xff;	tc_wmb();
    646 	vdac->bt_ovly = 0;	tc_wmb();
    647 }
    648 
    649 static int
    650 set_cursor(sc, p)
    651 	struct mfb_softc *sc;
    652 	struct wsdisplay_cursor *p;
    653 {
    654 #define	cc (&sc->sc_cursor)
    655 	int v, count;
    656 
    657 	v = p->which;
    658 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    659 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    660 			return (EINVAL);
    661 		count = ((p->size.x < 33) ? 4 : 8) * p->size.y;
    662 		if (!useracc(p->image, count, B_READ) ||
    663 		    !useracc(p->mask, count, B_READ))
    664 			return (EFAULT);
    665 	}
    666 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
    667 		if (v & WSDISPLAY_CURSOR_DOCUR)
    668 			cc->cc_hot = p->hot;
    669 		if (v & WSDISPLAY_CURSOR_DOPOS)
    670 			set_curpos(sc, &p->pos);
    671 		bt431_set_curpos(sc);
    672 	}
    673 
    674 	sc->sc_changed = 0;
    675 	if (v & WSDISPLAY_CURSOR_DOCUR) {
    676 		sc->sc_curenb = p->enable;
    677 		sc->sc_changed |= DATA_ENB_CHANGED;
    678 	}
    679 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    680 		cc->cc_size = p->size;
    681 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    682 		copyin(p->image, cc->cc_image, count);
    683 		copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, count);
    684 		sc->sc_changed |= DATA_CURSHAPE_CHANGED;
    685 	}
    686 
    687 	return (0);
    688 #undef cc
    689 }
    690 
    691 static int
    692 get_cursor(sc, p)
    693 	struct mfb_softc *sc;
    694 	struct wsdisplay_cursor *p;
    695 {
    696 	return (ENOTTY); /* XXX */
    697 }
    698 
    699 static void
    700 set_curpos(sc, curpos)
    701 	struct mfb_softc *sc;
    702 	struct wsdisplay_curpos *curpos;
    703 {
    704 	struct fb_devconfig *dc = sc->sc_dc;
    705 	int x = curpos->x, y = curpos->y;
    706 
    707 	if (y < 0)
    708 		y = 0;
    709 	else if (y > dc->dc_ht)
    710 		y = dc->dc_ht;
    711 	if (x < 0)
    712 		x = 0;
    713 	else if (x > dc->dc_wid)
    714 		x = dc->dc_wid;
    715 	sc->sc_cursor.cc_pos.x = x;
    716 	sc->sc_cursor.cc_pos.y = y;
    717 }
    718 
    719 void
    720 bt431_set_curpos(sc)
    721 	struct mfb_softc *sc;
    722 {
    723 	caddr_t mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    724 	struct bt431reg *curs = (void *)(mfbbase + MX_BT431_OFFSET);
    725 	u_int16_t twin;
    726 	int x, y, s;
    727 
    728 	x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
    729 	y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
    730 	x += sc->magic_x; y += sc->magic_y; /* magic offset of MX coordinate */
    731 
    732 	s = spltty();
    733 
    734 	BT431_SELECT(curs, BT431_REG_CURSOR_X_LOW);
    735 	curs->bt_ctl = TWIN_LO(x);	tc_wmb();
    736 	curs->bt_ctl = TWIN_HI(x);	tc_wmb();
    737 	curs->bt_ctl = TWIN_LO(y);	tc_wmb();
    738 	curs->bt_ctl = TWIN_HI(y);	tc_wmb();
    739 
    740 	splx(s);
    741 }
    742