Thu Mar 5 17:50:41 2015 UTC ()
Factor generic parts of intelfb out into a drmfb.

Adapting radeondrmkmsfb should not be hard.

This will make nouveaufb easier too.


(riastradh)
diff -r0 -r1.1 src/sys/external/bsd/drm2/drm/drmfb.c
diff -r1.10 -r1.11 src/sys/external/bsd/drm2/drm/files.drmkms
diff -r1.9 -r1.10 src/sys/external/bsd/drm2/i915drm/files.i915drmkms
diff -r1.10 -r1.11 src/sys/external/bsd/drm2/i915drm/intelfb.c
diff -r0 -r1.1 src/sys/external/bsd/drm2/include/drm/drmfb.h
diff -r0 -r1.1 src/sys/external/bsd/drm2/include/drm/drmfb_pci.h
diff -r0 -r1.1 src/sys/external/bsd/drm2/pci/drmfb_pci.c
diff -r1.4 -r1.5 src/sys/external/bsd/drm2/pci/files.drmkms_pci
diff -r1.8 -r1.9 src/sys/modules/drmkms/Makefile
diff -r1.4 -r1.5 src/sys/modules/drmkms_pci/Makefile

File Added: src/sys/external/bsd/drm2/drm/drmfb.c
/*	$NetBSD: drmfb.c,v 1.1 2015/03/05 17:50:41 riastradh Exp $	*/

/*-
 * Copyright (c) 2014 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Taylor R. Campbell.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * drmfb: wsdisplay support, via genfb, for any drm device.  Use this
 * if you're too lazy to write a hardware-accelerated framebuffer using
 * wsdisplay directly.
 *
 * This doesn't actually do anything interesting -- just hooks up
 * drmkms crap and genfb crap.
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: drmfb.c,v 1.1 2015/03/05 17:50:41 riastradh Exp $");

#ifdef _KERNEL_OPT
#include "vga.h"
#endif

#include <sys/types.h>
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/device.h>
#include <sys/kauth.h>

#if NVGA > 0
/*
 * XXX All we really need is vga_is_console from vgavar.h, but the
 * header files are missing their own dependencies, so we need to
 * explicitly drag in the other crap.
 */
#include <dev/ic/mc6845reg.h>
#include <dev/ic/pcdisplayvar.h>
#include <dev/ic/vgareg.h>
#include <dev/ic/vgavar.h>
#endif

#include <dev/wsfb/genfbvar.h>

#include <drm/drmP.h>
#include <drm/drm_fb_helper.h>
#include <drm/drmfb.h>

static int	drmfb_genfb_ioctl(void *, void *, unsigned long, void *, int,
		    struct lwp *);
static paddr_t	drmfb_genfb_mmap(void *, void *, off_t, int);
static int	drmfb_genfb_enable_polling(void *);
static int	drmfb_genfb_disable_polling(void *);
static bool	drmfb_genfb_setmode(struct genfb_softc *, int);

static const struct genfb_mode_callback drmfb_genfb_mode_callback = {
	.gmc_setmode = drmfb_genfb_setmode,
};

int
drmfb_attach(struct drmfb_softc *sc, const struct drmfb_attach_args *da)
{
	const struct drm_fb_helper_surface_size *const sizes = da->da_fb_sizes;
	const prop_dictionary_t dict = device_properties(da->da_dev);
#if NVGA > 0
	struct drm_device *const dev = da->da_fb_helper->dev;
#endif
	static const struct genfb_ops zero_genfb_ops;
	struct genfb_ops genfb_ops = zero_genfb_ops;
	enum { CONS_VGA, CONS_GENFB, CONS_NONE } what_was_cons;
	int error;

	/* genfb requires this.  */
	KASSERTMSG((void *)&sc->sc_genfb == device_private(da->da_dev),
	    "drmfb_softc must be first member of device softc");

	sc->sc_da = *da;

	prop_dictionary_set_uint32(dict, "width", sizes->surface_width);
	prop_dictionary_set_uint32(dict, "height", sizes->surface_height);
	prop_dictionary_set_uint8(dict, "depth", sizes->surface_bpp);
	prop_dictionary_set_uint16(dict, "linebytes",
	    roundup2((sizes->surface_width * howmany(sizes->surface_bpp, 8)),
		64));
	prop_dictionary_set_uint32(dict, "address", 0); /* XXX >32-bit */
	CTASSERT(sizeof(uintptr_t) <= sizeof(uint64_t));
	prop_dictionary_set_uint64(dict, "virtual_address",
	    (uint64_t)(uintptr_t)da->da_fb_vaddr);

	prop_dictionary_set_uint64(dict, "mode_callback",
	    (uint64_t)(uintptr_t)&drmfb_genfb_mode_callback);

	/* XXX Whattakludge!  */
#if NVGA > 0
	if ((da->da_params->dp_is_vga_console != NULL) &&
	    (*da->da_params->dp_is_vga_console)(dev)) {
		what_was_cons = CONS_VGA;
		prop_dictionary_set_bool(dict, "is_console", true);
		vga_cndetach();
		if (da->da_params->dp_disable_vga)
			(*da->da_params->dp_disable_vga)(dev);
	} else
#endif
	if (genfb_is_console() && genfb_is_enabled()) {
		what_was_cons = CONS_GENFB;
		prop_dictionary_set_bool(dict, "is_console", true);
	} else {
		what_was_cons = CONS_NONE;
		prop_dictionary_set_bool(dict, "is_console", false);
	}

	sc->sc_genfb.sc_dev = sc->sc_da.da_dev;
	genfb_init(&sc->sc_genfb);
	genfb_ops.genfb_ioctl = drmfb_genfb_ioctl;
	genfb_ops.genfb_mmap = drmfb_genfb_mmap;
	genfb_ops.genfb_enable_polling = drmfb_genfb_enable_polling;
	genfb_ops.genfb_disable_polling = drmfb_genfb_disable_polling;

	error = genfb_attach(&sc->sc_genfb, &genfb_ops);
	if (error) {
		aprint_error_dev(sc->sc_da.da_dev,
		    "failed to attach genfb: %d\n", error);
		goto fail0;
	}

	/* Success!  */
	return 0;

fail0:	KASSERT(error);
	/* XXX Restore console...  */
	switch (what_was_cons) {
	case CONS_VGA:
		break;
	case CONS_GENFB:
		break;
	case CONS_NONE:
		break;
	default:
		break;
	}
	return error;
}

int
drmfb_detach(struct drmfb_softc *sc, int flags)
{

	/* XXX genfb detach?  */
	return 0;
}

static int
drmfb_genfb_ioctl(void *v, void *vs, unsigned long cmd, void *data, int flag,
    struct lwp *l)
{
	struct genfb_softc *const genfb = v;
	struct drmfb_softc *const sc = container_of(genfb, struct drmfb_softc,
	    sc_genfb);
	int error;

	if (sc->sc_da.da_params->dp_ioctl) {
		error = (*sc->sc_da.da_params->dp_ioctl)(sc, cmd, data, flag,
		    l);
		if (error != EPASSTHROUGH)
			return error;
	}

