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 void bhndb_free_resources( 67 struct bhndb_resources *br); 68 69 int bhndb_add_resource_region( 70 struct bhndb_resources *br, 71 bhnd_addr_t addr, bhnd_size_t size, 72 bhndb_priority_t priority, 73 const struct bhndb_regwin *static_regwin); 74 75 int bhndb_find_resource_limits( 76 struct bhndb_resources *br, 77 struct resource *r, rman_res_t *start, 78 rman_res_t *end); 79 80 struct bhndb_region *bhndb_find_resource_region( 81 struct bhndb_resources *br, 82 bhnd_addr_t addr, bhnd_size_t size); 83 84 struct bhndb_dw_alloc *bhndb_dw_find_resource( 85 struct bhndb_resources *dr, 86 struct resource *r); 87 88 struct bhndb_dw_alloc *bhndb_dw_find_mapping( 89 struct bhndb_resources *br, 90 bhnd_addr_t addr, bhnd_size_t size); 91 92 int bhndb_dw_retain( 93 struct bhndb_resources *br, 94 struct bhndb_dw_alloc *dwa, 95 struct resource *res); 96 97 void bhndb_dw_release( 98 struct bhndb_resources *br, 99 struct bhndb_dw_alloc *dwa, 100 struct resource *res); 101 102 int bhndb_dw_set_addr(device_t dev, 103 struct bhndb_resources *br, 104 struct bhndb_dw_alloc *dwa, 105 bus_addr_t addr, bus_size_t size); 106 107 size_t bhndb_regwin_count( 108 const struct bhndb_regwin *table, 109 bhndb_regwin_type_t type); 110 111 const struct bhndb_regwin *bhndb_regwin_find_type( 112 const struct bhndb_regwin *table, 113 bhndb_regwin_type_t type, 114 bus_size_t min_size); 115 116 const struct bhndb_regwin *bhndb_regwin_find_core( 117 const struct bhndb_regwin *table, 118 bhnd_devclass_t class, int unit, 119 bhnd_port_type port_type, u_int port, 120 u_int region); 121 122 123 const struct bhndb_regwin *bhndb_regwin_find_best( 124 const struct bhndb_regwin *table, 125 bhnd_devclass_t class, int unit, 126 bhnd_port_type port_type, u_int port, 127 u_int region, bus_size_t min_size); 128 129 bool bhndb_regwin_matches_device( 130 const struct bhndb_regwin *regw, 131 device_t dev); 132 133 const struct bhndb_hw_priority *bhndb_hw_priority_find_device( 134 const struct bhndb_hw_priority *table, 135 device_t device); 136 137 138 /** 139 * Dynamic register window allocation reference. 140 */ 141 struct bhndb_dw_rentry { 142 struct resource *dw_res; /**< child resource */ 143 LIST_ENTRY(bhndb_dw_rentry) dw_link; 144 }; 145 146 /** 147 * A dynamic register window allocation record. 148 */ 149 struct bhndb_dw_alloc { 150 const struct bhndb_regwin *win; /**< window definition */ 151 struct resource *parent_res; /**< enclosing resource */ 152 u_int rnid; /**< region identifier */ 153 rman_res_t target; /**< the current window address, or 0x0 if unknown */ 154 155 LIST_HEAD(, bhndb_dw_rentry) refs; /**< references */ 156 }; 157 158 /** 159 * A bus address region description. 160 */ 161 struct bhndb_region { 162 bhnd_addr_t addr; /**< start of mapped range */ 163 bhnd_size_t size; /**< size of mapped range */ 164 bhndb_priority_t priority; /**< direct resource allocation priority */ 165 const struct bhndb_regwin *static_regwin; /**< fixed mapping regwin, if any */ 166 167 STAILQ_ENTRY(bhndb_region) link; 168 }; 169 170 /** 171 * BHNDB resource allocation state. 172 */ 173 struct bhndb_resources { 174 device_t dev; /**< bridge device */ 175 const struct bhndb_hwcfg *cfg; /**< hardware configuration */ 176 177 device_t parent_dev; /**< parent device */ 178 struct resource_spec *res_spec; /**< parent bus resource specs */ 179 struct resource **res; /**< parent bus resources */ 180 181 struct rman ht_mem_rman; /**< host memory manager */ 182 struct rman br_mem_rman; /**< bridged memory manager */ 183 184 STAILQ_HEAD(, bhndb_region) bus_regions; /**< bus region descriptors */ 185 186 struct bhndb_dw_alloc *dw_alloc; /**< dynamic window allocation records */ 187 size_t dwa_count; /**< number of dynamic windows available. */ 188 bitstr_t *dwa_freelist; /**< dynamic window free list */ 189 bhndb_priority_t min_prio; /**< minimum resource priority required to 190 allocate a dynamic window */ 191 }; 192 193 /** 194 * Returns true if the all dynamic windows are marked free, false 195 * otherwise. 196 * 197 * @param br The resource state to check. 198 */ 199 static inline bool 200 bhndb_dw_all_free(struct bhndb_resources *br) 201 { 202 int bit; 203 bit_ffs(br->dwa_freelist, br->dwa_count, &bit); 204 return (bit == -1); 205 } 206 207 /** 208 * Find the next free dynamic window region in @p br. 209 * 210 * @param br The resource state to search. 211 */ 212 static inline struct bhndb_dw_alloc * 213 bhndb_dw_next_free(struct bhndb_resources *br) 214 { 215 struct bhndb_dw_alloc *dw_free; 216 int bit; 217 218 bit_ffc(br->dwa_freelist, br->dwa_count, &bit); 219 if (bit == -1) 220 return (NULL); 221 222 dw_free = &br->dw_alloc[bit]; 223 224 KASSERT(LIST_EMPTY(&dw_free->refs), 225 ("free list out of sync with refs")); 226 227 return (dw_free); 228 } 229 230 /** 231 * Returns true if a dynamic window allocation is marked as free. 232 * 233 * @param br The resource state owning @p dwa. 234 * @param dwa The dynamic window allocation record to be checked. 235 */ 236 static inline bool 237 bhndb_dw_is_free(struct bhndb_resources *br, struct bhndb_dw_alloc *dwa) 238 { 239 bool is_free = LIST_EMPTY(&dwa->refs); 240 241 KASSERT(is_free == !bit_test(br->dwa_freelist, dwa->rnid), 242 ("refs out of sync with free list")); 243 244 return (is_free); 245 } 246 247 248 #define BHNDB_LOCK_INIT(sc) \ 249 mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev), \ 250 "bhndb resource allocator lock", MTX_DEF) 251 #define BHNDB_LOCK(sc) mtx_lock(&(sc)->sc_mtx) 252 #define BHNDB_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) 253 #define BHNDB_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->sc_mtx, what) 254 #define BHNDB_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx) 255 256 #endif /* _BHND_BHNDB_PRIVATE_H_ */ 257