Module Name:    src
Committed By:   riastradh
Date:           Fri Jul 25 12:35:03 UTC 2014

Modified Files:
        src/sys/arch/amd64/conf: DRMKMS
        src/sys/arch/i386/conf: DRMKMS
        src/sys/external/bsd/drm2/radeon: files.radeon radeon_pci.c
Added Files:
        src/sys/external/bsd/drm2/radeon: radeon_task.h radeondrmkmsfb.c
            radeondrmkmsfb.h

Log Message:
Hook up radeondrmkmsfb code.

Builds, not testable yet.


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/amd64/conf/DRMKMS
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/i386/conf/DRMKMS
cvs rdiff -u -r1.2 -r1.3 src/sys/external/bsd/drm2/radeon/files.radeon
cvs rdiff -u -r1.1 -r1.2 src/sys/external/bsd/drm2/radeon/radeon_pci.c
cvs rdiff -u -r0 -r1.1 src/sys/external/bsd/drm2/radeon/radeon_task.h \
    src/sys/external/bsd/drm2/radeon/radeondrmkmsfb.c \
    src/sys/external/bsd/drm2/radeon/radeondrmkmsfb.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/amd64/conf/DRMKMS
diff -u src/sys/arch/amd64/conf/DRMKMS:1.5 src/sys/arch/amd64/conf/DRMKMS:1.6
--- src/sys/arch/amd64/conf/DRMKMS:1.5	Thu Jul 24 21:18:40 2014
+++ src/sys/arch/amd64/conf/DRMKMS	Fri Jul 25 12:35:03 2014
@@ -2,11 +2,19 @@ include "arch/amd64/conf/NO_DRM"
 
 i915drmkms* 	at pci? dev ? function ?
 intelfb*	at intelfbbus?
+
+radeondrmkms*	at pci? dev ? function ?
+radeondrmkmsfb* at radeonfbbus?
+
 #nouveau*	at pci? dev ? function ?
-#radeondrmkms*	at pci? dev ? function ?
+#nouveaufb*	at nouveaufbbus
 
 no options 	DIAGNOSTIC
 options 	DIAGNOSTIC	# expensive kernel consistency check
 options 	DEBUG		# expensive debugging checks/support
 options 	LOCKDEBUG	# debug locks
 makeoptions 	DEBUG="-g"	# compile full symbol table
+
+#options 	ACPIVERBOSE	# verbose ACPI device autoconfig messages
+options 	PCIVERBOSE	# verbose PCI device autoconfig messages
+options 	USBVERBOSE	# verbose USB device autoconfig messages

Index: src/sys/arch/i386/conf/DRMKMS
diff -u src/sys/arch/i386/conf/DRMKMS:1.3 src/sys/arch/i386/conf/DRMKMS:1.4
--- src/sys/arch/i386/conf/DRMKMS:1.3	Fri Jul 25 11:51:21 2014
+++ src/sys/arch/i386/conf/DRMKMS	Fri Jul 25 12:35:03 2014
@@ -3,6 +3,12 @@ include "arch/i386/conf/NO_DRM"
 i915drmkms* 	at pci? dev ? function ?
 intelfb* 	at intelfbbus?
 
+radeondrmkms* 	at pci? dev ? function ?
+radeondrmkmsfb* at radeonfbbus?
+
+#nouveau*	at pci? dev ? function ?
+#nouveaufb*	at nouveaufbbus
+
 no options 	DIAGNOSTIC
 options 	DIAGNOSTIC	# expensive kernel consistency check
 options 	DEBUG		# expensive debugging checks/support

Index: src/sys/external/bsd/drm2/radeon/files.radeon
diff -u src/sys/external/bsd/drm2/radeon/files.radeon:1.2 src/sys/external/bsd/drm2/radeon/files.radeon:1.3
--- src/sys/external/bsd/drm2/radeon/files.radeon:1.2	Thu Jul 17 14:05:12 2014
+++ src/sys/external/bsd/drm2/radeon/files.radeon	Fri Jul 25 12:35:03 2014
@@ -1,10 +1,16 @@
-#	$NetBSD: files.radeon,v 1.2 2014/07/17 14:05:12 riastradh Exp $
+#	$NetBSD: files.radeon,v 1.3 2014/07/25 12:35:03 riastradh Exp $
 
