Index: head/sys/kern/bus_if.m =================================================================== --- head/sys/kern/bus_if.m +++ head/sys/kern/bus_if.m @@ -418,6 +418,35 @@ }; /** + * @brief Map an interrupt + * + * This method is used to get an interrupt mapping data according to provided + * hints. The hints could be modified afterwards, but only if mapping data was + * allocated. This method is intended to be called before BUS_ALLOC_RESOURCE(). + * + * @param _dev the parent device of @p _child + * @param _child the device which is requesting an allocation + * @param _rid a pointer to the resource identifier + * @param _start a pointer to the hint at the start of the resource + * range - pass @c 0 for any start address + * @param _end a pointer to the hint at the end of the resource + * range - pass @c ~0 for any end address + * @param _count a pointer to the hint at the size of resource + * range required - pass @c 1 for any size + * @param _imd a pointer to the interrupt mapping data which was + * allocated + */ +METHOD int 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; +} DEFAULT bus_generic_map_intr; + +/** * @brief Install an interrupt handler * * This method is used to associate an interrupt handler function with Index: head/sys/kern/subr_bus.c =================================================================== --- head/sys/kern/subr_bus.c +++ head/sys/kern/subr_bus.c @@ -3951,6 +3951,23 @@ } /** + * @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 @@ } } +#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 @@ * 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 @@ 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); } /** Index: head/sys/kern/subr_intr.c =================================================================== --- head/sys/kern/subr_intr.c +++ head/sys/kern/subr_intr.c @@ -560,7 +560,6 @@ mtx_unlock(&isrc_table_lock); ddata->idd_data = (struct intr_map_data *)((uintptr_t)ddata + size); - ddata->idd_data->size = extsize; return (ddata); } Index: head/sys/sys/bus.h =================================================================== --- head/sys/sys/bus.h +++ head/sys/sys/bus.h @@ -272,6 +272,17 @@ INTR_POLARITY_LOW = 2 }; +enum intr_map_data_type { + INTR_MAP_DATA_ACPI, + INTR_MAP_DATA_FDT, + INTR_MAP_DATA_GPIO, +}; + +struct intr_map_data { + enum intr_map_data_type type; + void (*destruct)(struct intr_map_data *); +}; + /** * CPU sets supported by bus_get_cpus(). Note that not all sets may be * supported for a given device. If a request is not supported by a @@ -448,6 +459,9 @@ int type, int rid, struct resource *r); int bus_generic_resume(device_t dev); int bus_generic_resume_child(device_t dev, device_t child); +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); int bus_generic_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_filter_t *filter, driver_intr_t *intr, Index: head/sys/sys/intr.h =================================================================== --- head/sys/sys/intr.h +++ head/sys/sys/intr.h @@ -34,17 +34,6 @@ #define INTR_IRQ_INVALID 0xFFFFFFFF -enum intr_map_data_type { - INTR_MAP_DATA_ACPI, - INTR_MAP_DATA_FDT, - INTR_MAP_DATA_GPIO, -}; - -struct intr_map_data { - enum intr_map_data_type type; - size_t size; -}; - #ifdef DEV_ACPI struct intr_map_data_acpi { struct intr_map_data hdr;