xref: /openbsd/sys/arch/loongson/dev/radeonfb.c (revision 905646f0)
1 /*	$OpenBSD: radeonfb.c,v 1.4 2020/05/25 09:55:48 jsg 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/bus.h>
25 #include <machine/cpu.h>
26 
27 #include <uvm/uvm_extern.h>
28 
29 #include <dev/pci/pcireg.h>
30 #include <dev/pci/pcivar.h>
31 #include <dev/pci/pcidevs.h>
32 
33 #include <dev/wscons/wsconsio.h>
34 #include <dev/wscons/wsdisplayvar.h>
35 #include <dev/rasops/rasops.h>
36 
37 #define RADEON_PCI_MEM		0x10
38 #define RADEON_PCI_MMIO		0x18
39 
40 #define RADEON_CRTC_OFFSET		0x0224
41 
42 #define RADEON_RBBM_STATUS		0x0e40
43 #define  RADEON_RBBM_FIFOCNT_MASK	0x0000007f
44 #define  RADEON_RBBM_ACTIVE		0x80000000
45 
46 #define RADEON_SRC_Y_X			0x1434
47 #define RADEON_DST_Y_X			0x1438
48 #define RADEON_DST_HEIGHT_WIDTH		0x143c
49 
50 #define RADEON_DP_GUI_MASTER_CNTL	0x146c
51 #define  RADEON_GMC_DST_8BPP		0x00000200
52 #define  RADEON_GMC_DST_16BPP		0x00000400
53 #define  RADEON_GMC_DST_32BPP		0x00000600
54 #define  RADEON_GMC_BRUSH_NONE		0x000000e0
55 #define  RADEON_GMC_BRUSH_SOLID_COLOR	0x000000d0
56 #define  RADEON_GMC_SRC_DATATYPE_COLOR	0x00003000
57 #define  RADEON_GMC_SRC_SOURCE_MEMORY	0x02000000
58 #define  RADEON_ROP3_S			0x00cc0000
59 #define  RADEON_ROP3_P			0x00f00000
60 #define  RADEON_GMC_CLR_CMP_CNTL_DIS    0x10000000
61 
62 #define RADEON_DP_BRUSH_BKGD_CLR	0x1478
63 #define RADEON_DP_BRUSH_FRGD_CLR	0x147c
64 
65 #define RADEON_DP_CNTL			0x16c0
66 #define  RADEON_DST_X_LEFT_TO_RIGHT	0x00000001
67 #define  RADEON_DST_Y_TOP_TO_BOTTOM	0x00000002
68 #define RADEON_DP_WRITE_MASK		0x16cc
69 
70 #define RADEON_DEFAULT_PITCH_OFFSET	0x16e0
71 #define RADEON_DEFAULT_SC_BOTTOM_RIGHT	0x16e8
72 
73 #define RADEON_WAIT_UNTIL		0x1720
74 #define  RADEON_WAIT_2D_IDLECLEAN	0x00010000
75 #define  RADEON_WAIT_3D_IDLECLEAN	0x00020000
76 #define  RADEON_WAIT_HOST_IDLECLEAN	0x00040000
77 
78 #define RADEON_RB3D_DSTCACHE_CTLSTAT	0x325c
79 #define  RADEON_RB3D_DC_FLUSH_ALL	0x0000000f
80 #define  RADEON_RB3D_DC_BUSY		0x80000000
81 
82 #define RADEON_COORDS(x, y)		((y << 16) | (x))
83 
84 #ifdef APERTURE
85 extern int allowaperture;
86 #endif
87 
88 struct radeonfb_softc;
89 
90 /* minimal frame buffer information, suitable for early console */
91 struct radeonfb {
92 	struct radeonfb_softc	*sc;
93 	struct rasops_info	 ri;
94 
95 	bus_space_tag_t		 fbt;
96 	bus_space_handle_t	 fbh;
97 
98 	bus_space_tag_t		 mmiot;
99 	bus_space_handle_t	 mmioh;
100 	bus_size_t		 memoff;
101 
102 	struct wsscreen_descr	 wsd;
103 };
104 
105 struct radeonfb_softc {
106 	struct device		 sc_dev;
107 	struct radeonfb		*sc_fb;
108 	struct radeonfb		 sc_fb_store;
109 
110 	struct wsscreen_list	 sc_wsl;
111 	struct wsscreen_descr	*sc_scrlist[1];
112 	int			 sc_nscr;
113 
114 	bus_addr_t	sc_membase;
115 	bus_size_t	sc_memsize;
116 
117 	bus_addr_t	sc_mmiobase;
118 	bus_size_t	sc_mmiosize;
119 
120 	pcitag_t	sc_pcitag;
121 
122 	int		sc_mode;
123 };
124 
125 int	radeonfb_alloc_screen(void *, const struct wsscreen_descr *, void **,
126 	    int *, int *, uint32_t *);
127 void	radeonfb_free_screen(void *, void *);
128 int	radeonfb_ioctl(void *, u_long, caddr_t, int, struct proc *);
129 int	radeonfb_list_font(void *, struct wsdisplay_font *);
130 int	radeonfb_load_font(void *, void *, struct wsdisplay_font *);
131 paddr_t	radeonfb_mmap(void *, off_t, int);
132 int	radeonfb_show_screen(void *, void *, int, void (*)(void *, int, int),
133 	    void *);
134 
135 struct wsdisplay_accessops radeonfb_accessops = {
136 	.ioctl = radeonfb_ioctl,
137 	.mmap = radeonfb_mmap,
138 	.alloc_screen = radeonfb_alloc_screen,
139 	.free_screen = radeonfb_free_screen,
140 	.show_screen = radeonfb_show_screen,
141 	.load_font = radeonfb_load_font,
142 	.list_font = radeonfb_list_font
143 };
144 
145 int	radeonfb_match(struct device *, void *, void *);
146 void	radeonfb_attach(struct device *, struct device *, void *);
147 
148 const struct cfattach radeonfb_ca = {
149 	sizeof(struct radeonfb_softc), radeonfb_match, radeonfb_attach
150 };
151 
152 struct cfdriver radeonfb_cd = {
153 	NULL, "radeonfb", DV_DULL
154 };
155 
156 int	radeonfb_copycols(void *, int, int, int, int);
157 int	radeonfb_erasecols(void *, int, int, int, uint32_t);
158 int	radeonfb_copyrows(void *, int, int, int);
159 int	radeonfb_eraserows(void *, int, int, uint32_t);
160 
161 int	radeonfb_setup(struct radeonfb *);
162 void	radeonfb_wait_fifo(struct radeonfb *, int);
163 void	radeonfb_wait(struct radeonfb *);
164 void	radeonfb_copyrect(struct radeonfb *, int, int, int, int, int, int);
165 void	radeonfb_fillrect(struct radeonfb *, int, int, int, int, int);
166 
167 static struct radeonfb radeonfbcn;
168 
169 const struct pci_matchid radeonfb_devices[] = {
170 	{ PCI_VENDOR_ATI, 0x9615 }
171 };
172 
173 int
174 radeonfb_match(struct device *parent, void *cf, void *aux)
175 {
176 	struct pci_attach_args *pa = aux;
177 
178 	return pci_matchbyid(pa, radeonfb_devices, nitems(radeonfb_devices));
179 }
180 
181 void
182 radeonfb_attach(struct device *parent, struct device *self, void *aux)
183 {
184 	struct radeonfb_softc *sc = (struct radeonfb_softc *)self;
185 	struct pci_attach_args *pa = aux;
186 	struct wsemuldisplaydev_attach_args waa;
187 	bus_space_tag_t fbt, mmiot;
188 	bus_space_handle_t fbh, mmioh;
189 #if 0
190 	bus_size_t fbsize, mmiosize;
191 #endif
192 	struct radeonfb *fb;
193 	int console;
194 
195 	sc->sc_pcitag = pa->pa_tag;
196 
197 	if (pci_mapreg_map(pa, RADEON_PCI_MEM, PCI_MAPREG_TYPE_MEM,
198 	    BUS_SPACE_MAP_LINEAR, &fbt, &fbh,
199 	    &sc->sc_membase, &sc->sc_memsize, 0)) {
200 		printf(": can't map video memory\n");
201 		return;
202 	}
203 
204 	if (pci_mapreg_map(pa, RADEON_PCI_MMIO, PCI_MAPREG_TYPE_MEM, 0,
205 	    &mmiot, &mmioh, &sc->sc_mmiobase,
206 	    &sc->sc_mmiosize, 0)) {
207 		printf(": can't map registers\n");
208 		return;
209 	}
210 
211 	console = radeonfbcn.ri.ri_hw != NULL;
212 
213 	if (console)
214 		fb = &radeonfbcn;
215 	else
216 		fb = &sc->sc_fb_store;
217 
218 	fb->sc = sc;
219 	fb->fbt = fbt;
220 	fb->fbh = fbh;
221 	fb->mmiot = mmiot;
222 	fb->mmioh = mmioh;
223 	sc->sc_fb = fb;
224 
225 	if (!console) {
226 		if (radeonfb_setup(fb) != 0) {
227 			printf(": can't setup frame buffer\n");
228 			return;
229 		}
230 	}
231 
232 	printf(": %dx%d, %dbpp\n",
233 	    fb->ri.ri_width, fb->ri.ri_height, fb->ri.ri_depth);
234 
235 	sc->sc_scrlist[0] = &fb->wsd;
236 	sc->sc_wsl.nscreens = 1;
237 	sc->sc_wsl.screens = (const struct wsscreen_descr **)sc->sc_scrlist;
238 
239 	waa.console = console;
240 	waa.scrdata = &sc->sc_wsl;
241 	waa.accessops = &radeonfb_accessops;
242 	waa.accesscookie = sc;
243 	waa.defaultscreens = 0;
244 
245 	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
246 
247 	config_found(self, &waa, wsemuldisplaydevprint);
248 }
249 
250 /*
251  * wsdisplay accessops
252  */
253 
254 int
255 radeonfb_alloc_screen(void *v, const struct wsscreen_descr *type,
256     void **cookiep, int *curxp, int *curyp, uint32_t *attrp)
257 {
258 	struct radeonfb_softc *sc = (struct radeonfb_softc *)v;
259 	struct rasops_info *ri = &sc->sc_fb->ri;
260 
261 	if (sc->sc_nscr > 0)
262 		return ENOMEM;
263 
264 	*cookiep = ri;
265 	*curxp = *curyp = 0;
266 	ri->ri_ops.pack_attr(ri, 0, 0, 0, attrp);
267 	sc->sc_nscr++;
268 
269 	return 0;
270 }
271 
272 void
273 radeonfb_free_screen(void *v, void *cookie)
274 {
275 	struct radeonfb_softc *sc = (struct radeonfb_softc *)v;
276 
277 	sc->sc_nscr--;
278 }
279 
280 int
281 radeonfb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
282 {
283 	struct radeonfb_softc *sc = (struct radeonfb_softc *)v;
284 	struct radeonfb *fb = sc->sc_fb;
285 	struct rasops_info *ri = &fb->ri;
286 	struct wsdisplay_fbinfo *wdf;
287 #if 0
288 	struct pcisel *sel;
289 #endif
290 
291 	switch (cmd) {
292 	case WSDISPLAYIO_GTYPE:
293 		*(u_int *)data = WSDISPLAY_TYPE_RADEONFB;
294 		break;
295 	case WSDISPLAYIO_SMODE:
296 		sc->sc_mode = *(u_int *)data;
297 		if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
298 			/* Clear screen. */
299 			radeonfb_setup(fb);
300 			radeonfb_fillrect(fb, 0, 0, ri->ri_width,
301 			    ri->ri_height, ri->ri_devcmap[WSCOL_BLACK]);
302 		}
303 		break;
304 	case WSDISPLAYIO_GINFO:
305 		wdf = (struct wsdisplay_fbinfo *)data;
306 		wdf->width = ri->ri_width;
307 		wdf->height = ri->ri_height;
308 		wdf->depth = ri->ri_depth;
309 		wdf->cmsize = 0;
310 		break;
311 	case WSDISPLAYIO_LINEBYTES:
312 		*(u_int *)data = ri->ri_stride;
313 		break;
314 
315 #if 0
316 	case WSDISPLAYIO_GPCIID:
317 		sel = (struct pcisel *)data;
318 		sel->pc_bus = PCITAG_BUS(sc->sc_pcitag);
319 		sel->pc_dev = PCITAG_DEV(sc->sc_pcitag);
320 		sel->pc_func = PCITAG_FUN(sc->sc_pcitag);
321 		break;
322 #endif
323 
324 	case WSDISPLAYIO_SVIDEO:
325 	case WSDISPLAYIO_GVIDEO:
326 		break;
327 
328 	default:
329 		return -1;
330         }
331 
332 	return 0;
333 }
334 
335 int
336 radeonfb_show_screen(void *v, void *cookie, int waitok,
337     void (*cb)(void *, int, int), void *cbarg)
338 {
339 	return 0;
340 }
341 
342 paddr_t
343 radeonfb_mmap(void *v, off_t off, int prot)
344 {
345 	struct radeonfb_softc *sc = (struct radeonfb_softc *)v;
346 	struct radeonfb *fb = sc->sc_fb;
347 
348 	if ((off & PAGE_MASK) != 0)
349 		return -1;
350 
351 	switch (sc->sc_mode) {
352 	case WSDISPLAYIO_MODE_MAPPED:
353 #ifdef APERTURE
354 		if (allowaperture == 0)
355 			return (-1);
356 #endif
357 
358 		if (sc->sc_mmiosize == 0)
359 			return (-1);
360 
361 		if (off >= sc->sc_membase &&
362 		    off < (sc->sc_membase + sc->sc_memsize))
363 			return (bus_space_mmap(fb->fbt,
364 			    sc->sc_membase, off - sc->sc_membase,
365 			    prot, BUS_SPACE_MAP_LINEAR));
366 
367 		if (off >= sc->sc_mmiobase &&
368 		    off < (sc->sc_mmiobase + sc->sc_mmiosize))
369 			return (bus_space_mmap(fb->mmiot,
370 			    sc->sc_mmiobase, off - sc->sc_mmiobase,
371 			    prot, BUS_SPACE_MAP_LINEAR));
372 		break;
373 
374 	case WSDISPLAYIO_MODE_DUMBFB:
375 		/*
376 		 * Don't allow mmap if the frame buffer area is not page aligned.
377 		 * XXX we should reprogram it to a page aligned boundary at attach
378 		 * XXX time if this isn't the case.
379 		 */
380 		if ((fb->memoff % PAGE_SIZE) != 0)
381 			return (-1);
382 
383 		if (off >= 0 && off < sc->sc_memsize / 2) {
384 			bus_addr_t base = sc->sc_membase + fb->memoff;
385 
386 			return (bus_space_mmap(fb->fbt, base, off,
387 			    prot, BUS_SPACE_MAP_LINEAR));
388 		}
389 		break;
390 	}
391 
392 	return (-1);
393 }
394 
395 int
396 radeonfb_load_font(void *v, void *emulcookie, struct wsdisplay_font *font)
397 {
398 	struct radeonfb_softc *sc = (struct radeonfb_softc *)v;
399 	struct rasops_info *ri = &sc->sc_fb->ri;
400 
401 	return rasops_load_font(ri, emulcookie, font);
402 }
403 
404 int
405 radeonfb_list_font(void *v, struct wsdisplay_font *font)
406 {
407 	struct radeonfb_softc *sc = (struct radeonfb_softc *)v;
408 	struct rasops_info *ri = &sc->sc_fb->ri;
409 
410 	return rasops_list_font(ri, font);
411 }
412 
413 /*
414  * Accelerated routines.
415  */
416 
417 int
418 radeonfb_copycols(void *cookie, int row, int src, int dst, int num)
419 {
420 	struct rasops_info *ri = cookie;
421 	struct radeonfb *fb = ri->ri_hw;
422 
423 	num *= ri->ri_font->fontwidth;
424 	src *= ri->ri_font->fontwidth;
425 	dst *= ri->ri_font->fontwidth;
426 	row *= ri->ri_font->fontheight;
427 
428 	radeonfb_copyrect(fb, ri->ri_xorigin + src, ri->ri_yorigin + row,
429 	    ri->ri_xorigin + dst, ri->ri_yorigin + row,
430 	    num, ri->ri_font->fontheight);
431 
432 	return 0;
433 }
434 
435 int
436 radeonfb_erasecols(void *cookie, int row, int col, int num, uint32_t attr)
437 {
438 	struct rasops_info *ri = cookie;
439 	struct radeonfb *fb = ri->ri_hw;
440 	int bg, fg;
441 
442 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
443 
444 	row *= ri->ri_font->fontheight;
445 	col *= ri->ri_font->fontwidth;
446 	num *= ri->ri_font->fontwidth;
447 
448 	radeonfb_fillrect(fb, ri->ri_xorigin + col, ri->ri_yorigin + row,
449 	    num, ri->ri_font->fontheight, ri->ri_devcmap[bg]);
450 
451 	return 0;
452 }
453 
454 int
455 radeonfb_copyrows(void *cookie, int src, int dst, int num)
456 {
457 	struct rasops_info *ri = cookie;
458 	struct radeonfb *fb = ri->ri_hw;
459 
460 	num *= ri->ri_font->fontheight;
461 	src *= ri->ri_font->fontheight;
462 	dst *= ri->ri_font->fontheight;
463 
464 	radeonfb_copyrect(fb, ri->ri_xorigin, ri->ri_yorigin + src,
465 	    ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num);
466 
467 	return 0;
468 }
469 
470 int
471 radeonfb_eraserows(void *cookie, int row, int num, uint32_t attr)
472 {
473 	struct rasops_info *ri = cookie;
474 	struct radeonfb *fb = ri->ri_hw;
475 	int bg, fg;
476 	int x, y, w;
477 
478 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
479 
480 	if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
481 		num = ri->ri_height;
482 		x = y = 0;
483 		w = ri->ri_width;
484 	} else {
485 		num *= ri->ri_font->fontheight;
486 		x = ri->ri_xorigin;
487 		y = ri->ri_yorigin + row * ri->ri_font->fontheight;
488 		w = ri->ri_emuwidth;
489 	}
490 	radeonfb_fillrect(fb, x, y, w, num, ri->ri_devcmap[bg]);
491 
492 	return 0;
493 }
494 
495 void
496 radeonfb_wait_fifo(struct radeonfb *fb, int n)
497 {
498 	int i;
499 
500 	for (i = 1000000; i != 0; i--) {
501 		if ((bus_space_read_4(fb->mmiot, fb->mmioh,
502 		    RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK) >= n)
503 			break;
504 		DELAY(1);
505 	}
506 }
507 
508 void
509 radeonfb_wait(struct radeonfb *fb)
510 {
511 	int i;
512 
513 	radeonfb_wait_fifo(fb, 64);
514 
515 	for (i = 1000000; i != 0; i--) {
516 		if ((bus_space_read_4(fb->mmiot, fb->mmioh,
517 		    RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE) == 0)
518 			break;
519 		DELAY(1);
520 	}
521 
522 	bus_space_write_4(fb->mmiot, fb->mmioh,
523 	    RADEON_RB3D_DSTCACHE_CTLSTAT, RADEON_RB3D_DC_FLUSH_ALL);
524 
525 	for (i = 1000000; i != 0; i--) {
526 		if ((bus_space_read_4(fb->mmiot, fb->mmioh,
527 		    RADEON_RB3D_DSTCACHE_CTLSTAT) & RADEON_RB3D_DC_BUSY) == 0)
528 			break;
529 		DELAY(1);
530 	}
531 }
532 
533 void
534 radeonfb_copyrect(struct radeonfb *fb, int sx, int sy, int dx, int dy,
535     int w, int h)
536 {
537 	uint32_t gmc;
538 	uint32_t dir;
539 
540 	radeonfb_wait_fifo(fb, 1);
541 	bus_space_write_4(fb->mmiot, fb->mmioh, RADEON_WAIT_UNTIL,
542 	    RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN);
543 
544 	if (dy < sy) {
545 		dir = RADEON_DST_Y_TOP_TO_BOTTOM;
546 	} else {
547 		sy += h - 1;
548 		dy += h - 1;
549 		dir = 0;
550 	}
551 	if (dx < sx) {
552 		dir |= RADEON_DST_X_LEFT_TO_RIGHT;
553 	} else {
554 		sx += w - 1;
555 		dx += w - 1;
556 	}
557 
558 	radeonfb_wait_fifo(fb, 6);
559 
560 	gmc = RADEON_GMC_DST_16BPP;
561 	gmc |= RADEON_GMC_BRUSH_NONE;
562 	gmc |= RADEON_GMC_SRC_DATATYPE_COLOR;
563 	gmc |= RADEON_GMC_SRC_SOURCE_MEMORY;
564 	gmc |= RADEON_ROP3_S;
565 	gmc |= RADEON_GMC_CLR_CMP_CNTL_DIS;
566 	bus_space_write_4(fb->mmiot, fb->mmioh,
567 	    RADEON_DP_GUI_MASTER_CNTL, gmc);
568 	bus_space_write_4(fb->mmiot, fb->mmioh,
569 	    RADEON_DP_WRITE_MASK, 0xffffffff);
570 	bus_space_write_4(fb->mmiot, fb->mmioh,
571 	    RADEON_DP_CNTL, dir);
572 
573 	bus_space_write_4(fb->mmiot, fb->mmioh,
574 	    RADEON_SRC_Y_X, RADEON_COORDS(sx, sy));
575 	bus_space_write_4(fb->mmiot, fb->mmioh,
576 	    RADEON_DST_Y_X, RADEON_COORDS(dx, dy));
577 	bus_space_write_4(fb->mmiot, fb->mmioh,
578 	    RADEON_DST_HEIGHT_WIDTH, RADEON_COORDS(w, h));
579 
580 	radeonfb_wait(fb);
581 }
582 
583 void
584 radeonfb_fillrect(struct radeonfb *fb, int x, int y, int w, int h, int color)
585 {
586 	uint32_t gmc;
587 
588 	radeonfb_wait_fifo(fb, 1);
589 	bus_space_write_4(fb->mmiot, fb->mmioh, RADEON_WAIT_UNTIL,
590 	    RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN);
591 
592 	radeonfb_wait_fifo(fb, 6);
593 
594 	gmc = RADEON_GMC_DST_16BPP;
595 	gmc |= RADEON_GMC_BRUSH_SOLID_COLOR;
596 	gmc |= RADEON_GMC_SRC_DATATYPE_COLOR;
597 	gmc |= RADEON_ROP3_P;
598 	gmc |= RADEON_GMC_CLR_CMP_CNTL_DIS;
599 	bus_space_write_4(fb->mmiot, fb->mmioh,
600 	    RADEON_DP_GUI_MASTER_CNTL, gmc);
601 	bus_space_write_4(fb->mmiot, fb->mmioh,
602 	    RADEON_DP_BRUSH_FRGD_CLR, color);
603 	bus_space_write_4(fb->mmiot, fb->mmioh,
604 	    RADEON_DP_WRITE_MASK, 0xffffffff);
605 	bus_space_write_4(fb->mmiot, fb->mmioh, RADEON_DP_CNTL,
606 	    RADEON_DST_Y_TOP_TO_BOTTOM | RADEON_DST_X_LEFT_TO_RIGHT);
607 
608 	bus_space_write_4(fb->mmiot, fb->mmioh,
609 	    RADEON_DST_Y_X, RADEON_COORDS(x, y));
610 	bus_space_write_4(fb->mmiot, fb->mmioh,
611 	    RADEON_DST_HEIGHT_WIDTH, RADEON_COORDS(w, h));
612 
613         radeonfb_wait(fb);
614 }
615 
616 /*
617  * Frame buffer initialization.
618  */
619 
620 int
621 radeonfb_setup(struct radeonfb *fb)
622 {
623 	struct rasops_info *ri;
624 	uint width, height, bpp;
625 
626 	/*
627 	 * The firmware sets up the framebuffer such that at starts at
628 	 * an offset from the start of video memory.
629 	 */
630 	fb->memoff =
631 	    bus_space_read_4(fb->mmiot, fb->mmioh, RADEON_CRTC_OFFSET);
632 
633 	width = 800;	/* XXX */
634 	height = 600;	/* XXX */
635 	bpp = 16;
636 
637 	ri = &fb->ri;
638 	ri->ri_width = width;
639 	ri->ri_height = height;
640 	ri->ri_depth = bpp;
641 	ri->ri_stride = (ri->ri_width * ri->ri_depth) / 8;
642 	ri->ri_flg = RI_CENTER | RI_CLEAR | RI_FULLCLEAR;
643 	ri->ri_bits = (void *)(bus_space_vaddr(fb->fbt, fb->fbh) + fb->memoff);
644 	ri->ri_hw = fb;
645 
646 	ri->ri_rnum = 5;
647 	ri->ri_rpos = 11;
648 	ri->ri_gnum = 6;
649 	ri->ri_gpos = 5;
650 	ri->ri_bnum = 5;
651 	ri->ri_bpos = 0;
652 
653 	radeonfb_wait_fifo(fb, 2);
654 	bus_space_write_4(fb->mmiot, fb->mmioh, RADEON_DEFAULT_PITCH_OFFSET,
655 	    ((ri->ri_stride >> 6) << 22) | (fb->memoff >> 10));
656 	bus_space_write_4(fb->mmiot, fb->mmioh,
657 	    RADEON_DEFAULT_SC_BOTTOM_RIGHT, 0x1fff1fff);
658 
659 	rasops_init(ri, 160, 160);
660 
661 	strlcpy(fb->wsd.name, "std", sizeof(fb->wsd.name));
662 	fb->wsd.ncols = ri->ri_cols;
663 	fb->wsd.nrows = ri->ri_rows;
664 	fb->wsd.textops = &ri->ri_ops;
665 	fb->wsd.fontwidth = ri->ri_font->fontwidth;
666 	fb->wsd.fontheight = ri->ri_font->fontheight;
667 	fb->wsd.capabilities = ri->ri_caps;
668 
669 #if 0
670 	ri->ri_ops.copyrows = radeonfb_copyrows;
671 	ri->ri_ops.copycols = radeonfb_copycols;
672 	ri->ri_ops.eraserows = radeonfb_eraserows;
673 	ri->ri_ops.erasecols = radeonfb_erasecols;
674 #endif
675 
676 	return 0;
677 }
678 
679 /*
680  * Early console code
681  */
682 
683 int radeonfb_cnattach(bus_space_tag_t, bus_space_tag_t, pcitag_t, pcireg_t);
684 
685 int
686 radeonfb_cnattach(bus_space_tag_t memt, bus_space_tag_t iot, pcitag_t tag,
687     pcireg_t id)
688 {
689 	uint32_t defattr;
690 	struct rasops_info *ri;
691 	pcireg_t bar;
692 	int rc;
693 
694 	/* filter out unrecognized devices */
695 	switch (id) {
696 	default:
697 		return ENODEV;
698 	case PCI_ID_CODE(PCI_VENDOR_ATI, 0x9615):
699 		break;
700 	}
701 
702 	bar = pci_conf_read_early(tag, RADEON_PCI_MEM);
703 	if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM)
704 		return EINVAL;
705 	radeonfbcn.fbt = memt;
706 	rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */,
707 	    BUS_SPACE_MAP_LINEAR, &radeonfbcn.fbh);
708 	if (rc != 0)
709 		return rc;
710 
711 	bar = pci_conf_read_early(tag, RADEON_PCI_MMIO);
712 	if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM)
713 		return EINVAL;
714 	radeonfbcn.mmiot = memt;
715 	rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */,
716 	    BUS_SPACE_MAP_LINEAR, &radeonfbcn.mmioh);
717 	if (rc != 0)
718 		return rc;
719 
720 	rc = radeonfb_setup(&radeonfbcn);
721 	if (rc != 0)
722 		return rc;
723 
724 	ri = &radeonfbcn.ri;
725 	ri->ri_ops.pack_attr(ri, 0, 0, 0, &defattr);
726 	wsdisplay_cnattach(&radeonfbcn.wsd, ri, 0, 0, defattr);
727 
728 	return 0;
729 }
730