Factor generic parts of intelfb out into a drmfb.
Adapting radeondrmkmsfb should not be hard. This will make nouveaufb easier too.
This commit is contained in:
parent
c48dc052b9
commit
894a903bb9
|
@ -0,0 +1,293 @@
|
|||
/* $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;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.drmkms,v 1.10 2015/03/05 17:42:48 riastradh Exp $
|
||||
# $NetBSD: files.drmkms,v 1.11 2015/03/05 17:50:41 riastradh Exp $
|
||||
|
||||
include "external/bsd/drm2/linux/files.drmkms_linux"
|
||||
|
||||
|
@ -67,4 +67,8 @@ file external/bsd/drm2/drm/drm_gem_vm.c drmkms
|
|||
file external/bsd/drm2/drm/drm_module.c drmkms
|
||||
file external/bsd/drm2/drm/drm_sysctl.c drmkms
|
||||
|
||||
# Generic, unaccelerated drm-based framebuffer.
|
||||
define drmfb: genfb
|
||||
file external/bsd/drm2/drm/drmfb.c drmfb
|
||||
|
||||
include "external/bsd/drm2/ttm/files.ttm"
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# $NetBSD: files.i915drmkms,v 1.9 2014/11/14 14:32:49 joerg Exp $
|
||||
# $NetBSD: files.i915drmkms,v 1.10 2015/03/05 17:50:41 riastradh Exp $
|
||||
|
||||
define intelfbbus { }
|
||||
device i915drmkms: drmkms, drmkms_pci, intelfbbus, agp_i810
|
||||
attach i915drmkms at pci
|
||||
|
||||
device intelfb: intelfbbus, genfb, wsemuldisplaydev
|
||||
device intelfb: intelfbbus, drmfb, drmfb_pci, wsemuldisplaydev
|
||||
attach intelfb at intelfbbus
|
||||
|
||||
makeoptions i915drmkms CPPFLAGS+="-I$S/external/bsd/drm2/dist/drm/i915"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: intelfb.c,v 1.10 2014/09/14 16:02:15 riastradh Exp $ */
|
||||
/* $NetBSD: intelfb.c,v 1.11 2015/03/05 17:50:41 riastradh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014 The NetBSD Foundation, Inc.
|
||||
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: intelfb.c,v 1.10 2014/09/14 16:02:15 riastradh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: intelfb.c,v 1.11 2015/03/05 17:50:41 riastradh Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "vga.h"
|
||||
|
@ -40,13 +40,6 @@ __KERNEL_RCSID(0, "$NetBSD: intelfb.c,v 1.10 2014/09/14 16:02:15 riastradh Exp $
|
|||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <dev/pci/pciio.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
|
||||
#include <dev/pci/wsdisplay_pci.h>
|
||||
#include <dev/wsfb/genfbvar.h>
|
||||
|
||||
#if NVGA > 0
|
||||
/*
|
||||
* XXX All we really need is vga_is_console from vgavar.h, but the
|
||||
|
@ -60,41 +53,41 @@ __KERNEL_RCSID(0, "$NetBSD: intelfb.c,v 1.10 2014/09/14 16:02:15 riastradh Exp $
|
|||
#endif
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drmfb.h>
|
||||
#include <drm/drmfb_pci.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_pci.h"
|
||||
#include "intelfb.h"
|
||||
|
||||
static int intelfb_match(device_t, cfdata_t, void *);
|
||||
static void intelfb_attach(device_t, device_t, void *);
|
||||
static int intelfb_detach(device_t, int);
|
||||
|
||||
static void intelfb_attach_task(struct i915drmkms_task *);
|
||||
|
||||
static bool intel_is_vga_console(struct drm_device *);
|
||||
static bool intelfb_shutdown(device_t, int);
|
||||
|
||||
static paddr_t intelfb_drmfb_mmapfb(struct drmfb_softc *, off_t, int);
|
||||
|
||||
struct intelfb_softc {
|
||||
/* XXX genfb requires the genfb_softc to be first. */
|
||||
struct genfb_softc sc_genfb;
|
||||
struct drmfb_softc sc_drmfb; /* XXX Must be first. */
|
||||
device_t sc_dev;
|
||||
struct intelfb_attach_args sc_ifa;
|
||||
bus_space_handle_t sc_fb_bsh;
|
||||
struct i915drmkms_task sc_setconfig_task;
|
||||
struct i915drmkms_task sc_attach_task;
|
||||
bool sc_mapped:1;
|
||||
bool sc_scheduled:1;
|
||||
bool sc_attached:1;
|
||||
};
|
||||
|
||||
static int intelfb_match(device_t, cfdata_t, void *);
|
||||
static void intelfb_attach(device_t, device_t, void *);
|
||||
static int intelfb_detach(device_t, int);
|
||||
|
||||
static void intelfb_setconfig_task(struct i915drmkms_task *);
|
||||
|
||||
static int intelfb_genfb_dpms(struct drm_device *, int);
|
||||
static int intelfb_genfb_ioctl(void *, void *, unsigned long, void *,
|
||||
int, struct lwp *);
|
||||
static paddr_t intelfb_genfb_mmap(void *, void *, off_t, int);
|
||||
static int intelfb_genfb_enable_polling(void *);
|
||||
static int intelfb_genfb_disable_polling(void *);
|
||||
static bool intelfb_genfb_shutdown(device_t, int);
|
||||
static bool intelfb_genfb_setmode(struct genfb_softc *, int);
|
||||
|
||||
static const struct genfb_mode_callback intelfb_genfb_mode_callback = {
|
||||
.gmc_setmode = intelfb_genfb_setmode,
|
||||
static const struct drmfb_params intelfb_drmfb_params = {
|
||||
.dp_mmapfb = intelfb_drmfb_mmapfb,
|
||||
.dp_mmap = drmfb_pci_mmap,
|
||||
.dp_ioctl = drmfb_pci_ioctl,
|
||||
.dp_is_vga_console = intel_is_vga_console,
|
||||
.dp_disable_vga = i915_disable_vga,
|
||||
};
|
||||
|
||||
CFATTACH_DECL_NEW(intelfb, sizeof(struct intelfb_softc),
|
||||
|
@ -126,7 +119,7 @@ intelfb_attach(device_t parent, device_t self, void *aux)
|
|||
/* XXX Defer this too? */
|
||||
error = bus_space_map(ifa->ifa_fb_bst, ifa->ifa_fb_addr,
|
||||
ifa->ifa_fb_size,
|
||||
(BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE),
|
||||
BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_PREFETCHABLE,
|
||||
&sc->sc_fb_bsh);
|
||||
if (error) {
|
||||
aprint_error_dev(self, "unable to map framebuffer: %d\n",
|
||||
|
@ -135,8 +128,8 @@ intelfb_attach(device_t parent, device_t self, void *aux)
|
|||
}
|
||||
sc->sc_mapped = true;
|
||||
|
||||
i915drmkms_task_init(&sc->sc_setconfig_task, &intelfb_setconfig_task);
|
||||
error = i915drmkms_task_schedule(parent, &sc->sc_setconfig_task);
|
||||
i915drmkms_task_init(&sc->sc_attach_task, &intelfb_attach_task);
|
||||
error = i915drmkms_task_schedule(parent, &sc->sc_attach_task);
|
||||
if (error) {
|
||||
aprint_error_dev(self, "failed to schedule mode set: %d\n",
|
||||
error);
|
||||
|
@ -156,12 +149,20 @@ static int
|
|||
intelfb_detach(device_t self, int flags)
|
||||
{
|
||||
struct intelfb_softc *const sc = device_private(self);
|
||||
int error;
|
||||
|
||||
if (sc->sc_scheduled)
|
||||
return EBUSY;
|
||||
|
||||
if (sc->sc_attached) {
|
||||
/* XXX genfb detach? Help? */
|
||||
pmf_device_deregister(self);
|
||||
error = drmfb_detach(&sc->sc_drmfb, flags);
|
||||
if (error) {
|
||||
/* XXX Ugh. */
|
||||
(void)pmf_device_register1(self, NULL, NULL,
|
||||
&intelfb_shutdown);
|
||||
return error;
|
||||
}
|
||||
sc->sc_attached = false;
|
||||
}
|
||||
|
||||
|
@ -175,268 +176,68 @@ intelfb_detach(device_t self, int flags)
|
|||
}
|
||||
|
||||
static void
|
||||
intelfb_setconfig_task(struct i915drmkms_task *task)
|
||||
intelfb_attach_task(struct i915drmkms_task *task)
|
||||
{
|
||||
struct intelfb_softc *const sc = container_of(task,
|
||||
struct intelfb_softc, sc_setconfig_task);
|
||||
const prop_dictionary_t dict = device_properties(sc->sc_dev);
|
||||
struct intelfb_softc, sc_attach_task);
|
||||
const struct intelfb_attach_args *const ifa = &sc->sc_ifa;
|
||||
const struct drm_fb_helper_surface_size *const sizes =
|
||||
&ifa->ifa_fb_sizes;
|
||||
#if NVGA > 0 /* XXX no workie for modules */
|
||||
struct drm_device *const dev = sc->sc_ifa.ifa_drm_dev;
|
||||
#endif
|
||||
enum { CONS_VGA, CONS_GENFB, CONS_NONE } what_was_cons;
|
||||
static const struct genfb_ops zero_genfb_ops;
|
||||
struct genfb_ops genfb_ops = zero_genfb_ops;
|
||||
const struct drmfb_attach_args da = {
|
||||
.da_dev = sc->sc_dev,
|
||||
.da_fb_helper = ifa->ifa_fb_helper,
|
||||
.da_fb_sizes = &ifa->ifa_fb_sizes,
|
||||
.da_fb_vaddr = bus_space_vaddr(ifa->ifa_fb_bst, sc->sc_fb_bsh),
|
||||
.da_params = &intelfb_drmfb_params,
|
||||
};
|
||||
int error;
|
||||
|
||||
KASSERT(sc->sc_scheduled);
|
||||
|
||||
if (ifa->ifa_fb_zero)
|
||||
bus_space_set_region_1(sc->sc_ifa.ifa_fb_bst, sc->sc_fb_bsh, 0,
|
||||
0, sc->sc_ifa.ifa_fb_size);
|
||||
|
||||
/* XXX Ugh... Pass these parameters some other way! */
|
||||
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)bus_space_vaddr(sc->sc_ifa.ifa_fb_bst,
|
||||
sc->sc_fb_bsh));
|
||||
|
||||
prop_dictionary_set_uint64(dict, "mode_callback",
|
||||
(uint64_t)(uintptr_t)&intelfb_genfb_mode_callback);
|
||||
|
||||
/* XXX Whattakludge! */
|
||||
#if NVGA > 0
|
||||
if (vga_is_console(dev->pdev->pd_pa.pa_iot, -1)) {
|
||||
what_was_cons = CONS_VGA;
|
||||
prop_dictionary_set_bool(dict, "is_console", true);
|
||||
vga_cndetach();
|
||||
i915_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_dev;
|
||||
genfb_init(&sc->sc_genfb);
|
||||
genfb_ops.genfb_ioctl = intelfb_genfb_ioctl;
|
||||
genfb_ops.genfb_mmap = intelfb_genfb_mmap;
|
||||
genfb_ops.genfb_enable_polling = intelfb_genfb_enable_polling;
|
||||
genfb_ops.genfb_disable_polling = intelfb_genfb_disable_polling;
|
||||
|
||||
error = genfb_attach(&sc->sc_genfb, &genfb_ops);
|
||||
error = drmfb_attach(&sc->sc_drmfb, &da);
|
||||
if (error) {
|
||||
aprint_error_dev(sc->sc_dev, "failed to attach genfb: %d\n",
|
||||
aprint_error_dev(sc->sc_dev, "failed to attach drmfb: %d\n",
|
||||
error);
|
||||
goto fail0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pmf_device_register1(sc->sc_dev, NULL, NULL, &intelfb_shutdown))
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"failed to register shutdown handler\n");
|
||||
|
||||
sc->sc_attached = true;
|
||||
|
||||
pmf_device_register1(sc->sc_dev, NULL, NULL,
|
||||
intelfb_genfb_shutdown);
|
||||
|
||||
/* Success! */
|
||||
sc->sc_scheduled = false;
|
||||
return;
|
||||
|
||||
fail0: /* XXX Restore console... */
|
||||
switch (what_was_cons) {
|
||||
case CONS_VGA:
|
||||
break;
|
||||
case CONS_GENFB:
|
||||
break;
|
||||
case CONS_NONE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
intelfb_genfb_dpms(struct drm_device *dev, int dpms_mode)
|
||||
static bool
|
||||
intel_is_vga_console(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *const dev_priv = dev->dev_private;
|
||||
/* XXX What guarantees dev_priv->fbdev stays around? */
|
||||
struct drm_fb_helper *const fb_helper = &dev_priv->fbdev->helper;
|
||||
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;
|
||||
#if NVGA > 0
|
||||
return vga_is_console(dev->pdev->pd_pa.pa_iot, -1);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
intelfb_genfb_ioctl(void *v, void *vs, unsigned long cmd, void *data, int flag,
|
||||
struct lwp *l)
|
||||
static bool
|
||||
intelfb_shutdown(device_t self, int flags)
|
||||
{
|
||||
struct genfb_softc *const genfb = v;
|
||||
struct intelfb_softc *const sc = container_of(genfb,
|
||||
struct intelfb_softc, sc_genfb);
|
||||
struct drm_device *const dev = sc->sc_ifa.ifa_fb_helper->dev;
|
||||
const struct pci_attach_args *const pa = &dev->pdev->pd_pa;
|
||||
struct intelfb_softc *const sc = device_private(self);
|
||||
|
||||
switch (cmd) {
|
||||
case WSDISPLAYIO_GTYPE:
|
||||
*(unsigned int *)data = WSDISPLAY_TYPE_PCIVGA;
|
||||
return 0;
|
||||
|
||||
/* 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);
|
||||
|
||||
case WSDISPLAYIO_GET_BUSID:
|
||||
return wsdisplayio_busid_pci(dev->dev, pa->pa_pc, pa->pa_tag,
|
||||
data);
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
return intelfb_genfb_dpms(dev,
|
||||
on? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF);
|
||||
}
|
||||
|
||||
default:
|
||||
return EPASSTHROUGH;
|
||||
}
|
||||
return drmfb_shutdown(&sc->sc_drmfb, flags);
|
||||
}
|
||||
|
||||
static paddr_t
|
||||
intelfb_genfb_mmap(void *v, void *vs, off_t offset, int prot)
|
||||
intelfb_drmfb_mmapfb(struct drmfb_softc *drmfb, off_t offset, int prot)
|
||||
{
|
||||
struct genfb_softc *const genfb = v;
|
||||
struct intelfb_softc *const sc = container_of(genfb,
|
||||
struct intelfb_softc, sc_genfb);
|
||||
struct intelfb_softc *const sc = container_of(drmfb,
|
||||
struct intelfb_softc, sc_drmfb);
|
||||
struct drm_fb_helper *const helper = sc->sc_ifa.ifa_fb_helper;
|
||||
struct intel_fbdev *const fbdev = container_of(helper,
|
||||
struct intel_fbdev, helper);
|
||||
struct drm_device *const dev = helper->dev;
|
||||
struct drm_i915_private *const dev_priv = dev->dev_private;
|
||||
const struct pci_attach_args *const pa = &dev->pdev->pd_pa;
|
||||
unsigned int i;
|
||||
|
||||
if (offset < 0)
|
||||
return -1;
|
||||
KASSERT(0 <= offset);
|
||||
KASSERT(offset < fbdev->fb->obj->base.size);
|
||||
|
||||
/* Treat low memory as the framebuffer itself. */
|
||||
if (offset < genfb->sc_fbsize)
|
||||
return bus_space_mmap(dev->bst,
|
||||
(dev_priv->gtt.mappable_base +
|
||||
i915_gem_obj_ggtt_offset(fbdev->fb->obj)),
|
||||
offset, prot,
|
||||
(BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE));
|
||||
|
||||
/* XXX Cargo-culted from genfb_pci. */
|
||||
if (kauth_authorize_machdep(kauth_cred_get(),
|
||||
KAUTH_MACHDEP_UNMANAGEDMEM, NULL, NULL, NULL, NULL) != 0) {
|
||||
aprint_normal_dev(dev->dev, "mmap at %"PRIxMAX" rejected\n",
|
||||
(uintmax_t)offset);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int
|
||||
intelfb_genfb_enable_polling(void *cookie)
|
||||
{
|
||||
struct genfb_softc *const genfb = cookie;
|
||||
struct intelfb_softc *const sc = container_of(genfb,
|
||||
struct intelfb_softc, sc_genfb);
|
||||
|
||||
return drm_fb_helper_debug_enter_fb(sc->sc_ifa.ifa_fb_helper);
|
||||
}
|
||||
|
||||
static int
|
||||
intelfb_genfb_disable_polling(void *cookie)
|
||||
{
|
||||
struct genfb_softc *const genfb = cookie;
|
||||
struct intelfb_softc *const sc = container_of(genfb,
|
||||
struct intelfb_softc, sc_genfb);
|
||||
|
||||
return drm_fb_helper_debug_leave_fb(sc->sc_ifa.ifa_fb_helper);
|
||||
}
|
||||
|
||||
static bool
|
||||
intelfb_genfb_shutdown(device_t self, int flags)
|
||||
{
|
||||
genfb_enable_polling(self);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intelfb_genfb_setmode(struct genfb_softc *genfb, int mode)
|
||||
{
|
||||
struct intelfb_softc *sc = (struct intelfb_softc *)genfb;
|
||||
|
||||
if (mode == WSDISPLAYIO_MODE_EMUL) {
|
||||
drm_fb_helper_set_config(sc->sc_ifa.ifa_fb_helper);
|
||||
}
|
||||
|
||||
return true;
|
||||
return bus_space_mmap(dev->bst, dev_priv->gtt.mappable_base,
|
||||
i915_gem_obj_ggtt_offset(fbdev->fb->obj) + offset,
|
||||
prot, BUS_SPACE_MAP_PREFETCHABLE);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/* $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_ */
|
|
@ -0,0 +1,44 @@
|
|||
/* $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_ */
|
|
@ -0,0 +1,134 @@
|
|||
/* $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;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.drmkms_pci,v 1.4 2014/08/06 13:54:40 riastradh Exp $
|
||||
# $NetBSD: files.drmkms_pci,v 1.5 2015/03/05 17:50:41 riastradh Exp $
|
||||
|
||||
define drmkms_pci: drmkms
|
||||
|
||||
|
@ -10,6 +10,9 @@ file external/bsd/drm2/dist/drm/drm_agpsupport.c drmkms_pci
|
|||
file external/bsd/drm2/pci/drm_pci.c drmkms_pci
|
||||
file external/bsd/drm2/pci/drm_pci_module.c drmkms_pci
|
||||
|
||||
define drmfb_pci: drmfb, drmkms_pci
|
||||
file external/bsd/drm2/pci/drmfb_pci.c drmfb_pci
|
||||
|
||||
include "external/bsd/drm2/i915drm/files.i915drmkms"
|
||||
include "external/bsd/drm2/radeon/files.radeon"
|
||||
include "external/bsd/drm2/nouveau/files.nouveau"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.8 2015/03/05 17:42:48 riastradh Exp $
|
||||
# $NetBSD: Makefile,v 1.9 2015/03/05 17:50:41 riastradh Exp $
|
||||
|
||||
.include "../Makefile.inc"
|
||||
.include "Makefile.inc"
|
||||
|
@ -56,6 +56,7 @@ SRCS+= drm_vma_manager.c
|
|||
# NetBSD additions.
|
||||
SRCS+= drm_gem_vm.c
|
||||
SRCS+= drm_module.c
|
||||
SRCS+= drmfb.c
|
||||
|
||||
COPTS.drm_crtc.c+= -Wno-shadow
|
||||
COPTS.drm_crtc.c+= -Wno-missing-field-initializers
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.4 2014/11/22 19:18:08 riastradh Exp $
|
||||
# $NetBSD: Makefile,v 1.5 2015/03/05 17:50:41 riastradh Exp $
|
||||
|
||||
.include "../Makefile.inc"
|
||||
.include "../drmkms/Makefile.inc"
|
||||
|
@ -13,4 +13,6 @@ SRCS+= drm_agpsupport.c
|
|||
SRCS+= drm_pci.c
|
||||
SRCS+= drm_pci_module.c
|
||||
|
||||
SRCS+= drmfb_pci.c
|
||||
|
||||
.include <bsd.kmodule.mk>
|
||||
|
|
Loading…
Reference in New Issue