Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F176831000
D5237.1793448391.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
13 KB
Referenced Files
None
Subscribers
None
D5237.1793448391.diff
View Options
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,58 @@
struct resource *_r;
};
+
+/**
+ * @brief Map a resource
+ *
+ * Allocate a mapping for a range of an active resource. The mapping
+ * is described by a struct resource_map object. 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 _map the mapping
+ */
+METHOD int map_resource {
+ device_t _dev;
+ device_t _child;
+ int _type;
+ struct resource *_r;
+ struct resource_map_request *_args;
+ struct resource_map *_map;
+} DEFAULT bus_generic_map_resource;
+
+
+/**
+ * @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 _map the mapping to release
+ */
+METHOD int unmap_resource {
+ device_t _dev;
+ device_t _child;
+ int _type;
+ struct resource *_r;
+ struct resource_map *_map;
+} DEFAULT bus_generic_unmap_resource;
+
+
/**
* @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
@@ -3017,6 +3017,15 @@
* Some useful method implementations to make life easier for bus drivers.
*/
+void
+resource_init_map_request_impl(struct resource_map_request *args, size_t sz)
+{
+
+ bzero(args, sz);
+ args->size = sz;
+ args->memattr = VM_MEMATTR_UNCACHEABLE;
+}
+
/**
* @brief Initialise a resource list.
*
@@ -4027,6 +4036,40 @@
}
/**
+ * @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,
+ struct resource_map *map)
+{
+ /* Propagate up the bus hierarchy until someone handles it. */
+ if (dev->parent)
+ return (BUS_MAP_RESOURCE(dev->parent, child, type, r, args,
+ map));
+ 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, struct resource_map *map)
+{
+ /* Propagate up the bus hierarchy until someone handles it. */
+ if (dev->parent)
+ return (BUS_UNMAP_RESOURCE(dev->parent, child, type, r, map));
+ return (EINVAL);
+}
+
+/**
* @brief Helper function for implementing BUS_BIND_INTR().
*
* This simple implementation of BUS_BIND_INTR() simply calls the
@@ -4342,6 +4385,36 @@
}
/**
+ * @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, struct resource_map *map)
+{
+ if (dev->parent == NULL)
+ return (EINVAL);
+ return (BUS_MAP_RESOURCE(dev->parent, dev, type, r, args, map));
+}
+
+/**
+ * @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,
+ struct resource_map *map)
+{
+ if (dev->parent == NULL)
+ return (EINVAL);
+ return (BUS_UNMAP_RESOURCE(dev->parent, dev, type, r, map));
+}
+
+/**
* @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,31 @@
KOBJ_CLASS_FIELDS;
};
+/**
+ * @brief A resource mapping.
+ */
+struct resource_map {
+ bus_space_tag_t r_bustag;
+ bus_space_handle_t r_bushandle;
+ bus_size_t r_size;
+ void *r_vaddr;
+};
+
+/**
+ * @brief Optional properties of a resource mapping request.
+ */
+struct resource_map_request {
+ size_t size;
+ rman_res_t offset;
+ rman_res_t length;
+ vm_memattr_t memattr;
+};
+
+void resource_init_map_request_impl(struct resource_map_request *_args,
+ size_t _sz);
+#define resource_init_map_request(rmr) \
+ resource_init_map_request_impl((rmr), sizeof(*(rmr)))
+
/*
* Definitions for drivers which need to keep simple lists of resources
* for their child devices.
@@ -386,6 +411,10 @@
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,
+ struct resource_map *map);
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 +448,9 @@
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,
+ struct resource_map *map);
int bus_generic_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
@@ -447,6 +479,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,
+ struct resource_map *map);
+int bus_unmap_resource(device_t dev, int type, struct resource *r,
+ struct resource_map *map);
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/vm/vm.h
===================================================================
--- sys/vm/vm.h
+++ sys/vm/vm.h
@@ -109,8 +109,9 @@
typedef int boolean_t;
/*
- * The exact set of memory attributes is machine dependent. However, every
- * machine is required to define VM_MEMATTR_DEFAULT.
+ * The exact set of memory attributes is machine dependent. However,
+ * every machine is required to define VM_MEMATTR_DEFAULT and
+ * VM_MEMATTR_UNCACHEABLE.
*/
typedef char vm_memattr_t; /* memory attribute codes */
Index: sys/x86/x86/nexus.c
===================================================================
--- sys/x86/x86/nexus.c
+++ sys/x86/x86/nexus.c
@@ -115,6 +115,12 @@
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,
+ struct resource_map *map);
+static int nexus_unmap_resource(device_t bus, device_t child, int type,
+ struct resource *r, struct resource_map *map);
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 +159,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 +434,79 @@
nexus_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
+ struct resource_map map;
+ 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, &map);
+ if (error) {
+ rman_deactivate_resource(r);
+ return (error);
+ }
+
+ rman_set_bustag(r, map->r_tag);
+ rman_set_bushandle(r, map->r_handle);
+ rman_set_virtual(r, map->r_vaddr);
+ return (0);
+}
+
+static int
+nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ struct resource_map map;
+ int error;
+
+ error = rman_deactivate_resource(r);
+ if (error)
+ return (error);
+
+ if (rman_get_flags(r) & RF_UNMAPPED)
+ return (0);
+
+ map.r_tag = rman_get_bustag(r);
+ map.r_handle = rman_get_bushandle(r);
+ map.r_size = rman_get_size(r);
+ map.r_vaddr = rman_get_virtual(r);
+ nexus_unmap_resource(bus, child, type, r, &map);
+ return (0);
+}
+
+static int
+nexus_map_resource(device_t bus, device_t child, int type, struct resource *r,
+ struct resource_map_request *argsp, struct resource_map *map)
+{
+ 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 +514,59 @@
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, &map->r_handle);
if (error)
return (error);
- rman_set_bushandle(r, bh);
#else
- rman_set_bushandle(r, rman_get_start(r));
+ map->r_handle = start;
#endif
- rman_set_bustag(r, X86_BUS_SPACE_IO);
+ map->r_tag = X86_BUS_SPACE_IO;
+ map->r_size = size;
+ map->r_vaddr = NULL;
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, &map->r_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);
+ map->r_vaddr = pmap_mapdev_attr(start, size, args.memattr);
+ map->r_tag = X86_BUS_SPACE_MEM;
+ map->r_size = size;
+
+ /*
+ * PC-98 stores the virtual address as a member of the
+ * structure in the handle. On plain x86, the handle is
+ * the virtual address.
+ */
#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);
+ map->r_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);
+ map->r_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,
+ struct resource_map *map)
{
-
+
/*
* 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));
- }
+ if (type == SYS_RES_MEMORY)
+ pmap_unmapdev((vm_offset_t)map->r_vaddr, map->r_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(map->r_tag, map->r_handle,
+ map->r_handle->bsh_sz);
}
#endif
- return (rman_deactivate_resource(r));
+ return (0);
}
static int
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Oct 31, 12:06 PM (12 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41262518
Default Alt Text
D5237.1793448391.diff (13 KB)
Attached To
Mode
D5237: WIP of BUS_MAP_RESOURCE.
Attached
Detach File
Event Timeline