Home | History | Annotate | Line # | Download | only in tc
mfb.c revision 1.9
      1 /* $NetBSD: mfb.c,v 1.9 1999/03/24 05:51:21 mrg 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.9 1999/03/24 05:51:21 mrg 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 <uvm/uvm_extern.h>
     59 
     60 /* XXX BUS'IFYING XXX */
     61 
     62 #if defined(pmax)
     63 #define	machine_btop(x) mips_btop(x)
     64 #define	MACHINE_KSEG0_TO_PHYS(x) MIPS_KSEG0_TO_PHYS(x)
     65 
     66 struct bt455reg {
     67 	u_int8_t	bt_reg;
     68 	unsigned : 24;
     69 	u_int8_t	bt_cmap;
     70 	unsigned : 24;
     71 	u_int8_t	bt_clr;
     72 	unsigned : 24;
     73 	u_int8_t	bt_ovly;
     74 };
     75 
     76 /*
     77  * N.B. a pair of Bt431s are located adjascently.
     78  * 	struct bt431twin {
     79  *		struct {
     80  *			u_int8_t u0;	for sprite image
     81  *			u_int8_t u1;	for sprite mask
     82  *			unsigned :16;
     83  *		} bt_lo;
     84  *		...
     85  */
     86 struct bt431reg {
     87 	u_int16_t	bt_lo;
     88 	unsigned : 16;
     89 	u_int16_t	bt_hi;
     90 	unsigned : 16;
     91 	u_int16_t	bt_ram;
     92 	unsigned : 16;
     93 	u_int16_t	bt_ctl;
     94 };
     95 
     96 #endif
     97 
     98 #if defined(__alpha__) || defined(alpha)
     99 /*
    100  * Digital UNIX never supports PMAG-AA
    101  */
    102 #define machine_btop(x) alpha_btop(x)
    103 #define MACHINE_KSEG0_TO_PHYS(x) ALPHA_K0SEG_TO_PHYS(x)
    104 
    105 struct bt455reg {
    106 	u_int32_t	bt_reg;
    107 	u_int32_t	bt_cmap;
    108 	u_int32_t	bt_clr;
    109 	u_int32_t	bt_ovly;
    110 };
    111 
    112 struct bt431reg {
    113 	u_int32_t	bt_lo;
    114 	u_int32_t	bt_hi;
    115 	u_int32_t	bt_ram;
    116 	u_int32_t	bt_ctl;
    117 };
    118 #endif
    119 
    120 /* XXX XXX XXX */
    121 
    122 struct fb_devconfig {
    123 	vaddr_t dc_vaddr;		/* memory space virtual base address */
    124 	paddr_t dc_paddr;		/* memory space physical base address */
    125 	vsize_t dc_size;		/* size of slot memory */
    126 	int	dc_wid;			/* width of frame buffer */
    127 	int	dc_ht;			/* height of frame buffer */
    128 	int	dc_depth;		/* depth, bits per pixel */
    129 	int	dc_rowbytes;		/* bytes in a FB scan line */
    130 	vaddr_t dc_videobase;		/* base of flat frame buffer */
    131 	struct raster	dc_raster;	/* raster description */
    132 	struct rcons	dc_rcons;	/* raster blitter control info */
    133 	int	    dc_blanked;		/* currently has video disabled */
    134 };
    135 
    136 struct hwcursor {
    137 	struct wsdisplay_curpos cc_pos;
    138 	struct wsdisplay_curpos cc_hot;
    139 	struct wsdisplay_curpos cc_size;
    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 hwcursor 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 	short magic_x, magic_y;		/* MX cursor location offset */
    158 #define	MX_MAGIC_X 360
    159 #define	MX_MAGIC_Y 36
    160 };
    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 = 1;
    314 	dc->dc_rowbytes = 2048 / 8;
    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 	sc->magic_x = MX_MAGIC_X;
    370 	sc->magic_y = MX_MAGIC_Y;
    371 
    372         tc_intr_establish(parent, ta->ta_cookie, TC_IPL_TTY, mfbintr, sc);
    373 
    374 	mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    375 	*(u_int8_t *)(mfbbase + MX_IREQ_OFFSET) = 0;
    376 	junk = *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET);
    377 	*(u_int8_t *)(mfbbase + MX_IREQ_OFFSET) = 1;
    378 
    379 	waa.console = console;
    380 	waa.scrdata = &mfb_screenlist;
    381 	waa.accessops = &mfb_accessops;
    382 	waa.accesscookie = sc;
    383 
    384 	config_found(self, &waa, wsemuldisplaydevprint);
    385 }
    386 
    387 int
    388 mfbioctl(v, cmd, data, flag, p)
    389 	void *v;
    390 	u_long cmd;
    391 	caddr_t data;
    392 	int flag;
    393 	struct proc *p;
    394 {
    395 	struct mfb_softc *sc = v;
    396 	struct fb_devconfig *dc = sc->sc_dc;
    397 	int turnoff;
    398 
    399 	switch (cmd) {
    400 	case WSDISPLAYIO_GTYPE:
    401 		*(u_int *)data = WSDISPLAY_TYPE_MFB;
    402 		return (0);
    403 
    404 	case WSDISPLAYIO_GINFO:
    405 #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    406 		wsd_fbip->height = sc->sc_dc->dc_ht;
    407 		wsd_fbip->width = sc->sc_dc->dc_wid;
    408 		wsd_fbip->depth = sc->sc_dc->dc_depth;
    409 		wsd_fbip->cmsize = 0;
    410 #undef fbt
    411 		return (0);
    412 
    413 	case WSDISPLAYIO_GETCMAP:
    414 	case WSDISPLAYIO_PUTCMAP:
    415 		return (ENOTTY);
    416 
    417 	case WSDISPLAYIO_SVIDEO:
    418 		turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
    419 		if ((dc->dc_blanked == 0) ^ turnoff) {
    420 			dc->dc_blanked = turnoff;
    421 			/* XXX later XXX */
    422 		}
    423 		return (0);
    424 
    425 	case WSDISPLAYIO_GVIDEO:
    426 		*(u_int *)data = dc->dc_blanked ?
    427 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
    428 		return (0);
    429 
    430 	case WSDISPLAYIO_GCURPOS:
    431 		*(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
    432 		return (0);
    433 
    434 	case WSDISPLAYIO_SCURPOS:
    435 		set_curpos(sc, (struct wsdisplay_curpos *)data);
    436 		bt431_set_curpos(sc);
    437 		return (0);
    438 
    439 	case WSDISPLAYIO_GCURMAX:
    440 		((struct wsdisplay_curpos *)data)->x =
    441 		((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
    442 		return (0);
    443 
    444 	case WSDISPLAYIO_GCURSOR:
    445 		return get_cursor(sc, (struct wsdisplay_cursor *)data);
    446 
    447 	case WSDISPLAYIO_SCURSOR:
    448 		return set_cursor(sc, (struct wsdisplay_cursor *)data);
    449 	}
    450 	return (ENOTTY);
    451 }
    452 
    453 int
    454 mfbmmap(v, offset, prot)
    455 	void *v;
    456 	off_t offset;
    457 	int prot;
    458 {
    459 	struct mfb_softc *sc = v;
    460 
    461 	if (offset >= MX_FB_SIZE || offset < 0)
    462 		return (-1);
    463 	return machine_btop(sc->sc_dc->dc_paddr + offset);
    464 }
    465 
    466 int
    467 mfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
    468 	void *v;
    469 	const struct wsscreen_descr *type;
    470 	void **cookiep;
    471 	int *curxp, *curyp;
    472 	long *attrp;
    473 {
    474 	struct mfb_softc *sc = v;
    475 	long defattr;
    476 
    477 	if (sc->nscreens > 0)
    478 		return (ENOMEM);
    479 
    480 	*cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
    481 	*curxp = 0;
    482 	*curyp = 0;
    483 	rcons_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
    484 	*attrp = defattr;
    485 	sc->nscreens++;
    486 	return (0);
    487 }
    488 
    489 void
    490 mfb_free_screen(v, cookie)
    491 	void *v;
    492 	void *cookie;
    493 {
    494 	struct mfb_softc *sc = v;
    495 
    496 	if (sc->sc_dc == &mfb_console_dc)
    497 		panic("mfb_free_screen: console");
    498 
    499 	sc->nscreens--;
    500 }
    501 
    502 void
    503 mfb_show_screen(v, cookie)
    504 	void *v;
    505 	void *cookie;
    506 {
    507 }
    508 
    509 int
    510 mfb_cnattach(addr)
    511         tc_addr_t addr;
    512 {
    513         struct fb_devconfig *dcp = &mfb_console_dc;
    514         long defattr;
    515 
    516         mfb_getdevconfig(addr, dcp);
    517 
    518         rcons_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
    519 
    520         wsdisplay_cnattach(&mfb_stdscreen, &dcp->dc_rcons,
    521                            0, 0, defattr);
    522         mfb_consaddr = addr;
    523         return (0);
    524 }
    525 
    526 
    527 int
    528 mfbintr(arg)
    529 	void *arg;
    530 {
    531 	struct mfb_softc *sc = arg;
    532 	caddr_t mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    533 	struct bt455reg *vdac;
    534 	struct bt431reg *curs;
    535 	int v;
    536 	volatile register int junk;
    537 
    538 	junk = *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET);
    539 	/* *(u_int8_t *)(mfbbase + MX_IREQ_OFFSET) = 1; */
    540 
    541 	if (sc->sc_changed == 0)
    542 		return (1);
    543 
    544 	vdac = (void *)(mfbbase + MX_BT455_OFFSET);
    545 	curs = (void *)(mfbbase + MX_BT431_OFFSET);
    546 
    547 	v = sc->sc_changed;
    548 	sc->sc_changed = 0;
    549 	if (v & DATA_ENB_CHANGED) {
    550 		BT431_SELECT(curs, BT431_REG_COMMAND);
    551 		curs->bt_ctl = (sc->sc_curenb) ? 0x4444 : 0x0404;
    552 	}
    553 	if (v & DATA_CURSHAPE_CHANGED) {
    554 		u_int8_t *ip, *mp, img, msk;
    555 		int bcnt;
    556 
    557 		ip = (u_int8_t *)sc->sc_cursor.cc_image;
    558 		mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
    559 
    560 		bcnt = 0;
    561 		BT431_SELECT(curs, BT431_REG_CRAM_BASE+0);
    562 		/* 64 pixel scan line is consisted with 16 byte cursor ram */
    563 		while (bcnt < sc->sc_cursor.cc_size.y * 16) {
    564 			/* pad right half 32 pixel when smaller than 33 */
    565 			if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
    566 				curs->bt_ram = 0;
    567 				tc_wmb();
    568 			}
    569 			else {
    570 				img = *ip++;
    571 				msk = *mp++;
    572 				img &= msk;	/* cookie off image */
    573 				curs->bt_ram = (flip[msk] << 8) | flip[img];
    574 				tc_wmb();
    575 			}
    576 			bcnt += 2;
    577 		}
    578 		/* pad unoccupied scan lines */
    579 		while (bcnt < CURSOR_MAX_SIZE * 16) {
    580 			curs->bt_ram = 0;
    581 			tc_wmb();
    582 			bcnt += 2;
    583 		}
    584 	}
    585 	return (1);
    586 }
    587 
    588 void
    589 mfbinit(dc)
    590 	struct fb_devconfig *dc;
    591 {
    592 	caddr_t mfbbase = (caddr_t)dc->dc_vaddr;
    593 	struct bt431reg *curs = (void *)(mfbbase + MX_BT431_OFFSET);
    594 	struct bt455reg *vdac = (void *)(mfbbase + MX_BT455_OFFSET);
    595 	int i;
    596 
    597 	BT431_SELECT(curs, BT431_REG_COMMAND);
    598 	curs->bt_ctl = 0x0404;	tc_wmb();
    599 	curs->bt_ctl = 0;	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 
    612 	BT455_SELECT(vdac, 0);
    613 	for (i = 0; i < 16; i++) {
    614 		vdac->bt_cmap = 0;	tc_wmb();
    615 		vdac->bt_cmap = 0;	tc_wmb();
    616 		vdac->bt_cmap = 0;	tc_wmb();
    617 	}
    618 
    619 	BT455_SELECT(vdac, 1);
    620 	vdac->bt_cmap = 0;	tc_wmb();
    621 	vdac->bt_cmap = 0xff;	tc_wmb();
    622 	vdac->bt_cmap = 0;	tc_wmb();
    623 
    624 	BT455_SELECT(vdac, 8);
    625 	vdac->bt_cmap = 0;	tc_wmb();
    626 	vdac->bt_cmap = 0xff;	tc_wmb();
    627 	vdac->bt_cmap = 0;	tc_wmb();
    628 
    629 	vdac->bt_ovly = 0;	tc_wmb();
    630 	vdac->bt_ovly = 0xff;	tc_wmb();
    631 	vdac->bt_ovly = 0;	tc_wmb();
    632 }
    633 
    634 static int
    635 set_cursor(sc, p)
    636 	struct mfb_softc *sc;
    637 	struct wsdisplay_cursor *p;
    638 {
    639 #define	cc (&sc->sc_cursor)
    640 	int v, count;
    641 
    642 	v = p->which;
    643 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    644 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    645 			return (EINVAL);
    646 		count = ((p->size.x < 33) ? 4 : 8) * p->size.y;
    647 		if (!uvm_useracc(p->image, count, B_READ) ||
    648 		    !uvm_useracc(p->mask, count, B_READ))
    649 			return (EFAULT);
    650 	}
    651 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
    652 		if (v & WSDISPLAY_CURSOR_DOCUR)
    653 			cc->cc_hot = p->hot;
    654 		if (v & WSDISPLAY_CURSOR_DOPOS)
    655 			set_curpos(sc, &p->pos);
    656 		bt431_set_curpos(sc);
    657 	}
    658 
    659 	sc->sc_changed = 0;
    660 	if (v & WSDISPLAY_CURSOR_DOCUR) {
    661 		sc->sc_curenb = p->enable;
    662 		sc->sc_changed |= DATA_ENB_CHANGED;
    663 	}
    664 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    665 		cc->cc_size = p->size;
    666 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    667 		copyin(p->image, cc->cc_image, count);
    668 		copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, count);
    669 		sc->sc_changed |= DATA_CURSHAPE_CHANGED;
    670 	}
    671 
    672 	return (0);
    673 #undef cc
    674 }
    675 
    676 static int
    677 get_cursor(sc, p)
    678 	struct mfb_softc *sc;
    679 	struct wsdisplay_cursor *p;
    680 {
    681 	return (ENOTTY); /* XXX */
    682 }
    683 
    684 static void
    685 set_curpos(sc, curpos)
    686 	struct mfb_softc *sc;
    687 	struct wsdisplay_curpos *curpos;
    688 {
    689 	struct fb_devconfig *dc = sc->sc_dc;
    690 	int x = curpos->x, y = curpos->y;
    691 
    692 	if (y < 0)
    693 		y = 0;
    694 	else if (y > dc->dc_ht)
    695 		y = dc->dc_ht;
    696 	if (x < 0)
    697 		x = 0;
    698 	else if (x > dc->dc_wid)
    699 		x = dc->dc_wid;
    700 	sc->sc_cursor.cc_pos.x = x;
    701 	sc->sc_cursor.cc_pos.y = y;
    702 }
    703 
    704 void
    705 bt431_set_curpos(sc)
    706 	struct mfb_softc *sc;
    707 {
    708 	caddr_t mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    709 	struct bt431reg *curs = (void *)(mfbbase + MX_BT431_OFFSET);
    710 	u_int16_t twin;
    711 	int x, y, s;
    712 
    713 	x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
    714 	y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
    715 	x += sc->magic_x; y += sc->magic_y; /* magic offset of MX coordinate */
    716 
    717 	s = spltty();
    718 
    719 	BT431_SELECT(curs, BT431_REG_CURSOR_X_LOW);
    720 	curs->bt_ctl = TWIN_LO(x);	tc_wmb();
    721 	curs->bt_ctl = TWIN_HI(x);	tc_wmb();
    722 	curs->bt_ctl = TWIN_LO(y);	tc_wmb();
    723 	curs->bt_ctl = TWIN_HI(y);	tc_wmb();
    724 
    725 	splx(s);
    726 }
    727