Page MenuHomeFreeBSD

D5237.id13162.diff
No OneTemporary

D5237.id13162.diff

Index: sys/amd64/include/vm.h
===================================================================
--- sys/amd64/include/vm.h
+++ sys/amd64/include/vm.h
@@ -41,5 +41,6 @@
#define VM_MEMATTR_WEAK_UNCACHEABLE ((vm_memattr_t)PAT_UNCACHED)
#define VM_MEMATTR_DEFAULT VM_MEMATTR_WRITE_BACK
+#define VM_MEMATTR_DEVICE_DEFAULT VM_MEMATTR_UNCACHEABLE
#endif /* !_MACHINE_VM_H_ */
Index: sys/i386/include/vm.h
===================================================================
--- sys/i386/include/vm.h
+++ sys/i386/include/vm.h
@@ -41,5 +41,6 @@
#define VM_MEMATTR_WEAK_UNCACHEABLE ((vm_memattr_t)PAT_UNCACHED)
#define VM_MEMATTR_DEFAULT VM_MEMATTR_WRITE_BACK
+#define VM_MEMATTR_DEVICE_DEFAULT VM_MEMATTR_UNCACHEABLE
#endif /* !_MACHINE_VM_H_ */
Index: sys/kern/bus_if.m
===================================================================
--- sys/kern/bus_if.m
+++ sys/kern/bus_if.m
@@ -274,8 +274,9 @@
* @brief Activate a resource
*
* Activate a resource previously allocated with
- * BUS_ALLOC_RESOURCE(). This may for instance map a memory region
- * into the kernel's virtual address space.
+ * BUS_ALLOC_RESOURCE(). This may enable decoding of this resource in a
+ * device for instance. It will also establish a mapping for the resource
+ * unless RF_UNMAPPED was set when allocating the resource.
*
* @param _dev the parent device of @p _child
* @param _child the device which allocated the resource
@@ -291,12 +292,62 @@
struct resource *_r;
};
+
+/**
+ * @brief Map a resource
+ *
+ * Allocate a mapping for a range of an active resource. The mapping
+ * is described by a bus space tag and handle. This may for instance
+ * map a memory region into the kernel's virtual address space.
+ *
+ * @param _dev the parent device of @p _child
+ * @param _child the device which allocated the resource
+ * @param _type the type of resource
+ * @param _r the resource to map
+ * @param _args optional attributes of the mapping
+ * @param _tag the tag for the mapping
+ * @param _handle the handle for the mapping
+ */
+METHOD int map_resource {
+ device_t _dev;
+ device_t _child;
+ int _type;
+ struct resource *_r;
+ struct resource_map_request *_args;
+ bus_space_tag_t *_tag;
+ bus_space_handle_t *_handle;
+};
+
+
+/**
+ * @brief Unmap a resource
+ *
+ * Release a mapping previously allocated with
+ * BUS_MAP_RESOURCE(). This may for instance unmap a memory region
+ * from the kernel's virtual address space.
+ *
+ * @param _dev the parent device of @p _child
+ * @param _child the device which allocated the resource
+ * @param _type the type of resource
+ * @param _r the resource
+ * @param _tag the tag of the mapping to release
+ * @param _handle the handle of the mapping to release
+ */
+METHOD int unmap_resource {
+ device_t _dev;
+ device_t _child;
+ int _type;
+ struct resource *_r;
+ bus_space_tag_t _tag;
+ bus_space_handle_t _handle;
+};
+
+
/**
* @brief Deactivate a resource
*
* Deactivate a resource previously allocated with
- * BUS_ALLOC_RESOURCE(). This may for instance unmap a memory region
- * from the kernel's virtual address space.
+ * BUS_ALLOC_RESOURCE().
*
* @param _dev the parent device of @p _child
* @param _child the device which allocated the resource
Index: sys/kern/subr_bus.c
===================================================================
--- sys/kern/subr_bus.c
+++ sys/kern/subr_bus.c
@@ -4027,6 +4027,41 @@
}
/**
+ * @brief Helper function for implementing BUS_MAP_RESOURCE().
+ *
+ * This simple implementation of BUS_MAP_RESOURCE() simply calls the
+ * BUS_MAP_RESOURCE() method of the parent of @p dev.
+ */
+int
+bus_generic_map_resource(device_t dev, device_t child, int type,
+ struct resource *r, struct resource_map_request *args, bus_space_tag_t *tag,
+ bus_space_handle_t *handle)
+{
+ /* Propagate up the bus hierarchy until someone handles it. */
+ if (dev->parent)
+ return (BUS_MAP_RESOURCE(dev->parent, child, type, r, args, tag,
+ handle));
+ return (EINVAL);
+}
+
+/**
+ * @brief Helper function for implementing BUS_UNMAP_RESOURCE().
+ *
+ * This simple implementation of BUS_UNMAP_RESOURCE() simply calls the
+ * BUS_UNMAP_RESOURCE() method of the parent of @p dev.
+ */
+int
+bus_generic_unmap_resource(device_t dev, device_t child, int type,
+ struct resource *r, bus_space_tag_t tag, bus_space_handle_t handle)
+{
+ /* Propagate up the bus hierarchy until someone handles it. */
+ if (dev->parent)
+ return (BUS_UNMAP_RESOURCE(dev->parent, child, type, r, tag,
+ handle));
+ return (EINVAL);
+}
+
+/**
* @brief Helper function for implementing BUS_BIND_INTR().
*
* This simple implementation of BUS_BIND_INTR() simply calls the
@@ -4342,6 +4377,37 @@
}
/**
+ * @brief Wrapper function for BUS_MAP_RESOURCE().
+ *
+ * This function simply calls the BUS_MAP_RESOURCE() method of the
+ * parent of @p dev.
+ */
+int
+bus_map_resource(device_t dev, int type, struct resource *r,
+ struct resource_map_request *args, bus_space_tag_t *tag,
+ bus_space_handle_t *handle)
+{
+ if (dev->parent == NULL)
+ return (EINVAL);
+ return (BUS_MAP_RESOURCE(dev->parent, dev, type, r, args, tag, handle));
+}
+
+/**
+ * @brief Wrapper function for BUS_UNMAP_RESOURCE().
+ *
+ * This function simply calls the BUS_UNMAP_RESOURCE() method of the
+ * parent of @p dev.
+ */
+int
+bus_unmap_resource(device_t dev, int type, struct resource *r,
+ bus_space_tag_t tag, bus_space_handle_t handle)
+{
+ if (dev->parent == NULL)
+ return (EINVAL);
+ return (BUS_UNMAP_RESOURCE(dev->parent, dev, type, r, tag, handle));
+}
+
+/**
* @brief Wrapper function for BUS_RELEASE_RESOURCE().
*
* This function simply calls the BUS_RELEASE_RESOURCE() method of the
Index: sys/sys/bus.h
===================================================================
--- sys/sys/bus.h
+++ sys/sys/bus.h
@@ -277,6 +277,22 @@
KOBJ_CLASS_FIELDS;
};
+/**
+ * @brief Optional properties of a resource mapping request.
+ */
+struct resource_map_request {
+ int size;
+ rman_res_t offset;
+ rman_res_t length;
+ vm_memattr_t memattr;
+};
+
+#define resource_init_map_request(rmr) do { \
+ bzero((rmr), sizeof(*(rmr))); \
+ (rmr)->size = sizeof(*(rmr)); \
+ (rmr)->memattr = VM_MEMATTR_DEVICE_DEFAULT; \
+} while (0)
+
/*
* Definitions for drivers which need to keep simple lists of resources
* for their child devices.
@@ -386,6 +402,11 @@
int bus_generic_get_domain(device_t dev, device_t child, int *domain);
struct resource_list *
bus_generic_get_resource_list (device_t, device_t);
+int bus_generic_map_resource(device_t dev, device_t child, int type,
+ struct resource *r,
+ struct resource_map_request *args,
+ bus_space_tag_t *tag,
+ bus_space_handle_t *handle);
void bus_generic_new_pass(device_t dev);
int bus_print_child_header(device_t dev, device_t child);
int bus_print_child_domain(device_t dev, device_t child);
@@ -419,6 +440,10 @@
int bus_generic_suspend_child(device_t dev, device_t child);
int bus_generic_teardown_intr(device_t dev, device_t child,
struct resource *irq, void *cookie);
+int bus_generic_unmap_resource(device_t dev, device_t child, int type,
+ struct resource *r,
+ bus_space_tag_t tag,
+ bus_space_handle_t handle);
int bus_generic_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
@@ -447,6 +472,11 @@
struct resource *r);
int bus_deactivate_resource(device_t dev, int type, int rid,
struct resource *r);
+int bus_map_resource(device_t dev, int type, struct resource *r,
+ struct resource_map_request *args,
+ bus_space_tag_t *tag, bus_space_handle_t *handle);
+int bus_unmap_resource(device_t dev, int type, struct resource *r,
+ bus_space_tag_t tag, bus_space_handle_t handle);
bus_dma_tag_t bus_get_dma_tag(device_t dev);
int bus_get_domain(device_t dev, int *domain);
int bus_release_resource(device_t dev, int type, int rid,
Index: sys/sys/rman.h
===================================================================
--- sys/sys/rman.h
+++ sys/sys/rman.h
@@ -47,6 +47,7 @@
#define RF_FIRSTSHARE 0x0020 /* first in sharing list */
#define RF_PREFETCHABLE 0x0040 /* resource is prefetchable */
#define RF_OPTIONAL 0x0080 /* for bus_alloc_resources() */
+#define RF_UNMAPPED 0x0100 /* don't map resource when activating */
#define RF_ALIGNMENT_SHIFT 10 /* alignment size bit starts bit 10 */
#define RF_ALIGNMENT_MASK (0x003F << RF_ALIGNMENT_SHIFT)
Index: sys/x86/x86/nexus.c
===================================================================
--- sys/x86/x86/nexus.c
+++ sys/x86/x86/nexus.c
@@ -115,6 +115,14 @@
struct resource *);
static int nexus_deactivate_resource(device_t, device_t, int, int,
struct resource *);
+static int nexus_map_resource(device_t bus, device_t child, int type,
+ struct resource *r,
+ struct resource_map_request *argsp,
+ bus_space_tag_t *tag,
+ bus_space_handle_t *handle);
+static int nexus_unmap_resource(device_t bus, device_t child, int type,
+ struct resource *r, bus_space_tag_t tag,
+ bus_space_handle_t handle);
static int nexus_release_resource(device_t, device_t, int, int,
struct resource *);
static int nexus_setup_intr(device_t, device_t, struct resource *, int flags,
@@ -153,6 +161,8 @@
DEVMETHOD(bus_release_resource, nexus_release_resource),
DEVMETHOD(bus_activate_resource, nexus_activate_resource),
DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
+ DEVMETHOD(bus_map_resource, nexus_map_resource),
+ DEVMETHOD(bus_unmap_resource, nexus_unmap_resource),
DEVMETHOD(bus_setup_intr, nexus_setup_intr),
DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
#ifdef SMP
@@ -426,12 +436,86 @@
nexus_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
+ bus_space_tag_t tag;
+ bus_space_handle_t handle;
+ int error;
+ void *vaddr;
+
+ error = rman_activate_resource(r);
+ if (error != 0)
+ return (error);
+
+ if (rman_get_flags(r) & RF_UNMAPPED)
+ return (0);
+
+ error = nexus_map_resource(bus, child, type, r, NULL, &tag, &handle);
+ if (error) {
+ rman_deactivate_resource(r);
+ return (error);
+ }
+
+ rman_set_bustag(r, tag);
+ rman_set_bushandle(r, handle);
+ if (type == SYS_RES_MEMORY) {
+#ifdef PC98
+ /* PC-98: the type of bus_space_handle_t is the structure. */
+ vaddr = (void *)handle->bsh_base;
+#else
+ /* IBM-PC: the type of bus_space_handle_t is u_int */
+ vaddr = (void *)handle;
+#endif
+ rman_set_virtual(r, vaddr);
+ }
+ return (0);
+}
+
+static int
+nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ int error;
+
+ error = rman_deactivate_resource(r);
+ if (error)
+ return (error);
+
+ if (rman_get_flags(r) & RF_UNMAPPED)
+ return (0);
+
+ nexus_unmap_resource(bus, child, type, r, rman_get_bustag(r),
+ rman_get_bushandle(r));
+ return (0);
+}
+
+static int
+nexus_map_resource(device_t bus, device_t child, int type, struct resource *r,
+ struct resource_map_request *argsp, bus_space_tag_t *tag,
+ bus_space_handle_t *handle)
+{
+ struct resource_map_request args;
+ rman_res_t start, size;
#ifdef PC98
- bus_space_handle_t bh;
int error;
#endif
void *vaddr;
+ /* Resources must be active to be mapped. */
+ if (!(rman_get_flags(r) & RF_ACTIVE))
+ return (ENXIO);
+
+ resource_init_map_request(&args);
+ if (argsp != NULL)
+ bcopy(argsp, &args, imin(argsp->size, args.size));
+ start = rman_get_start(r) + args.offset;
+ if (args.size == 0)
+ size = rman_get_size(r);
+ else
+ size = args.size;
+ if (start > rman_get_end(r) || start < rman_get_start(r))
+ return (EINVAL);
+ if (start + size > rman_get_end(r) || start + size < start)
+ return (EINVAL);
+
/*
* If this is a memory resource, map it into the kernel.
*/
@@ -439,58 +523,64 @@
case SYS_RES_IOPORT:
#ifdef PC98
error = i386_bus_space_handle_alloc(X86_BUS_SPACE_IO,
- rman_get_start(r), rman_get_size(r), &bh);
+ start, size, handle);
if (error)
return (error);
- rman_set_bushandle(r, bh);
#else
- rman_set_bushandle(r, rman_get_start(r));
+ *handle = start;
#endif
- rman_set_bustag(r, X86_BUS_SPACE_IO);
+ *tag = X86_BUS_SPACE_IO;
break;
case SYS_RES_MEMORY:
#ifdef PC98
error = i386_bus_space_handle_alloc(X86_BUS_SPACE_MEM,
- rman_get_start(r), rman_get_size(r), &bh);
+ start, size, handle);
if (error)
return (error);
#endif
- vaddr = pmap_mapdev(rman_get_start(r), rman_get_size(r));
- rman_set_virtual(r, vaddr);
- rman_set_bustag(r, X86_BUS_SPACE_MEM);
+ vaddr = pmap_mapdev_attr(start, size, args.memattr);
+ *tag = X86_BUS_SPACE_MEM;
#ifdef PC98
/* PC-98: the type of bus_space_handle_t is the structure. */
- bh->bsh_base = (bus_addr_t) vaddr;
- rman_set_bushandle(r, bh);
+ (*handle)->bsh_base = (bus_addr_t) vaddr;
#else
/* IBM-PC: the type of bus_space_handle_t is u_int */
- rman_set_bushandle(r, (bus_space_handle_t) vaddr);
+ *handle = (bus_space_handle_t) vaddr;
#endif
+ break;
}
- return (rman_activate_resource(r));
+ return (0);
}
static int
-nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
- struct resource *r)
+nexus_unmap_resource(device_t bus, device_t child, int type, struct resource *r,
+ bus_space_tag_t tag, bus_space_handle_t handle)
{
-
+ void *vaddr;
+ rman_res_t size;
+
/*
* If this is a memory resource, unmap it.
*/
if (type == SYS_RES_MEMORY) {
- pmap_unmapdev((vm_offset_t)rman_get_virtual(r),
- rman_get_size(r));
+#ifdef PC98
+ /* PC-98: the type of bus_space_handle_t is the structure. */
+ vaddr = (void *)handle->bsh_base;
+ size = handle->bsh_sz;
+#else
+ /* IBM-PC: the type of bus_space_handle_t is u_int */
+ vaddr = (void *)handle;
+ /* XXX: size is wrong */
+ size = rman_get_size(r)
+#endif
+ pmap_unmapdev((vm_offset_t)vaddr, size);
}
#ifdef PC98
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
- bus_space_handle_t bh;
-
- bh = rman_get_bushandle(r);
- i386_bus_space_handle_free(rman_get_bustag(r), bh, bh->bsh_sz);
+ i386_bus_space_handle_free(tag, handle, handle->bsh_sz);
}
#endif
- return (rman_deactivate_resource(r));
+ return (0);
}
static int

File Metadata

Mime Type
text/plain
Expires
Tue, Jan 20, 10:23 AM (11 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27762180
Default Alt Text
D5237.id13162.diff (13 KB)

Event Timeline