summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/subr_bus.c')
-rw-r--r--sys/kern/subr_bus.c94
1 files changed, 89 insertions, 5 deletions
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index f491643..af3ca57 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -3951,6 +3951,23 @@ bus_generic_new_pass(device_t dev)
}
/**
+ * @brief Helper function for implementing BUS_MAP_INTR().
+ *
+ * This simple implementation of BUS_MAP_INTR() simply calls the
+ * BUS_MAP_INTR() method of the parent of @p dev.
+ */
+int
+bus_generic_map_intr(device_t dev, device_t child, int *rid, rman_res_t *start,
+ rman_res_t *end, rman_res_t *count, struct intr_map_data **imd)
+{
+ /* Propagate up the bus hierarchy until someone handles it. */
+ if (dev->parent)
+ return (BUS_MAP_INTR(dev->parent, child, rid, start, end, count,
+ imd));
+ return (EINVAL);
+}
+
+/**
* @brief Helper function for implementing BUS_SETUP_INTR().
*
* This simple implementation of BUS_SETUP_INTR() simply calls the
@@ -4405,6 +4422,41 @@ bus_release_resources(device_t dev, const struct resource_spec *rs,
}
}
+#ifdef INTRNG
+/**
+ * @internal
+ *
+ * This can be converted to bus method later. (XXX)
+ */
+static struct intr_map_data *
+bus_extend_resource(device_t dev, int type, int *rid, rman_res_t *start,
+ rman_res_t *end, rman_res_t *count)
+{
+ struct intr_map_data *imd;
+ struct resource_list *rl;
+ int rv;
+
+ if (dev->parent == NULL)
+ return (NULL);
+ if (type != SYS_RES_IRQ)
+ return (NULL);
+
+ if (!RMAN_IS_DEFAULT_RANGE(*start, *end))
+ return (NULL);
+ rl = BUS_GET_RESOURCE_LIST(dev->parent, dev);
+ if (rl != NULL) {
+ if (resource_list_find(rl, type, *rid) != NULL)
+ return (NULL);
+ }
+ rv = BUS_MAP_INTR(dev->parent, dev, rid, start, end, count, &imd);
+ if (rv != 0)
+ return (NULL);
+ if (rl != NULL)
+ resource_list_add(rl, type, *rid, *start, *end, *count);
+ return (imd);
+}
+#endif
+
/**
* @brief Wrapper function for BUS_ALLOC_RESOURCE().
*
@@ -4412,13 +4464,31 @@ bus_release_resources(device_t dev, const struct resource_spec *rs,
* parent of @p dev.
*/
struct resource *
-bus_alloc_resource(device_t dev, int type, int *rid, rman_res_t start, rman_res_t end,
- rman_res_t count, u_int flags)
+bus_alloc_resource(device_t dev, int type, int *rid, rman_res_t start,
+ rman_res_t end, rman_res_t count, u_int flags)
{
+ struct resource *res;
+#ifdef INTRNG
+ struct intr_map_data *imd;
+#endif
+
if (dev->parent == NULL)
return (NULL);
- return (BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end,
- count, flags));
+
+#ifdef INTRNG
+ imd = bus_extend_resource(dev, type, rid, &start, &end, &count);
+#endif
+ res = BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end,
+ count, flags);
+#ifdef INTRNG
+ if (imd != NULL) {
+ if (res != NULL && rman_get_virtual(res) == NULL)
+ rman_set_virtual(res, imd);
+ else
+ imd->destruct(imd);
+ }
+#endif
+ return (res);
}
/**
@@ -4503,9 +4573,23 @@ bus_unmap_resource(device_t dev, int type, struct resource *r,
int
bus_release_resource(device_t dev, int type, int rid, struct resource *r)
{
+ int rv;
+#ifdef INTRNG
+ struct intr_map_data *imd;
+#endif
+
if (dev->parent == NULL)
return (EINVAL);
- return (BUS_RELEASE_RESOURCE(dev->parent, dev, type, rid, r));
+
+#ifdef INTRNG
+ imd = (type == SYS_RES_IRQ) ? rman_get_virtual(r) : NULL;
+#endif
+ rv = BUS_RELEASE_RESOURCE(dev->parent, dev, type, rid, r);
+#ifdef INTRNG
+ if (imd != NULL)
+ imd->destruct(imd);
+#endif
+ return (rv);
}
/**
OpenPOWER on IntegriCloud