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