1 /*- 2 * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org> 3 * Copyright (c) 2017 The FreeBSD Foundation 4 * All rights reserved. 5 * 6 * Portions of this software were developed by Landon Fuller 7 * under sponsorship from the FreeBSD Foundation. 8 * 9 * Portions of this software were developed by Landon Fuller 10 * under sponsorship from the FreeBSD Foundation. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 20 * redistribution must be conditioned upon including a substantially 21 * similar Disclaimer requirement for further binary redistribution. 22 * 23 * NO WARRANTY 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 28 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 29 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 32 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 34 * THE POSSIBILITY OF SUCH DAMAGES. 35 * 36 */ 37 38 #ifndef _BHND_BHNDB_PRIVATE_H_ 39 #define _BHND_BHNDB_PRIVATE_H_ 40 41 #include <sys/param.h> 42 #include <sys/bitstring.h> 43 #include <sys/bus.h> 44 #include <sys/systm.h> 45 46 #include <machine/bus.h> 47 #include <sys/rman.h> 48 #include <machine/resource.h> 49 50 #include "bhndbvar.h" 51 52 /* 53 * Private bhndb(4) driver definitions. 54 */ 55 56 struct bhndb_dw_alloc; 57 struct bhndb_intr_handler; 58 struct bhndb_region; 59 struct bhndb_resources; 60 61 struct bhndb_resources *bhndb_alloc_resources(device_t dev, 62 device_t parent_dev, 63 const struct bhndb_hwcfg *cfg); 64 65 void bhndb_free_resources( 66 struct bhndb_resources *br); 67 68 int bhndb_add_resource_region( 69 struct bhndb_resources *br, 70 bhnd_addr_t addr, bhnd_size_t size, 71 bhndb_priority_t priority, 72 uint32_t alloc_flags, 73 const struct bhndb_regwin *static_regwin); 74 75 int bhndb_find_resource_limits( 76 struct bhndb_resources *br, int type, 77 struct resource *r, rman_res_t *start, 78 rman_res_t *end); 79 80 struct bhndb_intr_handler *bhndb_alloc_intr_handler(device_t owner, 81 struct resource *r, 82 struct bhndb_intr_isrc *isrc); 83 void bhndb_free_intr_handler( 84 struct bhndb_intr_handler *ih); 85 86 void bhndb_register_intr_handler( 87 struct bhndb_resources *br, 88 struct bhndb_intr_handler *ih); 89 void bhndb_deregister_intr_handler( 90 struct bhndb_resources *br, 91 struct bhndb_intr_handler *ih); 92 struct bhndb_intr_handler *bhndb_find_intr_handler( 93 struct bhndb_resources *br, 94 void *cookiep); 95 96 bool bhndb_has_static_region_mapping( 97 struct bhndb_resources *br, 98 bhnd_addr_t addr, bhnd_size_t size); 99 100 struct bhndb_region *bhndb_find_resource_region( 101 struct bhndb_resources *br, 102 bhnd_addr_t addr, bhnd_size_t size); 103 104 struct bhndb_dw_alloc *bhndb_dw_find_resource( 105 struct bhndb_resources *dr, 106 struct resource *r); 107 108 struct bhndb_dw_alloc *bhndb_dw_find_mapping( 109 struct bhndb_resources *br, 110 bhnd_addr_t addr, bhnd_size_t size); 111 112 int bhndb_dw_retain( 113 struct bhndb_resources *br, 114 struct bhndb_dw_alloc *dwa, 115 struct resource *res); 116 117 void bhndb_dw_release( 118 struct bhndb_resources *br, 119 struct bhndb_dw_alloc *dwa, 120 struct resource *res); 121 122 int bhndb_dw_set_addr(device_t dev, 123 struct bhndb_resources *br, 124 struct bhndb_dw_alloc *dwa, 125 bus_addr_t addr, bus_size_t size); 126 127 struct bhndb_dw_alloc *bhndb_dw_steal(struct bhndb_resources *br, 128 bus_addr_t *saved); 129 130 void bhndb_dw_return_stolen(device_t dev, 131 struct bhndb_resources *br, 132 struct bhndb_dw_alloc *dwa, 133 bus_addr_t saved); 134 135 const struct bhndb_hw_priority *bhndb_hw_priority_find_core( 136 const struct bhndb_hw_priority *table, 137 struct bhnd_core_info *core); 138 139 const struct bhndb_port_priority *bhndb_hw_priorty_find_port( 140 const struct bhndb_hw_priority *table, 141 struct bhnd_core_info *core, 142 bhnd_port_type port_type, u_int port, 143 u_int region); 144 145 /** 146 * Dynamic register window allocation reference. 147 */ 148 struct bhndb_dw_rentry { 149 struct resource *dw_res; /**< child resource */ 150 LIST_ENTRY(bhndb_dw_rentry) dw_link; 151 }; 152 153 /** 154 * A dynamic register window allocation record. 155 */ 156 struct bhndb_dw_alloc { 157 const struct bhndb_regwin *win; /**< window definition */ 158 struct resource *parent_res; /**< enclosing resource */ 159 u_int rnid; /**< region identifier */ 160 rman_res_t target; /**< the current window address, or 0x0 if unknown */ 161 162 LIST_HEAD(, bhndb_dw_rentry) refs; /**< references */ 163 }; 164 165 /** 166 * A bus address region description. 167 */ 168 struct bhndb_region { 169 bhnd_addr_t addr; /**< start of mapped range */ 170 bhnd_size_t size; /**< size of mapped range */ 171 bhndb_priority_t priority; /**< direct resource allocation priority */ 172 uint32_t alloc_flags; /**< resource allocation flags (@see bhndb_alloc_flags) */ 173 const struct bhndb_regwin *static_regwin; /**< fixed mapping regwin, if any */ 174 175 STAILQ_ENTRY(bhndb_region) link; 176 }; 177 178 /** 179 * Attached interrupt handler state 180 */ 181 struct bhndb_intr_handler { 182 device_t ih_owner; /**< child device */ 183 struct resource *ih_res; /**< child resource */ 184 void *ih_cookiep; /**< hostb-assigned cookiep, or NULL if bus_setup_intr() incomplete. */ 185 struct bhndb_intr_isrc *ih_isrc; /**< host interrupt source routing the child's interrupt */ 186 bool ih_active; /**< handler has been registered via bhndb_register_intr_handler */ 187 188 STAILQ_ENTRY(bhndb_intr_handler) ih_link; 189 }; 190 191 /** 192 * BHNDB resource allocation state. 193 */ 194 struct bhndb_resources { 195 device_t dev; /**< bridge device */ 196 const struct bhndb_hwcfg *cfg; /**< hardware configuration */ 197 198 struct bhndb_host_resources *res; /**< host resources, or NULL if not allocated */ 199 200 struct rman ht_mem_rman; /**< host memory manager */ 201 struct rman br_mem_rman; /**< bridged memory manager */ 202 struct rman br_irq_rman; /**< bridged irq manager */ 203 204 STAILQ_HEAD(, bhndb_region) bus_regions; /**< bus region descriptors */ 205 206 struct mtx dw_steal_mtx; /**< spinlock must be held when stealing a dynamic window allocation */ 207 struct bhndb_dw_alloc *dw_alloc; /**< dynamic window allocation records */ 208 size_t dwa_count; /**< number of dynamic windows available. */ 209 bitstr_t *dwa_freelist; /**< dynamic window free list */ 210 bhndb_priority_t min_prio; /**< minimum resource priority required to 211 allocate a dynamic window */ 212 213 STAILQ_HEAD(,bhndb_intr_handler) bus_intrs; /**< attached child interrupt handlers */ 214 }; 215 216 /** 217 * Returns true if the all dynamic windows are marked free, false 218 * otherwise. 219 * 220 * @param br The resource state to check. 221 */ 222 static inline bool 223 bhndb_dw_all_free(struct bhndb_resources *br) 224 { 225 int bit; 226 bit_ffs(br->dwa_freelist, br->dwa_count, &bit); 227 return (bit == -1); 228 } 229 230 /** 231 * Find the next free dynamic window region in @p br. 232 * 233 * @param br The resource state to search. 234 */ 235 static inline struct bhndb_dw_alloc * 236 bhndb_dw_next_free(struct bhndb_resources *br) 237 { 238 struct bhndb_dw_alloc *dw_free; 239 int bit; 240 241 bit_ffc(br->dwa_freelist, br->dwa_count, &bit); 242 if (bit == -1) 243 return (NULL); 244 245 dw_free = &br->dw_alloc[bit]; 246 247 KASSERT(LIST_EMPTY(&dw_free->refs), 248 ("free list out of sync with refs")); 249 250 return (dw_free); 251 } 252 253 /** 254 * Returns true if a dynamic window allocation is marked as free. 255 * 256 * @param br The resource state owning @p dwa. 257 * @param dwa The dynamic window allocation record to be checked. 258 */ 259 static inline bool 260 bhndb_dw_is_free(struct bhndb_resources *br, struct bhndb_dw_alloc *dwa) 261 { 262 bool is_free = LIST_EMPTY(&dwa->refs); 263 264 KASSERT(is_free == !bit_test(br->dwa_freelist, dwa->rnid), 265 ("refs out of sync with free list")); 266 267 return (is_free); 268 } 269 270 #define BHNDB_LOCK_INIT(sc) \ 271 mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev), \ 272 "bhndb resource allocator lock", MTX_DEF) 273 #define BHNDB_LOCK(sc) mtx_lock(&(sc)->sc_mtx) 274 #define BHNDB_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) 275 #define BHNDB_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->sc_mtx, what) 276 #define BHNDB_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx) 277 278 #endif /* _BHND_BHNDB_PRIVATE_H_ */ 279