svn commit: r300318 - head/sys/x86/x86
John Baldwin
jhb at FreeBSD.org
Fri May 20 18:00:12 UTC 2016
Author: jhb
Date: Fri May 20 18:00:10 2016
New Revision: 300318
URL: https://svnweb.freebsd.org/changeset/base/300318
Log:
Implement support for RF_UNMAPPED and bus_map/unmap_resource on x86.
Add implementations of bus_map/unmap_resource to the x86 nexus driver.
Change bus_activate/deactivate_resource to honor RF_UNMAPPED and to
use bus_map/unmap_resource to create/destroy the implicit mapping when
RF_UNMAPPED is not set.
Reviewed by: cem
Differential Revision: https://reviews.freebsd.org/D5237
Modified:
head/sys/x86/x86/nexus.c
Modified: head/sys/x86/x86/nexus.c
==============================================================================
--- head/sys/x86/x86/nexus.c Fri May 20 17:57:47 2016 (r300317)
+++ head/sys/x86/x86/nexus.c Fri May 20 18:00:10 2016 (r300318)
@@ -114,6 +114,12 @@ static int nexus_activate_resource(devic
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,
@@ -154,6 +160,8 @@ static device_method_t nexus_methods[] =
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
@@ -432,11 +440,81 @@ static int
nexus_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
+ struct resource_map map;
+ int error;
+
+ error = rman_activate_resource(r);
+ if (error != 0)
+ return (error);
+
+ if (!(rman_get_flags(r) & RF_UNMAPPED) &&
+ (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT)) {
+ error = nexus_map_resource(bus, child, type, r, NULL, &map);
+ if (error) {
+ rman_deactivate_resource(r);
+ return (error);
+ }
+
+ rman_set_mapping(r,&map);
+ }
+ 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) &&
+ (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT)) {
+ rman_get_mapping(r, &map);
+ 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 end, length, start;
#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);
+
+ /* Mappings are only supported on I/O and memory resources. */
+ switch (type) {
+ case SYS_RES_IOPORT:
+ case SYS_RES_MEMORY:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ 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.length == 0)
+ length = rman_get_size(r);
+ else
+ length = args.length;
+ end = start + length - 1;
+ if (start > rman_get_end(r) || start < rman_get_start(r))
+ return (EINVAL);
+ if (end > rman_get_end(r) || end < start)
+ return (EINVAL);
/*
* If this is a memory resource, map it into the kernel.
@@ -445,58 +523,64 @@ nexus_activate_resource(device_t bus, de
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, length, &map->r_bushandle);
if (error)
return (error);
- rman_set_bushandle(r, bh);
#else
- rman_set_bushandle(r, rman_get_start(r));
+ map->r_bushandle = start;
#endif
- rman_set_bustag(r, X86_BUS_SPACE_IO);
+ map->r_bustag = X86_BUS_SPACE_IO;
+ map->r_size = length;
+ 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, length, &map->r_bushandle);
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, length, args.memattr);
+ map->r_bustag = X86_BUS_SPACE_MEM;
+ map->r_size = length;
+
+ /*
+ * 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_bushandle->bsh_base = (bus_addr_t)map->r_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_bushandle = (bus_space_handle_t)map->r_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));
- }
+ switch (type) {
+ case SYS_RES_MEMORY:
+ pmap_unmapdev((vm_offset_t)map->r_vaddr, map->r_size);
+ /* FALLTHROUGH */
+ case SYS_RES_IOPORT:
#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_bustag, map->r_bushandle,
+ map->r_bushandle->bsh_sz);
#endif
- return (rman_deactivate_resource(r));
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (0);
}
static int
More information about the svn-src-all
mailing list