Home | History | Annotate | Line # | Download | only in tc
sfb.c revision 1.8
      1 /* $NetBSD: sfb.c,v 1.8 1999/01/15 23:31:25 thorpej 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: sfb.c,v 1.8 1999/01/15 23:31:25 thorpej 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/bt459reg.h>
     57 #include <dev/tc/sfbreg.h>
     58 
     59 #include "opt_uvm.h"
     60 #if defined(UVM)
     61 #include <uvm/uvm_extern.h>
     62 #define useracc uvm_useracc
     63 #endif
     64 
     65 /* XXX BUS'IFYING XXX */
     66 
     67 #if defined(pmax)
     68 #define	machine_btop(x) mips_btop(x)
     69 #define	MACHINE_KSEG0_TO_PHYS(x) MIPS_KSEG1_TO_PHYS(x)
     70 #endif
     71 
     72 #if defined(__alpha__) || defined(alpha)
     73 #define machine_btop(x) alpha_btop(x)
     74 #define MACHINE_KSEG0_TO_PHYS(x) ALPHA_K0SEG_TO_PHYS(x)
     75 #endif
     76 
     77 /*
     78  * N.B., Bt459 registers are 8bit width.  Some of TC framebuffers have
     79  * obscure register layout such as 2nd and 3rd Bt459 registers are
     80  * adjacent each other in a word, i.e.,
     81  *	struct bt459triplet {
     82  * 		struct {
     83  *			u_int8_t u0;
     84  *			u_int8_t u1;
     85  *			u_int8_t u2;
     86  *			unsigned :8;
     87  *		} bt_lo;
     88  *		...
     89  * Although HX has single Bt459, 32bit R/W can be done w/o any trouble.
     90  */
     91 struct bt459reg {
     92         u_int32_t       bt_lo;
     93         u_int32_t       bt_hi;
     94         u_int32_t       bt_reg;
     95         u_int32_t       bt_cmap;
     96 };
     97 
     98 /* XXX XXX XXX */
     99 
    100 struct fb_devconfig {
    101 	vaddr_t dc_vaddr;		/* memory space virtual base address */
    102 	paddr_t dc_paddr;		/* memory space physical base address */
    103 	vsize_t dc_size;		/* size of slot memory */
    104 	int	dc_wid;			/* width of frame buffer */
    105 	int	dc_ht;			/* height of frame buffer */
    106 	int	dc_depth;		/* depth, bits per pixel */
    107 	int	dc_rowbytes;		/* bytes in a FB scan line */
    108 	vaddr_t	dc_videobase;		/* base of flat frame buffer */
    109 	struct raster	dc_raster;	/* raster description */
    110 	struct rcons	dc_rcons;	/* raster blitter control info */
    111 	int	    dc_blanked;		/* currently has video disabled */
    112 };
    113 
    114 struct hwcmap {
    115 #define	CMAP_SIZE	256	/* 256 R/G/B entries */
    116 	u_int8_t r[CMAP_SIZE];
    117 	u_int8_t g[CMAP_SIZE];
    118 	u_int8_t b[CMAP_SIZE];
    119 };
    120 
    121 struct hwcursor {
    122 	struct wsdisplay_curpos cc_pos;
    123 	struct wsdisplay_curpos cc_hot;
    124 	struct wsdisplay_curpos cc_size;
    125 #define	CURSOR_MAX_SIZE	64
    126 	u_int8_t cc_color[6];
    127 	u_int64_t cc_image[64 + 64];
    128 };
    129 
    130 struct sfb_softc {
    131 	struct device sc_dev;
    132 	struct fb_devconfig *sc_dc;	/* device configuration */
    133 	struct hwcmap sc_cmap;		/* software copy of colormap */
    134 	struct hwcursor sc_cursor;	/* software copy of cursor */
    135 	int sc_curenb;			/* cursor sprite enabled */
    136 	int sc_changed;			/* need update of colormap */
    137 #define	DATA_ENB_CHANGED	0x01	/* cursor enable changed */
    138 #define	DATA_CURCMAP_CHANGED	0x02	/* cursor colormap changed */
    139 #define	DATA_CURSHAPE_CHANGED	0x04	/* cursor size, image, mask changed */
    140 #define	DATA_CMAP_CHANGED	0x08	/* colormap changed */
    141 #define	DATA_ALL_CHANGED	0x0f
    142 	int nscreens;
    143 	short magic_x, magic_y;		/* HX cursor location offset */
    144 #define	HX_MAGIC_X 368
    145 #define	HX_MAGIC_Y 38
    146 };
    147 
    148 int  sfbmatch __P((struct device *, struct cfdata *, void *));
    149 void sfbattach __P((struct device *, struct device *, void *));
    150 
    151 struct cfattach sfb_ca = {
    152 	sizeof(struct sfb_softc), sfbmatch, sfbattach,
    153 };
    154 
    155 void sfb_getdevconfig __P((tc_addr_t, struct fb_devconfig *));
    156 struct fb_devconfig sfb_console_dc;
    157 tc_addr_t sfb_consaddr;
    158 
    159 struct wsdisplay_emulops sfb_emulops = {
    160 	rcons_cursor,			/* could use hardware cursor; punt */
    161 	rcons_mapchar,
    162 	rcons_putchar,
    163 	rcons_copycols,
    164 	rcons_erasecols,
    165 	rcons_copyrows,
    166 	rcons_eraserows,
    167 	rcons_alloc_attr
    168 };
    169 
    170 struct wsscreen_descr sfb_stdscreen = {
    171 	"std", 0, 0,
    172 	&sfb_emulops,
    173 	0, 0,
    174 	0
    175 };
    176 
    177 const struct wsscreen_descr *_sfb_scrlist[] = {
    178 	&sfb_stdscreen,
    179 };
    180 
    181 struct wsscreen_list sfb_screenlist = {
    182 	sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist
    183 };
    184 
    185 int	sfbioctl __P((void *, u_long, caddr_t, int, struct proc *));
    186 int	sfbmmap __P((void *, off_t, int));
    187 
    188 int	sfb_alloc_screen __P((void *, const struct wsscreen_descr *,
    189 				      void **, int *, int *, long *));
    190 void	sfb_free_screen __P((void *, void *));
    191 void	sfb_show_screen __P((void *, void *));
    192 
    193 struct wsdisplay_accessops sfb_accessops = {
    194 	sfbioctl,
    195 	sfbmmap,
    196 	sfb_alloc_screen,
    197 	sfb_free_screen,
    198 	sfb_show_screen,
    199 	0 /* load_font */
    200 };
    201 
    202 int  sfb_cnattach __P((tc_addr_t));
    203 int  sfbintr __P((void *));
    204 void sfbinit __P((struct fb_devconfig *));
    205 
    206 static int  get_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *));
    207 static int  set_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *));
    208 static int  set_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *));
    209 static int  get_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *));
    210 static void set_curpos __P((struct sfb_softc *, struct wsdisplay_curpos *));
    211 static void bt459_set_curpos __P((struct sfb_softc *));
    212 
    213 /* XXX XXX XXX */
    214 #define	BT459_SELECT(vdac, regno) do {		\
    215 	vdac->bt_lo = (regno) & 0x00ff;		\
    216 	vdac->bt_hi = ((regno)& 0x0f00) >> 8 ;	\
    217 	tc_wmb();				\
    218    } while (0)
    219 /* XXX XXX XXX */
    220 
    221 /*
    222  * Compose 2 bit/pixel cursor image.  Bit order will be reversed.
    223  *   M M M M I I I I		M I M I M I M I
    224  *	[ before ]		   [ after ]
    225  *   3 2 1 0 3 2 1 0		0 0 1 1 2 2 3 3
    226  *   7 6 5 4 7 6 5 4		4 4 5 5 6 6 7 7
    227  */
    228 const static u_int8_t shuffle[256] = {
    229 	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
    230 	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55,
    231 	0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4,
    232 	0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5,
    233 	0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74,
    234 	0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75,
    235 	0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4,
    236 	0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5,
    237 	0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c,
    238 	0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d,
    239 	0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc,
    240 	0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd,
    241 	0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c,
    242 	0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d,
    243 	0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc,
    244 	0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd,
    245 	0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56,
    246 	0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57,
    247 	0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6,
    248 	0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7,
    249 	0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76,
    250 	0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77,
    251 	0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6,
    252 	0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7,
    253 	0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e,
    254 	0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f,
    255 	0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde,
    256 	0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf,
    257 	0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e,
    258 	0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f,
    259 	0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe,
    260 	0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff,
    261 };
    262 
    263 int
    264 sfbmatch(parent, match, aux)
    265 	struct device *parent;
    266 	struct cfdata *match;
    267 	void *aux;
    268 {
    269 	struct tc_attach_args *ta = aux;
    270 
    271 	if (strncmp("PMAGB-BA", ta->ta_modname, TC_ROM_LLEN) != 0)
    272 		return (0);
    273 
    274 	return (1);
    275 }
    276 
    277 void
    278 sfb_getdevconfig(dense_addr, dc)
    279 	tc_addr_t dense_addr;
    280 	struct fb_devconfig *dc;
    281 {
    282 	struct raster *rap;
    283 	struct rcons *rcp;
    284 	caddr_t sfbasic;
    285 	int i, hsetup, vsetup, vbase;
    286 
    287 	dc->dc_vaddr = dense_addr;
    288 	dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr);
    289 
    290 	sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
    291 	hsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_HSETUP);
    292 	vsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VSETUP);
    293 	vbase  = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_BASE) & 0x1ff;
    294 
    295 	dc->dc_wid = (hsetup & 0x1ff) << 2;
    296 	dc->dc_ht = (vsetup & 0x7ff);
    297 	dc->dc_depth = 8;
    298 	dc->dc_rowbytes = dc->dc_wid * (dc->dc_depth / 8);
    299 	dc->dc_videobase = dc->dc_vaddr + SFB_FB_OFFSET + vbase * 4096;
    300 	dc->dc_blanked = 0;
    301 
    302 	/* initialize colormap and cursor resource */
    303 	sfbinit(dc);
    304 
    305 	/* clear the screen */
    306 	for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
    307 		*(u_int32_t *)(dc->dc_videobase + i) = 0x0;
    308 
    309 	/* initialize the raster */
    310 	rap = &dc->dc_raster;
    311 	rap->width = dc->dc_wid;
    312 	rap->height = dc->dc_ht;
    313 	rap->depth = dc->dc_depth;
    314 	rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
    315 	rap->pixels = (u_int32_t *)dc->dc_videobase;
    316 
    317 	/* initialize the raster console blitter */
    318 	rcp = &dc->dc_rcons;
    319 	rcp->rc_sp = rap;
    320 	rcp->rc_crow = rcp->rc_ccol = -1;
    321 	rcp->rc_crowp = &rcp->rc_crow;
    322 	rcp->rc_ccolp = &rcp->rc_ccol;
    323 	rcons_init(rcp, 34, 80);
    324 
    325 	sfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
    326 	sfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
    327 
    328 }
    329 
    330 void
    331 sfbattach(parent, self, aux)
    332 	struct device *parent, *self;
    333 	void *aux;
    334 {
    335 	struct sfb_softc *sc = (struct sfb_softc *)self;
    336 	struct tc_attach_args *ta = aux;
    337 	struct wsemuldisplaydev_attach_args waa;
    338 	struct hwcmap *cm;
    339 	caddr_t sfbasic;
    340 	int console, i;
    341 
    342 	console = (ta->ta_addr == sfb_consaddr);
    343 	if (console) {
    344 		sc->sc_dc = &sfb_console_dc;
    345 		sc->nscreens = 1;
    346 	}
    347 	else {
    348 		sc->sc_dc = (struct fb_devconfig *)
    349 		    malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
    350 		sfb_getdevconfig(ta->ta_addr, sc->sc_dc);
    351 	}
    352 	printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
    353 	    sc->sc_dc->dc_depth);
    354 
    355 	cm = &sc->sc_cmap;
    356 	cm->r[0] = cm->g[0] = cm->b[0] = 0;
    357 	for (i = 1; i < CMAP_SIZE; i++) {
    358 		cm->r[i] = cm->g[i] = cm->b[i] = 0xff;
    359 	}
    360 	sc->magic_x = HX_MAGIC_X; sc->magic_y = HX_MAGIC_Y;
    361 
    362         tc_intr_establish(parent, ta->ta_cookie, TC_IPL_TTY, sfbintr, sc);
    363 
    364 	sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET);
    365 	*(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
    366 	*(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1;
    367 
    368 	waa.console = console;
    369 	waa.scrdata = &sfb_screenlist;
    370 	waa.accessops = &sfb_accessops;
    371 	waa.accesscookie = sc;
    372 
    373 	config_found(self, &waa, wsemuldisplaydevprint);
    374 }
    375 
    376 int
    377 sfbioctl(v, cmd, data, flag, p)
    378 	void *v;
    379 	u_long cmd;
    380 	caddr_t data;
    381 	int flag;
    382 	struct proc *p;
    383 {
    384 	struct sfb_softc *sc = v;
    385 	struct fb_devconfig *dc = sc->sc_dc;
    386 	int turnoff;
    387 
    388 	switch (cmd) {
    389 	case WSDISPLAYIO_GTYPE:
    390 		*(u_int *)data = WSDISPLAY_TYPE_SFB;
    391 		return (0);
    392 
    393 	case WSDISPLAYIO_GINFO:
    394 #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    395 		wsd_fbip->height = sc->sc_dc->dc_ht;
    396 		wsd_fbip->width = sc->sc_dc->dc_wid;
    397 		wsd_fbip->depth = sc->sc_dc->dc_depth;
    398 		wsd_fbip->cmsize = CMAP_SIZE;
    399 #undef fbt
    400 		return (0);
    401 
    402 	case WSDISPLAYIO_GETCMAP:
    403 		return get_cmap(sc, (struct wsdisplay_cmap *)data);
    404 
    405 	case WSDISPLAYIO_PUTCMAP:
    406 		return set_cmap(sc, (struct wsdisplay_cmap *)data);
    407 
    408 	case WSDISPLAYIO_SVIDEO:
    409 		turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
    410 		if ((dc->dc_blanked == 0) ^ turnoff) {
    411 			dc->dc_blanked = turnoff;
    412 			/* XXX later XXX */
    413 		}
    414 		return (0);
    415 
    416 	case WSDISPLAYIO_GVIDEO:
    417 		*(u_int *)data = dc->dc_blanked ?
    418 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
    419 		return (0);
    420 
    421 	case WSDISPLAYIO_GCURPOS:
    422 		*(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
    423 		return (0);
    424 
    425 	case WSDISPLAYIO_SCURPOS:
    426 		set_curpos(sc, (struct wsdisplay_curpos *)data);
    427 		bt459_set_curpos(sc);
    428 		return (0);
    429 
    430 	case WSDISPLAYIO_GCURMAX:
    431 		((struct wsdisplay_curpos *)data)->x =
    432 		((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
    433 		return (0);
    434 
    435 	case WSDISPLAYIO_GCURSOR:
    436 		return get_cursor(sc, (struct wsdisplay_cursor *)data);
    437 
    438 	case WSDISPLAYIO_SCURSOR:
    439 		return set_cursor(sc, (struct wsdisplay_cursor *)data);
    440 	}
    441 	return ENOTTY;
    442 }
    443 
    444 int
    445 sfbmmap(v, offset, prot)
    446 	void *v;
    447 	off_t offset;
    448 	int prot;
    449 {
    450 	struct sfb_softc *sc = v;
    451 
    452 	if (offset >= 0x1000000 || offset < 0)
    453 		return (-1);
    454 	return machine_btop(sc->sc_dc->dc_paddr + offset);
    455 }
    456 
    457 int
    458 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
    459 	void *v;
    460 	const struct wsscreen_descr *type;
    461 	void **cookiep;
    462 	int *curxp, *curyp;
    463 	long *attrp;
    464 {
    465 	struct sfb_softc *sc = v;
    466 	long defattr;
    467 
    468 	if (sc->nscreens > 0)
    469 		return (ENOMEM);
    470 
    471 	*cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
    472 	*curxp = 0;
    473 	*curyp = 0;
    474 	rcons_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
    475 	*attrp = defattr;
    476 	sc->nscreens++;
    477 	return (0);
    478 }
    479 
    480 void
    481 sfb_free_screen(v, cookie)
    482 	void *v;
    483 	void *cookie;
    484 {
    485 	struct sfb_softc *sc = v;
    486 
    487 	if (sc->sc_dc == &sfb_console_dc)
    488 		panic("sfb_free_screen: console");
    489 
    490 	sc->nscreens--;
    491 }
    492 
    493 void
    494 sfb_show_screen(v, cookie)
    495 	void *v;
    496 	void *cookie;
    497 {
    498 }
    499 
    500 int
    501 sfb_cnattach(addr)
    502         tc_addr_t addr;
    503 {
    504         struct fb_devconfig *dcp = &sfb_console_dc;
    505         long defattr;
    506 
    507         sfb_getdevconfig(addr, dcp);
    508 
    509         rcons_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
    510 
    511         wsdisplay_cnattach(&sfb_stdscreen, &dcp->dc_rcons,
    512                            0, 0, defattr);
    513         sfb_consaddr = addr;
    514         return(0);
    515 }
    516 
    517 int
    518 sfbintr(arg)
    519 	void *arg;
    520 {
    521 	struct sfb_softc *sc = arg;
    522 	caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    523 	caddr_t sfbasic = sfbbase + SFB_ASIC_OFFSET;
    524 	struct bt459reg *vdac;
    525 	int v;
    526 
    527 	*(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
    528 	/* *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; */
    529 
    530 	if (sc->sc_changed == 0)
    531 		return (1);
    532 
    533 	vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
    534 	v = sc->sc_changed;
    535 	sc->sc_changed = 0;
    536 
    537 	if (v & DATA_ENB_CHANGED) {
    538 		BT459_SELECT(vdac, BT459_REG_CCR);
    539 		vdac->bt_reg = (sc->sc_curenb) ? 0xc0 : 0x00;
    540 	}
    541 	if (v & DATA_CURCMAP_CHANGED) {
    542 		u_int8_t *cp = sc->sc_cursor.cc_color;
    543 
    544 		BT459_SELECT(vdac, BT459_REG_CCOLOR_2);
    545 		vdac->bt_reg = cp[1];	tc_wmb();
    546 		vdac->bt_reg = cp[3];	tc_wmb();
    547 		vdac->bt_reg = cp[5];	tc_wmb();
    548 
    549 		vdac->bt_reg = cp[0];	tc_wmb();
    550 		vdac->bt_reg = cp[2];	tc_wmb();
    551 		vdac->bt_reg = cp[4];	tc_wmb();
    552 	}
    553 	if (v & DATA_CURSHAPE_CHANGED) {
    554 		u_int8_t *ip, *mp, img, msk;
    555 		u_int8_t u;
    556 		int bcnt;
    557 
    558 		ip = (u_int8_t *)sc->sc_cursor.cc_image;
    559 		mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
    560 
    561 		bcnt = 0;
    562 		BT459_SELECT(vdac, BT459_REG_CRAM_BASE+0);
    563 		/* 64 pixel scan line is consisted with 16 byte cursor ram */
    564 		while (bcnt < sc->sc_cursor.cc_size.y * 16) {
    565 			/* pad right half 32 pixel when smaller than 33 */
    566 			if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
    567 				vdac->bt_reg = 0; tc_wmb();
    568 				vdac->bt_reg = 0; tc_wmb();
    569 			}
    570 			else {
    571 				img = *ip++;
    572 				msk = *mp++;
    573 				img &= msk;	/* cookie off image */
    574 				u = (msk & 0x0f) << 4 | (img & 0x0f);
    575 				vdac->bt_reg = shuffle[u];	tc_wmb();
    576 				u = (msk & 0xf0) | (img & 0xf0) >> 4;
    577 				vdac->bt_reg = shuffle[u];	tc_wmb();
    578 			}
    579 			bcnt += 2;
    580 		}
    581 		/* pad unoccupied scan lines */
    582 		while (bcnt < CURSOR_MAX_SIZE * 16) {
    583 			vdac->bt_reg = 0; tc_wmb();
    584 			vdac->bt_reg = 0; tc_wmb();
    585 			bcnt += 2;
    586 		}
    587 	}
    588 	if (v & DATA_CMAP_CHANGED) {
    589 		struct hwcmap *cm = &sc->sc_cmap;
    590 		int index;
    591 
    592 		BT459_SELECT(vdac, 0);
    593 		for (index = 0; index < CMAP_SIZE; index++) {
    594 			vdac->bt_cmap = cm->r[index];	tc_wmb();
    595 			vdac->bt_cmap = cm->g[index];	tc_wmb();
    596 			vdac->bt_cmap = cm->b[index];	tc_wmb();
    597 		}
    598 	}
    599 	return (1);
    600 }
    601 
    602 void
    603 sfbinit(dc)
    604 	struct fb_devconfig *dc;
    605 {
    606 	caddr_t sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
    607 	struct bt459reg *vdac = (void *)(dc->dc_vaddr + SFB_RAMDAC_OFFSET);
    608 	int i;
    609 
    610 	*(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0;
    611 	*(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VALID) = 1;
    612 	*(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0;
    613 	*(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0;
    614 
    615 	*(u_int32_t *)(sfbasic + 0x180000) = 0; /* Bt459 reset */
    616 
    617 	BT459_SELECT(vdac, BT459_REG_COMMAND_0);
    618 	vdac->bt_reg = 0x40; /* CMD0 */	tc_wmb();
    619 	vdac->bt_reg = 0x0;  /* CMD1 */	tc_wmb();
    620 	vdac->bt_reg = 0xc0; /* CMD2 */	tc_wmb();
    621 	vdac->bt_reg = 0xff; /* PRM */	tc_wmb();
    622 	vdac->bt_reg = 0;    /* 205 */	tc_wmb();
    623 	vdac->bt_reg = 0x0;  /* PBM */	tc_wmb();
    624 	vdac->bt_reg = 0;    /* 207 */	tc_wmb();
    625 	vdac->bt_reg = 0x0;  /* ORM */	tc_wmb();
    626 	vdac->bt_reg = 0x0;  /* OBM */	tc_wmb();
    627 	vdac->bt_reg = 0x0;  /* ILV */	tc_wmb();
    628 	vdac->bt_reg = 0x0;  /* TEST */	tc_wmb();
    629 
    630 	BT459_SELECT(vdac, BT459_REG_CCR);
    631 	vdac->bt_reg = 0x0;	tc_wmb();
    632 	vdac->bt_reg = 0x0;	tc_wmb();
    633 	vdac->bt_reg = 0x0;	tc_wmb();
    634 	vdac->bt_reg = 0x0;	tc_wmb();
    635 	vdac->bt_reg = 0x0;	tc_wmb();
    636 	vdac->bt_reg = 0x0;	tc_wmb();
    637 	vdac->bt_reg = 0x0;	tc_wmb();
    638 	vdac->bt_reg = 0x0;	tc_wmb();
    639 	vdac->bt_reg = 0x0;	tc_wmb();
    640 	vdac->bt_reg = 0x0;	tc_wmb();
    641 	vdac->bt_reg = 0x0;	tc_wmb();
    642 	vdac->bt_reg = 0x0;	tc_wmb();
    643 	vdac->bt_reg = 0x0;	tc_wmb();
    644 
    645 	/* build sane colormap */
    646 	BT459_SELECT(vdac, 0);
    647 	vdac->bt_cmap = 0;	tc_wmb();
    648 	vdac->bt_cmap = 0;	tc_wmb();
    649 	vdac->bt_cmap = 0;	tc_wmb();
    650 	for (i = 1; i < CMAP_SIZE; i++) {
    651 		vdac->bt_cmap = 0xff;	tc_wmb();
    652 		vdac->bt_cmap = 0xff;	tc_wmb();
    653 		vdac->bt_cmap = 0xff;	tc_wmb();
    654 	}
    655 
    656 	/* clear out cursor image */
    657 	BT459_SELECT(vdac, BT459_REG_CRAM_BASE);
    658 	for (i = 0; i < 1024; i++)
    659 		vdac->bt_reg = 0xff;	tc_wmb();
    660 
    661 	/*
    662 	 * 2 bit/pixel cursor.  Assign MSB for cursor mask and LSB for
    663 	 * cursor image.  CCOLOR_2 for mask color, while CCOLOR_3 for
    664 	 * image color.  CCOLOR_1 will be never used.
    665 	 */
    666 	BT459_SELECT(vdac, BT459_REG_CCOLOR_1);
    667 	vdac->bt_reg = 0xff;	tc_wmb();
    668 	vdac->bt_reg = 0xff;	tc_wmb();
    669 	vdac->bt_reg = 0xff;	tc_wmb();
    670 
    671 	vdac->bt_reg = 0;	tc_wmb();
    672 	vdac->bt_reg = 0;	tc_wmb();
    673 	vdac->bt_reg = 0;	tc_wmb();
    674 
    675 	vdac->bt_reg = 0xff;	tc_wmb();
    676 	vdac->bt_reg = 0xff;	tc_wmb();
    677 	vdac->bt_reg = 0xff;	tc_wmb();
    678 }
    679 
    680 static int
    681 get_cmap(sc, p)
    682 	struct sfb_softc *sc;
    683 	struct wsdisplay_cmap *p;
    684 {
    685 	u_int index = p->index, count = p->count;
    686 
    687 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    688 		return (EINVAL);
    689 
    690 	if (!useracc(p->red, count, B_WRITE) ||
    691 	    !useracc(p->green, count, B_WRITE) ||
    692 	    !useracc(p->blue, count, B_WRITE))
    693 		return (EFAULT);
    694 
    695 	copyout(&sc->sc_cmap.r[index], p->red, count);
    696 	copyout(&sc->sc_cmap.g[index], p->green, count);
    697 	copyout(&sc->sc_cmap.b[index], p->blue, count);
    698 
    699 	return (0);
    700 }
    701 
    702 static int
    703 set_cmap(sc, p)
    704 	struct sfb_softc *sc;
    705 	struct wsdisplay_cmap *p;
    706 {
    707 	u_int index = p->index, count = p->count;
    708 
    709 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    710 		return (EINVAL);
    711 
    712 	if (!useracc(p->red, count, B_READ) ||
    713 	    !useracc(p->green, count, B_READ) ||
    714 	    !useracc(p->blue, count, B_READ))
    715 		return (EFAULT);
    716 
    717 	copyin(p->red, &sc->sc_cmap.r[index], count);
    718 	copyin(p->green, &sc->sc_cmap.g[index], count);
    719 	copyin(p->blue, &sc->sc_cmap.b[index], count);
    720 
    721 	sc->sc_changed |= DATA_CMAP_CHANGED;
    722 
    723 	return (0);
    724 }
    725 
    726 
    727 static int
    728 set_cursor(sc, p)
    729 	struct sfb_softc *sc;
    730 	struct wsdisplay_cursor *p;
    731 {
    732 #define	cc (&sc->sc_cursor)
    733 	int v, index, count, icount;
    734 
    735 	v = p->which;
    736 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    737 		index = p->cmap.index;
    738 		count = p->cmap.count;
    739 		if (index >= 2 || (index + count) > 2)
    740 			return (EINVAL);
    741 		if (!useracc(p->cmap.red, count, B_READ) ||
    742 		    !useracc(p->cmap.green, count, B_READ) ||
    743 		    !useracc(p->cmap.blue, count, B_READ))
    744 			return (EFAULT);
    745 	}
    746 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    747 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    748 			return (EINVAL);
    749 		icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
    750 		if (!useracc(p->image, count, B_READ) ||
    751 		    !useracc(p->mask, count, B_READ))
    752 			return (EFAULT);
    753 	}
    754 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
    755 		if (v & WSDISPLAY_CURSOR_DOCUR)
    756 			cc->cc_hot = p->hot;
    757 		if (v & WSDISPLAY_CURSOR_DOPOS)
    758 			set_curpos(sc, &p->pos);
    759 		bt459_set_curpos(sc);
    760 	}
    761 
    762 	sc->sc_changed = 0;
    763 	if (v & WSDISPLAY_CURSOR_DOCUR) {
    764 		sc->sc_curenb = p->enable;
    765 		sc->sc_changed |= DATA_ENB_CHANGED;
    766 	}
    767 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    768 		copyin(p->cmap.red, &cc->cc_color[index], count);
    769 		copyin(p->cmap.green, &cc->cc_color[index + 2], count);
    770 		copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
    771 		sc->sc_changed |= DATA_CURCMAP_CHANGED;
    772 	}
    773 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    774 		cc->cc_size = p->size;
    775 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    776 		copyin(p->image, cc->cc_image, icount);
    777 		copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
    778 		sc->sc_changed |= DATA_CURSHAPE_CHANGED;
    779 	}
    780 
    781 	return (0);
    782 #undef cc
    783 }
    784 
    785 static int
    786 get_cursor(sc, p)
    787 	struct sfb_softc *sc;
    788 	struct wsdisplay_cursor *p;
    789 {
    790 	return (ENOTTY); /* XXX */
    791 }
    792 
    793 static void
    794 set_curpos(sc, curpos)
    795 	struct sfb_softc *sc;
    796 	struct wsdisplay_curpos *curpos;
    797 {
    798 	struct fb_devconfig *dc = sc->sc_dc;
    799 	int x = curpos->x, y = curpos->y;
    800 
    801 	if (y < 0)
    802 		y = 0;
    803 	else if (y > dc->dc_ht)
    804 		y = dc->dc_ht;
    805 	if (x < 0)
    806 		x = 0;
    807 	else if (x > dc->dc_wid)
    808 		x = dc->dc_wid;
    809 	sc->sc_cursor.cc_pos.x = x;
    810 	sc->sc_cursor.cc_pos.y = y;
    811 }
    812 
    813 static void
    814 bt459_set_curpos(sc)
    815 	struct sfb_softc *sc;
    816 {
    817 	caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    818 	struct bt459reg *vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
    819 	int x, y, s;
    820 
    821 	x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
    822 	y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
    823 	x += sc->magic_x; y += sc->magic_y; /* magic offset of HX coordinate */
    824 
    825 	s = spltty();
    826 
    827 	BT459_SELECT(vdac, BT459_REG_CURSOR_X_LOW);
    828 	vdac->bt_reg = x;	tc_wmb();
    829 	vdac->bt_reg = x >> 8;	tc_wmb();
    830 	vdac->bt_reg = y;	tc_wmb();
    831 	vdac->bt_reg = y >> 8;	tc_wmb();
    832 
    833 	splx(s);
    834 }
    835