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