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