Module Name:    src
Committed By:   dyoung
Date:           Wed Jul  6 18:46:04 UTC 2011

Modified Files:
        src/sys/arch/amd64/include: types.h
        src/sys/arch/i386/include: types.h
        src/sys/arch/x86/x86: bus_space.c

Log Message:
Implement bus_space_tag_create() and _destroy().

Factor bus_space_reserve(), bus_space_release(), et cetera out of
bus_space_alloc(), bus_space_map(), bus_space_free(), bus_space_unmap(),
et cetera.

For i386 and amd64, activate the use of <machine/bus_defs.h> and
<machine/bus_funcs.h> by #defining __HAVE_NEW_STYLE_BUS_H in
their respective types.h.  While I'm here, remove unnecessary
__HAVE_DEVICE_REGISTER #defines.


To generate a diff of this commit:
cvs rdiff -u -r1.38 -r1.39 src/sys/arch/amd64/include/types.h
cvs rdiff -u -r1.73 -r1.74 src/sys/arch/i386/include/types.h
cvs rdiff -u -r1.33 -r1.34 src/sys/arch/x86/x86/bus_space.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/arch/amd64/include/types.h
diff -u src/sys/arch/amd64/include/types.h:1.38 src/sys/arch/amd64/include/types.h:1.39
--- src/sys/arch/amd64/include/types.h:1.38	Sun Jun 12 03:35:38 2011
+++ src/sys/arch/amd64/include/types.h	Wed Jul  6 18:46:04 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: types.h,v 1.38 2011/06/12 03:35:38 rmind Exp $	*/
+/*	$NetBSD: types.h,v 1.39 2011/07/06 18:46:04 dyoung Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -76,7 +76,7 @@
 /* The amd64 does not have strict alignment requirements. */
 #define	__NO_STRICT_ALIGNMENT
 
-#define	__HAVE_DEVICE_REGISTER
+#define	__HAVE_NEW_STYLE_BUS_H
 #define	__HAVE_CPU_COUNTER
 #define	__HAVE_CPU_DATA_FIRST
 #define	__HAVE_MD_CPU_OFFLINE

Index: src/sys/arch/i386/include/types.h
diff -u src/sys/arch/i386/include/types.h:1.73 src/sys/arch/i386/include/types.h:1.74
--- src/sys/arch/i386/include/types.h:1.73	Sun Jun 12 03:35:42 2011
+++ src/sys/arch/i386/include/types.h	Wed Jul  6 18:46:04 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: types.h,v 1.73 2011/06/12 03:35:42 rmind Exp $	*/
+/*	$NetBSD: types.h,v 1.74 2011/07/06 18:46:04 dyoung Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -101,7 +101,7 @@
 /* The x86 does not have strict alignment requirements. */
 #define	__NO_STRICT_ALIGNMENT
 
-#define	__HAVE_DEVICE_REGISTER
+#define	__HAVE_NEW_STYLE_BUS_H
 #define	__HAVE_CPU_DATA_FIRST
 #define	__HAVE_CPU_COUNTER
 #define	__HAVE_MD_CPU_OFFLINE

