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