-device	radeondrmkms: drmkms, drmkms_pci, drmkms_ttm, genfb, wsemuldisplaydev
+define	radeonfbbus	{ }
+device	radeondrmkms: drmkms, drmkms_pci, drmkms_ttm, radeonfbbus
 attach	radeondrmkms at pci
 
+# XXX Rename this to radeonfb when the legacy radeonfb(4) is gone.
+device	radeondrmkmsfb: radeonfbbus, genfb, wsemuldisplaydev
+attach	radeondrmkmsfb at radeonfbbus
+
 makeoptions	radeondrmkms	CPPFLAGS+="-I$S/external/bsd/drm2/dist/drm/radeon"
 makeoptions	radeondrmkms	CPPFLAGS+="-I$S/external/bsd/drm2/include/radeon"
+makeoptions	radeondrmkms	CPPFLAGS+="-I$S/external/bsd/drm2/radeon"
 
 makeoptions	radeondrmkms	"CWARNFLAGS.atombios_encoders.c"+="-Wno-missing-prototypes"
 makeoptions	radeondrmkms	"CWARNFLAGS.atombios_i2c.c"+="-Wno-missing-prototypes"
@@ -154,3 +160,5 @@ file	external/bsd/drm2/dist/drm/radeon/v
 
 file	external/bsd/drm2/radeon/radeon_module.c		radeondrmkms
 file	external/bsd/drm2/radeon/radeon_pci.c			radeondrmkms
+
+file	external/bsd/drm2/radeon/radeondrmkmsfb.c		radeondrmkmsfb

