xref: /freebsd/sys/dev/ath/ah_osdep.c (revision 718cf2ccb9956613756ab15d7a0e28f2c8e91cab)
13fe92528SSam Leffler /*-
2*718cf2ccSPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*718cf2ccSPedro F. Giffuni  *
4b032f27cSSam Leffler  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
53fe92528SSam Leffler  * All rights reserved.
63fe92528SSam Leffler  *
73fe92528SSam Leffler  * Redistribution and use in source and binary forms, with or without
83fe92528SSam Leffler  * modification, are permitted provided that the following conditions
93fe92528SSam Leffler  * are met:
103fe92528SSam Leffler  * 1. Redistributions of source code must retain the above copyright
113fe92528SSam Leffler  *    notice, this list of conditions and the following disclaimer,
123fe92528SSam Leffler  *    without modification.
133fe92528SSam Leffler  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
143fe92528SSam Leffler  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
153fe92528SSam Leffler  *    redistribution must be conditioned upon including a substantially
163fe92528SSam Leffler  *    similar Disclaimer requirement for further binary redistribution.
173fe92528SSam Leffler  *
183fe92528SSam Leffler  * NO WARRANTY
193fe92528SSam Leffler  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
203fe92528SSam Leffler  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
213fe92528SSam Leffler  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
223fe92528SSam Leffler  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
233fe92528SSam Leffler  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
243fe92528SSam Leffler  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
253fe92528SSam Leffler  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
263fe92528SSam Leffler  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
273fe92528SSam Leffler  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
283fe92528SSam Leffler  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
293fe92528SSam Leffler  * THE POSSIBILITY OF SUCH DAMAGES.
303fe92528SSam Leffler  *
313fe92528SSam Leffler  * $FreeBSD$
323fe92528SSam Leffler  */
333fe92528SSam Leffler #include "opt_ah.h"
343fe92528SSam Leffler 
353fe92528SSam Leffler #include <sys/param.h>
363fe92528SSam Leffler #include <sys/systm.h>
373fe92528SSam Leffler #include <sys/kernel.h>
383fe92528SSam Leffler #include <sys/module.h>
393fe92528SSam Leffler #include <sys/sysctl.h>
403fe92528SSam Leffler #include <sys/bus.h>
413fe92528SSam Leffler #include <sys/malloc.h>
423fe92528SSam Leffler #include <sys/proc.h>
432fe1131cSAdrian Chadd #include <sys/pcpu.h>
44ddbe3036SAdrian Chadd #include <sys/lock.h>
45ddbe3036SAdrian Chadd #include <sys/mutex.h>
4641059135SAdrian Chadd #include <sys/conf.h>
473fe92528SSam Leffler 
483fe92528SSam Leffler #include <machine/stdarg.h>
493fe92528SSam Leffler 
503fe92528SSam Leffler #include <net/ethernet.h>		/* XXX for ether_sprintf */
513fe92528SSam Leffler 
5233644623SSam Leffler #include <dev/ath/ath_hal/ah.h>
53020841a2SAdrian Chadd #include <dev/ath/ath_hal/ah_debug.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
6633644623SSam Leffler #define	BUSTAG(ah)	((ah)->ah_st)
673fe92528SSam Leffler #endif
683fe92528SSam Leffler 
69ddbe3036SAdrian Chadd /*
70ddbe3036SAdrian Chadd  * This lock is used to seralise register access for chips which have
71ddbe3036SAdrian Chadd  * problems w/ SMP CPUs issuing concurrent PCI transactions.
72ddbe3036SAdrian Chadd  *
73ddbe3036SAdrian Chadd  * XXX This is a global lock for now; it should be pushed to
74ddbe3036SAdrian Chadd  * a per-device lock in some platform-independent fashion.
75ddbe3036SAdrian Chadd  */
76ddbe3036SAdrian Chadd struct mtx ah_regser_mtx;
77ddbe3036SAdrian Chadd MTX_SYSINIT(ah_regser, &ah_regser_mtx, "Atheros register access mutex",
78ddbe3036SAdrian Chadd     MTX_SPIN);
79ddbe3036SAdrian Chadd 
803fe92528SSam Leffler extern	void ath_hal_printf(struct ath_hal *, const char*, ...)
813fe92528SSam Leffler 		__printflike(2,3);
823fe92528SSam Leffler extern	void ath_hal_vprintf(struct ath_hal *, const char*, __va_list)
833fe92528SSam Leffler 		__printflike(2, 0);
843fe92528SSam Leffler extern	const char* ath_hal_ether_sprintf(const u_int8_t *mac);
853fe92528SSam Leffler extern	void *ath_hal_malloc(size_t);
863fe92528SSam Leffler extern	void ath_hal_free(void *);
873fe92528SSam Leffler #ifdef AH_ASSERT
883fe92528SSam Leffler extern	void ath_hal_assert_failed(const char* filename,
893fe92528SSam Leffler 		int lineno, const char* msg);
903fe92528SSam Leffler #endif
913fe92528SSam Leffler #ifdef AH_DEBUG
92f247e820SAdrian Chadd extern	void DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...);
933fe92528SSam Leffler #endif /* AH_DEBUG */
943fe92528SSam Leffler 
953fe92528SSam Leffler /* NB: put this here instead of the driver to avoid circular references */
963fe92528SSam Leffler SYSCTL_NODE(_hw, OID_AUTO, ath, CTLFLAG_RD, 0, "Atheros driver parameters");
976472ac3dSEd Schouten static SYSCTL_NODE(_hw_ath, OID_AUTO, hal, CTLFLAG_RD, 0,
986472ac3dSEd Schouten     "Atheros HAL parameters");
991a940429SAdrian Chadd 
1001a940429SAdrian Chadd #ifdef AH_DEBUG
1011a940429SAdrian Chadd int ath_hal_debug = 0;
102af3b2549SHans Petter Selasky SYSCTL_INT(_hw_ath_hal, OID_AUTO, debug, CTLFLAG_RWTUN, &ath_hal_debug,
1031a940429SAdrian Chadd     0, "Atheros HAL debugging printfs");
1041a940429SAdrian Chadd #endif /* AH_DEBUG */
1053fe92528SSam Leffler 
106d745c852SEd Schouten static MALLOC_DEFINE(M_ATH_HAL, "ath_hal", "ath hal data");
1073fe92528SSam Leffler 
1083fe92528SSam Leffler void*
1093fe92528SSam Leffler ath_hal_malloc(size_t size)
1103fe92528SSam Leffler {
1113fe92528SSam Leffler 	return malloc(size, M_ATH_HAL, M_NOWAIT | M_ZERO);
1123fe92528SSam Leffler }
1133fe92528SSam Leffler 
1143fe92528SSam Leffler void
1153fe92528SSam Leffler ath_hal_free(void* p)
1163fe92528SSam Leffler {
1172ef29b4cSSam Leffler 	free(p, M_ATH_HAL);
1183fe92528SSam Leffler }
1193fe92528SSam Leffler 
1203fe92528SSam Leffler void
1213fe92528SSam Leffler ath_hal_vprintf(struct ath_hal *ah, const char* fmt, va_list ap)
1223fe92528SSam Leffler {
1233fe92528SSam Leffler 	vprintf(fmt, ap);
1243fe92528SSam Leffler }
1253fe92528SSam Leffler 
1263fe92528SSam Leffler void
1273fe92528SSam Leffler ath_hal_printf(struct ath_hal *ah, const char* fmt, ...)
1283fe92528SSam Leffler {
1293fe92528SSam Leffler 	va_list ap;
1303fe92528SSam Leffler 	va_start(ap, fmt);
1313fe92528SSam Leffler 	ath_hal_vprintf(ah, fmt, ap);
1323fe92528SSam Leffler 	va_end(ap);
1333fe92528SSam Leffler }
1343fe92528SSam Leffler 
1353fe92528SSam Leffler const char*
1363fe92528SSam Leffler ath_hal_ether_sprintf(const u_int8_t *mac)
1373fe92528SSam Leffler {
1383fe92528SSam Leffler 	return ether_sprintf(mac);
1393fe92528SSam Leffler }
1403fe92528SSam Leffler 
1413fe92528SSam Leffler #ifdef AH_DEBUG
1426c63a20bSAdrian Chadd 
1436ed22faeSAdrian Chadd /*
1446ed22faeSAdrian Chadd  * XXX This is highly relevant only for the AR5416 and later
1456ed22faeSAdrian Chadd  * PCI/PCIe NICs.  It'll need adjustment for other hardware
1466ed22faeSAdrian Chadd  * variations.
1476ed22faeSAdrian Chadd  */
1486ed22faeSAdrian Chadd static int
1496ed22faeSAdrian Chadd ath_hal_reg_whilst_asleep(struct ath_hal *ah, uint32_t reg)
1506ed22faeSAdrian Chadd {
1516ed22faeSAdrian Chadd 
1526ed22faeSAdrian Chadd 	if (reg >= 0x4000 && reg < 0x5000)
1536ed22faeSAdrian Chadd 		return (1);
1546ed22faeSAdrian Chadd 	if (reg >= 0x6000 && reg < 0x7000)
1556ed22faeSAdrian Chadd 		return (1);
1566ed22faeSAdrian Chadd 	if (reg >= 0x7000 && reg < 0x8000)
1576ed22faeSAdrian Chadd 		return (1);
1586ed22faeSAdrian Chadd 	return (0);
1596ed22faeSAdrian Chadd }
1606ed22faeSAdrian Chadd 
161411373ebSSam Leffler void
162f247e820SAdrian Chadd DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...)
163411373ebSSam Leffler {
1641292e2e9SAdrian Chadd 	if ((mask == HAL_DEBUG_UNMASKABLE) ||
1650e56140aSAdrian Chadd 	    (ah != NULL && ah->ah_config.ah_debug & mask) ||
1661292e2e9SAdrian Chadd 	    (ath_hal_debug & mask)) {
167411373ebSSam Leffler 		__va_list ap;
168411373ebSSam Leffler 		va_start(ap, fmt);
169411373ebSSam Leffler 		ath_hal_vprintf(ah, fmt, ap);
170411373ebSSam Leffler 		va_end(ap);
171411373ebSSam Leffler 	}
172411373ebSSam Leffler }
1736c63a20bSAdrian Chadd #undef	HAL_DEBUG_UNMASKABLE
1743fe92528SSam Leffler #endif /* AH_DEBUG */
1753fe92528SSam Leffler 
1763fe92528SSam Leffler #ifdef AH_DEBUG_ALQ
1773fe92528SSam Leffler /*
1783fe92528SSam Leffler  * ALQ register tracing support.
1793fe92528SSam Leffler  *
1803fe92528SSam Leffler  * Setting hw.ath.hal.alq=1 enables tracing of all register reads and
1813fe92528SSam Leffler  * writes to the file /tmp/ath_hal.log.  The file format is a simple
1823fe92528SSam Leffler  * fixed-size array of records.  When done logging set hw.ath.hal.alq=0
1833fe92528SSam Leffler  * and then decode the file with the arcode program (that is part of the
1843fe92528SSam Leffler  * HAL).  If you start+stop tracing the data will be appended to an
1853fe92528SSam Leffler  * existing file.
1863fe92528SSam Leffler  *
1873fe92528SSam Leffler  * NB: doesn't handle multiple devices properly; only one DEVICE record
1883fe92528SSam Leffler  *     is emitted and the different devices are not identified.
1893fe92528SSam Leffler  */
1903fe92528SSam Leffler #include <sys/alq.h>
1913fe92528SSam Leffler #include <sys/pcpu.h>
19233644623SSam Leffler #include <dev/ath/ath_hal/ah_decode.h>
1933fe92528SSam Leffler 
1943fe92528SSam Leffler static	struct alq *ath_hal_alq;
1953fe92528SSam Leffler static	int ath_hal_alq_emitdev;	/* need to emit DEVICE record */
1963fe92528SSam Leffler static	u_int ath_hal_alq_lost;		/* count of lost records */
197c5d52723SAdrian Chadd static	char ath_hal_logfile[MAXPATHLEN] = "/tmp/ath_hal.log";
198c5d52723SAdrian Chadd 
199c5d52723SAdrian Chadd SYSCTL_STRING(_hw_ath_hal, OID_AUTO, alq_logfile, CTLFLAG_RW,
200c5d52723SAdrian Chadd     &ath_hal_logfile, sizeof(kernelname), "Name of ALQ logfile");
201c5d52723SAdrian Chadd 
2023fe92528SSam Leffler static	u_int ath_hal_alq_qsize = 64*1024;
2033fe92528SSam Leffler 
2043fe92528SSam Leffler static int
2053fe92528SSam Leffler ath_hal_setlogging(int enable)
2063fe92528SSam Leffler {
2073fe92528SSam Leffler 	int error;
2083fe92528SSam Leffler 
2093fe92528SSam Leffler 	if (enable) {
2103fe92528SSam Leffler 		error = alq_open(&ath_hal_alq, ath_hal_logfile,
2113fe92528SSam Leffler 			curthread->td_ucred, ALQ_DEFAULT_CMODE,
2123fe92528SSam Leffler 			sizeof (struct athregrec), ath_hal_alq_qsize);
2133fe92528SSam Leffler 		ath_hal_alq_lost = 0;
2143fe92528SSam Leffler 		ath_hal_alq_emitdev = 1;
2153fe92528SSam Leffler 		printf("ath_hal: logging to %s enabled\n",
2163fe92528SSam Leffler 			ath_hal_logfile);
2173fe92528SSam Leffler 	} else {
2183fe92528SSam Leffler 		if (ath_hal_alq)
2193fe92528SSam Leffler 			alq_close(ath_hal_alq);
2203fe92528SSam Leffler 		ath_hal_alq = NULL;
2213fe92528SSam Leffler 		printf("ath_hal: logging disabled\n");
2223fe92528SSam Leffler 		error = 0;
2233fe92528SSam Leffler 	}
2243fe92528SSam Leffler 	return (error);
2253fe92528SSam Leffler }
2263fe92528SSam Leffler 
2273fe92528SSam Leffler static int
2283fe92528SSam Leffler sysctl_hw_ath_hal_log(SYSCTL_HANDLER_ARGS)
2293fe92528SSam Leffler {
2303fe92528SSam Leffler 	int error, enable;
2313fe92528SSam Leffler 
2323fe92528SSam Leffler 	enable = (ath_hal_alq != NULL);
2333fe92528SSam Leffler         error = sysctl_handle_int(oidp, &enable, 0, req);
2343fe92528SSam Leffler         if (error || !req->newptr)
2353fe92528SSam Leffler                 return (error);
2363fe92528SSam Leffler 	else
2373fe92528SSam Leffler 		return (ath_hal_setlogging(enable));
2383fe92528SSam Leffler }
2393fe92528SSam Leffler SYSCTL_PROC(_hw_ath_hal, OID_AUTO, alq, CTLTYPE_INT|CTLFLAG_RW,
2403fe92528SSam Leffler 	0, 0, sysctl_hw_ath_hal_log, "I", "Enable HAL register logging");
2413fe92528SSam Leffler SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_size, CTLFLAG_RW,
2423fe92528SSam Leffler 	&ath_hal_alq_qsize, 0, "In-memory log size (#records)");
2433fe92528SSam Leffler SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_lost, CTLFLAG_RW,
2443fe92528SSam Leffler 	&ath_hal_alq_lost, 0, "Register operations not logged");
2453fe92528SSam Leffler 
2463fe92528SSam Leffler static struct ale *
2473fe92528SSam Leffler ath_hal_alq_get(struct ath_hal *ah)
2483fe92528SSam Leffler {
2493fe92528SSam Leffler 	struct ale *ale;
2503fe92528SSam Leffler 
2513fe92528SSam Leffler 	if (ath_hal_alq_emitdev) {
2523fe92528SSam Leffler 		ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
2533fe92528SSam Leffler 		if (ale) {
2543fe92528SSam Leffler 			struct athregrec *r =
2553fe92528SSam Leffler 				(struct athregrec *) ale->ae_data;
2563fe92528SSam Leffler 			r->op = OP_DEVICE;
2573fe92528SSam Leffler 			r->reg = 0;
2583fe92528SSam Leffler 			r->val = ah->ah_devid;
2593fe92528SSam Leffler 			alq_post(ath_hal_alq, ale);
2603fe92528SSam Leffler 			ath_hal_alq_emitdev = 0;
2613fe92528SSam Leffler 		} else
2623fe92528SSam Leffler 			ath_hal_alq_lost++;
2633fe92528SSam Leffler 	}
2643fe92528SSam Leffler 	ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
2653fe92528SSam Leffler 	if (!ale)
2663fe92528SSam Leffler 		ath_hal_alq_lost++;
2673fe92528SSam Leffler 	return ale;
2683fe92528SSam Leffler }
2693fe92528SSam Leffler 
2703fe92528SSam Leffler void
2713fe92528SSam Leffler ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
2723fe92528SSam Leffler {
2733fe92528SSam Leffler 	bus_space_tag_t tag = BUSTAG(ah);
27433644623SSam Leffler 	bus_space_handle_t h = ah->ah_sh;
2753fe92528SSam Leffler 
27617f42e0dSAdrian Chadd #ifdef	AH_DEBUG
277517dfcb1SAdrian Chadd 	/* Debug - complain if we haven't fully waken things up */
2786ed22faeSAdrian Chadd 	if (! ath_hal_reg_whilst_asleep(ah, reg) &&
2796ed22faeSAdrian Chadd 	    ah->ah_powerMode != HAL_PM_AWAKE) {
280517dfcb1SAdrian Chadd 		ath_hal_printf(ah, "%s: reg=0x%08x, val=0x%08x, pm=%d\n",
281517dfcb1SAdrian Chadd 		    __func__, reg, val, ah->ah_powerMode);
282517dfcb1SAdrian Chadd 	}
28317f42e0dSAdrian Chadd #endif
284517dfcb1SAdrian Chadd 
2853fe92528SSam Leffler 	if (ath_hal_alq) {
2863fe92528SSam Leffler 		struct ale *ale = ath_hal_alq_get(ah);
2873fe92528SSam Leffler 		if (ale) {
2883fe92528SSam Leffler 			struct athregrec *r = (struct athregrec *) ale->ae_data;
2892fe1131cSAdrian Chadd 			r->threadid = curthread->td_tid;
2903fe92528SSam Leffler 			r->op = OP_WRITE;
2913fe92528SSam Leffler 			r->reg = reg;
2923fe92528SSam Leffler 			r->val = val;
2933fe92528SSam Leffler 			alq_post(ath_hal_alq, ale);
2943fe92528SSam Leffler 		}
2953fe92528SSam Leffler 	}
296ddbe3036SAdrian Chadd 	if (ah->ah_config.ah_serialise_reg_war)
297ddbe3036SAdrian Chadd 		mtx_lock_spin(&ah_regser_mtx);
2983fe92528SSam Leffler 	bus_space_write_4(tag, h, reg, val);
299ef91dbceSAdrian Chadd 	OS_BUS_BARRIER_REG(ah, reg, OS_BUS_BARRIER_WRITE);
300ddbe3036SAdrian Chadd 	if (ah->ah_config.ah_serialise_reg_war)
301ddbe3036SAdrian Chadd 		mtx_unlock_spin(&ah_regser_mtx);
3023fe92528SSam Leffler }
3033fe92528SSam Leffler 
3043fe92528SSam Leffler u_int32_t
3053fe92528SSam Leffler ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
3063fe92528SSam Leffler {
3073fe92528SSam Leffler 	bus_space_tag_t tag = BUSTAG(ah);
30833644623SSam Leffler 	bus_space_handle_t h = ah->ah_sh;
3093fe92528SSam Leffler 	u_int32_t val;
3103fe92528SSam Leffler 
31117f42e0dSAdrian Chadd #ifdef	AH_DEBUG
312517dfcb1SAdrian Chadd 	/* Debug - complain if we haven't fully waken things up */
3136ed22faeSAdrian Chadd 	if (! ath_hal_reg_whilst_asleep(ah, reg) &&
3146ed22faeSAdrian Chadd 	    ah->ah_powerMode != HAL_PM_AWAKE) {
315517dfcb1SAdrian Chadd 		ath_hal_printf(ah, "%s: reg=0x%08x, pm=%d\n",
316517dfcb1SAdrian Chadd 		    __func__, reg, ah->ah_powerMode);
317517dfcb1SAdrian Chadd 	}
31817f42e0dSAdrian Chadd #endif
319517dfcb1SAdrian Chadd 
320ddbe3036SAdrian Chadd 	if (ah->ah_config.ah_serialise_reg_war)
321ddbe3036SAdrian Chadd 		mtx_lock_spin(&ah_regser_mtx);
322ef91dbceSAdrian Chadd 	OS_BUS_BARRIER_REG(ah, reg, OS_BUS_BARRIER_READ);
3233fe92528SSam Leffler 	val = bus_space_read_4(tag, h, reg);
324ddbe3036SAdrian Chadd 	if (ah->ah_config.ah_serialise_reg_war)
325ddbe3036SAdrian Chadd 		mtx_unlock_spin(&ah_regser_mtx);
3263fe92528SSam Leffler 	if (ath_hal_alq) {
3273fe92528SSam Leffler 		struct ale *ale = ath_hal_alq_get(ah);
3283fe92528SSam Leffler 		if (ale) {
3293fe92528SSam Leffler 			struct athregrec *r = (struct athregrec *) ale->ae_data;
3302fe1131cSAdrian Chadd 			r->threadid = curthread->td_tid;
3313fe92528SSam Leffler 			r->op = OP_READ;
3323fe92528SSam Leffler 			r->reg = reg;
3333fe92528SSam Leffler 			r->val = val;
3343fe92528SSam Leffler 			alq_post(ath_hal_alq, ale);
3353fe92528SSam Leffler 		}
3363fe92528SSam Leffler 	}
3373fe92528SSam Leffler 	return val;
3383fe92528SSam Leffler }
3393fe92528SSam Leffler 
3403fe92528SSam Leffler void
3413fe92528SSam Leffler OS_MARK(struct ath_hal *ah, u_int id, u_int32_t v)
3423fe92528SSam Leffler {
3433fe92528SSam Leffler 	if (ath_hal_alq) {
3443fe92528SSam Leffler 		struct ale *ale = ath_hal_alq_get(ah);
3453fe92528SSam Leffler 		if (ale) {
3463fe92528SSam Leffler 			struct athregrec *r = (struct athregrec *) ale->ae_data;
3472fe1131cSAdrian Chadd 			r->threadid = curthread->td_tid;
3483fe92528SSam Leffler 			r->op = OP_MARK;
3493fe92528SSam Leffler 			r->reg = id;
3503fe92528SSam Leffler 			r->val = v;
3513fe92528SSam Leffler 			alq_post(ath_hal_alq, ale);
3523fe92528SSam Leffler 		}
3533fe92528SSam Leffler 	}
3543fe92528SSam Leffler }
35517f42e0dSAdrian Chadd #else /* AH_DEBUG_ALQ */
35617f42e0dSAdrian Chadd 
3573fe92528SSam Leffler /*
3583fe92528SSam Leffler  * Memory-mapped device register read/write.  These are here
3593fe92528SSam Leffler  * as routines when debugging support is enabled and/or when
3603fe92528SSam Leffler  * explicitly configured to use function calls.  The latter is
3613fe92528SSam Leffler  * for architectures that might need to do something before
3623fe92528SSam Leffler  * referencing memory (e.g. remap an i/o window).
3633fe92528SSam Leffler  *
3643fe92528SSam Leffler  * NB: see the comments in ah_osdep.h about byte-swapping register
3653fe92528SSam Leffler  *     reads and writes to understand what's going on below.
3663fe92528SSam Leffler  */
3673fe92528SSam Leffler 
3683fe92528SSam Leffler void
3693fe92528SSam Leffler ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
3703fe92528SSam Leffler {
3713fe92528SSam Leffler 	bus_space_tag_t tag = BUSTAG(ah);
37233644623SSam Leffler 	bus_space_handle_t h = ah->ah_sh;
3733fe92528SSam Leffler 
37417f42e0dSAdrian Chadd #ifdef	AH_DEBUG
375517dfcb1SAdrian Chadd 	/* Debug - complain if we haven't fully waken things up */
3766ed22faeSAdrian Chadd 	if (! ath_hal_reg_whilst_asleep(ah, reg) &&
3776ed22faeSAdrian Chadd 	    ah->ah_powerMode != HAL_PM_AWAKE) {
378517dfcb1SAdrian Chadd 		ath_hal_printf(ah, "%s: reg=0x%08x, val=0x%08x, pm=%d\n",
379517dfcb1SAdrian Chadd 		    __func__, reg, val, ah->ah_powerMode);
380517dfcb1SAdrian Chadd 	}
38117f42e0dSAdrian Chadd #endif
382517dfcb1SAdrian Chadd 
383ddbe3036SAdrian Chadd 	if (ah->ah_config.ah_serialise_reg_war)
384ddbe3036SAdrian Chadd 		mtx_lock_spin(&ah_regser_mtx);
3853fe92528SSam Leffler 	bus_space_write_4(tag, h, reg, val);
386ef91dbceSAdrian Chadd 	OS_BUS_BARRIER_REG(ah, reg, OS_BUS_BARRIER_WRITE);
387ddbe3036SAdrian Chadd 	if (ah->ah_config.ah_serialise_reg_war)
388ddbe3036SAdrian Chadd 		mtx_unlock_spin(&ah_regser_mtx);
3893fe92528SSam Leffler }
3903fe92528SSam Leffler 
3913fe92528SSam Leffler u_int32_t
3923fe92528SSam Leffler ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
3933fe92528SSam Leffler {
3943fe92528SSam Leffler 	bus_space_tag_t tag = BUSTAG(ah);
39533644623SSam Leffler 	bus_space_handle_t h = ah->ah_sh;
3963fe92528SSam Leffler 	u_int32_t val;
3973fe92528SSam Leffler 
39817f42e0dSAdrian Chadd #ifdef	AH_DEBUG
399517dfcb1SAdrian Chadd 	/* Debug - complain if we haven't fully waken things up */
4006ed22faeSAdrian Chadd 	if (! ath_hal_reg_whilst_asleep(ah, reg) &&
4016ed22faeSAdrian Chadd 	    ah->ah_powerMode != HAL_PM_AWAKE) {
402517dfcb1SAdrian Chadd 		ath_hal_printf(ah, "%s: reg=0x%08x, pm=%d\n",
403517dfcb1SAdrian Chadd 		    __func__, reg, ah->ah_powerMode);
404517dfcb1SAdrian Chadd 	}
40517f42e0dSAdrian Chadd #endif
406517dfcb1SAdrian Chadd 
407ddbe3036SAdrian Chadd 	if (ah->ah_config.ah_serialise_reg_war)
408ddbe3036SAdrian Chadd 		mtx_lock_spin(&ah_regser_mtx);
409ef91dbceSAdrian Chadd 	OS_BUS_BARRIER_REG(ah, reg, OS_BUS_BARRIER_READ);
4103fe92528SSam Leffler 	val = bus_space_read_4(tag, h, reg);
411ddbe3036SAdrian Chadd 	if (ah->ah_config.ah_serialise_reg_war)
412ddbe3036SAdrian Chadd 		mtx_unlock_spin(&ah_regser_mtx);
4133fe92528SSam Leffler 	return val;
4143fe92528SSam Leffler }
41517f42e0dSAdrian Chadd #endif /* AH_DEBUG_ALQ */
4163fe92528SSam Leffler 
4173fe92528SSam Leffler #ifdef AH_ASSERT
4183fe92528SSam Leffler void
4193fe92528SSam Leffler ath_hal_assert_failed(const char* filename, int lineno, const char *msg)
4203fe92528SSam Leffler {
4213fe92528SSam Leffler 	printf("Atheros HAL assertion failure: %s: line %u: %s\n",
4223fe92528SSam Leffler 		filename, lineno, msg);
4233fe92528SSam Leffler 	panic("ath_hal_assert");
4243fe92528SSam Leffler }
4253fe92528SSam Leffler #endif /* AH_ASSERT */
42641059135SAdrian Chadd 
42741059135SAdrian Chadd static int
42841059135SAdrian Chadd ath_hal_modevent(module_t mod __unused, int type, void *data __unused)
42941059135SAdrian Chadd {
43041059135SAdrian Chadd 	int error = 0;
43141059135SAdrian Chadd 
43241059135SAdrian Chadd 	switch (type) {
43341059135SAdrian Chadd 	case MOD_LOAD:
43441059135SAdrian Chadd 		printf("[ath_hal] loaded\n");
43541059135SAdrian Chadd 		break;
43641059135SAdrian Chadd 
43741059135SAdrian Chadd 	case MOD_UNLOAD:
43841059135SAdrian Chadd 		printf("[ath_hal] unloaded\n");
43941059135SAdrian Chadd 		break;
44041059135SAdrian Chadd 
44141059135SAdrian Chadd 	case MOD_SHUTDOWN:
44241059135SAdrian Chadd 		break;
44341059135SAdrian Chadd 
44441059135SAdrian Chadd 	default:
44541059135SAdrian Chadd 		error = EOPNOTSUPP;
44641059135SAdrian Chadd 		break;
44741059135SAdrian Chadd 
44841059135SAdrian Chadd 	}
44941059135SAdrian Chadd 	return (error);
45041059135SAdrian Chadd }
45141059135SAdrian Chadd 
45241059135SAdrian Chadd DEV_MODULE(ath_hal, ath_hal_modevent, NULL);
45341059135SAdrian Chadd MODULE_VERSION(ath_hal, 1);
45486a656deSAdrian Chadd #if	defined(AH_DEBUG_ALQ)
45586a656deSAdrian Chadd MODULE_DEPEND(ath_hal, alq, 1, 1, 1);
45686a656deSAdrian Chadd #endif
457