xref: /freebsd/sys/dev/ath/ah_osdep.c (revision 6ed22fae0a041f4b37ca6233981053fef5009554)
13fe92528SSam Leffler /*-
2b032f27cSSam Leffler  * Copyright (c) 2002-2008 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  *
163fe92528SSam Leffler  * NO WARRANTY
173fe92528SSam Leffler  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
183fe92528SSam Leffler  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
193fe92528SSam Leffler  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
203fe92528SSam Leffler  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
213fe92528SSam Leffler  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
223fe92528SSam Leffler  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
233fe92528SSam Leffler  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
243fe92528SSam Leffler  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
253fe92528SSam Leffler  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
263fe92528SSam Leffler  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
273fe92528SSam Leffler  * THE POSSIBILITY OF SUCH DAMAGES.
283fe92528SSam Leffler  *
293fe92528SSam Leffler  * $FreeBSD$
303fe92528SSam Leffler  */
313fe92528SSam Leffler #include "opt_ah.h"
323fe92528SSam Leffler 
333fe92528SSam Leffler #include <sys/param.h>
343fe92528SSam Leffler #include <sys/systm.h>
353fe92528SSam Leffler #include <sys/kernel.h>
363fe92528SSam Leffler #include <sys/module.h>
373fe92528SSam Leffler #include <sys/sysctl.h>
383fe92528SSam Leffler #include <sys/bus.h>
393fe92528SSam Leffler #include <sys/malloc.h>
403fe92528SSam Leffler #include <sys/proc.h>
412fe1131cSAdrian Chadd #include <sys/pcpu.h>
42ddbe3036SAdrian Chadd #include <sys/lock.h>
43ddbe3036SAdrian Chadd #include <sys/mutex.h>
443fe92528SSam Leffler 
453fe92528SSam Leffler #include <machine/stdarg.h>
463fe92528SSam Leffler 
473fe92528SSam Leffler #include <net/ethernet.h>		/* XXX for ether_sprintf */
483fe92528SSam Leffler 
4933644623SSam Leffler #include <dev/ath/ath_hal/ah.h>
50020841a2SAdrian Chadd #include <dev/ath/ath_hal/ah_debug.h>
513fe92528SSam Leffler 
523fe92528SSam Leffler /*
533fe92528SSam Leffler  * WiSoC boards overload the bus tag with information about the
543fe92528SSam Leffler  * board layout.  We must extract the bus space tag from that
553fe92528SSam Leffler  * indirect structure.  For everyone else the tag is passed in
563fe92528SSam Leffler  * directly.
573fe92528SSam Leffler  * XXX cache indirect ref privately
583fe92528SSam Leffler  */
593fe92528SSam Leffler #ifdef AH_SUPPORT_AR5312
603fe92528SSam Leffler #define	BUSTAG(ah) \
613fe92528SSam Leffler 	((bus_space_tag_t) ((struct ar531x_config *)((ah)->ah_st))->tag)
623fe92528SSam Leffler #else
6333644623SSam Leffler #define	BUSTAG(ah)	((ah)->ah_st)
643fe92528SSam Leffler #endif
653fe92528SSam Leffler 
66ddbe3036SAdrian Chadd /*
67ddbe3036SAdrian Chadd  * This lock is used to seralise register access for chips which have
68ddbe3036SAdrian Chadd  * problems w/ SMP CPUs issuing concurrent PCI transactions.
69ddbe3036SAdrian Chadd  *
70ddbe3036SAdrian Chadd  * XXX This is a global lock for now; it should be pushed to
71ddbe3036SAdrian Chadd  * a per-device lock in some platform-independent fashion.
72ddbe3036SAdrian Chadd  */
73ddbe3036SAdrian Chadd struct mtx ah_regser_mtx;
74ddbe3036SAdrian Chadd MTX_SYSINIT(ah_regser, &ah_regser_mtx, "Atheros register access mutex",
75ddbe3036SAdrian Chadd     MTX_SPIN);
76ddbe3036SAdrian Chadd 
773fe92528SSam Leffler extern	void ath_hal_printf(struct ath_hal *, const char*, ...)
783fe92528SSam Leffler 		__printflike(2,3);
793fe92528SSam Leffler extern	void ath_hal_vprintf(struct ath_hal *, const char*, __va_list)
803fe92528SSam Leffler 		__printflike(2, 0);
813fe92528SSam Leffler extern	const char* ath_hal_ether_sprintf(const u_int8_t *mac);
823fe92528SSam Leffler extern	void *ath_hal_malloc(size_t);
833fe92528SSam Leffler extern	void ath_hal_free(void *);
843fe92528SSam Leffler #ifdef AH_ASSERT
853fe92528SSam Leffler extern	void ath_hal_assert_failed(const char* filename,
863fe92528SSam Leffler 		int lineno, const char* msg);
873fe92528SSam Leffler #endif
883fe92528SSam Leffler #ifdef AH_DEBUG
89f247e820SAdrian Chadd extern	void DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...);
903fe92528SSam Leffler #endif /* AH_DEBUG */
913fe92528SSam Leffler 
923fe92528SSam Leffler /* NB: put this here instead of the driver to avoid circular references */
933fe92528SSam Leffler SYSCTL_NODE(_hw, OID_AUTO, ath, CTLFLAG_RD, 0, "Atheros driver parameters");
946472ac3dSEd Schouten static SYSCTL_NODE(_hw_ath, OID_AUTO, hal, CTLFLAG_RD, 0,
956472ac3dSEd Schouten     "Atheros HAL parameters");
961a940429SAdrian Chadd 
971a940429SAdrian Chadd #ifdef AH_DEBUG
981a940429SAdrian Chadd int ath_hal_debug = 0;
991a940429SAdrian Chadd SYSCTL_INT(_hw_ath_hal, OID_AUTO, debug, CTLFLAG_RW, &ath_hal_debug,
1001a940429SAdrian Chadd     0, "Atheros HAL debugging printfs");
1011a940429SAdrian Chadd TUNABLE_INT("hw.ath.hal.debug", &ath_hal_debug);
1021a940429SAdrian Chadd #endif /* AH_DEBUG */
1033fe92528SSam Leffler 
104d745c852SEd Schouten static MALLOC_DEFINE(M_ATH_HAL, "ath_hal", "ath hal data");
1053fe92528SSam Leffler 
1063fe92528SSam Leffler void*
1073fe92528SSam Leffler ath_hal_malloc(size_t size)
1083fe92528SSam Leffler {
1093fe92528SSam Leffler 	return malloc(size, M_ATH_HAL, M_NOWAIT | M_ZERO);
1103fe92528SSam Leffler }
1113fe92528SSam Leffler 
1123fe92528SSam Leffler void
1133fe92528SSam Leffler ath_hal_free(void* p)
1143fe92528SSam Leffler {
1152ef29b4cSSam Leffler 	free(p, M_ATH_HAL);
1163fe92528SSam Leffler }
1173fe92528SSam Leffler 
1183fe92528SSam Leffler void
1193fe92528SSam Leffler ath_hal_vprintf(struct ath_hal *ah, const char* fmt, va_list ap)
1203fe92528SSam Leffler {
1213fe92528SSam Leffler 	vprintf(fmt, ap);
1223fe92528SSam Leffler }
1233fe92528SSam Leffler 
1243fe92528SSam Leffler void
1253fe92528SSam Leffler ath_hal_printf(struct ath_hal *ah, const char* fmt, ...)
1263fe92528SSam Leffler {
1273fe92528SSam Leffler 	va_list ap;
1283fe92528SSam Leffler 	va_start(ap, fmt);
1293fe92528SSam Leffler 	ath_hal_vprintf(ah, fmt, ap);
1303fe92528SSam Leffler 	va_end(ap);
1313fe92528SSam Leffler }
1323fe92528SSam Leffler 
1333fe92528SSam Leffler const char*
1343fe92528SSam Leffler ath_hal_ether_sprintf(const u_int8_t *mac)
1353fe92528SSam Leffler {
1363fe92528SSam Leffler 	return ether_sprintf(mac);
1373fe92528SSam Leffler }
1383fe92528SSam Leffler 
1393fe92528SSam Leffler #ifdef AH_DEBUG
1406c63a20bSAdrian Chadd 
141*6ed22faeSAdrian Chadd /*
142*6ed22faeSAdrian Chadd  * XXX This is highly relevant only for the AR5416 and later
143*6ed22faeSAdrian Chadd  * PCI/PCIe NICs.  It'll need adjustment for other hardware
144*6ed22faeSAdrian Chadd  * variations.
145*6ed22faeSAdrian Chadd  */
146*6ed22faeSAdrian Chadd static int
147*6ed22faeSAdrian Chadd ath_hal_reg_whilst_asleep(struct ath_hal *ah, uint32_t reg)
148*6ed22faeSAdrian Chadd {
149*6ed22faeSAdrian Chadd 
150*6ed22faeSAdrian Chadd 	if (reg >= 0x4000 && reg < 0x5000)
151*6ed22faeSAdrian Chadd 		return (1);
152*6ed22faeSAdrian Chadd 	if (reg >= 0x6000 && reg < 0x7000)
153*6ed22faeSAdrian Chadd 		return (1);
154*6ed22faeSAdrian Chadd 	if (reg >= 0x7000 && reg < 0x8000)
155*6ed22faeSAdrian Chadd 		return (1);
156*6ed22faeSAdrian Chadd 	return (0);
157*6ed22faeSAdrian Chadd }
158*6ed22faeSAdrian Chadd 
159411373ebSSam Leffler void
160f247e820SAdrian Chadd DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...)
161411373ebSSam Leffler {
1621292e2e9SAdrian Chadd 	if ((mask == HAL_DEBUG_UNMASKABLE) ||
1630e56140aSAdrian Chadd 	    (ah != NULL && ah->ah_config.ah_debug & mask) ||
1641292e2e9SAdrian Chadd 	    (ath_hal_debug & mask)) {
165411373ebSSam Leffler 		__va_list ap;
166411373ebSSam Leffler 		va_start(ap, fmt);
167411373ebSSam Leffler 		ath_hal_vprintf(ah, fmt, ap);
168411373ebSSam Leffler 		va_end(ap);
169411373ebSSam Leffler 	}
170411373ebSSam Leffler }
1716c63a20bSAdrian Chadd #undef	HAL_DEBUG_UNMASKABLE
1723fe92528SSam Leffler #endif /* AH_DEBUG */
1733fe92528SSam Leffler 
1743fe92528SSam Leffler #ifdef AH_DEBUG_ALQ
1753fe92528SSam Leffler /*
1763fe92528SSam Leffler  * ALQ register tracing support.
1773fe92528SSam Leffler  *
1783fe92528SSam Leffler  * Setting hw.ath.hal.alq=1 enables tracing of all register reads and
1793fe92528SSam Leffler  * writes to the file /tmp/ath_hal.log.  The file format is a simple
1803fe92528SSam Leffler  * fixed-size array of records.  When done logging set hw.ath.hal.alq=0
1813fe92528SSam Leffler  * and then decode the file with the arcode program (that is part of the
1823fe92528SSam Leffler  * HAL).  If you start+stop tracing the data will be appended to an
1833fe92528SSam Leffler  * existing file.
1843fe92528SSam Leffler  *
1853fe92528SSam Leffler  * NB: doesn't handle multiple devices properly; only one DEVICE record
1863fe92528SSam Leffler  *     is emitted and the different devices are not identified.
1873fe92528SSam Leffler  */
1883fe92528SSam Leffler #include <sys/alq.h>
1893fe92528SSam Leffler #include <sys/pcpu.h>
19033644623SSam Leffler #include <dev/ath/ath_hal/ah_decode.h>
1913fe92528SSam Leffler 
1923fe92528SSam Leffler static	struct alq *ath_hal_alq;
1933fe92528SSam Leffler static	int ath_hal_alq_emitdev;	/* need to emit DEVICE record */
1943fe92528SSam Leffler static	u_int ath_hal_alq_lost;		/* count of lost records */
195c5d52723SAdrian Chadd static	char ath_hal_logfile[MAXPATHLEN] = "/tmp/ath_hal.log";
196c5d52723SAdrian Chadd 
197c5d52723SAdrian Chadd SYSCTL_STRING(_hw_ath_hal, OID_AUTO, alq_logfile, CTLFLAG_RW,
198c5d52723SAdrian Chadd     &ath_hal_logfile, sizeof(kernelname), "Name of ALQ logfile");
199c5d52723SAdrian Chadd 
2003fe92528SSam Leffler static	u_int ath_hal_alq_qsize = 64*1024;
2013fe92528SSam Leffler 
2023fe92528SSam Leffler static int
2033fe92528SSam Leffler ath_hal_setlogging(int enable)
2043fe92528SSam Leffler {
2053fe92528SSam Leffler 	int error;
2063fe92528SSam Leffler 
2073fe92528SSam Leffler 	if (enable) {
2083fe92528SSam Leffler 		error = alq_open(&ath_hal_alq, ath_hal_logfile,
2093fe92528SSam Leffler 			curthread->td_ucred, ALQ_DEFAULT_CMODE,
2103fe92528SSam Leffler 			sizeof (struct athregrec), ath_hal_alq_qsize);
2113fe92528SSam Leffler 		ath_hal_alq_lost = 0;
2123fe92528SSam Leffler 		ath_hal_alq_emitdev = 1;
2133fe92528SSam Leffler 		printf("ath_hal: logging to %s enabled\n",
2143fe92528SSam Leffler 			ath_hal_logfile);
2153fe92528SSam Leffler 	} else {
2163fe92528SSam Leffler 		if (ath_hal_alq)
2173fe92528SSam Leffler 			alq_close(ath_hal_alq);
2183fe92528SSam Leffler 		ath_hal_alq = NULL;
2193fe92528SSam Leffler 		printf("ath_hal: logging disabled\n");
2203fe92528SSam Leffler 		error = 0;
2213fe92528SSam Leffler 	}
2223fe92528SSam Leffler 	return (error);
2233fe92528SSam Leffler }
2243fe92528SSam Leffler 
2253fe92528SSam Leffler static int
2263fe92528SSam Leffler sysctl_hw_ath_hal_log(SYSCTL_HANDLER_ARGS)
2273fe92528SSam Leffler {
2283fe92528SSam Leffler 	int error, enable;
2293fe92528SSam Leffler 
2303fe92528SSam Leffler 	enable = (ath_hal_alq != NULL);
2313fe92528SSam Leffler         error = sysctl_handle_int(oidp, &enable, 0, req);
2323fe92528SSam Leffler         if (error || !req->newptr)
2333fe92528SSam Leffler                 return (error);
2343fe92528SSam Leffler 	else
2353fe92528SSam Leffler 		return (ath_hal_setlogging(enable));
2363fe92528SSam Leffler }
2373fe92528SSam Leffler SYSCTL_PROC(_hw_ath_hal, OID_AUTO, alq, CTLTYPE_INT|CTLFLAG_RW,
2383fe92528SSam Leffler 	0, 0, sysctl_hw_ath_hal_log, "I", "Enable HAL register logging");
2393fe92528SSam Leffler SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_size, CTLFLAG_RW,
2403fe92528SSam Leffler 	&ath_hal_alq_qsize, 0, "In-memory log size (#records)");
2413fe92528SSam Leffler SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_lost, CTLFLAG_RW,
2423fe92528SSam Leffler 	&ath_hal_alq_lost, 0, "Register operations not logged");
2433fe92528SSam Leffler 
2443fe92528SSam Leffler static struct ale *
2453fe92528SSam Leffler ath_hal_alq_get(struct ath_hal *ah)
2463fe92528SSam Leffler {
2473fe92528SSam Leffler 	struct ale *ale;
2483fe92528SSam Leffler 
2493fe92528SSam Leffler 	if (ath_hal_alq_emitdev) {
2503fe92528SSam Leffler 		ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
2513fe92528SSam Leffler 		if (ale) {
2523fe92528SSam Leffler 			struct athregrec *r =
2533fe92528SSam Leffler 				(struct athregrec *) ale->ae_data;
2543fe92528SSam Leffler 			r->op = OP_DEVICE;
2553fe92528SSam Leffler 			r->reg = 0;
2563fe92528SSam Leffler 			r->val = ah->ah_devid;
2573fe92528SSam Leffler 			alq_post(ath_hal_alq, ale);
2583fe92528SSam Leffler 			ath_hal_alq_emitdev = 0;
2593fe92528SSam Leffler 		} else
2603fe92528SSam Leffler 			ath_hal_alq_lost++;
2613fe92528SSam Leffler 	}
2623fe92528SSam Leffler 	ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
2633fe92528SSam Leffler 	if (!ale)
2643fe92528SSam Leffler 		ath_hal_alq_lost++;
2653fe92528SSam Leffler 	return ale;
2663fe92528SSam Leffler }
2673fe92528SSam Leffler 
2683fe92528SSam Leffler void
2693fe92528SSam Leffler ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
2703fe92528SSam Leffler {
2713fe92528SSam Leffler 	bus_space_tag_t tag = BUSTAG(ah);
27233644623SSam Leffler 	bus_space_handle_t h = ah->ah_sh;
2733fe92528SSam Leffler 
274517dfcb1SAdrian Chadd 	/* Debug - complain if we haven't fully waken things up */
275*6ed22faeSAdrian Chadd 	if (! ath_hal_reg_whilst_asleep(ah, reg) &&
276*6ed22faeSAdrian Chadd 	    ah->ah_powerMode != HAL_PM_AWAKE) {
277517dfcb1SAdrian Chadd 		ath_hal_printf(ah, "%s: reg=0x%08x, val=0x%08x, pm=%d\n",
278517dfcb1SAdrian Chadd 		    __func__, reg, val, ah->ah_powerMode);
279517dfcb1SAdrian Chadd 	}
280517dfcb1SAdrian Chadd 
2813fe92528SSam Leffler 	if (ath_hal_alq) {
2823fe92528SSam Leffler 		struct ale *ale = ath_hal_alq_get(ah);
2833fe92528SSam Leffler 		if (ale) {
2843fe92528SSam Leffler 			struct athregrec *r = (struct athregrec *) ale->ae_data;
2852fe1131cSAdrian Chadd 			r->threadid = curthread->td_tid;
2863fe92528SSam Leffler 			r->op = OP_WRITE;
2873fe92528SSam Leffler 			r->reg = reg;
2883fe92528SSam Leffler 			r->val = val;
2893fe92528SSam Leffler 			alq_post(ath_hal_alq, ale);
2903fe92528SSam Leffler 		}
2913fe92528SSam Leffler 	}
292ddbe3036SAdrian Chadd 	if (ah->ah_config.ah_serialise_reg_war)
293ddbe3036SAdrian Chadd 		mtx_lock_spin(&ah_regser_mtx);
2943fe92528SSam Leffler 	bus_space_write_4(tag, h, reg, val);
295ddbe3036SAdrian Chadd 	if (ah->ah_config.ah_serialise_reg_war)
296ddbe3036SAdrian Chadd 		mtx_unlock_spin(&ah_regser_mtx);
2973fe92528SSam Leffler }
2983fe92528SSam Leffler 
2993fe92528SSam Leffler u_int32_t
3003fe92528SSam Leffler ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
3013fe92528SSam Leffler {
3023fe92528SSam Leffler 	bus_space_tag_t tag = BUSTAG(ah);
30333644623SSam Leffler 	bus_space_handle_t h = ah->ah_sh;
3043fe92528SSam Leffler 	u_int32_t val;
3053fe92528SSam Leffler 
306517dfcb1SAdrian Chadd 	/* Debug - complain if we haven't fully waken things up */
307*6ed22faeSAdrian Chadd 	if (! ath_hal_reg_whilst_asleep(ah, reg) &&
308*6ed22faeSAdrian Chadd 	    ah->ah_powerMode != HAL_PM_AWAKE) {
309517dfcb1SAdrian Chadd 		ath_hal_printf(ah, "%s: reg=0x%08x, pm=%d\n",
310517dfcb1SAdrian Chadd 		    __func__, reg, ah->ah_powerMode);
311517dfcb1SAdrian Chadd 	}
312517dfcb1SAdrian Chadd 
313ddbe3036SAdrian Chadd 	if (ah->ah_config.ah_serialise_reg_war)
314ddbe3036SAdrian Chadd 		mtx_lock_spin(&ah_regser_mtx);
3153fe92528SSam Leffler 	val = bus_space_read_4(tag, h, reg);
316ddbe3036SAdrian Chadd 	if (ah->ah_config.ah_serialise_reg_war)
317ddbe3036SAdrian Chadd 		mtx_unlock_spin(&ah_regser_mtx);
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;
3222fe1131cSAdrian Chadd 			r->threadid = curthread->td_tid;
3233fe92528SSam Leffler 			r->op = OP_READ;
3243fe92528SSam Leffler 			r->reg = reg;
3253fe92528SSam Leffler 			r->val = val;
3263fe92528SSam Leffler 			alq_post(ath_hal_alq, ale);
3273fe92528SSam Leffler 		}
3283fe92528SSam Leffler 	}
3293fe92528SSam Leffler 	return val;
3303fe92528SSam Leffler }
3313fe92528SSam Leffler 
3323fe92528SSam Leffler void
3333fe92528SSam Leffler OS_MARK(struct ath_hal *ah, u_int id, u_int32_t v)
3343fe92528SSam Leffler {
3353fe92528SSam Leffler 	if (ath_hal_alq) {
3363fe92528SSam Leffler 		struct ale *ale = ath_hal_alq_get(ah);
3373fe92528SSam Leffler 		if (ale) {
3383fe92528SSam Leffler 			struct athregrec *r = (struct athregrec *) ale->ae_data;
3392fe1131cSAdrian Chadd 			r->threadid = curthread->td_tid;
3403fe92528SSam Leffler 			r->op = OP_MARK;
3413fe92528SSam Leffler 			r->reg = id;
3423fe92528SSam Leffler 			r->val = v;
3433fe92528SSam Leffler 			alq_post(ath_hal_alq, ale);
3443fe92528SSam Leffler 		}
3453fe92528SSam Leffler 	}
3463fe92528SSam Leffler }
3473fe92528SSam Leffler #elif defined(AH_DEBUG) || defined(AH_REGOPS_FUNC)
3483fe92528SSam Leffler /*
3493fe92528SSam Leffler  * Memory-mapped device register read/write.  These are here
3503fe92528SSam Leffler  * as routines when debugging support is enabled and/or when
3513fe92528SSam Leffler  * explicitly configured to use function calls.  The latter is
3523fe92528SSam Leffler  * for architectures that might need to do something before
3533fe92528SSam Leffler  * referencing memory (e.g. remap an i/o window).
3543fe92528SSam Leffler  *
3553fe92528SSam Leffler  * NB: see the comments in ah_osdep.h about byte-swapping register
3563fe92528SSam Leffler  *     reads and writes to understand what's going on below.
3573fe92528SSam Leffler  */
3583fe92528SSam Leffler 
3593fe92528SSam Leffler void
3603fe92528SSam Leffler ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
3613fe92528SSam Leffler {
3623fe92528SSam Leffler 	bus_space_tag_t tag = BUSTAG(ah);
36333644623SSam Leffler 	bus_space_handle_t h = ah->ah_sh;
3643fe92528SSam Leffler 
365517dfcb1SAdrian Chadd 	/* Debug - complain if we haven't fully waken things up */
366*6ed22faeSAdrian Chadd 	if (! ath_hal_reg_whilst_asleep(ah, reg) &&
367*6ed22faeSAdrian Chadd 	    ah->ah_powerMode != HAL_PM_AWAKE) {
368517dfcb1SAdrian Chadd 		ath_hal_printf(ah, "%s: reg=0x%08x, val=0x%08x, pm=%d\n",
369517dfcb1SAdrian Chadd 		    __func__, reg, val, ah->ah_powerMode);
370517dfcb1SAdrian Chadd 	}
371517dfcb1SAdrian Chadd 
372ddbe3036SAdrian Chadd 	if (ah->ah_config.ah_serialise_reg_war)
373ddbe3036SAdrian Chadd 		mtx_lock_spin(&ah_regser_mtx);
3743fe92528SSam Leffler 	bus_space_write_4(tag, h, reg, val);
375ddbe3036SAdrian Chadd 	if (ah->ah_config.ah_serialise_reg_war)
376ddbe3036SAdrian Chadd 		mtx_unlock_spin(&ah_regser_mtx);
3773fe92528SSam Leffler }
3783fe92528SSam Leffler 
3793fe92528SSam Leffler u_int32_t
3803fe92528SSam Leffler ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
3813fe92528SSam Leffler {
3823fe92528SSam Leffler 	bus_space_tag_t tag = BUSTAG(ah);
38333644623SSam Leffler 	bus_space_handle_t h = ah->ah_sh;
3843fe92528SSam Leffler 	u_int32_t val;
3853fe92528SSam Leffler 
386517dfcb1SAdrian Chadd 	/* Debug - complain if we haven't fully waken things up */
387*6ed22faeSAdrian Chadd 	if (! ath_hal_reg_whilst_asleep(ah, reg) &&
388*6ed22faeSAdrian Chadd 	    ah->ah_powerMode != HAL_PM_AWAKE) {
389517dfcb1SAdrian Chadd 		ath_hal_printf(ah, "%s: reg=0x%08x, pm=%d\n",
390517dfcb1SAdrian Chadd 		    __func__, reg, ah->ah_powerMode);
391517dfcb1SAdrian Chadd 	}
392517dfcb1SAdrian Chadd 
393ddbe3036SAdrian Chadd 	if (ah->ah_config.ah_serialise_reg_war)
394ddbe3036SAdrian Chadd 		mtx_lock_spin(&ah_regser_mtx);
3953fe92528SSam Leffler 	val = bus_space_read_4(tag, h, reg);
396ddbe3036SAdrian Chadd 	if (ah->ah_config.ah_serialise_reg_war)
397ddbe3036SAdrian Chadd 		mtx_unlock_spin(&ah_regser_mtx);
3983fe92528SSam Leffler 	return val;
3993fe92528SSam Leffler }
4003fe92528SSam Leffler #endif /* AH_DEBUG || AH_REGOPS_FUNC */
4013fe92528SSam Leffler 
4023fe92528SSam Leffler #ifdef AH_ASSERT
4033fe92528SSam Leffler void
4043fe92528SSam Leffler ath_hal_assert_failed(const char* filename, int lineno, const char *msg)
4053fe92528SSam Leffler {
4063fe92528SSam Leffler 	printf("Atheros HAL assertion failure: %s: line %u: %s\n",
4073fe92528SSam Leffler 		filename, lineno, msg);
4083fe92528SSam Leffler 	panic("ath_hal_assert");
4093fe92528SSam Leffler }
4103fe92528SSam Leffler #endif /* AH_ASSERT */
411