	switch (cmd) {
	/*
	 * Screen blanking ioctls.  Not to be confused with backlight
	 * (can be disabled while stuff is still drawn on the screen),
	 * brightness, or contrast (which we don't support).  Backlight
	 * and brightness are done through WSDISPLAYIO_{GET,SET}PARAM.
	 * This toggles between DPMS ON and DPMS OFF; backlight toggles
	 * between DPMS ON and DPMS SUSPEND.
	 */
	case WSDISPLAYIO_GVIDEO: {
		int *onp = (int *)data;

		/* XXX Can't really determine a single answer here.  */
		*onp = 1;
		return 0;
	}
	case WSDISPLAYIO_SVIDEO: {
		const int on = *(const int *)data;
		const int dpms_mode = on? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF;
		struct drm_fb_helper *const fb_helper = sc->sc_da.da_fb_helper;
		struct drm_device *const dev = fb_helper->dev;
		unsigned i;

		drm_modeset_lock_all(dev);
		for (i = 0; i < fb_helper->connector_count; i++) {
			struct drm_connector *const connector =
			    fb_helper->connector_info[i]->connector;
			(*connector->funcs->dpms)(connector, dpms_mode);
			drm_object_property_set_value(&connector->base,
			    dev->mode_config.dpms_property, dpms_mode);
		}
		drm_modeset_unlock_all(dev);

		return 0;
	}
	default:
		return EPASSTHROUGH;
	}
}

static paddr_t
drmfb_genfb_mmap(void *v, void *vs, off_t offset, int prot)
{
	struct genfb_softc *const genfb = v;
	struct drmfb_softc *const sc = container_of(genfb, struct drmfb_softc,
	    sc_genfb);

	KASSERT(0 <= offset);

	if (offset < genfb->sc_fbsize) {
		if (sc->sc_da.da_params->dp_mmapfb == NULL)
			return -1;
		return (*sc->sc_da.da_params->dp_mmapfb)(sc, offset, prot);
	} else {
		if (kauth_authorize_machdep(kauth_cred_get(),
			KAUTH_MACHDEP_UNMANAGEDMEM, NULL, NULL, NULL, NULL)
		    != 0)
			return -1;
		if (sc->sc_da.da_params->dp_mmap == NULL)
			return -1;
		return (*sc->sc_da.da_params->dp_mmap)(sc, offset, prot);
	}
}

static int
drmfb_genfb_enable_polling(void *cookie)
{
	struct genfb_softc *const genfb = cookie;
	struct drmfb_softc *const sc = container_of(genfb, struct drmfb_softc,
	    sc_genfb);

	return drm_fb_helper_debug_enter_fb(sc->sc_da.da_fb_helper);
}

static int
drmfb_genfb_disable_polling(void *cookie)
{
	struct genfb_softc *const genfb = cookie;
	struct drmfb_softc *const sc = container_of(genfb, struct drmfb_softc,
	    sc_genfb);

	return drm_fb_helper_debug_leave_fb(sc->sc_da.da_fb_helper);
}

static bool
drmfb_genfb_setmode(struct genfb_softc *genfb, int mode)
{
	struct drmfb_softc *sc = container_of(genfb, struct drmfb_softc,
	    sc_genfb);

	if (mode == WSDISPLAYIO_MODE_EMUL)
		drm_fb_helper_set_config(sc->sc_da.da_fb_helper);

	return true;
}

bool
drmfb_shutdown(struct drmfb_softc *sc, int flags __unused)
{

	genfb_enable_polling(sc->sc_da.da_dev);
	return true;
}

cvs diff -r1.10 -r1.11 src/sys/external/bsd/drm2/drm/files.drmkms (expand / switch to unified diff)

--- src/sys/external/bsd/drm2/drm/files.drmkms 2015/03/05 17:42:48 1.10
+++ src/sys/external/bsd/drm2/drm/files.drmkms 2015/03/05 17:50:41 1.11
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# $NetBSD: files.drmkms,v 1.10 2015/03/05 17:42:48 riastradh Exp $ 1# $NetBSD: files.drmkms,v 1.11 2015/03/05 17:50:41 riastradh Exp $
2 2
3include "external/bsd/drm2/linux/files.drmkms_linux" 3include "external/bsd/drm2/linux/files.drmkms_linux"
4 4
5# i2c code is not separated out, but it is marked so that it could be 5# i2c code is not separated out, but it is marked so that it could be
6# if we wanted. Not clear that this provides as much advantage as 6# if we wanted. Not clear that this provides as much advantage as
7# separating out PCI code, which will be necessary for, e.g., PCIless 7# separating out PCI code, which will be necessary for, e.g., PCIless
8# ARM SoC graphics drivers. 8# ARM SoC graphics drivers.
9define drmkms_i2c: drmkms_linux 9define drmkms_i2c: drmkms_linux
10 10
11define drmkms: drmkms_linux, drmkms_i2c 11define drmkms: drmkms_linux, drmkms_i2c
12 12
13defflag opt_drmkms.h DRMKMS_DEBUG 13defflag opt_drmkms.h DRMKMS_DEBUG
14makeoptions drmkms CPPFLAGS+="-I$S/external/bsd/drm2/include" 14makeoptions drmkms CPPFLAGS+="-I$S/external/bsd/drm2/include"
@@ -57,14 +57,18 @@ file external/bsd/drm2/dist/drm/drm_plan @@ -57,14 +57,18 @@ file external/bsd/drm2/dist/drm/drm_plan
57#file external/bsd/drm2/dist/drm/drm_prime.c drmkms 57#file external/bsd/drm2/dist/drm/drm_prime.c drmkms
58file external/bsd/drm2/dist/drm/drm_probe_helper.c drmkms 58file external/bsd/drm2/dist/drm/drm_probe_helper.c drmkms
59file external/bsd/drm2/dist/drm/drm_rect.c drmkms 59file external/bsd/drm2/dist/drm/drm_rect.c drmkms
60file external/bsd/drm2/drm/drm_scatter.c drmkms 60file external/bsd/drm2/drm/drm_scatter.c drmkms
61file external/bsd/drm2/dist/drm/drm_stub.c drmkms 61file external/bsd/drm2/dist/drm/drm_stub.c drmkms
62file external/bsd/drm2/drm/drm_sysfs.c drmkms 62file external/bsd/drm2/drm/drm_sysfs.c drmkms
63file external/bsd/drm2/drm/drm_vm.c drmkms 63file external/bsd/drm2/drm/drm_vm.c drmkms
64file external/bsd/drm2/drm/drm_vma_manager.c drmkms 64file external/bsd/drm2/drm/drm_vma_manager.c drmkms
65 65
66file external/bsd/drm2/drm/drm_gem_vm.c drmkms 66file external/bsd/drm2/drm/drm_gem_vm.c drmkms
67file external/bsd/drm2/drm/drm_module.c drmkms 67file external/bsd/drm2/drm/drm_module.c drmkms
68file external/bsd/drm2/drm/drm_sysctl.c drmkms 68file external/bsd/drm2/drm/drm_sysctl.c drmkms
69 69
 70# Generic, unaccelerated drm-based framebuffer.
 71define drmfb: genfb
 72file external/bsd/drm2/drm/drmfb.c drmfb
 73
