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