xref: /openbsd-src/sys/arch/sparc64/dev/machfb.c (revision 63294167c4eaf171adac4fb2d8cc6d072a13af61)
1*63294167Skettenis /*	$OpenBSD: machfb.c,v 1.13 2022/07/15 17:57:26 kettenis Exp $	*/
2f1f6d7c6Skettenis 
3f1f6d7c6Skettenis /*
4f1f6d7c6Skettenis  * Copyright (c) 2009 Mark Kettenis.
5f1f6d7c6Skettenis  *
6f1f6d7c6Skettenis  * Permission to use, copy, modify, and distribute this software for any
7f1f6d7c6Skettenis  * purpose with or without fee is hereby granted, provided that the above
8f1f6d7c6Skettenis  * copyright notice and this permission notice appear in all copies.
9f1f6d7c6Skettenis  *
10f1f6d7c6Skettenis  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11f1f6d7c6Skettenis  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12f1f6d7c6Skettenis  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13f1f6d7c6Skettenis  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14f1f6d7c6Skettenis  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15f1f6d7c6Skettenis  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16f1f6d7c6Skettenis  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17f1f6d7c6Skettenis  */
18f1f6d7c6Skettenis 
19f1f6d7c6Skettenis #include <sys/param.h>
20f1f6d7c6Skettenis #include <sys/device.h>
21f1f6d7c6Skettenis #include <sys/pciio.h>
22f1f6d7c6Skettenis #include <sys/systm.h>
23f1f6d7c6Skettenis 
24f1f6d7c6Skettenis #include <machine/autoconf.h>
25f1f6d7c6Skettenis #include <machine/bus.h>
26f1f6d7c6Skettenis #include <machine/openfirm.h>
27f1f6d7c6Skettenis 
28f1f6d7c6Skettenis #include <dev/pci/pcireg.h>
29f1f6d7c6Skettenis #include <dev/pci/pcivar.h>
30f1f6d7c6Skettenis #include <dev/pci/pcidevs.h>
31f1f6d7c6Skettenis 
32f1f6d7c6Skettenis #include <dev/wscons/wsconsio.h>
33f1f6d7c6Skettenis #include <dev/wscons/wsdisplayvar.h>
34f1f6d7c6Skettenis 
35f1f6d7c6Skettenis #include <dev/rasops/rasops.h>
36f1f6d7c6Skettenis 
37f1f6d7c6Skettenis #include <machine/fbvar.h>
38f1f6d7c6Skettenis 
39f1f6d7c6Skettenis #define M64_PCI_MEM		0x10
40f1f6d7c6Skettenis #define M64_PCI_MMIO		0x18
41f1f6d7c6Skettenis 
42f1f6d7c6Skettenis #define M64_REG_OFF		0x007ffc00
43f1f6d7c6Skettenis #define M64_REG_SIZE		0x0400
44f1f6d7c6Skettenis 
45f1f6d7c6Skettenis #define M64_CRTC_INT_CNTL	0x0018
46f1f6d7c6Skettenis 
47f1f6d7c6Skettenis #define M64_BUS_CNTL		0x00a0
48f1f6d7c6Skettenis #define  M64_BUS_FIFO_ERR_ACK	0x00200000
49f1f6d7c6Skettenis #define  M64_BUS_HOST_ERR_ACK	0x00800000
50f1f6d7c6Skettenis #define  M64_BUS_APER_REG_DIS	0x00000010
51f1f6d7c6Skettenis 
52f1f6d7c6Skettenis #define M64_DAC_WINDEX		0x00c0
53f1f6d7c6Skettenis #define M64_DAC_DATA		0x00c1
54f1f6d7c6Skettenis #define M64_DAC_MASK		0x00c2
55f1f6d7c6Skettenis #define M64_DAC_RINDEX		0x00c3
56f1f6d7c6Skettenis #define M64_DAC_CNTL		0x00c4
57f1f6d7c6Skettenis #define  M64_DAC_8BIT_EN		0x00000100
58f1f6d7c6Skettenis 
59f1f6d7c6Skettenis #define M64_GEN_TEST_CNTL	0x00d0
60f1f6d7c6Skettenis #define  M64_GEN_GUI_EN			0x00000100
61f1f6d7c6Skettenis 
62f1f6d7c6Skettenis #define M64_DST_OFF_PITCH	0x0100
63f1f6d7c6Skettenis #define M64_DST_X		0x0104
64f1f6d7c6Skettenis #define M64_DST_Y		0x0108
65f1f6d7c6Skettenis #define M64_DST_Y_X		0x010c
66f1f6d7c6Skettenis #define M64_DST_WIDTH		0x0110
67f1f6d7c6Skettenis #define M64_DST_HEIGHT		0x0114
68f1f6d7c6Skettenis #define M64_DST_HEIGHT_WIDTH	0x0118
69f1f6d7c6Skettenis #define M64_DST_X_WIDTH		0x011c
70f1f6d7c6Skettenis #define M64_DST_BRES_LNTH	0x0120
71f1f6d7c6Skettenis #define M64_DST_BRES_ERR	0x0124
72f1f6d7c6Skettenis #define M64_DST_BRES_INC	0x0128
73f1f6d7c6Skettenis #define M64_DST_BRES_DEC	0x012c
74f1f6d7c6Skettenis #define M64_DST_CNTL		0x0130
75f1f6d7c6Skettenis #define  M64_DST_X_RIGHT_TO_LEFT	0x00000000
76f1f6d7c6Skettenis #define  M64_DST_X_LEFT_TO_RIGHT	0x00000001
77f1f6d7c6Skettenis #define  M64_DST_Y_BOTTOM_TO_TOP	0x00000000
78f1f6d7c6Skettenis #define  M64_DST_Y_TOP_TO_BOTTOM	0x00000002
79f1f6d7c6Skettenis #define  M64_DST_X_MAJOR		0x00000000
80f1f6d7c6Skettenis #define  M64_DST_Y_MAJOR		0x00000004
81f1f6d7c6Skettenis #define  M64_DST_X_TILE			0x00000008
82f1f6d7c6Skettenis #define  M64_DST_Y_TILE			0x00000010
83f1f6d7c6Skettenis #define  M64_DST_LAST_PEL		0x00000020
84f1f6d7c6Skettenis #define  M64_DST_POLYGON_EN		0x00000040
85f1f6d7c6Skettenis #define  M64_DST_24_ROT_EN		0x00000080
86f1f6d7c6Skettenis 
87f1f6d7c6Skettenis #define M64_SRC_OFF_PITCH	0x0180
88f1f6d7c6Skettenis #define M64_SRC_X		0x0184
89f1f6d7c6Skettenis #define M64_SRC_Y		0x0188
90f1f6d7c6Skettenis #define M64_SRC_Y_X		0x018c
91f1f6d7c6Skettenis #define M64_SRC_WIDTH1		0x0190
92f1f6d7c6Skettenis #define M64_SRC_HEIGHT1		0x0194
93f1f6d7c6Skettenis #define M64_SRC_HEIGHT1_WIDTH1	0x0198
94f1f6d7c6Skettenis #define M64_SRC_X_START		0x019c
95f1f6d7c6Skettenis #define M64_SRC_Y_START		0x01a0
96f1f6d7c6Skettenis #define M64_SRC_Y_X_START	0x01a4
97f1f6d7c6Skettenis #define M64_SRC_WIDTH2		0x01a8
98f1f6d7c6Skettenis #define M64_SRC_HEIGHT2		0x01ac
99f1f6d7c6Skettenis #define M64_SRC_HEIGHT2_WIDTH2	0x01b0
100f1f6d7c6Skettenis #define M64_SRC_CNTL		0x01b4
101f1f6d7c6Skettenis #define  M64_SRC_PATT_EN		0x00000001
102f1f6d7c6Skettenis #define  M64_SRC_PATT_ROT_EN		0x00000002
103f1f6d7c6Skettenis #define  M64_SRC_LINEAR_EN		0x00000004
104f1f6d7c6Skettenis #define  M64_SRC_BYTE_ALIGN 		0x00000008
105f1f6d7c6Skettenis #define  M64_SRC_LINE_X_RIGHT_TO_LEFT	0x00000000
106f1f6d7c6Skettenis #define  M64_SRC_LINE_X_LEFT_TO_RIGHT	0x00000010
107f1f6d7c6Skettenis 
108f1f6d7c6Skettenis #define M64_HOST_CNTL		0x0240
109f1f6d7c6Skettenis 
110f1f6d7c6Skettenis #define M64_PAT_REG0		0x0280
111f1f6d7c6Skettenis #define M64_PAT_REG1		0x0284
112f1f6d7c6Skettenis #define M64_PAT_CNTL		0x0288
113f1f6d7c6Skettenis 
114f1f6d7c6Skettenis #define M64_SC_LEFT		0x02a0
115f1f6d7c6Skettenis #define M64_SC_RIGHT		0x02a4
116f1f6d7c6Skettenis #define M64_SC_LEFT_RIGHT	0x02a8
117f1f6d7c6Skettenis #define M64_SC_TOP		0x02ac
118f1f6d7c6Skettenis #define M64_SC_BOTTOM		0x02b0
119f1f6d7c6Skettenis #define M64_SC_TOP_BOTTOM	0x02b4
120f1f6d7c6Skettenis 
121f1f6d7c6Skettenis #define M64_DP_BKGD_CLR		0x02c0
122f1f6d7c6Skettenis #define M64_DP_FRGD_CLR		0x02c4
123f1f6d7c6Skettenis #define M64_DP_WRITE_MASK	0x02c8
124f1f6d7c6Skettenis 
125f1f6d7c6Skettenis #define M64_DP_CHAIN_MASK	0x02cc
126f1f6d7c6Skettenis #define  M64_DP_CHAIN_8BPP		0x00008080
127f1f6d7c6Skettenis #define M64_DP_PIX_WIDTH	0x02d0
128f1f6d7c6Skettenis #define  M64_DST_8BPP			0x00000002
129f1f6d7c6Skettenis #define  M64_SRC_8BPP			0x00000200
130f1f6d7c6Skettenis #define  M64_HOST_8BPP			0x00020000
131f1f6d7c6Skettenis #define M64_DP_MIX		0x02d4
132f1f6d7c6Skettenis #define  M64_MIX_DST			0x00000003
133f1f6d7c6Skettenis #define  M64_MIX_SRC			0x00000007
134f1f6d7c6Skettenis #define M64_DP_SRC           0x02d8
135f1f6d7c6Skettenis #define  M64_BKGD_SRC_BKGD_CLR		0x00000000
136f1f6d7c6Skettenis #define  M64_BKGD_SRC_FRGD_CLR		0x00000001
137f1f6d7c6Skettenis #define  M64_BKGD_SRC_HOST		0x00000002
138f1f6d7c6Skettenis #define  M64_BKGD_SRC_BLIT		0x00000003
139f1f6d7c6Skettenis #define  M64_BKGD_SRC_PATTERN		0x00000004
140f1f6d7c6Skettenis #define  M64_FRGD_SRC_BKGD_CLR		0x00000000
141f1f6d7c6Skettenis #define  M64_FRGD_SRC_FRGD_CLR		0x00000100
142f1f6d7c6Skettenis #define  M64_FRGD_SRC_HOST		0x00000200
143f1f6d7c6Skettenis #define  M64_FRGD_SRC_BLIT		0x00000300
144f1f6d7c6Skettenis #define  M64_FRGD_SRC_PATTERN		0x00000400
145f1f6d7c6Skettenis #define  M64_MONO_SRC_ONE		0x00000000
146f1f6d7c6Skettenis #define  M64_MONO_SRC_PATTERN		0x00010000
147f1f6d7c6Skettenis #define  M64_MONO_SRC_HOST		0x00020000
148f1f6d7c6Skettenis #define  M64_MONO_SRC_BLIT		0x00030000
149f1f6d7c6Skettenis 
150f1f6d7c6Skettenis #define M64_CLR_CMP_CLR		0x0300
151f1f6d7c6Skettenis #define M64_CLR_CMP_MASK	0x0304
152f1f6d7c6Skettenis #define M64_CLR_CMP_CNTL	0x0308
153f1f6d7c6Skettenis 
154f1f6d7c6Skettenis #define M64_FIFO_STAT		0x0310
155f1f6d7c6Skettenis #define  M64_FIFO_STAT_MASK		0x0000ffff
156f1f6d7c6Skettenis 
157f1f6d7c6Skettenis #define M64_CONTEXT_MASK	0x0320
158f1f6d7c6Skettenis 
159f1f6d7c6Skettenis #define M64_GUI_TRAJ_CNTL	0x0330
160f1f6d7c6Skettenis #define M64_GUI_STAT		0x0338
161f1f6d7c6Skettenis #define  M64_GUI_ACTIVE		 0x00000001
162f1f6d7c6Skettenis 
163f1f6d7c6Skettenis #define M64_COORDS(x, y)	((x << 16) | (y))
164f1f6d7c6Skettenis 
165f1f6d7c6Skettenis #ifdef APERTURE
166f1f6d7c6Skettenis extern int allowaperture;
167f1f6d7c6Skettenis #endif
168f1f6d7c6Skettenis 
169f1f6d7c6Skettenis struct machfb_softc {
170f1f6d7c6Skettenis 	struct sunfb	sc_sunfb;
171f1f6d7c6Skettenis 
172f1f6d7c6Skettenis 	bus_space_tag_t sc_memt;
173f1f6d7c6Skettenis 	bus_space_handle_t sc_memh;
174f1f6d7c6Skettenis 	bus_addr_t	sc_membase;
175f1f6d7c6Skettenis 	bus_size_t	sc_memsize;
176f1f6d7c6Skettenis 
177f1f6d7c6Skettenis 	bus_space_tag_t	sc_regt;
178f1f6d7c6Skettenis 	bus_space_handle_t sc_regh;
179f1f6d7c6Skettenis 
180f1f6d7c6Skettenis 	bus_space_tag_t	sc_mmiot;
181f1f6d7c6Skettenis 	bus_space_handle_t sc_mmioh;
182f1f6d7c6Skettenis 	bus_addr_t	sc_mmiobase;
183f1f6d7c6Skettenis 	bus_size_t	sc_mmiosize;
184f1f6d7c6Skettenis 
185f1f6d7c6Skettenis 	pcitag_t	sc_pcitag;
186f1f6d7c6Skettenis 
187f1f6d7c6Skettenis 	int		sc_mode;
188f1f6d7c6Skettenis 	u_int8_t	sc_cmap_red[256];
189f1f6d7c6Skettenis 	u_int8_t	sc_cmap_green[256];
190f1f6d7c6Skettenis 	u_int8_t	sc_cmap_blue[256];
191f1f6d7c6Skettenis };
192f1f6d7c6Skettenis 
193f1f6d7c6Skettenis int	machfb_ioctl(void *, u_long, caddr_t, int, struct proc *);
194f1f6d7c6Skettenis paddr_t	machfb_mmap(void *, off_t, int);
195f1f6d7c6Skettenis 
196f1f6d7c6Skettenis struct wsdisplay_accessops machfb_accessops = {
19787eec248Smiod 	.ioctl = machfb_ioctl,
19887eec248Smiod 	.mmap = machfb_mmap
199f1f6d7c6Skettenis };
200f1f6d7c6Skettenis 
201f1f6d7c6Skettenis int	machfb_match(struct device *, void *, void *);
202f1f6d7c6Skettenis void	machfb_attach(struct device *, struct device *, void *);
203f1f6d7c6Skettenis 
204eb7eaf8dSmpi const struct cfattach machfb_ca = {
205f1f6d7c6Skettenis 	sizeof(struct machfb_softc), machfb_match, machfb_attach
206f1f6d7c6Skettenis };
207f1f6d7c6Skettenis 
208f1f6d7c6Skettenis struct cfdriver machfb_cd = {
209f1f6d7c6Skettenis 	NULL, "machfb", DV_DULL
210f1f6d7c6Skettenis };
211f1f6d7c6Skettenis 
212f1f6d7c6Skettenis int	machfb_is_console(int);
213f1f6d7c6Skettenis int	machfb_getcmap(struct machfb_softc *, struct wsdisplay_cmap *);
214f1f6d7c6Skettenis int	machfb_putcmap(struct machfb_softc *, struct wsdisplay_cmap *);
215f1f6d7c6Skettenis void	machfb_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
216f1f6d7c6Skettenis 
217072953e3Smiod int	machfb_copycols(void *, int, int, int, int);
218e0c3e559Sjsg int	machfb_erasecols(void *, int, int, int, uint32_t);
219072953e3Smiod int	machfb_copyrows(void *, int, int, int);
220e0c3e559Sjsg int	machfb_eraserows(void *, int, int, uint32_t);
221f1f6d7c6Skettenis 
222f1f6d7c6Skettenis void	machfb_init(struct machfb_softc *);
223f1f6d7c6Skettenis int	machfb_wait_fifo(struct machfb_softc *, int);
224f1f6d7c6Skettenis int	machfb_wait(struct machfb_softc *);
225f1f6d7c6Skettenis void	machfb_copyrect(struct machfb_softc *, int, int, int, int, int, int);
226f1f6d7c6Skettenis void	machfb_fillrect(struct machfb_softc *, int, int, int, int, int);
227f1f6d7c6Skettenis 
228f1f6d7c6Skettenis int
machfb_match(struct device * parent,void * cf,void * aux)229f1f6d7c6Skettenis machfb_match(struct device *parent, void *cf, void *aux)
230f1f6d7c6Skettenis {
231f1f6d7c6Skettenis 	struct pci_attach_args *pa = aux;
232f1f6d7c6Skettenis 	char buf[32];
233f1f6d7c6Skettenis 	int node;
234f1f6d7c6Skettenis 
235f1f6d7c6Skettenis 	node = PCITAG_NODE(pa->pa_tag);
236f1f6d7c6Skettenis 	OF_getprop(node, "name", buf, sizeof(buf));
237f1f6d7c6Skettenis 	if (strcmp(buf, "SUNW,m64B") == 0)
238f1f6d7c6Skettenis 		return (10);
239f1f6d7c6Skettenis 
240f1f6d7c6Skettenis 	if (OF_getprop(node, "compatible", buf, sizeof(buf)) > 0 &&
241f1f6d7c6Skettenis 	    strcmp(buf, "SUNW,m64B") == 0)
242f1f6d7c6Skettenis 		return (10);
243f1f6d7c6Skettenis 
244f1f6d7c6Skettenis 	return (0);
245f1f6d7c6Skettenis }
246f1f6d7c6Skettenis 
247f1f6d7c6Skettenis void
machfb_attach(struct device * parent,struct device * self,void * aux)248f1f6d7c6Skettenis machfb_attach(struct device *parent, struct device *self, void *aux)
249f1f6d7c6Skettenis {
250f1f6d7c6Skettenis 	struct machfb_softc *sc = (struct machfb_softc *)self;
251f1f6d7c6Skettenis 	struct pci_attach_args *pa = aux;
252f1f6d7c6Skettenis 	struct rasops_info *ri;
253f1f6d7c6Skettenis 	int node, console;
254f1f6d7c6Skettenis 	char *model;
255f1f6d7c6Skettenis 
256f1f6d7c6Skettenis 	sc->sc_pcitag = pa->pa_tag;
257f1f6d7c6Skettenis 
258f1f6d7c6Skettenis 	node = PCITAG_NODE(pa->pa_tag);
259f1f6d7c6Skettenis 	console = machfb_is_console(node);
260f1f6d7c6Skettenis 
261f1f6d7c6Skettenis 	printf("\n");
262f1f6d7c6Skettenis 
263f1f6d7c6Skettenis 	model = getpropstring(node, "model");
264f1f6d7c6Skettenis 	printf("%s: %s", self->dv_xname, model);
265f1f6d7c6Skettenis 
266f1f6d7c6Skettenis 	if (pci_mapreg_map(pa, M64_PCI_MEM, PCI_MAPREG_TYPE_MEM,
267f1f6d7c6Skettenis 	    BUS_SPACE_MAP_LINEAR, &sc->sc_memt, &sc->sc_memh,
268f1f6d7c6Skettenis 	    &sc->sc_membase, &sc->sc_memsize, 0)) {
269f1f6d7c6Skettenis 		printf("\n%s: can't map video memory\n", self->dv_xname);
270f1f6d7c6Skettenis 		return;
271f1f6d7c6Skettenis 	}
272f1f6d7c6Skettenis 
273f1f6d7c6Skettenis 	sc->sc_regt = sc->sc_memt;
274f1f6d7c6Skettenis 	if (bus_space_subregion(sc->sc_memt, sc->sc_memh,
275f1f6d7c6Skettenis 	    M64_REG_OFF, M64_REG_SIZE, &sc->sc_regh)) {
276f1f6d7c6Skettenis 		printf("\n%s: can't map registers\n", self->dv_xname);
277f1f6d7c6Skettenis 		return;
278f1f6d7c6Skettenis 	}
279f1f6d7c6Skettenis 
280f1f6d7c6Skettenis 	if (pci_mapreg_map(pa, M64_PCI_MMIO, PCI_MAPREG_TYPE_MEM, 0,
281f1f6d7c6Skettenis 	    &sc->sc_mmiot, &sc->sc_mmioh, &sc->sc_mmiobase,
282f1f6d7c6Skettenis 	    &sc->sc_mmiosize, 0)) {
283f1f6d7c6Skettenis 		printf("\n%s: can't map registers\n", self->dv_xname);
284f1f6d7c6Skettenis 		return;
285f1f6d7c6Skettenis 	}
286f1f6d7c6Skettenis 
287f1f6d7c6Skettenis 	fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);
288f1f6d7c6Skettenis 	if (sc->sc_sunfb.sf_depth == 24) {
289f1f6d7c6Skettenis 		sc->sc_sunfb.sf_depth = 32;
290f1f6d7c6Skettenis 		sc->sc_sunfb.sf_linebytes =
291f1f6d7c6Skettenis 		    (sc->sc_sunfb.sf_depth / 8) * sc->sc_sunfb.sf_width;
292f1f6d7c6Skettenis 		sc->sc_sunfb.sf_fbsize =
293f1f6d7c6Skettenis 		    sc->sc_sunfb.sf_height * sc->sc_sunfb.sf_linebytes;
294f1f6d7c6Skettenis 	}
295f1f6d7c6Skettenis 
296f1f6d7c6Skettenis 	printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
297f1f6d7c6Skettenis 
2983809ecbaSjsg #ifdef RAMDISK_HOOKS
2996de07763Skettenis 	printf("%s: aperture needed\n", self->dv_xname);
3006de07763Skettenis #endif
3016de07763Skettenis 
302f1f6d7c6Skettenis 	ri = &sc->sc_sunfb.sf_ro;
303f1f6d7c6Skettenis 	ri->ri_bits = bus_space_vaddr(sc->sc_memt, sc->sc_memh);
304f1f6d7c6Skettenis 	ri->ri_hw = sc;
305f1f6d7c6Skettenis 
306f1f6d7c6Skettenis 	fbwscons_init(&sc->sc_sunfb, RI_BSWAP, console);
307f1f6d7c6Skettenis 	fbwscons_setcolormap(&sc->sc_sunfb, machfb_setcolor);
308f1f6d7c6Skettenis 	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
309f1f6d7c6Skettenis 
310f1f6d7c6Skettenis 	machfb_init(sc);
311f1f6d7c6Skettenis 	ri->ri_ops.copyrows = machfb_copyrows;
312f1f6d7c6Skettenis 	ri->ri_ops.copycols = machfb_copycols;
313f1f6d7c6Skettenis 	ri->ri_ops.eraserows = machfb_eraserows;
314f1f6d7c6Skettenis 	ri->ri_ops.erasecols = machfb_erasecols;
315f1f6d7c6Skettenis 
316f1f6d7c6Skettenis 	if (console)
317f1f6d7c6Skettenis 		fbwscons_console_init(&sc->sc_sunfb, -1);
318f1f6d7c6Skettenis 	fbwscons_attach(&sc->sc_sunfb, &machfb_accessops, console);
319f1f6d7c6Skettenis }
320f1f6d7c6Skettenis 
321f1f6d7c6Skettenis int
machfb_ioctl(void * v,u_long cmd,caddr_t data,int flags,struct proc * p)322f1f6d7c6Skettenis machfb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
323f1f6d7c6Skettenis {
324f1f6d7c6Skettenis 	struct machfb_softc *sc = v;
325f1f6d7c6Skettenis 	struct wsdisplay_fbinfo *wdf;
326f1f6d7c6Skettenis 	struct pcisel *sel;
327f1f6d7c6Skettenis 
328f1f6d7c6Skettenis 	switch (cmd) {
329f1f6d7c6Skettenis 	case WSDISPLAYIO_GTYPE:
330b1fcb574Skettenis 		*(u_int *)data = WSDISPLAY_TYPE_MACHFB;
331f1f6d7c6Skettenis 		break;
332f1f6d7c6Skettenis 	case WSDISPLAYIO_SMODE:
333f1f6d7c6Skettenis 		sc->sc_mode = *(u_int *)data;
334b54ada20Skettenis 		if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
335b54ada20Skettenis 			struct rasops_info *ri = &sc->sc_sunfb.sf_ro;
336b54ada20Skettenis 
337b54ada20Skettenis 			/* Restore colormap. */
338f1f6d7c6Skettenis 			fbwscons_setcolormap(&sc->sc_sunfb, machfb_setcolor);
339b54ada20Skettenis 
340b54ada20Skettenis 			/* Clear screen. */
341b54ada20Skettenis 			machfb_fillrect(sc, 0, 0, ri->ri_width, ri->ri_height,
342b54ada20Skettenis 			    ri->ri_devcmap[WSCOL_WHITE]);
343b54ada20Skettenis 		}
344f1f6d7c6Skettenis 		break;
345f1f6d7c6Skettenis 	case WSDISPLAYIO_GINFO:
346f1f6d7c6Skettenis 		wdf = (void *)data;
347f1f6d7c6Skettenis 		wdf->height = sc->sc_sunfb.sf_height;
348f1f6d7c6Skettenis 		wdf->width  = sc->sc_sunfb.sf_width;
349f1f6d7c6Skettenis 		wdf->depth  = sc->sc_sunfb.sf_depth;
350*63294167Skettenis 		wdf->stride = sc->sc_sunfb.sf_linebytes;
351*63294167Skettenis 		wdf->offset = 0;
352f1f6d7c6Skettenis 		wdf->cmsize = 256;
353f1f6d7c6Skettenis 		break;
354f1f6d7c6Skettenis 	case WSDISPLAYIO_LINEBYTES:
355f1f6d7c6Skettenis 		*(u_int *)data = sc->sc_sunfb.sf_linebytes;
356f1f6d7c6Skettenis 		break;
357f1f6d7c6Skettenis 
358f1f6d7c6Skettenis 	case WSDISPLAYIO_GETCMAP:
359f1f6d7c6Skettenis 		return machfb_getcmap(sc, (struct wsdisplay_cmap *)data);
360f1f6d7c6Skettenis 	case WSDISPLAYIO_PUTCMAP:
361f1f6d7c6Skettenis 		return machfb_putcmap(sc, (struct wsdisplay_cmap *)data);
362f1f6d7c6Skettenis 
363f1f6d7c6Skettenis 	case WSDISPLAYIO_GPCIID:
364f1f6d7c6Skettenis 		sel = (struct pcisel *)data;
365f1f6d7c6Skettenis 		sel->pc_bus = PCITAG_BUS(sc->sc_pcitag);
366f1f6d7c6Skettenis 		sel->pc_dev = PCITAG_DEV(sc->sc_pcitag);
367f1f6d7c6Skettenis 		sel->pc_func = PCITAG_FUN(sc->sc_pcitag);
368f1f6d7c6Skettenis 		break;
369f1f6d7c6Skettenis 
370f1f6d7c6Skettenis 	case WSDISPLAYIO_SVIDEO:
371f1f6d7c6Skettenis 	case WSDISPLAYIO_GVIDEO:
372f1f6d7c6Skettenis 		break;
373f1f6d7c6Skettenis 
374f1f6d7c6Skettenis 	case WSDISPLAYIO_GCURPOS:
375f1f6d7c6Skettenis 	case WSDISPLAYIO_SCURPOS:
376f1f6d7c6Skettenis 	case WSDISPLAYIO_GCURMAX:
377f1f6d7c6Skettenis 	case WSDISPLAYIO_GCURSOR:
378f1f6d7c6Skettenis 	case WSDISPLAYIO_SCURSOR:
379f1f6d7c6Skettenis 	default:
380f1f6d7c6Skettenis 		return -1; /* not supported yet */
381f1f6d7c6Skettenis         }
382f1f6d7c6Skettenis 
383f1f6d7c6Skettenis 	return (0);
384f1f6d7c6Skettenis }
385f1f6d7c6Skettenis 
386f1f6d7c6Skettenis paddr_t
machfb_mmap(void * v,off_t off,int prot)387f1f6d7c6Skettenis machfb_mmap(void *v, off_t off, int prot)
388f1f6d7c6Skettenis {
389f1f6d7c6Skettenis 	struct machfb_softc *sc = v;
390f1f6d7c6Skettenis 
391f1f6d7c6Skettenis 	if (off & PGOFSET)
392f1f6d7c6Skettenis 		return (-1);
393f1f6d7c6Skettenis 
394f1f6d7c6Skettenis 	switch (sc->sc_mode) {
395f1f6d7c6Skettenis 	case WSDISPLAYIO_MODE_MAPPED:
396f1f6d7c6Skettenis #ifdef APERTURE
397f1f6d7c6Skettenis 		if (allowaperture == 0)
398f1f6d7c6Skettenis 			return (-1);
399f1f6d7c6Skettenis #endif
400f1f6d7c6Skettenis 
401f1f6d7c6Skettenis 		if (sc->sc_mmiosize == 0)
402f1f6d7c6Skettenis 			return (-1);
403f1f6d7c6Skettenis 
404f1f6d7c6Skettenis 		if (off >= sc->sc_membase &&
405f1f6d7c6Skettenis 		    off < (sc->sc_membase + sc->sc_memsize))
406f1f6d7c6Skettenis 			return (bus_space_mmap(sc->sc_memt,
407f1f6d7c6Skettenis 			    sc->sc_membase, off - sc->sc_membase,
408f1f6d7c6Skettenis 			    prot, BUS_SPACE_MAP_LINEAR));
409f1f6d7c6Skettenis 
410f1f6d7c6Skettenis 		if (off >= sc->sc_mmiobase &&
411f1f6d7c6Skettenis 		    off < (sc->sc_mmiobase + sc->sc_mmiosize))
412f1f6d7c6Skettenis 			return (bus_space_mmap(sc->sc_mmiot,
413f1f6d7c6Skettenis 			    sc->sc_mmiobase, off - sc->sc_mmiobase,
414f1f6d7c6Skettenis 			    prot, BUS_SPACE_MAP_LINEAR));
415f1f6d7c6Skettenis 		break;
416f1f6d7c6Skettenis 
417f1f6d7c6Skettenis 	case WSDISPLAYIO_MODE_DUMBFB:
418f1f6d7c6Skettenis 		if (off >= 0 && off < sc->sc_memsize)
419f1f6d7c6Skettenis 			return (bus_space_mmap(sc->sc_memt, sc->sc_membase,
420f1f6d7c6Skettenis 			    off, prot, BUS_SPACE_MAP_LINEAR));
421f1f6d7c6Skettenis 		break;
422f1f6d7c6Skettenis 	}
423f1f6d7c6Skettenis 
424f1f6d7c6Skettenis 	return (-1);
425f1f6d7c6Skettenis }
426f1f6d7c6Skettenis 
427f1f6d7c6Skettenis int
machfb_is_console(int node)428f1f6d7c6Skettenis machfb_is_console(int node)
429f1f6d7c6Skettenis {
430f1f6d7c6Skettenis 	extern int fbnode;
431f1f6d7c6Skettenis 
432f1f6d7c6Skettenis 	return (fbnode == node);
433f1f6d7c6Skettenis }
434f1f6d7c6Skettenis 
435f1f6d7c6Skettenis int
machfb_getcmap(struct machfb_softc * sc,struct wsdisplay_cmap * cm)436f1f6d7c6Skettenis machfb_getcmap(struct machfb_softc *sc, struct wsdisplay_cmap *cm)
437f1f6d7c6Skettenis {
438f1f6d7c6Skettenis 	u_int index = cm->index;
439f1f6d7c6Skettenis 	u_int count = cm->count;
440f1f6d7c6Skettenis 	int error;
441f1f6d7c6Skettenis 
442f1f6d7c6Skettenis 	if (index >= 256 || count > 256 - index)
443f1f6d7c6Skettenis 		return (EINVAL);
444f1f6d7c6Skettenis 
445f1f6d7c6Skettenis 	error = copyout(&sc->sc_cmap_red[index], cm->red, count);
446f1f6d7c6Skettenis 	if (error)
447f1f6d7c6Skettenis 		return (error);
448f1f6d7c6Skettenis 	error = copyout(&sc->sc_cmap_green[index], cm->green, count);
449f1f6d7c6Skettenis 	if (error)
450f1f6d7c6Skettenis 		return (error);
451f1f6d7c6Skettenis 	error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
452f1f6d7c6Skettenis 	if (error)
453f1f6d7c6Skettenis 		return (error);
454f1f6d7c6Skettenis 	return (0);
455f1f6d7c6Skettenis }
456f1f6d7c6Skettenis 
457f1f6d7c6Skettenis int
machfb_putcmap(struct machfb_softc * sc,struct wsdisplay_cmap * cm)458f1f6d7c6Skettenis machfb_putcmap(struct machfb_softc *sc, struct wsdisplay_cmap *cm)
459f1f6d7c6Skettenis {
460f1f6d7c6Skettenis 	u_int index = cm->index;
461f1f6d7c6Skettenis 	u_int count = cm->count;
462f1f6d7c6Skettenis 	u_int i;
463f1f6d7c6Skettenis 	int error;
464f1f6d7c6Skettenis 	u_char *r, *g, *b;
465f1f6d7c6Skettenis 
466f1f6d7c6Skettenis 	if (index >= 256 || count > 256 - index)
467f1f6d7c6Skettenis 		return (EINVAL);
468f1f6d7c6Skettenis 
469f1f6d7c6Skettenis 	if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0)
470f1f6d7c6Skettenis 		return (error);
471f1f6d7c6Skettenis 	if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0)
472f1f6d7c6Skettenis 		return (error);
473f1f6d7c6Skettenis 	if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0)
474f1f6d7c6Skettenis 		return (error);
475f1f6d7c6Skettenis 
476f1f6d7c6Skettenis 	r = &sc->sc_cmap_red[index];
477f1f6d7c6Skettenis 	g = &sc->sc_cmap_green[index];
478f1f6d7c6Skettenis 	b = &sc->sc_cmap_blue[index];
479f1f6d7c6Skettenis 
480f1f6d7c6Skettenis 	bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_MASK, 0xff);
481b8209d5eSkettenis 	bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_WINDEX, index);
482f1f6d7c6Skettenis 	for (i = 0; i < count; i++) {
483f1f6d7c6Skettenis 		bus_space_write_1(sc->sc_regt, sc->sc_regh,
484f1f6d7c6Skettenis 		    M64_DAC_DATA, *r);
485f1f6d7c6Skettenis 		bus_space_write_1(sc->sc_regt, sc->sc_regh,
486f1f6d7c6Skettenis 		    M64_DAC_DATA, *g);
487f1f6d7c6Skettenis 		bus_space_write_1(sc->sc_regt, sc->sc_regh,
488f1f6d7c6Skettenis 		    M64_DAC_DATA, *b);
489b8209d5eSkettenis 		r++, g++, b++;
490f1f6d7c6Skettenis 	}
491f1f6d7c6Skettenis 	return (0);
492f1f6d7c6Skettenis }
493f1f6d7c6Skettenis 
494f1f6d7c6Skettenis void
machfb_setcolor(void * v,u_int index,u_int8_t r,u_int8_t g,u_int8_t b)495f1f6d7c6Skettenis machfb_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
496f1f6d7c6Skettenis {
497f1f6d7c6Skettenis 	struct machfb_softc *sc = v;
498f1f6d7c6Skettenis 
499f1f6d7c6Skettenis 	sc->sc_cmap_red[index] = r;
500f1f6d7c6Skettenis 	sc->sc_cmap_green[index] = g;
501f1f6d7c6Skettenis 	sc->sc_cmap_blue[index] = b;
502f1f6d7c6Skettenis 
503f1f6d7c6Skettenis 	bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_MASK, 0xff);
504f1f6d7c6Skettenis 	bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_WINDEX, index);
505f1f6d7c6Skettenis 	bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_DATA, r);
506f1f6d7c6Skettenis 	bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_DATA, g);
507f1f6d7c6Skettenis 	bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_DATA, b);
508f1f6d7c6Skettenis }
509f1f6d7c6Skettenis 
510f1f6d7c6Skettenis /*
511f1f6d7c6Skettenis  * Accelerated routines.
512f1f6d7c6Skettenis  */
513f1f6d7c6Skettenis 
514072953e3Smiod int
machfb_copycols(void * cookie,int row,int src,int dst,int num)515f1f6d7c6Skettenis machfb_copycols(void *cookie, int row, int src, int dst, int num)
516f1f6d7c6Skettenis {
517f1f6d7c6Skettenis 	struct rasops_info *ri = cookie;
518f1f6d7c6Skettenis 	struct machfb_softc *sc = ri->ri_hw;
519f1f6d7c6Skettenis 
520f1f6d7c6Skettenis 	num *= ri->ri_font->fontwidth;
521f1f6d7c6Skettenis 	src *= ri->ri_font->fontwidth;
522f1f6d7c6Skettenis 	dst *= ri->ri_font->fontwidth;
523f1f6d7c6Skettenis 	row *= ri->ri_font->fontheight;
524f1f6d7c6Skettenis 
525f1f6d7c6Skettenis 	machfb_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row,
526f1f6d7c6Skettenis 	    ri->ri_xorigin + dst, ri->ri_yorigin + row,
527f1f6d7c6Skettenis 	    num, ri->ri_font->fontheight);
528072953e3Smiod 
529072953e3Smiod 	return 0;
530f1f6d7c6Skettenis }
531f1f6d7c6Skettenis 
532072953e3Smiod int
machfb_erasecols(void * cookie,int row,int col,int num,uint32_t attr)533e0c3e559Sjsg machfb_erasecols(void *cookie, int row, int col, int num, uint32_t attr)
534f1f6d7c6Skettenis {
535f1f6d7c6Skettenis 	struct rasops_info *ri = cookie;
536f1f6d7c6Skettenis 	struct machfb_softc *sc = ri->ri_hw;
537f1f6d7c6Skettenis 	int bg, fg;
538f1f6d7c6Skettenis 
539f1f6d7c6Skettenis 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
540f1f6d7c6Skettenis 
541f1f6d7c6Skettenis 	row *= ri->ri_font->fontheight;
542f1f6d7c6Skettenis 	col *= ri->ri_font->fontwidth;
543f1f6d7c6Skettenis 	num *= ri->ri_font->fontwidth;
544f1f6d7c6Skettenis 
545f1f6d7c6Skettenis 	machfb_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row,
546f1f6d7c6Skettenis 	    num, ri->ri_font->fontheight, ri->ri_devcmap[bg]);
547072953e3Smiod 
548072953e3Smiod 	return 0;
549f1f6d7c6Skettenis }
550f1f6d7c6Skettenis 
551072953e3Smiod int
machfb_copyrows(void * cookie,int src,int dst,int num)552f1f6d7c6Skettenis machfb_copyrows(void *cookie, int src, int dst, int num)
553f1f6d7c6Skettenis {
554f1f6d7c6Skettenis 	struct rasops_info *ri = cookie;
555f1f6d7c6Skettenis 	struct machfb_softc *sc = ri->ri_hw;
556f1f6d7c6Skettenis 
557f1f6d7c6Skettenis 	num *= ri->ri_font->fontheight;
558f1f6d7c6Skettenis 	src *= ri->ri_font->fontheight;
559f1f6d7c6Skettenis 	dst *= ri->ri_font->fontheight;
560f1f6d7c6Skettenis 
561f1f6d7c6Skettenis 	machfb_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src,
562f1f6d7c6Skettenis 	    ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num);
563072953e3Smiod 
564072953e3Smiod 	return 0;
565f1f6d7c6Skettenis }
566f1f6d7c6Skettenis 
567072953e3Smiod int
machfb_eraserows(void * cookie,int row,int num,uint32_t attr)568e0c3e559Sjsg machfb_eraserows(void *cookie, int row, int num, uint32_t attr)
569f1f6d7c6Skettenis {
570f1f6d7c6Skettenis 	struct rasops_info *ri = cookie;
571f1f6d7c6Skettenis 	struct machfb_softc *sc = ri->ri_hw;
572f1f6d7c6Skettenis 	int bg, fg;
573f1f6d7c6Skettenis 	int x, y, w;
574f1f6d7c6Skettenis 
575f1f6d7c6Skettenis 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
576f1f6d7c6Skettenis 
577f1f6d7c6Skettenis 	if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
578f1f6d7c6Skettenis 		num = ri->ri_height;
579f1f6d7c6Skettenis 		x = y = 0;
580f1f6d7c6Skettenis 		w = ri->ri_width;
581f1f6d7c6Skettenis 	} else {
582f1f6d7c6Skettenis 		num *= ri->ri_font->fontheight;
583f1f6d7c6Skettenis 		x = ri->ri_xorigin;
584f1f6d7c6Skettenis 		y = ri->ri_yorigin + row * ri->ri_font->fontheight;
585f1f6d7c6Skettenis 		w = ri->ri_emuwidth;
586f1f6d7c6Skettenis 	}
587f1f6d7c6Skettenis 	machfb_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]);
588072953e3Smiod 
589072953e3Smiod 	return 0;
590f1f6d7c6Skettenis }
591f1f6d7c6Skettenis 
592f1f6d7c6Skettenis void
machfb_init(struct machfb_softc * sc)593f1f6d7c6Skettenis machfb_init(struct machfb_softc *sc)
594f1f6d7c6Skettenis {
595f1f6d7c6Skettenis 	uint32_t reg;
596f1f6d7c6Skettenis 
597f1f6d7c6Skettenis         /* Reset engine. */
598f1f6d7c6Skettenis 	reg = bus_space_read_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL);
599f1f6d7c6Skettenis 	reg &= ~M64_GEN_GUI_EN;
600f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL, reg);
601f1f6d7c6Skettenis 
602f1f6d7c6Skettenis         /* Enable engine. */
603f1f6d7c6Skettenis 	reg = bus_space_read_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL);
604f1f6d7c6Skettenis 	reg &= M64_GEN_GUI_EN;
605f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL, reg);
606f1f6d7c6Skettenis 
607f1f6d7c6Skettenis         /* Clearing any FIFO or host errors. */
608f1f6d7c6Skettenis 	reg = bus_space_read_4(sc->sc_regt, sc->sc_regh, M64_BUS_CNTL);
609f1f6d7c6Skettenis 	reg |= M64_BUS_HOST_ERR_ACK | M64_BUS_FIFO_ERR_ACK;
610f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_BUS_CNTL, reg);
611f1f6d7c6Skettenis 
612f1f6d7c6Skettenis 	machfb_wait_fifo(sc, 14);
613f1f6d7c6Skettenis 
614f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh,
615f1f6d7c6Skettenis 	    M64_CONTEXT_MASK, 0xffffffff);
616f1f6d7c6Skettenis 
617f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_OFF_PITCH,
618f1f6d7c6Skettenis 	    (sc->sc_sunfb.sf_linebytes / 8) << 22);
619f1f6d7c6Skettenis 
620f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_Y_X, 0);
621f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_HEIGHT, 0);
622f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_BRES_ERR, 0);
623f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_BRES_INC, 0);
624f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_BRES_DEC, 0);
625f1f6d7c6Skettenis 
626f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_CNTL,
627f1f6d7c6Skettenis 	    M64_DST_LAST_PEL | M64_DST_X_LEFT_TO_RIGHT |
628f1f6d7c6Skettenis 	    M64_DST_Y_TOP_TO_BOTTOM);
629f1f6d7c6Skettenis 
630f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_OFF_PITCH,
631f1f6d7c6Skettenis 	    (sc->sc_sunfb.sf_linebytes / 8) << 22);
632f1f6d7c6Skettenis 
633f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_Y_X, 0);
634f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh,
635f1f6d7c6Skettenis 	    M64_SRC_HEIGHT1_WIDTH1, 1);
636f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_Y_X_START, 0);
637f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh,
638f1f6d7c6Skettenis 	    M64_SRC_HEIGHT2_WIDTH2, 1);
639f1f6d7c6Skettenis 
640f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_CNTL,
641f1f6d7c6Skettenis 	    M64_SRC_LINE_X_LEFT_TO_RIGHT);
642f1f6d7c6Skettenis 
643f1f6d7c6Skettenis 	machfb_wait_fifo(sc, 13);
644f1f6d7c6Skettenis 
645f1f6d7c6Skettenis 	/* Host attributes. */
646f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_HOST_CNTL, 0);
647f1f6d7c6Skettenis 
648f1f6d7c6Skettenis 	/* Pattern attributes. */
649f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_PAT_REG0, 0);
650f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_PAT_REG1, 0);
651f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_PAT_CNTL, 0);
652f1f6d7c6Skettenis 
653f1f6d7c6Skettenis 	/* Scissors. */
654f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_LEFT, 0);
655f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_TOP, 0);
656f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_BOTTOM,
657f1f6d7c6Skettenis 	    sc->sc_sunfb.sf_height - 1);
658f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_RIGHT,
659f1f6d7c6Skettenis 	    sc->sc_sunfb.sf_linebytes - 1);
660f1f6d7c6Skettenis 
661f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_BKGD_CLR, 0);
662f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh,
663f1f6d7c6Skettenis 	    M64_DP_FRGD_CLR, 0xffffffff);
664f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh,
665f1f6d7c6Skettenis 	    M64_DP_WRITE_MASK, 0xffffffff);
666f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh,
667f1f6d7c6Skettenis 	    M64_DP_MIX, (M64_MIX_SRC << 16) | M64_MIX_DST);
668f1f6d7c6Skettenis 
669f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh,
670f1f6d7c6Skettenis 	    M64_DP_SRC, M64_FRGD_SRC_FRGD_CLR);
671f1f6d7c6Skettenis 
672f1f6d7c6Skettenis 	machfb_wait_fifo(sc, 3);
673f1f6d7c6Skettenis 
674f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CLR, 0);
675f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh,
676f1f6d7c6Skettenis 	    M64_CLR_CMP_MASK, 0xffffffff);
677f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CNTL, 0);
678f1f6d7c6Skettenis 
679f1f6d7c6Skettenis 	machfb_wait_fifo(sc, 3);
680f1f6d7c6Skettenis 
681f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_PIX_WIDTH,
682f1f6d7c6Skettenis 	    M64_HOST_8BPP | M64_SRC_8BPP | M64_DST_8BPP);
683f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_CHAIN_MASK,
684f1f6d7c6Skettenis 	    M64_DP_CHAIN_8BPP);
685f1f6d7c6Skettenis 
686f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_GUI_TRAJ_CNTL,
687f1f6d7c6Skettenis 	    M64_DST_X_LEFT_TO_RIGHT | M64_DST_Y_TOP_TO_BOTTOM);
688f1f6d7c6Skettenis 
689f1f6d7c6Skettenis 	machfb_wait(sc);
690f1f6d7c6Skettenis }
691f1f6d7c6Skettenis 
692f1f6d7c6Skettenis int
machfb_wait_fifo(struct machfb_softc * sc,int v)693f1f6d7c6Skettenis machfb_wait_fifo(struct machfb_softc *sc, int v)
694f1f6d7c6Skettenis {
695f1f6d7c6Skettenis 	int i;
696f1f6d7c6Skettenis 
697f1f6d7c6Skettenis 	for (i = 1000000; i != 0; i--) {
698f1f6d7c6Skettenis 		if ((bus_space_read_4(sc->sc_regt, sc->sc_regh,
699f1f6d7c6Skettenis 		    M64_FIFO_STAT) & M64_FIFO_STAT_MASK) <= (0x8000 >> v))
700f1f6d7c6Skettenis 			break;
701f1f6d7c6Skettenis 		DELAY(1);
702f1f6d7c6Skettenis 	}
703f1f6d7c6Skettenis 
704f1f6d7c6Skettenis 	return i;
705f1f6d7c6Skettenis }
706f1f6d7c6Skettenis 
707f1f6d7c6Skettenis int
machfb_wait(struct machfb_softc * sc)708f1f6d7c6Skettenis machfb_wait(struct machfb_softc *sc)
709f1f6d7c6Skettenis {
710f1f6d7c6Skettenis 	int i;
711f1f6d7c6Skettenis 
712f1f6d7c6Skettenis 	machfb_wait_fifo(sc, 16);
713f1f6d7c6Skettenis 	for (i = 1000000; i != 0; i--) {
714f1f6d7c6Skettenis 		if ((bus_space_read_4(sc->sc_regt, sc->sc_regh,
715f1f6d7c6Skettenis 		    M64_GUI_STAT) & M64_GUI_ACTIVE) == 0)
716f1f6d7c6Skettenis 			break;
717f1f6d7c6Skettenis 		DELAY(1);
718f1f6d7c6Skettenis 	}
719f1f6d7c6Skettenis 
720f1f6d7c6Skettenis 	return i;
721f1f6d7c6Skettenis }
722f1f6d7c6Skettenis 
723f1f6d7c6Skettenis void
machfb_copyrect(struct machfb_softc * sc,int sx,int sy,int dx,int dy,int w,int h)724f1f6d7c6Skettenis machfb_copyrect(struct machfb_softc *sc, int sx, int sy, int dx, int dy,
725f1f6d7c6Skettenis     int w, int h)
726f1f6d7c6Skettenis {
727f1f6d7c6Skettenis 	uint32_t dest_ctl = 0;
728f1f6d7c6Skettenis 
729f1f6d7c6Skettenis 	machfb_wait_fifo(sc, 10);
730f1f6d7c6Skettenis 
731f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh,
732f1f6d7c6Skettenis 	    M64_DP_WRITE_MASK, 0xff);
733f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh,
734f1f6d7c6Skettenis 	    M64_DP_SRC, M64_FRGD_SRC_BLIT);
735f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh,
736f1f6d7c6Skettenis 	    M64_DP_MIX, M64_MIX_SRC << 16);
737f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CNTL, 0);
738f1f6d7c6Skettenis 	if (dy < sy) {
739f1f6d7c6Skettenis 		dest_ctl = M64_DST_Y_TOP_TO_BOTTOM;
740f1f6d7c6Skettenis 	} else {
741f1f6d7c6Skettenis 		sy += h - 1;
742f1f6d7c6Skettenis 		dy += h - 1;
743f1f6d7c6Skettenis 		dest_ctl = M64_DST_Y_BOTTOM_TO_TOP;
744f1f6d7c6Skettenis 	}
745f1f6d7c6Skettenis 	if (dx < sx) {
746f1f6d7c6Skettenis 		dest_ctl |= M64_DST_X_LEFT_TO_RIGHT;
747f1f6d7c6Skettenis 		bus_space_write_4(sc->sc_regt, sc->sc_regh,
748f1f6d7c6Skettenis 		    M64_SRC_CNTL, M64_SRC_LINE_X_LEFT_TO_RIGHT);
749f1f6d7c6Skettenis 	} else {
750f1f6d7c6Skettenis 		dest_ctl |= M64_DST_X_RIGHT_TO_LEFT;
751f1f6d7c6Skettenis 		sx += w - 1;
752f1f6d7c6Skettenis 		dx += w - 1;
753f1f6d7c6Skettenis 		bus_space_write_4(sc->sc_regt, sc->sc_regh,
754f1f6d7c6Skettenis 		    M64_SRC_CNTL, M64_SRC_LINE_X_RIGHT_TO_LEFT);
755f1f6d7c6Skettenis 	}
756f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_CNTL, dest_ctl);
757f1f6d7c6Skettenis 
758f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh,
759f1f6d7c6Skettenis 	    M64_SRC_Y_X, M64_COORDS(sx, sy));
760f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_WIDTH1, w);
761f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh,
762f1f6d7c6Skettenis 	    M64_DST_Y_X, M64_COORDS(dx, dy));
763f1f6d7c6Skettenis 	bus_space_write_4(sc->sc_regt, sc->sc_regh,
764f1f6d7c6Skettenis 	    M64_DST_HEIGHT_WIDTH, M64_COORDS(w, h));
765f1f6d7c6Skettenis 
766f1f6d7c6Skettenis 	machfb_wait(sc);
767f1f6d7c6Skettenis }
768f1f6d7c6Skettenis 
769f1f6d7c6Skettenis void
machfb_fillrect(struct machfb_softc * sc,int x,int y,int w,int h,int color)770f1f6d7c6Skettenis machfb_fillrect(struct machfb_softc *sc, int x, int y, int w, int h, int color)
771f1f6d7c6Skettenis {
772f1f6d7c6Skettenis 	machfb_wait_fifo(sc, 11);
773f1f6d7c6Skettenis 
774f1f6d7c6Skettenis         bus_space_write_4(sc->sc_regt, sc->sc_regh,
775f1f6d7c6Skettenis 	    M64_DP_WRITE_MASK, 0xff);
776f1f6d7c6Skettenis         bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_FRGD_CLR, color);
777f1f6d7c6Skettenis         bus_space_write_4(sc->sc_regt, sc->sc_regh,
778f1f6d7c6Skettenis 	    M64_DP_SRC, M64_FRGD_SRC_FRGD_CLR);
779f1f6d7c6Skettenis         bus_space_write_4(sc->sc_regt, sc->sc_regh,
780f1f6d7c6Skettenis 	    M64_DP_MIX, M64_MIX_SRC << 16);
781f1f6d7c6Skettenis         bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CNTL, 0);
782f1f6d7c6Skettenis         bus_space_write_4(sc->sc_regt, sc->sc_regh,
783f1f6d7c6Skettenis 	    M64_SRC_CNTL, M64_SRC_LINE_X_LEFT_TO_RIGHT);
784f1f6d7c6Skettenis         bus_space_write_4(sc->sc_regt, sc->sc_regh,
785f1f6d7c6Skettenis 	    M64_DST_CNTL, M64_DST_X_LEFT_TO_RIGHT | M64_DST_Y_TOP_TO_BOTTOM);
786f1f6d7c6Skettenis 
787f1f6d7c6Skettenis         bus_space_write_4(sc->sc_regt, sc->sc_regh,
788f1f6d7c6Skettenis 	    M64_SRC_Y_X, M64_COORDS(x, y));
789f1f6d7c6Skettenis         bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_WIDTH1, w);
790f1f6d7c6Skettenis         bus_space_write_4(sc->sc_regt, sc->sc_regh,
791f1f6d7c6Skettenis 	    M64_DST_Y_X, M64_COORDS(x, y));
792f1f6d7c6Skettenis         bus_space_write_4(sc->sc_regt, sc->sc_regh,
793f1f6d7c6Skettenis 	    M64_DST_HEIGHT_WIDTH, M64_COORDS(w, h));
794f1f6d7c6Skettenis 
795f1f6d7c6Skettenis         machfb_wait(sc);
796f1f6d7c6Skettenis }
797