182bb7c22SToomas Soome /*
282bb7c22SToomas Soome  * This file and its contents are supplied under the terms of the
382bb7c22SToomas Soome  * Common Development and Distribution License ("CDDL"), version 1.0.
482bb7c22SToomas Soome  * You may only use this file in accordance with the terms of version
582bb7c22SToomas Soome  * 1.0 of the CDDL.
682bb7c22SToomas Soome  *
782bb7c22SToomas Soome  * A full copy of the text of the CDDL should have accompanied this
882bb7c22SToomas Soome  * source.  A copy of the CDDL is also available via the Internet at
982bb7c22SToomas Soome  * http://www.illumos.org/license/CDDL.
1082bb7c22SToomas Soome  */
1182bb7c22SToomas Soome 
1282bb7c22SToomas Soome /*
1382bb7c22SToomas Soome  * Copyright 2016 Toomas Soome <tsoome@me.com>
1482bb7c22SToomas Soome  */
1582bb7c22SToomas Soome 
1682bb7c22SToomas Soome /*
1782bb7c22SToomas Soome  * Framebuffer based console support.
1882bb7c22SToomas Soome  *
1982bb7c22SToomas Soome  * Missing (no particular order):
2082bb7c22SToomas Soome  * memory barriers
2182bb7c22SToomas Soome  * shadow buffering
2282bb7c22SToomas Soome  * copyin for userspace calls and then polled io split.
2382bb7c22SToomas Soome  * callbacks for hw blt() and others?
2482bb7c22SToomas Soome  */
2582bb7c22SToomas Soome #include <sys/types.h>
2682bb7c22SToomas Soome #include <sys/visual_io.h>
2782bb7c22SToomas Soome #include <sys/fbio.h>
2882bb7c22SToomas Soome #include <sys/ddi.h>
2982bb7c22SToomas Soome #include <sys/kd.h>
3082bb7c22SToomas Soome #include <sys/sunddi.h>
31cbc8e155SToomas Soome #include <sys/rgb.h>
3282bb7c22SToomas Soome #include <sys/gfx_private.h>
3382bb7c22SToomas Soome #include "gfxp_fb.h"
3482bb7c22SToomas Soome 
3582bb7c22SToomas Soome #define	MYNAME	"gfxp_bitmap"
3682bb7c22SToomas Soome 
3782bb7c22SToomas Soome static ddi_device_acc_attr_t dev_attr = {
3882bb7c22SToomas Soome 	DDI_DEVICE_ATTR_V0,
3982bb7c22SToomas Soome 	DDI_NEVERSWAP_ACC,
4082bb7c22SToomas Soome 	DDI_MERGING_OK_ACC
4182bb7c22SToomas Soome };
4282bb7c22SToomas Soome 
4382bb7c22SToomas Soome /* default structure for FBIOGATTR ioctl */
4482bb7c22SToomas Soome static struct fbgattr bitmap_attr =  {
4582bb7c22SToomas Soome /*	real_type	owner */
4682bb7c22SToomas Soome 	FBTYPE_MEMCOLOR, 0,
4782bb7c22SToomas Soome /* fbtype: type		h  w  depth cms  size */
4882bb7c22SToomas Soome 	{ FBTYPE_MEMCOLOR, 0, 0, 0, 0, 0 },
4982bb7c22SToomas Soome /* fbsattr: flags emu_type	dev_specific */
5082bb7c22SToomas Soome 	{ 0, FBTYPE_MEMCOLOR, { 0 } },
5182bb7c22SToomas Soome /*	emu_types */
5282bb7c22SToomas Soome 	{ -1 }
5382bb7c22SToomas Soome };
5482bb7c22SToomas Soome 
5582bb7c22SToomas Soome static struct vis_identifier gfxp_bitmap_ident = { "illumos_fb" };
5682bb7c22SToomas Soome 
5782bb7c22SToomas Soome static void bitmap_copy_fb(struct gfxp_fb_softc *, uint8_t *, uint8_t *);
5882bb7c22SToomas Soome static int bitmap_kdsetmode(struct gfxp_fb_softc *, int);
5982bb7c22SToomas Soome static int bitmap_devinit(struct gfxp_fb_softc *, struct vis_devinit *);
6082bb7c22SToomas Soome static void	bitmap_cons_copy(struct gfxp_fb_softc *, struct vis_conscopy *);
6182bb7c22SToomas Soome static void	bitmap_cons_display(struct gfxp_fb_softc *,
6282bb7c22SToomas Soome     struct vis_consdisplay *);
6382bb7c22SToomas Soome static int	bitmap_cons_clear(struct gfxp_fb_softc *,
6482bb7c22SToomas Soome     struct vis_consclear *);
6582bb7c22SToomas Soome static void	bitmap_cons_cursor(struct gfxp_fb_softc *,
6682bb7c22SToomas Soome     struct vis_conscursor *);
6782bb7c22SToomas Soome static void	bitmap_polled_copy(struct vis_polledio_arg *,
6882bb7c22SToomas Soome     struct vis_conscopy *);
6982bb7c22SToomas Soome static void	bitmap_polled_display(struct vis_polledio_arg *,
7082bb7c22SToomas Soome     struct vis_consdisplay *);
7182bb7c22SToomas Soome static void	bitmap_polled_cursor(struct vis_polledio_arg *,
7282bb7c22SToomas Soome     struct vis_conscursor *);
7382bb7c22SToomas Soome static int	bitmap_suspend(struct gfxp_fb_softc *softc);
7482bb7c22SToomas Soome static void	bitmap_resume(struct gfxp_fb_softc *softc);
7582bb7c22SToomas Soome static int	bitmap_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off,
7682bb7c22SToomas Soome     size_t len, size_t *maplen, uint_t model, void *ptr);
7782bb7c22SToomas Soome 
7882bb7c22SToomas Soome static struct gfxp_ops gfxp_bitmap_ops = {
7982bb7c22SToomas Soome 	.ident = &gfxp_bitmap_ident,
8082bb7c22SToomas Soome 	.kdsetmode = bitmap_kdsetmode,
8182bb7c22SToomas Soome 	.devinit = bitmap_devinit,
8282bb7c22SToomas Soome 	.cons_copy = bitmap_cons_copy,
8382bb7c22SToomas Soome 	.cons_display = bitmap_cons_display,
8482bb7c22SToomas Soome 	.cons_cursor = bitmap_cons_cursor,
8582bb7c22SToomas Soome 	.cons_clear = bitmap_cons_clear,
8682bb7c22SToomas Soome 	.suspend = bitmap_suspend,
8782bb7c22SToomas Soome 	.resume = bitmap_resume,
8882bb7c22SToomas Soome 	.devmap = bitmap_devmap
8982bb7c22SToomas Soome };
9082bb7c22SToomas Soome 
9182bb7c22SToomas Soome void
gfxp_bm_register_fbops(gfxp_fb_softc_ptr_t ptr,struct gfxp_blt_ops * ops)9282bb7c22SToomas Soome gfxp_bm_register_fbops(gfxp_fb_softc_ptr_t ptr, struct gfxp_blt_ops *ops)
9382bb7c22SToomas Soome {
9482bb7c22SToomas Soome 	struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)ptr;
9582bb7c22SToomas Soome 
9682bb7c22SToomas Soome 	if (softc != NULL) {
9782bb7c22SToomas Soome 		softc->blt_ops.blt = ops->blt;
9882bb7c22SToomas Soome 		softc->blt_ops.copy = ops->copy;
9982bb7c22SToomas Soome 		softc->blt_ops.clear = ops->clear;
10082bb7c22SToomas Soome 		softc->blt_ops.setmode = ops->setmode;
10182bb7c22SToomas Soome 	}
10282bb7c22SToomas Soome }
10382bb7c22SToomas Soome 
10482bb7c22SToomas Soome void
gfxp_bm_getfb_info(gfxp_fb_softc_ptr_t ptr,struct gfxp_bm_fb_info * fbip)10582bb7c22SToomas Soome gfxp_bm_getfb_info(gfxp_fb_softc_ptr_t ptr, struct gfxp_bm_fb_info *fbip)
10682bb7c22SToomas Soome {
10782bb7c22SToomas Soome 	struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)ptr;
10882bb7c22SToomas Soome 
10982bb7c22SToomas Soome 	switch (softc->fb_type) {
11082bb7c22SToomas Soome 	case GFXP_BITMAP:
11182bb7c22SToomas Soome 		fbip->xres = softc->console->fb.screen.x;
11282bb7c22SToomas Soome 		fbip->yres = softc->console->fb.screen.y;
11382bb7c22SToomas Soome 		fbip->bpp = softc->console->fb.bpp;
11482bb7c22SToomas Soome 		fbip->depth = softc->console->fb.depth;
11582bb7c22SToomas Soome 		break;
11682bb7c22SToomas Soome 	case GFXP_VGATEXT:
11782bb7c22SToomas Soome 		/*
11882bb7c22SToomas Soome 		 * By current knowledge, DRM can not cope with text mode
11982bb7c22SToomas Soome 		 * and the VGA is disabled. The proper approach here
12082bb7c22SToomas Soome 		 * is to set all values to 0. See the drm_getfb_size() and
12182bb7c22SToomas Soome 		 * the i915_gem_init() how the size is used.
12282bb7c22SToomas Soome 		 */
12382bb7c22SToomas Soome 		fbip->xres = 0;
12482bb7c22SToomas Soome 		fbip->yres = 0;
12582bb7c22SToomas Soome 		fbip->bpp = 0;
12682bb7c22SToomas Soome 		fbip->depth = 0;
12782bb7c22SToomas Soome 		break;
12882bb7c22SToomas Soome 	}
12982bb7c22SToomas Soome }
13082bb7c22SToomas Soome 
13182bb7c22SToomas Soome int
gfxp_bm_attach(dev_info_t * devi __unused,struct gfxp_fb_softc * softc)13282bb7c22SToomas Soome gfxp_bm_attach(dev_info_t *devi __unused, struct gfxp_fb_softc *softc)
13382bb7c22SToomas Soome {
13482bb7c22SToomas Soome 	softc->polledio.display = bitmap_polled_display;
13582bb7c22SToomas Soome 	softc->polledio.copy = bitmap_polled_copy;
13682bb7c22SToomas Soome 	softc->polledio.cursor = bitmap_polled_cursor;
13782bb7c22SToomas Soome 	softc->gfxp_ops = &gfxp_bitmap_ops;
13882bb7c22SToomas Soome 	softc->fbgattr = &bitmap_attr;
13982bb7c22SToomas Soome 	softc->silent = 0;
14082bb7c22SToomas Soome 
14182bb7c22SToomas Soome 	return (DDI_SUCCESS);
14282bb7c22SToomas Soome }
14382bb7c22SToomas Soome 
14482bb7c22SToomas Soome int
gfxp_bm_detach(dev_info_t * devi __unused,struct gfxp_fb_softc * softc)14582bb7c22SToomas Soome gfxp_bm_detach(dev_info_t *devi __unused, struct gfxp_fb_softc *softc)
14682bb7c22SToomas Soome {
14782bb7c22SToomas Soome 	if (softc == NULL || softc->console == NULL)
14882bb7c22SToomas Soome 		return (DDI_SUCCESS);
14982bb7c22SToomas Soome 
15082bb7c22SToomas Soome 	if (softc->console->fb.fb_size != 0) {
15182bb7c22SToomas Soome 		gfxp_unmap_kernel_space((gfxp_kva_t)softc->console->fb.fb,
15282bb7c22SToomas Soome 		    softc->console->fb.fb_size);
15382bb7c22SToomas Soome 		fb_info.fb = NULL;
15482bb7c22SToomas Soome 		kmem_free(softc->console->fb.shadow_fb,
15582bb7c22SToomas Soome 		    softc->console->fb.fb_size);
15682bb7c22SToomas Soome 		softc->console->fb.shadow_fb = NULL;
15782bb7c22SToomas Soome 	}
15882bb7c22SToomas Soome 	return (DDI_SUCCESS);
15982bb7c22SToomas Soome }
16082bb7c22SToomas Soome 
16182bb7c22SToomas Soome static void
bitmap_kdsettext(struct gfxp_fb_softc * softc)16282bb7c22SToomas Soome bitmap_kdsettext(struct gfxp_fb_softc *softc)
16382bb7c22SToomas Soome {
16482bb7c22SToomas Soome 	bitmap_copy_fb(softc, softc->console->fb.shadow_fb,
16582bb7c22SToomas Soome 	    softc->console->fb.fb);
16682bb7c22SToomas Soome }
16782bb7c22SToomas Soome 
16882bb7c22SToomas Soome static void
bitmap_kdsetgraphics(struct gfxp_fb_softc * softc __unused)16982bb7c22SToomas Soome bitmap_kdsetgraphics(struct gfxp_fb_softc *softc __unused)
17082bb7c22SToomas Soome {
17182bb7c22SToomas Soome 	/* we have the copy of fb content in shadow_fb */
17282bb7c22SToomas Soome }
17382bb7c22SToomas Soome 
17482bb7c22SToomas Soome static int
bitmap_suspend(struct gfxp_fb_softc * softc __unused)17582bb7c22SToomas Soome bitmap_suspend(struct gfxp_fb_softc *softc __unused)
17682bb7c22SToomas Soome {
17782bb7c22SToomas Soome 	/* we have the copy of fb content in shadow_fb */
17882bb7c22SToomas Soome 	return (DDI_SUCCESS);
17982bb7c22SToomas Soome }
18082bb7c22SToomas Soome 
18182bb7c22SToomas Soome static void
bitmap_resume(struct gfxp_fb_softc * softc)18282bb7c22SToomas Soome bitmap_resume(struct gfxp_fb_softc *softc)
18382bb7c22SToomas Soome {
18482bb7c22SToomas Soome 	bitmap_kdsettext(softc);
18582bb7c22SToomas Soome }
18682bb7c22SToomas Soome 
18782bb7c22SToomas Soome static int
bitmap_kdsetmode(struct gfxp_fb_softc * softc,int mode)18882bb7c22SToomas Soome bitmap_kdsetmode(struct gfxp_fb_softc *softc, int mode)
18982bb7c22SToomas Soome {
19082bb7c22SToomas Soome 	switch (mode) {
19182bb7c22SToomas Soome 	case KD_TEXT:
19282bb7c22SToomas Soome 		if (softc->blt_ops.setmode != NULL)
193ceedf124SToomas Soome 			if (softc->blt_ops.setmode(KD_TEXT) != 0)
194ceedf124SToomas Soome 				return (EIO);
195ceedf124SToomas Soome 
19682bb7c22SToomas Soome 		bitmap_kdsettext(softc);
19782bb7c22SToomas Soome 		break;
19882bb7c22SToomas Soome 	case KD_GRAPHICS:
19982bb7c22SToomas Soome 		bitmap_kdsetgraphics(softc);
20082bb7c22SToomas Soome 		if (softc->blt_ops.setmode != NULL)
201ceedf124SToomas Soome 			if (softc->blt_ops.setmode(KD_GRAPHICS) != 0) {
202ceedf124SToomas Soome 				bitmap_kdsettext(softc);
203ceedf124SToomas Soome 				return (EIO);
204ceedf124SToomas Soome 			}
20582bb7c22SToomas Soome 		break;
20682bb7c22SToomas Soome 	case KD_RESETTEXT:
20782bb7c22SToomas Soome 		/*
20882bb7c22SToomas Soome 		 * In order to avoid racing with a starting X server,
20982bb7c22SToomas Soome 		 * this needs to be a test and set that is performed in
21082bb7c22SToomas Soome 		 * a single (softc->lock protected) ioctl into this driver.
21182bb7c22SToomas Soome 		 */
21282bb7c22SToomas Soome 		if (softc->mode == KD_TEXT && softc->silent == 1) {
21382bb7c22SToomas Soome 			bitmap_kdsettext(softc);
21482bb7c22SToomas Soome 		}
21582bb7c22SToomas Soome 		mode = KD_TEXT;
21682bb7c22SToomas Soome 		break;
21782bb7c22SToomas Soome 	default:
21882bb7c22SToomas Soome 		return (EINVAL);
21982bb7c22SToomas Soome 	}
22082bb7c22SToomas Soome 
22182bb7c22SToomas Soome 	softc->mode = mode;
22282bb7c22SToomas Soome 	return (0);
22382bb7c22SToomas Soome }
22482bb7c22SToomas Soome 
22582bb7c22SToomas Soome /*
22682bb7c22SToomas Soome  * Copy fb_info from early boot and set up the FB
22782bb7c22SToomas Soome  */
22882bb7c22SToomas Soome static int
bitmap_setup_fb(struct gfxp_fb_softc * softc)22982bb7c22SToomas Soome bitmap_setup_fb(struct gfxp_fb_softc *softc)
23082bb7c22SToomas Soome {
23182bb7c22SToomas Soome 	size_t size;
23282bb7c22SToomas Soome 	struct gfxfb_info *gfxfb_info;
23382bb7c22SToomas Soome 
23482bb7c22SToomas Soome 	softc->console = (union gfx_console *)&fb_info;
23582bb7c22SToomas Soome 	size = ptob(btopr(fb_info.fb_size));
23682bb7c22SToomas Soome 	softc->console->fb.fb_size = size;
23782bb7c22SToomas Soome 	softc->console->fb.fb = (uint8_t *)gfxp_map_kernel_space(fb_info.paddr,
23882bb7c22SToomas Soome 	    size, GFXP_MEMORY_WRITECOMBINED);
23982bb7c22SToomas Soome 	if (softc->console->fb.fb == NULL)
24082bb7c22SToomas Soome 		return (DDI_FAILURE);
24182bb7c22SToomas Soome 
24282bb7c22SToomas Soome 	softc->console->fb.shadow_fb = kmem_zalloc(size, KM_SLEEP);
24382bb7c22SToomas Soome 
24482bb7c22SToomas Soome 	bitmap_attr.fbtype.fb_height = fb_info.screen.y;
24582bb7c22SToomas Soome 	bitmap_attr.fbtype.fb_width = fb_info.screen.x;
24682bb7c22SToomas Soome 	bitmap_attr.fbtype.fb_depth = fb_info.depth;
24782bb7c22SToomas Soome 	bitmap_attr.fbtype.fb_size = size;
24882bb7c22SToomas Soome 	if (fb_info.depth == 32)
24982bb7c22SToomas Soome 		bitmap_attr.fbtype.fb_cmsize = 1 << 24;
25082bb7c22SToomas Soome 	else
25182bb7c22SToomas Soome 		bitmap_attr.fbtype.fb_cmsize = 1 << fb_info.depth;
25282bb7c22SToomas Soome 
25382bb7c22SToomas Soome 	gfxfb_info = (struct gfxfb_info *)bitmap_attr.sattr.dev_specific;
25482bb7c22SToomas Soome 	gfxfb_info->terminal_origin_x = fb_info.terminal_origin.x;
25582bb7c22SToomas Soome 	gfxfb_info->terminal_origin_y = fb_info.terminal_origin.y;
25682bb7c22SToomas Soome 	gfxfb_info->pitch = fb_info.pitch;
25782bb7c22SToomas Soome 	gfxfb_info->font_width = fb_info.font_width;
25882bb7c22SToomas Soome 	gfxfb_info->font_height = fb_info.font_height;
25982bb7c22SToomas Soome 	gfxfb_info->red_mask_size = fb_info.rgb.red.size;
26082bb7c22SToomas Soome 	gfxfb_info->red_field_position = fb_info.rgb.red.pos;
26182bb7c22SToomas Soome 	gfxfb_info->green_mask_size = fb_info.rgb.green.size;
26282bb7c22SToomas Soome 	gfxfb_info->green_field_position = fb_info.rgb.green.pos;
26382bb7c22SToomas Soome 	gfxfb_info->blue_mask_size = fb_info.rgb.blue.size;
26482bb7c22SToomas Soome 	gfxfb_info->blue_field_position = fb_info.rgb.blue.pos;
26582bb7c22SToomas Soome 
26682bb7c22SToomas Soome 	return (DDI_SUCCESS);
26782bb7c22SToomas Soome }
26882bb7c22SToomas Soome 
26982bb7c22SToomas Soome static int
bitmap_devinit(struct gfxp_fb_softc * softc,struct vis_devinit * data)27082bb7c22SToomas Soome bitmap_devinit(struct gfxp_fb_softc *softc, struct vis_devinit *data)
27182bb7c22SToomas Soome {
27282bb7c22SToomas Soome 	union gfx_console *console;
27382bb7c22SToomas Soome 
27482bb7c22SToomas Soome 	if (bitmap_setup_fb(softc) == DDI_FAILURE)
27582bb7c22SToomas Soome 		return (1);
27682bb7c22SToomas Soome 
27782bb7c22SToomas Soome 	console = softc->console;
27882bb7c22SToomas Soome 
27982bb7c22SToomas Soome 	/* make sure we have current state of the screen */
28082bb7c22SToomas Soome 	bitmap_copy_fb(softc, console->fb.fb, console->fb.shadow_fb);
28182bb7c22SToomas Soome 
28282bb7c22SToomas Soome 	/* initialize console instance */
28382bb7c22SToomas Soome 	data->version = VIS_CONS_REV;
28482bb7c22SToomas Soome 	data->width = console->fb.screen.x;
28582bb7c22SToomas Soome 	data->height = console->fb.screen.y;
28682bb7c22SToomas Soome 	data->linebytes = console->fb.pitch;
287a4e6b9b6SToomas Soome 	data->color_map = boot_color_map;
28882bb7c22SToomas Soome 	data->depth = console->fb.depth;
28982bb7c22SToomas Soome 	data->mode = VIS_PIXEL;
29082bb7c22SToomas Soome 	data->polledio = &softc->polledio;
29182bb7c22SToomas Soome #if 0
29282bb7c22SToomas Soome 	data->modechg_cb;
29382bb7c22SToomas Soome 	data->modechg_arg;
29482bb7c22SToomas Soome #endif
29582bb7c22SToomas Soome 	return (0);
29682bb7c22SToomas Soome }
29782bb7c22SToomas Soome 
29882bb7c22SToomas Soome /* Buffer to Buffer copy */
29982bb7c22SToomas Soome static void
bitmap_copy_fb(struct gfxp_fb_softc * softc,uint8_t * src,uint8_t * dst)30082bb7c22SToomas Soome bitmap_copy_fb(struct gfxp_fb_softc *softc, uint8_t *src, uint8_t *dst)
30182bb7c22SToomas Soome {
30282bb7c22SToomas Soome 	uint32_t i, pitch, height;
30382bb7c22SToomas Soome 
30482bb7c22SToomas Soome 	pitch = softc->console->fb.pitch;
30582bb7c22SToomas Soome 	height = softc->console->fb.screen.y;
30682bb7c22SToomas Soome 
30782bb7c22SToomas Soome 	for (i = 0; i < height; i++) {
30882bb7c22SToomas Soome 		(void) memmove(dst + i * pitch, src + i * pitch, pitch);
30982bb7c22SToomas Soome 	}
31082bb7c22SToomas Soome }
31182bb7c22SToomas Soome 
31282bb7c22SToomas Soome static void
bitmap_cons_copy(struct gfxp_fb_softc * softc,struct vis_conscopy * ma)31382bb7c22SToomas Soome bitmap_cons_copy(struct gfxp_fb_softc *softc, struct vis_conscopy *ma)
31482bb7c22SToomas Soome {
31582bb7c22SToomas Soome 	union gfx_console *console;
31682bb7c22SToomas Soome 	uint32_t soffset, toffset;
31782bb7c22SToomas Soome 	uint32_t width, height, pitch;
31882bb7c22SToomas Soome 	uint8_t *src, *dst, *sdst;
31982bb7c22SToomas Soome 	int i;
32082bb7c22SToomas Soome 
32182bb7c22SToomas Soome 	console = softc->console;
32282bb7c22SToomas Soome 	soffset = ma->s_col * console->fb.bpp + ma->s_row * console->fb.pitch;
32382bb7c22SToomas Soome 	toffset = ma->t_col * console->fb.bpp + ma->t_row * console->fb.pitch;
32482bb7c22SToomas Soome 	src = console->fb.shadow_fb + soffset;
32582bb7c22SToomas Soome 	dst = console->fb.fb + toffset;
32682bb7c22SToomas Soome 	sdst = console->fb.shadow_fb + toffset;
32782bb7c22SToomas Soome 	width = (ma->e_col - ma->s_col + 1) * console->fb.bpp;
32882bb7c22SToomas Soome 	height = ma->e_row - ma->s_row + 1;
32982bb7c22SToomas Soome 	pitch = console->fb.pitch;
33082bb7c22SToomas Soome 
33182bb7c22SToomas Soome 	if (toffset <= soffset) {
33282bb7c22SToomas Soome 		for (i = 0; i < height; i++) {
33382bb7c22SToomas Soome 			uint32_t increment = i * pitch;
33482bb7c22SToomas Soome 			if (softc->mode == KD_TEXT) {
33582bb7c22SToomas Soome 				(void) memmove(dst + increment,
33682bb7c22SToomas Soome 				    src + increment, width);
33782bb7c22SToomas Soome 			}
33882bb7c22SToomas Soome 			(void) memmove(sdst + increment, src + increment,
33982bb7c22SToomas Soome 			    width);
34082bb7c22SToomas Soome 		}
34182bb7c22SToomas Soome 	} else {
34282bb7c22SToomas Soome 		for (i = height - 1; i >= 0; i--) {
34382bb7c22SToomas Soome 			uint32_t increment = i * pitch;
34482bb7c22SToomas Soome 			if (softc->mode == KD_TEXT) {
34582bb7c22SToomas Soome 				(void) memmove(dst + increment,
34682bb7c22SToomas Soome 				    src + increment, width);
34782bb7c22SToomas Soome 			}
34882bb7c22SToomas Soome 			(void) memmove(sdst + increment, src + increment,
34982bb7c22SToomas Soome 			    width);
35082bb7c22SToomas Soome 		}
35182bb7c22SToomas Soome 	}
35282bb7c22SToomas Soome }
35382bb7c22SToomas Soome 
35482bb7c22SToomas Soome /*
35582bb7c22SToomas Soome  * Implements alpha blending for RGBA data, could use pixels for arguments,
35682bb7c22SToomas Soome  * but byte stream seems more generic.
35782bb7c22SToomas Soome  * The generic alpha blending is:
35882bb7c22SToomas Soome  * blend = alpha * fg + (1.0 - alpha) * bg.
35982bb7c22SToomas Soome  * Since our alpha is not from range [0..1], we scale appropriately.
36082bb7c22SToomas Soome  */
36182bb7c22SToomas Soome static uint8_t
alpha_blend(uint8_t fg,uint8_t bg,uint8_t alpha)36282bb7c22SToomas Soome alpha_blend(uint8_t fg, uint8_t bg, uint8_t alpha)
36382bb7c22SToomas Soome {
36482bb7c22SToomas Soome 	uint16_t blend, h, l;
36582bb7c22SToomas Soome 
36682bb7c22SToomas Soome 	/* trivial corner cases */
36782bb7c22SToomas Soome 	if (alpha == 0)
36882bb7c22SToomas Soome 		return (bg);
36982bb7c22SToomas Soome 	if (alpha == 0xFF)
37082bb7c22SToomas Soome 		return (fg);
37182bb7c22SToomas Soome 	blend = (alpha * fg + (0xFF - alpha) * bg);
37282bb7c22SToomas Soome 	/* Division by 0xFF */
37382bb7c22SToomas Soome 	h = blend >> 8;
37482bb7c22SToomas Soome 	l = blend & 0xFF;
37582bb7c22SToomas Soome 	if (h + l >= 0xFF)
37682bb7c22SToomas Soome 		h++;
37782bb7c22SToomas Soome 	return (h);
37882bb7c22SToomas Soome }
37982bb7c22SToomas Soome 
38082bb7c22SToomas Soome /* Copy memory to framebuffer or to memory. */
38182bb7c22SToomas Soome static void
bitmap_cpy(uint8_t * dst,uint8_t * src,uint32_t len,int bpp)38282bb7c22SToomas Soome bitmap_cpy(uint8_t *dst, uint8_t *src, uint32_t len, int bpp)
38382bb7c22SToomas Soome {
38482bb7c22SToomas Soome 	uint32_t i;
38582bb7c22SToomas Soome 	uint8_t a;
38682bb7c22SToomas Soome 
38782bb7c22SToomas Soome 	switch (bpp) {
38882bb7c22SToomas Soome 	case 4:
38982bb7c22SToomas Soome 		for (i = 0; i < len; i += bpp) {
39082bb7c22SToomas Soome 			a = src[i+3];
39182bb7c22SToomas Soome 			dst[i] = alpha_blend(src[i], dst[i], a);
39282bb7c22SToomas Soome 			dst[i+1] = alpha_blend(src[i+1], dst[i+1], a);
39382bb7c22SToomas Soome 			dst[i+2] = alpha_blend(src[i+2], dst[i+2], a);
39482bb7c22SToomas Soome 			dst[i+3] = a;
39582bb7c22SToomas Soome 		}
39682bb7c22SToomas Soome 		break;
39782bb7c22SToomas Soome 	default:
39882bb7c22SToomas Soome 		(void) memcpy(dst, src, len);
39982bb7c22SToomas Soome 		break;
40082bb7c22SToomas Soome 	}
40182bb7c22SToomas Soome }
40282bb7c22SToomas Soome 
40382bb7c22SToomas Soome static void
bitmap_cons_display(struct gfxp_fb_softc * softc,struct vis_consdisplay * da)40482bb7c22SToomas Soome bitmap_cons_display(struct gfxp_fb_softc *softc, struct vis_consdisplay *da)
40582bb7c22SToomas Soome {
40682bb7c22SToomas Soome 	union gfx_console *console;
40782bb7c22SToomas Soome 	uint32_t size;		/* write size per scanline */
40882bb7c22SToomas Soome 	uint8_t *fbp, *sfbp;	/* fb + calculated offset */
40982bb7c22SToomas Soome 	int i;
41082bb7c22SToomas Soome 
41182bb7c22SToomas Soome 	console = softc->console;
41282bb7c22SToomas Soome 	/* make sure we will not write past FB */
41382bb7c22SToomas Soome 	if (da->col >= console->fb.screen.x ||
41482bb7c22SToomas Soome 	    da->row >= console->fb.screen.y ||
41582bb7c22SToomas Soome 	    da->col + da->width > console->fb.screen.x ||
41682bb7c22SToomas Soome 	    da->row + da->height > console->fb.screen.y)
41782bb7c22SToomas Soome 		return;
41882bb7c22SToomas Soome 
41982bb7c22SToomas Soome 	size = da->width * console->fb.bpp;
42082bb7c22SToomas Soome 	fbp = console->fb.fb + da->col * console->fb.bpp +
42182bb7c22SToomas Soome 	    da->row * console->fb.pitch;
42282bb7c22SToomas Soome 	sfbp = console->fb.shadow_fb + da->col * console->fb.bpp +
42382bb7c22SToomas Soome 	    da->row * console->fb.pitch;
42482bb7c22SToomas Soome 
42582bb7c22SToomas Soome 	/* write all scanlines in rectangle */
42682bb7c22SToomas Soome 	for (i = 0; i < da->height; i++) {
427*80cb7d83SToomas Soome 		uint8_t *dest = sfbp + i * console->fb.pitch;
42882bb7c22SToomas Soome 		uint8_t *src = da->data + i * size;
429*80cb7d83SToomas Soome 
430*80cb7d83SToomas Soome 		/* alpha blend bitmap to shadow fb. */
43182bb7c22SToomas Soome 		bitmap_cpy(dest, src, size, console->fb.bpp);
432*80cb7d83SToomas Soome 		if (softc->mode == KD_TEXT) {
433*80cb7d83SToomas Soome 			/* Copy from shadow to fb. */
434*80cb7d83SToomas Soome 			src = dest;
435*80cb7d83SToomas Soome 			dest = fbp + i * console->fb.pitch;
436*80cb7d83SToomas Soome 			(void) memcpy(dest, src, size);
437*80cb7d83SToomas Soome 		}
43882bb7c22SToomas Soome 	}
43982bb7c22SToomas Soome }
44082bb7c22SToomas Soome 
44182bb7c22SToomas Soome static int
bitmap_cons_clear(struct gfxp_fb_softc * softc,struct vis_consclear * ca)44282bb7c22SToomas Soome bitmap_cons_clear(struct gfxp_fb_softc *softc, struct vis_consclear *ca)
44382bb7c22SToomas Soome {
44482bb7c22SToomas Soome 	union gfx_console *console;
44582bb7c22SToomas Soome 	uint8_t *fb, *sfb;
44682bb7c22SToomas Soome 	uint16_t *fb16, *sfb16;
44782bb7c22SToomas Soome 	uint32_t data, *fb32, *sfb32;
44882bb7c22SToomas Soome 	int i, j, pitch;
44982bb7c22SToomas Soome 
45082bb7c22SToomas Soome 	console = softc->console;
45182bb7c22SToomas Soome 	pitch = console->fb.pitch;
452fa9eb222SToomas Soome 
45382bb7c22SToomas Soome 	switch (console->fb.depth) {
45482bb7c22SToomas Soome 	case 8:
455fa9eb222SToomas Soome 		data = ca->bg_color.eight;
45682bb7c22SToomas Soome 		for (i = 0; i < console->fb.screen.y; i++) {
45782bb7c22SToomas Soome 			if (softc->mode == KD_TEXT) {
45882bb7c22SToomas Soome 				fb = console->fb.fb + i * pitch;
459109b6524SToomas Soome 				(void) memset(fb, data, pitch);
46082bb7c22SToomas Soome 			}
46182bb7c22SToomas Soome 			fb = console->fb.shadow_fb + i * pitch;
462109b6524SToomas Soome 			(void) memset(fb, data, pitch);
46382bb7c22SToomas Soome 		}
46482bb7c22SToomas Soome 		break;
46582bb7c22SToomas Soome 	case 15:
46682bb7c22SToomas Soome 	case 16:
467fa9eb222SToomas Soome 		data = (ca->bg_color.sixteen[0] << 8) |
468fa9eb222SToomas Soome 		    ca->bg_color.sixteen[1];
46982bb7c22SToomas Soome 		for (i = 0; i < console->fb.screen.y; i++) {
47082bb7c22SToomas Soome 			fb16 = (uint16_t *)(console->fb.fb + i * pitch);
47182bb7c22SToomas Soome 			sfb16 = (uint16_t *)(console->fb.shadow_fb + i * pitch);
47282bb7c22SToomas Soome 			for (j = 0; j < console->fb.screen.x; j++) {
47382bb7c22SToomas Soome 				if (softc->mode == KD_TEXT)
47482bb7c22SToomas Soome 					fb16[j] = (uint16_t)data & 0xffff;
47582bb7c22SToomas Soome 				sfb16[j] = (uint16_t)data & 0xffff;
47682bb7c22SToomas Soome 			}
47782bb7c22SToomas Soome 		}
47882bb7c22SToomas Soome 		break;
47982bb7c22SToomas Soome 	case 24:
480fa9eb222SToomas Soome 		data = ca->bg_color.twentyfour[0] << 16;
481fa9eb222SToomas Soome 		data |= ca->bg_color.twentyfour[1] << 8;
482fa9eb222SToomas Soome 		data |= ca->bg_color.twentyfour[2];
48382bb7c22SToomas Soome 		for (i = 0; i < console->fb.screen.y; i++) {
48482bb7c22SToomas Soome 			fb = console->fb.fb + i * pitch;
48582bb7c22SToomas Soome 			sfb = console->fb.shadow_fb + i * pitch;
48682bb7c22SToomas Soome 			for (j = 0; j < pitch; j += 3) {
48782bb7c22SToomas Soome 				if (softc->mode == KD_TEXT) {
48882bb7c22SToomas Soome 					fb[j] = (data >> 16) & 0xff;
48982bb7c22SToomas Soome 					fb[j+1] = (data >> 8) & 0xff;
49082bb7c22SToomas Soome 					fb[j+2] = data & 0xff;
49182bb7c22SToomas Soome 				}
49282bb7c22SToomas Soome 
49382bb7c22SToomas Soome 				sfb[j] = (data >> 16) & 0xff;
49482bb7c22SToomas Soome 				sfb[j+1] = (data >> 8) & 0xff;
49582bb7c22SToomas Soome 				sfb[j+2] = data & 0xff;
49682bb7c22SToomas Soome 			}
49782bb7c22SToomas Soome 		}
49882bb7c22SToomas Soome 		break;
49982bb7c22SToomas Soome 	case 32:
500fa9eb222SToomas Soome 		data = *(uint32_t *)&ca->bg_color;
50182bb7c22SToomas Soome 		for (i = 0; i < console->fb.screen.y; i++) {
50282bb7c22SToomas Soome 			fb32 = (uint32_t *)(console->fb.fb + i * pitch);
50382bb7c22SToomas Soome 			sfb32 = (uint32_t *)(console->fb.shadow_fb + i * pitch);
50482bb7c22SToomas Soome 			for (j = 0; j < console->fb.screen.x; j++) {
50582bb7c22SToomas Soome 				if (softc->mode == KD_TEXT)
50682bb7c22SToomas Soome 					fb32[j] = data;
50782bb7c22SToomas Soome 				sfb32[j] = data;
50882bb7c22SToomas Soome 			}
50982bb7c22SToomas Soome 		}
51082bb7c22SToomas Soome 		break;
51182bb7c22SToomas Soome 	}
51282bb7c22SToomas Soome 
51382bb7c22SToomas Soome 	return (0);
51482bb7c22SToomas Soome }
51582bb7c22SToomas Soome 
51682bb7c22SToomas Soome static void
bitmap_display_cursor(struct gfxp_fb_softc * softc,struct vis_conscursor * ca)51782bb7c22SToomas Soome bitmap_display_cursor(struct gfxp_fb_softc *softc, struct vis_conscursor *ca)
51882bb7c22SToomas Soome {
51982bb7c22SToomas Soome 	union gfx_console *console;
52082bb7c22SToomas Soome 	uint32_t fg, bg, offset, size;
52182bb7c22SToomas Soome 	uint32_t *fb32, *sfb32;
52282bb7c22SToomas Soome 	uint16_t *fb16, *sfb16;
52382bb7c22SToomas Soome 	uint8_t *fb8, *sfb8;
52482bb7c22SToomas Soome 	int i, j, bpp, pitch;
52582bb7c22SToomas Soome 
52682bb7c22SToomas Soome 	console = softc->console;
52782bb7c22SToomas Soome 	pitch = console->fb.pitch;
52882bb7c22SToomas Soome 	bpp = console->fb.bpp;
52982bb7c22SToomas Soome 	size = ca->width * bpp;
53082bb7c22SToomas Soome 
53182bb7c22SToomas Soome 	/*
53282bb7c22SToomas Soome 	 * Build cursor image. We are building mirror image of data on
53382bb7c22SToomas Soome 	 * frame buffer by (D xor FG) xor BG.
53482bb7c22SToomas Soome 	 */
53582bb7c22SToomas Soome 	offset = ca->col * bpp + ca->row * pitch;
53682bb7c22SToomas Soome 	switch (console->fb.depth) {
53782bb7c22SToomas Soome 	case 8:
538fa9eb222SToomas Soome 		fg = ca->fg_color.eight;
539fa9eb222SToomas Soome 		bg = ca->bg_color.eight;
54082bb7c22SToomas Soome 		for (i = 0; i < ca->height; i++) {
54182bb7c22SToomas Soome 			fb8 = console->fb.fb + offset + i * pitch;
54282bb7c22SToomas Soome 			sfb8 = console->fb.shadow_fb + offset + i * pitch;
54382bb7c22SToomas Soome 			for (j = 0; j < size; j += 1) {
544*80cb7d83SToomas Soome 				sfb8[j] = (sfb8[j] ^ (fg & 0xff)) ^ (bg & 0xff);
54582bb7c22SToomas Soome 				if (softc->mode == KD_TEXT) {
546*80cb7d83SToomas Soome 					fb8[j] = sfb8[j];
54782bb7c22SToomas Soome 				}
54882bb7c22SToomas Soome 			}
54982bb7c22SToomas Soome 		}
55082bb7c22SToomas Soome 		break;
55182bb7c22SToomas Soome 	case 15:
55282bb7c22SToomas Soome 	case 16:
55382bb7c22SToomas Soome 		fg = ca->fg_color.sixteen[0] << 8;
55482bb7c22SToomas Soome 		fg |= ca->fg_color.sixteen[1];
55582bb7c22SToomas Soome 		bg = ca->bg_color.sixteen[0] << 8;
55682bb7c22SToomas Soome 		bg |= ca->bg_color.sixteen[1];
55782bb7c22SToomas Soome 		for (i = 0; i < ca->height; i++) {
55882bb7c22SToomas Soome 			fb16 = (uint16_t *)
55982bb7c22SToomas Soome 			    (console->fb.fb + offset + i * pitch);
56082bb7c22SToomas Soome 			sfb16 = (uint16_t *)
56182bb7c22SToomas Soome 			    (console->fb.shadow_fb + offset + i * pitch);
56282bb7c22SToomas Soome 			for (j = 0; j < ca->width; j++) {
56382bb7c22SToomas Soome 				sfb16[j] = (sfb16[j] ^ (fg & 0xffff)) ^
56482bb7c22SToomas Soome 				    (bg & 0xffff);
565*80cb7d83SToomas Soome 				if (softc->mode == KD_TEXT) {
566*80cb7d83SToomas Soome 					fb16[j] = sfb16[j];
567*80cb7d83SToomas Soome 				}
56882bb7c22SToomas Soome 			}
56982bb7c22SToomas Soome 		}
57082bb7c22SToomas Soome 		break;
57182bb7c22SToomas Soome 	case 24:
572fa9eb222SToomas Soome 		fg = ca->fg_color.twentyfour[0] << 16;
573fa9eb222SToomas Soome 		fg |= ca->fg_color.twentyfour[1] << 8;
574fa9eb222SToomas Soome 		fg |= ca->fg_color.twentyfour[2];
575fa9eb222SToomas Soome 		bg = ca->bg_color.twentyfour[0] << 16;
576fa9eb222SToomas Soome 		bg |= ca->bg_color.twentyfour[1] << 8;
577fa9eb222SToomas Soome 		bg |= ca->bg_color.twentyfour[2];
57882bb7c22SToomas Soome 		for (i = 0; i < ca->height; i++) {
57982bb7c22SToomas Soome 			fb8 = console->fb.fb + offset + i * pitch;
58082bb7c22SToomas Soome 			sfb8 = console->fb.shadow_fb + offset + i * pitch;
58182bb7c22SToomas Soome 			for (j = 0; j < size; j += 3) {
58282bb7c22SToomas Soome 				sfb8[j] = (sfb8[j] ^ ((fg >> 16) & 0xff)) ^
58382bb7c22SToomas Soome 				    ((bg >> 16) & 0xff);
58482bb7c22SToomas Soome 				sfb8[j+1] = (sfb8[j+1] ^ ((fg >> 8) & 0xff)) ^
58582bb7c22SToomas Soome 				    ((bg >> 8) & 0xff);
58682bb7c22SToomas Soome 				sfb8[j+2] = (sfb8[j+2] ^ (fg & 0xff)) ^
58782bb7c22SToomas Soome 				    (bg & 0xff);
588*80cb7d83SToomas Soome 				if (softc->mode == KD_TEXT) {
589*80cb7d83SToomas Soome 					fb8[j] = sfb8[j];
590*80cb7d83SToomas Soome 					fb8[j+1] = sfb8[j+1];
591*80cb7d83SToomas Soome 					fb8[j+2] = sfb8[j+2];
592*80cb7d83SToomas Soome 				}
59382bb7c22SToomas Soome 			}
59482bb7c22SToomas Soome 		}
59582bb7c22SToomas Soome 		break;
59682bb7c22SToomas Soome 	case 32:
597fa9eb222SToomas Soome 		fg = *(uint32_t *)&ca->fg_color;
598fa9eb222SToomas Soome 		bg = *(uint32_t *)&ca->bg_color;
59982bb7c22SToomas Soome 		for (i = 0; i < ca->height; i++) {
60082bb7c22SToomas Soome 			fb32 = (uint32_t *)
60182bb7c22SToomas Soome 			    (console->fb.fb + offset + i * pitch);
60282bb7c22SToomas Soome 			sfb32 = (uint32_t *)
60382bb7c22SToomas Soome 			    (console->fb.shadow_fb + offset + i * pitch);
60482bb7c22SToomas Soome 			for (j = 0; j < ca->width; j++) {
60582bb7c22SToomas Soome 				sfb32[j] = (sfb32[j] ^ fg) ^ bg;
606*80cb7d83SToomas Soome 				if (softc->mode == KD_TEXT)
607*80cb7d83SToomas Soome 					fb32[j] = sfb32[j];
60882bb7c22SToomas Soome 			}
60982bb7c22SToomas Soome 		}
61082bb7c22SToomas Soome 		break;
61182bb7c22SToomas Soome 	}
61282bb7c22SToomas Soome }
61382bb7c22SToomas Soome 
61482bb7c22SToomas Soome static void
bitmap_cons_cursor(struct gfxp_fb_softc * softc,struct vis_conscursor * ca)61582bb7c22SToomas Soome bitmap_cons_cursor(struct gfxp_fb_softc *softc, struct vis_conscursor *ca)
61682bb7c22SToomas Soome {
61782bb7c22SToomas Soome 	union gfx_console *console = softc->console;
61882bb7c22SToomas Soome 
61982bb7c22SToomas Soome 	switch (ca->action) {
62082bb7c22SToomas Soome 	case VIS_HIDE_CURSOR:
62182bb7c22SToomas Soome 		bitmap_display_cursor(softc, ca);
62282bb7c22SToomas Soome 		console->fb.cursor.visible = B_FALSE;
62382bb7c22SToomas Soome 		break;
62482bb7c22SToomas Soome 	case VIS_DISPLAY_CURSOR:
62582bb7c22SToomas Soome 		/* keep track of cursor position for polled mode */
62682bb7c22SToomas Soome 		console->fb.cursor.pos.x =
62782bb7c22SToomas Soome 		    (ca->col - console->fb.terminal_origin.x) /
62882bb7c22SToomas Soome 		    console->fb.font_width;
62982bb7c22SToomas Soome 		console->fb.cursor.pos.y =
63082bb7c22SToomas Soome 		    (ca->row - console->fb.terminal_origin.y) /
63182bb7c22SToomas Soome 		    console->fb.font_height;
63282bb7c22SToomas Soome 		console->fb.cursor.origin.x = ca->col;
63382bb7c22SToomas Soome 		console->fb.cursor.origin.y = ca->row;
63482bb7c22SToomas Soome 
63582bb7c22SToomas Soome 		bitmap_display_cursor(softc, ca);
63682bb7c22SToomas Soome 		console->fb.cursor.visible = B_TRUE;
63782bb7c22SToomas Soome 		break;
63882bb7c22SToomas Soome 	case VIS_GET_CURSOR:
63982bb7c22SToomas Soome 		ca->row = console->fb.cursor.origin.y;
64082bb7c22SToomas Soome 		ca->col = console->fb.cursor.origin.x;
64182bb7c22SToomas Soome 		break;
64282bb7c22SToomas Soome 	}
64382bb7c22SToomas Soome }
64482bb7c22SToomas Soome 
64582bb7c22SToomas Soome static void
bitmap_polled_copy(struct vis_polledio_arg * arg,struct vis_conscopy * ca)64682bb7c22SToomas Soome bitmap_polled_copy(struct vis_polledio_arg *arg, struct vis_conscopy *ca)
64782bb7c22SToomas Soome {
64882bb7c22SToomas Soome 	struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)arg;
64982bb7c22SToomas Soome 	bitmap_cons_copy(softc, ca);
65082bb7c22SToomas Soome }
65182bb7c22SToomas Soome 
65282bb7c22SToomas Soome static void
bitmap_polled_display(struct vis_polledio_arg * arg,struct vis_consdisplay * da)65382bb7c22SToomas Soome bitmap_polled_display(struct vis_polledio_arg *arg, struct vis_consdisplay *da)
65482bb7c22SToomas Soome {
65582bb7c22SToomas Soome 	struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)arg;
65682bb7c22SToomas Soome 	bitmap_cons_display(softc, da);
65782bb7c22SToomas Soome }
65882bb7c22SToomas Soome 
65982bb7c22SToomas Soome static void
bitmap_polled_cursor(struct vis_polledio_arg * arg,struct vis_conscursor * ca)66082bb7c22SToomas Soome bitmap_polled_cursor(struct vis_polledio_arg *arg, struct vis_conscursor *ca)
66182bb7c22SToomas Soome {
66282bb7c22SToomas Soome 	struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)arg;
66382bb7c22SToomas Soome 	bitmap_cons_cursor(softc, ca);
66482bb7c22SToomas Soome }
66582bb7c22SToomas Soome 
66682bb7c22SToomas Soome /*
66782bb7c22SToomas Soome  * Device mapping support. Should be possible to mmmap frame buffer
66882bb7c22SToomas Soome  * to user space. Currently not working, mmap will receive -1 as pointer.
66982bb7c22SToomas Soome  */
67082bb7c22SToomas Soome /*ARGSUSED*/
67182bb7c22SToomas Soome static int
bitmap_devmap(dev_t dev,devmap_cookie_t dhp,offset_t off,size_t len,size_t * maplen,uint_t model,void * ptr)67282bb7c22SToomas Soome bitmap_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off,
67382bb7c22SToomas Soome     size_t len, size_t *maplen, uint_t model, void *ptr)
67482bb7c22SToomas Soome {
67582bb7c22SToomas Soome 	struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)ptr;
676ceedf124SToomas Soome 	union gfx_console *console;
67782bb7c22SToomas Soome 	size_t length;
67882bb7c22SToomas Soome 
67982bb7c22SToomas Soome 	if (softc == NULL) {
68082bb7c22SToomas Soome 		cmn_err(CE_WARN, "bitmap: Can't find softstate");
68182bb7c22SToomas Soome 		return (ENXIO);
68282bb7c22SToomas Soome 	}
68382bb7c22SToomas Soome 
684ceedf124SToomas Soome 	console = softc->console;
685ceedf124SToomas Soome 
68682bb7c22SToomas Soome 	if (off >= console->fb.fb_size) {
68782bb7c22SToomas Soome 		cmn_err(CE_WARN, "bitmap: Can't map offset 0x%llx", off);
68882bb7c22SToomas Soome 		return (ENXIO);
68982bb7c22SToomas Soome 	}
69082bb7c22SToomas Soome 
69182bb7c22SToomas Soome 	if (off + len > console->fb.fb_size)
69282bb7c22SToomas Soome 		length = console->fb.fb_size - off;
69382bb7c22SToomas Soome 	else
69482bb7c22SToomas Soome 		length = len;
69582bb7c22SToomas Soome 
69682bb7c22SToomas Soome 	gfxp_map_devmem(dhp, console->fb.paddr, length, &dev_attr);
69782bb7c22SToomas Soome 
69882bb7c22SToomas Soome 	*maplen = length;
69982bb7c22SToomas Soome 
70082bb7c22SToomas Soome 	return (0);
70182bb7c22SToomas Soome }
702