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