70include "external/bsd/drm2/ttm/files.ttm" 74include "external/bsd/drm2/ttm/files.ttm"

cvs diff -r1.9 -r1.10 src/sys/external/bsd/drm2/i915drm/files.i915drmkms (expand / switch to unified diff)

--- src/sys/external/bsd/drm2/i915drm/files.i915drmkms 2014/11/14 14:32:49 1.9
+++ src/sys/external/bsd/drm2/i915drm/files.i915drmkms 2015/03/05 17:50:41 1.10
@@ -1,20 +1,20 @@ @@ -1,20 +1,20 @@
1# $NetBSD: files.i915drmkms,v 1.9 2014/11/14 14:32:49 joerg Exp $ 1# $NetBSD: files.i915drmkms,v 1.10 2015/03/05 17:50:41 riastradh Exp $
2 2
3define intelfbbus { } 3define intelfbbus { }
4device i915drmkms: drmkms, drmkms_pci, intelfbbus, agp_i810 4device i915drmkms: drmkms, drmkms_pci, intelfbbus, agp_i810
5attach i915drmkms at pci 5attach i915drmkms at pci
6 6
7device intelfb: intelfbbus, genfb, wsemuldisplaydev 7device intelfb: intelfbbus, drmfb, drmfb_pci, wsemuldisplaydev
8attach intelfb at intelfbbus 8attach intelfb at intelfbbus
9 9
10makeoptions i915drmkms CPPFLAGS+="-I$S/external/bsd/drm2/dist/drm/i915" 10makeoptions i915drmkms CPPFLAGS+="-I$S/external/bsd/drm2/dist/drm/i915"
11makeoptions i915drmkms CPPFLAGS+="-I$S/external/bsd/drm2/i915drm" 11makeoptions i915drmkms CPPFLAGS+="-I$S/external/bsd/drm2/i915drm"
12 12
13makeoptions i915drmkms "CWARNFLAGS.i915_drv.c"+="${${ACTIVE_CC} == gcc:? -Wno-override-init :}" 13makeoptions i915drmkms "CWARNFLAGS.i915_drv.c"+="${${ACTIVE_CC} == gcc:? -Wno-override-init :}"
14makeoptions i915drmkms "CWARNFLAGS.i915_drv.c"+="${${ACTIVE_CC} == clang:? -Wno-initializer-overrides :}" 14makeoptions i915drmkms "CWARNFLAGS.i915_drv.c"+="${${ACTIVE_CC} == clang:? -Wno-initializer-overrides :}"
15makeoptions i915drmkms "CWARNFLAGS.intel_display.c"+="-Wno-shadow -Wno-conversion" 15makeoptions i915drmkms "CWARNFLAGS.intel_display.c"+="-Wno-shadow -Wno-conversion"
16makeoptions i915drmkms "CWARNFLAGS.intel_panel.c"+="-Wno-shadow" 16makeoptions i915drmkms "CWARNFLAGS.intel_panel.c"+="-Wno-shadow"
17makeoptions i915drmkms "CWARNFLAGS.intel_pm.c"+="-Wno-shadow" 17makeoptions i915drmkms "CWARNFLAGS.intel_pm.c"+="-Wno-shadow"
18 18
19# XXX x86 kludge. 19# XXX x86 kludge.
20makeoptions i915drmkms CPPFLAGS+="-DCONFIG_DRM_I915_FBDEV" 20makeoptions i915drmkms CPPFLAGS+="-DCONFIG_DRM_I915_FBDEV"

cvs diff -r1.10 -r1.11 src/sys/external/bsd/drm2/i915drm/intelfb.c (expand / switch to unified diff)

--- src/sys/external/bsd/drm2/i915drm/intelfb.c 2014/09/14 16:02:15 1.10
+++ src/sys/external/bsd/drm2/i915drm/intelfb.c 2015/03/05 17:50:41 1.11
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: intelfb.c,v 1.10 2014/09/14 16:02:15 riastradh Exp $ */ 1/* $NetBSD: intelfb.c,v 1.11 2015/03/05 17:50:41 riastradh Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2014 The NetBSD Foundation, Inc. 4 * Copyright (c) 2014 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Taylor R. Campbell. 8 * by Taylor R. Campbell.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -20,91 +20,84 @@ @@ -20,91 +20,84 @@
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: intelfb.c,v 1.10 2014/09/14 16:02:15 riastradh Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: intelfb.c,v 1.11 2015/03/05 17:50:41 riastradh Exp $");
34 34
35#ifdef _KERNEL_OPT 35#ifdef _KERNEL_OPT
36#include "vga.h" 36#include "vga.h"
37#endif 37#endif
38 38
39#include <sys/types.h> 39#include <sys/types.h>
40#include <sys/bus.h> 40#include <sys/bus.h>
41#include <sys/device.h> 41#include <sys/device.h>
42 42
43#include <dev/pci/pciio.h> 
44#include <dev/pci/pcireg.h> 
45#include <dev/pci/pcivar.h> 
46 
47#include <dev/pci/wsdisplay_pci.h> 
48#include <dev/wsfb/genfbvar.h> 
49 
50#if NVGA > 0 43#if NVGA > 0
51/* 44/*
52 * XXX All we really need is vga_is_console from vgavar.h, but the 45 * XXX All we really need is vga_is_console from vgavar.h, but the
53 * header files are missing their own dependencies, so we need to 46 * header files are missing their own dependencies, so we need to
54 * explicitly drag in the other crap. 47 * explicitly drag in the other crap.
55 */ 48 */
56#include <dev/ic/mc6845reg.h> 49#include <dev/ic/mc6845reg.h>
57#include <dev/ic/pcdisplayvar.h> 50#include <dev/ic/pcdisplayvar.h>
58#include <dev/ic/vgareg.h> 51#include <dev/ic/vgareg.h>
59#include <dev/ic/vgavar.h> 52#include <dev/ic/vgavar.h>
60#endif 53#endif
61 54
62#include <drm/drmP.h> 55#include <drm/drmP.h>
63#include <drm/drm_fb_helper.h> 56#include <drm/drmfb.h>
 57#include <drm/drmfb_pci.h>
64 58
65#include "i915_drv.h" 59#include "i915_drv.h"
66#include "i915_pci.h" 60#include "i915_pci.h"
67#include "intelfb.h" 61#include "intelfb.h"
68 62
 63static int intelfb_match(device_t, cfdata_t, void *);
 64static void intelfb_attach(device_t, device_t, void *);
 65static int intelfb_detach(device_t, int);
 66
 67static void intelfb_attach_task(struct i915drmkms_task *);
 68
 69static bool intel_is_vga_console(struct drm_device *);
 70static bool intelfb_shutdown(device_t, int);
 71
 72static paddr_t intelfb_drmfb_mmapfb(struct drmfb_softc *, off_t, int);
 73
