2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2008 Atheros Communications, Inc.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 #include <linux/config.h>
26 #include <linux/version.h>
27 #include <linux/module.h>
28 #include <linux/init.h>
30 #include <linux/kernel.h>
31 #include <linux/slab.h>
32 #include <linux/delay.h>
34 #include <linux/sysctl.h>
35 #include <linux/proc_fs.h>
41 #ifndef __MOD_INC_USE_COUNT
42 #define AH_MOD_INC_USE_COUNT(_m) \
43 if (!try_module_get(_m)) { \
44 printk(KERN_WARNING "try_module_get failed\n"); \
47 #define AH_MOD_DEC_USE_COUNT(_m) module_put(_m)
49 #define AH_MOD_INC_USE_COUNT(_m) MOD_INC_USE_COUNT
50 #define AH_MOD_DEC_USE_COUNT(_m) MOD_DEC_USE_COUNT
54 static int ath_hal_debug
= 0;
57 int ath_hal_dma_beacon_response_time
= 2; /* in TU's */
58 int ath_hal_sw_beacon_response_time
= 10; /* in TU's */
59 int ath_hal_additional_swba_backoff
= 0; /* in TU's */
62 _ath_hal_attach(uint16_t devid
, HAL_SOFTC sc
,
63 HAL_BUS_TAG t
, HAL_BUS_HANDLE h
, void* s
)
66 struct ath_hal
*ah
= ath_hal_attach(devid
, sc
, t
, h
, &status
);
68 *(HAL_STATUS
*)s
= status
;
70 AH_MOD_INC_USE_COUNT(THIS_MODULE
);
75 ath_hal_detach(struct ath_hal
*ah
)
78 AH_MOD_DEC_USE_COUNT(THIS_MODULE
);
82 * Print/log message support.
86 ath_hal_vprintf(struct ath_hal
*ah
, const char* fmt
, va_list ap
)
88 char buf
[1024]; /* XXX */
89 vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
94 ath_hal_printf(struct ath_hal
*ah
, const char* fmt
, ...)
98 ath_hal_vprintf(ah
, fmt
, ap
);
101 EXPORT_SYMBOL(ath_hal_printf
);
104 * Format an Ethernet MAC for printing.
107 ath_hal_ether_sprintf(const uint8_t *mac
)
109 static char etherbuf
[18];
110 snprintf(etherbuf
, sizeof(etherbuf
), "%02x:%02x:%02x:%02x:%02x:%02x",
111 mac
[0], mac
[1], mac
[2], mac
[3], mac
[4], mac
[5]);
117 ath_hal_assert_failed(const char* filename
, int lineno
, const char *msg
)
119 printk("Atheros HAL assertion failure: %s: line %u: %s\n",
120 filename
, lineno
, msg
);
121 panic("ath_hal_assert");
123 #endif /* AH_ASSERT */
127 * ALQ register tracing support.
129 * Setting hw.ath.hal.alq=1 enables tracing of all register reads and
130 * writes to the file /tmp/ath_hal.log. The file format is a simple
131 * fixed-size array of records. When done logging set hw.ath.hal.alq=0
132 * and then decode the file with the ardecode program (that is part of the
133 * HAL). If you start+stop tracing the data will be appended to an
136 * NB: doesn't handle multiple devices properly; only one DEVICE record
137 * is emitted and the different devices are not identified.
140 #include "ah_decode.h"
142 static struct alq
*ath_hal_alq
;
143 static int ath_hal_alq_emitdev
; /* need to emit DEVICE record */
144 static u_int ath_hal_alq_lost
; /* count of lost records */
145 static const char *ath_hal_logfile
= "/tmp/ath_hal.log";
146 static u_int ath_hal_alq_qsize
= 8*1024;
149 ath_hal_setlogging(int enable
)
154 if (!capable(CAP_NET_ADMIN
))
156 error
= alq_open(&ath_hal_alq
, ath_hal_logfile
,
157 sizeof (struct athregrec
), ath_hal_alq_qsize
);
158 ath_hal_alq_lost
= 0;
159 ath_hal_alq_emitdev
= 1;
160 printk("ath_hal: logging to %s %s\n", ath_hal_logfile
,
161 error
== 0 ? "enabled" : "could not be setup");
164 alq_close(ath_hal_alq
);
166 printk("ath_hal: logging disabled\n");
173 * Deal with the sysctl handler api changing.
175 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)
176 #define AH_SYSCTL_ARGS_DECL \
177 ctl_table *ctl, int write, struct file *filp, void *buffer, \
179 #define AH_SYSCTL_ARGS ctl, write, filp, buffer, lenp
180 #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8) */
181 #define AH_SYSCTL_ARGS_DECL \
182 ctl_table *ctl, int write, struct file *filp, void *buffer,\
183 size_t *lenp, loff_t *ppos
184 #define AH_SYSCTL_ARGS ctl, write, filp, buffer, lenp, ppos
188 sysctl_hw_ath_hal_log(AH_SYSCTL_ARGS_DECL
)
193 ctl
->maxlen
= sizeof(enable
);
194 enable
= (ath_hal_alq
!= NULL
);
195 error
= proc_dointvec(AH_SYSCTL_ARGS
);
199 return ath_hal_setlogging(enable
);
203 ath_hal_alq_get(struct ath_hal
*ah
)
207 if (ath_hal_alq_emitdev
) {
208 ale
= alq_get(ath_hal_alq
, ALQ_NOWAIT
);
210 struct athregrec
*r
=
211 (struct athregrec
*) ale
->ae_data
;
214 r
->val
= ah
->ah_devid
;
215 alq_post(ath_hal_alq
, ale
);
216 ath_hal_alq_emitdev
= 0;
220 ale
= alq_get(ath_hal_alq
, ALQ_NOWAIT
);
227 ath_hal_reg_write(struct ath_hal
*ah
, uint32_t reg
, uint32_t val
)
233 local_irq_save(flags
);
234 ale
= ath_hal_alq_get(ah
);
236 struct athregrec
*r
= (struct athregrec
*) ale
->ae_data
;
240 alq_post(ath_hal_alq
, ale
);
242 local_irq_restore(flags
);
244 _OS_REG_WRITE(ah
, reg
, val
);
246 EXPORT_SYMBOL(ath_hal_reg_write
);
249 ath_hal_reg_read(struct ath_hal
*ah
, uint32_t reg
)
253 val
= _OS_REG_READ(ah
, reg
);
258 local_irq_save(flags
);
259 ale
= ath_hal_alq_get(ah
);
261 struct athregrec
*r
= (struct athregrec
*) ale
->ae_data
;
265 alq_post(ath_hal_alq
, ale
);
267 local_irq_restore(flags
);
271 EXPORT_SYMBOL(ath_hal_reg_read
);
274 OS_MARK(struct ath_hal
*ah
, u_int id
, uint32_t v
)
280 local_irq_save(flags
);
281 ale
= ath_hal_alq_get(ah
);
283 struct athregrec
*r
= (struct athregrec
*) ale
->ae_data
;
287 alq_post(ath_hal_alq
, ale
);
289 local_irq_restore(flags
);
292 EXPORT_SYMBOL(OS_MARK
);
293 #elif defined(AH_DEBUG) || defined(AH_REGOPS_FUNC)
295 * Memory-mapped device register read/write. These are here
296 * as routines when debugging support is enabled and/or when
297 * explicitly configured to use function calls. The latter is
298 * for architectures that might need to do something before
299 * referencing memory (e.g. remap an i/o window).
301 * NB: see the comments in ah_osdep.h about byte-swapping register
302 * reads and writes to understand what's going on below.
305 ath_hal_reg_write(struct ath_hal
*ah
, u_int reg
, uint32_t val
)
308 if (ath_hal_debug
> 1)
309 ath_hal_printf(ah
, "WRITE 0x%x <= 0x%x\n", reg
, val
);
311 _OS_REG_WRITE(ah
, reg
, val
);
313 EXPORT_SYMBOL(ath_hal_reg_write
);
316 ath_hal_reg_read(struct ath_hal
*ah
, u_int reg
)
320 val
= _OS_REG_READ(ah
, reg
);
322 if (ath_hal_debug
> 1)
323 ath_hal_printf(ah
, "READ 0x%x => 0x%x\n", reg
, val
);
327 EXPORT_SYMBOL(ath_hal_reg_read
);
328 #endif /* AH_DEBUG || AH_REGOPS_FUNC */
332 HALDEBUG(struct ath_hal
*ah
, const char* fmt
, ...)
337 ath_hal_vprintf(ah
, fmt
, ap
);
344 HALDEBUGn(struct ath_hal
*ah
, u_int level
, const char* fmt
, ...)
346 if (ath_hal_debug
>= level
) {
349 ath_hal_vprintf(ah
, fmt
, ap
);
353 #endif /* AH_DEBUG */
356 * Delay n microseconds.
365 ath_hal_getuptime(struct ath_hal
*ah
)
367 return ((jiffies
/ HZ
) * 1000) + (jiffies
% HZ
) * (1000 / HZ
);
369 EXPORT_SYMBOL(ath_hal_getuptime
);
372 * Allocate/free memory.
376 ath_hal_malloc(size_t size
)
379 p
= kmalloc(size
, GFP_KERNEL
);
387 ath_hal_free(void* p
)
393 ath_hal_memzero(void *dst
, size_t n
)
397 EXPORT_SYMBOL(ath_hal_memzero
);
400 ath_hal_memcpy(void *dst
, const void *src
, size_t n
)
402 return memcpy(dst
, src
, n
);
404 EXPORT_SYMBOL(ath_hal_memcpy
);
407 ath_hal_memcmp(const void *a
, const void *b
, size_t n
)
409 return memcmp(a
, b
, n
);
411 EXPORT_SYMBOL(ath_hal_memcmp
);
415 DEV_ATH
= 9, /* XXX must match driver */
418 #define CTL_AUTO -2 /* cannot be CTL_ANY or CTL_NONE */
420 static ctl_table ath_hal_sysctls
[] = {
422 { .ctl_name
= CTL_AUTO
,
425 .data
= &ath_hal_debug
,
426 .maxlen
= sizeof(ath_hal_debug
),
427 .proc_handler
= proc_dointvec
430 { .ctl_name
= CTL_AUTO
,
431 .procname
= "dma_beacon_response_time",
432 .data
= &ath_hal_dma_beacon_response_time
,
433 .maxlen
= sizeof(ath_hal_dma_beacon_response_time
),
435 .proc_handler
= proc_dointvec
437 { .ctl_name
= CTL_AUTO
,
438 .procname
= "sw_beacon_response_time",
440 .data
= &ath_hal_sw_beacon_response_time
,
441 .maxlen
= sizeof(ath_hal_sw_beacon_response_time
),
442 .proc_handler
= proc_dointvec
444 { .ctl_name
= CTL_AUTO
,
445 .procname
= "swba_backoff",
447 .data
= &ath_hal_additional_swba_backoff
,
448 .maxlen
= sizeof(ath_hal_additional_swba_backoff
),
449 .proc_handler
= proc_dointvec
452 { .ctl_name
= CTL_AUTO
,
455 .proc_handler
= sysctl_hw_ath_hal_log
457 { .ctl_name
= CTL_AUTO
,
458 .procname
= "alq_size",
460 .data
= &ath_hal_alq_qsize
,
461 .maxlen
= sizeof(ath_hal_alq_qsize
),
462 .proc_handler
= proc_dointvec
464 { .ctl_name
= CTL_AUTO
,
465 .procname
= "alq_lost",
467 .data
= &ath_hal_alq_lost
,
468 .maxlen
= sizeof(ath_hal_alq_lost
),
469 .proc_handler
= proc_dointvec
474 static ctl_table ath_hal_table
[] = {
475 { .ctl_name
= CTL_AUTO
,
478 .child
= ath_hal_sysctls
481 static ctl_table ath_ath_table
[] = {
482 { .ctl_name
= DEV_ATH
,
485 .child
= ath_hal_table
488 static ctl_table ath_root_table
[] = {
489 { .ctl_name
= CTL_DEV
,
492 .child
= ath_ath_table
495 static struct ctl_table_header
*ath_hal_sysctl_header
;
498 ath_hal_sysctl_register(void)
500 static int initialized
= 0;
503 ath_hal_sysctl_header
=
504 register_sysctl_table(ath_root_table
, 1);
510 ath_hal_sysctl_unregister(void)
512 if (ath_hal_sysctl_header
)
513 unregister_sysctl_table(ath_hal_sysctl_header
);
515 #endif /* CONFIG_SYSCTL */
520 static char *dev_info
= "ath_hal";
522 MODULE_AUTHOR("Errno Consulting, Sam Leffler");
523 MODULE_DESCRIPTION("Atheros Hardware Access Layer (HAL)");
524 MODULE_SUPPORTED_DEVICE("Atheros WLAN devices");
525 #ifdef MODULE_LICENSE
526 MODULE_LICENSE("Proprietary");
529 EXPORT_SYMBOL(ath_hal_probe
);
530 EXPORT_SYMBOL(_ath_hal_attach
);
531 EXPORT_SYMBOL(ath_hal_detach
);
532 EXPORT_SYMBOL(ath_hal_init_channels
);
533 EXPORT_SYMBOL(ath_hal_getwirelessmodes
);
534 EXPORT_SYMBOL(ath_hal_computetxtime
);
535 EXPORT_SYMBOL(ath_hal_mhz2ieee
);
536 EXPORT_SYMBOL(ath_hal_process_noisefloor
);
544 printk(KERN_INFO
"%s: %s (", dev_info
, ath_hal_version
);
546 for (i
= 0; ath_hal_buildopts
[i
] != NULL
; i
++) {
547 printk("%s%s", sep
, ath_hal_buildopts
[i
]);
552 ath_hal_sysctl_register();
556 module_init(init_ath_hal
);
562 ath_hal_sysctl_unregister();
564 printk(KERN_INFO
"%s: driver unloaded\n", dev_info
);
566 module_exit(exit_ath_hal
);