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