xref: /freebsd/sys/dev/ath/ah_osdep.c (revision 3fe92528afe8313fecf48822dde74bad5e380f48)
13fe92528SSam Leffler /*-
23fe92528SSam Leffler  * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
33fe92528SSam Leffler  * All rights reserved.
43fe92528SSam Leffler  *
53fe92528SSam Leffler  * Redistribution and use in source and binary forms, with or without
63fe92528SSam Leffler  * modification, are permitted provided that the following conditions
73fe92528SSam Leffler  * are met:
83fe92528SSam Leffler  * 1. Redistributions of source code must retain the above copyright
93fe92528SSam Leffler  *    notice, this list of conditions and the following disclaimer,
103fe92528SSam Leffler  *    without modification.
113fe92528SSam Leffler  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
123fe92528SSam Leffler  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
133fe92528SSam Leffler  *    redistribution must be conditioned upon including a substantially
143fe92528SSam Leffler  *    similar Disclaimer requirement for further binary redistribution.
153fe92528SSam Leffler  * 3. Neither the names of the above-listed copyright holders nor the names
163fe92528SSam Leffler  *    of any contributors may be used to endorse or promote products derived
173fe92528SSam Leffler  *    from this software without specific prior written permission.
183fe92528SSam Leffler  *
193fe92528SSam Leffler  * Alternatively, this software may be distributed under the terms of the
203fe92528SSam Leffler  * GNU General Public License ("GPL") version 2 as published by the Free
213fe92528SSam Leffler  * Software Foundation.
223fe92528SSam Leffler  *
233fe92528SSam Leffler  * NO WARRANTY
243fe92528SSam Leffler  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
253fe92528SSam Leffler  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
263fe92528SSam Leffler  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
273fe92528SSam Leffler  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
283fe92528SSam Leffler  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
293fe92528SSam Leffler  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
303fe92528SSam Leffler  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
313fe92528SSam Leffler  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
323fe92528SSam Leffler  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
333fe92528SSam Leffler  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
343fe92528SSam Leffler  * THE POSSIBILITY OF SUCH DAMAGES.
353fe92528SSam Leffler  *
363fe92528SSam Leffler  * $FreeBSD$
373fe92528SSam Leffler  */
383fe92528SSam Leffler #include "opt_ah.h"
393fe92528SSam Leffler 
403fe92528SSam Leffler #include <sys/param.h>
413fe92528SSam Leffler #include <sys/systm.h>
423fe92528SSam Leffler #include <sys/kernel.h>
433fe92528SSam Leffler #include <sys/module.h>
443fe92528SSam Leffler #include <sys/sysctl.h>
453fe92528SSam Leffler #include <sys/bus.h>
463fe92528SSam Leffler #include <sys/malloc.h>
473fe92528SSam Leffler #include <sys/proc.h>
483fe92528SSam Leffler 
493fe92528SSam Leffler #include <machine/stdarg.h>
503fe92528SSam Leffler 
513fe92528SSam Leffler #include <net/ethernet.h>		/* XXX for ether_sprintf */
523fe92528SSam Leffler 
533fe92528SSam Leffler #include <contrib/dev/ath/ah.h>
543fe92528SSam Leffler 
553fe92528SSam Leffler /*
563fe92528SSam Leffler  * WiSoC boards overload the bus tag with information about the
573fe92528SSam Leffler  * board layout.  We must extract the bus space tag from that
583fe92528SSam Leffler  * indirect structure.  For everyone else the tag is passed in
593fe92528SSam Leffler  * directly.
603fe92528SSam Leffler  * XXX cache indirect ref privately
613fe92528SSam Leffler  */
623fe92528SSam Leffler #ifdef AH_SUPPORT_AR5312
633fe92528SSam Leffler #define	BUSTAG(ah) \
643fe92528SSam Leffler 	((bus_space_tag_t) ((struct ar531x_config *)((ah)->ah_st))->tag)
653fe92528SSam Leffler #else
663fe92528SSam Leffler #define	BUSTAG(ah)	((bus_space_tag_t) (ah)->ah_st)
673fe92528SSam Leffler #endif
683fe92528SSam Leffler 
693fe92528SSam Leffler extern	void ath_hal_printf(struct ath_hal *, const char*, ...)
703fe92528SSam Leffler 		__printflike(2,3);
713fe92528SSam Leffler extern	void ath_hal_vprintf(struct ath_hal *, const char*, __va_list)
723fe92528SSam Leffler 		__printflike(2, 0);
733fe92528SSam Leffler extern	const char* ath_hal_ether_sprintf(const u_int8_t *mac);
743fe92528SSam Leffler extern	void *ath_hal_malloc(size_t);
753fe92528SSam Leffler extern	void ath_hal_free(void *);
763fe92528SSam Leffler #ifdef AH_ASSERT
773fe92528SSam Leffler extern	void ath_hal_assert_failed(const char* filename,
783fe92528SSam Leffler 		int lineno, const char* msg);
793fe92528SSam Leffler #endif
803fe92528SSam Leffler #ifdef AH_DEBUG
813fe92528SSam Leffler extern	void HALDEBUG(struct ath_hal *ah, const char* fmt, ...);
823fe92528SSam Leffler extern	void HALDEBUGn(struct ath_hal *ah, u_int level, const char* fmt, ...);
833fe92528SSam Leffler #endif /* AH_DEBUG */
843fe92528SSam Leffler 
853fe92528SSam Leffler /* NB: put this here instead of the driver to avoid circular references */
863fe92528SSam Leffler SYSCTL_NODE(_hw, OID_AUTO, ath, CTLFLAG_RD, 0, "Atheros driver parameters");
873fe92528SSam Leffler SYSCTL_NODE(_hw_ath, OID_AUTO, hal, CTLFLAG_RD, 0, "Atheros HAL parameters");
883fe92528SSam Leffler 
893fe92528SSam Leffler #ifdef AH_DEBUG
903fe92528SSam Leffler static	int ath_hal_debug = 0;
913fe92528SSam Leffler SYSCTL_INT(_hw_ath_hal, OID_AUTO, debug, CTLFLAG_RW, &ath_hal_debug,
923fe92528SSam Leffler 	    0, "Atheros HAL debugging printfs");
933fe92528SSam Leffler TUNABLE_INT("hw.ath.hal.debug", &ath_hal_debug);
943fe92528SSam Leffler #endif /* AH_DEBUG */
953fe92528SSam Leffler 
963fe92528SSam Leffler SYSCTL_STRING(_hw_ath_hal, OID_AUTO, version, CTLFLAG_RD, ath_hal_version, 0,
973fe92528SSam Leffler 	"Atheros HAL version");
983fe92528SSam Leffler 
993fe92528SSam Leffler /* NB: these are deprecated; they exist for now for compatibility */
1003fe92528SSam Leffler int	ath_hal_dma_beacon_response_time = 2;	/* in TU's */
1013fe92528SSam Leffler SYSCTL_INT(_hw_ath_hal, OID_AUTO, dma_brt, CTLFLAG_RW,
1023fe92528SSam Leffler 	   &ath_hal_dma_beacon_response_time, 0,
1033fe92528SSam Leffler 	   "Atheros HAL DMA beacon response time");
1043fe92528SSam Leffler int	ath_hal_sw_beacon_response_time = 10;	/* in TU's */
1053fe92528SSam Leffler SYSCTL_INT(_hw_ath_hal, OID_AUTO, sw_brt, CTLFLAG_RW,
1063fe92528SSam Leffler 	   &ath_hal_sw_beacon_response_time, 0,
1073fe92528SSam Leffler 	   "Atheros HAL software beacon response time");
1083fe92528SSam Leffler int	ath_hal_additional_swba_backoff = 0;	/* in TU's */
1093fe92528SSam Leffler SYSCTL_INT(_hw_ath_hal, OID_AUTO, swba_backoff, CTLFLAG_RW,
1103fe92528SSam Leffler 	   &ath_hal_additional_swba_backoff, 0,
1113fe92528SSam Leffler 	   "Atheros HAL additional SWBA backoff time");
1123fe92528SSam Leffler 
1133fe92528SSam Leffler MALLOC_DEFINE(M_ATH_HAL, "ath_hal", "ath hal data");
1143fe92528SSam Leffler 
1153fe92528SSam Leffler void*
1163fe92528SSam Leffler ath_hal_malloc(size_t size)
1173fe92528SSam Leffler {
1183fe92528SSam Leffler 	return malloc(size, M_ATH_HAL, M_NOWAIT | M_ZERO);
1193fe92528SSam Leffler }
1203fe92528SSam Leffler 
1213fe92528SSam Leffler void
1223fe92528SSam Leffler ath_hal_free(void* p)
1233fe92528SSam Leffler {
1243fe92528SSam Leffler 	return free(p, M_ATH_HAL);
1253fe92528SSam Leffler }
1263fe92528SSam Leffler 
1273fe92528SSam Leffler void
1283fe92528SSam Leffler ath_hal_vprintf(struct ath_hal *ah, const char* fmt, va_list ap)
1293fe92528SSam Leffler {
1303fe92528SSam Leffler 	vprintf(fmt, ap);
1313fe92528SSam Leffler }
1323fe92528SSam Leffler 
1333fe92528SSam Leffler void
1343fe92528SSam Leffler ath_hal_printf(struct ath_hal *ah, const char* fmt, ...)
1353fe92528SSam Leffler {
1363fe92528SSam Leffler 	va_list ap;
1373fe92528SSam Leffler 	va_start(ap, fmt);
1383fe92528SSam Leffler 	ath_hal_vprintf(ah, fmt, ap);
1393fe92528SSam Leffler 	va_end(ap);
1403fe92528SSam Leffler }
1413fe92528SSam Leffler 
1423fe92528SSam Leffler const char*
1433fe92528SSam Leffler ath_hal_ether_sprintf(const u_int8_t *mac)
1443fe92528SSam Leffler {
1453fe92528SSam Leffler 	return ether_sprintf(mac);
1463fe92528SSam Leffler }
1473fe92528SSam Leffler 
1483fe92528SSam Leffler #ifdef AH_DEBUG
1493fe92528SSam Leffler void
1503fe92528SSam Leffler HALDEBUG(struct ath_hal *ah, const char* fmt, ...)
1513fe92528SSam Leffler {
1523fe92528SSam Leffler 	if (ath_hal_debug) {
1533fe92528SSam Leffler 		__va_list ap;
1543fe92528SSam Leffler 		va_start(ap, fmt);
1553fe92528SSam Leffler 		ath_hal_vprintf(ah, fmt, ap);
1563fe92528SSam Leffler 		va_end(ap);
1573fe92528SSam Leffler 	}
1583fe92528SSam Leffler }
1593fe92528SSam Leffler 
1603fe92528SSam Leffler void
1613fe92528SSam Leffler HALDEBUGn(struct ath_hal *ah, u_int level, const char* fmt, ...)
1623fe92528SSam Leffler {
1633fe92528SSam Leffler 	if (ath_hal_debug >= level) {
1643fe92528SSam Leffler 		__va_list ap;
1653fe92528SSam Leffler 		va_start(ap, fmt);
1663fe92528SSam Leffler 		ath_hal_vprintf(ah, fmt, ap);
1673fe92528SSam Leffler 		va_end(ap);
1683fe92528SSam Leffler 	}
1693fe92528SSam Leffler }
1703fe92528SSam Leffler #endif /* AH_DEBUG */
1713fe92528SSam Leffler 
1723fe92528SSam Leffler #ifdef AH_DEBUG_ALQ
1733fe92528SSam Leffler /*
1743fe92528SSam Leffler  * ALQ register tracing support.
1753fe92528SSam Leffler  *
1763fe92528SSam Leffler  * Setting hw.ath.hal.alq=1 enables tracing of all register reads and
1773fe92528SSam Leffler  * writes to the file /tmp/ath_hal.log.  The file format is a simple
1783fe92528SSam Leffler  * fixed-size array of records.  When done logging set hw.ath.hal.alq=0
1793fe92528SSam Leffler  * and then decode the file with the arcode program (that is part of the
1803fe92528SSam Leffler  * HAL).  If you start+stop tracing the data will be appended to an
1813fe92528SSam Leffler  * existing file.
1823fe92528SSam Leffler  *
1833fe92528SSam Leffler  * NB: doesn't handle multiple devices properly; only one DEVICE record
1843fe92528SSam Leffler  *     is emitted and the different devices are not identified.
1853fe92528SSam Leffler  */
1863fe92528SSam Leffler #include <sys/alq.h>
1873fe92528SSam Leffler #include <sys/pcpu.h>
1883fe92528SSam Leffler #include <contrib/dev/ath/ah_decode.h>
1893fe92528SSam Leffler 
1903fe92528SSam Leffler static	struct alq *ath_hal_alq;
1913fe92528SSam Leffler static	int ath_hal_alq_emitdev;	/* need to emit DEVICE record */
1923fe92528SSam Leffler static	u_int ath_hal_alq_lost;		/* count of lost records */
1933fe92528SSam Leffler static	const char *ath_hal_logfile = "/tmp/ath_hal.log";
1943fe92528SSam Leffler static	u_int ath_hal_alq_qsize = 64*1024;
1953fe92528SSam Leffler 
1963fe92528SSam Leffler static int
1973fe92528SSam Leffler ath_hal_setlogging(int enable)
1983fe92528SSam Leffler {
1993fe92528SSam Leffler 	int error;
2003fe92528SSam Leffler 
2013fe92528SSam Leffler 	if (enable) {
2023fe92528SSam Leffler 		error = suser(curthread);
2033fe92528SSam Leffler 		if (error == 0) {
2043fe92528SSam Leffler 			error = alq_open(&ath_hal_alq, ath_hal_logfile,
2053fe92528SSam Leffler 				curthread->td_ucred, ALQ_DEFAULT_CMODE,
2063fe92528SSam Leffler 				sizeof (struct athregrec), ath_hal_alq_qsize);
2073fe92528SSam Leffler 			ath_hal_alq_lost = 0;
2083fe92528SSam Leffler 			ath_hal_alq_emitdev = 1;
2093fe92528SSam Leffler 			printf("ath_hal: logging to %s enabled\n",
2103fe92528SSam Leffler 				ath_hal_logfile);
2113fe92528SSam Leffler 		}
2123fe92528SSam Leffler 	} else {
2133fe92528SSam Leffler 		if (ath_hal_alq)
2143fe92528SSam Leffler 			alq_close(ath_hal_alq);
2153fe92528SSam Leffler 		ath_hal_alq = NULL;
2163fe92528SSam Leffler 		printf("ath_hal: logging disabled\n");
2173fe92528SSam Leffler 		error = 0;
2183fe92528SSam Leffler 	}
2193fe92528SSam Leffler 	return (error);
2203fe92528SSam Leffler }
2213fe92528SSam Leffler 
2223fe92528SSam Leffler static int
2233fe92528SSam Leffler sysctl_hw_ath_hal_log(SYSCTL_HANDLER_ARGS)
2243fe92528SSam Leffler {
2253fe92528SSam Leffler 	int error, enable;
2263fe92528SSam Leffler 
2273fe92528SSam Leffler 	enable = (ath_hal_alq != NULL);
2283fe92528SSam Leffler         error = sysctl_handle_int(oidp, &enable, 0, req);
2293fe92528SSam Leffler         if (error || !req->newptr)
2303fe92528SSam Leffler                 return (error);
2313fe92528SSam Leffler 	else
2323fe92528SSam Leffler 		return (ath_hal_setlogging(enable));
2333fe92528SSam Leffler }
2343fe92528SSam Leffler SYSCTL_PROC(_hw_ath_hal, OID_AUTO, alq, CTLTYPE_INT|CTLFLAG_RW,
2353fe92528SSam Leffler 	0, 0, sysctl_hw_ath_hal_log, "I", "Enable HAL register logging");
2363fe92528SSam Leffler SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_size, CTLFLAG_RW,
2373fe92528SSam Leffler 	&ath_hal_alq_qsize, 0, "In-memory log size (#records)");
2383fe92528SSam Leffler SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_lost, CTLFLAG_RW,
2393fe92528SSam Leffler 	&ath_hal_alq_lost, 0, "Register operations not logged");
2403fe92528SSam Leffler 
2413fe92528SSam Leffler static struct ale *
2423fe92528SSam Leffler ath_hal_alq_get(struct ath_hal *ah)
2433fe92528SSam Leffler {
2443fe92528SSam Leffler 	struct ale *ale;
2453fe92528SSam Leffler 
2463fe92528SSam Leffler 	if (ath_hal_alq_emitdev) {
2473fe92528SSam Leffler 		ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
2483fe92528SSam Leffler 		if (ale) {
2493fe92528SSam Leffler 			struct athregrec *r =
2503fe92528SSam Leffler 				(struct athregrec *) ale->ae_data;
2513fe92528SSam Leffler 			r->op = OP_DEVICE;
2523fe92528SSam Leffler 			r->reg = 0;
2533fe92528SSam Leffler 			r->val = ah->ah_devid;
2543fe92528SSam Leffler 			alq_post(ath_hal_alq, ale);
2553fe92528SSam Leffler 			ath_hal_alq_emitdev = 0;
2563fe92528SSam Leffler 		} else
2573fe92528SSam Leffler 			ath_hal_alq_lost++;
2583fe92528SSam Leffler 	}
2593fe92528SSam Leffler 	ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
2603fe92528SSam Leffler 	if (!ale)
2613fe92528SSam Leffler 		ath_hal_alq_lost++;
2623fe92528SSam Leffler 	return ale;
2633fe92528SSam Leffler }
2643fe92528SSam Leffler 
2653fe92528SSam Leffler void
2663fe92528SSam Leffler ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
2673fe92528SSam Leffler {
2683fe92528SSam Leffler 	bus_space_tag_t tag = BUSTAG(ah);
2693fe92528SSam Leffler 	bus_space_handle_t h = (bus_space_handle_t) ah->ah_sh;
2703fe92528SSam Leffler 
2713fe92528SSam Leffler 	if (ath_hal_alq) {
2723fe92528SSam Leffler 		struct ale *ale = ath_hal_alq_get(ah);
2733fe92528SSam Leffler 		if (ale) {
2743fe92528SSam Leffler 			struct athregrec *r = (struct athregrec *) ale->ae_data;
2753fe92528SSam Leffler 			r->op = OP_WRITE;
2763fe92528SSam Leffler 			r->reg = reg;
2773fe92528SSam Leffler 			r->val = val;
2783fe92528SSam Leffler 			alq_post(ath_hal_alq, ale);
2793fe92528SSam Leffler 		}
2803fe92528SSam Leffler 	}
2813fe92528SSam Leffler #if _BYTE_ORDER == _BIG_ENDIAN
2823fe92528SSam Leffler 	if (reg >= 0x4000 && reg < 0x5000)
2833fe92528SSam Leffler 		bus_space_write_4(tag, h, reg, val);
2843fe92528SSam Leffler 	else
2853fe92528SSam Leffler #endif
2863fe92528SSam Leffler 		bus_space_write_stream_4(tag, h, reg, val);
2873fe92528SSam Leffler }
2883fe92528SSam Leffler 
2893fe92528SSam Leffler u_int32_t
2903fe92528SSam Leffler ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
2913fe92528SSam Leffler {
2923fe92528SSam Leffler 	bus_space_tag_t tag = BUSTAG(ah);
2933fe92528SSam Leffler 	bus_space_handle_t h = (bus_space_handle_t) ah->ah_sh;
2943fe92528SSam Leffler 	u_int32_t val;
2953fe92528SSam Leffler 
2963fe92528SSam Leffler #if _BYTE_ORDER == _BIG_ENDIAN
2973fe92528SSam Leffler 	if (reg >= 0x4000 && reg < 0x5000)
2983fe92528SSam Leffler 		val = bus_space_read_4(tag, h, reg);
2993fe92528SSam Leffler 	else
3003fe92528SSam Leffler #endif
3013fe92528SSam Leffler 		val = bus_space_read_stream_4(tag, h, reg);
3023fe92528SSam Leffler 	if (ath_hal_alq) {
3033fe92528SSam Leffler 		struct ale *ale = ath_hal_alq_get(ah);
3043fe92528SSam Leffler 		if (ale) {
3053fe92528SSam Leffler 			struct athregrec *r = (struct athregrec *) ale->ae_data;
3063fe92528SSam Leffler 			r->op = OP_READ;
3073fe92528SSam Leffler 			r->reg = reg;
3083fe92528SSam Leffler 			r->val = val;
3093fe92528SSam Leffler 			alq_post(ath_hal_alq, ale);
3103fe92528SSam Leffler 		}
3113fe92528SSam Leffler 	}
3123fe92528SSam Leffler 	return val;
3133fe92528SSam Leffler }
3143fe92528SSam Leffler 
3153fe92528SSam Leffler void
3163fe92528SSam Leffler OS_MARK(struct ath_hal *ah, u_int id, u_int32_t v)
3173fe92528SSam Leffler {
3183fe92528SSam Leffler 	if (ath_hal_alq) {
3193fe92528SSam Leffler 		struct ale *ale = ath_hal_alq_get(ah);
3203fe92528SSam Leffler 		if (ale) {
3213fe92528SSam Leffler 			struct athregrec *r = (struct athregrec *) ale->ae_data;
3223fe92528SSam Leffler 			r->op = OP_MARK;
3233fe92528SSam Leffler 			r->reg = id;
3243fe92528SSam Leffler 			r->val = v;
3253fe92528SSam Leffler 			alq_post(ath_hal_alq, ale);
3263fe92528SSam Leffler 		}
3273fe92528SSam Leffler 	}
3283fe92528SSam Leffler }
3293fe92528SSam Leffler #elif defined(AH_DEBUG) || defined(AH_REGOPS_FUNC)
3303fe92528SSam Leffler /*
3313fe92528SSam Leffler  * Memory-mapped device register read/write.  These are here
3323fe92528SSam Leffler  * as routines when debugging support is enabled and/or when
3333fe92528SSam Leffler  * explicitly configured to use function calls.  The latter is
3343fe92528SSam Leffler  * for architectures that might need to do something before
3353fe92528SSam Leffler  * referencing memory (e.g. remap an i/o window).
3363fe92528SSam Leffler  *
3373fe92528SSam Leffler  * NB: see the comments in ah_osdep.h about byte-swapping register
3383fe92528SSam Leffler  *     reads and writes to understand what's going on below.
3393fe92528SSam Leffler  */
3403fe92528SSam Leffler 
3413fe92528SSam Leffler void
3423fe92528SSam Leffler ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
3433fe92528SSam Leffler {
3443fe92528SSam Leffler 	bus_space_tag_t tag = BUSTAG(ah);
3453fe92528SSam Leffler 	bus_space_handle_t h = (bus_space_handle_t) ah->ah_sh;
3463fe92528SSam Leffler 
3473fe92528SSam Leffler #if _BYTE_ORDER == _BIG_ENDIAN
3483fe92528SSam Leffler 	if (reg >= 0x4000 && reg < 0x5000)
3493fe92528SSam Leffler 		bus_space_write_4(tag, h, reg, val);
3503fe92528SSam Leffler 	else
3513fe92528SSam Leffler #endif
3523fe92528SSam Leffler 		bus_space_write_stream_4(tag, h, reg, val);
3533fe92528SSam Leffler }
3543fe92528SSam Leffler 
3553fe92528SSam Leffler u_int32_t
3563fe92528SSam Leffler ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
3573fe92528SSam Leffler {
3583fe92528SSam Leffler 	bus_space_tag_t tag = BUSTAG(ah);
3593fe92528SSam Leffler 	bus_space_handle_t h = (bus_space_handle_t) ah->ah_sh;
3603fe92528SSam Leffler 	u_int32_t val;
3613fe92528SSam Leffler 
3623fe92528SSam Leffler #if _BYTE_ORDER == _BIG_ENDIAN
3633fe92528SSam Leffler 	if (reg >= 0x4000 && reg < 0x5000)
3643fe92528SSam Leffler 		val = bus_space_read_4(tag, h, reg);
3653fe92528SSam Leffler 	else
3663fe92528SSam Leffler #endif
3673fe92528SSam Leffler 		val = bus_space_read_stream_4(tag, h, reg);
3683fe92528SSam Leffler 	return val;
3693fe92528SSam Leffler }
3703fe92528SSam Leffler #endif /* AH_DEBUG || AH_REGOPS_FUNC */
3713fe92528SSam Leffler 
3723fe92528SSam Leffler #ifdef AH_ASSERT
3733fe92528SSam Leffler void
3743fe92528SSam Leffler ath_hal_assert_failed(const char* filename, int lineno, const char *msg)
3753fe92528SSam Leffler {
3763fe92528SSam Leffler 	printf("Atheros HAL assertion failure: %s: line %u: %s\n",
3773fe92528SSam Leffler 		filename, lineno, msg);
3783fe92528SSam Leffler 	panic("ath_hal_assert");
3793fe92528SSam Leffler }
3803fe92528SSam Leffler #endif /* AH_ASSERT */
3813fe92528SSam Leffler 
3823fe92528SSam Leffler /*
3833fe92528SSam Leffler  * Delay n microseconds.
3843fe92528SSam Leffler  */
3853fe92528SSam Leffler void
3863fe92528SSam Leffler ath_hal_delay(int n)
3873fe92528SSam Leffler {
3883fe92528SSam Leffler 	DELAY(n);
3893fe92528SSam Leffler }
3903fe92528SSam Leffler 
3913fe92528SSam Leffler u_int32_t
3923fe92528SSam Leffler ath_hal_getuptime(struct ath_hal *ah)
3933fe92528SSam Leffler {
3943fe92528SSam Leffler 	struct bintime bt;
3953fe92528SSam Leffler 	getbinuptime(&bt);
3963fe92528SSam Leffler 	return (bt.sec * 1000) +
3973fe92528SSam Leffler 		(((uint64_t)1000 * (uint32_t)(bt.frac >> 32)) >> 32);
3983fe92528SSam Leffler }
3993fe92528SSam Leffler 
4003fe92528SSam Leffler void
4013fe92528SSam Leffler ath_hal_memzero(void *dst, size_t n)
4023fe92528SSam Leffler {
4033fe92528SSam Leffler 	bzero(dst, n);
4043fe92528SSam Leffler }
4053fe92528SSam Leffler 
4063fe92528SSam Leffler void *
4073fe92528SSam Leffler ath_hal_memcpy(void *dst, const void *src, size_t n)
4083fe92528SSam Leffler {
4093fe92528SSam Leffler 	return memcpy(dst, src, n);
4103fe92528SSam Leffler }
4113fe92528SSam Leffler 
4123fe92528SSam Leffler /*
4133fe92528SSam Leffler  * Module glue.
4143fe92528SSam Leffler  */
4153fe92528SSam Leffler 
4163fe92528SSam Leffler static int
4173fe92528SSam Leffler ath_hal_modevent(module_t mod, int type, void *unused)
4183fe92528SSam Leffler {
4193fe92528SSam Leffler 	const char *sep;
4203fe92528SSam Leffler 	int i;
4213fe92528SSam Leffler 
4223fe92528SSam Leffler 	switch (type) {
4233fe92528SSam Leffler 	case MOD_LOAD:
4243fe92528SSam Leffler 		printf("ath_hal: %s (", ath_hal_version);
4253fe92528SSam Leffler 		sep = "";
4263fe92528SSam Leffler 		for (i = 0; ath_hal_buildopts[i] != NULL; i++) {
4273fe92528SSam Leffler 			printf("%s%s", sep, ath_hal_buildopts[i]);
4283fe92528SSam Leffler 			sep = ", ";
4293fe92528SSam Leffler 		}
4303fe92528SSam Leffler 		printf(")\n");
4313fe92528SSam Leffler 		return 0;
4323fe92528SSam Leffler 	case MOD_UNLOAD:
4333fe92528SSam Leffler 		return 0;
4343fe92528SSam Leffler 	}
4353fe92528SSam Leffler 	return EINVAL;
4363fe92528SSam Leffler }
4373fe92528SSam Leffler 
4383fe92528SSam Leffler static moduledata_t ath_hal_mod = {
4393fe92528SSam Leffler 	"ath_hal",
4403fe92528SSam Leffler 	ath_hal_modevent,
4413fe92528SSam Leffler 	0
4423fe92528SSam Leffler };
4433fe92528SSam Leffler DECLARE_MODULE(ath_hal, ath_hal_mod, SI_SUB_DRIVERS, SI_ORDER_ANY);
4443fe92528SSam Leffler MODULE_VERSION(ath_hal, 1);
445