69struct intelfb_softc { 74struct intelfb_softc {
70 /* XXX genfb requires the genfb_softc to be first. */ 75 struct drmfb_softc sc_drmfb; /* XXX Must be first. */
71 struct genfb_softc sc_genfb; 
72 device_t sc_dev; 76 device_t sc_dev;
73 struct intelfb_attach_args sc_ifa; 77 struct intelfb_attach_args sc_ifa;
74 bus_space_handle_t sc_fb_bsh; 78 bus_space_handle_t sc_fb_bsh;
75 struct i915drmkms_task sc_setconfig_task; 79 struct i915drmkms_task sc_attach_task;
76 bool sc_mapped:1; 80 bool sc_mapped:1;
77 bool sc_scheduled:1; 81 bool sc_scheduled:1;
78 bool sc_attached:1; 82 bool sc_attached:1;
79}; 83};
80 84
81static int intelfb_match(device_t, cfdata_t, void *); 85static const struct drmfb_params intelfb_drmfb_params = {
82static void intelfb_attach(device_t, device_t, void *); 86 .dp_mmapfb = intelfb_drmfb_mmapfb,
83static int intelfb_detach(device_t, int); 87 .dp_mmap = drmfb_pci_mmap,
84 88 .dp_ioctl = drmfb_pci_ioctl,
85static void intelfb_setconfig_task(struct i915drmkms_task *); 89 .dp_is_vga_console = intel_is_vga_console,
86 90 .dp_disable_vga = i915_disable_vga,
87static int intelfb_genfb_dpms(struct drm_device *, int); 
88static int intelfb_genfb_ioctl(void *, void *, unsigned long, void *, 
89 int, struct lwp *); 
90static paddr_t intelfb_genfb_mmap(void *, void *, off_t, int); 
91static int intelfb_genfb_enable_polling(void *); 
92static int intelfb_genfb_disable_polling(void *); 
93static bool intelfb_genfb_shutdown(device_t, int); 
94static bool intelfb_genfb_setmode(struct genfb_softc *, int); 
95 
96static const struct genfb_mode_callback intelfb_genfb_mode_callback = { 
97 .gmc_setmode = intelfb_genfb_setmode, 
98}; 91};
99 92
100CFATTACH_DECL_NEW(intelfb, sizeof(struct intelfb_softc), 93CFATTACH_DECL_NEW(intelfb, sizeof(struct intelfb_softc),
101 intelfb_match, intelfb_attach, intelfb_detach, NULL); 94 intelfb_match, intelfb_attach, intelfb_detach, NULL);
102 95
103static int 96static int
104intelfb_match(device_t parent, cfdata_t match, void *aux) 97intelfb_match(device_t parent, cfdata_t match, void *aux)
105{ 98{
106 99
107 return 1; 100 return 1;
108} 101}
109 102
110static void 103static void
@@ -116,327 +109,135 @@ intelfb_attach(device_t parent, device_t @@ -116,327 +109,135 @@ intelfb_attach(device_t parent, device_t
116 109
117 sc->sc_dev = self; 110 sc->sc_dev = self;
118 sc->sc_ifa = *ifa; 111 sc->sc_ifa = *ifa;
119 sc->sc_mapped = false; 112 sc->sc_mapped = false;
120 sc->sc_scheduled = false; 113 sc->sc_scheduled = false;
121 sc->sc_attached = false; 114 sc->sc_attached = false;
122 115
123 aprint_naive("\n"); 116 aprint_naive("\n");
124 aprint_normal("\n"); 117 aprint_normal("\n");
125 118
126 /* XXX Defer this too? */ 119 /* XXX Defer this too? */
127 error = bus_space_map(ifa->ifa_fb_bst, ifa->ifa_fb_addr, 120 error = bus_space_map(ifa->ifa_fb_bst, ifa->ifa_fb_addr,
128 ifa->ifa_fb_size, 121 ifa->ifa_fb_size,
129 (BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE), 122 BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_PREFETCHABLE,
130 &sc->sc_fb_bsh); 123 &sc->sc_fb_bsh);
131 if (error) { 124 if (error) {
132 aprint_error_dev(self, "unable to map framebuffer: %d\n", 125 aprint_error_dev(self, "unable to map framebuffer: %d\n",
133 error); 126 error);
134 goto fail0; 127 goto fail0;
135 } 128 }
136 sc->sc_mapped = true; 129 sc->sc_mapped = true;
137 130
138 i915drmkms_task_init(&sc->sc_setconfig_task, &intelfb_setconfig_task); 131 i915drmkms_task_init(&sc->sc_attach_task, &intelfb_attach_task);
139 error = i915drmkms_task_schedule(parent, &sc->sc_setconfig_task); 132 error = i915drmkms_task_schedule(parent, &sc->sc_attach_task);
140 if (error) { 133 if (error) {
141 aprint_error_dev(self, "failed to schedule mode set: %d\n", 134 aprint_error_dev(self, "failed to schedule mode set: %d\n",
142 error); 135 error);
143 goto fail1; 136 goto fail1;
144 } 137 }
145 sc->sc_scheduled = true; 138 sc->sc_scheduled = true;
146 139
147 /* Success! */ 140 /* Success! */
148 return; 141 return;
149 142
150fail1: bus_space_unmap(ifa->ifa_fb_bst, sc->sc_fb_bsh, ifa->ifa_fb_size); 143fail1: bus_space_unmap(ifa->ifa_fb_bst, sc->sc_fb_bsh, ifa->ifa_fb_size);
151 sc->sc_mapped = false; 144 sc->sc_mapped = false;
152fail0: return; 145fail0: return;
153} 146}
154 147
155static int 148static int
156intelfb_detach(device_t self, int flags) 149intelfb_detach(device_t self, int flags)
157{ 150{
158 struct intelfb_softc *const sc = device_private(self); 151 struct intelfb_softc *const sc = device_private(self);
 152 int error;
159 153
160 if (sc->sc_scheduled) 154 if (sc->sc_scheduled)
161 return EBUSY; 155 return EBUSY;
162 156
163 if (sc->sc_attached) { 157 if (sc->sc_attached) {
164 /* XXX genfb detach? Help? */ 158 pmf_device_deregister(self);
 159 error = drmfb_detach(&sc->sc_drmfb, flags);
 160 if (error) {
 161 /* XXX Ugh. */
 162 (void)pmf_device_register1(self, NULL, NULL,
 163 &intelfb_shutdown);
 164 return error;
 165 }
165 sc->sc_attached = false; 166 sc->sc_attached = false;
166 } 167 }
167 168
168 if (sc->sc_mapped) { 169 if (sc->sc_mapped) {
169 bus_space_unmap(sc->sc_ifa.ifa_fb_bst, sc->sc_fb_bsh, 170 bus_space_unmap(sc->sc_ifa.ifa_fb_bst, sc->sc_fb_bsh,
170 sc->sc_ifa.ifa_fb_size); 171 sc->sc_ifa.ifa_fb_size);
171 sc->sc_mapped = false; 172 sc->sc_mapped = false;
172 } 173 }
173 174
174 return 0; 175 return 0;
175} 176}
176 177
177static void 178static void
178intelfb_setconfig_task(struct i915drmkms_task *task) 179intelfb_attach_task(struct i915drmkms_task *task)
179{ 180{
180 struct intelfb_softc *const sc = container_of(task, 181 struct intelfb_softc *const sc = container_of(task,
181 struct intelfb_softc, sc_setconfig_task); 182 struct intelfb_softc, sc_attach_task);
182 const prop_dictionary_t dict = device_properties(sc->sc_dev); 
183 const struct intelfb_attach_args *const ifa = &sc->sc_ifa; 183 const struct intelfb_attach_args *const ifa = &sc->sc_ifa;
184 const struct drm_fb_helper_surface_size *const sizes = 184 const struct drmfb_attach_args da = {
185 &ifa->ifa_fb_sizes; 185 .da_dev = sc->sc_dev,
186#if NVGA > 0 /* XXX no workie for modules */ 186 .da_fb_helper = ifa->ifa_fb_helper,
187 struct drm_device *const dev = sc->sc_ifa.ifa_drm_dev; 187 .da_fb_sizes = &ifa->ifa_fb_sizes,
188#endif 188 .da_fb_vaddr = bus_space_vaddr(ifa->ifa_fb_bst, sc->sc_fb_bsh),
189 enum { CONS_VGA, CONS_GENFB, CONS_NONE } what_was_cons; 189 .da_params = &intelfb_drmfb_params,
190 static const struct genfb_ops zero_genfb_ops; 190 };
191 struct genfb_ops genfb_ops = zero_genfb_ops; 
192 int error; 191 int error;
193 192
194 KASSERT(sc->sc_scheduled); 193 error = drmfb_attach(&sc->sc_drmfb, &da);
195 
196 if (ifa->ifa_fb_zero) 
197 bus_space_set_region_1(sc->sc_ifa.ifa_fb_bst, sc->sc_fb_bsh, 0, 
198 0, sc->sc_ifa.ifa_fb_size); 
199 
200 /* XXX Ugh... Pass these parameters some other way! */ 
201 prop_dictionary_set_uint32(dict, "width", sizes->surface_width); 
202 prop_dictionary_set_uint32(dict, "height", sizes->surface_height); 
203 prop_dictionary_set_uint8(dict, "depth", sizes->surface_bpp); 
204 prop_dictionary_set_uint16(dict, "linebytes", 
205 roundup2((sizes->surface_width * howmany(sizes->surface_bpp, 8)), 
206 64)); 
207 prop_dictionary_set_uint32(dict, "address", 0); /* XXX >32-bit */ 
208 CTASSERT(sizeof(uintptr_t) <= sizeof(uint64_t)); 
209 prop_dictionary_set_uint64(dict, "virtual_address", 
210 (uint64_t)(uintptr_t)bus_space_vaddr(sc->sc_ifa.ifa_fb_bst, 
211 sc->sc_fb_bsh)); 
212 
213 prop_dictionary_set_uint64(dict, "mode_callback", 
214 (uint64_t)(uintptr_t)&intelfb_genfb_mode_callback); 
215 
216 /* XXX Whattakludge! */ 
217#if NVGA > 0 
218 if (vga_is_console(dev->pdev->pd_pa.pa_iot, -1)) { 
219 what_was_cons = CONS_VGA; 
220 prop_dictionary_set_bool(dict, "is_console", true); 
221 vga_cndetach(); 
222 i915_disable_vga(dev); 
223 } else 
224#endif 
225 if (genfb_is_console() && genfb_is_enabled()) { 
226 what_was_cons = CONS_GENFB; 
227 prop_dictionary_set_bool(dict, "is_console", true); 
228 } else { 
229 what_was_cons = CONS_NONE; 
230 prop_dictionary_set_bool(dict, "is_console", false); 
231 } 
232 
233 sc->sc_genfb.sc_dev = sc->sc_dev; 
234 genfb_init(&sc->sc_genfb); 
235 genfb_ops.genfb_ioctl = intelfb_genfb_ioctl; 
236 genfb_ops.genfb_mmap = intelfb_genfb_mmap; 
237 genfb_ops.genfb_enable_polling = intelfb_genfb_enable_polling; 
238 genfb_ops.genfb_disable_polling = intelfb_genfb_disable_polling; 
239 
240 error = genfb_attach(&sc->sc_genfb, &genfb_ops); 
241 if (error) { 194 if (error) {
242 aprint_error_dev(sc->sc_dev, "failed to attach genfb: %d\n", 195 aprint_error_dev(sc->sc_dev, "failed to attach drmfb: %d\n",
243 error); 196 error);
244 goto fail0; 197 return;
245 } 198 }
246 sc->sc_attached = true; 
247 
248 pmf_device_register1(sc->sc_dev, NULL, NULL, 
249 intelfb_genfb_shutdown); 
250 199
251 /* Success! */ 200 if (pmf_device_register1(sc->sc_dev, NULL, NULL, &intelfb_shutdown))
252 sc->sc_scheduled = false; 201 aprint_error_dev(sc->sc_dev,
253 return; 202 "failed to register shutdown handler\n");
254 203
255fail0: /* XXX Restore console... */ 204 sc->sc_attached = true;
256 switch (what_was_cons) { 
257 case CONS_VGA: 
258 break; 
259 case CONS_GENFB: 
260 break; 
261 case CONS_NONE: 
262 break; 
263 default: 
264 break; 
265 } 
266} 205}
267 206
268static int 207static bool
269intelfb_genfb_dpms(struct drm_device *dev, int dpms_mode) 208intel_is_vga_console(struct drm_device *dev)
270{ 209{
271 struct drm_i915_private *const dev_priv = dev->dev_private; 
272 /* XXX What guarantees dev_priv->fbdev stays around? */ 
273 struct drm_fb_helper *const fb_helper = &dev_priv->fbdev->helper; 
274 unsigned i; 
275 
276 drm_modeset_lock_all(dev); 
277 for (i = 0; i < fb_helper->connector_count; i++) { 
278 struct drm_connector *const connector = 
279 fb_helper->connector_info[i]->connector; 
280 (*connector->funcs->dpms)(connector, dpms_mode); 
281 drm_object_property_set_value(&connector->base, 
282 dev->mode_config.dpms_property, dpms_mode); 
283 } 
284 drm_modeset_unlock_all(dev); 
285 210
286 return 0; 211#if NVGA > 0
 212 return vga_is_console(dev->pdev->pd_pa.pa_iot, -1);
 213#else
 214 return false;
 215#endif
287} 216}
288 217
289static int 218static bool
290intelfb_genfb_ioctl(void *v, void *vs, unsigned long cmd, void *data, int flag, 219intelfb_shutdown(device_t self, int flags)
291 struct lwp *l) 
292{ 220{
293 struct genfb_softc *const genfb = v; 221 struct intelfb_softc *const sc = device_private(self);
294 struct intelfb_softc *const sc = container_of(genfb, 
295 struct intelfb_softc, sc_genfb); 
296 struct drm_device *const dev = sc->sc_ifa.ifa_fb_helper->dev; 
297 const struct pci_attach_args *const pa = &dev->pdev->pd_pa; 
298 
299 switch (cmd) { 
300 case WSDISPLAYIO_GTYPE: 
301 *(unsigned int *)data = WSDISPLAY_TYPE_PCIVGA; 
302 return 0; 
303 
304 /* PCI config read/write passthrough. */ 
305 case PCI_IOC_CFGREAD: 
306 case PCI_IOC_CFGWRITE: 
307 return pci_devioctl(pa->pa_pc, pa->pa_tag, cmd, data, flag, l); 
308 
309 case WSDISPLAYIO_GET_BUSID: 
310 return wsdisplayio_busid_pci(dev->dev, pa->pa_pc, pa->pa_tag, 
311 data); 
312 
313 /* 
314 * Screen blanking ioctls. Not to be confused with backlight 
315 * (can be disabled while stuff is still drawn on the screen), 
316 * brightness, or contrast (which we don't support). Backlight 
317 * and brightness are done through WSDISPLAYIO_{GET,SET}PARAM. 
318 * This toggles between DPMS ON and DPMS OFF; backlight toggles 
319 * between DPMS ON and DPMS SUSPEND. 
320 */ 
321 case WSDISPLAYIO_GVIDEO: { 
322 int *onp = (int *)data; 
323 
324 /* XXX Can't really determine a single answer here. */ 
325 *onp = 1; 
326 return 0; 
327 } 
328 
329 case WSDISPLAYIO_SVIDEO: { 
330 const int on = *(const int *)data; 
331 
332 return intelfb_genfb_dpms(dev, 
333 on? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF); 
334 } 
335 222
336 default: 223 return drmfb_shutdown(&sc->sc_drmfb, flags);
337 return EPASSTHROUGH; 
338 } 
339} 224}
340 225
341static paddr_t 226static paddr_t
342intelfb_genfb_mmap(void *v, void *vs, off_t offset, int prot) 227intelfb_drmfb_mmapfb(struct drmfb_softc *drmfb, off_t offset, int prot)
343{ 228{
344 struct genfb_softc *const genfb = v; 229 struct intelfb_softc *const sc = container_of(drmfb,
345 struct intelfb_softc *const sc = container_of(genfb, 230 struct intelfb_softc, sc_drmfb);
346 struct intelfb_softc, sc_genfb); 
347 struct drm_fb_helper *const helper = sc->sc_ifa.ifa_fb_helper; 231 struct drm_fb_helper *const helper = sc->sc_ifa.ifa_fb_helper;
348 struct intel_fbdev *const fbdev = container_of(helper, 232 struct intel_fbdev *const fbdev = container_of(helper,
349 struct intel_fbdev, helper); 233 struct intel_fbdev, helper);
350 struct drm_device *const dev = helper->dev; 234 struct drm_device *const dev = helper->dev;
351 struct drm_i915_private *const dev_priv = dev->dev_private; 235 struct drm_i915_private *const dev_priv = dev->dev_private;
352 const struct pci_attach_args *const pa = &dev->pdev->pd_pa; 
353 unsigned int i; 
354 
355 if (offset < 0) 
356 return -1; 
357 
358 /* Treat low memory as the framebuffer itself. */ 
359 if (offset < genfb->sc_fbsize) 
360 return bus_space_mmap(dev->bst, 
361 (dev_priv->gtt.mappable_base + 
362 i915_gem_obj_ggtt_offset(fbdev->fb->obj)), 
363 offset, prot, 
364 (BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE)); 
365 
366 /* XXX Cargo-culted from genfb_pci. */ 
367 if (kauth_authorize_machdep(kauth_cred_get(), 
368 KAUTH_MACHDEP_UNMANAGEDMEM, NULL, NULL, NULL, NULL) != 0) { 
369 aprint_normal_dev(dev->dev, "mmap at %"PRIxMAX" rejected\n", 
370 (uintmax_t)offset); 
371 return -1; 
372 } 
373 
374 for (i = 0; PCI_BAR(i) <= PCI_MAPREG_ROM; i++) { 
375 pcireg_t type; 
376 bus_addr_t addr; 
377 bus_size_t size; 
378 int flags; 
379 
380 /* Interrogate the BAR. */ 
381 if (!pci_mapreg_probe(pa->pa_pc, pa->pa_tag, PCI_BAR(i), 
382 &type)) 
383 continue; 
384 if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM) 
385 continue; 
386 if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, PCI_BAR(i), type, 
387 &addr, &size, &flags)) 
388 continue; 
389 
390 /* Try to map it if it's in range. */ 
391 if ((addr <= offset) && (offset < (addr + size))) 
392 return bus_space_mmap(pa->pa_memt, addr, 
393 (offset - addr), prot, flags); 
394 
395 /* Skip a slot if this was a 64-bit BAR. */ 
396 if ((PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_MEM) && 
397 (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT)) 
398 i += 1; 
399 } 
400 
401 /* Failure! */ 
402 return -1; 
403} 
404 236
405static int 237 KASSERT(0 <= offset);
406intelfb_genfb_enable_polling(void *cookie) 238 KASSERT(offset < fbdev->fb->obj->base.size);
407{ 
408 struct genfb_softc *const genfb = cookie; 
409 struct intelfb_softc *const sc = container_of(genfb, 
410 struct intelfb_softc, sc_genfb); 
411 
412 return drm_fb_helper_debug_enter_fb(sc->sc_ifa.ifa_fb_helper); 
413} 
414 
415static int 
416intelfb_genfb_disable_polling(void *cookie) 
417{ 
418 struct genfb_softc *const genfb = cookie; 
419 struct intelfb_softc *const sc = container_of(genfb, 
420 struct intelfb_softc, sc_genfb); 
421 
422 return drm_fb_helper_debug_leave_fb(sc->sc_ifa.ifa_fb_helper); 
423} 
424 
425static bool 
426intelfb_genfb_shutdown(device_t self, int flags) 
427{ 
428 genfb_enable_polling(self); 
429 return true; 
430} 
431 
432static bool 
433intelfb_genfb_setmode(struct genfb_softc *genfb, int mode) 
434{ 
435 struct intelfb_softc *sc = (struct intelfb_softc *)genfb; 
436 
437 if (mode == WSDISPLAYIO_MODE_EMUL) { 
438 drm_fb_helper_set_config(sc->sc_ifa.ifa_fb_helper); 
439 } 
440 239
441 return true; 240 return bus_space_mmap(dev->bst, dev_priv->gtt.mappable_base,
 241 i915_gem_obj_ggtt_offset(fbdev->fb->obj) + offset,
 242 prot, BUS_SPACE_MAP_PREFETCHABLE);
442} 243}

