xref: /netbsd-src/sys/arch/hppa/dev/hyperfb.c (revision 64ffcac262f1554c09c483b1615c13b4409bd7e0)
1*64ffcac2Smacallan /*	$NetBSD: hyperfb.c,v 1.19 2024/11/13 08:21:16 macallan Exp $	*/
2cf4b16e0Smacallan 
3cf4b16e0Smacallan /*
4cf4b16e0Smacallan  * Copyright (c) 2024 Michael Lorenz
5cf4b16e0Smacallan  * All rights reserved.
6cf4b16e0Smacallan  *
7cf4b16e0Smacallan  * Redistribution and use in source and binary forms, with or without
8cf4b16e0Smacallan  * modification, are permitted provided that the following conditions
9cf4b16e0Smacallan  * are met:
10cf4b16e0Smacallan  * 1. Redistributions of source code must retain the above copyright
11cf4b16e0Smacallan  *    notice, this list of conditions and the following disclaimer.
12cf4b16e0Smacallan  * 2. Redistributions in binary form must reproduce the above copyright
13cf4b16e0Smacallan  *    notice, this list of conditions and the following disclaimer in the
14cf4b16e0Smacallan  *    documentation and/or other materials provided with the distribution.
15cf4b16e0Smacallan  *
16cf4b16e0Smacallan  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17cf4b16e0Smacallan  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18cf4b16e0Smacallan  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19cf4b16e0Smacallan  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20cf4b16e0Smacallan  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21cf4b16e0Smacallan  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22cf4b16e0Smacallan  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23cf4b16e0Smacallan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24cf4b16e0Smacallan  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25cf4b16e0Smacallan  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26cf4b16e0Smacallan  * THE POSSIBILITY OF SUCH DAMAGE.
27cf4b16e0Smacallan  */
28cf4b16e0Smacallan 
29cf4b16e0Smacallan /*
30cf4b16e0Smacallan  * a native driver for HCRX / hyperdrive cards
315462a444Smacallan  * tested on a HCRX24Z in a C360 only so far
32cf4b16e0Smacallan  */
33cf4b16e0Smacallan 
34cf4b16e0Smacallan #include <sys/cdefs.h>
35*64ffcac2Smacallan __KERNEL_RCSID(0, "$NetBSD: hyperfb.c,v 1.19 2024/11/13 08:21:16 macallan Exp $");
36cf4b16e0Smacallan 
37cf4b16e0Smacallan #include "opt_cputype.h"
38cf4b16e0Smacallan #include "opt_hyperfb.h"
39cf4b16e0Smacallan 
40cf4b16e0Smacallan #include <sys/param.h>
41cf4b16e0Smacallan #include <sys/systm.h>
42cf4b16e0Smacallan #include <sys/device.h>
43cf4b16e0Smacallan 
44cf4b16e0Smacallan #include <sys/bus.h>
45cf4b16e0Smacallan #include <machine/cpu.h>
46cf4b16e0Smacallan #include <machine/iomod.h>
47cf4b16e0Smacallan #include <machine/autoconf.h>
48cf4b16e0Smacallan 
49cf4b16e0Smacallan #include <dev/wscons/wsdisplayvar.h>
50cf4b16e0Smacallan #include <dev/wscons/wsconsio.h>
51cf4b16e0Smacallan #include <dev/wsfont/wsfont.h>
52cf4b16e0Smacallan #include <dev/rasops/rasops.h>
53cf4b16e0Smacallan #include <dev/wscons/wsdisplay_vconsvar.h>
54cf4b16e0Smacallan #include <dev/wscons/wsdisplay_glyphcachevar.h>
55cf4b16e0Smacallan 
56cf4b16e0Smacallan #include <dev/ic/stireg.h>
57cf4b16e0Smacallan #include <dev/ic/stivar.h>
58cf4b16e0Smacallan 
59cf4b16e0Smacallan #include <hppa/dev/cpudevs.h>
60cf4b16e0Smacallan #include <hppa/hppa/machdep.h>
61cf4b16e0Smacallan 
62cf4b16e0Smacallan #ifdef HYPERFB_DEBUG
63cf4b16e0Smacallan #define	DPRINTF printf
64cf4b16e0Smacallan #else
65cf4b16e0Smacallan #define DPRINTF if (0) printf
66cf4b16e0Smacallan #endif
67cf4b16e0Smacallan 
68cf4b16e0Smacallan #define	STI_ROMSIZE	(sizeof(struct sti_dd) * 4)
69cf4b16e0Smacallan 
70cf4b16e0Smacallan #define HCRX_FBOFFSET	0x01000000
71cf4b16e0Smacallan #define HCRX_FBLEN	0x01000000
72cf4b16e0Smacallan #define HCRX_REGOFFSET	0x00100000
73cf4b16e0Smacallan #define HCRX_REGLEN	0x00280000
74cf4b16e0Smacallan 
75cf4b16e0Smacallan #define HCRX_CONFIG_24BIT	0x100
76cf4b16e0Smacallan 
77cf4b16e0Smacallan int hyperfb_match(device_t, cfdata_t, void *);
78cf4b16e0Smacallan void hyperfb_attach(device_t, device_t, void *);
79cf4b16e0Smacallan 
80cf4b16e0Smacallan struct	hyperfb_softc {
81cf4b16e0Smacallan 	device_t		sc_dev;
82cf4b16e0Smacallan 	bus_space_tag_t		sc_iot;
83cf4b16e0Smacallan 	bus_addr_t		sc_base;
84cf4b16e0Smacallan 	bus_space_handle_t	sc_hfb, sc_hreg;
85cf4b16e0Smacallan 	void 			*sc_fb;
86cf4b16e0Smacallan 
87cf4b16e0Smacallan 	int sc_width, sc_height;
88cf4b16e0Smacallan 	int sc_locked, sc_is_console, sc_24bit;
89cf4b16e0Smacallan 	struct vcons_screen sc_console_screen;
90cf4b16e0Smacallan 	struct wsscreen_descr sc_defaultscreen_descr;
91cf4b16e0Smacallan 	const struct wsscreen_descr *sc_screens[1];
92cf4b16e0Smacallan 	struct wsscreen_list sc_screenlist;
93cf4b16e0Smacallan 	struct vcons_data vd;
94cf4b16e0Smacallan 	int sc_mode;
95cf4b16e0Smacallan 	u_char sc_cmap_red[256];
96cf4b16e0Smacallan 	u_char sc_cmap_green[256];
97cf4b16e0Smacallan 	u_char sc_cmap_blue[256];
98cf4b16e0Smacallan 	kmutex_t sc_hwlock;
99cf4b16e0Smacallan 	uint32_t sc_hwmode;
100cf4b16e0Smacallan #define HW_FB		0
101cf4b16e0Smacallan #define HW_FILL		1
102cf4b16e0Smacallan #define HW_BLIT		2
10343af28fdSmacallan #define HW_SFILL	3
104cf4b16e0Smacallan 	/* cursor stuff */
105cf4b16e0Smacallan 	int sc_cursor_x, sc_cursor_y;
106cf4b16e0Smacallan 	int sc_hot_x, sc_hot_y, sc_enabled;
107cf4b16e0Smacallan 	int sc_video_on;
108cf4b16e0Smacallan 	glyphcache sc_gc;
109cf4b16e0Smacallan };
110cf4b16e0Smacallan 
111cf4b16e0Smacallan extern struct cfdriver hyperfb_cd;
112cf4b16e0Smacallan 
113cf4b16e0Smacallan CFATTACH_DECL_NEW(hyperfb, sizeof(struct hyperfb_softc), hyperfb_match,
114cf4b16e0Smacallan     hyperfb_attach, NULL, NULL);
115cf4b16e0Smacallan 
116aee609b2Smacallan static inline void  hyperfb_setup_fb(struct hyperfb_softc *);
117aee609b2Smacallan static inline void  hyperfb_setup_fb24(struct hyperfb_softc *);
118cf4b16e0Smacallan static void 	hyperfb_init_screen(void *, struct vcons_screen *,
119cf4b16e0Smacallan 			    int, long *);
120cf4b16e0Smacallan static int	hyperfb_ioctl(void *, void *, u_long, void *, int,
121cf4b16e0Smacallan 			     struct lwp *);
122cf4b16e0Smacallan static paddr_t	hyperfb_mmap(void *, void *, off_t, int);
123cf4b16e0Smacallan 
124f7add90dSriastradh static int	hyperfb_putcmap(struct hyperfb_softc *,
125f7add90dSriastradh 		    struct wsdisplay_cmap *);
126f7add90dSriastradh static int 	hyperfb_getcmap(struct hyperfb_softc *,
127f7add90dSriastradh 		    struct wsdisplay_cmap *);
128cf4b16e0Smacallan static void	hyperfb_restore_palette(struct hyperfb_softc *);
129cf4b16e0Smacallan static int 	hyperfb_putpalreg(struct hyperfb_softc *, uint8_t, uint8_t,
130cf4b16e0Smacallan 			    uint8_t, uint8_t);
131cf4b16e0Smacallan void 	hyperfb_setup(struct hyperfb_softc *);
132cf4b16e0Smacallan static void	hyperfb_set_video(struct hyperfb_softc *, int);
133cf4b16e0Smacallan 
1347d0f5abeSmacallan static void	hyperfb_rectfill(struct hyperfb_softc *, int, int, int, int,
1357d0f5abeSmacallan 			    uint32_t);
1367d0f5abeSmacallan static void	hyperfb_bitblt(void *, int, int, int, int, int,
1377d0f5abeSmacallan 			    int, int);
1387d0f5abeSmacallan 
1397d0f5abeSmacallan static void	hyperfb_cursor(void *, int, int, int);
1407d0f5abeSmacallan static void	hyperfb_putchar(void *, int, int, u_int, long);
1417d0f5abeSmacallan static void	hyperfb_copycols(void *, int, int, int, int);
1427d0f5abeSmacallan static void	hyperfb_erasecols(void *, int, int, int, long);
1437d0f5abeSmacallan static void	hyperfb_copyrows(void *, int, int, int);
1447d0f5abeSmacallan static void	hyperfb_eraserows(void *, int, int, long);
1457d0f5abeSmacallan 
1467d0f5abeSmacallan static void	hyperfb_move_cursor(struct hyperfb_softc *, int, int);
147f7add90dSriastradh static int	hyperfb_do_cursor(struct hyperfb_softc *,
148f7add90dSriastradh 		    struct wsdisplay_cursor *);
1497d0f5abeSmacallan 
1507d0f5abeSmacallan static inline void hyperfb_wait_fifo(struct hyperfb_softc *, uint32_t);
1517d0f5abeSmacallan 
152cf4b16e0Smacallan #define	ngle_bt458_write(sc, r, v) \
153cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24)
154cf4b16e0Smacallan 
155cf4b16e0Smacallan struct wsdisplay_accessops hyperfb_accessops = {
156cf4b16e0Smacallan 	hyperfb_ioctl,
157cf4b16e0Smacallan 	hyperfb_mmap,
158cf4b16e0Smacallan 	NULL,	/* alloc_screen */
159cf4b16e0Smacallan 	NULL,	/* free_screen */
160cf4b16e0Smacallan 	NULL,	/* show_screen */
161cf4b16e0Smacallan 	NULL, 	/* load_font */
162cf4b16e0Smacallan 	NULL,	/* pollc */
163cf4b16e0Smacallan 	NULL	/* scroll */
164cf4b16e0Smacallan };
165cf4b16e0Smacallan 
166cf4b16e0Smacallan static inline uint32_t
167cf4b16e0Smacallan hyperfb_read4(struct hyperfb_softc *sc, uint32_t offset)
168cf4b16e0Smacallan {
169cf4b16e0Smacallan 	return bus_space_read_4(sc->sc_iot, sc->sc_hreg, offset);
170cf4b16e0Smacallan }
171cf4b16e0Smacallan 
172cf4b16e0Smacallan static inline uint8_t
173cf4b16e0Smacallan hyperfb_read1(struct hyperfb_softc *sc, uint32_t offset)
174cf4b16e0Smacallan {
175cf4b16e0Smacallan 	return bus_space_read_1(sc->sc_iot, sc->sc_hreg, offset);
176cf4b16e0Smacallan }
177cf4b16e0Smacallan 
178cf4b16e0Smacallan static inline void
179cf4b16e0Smacallan hyperfb_write4(struct hyperfb_softc *sc, uint32_t offset, uint32_t val)
180cf4b16e0Smacallan {
181cf4b16e0Smacallan 	bus_space_write_4(sc->sc_iot, sc->sc_hreg, offset, val);
182cf4b16e0Smacallan }
183cf4b16e0Smacallan 
184cf4b16e0Smacallan static inline void
185cf4b16e0Smacallan hyperfb_write1(struct hyperfb_softc *sc, uint32_t offset, uint8_t val)
186cf4b16e0Smacallan {
187cf4b16e0Smacallan 	bus_space_write_1(sc->sc_iot, sc->sc_hreg, offset, val);
188cf4b16e0Smacallan }
189cf4b16e0Smacallan 
190cf4b16e0Smacallan static inline void
191cf4b16e0Smacallan hyperfb_wait(struct hyperfb_softc *sc)
192cf4b16e0Smacallan {
193cf4b16e0Smacallan 	uint8_t stat;
194cf4b16e0Smacallan 
195cf4b16e0Smacallan 	do {
196cf4b16e0Smacallan 		stat = hyperfb_read1(sc, NGLE_REG_15b0);
197cf4b16e0Smacallan 		if (stat == 0)
198cf4b16e0Smacallan 			stat = hyperfb_read1(sc, NGLE_REG_15b0);
199cf4b16e0Smacallan 	} while (stat != 0);
200cf4b16e0Smacallan }
201cf4b16e0Smacallan 
2027d0f5abeSmacallan static inline void
2037d0f5abeSmacallan hyperfb_wait_fifo(struct hyperfb_softc *sc, uint32_t slots)
2047d0f5abeSmacallan {
2057d0f5abeSmacallan 	uint32_t reg;
2067d0f5abeSmacallan 
2077d0f5abeSmacallan 	do {
2087d0f5abeSmacallan 		reg = hyperfb_read4(sc, NGLE_REG_34);
2097d0f5abeSmacallan 	} while (reg < slots);
2107d0f5abeSmacallan }
2117d0f5abeSmacallan 
212aee609b2Smacallan static inline void
213cf4b16e0Smacallan hyperfb_setup_fb(struct hyperfb_softc *sc)
214cf4b16e0Smacallan {
215cf4b16e0Smacallan 
21643af28fdSmacallan 	/*
21743af28fdSmacallan 	 * turns out the plane mask is applied to everything, including
21843af28fdSmacallan 	 * direct framebuffer writes, so make sure we always set it
21943af28fdSmacallan 	 */
220cf4b16e0Smacallan 	hyperfb_wait(sc);
221aee609b2Smacallan 	if ((sc->sc_mode != WSDISPLAYIO_MODE_EMUL) && sc->sc_24bit) {
22215644928Smacallan 		hyperfb_write4(sc, NGLE_REG_10,
22315644928Smacallan 		    BA(FractDcd, Otc24, Ots08, AddrLong, 0, BINapp0F8, 0));
224aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_13, 0xffffffff);
22543af28fdSmacallan 	} else {
22615644928Smacallan 		hyperfb_write4(sc, NGLE_REG_10,
22715644928Smacallan 		    BA(IndexedDcd, Otc04, Ots08, AddrByte, 0, BINovly, 0));
22843af28fdSmacallan 		hyperfb_write4(sc, NGLE_REG_13, 0xff);
22943af28fdSmacallan 	}
230cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_14, 0x83000300);
231cf4b16e0Smacallan 	hyperfb_wait(sc);
232cf4b16e0Smacallan 	hyperfb_write1(sc, NGLE_REG_16b1, 1);
233cf4b16e0Smacallan 	sc->sc_hwmode = HW_FB;
234cf4b16e0Smacallan }
235cf4b16e0Smacallan 
236aee609b2Smacallan static inline void
237aee609b2Smacallan hyperfb_setup_fb24(struct hyperfb_softc *sc)
238aee609b2Smacallan {
239aee609b2Smacallan 
240aee609b2Smacallan 	hyperfb_wait(sc);
24115644928Smacallan 	hyperfb_write4(sc, NGLE_REG_10,
24215644928Smacallan 	    BA(FractDcd, Otc24, Ots08, AddrLong, 0, BINapp0F8, 0));
243aee609b2Smacallan 	hyperfb_write4(sc, NGLE_REG_13, 0xffffffff);
244aee609b2Smacallan 	hyperfb_write4(sc, NGLE_REG_14, 0x83000300);
245aee609b2Smacallan 	//IBOvals(RopSrc,0,BitmapExtent08,0,DataDynamic,MaskDynamic,0,0)
246aee609b2Smacallan 	hyperfb_wait(sc);
247aee609b2Smacallan 	hyperfb_write1(sc, NGLE_REG_16b1, 1);
248aee609b2Smacallan 	sc->sc_hwmode = HW_FB;
249aee609b2Smacallan }
250aee609b2Smacallan 
251cf4b16e0Smacallan int
252cf4b16e0Smacallan hyperfb_match(device_t parent, cfdata_t cf, void *aux)
253cf4b16e0Smacallan {
254cf4b16e0Smacallan 	struct confargs *ca = aux;
255cf4b16e0Smacallan 	bus_space_handle_t romh;
256cf4b16e0Smacallan 	paddr_t rom;
257cf4b16e0Smacallan 	uint32_t id = 0;
258cf4b16e0Smacallan 	u_char devtype;
259cf4b16e0Smacallan 	int rv = 0, romunmapped = 0;
260cf4b16e0Smacallan 
261cf4b16e0Smacallan 	if (ca->ca_type.iodc_type != HPPA_TYPE_FIO)
262cf4b16e0Smacallan 		return 0;
263cf4b16e0Smacallan 
264cf4b16e0Smacallan 	/* these need further checking for the graphics id */
265cf4b16e0Smacallan 	if (ca->ca_type.iodc_sv_model != HPPA_FIO_GSGC &&
266cf4b16e0Smacallan 	    ca->ca_type.iodc_sv_model != HPPA_FIO_SGC)
267cf4b16e0Smacallan 		return 0;
268cf4b16e0Smacallan 
269cf4b16e0Smacallan 	if (ca->ca_naddrs > 0)
270cf4b16e0Smacallan 		rom = ca->ca_addrs[0].addr;
271cf4b16e0Smacallan 	else
272cf4b16e0Smacallan 		rom = ca->ca_hpa;
273cf4b16e0Smacallan 
274cf4b16e0Smacallan 	DPRINTF("%s: hpa=%x, rom=%x\n", __func__, (uint)ca->ca_hpa,
275cf4b16e0Smacallan 	    (uint)rom);
276cf4b16e0Smacallan 
277cf4b16e0Smacallan 	/* if it does not map, probably part of the lasi space */
278cf4b16e0Smacallan 	if (bus_space_map(ca->ca_iot, rom, STI_ROMSIZE, 0, &romh)) {
279cf4b16e0Smacallan 		DPRINTF("%s: can't map rom space (%d)\n", __func__, rv);
280cf4b16e0Smacallan 
281cf4b16e0Smacallan 		if ((rom & HPPA_IOBEGIN) == HPPA_IOBEGIN) {
282cf4b16e0Smacallan 			romh = rom;
283cf4b16e0Smacallan 			romunmapped++;
284cf4b16e0Smacallan 		} else {
285cf4b16e0Smacallan 			/* in this case nobody has no freaking idea */
286cf4b16e0Smacallan 			return 0;
287cf4b16e0Smacallan 		}
288cf4b16e0Smacallan 	}
289cf4b16e0Smacallan 
290cf4b16e0Smacallan 	devtype = bus_space_read_1(ca->ca_iot, romh, 3);
291cf4b16e0Smacallan 	DPRINTF("%s: devtype=%d\n", __func__, devtype);
292cf4b16e0Smacallan 	rv = 1;
293cf4b16e0Smacallan 	switch (devtype) {
294cf4b16e0Smacallan 	case STI_DEVTYPE4:
295cf4b16e0Smacallan 		id = bus_space_read_4(ca->ca_iot, romh, STI_DEV4_DD_GRID);
296cf4b16e0Smacallan 		break;
297cf4b16e0Smacallan 	case STI_DEVTYPE1:
298cf4b16e0Smacallan 		id = (bus_space_read_1(ca->ca_iot, romh, STI_DEV1_DD_GRID
299cf4b16e0Smacallan 		    +  3) << 24) |
300cf4b16e0Smacallan 		    (bus_space_read_1(ca->ca_iot, romh, STI_DEV1_DD_GRID
301cf4b16e0Smacallan 		    +  7) << 16) |
302cf4b16e0Smacallan 		    (bus_space_read_1(ca->ca_iot, romh, STI_DEV1_DD_GRID
303cf4b16e0Smacallan 		    + 11) <<  8) |
304cf4b16e0Smacallan 		    (bus_space_read_1(ca->ca_iot, romh, STI_DEV1_DD_GRID
305cf4b16e0Smacallan 		    + 15));
306cf4b16e0Smacallan 		break;
307cf4b16e0Smacallan 	default:
308cf4b16e0Smacallan 		DPRINTF("%s: unknown type (%x)\n", __func__, devtype);
309cf4b16e0Smacallan 		rv = 0;
310cf4b16e0Smacallan 	}
311cf4b16e0Smacallan 
312cf4b16e0Smacallan 	if (id == STI_DD_HCRX)
313cf4b16e0Smacallan 		rv = 100;	/* beat out sti */
314cf4b16e0Smacallan 
315cf4b16e0Smacallan 	ca->ca_addrs[ca->ca_naddrs].addr = rom;
316cf4b16e0Smacallan 	ca->ca_addrs[ca->ca_naddrs].size = sti_rom_size(ca->ca_iot, romh);
317cf4b16e0Smacallan 	ca->ca_naddrs++;
318cf4b16e0Smacallan 
319cf4b16e0Smacallan 	if (!romunmapped)
320cf4b16e0Smacallan 		bus_space_unmap(ca->ca_iot, romh, STI_ROMSIZE);
321cf4b16e0Smacallan 	return rv;
322cf4b16e0Smacallan }
323cf4b16e0Smacallan 
324cf4b16e0Smacallan void
325cf4b16e0Smacallan hyperfb_attach(device_t parent, device_t self, void *aux)
326cf4b16e0Smacallan {
327cf4b16e0Smacallan 	struct hyperfb_softc *sc = device_private(self);
328cf4b16e0Smacallan 	struct confargs *ca = aux;
329cf4b16e0Smacallan 	struct rasops_info *ri;
330cf4b16e0Smacallan 	struct wsemuldisplaydev_attach_args aa;
331cf4b16e0Smacallan 	bus_space_handle_t hrom;
332cf4b16e0Smacallan 	hppa_hpa_t consaddr;
333cf4b16e0Smacallan 	long defattr;
334cf4b16e0Smacallan 	int pagezero_cookie;
335cf4b16e0Smacallan 	paddr_t rom;
336cf4b16e0Smacallan 	uint32_t config;
337cf4b16e0Smacallan 
338cf4b16e0Smacallan 	pagezero_cookie = hppa_pagezero_map();
339cf4b16e0Smacallan 	consaddr = (hppa_hpa_t)PAGE0->mem_cons.pz_hpa;
340cf4b16e0Smacallan 	hppa_pagezero_unmap(pagezero_cookie);
341cf4b16e0Smacallan 
342cf4b16e0Smacallan 	sc->sc_dev = self;
343cf4b16e0Smacallan 	sc->sc_base = ca->ca_hpa;
344cf4b16e0Smacallan 	sc->sc_iot = ca->ca_iot;
345cf4b16e0Smacallan 	sc->sc_is_console =(ca->ca_hpa == consaddr);
346cf4b16e0Smacallan 	sc->sc_width = 1280;
347cf4b16e0Smacallan 	sc->sc_height = 1024;
348cf4b16e0Smacallan 
349cf4b16e0Smacallan 	/* we can *not* be interrupted when doing colour map accesses */
350cf4b16e0Smacallan 	mutex_init(&sc->sc_hwlock, MUTEX_DEFAULT, IPL_HIGH);
351cf4b16e0Smacallan 
352cf4b16e0Smacallan 	/* we stashed rom addr/len into the last slot during probe */
353cf4b16e0Smacallan 	rom = ca->ca_addrs[ca->ca_naddrs - 1].addr;
354cf4b16e0Smacallan 
355cf4b16e0Smacallan 	if (bus_space_map(sc->sc_iot,
356cf4b16e0Smacallan 	    sc->sc_base + HCRX_FBOFFSET, HCRX_FBLEN,
357cf4b16e0Smacallan 	    BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE,
358cf4b16e0Smacallan 	    &sc->sc_hfb)) {
359f7add90dSriastradh 	    	aprint_error_dev(sc->sc_dev,
360f7add90dSriastradh 		    "failed to map the framebuffer\n");
361cf4b16e0Smacallan 	    	return;
362cf4b16e0Smacallan 	}
363cf4b16e0Smacallan 	sc->sc_fb = bus_space_vaddr(sc->sc_iot, sc->sc_hfb);
364cf4b16e0Smacallan 
365cf4b16e0Smacallan 	if (bus_space_map(sc->sc_iot,
366cf4b16e0Smacallan 	    sc->sc_base + HCRX_REGOFFSET, HCRX_REGLEN, 0, &sc->sc_hreg)) {
367cf4b16e0Smacallan 	    	aprint_error_dev(sc->sc_dev, "failed to map registers\n");
368cf4b16e0Smacallan 	    	return;
369cf4b16e0Smacallan 	}
370cf4b16e0Smacallan 
371cf4b16e0Smacallan 	/*
372cf4b16e0Smacallan 	 * we really only need the first word so we can grab the config bits
373cf4b16e0Smacallan 	 * between the bytes
374cf4b16e0Smacallan 	 */
375f7add90dSriastradh 	if (bus_space_map(sc->sc_iot, rom, 4, 0, &hrom)) {
376f7add90dSriastradh 	    	aprint_error_dev(sc->sc_dev,
377f7add90dSriastradh 		    "failed to map ROM, assuming 8bit\n");
378cf4b16e0Smacallan 	    	config = 0;
379cf4b16e0Smacallan 	} else {
380cf4b16e0Smacallan 		/* alright, we got the ROM. now do the idle dance. */
381cf4b16e0Smacallan 		volatile uint32_t r = hyperfb_read4(sc, NGLE_REG_15);
382cf4b16e0Smacallan 		__USE(r);
383cf4b16e0Smacallan 		hyperfb_wait(sc);
384cf4b16e0Smacallan 		config = bus_space_read_4(sc->sc_iot, hrom, 0);
385cf4b16e0Smacallan 		bus_space_unmap(sc->sc_iot, hrom, 4);
386cf4b16e0Smacallan 	}
387cf4b16e0Smacallan 	sc->sc_24bit = ((config & HCRX_CONFIG_24BIT) != 0);
388cf4b16e0Smacallan 
389cf4b16e0Smacallan 	printf(" %s\n", sc->sc_24bit ? "HCRX24" : "HCRX");
390cf4b16e0Smacallan #ifdef HP7300LC_CPU
391cf4b16e0Smacallan 	/*
392cf4b16e0Smacallan 	 * PCXL2: enable accel I/O for this space, see PCX-L2 ERS "ACCEL_IO".
393cf4b16e0Smacallan 	 * "pcxl2_ers.{ps,pdf}", (section / chapter . rel. page / abs. page)
394cf4b16e0Smacallan 	 * 8.7.4 / 8-12 / 92, 11.3.14 / 11-14 / 122 and 14.8 / 14-5 / 203.
395cf4b16e0Smacallan 	 */
396cf4b16e0Smacallan 	if (hppa_cpu_info->hci_cputype == hpcxl2
397cf4b16e0Smacallan 	    && ca->ca_hpa >= PCXL2_ACCEL_IO_START
398cf4b16e0Smacallan 	    && ca->ca_hpa <= PCXL2_ACCEL_IO_END)
399cf4b16e0Smacallan 		eaio_l2(PCXL2_ACCEL_IO_ADDR2MASK(ca->ca_hpa));
400cf4b16e0Smacallan #endif /* HP7300LC_CPU */
401cf4b16e0Smacallan 
402aee609b2Smacallan 	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
403aee609b2Smacallan 	sc->sc_locked = 0;
404aee609b2Smacallan 
405cf4b16e0Smacallan 	hyperfb_setup(sc);
406cf4b16e0Smacallan 	hyperfb_setup_fb(sc);
407cf4b16e0Smacallan 
408cf4b16e0Smacallan 	sc->sc_defaultscreen_descr = (struct wsscreen_descr){
409cf4b16e0Smacallan 		"default",
410cf4b16e0Smacallan 		0, 0,
411cf4b16e0Smacallan 		NULL,
412cf4b16e0Smacallan 		8, 16,
413cf4b16e0Smacallan 		WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE |
414cf4b16e0Smacallan 		      WSSCREEN_RESIZE,
415cf4b16e0Smacallan 		NULL
416cf4b16e0Smacallan 	};
417cf4b16e0Smacallan 
418cf4b16e0Smacallan 	sc->sc_screens[0] = &sc->sc_defaultscreen_descr;
419cf4b16e0Smacallan 	sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens};
420cf4b16e0Smacallan 
421cf4b16e0Smacallan 	vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
422cf4b16e0Smacallan 	    &hyperfb_accessops);
423cf4b16e0Smacallan 	sc->vd.init_screen = hyperfb_init_screen;
424cf4b16e0Smacallan 	sc->vd.show_screen_cookie = &sc->sc_gc;
425cf4b16e0Smacallan 	sc->vd.show_screen_cb = glyphcache_adapt;
426cf4b16e0Smacallan 
427cf4b16e0Smacallan 	ri = &sc->sc_console_screen.scr_ri;
428cf4b16e0Smacallan 
429cf4b16e0Smacallan 	//sc->sc_gc.gc_bitblt = hyperfb_bitblt;
430cf4b16e0Smacallan 	//sc->sc_gc.gc_blitcookie = sc;
431cf4b16e0Smacallan 	//sc->sc_gc.gc_rop = RopSrc;
432cf4b16e0Smacallan 
433*64ffcac2Smacallan 	vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, &defattr);
434cf4b16e0Smacallan 	sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
435cf4b16e0Smacallan 
436cf4b16e0Smacallan 	sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
437cf4b16e0Smacallan 	sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
438cf4b16e0Smacallan 	sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
439cf4b16e0Smacallan 	sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
440cf4b16e0Smacallan 
441cf4b16e0Smacallan #if 0
442cf4b16e0Smacallan 	glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
443cf4b16e0Smacallan 			sc->sc_scr.fbheight - sc->sc_height - 5,
444cf4b16e0Smacallan 			sc->sc_scr.fbwidth,
445cf4b16e0Smacallan 			ri->ri_font->fontwidth,
446cf4b16e0Smacallan 			ri->ri_font->fontheight,
447cf4b16e0Smacallan 			defattr);
448cf4b16e0Smacallan #endif
4497d0f5abeSmacallan 
450cf4b16e0Smacallan 	hyperfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height,
451cf4b16e0Smacallan 	    ri->ri_devcmap[(defattr >> 16) & 0xff]);
452cf4b16e0Smacallan 	hyperfb_restore_palette(sc);
453cf4b16e0Smacallan 
454*64ffcac2Smacallan 	if (sc->sc_is_console) {
455*64ffcac2Smacallan 
456*64ffcac2Smacallan 		wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
457*64ffcac2Smacallan 		    defattr);
458*64ffcac2Smacallan 		vcons_replay_msgbuf(&sc->sc_console_screen);
459*64ffcac2Smacallan 	}
460*64ffcac2Smacallan 
461cf4b16e0Smacallan 	/* no suspend/resume support yet */
462cf4b16e0Smacallan 	if (!pmf_device_register(sc->sc_dev, NULL, NULL))
463cf4b16e0Smacallan 		aprint_error_dev(sc->sc_dev,
464cf4b16e0Smacallan 		    "couldn't establish power handler\n");
465cf4b16e0Smacallan 
466cf4b16e0Smacallan 	aa.console = sc->sc_is_console;
467cf4b16e0Smacallan 	aa.scrdata = &sc->sc_screenlist;
468cf4b16e0Smacallan 	aa.accessops = &hyperfb_accessops;
469cf4b16e0Smacallan 	aa.accesscookie = &sc->vd;
470cf4b16e0Smacallan 
471cf4b16e0Smacallan 	config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, CFARGS_NONE);
472cf4b16e0Smacallan 
473aee609b2Smacallan 	hyperfb_setup_fb(sc);
474bb4ea6beSmacallan 
475bb4ea6beSmacallan #ifdef HYPERFB_DEBUG
476bb4ea6beSmacallan 	int i;
477bb4ea6beSmacallan 
478bb4ea6beSmacallan 	hyperfb_wait_fifo(sc, 4);
479bb4ea6beSmacallan 	/* transfer data */
480bb4ea6beSmacallan 	hyperfb_write4(sc, NGLE_REG_8, 0xff00ff00);
481bb4ea6beSmacallan 	/* plane mask */
482bb4ea6beSmacallan 	hyperfb_write4(sc, NGLE_REG_13, 0xff);
483bb4ea6beSmacallan 	/* bitmap op */
484bb4ea6beSmacallan 	hyperfb_write4(sc, NGLE_REG_14,
485bb4ea6beSmacallan 	    IBOvals(RopSrc, 0, BitmapExtent08, 0, DataDynamic, MaskOtc, 1, 0));
486bb4ea6beSmacallan 	/* dst bitmap access */
487bb4ea6beSmacallan 	hyperfb_write4(sc, NGLE_REG_11,
488bb4ea6beSmacallan 	    BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, 0, BINovly, 0));
489bb4ea6beSmacallan 
490bb4ea6beSmacallan 	hyperfb_wait_fifo(sc, 3);
491bb4ea6beSmacallan 	hyperfb_write4(sc, NGLE_REG_35, 0xe0);
492bb4ea6beSmacallan 	hyperfb_write4(sc, NGLE_REG_36, 0x1c);
493bb4ea6beSmacallan 	/* dst XY */
494bb4ea6beSmacallan 	hyperfb_write4(sc, NGLE_REG_6, (2 << 16) | 902);
495bb4ea6beSmacallan 	/* len XY start */
496bb4ea6beSmacallan 	hyperfb_write4(sc, NGLE_REG_9, (28 << 16) | 32);
497bb4ea6beSmacallan 
498bb4ea6beSmacallan 	for (i = 0; i < 32; i++)
499bb4ea6beSmacallan 		hyperfb_write4(sc, NGLE_REG_8, (i & 4) ? 0xff00ff00 : 0x00ff00ff);
500bb4ea6beSmacallan 
501bb4ea6beSmacallan 	hyperfb_rectfill(sc, 70, 902, 16, 32, 0xe0);
502bb4ea6beSmacallan 	hyperfb_rectfill(sc, 50, 902, 16, 32, 0x1c);
503bb4ea6beSmacallan #endif
504cf4b16e0Smacallan }
505cf4b16e0Smacallan 
506cf4b16e0Smacallan static void
507cf4b16e0Smacallan hyperfb_init_screen(void *cookie, struct vcons_screen *scr,
508cf4b16e0Smacallan     int existing, long *defattr)
509cf4b16e0Smacallan {
510cf4b16e0Smacallan 	struct hyperfb_softc *sc = cookie;
511cf4b16e0Smacallan 	struct rasops_info *ri = &scr->scr_ri;
512cf4b16e0Smacallan 
513cf4b16e0Smacallan 	ri->ri_depth = 8;
514cf4b16e0Smacallan 	ri->ri_width = 1280;
515bb4ea6beSmacallan #ifdef HYPERFB_DEBUG
516bb4ea6beSmacallan 	ri->ri_height = 900;
517bb4ea6beSmacallan #else
518cf4b16e0Smacallan 	ri->ri_height = 1024;
519bb4ea6beSmacallan #endif
520cf4b16e0Smacallan 	ri->ri_stride = 2048;
521cf4b16e0Smacallan 	ri->ri_flg = RI_CENTER | RI_8BIT_IS_RGB /*|
522cf4b16e0Smacallan 		     RI_ENABLE_ALPHA | RI_PREFER_ALPHA*/;
523cf4b16e0Smacallan 
524cf4b16e0Smacallan 	ri->ri_bits = (void *)sc->sc_fb;
525cf4b16e0Smacallan 	rasops_init(ri, 0, 0);
526cf4b16e0Smacallan 	ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE |
527cf4b16e0Smacallan 		      WSSCREEN_RESIZE;
5287d0f5abeSmacallan 	scr->scr_flags |= VCONS_LOADFONT;
529cf4b16e0Smacallan 
530cf4b16e0Smacallan 	rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
531cf4b16e0Smacallan 		    sc->sc_width / ri->ri_font->fontwidth);
532cf4b16e0Smacallan 
533cf4b16e0Smacallan 	ri->ri_hw = scr;
5347d0f5abeSmacallan 
5357d0f5abeSmacallan 	ri->ri_ops.copyrows = hyperfb_copyrows;
5367d0f5abeSmacallan 	ri->ri_ops.copycols = hyperfb_copycols;
5377d0f5abeSmacallan 	ri->ri_ops.eraserows = hyperfb_eraserows;
5387d0f5abeSmacallan 	ri->ri_ops.erasecols = hyperfb_erasecols;
5397d0f5abeSmacallan 	ri->ri_ops.cursor = hyperfb_cursor;
5407d0f5abeSmacallan 	ri->ri_ops.putchar = hyperfb_putchar;
541cf4b16e0Smacallan }
542cf4b16e0Smacallan 
543cf4b16e0Smacallan static int
544cf4b16e0Smacallan hyperfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
545cf4b16e0Smacallan     struct lwp *l)
546cf4b16e0Smacallan {
547cf4b16e0Smacallan 	struct vcons_data *vd = v;
548cf4b16e0Smacallan 	struct hyperfb_softc *sc = vd->cookie;
549cf4b16e0Smacallan 	struct wsdisplay_fbinfo *wdf;
550cf4b16e0Smacallan 	struct vcons_screen *ms = vd->active;
551cf4b16e0Smacallan 
552cf4b16e0Smacallan 	switch (cmd) {
553cf4b16e0Smacallan 	case WSDISPLAYIO_GTYPE:
554cf4b16e0Smacallan 		*(u_int *)data = WSDISPLAY_TYPE_STI;
555cf4b16e0Smacallan 		return 0;
556cf4b16e0Smacallan 
5577f6c1850Smacallan 	case GCID:
5587f6c1850Smacallan 		*(u_int *)data = STI_DD_HCRX;
5597f6c1850Smacallan 		return 0;
5607f6c1850Smacallan 
561cf4b16e0Smacallan 	case WSDISPLAYIO_GINFO:
562cf4b16e0Smacallan 		if (ms == NULL)
563cf4b16e0Smacallan 			return ENODEV;
564cf4b16e0Smacallan 		wdf = (void *)data;
565cf4b16e0Smacallan 		wdf->height = ms->scr_ri.ri_height;
566f7add90dSriastradh 		wdf->width = sc->sc_24bit ? ms->scr_ri.ri_width << 2
567f7add90dSriastradh 		    : ms->scr_ri.ri_width;
568cf4b16e0Smacallan 		wdf->depth = ms->scr_ri.ri_depth;
569cf4b16e0Smacallan 		wdf->cmsize = 256;
570cf4b16e0Smacallan 		return 0;
571cf4b16e0Smacallan 
572cf4b16e0Smacallan 	case WSDISPLAYIO_GETCMAP:
573cf4b16e0Smacallan 		return hyperfb_getcmap(sc,
574cf4b16e0Smacallan 		    (struct wsdisplay_cmap *)data);
575cf4b16e0Smacallan 
576cf4b16e0Smacallan 	case WSDISPLAYIO_PUTCMAP:
577cf4b16e0Smacallan 		return hyperfb_putcmap(sc,
578cf4b16e0Smacallan 		    (struct wsdisplay_cmap *)data);
579cf4b16e0Smacallan 	case WSDISPLAYIO_LINEBYTES:
580aee609b2Smacallan 		*(u_int *)data = sc->sc_24bit ? 8192 : 2048;
581cf4b16e0Smacallan 		return 0;
582cf4b16e0Smacallan 
583cf4b16e0Smacallan 	case WSDISPLAYIO_SMODE: {
584cf4b16e0Smacallan 		int new_mode = *(int*)data;
585cf4b16e0Smacallan 		if (new_mode != sc->sc_mode) {
586cf4b16e0Smacallan 			sc->sc_mode = new_mode;
587cf4b16e0Smacallan 			if (new_mode == WSDISPLAYIO_MODE_EMUL) {
588cf4b16e0Smacallan 				hyperfb_setup(sc);
589cf4b16e0Smacallan 				hyperfb_restore_palette(sc);
590cf4b16e0Smacallan #if 0
591cf4b16e0Smacallan 				glyphcache_wipe(&sc->sc_gc);
5927d0f5abeSmacallan #endif
593cf4b16e0Smacallan 				hyperfb_rectfill(sc, 0, 0, sc->sc_width,
594cf4b16e0Smacallan 				    sc->sc_height, ms->scr_ri.ri_devcmap[
595cf4b16e0Smacallan 				    (ms->scr_defattr >> 16) & 0xff]);
596cf4b16e0Smacallan 				vcons_redraw_screen(ms);
597cf4b16e0Smacallan 				hyperfb_set_video(sc, 1);
598aee609b2Smacallan 			} else {
599aee609b2Smacallan 				hyperfb_setup(sc);
600aee609b2Smacallan 				hyperfb_rectfill(sc, 0, 0, sc->sc_width,
601aee609b2Smacallan 				    sc->sc_height, 0xff);
602aee609b2Smacallan 				hyperfb_setup_fb24(sc);
603cf4b16e0Smacallan 			}
604cf4b16e0Smacallan 		}
605cf4b16e0Smacallan 		}
606cf4b16e0Smacallan 		return 0;
607cf4b16e0Smacallan 
608f7add90dSriastradh 	case WSDISPLAYIO_GET_FBINFO: {
609cf4b16e0Smacallan 		struct wsdisplayio_fbinfo *fbi = data;
610cf4b16e0Smacallan 		int ret;
611cf4b16e0Smacallan 
612cf4b16e0Smacallan 		ret = wsdisplayio_get_fbinfo(&ms->scr_ri, fbi);
613cf4b16e0Smacallan 		fbi->fbi_fbsize = sc->sc_height * 2048;
614aee609b2Smacallan 		if (sc->sc_24bit) {
615aee609b2Smacallan 			fbi->fbi_stride = 8192;
616aee609b2Smacallan 			fbi->fbi_bitsperpixel = 32;
617aee609b2Smacallan 			fbi->fbi_pixeltype = WSFB_RGB;
618aee609b2Smacallan 			fbi->fbi_subtype.fbi_rgbmasks.red_offset = 16;
619aee609b2Smacallan 			fbi->fbi_subtype.fbi_rgbmasks.red_size = 8;
620aee609b2Smacallan 			fbi->fbi_subtype.fbi_rgbmasks.green_offset = 8;
621aee609b2Smacallan 			fbi->fbi_subtype.fbi_rgbmasks.green_size = 8;
622aee609b2Smacallan 			fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 0;
623aee609b2Smacallan 			fbi->fbi_subtype.fbi_rgbmasks.blue_size = 8;
624aee609b2Smacallan 			fbi->fbi_subtype.fbi_rgbmasks.alpha_size = 0;
625aee609b2Smacallan 				fbi->fbi_fbsize = sc->sc_height * 8192;
626aee609b2Smacallan 		}
627cf4b16e0Smacallan 		return ret;
628cf4b16e0Smacallan 	}
629cf4b16e0Smacallan 
630f7add90dSriastradh 	case WSDISPLAYIO_GCURPOS: {
631cf4b16e0Smacallan 		struct wsdisplay_curpos *cp = (void *)data;
632cf4b16e0Smacallan 
633cf4b16e0Smacallan 		cp->x = sc->sc_cursor_x;
634cf4b16e0Smacallan 		cp->y = sc->sc_cursor_y;
635cf4b16e0Smacallan 	}
636cf4b16e0Smacallan 		return 0;
637cf4b16e0Smacallan 
638f7add90dSriastradh 	case WSDISPLAYIO_SCURPOS: {
639cf4b16e0Smacallan 		struct wsdisplay_curpos *cp = (void *)data;
640cf4b16e0Smacallan 
6417d0f5abeSmacallan 		hyperfb_move_cursor(sc, cp->x, cp->y);
642cf4b16e0Smacallan 	}
643cf4b16e0Smacallan 		return 0;
644cf4b16e0Smacallan 
645f7add90dSriastradh 	case WSDISPLAYIO_GCURMAX: {
646cf4b16e0Smacallan 		struct wsdisplay_curpos *cp = (void *)data;
647cf4b16e0Smacallan 
648cf4b16e0Smacallan 		cp->x = 64;
649cf4b16e0Smacallan 		cp->y = 64;
650cf4b16e0Smacallan 	}
651cf4b16e0Smacallan 		return 0;
652cf4b16e0Smacallan 
653f7add90dSriastradh 	case WSDISPLAYIO_SCURSOR: {
654cf4b16e0Smacallan 		struct wsdisplay_cursor *cursor = (void *)data;
655cf4b16e0Smacallan 
6567d0f5abeSmacallan 		return hyperfb_do_cursor(sc, cursor);
657cf4b16e0Smacallan 	}
658cf4b16e0Smacallan 
659cf4b16e0Smacallan 	case WSDISPLAYIO_SVIDEO:
660cf4b16e0Smacallan 		hyperfb_set_video(sc, *(int *)data);
661cf4b16e0Smacallan 		return 0;
662cf4b16e0Smacallan 	case WSDISPLAYIO_GVIDEO:
6631aa0b529Smacallan 		*(u_int *)data = sc->sc_video_on ?
664cf4b16e0Smacallan 		    WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF;
6651aa0b529Smacallan 		return 0;
666cf4b16e0Smacallan 	}
667cf4b16e0Smacallan 	return EPASSTHROUGH;
668cf4b16e0Smacallan }
669cf4b16e0Smacallan 
670cf4b16e0Smacallan static paddr_t
671cf4b16e0Smacallan hyperfb_mmap(void *v, void *vs, off_t offset, int prot)
672cf4b16e0Smacallan {
673cf4b16e0Smacallan 	struct vcons_data *vd = v;
674cf4b16e0Smacallan 	struct hyperfb_softc *sc = vd->cookie;
675cf4b16e0Smacallan 	paddr_t pa = -1;
676cf4b16e0Smacallan 
677cf4b16e0Smacallan 
678cf4b16e0Smacallan 	if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)
679cf4b16e0Smacallan 		return -1;
680cf4b16e0Smacallan 
681e229c7a9Smacallan 	/* GSC framebuffer space is 16MB */
682e229c7a9Smacallan 	if (offset >= 0 && offset < 0x1000000) {
683cf4b16e0Smacallan 		/* framebuffer */
684f7add90dSriastradh 		pa = bus_space_mmap(sc->sc_iot, sc->sc_base + HCRX_FBOFFSET,
685f7add90dSriastradh 		    offset, prot,
686f7add90dSriastradh 		    BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE);
687f020d495Smacallan 	} else if (offset >= 0x80000000 && offset < 0x80400000) {
688cf4b16e0Smacallan 		/* blitter registers etc. */
689cf4b16e0Smacallan 		pa = bus_space_mmap(sc->sc_iot, sc->sc_base + HCRX_REGOFFSET,
690cf4b16e0Smacallan 		    offset - 0x80000000, prot, BUS_SPACE_MAP_LINEAR);
691cf4b16e0Smacallan 	}
692cf4b16e0Smacallan 
693cf4b16e0Smacallan 	return pa;
694cf4b16e0Smacallan }
695cf4b16e0Smacallan 
696cf4b16e0Smacallan static int
697cf4b16e0Smacallan hyperfb_putcmap(struct hyperfb_softc *sc, struct wsdisplay_cmap *cm)
698cf4b16e0Smacallan {
699cf4b16e0Smacallan 	u_char *r, *g, *b;
700cf4b16e0Smacallan 	u_int index = cm->index;
701cf4b16e0Smacallan 	u_int count = cm->count;
702cf4b16e0Smacallan 	int i, error;
703cf4b16e0Smacallan 	u_char rbuf[256], gbuf[256], bbuf[256];
704cf4b16e0Smacallan 
705cf4b16e0Smacallan 	if (cm->index >= 256 || cm->count > 256 ||
706cf4b16e0Smacallan 	    (cm->index + cm->count) > 256)
707cf4b16e0Smacallan 		return EINVAL;
708cf4b16e0Smacallan 	error = copyin(cm->red, &rbuf[index], count);
709cf4b16e0Smacallan 	if (error)
710cf4b16e0Smacallan 		return error;
711cf4b16e0Smacallan 	error = copyin(cm->green, &gbuf[index], count);
712cf4b16e0Smacallan 	if (error)
713cf4b16e0Smacallan 		return error;
714cf4b16e0Smacallan 	error = copyin(cm->blue, &bbuf[index], count);
715cf4b16e0Smacallan 	if (error)
716cf4b16e0Smacallan 		return error;
717cf4b16e0Smacallan 
718cf4b16e0Smacallan 	memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
719cf4b16e0Smacallan 	memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
720cf4b16e0Smacallan 	memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
721cf4b16e0Smacallan 
722cf4b16e0Smacallan 	r = &sc->sc_cmap_red[index];
723cf4b16e0Smacallan 	g = &sc->sc_cmap_green[index];
724cf4b16e0Smacallan 	b = &sc->sc_cmap_blue[index];
725cf4b16e0Smacallan 
726cf4b16e0Smacallan 	for (i = 0; i < count; i++) {
727cf4b16e0Smacallan 		hyperfb_putpalreg(sc, index, *r, *g, *b);
728cf4b16e0Smacallan 		index++;
729cf4b16e0Smacallan 		r++, g++, b++;
730cf4b16e0Smacallan 	}
731cf4b16e0Smacallan 	return 0;
732cf4b16e0Smacallan }
733cf4b16e0Smacallan 
734cf4b16e0Smacallan static int
735cf4b16e0Smacallan hyperfb_getcmap(struct hyperfb_softc *sc, struct wsdisplay_cmap *cm)
736cf4b16e0Smacallan {
737cf4b16e0Smacallan 	u_int index = cm->index;
738cf4b16e0Smacallan 	u_int count = cm->count;
739cf4b16e0Smacallan 	int error;
740cf4b16e0Smacallan 
741cf4b16e0Smacallan 	if (index >= 255 || count > 256 || index + count > 256)
742cf4b16e0Smacallan 		return EINVAL;
743cf4b16e0Smacallan 
744cf4b16e0Smacallan 	error = copyout(&sc->sc_cmap_red[index],   cm->red,   count);
745cf4b16e0Smacallan 	if (error)
746cf4b16e0Smacallan 		return error;
747cf4b16e0Smacallan 	error = copyout(&sc->sc_cmap_green[index], cm->green, count);
748cf4b16e0Smacallan 	if (error)
749cf4b16e0Smacallan 		return error;
750cf4b16e0Smacallan 	error = copyout(&sc->sc_cmap_blue[index],  cm->blue,  count);
751cf4b16e0Smacallan 	if (error)
752cf4b16e0Smacallan 		return error;
753cf4b16e0Smacallan 
754cf4b16e0Smacallan 	return 0;
755cf4b16e0Smacallan }
756cf4b16e0Smacallan 
757cf4b16e0Smacallan static void
758cf4b16e0Smacallan hyperfb_restore_palette(struct hyperfb_softc *sc)
759cf4b16e0Smacallan {
760cf4b16e0Smacallan 	uint8_t cmap[768];
761cf4b16e0Smacallan 	int i, j;
762cf4b16e0Smacallan 
763cf4b16e0Smacallan 	j = 0;
764cf4b16e0Smacallan 	rasops_get_cmap(&sc->sc_console_screen.scr_ri, cmap, sizeof(cmap));
765cf4b16e0Smacallan 	for (i = 0; i < 256; i++) {
766cf4b16e0Smacallan 		sc->sc_cmap_red[i] = cmap[j];
767cf4b16e0Smacallan 		sc->sc_cmap_green[i] = cmap[j + 1];
768cf4b16e0Smacallan 		sc->sc_cmap_blue[i] = cmap[j + 2];
769cf4b16e0Smacallan 		hyperfb_putpalreg(sc, i, cmap[j], cmap[j + 1], cmap[j + 2]);
770cf4b16e0Smacallan 		j += 3;
771cf4b16e0Smacallan 	}
772cf4b16e0Smacallan }
773cf4b16e0Smacallan 
774cf4b16e0Smacallan static int
775cf4b16e0Smacallan hyperfb_putpalreg(struct hyperfb_softc *sc, uint8_t idx, uint8_t r, uint8_t g,
776cf4b16e0Smacallan     uint8_t b)
777cf4b16e0Smacallan {
778cf4b16e0Smacallan 
779cf4b16e0Smacallan 	mutex_enter(&sc->sc_hwlock);
780cf4b16e0Smacallan 	hyperfb_wait(sc);
781cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_10, 0xbbe0f000);
782cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_14, 0x03000300);
783cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_13, 0xffffffff);
784cf4b16e0Smacallan 
785cf4b16e0Smacallan 	hyperfb_wait(sc);
786cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_3, 0x400 | (idx << 2));
787cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_4, (r << 16) | (g << 8) | b);
788cf4b16e0Smacallan 
789cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_2, 0x400);
790cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_38, 0x82000100);
791cf4b16e0Smacallan 	hyperfb_setup_fb(sc);
792cf4b16e0Smacallan 	mutex_exit(&sc->sc_hwlock);
793cf4b16e0Smacallan 	return 0;
794cf4b16e0Smacallan }
795cf4b16e0Smacallan 
796cf4b16e0Smacallan void
797cf4b16e0Smacallan hyperfb_setup(struct hyperfb_softc *sc)
798cf4b16e0Smacallan {
799cf4b16e0Smacallan 	int i;
800cf4b16e0Smacallan 	uint32_t reg;
801cf4b16e0Smacallan 
802cf4b16e0Smacallan 	sc->sc_hwmode = HW_FB;
803cf4b16e0Smacallan 	sc->sc_hot_x = 0;
804cf4b16e0Smacallan 	sc->sc_hot_y = 0;
805cf4b16e0Smacallan 	sc->sc_enabled = 0;
806cf4b16e0Smacallan 	sc->sc_video_on = 1;
807cf4b16e0Smacallan 
808cf4b16e0Smacallan 	/* set Bt458 read mask register to all planes */
809cf4b16e0Smacallan 	/* XXX I'm not sure HCRX even has one of these */
810cf4b16e0Smacallan 	hyperfb_wait(sc);
811cf4b16e0Smacallan 	ngle_bt458_write(sc, 0x08, 0x04);
812cf4b16e0Smacallan 	ngle_bt458_write(sc, 0x0a, 0xff);
813cf4b16e0Smacallan 
814cf4b16e0Smacallan 	reg = hyperfb_read4(sc, NGLE_REG_32);
815cf4b16e0Smacallan 	DPRINTF("planereg %08x\n", reg);
816aee609b2Smacallan 	hyperfb_write4(sc, NGLE_REG_32, 0xffffffff);
817cf4b16e0Smacallan 
818cf4b16e0Smacallan 	/* hyperbowl */
819cf4b16e0Smacallan 	hyperfb_wait(sc);
820cf4b16e0Smacallan 	if (sc->sc_24bit) {
821cf4b16e0Smacallan 		/* write must happen twice because hw bug */
822f7add90dSriastradh 		hyperfb_write4(sc, NGLE_REG_40,
823f7add90dSriastradh 		    HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE);
824f7add90dSriastradh 		hyperfb_write4(sc, NGLE_REG_40,
825f7add90dSriastradh 		    HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE);
826cf4b16e0Smacallan 		hyperfb_write4(sc, NGLE_REG_39, HYPERBOWL_MODE2_8_24);
827f7add90dSriastradh 		/* Set lut 0 to be the direct color */
828f7add90dSriastradh 		hyperfb_write4(sc, NGLE_REG_42, 0x014c0148);
829cf4b16e0Smacallan 		hyperfb_write4(sc, NGLE_REG_43, 0x404c4048);
830cf4b16e0Smacallan 		hyperfb_write4(sc, NGLE_REG_44, 0x034c0348);
831cf4b16e0Smacallan 		hyperfb_write4(sc, NGLE_REG_45, 0x444c4448);
832cf4b16e0Smacallan 	} else {
833f7add90dSriastradh 		hyperfb_write4(sc, NGLE_REG_40,
834f7add90dSriastradh 		    HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES);
835f7add90dSriastradh 		hyperfb_write4(sc, NGLE_REG_40,
836f7add90dSriastradh 		    HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES);
837cf4b16e0Smacallan 
838cf4b16e0Smacallan 		hyperfb_write4(sc, NGLE_REG_42, 0);
839cf4b16e0Smacallan 		hyperfb_write4(sc, NGLE_REG_43, 0);
840cf4b16e0Smacallan 		hyperfb_write4(sc, NGLE_REG_44, 0);
841aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_45, 0x444c4048);
842cf4b16e0Smacallan 	}
843aee609b2Smacallan 
844aee609b2Smacallan 	/* attr. planes */
845aee609b2Smacallan 	hyperfb_wait(sc);
846aee609b2Smacallan 	hyperfb_write4(sc, NGLE_REG_11,
847aee609b2Smacallan 	    BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, 0, BINattr, 0));
848aee609b2Smacallan 	hyperfb_write4(sc, NGLE_REG_14,
849aee609b2Smacallan 	    IBOvals(RopSrc, 0, BitmapExtent08, 1, DataDynamic, MaskOtc, 1, 0));
850aee609b2Smacallan 	hyperfb_write4(sc, NGLE_REG_12, 0x04000F00/*NGLE_BUFF0_CMAP0*/);
851aee609b2Smacallan 	hyperfb_write4(sc, NGLE_REG_8, 0xffffffff);
852aee609b2Smacallan 
853aee609b2Smacallan 	hyperfb_wait(sc);
854aee609b2Smacallan 	hyperfb_write4(sc, NGLE_REG_6, 0x00000000);
855aee609b2Smacallan 	hyperfb_write4(sc, NGLE_REG_9,
856aee609b2Smacallan 	    (sc->sc_width << 16) | sc->sc_height);
857aee609b2Smacallan 	/*
858aee609b2Smacallan 	 * blit into offscreen memory to force flush previous - apparently
859aee609b2Smacallan 	 * some chips have a bug this works around
860aee609b2Smacallan 	 */
861aee609b2Smacallan 	hyperfb_wait(sc);
862aee609b2Smacallan 	hyperfb_write4(sc, NGLE_REG_6, 0x05000000);
863aee609b2Smacallan 	hyperfb_write4(sc, NGLE_REG_9, 0x00040001);
864aee609b2Smacallan 
865aee609b2Smacallan 	/*
866aee609b2Smacallan 	 * on 24bit-capable hardware we:
867aee609b2Smacallan 	 * - make overlay colour 255 transparent
868aee609b2Smacallan 	 * - blit the 24bit buffer all white
869aee609b2Smacallan 	 * - install a linear ramp in CMAP 0
870aee609b2Smacallan 	 */
871aee609b2Smacallan 	if (sc->sc_24bit) {
872aee609b2Smacallan 		/* overlay transparency */
873aee609b2Smacallan 		hyperfb_wait_fifo(sc, 7);
87415644928Smacallan 		hyperfb_write4(sc, NGLE_REG_11,
87515644928Smacallan 		    BA(IndexedDcd, Otc04, Ots08, AddrLong, 0, BINovly, 0));
876aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_14, 0x03000300);
877aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_3, 0x000017f0);
878aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_13, 0xffffffff);
879aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_22, 0xffffffff);
880aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_23, 0x0);
881aee609b2Smacallan 
882aee609b2Smacallan 		hyperfb_wait(sc);
883aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_12, 0x00000000);
884aee609b2Smacallan 
885aee609b2Smacallan 		/* clear 24bit buffer */
886aee609b2Smacallan 		hyperfb_wait(sc);
887aee609b2Smacallan 		/* plane mask */
888aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_13, 0xffffffff);
889aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_8, 0xffffffff); /* transfer data */
890aee609b2Smacallan 		/* bitmap op */
891aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_14,
892f7add90dSriastradh 		    IBOvals(RopSrc, 0, BitmapExtent32, 0, DataDynamic, MaskOtc,
893f7add90dSriastradh 			0, 0));
894aee609b2Smacallan 		/* dst bitmap access */
895aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_11,
896*64ffcac2Smacallan 		    BA(FractDcd, Otc32, OtsIndirect, AddrLong, 0, BINapp0F8,
897f7add90dSriastradh 			0));
898aee609b2Smacallan 		hyperfb_wait_fifo(sc, 3);
899aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_35, 0x00ffffff);	/* fg colour */
900aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_6, 0x00000000);	/* dst xy */
901aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_9,
902aee609b2Smacallan 		    (sc->sc_width << 16) | sc->sc_height);
903aee609b2Smacallan 
904aee609b2Smacallan 		/* write a linear ramp into CMAP0 */
905aee609b2Smacallan 		hyperfb_wait(sc);
906aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_10, 0xbbe0f000);
907aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_14, 0x03000300);
908aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_13, 0xffffffff);
909aee609b2Smacallan 
910aee609b2Smacallan 		hyperfb_wait(sc);
911aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_3, 0);
912aee609b2Smacallan 		for (i = 0; i < 256; i++) {
913aee609b2Smacallan 			hyperfb_wait(sc);
914f7add90dSriastradh 			hyperfb_write4(sc, NGLE_REG_4,
915f7add90dSriastradh 			    (i << 16) | (i << 8) | i);
916aee609b2Smacallan 		}
917aee609b2Smacallan 		hyperfb_write4(sc, NGLE_REG_2, 0x0);
918f7add90dSriastradh 		hyperfb_write4(sc, NGLE_REG_38,
919f7add90dSriastradh 		    LBC_ENABLE | LBC_TYPE_CMAP | 0x100);
920aee609b2Smacallan 		hyperfb_wait(sc);
921aee609b2Smacallan 	}
922aee609b2Smacallan 
923aee609b2Smacallan 	hyperfb_setup_fb(sc);
924aee609b2Smacallan 
925aee609b2Smacallan 	/* make sure video output is enabled */
926aee609b2Smacallan 	hyperfb_wait(sc);
927aee609b2Smacallan 	hyperfb_write4(sc, NGLE_REG_33,
928aee609b2Smacallan 	    hyperfb_read4(sc, NGLE_REG_33) | 0x0a000000);
929aee609b2Smacallan 
930cf4b16e0Smacallan 	/* cursor mask */
931cf4b16e0Smacallan 	hyperfb_wait(sc);
932cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_30, 0);
933cf4b16e0Smacallan 	for (i = 0; i < 64; i++) {
934cf4b16e0Smacallan 		hyperfb_write4(sc, NGLE_REG_31, 0xffffffff);
935cf4b16e0Smacallan 		hyperfb_write4(sc, NGLE_REG_31, 0xffffffff);
936cf4b16e0Smacallan 	}
937cf4b16e0Smacallan 
938cf4b16e0Smacallan 	/* cursor image */
939cf4b16e0Smacallan 	hyperfb_wait(sc);
940cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_30, 0x80);
941cf4b16e0Smacallan 	for (i = 0; i < 64; i++) {
942cf4b16e0Smacallan 		hyperfb_write4(sc, NGLE_REG_31, 0xff00ff00);
943cf4b16e0Smacallan 		hyperfb_write4(sc, NGLE_REG_31, 0xff00ff00);
944cf4b16e0Smacallan 	}
945cf4b16e0Smacallan 
946aee609b2Smacallan 	/* colour map */
947cf4b16e0Smacallan 	hyperfb_wait(sc);
948cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_10, 0xBBE0F000);
949cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_14, 0x03000300);
950cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_13, 0xffffffff);
951cf4b16e0Smacallan 	hyperfb_wait(sc);
952cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_3, 0);
953cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_4, 0x000000ff);	/* BG */
954cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_4, 0x00ff0000);	/* FG */
955cf4b16e0Smacallan 	hyperfb_wait(sc);
956cf4b16e0Smacallan 	hyperfb_write4(sc, NGLE_REG_2, 0);
957357dd059Smacallan 	hyperfb_write4(sc, NGLE_REG_38, LBC_ENABLE | LBC_TYPE_CURSOR | 4);
958cf4b16e0Smacallan 	hyperfb_setup_fb(sc);
959cf4b16e0Smacallan 
960357dd059Smacallan 	hyperfb_move_cursor(sc, 100, 100);
961cf4b16e0Smacallan }
962cf4b16e0Smacallan 
963cf4b16e0Smacallan static void
964cf4b16e0Smacallan hyperfb_set_video(struct hyperfb_softc *sc, int on)
965cf4b16e0Smacallan {
966cf4b16e0Smacallan 	uint32_t reg;
967cf4b16e0Smacallan 
968cf4b16e0Smacallan 	if (sc->sc_video_on == on)
969cf4b16e0Smacallan 		return;
970cf4b16e0Smacallan 
971cf4b16e0Smacallan 	sc->sc_video_on = on;
972cf4b16e0Smacallan 
973cf4b16e0Smacallan 	hyperfb_wait(sc);
974cf4b16e0Smacallan 	reg = hyperfb_read4(sc, NGLE_REG_33);
975cf4b16e0Smacallan 
976cf4b16e0Smacallan 	if (on) {
977357dd059Smacallan 		hyperfb_write4(sc, NGLE_REG_33, reg | HCRX_VIDEO_ENABLE);
978cf4b16e0Smacallan 	} else {
979357dd059Smacallan 		hyperfb_write4(sc, NGLE_REG_33, reg & ~HCRX_VIDEO_ENABLE);
980cf4b16e0Smacallan 	}
981cf4b16e0Smacallan }
9827d0f5abeSmacallan 
9837d0f5abeSmacallan static void
9847d0f5abeSmacallan hyperfb_rectfill(struct hyperfb_softc *sc, int x, int y, int wi, int he,
9857d0f5abeSmacallan     uint32_t bg)
9867d0f5abeSmacallan {
987bb4ea6beSmacallan 	uint32_t mask = 0xffffffff;
988bb4ea6beSmacallan 
9897d0f5abeSmacallan 	/*
9907d0f5abeSmacallan 	 * XXX
991bb4ea6beSmacallan 	 * HCRX and EG both always draw rectangles at least 32 pixels wide
992bb4ea6beSmacallan 	 * for anything narrower we need to set a bit mask and enable
993bb4ea6beSmacallan 	 * transparency
9947d0f5abeSmacallan 	 */
9957d0f5abeSmacallan 
9967d0f5abeSmacallan 	if (sc->sc_hwmode != HW_FILL) {
997bb4ea6beSmacallan 		hyperfb_wait_fifo(sc, 3);
9987d0f5abeSmacallan 		/* plane mask */
9997d0f5abeSmacallan 		hyperfb_write4(sc, NGLE_REG_13, 0xff);
10007d0f5abeSmacallan 		/* bitmap op */
10017d0f5abeSmacallan 		hyperfb_write4(sc, NGLE_REG_14,
1002f7add90dSriastradh 		    IBOvals(RopSrc, 0, BitmapExtent08, 0, DataDynamic, MaskOtc,
1003bb4ea6beSmacallan 			1 /* bg transparent */, 0));
10047d0f5abeSmacallan 		/* dst bitmap access */
10057d0f5abeSmacallan 		hyperfb_write4(sc, NGLE_REG_11,
1006f7add90dSriastradh 		    BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, 0, BINovly,
1007f7add90dSriastradh 			0));
10087d0f5abeSmacallan 		sc->sc_hwmode = HW_FILL;
10097d0f5abeSmacallan 	}
1010bb4ea6beSmacallan 	hyperfb_wait_fifo(sc, 4);
1011bb4ea6beSmacallan 	if (wi < 32)
1012bb4ea6beSmacallan 		mask = 0xffffffff << (32 - wi);
1013bb4ea6beSmacallan 	/*
1014bb4ea6beSmacallan 	 * XXX - the NGLE code calls this 'transfer data'
1015bb4ea6beSmacallan 	 * in reality it's a bit mask applied per pixel,
1016bb4ea6beSmacallan 	 * foreground colour in reg 35, bg in 36
1017bb4ea6beSmacallan 	 */
1018bb4ea6beSmacallan 	hyperfb_write4(sc, NGLE_REG_8, mask);
1019bb4ea6beSmacallan 
10207d0f5abeSmacallan 	hyperfb_write4(sc, NGLE_REG_35, bg);
10217d0f5abeSmacallan 	/* dst XY */
10227d0f5abeSmacallan 	hyperfb_write4(sc, NGLE_REG_6, (x << 16) | y);
10237d0f5abeSmacallan 	/* len XY start */
10247d0f5abeSmacallan 	hyperfb_write4(sc, NGLE_REG_9, (wi << 16) | he);
10257d0f5abeSmacallan }
10267d0f5abeSmacallan 
10277d0f5abeSmacallan static void
10287d0f5abeSmacallan hyperfb_bitblt(void *cookie, int xs, int ys, int xd, int yd, int wi,
10297d0f5abeSmacallan     int he, int rop)
10307d0f5abeSmacallan {
10317d0f5abeSmacallan 	struct hyperfb_softc *sc = cookie;
10327d0f5abeSmacallan 
10337d0f5abeSmacallan 	if (sc->sc_hwmode != HW_BLIT) {
10347d0f5abeSmacallan 		hyperfb_wait(sc);
103515644928Smacallan 		hyperfb_write4(sc, NGLE_REG_10,
103615644928Smacallan 		    BA(IndexedDcd, Otc04, Ots08, AddrLong, 0, BINovly, 0));
10377d0f5abeSmacallan 		hyperfb_write4(sc, NGLE_REG_13, 0xff);
10387d0f5abeSmacallan 		sc->sc_hwmode = HW_BLIT;
10397d0f5abeSmacallan 	}
10407d0f5abeSmacallan 	hyperfb_wait_fifo(sc, 4);
10417d0f5abeSmacallan 	hyperfb_write4(sc, NGLE_REG_14, ((rop << 8) & 0xf00) | 0x23000000);
10427d0f5abeSmacallan 	/* IBOvals(rop, 0, BitmapExtent08, 1, DataDynamic, MaskOtc, 0, 0) */
10437d0f5abeSmacallan 	hyperfb_write4(sc, NGLE_REG_24, (xs << 16) | ys);
10447d0f5abeSmacallan 	hyperfb_write4(sc, NGLE_REG_7, (wi << 16) | he);
10457d0f5abeSmacallan 	hyperfb_write4(sc, NGLE_REG_25, (xd << 16) | yd);
10467d0f5abeSmacallan }
10477d0f5abeSmacallan 
10487d0f5abeSmacallan static void
10497d0f5abeSmacallan hyperfb_nuke_cursor(struct rasops_info *ri)
10507d0f5abeSmacallan {
10517d0f5abeSmacallan 	struct vcons_screen *scr = ri->ri_hw;
10527d0f5abeSmacallan 	struct hyperfb_softc *sc = scr->scr_cookie;
10537d0f5abeSmacallan 	int wi, he, x, y;
10547d0f5abeSmacallan 
10557d0f5abeSmacallan 	if (ri->ri_flg & RI_CURSOR) {
10567d0f5abeSmacallan 		wi = ri->ri_font->fontwidth;
10577d0f5abeSmacallan 		he = ri->ri_font->fontheight;
10587d0f5abeSmacallan 		x = ri->ri_ccol * wi + ri->ri_xorigin;
10597d0f5abeSmacallan 		y = ri->ri_crow * he + ri->ri_yorigin;
10607d0f5abeSmacallan 		hyperfb_bitblt(sc, x, y, x, y, wi, he, RopInv);
10617d0f5abeSmacallan 		ri->ri_flg &= ~RI_CURSOR;
10627d0f5abeSmacallan 	}
10637d0f5abeSmacallan }
10647d0f5abeSmacallan 
10657d0f5abeSmacallan static void
10667d0f5abeSmacallan hyperfb_cursor(void *cookie, int on, int row, int col)
10677d0f5abeSmacallan {
10687d0f5abeSmacallan 	struct rasops_info *ri = cookie;
10697d0f5abeSmacallan 	struct vcons_screen *scr = ri->ri_hw;
10707d0f5abeSmacallan 	struct hyperfb_softc *sc = scr->scr_cookie;
10717d0f5abeSmacallan 	int x, y, wi, he;
10727d0f5abeSmacallan 
10737d0f5abeSmacallan 	wi = ri->ri_font->fontwidth;
10747d0f5abeSmacallan 	he = ri->ri_font->fontheight;
10757d0f5abeSmacallan 
10767d0f5abeSmacallan 	if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
10777d0f5abeSmacallan 		if (on) {
10787d0f5abeSmacallan 			if (ri->ri_flg & RI_CURSOR) {
10797d0f5abeSmacallan 				hyperfb_nuke_cursor(ri);
10807d0f5abeSmacallan 			}
10817d0f5abeSmacallan 			x = col * wi + ri->ri_xorigin;
10827d0f5abeSmacallan 			y = row * he + ri->ri_yorigin;
10837d0f5abeSmacallan 			hyperfb_bitblt(sc, x, y, x, y, wi, he, RopInv);
10847d0f5abeSmacallan 			ri->ri_flg |= RI_CURSOR;
10857d0f5abeSmacallan 		}
10867d0f5abeSmacallan 		ri->ri_crow = row;
10877d0f5abeSmacallan 		ri->ri_ccol = col;
1088f7add90dSriastradh 	} else {
10897d0f5abeSmacallan 		ri->ri_crow = row;
10907d0f5abeSmacallan 		ri->ri_ccol = col;
10917d0f5abeSmacallan 		ri->ri_flg &= ~RI_CURSOR;
10927d0f5abeSmacallan 	}
10937d0f5abeSmacallan }
10947d0f5abeSmacallan 
10957d0f5abeSmacallan static void
10967d0f5abeSmacallan hyperfb_putchar(void *cookie, int row, int col, u_int c, long attr)
10977d0f5abeSmacallan {
10987d0f5abeSmacallan 	struct rasops_info *ri = cookie;
10997d0f5abeSmacallan 	struct wsdisplay_font *font = PICK_FONT(ri, c);
11007d0f5abeSmacallan 	struct vcons_screen *scr = ri->ri_hw;
11017d0f5abeSmacallan 	struct hyperfb_softc *sc = scr->scr_cookie;
1102a74af143Smacallan 	void *data;
110302a20feaSmacallan 	int i, x, y, wi, he/*, rv = GC_NOPE*/;
110402a20feaSmacallan 	uint32_t bg, fg, mask;
11057d0f5abeSmacallan 
11067d0f5abeSmacallan 	if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL)
11077d0f5abeSmacallan 		return;
11087d0f5abeSmacallan 
11097d0f5abeSmacallan 	if (!CHAR_IN_FONT(c, font))
11107d0f5abeSmacallan 		return;
11117d0f5abeSmacallan 
11127d0f5abeSmacallan 	if (row == ri->ri_crow && col == ri->ri_ccol) {
11137d0f5abeSmacallan 		ri->ri_flg &= ~RI_CURSOR;
11147d0f5abeSmacallan 	}
11157d0f5abeSmacallan 
11167d0f5abeSmacallan 	wi = font->fontwidth;
11177d0f5abeSmacallan 	he = font->fontheight;
11187d0f5abeSmacallan 
11197d0f5abeSmacallan 	x = ri->ri_xorigin + col * wi;
11207d0f5abeSmacallan 	y = ri->ri_yorigin + row * he;
11217d0f5abeSmacallan 
11227d0f5abeSmacallan 	bg = ri->ri_devcmap[(attr >> 16) & 0xf];
112302a20feaSmacallan 	fg = ri->ri_devcmap[(attr >> 24) & 0x0f];
11247d0f5abeSmacallan 
112502a20feaSmacallan 	/* clear the character cell */
11267d0f5abeSmacallan 	hyperfb_rectfill(sc, x, y, wi, he, bg);
112702a20feaSmacallan 
112802a20feaSmacallan 	/* if we're drawing a space we're done here */
112902a20feaSmacallan 	if (c == 0x20)
11307d0f5abeSmacallan 		return;
11317d0f5abeSmacallan 
11327d0f5abeSmacallan #if 0
11337d0f5abeSmacallan 	rv = glyphcache_try(&sc->sc_gc, c, x, y, attr);
11347d0f5abeSmacallan 	if (rv == GC_OK)
11357d0f5abeSmacallan 		return;
11367d0f5abeSmacallan #endif
113702a20feaSmacallan 
113802a20feaSmacallan 	data = WSFONT_GLYPH(c, font);
113902a20feaSmacallan 
114002a20feaSmacallan 	hyperfb_wait_fifo(sc, 2);
114102a20feaSmacallan 
114202a20feaSmacallan 	/* character colour */
114302a20feaSmacallan 	hyperfb_write4(sc, NGLE_REG_35, fg);
114402a20feaSmacallan 	/* dst XY */
114502a20feaSmacallan 	hyperfb_write4(sc, NGLE_REG_6, (x << 16) | y);
114602a20feaSmacallan 
114702a20feaSmacallan 	/*
114802a20feaSmacallan 	 * drawing a rectangle moves the starting coordinates down the
114902a20feaSmacallan 	 * y-axis so we can just hammer the wi/he register to draw a full
115002a20feaSmacallan 	 * character
115102a20feaSmacallan 	 */
115202a20feaSmacallan 	if (ri->ri_font->stride == 1) {
1153a74af143Smacallan 		uint8_t *data8 = data;
115402a20feaSmacallan 		for (i = 0; i < he; i++) {
115502a20feaSmacallan 			hyperfb_wait_fifo(sc, 2);
1156a74af143Smacallan 			mask = *data8;
1157a74af143Smacallan 			hyperfb_write4(sc, NGLE_REG_8, mask << 24);
115802a20feaSmacallan 			hyperfb_write4(sc, NGLE_REG_9, (wi << 16) | 1);
1159a74af143Smacallan 			data8++;
116002a20feaSmacallan 		}
116102a20feaSmacallan 	} else {
1162a74af143Smacallan 		uint16_t *data16 = data;
116302a20feaSmacallan 		for (i = 0; i < he; i++) {
116402a20feaSmacallan 			hyperfb_wait_fifo(sc, 2);
1165a74af143Smacallan 			mask = *data16;
116602a20feaSmacallan 			hyperfb_write4(sc, NGLE_REG_8, mask << 16);
116702a20feaSmacallan 			hyperfb_write4(sc, NGLE_REG_9, (wi << 16) | 1);
1168a74af143Smacallan 			data16++;
116902a20feaSmacallan 		}
117002a20feaSmacallan 	}
11717d0f5abeSmacallan #if 0
11727d0f5abeSmacallan 	if (rv == GC_ADD)
11737d0f5abeSmacallan 		glyphcache_add(&sc->sc_gc, c, x, y);
11747d0f5abeSmacallan #endif
11757d0f5abeSmacallan }
11767d0f5abeSmacallan 
11777d0f5abeSmacallan static void
11787d0f5abeSmacallan hyperfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
11797d0f5abeSmacallan {
11807d0f5abeSmacallan 	struct rasops_info *ri = cookie;
11817d0f5abeSmacallan 	struct vcons_screen *scr = ri->ri_hw;
11827d0f5abeSmacallan 	struct hyperfb_softc *sc = scr->scr_cookie;
11837d0f5abeSmacallan 	int32_t xs, xd, y, width, height;
11847d0f5abeSmacallan 
11857d0f5abeSmacallan 	if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
11867d0f5abeSmacallan 		if (ri->ri_crow == row &&
11877d0f5abeSmacallan 		   (ri->ri_ccol >= srccol && ri->ri_ccol < (srccol + ncols)) &&
11887d0f5abeSmacallan 		   (ri->ri_flg & RI_CURSOR)) {
11897d0f5abeSmacallan 			hyperfb_nuke_cursor(ri);
11907d0f5abeSmacallan 		}
11917d0f5abeSmacallan 
11927d0f5abeSmacallan 		xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol;
11937d0f5abeSmacallan 		xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol;
11947d0f5abeSmacallan 		y = ri->ri_yorigin + ri->ri_font->fontheight * row;
11957d0f5abeSmacallan 		width = ri->ri_font->fontwidth * ncols;
11967d0f5abeSmacallan 		height = ri->ri_font->fontheight;
11977d0f5abeSmacallan 		hyperfb_bitblt(sc, xs, y, xd, y, width, height, RopSrc);
11987d0f5abeSmacallan 		if (ri->ri_crow == row &&
11997d0f5abeSmacallan 		   (ri->ri_ccol >= dstcol && ri->ri_ccol < (dstcol + ncols)))
12007d0f5abeSmacallan 			ri->ri_flg &= ~RI_CURSOR;
12017d0f5abeSmacallan 	}
12027d0f5abeSmacallan }
12037d0f5abeSmacallan 
12047d0f5abeSmacallan static void
1205f7add90dSriastradh hyperfb_erasecols(void *cookie, int row, int startcol, int ncols,
1206f7add90dSriastradh     long fillattr)
12077d0f5abeSmacallan {
12087d0f5abeSmacallan 	struct rasops_info *ri = cookie;
12097d0f5abeSmacallan 	struct vcons_screen *scr = ri->ri_hw;
12107d0f5abeSmacallan 	struct hyperfb_softc *sc = scr->scr_cookie;
12117d0f5abeSmacallan 	int32_t x, y, width, height, fg, bg, ul;
12127d0f5abeSmacallan 
12137d0f5abeSmacallan 	if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
12147d0f5abeSmacallan 		x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol;
12157d0f5abeSmacallan 		y = ri->ri_yorigin + ri->ri_font->fontheight * row;
12167d0f5abeSmacallan 		width = ri->ri_font->fontwidth * ncols;
12177d0f5abeSmacallan 		height = ri->ri_font->fontheight;
12187d0f5abeSmacallan 		rasops_unpack_attr(fillattr, &fg, &bg, &ul);
12197d0f5abeSmacallan 
12207d0f5abeSmacallan 		hyperfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
12217d0f5abeSmacallan 		if (ri->ri_crow == row &&
1222f7add90dSriastradh 		    (ri->ri_ccol >= startcol &&
1223f7add90dSriastradh 			ri->ri_ccol < (startcol + ncols)))
12247d0f5abeSmacallan 			ri->ri_flg &= ~RI_CURSOR;
12257d0f5abeSmacallan 	}
12267d0f5abeSmacallan }
12277d0f5abeSmacallan 
12287d0f5abeSmacallan static void
12297d0f5abeSmacallan hyperfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
12307d0f5abeSmacallan {
12317d0f5abeSmacallan 	struct rasops_info *ri = cookie;
12327d0f5abeSmacallan 	struct vcons_screen *scr = ri->ri_hw;
12337d0f5abeSmacallan 	struct hyperfb_softc *sc = scr->scr_cookie;
12347d0f5abeSmacallan 	int32_t x, ys, yd, width, height;
12357d0f5abeSmacallan 
12367d0f5abeSmacallan 	if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1237f7add90dSriastradh 		if ((ri->ri_crow >= srcrow &&
1238f7add90dSriastradh 			ri->ri_crow < (srcrow + nrows)) &&
12397d0f5abeSmacallan 		    (ri->ri_flg & RI_CURSOR)) {
12407d0f5abeSmacallan 			hyperfb_nuke_cursor(ri);
12417d0f5abeSmacallan 		}
12427d0f5abeSmacallan 		x = ri->ri_xorigin;
12437d0f5abeSmacallan 		ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow;
12447d0f5abeSmacallan 		yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow;
12457d0f5abeSmacallan 		width = ri->ri_emuwidth;
12467d0f5abeSmacallan 		height = ri->ri_font->fontheight * nrows;
12477d0f5abeSmacallan 		hyperfb_bitblt(sc, x, ys, x, yd, width, height, RopSrc);
12487d0f5abeSmacallan 		if (ri->ri_crow >= dstrow && ri->ri_crow < (dstrow + nrows))
12497d0f5abeSmacallan 			ri->ri_flg &= ~RI_CURSOR;
12507d0f5abeSmacallan 	}
12517d0f5abeSmacallan }
12527d0f5abeSmacallan 
12537d0f5abeSmacallan static void
12547d0f5abeSmacallan hyperfb_eraserows(void *cookie, int row, int nrows, long fillattr)
12557d0f5abeSmacallan {
12567d0f5abeSmacallan 	struct rasops_info *ri = cookie;
12577d0f5abeSmacallan 	struct vcons_screen *scr = ri->ri_hw;
12587d0f5abeSmacallan 	struct hyperfb_softc *sc = scr->scr_cookie;
12597d0f5abeSmacallan 	int32_t x, y, width, height, fg, bg, ul;
12607d0f5abeSmacallan 
12617d0f5abeSmacallan 	if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
12627d0f5abeSmacallan 		x = ri->ri_xorigin;
12637d0f5abeSmacallan 		y = ri->ri_yorigin + ri->ri_font->fontheight * row;
12647d0f5abeSmacallan 		width = ri->ri_emuwidth;
12657d0f5abeSmacallan 		height = ri->ri_font->fontheight * nrows;
12667d0f5abeSmacallan 		rasops_unpack_attr(fillattr, &fg, &bg, &ul);
12677d0f5abeSmacallan 
12687d0f5abeSmacallan 		hyperfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
12697d0f5abeSmacallan 
12707d0f5abeSmacallan 		if (ri->ri_crow >= row && ri->ri_crow < (row + nrows))
12717d0f5abeSmacallan 			ri->ri_flg &= ~RI_CURSOR;
12727d0f5abeSmacallan 	}
12737d0f5abeSmacallan }
1274357dd059Smacallan 
1275357dd059Smacallan static void
1276357dd059Smacallan hyperfb_move_cursor(struct hyperfb_softc *sc, int x, int y)
1277357dd059Smacallan {
1278357dd059Smacallan 	uint32_t pos;
1279357dd059Smacallan 
1280357dd059Smacallan 	sc->sc_cursor_x = x;
1281357dd059Smacallan 	x -= sc->sc_hot_x;
1282357dd059Smacallan 	sc->sc_cursor_y = y;
1283357dd059Smacallan 	y -= sc->sc_hot_y;
1284357dd059Smacallan 
1285357dd059Smacallan 	if (x < 0) x = 0x1000 - x;
1286357dd059Smacallan 	if (y < 0) y = 0x1000 - y;
1287357dd059Smacallan 	pos = (x << 16) | y;
1288357dd059Smacallan 	if (sc->sc_enabled) pos |= HCRX_ENABLE_CURSOR;
128996681a35Smacallan 	hyperfb_wait_fifo(sc, 2);
129096681a35Smacallan 	hyperfb_write4(sc, NGLE_REG_28, 0);
1291357dd059Smacallan 	hyperfb_write4(sc, NGLE_REG_29, pos);
1292357dd059Smacallan }
1293357dd059Smacallan 
1294357dd059Smacallan static int
1295357dd059Smacallan hyperfb_do_cursor(struct hyperfb_softc *sc, struct wsdisplay_cursor *cur)
1296357dd059Smacallan {
1297357dd059Smacallan 
1298357dd059Smacallan 	if (cur->which & WSDISPLAY_CURSOR_DOCUR) {
1299357dd059Smacallan 
1300357dd059Smacallan 		sc->sc_enabled = cur->enable;
1301357dd059Smacallan 		cur->which |= WSDISPLAY_CURSOR_DOPOS;
1302357dd059Smacallan 	}
1303357dd059Smacallan 	if (cur->which & WSDISPLAY_CURSOR_DOHOT) {
1304357dd059Smacallan 
1305357dd059Smacallan 		sc->sc_hot_x = cur->hot.x;
1306357dd059Smacallan 		sc->sc_hot_y = cur->hot.y;
1307357dd059Smacallan 		cur->which |= WSDISPLAY_CURSOR_DOPOS;
1308357dd059Smacallan 	}
1309357dd059Smacallan 	if (cur->which & WSDISPLAY_CURSOR_DOPOS) {
1310357dd059Smacallan 
1311357dd059Smacallan 		hyperfb_move_cursor(sc, cur->pos.x, cur->pos.y);
1312357dd059Smacallan 	}
1313357dd059Smacallan 	if (cur->which & WSDISPLAY_CURSOR_DOCMAP) {
1314357dd059Smacallan 		uint32_t rgb;
1315357dd059Smacallan 		uint8_t r[2], g[2], b[2];
1316357dd059Smacallan 
1317357dd059Smacallan 		copyin(cur->cmap.blue, b, 2);
1318357dd059Smacallan 		copyin(cur->cmap.green, g, 2);
1319357dd059Smacallan 		copyin(cur->cmap.red, r, 2);
1320357dd059Smacallan 		mutex_enter(&sc->sc_hwlock);
1321357dd059Smacallan 		hyperfb_wait(sc);
1322357dd059Smacallan 		hyperfb_write4(sc, NGLE_REG_10, 0xBBE0F000);
1323357dd059Smacallan 		hyperfb_write4(sc, NGLE_REG_14, 0x03000300);
1324357dd059Smacallan 		hyperfb_write4(sc, NGLE_REG_13, 0xffffffff);
1325357dd059Smacallan 		hyperfb_wait(sc);
1326357dd059Smacallan 		hyperfb_write4(sc, NGLE_REG_3, 0);
1327357dd059Smacallan 		rgb = (r[0] << 16) | (g[0] << 8) | b[0];
1328357dd059Smacallan 		hyperfb_write4(sc, NGLE_REG_4, rgb);	/* BG */
1329357dd059Smacallan 		rgb = (r[1] << 16) | (g[1] << 8) | b[1];
1330357dd059Smacallan 		hyperfb_write4(sc, NGLE_REG_4, rgb);	/* FG */
1331357dd059Smacallan 		hyperfb_write4(sc, NGLE_REG_2, 0);
1332f7add90dSriastradh 		hyperfb_write4(sc, NGLE_REG_38,
1333f7add90dSriastradh 		    LBC_ENABLE | LBC_TYPE_CURSOR | 4);
1334357dd059Smacallan 
1335357dd059Smacallan 		hyperfb_setup_fb(sc);
1336357dd059Smacallan 		mutex_exit(&sc->sc_hwlock);
1337357dd059Smacallan 
1338357dd059Smacallan 	}
1339357dd059Smacallan 	if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) {
1340357dd059Smacallan 		uint32_t buffer[128], latch, tmp;
1341357dd059Smacallan 		int i;
1342357dd059Smacallan 
1343357dd059Smacallan 		copyin(cur->mask, buffer, 512);
1344357dd059Smacallan 		hyperfb_wait(sc);
1345357dd059Smacallan 		hyperfb_write4(sc, NGLE_REG_30, 0);
1346357dd059Smacallan 		for (i = 0; i < 128; i += 2) {
1347357dd059Smacallan 			latch = 0;
1348357dd059Smacallan 			tmp = buffer[i] & 0x80808080;
1349357dd059Smacallan 			latch |= tmp >> 7;
1350357dd059Smacallan 			tmp = buffer[i] & 0x40404040;
1351357dd059Smacallan 			latch |= tmp >> 5;
1352357dd059Smacallan 			tmp = buffer[i] & 0x20202020;
1353357dd059Smacallan 			latch |= tmp >> 3;
1354357dd059Smacallan 			tmp = buffer[i] & 0x10101010;
1355357dd059Smacallan 			latch |= tmp >> 1;
1356357dd059Smacallan 			tmp = buffer[i] & 0x08080808;
1357357dd059Smacallan 			latch |= tmp << 1;
1358357dd059Smacallan 			tmp = buffer[i] & 0x04040404;
1359357dd059Smacallan 			latch |= tmp << 3;
1360357dd059Smacallan 			tmp = buffer[i] & 0x02020202;
1361357dd059Smacallan 			latch |= tmp << 5;
1362357dd059Smacallan 			tmp = buffer[i] & 0x01010101;
1363357dd059Smacallan 			latch |= tmp << 7;
1364357dd059Smacallan 			hyperfb_write4(sc, NGLE_REG_31, latch);
1365357dd059Smacallan 			latch = 0;
1366357dd059Smacallan 			tmp = buffer[i + 1] & 0x80808080;
1367357dd059Smacallan 			latch |= tmp >> 7;
1368357dd059Smacallan 			tmp = buffer[i + 1] & 0x40404040;
1369357dd059Smacallan 			latch |= tmp >> 5;
1370357dd059Smacallan 			tmp = buffer[i + 1] & 0x20202020;
1371357dd059Smacallan 			latch |= tmp >> 3;
1372357dd059Smacallan 			tmp = buffer[i + 1] & 0x10101010;
1373357dd059Smacallan 			latch |= tmp >> 1;
1374357dd059Smacallan 			tmp = buffer[i + 1] & 0x08080808;
1375357dd059Smacallan 			latch |= tmp << 1;
1376357dd059Smacallan 			tmp = buffer[i + 1] & 0x04040404;
1377357dd059Smacallan 			latch |= tmp << 3;
1378357dd059Smacallan 			tmp = buffer[i + 1] & 0x02020202;
1379357dd059Smacallan 			latch |= tmp << 5;
1380357dd059Smacallan 			tmp = buffer[i + 1] & 0x01010101;
1381357dd059Smacallan 			latch |= tmp << 7;
1382357dd059Smacallan 			hyperfb_write4(sc, NGLE_REG_31, latch);
1383357dd059Smacallan 		}
1384357dd059Smacallan 
1385357dd059Smacallan 		copyin(cur->image, buffer, 512);
1386357dd059Smacallan 		hyperfb_wait(sc);
1387357dd059Smacallan 		hyperfb_write4(sc, NGLE_REG_30, 0x80);
1388357dd059Smacallan 		for (i = 0; i < 128; i += 2) {
1389357dd059Smacallan 			latch = 0;
1390357dd059Smacallan 			tmp = buffer[i] & 0x80808080;
1391357dd059Smacallan 			latch |= tmp >> 7;
1392357dd059Smacallan 			tmp = buffer[i] & 0x40404040;
1393357dd059Smacallan 			latch |= tmp >> 5;
1394357dd059Smacallan 			tmp = buffer[i] & 0x20202020;
1395357dd059Smacallan 			latch |= tmp >> 3;
1396357dd059Smacallan 			tmp = buffer[i] & 0x10101010;
1397357dd059Smacallan 			latch |= tmp >> 1;
1398357dd059Smacallan 			tmp = buffer[i] & 0x08080808;
1399357dd059Smacallan 			latch |= tmp << 1;
1400357dd059Smacallan 			tmp = buffer[i] & 0x04040404;
1401357dd059Smacallan 			latch |= tmp << 3;
1402357dd059Smacallan 			tmp = buffer[i] & 0x02020202;
1403357dd059Smacallan 			latch |= tmp << 5;
1404357dd059Smacallan 			tmp = buffer[i] & 0x01010101;
1405357dd059Smacallan 			latch |= tmp << 7;
1406357dd059Smacallan 			hyperfb_write4(sc, NGLE_REG_31, latch);
1407357dd059Smacallan 			latch = 0;
1408357dd059Smacallan 			tmp = buffer[i + 1] & 0x80808080;
1409357dd059Smacallan 			latch |= tmp >> 7;
1410357dd059Smacallan 			tmp = buffer[i + 1] & 0x40404040;
1411357dd059Smacallan 			latch |= tmp >> 5;
1412357dd059Smacallan 			tmp = buffer[i + 1] & 0x20202020;
1413357dd059Smacallan 			latch |= tmp >> 3;
1414357dd059Smacallan 			tmp = buffer[i + 1] & 0x10101010;
1415357dd059Smacallan 			latch |= tmp >> 1;
1416357dd059Smacallan 			tmp = buffer[i + 1] & 0x08080808;
1417357dd059Smacallan 			latch |= tmp << 1;
1418357dd059Smacallan 			tmp = buffer[i + 1] & 0x04040404;
1419357dd059Smacallan 			latch |= tmp << 3;
1420357dd059Smacallan 			tmp = buffer[i + 1] & 0x02020202;
1421357dd059Smacallan 			latch |= tmp << 5;
1422357dd059Smacallan 			tmp = buffer[i + 1] & 0x01010101;
1423357dd059Smacallan 			latch |= tmp << 7;
1424357dd059Smacallan 			hyperfb_write4(sc, NGLE_REG_31, latch);
1425357dd059Smacallan 		}
1426357dd059Smacallan 		hyperfb_setup_fb(sc);
1427357dd059Smacallan 	}
1428357dd059Smacallan 
1429357dd059Smacallan 	return 0;
1430357dd059Smacallan }
1431