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
bhndb_dw_exhausted(struct bhndb_resources * br)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 *
bhndb_dw_next_free(struct bhndb_resources * br)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
bhndb_dw_is_free(struct bhndb_resources * br,struct bhndb_dw_alloc * dwa)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