Index: src/sys/external/bsd/drm2/radeon/radeon_pci.c
diff -u src/sys/external/bsd/drm2/radeon/radeon_pci.c:1.1 src/sys/external/bsd/drm2/radeon/radeon_pci.c:1.2
--- src/sys/external/bsd/drm2/radeon/radeon_pci.c:1.1	Wed Jul 16 20:59:58 2014
+++ src/sys/external/bsd/drm2/radeon/radeon_pci.c	Fri Jul 25 12:35:03 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: radeon_pci.c,v 1.1 2014/07/16 20:59:58 riastradh Exp $	*/
+/*	$NetBSD: radeon_pci.c,v 1.2 2014/07/25 12:35:03 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: radeon_pci.c,v 1.1 2014/07/16 20:59:58 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: radeon_pci.c,v 1.2 2014/07/25 12:35:03 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "vga.h"
@@ -65,25 +65,31 @@ __KERNEL_RCSID(0, "$NetBSD: radeon_pci.c
 
 #include <radeon.h>
 #include "radeon_drv.h"
+#include "radeon_task.h"
 
-struct radeon_genfb_work;
-SIMPLEQ_HEAD(radeon_genfb_work_head, radeon_genfb_work);
+SIMPLEQ_HEAD(radeon_task_head, radeon_task);
 
 struct radeon_softc {
 	device_t			sc_dev;
-	struct workqueue		*sc_genfb_wq;
-	struct radeon_genfb_work_head	sc_genfb_work;
+	enum {
+		RADEON_TASK_ATTACH,
+		RADEON_TASK_WORKQUEUE,
+	}				sc_task_state;
+	union {
+		struct workqueue		*workqueue;
+		struct radeon_task_head		attach;
+	}				sc_task_u;
 	struct drm_device		*sc_drm_dev;
 	struct pci_dev			sc_pci_dev;
 };
 
-struct radeon_genfb_work {
-	struct drm_fb_helper	*rgw_fb_helper;
-	union {
-		SIMPLEQ_ENTRY(radeon_genfb_work)	queue;
-		struct work				work;
-	}			rgw_u;
-};
+struct radeon_device *
+radeon_device_private(device_t self)
+{
+	struct radeon_softc *const sc = device_private(self);
+
+	return sc->sc_drm_dev->dev_private;
+}
 
 static bool	radeon_pci_lookup(const struct pci_attach_args *,
 		    unsigned long *);
@@ -92,12 +98,7 @@ static int	radeon_match(device_t, cfdata
 static void	radeon_attach(device_t, device_t, void *);
 static int	radeon_detach(device_t, int);
 
-static void	radeon_genfb_defer_set_config(struct drm_fb_helper *);
-static void	radeon_genfb_set_config_work(struct work *, void *);
-static void	radeon_genfb_set_config(struct radeon_genfb_work *);
-static int	radeon_genfb_ioctl(void *, void *, unsigned long, void *,
-		    int, struct lwp *);
-static paddr_t	radeon_genfb_mmap(void *, void *, off_t, int);
+static void	radeon_task_work(struct work *, void *);
 
 CFATTACH_DECL_NEW(radeondrmkms, sizeof(struct radeon_softc),
     radeon_match, radeon_attach, radeon_detach, NULL);
@@ -162,7 +163,8 @@ radeon_attach(device_t parent, device_t 
 
 	pci_aprint_devinfo(pa, NULL);
 
-	SIMPLEQ_INIT(&sc->sc_genfb_work);
+	sc->sc_task_state = RADEON_TASK_ATTACH;
+	SIMPLEQ_INIT(&sc->sc_task_u.attach);
 
 	/* XXX errno Linux->NetBSD */
 	error = -drm_pci_attach(self, pa, &sc->sc_pci_dev, radeon_drm_driver,
@@ -172,20 +174,21 @@ radeon_attach(device_t parent, device_t 
 		return;
 	}
 
-	while (!SIMPLEQ_EMPTY(&sc->sc_genfb_work)) {
-		struct radeon_genfb_work *const work =
-		    SIMPLEQ_FIRST(&sc->sc_genfb_work);
+	while (!SIMPLEQ_EMPTY(&sc->sc_task_u.attach)) {
+		struct radeon_task *const task =
+		    SIMPLEQ_FIRST(&sc->sc_task_u.attach);
 
-		SIMPLEQ_REMOVE_HEAD(&sc->sc_genfb_work, rgw_u.queue);
-		radeon_genfb_set_config(work);
+		SIMPLEQ_REMOVE_HEAD(&sc->sc_task_u.attach, rt_u.queue);
+		(*task->rt_fn)(task);
 	}
 
-	error = workqueue_create(&sc->sc_genfb_wq, "radeonfb",
-	    &radeon_genfb_set_config_work, NULL, PRI_NONE, IPL_NONE,
-	    WQ_MPSAFE);
+	sc->sc_task_state = RADEON_TASK_WORKQUEUE;
+	error = workqueue_create(&sc->sc_task_u.workqueue, "radeonfb",
+	    &radeon_task_work, NULL, PRI_NONE, IPL_NONE, WQ_MPSAFE);
 	if (error) {
 		aprint_error_dev(self, "unable to create workqueue: %d\n",
 		    error);
+		sc->sc_task_u.workqueue = NULL;
 		return;
 	}
 }
@@ -201,228 +204,53 @@ radeon_detach(device_t self, int flags)
 	if (error)
 		return error;
 
-	if (sc->sc_genfb_wq == NULL)
+	if (sc->sc_task_state == RADEON_TASK_ATTACH)
 		return 0;
-	workqueue_destroy(sc->sc_genfb_wq);
+	if (sc->sc_task_u.workqueue != NULL) {
+		workqueue_destroy(sc->sc_task_u.workqueue);
+		sc->sc_task_u.workqueue = NULL;
+	}
 
 	if (sc->sc_drm_dev == NULL)
 		return 0;
 	/* XXX errno Linux->NetBSD */
 	error = -drm_pci_detach(sc->sc_drm_dev, flags);
 	if (error)
+		/* XXX Kinda too late to fail now...  */
 		return error;
+	sc->sc_drm_dev = NULL;
 
 	return 0;
 }
 
