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