1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2022 Scott Long
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #ifndef _ROUTER_VAR_H
30 #define _ROUTER_VAR_H
31
32 struct router_softc;
33 struct router_command;
34 struct router_topo;
35
36 typedef void (*router_callback_t)(struct router_softc *,
37 struct router_command *, void *);
38
39 struct router_command {
40 TAILQ_ENTRY(router_command) link;
41 struct router_softc *sc;
42 struct nhi_cmd_frame *nhicmd;
43 u_int flags;
44 #define RCMD_POLLED (1 << 0)
45 #define RCMD_POLL_COMPLETE (1 << 1)
46 int resp_len;
47 router_callback_t callback;
48 void *callback_arg;
49 u_int dwlen;
50 u_int timeout;
51 int retries;
52 u_int ev;
53 uint8_t resp_buffer[NHI_RING0_FRAME_SIZE];
54 };
55
56 struct router_softc {
57 TAILQ_ENTRY(router_softc) link;
58 u_int debug;
59 tb_route_t route;
60 device_t dev;
61 struct nhi_softc *nsc;
62
63 struct mtx mtx;
64 struct nhi_ring_pair *ring0;
65 TAILQ_HEAD(,router_command) cmd_queue;
66
67 struct router_command *inflight_cmd;
68
69 uint8_t depth;
70 uint8_t max_adap;
71
72 struct router_softc **adapters;
73
74 uint32_t uuid[4];
75 };
76
77 struct router_cfg_cap {
78 uint16_t current_cap;
79 uint16_t next_cap;
80 uint32_t space;
81 uint8_t adap;
82 uint8_t cap_id;
83 uint8_t vsc_id;
84 uint8_t vsc_len;
85 uint16_t vsec_len;
86 };
87
88 /* Router reset registers */
89 #define ROUTER_HRR 0x39898
90 #define ROUTER_HIR 0x39858
91
92 int tb_router_attach(struct router_softc *, tb_route_t);
93 int tb_router_attach_root(struct nhi_softc *, tb_route_t);
94 int tb_router_detach(struct router_softc *);
95 int tb_config_read(struct router_softc *, u_int, u_int, u_int, u_int,
96 uint32_t *);
97 int tb_config_read_polled(struct router_softc *, u_int, u_int, u_int, u_int,
98 uint32_t *);
99 int tb_config_read_async(struct router_softc *, u_int, u_int, u_int, u_int,
100 uint32_t *, void *);
101 int tb_config_write(struct router_softc *, u_int, u_int, u_int, u_int,
102 uint32_t *);
103 int tb_config_next_cap(struct router_softc *, struct router_cfg_cap *);
104 int tb_config_find_cap(struct router_softc *, struct router_cfg_cap *);
105 int tb_config_find_router_cap(struct router_softc *, u_int, u_int, u_int *);
106 int tb_config_find_router_vsc(struct router_softc *, u_int, u_int *);
107 int tb_config_find_router_vsec(struct router_softc *, u_int, u_int *);
108 int tb_config_find_adapter_cap(struct router_softc *, u_int, u_int, u_int *);
109 int tb_config_get_lc_uuid(struct router_softc *, uint8_t *);
110
111 #define TB_CONFIG_ADDR(seq, space, adapter, dwlen, offset) \
112 ((seq << TB_CFG_SEQ_SHIFT) | space | \
113 (adapter << TB_CFG_ADAPTER_SHIFT) | (dwlen << TB_CFG_SIZE_SHIFT) | \
114 (offset & TB_CFG_ADDR_MASK))
115
116 #define TB_ROUTE(router) \
117 ((uint64_t)(router)->route.hi << 32) | (router)->route.lo
118
119 static __inline void *
router_get_frame_data(struct router_command * cmd)120 router_get_frame_data(struct router_command *cmd)
121 {
122 return ((void *)cmd->nhicmd->data);
123 }
124
125 /*
126 * Read the Router config space for the router referred to in the softc.
127 * addr - The dword offset in the config space
128 * dwlen - The number of dwords
129 * buf - must be large enough to hold the number of dwords requested.
130 */
131 static __inline int
tb_config_router_read(struct router_softc * sc,u_int addr,u_int dwlen,uint32_t * buf)132 tb_config_router_read(struct router_softc *sc, u_int addr, u_int dwlen,
133 uint32_t *buf)
134 {
135 return (tb_config_read(sc, TB_CFG_CS_ROUTER, 0, addr, dwlen, buf));
136 }
137
138 static __inline int
tb_config_router_read_polled(struct router_softc * sc,u_int addr,u_int dwlen,uint32_t * buf)139 tb_config_router_read_polled(struct router_softc *sc, u_int addr, u_int dwlen,
140 uint32_t *buf)
141 {
142 return (tb_config_read_polled(sc, TB_CFG_CS_ROUTER, 0, addr, dwlen, buf));
143 }
144
145 /*
146 * Write the Router config space for the router referred to in the softc.
147 * addr - The dword offset in the config space
148 * dwlen - The number of dwords
149 * buf - must be large enough to hold the number of dwords requested.
150 */
151 static __inline int
tb_config_router_write(struct router_softc * sc,u_int addr,u_int dwlen,uint32_t * buf)152 tb_config_router_write(struct router_softc *sc, u_int addr, u_int dwlen,
153 uint32_t *buf)
154 {
155 return (tb_config_write(sc, TB_CFG_CS_ROUTER, 0, addr, dwlen, buf));
156 }
157
158 /*
159 * Read the Adapter config space for the router referred to in the softc.
160 * adap - Adapter number
161 * addr - The dword offset in the config space
162 * dwlen - The number of dwords
163 * buf - must be large enough to hold the number of dwords requested.
164 */
165 static __inline int
tb_config_adapter_read(struct router_softc * sc,u_int adap,u_int addr,u_int dwlen,uint32_t * buf)166 tb_config_adapter_read(struct router_softc *sc, u_int adap, u_int addr,
167 u_int dwlen, uint32_t *buf)
168 {
169 return (tb_config_read(sc, TB_CFG_CS_ADAPTER, adap, addr, dwlen, buf));
170 }
171
172 /*
173 * Read the Adapter config space for the router referred to in the softc.
174 * adap - Adapter number
175 * addr - The dword offset in the config space
176 * dwlen - The number of dwords
177 * buf - must be large enough to hold the number of dwords requested.
178 */
179 static __inline int
tb_config_adapter_write(struct router_softc * sc,u_int adap,u_int addr,u_int dwlen,uint32_t * buf)180 tb_config_adapter_write(struct router_softc *sc, u_int adap, u_int addr,
181 u_int dwlen, uint32_t *buf)
182 {
183 return (tb_config_write(sc, TB_CFG_CS_ADAPTER, adap, addr, dwlen, buf));
184 }
185
186 /*
187 * Read the Path config space for the router referred to in the softc.
188 * adap - Adapter number
189 * hopid - HopID of the path
190 * len - The number of adjacent paths
191 * buf - must be large enough to hold the number of dwords requested.
192 */
193 static __inline int
tb_config_path_read(struct router_softc * sc,u_int adap,u_int hopid,u_int num,uint32_t * buf)194 tb_config_path_read(struct router_softc *sc, u_int adap, u_int hopid,
195 u_int num, uint32_t *buf)
196 {
197 return (tb_config_read(sc, TB_CFG_CS_PATH, adap, hopid * 2,
198 num * 2, buf));
199 }
200
201 /*
202 * Write the Path config space for the router referred to in the softc.
203 * adap - Adapter number
204 * hopid - HopID of the path
205 * len - The number of adjacent paths
206 * buf - must be large enough to hold the number of dwords requested.
207 */
208 static __inline int
tb_config_path_write(struct router_softc * sc,u_int adap,u_int hopid,u_int num,uint32_t * buf)209 tb_config_path_write(struct router_softc *sc, u_int adap, u_int hopid,
210 u_int num, uint32_t *buf)
211 {
212 return (tb_config_write(sc, TB_CFG_CS_PATH, adap, hopid * 2,
213 num * 2, buf));
214 }
215
216 /*
217 * Read the Counters config space for the router referred to in the softc.
218 * Counters come in sets of 3 dwords.
219 * adap - Adapter number
220 * set - The counter set index
221 * num - The number of adjacent counter sets to read
222 * buf - must be large enough to hold the number of dwords requested.
223 */
224 static __inline int
tb_config_counters_read(struct router_softc * sc,u_int adap,u_int set,u_int num,uint32_t * buf)225 tb_config_counters_read(struct router_softc *sc, u_int adap, u_int set,
226 u_int num, uint32_t *buf)
227 {
228 return (tb_config_read(sc, TB_CFG_CS_COUNTERS, adap, set * 3,
229 num * 3, buf));
230 }
231
232 static __inline void
tb_config_set_root(struct router_softc * sc)233 tb_config_set_root(struct router_softc *sc)
234 {
235 sc->nsc->root_rsc = sc;
236 }
237
238 static __inline void *
tb_config_get_root(struct router_softc * sc)239 tb_config_get_root(struct router_softc *sc)
240 {
241 return (sc->nsc->root_rsc);
242 }
243
244 #endif /* _ROUTER_VAR_H */
245