Index: src/sys/arch/x86/x86/bus_space.c
diff -u src/sys/arch/x86/x86/bus_space.c:1.33 src/sys/arch/x86/x86/bus_space.c:1.34
--- src/sys/arch/x86/x86/bus_space.c:1.33	Fri Feb 11 23:08:38 2011
+++ src/sys/arch/x86/x86/bus_space.c	Wed Jul  6 18:46:04 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: bus_space.c,v 1.33 2011/02/11 23:08:38 jmcneill Exp $	*/
+/*	$NetBSD: bus_space.c,v 1.34 2011/07/06 18:46:04 dyoung Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@@ -31,12 +31,13 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bus_space.c,v 1.33 2011/02/11 23:08:38 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bus_space.c,v 1.34 2011/07/06 18:46:04 dyoung Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/malloc.h>
 #include <sys/extent.h>
+#include <sys/kmem.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -156,42 +157,58 @@
 bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size,
 		int flags, bus_space_handle_t *bshp)
 {
+	bus_space_reservation_t bsr;
 	int error;
-	struct extent *ex;
 
-	/*
-	 * Pick the appropriate extent map.
-	 */
-	if (x86_bus_space_is_io(t)) {
-		if (flags & BUS_SPACE_MAP_LINEAR)
-			return (EOPNOTSUPP);
-		ex = ioport_ex;
-	} else if (x86_bus_space_is_mem(t))
-		ex = iomem_ex;
-	else
-		panic("x86_memio_map: bad bus space tag");
+	if ((t->bst_present & BUS_SPACE_OVERRIDE_MAP) != 0) {
+		return (*t->bst_ov->ov_space_map)(t->bst_ctx, t, bpa, size,
+		    flags, bshp);
+	}
+	if (t->bst_super != NULL)
+		return bus_space_map(t->bst_super, bpa, size, flags, bshp);
+
+	error = bus_space_reserve(t, bpa, size, flags, &bsr);
+	if (error != 0)
+		return error;
+
+	error = bus_space_reservation_map(t, &bsr, flags, bshp);
+	if (error != 0)
+		bus_space_release(t, &bsr);
 
