1 /* $NetBSD: crmfb.c,v 1.25 2008/05/08 02:10:59 jmcneill Exp $ */
4 * Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca>
5 * 2008 Michael Lorenz <macallan@netbsd.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
31 * SGI-CRM (O2) Framebuffer driver
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: crmfb.c,v 1.25 2008/05/08 02:10:59 jmcneill Exp $");
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/device.h>
40 #include <sys/malloc.h>
42 #define _SGIMIPS_BUS_DMA_PRIVATE
43 #include <machine/autoconf.h>
44 #include <machine/bus.h>
45 #include <machine/machtype.h>
46 #include <machine/vmparam.h>
48 #include <dev/arcbios/arcbios.h>
49 #include <dev/arcbios/arcbiosvar.h>
51 #include <dev/wscons/wsdisplayvar.h>
52 #include <dev/wscons/wsconsio.h>
53 #include <dev/wsfont/wsfont.h>
54 #include <dev/rasops/rasops.h>
55 #include <dev/wscons/wsdisplay_vconsvar.h>
57 #include <arch/sgimips/dev/crmfbreg.h>
59 /*#define CRMFB_DEBUG*/
61 struct wsscreen_descr crmfb_defaultscreen
= {
70 const struct wsscreen_descr
*_crmfb_scrlist
[] = {
74 struct wsscreen_list crmfb_screenlist
= {
75 sizeof(_crmfb_scrlist
) / sizeof(struct wsscreen_descr
*),
79 static struct vcons_screen crmfb_console_screen
;
81 static int crmfb_ioctl(void *, void *, u_long
, void *, int, struct lwp
*);
82 static paddr_t
crmfb_mmap(void *, void *, off_t
, int);
83 static void crmfb_init_screen(void *, struct vcons_screen
*, int, long *);
85 struct wsdisplay_accessops crmfb_accessops
= {
88 NULL
, /* alloc_screen */
89 NULL
, /* free_screen */
90 NULL
, /* show_screen */
96 /* Memory to allocate to SGI-CRM -- remember, this is stolen from
99 #define CRMFB_TILESIZE (512*128)
101 static int crmfb_match(struct device
*, struct cfdata
*, void *);
102 static void crmfb_attach(struct device
*, struct device
*, void *);
103 int crmfb_probe(void);
105 #define KERNADDR(p) ((void *)((p).addr))
106 #define DMAADDR(p) ((p).map->dm_segs[0].ds_addr)
108 #define CRMFB_REG_MASK(msb, lsb) \
109 ( (((uint32_t) 1 << ((msb)-(lsb)+1)) - 1) << (lsb) )
115 bus_dma_segment_t segs
[1];
121 struct device sc_dev
;
122 struct vcons_data sc_vd
;
124 bus_space_tag_t sc_iot
;
125 bus_space_handle_t sc_ioh
;
126 bus_space_handle_t sc_reh
;
128 bus_dma_tag_t sc_dmat
;
130 struct crmfb_dma sc_dma
;
131 struct crmfb_dma sc_dmai
;
136 int sc_tiles_x
, sc_tiles_y
;
138 int sc_mte_direction
;
141 struct rasops_info sc_rasops
;
152 u_char sc_cmap_red
[256];
153 u_char sc_cmap_green
[256];
154 u_char sc_cmap_blue
[256];
157 static int crmfb_putcmap(struct crmfb_softc
*, struct wsdisplay_cmap
*);
158 static int crmfb_getcmap(struct crmfb_softc
*, struct wsdisplay_cmap
*);
159 static void crmfb_set_palette(struct crmfb_softc
*,
160 int, uint8_t, uint8_t, uint8_t);
161 static int crmfb_set_curpos(struct crmfb_softc
*, int, int);
162 static int crmfb_gcursor(struct crmfb_softc
*, struct wsdisplay_cursor
*);
163 static int crmfb_scursor(struct crmfb_softc
*, struct wsdisplay_cursor
*);
164 static inline void crmfb_write_reg(struct crmfb_softc
*, int, uint32_t);
165 static inline uint32_t crmfb_read_reg(struct crmfb_softc
*, int);
166 static int crmfb_wait_dma_idle(struct crmfb_softc
*);
168 /* setup video hw in given colour depth */
169 static int crmfb_setup_video(struct crmfb_softc
*, int);
170 static void crmfb_setup_palette(struct crmfb_softc
*);
173 void crmfb_test_mte(struct crmfb_softc
*);
176 static void crmfb_fill_rect(struct crmfb_softc
*, int, int, int, int, uint32_t);
177 static void crmfb_bitblt(struct crmfb_softc
*, int, int, int, int, int, int,
179 static void crmfb_scroll(struct crmfb_softc
*, int, int, int, int, int, int);
181 static void crmfb_copycols(void *, int, int, int, int);
182 static void crmfb_erasecols(void *, int, int, int, long);
183 static void crmfb_copyrows(void *, int, int, int);
184 static void crmfb_eraserows(void *, int, int, long);
185 static void crmfb_cursor(void *, int, int, int);
186 static void crmfb_putchar(void *, int, int, u_int
, long);
188 CFATTACH_DECL(crmfb
, sizeof(struct crmfb_softc
),
189 crmfb_match
, crmfb_attach
, NULL
, NULL
);
192 crmfb_match(struct device
*parent
, struct cfdata
*cf
, void *opaque
)
194 return crmfb_probe();
198 crmfb_attach(struct device
*parent
, struct device
*self
, void *opaque
)
200 struct mainbus_attach_args
*ma
;
201 struct crmfb_softc
*sc
;
202 struct rasops_info
*ri
;
203 struct wsemuldisplaydev_attach_args aa
;
211 sc
= (struct crmfb_softc
*)self
;
212 ma
= (struct mainbus_attach_args
*)opaque
;
214 sc
->sc_iot
= SGIMIPS_BUS_SPACE_CRIME
;
215 sc
->sc_dmat
= &sgimips_default_bus_dma_tag
;
216 sc
->sc_wsmode
= WSDISPLAYIO_MODE_EMUL
;
218 aprint_normal(": SGI CRIME Graphics Display Engine\n");
219 rv
= bus_space_map(sc
->sc_iot
, ma
->ma_addr
, 0 /* XXX */,
220 BUS_SPACE_MAP_LINEAR
, &sc
->sc_ioh
);
222 panic("crmfb_attach: can't map I/O space");
223 rv
= bus_space_map(sc
->sc_iot
, 0x15000000, 0x6000, 0, &sc
->sc_reh
);
225 panic("crmfb_attach: can't map rendering engine");
227 /* determine mode configured by firmware */
228 d
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, CRMFB_VT_HCMAP
);
229 sc
->sc_width
= (d
>> CRMFB_VT_HCMAP_ON_SHIFT
) & 0xfff;
230 d
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, CRMFB_VT_VCMAP
);
231 sc
->sc_height
= (d
>> CRMFB_VT_VCMAP_ON_SHIFT
) & 0xfff;
232 d
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, CRMFB_FRM_TILESIZE
);
233 h
= (d
>> CRMFB_FRM_TILESIZE_DEPTH_SHIFT
) & 0x3;
241 if (sc
->sc_width
== 0 || sc
->sc_height
== 0) {
242 aprint_error("%s: device unusable if not setup by firmware\n",
243 sc
->sc_dev
.dv_xname
);
244 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, 0 /* XXX */);
248 aprint_normal("%s: initial resolution %dx%d\n",
249 sc
->sc_dev
.dv_xname
, sc
->sc_width
, sc
->sc_height
);
252 * first determine how many tiles we need
253 * in 32bit each tile is 128x128 pixels
255 sc
->sc_tiles_x
= (sc
->sc_width
+ 127) >> 7;
256 sc
->sc_tiles_y
= (sc
->sc_height
+ 127) >> 7;
257 sc
->sc_fbsize
= 0x10000 * sc
->sc_tiles_x
* sc
->sc_tiles_y
;
259 sc
->sc_dmai
.size
= 256 * sizeof(uint16_t);
260 rv
= bus_dmamem_alloc(sc
->sc_dmat
, sc
->sc_dmai
.size
, 65536, 0,
262 sizeof(sc
->sc_dmai
.segs
) / sizeof(sc
->sc_dmai
.segs
[0]),
263 &sc
->sc_dmai
.nsegs
, BUS_DMA_NOWAIT
);
265 panic("crmfb_attach: can't allocate DMA memory");
266 rv
= bus_dmamem_map(sc
->sc_dmat
, sc
->sc_dmai
.segs
, sc
->sc_dmai
.nsegs
,
267 sc
->sc_dmai
.size
, &sc
->sc_dmai
.addr
,
270 panic("crmfb_attach: can't map DMA memory");
271 rv
= bus_dmamap_create(sc
->sc_dmat
, sc
->sc_dmai
.size
, 1,
272 sc
->sc_dmai
.size
, 0, BUS_DMA_NOWAIT
, &sc
->sc_dmai
.map
);
274 panic("crmfb_attach: can't create DMA map");
275 rv
= bus_dmamap_load(sc
->sc_dmat
, sc
->sc_dmai
.map
, sc
->sc_dmai
.addr
,
276 sc
->sc_dmai
.size
, NULL
, BUS_DMA_NOWAIT
);
278 panic("crmfb_attach: can't load DMA map");
280 /* allocate an extra 64Kb for a linear buffer */
281 sc
->sc_dma
.size
= 0x10000 * (16 * sc
->sc_tiles_x
+ 1);
282 rv
= bus_dmamem_alloc(sc
->sc_dmat
, sc
->sc_dma
.size
, 65536, 0,
284 sizeof(sc
->sc_dma
.segs
) / sizeof(sc
->sc_dma
.segs
[0]),
285 &sc
->sc_dma
.nsegs
, BUS_DMA_NOWAIT
);
287 panic("crmfb_attach: can't allocate DMA memory");
288 rv
= bus_dmamem_map(sc
->sc_dmat
, sc
->sc_dma
.segs
, sc
->sc_dma
.nsegs
,
289 sc
->sc_dma
.size
, &sc
->sc_dma
.addr
,
290 BUS_DMA_NOWAIT
| BUS_DMA_COHERENT
);
292 panic("crmfb_attach: can't map DMA memory");
293 rv
= bus_dmamap_create(sc
->sc_dmat
, sc
->sc_dma
.size
, 1,
294 sc
->sc_dma
.size
, 0, BUS_DMA_NOWAIT
, &sc
->sc_dma
.map
);
296 panic("crmfb_attach: can't create DMA map");
297 rv
= bus_dmamap_load(sc
->sc_dmat
, sc
->sc_dma
.map
, sc
->sc_dma
.addr
,
298 sc
->sc_dma
.size
, NULL
, BUS_DMA_NOWAIT
);
300 panic("crmfb_attach: can't load DMA map");
302 p
= KERNADDR(sc
->sc_dmai
);
303 v
= (unsigned long)DMAADDR(sc
->sc_dma
);
304 for (i
= 0; i
< (sc
->sc_tiles_x
* sc
->sc_tiles_y
); i
++) {
305 p
[i
] = ((uint32_t)v
>> 16) + i
;
307 bus_dmamap_sync(sc
->sc_dmat
, sc
->sc_dmai
.map
, 0, sc
->sc_dmai
.size
,
308 BUS_DMASYNC_PREWRITE
);
309 sc
->sc_scratch
= (char *)KERNADDR(sc
->sc_dma
) + (0xf0000 * sc
->sc_tiles_x
);
310 sc
->sc_linear
= (paddr_t
)DMAADDR(sc
->sc_dma
) + 0x100000 * sc
->sc_tiles_x
;
312 aprint_normal("%s: allocated %d byte fb @ %p (%p)\n",
314 sc
->sc_fbsize
, KERNADDR(sc
->sc_dmai
), KERNADDR(sc
->sc_dma
));
316 sc
->sc_current_cell
= 0;
318 crmfb_setup_video(sc
, 8);
319 ri
= &crmfb_console_screen
.scr_ri
;
320 memset(ri
, 0, sizeof(struct rasops_info
));
322 vcons_init(&sc
->sc_vd
, sc
, &crmfb_defaultscreen
, &crmfb_accessops
);
323 sc
->sc_vd
.init_screen
= crmfb_init_screen
;
324 crmfb_console_screen
.scr_flags
|= VCONS_SCREEN_IS_STATIC
;
325 vcons_init_screen(&sc
->sc_vd
, &crmfb_console_screen
, 1, &defattr
);
327 crmfb_defaultscreen
.ncols
= ri
->ri_cols
;
328 crmfb_defaultscreen
.nrows
= ri
->ri_rows
;
329 crmfb_defaultscreen
.textops
= &ri
->ri_ops
;
330 crmfb_defaultscreen
.capabilities
= ri
->ri_caps
;
331 crmfb_defaultscreen
.modecookie
= NULL
;
333 crmfb_setup_palette(sc
);
334 crmfb_fill_rect(sc
, 0, 0, sc
->sc_width
, sc
->sc_height
,
335 ri
->ri_devcmap
[(defattr
>> 16) & 0xff]);
337 consdev
= ARCBIOS
->GetEnvironmentVariable("ConsoleOut");
338 if (consdev
!= NULL
&& strcmp(consdev
, "video()") == 0) {
339 wsdisplay_cnattach(&crmfb_defaultscreen
, ri
, 0, 0, defattr
);
343 aa
.scrdata
= &crmfb_screenlist
;
344 aa
.accessops
= &crmfb_accessops
;
345 aa
.accesscookie
= &sc
->sc_vd
;
347 config_found(self
, &aa
, wsemuldisplaydevprint
);
364 if (mach_type
!= MACH_SGI_IP32
)
371 crmfb_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
373 struct vcons_data
*vd
;
374 struct crmfb_softc
*sc
;
375 struct vcons_screen
*ms
;
376 struct wsdisplay_fbinfo
*wdf
;
379 vd
= (struct vcons_data
*)v
;
380 sc
= (struct crmfb_softc
*)vd
->cookie
;
381 ms
= (struct vcons_screen
*)vd
->active
;
384 case WSDISPLAYIO_GTYPE
:
385 /* not really, but who cares? */
387 *(u_int
*)data
= WSDISPLAY_TYPE_CRIME
;
389 case WSDISPLAYIO_GINFO
:
390 if (vd
->active
!= NULL
) {
392 wdf
->height
= sc
->sc_height
;
393 wdf
->width
= sc
->sc_width
;
399 case WSDISPLAYIO_GETCMAP
:
400 if (sc
->sc_depth
== 8)
401 return crmfb_getcmap(sc
, (struct wsdisplay_cmap
*)data
);
404 case WSDISPLAYIO_PUTCMAP
:
405 if (sc
->sc_depth
== 8)
406 return crmfb_putcmap(sc
, (struct wsdisplay_cmap
*)data
);
409 case WSDISPLAYIO_LINEBYTES
:
410 *(u_int
*)data
= sc
->sc_width
* sc
->sc_depth
/ 8;
412 case WSDISPLAYIO_SMODE
:
413 nmode
= *(int *)data
;
414 if (nmode
!= sc
->sc_wsmode
) {
415 sc
->sc_wsmode
= nmode
;
416 if (nmode
== WSDISPLAYIO_MODE_EMUL
) {
417 crmfb_setup_video(sc
, 8);
418 crmfb_setup_palette(sc
);
419 vcons_redraw_screen(vd
->active
);
421 crmfb_setup_video(sc
, 32);
425 case WSDISPLAYIO_SVIDEO
:
426 case WSDISPLAYIO_GVIDEO
:
427 return ENODEV
; /* not supported yet */
429 case WSDISPLAYIO_GCURPOS
:
431 struct wsdisplay_curpos
*pos
;
433 pos
= (struct wsdisplay_curpos
*)data
;
434 pos
->x
= sc
->sc_cur_x
;
435 pos
->y
= sc
->sc_cur_y
;
438 case WSDISPLAYIO_SCURPOS
:
440 struct wsdisplay_curpos
*pos
;
442 pos
= (struct wsdisplay_curpos
*)data
;
443 crmfb_set_curpos(sc
, pos
->x
, pos
->y
);
446 case WSDISPLAYIO_GCURMAX
:
448 struct wsdisplay_curpos
*pos
;
450 pos
= (struct wsdisplay_curpos
*)data
;
455 case WSDISPLAYIO_GCURSOR
:
457 struct wsdisplay_cursor
*cu
;
459 cu
= (struct wsdisplay_cursor
*)data
;
460 return crmfb_gcursor(sc
, cu
);
462 case WSDISPLAYIO_SCURSOR
:
464 struct wsdisplay_cursor
*cu
;
466 cu
= (struct wsdisplay_cursor
*)data
;
467 return crmfb_scursor(sc
, cu
);
474 crmfb_mmap(void *v
, void *vs
, off_t offset
, int prot
)
476 struct vcons_data
*vd
;
477 struct crmfb_softc
*sc
;
480 vd
= (struct vcons_data
*)v
;
481 sc
= (struct crmfb_softc
*)vd
->cookie
;
483 /* we probably shouldn't let anyone mmap the framebuffer */
485 if (offset
>= 0 && offset
< (0x100000 * sc
->sc_tiles_x
)) {
486 pa
= bus_dmamem_mmap(sc
->sc_dmat
, sc
->sc_dma
.segs
,
487 sc
->sc_dma
.nsegs
, offset
, prot
,
488 BUS_DMA_WAITOK
| BUS_DMA_COHERENT
);
493 * here would the TLBs be but we don't want to show them to userland
494 * so we return the page containing the status register
496 if ((offset
>= 0x15000000) && (offset
< 0x15002000))
497 return bus_space_mmap(sc
->sc_iot
, 0x15004000, 0, prot
, 0);
498 /* now the actual engine registers */
499 if ((offset
>= 0x15002000) && (offset
< 0x15005000))
500 return bus_space_mmap(sc
->sc_iot
, offset
, 0, prot
, 0);
501 /* and now the scratch area */
502 if ((offset
>= 0x15010000) && (offset
< 0x15020000))
503 return bus_dmamem_mmap(sc
->sc_dmat
, sc
->sc_dma
.segs
,
505 offset
+ (0x100000 * sc
->sc_tiles_x
) - 0x15010000,
506 prot
, BUS_DMA_WAITOK
| BUS_DMA_COHERENT
);
511 crmfb_init_screen(void *c
, struct vcons_screen
*scr
, int existing
,
514 struct crmfb_softc
*sc
;
515 struct rasops_info
*ri
;
517 sc
= (struct crmfb_softc
*)c
;
520 ri
->ri_flg
= RI_CENTER
| RI_FULLCLEAR
;
521 ri
->ri_depth
= sc
->sc_depth
;
522 ri
->ri_width
= sc
->sc_width
;
523 ri
->ri_height
= sc
->sc_height
;
524 ri
->ri_stride
= ri
->ri_width
* (ri
->ri_depth
/ 8);
526 switch (ri
->ri_depth
) {
528 ri
->ri_rnum
= ri
->ri_gnum
= ri
->ri_bnum
= 5;
534 ri
->ri_rnum
= ri
->ri_gnum
= ri
->ri_bnum
= 8;
541 ri
->ri_bits
= KERNADDR(sc
->sc_dma
);
544 ri
->ri_flg
|= RI_CLEAR
;
546 rasops_init(ri
, ri
->ri_height
/ 16, ri
->ri_width
/ 8);
547 ri
->ri_caps
= WSSCREEN_WSCOLORS
;
548 rasops_reconfig(ri
, ri
->ri_height
/ ri
->ri_font
->fontheight
,
549 ri
->ri_width
/ ri
->ri_font
->fontwidth
);
552 /* now make a fake rasops_info for drawing into the scratch tile */
553 memcpy(&sc
->sc_rasops
, ri
, sizeof(struct rasops_info
));
554 sc
->sc_rasops
.ri_width
= 512; /* assume we're always in 8bit here */
555 sc
->sc_rasops
.ri_stride
= 512;
556 sc
->sc_rasops
.ri_height
= 128;
557 sc
->sc_rasops
.ri_xorigin
= 0;
558 sc
->sc_rasops
.ri_yorigin
= 0;
559 sc
->sc_rasops
.ri_bits
= sc
->sc_scratch
;
560 sc
->sc_cells
= 512 / ri
->ri_font
->fontwidth
;
562 ri
->ri_ops
.cursor
= crmfb_cursor
;
563 ri
->ri_ops
.copyrows
= crmfb_copyrows
;
564 ri
->ri_ops
.eraserows
= crmfb_eraserows
;
565 ri
->ri_ops
.copycols
= crmfb_copycols
;
566 ri
->ri_ops
.erasecols
= crmfb_erasecols
;
567 ri
->ri_ops
.putchar
= crmfb_putchar
;
573 crmfb_putcmap(struct crmfb_softc
*sc
, struct wsdisplay_cmap
*cm
)
576 u_char r
[256], g
[256], b
[256];
577 u_char
*rp
, *gp
, *bp
;
583 if (idx
>= 255 || cnt
> 256 || idx
+ cnt
> 256)
586 rv
= copyin(cm
->red
, &r
[idx
], cnt
);
589 rv
= copyin(cm
->green
, &g
[idx
], cnt
);
592 rv
= copyin(cm
->blue
, &b
[idx
], cnt
);
596 memcpy(&sc
->sc_cmap_red
[idx
], &r
[idx
], cnt
);
597 memcpy(&sc
->sc_cmap_green
[idx
], &g
[idx
], cnt
);
598 memcpy(&sc
->sc_cmap_blue
[idx
], &b
[idx
], cnt
);
600 rp
= &sc
->sc_cmap_red
[idx
];
601 gp
= &sc
->sc_cmap_green
[idx
];
602 bp
= &sc
->sc_cmap_blue
[idx
];
604 for (i
= 0; i
< cnt
; i
++) {
605 crmfb_set_palette(sc
, idx
, *rp
, *gp
, *bp
);
614 crmfb_getcmap(struct crmfb_softc
*sc
, struct wsdisplay_cmap
*cm
)
622 if (idx
>= 255 || cnt
> 256 || idx
+ cnt
> 256)
625 rv
= copyout(&sc
->sc_cmap_red
[idx
], cm
->red
, cnt
);
628 rv
= copyout(&sc
->sc_cmap_green
[idx
], cm
->green
, cnt
);
631 rv
= copyout(&sc
->sc_cmap_blue
[idx
], cm
->blue
, cnt
);
639 crmfb_set_palette(struct crmfb_softc
*sc
, int reg
, uint8_t r
, uint8_t g
,
644 if (reg
> 255 || sc
->sc_depth
!= 8)
647 while (bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, CRMFB_CMAP_FIFO
) >= 63)
650 val
= (r
<< 8) | (g
<< 16) | (b
<< 24);
651 crmfb_write_reg(sc
, CRMFB_CMAP
+ (reg
* 4), val
);
657 crmfb_set_curpos(struct crmfb_softc
*sc
, int x
, int y
)
664 val
= ((x
- sc
->sc_hot_x
) & 0xffff) | ((y
- sc
->sc_hot_y
) << 16);
665 crmfb_write_reg(sc
, CRMFB_CURSOR_POS
, val
);
671 crmfb_gcursor(struct crmfb_softc
*sc
, struct wsdisplay_cursor
*cur
)
673 /* do nothing for now */
678 crmfb_scursor(struct crmfb_softc
*sc
, struct wsdisplay_cursor
*cur
)
680 if (cur
->which
& WSDISPLAY_CURSOR_DOCUR
) {
682 crmfb_write_reg(sc
, CRMFB_CURSOR_CONTROL
, cur
->enable
? 1 : 0);
684 if (cur
->which
& WSDISPLAY_CURSOR_DOHOT
) {
686 sc
->sc_hot_x
= cur
->hot
.x
;
687 sc
->sc_hot_y
= cur
->hot
.y
;
689 if (cur
->which
& WSDISPLAY_CURSOR_DOPOS
) {
691 crmfb_set_curpos(sc
, cur
->pos
.x
, cur
->pos
.y
);
693 if (cur
->which
& WSDISPLAY_CURSOR_DOCMAP
) {
697 for (i
= 0; i
< cur
->cmap
.count
; i
++) {
698 val
= (cur
->cmap
.red
[i
] << 24) |
699 (cur
->cmap
.green
[i
] << 16) |
700 (cur
->cmap
.blue
[i
] << 8);
701 crmfb_write_reg(sc
, CRMFB_CURSOR_CMAP0
+
702 ((i
+ cur
->cmap
.index
) << 2), val
);
705 if (cur
->which
& WSDISPLAY_CURSOR_DOSHAPE
) {
708 uint32_t latch
= 0, omask
;
710 for (i
= 0; i
< 64; i
++) {
713 cur
->image
[cnt
] &= cur
->mask
[cnt
];
714 for (j
= 0; j
< 8; j
++) {
715 if (cur
->image
[cnt
] & imask
)
718 if (cur
->mask
[cnt
] & imask
)
725 cur
->image
[cnt
] &= cur
->mask
[cnt
];
726 for (j
= 0; j
< 8; j
++) {
727 if (cur
->image
[cnt
] & imask
)
730 if (cur
->mask
[cnt
] & imask
)
736 crmfb_write_reg(sc
, CRMFB_CURSOR_BITMAP
+ (i
<< 2),
745 crmfb_write_reg(struct crmfb_softc
*sc
, int offset
, uint32_t val
)
748 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, offset
, val
);
752 static inline uint32_t
753 crmfb_read_reg(struct crmfb_softc
*sc
, int offset
)
756 return bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, offset
);
760 crmfb_wait_dma_idle(struct crmfb_softc
*sc
)
762 int bail
= 100000, idle
;
765 idle
= ((bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
,
766 CRMFB_OVR_CONTROL
) & 1) == 0) &&
767 ((bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
,
768 CRMFB_FRM_CONTROL
) & 1) == 0) &&
769 ((bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
,
770 CRMFB_DID_CONTROL
) & 1) == 0);
774 } while ((!idle
) && (bail
> 0));
779 crmfb_setup_video(struct crmfb_softc
*sc
, int depth
)
782 uint32_t d
, h
, mode
, page
;
783 int i
, bail
, tile_width
, tlbptr
, lptr
, j
, tx
, shift
;
784 const char *wantsync
;
788 d
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, CRMFB_OVR_CONTROL
);
789 d
&= ~(1 << CRMFB_OVR_CONTROL_DMAEN_SHIFT
);
790 crmfb_write_reg(sc
, CRMFB_OVR_CONTROL
, d
);
792 d
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, CRMFB_FRM_CONTROL
);
793 d
&= ~(1 << CRMFB_FRM_CONTROL_DMAEN_SHIFT
);
794 crmfb_write_reg(sc
, CRMFB_FRM_CONTROL
, d
);
796 crmfb_write_reg(sc
, CRMFB_DID_CONTROL
, 0);
799 if (!crmfb_wait_dma_idle(sc
))
800 aprint_error("crmfb: crmfb_wait_dma_idle timed out\n");
802 /* ensure that CRM starts drawing at the top left of the screen
803 * when we re-enable DMA later
805 d
= (1 << CRMFB_VT_XY_FREEZE_SHIFT
);
806 crmfb_write_reg(sc
, CRMFB_VT_XY
, d
);
808 d
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, CRMFB_DOTCLOCK
);
809 d
&= ~(1 << CRMFB_DOTCLOCK_CLKRUN_SHIFT
);
810 crmfb_write_reg(sc
, CRMFB_DOTCLOCK
, d
);
812 /* wait for dotclock to turn off */
814 while ((bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, CRMFB_DOTCLOCK
) &
815 (1 << CRMFB_DOTCLOCK_CLKRUN_SHIFT
)) && (bail
> 0)) {
821 d
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, CRMFB_FRM_TILESIZE
);
822 d
|= (1 << CRMFB_FRM_TILESIZE_FIFOR_SHIFT
);
823 crmfb_write_reg(sc
, CRMFB_FRM_TILESIZE
, d
);
824 d
&= ~(1 << CRMFB_FRM_TILESIZE_FIFOR_SHIFT
);
825 crmfb_write_reg(sc
, CRMFB_FRM_TILESIZE
, d
);
827 /* setup colour mode */
830 h
= CRMFB_MODE_TYP_I8
;
834 h
= CRMFB_MODE_TYP_ARGB5
;
838 h
= CRMFB_MODE_TYP_RGB8
;
842 panic("Unsupported depth");
844 d
= h
<< CRMFB_MODE_TYP_SHIFT
;
845 d
|= CRMFB_MODE_BUF_BOTH
<< CRMFB_MODE_BUF_SHIFT
;
846 for (i
= 0; i
< (32 * 4); i
+= 4)
847 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, CRMFB_MODE
+ i
, d
);
850 /* setup tile pointer, but don't turn on DMA yet! */
851 h
= DMAADDR(sc
->sc_dmai
);
852 d
= (h
>> 9) << CRMFB_FRM_CONTROL_TILEPTR_SHIFT
;
853 crmfb_write_reg(sc
, CRMFB_FRM_CONTROL
, d
);
855 /* init framebuffer width and pixel size */
856 /*d = (1 << CRMFB_FRM_TILESIZE_WIDTH_SHIFT);*/
858 d
= ((int)(sc
->sc_width
/ tile_width
)) <<
859 CRMFB_FRM_TILESIZE_WIDTH_SHIFT
;
860 if ((sc
->sc_width
& (tile_width
- 1)) != 0)
865 h
= CRMFB_FRM_TILESIZE_DEPTH_8
;
868 h
= CRMFB_FRM_TILESIZE_DEPTH_16
;
871 h
= CRMFB_FRM_TILESIZE_DEPTH_32
;
874 panic("Unsupported depth");
876 d
|= (h
<< CRMFB_FRM_TILESIZE_DEPTH_SHIFT
);
877 crmfb_write_reg(sc
, CRMFB_FRM_TILESIZE
, d
);
879 /*h = sc->sc_width * sc->sc_height / (512 / (depth >> 3));*/
881 d
= h
<< CRMFB_FRM_PIXSIZE_HEIGHT_SHIFT
;
882 crmfb_write_reg(sc
, CRMFB_FRM_PIXSIZE
, d
);
884 /* turn off firmware overlay and hardware cursor */
885 crmfb_write_reg(sc
, CRMFB_OVR_WIDTH_TILE
, 0);
886 crmfb_write_reg(sc
, CRMFB_CURSOR_CONTROL
, 0);
888 /* enable drawing again */
889 d
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, CRMFB_DOTCLOCK
);
890 d
|= (1 << CRMFB_DOTCLOCK_CLKRUN_SHIFT
);
891 crmfb_write_reg(sc
, CRMFB_DOTCLOCK
, d
);
892 crmfb_write_reg(sc
, CRMFB_VT_XY
, 0);
894 /* turn on DMA for the framebuffer */
895 d
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, CRMFB_FRM_CONTROL
);
896 d
|= (1 << CRMFB_FRM_CONTROL_DMAEN_SHIFT
);
897 crmfb_write_reg(sc
, CRMFB_FRM_CONTROL
, d
);
899 /* turn off sync-on-green */
901 wantsync
= ARCBIOS
->GetEnvironmentVariable("SyncOnGreen");
902 if ( (wantsync
!= NULL
) && (wantsync
[0] == 'n') ) {
903 d
= ( 1 << CRMFB_VT_FLAGS_SYNC_LOW_LSB
) &
904 CRMFB_REG_MASK(CRMFB_VT_FLAGS_SYNC_LOW_MSB
,
905 CRMFB_VT_FLAGS_SYNC_LOW_LSB
);
906 crmfb_write_reg(sc
, CRMFB_VT_FLAGS
, d
);
909 sc
->sc_depth
= depth
;
911 /* finally set up the drawing engine's TLB A */
912 v
= (DMAADDR(sc
->sc_dma
) >> 16) & 0xffff;
914 tx
= ((sc
->sc_width
+ (tile_width
- 1)) & ~(tile_width
- 1)) /
918 printf("tx: %d\n", tx
);
921 for (i
= 0; i
< 16; i
++) {
925 for (j
= 0; j
< tx
; j
++) {
927 reg
|= (((uint64_t)(v
| 0x8000)) << shift
);
930 bus_space_write_8(sc
->sc_iot
, sc
->sc_reh
,
931 CRIME_RE_TLB_A
+ tlbptr
+ lptr
,
934 printf("%04x: %016llx\n", tlbptr
+ lptr
, reg
);
942 bus_space_write_8(sc
->sc_iot
, sc
->sc_reh
,
943 CRIME_RE_TLB_A
+ tlbptr
+ lptr
, reg
);
945 printf("%04x: %016llx\n", tlbptr
+ lptr
, reg
);
950 sc
->sc_scratch
= (char *)KERNADDR(sc
->sc_dma
) + (0xf0000 * tx
);
952 /* now put the last 64kB into the 1st linear TLB */
953 page
= (sc
->sc_linear
>> 12) | 0x80000000;
955 for (i
= 0; i
< 8; i
++) {
956 reg
= ((uint64_t)page
<< 32) | (page
+ 1);
957 bus_space_write_8(sc
->sc_iot
, sc
->sc_reh
,
958 CRIME_RE_LINEAR_A
+ tlbptr
, reg
);
964 /* do some very basic engine setup */
965 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_CLIPMODE
, 0);
966 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_WINOFFSET_SRC
, 0);
967 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_WINOFFSET_DST
, 0);
968 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_PLANEMASK
,
971 bus_space_write_8(sc
->sc_iot
, sc
->sc_reh
, 0x20, 0);
972 bus_space_write_8(sc
->sc_iot
, sc
->sc_reh
, 0x28, 0);
973 bus_space_write_8(sc
->sc_iot
, sc
->sc_reh
, 0x30, 0);
974 bus_space_write_8(sc
->sc_iot
, sc
->sc_reh
, 0x38, 0);
975 bus_space_write_8(sc
->sc_iot
, sc
->sc_reh
, 0x40, 0);
979 mode
= DE_MODE_TLB_A
| DE_MODE_BUFDEPTH_8
|
980 DE_MODE_TYPE_CI
| DE_MODE_PIXDEPTH_8
;
983 mode
= DE_MODE_TLB_A
| DE_MODE_BUFDEPTH_16
|
984 DE_MODE_TYPE_RGB
| DE_MODE_PIXDEPTH_16
;
987 mode
= DE_MODE_TLB_A
| DE_MODE_BUFDEPTH_32
|
988 DE_MODE_TYPE_RGBA
| DE_MODE_PIXDEPTH_32
;
991 panic("%s: unsuported colour depth %d\n", __func__
,
994 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_MODE_DST
, mode
);
995 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_MODE_SRC
, mode
);
996 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_XFER_STEP_X
, 1);
997 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_XFER_STEP_Y
, 1);
999 /* initialize memory transfer engine */
1000 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_MODE
,
1002 (MTE_TLB_A
<< MTE_DST_TLB_SHIFT
) |
1003 (MTE_TLB_A
<< MTE_SRC_TLB_SHIFT
) |
1004 (MTE_DEPTH_8
<< MTE_DEPTH_SHIFT
) |
1006 sc
->sc_mte_direction
= 1;
1007 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_DST_Y_STEP
, 1);
1008 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_SRC_Y_STEP
, 1);
1014 crmfb_set_mte_direction(struct crmfb_softc
*sc
, int dir
)
1016 if (dir
== sc
->sc_mte_direction
)
1019 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_DST_Y_STEP
, dir
);
1020 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_SRC_Y_STEP
, dir
);
1021 sc
->sc_mte_direction
= dir
;
1025 crmfb_setup_palette(struct crmfb_softc
*sc
)
1029 for (i
= 0; i
< 256; i
++) {
1030 crmfb_set_palette(sc
, i
, rasops_cmap
[(i
* 3) + 2],
1031 rasops_cmap
[(i
* 3) + 1], rasops_cmap
[(i
* 3) + 0]);
1032 sc
->sc_cmap_red
[i
] = rasops_cmap
[(i
* 3) + 2];
1033 sc
->sc_cmap_green
[i
] = rasops_cmap
[(i
* 3) + 1];
1034 sc
->sc_cmap_blue
[i
] = rasops_cmap
[(i
* 3) + 0];
1039 crmfb_wait_idle(struct crmfb_softc
*sc
)
1045 } while (((bus_space_read_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_STATUS
) &
1046 CRIME_DE_IDLE
) == 0) && (i
< 100000000));
1048 aprint_error("crmfb_wait_idle() timed out\n");
1052 crmfb_fill_rect(struct crmfb_softc
*sc
, int x
, int y
, int width
, int height
,
1055 crmfb_wait_idle(sc
);
1056 crmfb_set_mte_direction(sc
, 1);
1057 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_MODE
,
1059 (MTE_TLB_A
<< MTE_DST_TLB_SHIFT
) |
1060 (MTE_TLB_A
<< MTE_SRC_TLB_SHIFT
) |
1061 (MTE_DEPTH_8
<< MTE_DEPTH_SHIFT
) |
1063 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_BG
, colour
);
1064 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_DST0
,
1065 (x
<< 16) | (y
& 0xffff));
1066 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
,
1067 CRIME_MTE_DST1
| CRIME_DE_START
,
1068 ((x
+ width
- 1) << 16) | ((y
+ height
- 1) & 0xffff));
1072 crmfb_bitblt(struct crmfb_softc
*sc
, int xs
, int ys
, int xd
, int yd
,
1073 int wi
, int he
, uint32_t rop
)
1075 uint32_t prim
= DE_PRIM_RECTANGLE
;
1076 int rxa
, rya
, rxe
, rye
, rxs
, rys
;
1077 crmfb_wait_idle(sc
);
1078 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_DRAWMODE
,
1079 DE_DRAWMODE_PLANEMASK
| DE_DRAWMODE_BYTEMASK
| DE_DRAWMODE_ROP
|
1080 DE_DRAWMODE_XFER_EN
);
1081 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_ROP
, rop
);
1104 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_PRIMITIVE
, prim
);
1105 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_XFER_ADDR_SRC
,
1106 (rxs
<< 16) | (rys
& 0xffff));
1107 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_X_VERTEX_0
,
1108 (rxa
<< 16) | (rya
& 0xffff));
1109 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
,
1110 CRIME_DE_X_VERTEX_1
| CRIME_DE_START
,
1111 (rxe
<< 16) | (rye
& 0xffff));
1115 crmfb_scroll(struct crmfb_softc
*sc
, int xs
, int ys
, int xd
, int yd
,
1118 int rxa
, rya
, rxe
, rye
, rxd
, ryd
, rxde
, ryde
;
1125 crmfb_wait_idle(sc
);
1127 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_MODE
,
1129 (MTE_TLB_A
<< MTE_DST_TLB_SHIFT
) |
1130 (MTE_TLB_A
<< MTE_SRC_TLB_SHIFT
) |
1131 (MTE_DEPTH_8
<< MTE_DEPTH_SHIFT
) |
1140 crmfb_set_mte_direction(sc
, -1);
1147 crmfb_set_mte_direction(sc
, 1);
1149 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_SRC0
,
1151 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_SRC1
,
1153 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
,
1156 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_DST1
|
1158 (rxde
<< 16) | ryde
);
1163 crmfb_test_mte(struct crmfb_softc
*sc
)
1166 uint32_t addrs
[256];
1169 crmfb_wait_idle(sc
);
1170 addr
= (uint64_t)(DMAADDR(sc
->sc_dma
) + sc
->sc_fbsize
);
1172 for (i
= 0; i
< 64; i
+= 8) {
1174 reg
= (addr
<< 32) | (addr
+ 1) | 0x8000000080000000LL
;
1175 bus_space_write_8(sc
->sc_iot
, sc
->sc_reh
,
1176 CRIME_RE_LINEAR_A
+ i
, reg
);
1177 printf(" %08x", (uint32_t)(addr
& 0xffffffff));
1182 memset(sc
->sc_scratch
, 4, 0x10000);
1183 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_MODE_SRC
,
1184 DE_MODE_LIN_A
| DE_MODE_BUFDEPTH_8
| DE_MODE_TYPE_CI
|
1185 DE_MODE_PIXDEPTH_8
);
1186 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_XFER_STRD_SRC
, 1);
1187 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_DRAWMODE
,
1188 DE_DRAWMODE_PLANEMASK
| DE_DRAWMODE_BYTEMASK
| DE_DRAWMODE_ROP
|
1189 DE_DRAWMODE_XFER_EN
);
1190 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_ROP
, 3);
1191 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_PRIMITIVE
,
1192 DE_PRIM_RECTANGLE
| DE_PRIM_TB
);
1193 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_XFER_ADDR_SRC
, 0);
1194 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_X_VERTEX_0
,
1196 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
,
1197 CRIME_DE_X_VERTEX_1
| CRIME_DE_START
,
1200 crmfb_wait_idle(sc
);
1201 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_MODE_SRC
,
1202 DE_MODE_TLB_A
| DE_MODE_BUFDEPTH_8
| DE_MODE_TYPE_CI
|
1203 DE_MODE_PIXDEPTH_8
);
1208 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_BG
, 0x15151515);
1209 crmfb_wait_idle(sc
);
1210 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_MODE
,
1212 (MTE_TLB_LIN_A
<< MTE_DST_TLB_SHIFT
) |
1213 (MTE_TLB_A
<< MTE_SRC_TLB_SHIFT
) |
1214 (MTE_DEPTH_8
<< MTE_DEPTH_SHIFT
) |
1215 0/*MTE_MODE_COPY*/);
1216 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_DST_STRIDE
, 1);
1217 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_SRC_STRIDE
, 1);
1218 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_SRC0
, 0x00000000);
1219 //bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_MTE_SRC1, 0x01000100);
1220 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_DST0
, 0x00000000);
1221 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_DST1
|
1222 CRIME_DE_START
, 0x00010000);
1223 //status[9] = bus_space_read_4(sc->sc_iot, sc->sc_reh, CRIME_DE_STATUS);
1224 crmfb_wait_idle(sc
);
1225 /* now look for 0x05050505 in RAM */
1228 for (i
= 0xA0000000; i
< 0xB0000000; i
+= 0x1000)
1229 if (*((uint32_t *)i
) == 0x15151515) {
1230 /* see if there's more */
1232 while ((j
< 0x100) && (*((uint32_t *)(i
+ j
)) ==
1241 for (i
= 0; i
< boo
; i
++)
1242 printf(" %08x", addrs
[i
]);
1245 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_MODE_SRC
,
1246 DE_MODE_LIN_A
| DE_MODE_BUFDEPTH_8
| DE_MODE_TYPE_CI
|
1247 DE_MODE_PIXDEPTH_8
);
1248 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_XFER_STRD_SRC
, 1);
1249 crmfb_bitblt(sc
, 0, 0, 400, 0, 512, 64, 3);
1250 crmfb_wait_idle(sc
);
1251 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_MODE_SRC
,
1252 DE_MODE_TLB_A
| DE_MODE_BUFDEPTH_8
| DE_MODE_TYPE_CI
|
1253 DE_MODE_PIXDEPTH_8
);
1255 bus_space_write_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_MTE_MODE
,
1257 (MTE_TLB_A
<< MTE_DST_TLB_SHIFT
) |
1258 (MTE_TLB_A
<< MTE_SRC_TLB_SHIFT
) |
1259 (MTE_DEPTH_8
<< MTE_DEPTH_SHIFT
) |
1260 0/*MTE_MODE_COPY*/);
1264 for (i
= 0; i
< 128; i
+=8)
1265 printf("%016llx\n", bus_space_read_8(sc
->sc_iot
, sc
->sc_reh
,
1266 CRIME_RE_LINEAR_B
+ i
));
1269 printf("flush: %08x\n",
1270 bus_space_read_4(sc
->sc_iot
, sc
->sc_reh
, CRIME_DE_FLUSH
));
1273 #endif /* CRMFB_DEBUG */
1276 crmfb_copycols(void *cookie
, int row
, int srccol
, int dstcol
, int ncols
)
1278 struct rasops_info
*ri
= cookie
;
1279 struct vcons_screen
*scr
= ri
->ri_hw
;
1280 int32_t xs
, xd
, y
, width
, height
;
1282 xs
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* srccol
;
1283 xd
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* dstcol
;
1284 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
1285 width
= ri
->ri_font
->fontwidth
* ncols
;
1286 height
= ri
->ri_font
->fontheight
;
1287 crmfb_bitblt(scr
->scr_cookie
, xs
, y
, xd
, y
, width
, height
, 3);
1291 crmfb_erasecols(void *cookie
, int row
, int startcol
, int ncols
, long fillattr
)
1293 struct rasops_info
*ri
= cookie
;
1294 struct vcons_screen
*scr
= ri
->ri_hw
;
1295 int32_t x
, y
, width
, height
, bg
;
1297 x
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* startcol
;
1298 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
1299 width
= ri
->ri_font
->fontwidth
* ncols
;
1300 height
= ri
->ri_font
->fontheight
;
1301 bg
= (uint32_t)ri
->ri_devcmap
[(fillattr
>> 16) & 0xff];
1302 crmfb_fill_rect(scr
->scr_cookie
, x
, y
, width
, height
, bg
);
1306 crmfb_copyrows(void *cookie
, int srcrow
, int dstrow
, int nrows
)
1308 struct rasops_info
*ri
= cookie
;
1309 struct vcons_screen
*scr
= ri
->ri_hw
;
1310 int32_t x
, ys
, yd
, width
, height
;
1313 ys
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* srcrow
;
1314 yd
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* dstrow
;
1315 width
= ri
->ri_emuwidth
;
1316 height
= ri
->ri_font
->fontheight
* nrows
;
1318 crmfb_scroll(scr
->scr_cookie
, x
, ys
, x
, yd
, width
, height
);
1322 crmfb_eraserows(void *cookie
, int row
, int nrows
, long fillattr
)
1324 struct rasops_info
*ri
= cookie
;
1325 struct vcons_screen
*scr
= ri
->ri_hw
;
1326 int32_t x
, y
, width
, height
, bg
;
1328 if ((row
== 0) && (nrows
== ri
->ri_rows
)) {
1330 width
= ri
->ri_width
;
1331 height
= ri
->ri_height
;
1334 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
1335 width
= ri
->ri_emuwidth
;
1336 height
= ri
->ri_font
->fontheight
* nrows
;
1338 bg
= (uint32_t)ri
->ri_devcmap
[(fillattr
>> 16) & 0xff];
1339 crmfb_fill_rect(scr
->scr_cookie
, x
, y
, width
, height
, bg
);
1343 crmfb_cursor(void *cookie
, int on
, int row
, int col
)
1345 struct rasops_info
*ri
= cookie
;
1346 struct vcons_screen
*scr
= ri
->ri_hw
;
1347 struct crmfb_softc
*sc
= scr
->scr_cookie
;
1350 wi
= ri
->ri_font
->fontwidth
;
1351 he
= ri
->ri_font
->fontheight
;
1353 if (ri
->ri_flg
& RI_CURSOR
) {
1354 x
= ri
->ri_ccol
* wi
+ ri
->ri_xorigin
;
1355 y
= ri
->ri_crow
* he
+ ri
->ri_yorigin
;
1356 crmfb_bitblt(sc
, x
, y
, x
, y
, wi
, he
, 12);
1357 ri
->ri_flg
&= ~RI_CURSOR
;
1365 x
= ri
->ri_ccol
* wi
+ ri
->ri_xorigin
;
1366 y
= ri
->ri_crow
* he
+ ri
->ri_yorigin
;
1367 crmfb_bitblt(sc
, x
, y
, x
, y
, wi
, he
, 12);
1368 ri
->ri_flg
|= RI_CURSOR
;
1373 crmfb_putchar(void *cookie
, int row
, int col
, u_int c
, long attr
)
1375 struct rasops_info
*ri
= cookie
;
1376 struct vcons_screen
*scr
= ri
->ri_hw
;
1377 struct crmfb_softc
*sc
= scr
->scr_cookie
;
1378 struct rasops_info
*fri
= &sc
->sc_rasops
;
1380 int x
, y
, wi
, he
, xs
;
1382 wi
= ri
->ri_font
->fontwidth
;
1383 he
= ri
->ri_font
->fontheight
;
1385 x
= ri
->ri_xorigin
+ col
* wi
;
1386 y
= ri
->ri_yorigin
+ row
* he
;
1388 bg
= ri
->ri_devcmap
[(attr
>> 16) & 0xff];
1390 crmfb_fill_rect(sc
, x
, y
, wi
, he
, bg
);
1393 * we rotate over all available character cells in the scratch
1394 * tile. The idea is to have more cells than there's room for
1395 * drawing commands in the engine's pipeline so we don't have
1396 * to wait for the engine until we're done drawing the
1397 * character and ready to blit it into place
1399 fri
->ri_ops
.putchar(fri
, 0, sc
->sc_current_cell
, c
, attr
);
1400 xs
= sc
->sc_current_cell
* wi
;
1401 sc
->sc_current_cell
++;
1402 if (sc
->sc_current_cell
>= sc
->sc_cells
)
1403 sc
->sc_current_cell
= 0;
1404 crmfb_bitblt(sc
, xs
, 2048-128, x
, y
, wi
, he
, 3);