2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 * redistribution must be conditioned upon including a substantially
14 * similar Disclaimer requirement for further binary redistribution.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGES.
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/module.h>
37 #include <sys/sysctl.h>
39 #include <sys/malloc.h>
43 #include <sys/mutex.h>
46 #include <machine/stdarg.h>
48 #include <net/ethernet.h> /* XXX for ether_sprintf */
50 #include <dev/ath/ath_hal/ah.h>
51 #include <dev/ath/ath_hal/ah_debug.h>
54 * WiSoC boards overload the bus tag with information about the
55 * board layout. We must extract the bus space tag from that
56 * indirect structure. For everyone else the tag is passed in
58 * XXX cache indirect ref privately
60 #ifdef AH_SUPPORT_AR5312
62 ((bus_space_tag_t) ((struct ar531x_config *)((ah)->ah_st))->tag)
64 #define BUSTAG(ah) ((ah)->ah_st)
68 * This lock is used to seralise register access for chips which have
69 * problems w/ SMP CPUs issuing concurrent PCI transactions.
71 * XXX This is a global lock for now; it should be pushed to
72 * a per-device lock in some platform-independent fashion.
74 struct mtx ah_regser_mtx;
75 MTX_SYSINIT(ah_regser, &ah_regser_mtx, "Atheros register access mutex",
78 extern void ath_hal_printf(struct ath_hal *, const char*, ...)
80 extern void ath_hal_vprintf(struct ath_hal *, const char*, __va_list)
82 extern const char* ath_hal_ether_sprintf(const u_int8_t *mac);
83 extern void *ath_hal_malloc(size_t);
84 extern void ath_hal_free(void *);
86 extern void ath_hal_assert_failed(const char* filename,
87 int lineno, const char* msg);
90 extern void DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...);
93 /* NB: put this here instead of the driver to avoid circular references */
94 SYSCTL_NODE(_hw, OID_AUTO, ath, CTLFLAG_RD, 0, "Atheros driver parameters");
95 static SYSCTL_NODE(_hw_ath, OID_AUTO, hal, CTLFLAG_RD, 0,
96 "Atheros HAL parameters");
99 int ath_hal_debug = 0;
100 SYSCTL_INT(_hw_ath_hal, OID_AUTO, debug, CTLFLAG_RWTUN, &ath_hal_debug,
101 0, "Atheros HAL debugging printfs");
102 #endif /* AH_DEBUG */
104 static MALLOC_DEFINE(M_ATH_HAL, "ath_hal", "ath hal data");
107 ath_hal_malloc(size_t size)
109 return malloc(size, M_ATH_HAL, M_NOWAIT | M_ZERO);
113 ath_hal_free(void* p)
119 ath_hal_vprintf(struct ath_hal *ah, const char* fmt, va_list ap)
125 ath_hal_printf(struct ath_hal *ah, const char* fmt, ...)
129 ath_hal_vprintf(ah, fmt, ap);
134 ath_hal_ether_sprintf(const u_int8_t *mac)
136 return ether_sprintf(mac);
142 * XXX This is highly relevant only for the AR5416 and later
143 * PCI/PCIe NICs. It'll need adjustment for other hardware
147 ath_hal_reg_whilst_asleep(struct ath_hal *ah, uint32_t reg)
150 if (reg >= 0x4000 && reg < 0x5000)
152 if (reg >= 0x6000 && reg < 0x7000)
154 if (reg >= 0x7000 && reg < 0x8000)
160 DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...)
162 if ((mask == HAL_DEBUG_UNMASKABLE) ||
163 (ah != NULL && ah->ah_config.ah_debug & mask) ||
164 (ath_hal_debug & mask)) {
167 ath_hal_vprintf(ah, fmt, ap);
171 #undef HAL_DEBUG_UNMASKABLE
172 #endif /* AH_DEBUG */
176 * ALQ register tracing support.
178 * Setting hw.ath.hal.alq=1 enables tracing of all register reads and
179 * writes to the file /tmp/ath_hal.log. The file format is a simple
180 * fixed-size array of records. When done logging set hw.ath.hal.alq=0
181 * and then decode the file with the arcode program (that is part of the
182 * HAL). If you start+stop tracing the data will be appended to an
185 * NB: doesn't handle multiple devices properly; only one DEVICE record
186 * is emitted and the different devices are not identified.
189 #include <sys/pcpu.h>
190 #include <dev/ath/ath_hal/ah_decode.h>
192 static struct alq *ath_hal_alq;
193 static int ath_hal_alq_emitdev; /* need to emit DEVICE record */
194 static u_int ath_hal_alq_lost; /* count of lost records */
195 static char ath_hal_logfile[MAXPATHLEN] = "/tmp/ath_hal.log";
197 SYSCTL_STRING(_hw_ath_hal, OID_AUTO, alq_logfile, CTLFLAG_RW,
198 &ath_hal_logfile, sizeof(kernelname), "Name of ALQ logfile");
200 static u_int ath_hal_alq_qsize = 64*1024;
203 ath_hal_setlogging(int enable)
208 error = alq_open(&ath_hal_alq, ath_hal_logfile,
209 curthread->td_ucred, ALQ_DEFAULT_CMODE,
210 sizeof (struct athregrec), ath_hal_alq_qsize);
211 ath_hal_alq_lost = 0;
212 ath_hal_alq_emitdev = 1;
213 printf("ath_hal: logging to %s enabled\n",
217 alq_close(ath_hal_alq);
219 printf("ath_hal: logging disabled\n");
226 sysctl_hw_ath_hal_log(SYSCTL_HANDLER_ARGS)
230 enable = (ath_hal_alq != NULL);
231 error = sysctl_handle_int(oidp, &enable, 0, req);
232 if (error || !req->newptr)
235 return (ath_hal_setlogging(enable));
237 SYSCTL_PROC(_hw_ath_hal, OID_AUTO, alq, CTLTYPE_INT|CTLFLAG_RW,
238 0, 0, sysctl_hw_ath_hal_log, "I", "Enable HAL register logging");
239 SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_size, CTLFLAG_RW,
240 &ath_hal_alq_qsize, 0, "In-memory log size (#records)");
241 SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_lost, CTLFLAG_RW,
242 &ath_hal_alq_lost, 0, "Register operations not logged");
245 ath_hal_alq_get(struct ath_hal *ah)
249 if (ath_hal_alq_emitdev) {
250 ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
252 struct athregrec *r =
253 (struct athregrec *) ale->ae_data;
256 r->val = ah->ah_devid;
257 alq_post(ath_hal_alq, ale);
258 ath_hal_alq_emitdev = 0;
262 ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
269 ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
271 bus_space_tag_t tag = BUSTAG(ah);
272 bus_space_handle_t h = ah->ah_sh;
275 /* Debug - complain if we haven't fully waken things up */
276 if (! ath_hal_reg_whilst_asleep(ah, reg) &&
277 ah->ah_powerMode != HAL_PM_AWAKE) {
278 ath_hal_printf(ah, "%s: reg=0x%08x, val=0x%08x, pm=%d\n",
279 __func__, reg, val, ah->ah_powerMode);
284 struct ale *ale = ath_hal_alq_get(ah);
286 struct athregrec *r = (struct athregrec *) ale->ae_data;
287 r->threadid = curthread->td_tid;
291 alq_post(ath_hal_alq, ale);
294 if (ah->ah_config.ah_serialise_reg_war)
295 mtx_lock_spin(&ah_regser_mtx);
296 bus_space_write_4(tag, h, reg, val);
297 OS_BUS_BARRIER_REG(ah, reg, OS_BUS_BARRIER_WRITE);
298 if (ah->ah_config.ah_serialise_reg_war)
299 mtx_unlock_spin(&ah_regser_mtx);
303 ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
305 bus_space_tag_t tag = BUSTAG(ah);
306 bus_space_handle_t h = ah->ah_sh;
310 /* Debug - complain if we haven't fully waken things up */
311 if (! ath_hal_reg_whilst_asleep(ah, reg) &&
312 ah->ah_powerMode != HAL_PM_AWAKE) {
313 ath_hal_printf(ah, "%s: reg=0x%08x, pm=%d\n",
314 __func__, reg, ah->ah_powerMode);
318 if (ah->ah_config.ah_serialise_reg_war)
319 mtx_lock_spin(&ah_regser_mtx);
320 OS_BUS_BARRIER_REG(ah, reg, OS_BUS_BARRIER_READ);
321 val = bus_space_read_4(tag, h, reg);
322 if (ah->ah_config.ah_serialise_reg_war)
323 mtx_unlock_spin(&ah_regser_mtx);
325 struct ale *ale = ath_hal_alq_get(ah);
327 struct athregrec *r = (struct athregrec *) ale->ae_data;
328 r->threadid = curthread->td_tid;
332 alq_post(ath_hal_alq, ale);
339 OS_MARK(struct ath_hal *ah, u_int id, u_int32_t v)
342 struct ale *ale = ath_hal_alq_get(ah);
344 struct athregrec *r = (struct athregrec *) ale->ae_data;
345 r->threadid = curthread->td_tid;
349 alq_post(ath_hal_alq, ale);
353 #else /* AH_DEBUG_ALQ */
356 * Memory-mapped device register read/write. These are here
357 * as routines when debugging support is enabled and/or when
358 * explicitly configured to use function calls. The latter is
359 * for architectures that might need to do something before
360 * referencing memory (e.g. remap an i/o window).
362 * NB: see the comments in ah_osdep.h about byte-swapping register
363 * reads and writes to understand what's going on below.
367 ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
369 bus_space_tag_t tag = BUSTAG(ah);
370 bus_space_handle_t h = ah->ah_sh;
373 /* Debug - complain if we haven't fully waken things up */
374 if (! ath_hal_reg_whilst_asleep(ah, reg) &&
375 ah->ah_powerMode != HAL_PM_AWAKE) {
376 ath_hal_printf(ah, "%s: reg=0x%08x, val=0x%08x, pm=%d\n",
377 __func__, reg, val, ah->ah_powerMode);
381 if (ah->ah_config.ah_serialise_reg_war)
382 mtx_lock_spin(&ah_regser_mtx);
383 bus_space_write_4(tag, h, reg, val);
384 OS_BUS_BARRIER_REG(ah, reg, OS_BUS_BARRIER_WRITE);
385 if (ah->ah_config.ah_serialise_reg_war)
386 mtx_unlock_spin(&ah_regser_mtx);
390 ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
392 bus_space_tag_t tag = BUSTAG(ah);
393 bus_space_handle_t h = ah->ah_sh;
397 /* Debug - complain if we haven't fully waken things up */
398 if (! ath_hal_reg_whilst_asleep(ah, reg) &&
399 ah->ah_powerMode != HAL_PM_AWAKE) {
400 ath_hal_printf(ah, "%s: reg=0x%08x, pm=%d\n",
401 __func__, reg, ah->ah_powerMode);
405 if (ah->ah_config.ah_serialise_reg_war)
406 mtx_lock_spin(&ah_regser_mtx);
407 OS_BUS_BARRIER_REG(ah, reg, OS_BUS_BARRIER_READ);
408 val = bus_space_read_4(tag, h, reg);
409 if (ah->ah_config.ah_serialise_reg_war)
410 mtx_unlock_spin(&ah_regser_mtx);
413 #endif /* AH_DEBUG_ALQ */
417 ath_hal_assert_failed(const char* filename, int lineno, const char *msg)
419 printf("Atheros HAL assertion failure: %s: line %u: %s\n",
420 filename, lineno, msg);
421 panic("ath_hal_assert");
423 #endif /* AH_ASSERT */
426 ath_hal_modevent(module_t mod __unused, int type, void *data __unused)
432 printf("[ath_hal] loaded\n");
436 printf("[ath_hal] unloaded\n");
450 DEV_MODULE(ath_hal, ath_hal_modevent, NULL);
451 MODULE_VERSION(ath_hal, 1);
452 #if defined(AH_DEBUG_ALQ)
453 MODULE_DEPEND(ath_hal, alq, 1, 1, 1);