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 bool suspended; 63 64 struct mtx mtx; 65 struct nhi_ring_pair *ring0; 66 TAILQ_HEAD(,router_command) cmd_queue; 67 68 struct router_command *inflight_cmd; 69 70 uint8_t depth; 71 uint8_t max_adap; 72 73 struct router_softc **adapters; 74 75 uint32_t uuid[4]; 76 }; 77 78 struct router_cfg_cap { 79 uint16_t current_cap; 80 uint16_t next_cap; 81 uint32_t space; 82 uint8_t adap; 83 uint8_t cap_id; 84 uint8_t vsc_id; 85 uint8_t vsc_len; 86 uint16_t vsec_len; 87 }; 88 89 /* Router reset registers */ 90 #define ROUTER_HRR 0x39898 91 #define ROUTER_HIR 0x39858 92 93 /* Router config space registers */ 94 #define ROUTER_CS_5 5 95 #define ROUTER_SLP (1<<0) /* Enter sleep (CS5). */ 96 #define ROUTER_WOP (1<<1) /* Wake on PCIe (CS5). */ 97 #define ROUTER_WOU (1<<2) /* Wake on USB3 (CS5). */ 98 #define ROUTER_WOD (1<<3) /* Wake on DP (CS5). */ 99 #define ROUTER_CS_6 6 100 #define ROUTER_SLPR (1<<0) /* Sleep ready (CS6). */ 101 102 int tb_router_attach(struct router_softc *, tb_route_t); 103 int tb_router_attach_root(struct nhi_softc *, tb_route_t); 104 int tb_router_detach(struct router_softc *); 105 int tb_router_suspend(struct router_softc *); 106 int tb_config_read(struct router_softc *, u_int, u_int, u_int, u_int, 107 uint32_t *); 108 int tb_config_read_polled(struct router_softc *, u_int, u_int, u_int, u_int, 109 uint32_t *); 110 int tb_config_read_async(struct router_softc *, u_int, u_int, u_int, u_int, 111 uint32_t *, void *); 112 int tb_config_write(struct router_softc *, u_int, u_int, u_int, u_int, 113 uint32_t *); 114 int tb_config_next_cap(struct router_softc *, struct router_cfg_cap *); 115 int tb_config_find_cap(struct router_softc *, struct router_cfg_cap *); 116 int tb_config_find_router_cap(struct router_softc *, u_int, u_int, u_int *); 117 int tb_config_find_router_vsc(struct router_softc *, u_int, u_int *); 118 int tb_config_find_router_vsec(struct router_softc *, u_int, u_int *); 119 int tb_config_find_adapter_cap(struct router_softc *, u_int, u_int, u_int *); 120 int tb_config_get_lc_uuid(struct router_softc *, uint8_t *); 121 122 #define TB_CONFIG_ADDR(seq, space, adapter, dwlen, offset) \ 123 ((seq << TB_CFG_SEQ_SHIFT) | space | \ 124 (adapter << TB_CFG_ADAPTER_SHIFT) | (dwlen << TB_CFG_SIZE_SHIFT) | \ 125 (offset & TB_CFG_ADDR_MASK)) 126 127 #define TB_ROUTE(router) \ 128 ((uint64_t)(router)->route.hi << 32) | (router)->route.lo 129 130 static __inline void * 131 router_get_frame_data(struct router_command *cmd) 132 { 133 return ((void *)cmd->nhicmd->data); 134 } 135 136 /* 137 * Read the Router config space for the router referred to in the softc. 138 * addr - The dword offset in the config space 139 * dwlen - The number of dwords 140 * buf - must be large enough to hold the number of dwords requested. 141 */ 142 static __inline int 143 tb_config_router_read(struct router_softc *sc, u_int addr, u_int dwlen, 144 uint32_t *buf) 145 { 146 return (tb_config_read(sc, TB_CFG_CS_ROUTER, 0, addr, dwlen, buf)); 147 } 148 149 static __inline int 150 tb_config_router_read_polled(struct router_softc *sc, u_int addr, u_int dwlen, 151 uint32_t *buf) 152 { 153 return (tb_config_read_polled(sc, TB_CFG_CS_ROUTER, 0, addr, dwlen, buf)); 154 } 155 156 /* 157 * Write the Router config space for the router referred to in the softc. 158 * addr - The dword offset in the config space 159 * dwlen - The number of dwords 160 * buf - must be large enough to hold the number of dwords requested. 161 */ 162 static __inline int 163 tb_config_router_write(struct router_softc *sc, u_int addr, u_int dwlen, 164 uint32_t *buf) 165 { 166 return (tb_config_write(sc, TB_CFG_CS_ROUTER, 0, addr, dwlen, buf)); 167 } 168 169 /* 170 * Read the Adapter config space for the router referred to in the softc. 171 * adap - Adapter number 172 * addr - The dword offset in the config space 173 * dwlen - The number of dwords 174 * buf - must be large enough to hold the number of dwords requested. 175 */ 176 static __inline int 177 tb_config_adapter_read(struct router_softc *sc, u_int adap, u_int addr, 178 u_int dwlen, uint32_t *buf) 179 { 180 return (tb_config_read(sc, TB_CFG_CS_ADAPTER, adap, addr, dwlen, buf)); 181 } 182 183 /* 184 * Read the Adapter config space for the router referred to in the softc. 185 * adap - Adapter number 186 * addr - The dword offset in the config space 187 * dwlen - The number of dwords 188 * buf - must be large enough to hold the number of dwords requested. 189 */ 190 static __inline int 191 tb_config_adapter_write(struct router_softc *sc, u_int adap, u_int addr, 192 u_int dwlen, uint32_t *buf) 193 { 194 return (tb_config_write(sc, TB_CFG_CS_ADAPTER, adap, addr, dwlen, buf)); 195 } 196 197 /* 198 * Read the Path config space for the router referred to in the softc. 199 * adap - Adapter number 200 * hopid - HopID of the path 201 * len - The number of adjacent paths 202 * buf - must be large enough to hold the number of dwords requested. 203 */ 204 static __inline int 205 tb_config_path_read(struct router_softc *sc, u_int adap, u_int hopid, 206 u_int num, uint32_t *buf) 207 { 208 return (tb_config_read(sc, TB_CFG_CS_PATH, adap, hopid * 2, 209 num * 2, buf)); 210 } 211 212 /* 213 * Write the Path config space for the router referred to in the softc. 214 * adap - Adapter number 215 * hopid - HopID of the path 216 * len - The number of adjacent paths 217 * buf - must be large enough to hold the number of dwords requested. 218 */ 219 static __inline int 220 tb_config_path_write(struct router_softc *sc, u_int adap, u_int hopid, 221 u_int num, uint32_t *buf) 222 { 223 return (tb_config_write(sc, TB_CFG_CS_PATH, adap, hopid * 2, 224 num * 2, buf)); 225 } 226 227 /* 228 * Read the Counters config space for the router referred to in the softc. 229 * Counters come in sets of 3 dwords. 230 * adap - Adapter number 231 * set - The counter set index 232 * num - The number of adjacent counter sets to read 233 * buf - must be large enough to hold the number of dwords requested. 234 */ 235 static __inline int 236 tb_config_counters_read(struct router_softc *sc, u_int adap, u_int set, 237 u_int num, uint32_t *buf) 238 { 239 return (tb_config_read(sc, TB_CFG_CS_COUNTERS, adap, set * 3, 240 num * 3, buf)); 241 } 242 243 static __inline void 244 tb_config_set_root(struct router_softc *sc) 245 { 246 sc->nsc->root_rsc = sc; 247 } 248 249 static __inline void * 250 tb_config_get_root(struct router_softc *sc) 251 { 252 return (sc->nsc->root_rsc); 253 } 254 255 #endif /* _ROUTER_VAR_H */ 256