Home | History | Annotate | Line # | Download | only in tc
mfb.c revision 1.2
      1 /* $NetBSD: mfb.c,v 1.2 1998/10/30 00:53:12 nisimura Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1996, 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.2 1998/10/30 00:53:12 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 /* it's really painful to manipulate 'twined' registers... */
    108 struct bt431reg {
    109 	u_int32_t	bt_lo;
    110 	u_int32_t	bt_hi;
    111 	u_int32_t	bt_ram;
    112 	u_int32_t	bt_ctl;
    113 };
    114 #endif
    115 
    116 /* XXX XXX XXX */
    117 
    118 struct fb_devconfig {
    119 	vaddr_t dc_vaddr;		/* memory space virtual base address */
    120 	paddr_t dc_paddr;		/* memory space physical base address */
    121 	vsize_t dc_size;		/* size of slot memory */
    122 	int	dc_wid;			/* width of frame buffer */
    123 	int	dc_ht;			/* height of frame buffer */
    124 	int	dc_depth;		/* depth, bits per pixel */
    125 	int	dc_rowbytes;		/* bytes in a FB scan line */
    126 	vaddr_t dc_videobase;		/* base of flat frame buffer */
    127 	struct raster	dc_raster;	/* raster description */
    128 	struct rcons	dc_rcons;	/* raster blitter control info */
    129 	int	    dc_blanked;		/* currently has video disabled */
    130 };
    131 
    132 struct hwcursor {
    133 	struct wsdisplay_curpos cc_pos;
    134 	struct wsdisplay_curpos cc_hot;
    135 	struct wsdisplay_curpos cc_size;
    136 #define	CURSOR_MAX_SIZE	64
    137 	u_int8_t cc_color[6];
    138 	u_int64_t cc_image[64 + 64];
    139 };
    140 
    141 struct mfb_softc {
    142 	struct device sc_dev;
    143 	struct fb_devconfig *sc_dc;	/* device configuration */
    144 	struct hwcursor sc_cursor;	/* software copy of cursor */
    145 	int sc_curenb;			/* cursor sprite enabled */
    146 	int sc_changed;			/* need update of colormap */
    147 #define	DATA_ENB_CHANGED	0x01	/* cursor enable changed */
    148 #define	DATA_CURCMAP_CHANGED	0x02	/* cursor colormap changed */
    149 #define	DATA_CURSHAPE_CHANGED	0x04	/* cursor size, image, mask changed */
    150 #define	DATA_CMAP_CHANGED	0x08	/* colormap changed */
    151 #define	DATA_ALL_CHANGED	0x0f
    152 	int nscreens;
    153 };
    154 
    155 int  mfbmatch __P((struct device *, struct cfdata *, void *));
    156 void mfbattach __P((struct device *, struct device *, void *));
    157 
    158 struct cfattach mfb_ca = {
    159 	sizeof(struct mfb_softc), mfbmatch, mfbattach,
    160 };
    161 
    162 void mfb_getdevconfig __P((tc_addr_t, struct fb_devconfig *));
    163 struct fb_devconfig mfb_console_dc;
    164 tc_addr_t mfb_consaddr;
    165 
    166 struct wsdisplay_emulops mfb_emulops = {
    167 	rcons_cursor,			/* could use hardware cursor; punt */
    168 	rcons_mapchar,
    169 	rcons_putchar,
    170 	rcons_copycols,
    171 	rcons_erasecols,
    172 	rcons_copyrows,
    173 	rcons_eraserows,
    174 	rcons_alloc_attr
    175 };
    176 
    177 struct wsscreen_descr mfb_stdscreen = {
    178 	"std", 0, 0,
    179 	&mfb_emulops,
    180 	0, 0,
    181 	0
    182 };
    183 
    184 const struct wsscreen_descr *_mfb_scrlist[] = {
    185 	&mfb_stdscreen,
    186 };
    187 
    188 struct wsscreen_list mfb_screenlist = {
    189 	sizeof(_mfb_scrlist) / sizeof(struct wsscreen_descr *), _mfb_scrlist
    190 };
    191 
    192 int	mfbioctl __P((void *, u_long, caddr_t, int, struct proc *));
    193 int	mfbmmap __P((void *, off_t, int));
    194 
    195 int	mfb_alloc_screen __P((void *, const struct wsscreen_descr *,
    196 				      void **, int *, int *, long *));
    197 void	mfb_free_screen __P((void *, void *));
    198 void	mfb_show_screen __P((void *, void *));
    199 int	mfb_load_font __P((void *, void *, int, int, int, void *));
    200 
    201 struct wsdisplay_accessops mfb_accessops = {
    202 	mfbioctl,
    203 	mfbmmap,
    204 	mfb_alloc_screen,
    205 	mfb_free_screen,
    206 	mfb_show_screen,
    207 	mfb_load_font
    208 };
    209 
    210 int  mfb_cnattach __P((tc_addr_t));
    211 int  mfbintr __P((void *));
    212 void mfbinit __P((struct fb_devconfig *));
    213 
    214 static int  set_cursor __P((struct mfb_softc *, struct wsdisplay_cursor *));
    215 static int  get_cursor __P((struct mfb_softc *, struct wsdisplay_cursor *));
    216 static void set_curpos __P((struct mfb_softc *, struct wsdisplay_curpos *));
    217 void bt431_set_curpos __P((struct mfb_softc *));
    218 
    219 #define	TWIN_LO(x) (twin = (x) & 0x00ff, twin << 8 | twin)
    220 #define	TWIN_HI(x) (twin = (x) & 0xff00, twin | twin >> 8)
    221 
    222 /* XXX XXX XXX */
    223 #define	BT431_SELECT(curs, regno) do {	\
    224 	u_int16_t twin;			\
    225 	curs->bt_lo = TWIN_LO(regno);	\
    226 	curs->bt_hi = TWIN_HI(regno);	\
    227 	tc_wmb();			\
    228    } while (0)
    229 
    230 #define BT455_SELECT(vdac, index) do {	\
    231 	vdac->bt_reg = index;		\
    232 	vdac->bt_clr = 0;		\
    233 	tc_wmb();			\
    234    } while (0)
    235 /* XXX XXX XXX */
    236 
    237 #define	MFB_FB_OFFSET		0x200000
    238 #define	MFB_FB_SIZE		 0x40000
    239 #define	MFB_BT455_OFFSET	0x100000
    240 #define	MFB_BT431_OFFSET	0x180000
    241 #define	MFB_IREQ_OFFSET		0x080000	/* Interrupt req. control */
    242 
    243 int
    244 mfbmatch(parent, match, aux)
    245 	struct device *parent;
    246 	struct cfdata *match;
    247 	void *aux;
    248 {
    249 	struct tc_attach_args *ta = aux;
    250 
    251 	if (strncmp("PMAG-AA ", ta->ta_modname, TC_ROM_LLEN) != 0)
    252 		return (0);
    253 
    254 	return (1);
    255 }
    256 
    257 void
    258 mfb_getdevconfig(dense_addr, dc)
    259 	tc_addr_t dense_addr;
    260 	struct fb_devconfig *dc;
    261 {
    262 	struct raster *rap;
    263 	struct rcons *rcp;
    264 	int i;
    265 
    266 	dc->dc_vaddr = dense_addr;
    267 	dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr + MFB_FB_OFFSET);
    268 
    269 	dc->dc_wid = 1280;
    270 	dc->dc_ht = 1024;
    271 	dc->dc_depth = 1;
    272 	dc->dc_rowbytes = 2048 / 8;
    273 	dc->dc_videobase = dc->dc_vaddr + MFB_FB_OFFSET;
    274 	dc->dc_blanked = 0;
    275 
    276 	/* initialize colormap and cursor resource */
    277 	mfbinit(dc);
    278 
    279 	/* clear the screen */
    280 	for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
    281 		*(u_int32_t *)(dc->dc_videobase + i) = 0;
    282 
    283 	/* initialize the raster */
    284 	rap = &dc->dc_raster;
    285 	rap->width = dc->dc_wid;
    286 	rap->height = dc->dc_ht;
    287 	rap->depth = dc->dc_depth;
    288 	rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
    289 	rap->pixels = (u_int32_t *)dc->dc_videobase;
    290 
    291 	/* initialize the raster console blitter */
    292 	rcp = &dc->dc_rcons;
    293 	rcp->rc_sp = rap;
    294 	rcp->rc_crow = rcp->rc_ccol = -1;
    295 	rcp->rc_crowp = &rcp->rc_crow;
    296 	rcp->rc_ccolp = &rcp->rc_ccol;
    297 	rcons_init(rcp, 34, 80);
    298 
    299 	mfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
    300 	mfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
    301 }
    302 
    303 void
    304 mfbattach(parent, self, aux)
    305 	struct device *parent, *self;
    306 	void *aux;
    307 {
    308 	struct mfb_softc *sc = (struct mfb_softc *)self;
    309 	struct tc_attach_args *ta = aux;
    310 	struct wsemuldisplaydev_attach_args waa;
    311 	caddr_t mfbbase;
    312 	int console;
    313 	volatile register int junk;
    314 
    315 	console = (ta->ta_addr == mfb_consaddr);
    316 	if (console) {
    317 		sc->sc_dc = &mfb_console_dc;
    318 		sc->nscreens = 1;
    319 	}
    320 	else {
    321 		sc->sc_dc = (struct fb_devconfig *)
    322 		    malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
    323 		mfb_getdevconfig(ta->ta_addr, sc->sc_dc);
    324 	}
    325 	printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
    326 	    sc->sc_dc->dc_depth);
    327 
    328         tc_intr_establish(parent, ta->ta_cookie, TC_IPL_TTY, mfbintr, sc);
    329 
    330 	mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    331 	*(u_int8_t *)(mfbbase + MFB_IREQ_OFFSET) = 0;
    332 	junk = *(u_int8_t *)(mfbbase + MFB_IREQ_OFFSET);
    333 	*(u_int8_t *)(mfbbase + MFB_IREQ_OFFSET) = 1;
    334 
    335 	waa.console = console;
    336 	waa.scrdata = &mfb_screenlist;
    337 	waa.accessops = &mfb_accessops;
    338 	waa.accesscookie = sc;
    339 
    340 	config_found(self, &waa, wsemuldisplaydevprint);
    341 }
    342 
    343 int
    344 mfbioctl(v, cmd, data, flag, p)
    345 	void *v;
    346 	u_long cmd;
    347 	caddr_t data;
    348 	int flag;
    349 	struct proc *p;
    350 {
    351 	struct mfb_softc *sc = v;
    352 	struct fb_devconfig *dc = sc->sc_dc;
    353 	int turnoff;
    354 
    355 	switch (cmd) {
    356 	case WSDISPLAYIO_GTYPE:
    357 		*(u_int *)data = WSDISPLAY_TYPE_MFB;
    358 		return (0);
    359 
    360 	case WSDISPLAYIO_GINFO:
    361 #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    362 		wsd_fbip->height = sc->sc_dc->dc_ht;
    363 		wsd_fbip->width = sc->sc_dc->dc_wid;
    364 		wsd_fbip->depth = sc->sc_dc->dc_depth;
    365 		wsd_fbip->cmsize = 0;
    366 #undef fbt
    367 		return (0);
    368 
    369 	case WSDISPLAYIO_GETCMAP:
    370 	case WSDISPLAYIO_PUTCMAP:
    371 		return (ENOTTY);
    372 
    373 	case WSDISPLAYIO_SVIDEO:
    374 		turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
    375 		if ((dc->dc_blanked == 0) ^ turnoff) {
    376 			/* sc->sc_changed |= DATA_ALL_CHANGED; */
    377 			dc->dc_blanked = turnoff;
    378 		}
    379 		return (0);
    380 
    381 	case WSDISPLAYIO_GVIDEO:
    382 		*(u_int *)data = dc->dc_blanked ?
    383 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
    384 		return (0);
    385 
    386 	case WSDISPLAYIO_GCURPOS:
    387 		*(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
    388 		return (0);
    389 
    390 	case WSDISPLAYIO_SCURPOS:
    391 		set_curpos(sc, (struct wsdisplay_curpos *)data);
    392 		bt431_set_curpos(sc);
    393 		return (0);
    394 
    395 	case WSDISPLAYIO_GCURMAX:
    396 		((struct wsdisplay_curpos *)data)->x =
    397 		((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
    398 		return (0);
    399 
    400 	case WSDISPLAYIO_GCURSOR:
    401 		return get_cursor(sc, (struct wsdisplay_cursor *)data);
    402 
    403 	case WSDISPLAYIO_SCURSOR:
    404 		return set_cursor(sc, (struct wsdisplay_cursor *)data);
    405 	}
    406 	return ENOTTY;
    407 }
    408 
    409 int
    410 mfbmmap(v, offset, prot)
    411 	void *v;
    412 	off_t offset;
    413 	int prot;
    414 {
    415 	struct mfb_softc *sc = v;
    416 
    417 	if (offset > MFB_FB_SIZE)
    418 		return (-1);
    419 	return machine_btop(sc->sc_dc->dc_paddr + offset);
    420 }
    421 
    422 int
    423 mfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
    424 	void *v;
    425 	const struct wsscreen_descr *type;
    426 	void **cookiep;
    427 	int *curxp, *curyp;
    428 	long *attrp;
    429 {
    430 	struct mfb_softc *sc = v;
    431 	long defattr;
    432 
    433 	if (sc->nscreens > 0)
    434 		return (ENOMEM);
    435 
    436 	*cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
    437 	*curxp = 0;
    438 	*curyp = 0;
    439 	rcons_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
    440 	*attrp = defattr;
    441 	sc->nscreens++;
    442 	return (0);
    443 }
    444 
    445 void
    446 mfb_free_screen(v, cookie)
    447 	void *v;
    448 	void *cookie;
    449 {
    450 	struct mfb_softc *sc = v;
    451 
    452 	if (sc->sc_dc == &mfb_console_dc)
    453 		panic("mfb_free_screen: console");
    454 
    455 	sc->nscreens--;
    456 }
    457 
    458 void
    459 mfb_show_screen(v, cookie)
    460 	void *v;
    461 	void *cookie;
    462 {
    463 }
    464 
    465 int
    466 mfb_load_font(v, cookie, first, num, stride, data)
    467 	void *v;
    468 	void *cookie;
    469 	int first, num, stride;
    470 	void *data;
    471 {
    472 	return (EINVAL);
    473 }
    474 
    475 int
    476 mfb_cnattach(addr)
    477         tc_addr_t addr;
    478 {
    479         struct fb_devconfig *dcp = &mfb_console_dc;
    480         long defattr;
    481 
    482         mfb_getdevconfig(addr, dcp);
    483 
    484         rcons_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
    485 
    486         wsdisplay_cnattach(&mfb_stdscreen, &dcp->dc_rcons,
    487                            0, 0, defattr);
    488         mfb_consaddr = addr;
    489         return(0);
    490 }
    491 
    492 
    493 int
    494 mfbintr(arg)
    495 	void *arg;
    496 {
    497 	struct mfb_softc *sc = arg;
    498 	caddr_t mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    499 	struct bt455reg *vdac;
    500 	struct bt431reg *curs;
    501 	int v;
    502 	volatile register int junk;
    503 
    504 	junk = *(u_int8_t *)(mfbbase + MFB_IREQ_OFFSET);
    505 	/* *(u_int8_t *)(mfbbase + MFB_IREQ_OFFSET) = 1; */
    506 
    507 	if (sc->sc_changed == 0)
    508 		return (1);
    509 
    510 	vdac = (void *)(mfbbase + MFB_BT455_OFFSET);
    511 	curs = (void *)(mfbbase + MFB_BT431_OFFSET);
    512 
    513 	v = sc->sc_changed;
    514 	sc->sc_changed = 0;
    515 	if (v & DATA_ENB_CHANGED) {
    516 		BT431_SELECT(curs, BT431_REG_COMMAND);
    517 		curs->bt_ctl = (sc->sc_curenb) ? 0x4444 : 0x0404;
    518 	}
    519 	if (v & DATA_CURSHAPE_CHANGED) {
    520 		u_int8_t *bp1, *bp2;
    521 		u_int16_t twin;
    522 		int index;
    523 
    524 		bp1 = (u_int8_t *)&sc->sc_cursor.cc_image;
    525 		bp2 = (u_int8_t *)(&sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
    526 
    527 		BT431_SELECT(curs, BT431_REG_CRAM_BASE+0);
    528 		for (index = 0;
    529 		    index < sizeof(sc->sc_cursor.cc_image)/sizeof(u_int16_t);
    530 		    index++) {
    531 			twin = *bp1++ | (*bp2++ << 8);
    532 			curs->bt_ram = twin;
    533 			tc_wmb();
    534 		}
    535 	}
    536 	return (1);
    537 }
    538 
    539 void
    540 mfbinit(dc)
    541 	struct fb_devconfig *dc;
    542 {
    543 	caddr_t mfbbase = (caddr_t)dc->dc_vaddr;
    544 	struct bt431reg *curs = (void *)(mfbbase + MFB_BT431_OFFSET);
    545 	struct bt455reg *vdac = (void *)(mfbbase + MFB_BT455_OFFSET);
    546 	int i;
    547 
    548 	BT455_SELECT(vdac, 0);
    549 	vdac->bt_cmap = 0;	tc_wmb();
    550 	vdac->bt_cmap = 0;	tc_wmb();
    551 	vdac->bt_cmap = 0;	tc_wmb();
    552 
    553 	vdac->bt_cmap = 0;	tc_wmb();
    554 	vdac->bt_cmap = 0xff;	tc_wmb();
    555 	vdac->bt_cmap = 0;	tc_wmb();
    556 
    557 	for (i = 2; i < 16; i++) {
    558 		vdac->bt_cmap = 0;	tc_wmb();
    559 		vdac->bt_cmap = 0;	tc_wmb();
    560 		vdac->bt_cmap = 0;	tc_wmb();
    561 	}
    562 
    563 	BT455_SELECT(vdac, 8);
    564 	vdac->bt_cmap = 0;	tc_wmb();
    565 	vdac->bt_cmap = 0;	tc_wmb();
    566 	vdac->bt_cmap = 0;	tc_wmb();
    567 
    568 	vdac->bt_cmap = 0;	tc_wmb();
    569 	vdac->bt_cmap = 0;	tc_wmb();
    570 	vdac->bt_cmap = 0;	tc_wmb();
    571 
    572 	vdac->bt_ovly = 0;	tc_wmb();
    573 	vdac->bt_ovly = 0xff;	tc_wmb();
    574 	vdac->bt_ovly = 0;	tc_wmb();
    575 
    576 	BT431_SELECT(curs, BT431_REG_COMMAND);
    577 	curs->bt_ctl = 0x0404;	tc_wmb();
    578 	curs->bt_ctl = 0;	tc_wmb();
    579 	curs->bt_ctl = 0;	tc_wmb();
    580 	curs->bt_ctl = 0;	tc_wmb();
    581 	curs->bt_ctl = 0;	tc_wmb();
    582 	curs->bt_ctl = 0;	tc_wmb();
    583 	curs->bt_ctl = 0;	tc_wmb();
    584 	curs->bt_ctl = 0;	tc_wmb();
    585 	curs->bt_ctl = 0;	tc_wmb();
    586 	curs->bt_ctl = 0;	tc_wmb();
    587 	curs->bt_ctl = 0;	tc_wmb();
    588 	curs->bt_ctl = 0;	tc_wmb();
    589 	curs->bt_ctl = 0;	tc_wmb();
    590 }
    591 
    592 static int
    593 set_cursor(sc, p)
    594 	struct mfb_softc *sc;
    595 	struct wsdisplay_cursor *p;
    596 {
    597 #define	cc (&sc->sc_cursor)
    598 	int v, count;
    599 
    600 	v = p->which;
    601 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    602 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    603 			return (EINVAL);
    604 		count = (CURSOR_MAX_SIZE / NBBY) * p->size.y;
    605 		if (!useracc(p->image, count, B_READ) ||
    606 		    !useracc(p->mask, count, B_READ))
    607 			return (EFAULT);
    608 	}
    609 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
    610 		if (v & WSDISPLAY_CURSOR_DOCUR)
    611 			cc->cc_hot = p->hot;
    612 		if (v & WSDISPLAY_CURSOR_DOPOS)
    613 			set_curpos(sc, &p->pos);
    614 		bt431_set_curpos(sc);
    615 	}
    616 
    617 	sc->sc_changed = 0;
    618 	if (v & WSDISPLAY_CURSOR_DOCUR) {
    619 		sc->sc_curenb = p->enable;
    620 		sc->sc_changed |= DATA_ENB_CHANGED;
    621 	}
    622 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    623 		cc->cc_size = p->size;
    624 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    625 		copyin(p->image, (caddr_t)cc->cc_image, count);
    626 		copyin(p->mask, (caddr_t)(cc->cc_image+CURSOR_MAX_SIZE), count);
    627 		sc->sc_changed |= DATA_CURSHAPE_CHANGED;
    628 	}
    629 
    630 	return (0);
    631 #undef cc
    632 }
    633 
    634 static int
    635 get_cursor(sc, p)
    636 	struct mfb_softc *sc;
    637 	struct wsdisplay_cursor *p;
    638 {
    639 	return (ENOTTY); /* XXX */
    640 }
    641 
    642 static void
    643 set_curpos(sc, curpos)
    644 	struct mfb_softc *sc;
    645 	struct wsdisplay_curpos *curpos;
    646 {
    647 	struct fb_devconfig *dc = sc->sc_dc;
    648 	int x = curpos->x, y = curpos->y;
    649 
    650 	if (y < 0)
    651 		y = 0;
    652 	else if (y > dc->dc_ht - sc->sc_cursor.cc_size.y - 1)
    653 		y = dc->dc_ht - sc->sc_cursor.cc_size.y - 1;
    654 	if (x < 0)
    655 		x = 0;
    656 	else if (x > dc->dc_wid - sc->sc_cursor.cc_size.x - 1)
    657 		x = dc->dc_wid - sc->sc_cursor.cc_size.x - 1;
    658 	sc->sc_cursor.cc_pos.x = x;
    659 	sc->sc_cursor.cc_pos.y = y;
    660 }
    661 
    662 void
    663 bt431_set_curpos(sc)
    664 	struct mfb_softc *sc;
    665 {
    666 	caddr_t mfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    667 	struct bt431reg *curs = (void *)(mfbbase + MFB_BT431_OFFSET);
    668 	int x = 360, y = 36; /* magic offset of MX coordinate */
    669 	u_int16_t twin;
    670 	int s;
    671 
    672 	x += sc->sc_cursor.cc_pos.x;
    673 	y += sc->sc_cursor.cc_pos.y;
    674 
    675 #if 0 /* MACH legend tells */
    676 	/*
    677 	 * Cx = x + D + H - P
    678 	 *  P = 37 if 1:1, 52 if 4:1, 57 if 5:1
    679 	 *  D = pixel skew between outdata and external data
    680 	 *  H = pixels between HSYNCH falling and active video
    681 	 *
    682 	 * Cy = y + V - 32
    683 	 *  V = scanlines between HSYNCH falling, two or more
    684 	 *	clocks after VSYNCH falling, and active video
    685 	 */
    686 #endif
    687 	s = spltty();
    688 
    689 	BT431_SELECT(curs, BT431_REG_CURSOR_X_LOW);
    690 	curs->bt_ctl = TWIN_LO(x);
    691 	curs->bt_ctl = TWIN_HI(x);
    692 	curs->bt_ctl = TWIN_LO(y);
    693 	curs->bt_ctl = TWIN_HI(y);
    694 
    695 	splx(s);
    696 }
    697