-int
-radeon_genfb_attach(struct drm_device *dev, struct drm_fb_helper *helper,
-    const struct drm_fb_helper_surface_size *sizes, struct radeon_bo *rbo)
-{
-	struct radeon_softc *const sc = container_of(dev->pdev,
-	    struct radeon_softc, sc_pci_dev);
-	static const struct genfb_ops zero_genfb_ops;
-	struct genfb_ops genfb_ops = zero_genfb_ops;
-	const prop_dictionary_t dict = device_properties(sc->sc_dev);
-	enum { CONS_VGA, CONS_GENFB, CONS_NONE } what_was_cons;
-	int ret;
-
-#if NVGA > 0
-	if (vga_is_console(dev->pdev->pd_pa.pa_iot, -1) ||
-	    vga_is_console(dev->pdev->pd_pa.pa_iot, -1)) {
-		what_was_cons = CONS_VGA;
-		prop_dictionary_set_bool(dict, "is_console", true);
-		/*
-		 * There is a window from here until genfb attaches in
-		 * which kernel messages will go into a black hole,
-		 * until genfb replays the console.  Whattakludge.
-		 *
-		 * wsdisplay_cndetach must come first, to clear cn_tab,
-		 * so that nothing will use it; then vga_cndetach
-		 * unmaps the bus space that it would have used.
-		 */
-		wsdisplay_cndetach();
-		vga_cndetach();
-	} 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);
-	}
-
-	/* XXX Ugh...  Pass these parameters some other way!  */
-	prop_dictionary_set_uint32(dict, "width", sizes->fb_width);
-	prop_dictionary_set_uint32(dict, "height", sizes->fb_height);
-	prop_dictionary_set_uint8(dict, "depth", sizes->surface_bpp);
-	prop_dictionary_set_uint16(dict, "linebytes",
-	    roundup2((sizes->fb_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)rbo->kptr);
-
-	helper->genfb.sc_dev = sc->sc_dev;
-	genfb_init(&helper->genfb);
-	genfb_ops.genfb_ioctl = radeon_genfb_ioctl;
-	genfb_ops.genfb_mmap = radeon_genfb_mmap;
-
-	/* XXX errno NetBSD->Linux */
-	ret = -genfb_attach(&helper->genfb, &genfb_ops);
-	if (ret) {
-		DRM_ERROR("failed to attach genfb: %d\n", ret);
-		switch (what_was_cons) { /* XXX Restore console...  */
-		case CONS_VGA: break;
-		case CONS_GENFB: break;
-		case CONS_NONE: break;
-		default: break;
-		}
-		return ret;
-	}
-
-	radeon_genfb_defer_set_config(helper);
-
-	return 0;
-}
-
-static void
-radeon_genfb_defer_set_config(struct drm_fb_helper *helper)
-{
-	struct drm_device *const dev = helper->dev;
-	struct radeon_softc *const sc = container_of(dev->pdev,
-	    struct radeon_softc, sc_pci_dev);
-	struct radeon_genfb_work *work;
-
-	/* Really shouldn't sleep here...  */
-	work = kmem_alloc(sizeof(*work), KM_SLEEP);
-	work->rgw_fb_helper = helper;
-
-	if (sc->sc_genfb_wq == NULL) /* during attachment */
-		SIMPLEQ_INSERT_TAIL(&sc->sc_genfb_work, work, rgw_u.queue);
-	else
-		workqueue_enqueue(sc->sc_genfb_wq, &work->rgw_u.work, NULL);
-}
-
 static void
-radeon_genfb_set_config_work(struct work *work, void *cookie __unused)
+radeon_task_work(struct work *work, void *cookie __unused)
 {
+	struct radeon_task *const task = container_of(work, struct radeon_task,
+	    rt_u.work);
 
-	radeon_genfb_set_config(container_of(work, struct radeon_genfb_work,
-		rgw_u.work));
+	(*task->rt_fn)(task);
 }
 
