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