1 1.1 alc /*- 2 1.1 alc * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 1.1 alc * All rights reserved. 4 1.1 alc * 5 1.1 alc * Redistribution and use in source and binary forms, with or without 6 1.1 alc * modification, are permitted provided that the following conditions 7 1.1 alc * are met: 8 1.1 alc * 1. Redistributions of source code must retain the above copyright 9 1.1 alc * notice, this list of conditions and the following disclaimer, 10 1.1 alc * without modification. 11 1.1 alc * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 1.1 alc * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 1.1 alc * redistribution must be conditioned upon including a substantially 14 1.1 alc * similar Disclaimer requirement for further binary redistribution. 15 1.1 alc * 16 1.1 alc * NO WARRANTY 17 1.1 alc * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 1.1 alc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 1.1 alc * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20 1.1 alc * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 1.1 alc * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 1.1 alc * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 1.1 alc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 1.1 alc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 1.1 alc * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 1.1 alc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 1.1 alc * THE POSSIBILITY OF SUCH DAMAGES. 28 1.1 alc * 29 1.7 christos * $Id: ah_osdep.c,v 1.7 2021/09/21 14:51:28 christos Exp $ 30 1.1 alc */ 31 1.1 alc 32 1.1 alc #include <sys/cdefs.h> 33 1.7 christos __KERNEL_RCSID(0, "$NetBSD: ah_osdep.c,v 1.7 2021/09/21 14:51:28 christos Exp $"); 34 1.1 alc 35 1.4 jmcneill #ifdef _KERNEL_OPT 36 1.1 alc #include "opt_athhal.h" 37 1.4 jmcneill #endif 38 1.1 alc 39 1.1 alc #include <sys/param.h> 40 1.1 alc #include <sys/systm.h> 41 1.1 alc #include <sys/kernel.h> 42 1.1 alc #include <sys/sysctl.h> 43 1.1 alc #include <sys/malloc.h> 44 1.1 alc #include <sys/proc.h> 45 1.1 alc #include <sys/kauth.h> 46 1.4 jmcneill #include <sys/module.h> 47 1.1 alc 48 1.1 alc #include <net/if.h> 49 1.1 alc #include <net/if_dl.h> 50 1.1 alc #include <net/if_media.h> 51 1.1 alc #include <net/if_arp.h> 52 1.1 alc #include <net/if_ether.h> 53 1.1 alc 54 1.1 alc #include <external/isc/atheros_hal/dist/ah.h> 55 1.1 alc 56 1.1 alc extern void ath_hal_printf(struct ath_hal *, const char*, ...) 57 1.1 alc __printflike(2,3); 58 1.1 alc extern void ath_hal_vprintf(struct ath_hal *, const char*, va_list) 59 1.1 alc __printflike(2, 0); 60 1.1 alc extern const char* ath_hal_ether_sprintf(const u_int8_t *mac); 61 1.1 alc extern void *ath_hal_malloc(size_t); 62 1.1 alc extern void ath_hal_free(void *); 63 1.1 alc #ifdef ATHHAL_ASSERT 64 1.1 alc extern void ath_hal_assert_failed(const char* filename, 65 1.1 alc int lineno, const char* msg); 66 1.1 alc #endif 67 1.1 alc #ifdef ATHHAL_DEBUG 68 1.6 nakayama extern void HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) 69 1.6 nakayama __printflike(3,4); 70 1.1 alc #endif /* ATHHAL_DEBUG */ 71 1.1 alc 72 1.1 alc #ifdef ATHHAL_DEBUG 73 1.1 alc static int ath_hal_debug = 0; 74 1.1 alc #endif /* ATHHAL_DEBUG */ 75 1.1 alc 76 1.1 alc int ath_hal_dma_beacon_response_time = 2; /* in TU's */ 77 1.1 alc int ath_hal_sw_beacon_response_time = 10; /* in TU's */ 78 1.1 alc int ath_hal_additional_swba_backoff = 0; /* in TU's */ 79 1.1 alc 80 1.1 alc SYSCTL_SETUP(sysctl_ath_hal, "sysctl ath.hal subtree setup") 81 1.1 alc { 82 1.1 alc int rc; 83 1.1 alc const struct sysctlnode *cnode, *rnode; 84 1.1 alc 85 1.1 alc if ((rc = sysctl_createv(clog, 0, NULL, &rnode, CTLFLAG_PERMANENT, 86 1.1 alc CTLTYPE_NODE, "hw", NULL, NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) 87 1.1 alc goto err; 88 1.1 alc 89 1.1 alc if ((rc = sysctl_createv(clog, 0, &rnode, &rnode, CTLFLAG_PERMANENT, 90 1.1 alc CTLTYPE_NODE, "ath", SYSCTL_DESCR("Atheros driver parameters"), 91 1.1 alc NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) 92 1.1 alc goto err; 93 1.1 alc 94 1.1 alc if ((rc = sysctl_createv(clog, 0, &rnode, &rnode, CTLFLAG_PERMANENT, 95 1.1 alc CTLTYPE_NODE, "hal", SYSCTL_DESCR("Atheros HAL parameters"), 96 1.1 alc NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) 97 1.1 alc goto err; 98 1.1 alc 99 1.1 alc #if 0 100 1.1 alc if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, 101 1.1 alc CTLFLAG_PERMANENT|CTLFLAG_READONLY, CTLTYPE_STRING, "version", 102 1.1 alc SYSCTL_DESCR("Atheros HAL version"), NULL, 0, &ath_hal_version, 0, 103 1.1 alc CTL_CREATE, CTL_EOL)) != 0) 104 1.1 alc goto err; 105 1.1 alc #endif 106 1.1 alc 107 1.1 alc if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, 108 1.1 alc CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, "dma_brt", 109 1.1 alc SYSCTL_DESCR("Atheros HAL DMA beacon response time"), NULL, 0, 110 1.1 alc &ath_hal_dma_beacon_response_time, 0, CTL_CREATE, CTL_EOL)) != 0) 111 1.1 alc goto err; 112 1.1 alc 113 1.1 alc if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, 114 1.1 alc CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, "sw_brt", 115 1.1 alc SYSCTL_DESCR("Atheros HAL software beacon response time"), NULL, 0, 116 1.1 alc &ath_hal_sw_beacon_response_time, 0, CTL_CREATE, CTL_EOL)) != 0) 117 1.1 alc goto err; 118 1.1 alc 119 1.1 alc if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, 120 1.1 alc CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, "swba_backoff", 121 1.1 alc SYSCTL_DESCR("Atheros HAL additional SWBA backoff time"), NULL, 0, 122 1.1 alc &ath_hal_additional_swba_backoff, 0, CTL_CREATE, CTL_EOL)) != 0) 123 1.1 alc goto err; 124 1.1 alc 125 1.1 alc #ifdef ATHHAL_DEBUG 126 1.1 alc if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, 127 1.1 alc CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, "debug", 128 1.1 alc SYSCTL_DESCR("Atheros HAL debugging printfs"), NULL, 0, 129 1.1 alc &ath_hal_debug, 0, CTL_CREATE, CTL_EOL)) != 0) 130 1.1 alc goto err; 131 1.1 alc #endif /* ATHHAL_DEBUG */ 132 1.1 alc return; 133 1.1 alc err: 134 1.1 alc printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); 135 1.1 alc } 136 1.1 alc 137 1.1 alc MALLOC_DEFINE(M_ATH_HAL, "ath_hal", "ath hal data"); 138 1.1 alc 139 1.1 alc void* 140 1.1 alc ath_hal_malloc(size_t size) 141 1.1 alc { 142 1.2 martin return malloc(size, M_ATH_HAL, M_NOWAIT | M_ZERO); 143 1.1 alc } 144 1.1 alc 145 1.1 alc void 146 1.1 alc ath_hal_free(void* p) 147 1.1 alc { 148 1.1 alc free(p, M_ATH_HAL); 149 1.1 alc } 150 1.1 alc 151 1.1 alc void 152 1.1 alc ath_hal_vprintf(struct ath_hal *ah, const char* fmt, va_list ap) 153 1.1 alc { 154 1.1 alc vprintf(fmt, ap); 155 1.1 alc } 156 1.1 alc 157 1.1 alc void 158 1.1 alc ath_hal_printf(struct ath_hal *ah, const char* fmt, ...) 159 1.1 alc { 160 1.1 alc va_list ap; 161 1.1 alc va_start(ap, fmt); 162 1.1 alc ath_hal_vprintf(ah, fmt, ap); 163 1.1 alc va_end(ap); 164 1.1 alc } 165 1.1 alc 166 1.1 alc const char* 167 1.1 alc ath_hal_ether_sprintf(const u_int8_t *mac) 168 1.1 alc { 169 1.2 martin return ether_sprintf(mac); 170 1.1 alc } 171 1.1 alc 172 1.1 alc #ifdef ATHHAL_DEBUG 173 1.1 alc void 174 1.6 nakayama HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) 175 1.1 alc { 176 1.6 nakayama if (ath_hal_debug & mask) { 177 1.1 alc va_list ap; 178 1.1 alc va_start(ap, fmt); 179 1.1 alc ath_hal_vprintf(ah, fmt, ap); 180 1.1 alc va_end(ap); 181 1.1 alc } 182 1.1 alc } 183 1.1 alc #endif /* ATHHAL_DEBUG */ 184 1.1 alc 185 1.1 alc #ifdef ATHHAL_DEBUG_ALQ 186 1.1 alc /* 187 1.1 alc * ALQ register tracing support. 188 1.1 alc * 189 1.1 alc * Setting hw.ath.hal.alq=1 enables tracing of all register reads and 190 1.1 alc * writes to the file /tmp/ath_hal.log. The file format is a simple 191 1.1 alc * fixed-size array of records. When done logging set hw.ath.hal.alq=0 192 1.1 alc * and then decode the file with the arcode program (that is part of the 193 1.1 alc * HAL). If you start+stop tracing the data will be appended to an 194 1.1 alc * existing file. 195 1.1 alc * 196 1.1 alc * NB: doesn't handle multiple devices properly; only one DEVICE record 197 1.1 alc * is emitted and the different devices are not identified. 198 1.1 alc */ 199 1.1 alc #include <sys/alq.h> 200 1.1 alc #include <sys/pcpu.h> 201 1.1 alc 202 1.1 alc static struct alq *ath_hal_alq; 203 1.1 alc static int ath_hal_alq_emitdev; /* need to emit DEVICE record */ 204 1.1 alc static u_int ath_hal_alq_lost; /* count of lost records */ 205 1.1 alc static const char *ath_hal_logfile = "/tmp/ath_hal.log"; 206 1.1 alc static u_int ath_hal_alq_qsize = 64*1024; 207 1.1 alc 208 1.1 alc static int 209 1.1 alc ath_hal_setlogging(int enable) 210 1.1 alc { 211 1.1 alc int error; 212 1.1 alc 213 1.1 alc if (enable) { 214 1.7 christos error = kauth_authorize_network(kauth_cred_get(), 215 1.1 alc KAUTH_NETWORK_INTERFACE, 216 1.1 alc KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, NULL, NULL, NULL); 217 1.1 alc if (error == 0) { 218 1.1 alc error = alq_open(&ath_hal_alq, ath_hal_logfile, 219 1.1 alc curproc->p_ucred, 220 1.1 alc sizeof (struct athregrec), ath_hal_alq_qsize); 221 1.1 alc ath_hal_alq_lost = 0; 222 1.1 alc ath_hal_alq_emitdev = 1; 223 1.1 alc printf("ath_hal: logging to %s enabled\n", 224 1.1 alc ath_hal_logfile); 225 1.1 alc } 226 1.1 alc } else { 227 1.1 alc if (ath_hal_alq) 228 1.1 alc alq_close(ath_hal_alq); 229 1.1 alc ath_hal_alq = NULL; 230 1.1 alc printf("ath_hal: logging disabled\n"); 231 1.1 alc error = 0; 232 1.1 alc } 233 1.1 alc return (error); 234 1.1 alc } 235 1.1 alc 236 1.1 alc static int 237 1.1 alc sysctl_hw_ath_hal_log(SYSCTL_HANDLER_ARGS) 238 1.1 alc { 239 1.1 alc int error, enable; 240 1.1 alc 241 1.1 alc enable = (ath_hal_alq != NULL); 242 1.1 alc error = sysctl_handle_int(oidp, &enable, 0, req); 243 1.1 alc if (error || !req->newptr) 244 1.1 alc return (error); 245 1.1 alc else 246 1.1 alc return (ath_hal_setlogging(enable)); 247 1.1 alc } 248 1.1 alc SYSCTL_PROC(_hw_ath_hal, OID_AUTO, alq, CTLTYPE_INT|CTLFLAG_RW, 249 1.1 alc 0, 0, sysctl_hw_ath_hal_log, "I", "Enable HAL register logging"); 250 1.1 alc SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_size, CTLFLAG_RW, 251 1.1 alc &ath_hal_alq_qsize, 0, "In-memory log size (#records)"); 252 1.1 alc SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_lost, CTLFLAG_RW, 253 1.1 alc &ath_hal_alq_lost, 0, "Register operations not logged"); 254 1.1 alc 255 1.1 alc static struct ale * 256 1.1 alc ath_hal_alq_get(struct ath_hal *ah) 257 1.1 alc { 258 1.1 alc struct ale *ale; 259 1.1 alc 260 1.1 alc if (ath_hal_alq_emitdev) { 261 1.1 alc ale = alq_get(ath_hal_alq, ALQ_NOWAIT); 262 1.1 alc if (ale) { 263 1.1 alc struct athregrec *r = 264 1.1 alc (struct athregrec *) ale->ae_data; 265 1.1 alc r->op = OP_DEVICE; 266 1.1 alc r->reg = 0; 267 1.1 alc r->val = ah->ah_devid; 268 1.1 alc alq_post(ath_hal_alq, ale); 269 1.1 alc ath_hal_alq_emitdev = 0; 270 1.1 alc } else 271 1.1 alc ath_hal_alq_lost++; 272 1.1 alc } 273 1.1 alc ale = alq_get(ath_hal_alq, ALQ_NOWAIT); 274 1.1 alc if (!ale) 275 1.1 alc ath_hal_alq_lost++; 276 1.1 alc return ale; 277 1.1 alc } 278 1.1 alc 279 1.1 alc void 280 1.1 alc ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val) 281 1.1 alc { 282 1.1 alc bus_space_tag_t t = BUSTAG(ah); 283 1.1 alc 284 1.1 alc if (ath_hal_alq) { 285 1.1 alc struct ale *ale = ath_hal_alq_get(ah); 286 1.1 alc if (ale) { 287 1.1 alc struct athregrec *r = (struct athregrec *) ale->ae_data; 288 1.1 alc r->op = OP_WRITE; 289 1.1 alc r->reg = reg; 290 1.1 alc r->val = val; 291 1.1 alc alq_post(ath_hal_alq, ale); 292 1.1 alc } 293 1.1 alc } 294 1.1 alc #if _BYTE_ORDER == _BIG_ENDIAN 295 1.1 alc if (reg >= 0x4000 && reg < 0x5000) 296 1.1 alc bus_space_write_4(t, h, reg, val); 297 1.1 alc else 298 1.1 alc #endif 299 1.1 alc bus_space_write_stream_4(t, h, reg, val); 300 1.1 alc } 301 1.1 alc 302 1.1 alc u_int32_t 303 1.1 alc ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg) 304 1.1 alc { 305 1.1 alc u_int32_t val; 306 1.1 alc bus_space_handle_t h = BUSHANDLE(ah); 307 1.1 alc bus_space_tag_t t = BUSTAG(ah); 308 1.1 alc 309 1.1 alc #if _BYTE_ORDER == _BIG_ENDIAN 310 1.1 alc if (reg >= 0x4000 && reg < 0x5000) 311 1.1 alc val = bus_space_read_4(t, h, reg); 312 1.1 alc else 313 1.1 alc #endif 314 1.1 alc val = bus_space_read_stream_4(t, h, reg); 315 1.1 alc 316 1.1 alc if (ath_hal_alq) { 317 1.1 alc struct ale *ale = ath_hal_alq_get(ah); 318 1.1 alc if (ale) { 319 1.1 alc struct athregrec *r = (struct athregrec *) ale->ae_data; 320 1.1 alc r->op = OP_READ; 321 1.1 alc r->reg = reg; 322 1.1 alc r->val = val; 323 1.1 alc alq_post(ath_hal_alq, ale); 324 1.1 alc } 325 1.1 alc } 326 1.1 alc 327 1.1 alc return val; 328 1.1 alc } 329 1.1 alc 330 1.1 alc void 331 1.1 alc OS_MARK(struct ath_hal *ah, u_int id, u_int32_t v) 332 1.1 alc { 333 1.1 alc if (ath_hal_alq) { 334 1.1 alc struct ale *ale = ath_hal_alq_get(ah); 335 1.2 martin 336 1.1 alc if (ale) { 337 1.1 alc struct athregrec *r = (struct athregrec *) ale->ae_data; 338 1.1 alc r->op = OP_MARK; 339 1.1 alc r->reg = id; 340 1.1 alc r->val = v; 341 1.1 alc alq_post(ath_hal_alq, ale); 342 1.1 alc } 343 1.1 alc } 344 1.1 alc } 345 1.1 alc #elif defined(ATHHAL_DEBUG) || defined(AH_REGOPS_FUNC) 346 1.1 alc /* 347 1.1 alc * Memory-mapped device register read/write. These are here 348 1.1 alc * as routines when debugging support is enabled and/or when 349 1.1 alc * explicitly configured to use function calls. The latter is 350 1.1 alc * for architectures that might need to do something before 351 1.1 alc * referencing memory (e.g. remap an i/o window). 352 1.1 alc * 353 1.1 alc * NB: see the comments in ah_osdep.h about byte-swapping register 354 1.1 alc * reads and writes to understand what's going on below. 355 1.1 alc */ 356 1.1 alc 357 1.1 alc void 358 1.1 alc ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val) 359 1.1 alc { 360 1.1 alc bus_space_handle_t h = BUSHANDLE(ah); 361 1.1 alc bus_space_tag_t t = BUSTAG(ah); 362 1.1 alc 363 1.1 alc #if _BYTE_ORDER == _BIG_ENDIAN 364 1.1 alc if (reg >= 0x4000 && reg < 0x5000) 365 1.1 alc bus_space_write_4(t, h, reg, val); 366 1.1 alc else 367 1.1 alc #endif 368 1.1 alc bus_space_write_stream_4(t, h, reg, val); 369 1.1 alc } 370 1.1 alc 371 1.1 alc u_int32_t 372 1.1 alc ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg) 373 1.1 alc { 374 1.1 alc bus_space_handle_t h = BUSHANDLE(ah); 375 1.1 alc bus_space_tag_t t = BUSTAG(ah); 376 1.1 alc uint32_t ret; 377 1.1 alc 378 1.1 alc #if _BYTE_ORDER == _BIG_ENDIAN 379 1.1 alc if (reg >= 0x4000 && reg < 0x5000) 380 1.1 alc ret = bus_space_read_4(t, h, reg); 381 1.1 alc else 382 1.1 alc #endif 383 1.1 alc ret = bus_space_read_stream_4(t, h, reg); 384 1.1 alc 385 1.1 alc return ret; 386 1.1 alc } 387 1.1 alc #endif /* ATHHAL_DEBUG || AH_REGOPS_FUNC */ 388 1.1 alc 389 1.1 alc #ifdef ATHHAL_ASSERT 390 1.1 alc void 391 1.1 alc ath_hal_assert_failed(const char* filename, int lineno, const char *msg) 392 1.1 alc { 393 1.1 alc printf("Atheros HAL assertion failure: %s: line %u: %s\n", 394 1.1 alc filename, lineno, msg); 395 1.1 alc panic("ath_hal_assert"); 396 1.1 alc } 397 1.1 alc #endif /* ATHHAL_ASSERT */ 398 1.1 alc 399 1.1 alc /* 400 1.1 alc * Delay n microseconds. 401 1.1 alc */ 402 1.1 alc void 403 1.1 alc ath_hal_delay(int n) 404 1.1 alc { 405 1.1 alc DELAY(n); 406 1.1 alc } 407 1.1 alc 408 1.1 alc u_int32_t 409 1.1 alc ath_hal_getuptime(struct ath_hal *ah) 410 1.1 alc { 411 1.1 alc struct bintime bt; 412 1.1 alc uint32_t ret; 413 1.1 alc getbinuptime(&bt); 414 1.1 alc ret = (bt.sec * 1000) + 415 1.1 alc (((uint64_t)1000 * (uint32_t)(bt.frac >> 32)) >> 32); 416 1.1 alc return ret; 417 1.1 alc } 418 1.1 alc 419 1.1 alc void 420 1.1 alc ath_hal_memzero(void *dst, size_t n) 421 1.1 alc { 422 1.1 alc (void)memset(dst, 0, n); 423 1.1 alc } 424 1.1 alc 425 1.1 alc void * 426 1.1 alc ath_hal_memcpy(void *dst, const void *src, size_t n) 427 1.1 alc { 428 1.2 martin return memcpy(dst, src, n); 429 1.1 alc } 430 1.4 jmcneill 431 1.4 jmcneill MODULE(MODULE_CLASS_MISC, ath_hal, NULL); 432 1.4 jmcneill 433 1.4 jmcneill static int 434 1.4 jmcneill ath_hal_modcmd(modcmd_t cmd, void *opaque) 435 1.4 jmcneill { 436 1.4 jmcneill switch (cmd) { 437 1.4 jmcneill case MODULE_CMD_INIT: 438 1.4 jmcneill case MODULE_CMD_FINI: 439 1.4 jmcneill return 0; 440 1.4 jmcneill default: 441 1.4 jmcneill return ENOTTY; 442 1.4 jmcneill } 443 1.4 jmcneill } 444