File Added: src/sys/external/bsd/drm2/include/drm/drmfb.h
/*	$NetBSD: drmfb.h,v 1.1 2015/03/05 17:50:41 riastradh Exp $	*/

/*-
 * Copyright (c) 2014 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Taylor R. Campbell.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef	_DRM_DRMFB_H_
#define	_DRM_DRMFB_H_

#include <sys/device_if.h>

#include <dev/wsfb/genfbvar.h>

struct drm_fb_helper;
struct drm_fb_helper_surface_sizes;

struct drmfb_attach_args;
struct drmfb_params;
struct drmfb_softc;

struct drmfb_params {
	/*
	 * Framebuffer mmap.
	 */
	paddr_t		(*dp_mmapfb)(struct drmfb_softc *, off_t, int);

	/*
	 * Other mmap, e.g. for arbitrary PCI BARs.  Available only to
	 * users with privileges for access to unmanaged memory.
	 */
	paddr_t		(*dp_mmap)(struct drmfb_softc *, off_t, int);

	/*
	 * Ioctl handler.  Must handle:
	 *
	 * - WSDISPLAYIO_GET_BUSID
	 * - WSDISPLAYIO_GTYPE
	 *
	 * May add or override anything else.  Return EPASSTHROUGH to
	 * defer.
	 */
	int		(*dp_ioctl)(struct drmfb_softc *, unsigned long,
			    void *, int, struct lwp *);
	/* XXX Kludge!  */
	bool		(*dp_is_vga_console)(struct drm_device *);
	void		(*dp_disable_vga)(struct drm_device *);
};

