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