Module Name:    src
Committed By:   riastradh
Date:           Wed Jul 24 02:23:06 UTC 2013

Modified Files:
        src/sys/external/bsd/drm2/dist/include/drm [riastradh-drm2]: drmP.h
Added Files:
        src/sys/external/bsd/drm2/drm [riastradh-drm2]: drm_memory.c

Log Message:
Add local drm_memory.c to implement drm_ioremap and drm_iounmap.


To generate a diff of this commit:
cvs rdiff -u -r1.1.1.1.2.25 -r1.1.1.1.2.26 \
    src/sys/external/bsd/drm2/dist/include/drm/drmP.h
cvs rdiff -u -r0 -r1.1.2.1 src/sys/external/bsd/drm2/drm/drm_memory.c

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

Modified files:

Index: src/sys/external/bsd/drm2/dist/include/drm/drmP.h
diff -u src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.1.1.1.2.25 src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.1.1.1.2.26
--- src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.1.1.1.2.25	Wed Jul 24 02:21:22 2013
+++ src/sys/external/bsd/drm2/dist/include/drm/drmP.h	Wed Jul 24 02:23:06 2013
@@ -610,6 +610,19 @@ struct drm_sigdata {
 	struct drm_hw_lock *lock;
 };
 
+#ifdef __NetBSD__
+/*
+ * XXX Remember: memory mappings only.  bm_flags must include
+ * BUS_SPACE_MAP_LINEAR.
+ */
+struct drm_bus_map {
+	bus_addr_t		bm_base;
+	bus_size_t		bm_size;
+	bus_space_handle_t	bm_bsh;
+	int			bm_flags;
+	unsigned int		bm_mapped;
+};
+#endif
 
 /**
  * Kernel side of a mapping
@@ -622,6 +635,11 @@ struct drm_local_map {
 	void *handle;		 /**< User-space: "Handle" to pass to mmap() */
 				 /**< Kernel-space: kernel-virtual address */
 	int mtrr;		 /**< MTRR slot used */
+
+#ifdef __NetBSD__
+	bus_space_handle_t bsh;
+	struct drm_bus_map *bus_map;
+#endif
 };
 
 typedef struct drm_local_map drm_local_map_t;