struct drmfb_attach_args {
	device_t			da_dev;
	struct drm_fb_helper		*da_fb_helper;
	const struct drm_fb_helper_surface_size	*da_fb_sizes;
	void				*da_fb_vaddr;
	const struct drmfb_params	*da_params;
};

/* Treat as opaque.  Must be first member of device softc.  */
struct drmfb_softc {
	struct genfb_softc		sc_genfb; /* XXX Must be first. */
	struct drmfb_attach_args	sc_da;
};

int	drmfb_attach(struct drmfb_softc *, const struct drmfb_attach_args *);
int	drmfb_detach(struct drmfb_softc *, int);
bool	drmfb_shutdown(struct drmfb_softc *, int);

#endif	/* _DRM_DRMFB_H_ */

File Added: src/sys/external/bsd/drm2/include/drm/drmfb_pci.h
/*	$NetBSD: drmfb_pci.h,v 1.1 2015/03/05 17:50:41 riastradh Exp $	*/

/*-
 * Copyright (c) 2014 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Taylor R. Campbell.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef	_DRM_DRMFB_PCI_H_
#define	_DRM_DRMFB_PCI_H_

#include <sys/types.h>

struct drmfb_softc;
struct lwp;

paddr_t	drmfb_pci_mmap(struct drmfb_softc *, off_t, int);
int	drmfb_pci_ioctl(struct drmfb_softc *, unsigned long, void *, int,
	    struct lwp *);

#endif	/* _DRM_DRMFB_PCI_H_ */

