diff --git a/sys/external/bsd/drm2/drm/drmfb.c b/sys/external/bsd/drm2/drm/drmfb.c new file mode 100644 index 000000000000..c5f9a93dd3bc --- /dev/null +++ b/sys/external/bsd/drm2/drm/drmfb.c @@ -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 +__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 +#include +#include +#include +#include + +#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 +#include +#include +#include +#endif + +#include + +#include +#include +#include + +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; +} diff --git a/sys/external/bsd/drm2/drm/files.drmkms b/sys/external/bsd/drm2/drm/files.drmkms index 74c381b23e83..b423778e1794 100644 --- a/sys/external/bsd/drm2/drm/files.drmkms +++ b/sys/external/bsd/drm2/drm/files.drmkms @@ -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" diff --git a/sys/external/bsd/drm2/i915drm/files.i915drmkms b/sys/external/bsd/drm2/i915drm/files.i915drmkms index 149ec6af2b3e..3078905a7c19 100644 --- a/sys/external/bsd/drm2/i915drm/files.i915drmkms +++ b/sys/external/bsd/drm2/i915drm/files.i915drmkms @@ -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" diff --git a/sys/external/bsd/drm2/i915drm/intelfb.c b/sys/external/bsd/drm2/i915drm/intelfb.c index 1cd17e988363..b94b7a59e2e8 100644 --- a/sys/external/bsd/drm2/i915drm/intelfb.c +++ b/sys/external/bsd/drm2/i915drm/intelfb.c @@ -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 -__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 #include -#include -#include -#include - -#include -#include - #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 -#include +#include +#include #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); } diff --git a/sys/external/bsd/drm2/include/drm/drmfb.h b/sys/external/bsd/drm2/include/drm/drmfb.h new file mode 100644 index 000000000000..74477ae87675 --- /dev/null +++ b/sys/external/bsd/drm2/include/drm/drmfb.h @@ -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 + +#include + +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_ */ diff --git a/sys/external/bsd/drm2/include/drm/drmfb_pci.h b/sys/external/bsd/drm2/include/drm/drmfb_pci.h new file mode 100644 index 000000000000..b32e8d083b8e --- /dev/null +++ b/sys/external/bsd/drm2/include/drm/drmfb_pci.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 + +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_ */ diff --git a/sys/external/bsd/drm2/pci/drmfb_pci.c b/sys/external/bsd/drm2/pci/drmfb_pci.c new file mode 100644 index 000000000000..6ceaf5f0bb06 --- /dev/null +++ b/sys/external/bsd/drm2/pci/drmfb_pci.c @@ -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 +__KERNEL_RCSID(0, "$NetBSD: drmfb_pci.c,v 1.1 2015/03/05 17:50:41 riastradh Exp $"); + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#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; + } +} diff --git a/sys/external/bsd/drm2/pci/files.drmkms_pci b/sys/external/bsd/drm2/pci/files.drmkms_pci index 62c309d09d3f..cae9aa8d7bf4 100644 --- a/sys/external/bsd/drm2/pci/files.drmkms_pci +++ b/sys/external/bsd/drm2/pci/files.drmkms_pci @@ -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" diff --git a/sys/modules/drmkms/Makefile b/sys/modules/drmkms/Makefile index bff5c35d7fb7..1c91fa275662 100644 --- a/sys/modules/drmkms/Makefile +++ b/sys/modules/drmkms/Makefile @@ -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 diff --git a/sys/modules/drmkms_pci/Makefile b/sys/modules/drmkms_pci/Makefile index 0a00073bede1..0bb3057de397 100644 --- a/sys/modules/drmkms_pci/Makefile +++ b/sys/modules/drmkms_pci/Makefile @@ -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