Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142385168
D5237.id13162.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D5237.id13162.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D5237: WIP of BUS_MAP_RESOURCE.
Attached
Detach File
Event Timeline
Log In to Comment