14ad7e9b0SAdrian Chadd /*- 289294a78SLandon J. Fuller * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org> 3caeff9a3SLandon J. Fuller * Copyright (c) 2017 The FreeBSD Foundation 44ad7e9b0SAdrian Chadd * All rights reserved. 54ad7e9b0SAdrian Chadd * 689294a78SLandon J. Fuller * Portions of this software were developed by Landon Fuller 789294a78SLandon J. Fuller * under sponsorship from the FreeBSD Foundation. 889294a78SLandon J. Fuller * 9caeff9a3SLandon J. Fuller * Portions of this software were developed by Landon Fuller 10caeff9a3SLandon J. Fuller * under sponsorship from the FreeBSD Foundation. 11caeff9a3SLandon J. Fuller * 124ad7e9b0SAdrian Chadd * Redistribution and use in source and binary forms, with or without 134ad7e9b0SAdrian Chadd * modification, are permitted provided that the following conditions 144ad7e9b0SAdrian Chadd * are met: 154ad7e9b0SAdrian Chadd * 1. Redistributions of source code must retain the above copyright 164ad7e9b0SAdrian Chadd * notice, this list of conditions and the following disclaimer, 174ad7e9b0SAdrian Chadd * without modification. 184ad7e9b0SAdrian Chadd * 2. Redistributions in binary form must reproduce at minimum a disclaimer 194ad7e9b0SAdrian Chadd * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 204ad7e9b0SAdrian Chadd * redistribution must be conditioned upon including a substantially 214ad7e9b0SAdrian Chadd * similar Disclaimer requirement for further binary redistribution. 224ad7e9b0SAdrian Chadd * 234ad7e9b0SAdrian Chadd * NO WARRANTY 244ad7e9b0SAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 254ad7e9b0SAdrian Chadd * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 264ad7e9b0SAdrian Chadd * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 274ad7e9b0SAdrian Chadd * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 284ad7e9b0SAdrian Chadd * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 294ad7e9b0SAdrian Chadd * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 304ad7e9b0SAdrian Chadd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 314ad7e9b0SAdrian Chadd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 324ad7e9b0SAdrian Chadd * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 334ad7e9b0SAdrian Chadd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 344ad7e9b0SAdrian Chadd * THE POSSIBILITY OF SUCH DAMAGES. 354ad7e9b0SAdrian Chadd * 364ad7e9b0SAdrian Chadd * $FreeBSD$ 374ad7e9b0SAdrian Chadd */ 384ad7e9b0SAdrian Chadd 394ad7e9b0SAdrian Chadd #ifndef _BHND_BHNDB_PRIVATE_H_ 404ad7e9b0SAdrian Chadd #define _BHND_BHNDB_PRIVATE_H_ 414ad7e9b0SAdrian Chadd 424ad7e9b0SAdrian Chadd #include <sys/param.h> 439dfeb414SLandon J. Fuller #include <sys/bitstring.h> 444ad7e9b0SAdrian Chadd #include <sys/bus.h> 454ad7e9b0SAdrian Chadd #include <sys/systm.h> 464ad7e9b0SAdrian Chadd 474ad7e9b0SAdrian Chadd #include <machine/bus.h> 484ad7e9b0SAdrian Chadd #include <sys/rman.h> 494ad7e9b0SAdrian Chadd #include <machine/resource.h> 504ad7e9b0SAdrian Chadd 514ad7e9b0SAdrian Chadd #include "bhndbvar.h" 524ad7e9b0SAdrian Chadd 534ad7e9b0SAdrian Chadd /* 544ad7e9b0SAdrian Chadd * Private bhndb(4) driver definitions. 554ad7e9b0SAdrian Chadd */ 564ad7e9b0SAdrian Chadd 574ad7e9b0SAdrian Chadd struct bhndb_dw_alloc; 58caeff9a3SLandon J. Fuller struct bhndb_intr_handler; 594ad7e9b0SAdrian Chadd struct bhndb_region; 604ad7e9b0SAdrian Chadd struct bhndb_resources; 614ad7e9b0SAdrian Chadd 624ad7e9b0SAdrian Chadd struct bhndb_resources *bhndb_alloc_resources(device_t dev, 634ad7e9b0SAdrian Chadd device_t parent_dev, 644ad7e9b0SAdrian Chadd const struct bhndb_hwcfg *cfg); 654ad7e9b0SAdrian Chadd 664ad7e9b0SAdrian Chadd void bhndb_free_resources( 674ad7e9b0SAdrian Chadd struct bhndb_resources *br); 684ad7e9b0SAdrian Chadd 694ad7e9b0SAdrian Chadd int bhndb_add_resource_region( 704ad7e9b0SAdrian Chadd struct bhndb_resources *br, 714ad7e9b0SAdrian Chadd bhnd_addr_t addr, bhnd_size_t size, 724ad7e9b0SAdrian Chadd bhndb_priority_t priority, 73*eaa5fb4bSLandon J. Fuller uint32_t alloc_flags, 744ad7e9b0SAdrian Chadd const struct bhndb_regwin *static_regwin); 754ad7e9b0SAdrian Chadd 76249f3d3fSAdrian Chadd int bhndb_find_resource_limits( 77caeff9a3SLandon J. Fuller struct bhndb_resources *br, int type, 78249f3d3fSAdrian Chadd struct resource *r, rman_res_t *start, 79249f3d3fSAdrian Chadd rman_res_t *end); 80249f3d3fSAdrian Chadd 81caeff9a3SLandon J. Fuller struct bhndb_intr_handler *bhndb_alloc_intr_handler(device_t owner, 82caeff9a3SLandon J. Fuller struct resource *r, 83caeff9a3SLandon J. Fuller struct bhndb_intr_isrc *isrc); 84caeff9a3SLandon J. Fuller void bhndb_free_intr_handler( 85caeff9a3SLandon J. Fuller struct bhndb_intr_handler *ih); 86caeff9a3SLandon J. Fuller 87caeff9a3SLandon J. Fuller void bhndb_register_intr_handler( 88caeff9a3SLandon J. Fuller struct bhndb_resources *br, 89caeff9a3SLandon J. Fuller struct bhndb_intr_handler *ih); 90caeff9a3SLandon J. Fuller void bhndb_deregister_intr_handler( 91caeff9a3SLandon J. Fuller struct bhndb_resources *br, 92caeff9a3SLandon J. Fuller struct bhndb_intr_handler *ih); 93caeff9a3SLandon J. Fuller struct bhndb_intr_handler *bhndb_find_intr_handler( 94caeff9a3SLandon J. Fuller struct bhndb_resources *br, 95caeff9a3SLandon J. Fuller void *cookiep); 96caeff9a3SLandon J. Fuller 97*eaa5fb4bSLandon J. Fuller bool bhndb_has_static_region_mapping( 98*eaa5fb4bSLandon J. Fuller struct bhndb_resources *br, 99*eaa5fb4bSLandon J. Fuller bhnd_addr_t addr, bhnd_size_t size); 100*eaa5fb4bSLandon J. Fuller 1014ad7e9b0SAdrian Chadd struct bhndb_region *bhndb_find_resource_region( 1024ad7e9b0SAdrian Chadd struct bhndb_resources *br, 1034ad7e9b0SAdrian Chadd bhnd_addr_t addr, bhnd_size_t size); 1044ad7e9b0SAdrian Chadd 1054ad7e9b0SAdrian Chadd struct bhndb_dw_alloc *bhndb_dw_find_resource( 1064ad7e9b0SAdrian Chadd struct bhndb_resources *dr, 1074ad7e9b0SAdrian Chadd struct resource *r); 1084ad7e9b0SAdrian Chadd 1094ad7e9b0SAdrian Chadd struct bhndb_dw_alloc *bhndb_dw_find_mapping( 1104ad7e9b0SAdrian Chadd struct bhndb_resources *br, 1114ad7e9b0SAdrian Chadd bhnd_addr_t addr, bhnd_size_t size); 1124ad7e9b0SAdrian Chadd 1134ad7e9b0SAdrian Chadd int bhndb_dw_retain( 1144ad7e9b0SAdrian Chadd struct bhndb_resources *br, 1154ad7e9b0SAdrian Chadd struct bhndb_dw_alloc *dwa, 1164ad7e9b0SAdrian Chadd struct resource *res); 1174ad7e9b0SAdrian Chadd 1184ad7e9b0SAdrian Chadd void bhndb_dw_release( 1194ad7e9b0SAdrian Chadd struct bhndb_resources *br, 1204ad7e9b0SAdrian Chadd struct bhndb_dw_alloc *dwa, 1214ad7e9b0SAdrian Chadd struct resource *res); 1224ad7e9b0SAdrian Chadd 1234ad7e9b0SAdrian Chadd int bhndb_dw_set_addr(device_t dev, 1244ad7e9b0SAdrian Chadd struct bhndb_resources *br, 1254ad7e9b0SAdrian Chadd struct bhndb_dw_alloc *dwa, 1264ad7e9b0SAdrian Chadd bus_addr_t addr, bus_size_t size); 1274ad7e9b0SAdrian Chadd 128*eaa5fb4bSLandon J. Fuller struct bhndb_dw_alloc *bhndb_dw_steal(struct bhndb_resources *br, 129*eaa5fb4bSLandon J. Fuller bus_addr_t *saved); 130*eaa5fb4bSLandon J. Fuller 131*eaa5fb4bSLandon J. Fuller void bhndb_dw_return_stolen(device_t dev, 132*eaa5fb4bSLandon J. Fuller struct bhndb_resources *br, 133*eaa5fb4bSLandon J. Fuller struct bhndb_dw_alloc *dwa, 134*eaa5fb4bSLandon J. Fuller bus_addr_t saved); 135*eaa5fb4bSLandon J. Fuller 136111d7cb2SLandon J. Fuller const struct bhndb_hw_priority *bhndb_hw_priority_find_core( 1374ad7e9b0SAdrian Chadd const struct bhndb_hw_priority *table, 138111d7cb2SLandon J. Fuller struct bhnd_core_info *core); 1394ad7e9b0SAdrian Chadd 140*eaa5fb4bSLandon J. Fuller const struct bhndb_port_priority *bhndb_hw_priorty_find_port( 141*eaa5fb4bSLandon J. Fuller const struct bhndb_hw_priority *table, 142*eaa5fb4bSLandon J. Fuller struct bhnd_core_info *core, 143*eaa5fb4bSLandon J. Fuller bhnd_port_type port_type, u_int port, 144*eaa5fb4bSLandon J. Fuller u_int region); 145*eaa5fb4bSLandon J. Fuller 1464ad7e9b0SAdrian Chadd 1474ad7e9b0SAdrian Chadd /** 1484ad7e9b0SAdrian Chadd * Dynamic register window allocation reference. 1494ad7e9b0SAdrian Chadd */ 1504ad7e9b0SAdrian Chadd struct bhndb_dw_rentry { 1514ad7e9b0SAdrian Chadd struct resource *dw_res; /**< child resource */ 1524ad7e9b0SAdrian Chadd LIST_ENTRY(bhndb_dw_rentry) dw_link; 1534ad7e9b0SAdrian Chadd }; 1544ad7e9b0SAdrian Chadd 1554ad7e9b0SAdrian Chadd /** 1564ad7e9b0SAdrian Chadd * A dynamic register window allocation record. 1574ad7e9b0SAdrian Chadd */ 1584ad7e9b0SAdrian Chadd struct bhndb_dw_alloc { 1594ad7e9b0SAdrian Chadd const struct bhndb_regwin *win; /**< window definition */ 1604ad7e9b0SAdrian Chadd struct resource *parent_res; /**< enclosing resource */ 1614ad7e9b0SAdrian Chadd u_int rnid; /**< region identifier */ 1624ad7e9b0SAdrian Chadd rman_res_t target; /**< the current window address, or 0x0 if unknown */ 1634ad7e9b0SAdrian Chadd 1644ad7e9b0SAdrian Chadd LIST_HEAD(, bhndb_dw_rentry) refs; /**< references */ 1654ad7e9b0SAdrian Chadd }; 1664ad7e9b0SAdrian Chadd 1674ad7e9b0SAdrian Chadd /** 1684ad7e9b0SAdrian Chadd * A bus address region description. 1694ad7e9b0SAdrian Chadd */ 1704ad7e9b0SAdrian Chadd struct bhndb_region { 1714ad7e9b0SAdrian Chadd bhnd_addr_t addr; /**< start of mapped range */ 1724ad7e9b0SAdrian Chadd bhnd_size_t size; /**< size of mapped range */ 1734ad7e9b0SAdrian Chadd bhndb_priority_t priority; /**< direct resource allocation priority */ 174*eaa5fb4bSLandon J. Fuller uint32_t alloc_flags; /**< resource allocation flags (@see bhndb_alloc_flags) */ 1754ad7e9b0SAdrian Chadd const struct bhndb_regwin *static_regwin; /**< fixed mapping regwin, if any */ 1764ad7e9b0SAdrian Chadd 1774ad7e9b0SAdrian Chadd STAILQ_ENTRY(bhndb_region) link; 1784ad7e9b0SAdrian Chadd }; 1794ad7e9b0SAdrian Chadd 1804ad7e9b0SAdrian Chadd /** 181caeff9a3SLandon J. Fuller * Attached interrupt handler state 182caeff9a3SLandon J. Fuller */ 183caeff9a3SLandon J. Fuller struct bhndb_intr_handler { 184caeff9a3SLandon J. Fuller device_t ih_owner; /**< child device */ 185caeff9a3SLandon J. Fuller struct resource *ih_res; /**< child resource */ 186caeff9a3SLandon J. Fuller void *ih_cookiep; /**< hostb-assigned cookiep, or NULL if bus_setup_intr() incomplete. */ 187caeff9a3SLandon J. Fuller struct bhndb_intr_isrc *ih_isrc; /**< host interrupt source routing the child's interrupt */ 188caeff9a3SLandon J. Fuller bool ih_active; /**< handler has been registered via bhndb_register_intr_handler */ 189caeff9a3SLandon J. Fuller 190caeff9a3SLandon J. Fuller STAILQ_ENTRY(bhndb_intr_handler) ih_link; 191caeff9a3SLandon J. Fuller }; 192caeff9a3SLandon J. Fuller 193caeff9a3SLandon J. Fuller /** 1944ad7e9b0SAdrian Chadd * BHNDB resource allocation state. 1954ad7e9b0SAdrian Chadd */ 1964ad7e9b0SAdrian Chadd struct bhndb_resources { 1974ad7e9b0SAdrian Chadd device_t dev; /**< bridge device */ 1984ad7e9b0SAdrian Chadd const struct bhndb_hwcfg *cfg; /**< hardware configuration */ 1994ad7e9b0SAdrian Chadd 20089294a78SLandon J. Fuller struct bhndb_host_resources *res; /**< host resources, or NULL if not allocated */ 2014ad7e9b0SAdrian Chadd 202e9378f45SAdrian Chadd struct rman ht_mem_rman; /**< host memory manager */ 203e9378f45SAdrian Chadd struct rman br_mem_rman; /**< bridged memory manager */ 204caeff9a3SLandon J. Fuller struct rman br_irq_rman; /**< bridged irq manager */ 205e9378f45SAdrian Chadd 2064ad7e9b0SAdrian Chadd STAILQ_HEAD(, bhndb_region) bus_regions; /**< bus region descriptors */ 2074ad7e9b0SAdrian Chadd 208*eaa5fb4bSLandon J. Fuller struct mtx dw_steal_mtx; /**< spinlock must be held when stealing a dynamic window allocation */ 2094ad7e9b0SAdrian Chadd struct bhndb_dw_alloc *dw_alloc; /**< dynamic window allocation records */ 2104ad7e9b0SAdrian Chadd size_t dwa_count; /**< number of dynamic windows available. */ 2119dfeb414SLandon J. Fuller bitstr_t *dwa_freelist; /**< dynamic window free list */ 2124ad7e9b0SAdrian Chadd bhndb_priority_t min_prio; /**< minimum resource priority required to 2134ad7e9b0SAdrian Chadd allocate a dynamic window */ 214caeff9a3SLandon J. Fuller 215caeff9a3SLandon J. Fuller STAILQ_HEAD(,bhndb_intr_handler) bus_intrs; /**< attached child interrupt handlers */ 2164ad7e9b0SAdrian Chadd }; 2174ad7e9b0SAdrian Chadd 2184ad7e9b0SAdrian Chadd /** 2199dfeb414SLandon J. Fuller * Returns true if the all dynamic windows are marked free, false 2204ad7e9b0SAdrian Chadd * otherwise. 2214ad7e9b0SAdrian Chadd * 2224ad7e9b0SAdrian Chadd * @param br The resource state to check. 2234ad7e9b0SAdrian Chadd */ 2244ad7e9b0SAdrian Chadd static inline bool 2259dfeb414SLandon J. Fuller bhndb_dw_all_free(struct bhndb_resources *br) 2264ad7e9b0SAdrian Chadd { 2279dfeb414SLandon J. Fuller int bit; 2289dfeb414SLandon J. Fuller bit_ffs(br->dwa_freelist, br->dwa_count, &bit); 2299dfeb414SLandon J. Fuller return (bit == -1); 2304ad7e9b0SAdrian Chadd } 2314ad7e9b0SAdrian Chadd 2324ad7e9b0SAdrian Chadd /** 2334ad7e9b0SAdrian Chadd * Find the next free dynamic window region in @p br. 2344ad7e9b0SAdrian Chadd * 2354ad7e9b0SAdrian Chadd * @param br The resource state to search. 2364ad7e9b0SAdrian Chadd */ 2374ad7e9b0SAdrian Chadd static inline struct bhndb_dw_alloc * 2384ad7e9b0SAdrian Chadd bhndb_dw_next_free(struct bhndb_resources *br) 2394ad7e9b0SAdrian Chadd { 2404ad7e9b0SAdrian Chadd struct bhndb_dw_alloc *dw_free; 2419dfeb414SLandon J. Fuller int bit; 2424ad7e9b0SAdrian Chadd 2439dfeb414SLandon J. Fuller bit_ffc(br->dwa_freelist, br->dwa_count, &bit); 2449dfeb414SLandon J. Fuller if (bit == -1) 2454ad7e9b0SAdrian Chadd return (NULL); 2464ad7e9b0SAdrian Chadd 2479dfeb414SLandon J. Fuller dw_free = &br->dw_alloc[bit]; 2484ad7e9b0SAdrian Chadd 2494ad7e9b0SAdrian Chadd KASSERT(LIST_EMPTY(&dw_free->refs), 2504ad7e9b0SAdrian Chadd ("free list out of sync with refs")); 2514ad7e9b0SAdrian Chadd 2524ad7e9b0SAdrian Chadd return (dw_free); 2534ad7e9b0SAdrian Chadd } 2544ad7e9b0SAdrian Chadd 2554ad7e9b0SAdrian Chadd /** 2564ad7e9b0SAdrian Chadd * Returns true if a dynamic window allocation is marked as free. 2574ad7e9b0SAdrian Chadd * 2584ad7e9b0SAdrian Chadd * @param br The resource state owning @p dwa. 2594ad7e9b0SAdrian Chadd * @param dwa The dynamic window allocation record to be checked. 2604ad7e9b0SAdrian Chadd */ 2614ad7e9b0SAdrian Chadd static inline bool 2624ad7e9b0SAdrian Chadd bhndb_dw_is_free(struct bhndb_resources *br, struct bhndb_dw_alloc *dwa) 2634ad7e9b0SAdrian Chadd { 2644ad7e9b0SAdrian Chadd bool is_free = LIST_EMPTY(&dwa->refs); 2654ad7e9b0SAdrian Chadd 2669dfeb414SLandon J. Fuller KASSERT(is_free == !bit_test(br->dwa_freelist, dwa->rnid), 2674ad7e9b0SAdrian Chadd ("refs out of sync with free list")); 2684ad7e9b0SAdrian Chadd 2694ad7e9b0SAdrian Chadd return (is_free); 2704ad7e9b0SAdrian Chadd } 2714ad7e9b0SAdrian Chadd 2724ad7e9b0SAdrian Chadd 2734ad7e9b0SAdrian Chadd #define BHNDB_LOCK_INIT(sc) \ 2744ad7e9b0SAdrian Chadd mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev), \ 2754ad7e9b0SAdrian Chadd "bhndb resource allocator lock", MTX_DEF) 2764ad7e9b0SAdrian Chadd #define BHNDB_LOCK(sc) mtx_lock(&(sc)->sc_mtx) 2774ad7e9b0SAdrian Chadd #define BHNDB_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) 2784ad7e9b0SAdrian Chadd #define BHNDB_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->sc_mtx, what) 2794ad7e9b0SAdrian Chadd #define BHNDB_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx) 2804ad7e9b0SAdrian Chadd 2814ad7e9b0SAdrian Chadd #endif /* _BHND_BHNDB_PRIVATE_H_ */ 282