-	/*
-	 * Before we go any further, let's make sure that this
-	 * region is available.
-	 */
-	error = extent_alloc_region(ex, bpa, size,
-	    EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0));
-	if (error)
-		return (error);
+	return error;
+}
+
+int
+bus_space_reservation_map(bus_space_tag_t t, bus_space_reservation_t *bsr,
+    int flags, bus_space_handle_t *bshp)
+{
+	bus_addr_t bpa;
+	bus_size_t size;
+
+	if ((t->bst_present & BUS_SPACE_OVERRIDE_RESERVATION_MAP) != 0) {
+		return (*t->bst_ov->ov_space_reservation_map)(t->bst_ctx, t,
+		    bsr, flags, bshp);
+	}
+	if (t->bst_super != NULL) {
+		return bus_space_reservation_map(t->bst_super,
+		    bsr, flags, bshp);
+	}
+
+	bpa = bus_space_reservation_addr(bsr);
+	size = bus_space_reservation_size(bsr);
 
 	/*
 	 * For I/O space, that's all she wrote.
 	 */
 	if (x86_bus_space_is_io(t)) {
 		*bshp = bpa;
-		return (0);
+		return 0;
 	}
 
 #ifndef XEN
 	if (bpa >= IOM_BEGIN && (bpa + size) != 0 && (bpa + size) <= IOM_END) {
 		*bshp = (bus_space_handle_t)ISA_HOLE_VADDR(bpa);
-		return(0);
+		return 0;
 	}
 #endif	/* !XEN */
 
@@ -199,17 +216,7 @@
 	 * For memory space, map the bus physical address to
 	 * a kernel virtual address.
 	 */
-	error = x86_mem_add_mapping(bpa, size, flags, bshp);
-	if (error) {
-		if (extent_free(ex, bpa, size, EX_NOWAIT |
-		    (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
-			printf("x86_memio_map: pa 0x%jx, size 0x%jx\n",
-			    (uintmax_t)bpa, (uintmax_t)size);
-			printf("x86_memio_map: can't free region\n");
-		}
-	}
-
-	return (error);
+	return x86_mem_add_mapping(bpa, size, flags, bshp);
 }
 
 int
@@ -235,14 +242,66 @@
 }
 
 int
-bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, bus_addr_t rend,
-		bus_size_t size, bus_size_t alignment, bus_size_t boundary,
-		int flags, bus_addr_t *bpap, bus_space_handle_t *bshp)
+bus_space_reserve(bus_space_tag_t t,
+    bus_addr_t bpa,
+    bus_size_t size,
+    int flags, bus_space_reservation_t *bsrp)
 {
 	struct extent *ex;
+	int error;
+
+	if ((t->bst_present & BUS_SPACE_OVERRIDE_RESERVE) != 0) {
+		return (*t->bst_ov->ov_space_reserve)(t->bst_ctx, t,
+		    bpa, size, flags, bsrp);
+	}
+	if (t->bst_super != NULL)
+		return bus_space_reserve(t->bst_super, bpa, size, flags, bsrp);
+
+	/*
+	 * Pick the appropriate extent map.
+	 */
+	if (x86_bus_space_is_io(t)) {
+		if (flags & BUS_SPACE_MAP_LINEAR)
+			return (EOPNOTSUPP);
+		ex = ioport_ex;
+	} else if (x86_bus_space_is_mem(t))
+		ex = iomem_ex;
+	else
+		panic("x86_memio_alloc: bad bus space tag");
+
+	/*
+	 * Before we go any further, let's make sure that this
+	 * region is available.
+	 */
+	error = extent_alloc_region(ex, bpa, size,
+	    EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0));
+
+	if (error != 0)
+		return error;
+
+	bus_space_reservation_init(bsrp, bpa, size);
+
+	return 0;
+}
+
+int
+bus_space_reserve_subregion(bus_space_tag_t t,
+    bus_addr_t rstart, bus_addr_t rend,
+    bus_size_t size, bus_size_t alignment, bus_size_t boundary,
+    int flags, bus_space_reservation_t *bsrp)
+{
+	bus_space_reservation_t bsr;
+	struct extent *ex;
 	u_long bpa;
 	int error;
 
+	if ((t->bst_present & BUS_SPACE_OVERRIDE_RESERVE_SUBREGION) != 0) {
+		return (*t->bst_ov->ov_space_reserve_subregion)(t->bst_ctx, t,
+		    rstart, rend, size, alignment, boundary, flags, bsrp);
+	}
+	if (t->bst_super != NULL)
+		return bus_space_reserve(t->bst_super, bpa, size, flags, bsrp);
+
 	/*
 	 * Pick the appropriate extent map.
 	 */
@@ -258,7 +317,9 @@
 	/*
 	 * Sanity check the allocation against the extent's boundaries.
 	 */
-	if (rstart < ex->ex_start || rend > ex->ex_end)
+	rstart = MAX(rstart, ex->ex_start);
+	rend = MIN(rend, ex->ex_end);
+	if (rstart >= rend)
 		panic("x86_memio_alloc: bad region start/end");
 
 	/*
@@ -272,31 +333,79 @@
 	if (error)
 		return (error);
 
+	bus_space_reservation_init(&bsr, bpa, size);
+
+	*bsrp = bsr;
+
+	return 0;
+}
+
+void
+bus_space_release(bus_space_tag_t t, bus_space_reservation_t *bsr)
+{
+	struct extent *ex;
+
+	if ((t->bst_present & BUS_SPACE_OVERRIDE_RELEASE) != 0) {
+		(*t->bst_ov->ov_space_release)(t->bst_ctx, t, bsr);
+		return;
+	}
+	if (t->bst_super != NULL) {
+		bus_space_release(t->bst_super, bsr);
+		return;
+	}
 	/*
-	 * For I/O space, that's all she wrote.
+	 * Pick the appropriate extent map.
 	 */
 	if (x86_bus_space_is_io(t)) {
-		*bshp = *bpap = bpa;
-		return (0);
+		ex = ioport_ex;
+	} else if (x86_bus_space_is_mem(t))
+		ex = iomem_ex;
+	else
+		panic("x86_memio_alloc: bad bus space tag");
+
+	if (extent_free(ex, bus_space_reservation_addr(bsr),
+	    bus_space_reservation_size(bsr), EX_NOWAIT |
+	    (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
+		printf("%s: pa 0x%jx, size 0x%jx\n", __func__,
+		    (uintmax_t)bus_space_reservation_addr(bsr),
+		    (uintmax_t)bus_space_reservation_size(bsr));
+		printf("%s: can't free region\n", __func__);
+	}
+}
+
+int
+bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, bus_addr_t rend,
+		bus_size_t size, bus_size_t alignment, bus_size_t boundary,
+		int flags, bus_addr_t *bpap, bus_space_handle_t *bshp)
+{
+	bus_space_reservation_t bsr;
+	int error;
+
+	if ((t->bst_present & BUS_SPACE_OVERRIDE_ALLOC) != 0) {
+		return (*t->bst_ov->ov_space_alloc)(t->bst_ctx, t, rstart, rend,
+		    size, alignment, boundary, flags, bpap, bshp);
+	}
+	if (t->bst_super != NULL) {
+		return bus_space_alloc(t->bst_super, rstart, rend, size,
+		    alignment, boundary, flags, bpap, bshp);
 	}
 
 	/*
-	 * For memory space, map the bus physical address to
-	 * a kernel virtual address.
+	 * Do the requested allocation.
 	 */
-	error = x86_mem_add_mapping(bpa, size, flags, bshp);
-	if (error) {
-		if (extent_free(iomem_ex, bpa, size, EX_NOWAIT |
-		    (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
-			printf("x86_memio_alloc: pa 0x%jx, size 0x%jx\n",
-			    (uintmax_t)bpa, (uintmax_t)size);
-			printf("x86_memio_alloc: can't free region\n");
-		}
-	}
+	error = bus_space_reserve_subregion(t, rstart, rend, size, alignment,
+	    boundary, flags, &bsr);
+
+	if (error != 0)
+		return error;
+
+	error = bus_space_reservation_map(t, &bsr, flags, bshp);
+	if (error != 0)
+		bus_space_release(t, &bsr);
 
-	*bpap = bpa;
+	*bpap = bus_space_reservation_addr(&bsr);
 
-	return (error);
+	return error;
 }
 
 int
@@ -410,10 +519,10 @@
 	}
 }
 
-void
-bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
+static void
+bus_space_reservation_unmap1(bus_space_tag_t t, const bus_space_handle_t bsh,
+    const bus_size_t size, bus_addr_t *bpap)
 {
-	struct extent *ex;
 	u_long va, endva;
 	bus_addr_t bpa;
 
@@ -421,11 +530,8 @@
 	 * Find the correct extent and bus physical address.
 	 */
 	if (x86_bus_space_is_io(t)) {
-		ex = ioport_ex;
 		bpa = bsh;
 	} else if (x86_bus_space_is_mem(t)) {
-		ex = iomem_ex;
-
 		if (bsh >= atdevbase && (bsh + size) != 0 &&
 		    (bsh + size) <= (atdevbase + IOM_SIZE)) {
 			bpa = (bus_addr_t)ISA_PHYSADDR(bsh);
@@ -452,21 +558,62 @@
 		uvm_km_free(kernel_map, va, endva - va, UVM_KMF_VAONLY);
 	} else
 		panic("x86_memio_unmap: bad bus space tag");
-
 ok:
-	if (extent_free(ex, bpa, size,
-	    EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
-		printf("x86_memio_unmap: %s 0x%jx, size 0x%jx\n",
-		    x86_bus_space_is_io(t) ? "port" : "pa",
-		    (uintmax_t)bpa, (uintmax_t)size);
-		printf("x86_memio_unmap: can't free region\n");
+	if (bpap != NULL)
+		*bpap = bpa;
+}
+
+void
+bus_space_reservation_unmap(bus_space_tag_t t, const bus_space_handle_t bsh,
+    const bus_size_t size)
+{
+	if ((t->bst_present & BUS_SPACE_OVERRIDE_RESERVATION_UNMAP) != 0) {
+		(*t->bst_ov->ov_space_reservation_unmap)(t->bst_ctx,
+		    t, bsh, size);
+		return;
+	}
+	if (t->bst_super != NULL) {
+		bus_space_reservation_unmap(t->bst_super, bsh, size);
+		return;
+	}
+
+	bus_space_reservation_unmap1(t, bsh, size, NULL);
+}
+
+void
+bus_space_unmap(bus_space_tag_t t, const bus_space_handle_t bsh,
+    const bus_size_t size)
+{
+	bus_addr_t addr;
+	bus_space_reservation_t bsr;
+
+	if ((t->bst_present & BUS_SPACE_OVERRIDE_UNMAP) != 0) {
+		(*t->bst_ov->ov_space_unmap)(t->bst_ctx, t, bsh, size);
+		return;
 	}
+	if (t->bst_super != NULL) {
+		bus_space_unmap(t->bst_super, bsh, size);
+		return;
+	}
+
+	bus_space_reservation_unmap1(t, bsh, size, &addr);
+
+	bus_space_reservation_init(&bsr, addr, size);
+	bus_space_release(t, &bsr);
 }
 
 void
 bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
 {
 
+	if ((t->bst_present & BUS_SPACE_OVERRIDE_FREE) != 0) {
+		(*t->bst_ov->ov_space_free)(t->bst_ctx, t, bsh, size);
+		return;
+	}
+	if (t->bst_super != NULL) {
+		bus_space_free(t->bst_super, bsh, size);
+		return;
+	}
 	/* bus_space_unmap() does all that we need to do. */
 	bus_space_unmap(t, bsh, size);
 }
@@ -720,3 +867,76 @@
 
 	return x86_bus_space_is_mem(tag) ? (void *)bsh : NULL;
 }
+
+static const void *
+bit_to_function_pointer(const struct bus_space_overrides *ov, uint64_t bit)
+{
+	switch (bit) {
+	case BUS_SPACE_OVERRIDE_MAP:
+		return ov->ov_space_map;
+	case BUS_SPACE_OVERRIDE_UNMAP:
+		return ov->ov_space_unmap;
+	case BUS_SPACE_OVERRIDE_ALLOC:
+		return ov->ov_space_alloc;
+	case BUS_SPACE_OVERRIDE_FREE:
+		return ov->ov_space_free;
+	case BUS_SPACE_OVERRIDE_RESERVE:
+		return ov->ov_space_reserve;
+	case BUS_SPACE_OVERRIDE_RELEASE:
+		return ov->ov_space_release;
+	case BUS_SPACE_OVERRIDE_RESERVATION_MAP:
+		return ov->ov_space_reservation_map;
+	case BUS_SPACE_OVERRIDE_RESERVATION_UNMAP:
+		return ov->ov_space_reservation_unmap;
+	case BUS_SPACE_OVERRIDE_RESERVE_SUBREGION:
+		return ov->ov_space_reserve_subregion;
+	default:
+		return NULL;
+	}
+}
+
+void
+bus_space_tag_destroy(bus_space_tag_t bst)
+{
+	kmem_free(bst, sizeof(struct bus_space_tag));
+}
+
+int
+bus_space_tag_create(bus_space_tag_t obst, uint64_t present,
+    const struct bus_space_overrides *ov, void *ctx, bus_space_tag_t *bstp)
+{
+	uint64_t bit, bits, nbits;
+	bus_space_tag_t bst;
+	const void *fp;
+
+	if (ov == NULL || present != 0)
+		return EINVAL;
+
+	bst = kmem_alloc(sizeof(struct bus_space_tag), KM_SLEEP);
+
+	if (bst == NULL)
+		return ENOMEM;
+
+	bst->bst_super = obst;
+	bst->bst_type = obst->bst_type;
+
+	for (bits = present; bits != 0; bits = nbits) {
+		nbits = bits & (bits - 1);
+		bit = nbits ^ bits;
+		if ((fp = bit_to_function_pointer(ov, bit)) == NULL) {
+			printf("%s: missing bit %" PRIx64 "\n", __func__, bit);
+			goto einval;
+		}
+	}
+
+	bst->bst_ov = ov;
+	bst->bst_present = present;
+	bst->bst_ctx = ctx;
+
+	*bstp = bst;
+
+	return 0;
+einval:
+	kmem_free(bst, sizeof(struct bus_space_tag));
+	return EINVAL;
+}

Reply via email to