14ad7e9b0SAdrian Chadd /*-
289294a78SLandon J. Fuller * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
3caeff9a3SLandon J. Fuller * Copyright (c) 2017 The FreeBSD Foundation
44ad7e9b0SAdrian Chadd * All rights reserved.
54ad7e9b0SAdrian Chadd *
689294a78SLandon J. Fuller * Portions of this software were developed by Landon Fuller
789294a78SLandon J. Fuller * under sponsorship from the FreeBSD Foundation.
889294a78SLandon J. Fuller *
9caeff9a3SLandon J. Fuller * Portions of this software were developed by Landon Fuller
10caeff9a3SLandon J. Fuller * under sponsorship from the FreeBSD Foundation.
11caeff9a3SLandon J. Fuller *
124ad7e9b0SAdrian Chadd * Redistribution and use in source and binary forms, with or without
134ad7e9b0SAdrian Chadd * modification, are permitted provided that the following conditions
144ad7e9b0SAdrian Chadd * are met:
154ad7e9b0SAdrian Chadd * 1. Redistributions of source code must retain the above copyright
164ad7e9b0SAdrian Chadd * notice, this list of conditions and the following disclaimer,
174ad7e9b0SAdrian Chadd * without modification.
184ad7e9b0SAdrian Chadd * 2. Redistributions in binary form must reproduce at minimum a disclaimer
194ad7e9b0SAdrian Chadd * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
204ad7e9b0SAdrian Chadd * redistribution must be conditioned upon including a substantially
214ad7e9b0SAdrian Chadd * similar Disclaimer requirement for further binary redistribution.
224ad7e9b0SAdrian Chadd *
234ad7e9b0SAdrian Chadd * NO WARRANTY
244ad7e9b0SAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
254ad7e9b0SAdrian Chadd * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
264ad7e9b0SAdrian Chadd * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
274ad7e9b0SAdrian Chadd * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
284ad7e9b0SAdrian Chadd * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
294ad7e9b0SAdrian Chadd * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
304ad7e9b0SAdrian Chadd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
314ad7e9b0SAdrian Chadd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
324ad7e9b0SAdrian Chadd * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
334ad7e9b0SAdrian Chadd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
344ad7e9b0SAdrian Chadd * THE POSSIBILITY OF SUCH DAMAGES.
354ad7e9b0SAdrian Chadd *
364ad7e9b0SAdrian Chadd */
374ad7e9b0SAdrian Chadd
384ad7e9b0SAdrian Chadd #ifndef _BHND_BHNDB_PRIVATE_H_
394ad7e9b0SAdrian Chadd #define _BHND_BHNDB_PRIVATE_H_
404ad7e9b0SAdrian Chadd
414ad7e9b0SAdrian Chadd #include <sys/param.h>
429dfeb414SLandon J. Fuller #include <sys/bitstring.h>
434ad7e9b0SAdrian Chadd #include <sys/bus.h>
444ad7e9b0SAdrian Chadd #include <sys/systm.h>
454ad7e9b0SAdrian Chadd
464ad7e9b0SAdrian Chadd #include <machine/bus.h>
474ad7e9b0SAdrian Chadd #include <sys/rman.h>
484ad7e9b0SAdrian Chadd #include <machine/resource.h>
494ad7e9b0SAdrian Chadd
504ad7e9b0SAdrian Chadd #include "bhndbvar.h"
514ad7e9b0SAdrian Chadd
524ad7e9b0SAdrian Chadd /*
534ad7e9b0SAdrian Chadd * Private bhndb(4) driver definitions.
544ad7e9b0SAdrian Chadd */
554ad7e9b0SAdrian Chadd
564ad7e9b0SAdrian Chadd struct bhndb_dw_alloc;
57caeff9a3SLandon J. Fuller struct bhndb_intr_handler;
584ad7e9b0SAdrian Chadd struct bhndb_region;
594ad7e9b0SAdrian Chadd struct bhndb_resources;
604ad7e9b0SAdrian Chadd
614ad7e9b0SAdrian Chadd struct bhndb_resources *bhndb_alloc_resources(device_t dev,
624ad7e9b0SAdrian Chadd device_t parent_dev,
634ad7e9b0SAdrian Chadd const struct bhndb_hwcfg *cfg);
644ad7e9b0SAdrian Chadd
654ad7e9b0SAdrian Chadd void bhndb_free_resources(
664ad7e9b0SAdrian Chadd struct bhndb_resources *br);
674ad7e9b0SAdrian Chadd
684ad7e9b0SAdrian Chadd int bhndb_add_resource_region(
694ad7e9b0SAdrian Chadd struct bhndb_resources *br,
704ad7e9b0SAdrian Chadd bhnd_addr_t addr, bhnd_size_t size,
714ad7e9b0SAdrian Chadd bhndb_priority_t priority,
72eaa5fb4bSLandon J. Fuller uint32_t alloc_flags,
734ad7e9b0SAdrian Chadd const struct bhndb_regwin *static_regwin);
744ad7e9b0SAdrian Chadd
75249f3d3fSAdrian Chadd int bhndb_find_resource_limits(
76*3351964cSJohn Baldwin struct bhndb_resources *br,
77249f3d3fSAdrian Chadd struct resource *r, rman_res_t *start,
78249f3d3fSAdrian Chadd rman_res_t *end);
79249f3d3fSAdrian Chadd
80caeff9a3SLandon J. Fuller struct bhndb_intr_handler *bhndb_alloc_intr_handler(device_t owner,
81caeff9a3SLandon J. Fuller struct resource *r,
82caeff9a3SLandon J. Fuller struct bhndb_intr_isrc *isrc);
83caeff9a3SLandon J. Fuller void bhndb_free_intr_handler(
84caeff9a3SLandon J. Fuller struct bhndb_intr_handler *ih);
85caeff9a3SLandon J. Fuller
86caeff9a3SLandon J. Fuller void bhndb_register_intr_handler(
87caeff9a3SLandon J. Fuller struct bhndb_resources *br,
88caeff9a3SLandon J. Fuller struct bhndb_intr_handler *ih);
89caeff9a3SLandon J. Fuller void bhndb_deregister_intr_handler(
90caeff9a3SLandon J. Fuller struct bhndb_resources *br,
91caeff9a3SLandon J. Fuller struct bhndb_intr_handler *ih);
92caeff9a3SLandon J. Fuller struct bhndb_intr_handler *bhndb_find_intr_handler(
93caeff9a3SLandon J. Fuller struct bhndb_resources *br,
94caeff9a3SLandon J. Fuller void *cookiep);
95caeff9a3SLandon J. Fuller
96eaa5fb4bSLandon J. Fuller bool bhndb_has_static_region_mapping(
97eaa5fb4bSLandon J. Fuller struct bhndb_resources *br,
98eaa5fb4bSLandon J. Fuller bhnd_addr_t addr, bhnd_size_t size);
99eaa5fb4bSLandon J. Fuller
1004ad7e9b0SAdrian Chadd struct bhndb_region *bhndb_find_resource_region(
1014ad7e9b0SAdrian Chadd struct bhndb_resources *br,
1024ad7e9b0SAdrian Chadd bhnd_addr_t addr, bhnd_size_t size);
1034ad7e9b0SAdrian Chadd
1044ad7e9b0SAdrian Chadd struct bhndb_dw_alloc *bhndb_dw_find_resource(
1054ad7e9b0SAdrian Chadd struct bhndb_resources *dr,
1064ad7e9b0SAdrian Chadd struct resource *r);
1074ad7e9b0SAdrian Chadd
1084ad7e9b0SAdrian Chadd struct bhndb_dw_alloc *bhndb_dw_find_mapping(
1094ad7e9b0SAdrian Chadd struct bhndb_resources *br,
1104ad7e9b0SAdrian Chadd bhnd_addr_t addr, bhnd_size_t size);
1114ad7e9b0SAdrian Chadd
1124ad7e9b0SAdrian Chadd int bhndb_dw_retain(
1134ad7e9b0SAdrian Chadd struct bhndb_resources *br,
1144ad7e9b0SAdrian Chadd struct bhndb_dw_alloc *dwa,
1154ad7e9b0SAdrian Chadd struct resource *res);
1164ad7e9b0SAdrian Chadd
1174ad7e9b0SAdrian Chadd void bhndb_dw_release(
1184ad7e9b0SAdrian Chadd struct bhndb_resources *br,
1194ad7e9b0SAdrian Chadd struct bhndb_dw_alloc *dwa,
1204ad7e9b0SAdrian Chadd struct resource *res);
1214ad7e9b0SAdrian Chadd
1224ad7e9b0SAdrian Chadd int bhndb_dw_set_addr(device_t dev,
1234ad7e9b0SAdrian Chadd struct bhndb_resources *br,
1244ad7e9b0SAdrian Chadd struct bhndb_dw_alloc *dwa,
1254ad7e9b0SAdrian Chadd bus_addr_t addr, bus_size_t size);
1264ad7e9b0SAdrian Chadd
127eaa5fb4bSLandon J. Fuller struct bhndb_dw_alloc *bhndb_dw_steal(struct bhndb_resources *br,
128eaa5fb4bSLandon J. Fuller bus_addr_t *saved);
129eaa5fb4bSLandon J. Fuller
130eaa5fb4bSLandon J. Fuller void bhndb_dw_return_stolen(device_t dev,
131eaa5fb4bSLandon J. Fuller struct bhndb_resources *br,
132eaa5fb4bSLandon J. Fuller struct bhndb_dw_alloc *dwa,
133eaa5fb4bSLandon J. Fuller bus_addr_t saved);
134eaa5fb4bSLandon J. Fuller
135111d7cb2SLandon J. Fuller const struct bhndb_hw_priority *bhndb_hw_priority_find_core(
1364ad7e9b0SAdrian Chadd const struct bhndb_hw_priority *table,
137111d7cb2SLandon J. Fuller struct bhnd_core_info *core);
1384ad7e9b0SAdrian Chadd
139eaa5fb4bSLandon J. Fuller const struct bhndb_port_priority *bhndb_hw_priorty_find_port(
140eaa5fb4bSLandon J. Fuller const struct bhndb_hw_priority *table,
141eaa5fb4bSLandon J. Fuller struct bhnd_core_info *core,
142eaa5fb4bSLandon J. Fuller bhnd_port_type port_type, u_int port,
143eaa5fb4bSLandon J. Fuller u_int region);
144eaa5fb4bSLandon J. Fuller
1454ad7e9b0SAdrian Chadd /**
1464ad7e9b0SAdrian Chadd * Dynamic register window allocation reference.
1474ad7e9b0SAdrian Chadd */
1484ad7e9b0SAdrian Chadd struct bhndb_dw_rentry {
1494ad7e9b0SAdrian Chadd struct resource *dw_res; /**< child resource */
1504ad7e9b0SAdrian Chadd LIST_ENTRY(bhndb_dw_rentry) dw_link;
1514ad7e9b0SAdrian Chadd };
1524ad7e9b0SAdrian Chadd
1534ad7e9b0SAdrian Chadd /**
1544ad7e9b0SAdrian Chadd * A dynamic register window allocation record.
1554ad7e9b0SAdrian Chadd */
1564ad7e9b0SAdrian Chadd struct bhndb_dw_alloc {
1574ad7e9b0SAdrian Chadd const struct bhndb_regwin *win; /**< window definition */
1584ad7e9b0SAdrian Chadd struct resource *parent_res; /**< enclosing resource */
1594ad7e9b0SAdrian Chadd u_int rnid; /**< region identifier */
1604ad7e9b0SAdrian Chadd rman_res_t target; /**< the current window address, or 0x0 if unknown */
1614ad7e9b0SAdrian Chadd
1624ad7e9b0SAdrian Chadd LIST_HEAD(, bhndb_dw_rentry) refs; /**< references */
1634ad7e9b0SAdrian Chadd };
1644ad7e9b0SAdrian Chadd
1654ad7e9b0SAdrian Chadd /**
1664ad7e9b0SAdrian Chadd * A bus address region description.
1674ad7e9b0SAdrian Chadd */
1684ad7e9b0SAdrian Chadd struct bhndb_region {
1694ad7e9b0SAdrian Chadd bhnd_addr_t addr; /**< start of mapped range */
1704ad7e9b0SAdrian Chadd bhnd_size_t size; /**< size of mapped range */
1714ad7e9b0SAdrian Chadd bhndb_priority_t priority; /**< direct resource allocation priority */
172eaa5fb4bSLandon J. Fuller uint32_t alloc_flags; /**< resource allocation flags (@see bhndb_alloc_flags) */
1734ad7e9b0SAdrian Chadd const struct bhndb_regwin *static_regwin; /**< fixed mapping regwin, if any */
1744ad7e9b0SAdrian Chadd
1754ad7e9b0SAdrian Chadd STAILQ_ENTRY(bhndb_region) link;
1764ad7e9b0SAdrian Chadd };
1774ad7e9b0SAdrian Chadd
1784ad7e9b0SAdrian Chadd /**
179caeff9a3SLandon J. Fuller * Attached interrupt handler state
180caeff9a3SLandon J. Fuller */
181caeff9a3SLandon J. Fuller struct bhndb_intr_handler {
182caeff9a3SLandon J. Fuller device_t ih_owner; /**< child device */
183caeff9a3SLandon J. Fuller struct resource *ih_res; /**< child resource */
184caeff9a3SLandon J. Fuller void *ih_cookiep; /**< hostb-assigned cookiep, or NULL if bus_setup_intr() incomplete. */
185caeff9a3SLandon J. Fuller struct bhndb_intr_isrc *ih_isrc; /**< host interrupt source routing the child's interrupt */
186caeff9a3SLandon J. Fuller bool ih_active; /**< handler has been registered via bhndb_register_intr_handler */
187caeff9a3SLandon J. Fuller
188caeff9a3SLandon J. Fuller STAILQ_ENTRY(bhndb_intr_handler) ih_link;
189caeff9a3SLandon J. Fuller };
190caeff9a3SLandon J. Fuller
191caeff9a3SLandon J. Fuller /**
1924ad7e9b0SAdrian Chadd * BHNDB resource allocation state.
1934ad7e9b0SAdrian Chadd */
1944ad7e9b0SAdrian Chadd struct bhndb_resources {
1954ad7e9b0SAdrian Chadd device_t dev; /**< bridge device */
1964ad7e9b0SAdrian Chadd const struct bhndb_hwcfg *cfg; /**< hardware configuration */
1974ad7e9b0SAdrian Chadd
19889294a78SLandon J. Fuller struct bhndb_host_resources *res; /**< host resources, or NULL if not allocated */
1994ad7e9b0SAdrian Chadd
200e9378f45SAdrian Chadd struct rman ht_mem_rman; /**< host memory manager */
201e9378f45SAdrian Chadd struct rman br_mem_rman; /**< bridged memory manager */
202caeff9a3SLandon J. Fuller struct rman br_irq_rman; /**< bridged irq manager */
203e9378f45SAdrian Chadd
2044ad7e9b0SAdrian Chadd STAILQ_HEAD(, bhndb_region) bus_regions; /**< bus region descriptors */
2054ad7e9b0SAdrian Chadd
206eaa5fb4bSLandon J. Fuller struct mtx dw_steal_mtx; /**< spinlock must be held when stealing a dynamic window allocation */
2074ad7e9b0SAdrian Chadd struct bhndb_dw_alloc *dw_alloc; /**< dynamic window allocation records */
2084ad7e9b0SAdrian Chadd size_t dwa_count; /**< number of dynamic windows available. */
2099dfeb414SLandon J. Fuller bitstr_t *dwa_freelist; /**< dynamic window free list */
2104ad7e9b0SAdrian Chadd bhndb_priority_t min_prio; /**< minimum resource priority required to
2114ad7e9b0SAdrian Chadd allocate a dynamic window */
212caeff9a3SLandon J. Fuller
213caeff9a3SLandon J. Fuller STAILQ_HEAD(,bhndb_intr_handler) bus_intrs; /**< attached child interrupt handlers */
2144ad7e9b0SAdrian Chadd };
2154ad7e9b0SAdrian Chadd
2164ad7e9b0SAdrian Chadd /**
2179dfeb414SLandon J. Fuller * Returns true if the all dynamic windows are marked free, false
2184ad7e9b0SAdrian Chadd * otherwise.
2194ad7e9b0SAdrian Chadd *
2204ad7e9b0SAdrian Chadd * @param br The resource state to check.
2214ad7e9b0SAdrian Chadd */
2224ad7e9b0SAdrian Chadd static inline bool
bhndb_dw_all_free(struct bhndb_resources * br)2239dfeb414SLandon J. Fuller bhndb_dw_all_free(struct bhndb_resources *br)
2244ad7e9b0SAdrian Chadd {
2259dfeb414SLandon J. Fuller int bit;
2269dfeb414SLandon J. Fuller bit_ffs(br->dwa_freelist, br->dwa_count, &bit);
2279dfeb414SLandon J. Fuller return (bit == -1);
2284ad7e9b0SAdrian Chadd }
2294ad7e9b0SAdrian Chadd
2304ad7e9b0SAdrian Chadd /**
2314ad7e9b0SAdrian Chadd * Find the next free dynamic window region in @p br.
2324ad7e9b0SAdrian Chadd *
2334ad7e9b0SAdrian Chadd * @param br The resource state to search.
2344ad7e9b0SAdrian Chadd */
2354ad7e9b0SAdrian Chadd static inline struct bhndb_dw_alloc *
bhndb_dw_next_free(struct bhndb_resources * br)2364ad7e9b0SAdrian Chadd bhndb_dw_next_free(struct bhndb_resources *br)
2374ad7e9b0SAdrian Chadd {
2384ad7e9b0SAdrian Chadd struct bhndb_dw_alloc *dw_free;
2399dfeb414SLandon J. Fuller int bit;
2404ad7e9b0SAdrian Chadd
2419dfeb414SLandon J. Fuller bit_ffc(br->dwa_freelist, br->dwa_count, &bit);
2429dfeb414SLandon J. Fuller if (bit == -1)
2434ad7e9b0SAdrian Chadd return (NULL);
2444ad7e9b0SAdrian Chadd
2459dfeb414SLandon J. Fuller dw_free = &br->dw_alloc[bit];
2464ad7e9b0SAdrian Chadd
2474ad7e9b0SAdrian Chadd KASSERT(LIST_EMPTY(&dw_free->refs),
2484ad7e9b0SAdrian Chadd ("free list out of sync with refs"));
2494ad7e9b0SAdrian Chadd
2504ad7e9b0SAdrian Chadd return (dw_free);
2514ad7e9b0SAdrian Chadd }
2524ad7e9b0SAdrian Chadd
2534ad7e9b0SAdrian Chadd /**
2544ad7e9b0SAdrian Chadd * Returns true if a dynamic window allocation is marked as free.
2554ad7e9b0SAdrian Chadd *
2564ad7e9b0SAdrian Chadd * @param br The resource state owning @p dwa.
2574ad7e9b0SAdrian Chadd * @param dwa The dynamic window allocation record to be checked.
2584ad7e9b0SAdrian Chadd */
2594ad7e9b0SAdrian Chadd static inline bool
bhndb_dw_is_free(struct bhndb_resources * br,struct bhndb_dw_alloc * dwa)2604ad7e9b0SAdrian Chadd bhndb_dw_is_free(struct bhndb_resources *br, struct bhndb_dw_alloc *dwa)
2614ad7e9b0SAdrian Chadd {
2624ad7e9b0SAdrian Chadd bool is_free = LIST_EMPTY(&dwa->refs);
2634ad7e9b0SAdrian Chadd
2649dfeb414SLandon J. Fuller KASSERT(is_free == !bit_test(br->dwa_freelist, dwa->rnid),
2654ad7e9b0SAdrian Chadd ("refs out of sync with free list"));
2664ad7e9b0SAdrian Chadd
2674ad7e9b0SAdrian Chadd return (is_free);
2684ad7e9b0SAdrian Chadd }
2694ad7e9b0SAdrian Chadd
2704ad7e9b0SAdrian Chadd #define BHNDB_LOCK_INIT(sc) \
2714ad7e9b0SAdrian Chadd mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev), \
2724ad7e9b0SAdrian Chadd "bhndb resource allocator lock", MTX_DEF)
2734ad7e9b0SAdrian Chadd #define BHNDB_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
2744ad7e9b0SAdrian Chadd #define BHNDB_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
2754ad7e9b0SAdrian Chadd #define BHNDB_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->sc_mtx, what)
2764ad7e9b0SAdrian Chadd #define BHNDB_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx)
2774ad7e9b0SAdrian Chadd
2784ad7e9b0SAdrian Chadd #endif /* _BHND_BHNDB_PRIVATE_H_ */
279