File Added: src/sys/external/bsd/drm2/pci/drmfb_pci.c
/*	$NetBSD: drmfb_pci.c,v 1.1 2015/03/05 17:50:41 riastradh Exp $	*/

/*-
 * Copyright (c) 2014 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Taylor R. Campbell.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * drmfb_pci: drmfb hooks for PCI devices.
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: drmfb_pci.c,v 1.1 2015/03/05 17:50:41 riastradh Exp $");

#include <sys/types.h>
#include <sys/device.h>
#include <sys/errno.h>
#include <sys/systm.h>

#include <dev/pci/pciio.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/wsdisplay_pci.h>

#include <drm/drmP.h>
#include <drm/drm_fb_helper.h>

#include "drmfb.h"
#include "drmfb_pci.h"

/*
 * drmfb_pci_mmap: Implementation of drmfb_params::dp_mmap.  Don't use
 * this for dp_mmapfb -- how to get at the framebuffer is device-
 * specific.
 */
paddr_t
drmfb_pci_mmap(struct drmfb_softc *sc, off_t offset, int prot)
{
	struct drm_device *const dev = sc->sc_da.da_fb_helper->dev;
	const struct pci_attach_args *const pa = &dev->pdev->pd_pa;
	unsigned i;

	for (i = 0; PCI_BAR(i) <= PCI_MAPREG_ROM; i++) {
		pcireg_t type;
		bus_addr_t addr;
		bus_size_t size;
		int flags;

		/* Interrogate the BAR.  */
		if (!pci_mapreg_probe(pa->pa_pc, pa->pa_tag, PCI_BAR(i),
			&type))
			continue;
		if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM)
			continue;
		if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, PCI_BAR(i), type,
			&addr, &size, &flags))
			continue;

		/* Try to map it if it's in range.  */
		if ((addr <= offset) && (offset < (addr + size)))
			return bus_space_mmap(pa->pa_memt, addr,
			    (offset - addr), prot, flags);

		/* Skip a slot if this was a 64-bit BAR.  */
		if ((PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_MEM) &&
		    (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT))
			i += 1;
	}

	/* Failure!  */
	return -1;
}

/*
 * drmfb_pci_ioctl: Implementation of drmfb_params::dp_ioctl.  Provides:
 *
 * - WSDISPLAY_GET_BUSID
 * - WSDISPLAY_GTYPE
 *
 * Additionally allows access to PCI registers.
 *
 * XXX Do we need to provide access to PCI registers?  I can't find
 * anything that uses this functionality, and as is it is very
 * dangerous.
 */
int
drmfb_pci_ioctl(struct drmfb_softc *sc, unsigned long cmd, void *data,
    int flag, struct lwp *l)
{
	struct drm_device *const dev = sc->sc_da.da_fb_helper->dev;
	struct pci_attach_args *const pa = &dev->pdev->pd_pa;

	switch (cmd) {
	/* PCI config read/write passthrough.  */
	case PCI_IOC_CFGREAD:
	case PCI_IOC_CFGWRITE:
		return pci_devioctl(pa->pa_pc, pa->pa_tag, cmd, data, flag, l);

	/* PCI-specific wsdisplay ioctls.  */
	case WSDISPLAYIO_GET_BUSID:
		return wsdisplayio_busid_pci(dev->dev, pa->pa_pc, pa->pa_tag,
		    data);
	case WSDISPLAYIO_GTYPE:
		*(unsigned int *)data = WSDISPLAY_TYPE_PCIVGA;
		return 0;

	default:
		return EPASSTHROUGH;
	}
}

cvs diff -r1.4 -r1.5 src/sys/external/bsd/drm2/pci/files.drmkms_pci (expand / switch to unified diff)

