Home | History | Annotate | Line # | Download | only in dev
      1 /*	$NetBSD: topcat.c,v 1.15 2025/05/27 18:44:31 tsutsui Exp $	*/
      2 /*	$OpenBSD: topcat.c,v 1.15 2006/08/11 18:33:13 miod Exp $	*/
      3 
      4 /*
      5  * Copyright (c) 2005, Miodrag Vallat.
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     21  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     25  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     27  * POSSIBILITY OF SUCH DAMAGE.
     28  *
     29  */
     30 /*-
     31  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
     32  * All rights reserved.
     33  *
     34  * This code is derived from software contributed to The NetBSD Foundation
     35  * by Jason R. Thorpe.
     36  *
     37  * Redistribution and use in source and binary forms, with or without
     38  * modification, are permitted provided that the following conditions
     39  * are met:
     40  * 1. Redistributions of source code must retain the above copyright
     41  *    notice, this list of conditions and the following disclaimer.
     42  * 2. Redistributions in binary form must reproduce the above copyright
     43  *    notice, this list of conditions and the following disclaimer in the
     44  *    documentation and/or other materials provided with the distribution.
     45  *
     46  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     47  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     48  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     49  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     50  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     51  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     52  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     53  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     54  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     55  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     56  * POSSIBILITY OF SUCH DAMAGE.
     57  */
     58 
     59 /*
     60  * Copyright (c) 1988 University of Utah.
     61  * Copyright (c) 1990, 1993
     62  *	The Regents of the University of California.  All rights reserved.
     63  *
     64  * This code is derived from software contributed to Berkeley by
     65  * the Systems Programming Group of the University of Utah Computer
     66  * Science Department.
     67  *
     68  * Redistribution and use in source and binary forms, with or without
     69  * modification, are permitted provided that the following conditions
     70  * are met:
     71  * 1. Redistributions of source code must retain the above copyright
     72  *    notice, this list of conditions and the following disclaimer.
     73  * 2. Redistributions in binary form must reproduce the above copyright
     74  *    notice, this list of conditions and the following disclaimer in the
     75  *    documentation and/or other materials provided with the distribution.
     76  * 3. Neither the name of the University nor the names of its contributors
     77  *    may be used to endorse or promote products derived from this software
     78  *    without specific prior written permission.
     79  *
     80  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     81  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     82  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     83  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     84  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     85  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     86  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     87  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     88  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     89  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     90  * SUCH DAMAGE.
     91  *
     92  * from: Utah $Hdr: grf_tc.c 1.20 93/08/13$
     93  *
     94  *	@(#)grf_tc.c	8.4 (Berkeley) 1/12/94
     95  */
     96 
     97 /*
     98  * Graphics routines for TOPCAT, CATSEYE and KATHMANDU frame buffers
     99  */
    100 
    101 #include <sys/param.h>
    102 #include <sys/systm.h>
    103 #include <sys/conf.h>
    104 #include <sys/device.h>
    105 #include <sys/proc.h>
    106 #include <sys/ioctl.h>
    107 #include <sys/bus.h>
    108 #include <sys/cpu.h>
    109 
    110 #include <machine/autoconf.h>
    111 
    112 #include <hp300/dev/dioreg.h>
    113 #include <hp300/dev/diovar.h>
    114 #include <hp300/dev/diodevs.h>
    115 #include <hp300/dev/intiovar.h>
    116 
    117 #include <dev/wscons/wsconsio.h>
    118 #include <dev/wscons/wsdisplayvar.h>
    119 #include <dev/rasops/rasops.h>
    120 
    121 #include <hp300/dev/diofbreg.h>
    122 #include <hp300/dev/diofbvar.h>
    123 #include <hp300/dev/topcatreg.h>
    124 
    125 struct	topcat_softc {
    126 	device_t	sc_dev;
    127 	struct diofb	*sc_fb;
    128 	struct diofb	sc_fb_store;
    129 	int		sc_scode;
    130 };
    131 
    132 static int	topcat_dio_match(device_t, cfdata_t, void *);
    133 static void	topcat_dio_attach(device_t, device_t, void *);
    134 static int	topcat_intio_match(device_t, cfdata_t, void *);
    135 static void	topcat_intio_attach(device_t, device_t, void *);
    136 
    137 CFATTACH_DECL_NEW(topcat_dio, sizeof(struct topcat_softc),
    138     topcat_dio_match, topcat_dio_attach, NULL, NULL);
    139 
    140 CFATTACH_DECL_NEW(topcat_intio, sizeof(struct topcat_softc),
    141     topcat_intio_match, topcat_intio_attach, NULL, NULL);
    142 
    143 static void	topcat_end_attach(struct topcat_softc *, uint8_t);
    144 static int	topcat_reset(struct diofb *, int, struct diofbreg *);
    145 static void	topcat_restore(struct diofb *);
    146 static int	topcat_setcmap(struct diofb *, struct wsdisplay_cmap *);
    147 static void	topcat_setcolor(struct diofb *, u_int);
    148 static int	topcat_windowmove(struct diofb *, uint16_t, uint16_t, uint16_t,
    149 		    uint16_t, uint16_t, uint16_t, int16_t, int16_t);
    150 
    151 static int	topcat_ioctl(void *, void *, u_long, void *, int, struct lwp *);
    152 static void	topcat_putchar8(void *, int, int, u_int, long);
    153 static void	topcat_putchar1_4(void *, int, int, u_int, long);
    154 
    155 static struct wsdisplay_accessops topcat_accessops = {
    156 	.ioctl        = topcat_ioctl,
    157 	.mmap         = diofb_mmap,
    158 	.alloc_screen = diofb_alloc_screen,
    159 	.free_screen  = diofb_free_screen,
    160 	.show_screen  = diofb_show_screen,
    161 	.load_font    = NULL,
    162 };
    163 
    164 /*
    165  * Attachment glue
    166  */
    167 
    168 int
    169 topcat_intio_match(device_t parent, cfdata_t cf, void *aux)
    170 {
    171 	struct intio_attach_args *ia = aux;
    172 	struct diofbreg *fbr;
    173 
    174 	if (strcmp("fb", ia->ia_modname) != 0)
    175 		return 0;
    176 
    177 	fbr = (struct diofbreg *)ia->ia_addr;
    178 
    179 	if (badaddr((void *)fbr))
    180 		return 0;
    181 
    182 	if (fbr->id == GRFHWID) {
    183 		switch (fbr->fbid) {
    184 		case GID_TOPCAT:
    185 		case GID_LRCATSEYE:
    186 		case GID_HRCCATSEYE:
    187 		case GID_HRMCATSEYE:
    188 #if 0
    189 		case GID_XXXCATSEYE:
    190 #endif
    191 			return 1;
    192 		}
    193 	}
    194 
    195 	return 0;
    196 }
    197 
    198 void
    199 topcat_intio_attach(device_t parent, device_t self, void *aux)
    200 {
    201 	struct topcat_softc *sc = device_private(self);
    202 	struct intio_attach_args *ia = aux;
    203 	struct diofbreg *fbr;
    204 
    205 	sc->sc_dev = self;
    206 	fbr = (struct diofbreg *)ia->ia_addr;
    207 	sc->sc_scode = CONSCODE_INTERNAL;
    208 
    209 	if (sc->sc_scode == conscode) {
    210 		sc->sc_fb = &diofb_cn;
    211 	} else {
    212 		sc->sc_fb = &sc->sc_fb_store;
    213 		topcat_reset(sc->sc_fb, sc->sc_scode, fbr);
    214 	}
    215 
    216 	topcat_end_attach(sc, fbr->fbid);
    217 }
    218 
    219 int
    220 topcat_dio_match(device_t parent, cfdata_t cf, void *aux)
    221 {
    222 	struct dio_attach_args *da = aux;
    223 
    224 	if (da->da_id == DIO_DEVICE_ID_FRAMEBUFFER) {
    225 		switch (da->da_secid) {
    226 		case DIO_DEVICE_SECID_TOPCAT:
    227 		case DIO_DEVICE_SECID_LRCATSEYE:
    228 		case DIO_DEVICE_SECID_HRCCATSEYE:
    229 		case DIO_DEVICE_SECID_HRMCATSEYE:
    230 #if 0
    231 		case DIO_DEVICE_SECID_XXXCATSEYE:
    232 #endif
    233 			return 1;
    234 		}
    235 	}
    236 
    237 	return 0;
    238 }
    239 
    240 void
    241 topcat_dio_attach(device_t parent, device_t self, void *aux)
    242 {
    243 	struct topcat_softc *sc = device_private(self);
    244 	struct dio_attach_args *da = aux;
    245 	bus_space_handle_t bsh;
    246 	struct diofbreg *fbr;
    247 
    248 	sc->sc_dev = self;
    249 	sc->sc_scode = da->da_scode;
    250 	if (sc->sc_scode == conscode) {
    251 		fbr = (struct diofbreg *)conaddr;	/* already mapped */
    252 		sc->sc_fb = &diofb_cn;
    253 	} else {
    254 		sc->sc_fb = &sc->sc_fb_store;
    255 		if (bus_space_map(da->da_bst, da->da_addr, da->da_size, 0,
    256 		    &bsh)) {
    257 			aprint_error(": can't map framebuffer\n");
    258 			return;
    259 		}
    260 		fbr = bus_space_vaddr(da->da_bst, bsh);
    261 		if (topcat_reset(sc->sc_fb, sc->sc_scode, fbr) != 0) {
    262 			aprint_error(": can't reset framebuffer\n");
    263 			return;
    264 		}
    265 	}
    266 
    267 	topcat_end_attach(sc, fbr->fbid);
    268 }
    269 
    270 void
    271 topcat_end_attach(struct topcat_softc *sc, uint8_t id)
    272 {
    273 	const char *fbname = "unknown";
    274 
    275 	switch (id) {
    276 	case GID_TOPCAT:
    277 		switch (sc->sc_fb->planes) {
    278 		case 1:
    279 			if (sc->sc_fb->dheight == 400)
    280 				fbname = "HP98542 topcat";
    281 			else
    282 				fbname = "HP98544 topcat";
    283 			break;
    284 		case 4:
    285 			if (sc->sc_fb->dheight == 400)
    286 				fbname = "HP98543 topcat";
    287 			else
    288 				fbname = "HP98545 topcat";
    289 			break;
    290 		case 6:
    291 			fbname = "HP98547 topcat";
    292 			break;
    293 		}
    294 		break;
    295 	case GID_HRCCATSEYE:
    296 		fbname = "HP98550 catseye";	/* also A1416 kathmandu */
    297 		break;
    298 	case GID_LRCATSEYE:
    299 		fbname = "HP98549 catseye";
    300 		break;
    301 	case GID_HRMCATSEYE:
    302 		fbname = "HP98548 catseye";
    303 		break;
    304 	}
    305 
    306 	diofb_end_attach(sc->sc_dev, &topcat_accessops, sc->sc_fb,
    307 	    sc->sc_scode == conscode, fbname);
    308 }
    309 
    310 /*
    311  * Initialize hardware and display routines.
    312  */
    313 int
    314 topcat_reset(struct diofb *fb, int scode, struct diofbreg *fbr)
    315 {
    316 	volatile struct tcboxfb *tc = (struct tcboxfb *)fbr;
    317 	struct rasops_info *ri = &fb->ri;
    318 	int rc;
    319 	u_int i;
    320 	bool sparse = false;
    321 
    322 	if ((rc = diofb_fbinquire(fb, scode, fbr)) != 0)
    323 		return rc;
    324 
    325 	/*
    326 	 * If we could not get a valid number of planes, determine it
    327 	 * by writing to the first frame buffer display location,
    328 	 * then reading it back.
    329 	 */
    330 	if (fb->planes == 0) {
    331 		volatile uint8_t *fbp;
    332 		uint8_t save;
    333 
    334 		fbp = (uint8_t *)fb->fbkva;
    335 		tc->fben = ~0;
    336 		tc->wen = ~0;
    337 		tc->ren = ~0;
    338 		tc->prr = RR_COPY;
    339 		save = *fbp;
    340 		*fbp = 0xff;
    341 		fb->planemask = *fbp;
    342 		*fbp = save;
    343 
    344 		for (fb->planes = 1; fb->planemask >= (1 << fb->planes);
    345 		    fb->planes++);
    346 		if (fb->planes > 8)
    347 			fb->planes = 8;
    348 		fb->planemask = (1 << fb->planes) - 1;
    349 	}
    350 
    351 	/*
    352 	 * Some displays, such as the HP332 and HP340 internal video
    353 	 * and HP98542/98543 appear to return a display width of 1024
    354 	 * instead of 512. It looks these boards have actually have
    355 	 * enough 64KB (1bpp) or 256KB (4bpp) VRAM and RAMDAC capabilities
    356 	 * to display 1024x400 pixels.
    357 	 *
    358 	 * However HP's official "Service Information Manual" for
    359 	 * "HP 900 Series 300 Computers Models 330/350" says:
    360 	 *  "The medium-resolution board uses eight memory chips per plane.
    361 	 *   This is enough to display 512 doubled pixels by 400 scan lines."
    362 	 *
    363 	 * This "512 doubled pixels" implies that the native HP-UX treated
    364 	 * these 1024x400 framebuffers as pseudo 512x400 ones because
    365 	 * ancient 1980s CRTs (such as 35741) didn't display such higher
    366 	 * resolution. Furthermore, even modern LCDs can only handle
    367 	 * upto 720 pixels in the "400 line" as VGA compatible mode.
    368 	 *
    369 	 * As mentioned above, we treat these 1024x400 1 bit or 4 bit
    370 	 * framebuffers as "2 bytes per pixel" ones, so we have to handle
    371 	 * 512 pixels per line with 1024 bytes per line.
    372 	 */
    373 	if (fb->planes <= 4 && fb->dwidth == 1024 && fb->dheight == 400) {
    374 		fb->dwidth = 512;
    375 		sparse = true;
    376 	}
    377 
    378 	fb->bmv = topcat_windowmove;
    379 	topcat_restore(fb);
    380 	diofb_fbsetup(fb);
    381 	if (!sparse) {
    382 		/* save original rasops putchar op */
    383 		fb->wsputchar = ri->ri_ops.putchar;
    384 		ri->ri_ops.putchar = topcat_putchar8;
    385 	} else {
    386 		ri->ri_ops.putchar = topcat_putchar1_4;
    387 		/* copycols and erasecols ops require byte size of fontwidth */
    388 		fb->wsd.fontwidth *= 2;
    389 		/* copyrows and eraserows ops require byte size per line */
    390 		ri->ri_emuwidth *= 2;
    391 	}
    392 	for (i = 0; i <= fb->planemask; i++)
    393 		topcat_setcolor(fb, i);
    394 
    395 	return 0;
    396 }
    397 
    398 void
    399 topcat_restore(struct diofb *fb)
    400 {
    401 	volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva;
    402 
    403 	/*
    404 	 * Catseye looks a lot like a topcat, but not completely.
    405 	 * So, we set some bits to make it work.
    406 	 */
    407 	if (tc->regs.fbid != GID_TOPCAT) {
    408 		while ((tc->catseye_status & 1))
    409 			;
    410 		tc->catseye_status = 0x0;
    411 		tc->vb_select = 0x0;
    412 		tc->tcntrl = 0x0;
    413 		tc->acntrl = 0x0;
    414 		tc->pncntrl = 0x0;
    415 		tc->rug_cmdstat = 0x90;
    416 	}
    417 
    418 	/*
    419 	 * Enable reading/writing of all the planes.
    420 	 */
    421 	tc->fben = fb->planemask;
    422 	tc->wen  = fb->planemask;
    423 	tc->ren  = fb->planemask;
    424 	tc->prr  = RR_COPY;
    425 
    426 	/* Enable display */
    427 	tc->nblank = fb->planemask;
    428 }
    429 
    430 int
    431 topcat_ioctl(void *v, void *vs, u_long cmd, void *data, int flags,
    432     struct lwp *l)
    433 {
    434 	struct diofb *fb = v;
    435 	struct wsdisplay_fbinfo *wdf;
    436 	u_int i;
    437 
    438 	switch (cmd) {
    439 	case WSDISPLAYIO_GTYPE:
    440 		*(u_int *)data = WSDISPLAY_TYPE_TOPCAT;
    441 		return 0;
    442 	case WSDISPLAYIO_SMODE:
    443 		fb->mapmode = *(u_int *)data;
    444 		if (fb->mapmode == WSDISPLAYIO_MODE_EMUL) {
    445 			topcat_restore(fb);
    446 			for (i = 0; i <= fb->planemask; i++)
    447 				topcat_setcolor(fb, i);
    448 		}
    449 		return 0;
    450 	case WSDISPLAYIO_GINFO:
    451 		wdf = (void *)data;
    452 		wdf->width = fb->ri.ri_width;
    453 		wdf->height = fb->ri.ri_height;
    454 		wdf->depth = fb->ri.ri_depth;
    455 		wdf->cmsize = 1 << fb->planes;
    456 		return 0;
    457 	case WSDISPLAYIO_LINEBYTES:
    458 		*(u_int *)data = fb->ri.ri_stride;
    459 		return 0;
    460 	case WSDISPLAYIO_GETCMAP:
    461 		if (fb->planemask == 1)
    462 			return EPASSTHROUGH;
    463 		return diofb_getcmap(fb, (struct wsdisplay_cmap *)data);
    464 	case WSDISPLAYIO_PUTCMAP:
    465 		if (fb->planemask == 1)
    466 			return EPASSTHROUGH;
    467 		return topcat_setcmap(fb, (struct wsdisplay_cmap *)data);
    468 	case WSDISPLAYIO_GVIDEO:
    469 	case WSDISPLAYIO_SVIDEO:
    470 		return EPASSTHROUGH;
    471 	}
    472 
    473 	return EPASSTHROUGH;
    474 }
    475 
    476 void
    477 topcat_setcolor(struct diofb *fb, u_int index)
    478 {
    479 	volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva;
    480 
    481 	/* No color map registers on monochrome framebuffers. */
    482 	if (fb->planemask == 1)
    483 		return;
    484 
    485 	tc_waitbusy(tc, fb->planemask);
    486 
    487 	if (tc->regs.fbid != GID_TOPCAT) {
    488 		tccm_waitbusy(tc);
    489 		tc->plane_mask = fb->planemask;
    490 		tc->cindex = ~index;
    491 		tc->rdata  = fb->cmap.r[index];
    492 		tc->gdata  = fb->cmap.g[index];
    493 		tc->bdata  = fb->cmap.b[index];
    494 		tc->strobe = 0xff;
    495 		/* XXX delay required on 68020/30 to avoid bus error */
    496 		DELAY(100);
    497 
    498 		tccm_waitbusy(tc);
    499 		tc->cindex = 0;
    500 	} else {
    501 		tccm_waitbusy(tc);
    502 		tc->plane_mask = fb->planemask;
    503 		tc->rdata  = fb->cmap.r[index];
    504 		tc->gdata  = fb->cmap.g[index];
    505 		tc->bdata  = fb->cmap.b[index];
    506 		DELAY(1);	/* necessary for at least old HP98543 */
    507 		tc->cindex = ~index;
    508 		DELAY(1);	/* necessary for at least old HP98543 */
    509 		tc->strobe = 0xff;
    510 		/* XXX delay required on 68020/30 to avoid bus error */
    511 		DELAY(100);
    512 
    513 		tccm_waitbusy(tc);
    514 		tc->rdata  = 0;
    515 		tc->gdata  = 0;
    516 		tc->bdata  = 0;
    517 		tc->cindex = 0;
    518 	}
    519 }
    520 
    521 int
    522 topcat_setcmap(struct diofb *fb, struct wsdisplay_cmap *cm)
    523 {
    524 	uint8_t r[256], g[256], b[256];
    525 	u_int index = cm->index, count = cm->count;
    526 	u_int colcount = 1 << fb->planes;
    527 	int error;
    528 
    529 	if (index >= colcount || count > colcount - index)
    530 		return EINVAL;
    531 
    532 	if ((error = copyin(cm->red, r, count)) != 0)
    533 		return error;
    534 	if ((error = copyin(cm->green, g, count)) != 0)
    535 		return error;
    536 	if ((error = copyin(cm->blue, b, count)) != 0)
    537 		return error;
    538 
    539 	memcpy(fb->cmap.r + index, r, count);
    540 	memcpy(fb->cmap.g + index, g, count);
    541 	memcpy(fb->cmap.b + index, b, count);
    542 
    543 	while (count-- != 0)
    544 		topcat_setcolor(fb, index++);
    545 
    546 	return 0;
    547 }
    548 
    549 /*
    550  * Accelerated routines
    551  */
    552 
    553 int
    554 topcat_windowmove(struct diofb *fb, uint16_t sx, uint16_t sy,
    555     uint16_t dx, uint16_t dy, uint16_t cx, uint16_t cy, int16_t rop,
    556     int16_t planemask)
    557 {
    558 	volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva;
    559 
    560 	tc_waitbusy(tc, fb->planemask);
    561 
    562 	if (planemask != 0xff) {
    563 		tc->wen = planemask ^ 0xff;
    564 		tc->wmrr = rop ^ 0x0f;
    565 		tc->wen = fb->planemask;
    566 	} else {
    567 		tc->wen = planemask;
    568 		tc->wmrr = rop;
    569 	}
    570 	tc->source_y = sy;
    571 	tc->source_x = sx;
    572 	tc->dest_y = dy;
    573 	tc->dest_x = dx;
    574 	tc->wheight = cy;
    575 	tc->wwidth = cx;
    576 	tc->wmove = fb->planemask;
    577 
    578 	return 0;
    579 }
    580 
    581 static void
    582 topcat_putchar8(void *cookie, int row, int col, u_int uc, long attr)
    583 {
    584 	struct rasops_info *ri = (struct rasops_info *)cookie;
    585 	struct diofb *diofb = ri->ri_hw;
    586 	volatile struct tcboxfb *tc = (struct tcboxfb *)diofb->regkva;
    587 
    588 	/* Wait windowmove ops complete before drawing a glyph */
    589 	tc_waitbusy(tc, diofb->planemask);
    590 
    591 	/* Call the original rasops putchar */
    592 	(*diofb->wsputchar)(cookie, row, col, uc, attr);
    593 }
    594 
    595 /*
    596  * Put a single character on 1 bpp (98542) or 4 bpp (98543) variants
    597  * with 1024x400 VRAM to treat them as a pseudo 512x400 bitmap.
    598  */
    599 static void
    600 topcat_putchar1_4(void *cookie, int row, int col, u_int uc, long attr)
    601 {
    602 	int width, height, cnt, fs;
    603 	uint32_t fb;
    604 	uint8_t *fr, clr[2];
    605 	uint8_t *dp, *rp;
    606 	struct rasops_info *ri;
    607 	struct diofb *diofb;
    608 	volatile struct tcboxfb *tc;
    609 
    610 	ri = (struct rasops_info *)cookie;
    611 
    612 	if (!CHAR_IN_FONT(uc, ri->ri_font))
    613 		return;
    614 
    615 	rp = ri->ri_bits + (row * ri->ri_yscale) +
    616 	    (col * ri->ri_xscale * 2);
    617 
    618 	height = ri->ri_font->fontheight;
    619 	width = ri->ri_font->fontwidth;
    620 	clr[0] = (uint8_t)ri->ri_devcmap[(attr >> 16) & 0xf];
    621 	clr[1] = (uint8_t)ri->ri_devcmap[(attr >> 24) & 0xf];
    622 
    623 	/* Wait windowmove ops complete before drawing a glyph */
    624 	diofb = ri->ri_hw;
    625 	tc = (struct tcboxfb *)diofb->regkva;
    626 	tc_waitbusy(tc, diofb->planemask);
    627 
    628 	/*
    629 	 * We have to put pixel data to both odd and even addresses
    630 	 * to handle "doubled pixels" as noted above.
    631 	 */
    632 	if (uc == ' ') {
    633 		uint16_t c = clr[0];
    634 
    635 		c = c << 8 | c;
    636 		while (height--) {
    637 			dp = rp;
    638 			rp += ri->ri_stride;
    639 
    640 			for (cnt = width; cnt; cnt--) {
    641 				*(uint16_t *)dp = c;
    642 				dp += 2;
    643 			}
    644 		}
    645 	} else {
    646 		uc -= ri->ri_font->firstchar;
    647 		fr = (uint8_t *)ri->ri_font->data + uc * ri->ri_fontscale;
    648 		fs = ri->ri_font->stride;
    649 
    650 		while (height--) {
    651 			dp = rp;
    652 			fb = be32dec(fr);
    653 			fr += fs;
    654 			rp += ri->ri_stride;
    655 
    656 			for (cnt = width; cnt; cnt--) {
    657 				uint16_t c = clr[(fb >> 31) & 1];
    658 
    659 				c = c << 8 | c;
    660 				*(uint16_t *)dp = c;
    661 				dp += 2;
    662 				fb <<= 1;
    663 			}
    664 		}
    665 	}
    666 
    667 	/* Do underline */
    668 	if ((attr & WSATTR_UNDERLINE) != 0) {
    669 		uint16_t c = clr[1];
    670 
    671 		c = c << 8 | c;
    672 		rp -= ri->ri_stride * ri->ri_ul.off;
    673 
    674 		while (width--) {
    675 			*(uint16_t *)rp = c;
    676 			rp += 2;
    677 		}
    678 	}
    679 }
    680 
    681 /*
    682  *   Topcat/catseye console attachment
    683  */
    684 
    685 int
    686 topcatcnattach(bus_space_tag_t bst, bus_addr_t addr, int scode)
    687 {
    688 	bus_space_handle_t bsh;
    689 	void *va;
    690 	struct diofbreg *fbr;
    691 	struct diofb *fb = &diofb_cn;
    692 	int size;
    693 
    694 	if (bus_space_map(bst, addr, PAGE_SIZE, 0, &bsh))
    695 		return 1;
    696 	va = bus_space_vaddr(bst, bsh);
    697 	fbr = va;
    698 
    699 	if (badaddr(va) || fbr->id != GRFHWID) {
    700 		bus_space_unmap(bst, bsh, PAGE_SIZE);
    701 		return 1;
    702 	}
    703 
    704 	switch (fbr->fbid) {
    705 	case GID_TOPCAT:
    706 	case GID_LRCATSEYE:
    707 	case GID_HRCCATSEYE:
    708 	case GID_HRMCATSEYE:
    709 		break;
    710 
    711 	default:
    712 		bus_space_unmap(bst, bsh, PAGE_SIZE);
    713 		return 1;
    714 	}
    715 
    716 	size = DIO_SIZE(scode, va);
    717 
    718 	bus_space_unmap(bst, bsh, PAGE_SIZE);
    719 	if (bus_space_map(bst, addr, size, 0, &bsh))
    720 		return 1;
    721 	va = bus_space_vaddr(bst, bsh);
    722 
    723 	/*
    724 	 * Initialize the framebuffer hardware.
    725 	 */
    726 	conscode = scode;
    727 	conaddr = va;
    728 	topcat_reset(fb, conscode, (struct diofbreg *)conaddr);
    729 
    730 	/*
    731 	 * Initialize the terminal emulator.
    732 	 */
    733 	diofb_cnattach(fb);
    734 	return 0;
    735 }
    736