Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / networks / atheros5000 / hal / linux / ah_osdep.c
blobfcdf359b109167e98363e8fed9ffe97757afef34
1 /*
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.
17 * $Id$
19 #include "opt_ah.h"
21 #ifndef EXPORT_SYMTAB
22 #define EXPORT_SYMTAB
23 #endif
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>
37 #include <asm/io.h>
39 #include "ah.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"); \
45 return NULL; \
47 #define AH_MOD_DEC_USE_COUNT(_m) module_put(_m)
48 #else
49 #define AH_MOD_INC_USE_COUNT(_m) MOD_INC_USE_COUNT
50 #define AH_MOD_DEC_USE_COUNT(_m) MOD_DEC_USE_COUNT
51 #endif
53 #ifdef AH_DEBUG
54 static int ath_hal_debug = 0;
55 #endif
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 */
61 struct ath_hal *
62 _ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
63 HAL_BUS_TAG t, HAL_BUS_HANDLE h, void* s)
65 HAL_STATUS status;
66 struct ath_hal *ah = ath_hal_attach(devid, sc, t, h, &status);
68 *(HAL_STATUS *)s = status;
69 if (ah)
70 AH_MOD_INC_USE_COUNT(THIS_MODULE);
71 return ah;
74 void
75 ath_hal_detach(struct ath_hal *ah)
77 (*ah->ah_detach)(ah);
78 AH_MOD_DEC_USE_COUNT(THIS_MODULE);
82 * Print/log message support.
85 void __ahdecl
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);
90 printk("%s", buf);
93 void __ahdecl
94 ath_hal_printf(struct ath_hal *ah, const char* fmt, ...)
96 va_list ap;
97 va_start(ap, fmt);
98 ath_hal_vprintf(ah, fmt, ap);
99 va_end(ap);
101 EXPORT_SYMBOL(ath_hal_printf);
104 * Format an Ethernet MAC for printing.
106 const char* __ahdecl
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]);
112 return etherbuf;
115 #ifdef AH_ASSERT
116 void __ahdecl
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 */
125 #ifdef AH_DEBUG_ALQ
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
134 * existing file.
136 * NB: doesn't handle multiple devices properly; only one DEVICE record
137 * is emitted and the different devices are not identified.
139 #include "alq/alq.h"
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;
148 static int
149 ath_hal_setlogging(int enable)
151 int error;
153 if (enable) {
154 if (!capable(CAP_NET_ADMIN))
155 return -EPERM;
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");
162 } else {
163 if (ath_hal_alq)
164 alq_close(ath_hal_alq);
165 ath_hal_alq = NULL;
166 printk("ath_hal: logging disabled\n");
167 error = 0;
169 return error;
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, \
178 size_t *lenp
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
185 #endif
187 static int
188 sysctl_hw_ath_hal_log(AH_SYSCTL_ARGS_DECL)
190 int error, enable;
192 ctl->data = &enable;
193 ctl->maxlen = sizeof(enable);
194 enable = (ath_hal_alq != NULL);
195 error = proc_dointvec(AH_SYSCTL_ARGS);
196 if (error || !write)
197 return error;
198 else
199 return ath_hal_setlogging(enable);
202 static struct ale *
203 ath_hal_alq_get(struct ath_hal *ah)
205 struct ale *ale;
207 if (ath_hal_alq_emitdev) {
208 ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
209 if (ale) {
210 struct athregrec *r =
211 (struct athregrec *) ale->ae_data;
212 r->op = OP_DEVICE;
213 r->reg = 0;
214 r->val = ah->ah_devid;
215 alq_post(ath_hal_alq, ale);
216 ath_hal_alq_emitdev = 0;
217 } else
218 ath_hal_alq_lost++;
220 ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
221 if (!ale)
222 ath_hal_alq_lost++;
223 return ale;
226 void __ahdecl
227 ath_hal_reg_write(struct ath_hal *ah, uint32_t reg, uint32_t val)
229 if (ath_hal_alq) {
230 unsigned long flags;
231 struct ale *ale;
233 local_irq_save(flags);
234 ale = ath_hal_alq_get(ah);
235 if (ale) {
236 struct athregrec *r = (struct athregrec *) ale->ae_data;
237 r->op = OP_WRITE;
238 r->reg = reg;
239 r->val = val;
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);
248 uint32_t __ahdecl
249 ath_hal_reg_read(struct ath_hal *ah, uint32_t reg)
251 uint32_t val;
253 val = _OS_REG_READ(ah, reg);
254 if (ath_hal_alq) {
255 unsigned long flags;
256 struct ale *ale;
258 local_irq_save(flags);
259 ale = ath_hal_alq_get(ah);
260 if (ale) {
261 struct athregrec *r = (struct athregrec *) ale->ae_data;
262 r->op = OP_READ;
263 r->reg = reg;
264 r->val = val;
265 alq_post(ath_hal_alq, ale);
267 local_irq_restore(flags);
269 return val;
271 EXPORT_SYMBOL(ath_hal_reg_read);
273 void __ahdecl
274 OS_MARK(struct ath_hal *ah, u_int id, uint32_t v)
276 if (ath_hal_alq) {
277 unsigned long flags;
278 struct ale *ale;
280 local_irq_save(flags);
281 ale = ath_hal_alq_get(ah);
282 if (ale) {
283 struct athregrec *r = (struct athregrec *) ale->ae_data;
284 r->op = OP_MARK;
285 r->reg = id;
286 r->val = v;
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.
304 void __ahdecl
305 ath_hal_reg_write(struct ath_hal *ah, u_int reg, uint32_t val)
307 #ifdef AH_DEBUG
308 if (ath_hal_debug > 1)
309 ath_hal_printf(ah, "WRITE 0x%x <= 0x%x\n", reg, val);
310 #endif
311 _OS_REG_WRITE(ah, reg, val);
313 EXPORT_SYMBOL(ath_hal_reg_write);
315 uint32_t __ahdecl
316 ath_hal_reg_read(struct ath_hal *ah, u_int reg)
318 uint32_t val;
320 val = _OS_REG_READ(ah, reg);
321 #ifdef AH_DEBUG
322 if (ath_hal_debug > 1)
323 ath_hal_printf(ah, "READ 0x%x => 0x%x\n", reg, val);
324 #endif
325 return val;
327 EXPORT_SYMBOL(ath_hal_reg_read);
328 #endif /* AH_DEBUG || AH_REGOPS_FUNC */
330 #ifdef AH_DEBUG
331 void __ahdecl
332 HALDEBUG(struct ath_hal *ah, const char* fmt, ...)
334 if (ath_hal_debug) {
335 __va_list ap;
336 va_start(ap, fmt);
337 ath_hal_vprintf(ah, fmt, ap);
338 va_end(ap);
343 void __ahdecl
344 HALDEBUGn(struct ath_hal *ah, u_int level, const char* fmt, ...)
346 if (ath_hal_debug >= level) {
347 __va_list ap;
348 va_start(ap, fmt);
349 ath_hal_vprintf(ah, fmt, ap);
350 va_end(ap);
353 #endif /* AH_DEBUG */
356 * Delay n microseconds.
358 void __ahdecl
359 ath_hal_delay(int n)
361 udelay(n);
364 uint32_t __ahdecl
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.
375 void * __ahdecl
376 ath_hal_malloc(size_t size)
378 void *p;
379 p = kmalloc(size, GFP_KERNEL);
380 if (p)
381 OS_MEMZERO(p, size);
382 return p;
386 void __ahdecl
387 ath_hal_free(void* p)
389 kfree(p);
392 void __ahdecl
393 ath_hal_memzero(void *dst, size_t n)
395 memset(dst, 0, n);
397 EXPORT_SYMBOL(ath_hal_memzero);
399 void * __ahdecl
400 ath_hal_memcpy(void *dst, const void *src, size_t n)
402 return memcpy(dst, src, n);
404 EXPORT_SYMBOL(ath_hal_memcpy);
406 int __ahdecl
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);
413 #ifdef CONFIG_SYSCTL
414 enum {
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[] = {
421 #ifdef AH_DEBUG
422 { .ctl_name = CTL_AUTO,
423 .procname = "debug",
424 .mode = 0644,
425 .data = &ath_hal_debug,
426 .maxlen = sizeof(ath_hal_debug),
427 .proc_handler = proc_dointvec
429 #endif
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),
434 .mode = 0644,
435 .proc_handler = proc_dointvec
437 { .ctl_name = CTL_AUTO,
438 .procname = "sw_beacon_response_time",
439 .mode = 0644,
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",
446 .mode = 0644,
447 .data = &ath_hal_additional_swba_backoff,
448 .maxlen = sizeof(ath_hal_additional_swba_backoff),
449 .proc_handler = proc_dointvec
451 #ifdef AH_DEBUG_ALQ
452 { .ctl_name = CTL_AUTO,
453 .procname = "alq",
454 .mode = 0644,
455 .proc_handler = sysctl_hw_ath_hal_log
457 { .ctl_name = CTL_AUTO,
458 .procname = "alq_size",
459 .mode = 0644,
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",
466 .mode = 0644,
467 .data = &ath_hal_alq_lost,
468 .maxlen = sizeof(ath_hal_alq_lost),
469 .proc_handler = proc_dointvec
471 #endif
472 { 0 }
474 static ctl_table ath_hal_table[] = {
475 { .ctl_name = CTL_AUTO,
476 .procname = "hal",
477 .mode = 0555,
478 .child = ath_hal_sysctls
479 }, { 0 }
481 static ctl_table ath_ath_table[] = {
482 { .ctl_name = DEV_ATH,
483 .procname = "ath",
484 .mode = 0555,
485 .child = ath_hal_table
486 }, { 0 }
488 static ctl_table ath_root_table[] = {
489 { .ctl_name = CTL_DEV,
490 .procname = "dev",
491 .mode = 0555,
492 .child = ath_ath_table
493 }, { 0 }
495 static struct ctl_table_header *ath_hal_sysctl_header;
497 void
498 ath_hal_sysctl_register(void)
500 static int initialized = 0;
502 if (!initialized) {
503 ath_hal_sysctl_header =
504 register_sysctl_table(ath_root_table, 1);
505 initialized = 1;
509 void
510 ath_hal_sysctl_unregister(void)
512 if (ath_hal_sysctl_header)
513 unregister_sysctl_table(ath_hal_sysctl_header);
515 #endif /* CONFIG_SYSCTL */
518 * Module glue.
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");
527 #endif
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);
538 static int __init
539 init_ath_hal(void)
541 const char *sep;
542 int i;
544 printk(KERN_INFO "%s: %s (", dev_info, ath_hal_version);
545 sep = "";
546 for (i = 0; ath_hal_buildopts[i] != NULL; i++) {
547 printk("%s%s", sep, ath_hal_buildopts[i]);
548 sep = ", ";
550 printk(")\n");
551 #ifdef CONFIG_SYSCTL
552 ath_hal_sysctl_register();
553 #endif
554 return (0);
556 module_init(init_ath_hal);
558 static void __exit
559 exit_ath_hal(void)
561 #ifdef CONFIG_SYSCTL
562 ath_hal_sysctl_unregister();
563 #endif
564 printk(KERN_INFO "%s: driver unloaded\n", dev_info);
566 module_exit(exit_ath_hal);