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