xref: /openbsd/sys/arch/sparc64/dev/raptor.c (revision 91f110e0)
1 /*	$OpenBSD: raptor.c,v 1.8 2013/10/20 20:07:27 miod Exp $	*/
2 
3 /*
4  * Copyright (c) 2009 Mark Kettenis.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/param.h>
20 #include <sys/device.h>
21 #include <sys/pciio.h>
22 #include <sys/systm.h>
23 
24 #include <machine/autoconf.h>
25 #include <machine/bus.h>
26 
27 #include <dev/pci/pcireg.h>
28 #include <dev/pci/pcivar.h>
29 #include <dev/pci/pcidevs.h>
30 
31 #include <dev/wscons/wsconsio.h>
32 #include <dev/wscons/wsdisplayvar.h>
33 
34 #include <dev/rasops/rasops.h>
35 
36 #include <machine/fbvar.h>
37 
38 /*
39  * Tech Source uses the Raptor name for most of its graphics cards.
40  * This driver supports the origional Raptor GFX cards built around
41  * the Number 9 Imagine-128 chips.
42  *
43  * Official documentation for the Imagine-128 isn't available.  The
44  * information used for writing this driver comes mostly from the Xorg
45  * i128 driver.
46  */
47 
48 #define I128_PCI_MW0		0x10
49 #define I128_PCI_MW1		0x14
50 #define I128_PCI_RBASE		0x20
51 
52 #define I128_WR_ADR		0x0000
53 #define I128_PAL_DAT		0x0004
54 #define I128_PEL_MASK		0x0008
55 
56 #define I128_INTM		0x4004
57 #define I128_FLOW		0x4008
58 #define  I128_FLOW_DEB		0x00000001
59 #define  I128_FLOW_MCB		0x00000002
60 #define  I128_FLOW_CLP		0x00000004
61 #define  I128_FLOW_PRV		0x00000008
62 #define  I128_FLOW_ACTIVE	0x0000000f
63 #define I128_BUSY		0x400c
64 #define  I128_BUSY_BUSY		0x00000001
65 #define I128_BUF_CTRL		0x4020
66 #define  I128_BC_PSIZ_8B	0x00000000
67 #define  I128_BC_PSIZ_16B	0x01000000
68 #define  I128_BC_PSIZ_32B	0x02000000
69 #define I128_DE_PGE		0x4024
70 #define I128_DE_SORG		0x4028
71 #define I128_DE_DORG		0x402c
72 #define I128_DE_MSRC		0x4030
73 #define I128_DE_WKEY		0x4038
74 #define I128_DE_ZPTCH		0x403c
75 #define I128_DE_SPTCH		0x4040
76 #define I128_DE_DPTCH		0x4044
77 #define I128_CMD		0x4048
78 #define I128_CMD_OPC		0x4050
79 #define  I128_CO_BITBLT		0x00000001
80 #define I128_CMD_ROP		0x4054
81 #define  I128_CR_COPY		0x0000000c
82 #define I128_CMD_STYLE		0x4058
83 #define  I128_CS_SOLID		0x00000001
84 #define I128_CMD_PATRN		0x405c
85 #define I128_CMD_CLP		0x4060
86 #define I128_CMD_HDF		0x4064
87 #define I128_FORE		0x4068
88 #define I128_MASK		0x4070
89 #define I128_RMSK		0x4074
90 #define I128_LPAT		0x4078
91 #define I128_PCTRL		0x407c
92 #define I128_CLPTL		0x4080
93 #define I128_CLPBR		0x4084
94 #define I128_XY0_SRC		0x4088
95 #define I128_XY1_DST		0x408c
96 #define I128_XY2_WH		0x4090
97 #define I128_XY3_DIR		0x4094
98 #define  I128_DIR_BT		0x00000001
99 #define  I128_DIR_RL		0x00000002
100 #define I128_XY4_ZM		0x4098
101 #define  I128_ZOOM_NONE		0x00000000
102 #define I128_ACNTRL		0x416c
103 
104 #define I128_COORDS(x, y)	((x << 16) | (y))
105 
106 
107 #ifdef APERTURE
108 extern int allowaperture;
109 #endif
110 
111 struct raptor_softc {
112 	struct sunfb	sc_sunfb;
113 
114 	bus_space_tag_t sc_memt;
115 	bus_space_handle_t sc_memh;
116 	bus_addr_t	sc_membase;
117 	bus_size_t	sc_memsize;
118 
119 	bus_space_tag_t	sc_mmiot;
120 	bus_space_handle_t sc_mmioh;
121 	bus_addr_t	sc_mmiobase;
122 	bus_size_t	sc_mmiosize;
123 
124 	pcitag_t	sc_pcitag;
125 
126 	int		sc_mode;
127 	u_int8_t	sc_cmap_red[256];
128 	u_int8_t	sc_cmap_green[256];
129 	u_int8_t	sc_cmap_blue[256];
130 };
131 
132 int	raptor_ioctl(void *, u_long, caddr_t, int, struct proc *);
133 paddr_t	raptor_mmap(void *, off_t, int);
134 
135 struct wsdisplay_accessops raptor_accessops = {
136 	.ioctl = raptor_ioctl,
137 	.mmap = raptor_mmap
138 };
139 
140 int	raptor_match(struct device *, void *, void *);
141 void	raptor_attach(struct device *, struct device *, void *);
142 
143 struct cfattach raptor_ca = {
144 	sizeof(struct raptor_softc), raptor_match, raptor_attach
145 };
146 
147 struct cfdriver raptor_cd = {
148 	NULL, "raptor", DV_DULL
149 };
150 
151 int	raptor_is_console(int);
152 int	raptor_getcmap(struct raptor_softc *, struct wsdisplay_cmap *);
153 int	raptor_putcmap(struct raptor_softc *, struct wsdisplay_cmap *);
154 void	raptor_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
155 
156 int	raptor_copycols(void *, int, int, int, int);
157 int	raptor_erasecols(void *, int, int, int, long);
158 int	raptor_copyrows(void *, int, int, int);
159 int	raptor_eraserows(void *, int, int, long);
160 
161 void	raptor_init(struct raptor_softc *);
162 int	raptor_wait(struct raptor_softc *);
163 void	raptor_copyrect(struct raptor_softc *, int, int, int, int, int, int);
164 void	raptor_fillrect(struct raptor_softc *, int, int, int, int, int);
165 
166 int
167 raptor_match(struct device *parent, void *cf, void *aux)
168 {
169 	struct pci_attach_args *pa = aux;
170 	int node;
171 	char *name;
172 
173 	node = PCITAG_NODE(pa->pa_tag);
174 	name = getpropstring(node, "name");
175 	if (strcmp(name, "TECH-SOURCE,raptor") == 0 ||
176 	    strcmp(name, "TSI,raptor") == 0)
177 		return (10);
178 
179 	return (0);
180 }
181 
182 void
183 raptor_attach(struct device *parent, struct device *self, void *aux)
184 {
185 	struct raptor_softc *sc = (struct raptor_softc *)self;
186 	struct pci_attach_args *pa = aux;
187 	struct rasops_info *ri;
188 	int node, console;
189 	char *model;
190 
191 	sc->sc_pcitag = pa->pa_tag;
192 
193 	node = PCITAG_NODE(pa->pa_tag);
194 	console = raptor_is_console(node);
195 
196 	printf("\n");
197 
198 	model = getpropstring(node, "model");
199 	printf("%s: %s", self->dv_xname, model);
200 
201 	if (pci_mapreg_map(pa, I128_PCI_MW0, PCI_MAPREG_TYPE_MEM,
202 	    BUS_SPACE_MAP_LINEAR, &sc->sc_memt, &sc->sc_memh,
203 	    &sc->sc_membase, &sc->sc_memsize, 0)) {
204 		printf("\n%s: can't map video memory\n", self->dv_xname);
205 		return;
206 	}
207 
208 	if (pci_mapreg_map(pa, I128_PCI_RBASE, PCI_MAPREG_TYPE_MEM, 0,
209 	    &sc->sc_mmiot, &sc->sc_mmioh, &sc->sc_mmiobase,
210 	    &sc->sc_mmiosize, 0)) {
211 		bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_memsize);
212 		printf("\n%s: can't map mmio\n", self->dv_xname);
213 		return;
214 	}
215 
216 	fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);
217 
218 	printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
219 
220 	ri = &sc->sc_sunfb.sf_ro;
221 	ri->ri_bits = bus_space_vaddr(sc->sc_memt, sc->sc_memh);
222 	ri->ri_hw = sc;
223 
224 	fbwscons_init(&sc->sc_sunfb, RI_BSWAP, console);
225 	fbwscons_setcolormap(&sc->sc_sunfb, raptor_setcolor);
226 	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
227 
228 	raptor_init(sc);
229 	ri->ri_ops.copyrows = raptor_copyrows;
230 	ri->ri_ops.copycols = raptor_copycols;
231 	ri->ri_ops.eraserows = raptor_eraserows;
232 	ri->ri_ops.erasecols = raptor_erasecols;
233 
234 	if (console)
235 		fbwscons_console_init(&sc->sc_sunfb, -1);
236 	fbwscons_attach(&sc->sc_sunfb, &raptor_accessops, console);
237 }
238 
239 int
240 raptor_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
241 {
242 	struct raptor_softc *sc = v;
243 	struct wsdisplay_fbinfo *wdf;
244 	struct pcisel *sel;
245 
246 	switch (cmd) {
247 	case WSDISPLAYIO_GTYPE:
248 		*(u_int *)data = WSDISPLAY_TYPE_RAPTOR;
249 		break;
250 	case WSDISPLAYIO_SMODE:
251 		sc->sc_mode = *(u_int *)data;
252 		if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)
253 			fbwscons_setcolormap(&sc->sc_sunfb, raptor_setcolor);
254 		break;
255 	case WSDISPLAYIO_GINFO:
256 		wdf = (void *)data;
257 		wdf->height = sc->sc_sunfb.sf_height;
258 		wdf->width  = sc->sc_sunfb.sf_width;
259 		wdf->depth  = sc->sc_sunfb.sf_depth;
260 		wdf->cmsize = 256;
261 		break;
262 	case WSDISPLAYIO_LINEBYTES:
263 		*(u_int *)data = sc->sc_sunfb.sf_linebytes;
264 		break;
265 
266 	case WSDISPLAYIO_GETCMAP:
267 		return raptor_getcmap(sc, (struct wsdisplay_cmap *)data);
268 	case WSDISPLAYIO_PUTCMAP:
269 		return raptor_putcmap(sc, (struct wsdisplay_cmap *)data);
270 
271 	case WSDISPLAYIO_GPCIID:
272 		sel = (struct pcisel *)data;
273 		sel->pc_bus = PCITAG_BUS(sc->sc_pcitag);
274 		sel->pc_dev = PCITAG_DEV(sc->sc_pcitag);
275 		sel->pc_func = PCITAG_FUN(sc->sc_pcitag);
276 		break;
277 
278 	case WSDISPLAYIO_SVIDEO:
279 	case WSDISPLAYIO_GVIDEO:
280 		break;
281 
282 	case WSDISPLAYIO_GCURPOS:
283 	case WSDISPLAYIO_SCURPOS:
284 	case WSDISPLAYIO_GCURMAX:
285 	case WSDISPLAYIO_GCURSOR:
286 	case WSDISPLAYIO_SCURSOR:
287 	default:
288 		return -1; /* not supported yet */
289         }
290 
291 	return (0);
292 }
293 
294 paddr_t
295 raptor_mmap(void *v, off_t off, int prot)
296 {
297 	struct raptor_softc *sc = v;
298 
299 	if (off & PGOFSET)
300 		return (-1);
301 
302 	switch (sc->sc_mode) {
303 	case WSDISPLAYIO_MODE_MAPPED:
304 #ifdef APERTURE
305 		if (allowaperture == 0)
306 			return (-1);
307 #endif
308 
309 		if (sc->sc_mmiosize == 0)
310 			return (-1);
311 
312 		if (off >= sc->sc_membase &&
313 		    off < (sc->sc_membase + sc->sc_memsize))
314 			return (bus_space_mmap(sc->sc_memt,
315 			    sc->sc_membase, off - sc->sc_membase,
316 			    prot, BUS_SPACE_MAP_LINEAR));
317 
318 		if (off >= sc->sc_mmiobase &&
319 		    off < (sc->sc_mmiobase + sc->sc_mmiosize))
320 			return (bus_space_mmap(sc->sc_mmiot,
321 			    sc->sc_mmiobase, off - sc->sc_mmiobase,
322 			    prot, BUS_SPACE_MAP_LINEAR));
323 		break;
324 
325 	case WSDISPLAYIO_MODE_DUMBFB:
326 		if (off >= 0 && off < sc->sc_memsize)
327 			return (bus_space_mmap(sc->sc_memt, sc->sc_membase,
328 			    off, prot, BUS_SPACE_MAP_LINEAR));
329 		break;
330 	}
331 
332 	return (-1);
333 }
334 
335 int
336 raptor_is_console(int node)
337 {
338 	extern int fbnode;
339 
340 	return (fbnode == node);
341 }
342 
343 int
344 raptor_getcmap(struct raptor_softc *sc, struct wsdisplay_cmap *cm)
345 {
346 	u_int index = cm->index;
347 	u_int count = cm->count;
348 	int error;
349 
350 	if (index >= 256 || count > 256 - index)
351 		return (EINVAL);
352 
353 	error = copyout(&sc->sc_cmap_red[index], cm->red, count);
354 	if (error)
355 		return (error);
356 	error = copyout(&sc->sc_cmap_green[index], cm->green, count);
357 	if (error)
358 		return (error);
359 	error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
360 	if (error)
361 		return (error);
362 	return (0);
363 }
364 
365 int
366 raptor_putcmap(struct raptor_softc *sc, struct wsdisplay_cmap *cm)
367 {
368 	u_int index = cm->index;
369 	u_int count = cm->count;
370 	u_int i;
371 	int error;
372 	u_char *r, *g, *b;
373 
374 	if (index >= 256 || count > 256 - index)
375 		return (EINVAL);
376 
377 	if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0)
378 		return (error);
379 	if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0)
380 		return (error);
381 	if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0)
382 		return (error);
383 
384 	r = &sc->sc_cmap_red[index];
385 	g = &sc->sc_cmap_green[index];
386 	b = &sc->sc_cmap_blue[index];
387 
388 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_PEL_MASK, 0xff);
389 	for (i = 0; i < count; i++) {
390 		bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
391 		    I128_WR_ADR, index);
392 		bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
393 		    I128_PAL_DAT, *r);
394 		bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
395 		    I128_PAL_DAT, *g);
396 		bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
397 		    I128_PAL_DAT, *b);
398 		r++, g++, b++, index++;
399 	}
400 	return (0);
401 }
402 
403 void
404 raptor_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
405 {
406 	struct raptor_softc *sc = v;
407 
408 	sc->sc_cmap_red[index] = r;
409 	sc->sc_cmap_green[index] = g;
410 	sc->sc_cmap_blue[index] = b;
411 
412 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_PEL_MASK, 0xff);
413 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_WR_ADR, index);
414 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_PAL_DAT, r);
415 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_PAL_DAT, g);
416 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_PAL_DAT, b);
417 }
418 
419 /*
420  * Accelerated routines.
421  */
422 
423 int
424 raptor_copycols(void *cookie, int row, int src, int dst, int num)
425 {
426 	struct rasops_info *ri = cookie;
427 	struct raptor_softc *sc = ri->ri_hw;
428 
429 	num *= ri->ri_font->fontwidth;
430 	src *= ri->ri_font->fontwidth;
431 	dst *= ri->ri_font->fontwidth;
432 	row *= ri->ri_font->fontheight;
433 
434 	raptor_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row,
435 	    ri->ri_xorigin + dst, ri->ri_yorigin + row,
436 	    num, ri->ri_font->fontheight);
437 
438 	return 0;
439 }
440 
441 int
442 raptor_erasecols(void *cookie, int row, int col, int num, long attr)
443 {
444 	struct rasops_info *ri = cookie;
445 	struct raptor_softc *sc = ri->ri_hw;
446 	int bg, fg;
447 
448 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
449 
450 	row *= ri->ri_font->fontheight;
451 	col *= ri->ri_font->fontwidth;
452 	num *= ri->ri_font->fontwidth;
453 
454 	raptor_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row,
455 	    num, ri->ri_font->fontheight, ri->ri_devcmap[bg]);
456 
457 	return 0;
458 }
459 
460 int
461 raptor_copyrows(void *cookie, int src, int dst, int num)
462 {
463 	struct rasops_info *ri = cookie;
464 	struct raptor_softc *sc = ri->ri_hw;
465 
466 	num *= ri->ri_font->fontheight;
467 	src *= ri->ri_font->fontheight;
468 	dst *= ri->ri_font->fontheight;
469 
470 	raptor_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src,
471 	    ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num);
472 
473 	return 0;
474 }
475 
476 int
477 raptor_eraserows(void *cookie, int row, int num, long attr)
478 {
479 	struct rasops_info *ri = cookie;
480 	struct raptor_softc *sc = ri->ri_hw;
481 	int bg, fg;
482 	int x, y, w;
483 
484 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
485 
486 	if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
487 		num = ri->ri_height;
488 		x = y = 0;
489 		w = ri->ri_width;
490 	} else {
491 		num *= ri->ri_font->fontheight;
492 		x = ri->ri_xorigin;
493 		y = ri->ri_yorigin + row * ri->ri_font->fontheight;
494 		w = ri->ri_emuwidth;
495 	}
496 	raptor_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]);
497 
498 	return 0;
499 }
500 
501 void
502 raptor_init(struct raptor_softc *sc)
503 {
504 	/* Configure pixel format based on depth. */
505 	switch(sc->sc_sunfb.sf_depth) {
506 	case 8:
507 		bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
508 		    I128_BUF_CTRL, I128_BC_PSIZ_8B);
509 		break;
510 	case 16:
511 		bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
512 		    I128_BUF_CTRL, I128_BC_PSIZ_16B);
513 		break;
514 	case 24:
515 	case 32:
516 		bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
517 		    I128_BUF_CTRL, I128_BC_PSIZ_32B);
518 		break;
519 	default:
520 		panic("unsupported depth");
521 		break;
522 	}
523 
524 	/* Mostly magic. */
525 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_DE_PGE, 0);
526 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_DE_SORG, 0);
527 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_DE_DORG, 0);
528 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_DE_MSRC, 0);
529 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_DE_WKEY, 0);
530 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_DE_SPTCH,
531 	    sc->sc_sunfb.sf_linebytes);
532 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_DE_DPTCH,
533 	    sc->sc_sunfb.sf_linebytes);
534 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_DE_ZPTCH,
535 	    sc->sc_sunfb.sf_linebytes);
536 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_RMSK, 0);
537 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY4_ZM,
538 	    I128_ZOOM_NONE);
539 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_LPAT,
540 	    0xffffffff);
541 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_PCTRL, 0);
542 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_CLPTL, 0);
543 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_CLPBR,
544 	    I128_COORDS(4095, 2047));
545 #if 0
546 	/* XXX For some reason this makes schizo(4) freak out. */
547 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_ACNTRL, 0);
548 #endif
549 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_INTM, 3);
550 }
551 
552 int
553 raptor_wait(struct raptor_softc *sc)
554 {
555 	int i;
556 
557 	for (i = 1000000; i != 0; i--) {
558 		if ((bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh,
559 		    I128_FLOW) & I128_FLOW_ACTIVE) == 0)
560 			break;
561 		DELAY(1);
562 	}
563 
564 	return i;
565 }
566 
567 void
568 raptor_copyrect(struct raptor_softc *sc, int sx, int sy, int dx, int dy,
569     int w, int h)
570 {
571 	int dir = 0;
572 
573 	while (bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh,
574 	    I128_BUSY) & I128_BUSY_BUSY)
575 		DELAY(1);
576 
577 	if (sx < dx) {
578 		sx += w - 1;
579 		dx += w - 1;
580 		dir |= I128_DIR_RL;
581 	}
582 	if (sy < dy) {
583 		sy += h - 1;
584 		dy += h - 1;
585 		dir |= I128_DIR_BT;
586 	}
587 
588 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_CMD,
589 	    I128_CR_COPY << 8 | I128_CO_BITBLT);
590 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY3_DIR, dir);
591 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY2_WH,
592 	    I128_COORDS(w , h));
593 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY0_SRC,
594 	    I128_COORDS(sx, sy));
595 	/* Must be last; triggers operation. */
596 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY1_DST,
597 	    I128_COORDS(dx, dy));
598 
599 	raptor_wait(sc);
600 }
601 
602 void
603 raptor_fillrect(struct raptor_softc *sc, int x, int y, int w, int h, int color)
604 {
605 	while (bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh,
606 	    I128_BUSY) & I128_BUSY_BUSY)
607 		DELAY(1);
608 
609 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_CMD,
610 	    I128_CS_SOLID << 16 | I128_CR_COPY << 8 | I128_CO_BITBLT);
611 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_FORE, color);
612 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY3_DIR, 0);
613 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY2_WH,
614 	    I128_COORDS(w, h));
615 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY0_SRC, 0);
616 	/* Must be last; triggers operation. */
617 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY1_DST,
618 	    I128_COORDS(x, y));
619 
620 	raptor_wait(sc);
621 }
622