@@ -1255,6 +1273,15 @@ struct drm_device {
 	struct platform_device *platformdev; /**< Platform device struture */
 	struct usb_device *usbdev;
 
+#ifdef __NetBSD__
+	bus_space_tag_t bst;
+	struct drm_bus_map *bus_maps;
+	size_t bus_nmaps;
+	/* XXX What does this have to do with AGP?  */
+	struct drm_bus_map *agp_maps;
+	size_t agp_nmaps;
+#endif
+
 	struct drm_sg_mem *sg;	/**< Scatter gather memory */
 	unsigned int num_crtcs;                  /**< Number of CRTCs on this device */
 	void *dev_private;		/**< device private data */

Added files:

Index: src/sys/external/bsd/drm2/drm/drm_memory.c
diff -u /dev/null src/sys/external/bsd/drm2/drm/drm_memory.c:1.1.2.1
--- /dev/null	Wed Jul 24 02:23:06 2013
+++ src/sys/external/bsd/drm2/drm/drm_memory.c	Wed Jul 24 02:23:06 2013
@@ -0,0 +1,218 @@
+/*	$NetBSD: drm_memory.c,v 1.1.2.1 2013/07/24 02:23:06 riastradh Exp $	*/
+
+/*-
+ * Copyright (c) 2013 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: drm_memory.c,v 1.1.2.1 2013/07/24 02:23:06 riastradh Exp $");
+
+/* XXX Cargo-culted from the old drm_memory.c.  */
+
+#ifdef _KERNEL_OPT
+#include "agp_i810.h"
+#include "genfb.h"
+#else
+#define	NAGP_I810	1	/* XXX WTF?  */
+#define	NGENFB		0	/* XXX WTF?  */
+#endif
+
+#include <sys/bus.h>
+
+#if NAGP_I810 > 0
+/* XXX include order botch -- shouldn't need to include pcivar.h */
+#include <dev/pci/pcivar.h>
+#include <dev/pci/agpvar.h>
+#endif
+
+#if NGENFB > 0
+#include <dev/wsfb/genfbvar.h>
+#endif
+
+#include <drm/drmP.h>
+
+/*
+ * XXX drm_bus_borrow is a horrible kludge!
+ */
+static bool
+drm_bus_borrow(bus_addr_t base, bus_space_handle_t *handlep)
+{
+
+#if NAGP_I810 > 0
+	if (agp_i810_borrow(base, handlep))
+		return true;
+#endif
+
+#if NGENFB > 0
+	if (genfb_borrow(base, handlep))
+		return true;
+#endif
+
+	return false;
+}
+
+void *
+drm_ioremap(struct drm_device *dev, struct drm_local_map *map)
+{
+	const bus_space_tag_t bst = dev->bst;
+	unsigned int unit;
+	int error;
+
+	/*
+	 * Search dev's bus maps for a match.
+	 */
+	for (unit = 0; unit < dev->bus_nmaps; unit++) {
+		struct drm_bus_map *const bm = &dev->bus_maps[unit];
+
+		/* Reject maps starting after the request.  */
+		if (map->offset < bm->bm_base)
+			continue;
+
+		/* Reject maps smaller than the request.  */
+		if (bm->bm_size < map->size)
+			continue;
+
+		/*
+		 * Reject maps that the request doesn't fit in.  (Make
+		 * sure to avoid integer overflow.)
+		 */
+		if ((bm->bm_size - map->size) <
+		    (map->offset - bm->bm_base))
+			continue;
+
+		/* Has it been mapped yet?  If not, map it.  */
+		if (bm->bm_mapped == 0) {
+			KASSERT(ISSET(bm->bm_flags, BUS_SPACE_MAP_LINEAR));
+			error = bus_space_map(bst, bm->bm_base,
+			    bm->bm_size, bm->bm_flags, &bm->bm_bsh);
+			if (error) {
+				if (drm_bus_borrow(map->offset, &map->bsh)) {
+					map->bus_map = NULL;
+					goto win;
+				}
+				return NULL;
+			}
+		}
+
+		/* Mark it used and make a subregion just for the request.  */
+		bm->bm_mapped++;
+		error = bus_space_subregion(bst, bm->bm_bsh,
+		    map->offset - bm->bm_base, map->size, &map->bsh);
+		if (error) {
+			/*
+			 * Back out: unmark it and, if nobody else was
+			 * using it, unmap it.
+			 */
+			if (--bm->bm_mapped == 0)
+				bus_space_unmap(bst, bm->bm_bsh,
+				    bm->bm_size);
+			return NULL;
+		}
+
+		/* Got it!  */
+		map->bus_map = bm;
+		goto win;
+	}
+
+	/*
+	 * No dice.  Try mapping it directly ourselves.
+	 *
+	 * XXX Is this sensible?  What prevents us from clobbering some
+	 * existing map?  And what does this have to do with agp?
+	 */
+	for (unit = 0; unit < dev->agp_nmaps; unit++) {
+		struct drm_bus_map *const bm = &dev->agp_maps[unit];
+
+		/* Is this one allocated? */
+		if (bm->bm_mapped > 0) {
+			/*
+			 * Make sure it has the same base.
+			 *
+			 * XXX Why must it be the same base?  Can't we
+			 * subregion here too?
+			 */
+			if (bm->bm_base != map->offset)
+				continue;
+
+			/* Make sure it's big enough.  */
+			if (bm->bm_size < map->size)
+				continue;
+
+			/* Mark it used and return it.  */
+			bm->bm_mapped++;
+
+			/* XXX size is an input/output parameter too...?  */
+			map->size = bm->bm_size;
+
+			map->bsh = bm->bm_bsh;
+			map->bus_map = bm;
+			goto win;
+		} else {
+			const int flags = BUS_SPACE_MAP_PREFETCHABLE |
+			    BUS_SPACE_MAP_LINEAR;
+
+			/* Try mapping the request.  */
+			error = bus_space_map(bst, map->offset, map->size,
+			    flags, &bm->bm_bsh);
+			if (error)
+				return NULL; /* XXX Why not continue?  */
+
+			/* Got it.  Allocate this bus map.  */
+			bm->bm_mapped++;
+			bm->bm_base = map->offset;
+			bm->bm_size = map->size;
+			bm->bm_flags = flags; /* XXX What for?  */
+
+			map->bsh = bm->bm_bsh;
+			map->bus_map = bm;
+			goto win;
+		}
+	}
+
+	return NULL;
+
+win:
+	return bus_space_vaddr(bst, map->bsh);
+}
+
+void
+drm_iounmap(struct drm_device *dev, struct drm_local_map *map)
+{
+	const bus_space_tag_t bst = dev->bst;
+	struct drm_bus_map *const bm = map->bus_map;
+
+	/*
+	 * bm may be null if we have committed the horrible deed of
+	 * borrowing from agp_i810 or genfb.
+	 */
+	if (bm != NULL) {
+		KASSERT(bm->bm_mapped > 0);
+		if (--bm->bm_mapped)
+			bus_space_unmap(bst, bm->bm_bsh, bm->bm_size);
+	}
+}

Reply via email to