The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ath/ah_osdep.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    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.
   15  *
   16  * NO WARRANTY
   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.
   28  *
   29  * $FreeBSD$
   30  */
   31 #include "opt_ah.h"
   32 
   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>
   38 #include <sys/bus.h>
   39 #include <sys/malloc.h>
   40 #include <sys/proc.h>
   41 
   42 #include <machine/stdarg.h>
   43 
   44 #include <net/ethernet.h>               /* XXX for ether_sprintf */
   45 
   46 #include <dev/ath/ath_hal/ah.h>
   47 
   48 /*
   49  * WiSoC boards overload the bus tag with information about the
   50  * board layout.  We must extract the bus space tag from that
   51  * indirect structure.  For everyone else the tag is passed in
   52  * directly.
   53  * XXX cache indirect ref privately
   54  */
   55 #ifdef AH_SUPPORT_AR5312
   56 #define BUSTAG(ah) \
   57         ((bus_space_tag_t) ((struct ar531x_config *)((ah)->ah_st))->tag)
   58 #else
   59 #define BUSTAG(ah)      ((ah)->ah_st)
   60 #endif
   61 
   62 extern  void ath_hal_printf(struct ath_hal *, const char*, ...)
   63                 __printflike(2,3);
   64 extern  void ath_hal_vprintf(struct ath_hal *, const char*, __va_list)
   65                 __printflike(2, 0);
   66 extern  const char* ath_hal_ether_sprintf(const u_int8_t *mac);
   67 extern  void *ath_hal_malloc(size_t);
   68 extern  void ath_hal_free(void *);
   69 #ifdef AH_ASSERT
   70 extern  void ath_hal_assert_failed(const char* filename,
   71                 int lineno, const char* msg);
   72 #endif
   73 #ifdef AH_DEBUG
   74 extern  void DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...);
   75 #endif /* AH_DEBUG */
   76 
   77 /* NB: put this here instead of the driver to avoid circular references */
   78 SYSCTL_NODE(_hw, OID_AUTO, ath, CTLFLAG_RD, 0, "Atheros driver parameters");
   79 static SYSCTL_NODE(_hw_ath, OID_AUTO, hal, CTLFLAG_RD, 0,
   80     "Atheros HAL parameters");
   81 
   82 #ifdef AH_DEBUG
   83 int ath_hal_debug = 0;
   84 SYSCTL_INT(_hw_ath_hal, OID_AUTO, debug, CTLFLAG_RW, &ath_hal_debug,
   85     0, "Atheros HAL debugging printfs");
   86 TUNABLE_INT("hw.ath.hal.debug", &ath_hal_debug);
   87 #endif /* AH_DEBUG */
   88 
   89 static MALLOC_DEFINE(M_ATH_HAL, "ath_hal", "ath hal data");
   90 
   91 void*
   92 ath_hal_malloc(size_t size)
   93 {
   94         return malloc(size, M_ATH_HAL, M_NOWAIT | M_ZERO);
   95 }
   96 
   97 void
   98 ath_hal_free(void* p)
   99 {
  100         free(p, M_ATH_HAL);
  101 }
  102 
  103 void
  104 ath_hal_vprintf(struct ath_hal *ah, const char* fmt, va_list ap)
  105 {
  106         vprintf(fmt, ap);
  107 }
  108 
  109 void
  110 ath_hal_printf(struct ath_hal *ah, const char* fmt, ...)
  111 {
  112         va_list ap;
  113         va_start(ap, fmt);
  114         ath_hal_vprintf(ah, fmt, ap);
  115         va_end(ap);
  116 }
  117 
  118 const char*
  119 ath_hal_ether_sprintf(const u_int8_t *mac)
  120 {
  121         return ether_sprintf(mac);
  122 }
  123 
  124 #ifdef AH_DEBUG
  125 
  126 /* This must match the definition in ath_hal/ah_debug.h */
  127 #define HAL_DEBUG_UNMASKABLE    0xf0000000
  128 void
  129 DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...)
  130 {
  131         if ((mask == HAL_DEBUG_UNMASKABLE) ||
  132             (ah->ah_config.ah_debug & mask) ||
  133             (ath_hal_debug & mask)) {
  134                 __va_list ap;
  135                 va_start(ap, fmt);
  136                 ath_hal_vprintf(ah, fmt, ap);
  137                 va_end(ap);
  138         }
  139 }
  140 #undef  HAL_DEBUG_UNMASKABLE
  141 #endif /* AH_DEBUG */
  142 
  143 #ifdef AH_DEBUG_ALQ
  144 /*
  145  * ALQ register tracing support.
  146  *
  147  * Setting hw.ath.hal.alq=1 enables tracing of all register reads and
  148  * writes to the file /tmp/ath_hal.log.  The file format is a simple
  149  * fixed-size array of records.  When done logging set hw.ath.hal.alq=0
  150  * and then decode the file with the arcode program (that is part of the
  151  * HAL).  If you start+stop tracing the data will be appended to an
  152  * existing file.
  153  *
  154  * NB: doesn't handle multiple devices properly; only one DEVICE record
  155  *     is emitted and the different devices are not identified.
  156  */
  157 #include <sys/alq.h>
  158 #include <sys/pcpu.h>
  159 #include <dev/ath/ath_hal/ah_decode.h>
  160 
  161 static  struct alq *ath_hal_alq;
  162 static  int ath_hal_alq_emitdev;        /* need to emit DEVICE record */
  163 static  u_int ath_hal_alq_lost;         /* count of lost records */
  164 static  char ath_hal_logfile[MAXPATHLEN] = "/tmp/ath_hal.log";
  165 
  166 SYSCTL_STRING(_hw_ath_hal, OID_AUTO, alq_logfile, CTLFLAG_RW,
  167     &ath_hal_logfile, sizeof(kernelname), "Name of ALQ logfile");
  168 
  169 static  u_int ath_hal_alq_qsize = 64*1024;
  170 
  171 static int
  172 ath_hal_setlogging(int enable)
  173 {
  174         int error;
  175 
  176         if (enable) {
  177                 error = alq_open(&ath_hal_alq, ath_hal_logfile,
  178                         curthread->td_ucred, ALQ_DEFAULT_CMODE,
  179                         sizeof (struct athregrec), ath_hal_alq_qsize);
  180                 ath_hal_alq_lost = 0;
  181                 ath_hal_alq_emitdev = 1;
  182                 printf("ath_hal: logging to %s enabled\n",
  183                         ath_hal_logfile);
  184         } else {
  185                 if (ath_hal_alq)
  186                         alq_close(ath_hal_alq);
  187                 ath_hal_alq = NULL;
  188                 printf("ath_hal: logging disabled\n");
  189                 error = 0;
  190         }
  191         return (error);
  192 }
  193 
  194 static int
  195 sysctl_hw_ath_hal_log(SYSCTL_HANDLER_ARGS)
  196 {
  197         int error, enable;
  198 
  199         enable = (ath_hal_alq != NULL);
  200         error = sysctl_handle_int(oidp, &enable, 0, req);
  201         if (error || !req->newptr)
  202                 return (error);
  203         else
  204                 return (ath_hal_setlogging(enable));
  205 }
  206 SYSCTL_PROC(_hw_ath_hal, OID_AUTO, alq, CTLTYPE_INT|CTLFLAG_RW,
  207         0, 0, sysctl_hw_ath_hal_log, "I", "Enable HAL register logging");
  208 SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_size, CTLFLAG_RW,
  209         &ath_hal_alq_qsize, 0, "In-memory log size (#records)");
  210 SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_lost, CTLFLAG_RW,
  211         &ath_hal_alq_lost, 0, "Register operations not logged");
  212 
  213 static struct ale *
  214 ath_hal_alq_get(struct ath_hal *ah)
  215 {
  216         struct ale *ale;
  217 
  218         if (ath_hal_alq_emitdev) {
  219                 ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
  220                 if (ale) {
  221                         struct athregrec *r =
  222                                 (struct athregrec *) ale->ae_data;
  223                         r->op = OP_DEVICE;
  224                         r->reg = 0;
  225                         r->val = ah->ah_devid;
  226                         alq_post(ath_hal_alq, ale);
  227                         ath_hal_alq_emitdev = 0;
  228                 } else
  229                         ath_hal_alq_lost++;
  230         }
  231         ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
  232         if (!ale)
  233                 ath_hal_alq_lost++;
  234         return ale;
  235 }
  236 
  237 void
  238 ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
  239 {
  240         bus_space_tag_t tag = BUSTAG(ah);
  241         bus_space_handle_t h = ah->ah_sh;
  242 
  243         if (ath_hal_alq) {
  244                 struct ale *ale = ath_hal_alq_get(ah);
  245                 if (ale) {
  246                         struct athregrec *r = (struct athregrec *) ale->ae_data;
  247                         r->op = OP_WRITE;
  248                         r->reg = reg;
  249                         r->val = val;
  250                         alq_post(ath_hal_alq, ale);
  251                 }
  252         }
  253 #if _BYTE_ORDER == _BIG_ENDIAN
  254         if (OS_REG_UNSWAPPED(reg))
  255                 bus_space_write_4(tag, h, reg, val);
  256         else
  257 #endif
  258                 bus_space_write_stream_4(tag, h, reg, val);
  259 }
  260 
  261 u_int32_t
  262 ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
  263 {
  264         bus_space_tag_t tag = BUSTAG(ah);
  265         bus_space_handle_t h = ah->ah_sh;
  266         u_int32_t val;
  267 
  268 #if _BYTE_ORDER == _BIG_ENDIAN
  269         if (OS_REG_UNSWAPPED(reg))
  270                 val = bus_space_read_4(tag, h, reg);
  271         else
  272 #endif
  273                 val = bus_space_read_stream_4(tag, h, reg);
  274         if (ath_hal_alq) {
  275                 struct ale *ale = ath_hal_alq_get(ah);
  276                 if (ale) {
  277                         struct athregrec *r = (struct athregrec *) ale->ae_data;
  278                         r->op = OP_READ;
  279                         r->reg = reg;
  280                         r->val = val;
  281                         alq_post(ath_hal_alq, ale);
  282                 }
  283         }
  284         return val;
  285 }
  286 
  287 void
  288 OS_MARK(struct ath_hal *ah, u_int id, u_int32_t v)
  289 {
  290         if (ath_hal_alq) {
  291                 struct ale *ale = ath_hal_alq_get(ah);
  292                 if (ale) {
  293                         struct athregrec *r = (struct athregrec *) ale->ae_data;
  294                         r->op = OP_MARK;
  295                         r->reg = id;
  296                         r->val = v;
  297                         alq_post(ath_hal_alq, ale);
  298                 }
  299         }
  300 }
  301 #elif defined(AH_DEBUG) || defined(AH_REGOPS_FUNC)
  302 /*
  303  * Memory-mapped device register read/write.  These are here
  304  * as routines when debugging support is enabled and/or when
  305  * explicitly configured to use function calls.  The latter is
  306  * for architectures that might need to do something before
  307  * referencing memory (e.g. remap an i/o window).
  308  *
  309  * NB: see the comments in ah_osdep.h about byte-swapping register
  310  *     reads and writes to understand what's going on below.
  311  */
  312 
  313 void
  314 ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
  315 {
  316         bus_space_tag_t tag = BUSTAG(ah);
  317         bus_space_handle_t h = ah->ah_sh;
  318 
  319 #if _BYTE_ORDER == _BIG_ENDIAN
  320         if (OS_REG_UNSWAPPED(reg))
  321                 bus_space_write_4(tag, h, reg, val);
  322         else
  323 #endif
  324                 bus_space_write_stream_4(tag, h, reg, val);
  325 }
  326 
  327 u_int32_t
  328 ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
  329 {
  330         bus_space_tag_t tag = BUSTAG(ah);
  331         bus_space_handle_t h = ah->ah_sh;
  332         u_int32_t val;
  333 
  334 #if _BYTE_ORDER == _BIG_ENDIAN
  335         if (OS_REG_UNSWAPPED(reg))
  336                 val = bus_space_read_4(tag, h, reg);
  337         else
  338 #endif
  339                 val = bus_space_read_stream_4(tag, h, reg);
  340         return val;
  341 }
  342 #endif /* AH_DEBUG || AH_REGOPS_FUNC */
  343 
  344 #ifdef AH_ASSERT
  345 void
  346 ath_hal_assert_failed(const char* filename, int lineno, const char *msg)
  347 {
  348         printf("Atheros HAL assertion failure: %s: line %u: %s\n",
  349                 filename, lineno, msg);
  350         panic("ath_hal_assert");
  351 }
  352 #endif /* AH_ASSERT */

Cache object: de44bfeb85441bf0d7073fdc6ca3be6c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.