-static void
-radeon_genfb_set_config(struct radeon_genfb_work *work)
+int
+radeon_task_schedule(device_t self, struct radeon_task *task)
 {
+	struct radeon_softc *const sc = device_private(self);
 
-	drm_fb_helper_set_config(work->rgw_fb_helper);
-	kmem_free(work, sizeof(*work));
-}
-
-static int
-radeon_genfb_ioctl(void *v, void *vs, unsigned long cmd, void *data, int flag,
-    struct lwp *l)
-{
-	struct genfb_softc *const genfb = v;
-	struct drm_fb_helper *const helper = container_of(genfb,
-	    struct drm_fb_helper, genfb);
-	struct drm_device *const dev = helper->dev;
-	const struct pci_attach_args *const pa = &dev->pdev->pd_pa;
-
-	switch (cmd) {
-	case WSDISPLAYIO_GTYPE:
-		*(unsigned int *)data = WSDISPLAY_TYPE_PCIVGA;
+	switch (sc->sc_task_state) {
+	case RADEON_TASK_ATTACH:
+		SIMPLEQ_INSERT_TAIL(&sc->sc_task_u.attach, task, rt_u.queue);
+		return 0;
+	case RADEON_TASK_WORKQUEUE:
+		if (sc->sc_task_u.workqueue == NULL) {
+			aprint_error_dev(self, "unable to schedule task\n");
+			return EIO;
+		}
+		workqueue_enqueue(sc->sc_task_u.workqueue, &task->rt_u.work,
+		    NULL);
 		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(genfb->sc_dev,
-		    pa->pa_pc, pa->pa_tag, data);
-
 	default:
-		return EPASSTHROUGH;
-	}
-}
-
-static paddr_t
-radeon_genfb_mmap(void *v, void *vs, off_t offset, int prot)
-{
-	struct genfb_softc *const genfb = v;
-	struct drm_fb_helper *const helper = container_of(genfb,
-	    struct drm_fb_helper, genfb);
-	struct drm_framebuffer *const fb = helper->fb;
-	struct radeon_framebuffer *const rfb = container_of(fb,
-	    struct radeon_framebuffer, base);
-	struct drm_gem_object *const gobj = rfb->obj;
-	struct radeon_bo *const rbo = gem_to_radeon_bo(gobj);
-	struct drm_device *const dev = helper->dev;
-	const struct pci_attach_args *const pa = &dev->pdev->pd_pa;
-	unsigned int i;
-
-	if (offset < 0)
-		return -1;
-
-	/* Treat low memory as the framebuffer itself.  */
-	if (offset < genfb->sc_fbsize) {
-		const unsigned num_pages __diagused = rbo->tbo.num_pages;
-		bus_addr_t addr;
-		int flags = 0;
-
-		KASSERT(genfb->sc_fbsize == (num_pages << PAGE_SHIFT));
-		KASSERT(num_pages == rbo->tbo.ttm->num_pages);
-		addr = page_to_phys(rbo->tbo.ttm->pages[offset >> PAGE_SHIFT]);
-		/* XXX CACHEABLE?  PREFETCHABLE?  WC?  WB?  */
-		if (ISSET(rbo->tbo.mem.placement, TTM_PL_FLAG_CACHED))
-			flags |= BUS_SPACE_MAP_PREFETCHABLE;
-		/*
-		 * XXX Urk.  We assume bus_space_mmap can cope with
-		 * normal system RAM addresses.
-		 */
-		return bus_space_mmap(rbo->tbo.bdev->memt, addr, 0, prot,
-		    flags);
+		panic("radeon in invalid task state: %d\n",
+		    (int)sc->sc_task_state);
 	}
-
-	/* 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;
 }

Added files:

Index: src/sys/external/bsd/drm2/radeon/radeon_task.h
diff -u /dev/null src/sys/external/bsd/drm2/radeon/radeon_task.h:1.1
--- /dev/null	Fri Jul 25 12:35:03 2014
+++ src/sys/external/bsd/drm2/radeon/radeon_task.h	Fri Jul 25 12:35:03 2014
@@ -0,0 +1,55 @@
+/*	$NetBSD: radeon_task.h,v 1.1 2014/07/25 12:35:03 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	_RADEON_RADEON_TASK_H_
+#define	_RADEON_RADEON_TASK_H_
+
+#include <sys/queue.h>
+#include <sys/workqueue.h>
+
+struct radeon_task {
+	union {
+		SIMPLEQ_ENTRY(radeon_task)	queue;
+		struct work			work;
+	}			rt_u;
+	void			(*rt_fn)(struct radeon_task *);
+};
+
+static inline void
+radeon_task_init(struct radeon_task *task, void (*fn)(struct radeon_task *))
+{
+
+	task->rt_fn = fn;
+}
+
+int	radeon_task_schedule(device_t, struct radeon_task *);
+
+#endif	/* _RADEON_RADEON_TASK_H_ */
Index: src/sys/external/bsd/drm2/radeon/radeondrmkmsfb.c
diff -u /dev/null src/sys/external/bsd/drm2/radeon/radeondrmkmsfb.c:1.1
--- /dev/null	Fri Jul 25 12:35:03 2014
+++ src/sys/external/bsd/drm2/radeon/radeondrmkmsfb.c	Fri Jul 25 12:35:03 2014
@@ -0,0 +1,347 @@
+/*	$NetBSD: radeondrmkmsfb.c,v 1.1 2014/07/25 12:35:03 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.
+ */
+
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: radeondrmkmsfb.c,v 1.1 2014/07/25 12:35:03 riastradh Exp $");
+
+#ifdef _KERNEL_OPT
+#include "vga.h"
+#endif
+
+#include <sys/types.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
+ * 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 <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+
+#include <radeon.h>
+#include "radeon_drv.h"
+#include "radeon_task.h"
+#include "radeondrmkmsfb.h"
+
+struct radeonfb_softc {
+	/* XXX genfb requires the genfb_softc to be first.  */
+	struct genfb_softc		sc_genfb;
+	device_t			sc_dev;
+	struct radeonfb_attach_args	sc_rfa;
+	struct radeon_task		sc_setconfig_task;
+	bool				sc_scheduled:1;
+	bool				sc_attached:1;
+};
+
+static int	radeonfb_match(device_t, cfdata_t, void *);
+static void	radeonfb_attach(device_t, device_t, void *);
+static int	radeonfb_detach(device_t, int);
+
+static void	radeonfb_setconfig_task(struct radeon_task *);
+
+static int	radeonfb_genfb_ioctl(void *, void *, unsigned long, void *,
+		    int, struct lwp *);
+static paddr_t	radeonfb_genfb_mmap(void *, void *, off_t, int);
+static int	radeonfb_genfb_enable_polling(void *);
+static int	radeonfb_genfb_disable_polling(void *);
+
+CFATTACH_DECL_NEW(radeondrmkmsfb, sizeof(struct radeonfb_softc),
+    radeonfb_match, radeonfb_attach, radeonfb_detach, NULL);
+
+static int
+radeonfb_match(device_t parent, cfdata_t match, void *aux)
+{
+
+	return 1;
+}
+
+static void
+radeonfb_attach(device_t parent, device_t self, void *aux)
+{
+	struct radeonfb_softc *const sc = device_private(self);
+	const struct radeonfb_attach_args *const rfa = aux;
+	int error;
+
+	sc->sc_dev = self;
+	sc->sc_rfa = *rfa;
+	sc->sc_scheduled = false;
+	sc->sc_attached = false;
+
+	radeon_task_init(&sc->sc_setconfig_task, &radeonfb_setconfig_task);
+	error = radeon_task_schedule(parent, &sc->sc_setconfig_task);
+	if (error) {
+		aprint_error_dev(self, "failed to schedule mode set: %d\n",
+		    error);
+		goto fail0;
+	}
+	sc->sc_scheduled = true;
+
+	/* Success!  */
+	return;
+
+fail0:	return;
+}
+
+static int
+radeonfb_detach(device_t self, int flags)
+{
+	struct radeonfb_softc *const sc = device_private(self);
+
+	if (sc->sc_scheduled)
+		return EBUSY;
+
+	if (sc->sc_attached) {
+		/* XXX genfb detach?  Help?  */
+		sc->sc_attached = false;
+	}
+
+	return 0;
+}
+
+static void
+radeonfb_setconfig_task(struct radeon_task *task)
+{
+	struct radeonfb_softc *const sc = container_of(task,
+	    struct radeonfb_softc, sc_setconfig_task);
+	const prop_dictionary_t dict = device_properties(sc->sc_dev);
+	const struct radeonfb_attach_args *const rfa = &sc->sc_rfa;
+	const struct drm_fb_helper_surface_size *const sizes =
+	    &rfa->rfa_fb_sizes;
+	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;
+	int error;
+
+	KASSERT(sc->sc_scheduled);
+
+	/* XXX Ugh...  Pass these parameters some other way!  */
+	prop_dictionary_set_uint32(dict, "width", sizes->fb_width);
+	prop_dictionary_set_uint32(dict, "height", sizes->fb_height);
+	prop_dictionary_set_uint8(dict, "depth", sizes->surface_bpp);
+	prop_dictionary_set_uint16(dict, "linebytes",
+	    roundup2((sizes->fb_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)rfa->rfa_fb_ptr);
+
+	/* XXX Whattakludge!  */
+#if NVGA > 0
+	if (vga_is_console(rfa->rfa_fb_helper->dev->pdev->pd_pa.pa_iot, -1)) {
+		what_was_cons = CONS_VGA;
+		prop_dictionary_set_bool(dict, "is_console", true);
+		vga_cndetach();
+	} 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 = radeonfb_genfb_ioctl;
+	genfb_ops.genfb_mmap = radeonfb_genfb_mmap;
+	genfb_ops.genfb_enable_polling = radeonfb_genfb_enable_polling;
+	genfb_ops.genfb_disable_polling = radeonfb_genfb_disable_polling;
+
+	error = genfb_attach(&sc->sc_genfb, &genfb_ops);
+	if (error) {
+		aprint_error_dev(sc->sc_dev, "failed to attach genfb: %d\n",
+		    error);
+		goto fail0;
+	}
+	sc->sc_attached = true;
+
+	drm_fb_helper_set_config(sc->sc_rfa.rfa_fb_helper);
+
+	/* 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
+radeonfb_genfb_ioctl(void *v, void *vs, unsigned long cmd, void *data, int flag,
+    struct lwp *l)
+{
+	struct genfb_softc *const genfb = v;
+	struct radeonfb_softc *const sc = container_of(genfb,
+	    struct radeonfb_softc, sc_genfb);
+	struct drm_device *const dev = sc->sc_rfa.rfa_fb_helper->dev;
+	const struct pci_attach_args *const pa = &dev->pdev->pd_pa;
+
+	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);
+
+	default:
+		return EPASSTHROUGH;
+	}
+}
+
+static paddr_t
+radeonfb_genfb_mmap(void *v, void *vs, off_t offset, int prot)
+{
+	struct genfb_softc *const genfb = v;
+	struct radeonfb_softc *const sc = container_of(genfb,
+	    struct radeonfb_softc, sc_genfb);
+	struct drm_fb_helper *const helper = sc->sc_rfa.rfa_fb_helper;
+	struct drm_framebuffer *const fb = helper->fb;
+	struct radeon_framebuffer *const rfb = container_of(fb,
+	    struct radeon_framebuffer, base);
+	struct drm_gem_object *const gobj = rfb->obj;
+	struct radeon_bo *const rbo = gem_to_radeon_bo(gobj);
+	struct drm_device *const dev = helper->dev;
+	const struct pci_attach_args *const pa = &dev->pdev->pd_pa;
+	unsigned int i;
+
+	if (offset < 0)
+		return -1;
+
+	/* Treat low memory as the framebuffer itself.  */
+	if (offset < genfb->sc_fbsize) {
+		const unsigned num_pages __diagused = rbo->tbo.num_pages;
+		bus_addr_t addr;
+		int flags = 0;
+
+		KASSERT(genfb->sc_fbsize == (num_pages << PAGE_SHIFT));
+		KASSERT(num_pages == rbo->tbo.ttm->num_pages);
+		addr = page_to_phys(rbo->tbo.ttm->pages[offset >> PAGE_SHIFT]);
+		/* XXX CACHEABLE/  PREFETCHABLE?  WC?  WB?  */
+		if (ISSET(rbo->tbo.mem.placement, TTM_PL_FLAG_CACHED))
+			flags |= BUS_SPACE_MAP_PREFETCHABLE;
+		/*
+		 * XXX Urk.  We assume bus_space_mmap can cope with
+		 * normal system RAM addresses.
+		 */
+		return bus_space_mmap(rbo->tbo.bdev->memt, addr, 0, prot,
+		    flags);
+	}
+
+	/* 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
+radeonfb_genfb_enable_polling(void *cookie)
+{
+	struct genfb_softc *const genfb = cookie;
+	struct radeonfb_softc *const sc = container_of(genfb,
+	    struct radeonfb_softc, sc_genfb);
+
+	return drm_fb_helper_debug_enter_fb(sc->sc_rfa.rfa_fb_helper);
+}
+
+static int
+radeonfb_genfb_disable_polling(void *cookie)
+{
+	struct genfb_softc *const genfb = cookie;
+	struct radeonfb_softc *const sc = container_of(genfb,
+	    struct radeonfb_softc, sc_genfb);
+
+	return drm_fb_helper_debug_leave_fb(sc->sc_rfa.rfa_fb_helper);
+}
Index: src/sys/external/bsd/drm2/radeon/radeondrmkmsfb.h
diff -u /dev/null src/sys/external/bsd/drm2/radeon/radeondrmkmsfb.h:1.1
--- /dev/null	Fri Jul 25 12:35:03 2014
+++ src/sys/external/bsd/drm2/radeon/radeondrmkmsfb.h	Fri Jul 25 12:35:03 2014
@@ -0,0 +1,44 @@
+/*	$NetBSD: radeondrmkmsfb.h,v 1.1 2014/07/25 12:35:03 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	_RADEON_RADEONDRMKMSFB_H_
+#define	_RADEON_RADEONDRMKMSFB_H_
+
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+
+struct radeonfb_attach_args {
+	struct drm_fb_helper			*rfa_fb_helper;
+	struct drm_fb_helper_surface_size	rfa_fb_sizes;
+	void					*rfa_fb_ptr;
+};
+
+#endif	/* _RADEON_RADEONDRMKMS_H_ */

Reply via email to