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