]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/bhnd/bhndb/bhndb_private.h
MFV r316901:
[FreeBSD/FreeBSD.git] / sys / dev / bhnd / bhndb / bhndb_private.h
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 /**
148  * Dynamic register window allocation reference.
149  */
150 struct bhndb_dw_rentry {
151         struct resource                 *dw_res;        /**< child resource */
152         LIST_ENTRY(bhndb_dw_rentry)      dw_link;
153 };
154
155 /**
156  * A dynamic register window allocation record. 
157  */
158 struct bhndb_dw_alloc {
159         const struct bhndb_regwin       *win;           /**< window definition */
160         struct resource                 *parent_res;    /**< enclosing resource */
161         u_int                            rnid;          /**< region identifier */
162         rman_res_t                       target;        /**< the current window address, or 0x0 if unknown */
163
164         LIST_HEAD(, bhndb_dw_rentry)     refs;          /**< references */
165 };
166
167 /**
168  * A bus address region description.
169  */
170 struct bhndb_region {
171         bhnd_addr_t                      addr;          /**< start of mapped range */
172         bhnd_size_t                      size;          /**< size of mapped range */
173         bhndb_priority_t                 priority;      /**< direct resource allocation priority */
174         uint32_t                         alloc_flags;   /**< resource allocation flags (@see bhndb_alloc_flags) */
175         const struct bhndb_regwin       *static_regwin; /**< fixed mapping regwin, if any */
176
177         STAILQ_ENTRY(bhndb_region)       link;
178 };
179
180 /**
181  * Attached interrupt handler state
182  */
183 struct bhndb_intr_handler {
184         device_t                 ih_owner;      /**< child device */
185         struct resource         *ih_res;        /**< child resource */
186         void                    *ih_cookiep;    /**< hostb-assigned cookiep, or NULL if bus_setup_intr() incomplete. */
187         struct bhndb_intr_isrc  *ih_isrc;       /**< host interrupt source routing the child's interrupt  */
188         bool                     ih_active;     /**< handler has been registered via bhndb_register_intr_handler */
189
190         STAILQ_ENTRY(bhndb_intr_handler) ih_link;
191 };
192
193 /**
194  * BHNDB resource allocation state.
195  */
196 struct bhndb_resources {
197         device_t                         dev;           /**< bridge device */
198         const struct bhndb_hwcfg        *cfg;           /**< hardware configuration */
199
200         struct bhndb_host_resources     *res;           /**< host resources, or NULL if not allocated */
201         
202         struct rman                      ht_mem_rman;   /**< host memory manager */
203         struct rman                      br_mem_rman;   /**< bridged memory manager */
204         struct rman                      br_irq_rman;   /**< bridged irq manager */
205
206         STAILQ_HEAD(, bhndb_region)      bus_regions;   /**< bus region descriptors */
207
208         struct mtx                       dw_steal_mtx;  /**< spinlock must be held when stealing a dynamic window allocation */
209         struct bhndb_dw_alloc           *dw_alloc;      /**< dynamic window allocation records */
210         size_t                           dwa_count;     /**< number of dynamic windows available. */
211         bitstr_t                        *dwa_freelist;  /**< dynamic window free list */
212         bhndb_priority_t                 min_prio;      /**< minimum resource priority required to
213                                                              allocate a dynamic window */
214
215         STAILQ_HEAD(,bhndb_intr_handler) bus_intrs;     /**< attached child interrupt handlers */
216 };
217
218 /**
219  * Returns true if the all dynamic windows are marked free, false
220  * otherwise.
221  * 
222  * @param br The resource state to check.
223  */
224 static inline bool
225 bhndb_dw_all_free(struct bhndb_resources *br)
226 {
227         int bit;
228         bit_ffs(br->dwa_freelist, br->dwa_count, &bit);
229         return (bit == -1);
230 }
231
232 /**
233  * Find the next free dynamic window region in @p br.
234  * 
235  * @param br The resource state to search.
236  */
237 static inline struct bhndb_dw_alloc *
238 bhndb_dw_next_free(struct bhndb_resources *br)
239 {
240         struct bhndb_dw_alloc   *dw_free;
241         int                      bit;
242
243         bit_ffc(br->dwa_freelist, br->dwa_count, &bit);
244         if (bit == -1)
245                 return (NULL);
246
247         dw_free = &br->dw_alloc[bit];
248
249         KASSERT(LIST_EMPTY(&dw_free->refs),
250             ("free list out of sync with refs"));
251
252         return (dw_free);
253 }
254
255 /**
256  * Returns true if a dynamic window allocation is marked as free.
257  * 
258  * @param br The resource state owning @p dwa.
259  * @param dwa The dynamic window allocation record to be checked.
260  */
261 static inline bool
262 bhndb_dw_is_free(struct bhndb_resources *br, struct bhndb_dw_alloc *dwa)
263 {
264         bool is_free = LIST_EMPTY(&dwa->refs);
265
266         KASSERT(is_free == !bit_test(br->dwa_freelist, dwa->rnid),
267             ("refs out of sync with free list"));
268
269         return (is_free);
270 }
271
272
273 #define BHNDB_LOCK_INIT(sc) \
274         mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev), \
275             "bhndb resource allocator lock", MTX_DEF)
276 #define BHNDB_LOCK(sc)                  mtx_lock(&(sc)->sc_mtx)
277 #define BHNDB_UNLOCK(sc)                mtx_unlock(&(sc)->sc_mtx)
278 #define BHNDB_LOCK_ASSERT(sc, what)     mtx_assert(&(sc)->sc_mtx, what)
279 #define BHNDB_LOCK_DESTROY(sc)          mtx_destroy(&(sc)->sc_mtx)
280
281 #endif /* _BHND_BHNDB_PRIVATE_H_ */