--- src/sys/external/bsd/drm2/pci/files.drmkms_pci 2014/08/06 13:54:40 1.4
+++ src/sys/external/bsd/drm2/pci/files.drmkms_pci 2015/03/05 17:50:41 1.5
@@ -1,16 +1,19 @@ @@ -1,16 +1,19 @@
1# $NetBSD: files.drmkms_pci,v 1.4 2014/08/06 13:54:40 riastradh Exp $ 1# $NetBSD: files.drmkms_pci,v 1.5 2015/03/05 17:50:41 riastradh Exp $
2 2
3define drmkms_pci: drmkms 3define drmkms_pci: drmkms
4 4
5# XXX Not quite right! Should AGP stuff be kept separate? 5# XXX Not quite right! Should AGP stuff be kept separate?
6makeoptions drmkms_pci CPPFLAGS+="-DCONFIG_AGP" 6makeoptions drmkms_pci CPPFLAGS+="-DCONFIG_AGP"
7 7
8#file external/bsd/drm2/dist/drm/ati_pcigart.c drmkms_pci 8#file external/bsd/drm2/dist/drm/ati_pcigart.c drmkms_pci
9file external/bsd/drm2/dist/drm/drm_agpsupport.c drmkms_pci 9file external/bsd/drm2/dist/drm/drm_agpsupport.c drmkms_pci
10file external/bsd/drm2/pci/drm_pci.c drmkms_pci 10file external/bsd/drm2/pci/drm_pci.c drmkms_pci
11file external/bsd/drm2/pci/drm_pci_module.c drmkms_pci 11file external/bsd/drm2/pci/drm_pci_module.c drmkms_pci
12 12
 13define drmfb_pci: drmfb, drmkms_pci
 14file external/bsd/drm2/pci/drmfb_pci.c drmfb_pci
 15
13include "external/bsd/drm2/i915drm/files.i915drmkms" 16include "external/bsd/drm2/i915drm/files.i915drmkms"
14include "external/bsd/drm2/radeon/files.radeon" 17include "external/bsd/drm2/radeon/files.radeon"
15include "external/bsd/drm2/nouveau/files.nouveau" 18include "external/bsd/drm2/nouveau/files.nouveau"
16#... 19#...

cvs diff -r1.8 -r1.9 src/sys/modules/drmkms/Makefile (expand / switch to unified diff)

--- src/sys/modules/drmkms/Makefile 2015/03/05 17:42:48 1.8
+++ src/sys/modules/drmkms/Makefile 2015/03/05 17:50:41 1.9
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# $NetBSD: Makefile,v 1.8 2015/03/05 17:42:48 riastradh Exp $ 1# $NetBSD: Makefile,v 1.9 2015/03/05 17:50:41 riastradh Exp $
2 2
3.include "../Makefile.inc" 3.include "../Makefile.inc"
4.include "Makefile.inc" 4.include "Makefile.inc"
5 5
6.PATH: ${S}/external/bsd/drm2/drm 6.PATH: ${S}/external/bsd/drm2/drm
7.PATH: ${S}/external/bsd/drm2/i2c 7.PATH: ${S}/external/bsd/drm2/i2c
8.PATH: ${S}/external/bsd/drm2/pci 8.PATH: ${S}/external/bsd/drm2/pci
9.PATH: ${S}/external/bsd/drm2/dist/drm 9.PATH: ${S}/external/bsd/drm2/dist/drm
10 10
11MKLDSCRIPT=yes 11MKLDSCRIPT=yes
12KMOD= drmkms 12KMOD= drmkms
13 13
14# Upstream source files. 14# Upstream source files.
@@ -46,21 +46,22 @@ SRCS+= drm_plane_helper.c @@ -46,21 +46,22 @@ SRCS+= drm_plane_helper.c
46#SRCS+= drm_prime.c # XXX Revisit later. 46#SRCS+= drm_prime.c # XXX Revisit later.
47SRCS+= drm_probe_helper.c 47SRCS+= drm_probe_helper.c
48SRCS+= drm_rect.c 48SRCS+= drm_rect.c
49SRCS+= drm_scatter.c 49SRCS+= drm_scatter.c
50SRCS+= drm_stub.c 50SRCS+= drm_stub.c
51SRCS+= drm_sysctl.c 51SRCS+= drm_sysctl.c
52SRCS+= drm_sysfs.c 52SRCS+= drm_sysfs.c
53SRCS+= drm_vm.c 53SRCS+= drm_vm.c
54SRCS+= drm_vma_manager.c 54SRCS+= drm_vma_manager.c
55 55
56# NetBSD additions. 56# NetBSD additions.
57SRCS+= drm_gem_vm.c 57SRCS+= drm_gem_vm.c
58SRCS+= drm_module.c 58SRCS+= drm_module.c
 59SRCS+= drmfb.c
59 60
60COPTS.drm_crtc.c+= -Wno-shadow 61COPTS.drm_crtc.c+= -Wno-shadow
61COPTS.drm_crtc.c+= -Wno-missing-field-initializers 62COPTS.drm_crtc.c+= -Wno-missing-field-initializers
62COPTS.drm_edid.c+= -Wno-shadow 63COPTS.drm_edid.c+= -Wno-shadow
63 64
64CPPFLAGS+= -DNACPICA=1 65CPPFLAGS+= -DNACPICA=1
65 66
66.include <bsd.kmodule.mk> 67.include <bsd.kmodule.mk>

cvs diff -r1.4 -r1.5 src/sys/modules/drmkms_pci/Makefile (expand / switch to unified diff)

--- src/sys/modules/drmkms_pci/Makefile 2014/11/22 19:18:08 1.4
+++ src/sys/modules/drmkms_pci/Makefile 2015/03/05 17:50:41 1.5
@@ -1,16 +1,18 @@ @@ -1,16 +1,18 @@
1# $NetBSD: Makefile,v 1.4 2014/11/22 19:18:08 riastradh Exp $ 1# $NetBSD: Makefile,v 1.5 2015/03/05 17:50:41 riastradh Exp $
2 2
3.include "../Makefile.inc" 3.include "../Makefile.inc"
4.include "../drmkms/Makefile.inc" 4.include "../drmkms/Makefile.inc"
5 5
6.PATH: ${S}/external/bsd/drm2/pci 6.PATH: ${S}/external/bsd/drm2/pci
7.PATH: ${S}/external/bsd/drm2/dist/drm 7.PATH: ${S}/external/bsd/drm2/dist/drm
8 8
9KMOD= drmkms_pci 9KMOD= drmkms_pci
10 10
11#SRCS+= ati_pcigart.c # XXX Restore for ATI support. 11#SRCS+= ati_pcigart.c # XXX Restore for ATI support.
12SRCS+= drm_agpsupport.c 12SRCS+= drm_agpsupport.c
13SRCS+= drm_pci.c 13SRCS+= drm_pci.c
14SRCS+= drm_pci_module.c 14SRCS+= drm_pci_module.c
15 15
 16SRCS+= drmfb_pci.c
 17
16.include <bsd.kmodule.mk> 18.include <bsd.kmodule.mk>