From: Aggelos Economopoulos Date: Mon, 8 Jun 2009 14:54:38 +0000 (+0300) Subject: Merge branch 'master' of /home/aggelos/devel/dfly/dfly.git/ X-Git-Tag: v2.3.2~204^2 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/2a2493da55563ee281be59a57d1eb11a349d07a1?hp=9d7a637e6808396b43ab61ee634665b49704f752 Merge branch 'master' of /home/aggelos/devel/dfly/dfly.git/ --- diff --git a/Makefile.inc1 b/Makefile.inc1 index 9b1bdacc74..ab4343eee1 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -825,7 +825,7 @@ _btxld= usr.sbin/btxld cross-tools: .for _tool in ${_btxld} ${_binutils} \ - usr.bin/objformat usr.sbin/crunch/crunchide \ + usr.bin/objformat usr.bin/crunch/crunchide \ ${_gcc34_cross} ${_gcc41_cross} ${ECHODIR} "===> ${_tool} (cross-tools)"; \ cd ${.CURDIR}/${_tool}; \ diff --git a/Makefile_upgrade.inc b/Makefile_upgrade.inc index 140754ea6b..74af46a962 100644 --- a/Makefile_upgrade.inc +++ b/Makefile_upgrade.inc @@ -1107,3 +1107,10 @@ TO_REMOVE+=/usr/lib/gcc41/gcrt1.o TO_REMOVE+=/usr/lib/gcc41/crt1.o TO_REMOVE+=/usr/lib/gcc41/crti.o TO_REMOVE+=/usr/lib/gcc41/crtn.o +TO_REMOVE+=/etc/rc.d/atm2.sh +TO_REMOVE+=/etc/rc.d/atm3.sh +TO_REMOVE+=/etc/rc.d/rcconf.sh +TO_REMOVE+=/usr/share/man/cat9/namei.9.gz +TO_REMOVE+=/usr/share/man/man9/namei.9.gz +TO_REMOVE+=/usr/share/man/cat5/host.conf.5.gz +TO_REMOVE+=/usr/share/man/man5/host.conf.5.gz diff --git a/contrib/ipfilter/ip_lfil.c b/contrib/ipfilter/ip_lfil.c index 196d64e0fe..a1fad99a47 100644 --- a/contrib/ipfilter/ip_lfil.c +++ b/contrib/ipfilter/ip_lfil.c @@ -16,7 +16,7 @@ static const char rcsid[] = "@(#)$Id: ip_lfil.c,v 2.6.2.5 2002/10/03 13:47:19 da #include #include #include -#include +#include #include #ifndef _KERNEL # include diff --git a/contrib/ipfilter/ipmon.c b/contrib/ipfilter/ipmon.c index f7e2865430..aa5cf67fa9 100644 --- a/contrib/ipfilter/ipmon.c +++ b/contrib/ipfilter/ipmon.c @@ -29,7 +29,7 @@ # if (__FreeBSD_version >= 300000) # include # else -# include +# include # endif #else # include diff --git a/contrib/ipfilter/ipsd/ipsdr.c b/contrib/ipfilter/ipsd/ipsdr.c index 298f655944..6a6b6eeaf5 100644 --- a/contrib/ipfilter/ipsd/ipsdr.c +++ b/contrib/ipfilter/ipsd/ipsdr.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/contrib/ipfilter/ipsd/sbpf.c b/contrib/ipfilter/ipsd/sbpf.c index 97bb4ce0ff..465ed6c324 100644 --- a/contrib/ipfilter/ipsd/sbpf.c +++ b/contrib/ipfilter/ipsd/sbpf.c @@ -20,7 +20,7 @@ #if BSD < 199103 #include #endif -#include +#include #include #include diff --git a/contrib/ipfilter/ipsd/slinux.c b/contrib/ipfilter/ipsd/slinux.c index 2c5aa97d2e..af6cf5b0d8 100644 --- a/contrib/ipfilter/ipsd/slinux.c +++ b/contrib/ipfilter/ipsd/slinux.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/contrib/ipfilter/ipsd/snit.c b/contrib/ipfilter/ipsd/snit.c index ec7178f1f8..eb7e65e6cc 100644 --- a/contrib/ipfilter/ipsd/snit.c +++ b/contrib/ipfilter/ipsd/snit.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/contrib/ipfilter/ipsend/lsock.c b/contrib/ipfilter/ipsend/lsock.c index 23a762114f..1f2162cc35 100644 --- a/contrib/ipfilter/ipsend/lsock.c +++ b/contrib/ipfilter/ipsend/lsock.c @@ -21,7 +21,7 @@ static const char rcsid[] = "@(#)$Id: lsock.c,v 2.1.4.3 2002/12/06 11:40:36 darr #include #include #include -#include +#include #define __KERNEL__ #if LINUX >= 0200 # undef UINT_MAX diff --git a/contrib/ipfilter/ipsend/sbpf.c b/contrib/ipfilter/ipsend/sbpf.c index 276ca07ca7..7e4c9116cc 100644 --- a/contrib/ipfilter/ipsend/sbpf.c +++ b/contrib/ipfilter/ipsend/sbpf.c @@ -27,7 +27,7 @@ #if (__FreeBSD_version >= 300000) # include #else -# include +# include #endif #include diff --git a/contrib/ipfilter/ipsend/slinux.c b/contrib/ipfilter/ipsend/slinux.c index 7438d1c25c..e4308aa622 100644 --- a/contrib/ipfilter/ipsend/slinux.c +++ b/contrib/ipfilter/ipsend/slinux.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/contrib/ipfilter/ipsend/snit.c b/contrib/ipfilter/ipsend/snit.c index 6f2c66269e..5e60522b62 100644 --- a/contrib/ipfilter/ipsend/snit.c +++ b/contrib/ipfilter/ipsend/snit.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/contrib/ipfilter/ipsend/sock.c b/contrib/ipfilter/ipsend/sock.c index 4d72d8726a..313f36a7ab 100644 --- a/contrib/ipfilter/ipsend/sock.c +++ b/contrib/ipfilter/ipsend/sock.c @@ -24,7 +24,7 @@ #if (__FreeBSD_version >= 300000) # include #else -# include +# include #endif #define _KERNEL #define KERNEL diff --git a/contrib/tcp_wrappers/fix_options.c b/contrib/tcp_wrappers/fix_options.c index 9e6769b6b4..7a5de68040 100644 --- a/contrib/tcp_wrappers/fix_options.c +++ b/contrib/tcp_wrappers/fix_options.c @@ -35,6 +35,7 @@ static char sccsid[] = "@(#) fix_options.c 1.6 97/04/08 02:29:19"; /* fix_options - get rid of IP-level socket options */ +void fix_options(request) struct request_info *request; { diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 0f7895baea..625ef42876 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -391,6 +391,7 @@ sendmail_outbound_flags="-L sm-queue -q30m" # Flags to sendmail (outbound only) sendmail_msp_queue_enable="YES" # Dequeue stuck clientmqueue mail (YES/NO). sendmail_msp_queue_flags="-L sm-msp-queue -Ac -q30m" # Flags for sendmail_msp_queue daemon. +sendmail_rebuild_aliases="YES" # Run newaliases if necessary (YES/NO). ############################################################## diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index 7a0f6d41f3..91e70f5100 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -7,7 +7,7 @@ # note: bgfsk, devfs, and lomac left out (from 5.0) # FILES= DAEMON LOGIN NETWORKING SERVERS abi accounting addswap adjkerntz \ - amd apm apmd atm1 atm2.sh atm3.sh \ + amd apm apmd atm1 atm2 atm3 \ battd bootconf bootparams btconfig bthcid ccd cleanvar \ cleartmp cron devd dhclient diskless dmesg dumpon \ fsck ftpd hostapd hostname \ @@ -20,7 +20,7 @@ FILES= DAEMON LOGIN NETWORKING SERVERS abi accounting addswap adjkerntz \ named netif netoptions newsyslog \ network_ipv6 nfsclient nfsd nfsserver nisdomain nscd nsswitch \ dntpd othermta pf pflog ppp ppp-user pppoed pwcheck \ - quota random rarpd rcconf.sh resident rndcontrol root route6d routed \ + quota random rarpd rcconf resident rndcontrol root route6d routed \ routing rpcbind rtadvd rtsold rwho sysdb savecore sdpd securelevel \ sendmail sensorsd serial sppp sshd statd swap1 syscons sysctl syslogd \ timed ttys usbd varsym vinum virecover watchdogd wpa_supplicant \ diff --git a/etc/rc.d/atm2.sh b/etc/rc.d/atm2 similarity index 97% rename from etc/rc.d/atm2.sh rename to etc/rc.d/atm2 index 124e85d8c8..c9e7448a0f 100644 --- a/etc/rc.d/atm2.sh +++ b/etc/rc.d/atm2 @@ -88,7 +88,7 @@ atm2_start() done fi - # XXX - required by atm3.sh. I don't like having one script depend + # XXX - required by atm3. I don't like having one script depend # on variables in another script (especially in a dynamic # ordered system like this), but it's necessary for the moment. # diff --git a/etc/rc.d/atm3.sh b/etc/rc.d/atm3 similarity index 100% rename from etc/rc.d/atm3.sh rename to etc/rc.d/atm3 diff --git a/etc/rc.d/diskless b/etc/rc.d/diskless index 9406e79ea5..9ea8804909 100644 --- a/etc/rc.d/diskless +++ b/etc/rc.d/diskless @@ -107,11 +107,6 @@ fi echo "+++ create lastlog" /usr/bin/touch /var/log/lastlog -# Make sure our aliases database is uptodate, the aliases may have -# been overridden in /conf. -# -/usr/bin/newaliases - # XXX make sure to create one dir for each printer as requested by lpd # # If we do not have a writable /tmp, create a memory diff --git a/etc/rc.d/rcconf.sh b/etc/rc.d/rcconf similarity index 100% rename from etc/rc.d/rcconf.sh rename to etc/rc.d/rcconf diff --git a/etc/rc.d/sendmail b/etc/rc.d/sendmail index 492e1f9f01..4f492eead9 100644 --- a/etc/rc.d/sendmail +++ b/etc/rc.d/sendmail @@ -18,6 +18,7 @@ name="sendmail" rcvar=`set_rcvar` required_files="/etc/mail/${name}.cf" +start_precmd="sendmail_precmd" command=${sendmail_program:-/usr/sbin/sendmail} pidfile=${sendmail_pidfile:-/var/run/sendmail.pid} load_rc_config $name @@ -44,16 +45,18 @@ sendmail_precmd() fi # check modifications on /etc/mail/aliases - if [ -f "/etc/mail/aliases.db" ]; then - if [ "/etc/mail/aliases" -nt "/etc/mail/aliases.db" ]; then - echo \ + if checkyesno sendmail_rebuild_aliases; then + if [ -f "/etc/mail/aliases.db" ]; then + if [ "/etc/mail/aliases" -nt "/etc/mail/aliases.db" ]; then + echo \ "${name}: /etc/mail/aliases newer than /etc/mail/aliases.db, regenerating" - /usr/bin/newaliases - fi - else - echo \ + /usr/bin/newaliases + fi + else + echo \ "${name}: /etc/mail/aliases.db not present, generating" - /usr/bin/newaliases + /usr/bin/newaliases + fi fi # check couple of common db files, too diff --git a/gnu/lib/gcc41/libstdc++/Makefile b/gnu/lib/gcc41/libstdc++/Makefile index d54f5b8cb9..bafe045724 100644 --- a/gnu/lib/gcc41/libstdc++/Makefile +++ b/gnu/lib/gcc41/libstdc++/Makefile @@ -456,25 +456,29 @@ THRHDRS= gthr.h gthr-single.h gthr-posix.h gthr-default.h THRHDRSDIR= ${INCLUDEDIR}/c++/4.1/bits gthr.h: ${GCCDIR}/gcc/gthr.h - sed -e '/^#/s/\([ABCDEFGHIJKLMNOPQRSTUVWXYZ_][ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*\)/_GLIBCPP_\1/g' \ + sed -e '/^#pragma/b' \ + -e '/^#/s/\([ABCDEFGHIJKLMNOPQRSTUVWXYZ_][ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*\)/_GLIBCXX_\1/g' \ + -e 's/_GLIBCXX_SUPPORTS_WEAK/__GXX_WEAK__/g' \ -e 's,^#include "\(.*\)",#include ,g' \ < ${GCCDIR}/gcc/gthr.h > gthr.h gthr-single.h: ${GCCDIR}/gcc/gthr-single.h - sed -e 's/\(UNUSED\)/_GLIBCPP_\1/g' \ - -e 's/\(GCC[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*_H\)/_GLIBCPP_\1/g' \ + sed -e 's/\(UNUSED\)/_GLIBCXX_\1/g' \ + -e 's/\(GCC[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*_H\)/_GLIBCXX_\1/g' \ < ${GCCDIR}/gcc/gthr-single.h > gthr-single.h gthr-posix.h: ${GCCDIR}/gcc/gthr-posix.h - sed -e 's/\(UNUSED\)/_GLIBCPP_\1/g' \ - -e 's/\(GCC[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*_H\)/_GLIBCPP_\1/g' \ - -e 's/\([ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*WEAK\)/_GLIBCPP_\1/g' \ + sed -e 's/\(UNUSED\)/_GLIBCXX_\1/g' \ + -e 's/\(GCC[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*_H\)/_GLIBCXX_\1/g' \ + -e 's/SUPPORTS_WEAK/__GXX_WEAK__/g' \ + -e 's/\([ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*USE_WEAK\)/_GLIBCXX_\1/g' \ < ${GCCDIR}/gcc/gthr-posix.h > gthr-posix.h gthr-default.h: ${GCCDIR}/gcc/gthr-posix.h - sed -e 's/\(UNUSED\)/_GLIBCPP_\1/g' \ - -e 's/\(GCC[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*_H\)/_GLIBCPP_\1/g' \ - -e 's/\([ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*WEAK\)/_GLIBCPP_\1/g' \ + sed -e 's/\(UNUSED\)/_GLIBCXX_\1/g' \ + -e 's/\(GCC[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*_H\)/_GLIBCXX_\1/g' \ + -e 's/SUPPORTS_WEAK/__GXX_WEAK__/g' \ + -e 's/\([ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*USE_WEAK\)/_GLIBCXX_\1/g' \ -e 's,^#include "\(.*\)",#include ,g' \ < ${GCCDIR}/gcc/gthr-posix.h > gthr-default.h diff --git a/gnu/usr.bin/cc34/cc_prep/config/dragonfly-spec.h b/gnu/usr.bin/cc34/cc_prep/config/dragonfly-spec.h index 0b0b208fd5..c2cfe6a420 100644 --- a/gnu/usr.bin/cc34/cc_prep/config/dragonfly-spec.h +++ b/gnu/usr.bin/cc34/cc_prep/config/dragonfly-spec.h @@ -116,7 +116,7 @@ Boston, MA 02111-1307, USA. */ /* Provide a LIB_SPEC appropriate for DragonFly. Just select the appropriate libc, depending on whether we're doing profiling or need threads support. - (simular to the default, except no -lg, and no -p). */ + (similar to the default, except no -lg, and no -p). */ #ifdef DFBSD_NO_THREADS #define DFBSD_LIB_SPEC " \ diff --git a/include/pthread.h b/include/pthread.h index b623804323..9d0f06eef1 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -83,60 +83,6 @@ #define PTHREAD_CANCEL_ASYNCHRONOUS 2 #define PTHREAD_CANCELED ((void *) 1) -/* - * Forward structure definitions. - * - * These are mostly opaque to the user. - */ -struct pthread; -struct pthread_attr; -struct pthread_cond; -struct pthread_cond_attr; -struct pthread_mutex; -struct pthread_mutex_attr; -struct pthread_once; -struct pthread_rwlock; -struct pthread_rwlockattr; -struct pthread_barrier; -struct pthread_barrier_attr; - -/* - * Primitive system data type definitions required by P1003.1c. - * - * Note that P1003.1c specifies that there are no defined comparison - * or assignment operators for the types pthread_attr_t, pthread_cond_t, - * pthread_condattr_t, pthread_mutex_t, pthread_mutexattr_t. - */ -typedef struct pthread *pthread_t; -typedef struct pthread_attr *pthread_attr_t; -typedef struct pthread_mutex *pthread_mutex_t; -typedef struct pthread_mutex_attr *pthread_mutexattr_t; -typedef struct pthread_cond *pthread_cond_t; -typedef struct pthread_cond_attr *pthread_condattr_t; -typedef int pthread_key_t; -typedef struct pthread_once pthread_once_t; -typedef struct pthread_rwlock *pthread_rwlock_t; -typedef struct pthread_rwlockattr *pthread_rwlockattr_t; -typedef struct pthread_barrier *pthread_barrier_t; -typedef struct pthread_barrierattr *pthread_barrierattr_t; - -/* - * Additional type definitions: - * - * Note that P1003.1c reserves the prefixes pthread_ and PTHREAD_ for - * use in header symbols. - */ -typedef void *pthread_addr_t; -typedef void *(*pthread_startroutine_t) (void *); - -/* - * Once definitions. - */ -struct pthread_once { - int state; - pthread_mutex_t mutex; -}; - /* * Flags for once initialization. */ diff --git a/include/stdint.h b/include/stdint.h index 7965785061..d489f9ffc4 100644 --- a/include/stdint.h +++ b/include/stdint.h @@ -69,5 +69,13 @@ typedef __uint_least16_t uint_least16_t; typedef __uint_least32_t uint_least32_t; typedef __uint_least64_t uint_least64_t; +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) +#include +#endif /* !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) */ + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) +#include +#endif + #endif diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index 2d7f76b7ad..ec0a7fe34e 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -24,7 +24,7 @@ SRCS+= _pthread_stubs.c _rand48.c _spinlock_stub.c _thread_init.c \ msgget.c msgrcv.c msgsnd.c nftw.c nice.c \ nlist.c nrand48.c ntp_gettime.c opendir.c \ pause.c pmadvise.c popen.c posix_spawn.c posixshm.c \ - psignal.c pthread_fake.c pw_scan.c pwcache.c \ + psignal.c pw_scan.c pwcache.c \ raise.c readdir.c readpassphrase.c rewinddir.c \ scandir.c seed48.c seekdir.c semconfig.c semctl.c semget.c semop.c \ setdomainname.c sethostname.c setjmperr.c setmode.c setprogname.c \ diff --git a/lib/libc/gen/_pthread_stubs.c b/lib/libc/gen/_pthread_stubs.c index 5c6ae7b2b4..6a191a6ffc 100644 --- a/lib/libc/gen/_pthread_stubs.c +++ b/lib/libc/gen/_pthread_stubs.c @@ -27,43 +27,8 @@ * $DragonFly: src/lib/libc/gen/_pthread_stubs.c,v 1.4 2005/05/09 12:43:40 davidxu Exp $ */ -#include -#include -#include - -int _pthread_cond_init_stub(pthread_cond_t *, const pthread_condattr_t *); -int _pthread_cond_signal_stub(pthread_cond_t *); -int _pthread_cond_wait_stub(pthread_cond_t *, pthread_mutex_t *); -void *_pthread_getspecific_stub(pthread_key_t); -int _pthread_key_create_stub(pthread_key_t *, void (*)(void *)); -int _pthread_key_delete_stub(pthread_key_t); -int _pthread_main_np_stub(void); -int _pthread_mutex_destroy_stub(pthread_mutex_t *); -int _pthread_mutex_init_stub(pthread_mutex_t *, - const pthread_mutexattr_t *); -int _pthread_mutex_lock_stub(pthread_mutex_t *); -int _pthread_mutex_trylock_stub(pthread_mutex_t *); -int _pthread_mutex_unlock_stub(pthread_mutex_t *); -int _pthread_mutexattr_init_stub(pthread_mutexattr_t *); -int _pthread_mutexattr_destroy_stub(pthread_mutexattr_t *); -int _pthread_mutexattr_settype_stub(pthread_mutexattr_t *, int); -int _pthread_once_stub(pthread_once_t *, void (*)(void)); -int _pthread_rwlock_init_stub(pthread_rwlock_t *, - const pthread_rwlockattr_t *); -int _pthread_rwlock_destroy_stub(pthread_rwlock_t *); -int _pthread_rwlock_rdlock_stub(pthread_rwlock_t *); -int _pthread_rwlock_tryrdlock_stub(pthread_rwlock_t *); -int _pthread_rwlock_trywrlock_stub(pthread_rwlock_t *); -int _pthread_rwlock_unlock_stub(pthread_rwlock_t *); -int _pthread_rwlock_wrlock_stub(pthread_rwlock_t *); -int _pthread_setspecific_stub(pthread_key_t, const void *); -int _pthread_sigmask_stub(int, const sigset_t *, sigset_t *); - -/* define a null pthread structure just to satisfy _pthread_self */ -struct pthread { -}; - -static struct pthread main_thread; +#include +#include /* * Weak symbols: All libc internal usage of these functions should @@ -74,192 +39,152 @@ static struct pthread main_thread; * between application locks and libc locks (threads holding the * latter can't be allowed to exit/terminate). */ -__weak_reference(_pthread_cond_init_stub, _pthread_cond_init); -__weak_reference(_pthread_cond_signal_stub, _pthread_cond_signal); -__weak_reference(_pthread_cond_wait_stub, _pthread_cond_wait); -__weak_reference(_pthread_getspecific_stub, _pthread_getspecific); -__weak_reference(_pthread_key_create_stub, _pthread_key_create); -__weak_reference(_pthread_key_delete_stub, _pthread_key_delete); -__weak_reference(_pthread_main_np_stub, _pthread_main_np); -__weak_reference(_pthread_mutex_destroy_stub, _pthread_mutex_destroy); -__weak_reference(_pthread_mutex_init_stub, _pthread_mutex_init); -__weak_reference(_pthread_mutex_lock_stub, _pthread_mutex_lock); -__weak_reference(_pthread_mutex_trylock_stub, _pthread_mutex_trylock); -__weak_reference(_pthread_mutex_unlock_stub, _pthread_mutex_unlock); -__weak_reference(_pthread_mutexattr_init_stub, _pthread_mutexattr_init); -__weak_reference(_pthread_mutexattr_destroy_stub, _pthread_mutexattr_destroy); -__weak_reference(_pthread_mutexattr_settype_stub, _pthread_mutexattr_settype); -__weak_reference(_pthread_once_stub, _pthread_once); -__weak_reference(_pthread_self_stub, _pthread_self); -__weak_reference(_pthread_rwlock_init_stub, _pthread_rwlock_init); -__weak_reference(_pthread_rwlock_rdlock_stub, _pthread_rwlock_rdlock); -__weak_reference(_pthread_rwlock_tryrdlock_stub, _pthread_rwlock_tryrdlock); -__weak_reference(_pthread_rwlock_trywrlock_stub, _pthread_rwlock_trywrlock); -__weak_reference(_pthread_rwlock_unlock_stub, _pthread_rwlock_unlock); -__weak_reference(_pthread_rwlock_wrlock_stub, _pthread_rwlock_wrlock); -__weak_reference(_pthread_setspecific_stub, _pthread_setspecific); -__weak_reference(_pthread_sigmask_stub, _pthread_sigmask); - -int -_pthread_cond_init_stub(pthread_cond_t *cond __unused, - const pthread_condattr_t *cond_attr __unused) -{ - return (0); -} - -int -_pthread_cond_signal_stub(pthread_cond_t *cond __unused) -{ - return (0); -} -int -_pthread_cond_wait_stub(pthread_cond_t *cond __unused, - pthread_mutex_t *mutex __unused) -{ - return (0); -} - -void * -_pthread_getspecific_stub(pthread_key_t key __unused) +#define WR(f, n) \ + __weak_reference(f, _ ## n); \ + __weak_reference(f, n) + + +WR(stub_zero, pthread_atfork); +WR(stub_zero, pthread_attr_destroy); +WR(stub_zero, pthread_attr_get_np); +WR(stub_zero, pthread_attr_getdetachstate); +WR(stub_zero, pthread_attr_getinheritsched); +WR(stub_zero, pthread_attr_getschedparam); +WR(stub_zero, pthread_attr_getschedpolicy); +WR(stub_zero, pthread_attr_getscope); +WR(stub_zero, pthread_attr_getstack); +WR(stub_zero, pthread_attr_getstackaddr); +WR(stub_zero, pthread_attr_getstacksize); +WR(stub_zero, pthread_attr_init); +WR(stub_zero, pthread_attr_setcreatesuspend_np); +WR(stub_zero, pthread_attr_setdetachstate); +WR(stub_zero, pthread_attr_setinheritsched); +WR(stub_zero, pthread_attr_setschedparam); +WR(stub_zero, pthread_attr_setschedpolicy); +WR(stub_zero, pthread_attr_setscope); +WR(stub_zero, pthread_attr_setstack); +WR(stub_zero, pthread_attr_setstackaddr); +WR(stub_zero, pthread_attr_setstacksize); +WR(stub_zero, pthread_cancel); +WR(stub_zero, pthread_cleanup_pop); +WR(stub_zero, pthread_cleanup_push); +WR(stub_zero, pthread_cond_broadcast); +WR(stub_zero, pthread_cond_destroy); +WR(stub_zero, pthread_cond_init); +WR(stub_zero, pthread_cond_signal); +WR(stub_zero, pthread_cond_timedwait); +WR(stub_zero, pthread_cond_wait); +WR(stub_zero, pthread_condattr_destroy); +WR(stub_zero, pthread_condattr_init); +WR(stub_zero, pthread_detach); +WR(stub_true, pthread_equal); +WR(stub_exit, pthread_exit); +WR(stub_zero, pthread_getconcurrency); +WR(stub_zero, pthread_getprio); +WR(stub_zero, pthread_getschedparam); +WR(stub_null, pthread_getspecific); +WR(stub_zero, pthread_join); +WR(stub_zero, pthread_key_create); +WR(stub_zero, pthread_key_delete); +WR(stub_zero, pthread_kill); +WR(stub_main, pthread_main_np); +WR(stub_zero, pthread_multi_np); +WR(stub_zero, pthread_mutex_destroy); +WR(stub_zero, pthread_mutex_getprioceiling); +WR(stub_zero, pthread_mutex_init); +WR(stub_zero, pthread_mutex_lock); +WR(stub_zero, pthread_mutex_setprioceiling); +WR(stub_zero, pthread_mutex_trylock); +WR(stub_zero, pthread_mutex_unlock); +WR(stub_zero, pthread_mutexattr_destroy); +WR(stub_zero, pthread_mutexattr_getkind_np); +WR(stub_zero, pthread_mutexattr_getprioceiling); +WR(stub_zero, pthread_mutexattr_getprotocol); +WR(stub_zero, pthread_mutexattr_getpshared); +WR(stub_zero, pthread_mutexattr_gettype); +WR(stub_zero, pthread_mutexattr_init); +WR(stub_zero, pthread_mutexattr_setkind_np); +WR(stub_zero, pthread_mutexattr_setprioceiling); +WR(stub_zero, pthread_mutexattr_setprotocol); +WR(stub_zero, pthread_mutexattr_setpshared); +WR(stub_zero, pthread_mutexattr_settype); +WR(stub_zero, pthread_once); +WR(stub_zero, pthread_resume_all_np); +WR(stub_zero, pthread_resume_np); +WR(stub_zero, pthread_rwlock_destroy); +WR(stub_zero, pthread_rwlock_init); +WR(stub_zero, pthread_rwlock_rdlock); +WR(stub_zero, pthread_rwlock_tryrdlock); +WR(stub_zero, pthread_rwlock_trywrlock); +WR(stub_zero, pthread_rwlock_unlock); +WR(stub_zero, pthread_rwlock_wrlock); +WR(stub_zero, pthread_rwlockattr_destroy); +WR(stub_zero, pthread_rwlockattr_getpshared); +WR(stub_zero, pthread_rwlockattr_init); +WR(stub_zero, pthread_rwlockattr_setpshared); +WR(stub_self, pthread_self); +WR(stub_zero, pthread_set_name_np); +WR(stub_zero, pthread_setcancelstate); +WR(stub_zero, pthread_setcanceltype); +WR(stub_zero, pthread_setconcurrency); +WR(stub_zero, pthread_setprio); +WR(stub_zero, pthread_setschedparam); +WR(stub_zero, pthread_setspecific); +WR(stub_zero, pthread_sigmask); +WR(stub_zero, pthread_single_np); +WR(stub_zero, pthread_suspend_all_np); +WR(stub_zero, pthread_suspend_np); +WR(stub_zero, pthread_switch_add_np); +WR(stub_zero, pthread_switch_delete_np); +WR(stub_zero, pthread_testcancel); +WR(stub_zero, pthread_yield); +WR(stub_zero, sched_yield); +WR(stub_zero, sem_close); +WR(stub_zero, sem_destroy); +WR(stub_zero, sem_getvalue); +WR(stub_zero, sem_init); +WR(stub_zero, sem_open); +WR(stub_zero, sem_post); +WR(stub_zero, sem_trywait); +WR(stub_zero, sem_unlink); +WR(stub_zero, sem_wait); + + +static int __used +stub_zero(void) +{ + return (0); +} + +static void * __used +stub_null(void) { return (NULL); } -int -_pthread_key_create_stub(pthread_key_t *key __unused, - void (*destructor) (void *) __unused) +static void * __used +stub_self(void) { - return (0); -} + static struct {} main_thread; -int -_pthread_key_delete_stub(pthread_key_t key __unused) -{ - return (0); + return (&main_thread); } -int -_pthread_main_np_stub(void) +static int __used +stub_main(void) { return (-1); } -int -_pthread_mutex_destroy_stub(pthread_mutex_t *mattr __unused) +static int __used +stub_true(void) { - return (0); -} - -int -_pthread_mutex_init_stub(pthread_mutex_t *mutex __unused, - const pthread_mutexattr_t *mattr __unused) -{ - return (0); -} - -int -_pthread_mutex_lock_stub(pthread_mutex_t *mutex __unused) -{ - return (0); -} - -int -_pthread_mutex_trylock_stub(pthread_mutex_t *mutex __unused) -{ - return (0); -} - -int -_pthread_mutex_unlock_stub(pthread_mutex_t *mutex __unused) -{ - return (0); -} - -int -_pthread_mutexattr_init_stub(pthread_mutexattr_t *mattr __unused) -{ - return (0); -} - -int -_pthread_mutexattr_destroy_stub(pthread_mutexattr_t *mattr __unused) -{ - return (0); + return (1); } -int -_pthread_mutexattr_settype_stub(pthread_mutexattr_t *mattr __unused, - int type __unused) +static void __used +stub_exit(void) { - return (0); -} - -int -_pthread_once_stub(pthread_once_t *once_control __unused, - void (*init_routine) (void) __unused) -{ - return (0); -} - -int -_pthread_rwlock_init_stub(pthread_rwlock_t *rwlock __unused, - const pthread_rwlockattr_t *attr __unused) -{ - return (0); -} - -int -_pthread_rwlock_destroy_stub(pthread_rwlock_t *rwlock __unused) -{ - return (0); -} - -int -_pthread_rwlock_rdlock_stub(pthread_rwlock_t *rwlock __unused) -{ - return (0); -} - -int -_pthread_rwlock_tryrdlock_stub(pthread_rwlock_t *rwlock __unused) -{ - return (0); -} - -int -_pthread_rwlock_trywrlock_stub(pthread_rwlock_t *rwlock __unused) -{ - return (0); -} - -int -_pthread_rwlock_unlock_stub(pthread_rwlock_t *rwlock __unused) -{ - return (0); -} - -int -_pthread_rwlock_wrlock_stub(pthread_rwlock_t *rwlock __unused) -{ - return (0); -} - -pthread_t -_pthread_self_stub(void) -{ - return (&main_thread); -} -int -_pthread_setspecific_stub(pthread_key_t key __unused, - const void *value __unused) -{ - return (0); -} - -int -_pthread_sigmask_stub(int how __unused, const sigset_t *set __unused, - sigset_t *oset __unused) -{ - return (0); + exit(0); } diff --git a/lib/libc/gen/getobjformat.3 b/lib/libc/gen/getobjformat.3 index d3d29c4186..187897df52 100644 --- a/lib/libc/gen/getobjformat.3 +++ b/lib/libc/gen/getobjformat.3 @@ -25,7 +25,7 @@ .\" $FreeBSD: src/lib/libc/gen/getobjformat.3,v 1.3.2.6 2003/03/13 18:05:37 trhodes Exp $ .\" $DragonFly: src/lib/libc/gen/getobjformat.3,v 1.2 2003/06/17 04:26:42 dillon Exp $ .\" -.Dd September 7, 1998 +.Dd May 23, 2009 .Dt GETOBJFORMAT 3 .Os .Sh NAME @@ -36,67 +36,30 @@ .Sh SYNOPSIS .In objformat.h .Ft int -.Fn getobjformat "char *buf" "size_t bufsize" "int *argcp" "char **argv" +.Fn getobjformat "char *buf" "size_t bufsize" "int *argcp __unused" "char **argv __unused" .Sh DESCRIPTION The .Fn getobjformat -function -queries several sources to determine the preferred object file -format, and copies its name into a buffer provided by the caller. -.Pp -The object file format is determined as follows. If -.Va argv -is -.No non- Ns Ev NULL -and an explicit command line argument such as -.Fl aout -or -.Fl elf -is present, then that determines the object file format. -.Pp -Otherwise, if the variable -.Ev OBJFORMAT -is set in the environment, the object file format is taken from its -value. -.Pp -Otherwise, if the file -.Pa /etc/objformat -is readable and contains a line of the form -.Ql OBJFORMAT=xxx , -the object file format is taken from there. -.Pp -Otherwise, a built-in system default object file format is returned. +function copies the name of the preferred object file format +.Dq ( elf ) +into a buffer provided by the caller. +The function is currently provided only for backward compatibility. .Pp .Va buf points to a user-supplied buffer into which the name of the object file format is copied. .Va bufsize -gives the size of the buffer in bytes. The string placed in +gives the size of the buffer in bytes. +The string placed in .Va buf -is always null-terminated. It is an error if the buffer is too -small to hold the null-terminated name. +is always null-terminated. +It is an error if the buffer is too small to hold the null-terminated name. .Pp .Va argv -points to a -.Dv NULL Ns -terminated -argument vector to be scanned for object -format options. -.Va argv -may be -.Dv NULL , -in which case the argument vector is not scanned. -.Pp -If -.Va argcp -is non-NULL, any object format options are deleted from the -argument vector, and the updated argument count is stored into -the integer referenced by -.Va argcp . -If +and .Va argcp -is -.Dv NULL , -the argument vector is left unchanged. +are unused and new applications should set them to +.Dv NULL . .Sh RETURN VALUES On success, .Fn getobjformat @@ -105,23 +68,9 @@ null terminator. If the supplied buffer is too small to hold the object file format and its null terminator, .Fn getobjformat -returns -1. In that case, the contents of the buffer and argument +returns -1. +In that case, the contents of the buffer and argument vector supplied by the caller are indeterminate. -.Sh ENVIRONMENT -.Bl -tag -width OBJFORMAT -.It Ev OBJFORMAT -If the environment variable -.Ev OBJFORMAT -is set, it overrides the default object file format. -.Ev OBJFORMAT takes precedence over -.Pa /etc/objformat . -.El -.Sh FILES -.Bl -tag -width /etc/objformat -compact -.It Pa /etc/objformat -If present, specifies the object file format to use. Syntax is -.Ql OBJFORMAT=xxx . -.El .Sh SEE ALSO .Xr objformat 1 .Sh HISTORY diff --git a/lib/libc/gen/pthread_fake.c b/lib/libc/gen/pthread_fake.c deleted file mode 100644 index 7b28929f8b..0000000000 --- a/lib/libc/gen/pthread_fake.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2004 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Simon Schubert - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $DragonFly: src/lib/libc/gen/pthread_fake.c,v 1.3 2008/05/25 21:34:49 hasso Exp $ - */ - -#ifndef _THREAD_SAFE -/* - * Provide the functions for non-threaded programs using - * thread-aware dynamic modules. - * - * This list explicitly lakes pthread_create, since an application - * using this function clearly should be linked against -lc_r. - * Leaving this function out allows the linker to catch this. - * Same reason applies for thread-aware modules. - */ - -#include - -#include -#include - -int _pthread_fake_inval(void); -void *_pthread_fake_null(void); - -__weak_reference(_pthread_fake_inval, pthread_atfork); -__weak_reference(_pthread_fake_inval, pthread_attr_destroy); -__weak_reference(_pthread_fake_inval, pthread_attr_get_np); -__weak_reference(_pthread_fake_inval, pthread_attr_getdetachstate); -__weak_reference(_pthread_fake_inval, pthread_attr_getinheritsched); -__weak_reference(_pthread_fake_inval, pthread_attr_getschedparam); -__weak_reference(_pthread_fake_inval, pthread_attr_getschedpolicy); -__weak_reference(_pthread_fake_inval, pthread_attr_getscope); -__weak_reference(_pthread_fake_inval, pthread_attr_getstack); -__weak_reference(_pthread_fake_inval, pthread_attr_getstackaddr); -__weak_reference(_pthread_fake_inval, pthread_attr_getstacksize); -__weak_reference(_pthread_fake_inval, pthread_attr_init); -__weak_reference(_pthread_fake_inval, pthread_attr_setcreatesuspend_np); -__weak_reference(_pthread_fake_inval, pthread_attr_setdetachstate); -__weak_reference(_pthread_fake_inval, pthread_attr_setinheritsched); -__weak_reference(_pthread_fake_inval, pthread_attr_setschedparam); -__weak_reference(_pthread_fake_inval, pthread_attr_setschedpolicy); -__weak_reference(_pthread_fake_inval, pthread_attr_setscope); -__weak_reference(_pthread_fake_inval, pthread_attr_setstack); -__weak_reference(_pthread_fake_inval, pthread_attr_setstackaddr); -__weak_reference(_pthread_fake_inval, pthread_attr_setstacksize); -__weak_reference(_pthread_fake_inval, pthread_cancel); -__weak_reference(_pthread_fake_inval, pthread_setcancelstate); -__weak_reference(_pthread_fake_inval, pthread_setcanceltype); -__weak_reference(_pthread_fake_inval, pthread_testcancel);/*XXX void */ -__weak_reference(_pthread_fake_inval, pthread_cleanup_push);/*XXX void */ -__weak_reference(_pthread_fake_inval, pthread_cleanup_pop);/*XXX void */ -__weak_reference(_pthread_fake_inval, pthread_getconcurrency); -__weak_reference(_pthread_fake_inval, pthread_setconcurrency); -__weak_reference(_pthread_fake_inval, pthread_cond_init); -__weak_reference(_pthread_fake_inval, pthread_cond_destroy); -__weak_reference(_pthread_fake_inval, pthread_cond_wait); -__weak_reference(_pthread_fake_inval, pthread_cond_timedwait); -__weak_reference(_pthread_fake_inval, pthread_cond_signal); -__weak_reference(_pthread_fake_inval, pthread_cond_broadcast); -__weak_reference(_pthread_fake_inval, pthread_condattr_destroy); -__weak_reference(_pthread_fake_inval, pthread_condattr_init); -__weak_reference(_pthread_fake_inval, pthread_detach); -__weak_reference(_pthread_fake_inval, pthread_equal);/*XXX*/ -__weak_reference(_pthread_fake_inval, pthread_exit);/*XXX void*/ -__weak_reference(_pthread_fake_inval, pthread_getprio); -__weak_reference(_pthread_fake_inval, pthread_getschedparam); -__weak_reference(_pthread_fake_inval, pthread_set_name_np);/*XXX void*/ -__weak_reference(_pthread_fake_inval, pthread_join); -__weak_reference(_pthread_fake_inval, pthread_kill); -__weak_reference(_pthread_fake_inval, pthread_main_np); -__weak_reference(_pthread_fake_inval, pthread_mutexattr_init); -__weak_reference(_pthread_fake_inval, pthread_mutexattr_setkind_np); -__weak_reference(_pthread_fake_inval, pthread_mutexattr_getkind_np); -__weak_reference(_pthread_fake_inval, pthread_mutexattr_gettype); -__weak_reference(_pthread_fake_inval, pthread_mutexattr_settype); -__weak_reference(_pthread_fake_inval, pthread_multi_np); -__weak_reference(_pthread_fake_inval, pthread_mutex_init); -__weak_reference(_pthread_fake_inval, pthread_mutex_destroy); -__weak_reference(_pthread_fake_inval, pthread_mutex_trylock); -__weak_reference(_pthread_fake_inval, pthread_mutex_lock); -__weak_reference(_pthread_fake_inval, pthread_mutex_unlock); -__weak_reference(_pthread_fake_inval, pthread_mutexattr_getprioceiling); -__weak_reference(_pthread_fake_inval, pthread_mutexattr_setprioceiling); -__weak_reference(_pthread_fake_inval, pthread_mutex_getprioceiling); -__weak_reference(_pthread_fake_inval, pthread_mutex_setprioceiling); -__weak_reference(_pthread_fake_inval, pthread_mutexattr_getprotocol); -__weak_reference(_pthread_fake_inval, pthread_mutexattr_setprotocol); -__weak_reference(_pthread_fake_inval, pthread_mutexattr_destroy); -__weak_reference(_pthread_fake_inval, pthread_once); -__weak_reference(_pthread_fake_inval, pthread_resume_np); -__weak_reference(_pthread_fake_inval, pthread_resume_all_np);/*XXX void*/ -__weak_reference(_pthread_fake_inval, pthread_rwlock_destroy); -__weak_reference(_pthread_fake_inval, pthread_rwlock_init); -__weak_reference(_pthread_fake_inval, pthread_rwlock_rdlock); -__weak_reference(_pthread_fake_inval, pthread_rwlock_tryrdlock); -__weak_reference(_pthread_fake_inval, pthread_rwlock_trywrlock); -__weak_reference(_pthread_fake_inval, pthread_rwlock_unlock); -__weak_reference(_pthread_fake_inval, pthread_rwlock_wrlock); -__weak_reference(_pthread_fake_inval, pthread_rwlockattr_destroy); -__weak_reference(_pthread_fake_inval, pthread_rwlockattr_getpshared); -__weak_reference(_pthread_fake_inval, pthread_rwlockattr_init); -__weak_reference(_pthread_fake_inval, pthread_rwlockattr_setpshared); -__weak_reference(_pthread_fake_null, pthread_self);/*XXX pthread_t */ -__weak_reference(_pthread_fake_inval, sem_init); -__weak_reference(_pthread_fake_inval, sem_destroy); -__weak_reference(_pthread_fake_inval, sem_open); -__weak_reference(_pthread_fake_inval, sem_close); -__weak_reference(_pthread_fake_inval, sem_unlink); -__weak_reference(_pthread_fake_inval, sem_wait); -__weak_reference(_pthread_fake_inval, sem_trywait); -__weak_reference(_pthread_fake_inval, sem_post); -__weak_reference(_pthread_fake_inval, sem_getvalue); -__weak_reference(_pthread_fake_inval, pthread_setprio); -__weak_reference(_pthread_fake_inval, pthread_setschedparam); -__weak_reference(_pthread_fake_inval, pthread_sigmask); -__weak_reference(_pthread_fake_inval, pthread_single_np); -__weak_reference(_pthread_fake_inval, pthread_key_create); -__weak_reference(_pthread_fake_inval, pthread_key_delete); -__weak_reference(_pthread_fake_inval, pthread_getspecific); -__weak_reference(_pthread_fake_inval, pthread_setspecific); -__weak_reference(_pthread_fake_inval, pthread_suspend_np); -__weak_reference(_pthread_fake_inval, pthread_suspend_all_np);/*XXX void*/ -__weak_reference(_pthread_fake_inval, pthread_switch_add_np); -__weak_reference(_pthread_fake_inval, pthread_switch_delete_np); -__weak_reference(_pthread_fake_inval, sched_yield); -__weak_reference(_pthread_fake_inval, pthread_yield);/*XXX void*/ - -int -_pthread_fake_inval(void) -{ - return EINVAL; -} - -void * -_pthread_fake_null(void) -{ - return NULL; -} - -#endif /* _THREAD_SAFE */ diff --git a/lib/libc/stdlib/malloc.3 b/lib/libc/stdlib/malloc.3 index e4011d9ad5..d30cc559b5 100644 --- a/lib/libc/stdlib/malloc.3 +++ b/lib/libc/stdlib/malloc.3 @@ -265,7 +265,7 @@ and the process will dump core. .Xr alloca 3 , .Xr getpagesize 3 , .Xr memory 3 , -.Xr posix_memalign +.Xr posix_memalign 3 .Sh STANDARDS The .Fn malloc , diff --git a/lib/libc/stdlib/nmalloc.c b/lib/libc/stdlib/nmalloc.c index 2fb05f97bc..faa1e5cc60 100644 --- a/lib/libc/stdlib/nmalloc.c +++ b/lib/libc/stdlib/nmalloc.c @@ -284,7 +284,8 @@ _bigalloc_hash(void *ptr) { int hv; - hv = ((int)ptr >> PAGE_SHIFT) ^ ((int)ptr >> (PAGE_SHIFT + BIGHSHIFT)); + hv = ((int)(intptr_t)ptr >> PAGE_SHIFT) ^ + ((int)(intptr_t)ptr >> (PAGE_SHIFT + BIGHSHIFT)); return(hv); } @@ -458,7 +459,7 @@ posix_memalign(void **memptr, size_t alignment, size_t size) { bigalloc_t *bigp; bigalloc_t big; - int chunking; + size_t chunking; int zi; /* @@ -573,7 +574,7 @@ _slaballoc(size_t size, int flags) slzone_t z; slchunk_t chunk; slglobaldata_t slgd; - int chunking; + size_t chunking; int zi; #ifdef INVARIANTS int i; diff --git a/lib/libc/stdtime/localtime.c b/lib/libc/stdtime/localtime.c index 88cfa5428d..85efeec09b 100644 --- a/lib/libc/stdtime/localtime.c +++ b/lib/libc/stdtime/localtime.c @@ -308,10 +308,13 @@ settzname(void) static int differ_by_repeat(const time_t t1, const time_t t0) { + int_fast64_t _t0 = t0; + int_fast64_t _t1 = t1; + if (TYPE_INTEGRAL(time_t) && TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) return 0; - return t1 - t0 == SECSPERREPEAT; + return _t1 - _t0 == SECSPERREPEAT; } static int diff --git a/lib/libc_r/uthread/uthread_init.c b/lib/libc_r/uthread/uthread_init.c index 7b6bcea470..562014a0da 100644 --- a/lib/libc_r/uthread/uthread_init.c +++ b/lib/libc_r/uthread/uthread_init.c @@ -225,8 +225,8 @@ _thread_init(void) * thread stack that is just beyond. */ if (mmap(_usrstack - PTHREAD_STACK_INITIAL - - PTHREAD_STACK_GUARD, PTHREAD_STACK_GUARD, 0, MAP_ANON, - -1, 0) == MAP_FAILED) + PTHREAD_STACK_GUARD, PTHREAD_STACK_GUARD, 0, + MAP_ANON | MAP_TRYFIXED, -1, 0) == MAP_FAILED) PANIC("Cannot allocate red zone for initial thread"); _thread_initial->tcb = tls_get_tcb(); diff --git a/lib/libfetch/Makefile b/lib/libfetch/Makefile index 6358e62814..ebb99ea4d0 100644 --- a/lib/libfetch/Makefile +++ b/lib/libfetch/Makefile @@ -1,4 +1,4 @@ -# $FreeBSD: src/lib/libfetch/Makefile,v 1.14.2.5 2003/01/09 11:50:32 des Exp $ +# $FreeBSD: src/lib/libfetch/Makefile,v 1.51 2007/12/19 05:10:07 ru Exp $ # $DragonFly: src/lib/libfetch/Makefile,v 1.9 2007/08/05 21:48:12 swildner Exp $ LIB= fetch @@ -19,9 +19,9 @@ LDADD= -lssl -lcrypto SHLIB_MAJOR= 4 -ftperr.h: ftp.errors - @echo "static struct fetcherr _ftp_errlist[] = {" > ${.TARGET} - @cat ${.ALLSRC} \ +ftperr.h: ftp.errors ${.CURDIR}/Makefile + @echo "static struct fetcherr ftp_errlist[] = {" > ${.TARGET} + @cat ${.CURDIR}/ftp.errors \ | grep -v ^# \ | sort \ | while read NUM CAT STRING; do \ @@ -30,9 +30,9 @@ ftperr.h: ftp.errors @echo " { -1, FETCH_UNKNOWN, \"Unknown FTP error\" }" >> ${.TARGET} @echo "};" >> ${.TARGET} -httperr.h: http.errors - @echo "static struct fetcherr _http_errlist[] = {" > ${.TARGET} - @cat ${.ALLSRC} \ +httperr.h: http.errors ${.CURDIR}/Makefile + @echo "static struct fetcherr http_errlist[] = {" > ${.TARGET} + @cat ${.CURDIR}/http.errors \ | grep -v ^# \ | sort \ | while read NUM CAT STRING; do \ diff --git a/lib/libfetch/common.c b/lib/libfetch/common.c index bdd393aae8..9c8c990a52 100644 --- a/lib/libfetch/common.c +++ b/lib/libfetch/common.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/lib/libfetch/common.c,v 1.50 2005/02/16 12:46:46 des Exp $ + * $FreeBSD: src/lib/libfetch/common.c,v 1.56 2008/04/15 23:29:51 cperciva Exp $ * $DragonFly: src/lib/libfetch/common.c,v 1.5 2008/04/02 14:46:37 joerg Exp $ */ @@ -33,8 +33,10 @@ #include #include #include + #include +#include #include #include #include @@ -53,7 +55,7 @@ /* * Error messages for resolver errors */ -static struct fetcherr _netdb_errlist[] = { +static struct fetcherr netdb_errlist[] = { #ifdef EAI_NODATA { EAI_NODATA, FETCH_RESOLV, "Host not found" }, #endif @@ -73,7 +75,7 @@ static const char ENDL[2] = "\r\n"; * Map error code to string */ static struct fetcherr * -_fetch_finderr(struct fetcherr *p, int e) +fetch_finderr(struct fetcherr *p, int e) { while (p->num != -1 && p->num != e) p++; @@ -84,9 +86,9 @@ _fetch_finderr(struct fetcherr *p, int e) * Set error code */ void -_fetch_seterr(struct fetcherr *p, int e) +fetch_seterr(struct fetcherr *p, int e) { - p = _fetch_finderr(p, e); + p = fetch_finderr(p, e); fetchLastErrCode = p->cat; snprintf(fetchLastErrString, MAXERRSTRING, "%s", p->string); } @@ -95,7 +97,7 @@ _fetch_seterr(struct fetcherr *p, int e) * Set error code according to errno */ void -_fetch_syserr(void) +fetch_syserr(void) { switch (errno) { case 0: @@ -155,7 +157,7 @@ default: * Emit status message */ void -_fetch_info(const char *fmt, ...) +fetch_info(const char *fmt, ...) { va_list ap; @@ -172,7 +174,7 @@ _fetch_info(const char *fmt, ...) * Return the default port for a scheme */ int -_fetch_default_port(const char *scheme) +fetch_default_port(const char *scheme) { struct servent *se; @@ -189,7 +191,7 @@ _fetch_default_port(const char *scheme) * Return the default proxy port for a scheme */ int -_fetch_default_proxy_port(const char *scheme) +fetch_default_proxy_port(const char *scheme) { if (strcasecmp(scheme, SCHEME_FTP) == 0) return (FTP_DEFAULT_PROXY_PORT); @@ -203,7 +205,7 @@ _fetch_default_proxy_port(const char *scheme) * Create a connection for an existing descriptor. */ conn_t * -_fetch_reopen(int sd) +fetch_reopen(int sd) { conn_t *conn; @@ -220,7 +222,7 @@ _fetch_reopen(int sd) * Bump a connection's reference count. */ conn_t * -_fetch_ref(conn_t *conn) +fetch_ref(conn_t *conn) { ++conn->ref; @@ -232,7 +234,7 @@ _fetch_ref(conn_t *conn) * Bind a socket to a specific local address */ int -_fetch_bind(int sd, int af, const char *addr) +fetch_bind(int sd, int af, const char *addr) { struct addrinfo hints, *res, *res0; int err; @@ -254,7 +256,7 @@ _fetch_bind(int sd, int af, const char *addr) * Establish a TCP connection to the specified port on the specified host. */ conn_t * -_fetch_connect(const char *host, int port, int af, int verbose) +fetch_connect(const char *host, int port, int af, int verbose) { conn_t *conn; char pbuf[10]; @@ -265,7 +267,7 @@ _fetch_connect(const char *host, int port, int af, int verbose) DEBUG(fprintf(stderr, "---> %s:%d\n", host, port)); if (verbose) - _fetch_info("looking up %s", host); + fetch_info("looking up %s", host); /* look up host name and set up socket address structure */ snprintf(pbuf, sizeof(pbuf), "%d", port); @@ -274,13 +276,13 @@ _fetch_connect(const char *host, int port, int af, int verbose) hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; if ((err = getaddrinfo(host, pbuf, &hints, &res0)) != 0) { - _netdb_seterr(err); + netdb_seterr(err); return (NULL); } bindaddr = getenv("FETCH_BIND_ADDRESS"); if (verbose) - _fetch_info("connecting to %s:%d", host, port); + fetch_info("connecting to %s:%d", host, port); /* try to connect */ for (sd = -1, res = res0; res; sd = -1, res = res->ai_next) { @@ -288,8 +290,8 @@ _fetch_connect(const char *host, int port, int af, int verbose) res->ai_protocol)) == -1) continue; if (bindaddr != NULL && *bindaddr != '\0' && - _fetch_bind(sd, res->ai_family, bindaddr) != 0) { - _fetch_info("failed to bind to '%s'", bindaddr); + fetch_bind(sd, res->ai_family, bindaddr) != 0) { + fetch_info("failed to bind to '%s'", bindaddr); close(sd); continue; } @@ -299,12 +301,12 @@ _fetch_connect(const char *host, int port, int af, int verbose) } freeaddrinfo(res0); if (sd == -1) { - _fetch_syserr(); + fetch_syserr(); return (NULL); } - if ((conn = _fetch_reopen(sd)) == NULL) { - _fetch_syserr(); + if ((conn = fetch_reopen(sd)) == NULL) { + fetch_syserr(); close(sd); } return (conn); @@ -315,7 +317,7 @@ _fetch_connect(const char *host, int port, int af, int verbose) * Enable SSL on a connection. */ int -_fetch_ssl(conn_t *conn, int verbose) +fetch_ssl(conn_t *conn, int verbose) { #ifdef WITH_SSL @@ -373,9 +375,9 @@ _fetch_ssl(conn_t *conn, int verbose) * Read a character from a connection w/ timeout */ ssize_t -_fetch_read(conn_t *conn, char *buf, size_t len) +fetch_read(conn_t *conn, char *buf, size_t len) { - struct timeval now, timeout, wait; + struct timeval now, timeout, delta; fd_set readfds; ssize_t rlen, total; int r; @@ -391,23 +393,23 @@ _fetch_read(conn_t *conn, char *buf, size_t len) while (fetchTimeout && !FD_ISSET(conn->sd, &readfds)) { FD_SET(conn->sd, &readfds); gettimeofday(&now, NULL); - wait.tv_sec = timeout.tv_sec - now.tv_sec; - wait.tv_usec = timeout.tv_usec - now.tv_usec; - if (wait.tv_usec < 0) { - wait.tv_usec += 1000000; - wait.tv_sec--; + delta.tv_sec = timeout.tv_sec - now.tv_sec; + delta.tv_usec = timeout.tv_usec - now.tv_usec; + if (delta.tv_usec < 0) { + delta.tv_usec += 1000000; + delta.tv_sec--; } - if (wait.tv_sec < 0) { + if (delta.tv_sec < 0) { errno = ETIMEDOUT; - _fetch_syserr(); + fetch_syserr(); return (-1); } errno = 0; - r = select(conn->sd + 1, &readfds, NULL, NULL, &wait); + r = select(conn->sd + 1, &readfds, NULL, NULL, &delta); if (r == -1) { if (errno == EINTR && fetchRestartCalls) continue; - _fetch_syserr(); + fetch_syserr(); return (-1); } } @@ -438,7 +440,7 @@ _fetch_read(conn_t *conn, char *buf, size_t len) #define MIN_BUF_SIZE 1024 int -_fetch_getln(conn_t *conn) +fetch_getln(conn_t *conn) { char *tmp; size_t tmpsize; @@ -457,7 +459,7 @@ _fetch_getln(conn_t *conn) conn->buflen = 0; do { - len = _fetch_read(conn, &c, 1); + len = fetch_read(conn, &c, 1); if (len == -1) return (-1); if (len == 0) @@ -485,13 +487,13 @@ _fetch_getln(conn_t *conn) * Write to a connection w/ timeout */ ssize_t -_fetch_write(conn_t *conn, const char *buf, size_t len) +fetch_write(conn_t *conn, const char *buf, size_t len) { struct iovec iov; iov.iov_base = __DECONST(char *, buf); iov.iov_len = len; - return _fetch_writev(conn, &iov, 1); + return fetch_writev(conn, &iov, 1); } /* @@ -499,9 +501,9 @@ _fetch_write(conn_t *conn, const char *buf, size_t len) * Note: can modify the iovec. */ ssize_t -_fetch_writev(conn_t *conn, struct iovec *iov, int iovcnt) +fetch_writev(conn_t *conn, struct iovec *iov, int iovcnt) { - struct timeval now, timeout, wait; + struct timeval now, timeout, delta; fd_set writefds; ssize_t wlen, total; int r; @@ -517,19 +519,19 @@ _fetch_writev(conn_t *conn, struct iovec *iov, int iovcnt) while (fetchTimeout && !FD_ISSET(conn->sd, &writefds)) { FD_SET(conn->sd, &writefds); gettimeofday(&now, NULL); - wait.tv_sec = timeout.tv_sec - now.tv_sec; - wait.tv_usec = timeout.tv_usec - now.tv_usec; - if (wait.tv_usec < 0) { - wait.tv_usec += 1000000; - wait.tv_sec--; + delta.tv_sec = timeout.tv_sec - now.tv_sec; + delta.tv_usec = timeout.tv_usec - now.tv_usec; + if (delta.tv_usec < 0) { + delta.tv_usec += 1000000; + delta.tv_sec--; } - if (wait.tv_sec < 0) { + if (delta.tv_sec < 0) { errno = ETIMEDOUT; - _fetch_syserr(); + fetch_syserr(); return (-1); } errno = 0; - r = select(conn->sd + 1, NULL, &writefds, NULL, &wait); + r = select(conn->sd + 1, NULL, &writefds, NULL, &delta); if (r == -1) { if (errno == EINTR && fetchRestartCalls) continue; @@ -547,7 +549,7 @@ _fetch_writev(conn_t *conn, struct iovec *iov, int iovcnt) if (wlen == 0) { /* we consider a short write a failure */ errno = EPIPE; - _fetch_syserr(); + fetch_syserr(); return (-1); } if (wlen < 0) { @@ -574,7 +576,7 @@ _fetch_writev(conn_t *conn, struct iovec *iov, int iovcnt) * Write a line of text to a connection w/ timeout */ int -_fetch_putln(conn_t *conn, const char *str, size_t len) +fetch_putln(conn_t *conn, const char *str, size_t len) { struct iovec iov[2]; int ret; @@ -585,9 +587,9 @@ _fetch_putln(conn_t *conn, const char *str, size_t len) iov[1].iov_base = __DECONST(char *, ENDL); iov[1].iov_len = sizeof(ENDL); if (len == 0) - ret = _fetch_writev(conn, &iov[1], 1); + ret = fetch_writev(conn, &iov[1], 1); else - ret = _fetch_writev(conn, iov, 2); + ret = fetch_writev(conn, iov, 2); if (ret == -1) return (-1); return (0); @@ -598,7 +600,7 @@ _fetch_putln(conn_t *conn, const char *str, size_t len) * Close connection */ int -_fetch_close(conn_t *conn) +fetch_close(conn_t *conn) { int ret; @@ -614,7 +616,7 @@ _fetch_close(conn_t *conn) /*** Directory-related utility functions *************************************/ int -_fetch_add_entry(struct url_ent **p, int *size, int *len, +fetch_add_entry(struct url_ent **p, int *size, int *len, const char *name, struct url_stat *us) { struct url_ent *tmp; @@ -628,7 +630,7 @@ _fetch_add_entry(struct url_ent **p, int *size, int *len, tmp = realloc(*p, (*size * 2 + 1) * sizeof(**p)); if (tmp == NULL) { errno = ENOMEM; - _fetch_syserr(); + fetch_syserr(); return (-1); } *size = (*size * 2 + 1); @@ -637,7 +639,7 @@ _fetch_add_entry(struct url_ent **p, int *size, int *len, tmp = *p + *len; snprintf(tmp->name, PATH_MAX, "%s", name); - bcopy(us, &tmp->stat, sizeof(*us)); + memcpy(&tmp->stat, us, sizeof(*us)); (*len)++; (++tmp)->name[0] = 0; @@ -649,7 +651,7 @@ _fetch_add_entry(struct url_ent **p, int *size, int *len, /*** Authentication-related utility functions ********************************/ static const char * -_fetch_read_word(FILE *f) +fetch_read_word(FILE *f) { static char word[1024]; @@ -662,7 +664,7 @@ _fetch_read_word(FILE *f) * Get authentication data for a URL from .netrc */ int -_fetch_netrc_auth(struct url *url) +fetch_netrc_auth(struct url *url) { char fn[PATH_MAX]; const char *word; @@ -671,7 +673,7 @@ _fetch_netrc_auth(struct url *url) if ((p = getenv("NETRC")) != NULL) { if (snprintf(fn, sizeof(fn), "%s", p) >= (int)sizeof(fn)) { - _fetch_info("$NETRC specifies a file name " + fetch_info("$NETRC specifies a file name " "longer than PATH_MAX"); return (-1); } @@ -689,39 +691,39 @@ _fetch_netrc_auth(struct url *url) if ((f = fopen(fn, "r")) == NULL) return (-1); - while ((word = _fetch_read_word(f)) != NULL) { + while ((word = fetch_read_word(f)) != NULL) { if (strcmp(word, "default") == 0) { - DEBUG(_fetch_info("Using default .netrc settings")); + DEBUG(fetch_info("Using default .netrc settings")); break; } if (strcmp(word, "machine") == 0 && - (word = _fetch_read_word(f)) != NULL && + (word = fetch_read_word(f)) != NULL && strcasecmp(word, url->host) == 0) { - DEBUG(_fetch_info("Using .netrc settings for %s", word)); + DEBUG(fetch_info("Using .netrc settings for %s", word)); break; } } if (word == NULL) goto ferr; - while ((word = _fetch_read_word(f)) != NULL) { + while ((word = fetch_read_word(f)) != NULL) { if (strcmp(word, "login") == 0) { - if ((word = _fetch_read_word(f)) == NULL) + if ((word = fetch_read_word(f)) == NULL) goto ferr; if (snprintf(url->user, sizeof(url->user), "%s", word) > (int)sizeof(url->user)) { - _fetch_info("login name in .netrc is too long"); + fetch_info("login name in .netrc is too long"); url->user[0] = '\0'; } } else if (strcmp(word, "password") == 0) { - if ((word = _fetch_read_word(f)) == NULL) + if ((word = fetch_read_word(f)) == NULL) goto ferr; if (snprintf(url->pwd, sizeof(url->pwd), "%s", word) > (int)sizeof(url->pwd)) { - _fetch_info("password in .netrc is too long"); + fetch_info("password in .netrc is too long"); url->pwd[0] = '\0'; } } else if (strcmp(word, "account") == 0) { - if ((word = _fetch_read_word(f)) == NULL) + if ((word = fetch_read_word(f)) == NULL) goto ferr; /* XXX not supported! */ } else { @@ -734,3 +736,51 @@ _fetch_netrc_auth(struct url *url) fclose(f); return (-1); } + +/* + * The no_proxy environment variable specifies a set of domains for + * which the proxy should not be consulted; the contents is a comma-, + * or space-separated list of domain names. A single asterisk will + * override all proxy variables and no transactions will be proxied + * (for compatability with lynx and curl, see the discussion at + * ). + */ +int +fetch_no_proxy_match(const char *host) +{ + const char *no_proxy, *p, *q; + size_t h_len, d_len; + + if ((no_proxy = getenv("NO_PROXY")) == NULL && + (no_proxy = getenv("no_proxy")) == NULL) + return (0); + + /* asterisk matches any hostname */ + if (strcmp(no_proxy, "*") == 0) + return (1); + + h_len = strlen(host); + p = no_proxy; + do { + /* position p at the beginning of a domain suffix */ + while (*p == ',' || isspace((unsigned char)*p)) + p++; + + /* position q at the first separator character */ + for (q = p; *q; ++q) + if (*q == ',' || isspace((unsigned char)*q)) + break; + + d_len = q - p; + if (d_len > 0 && h_len > d_len && + strncasecmp(host + h_len - d_len, + p, d_len) == 0) { + /* domain name matches */ + return (1); + } + + p = q + 1; + } while (*q); + + return (0); +} diff --git a/lib/libfetch/common.h b/lib/libfetch/common.h index 4561a86fdc..21032a786c 100644 --- a/lib/libfetch/common.h +++ b/lib/libfetch/common.h @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/lib/libfetch/common.h,v 1.28 2004/09/21 18:35:20 des Exp $ + * $FreeBSD: src/lib/libfetch/common.h,v 1.30 2007/12/18 11:03:07 des Exp $ * $DragonFly: src/lib/libfetch/common.h,v 1.3 2007/08/05 21:48:12 swildner Exp $ */ @@ -69,33 +69,34 @@ struct fetcherr { const char *string; }; -/* for _fetch_writev */ +/* for fetch_writev */ struct iovec; -void _fetch_seterr(struct fetcherr *, int); -void _fetch_syserr(void); -void _fetch_info(const char *, ...); -int _fetch_default_port(const char *); -int _fetch_default_proxy_port(const char *); -int _fetch_bind(int, int, const char *); -conn_t *_fetch_connect(const char *, int, int, int); -conn_t *_fetch_reopen(int); -conn_t *_fetch_ref(conn_t *); -int _fetch_ssl(conn_t *, int); -ssize_t _fetch_read(conn_t *, char *, size_t); -int _fetch_getln(conn_t *); -ssize_t _fetch_write(conn_t *, const char *, size_t); -ssize_t _fetch_writev(conn_t *, struct iovec *, int); -int _fetch_putln(conn_t *, const char *, size_t); -int _fetch_close(conn_t *); -int _fetch_add_entry(struct url_ent **, int *, int *, +void fetch_seterr(struct fetcherr *, int); +void fetch_syserr(void); +void fetch_info(const char *, ...); +int fetch_default_port(const char *); +int fetch_default_proxy_port(const char *); +int fetch_bind(int, int, const char *); +conn_t *fetch_connect(const char *, int, int, int); +conn_t *fetch_reopen(int); +conn_t *fetch_ref(conn_t *); +int fetch_ssl(conn_t *, int); +ssize_t fetch_read(conn_t *, char *, size_t); +int fetch_getln(conn_t *); +ssize_t fetch_write(conn_t *, const char *, size_t); +ssize_t fetch_writev(conn_t *, struct iovec *, int); +int fetch_putln(conn_t *, const char *, size_t); +int fetch_close(conn_t *); +int fetch_add_entry(struct url_ent **, int *, int *, const char *, struct url_stat *); -int _fetch_netrc_auth(struct url *url); +int fetch_netrc_auth(struct url *url); +int fetch_no_proxy_match(const char *); -#define _ftp_seterr(n) _fetch_seterr(_ftp_errlist, n) -#define _http_seterr(n) _fetch_seterr(_http_errlist, n) -#define _netdb_seterr(n) _fetch_seterr(_netdb_errlist, n) -#define _url_seterr(n) _fetch_seterr(_url_errlist, n) +#define ftp_seterr(n) fetch_seterr(ftp_errlist, n) +#define http_seterr(n) fetch_seterr(http_errlist, n) +#define netdb_seterr(n) fetch_seterr(netdb_errlist, n) +#define url_seterr(n) fetch_seterr(url_errlist, n) #ifndef NDEBUG #define DEBUG(x) do { if (fetchDebug) { x; } } while (0) @@ -104,7 +105,7 @@ int _fetch_netrc_auth(struct url *url); #endif /* - * I don't really like exporting _http_request() and _ftp_request(), + * I don't really like exporting http_request() and ftp_request(), * but the HTTP and FTP code occasionally needs to cross-call * eachother, and this saves me from adding a lot of special-case code * to handle those cases. @@ -112,9 +113,9 @@ int _fetch_netrc_auth(struct url *url); * Note that _*_request() free purl, which is way ugly but saves us a * whole lot of trouble. */ -FILE *_http_request(struct url *, const char *, +FILE *http_request(struct url *, const char *, struct url_stat *, struct url *, const char *); -FILE *_ftp_request(struct url *, const char *, +FILE *ftp_request(struct url *, const char *, struct url_stat *, struct url *, const char *); /* diff --git a/lib/libfetch/fetch.3 b/lib/libfetch/fetch.3 index 35813d7413..6d412b5905 100644 --- a/lib/libfetch/fetch.3 +++ b/lib/libfetch/fetch.3 @@ -1,4 +1,5 @@ -.\" Copyright (c) 1998 Dag-Erling Coïdan Smørgrav +.\"- +.\" Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -22,10 +23,10 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/lib/libfetch/fetch.3,v 1.63 2007/05/24 20:28:14 des Exp $ +.\" $FreeBSD: src/lib/libfetch/fetch.3,v 1.66 2008/12/15 08:27:44 murray Exp $ .\" $DragonFly: src/lib/libfetch/fetch.3,v 1.5 2007/11/23 23:16:36 swildner Exp $ .\" -.Dd July 1, 1998 +.Dd May 10, 2009 .Dt FETCH 3 .Os .Sh NAME @@ -165,9 +166,16 @@ struct url { char *doc; off_t offset; size_t length; + time_t ims_time; }; .Ed .Pp +The +.Va ims_time +field stores the time value for +.Li If-Modified-Since +HTTP requests. +.Pp The pointer returned by .Fn fetchMakeURL or @@ -236,7 +244,7 @@ structure is defined as follows in .In fetch.h : .Bd -literal struct url_ent { - char name[MAXPATHLEN]; + char name[PATH_MAX]; struct url_stat stat; }; .Ed @@ -353,6 +361,22 @@ and .Fn fetchPutHTTP will use a direct connection even if a proxy server is defined. .Pp +If the +.Ql i +(if-modified-since) flag is specified, and +the +.Va ims_time +field is set in +.Vt "struct url" , +then +.Fn fetchXGetHTTP +and +.Fn fetchGetHTTP +will send a conditional +.Li If-Modified-Since +HTTP header to only fetch the content if it is newer than +.Va ims_time . +.Pp Since there seems to be no good way of implementing the HTTP PUT method in a manner consistent with the rest of the .Nm fetch @@ -532,6 +556,14 @@ See .Xr ftp 1 for a description of the file format. This feature is experimental. +.It Ev NO_PROXY +Either a single asterisk, which disables the use of proxies +altogether, or a comma- or whitespace-separated list of hosts for +which proxies should not be used. +.It Ev no_proxy +Same as +.Ev NO_PROXY , +for compatibility. .El .Sh EXAMPLES To access a proxy server on @@ -555,6 +587,14 @@ environment variable: HTTP_PROXY=http://proxy.example.com:8080 HTTP_PROXY_AUTH=basic:*:: .Ed +.Pp +To disable the use of a proxy for an HTTP server running on the local +host, define +.Ev NO_PROXY +as follows: +.Bd -literal -offset indent +NO_PROXY=localhost,127.0.0.1 +.Ed .Sh SEE ALSO .Xr fetch 1 , .Xr ftpio 3 , @@ -631,7 +671,7 @@ and .An Jordan K. Hubbard Aq jkh@FreeBSD.org . .Pp This manual page was written by -.An Dag-Erling Co\(:idan Sm\(/orgrav Aq des@FreeBSD.org . +.An Dag-Erling Sm\(/orgrav Aq des@FreeBSD.org . .Sh BUGS Some parts of the library are not yet implemented. The most notable diff --git a/lib/libfetch/fetch.c b/lib/libfetch/fetch.c index 1b5754d232..3f06c7eb0e 100644 --- a/lib/libfetch/fetch.c +++ b/lib/libfetch/fetch.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/lib/libfetch/fetch.c,v 1.38 2004/09/21 18:35:20 des Exp $ + * $FreeBSD: src/lib/libfetch/fetch.c,v 1.42 2008/12/17 18:00:18 murray Exp $ * $DragonFly: src/lib/libfetch/fetch.c,v 1.3 2007/08/05 21:48:12 swildner Exp $ */ @@ -56,7 +56,7 @@ int fetchDebug; #define URL_MALFORMED 1 #define URL_BAD_SCHEME 2 #define URL_BAD_PORT 3 -static struct fetcherr _url_errlist[] = { +static struct fetcherr url_errlist[] = { { URL_MALFORMED, FETCH_URL, "Malformed URL" }, { URL_BAD_SCHEME, FETCH_URL, "Invalid URL scheme" }, { URL_BAD_PORT, FETCH_URL, "Invalid server port" }, @@ -74,9 +74,7 @@ static struct fetcherr _url_errlist[] = { FILE * fetchXGet(struct url *URL, struct url_stat *us, const char *flags) { - int direct; - direct = CHECK_FLAG('d'); if (us != NULL) { us->size = -1; us->atime = us->mtime = 0; @@ -89,7 +87,7 @@ fetchXGet(struct url *URL, struct url_stat *us, const char *flags) return (fetchXGetHTTP(URL, us, flags)); else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0) return (fetchXGetHTTP(URL, us, flags)); - _url_seterr(URL_BAD_SCHEME); + url_seterr(URL_BAD_SCHEME); return (NULL); } @@ -110,9 +108,7 @@ fetchGet(struct url *URL, const char *flags) FILE * fetchPut(struct url *URL, const char *flags) { - int direct; - direct = CHECK_FLAG('d'); if (strcasecmp(URL->scheme, SCHEME_FILE) == 0) return (fetchPutFile(URL, flags)); else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0) @@ -121,7 +117,7 @@ fetchPut(struct url *URL, const char *flags) return (fetchPutHTTP(URL, flags)); else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0) return (fetchPutHTTP(URL, flags)); - _url_seterr(URL_BAD_SCHEME); + url_seterr(URL_BAD_SCHEME); return (NULL); } @@ -132,9 +128,7 @@ fetchPut(struct url *URL, const char *flags) int fetchStat(struct url *URL, struct url_stat *us, const char *flags) { - int direct; - direct = CHECK_FLAG('d'); if (us != NULL) { us->size = -1; us->atime = us->mtime = 0; @@ -147,7 +141,7 @@ fetchStat(struct url *URL, struct url_stat *us, const char *flags) return (fetchStatHTTP(URL, us, flags)); else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0) return (fetchStatHTTP(URL, us, flags)); - _url_seterr(URL_BAD_SCHEME); + url_seterr(URL_BAD_SCHEME); return (-1); } @@ -158,9 +152,7 @@ fetchStat(struct url *URL, struct url_stat *us, const char *flags) struct url_ent * fetchList(struct url *URL, const char *flags) { - int direct; - direct = CHECK_FLAG('d'); if (strcasecmp(URL->scheme, SCHEME_FILE) == 0) return (fetchListFile(URL, flags)); else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0) @@ -169,7 +161,7 @@ fetchList(struct url *URL, const char *flags) return (fetchListHTTP(URL, flags)); else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0) return (fetchListHTTP(URL, flags)); - _url_seterr(URL_BAD_SCHEME); + url_seterr(URL_BAD_SCHEME); return (NULL); } @@ -264,23 +256,23 @@ fetchMakeURL(const char *scheme, const char *host, int port, const char *doc, struct url *u; if (!scheme || (!host && !doc)) { - _url_seterr(URL_MALFORMED); + url_seterr(URL_MALFORMED); return (NULL); } if (port < 0 || port > 65535) { - _url_seterr(URL_BAD_PORT); + url_seterr(URL_BAD_PORT); return (NULL); } /* allocate struct url */ if ((u = calloc(1, sizeof(*u))) == NULL) { - _fetch_syserr(); + fetch_syserr(); return (NULL); } if ((u->doc = strdup(doc ? doc : "/")) == NULL) { - _fetch_syserr(); + fetch_syserr(); free(u); return (NULL); } @@ -311,7 +303,7 @@ fetchParseURL(const char *URL) /* allocate struct url */ if ((u = calloc(1, sizeof(*u))) == NULL) { - _fetch_syserr(); + fetch_syserr(); return (NULL); } @@ -369,11 +361,11 @@ fetchParseURL(const char *URL) /* port */ if (*p == ':') { for (q = ++p; *q && (*q != '/'); q++) - if (isdigit(*q)) + if (isdigit((unsigned char)*q)) u->port = u->port * 10 + (*q - '0'); else { /* invalid port */ - _url_seterr(URL_BAD_PORT); + url_seterr(URL_BAD_PORT); goto ouch; } p = q; @@ -390,12 +382,12 @@ nohost: /* percent-escape whitespace. */ if ((doc = malloc(strlen(p) * 3 + 1)) == NULL) { - _fetch_syserr(); + fetch_syserr(); goto ouch; } u->doc = doc; while (*p != '\0') { - if (!isspace(*p)) { + if (!isspace((unsigned char)*p)) { *doc++ = *p++; } else { *doc++ = '%'; @@ -406,7 +398,7 @@ nohost: } *doc = '\0'; } else if ((u->doc = strdup(p)) == NULL) { - _fetch_syserr(); + fetch_syserr(); goto ouch; } diff --git a/lib/libfetch/fetch.h b/lib/libfetch/fetch.h index 6fc5af23d2..193922c1e1 100644 --- a/lib/libfetch/fetch.h +++ b/lib/libfetch/fetch.h @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/lib/libfetch/fetch.h,v 1.26 2004/09/21 18:35:20 des Exp $ + * $FreeBSD: src/lib/libfetch/fetch.h,v 1.27 2008/12/15 08:27:44 murray Exp $ * $DragonFly: src/lib/libfetch/fetch.h,v 1.3 2007/08/05 21:48:12 swildner Exp $ */ @@ -47,6 +47,7 @@ struct url { char *doc; off_t offset; size_t length; + time_t ims_time; }; struct url_stat { diff --git a/lib/libfetch/file.c b/lib/libfetch/file.c index ed955ad320..35b111e2cc 100644 --- a/lib/libfetch/file.c +++ b/lib/libfetch/file.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/lib/libfetch/file.c,v 1.17 2004/09/21 18:35:20 des Exp $ + * $FreeBSD: src/lib/libfetch/file.c,v 1.18 2007/12/14 10:26:58 des Exp $ * $DragonFly: src/lib/libfetch/file.c,v 1.3 2007/08/05 21:48:12 swildner Exp $ */ @@ -50,11 +50,11 @@ fetchXGetFile(struct url *u, struct url_stat *us, const char *flags) f = fopen(u->doc, "r"); if (f == NULL) - _fetch_syserr(); + fetch_syserr(); if (u->offset && fseeko(f, u->offset, SEEK_SET) == -1) { fclose(f); - _fetch_syserr(); + fetch_syserr(); } return (f); @@ -77,25 +77,25 @@ fetchPutFile(struct url *u, const char *flags) f = fopen(u->doc, "w+"); if (f == NULL) - _fetch_syserr(); + fetch_syserr(); if (u->offset && fseeko(f, u->offset, SEEK_SET) == -1) { fclose(f); - _fetch_syserr(); + fetch_syserr(); } return (f); } static int -_fetch_stat_file(const char *fn, struct url_stat *us) +fetch_stat_file(const char *fn, struct url_stat *us) { struct stat sb; us->size = -1; us->atime = us->mtime = 0; if (stat(fn, &sb) == -1) { - _fetch_syserr(); + fetch_syserr(); return (-1); } us->size = sb.st_size; @@ -107,7 +107,7 @@ _fetch_stat_file(const char *fn, struct url_stat *us) int fetchStatFile(struct url *u, struct url_stat *us, const char *flags __unused) { - return (_fetch_stat_file(u->doc, us)); + return (fetch_stat_file(u->doc, us)); } struct url_ent * @@ -122,7 +122,7 @@ fetchListFile(struct url *u, const char *flags __unused) int l; if ((dir = opendir(u->doc)) == NULL) { - _fetch_syserr(); + fetch_syserr(); return (NULL); } @@ -136,10 +136,10 @@ fetchListFile(struct url *u, const char *flags __unused) while ((de = readdir(dir)) != NULL) { strncpy(p, de->d_name, l - 1); p[l - 1] = 0; - if (_fetch_stat_file(fn, &us) == -1) + if (fetch_stat_file(fn, &us) == -1) /* should I return a partial result, or abort? */ break; - _fetch_add_entry(&ue, &size, &len, de->d_name, &us); + fetch_add_entry(&ue, &size, &len, de->d_name, &us); } return (ue); diff --git a/lib/libfetch/ftp.c b/lib/libfetch/ftp.c index 0fa3b2dbbf..bf439d039c 100644 --- a/lib/libfetch/ftp.c +++ b/lib/libfetch/ftp.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/lib/libfetch/ftp.c,v 1.96 2007/04/22 22:33:29 njl Exp $ + * $FreeBSD: src/lib/libfetch/ftp.c,v 1.102 2008/02/08 09:48:48 des Exp $ * $DragonFly: src/lib/libfetch/ftp.c,v 1.4 2007/08/05 21:48:12 swildner Exp $ */ @@ -102,11 +102,16 @@ static struct url cached_host; static conn_t *cached_connection; -#define isftpreply(foo) (isdigit(foo[0]) && isdigit(foo[1]) \ - && isdigit(foo[2]) \ - && (foo[3] == ' ' || foo[3] == '\0')) -#define isftpinfo(foo) (isdigit(foo[0]) && isdigit(foo[1]) \ - && isdigit(foo[2]) && foo[3] == '-') +#define isftpreply(foo) \ + (isdigit((unsigned char)foo[0]) && \ + isdigit((unsigned char)foo[1]) && \ + isdigit((unsigned char)foo[2]) && \ + (foo[3] == ' ' || foo[3] == '\0')) +#define isftpinfo(foo) \ + (isdigit((unsigned char)foo[0]) && \ + isdigit((unsigned char)foo[1]) && \ + isdigit((unsigned char)foo[2]) && \ + foo[3] == '-') /* * Translate IPv4 mapped IPv6 address to IPv4 address @@ -135,27 +140,28 @@ unmappedaddr(struct sockaddr_in6 *sin6) * Get server response */ static int -_ftp_chkerr(conn_t *conn) +ftp_chkerr(conn_t *conn) { - if (_fetch_getln(conn) == -1) { - _fetch_syserr(); + if (fetch_getln(conn) == -1) { + fetch_syserr(); return (-1); } if (isftpinfo(conn->buf)) { while (conn->buflen && !isftpreply(conn->buf)) { - if (_fetch_getln(conn) == -1) { - _fetch_syserr(); + if (fetch_getln(conn) == -1) { + fetch_syserr(); return (-1); } } } - while (conn->buflen && isspace(conn->buf[conn->buflen - 1])) + while (conn->buflen && + isspace((unsigned char)conn->buf[conn->buflen - 1])) conn->buflen--; conn->buf[conn->buflen] = '\0'; if (!isftpreply(conn->buf)) { - _ftp_seterr(FTP_PROTOCOL_ERROR); + ftp_seterr(FTP_PROTOCOL_ERROR); return (-1); } @@ -170,7 +176,7 @@ _ftp_chkerr(conn_t *conn) * Send a command and check reply */ static int -_ftp_cmd(conn_t *conn, const char *fmt, ...) +ftp_cmd(conn_t *conn, const char *fmt, ...) { va_list ap; size_t len; @@ -183,26 +189,26 @@ _ftp_cmd(conn_t *conn, const char *fmt, ...) if (msg == NULL) { errno = ENOMEM; - _fetch_syserr(); + fetch_syserr(); return (-1); } - r = _fetch_putln(conn, msg, len); + r = fetch_putln(conn, msg, len); free(msg); if (r == -1) { - _fetch_syserr(); + fetch_syserr(); return (-1); } - return (_ftp_chkerr(conn)); + return (ftp_chkerr(conn)); } /* * Return a pointer to the filename part of a path */ static const char * -_ftp_filename(const char *file, int *len, int *type) +ftp_filename(const char *file, int *len, int *type) { const char *s; @@ -225,7 +231,7 @@ _ftp_filename(const char *file, int *len, int *type) * command. */ static int -_ftp_pwd(conn_t *conn, char *pwd, size_t pwdlen) +ftp_pwd(conn_t *conn, char *pwd, size_t pwdlen) { char *src, *dst, *end; int q; @@ -261,7 +267,7 @@ _ftp_pwd(conn_t *conn, char *pwd, size_t pwdlen) * file. */ static int -_ftp_cwd(conn_t *conn, const char *file) +ftp_cwd(conn_t *conn, const char *file) { const char *beg, *end; char pwd[PATH_MAX]; @@ -270,9 +276,9 @@ _ftp_cwd(conn_t *conn, const char *file) /* If no slashes in name, no need to change dirs. */ if ((end = strrchr(file, '/')) == NULL) return (0); - if ((e = _ftp_cmd(conn, "PWD")) != FTP_WORKING_DIRECTORY || - (e = _ftp_pwd(conn, pwd, sizeof(pwd))) != FTP_OK) { - _ftp_seterr(e); + if ((e = ftp_cmd(conn, "PWD")) != FTP_WORKING_DIRECTORY || + (e = ftp_pwd(conn, pwd, sizeof(pwd))) != FTP_OK) { + ftp_seterr(e); return (-1); } for (;;) { @@ -289,10 +295,10 @@ _ftp_cwd(conn_t *conn, const char *file) /* Keep going up a dir until we have a matching prefix. */ if (pwd[i] == '\0' && (file[i - 1] == '/' || file[i] == '/')) break; - if ((e = _ftp_cmd(conn, "CDUP")) != FTP_FILE_ACTION_OK || - (e = _ftp_cmd(conn, "PWD")) != FTP_WORKING_DIRECTORY || - (e = _ftp_pwd(conn, pwd, sizeof(pwd))) != FTP_OK) { - _ftp_seterr(e); + if ((e = ftp_cmd(conn, "CDUP")) != FTP_FILE_ACTION_OK || + (e = ftp_cmd(conn, "PWD")) != FTP_WORKING_DIRECTORY || + (e = ftp_pwd(conn, pwd, sizeof(pwd))) != FTP_OK) { + ftp_seterr(e); return (-1); } } @@ -307,7 +313,7 @@ _ftp_cwd(conn_t *conn, const char *file) return (0); /* Change to the directory all in one chunk (e.g., foo/bar/baz). */ - e = _ftp_cmd(conn, "CWD %.*s", (int)(end - beg), beg); + e = ftp_cmd(conn, "CWD %.*s", (int)(end - beg), beg); if (e == FTP_FILE_ACTION_OK) return (0); #endif /* FTP_COMBINE_CWDS */ @@ -318,9 +324,9 @@ _ftp_cwd(conn_t *conn, const char *file) ++beg, ++i; for (++i; file + i < end && file[i] != '/'; ++i) /* nothing */ ; - e = _ftp_cmd(conn, "CWD %.*s", file + i - beg, beg); + e = ftp_cmd(conn, "CWD %.*s", file + i - beg, beg); if (e != FTP_FILE_ACTION_OK) { - _ftp_seterr(e); + ftp_seterr(e); return (-1); } } @@ -331,7 +337,7 @@ _ftp_cwd(conn_t *conn, const char *file) * Set transfer mode and data type */ static int -_ftp_mode_type(conn_t *conn, int mode, int type) +ftp_mode_type(conn_t *conn, int mode, int type) { int e; @@ -344,7 +350,7 @@ _ftp_mode_type(conn_t *conn, int mode, int type) default: return (FTP_PROTOCOL_ERROR); } - if ((e = _ftp_cmd(conn, "MODE %c", mode)) != FTP_OK) { + if ((e = ftp_cmd(conn, "MODE %c", mode)) != FTP_OK) { if (mode == 'S') { /* * Stream mode is supposed to be the default - so @@ -380,7 +386,7 @@ _ftp_mode_type(conn_t *conn, int mode, int type) default: return (FTP_PROTOCOL_ERROR); } - if ((e = _ftp_cmd(conn, "TYPE %c", type)) != FTP_OK) + if ((e = ftp_cmd(conn, "TYPE %c", type)) != FTP_OK) return (e); return (FTP_OK); @@ -390,7 +396,7 @@ _ftp_mode_type(conn_t *conn, int mode, int type) * Request and parse file stats */ static int -_ftp_stat(conn_t *conn, const char *file, struct url_stat *us) +ftp_stat(conn_t *conn, const char *file, struct url_stat *us) { char *ln; const char *filename; @@ -402,24 +408,24 @@ _ftp_stat(conn_t *conn, const char *file, struct url_stat *us) us->size = -1; us->atime = us->mtime = 0; - filename = _ftp_filename(file, &filenamelen, &type); + filename = ftp_filename(file, &filenamelen, &type); - if ((e = _ftp_mode_type(conn, 0, type)) != FTP_OK) { - _ftp_seterr(e); + if ((e = ftp_mode_type(conn, 0, type)) != FTP_OK) { + ftp_seterr(e); return (-1); } - e = _ftp_cmd(conn, "SIZE %.*s", filenamelen, filename); + e = ftp_cmd(conn, "SIZE %.*s", filenamelen, filename); if (e != FTP_FILE_STATUS) { - _ftp_seterr(e); + ftp_seterr(e); return (-1); } - for (ln = conn->buf + 4; *ln && isspace(*ln); ln++) + for (ln = conn->buf + 4; *ln && isspace((unsigned char)*ln); ln++) /* nothing */ ; - for (us->size = 0; *ln && isdigit(*ln); ln++) + for (us->size = 0; *ln && isdigit((unsigned char)*ln); ln++) us->size = us->size * 10 + *ln - '0'; - if (*ln && !isspace(*ln)) { - _ftp_seterr(FTP_PROTOCOL_ERROR); + if (*ln && !isspace((unsigned char)*ln)) { + ftp_seterr(FTP_PROTOCOL_ERROR); us->size = -1; return (-1); } @@ -427,12 +433,12 @@ _ftp_stat(conn_t *conn, const char *file, struct url_stat *us) us->size = -1; DEBUG(fprintf(stderr, "size: [%lld]\n", (long long)us->size)); - e = _ftp_cmd(conn, "MDTM %.*s", filenamelen, filename); + e = ftp_cmd(conn, "MDTM %.*s", filenamelen, filename); if (e != FTP_FILE_STATUS) { - _ftp_seterr(e); + ftp_seterr(e); return (-1); } - for (ln = conn->buf + 4; *ln && isspace(*ln); ln++) + for (ln = conn->buf + 4; *ln && isspace((unsigned char)*ln); ln++) /* nothing */ ; switch (strspn(ln, "0123456789")) { case 14: @@ -443,13 +449,13 @@ _ftp_stat(conn_t *conn, const char *file, struct url_stat *us) ln[1] = '0'; break; default: - _ftp_seterr(FTP_PROTOCOL_ERROR); + ftp_seterr(FTP_PROTOCOL_ERROR); return (-1); } if (sscanf(ln, "%04d%02d%02d%02d%02d%02d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { - _ftp_seterr(FTP_PROTOCOL_ERROR); + ftp_seterr(FTP_PROTOCOL_ERROR); return (-1); } tm.tm_mon--; @@ -478,13 +484,13 @@ struct ftpio { int err; /* Error code */ }; -static int _ftp_readfn(void *, char *, int); -static int _ftp_writefn(void *, const char *, int); -static fpos_t _ftp_seekfn(void *, fpos_t, int); -static int _ftp_closefn(void *); +static int ftp_readfn(void *, char *, int); +static int ftp_writefn(void *, const char *, int); +static fpos_t ftp_seekfn(void *, fpos_t, int); +static int ftp_closefn(void *); static int -_ftp_readfn(void *v, char *buf, int len) +ftp_readfn(void *v, char *buf, int len) { struct ftpio *io; int r; @@ -504,7 +510,7 @@ _ftp_readfn(void *v, char *buf, int len) } if (io->eof) return (0); - r = _fetch_read(io->dconn, buf, len); + r = fetch_read(io->dconn, buf, len); if (r > 0) return (r); if (r == 0) { @@ -517,7 +523,7 @@ _ftp_readfn(void *v, char *buf, int len) } static int -_ftp_writefn(void *v, const char *buf, int len) +ftp_writefn(void *v, const char *buf, int len) { struct ftpio *io; int w; @@ -535,7 +541,7 @@ _ftp_writefn(void *v, const char *buf, int len) errno = io->err; return (-1); } - w = _fetch_write(io->dconn, buf, len); + w = fetch_write(io->dconn, buf, len); if (w >= 0) return (w); if (errno != EINTR) @@ -544,7 +550,7 @@ _ftp_writefn(void *v, const char *buf, int len) } static fpos_t -_ftp_seekfn(void *v, fpos_t pos __unused, int whence __unused) +ftp_seekfn(void *v, fpos_t pos __unused, int whence __unused) { struct ftpio *io; @@ -558,7 +564,7 @@ _ftp_seekfn(void *v, fpos_t pos __unused, int whence __unused) } static int -_ftp_closefn(void *v) +ftp_closefn(void *v) { struct ftpio *io; int r; @@ -574,20 +580,20 @@ _ftp_closefn(void *v) errno = EBADF; return (-1); } - _fetch_close(io->dconn); + fetch_close(io->dconn); io->dir = -1; io->dconn = NULL; DEBUG(fprintf(stderr, "Waiting for final status\n")); - r = _ftp_chkerr(io->cconn); + r = ftp_chkerr(io->cconn); if (io->cconn == cached_connection && io->cconn->ref == 1) cached_connection = NULL; - _fetch_close(io->cconn); + fetch_close(io->cconn); free(io); return (r == FTP_TRANSFER_COMPLETE) ? 0 : -1; } static FILE * -_ftp_setup(conn_t *cconn, conn_t *dconn, int mode) +ftp_setup(conn_t *cconn, conn_t *dconn, int mode) { struct ftpio *io; FILE *f; @@ -600,7 +606,7 @@ _ftp_setup(conn_t *cconn, conn_t *dconn, int mode) io->dconn = dconn; io->dir = mode; io->eof = io->err = 0; - f = funopen(io, _ftp_readfn, _ftp_writefn, _ftp_seekfn, _ftp_closefn); + f = funopen(io, ftp_readfn, ftp_writefn, ftp_seekfn, ftp_closefn); if (f == NULL) free(io); return (f); @@ -610,7 +616,7 @@ _ftp_setup(conn_t *cconn, conn_t *dconn, int mode) * Transfer file */ static FILE * -_ftp_transfer(conn_t *conn, const char *oper, const char *file, +ftp_transfer(conn_t *conn, const char *oper, const char *file, int mode, off_t offset, const char *flags) { struct sockaddr_storage sa; @@ -636,10 +642,10 @@ _ftp_transfer(conn_t *conn, const char *oper, const char *file, strncasecmp(s, "no", 2) != 0); /* isolate filename */ - filename = _ftp_filename(file, &filenamelen, &type); + filename = ftp_filename(file, &filenamelen, &type); /* set transfer mode and data type */ - if ((e = _ftp_mode_type(conn, 0, type)) != FTP_OK) + if ((e = ftp_mode_type(conn, 0, type)) != FTP_OK) goto ouch; /* find our own address, bind, and listen */ @@ -651,7 +657,7 @@ _ftp_transfer(conn_t *conn, const char *oper, const char *file, /* open data socket */ if ((sd = socket(sa.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) { - _fetch_syserr(); + fetch_syserr(); return (NULL); } @@ -663,17 +669,17 @@ _ftp_transfer(conn_t *conn, const char *oper, const char *file, /* send PASV command */ if (verbose) - _fetch_info("setting passive mode"); + fetch_info("setting passive mode"); switch (sa.ss_family) { case AF_INET: - if ((e = _ftp_cmd(conn, "PASV")) != FTP_PASSIVE_MODE) + if ((e = ftp_cmd(conn, "PASV")) != FTP_PASSIVE_MODE) goto ouch; break; case AF_INET6: - if ((e = _ftp_cmd(conn, "EPSV")) != FTP_EPASSIVE_MODE) { + if ((e = ftp_cmd(conn, "EPSV")) != FTP_EPASSIVE_MODE) { if (e == -1) goto ouch; - if ((e = _ftp_cmd(conn, "LPSV")) != + if ((e = ftp_cmd(conn, "LPSV")) != FTP_LPASSIVE_MODE) goto ouch; } @@ -691,7 +697,7 @@ _ftp_transfer(conn_t *conn, const char *oper, const char *file, switch (e) { case FTP_PASSIVE_MODE: case FTP_LPASSIVE_MODE: - for (p = ln + 3; *p && !isdigit(*p); p++) + for (p = ln + 3; *p && !isdigit((unsigned char)*p); p++) /* nothing */ ; if (!*p) { e = FTP_PROTOCOL_ERROR; @@ -725,7 +731,7 @@ _ftp_transfer(conn_t *conn, const char *oper, const char *file, /* seek to required offset */ if (offset) - if (_ftp_cmd(conn, "REST %lu", (u_long)offset) != FTP_FILE_OK) + if (ftp_cmd(conn, "REST %lu", (u_long)offset) != FTP_FILE_OK) goto sysouch; /* construct sockaddr for data socket */ @@ -740,8 +746,8 @@ _ftp_transfer(conn_t *conn, const char *oper, const char *file, if (e == FTP_EPASSIVE_MODE) sin6->sin6_port = htons(port); else { - bcopy(addr + 2, (char *)&sin6->sin6_addr, 16); - bcopy(addr + 19, (char *)&sin6->sin6_port, 2); + memcpy(&sin6->sin6_addr, addr + 2, 16); + memcpy(&sin6->sin6_port, addr + 19, 2); } break; case AF_INET: @@ -749,8 +755,8 @@ _ftp_transfer(conn_t *conn, const char *oper, const char *file, if (e == FTP_EPASSIVE_MODE) sin4->sin_port = htons(port); else { - bcopy(addr, (char *)&sin4->sin_addr, 4); - bcopy(addr + 4, (char *)&sin4->sin_port, 2); + memcpy(&sin4->sin_addr, addr, 4); + memcpy(&sin4->sin_port, addr + 4, 2); } break; default: @@ -760,18 +766,18 @@ _ftp_transfer(conn_t *conn, const char *oper, const char *file, /* connect to data port */ if (verbose) - _fetch_info("opening data connection"); + fetch_info("opening data connection"); bindaddr = getenv("FETCH_BIND_ADDRESS"); if (bindaddr != NULL && *bindaddr != '\0' && - _fetch_bind(sd, sa.ss_family, bindaddr) != 0) + fetch_bind(sd, sa.ss_family, bindaddr) != 0) goto sysouch; if (connect(sd, (struct sockaddr *)&sa, sa.ss_len) == -1) goto sysouch; /* make the server initiate the transfer */ if (verbose) - _fetch_info("initiating transfer"); - e = _ftp_cmd(conn, "%s %.*s", oper, filenamelen, filename); + fetch_info("initiating transfer"); + e = ftp_cmd(conn, "%s %.*s", oper, filenamelen, filename); if (e != FTP_CONNECTION_ALREADY_OPEN && e != FTP_OPEN_DATA_CONNECTION) goto ouch; @@ -801,7 +807,7 @@ _ftp_transfer(conn_t *conn, const char *oper, const char *file, break; } if (verbose) - _fetch_info("binding data socket"); + fetch_info("binding data socket"); if (bind(sd, (struct sockaddr *)&sa, sa.ss_len) == -1) goto sysouch; if (listen(sd, 1) == -1) @@ -815,7 +821,7 @@ _ftp_transfer(conn_t *conn, const char *oper, const char *file, sin4 = (struct sockaddr_in *)&sa; a = ntohl(sin4->sin_addr.s_addr); p = ntohs(sin4->sin_port); - e = _ftp_cmd(conn, "PORT %d,%d,%d,%d,%d,%d", + e = ftp_cmd(conn, "PORT %d,%d,%d,%d,%d,%d", (a >> 24) & 0xff, (a >> 16) & 0xff, (a >> 8) & 0xff, a & 0xff, (p >> 8) & 0xff, p & 0xff); @@ -828,14 +834,14 @@ _ftp_transfer(conn_t *conn, const char *oper, const char *file, if (getnameinfo((struct sockaddr *)&sa, sa.ss_len, hname, sizeof(hname), NULL, 0, NI_NUMERICHOST) == 0) { - e = _ftp_cmd(conn, "EPRT |%d|%s|%d|", 2, hname, + e = ftp_cmd(conn, "EPRT |%d|%s|%d|", 2, hname, htons(sin6->sin6_port)); if (e == -1) goto ouch; } if (e != FTP_OK) { ap = (char *)&sin6->sin6_addr; - e = _ftp_cmd(conn, + e = ftp_cmd(conn, "LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", 6, 16, UC(ap[0]), UC(ap[1]), UC(ap[2]), UC(ap[3]), @@ -856,13 +862,13 @@ _ftp_transfer(conn_t *conn, const char *oper, const char *file, /* seek to required offset */ if (offset) - if (_ftp_cmd(conn, "REST %ju", (uintmax_t)offset) != FTP_FILE_OK) + if (ftp_cmd(conn, "REST %ju", (uintmax_t)offset) != FTP_FILE_OK) goto sysouch; /* make the server initiate the transfer */ if (verbose) - _fetch_info("initiating transfer"); - e = _ftp_cmd(conn, "%s %.*s", oper, filenamelen, filename); + fetch_info("initiating transfer"); + e = ftp_cmd(conn, "%s %.*s", oper, filenamelen, filename); if (e != FTP_CONNECTION_ALREADY_OPEN && e != FTP_OPEN_DATA_CONNECTION) goto ouch; @@ -873,19 +879,19 @@ _ftp_transfer(conn_t *conn, const char *oper, const char *file, sd = d; } - if ((df = _ftp_setup(conn, _fetch_reopen(sd), mode)) == NULL) + if ((df = ftp_setup(conn, fetch_reopen(sd), mode)) == NULL) goto sysouch; return (df); sysouch: - _fetch_syserr(); + fetch_syserr(); if (sd >= 0) close(sd); return (NULL); ouch: if (e != -1) - _ftp_seterr(e); + ftp_seterr(e); if (sd >= 0) close(sd); return (NULL); @@ -895,7 +901,7 @@ ouch: * Authenticate */ static int -_ftp_authenticate(conn_t *conn, struct url *url, struct url *purl) +ftp_authenticate(conn_t *conn, struct url *url, struct url *purl) { const char *user, *pwd, *logname; char pbuf[MAXHOSTNAMELEN + MAXLOGNAME + 1]; @@ -905,18 +911,18 @@ _ftp_authenticate(conn_t *conn, struct url *url, struct url *purl) /* send user name and password */ if (url->user[0] == '\0') - _fetch_netrc_auth(url); + fetch_netrc_auth(url); user = url->user; if (*user == '\0') user = getenv("FTP_LOGIN"); if (user == NULL || *user == '\0') user = FTP_ANONYMOUS_USER; - if (purl && url->port == _fetch_default_port(url->scheme)) - e = _ftp_cmd(conn, "USER %s@%s", user, url->host); + if (purl && url->port == fetch_default_port(url->scheme)) + e = ftp_cmd(conn, "USER %s@%s", user, url->host); else if (purl) - e = _ftp_cmd(conn, "USER %s@%s@%d", user, url->host, url->port); + e = ftp_cmd(conn, "USER %s@%s@%d", user, url->host, url->port); else - e = _ftp_cmd(conn, "USER %s", user); + e = ftp_cmd(conn, "USER %s", user); /* did the server request a password? */ if (e == FTP_NEED_PASSWORD) { @@ -933,7 +939,7 @@ _ftp_authenticate(conn_t *conn, struct url *url, struct url *purl) gethostname(pbuf + len, sizeof(pbuf) - len); pwd = pbuf; } - e = _ftp_cmd(conn, "PASS %s", pwd); + e = ftp_cmd(conn, "PASS %s", pwd); } return (e); @@ -943,7 +949,7 @@ _ftp_authenticate(conn_t *conn, struct url *url, struct url *purl) * Log on to FTP server */ static conn_t * -_ftp_connect(struct url *url, struct url *purl, const char *flags) +ftp_connect(struct url *url, struct url *purl, const char *flags) { conn_t *conn; int e, direct, verbose; @@ -966,24 +972,24 @@ _ftp_connect(struct url *url, struct url *purl, const char *flags) /* check for proxy */ if (purl) { /* XXX proxy authentication! */ - conn = _fetch_connect(purl->host, purl->port, af, verbose); + conn = fetch_connect(purl->host, purl->port, af, verbose); } else { /* no proxy, go straight to target */ - conn = _fetch_connect(url->host, url->port, af, verbose); + conn = fetch_connect(url->host, url->port, af, verbose); purl = NULL; } /* check connection */ if (conn == NULL) - /* _fetch_connect() has already set an error code */ + /* fetch_connect() has already set an error code */ return (NULL); /* expect welcome message */ - if ((e = _ftp_chkerr(conn)) != FTP_SERVICE_READY) + if ((e = ftp_chkerr(conn)) != FTP_SERVICE_READY) goto fouch; /* authenticate */ - if ((e = _ftp_authenticate(conn, url, purl)) != FTP_LOGGED_IN) + if ((e = ftp_authenticate(conn, url, purl)) != FTP_LOGGED_IN) goto fouch; /* TODO: Request extended features supported, if any (RFC 3659). */ @@ -993,8 +999,8 @@ _ftp_connect(struct url *url, struct url *purl, const char *flags) fouch: if (e != -1) - _ftp_seterr(e); - _fetch_close(conn); + ftp_seterr(e); + fetch_close(conn); return (NULL); } @@ -1002,19 +1008,19 @@ fouch: * Disconnect from server */ static void -_ftp_disconnect(conn_t *conn) +ftp_disconnect(conn_t *conn) { - (void)_ftp_cmd(conn, "QUIT"); + (void)ftp_cmd(conn, "QUIT"); if (conn == cached_connection && conn->ref == 1) cached_connection = NULL; - _fetch_close(conn); + fetch_close(conn); } /* * Check if we're already connected */ static int -_ftp_isconnected(struct url *url) +ftp_isconnected(struct url *url) { return (cached_connection && (strcmp(url->host, cached_host.host) == 0) @@ -1027,28 +1033,28 @@ _ftp_isconnected(struct url *url) * Check the cache, reconnect if no luck */ static conn_t * -_ftp_cached_connect(struct url *url, struct url *purl, const char *flags) +ftp_cached_connect(struct url *url, struct url *purl, const char *flags) { conn_t *conn; int e; /* set default port */ if (!url->port) - url->port = _fetch_default_port(url->scheme); + url->port = fetch_default_port(url->scheme); /* try to use previously cached connection */ - if (_ftp_isconnected(url)) { - e = _ftp_cmd(cached_connection, "NOOP"); + if (ftp_isconnected(url)) { + e = ftp_cmd(cached_connection, "NOOP"); if (e == FTP_OK || e == FTP_SYNTAX_ERROR) - return (_fetch_ref(cached_connection)); + return (fetch_ref(cached_connection)); } /* connect to server */ - if ((conn = _ftp_connect(url, purl, flags)) == NULL) + if ((conn = ftp_connect(url, purl, flags)) == NULL) return (NULL); if (cached_connection) - _ftp_disconnect(cached_connection); - cached_connection = _fetch_ref(conn); + ftp_disconnect(cached_connection); + cached_connection = fetch_ref(conn); memcpy(&cached_host, url, sizeof(*url)); return (conn); } @@ -1057,13 +1063,15 @@ _ftp_cached_connect(struct url *url, struct url *purl, const char *flags) * Check the proxy settings */ static struct url * -_ftp_get_proxy(const char *flags) +ftp_get_proxy(struct url * url, const char *flags) { struct url *purl; char *p; if (flags != NULL && strchr(flags, 'd') != NULL) return (NULL); + if (fetch_no_proxy_match(url->host)) + return (NULL); if (((p = getenv("FTP_PROXY")) || (p = getenv("ftp_proxy")) || (p = getenv("HTTP_PROXY")) || (p = getenv("http_proxy"))) && *p && (purl = fetchParseURL(p)) != NULL) { @@ -1074,7 +1082,7 @@ _ftp_get_proxy(const char *flags) strcpy(purl->scheme, SCHEME_HTTP); } if (!purl->port) - purl->port = _fetch_default_proxy_port(purl->scheme); + purl->port = fetch_default_proxy_port(purl->scheme); if (strcasecmp(purl->scheme, SCHEME_FTP) == 0 || strcasecmp(purl->scheme, SCHEME_HTTP) == 0) return (purl); @@ -1087,7 +1095,7 @@ _ftp_get_proxy(const char *flags) * Process an FTP request */ FILE * -_ftp_request(struct url *url, const char *op, struct url_stat *us, +ftp_request(struct url *url, const char *op, struct url_stat *us, struct url *purl, const char *flags) { conn_t *conn; @@ -1096,9 +1104,9 @@ _ftp_request(struct url *url, const char *op, struct url_stat *us, /* check if we should use HTTP instead */ if (purl && strcasecmp(purl->scheme, SCHEME_HTTP) == 0) { if (strcmp(op, "STAT") == 0) - return (_http_request(url, "HEAD", us, purl, flags)); + return (http_request(url, "HEAD", us, purl, flags)); else if (strcmp(op, "RETR") == 0) - return (_http_request(url, "GET", us, purl, flags)); + return (http_request(url, "GET", us, purl, flags)); /* * Our HTTP code doesn't support PUT requests yet, so try * a direct connection. @@ -1106,18 +1114,18 @@ _ftp_request(struct url *url, const char *op, struct url_stat *us, } /* connect to server */ - conn = _ftp_cached_connect(url, purl, flags); + conn = ftp_cached_connect(url, purl, flags); if (purl) fetchFreeURL(purl); if (conn == NULL) return (NULL); /* change directory */ - if (_ftp_cwd(conn, url->doc) == -1) + if (ftp_cwd(conn, url->doc) == -1) return (NULL); /* stat file */ - if (us && _ftp_stat(conn, url->doc, us) == -1 + if (us && ftp_stat(conn, url->doc, us) == -1 && fetchLastErrCode != FETCH_PROTO && fetchLastErrCode != FETCH_UNAVAIL) return (NULL); @@ -1131,7 +1139,7 @@ _ftp_request(struct url *url, const char *op, struct url_stat *us, oflag = O_RDONLY; /* initiate the transfer */ - return (_ftp_transfer(conn, op, url->doc, oflag, url->offset, flags)); + return (ftp_transfer(conn, op, url->doc, oflag, url->offset, flags)); } /* @@ -1140,7 +1148,7 @@ _ftp_request(struct url *url, const char *op, struct url_stat *us, FILE * fetchXGetFTP(struct url *url, struct url_stat *us, const char *flags) { - return (_ftp_request(url, "RETR", us, _ftp_get_proxy(flags), flags)); + return (ftp_request(url, "RETR", us, ftp_get_proxy(url, flags), flags)); } /* @@ -1158,9 +1166,8 @@ fetchGetFTP(struct url *url, const char *flags) FILE * fetchPutFTP(struct url *url, const char *flags) { - - return (_ftp_request(url, CHECK_FLAG('a') ? "APPE" : "STOR", NULL, - _ftp_get_proxy(flags), flags)); + return (ftp_request(url, CHECK_FLAG('a') ? "APPE" : "STOR", NULL, + ftp_get_proxy(url, flags), flags)); } /* @@ -1171,9 +1178,14 @@ fetchStatFTP(struct url *url, struct url_stat *us, const char *flags) { FILE *f; - f = _ftp_request(url, "STAT", us, _ftp_get_proxy(flags), flags); + f = ftp_request(url, "STAT", us, ftp_get_proxy(url, flags), flags); if (f == NULL) return (-1); + /* + * When op is "STAT", ftp_request() will return either NULL or + * (FILE *)1, never a valid FILE *, so we mustn't fclose(f) before + * returning, as it would cause a segfault. + */ return (0); } diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c index f9ce043cf9..86b3e23a34 100644 --- a/lib/libfetch/http.c +++ b/lib/libfetch/http.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/lib/libfetch/http.c,v 1.78 2007/05/08 19:28:03 des Exp $ + * $FreeBSD: src/lib/libfetch/http.c,v 1.86 2008/12/15 08:27:44 murray Exp $ * $DragonFly: src/lib/libfetch/http.c,v 1.4 2007/08/05 21:48:12 swildner Exp $ */ @@ -63,6 +63,7 @@ #include #include +#include #include #include @@ -92,6 +93,7 @@ #define HTTP_MOVED_PERM 301 #define HTTP_MOVED_TEMP 302 #define HTTP_SEE_OTHER 303 +#define HTTP_NOT_MODIFIED 304 #define HTTP_TEMP_REDIRECT 307 #define HTTP_NEED_AUTH 401 #define HTTP_NEED_PROXY_AUTH 407 @@ -130,27 +132,27 @@ struct httpio * Get next chunk header */ static int -_http_new_chunk(struct httpio *io) +http_new_chunk(struct httpio *io) { char *p; - if (_fetch_getln(io->conn) == -1) + if (fetch_getln(io->conn) == -1) return (-1); - if (io->conn->buflen < 2 || !isxdigit(*io->conn->buf)) + if (io->conn->buflen < 2 || !isxdigit((unsigned char)*io->conn->buf)) return (-1); - for (p = io->conn->buf; *p && !isspace(*p); ++p) { + for (p = io->conn->buf; *p && !isspace((unsigned char)*p); ++p) { if (*p == ';') break; - if (!isxdigit(*p)) + if (!isxdigit((unsigned char)*p)) return (-1); - if (isdigit(*p)) { + if (isdigit((unsigned char)*p)) { io->chunksize = io->chunksize * 16 + *p - '0'; } else { io->chunksize = io->chunksize * 16 + - 10 + tolower(*p) - 'a'; + 10 + tolower((unsigned char)*p) - 'a'; } } @@ -173,7 +175,7 @@ _http_new_chunk(struct httpio *io) * Grow the input buffer to at least len bytes */ static inline int -_http_growbuf(struct httpio *io, size_t len) +http_growbuf(struct httpio *io, size_t len) { char *tmp; @@ -191,7 +193,7 @@ _http_growbuf(struct httpio *io, size_t len) * Fill the input buffer, do chunk decoding on the fly */ static int -_http_fillbuf(struct httpio *io, size_t len) +http_fillbuf(struct httpio *io, size_t len) { if (io->error) return (-1); @@ -199,9 +201,9 @@ _http_fillbuf(struct httpio *io, size_t len) return (0); if (io->chunked == 0) { - if (_http_growbuf(io, len) == -1) + if (http_growbuf(io, len) == -1) return (-1); - if ((io->buflen = _fetch_read(io->conn, io->buf, len)) == -1) { + if ((io->buflen = fetch_read(io->conn, io->buf, len)) == -1) { io->error = 1; return (-1); } @@ -210,7 +212,7 @@ _http_fillbuf(struct httpio *io, size_t len) } if (io->chunksize == 0) { - switch (_http_new_chunk(io)) { + switch (http_new_chunk(io)) { case -1: io->error = 1; return (-1); @@ -222,9 +224,9 @@ _http_fillbuf(struct httpio *io, size_t len) if (len > io->chunksize) len = io->chunksize; - if (_http_growbuf(io, len) == -1) + if (http_growbuf(io, len) == -1) return (-1); - if ((io->buflen = _fetch_read(io->conn, io->buf, len)) == -1) { + if ((io->buflen = fetch_read(io->conn, io->buf, len)) == -1) { io->error = 1; return (-1); } @@ -233,7 +235,7 @@ _http_fillbuf(struct httpio *io, size_t len) if (io->chunksize == 0) { char endl[2]; - if (_fetch_read(io->conn, endl, 2) != 2 || + if (fetch_read(io->conn, endl, 2) != 2 || endl[0] != '\r' || endl[1] != '\n') return (-1); } @@ -247,7 +249,7 @@ _http_fillbuf(struct httpio *io, size_t len) * Read function */ static int -_http_readfn(void *v, char *buf, int len) +http_readfn(void *v, char *buf, int len) { struct httpio *io = (struct httpio *)v; int l, pos; @@ -260,12 +262,12 @@ _http_readfn(void *v, char *buf, int len) for (pos = 0; len > 0; pos += l, len -= l) { /* empty buffer */ if (!io->buf || io->bufpos == io->buflen) - if (_http_fillbuf(io, len) < 1) + if (http_fillbuf(io, len) < 1) break; l = io->buflen - io->bufpos; if (len < l) l = len; - bcopy(io->buf + io->bufpos, buf + pos, l); + memcpy(buf + pos, io->buf + io->bufpos, l); io->bufpos += l; } @@ -278,23 +280,23 @@ _http_readfn(void *v, char *buf, int len) * Write function */ static int -_http_writefn(void *v, const char *buf, int len) +http_writefn(void *v, const char *buf, int len) { struct httpio *io = (struct httpio *)v; - return (_fetch_write(io->conn, buf, len)); + return (fetch_write(io->conn, buf, len)); } /* * Close function */ static int -_http_closefn(void *v) +http_closefn(void *v) { struct httpio *io = (struct httpio *)v; int r; - r = _fetch_close(io->conn); + r = fetch_close(io->conn); if (io->buf) free(io->buf); free(io); @@ -305,20 +307,20 @@ _http_closefn(void *v) * Wrap a file descriptor up */ static FILE * -_http_funopen(conn_t *conn, int chunked) +http_funopen(conn_t *conn, int chunked) { struct httpio *io; FILE *f; if ((io = calloc(1, sizeof(*io))) == NULL) { - _fetch_syserr(); + fetch_syserr(); return (NULL); } io->conn = conn; io->chunked = chunked; - f = funopen(io, _http_readfn, _http_writefn, NULL, _http_closefn); + f = funopen(io, http_readfn, http_writefn, NULL, http_closefn); if (f == NULL) { - _fetch_syserr(); + fetch_syserr(); free(io); return (NULL); } @@ -362,7 +364,7 @@ static struct { * Send a formatted line; optionally echo to terminal */ static int -_http_cmd(conn_t *conn, const char *fmt, ...) +http_cmd(conn_t *conn, const char *fmt, ...) { va_list ap; size_t len; @@ -375,15 +377,15 @@ _http_cmd(conn_t *conn, const char *fmt, ...) if (msg == NULL) { errno = ENOMEM; - _fetch_syserr(); + fetch_syserr(); return (-1); } - r = _fetch_putln(conn, msg, len); + r = fetch_putln(conn, msg, len); free(msg); if (r == -1) { - _fetch_syserr(); + fetch_syserr(); return (-1); } @@ -394,11 +396,11 @@ _http_cmd(conn_t *conn, const char *fmt, ...) * Get and parse status line */ static int -_http_get_reply(conn_t *conn) +http_get_reply(conn_t *conn) { char *p; - if (_fetch_getln(conn) == -1) + if (fetch_getln(conn) == -1) return (-1); /* * A valid status line looks like "HTTP/m.n xyz reason" where m @@ -417,7 +419,10 @@ _http_get_reply(conn_t *conn) return (HTTP_PROTOCOL_ERROR); p += 4; } - if (*p != ' ' || !isdigit(p[1]) || !isdigit(p[2]) || !isdigit(p[3])) + if (*p != ' ' || + !isdigit((unsigned char)p[1]) || + !isdigit((unsigned char)p[2]) || + !isdigit((unsigned char)p[3])) return (HTTP_PROTOCOL_ERROR); conn->err = (p[1] - '0') * 100 + (p[2] - '0') * 10 + (p[3] - '0'); @@ -429,13 +434,14 @@ _http_get_reply(conn_t *conn) * to the beginning of the value. */ static const char * -_http_match(const char *str, const char *hdr) +http_match(const char *str, const char *hdr) { - while (*str && *hdr && tolower(*str++) == tolower(*hdr++)) + while (*str && *hdr && + tolower((unsigned char)*str++) == tolower((unsigned char)*hdr++)) /* nothing */; if (*str || *hdr != ':') return (NULL); - while (*hdr && isspace(*++hdr)) + while (*hdr && isspace((unsigned char)*++hdr)) /* nothing */; return (hdr); } @@ -444,13 +450,13 @@ _http_match(const char *str, const char *hdr) * Get the next header and return the appropriate symbolic code. */ static hdr_t -_http_next_header(conn_t *conn, const char **p) +http_next_header(conn_t *conn, const char **p) { int i; - if (_fetch_getln(conn) == -1) + if (fetch_getln(conn) == -1) return (hdr_syserror); - while (conn->buflen && isspace(conn->buf[conn->buflen - 1])) + while (conn->buflen && isspace((unsigned char)conn->buf[conn->buflen - 1])) conn->buflen--; conn->buf[conn->buflen] = '\0'; if (conn->buflen == 0) @@ -462,7 +468,7 @@ _http_next_header(conn_t *conn, const char **p) * characters except "()<>@,;:\\\"{}". */ for (i = 0; hdr_names[i].num != hdr_unknown; i++) - if ((*p = _http_match(hdr_names[i].name, conn->buf)) != NULL) + if ((*p = http_match(hdr_names[i].name, conn->buf)) != NULL) return (hdr_names[i].num); return (hdr_unknown); } @@ -471,7 +477,7 @@ _http_next_header(conn_t *conn, const char **p) * Parse a last-modified header */ static int -_http_parse_mtime(const char *p, time_t *mtime) +http_parse_mtime(const char *p, time_t *mtime) { char locale[64], *r; struct tm tm; @@ -495,11 +501,11 @@ _http_parse_mtime(const char *p, time_t *mtime) * Parse a content-length header */ static int -_http_parse_length(const char *p, off_t *length) +http_parse_length(const char *p, off_t *length) { off_t len; - for (len = 0; *p && isdigit(*p); ++p) + for (len = 0; *p && isdigit((unsigned char)*p); ++p) len = len * 10 + (*p - '0'); if (*p) return (-1); @@ -513,7 +519,7 @@ _http_parse_length(const char *p, off_t *length) * Parse a content-range header */ static int -_http_parse_range(const char *p, off_t *offset, off_t *length, off_t *size) +http_parse_range(const char *p, off_t *offset, off_t *length, off_t *size) { off_t first, last, len; @@ -524,16 +530,16 @@ _http_parse_range(const char *p, off_t *offset, off_t *length, off_t *size) first = last = -1; ++p; } else { - for (first = 0; *p && isdigit(*p); ++p) + for (first = 0; *p && isdigit((unsigned char)*p); ++p) first = first * 10 + *p - '0'; if (*p != '-') return (-1); - for (last = 0, ++p; *p && isdigit(*p); ++p) + for (last = 0, ++p; *p && isdigit((unsigned char)*p); ++p) last = last * 10 + *p - '0'; } if (first > last || *p != '/') return (-1); - for (len = 0, ++p; *p && isdigit(*p); ++p) + for (len = 0, ++p; *p && isdigit((unsigned char)*p); ++p) len = len * 10 + *p - '0'; if (*p || len < last - first + 1) return (-1); @@ -560,7 +566,7 @@ _http_parse_range(const char *p, off_t *offset, off_t *length, off_t *size) * Base64 encoding */ static char * -_http_base64(const char *src) +http_base64(const char *src) { static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -616,7 +622,7 @@ _http_base64(const char *src) * Encode username and password */ static int -_http_basic_auth(conn_t *conn, const char *hdr, const char *usr, const char *pwd) +http_basic_auth(conn_t *conn, const char *hdr, const char *usr, const char *pwd) { char *upw, *auth; int r; @@ -625,11 +631,11 @@ _http_basic_auth(conn_t *conn, const char *hdr, const char *usr, const char *pwd DEBUG(fprintf(stderr, "pwd: [%s]\n", pwd)); if (asprintf(&upw, "%s:%s", usr, pwd) == -1) return (-1); - auth = _http_base64(upw); + auth = http_base64(upw); free(upw); if (auth == NULL) return (-1); - r = _http_cmd(conn, "%s: Basic %s", hdr, auth); + r = http_cmd(conn, "%s: Basic %s", hdr, auth); free(auth); return (r); } @@ -638,7 +644,7 @@ _http_basic_auth(conn_t *conn, const char *hdr, const char *usr, const char *pwd * Send an authorization header */ static int -_http_authorize(conn_t *conn, const char *hdr, const char *p) +http_authorize(conn_t *conn, const char *hdr, const char *p) { /* basic authorization */ if (strncasecmp(p, "basic:", 6) == 0) { @@ -655,7 +661,7 @@ _http_authorize(conn_t *conn, const char *hdr, const char *p) user = str; pwd = strchr(str, ':'); *pwd++ = '\0'; - r = _http_basic_auth(conn, hdr, user, pwd); + r = http_basic_auth(conn, hdr, user, pwd); free(str); return (r); } @@ -671,7 +677,7 @@ _http_authorize(conn_t *conn, const char *hdr, const char *p) * Connect to the correct HTTP server or proxy. */ static conn_t * -_http_connect(struct url *URL, struct url *purl, const char *flags) +http_connect(struct url *URL, struct url *purl, const char *flags) { conn_t *conn; int verbose; @@ -699,15 +705,15 @@ _http_connect(struct url *URL, struct url *purl, const char *flags) return (NULL); } - if ((conn = _fetch_connect(URL->host, URL->port, af, verbose)) == NULL) - /* _fetch_connect() has already set an error code */ + if ((conn = fetch_connect(URL->host, URL->port, af, verbose)) == NULL) + /* fetch_connect() has already set an error code */ return (NULL); if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0 && - _fetch_ssl(conn, verbose) == -1) { - _fetch_close(conn); + fetch_ssl(conn, verbose) == -1) { + fetch_close(conn); /* grrr */ errno = EAUTH; - _fetch_syserr(); + fetch_syserr(); return (NULL); } @@ -718,19 +724,21 @@ _http_connect(struct url *URL, struct url *purl, const char *flags) } static struct url * -_http_get_proxy(const char *flags) +http_get_proxy(struct url * url, const char *flags) { struct url *purl; char *p; if (flags != NULL && strchr(flags, 'd') != NULL) return (NULL); + if (fetch_no_proxy_match(url->host)) + return (NULL); if (((p = getenv("HTTP_PROXY")) || (p = getenv("http_proxy"))) && *p && (purl = fetchParseURL(p))) { if (!*purl->scheme) strcpy(purl->scheme, SCHEME_HTTP); if (!purl->port) - purl->port = _fetch_default_proxy_port(purl->scheme); + purl->port = fetch_default_proxy_port(purl->scheme); if (strcasecmp(purl->scheme, SCHEME_HTTP) == 0) return (purl); fetchFreeURL(purl); @@ -739,7 +747,7 @@ _http_get_proxy(const char *flags) } static void -_http_print_html(FILE *out, FILE *in) +http_print_html(FILE *out, FILE *in) { size_t len; char *line, *p, *q; @@ -747,7 +755,7 @@ _http_print_html(FILE *out, FILE *in) comment = tag = 0; while ((line = fgetln(in, &len)) != NULL) { - while (len && isspace(line[len - 1])) + while (len && isspace((unsigned char)line[len - 1])) --len; for (p = q = line; q < line + len; ++q) { if (comment && *q == '-') { @@ -788,23 +796,26 @@ _http_print_html(FILE *out, FILE *in) * XXX off into a separate function. */ FILE * -_http_request(struct url *URL, const char *op, struct url_stat *us, +http_request(struct url *URL, const char *op, struct url_stat *us, struct url *purl, const char *flags) { + char timebuf[80]; + char hbuf[MAXHOSTNAMELEN + 7], *host; conn_t *conn; struct url *url, *new; - int chunked, direct, need_auth, noredirect, verbose; + int chunked, direct, ims, need_auth, noredirect, verbose; int e, i, n, val; off_t offset, clength, length, size; time_t mtime; const char *p; FILE *f; hdr_t h; - char hbuf[MAXHOSTNAMELEN + 7], *host; + struct tm *timestruct; direct = CHECK_FLAG('d'); noredirect = CHECK_FLAG('A'); verbose = CHECK_FLAG('v'); + ims = CHECK_FLAG('i'); if (direct && purl) { fetchFreeURL(purl); @@ -831,18 +842,18 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, /* check port */ if (!url->port) - url->port = _fetch_default_port(url->scheme); + url->port = fetch_default_port(url->scheme); /* were we redirected to an FTP URL? */ if (purl == NULL && strcmp(url->scheme, SCHEME_FTP) == 0) { if (strcmp(op, "GET") == 0) - return (_ftp_request(url, "RETR", us, purl, flags)); + return (ftp_request(url, "RETR", us, purl, flags)); else if (strcmp(op, "HEAD") == 0) - return (_ftp_request(url, "STAT", us, purl, flags)); + return (ftp_request(url, "STAT", us, purl, flags)); } /* connect to server or proxy */ - if ((conn = _http_connect(url, purl, flags)) == NULL) + if ((conn = http_connect(url, purl, flags)) == NULL) goto ouch; host = url->host; @@ -852,7 +863,7 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, host = hbuf; } #endif - if (url->port != _fetch_default_port(url->scheme)) { + if (url->port != fetch_default_port(url->scheme)) { if (host != hbuf) { strcpy(hbuf, host); host = hbuf; @@ -863,38 +874,46 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, /* send request */ if (verbose) - _fetch_info("requesting %s://%s%s", + fetch_info("requesting %s://%s%s", url->scheme, host, url->doc); if (purl) { - _http_cmd(conn, "%s %s://%s%s HTTP/1.1", + http_cmd(conn, "%s %s://%s%s HTTP/1.1", op, url->scheme, host, url->doc); } else { - _http_cmd(conn, "%s %s HTTP/1.1", + http_cmd(conn, "%s %s HTTP/1.1", op, url->doc); } + if (ims && url->ims_time) { + timestruct = gmtime((time_t *)&url->ims_time); + (void)strftime(timebuf, 80, "%a, %d %b %Y %T GMT", + timestruct); + if (verbose) + fetch_info("If-Modified-Since: %s", timebuf); + http_cmd(conn, "If-Modified-Since: %s", timebuf); + } /* virtual host */ - _http_cmd(conn, "Host: %s", host); + http_cmd(conn, "Host: %s", host); /* proxy authorization */ if (purl) { if (*purl->user || *purl->pwd) - _http_basic_auth(conn, "Proxy-Authorization", + http_basic_auth(conn, "Proxy-Authorization", purl->user, purl->pwd); else if ((p = getenv("HTTP_PROXY_AUTH")) != NULL && *p != '\0') - _http_authorize(conn, "Proxy-Authorization", p); + http_authorize(conn, "Proxy-Authorization", p); } /* server authorization */ if (need_auth || *url->user || *url->pwd) { if (*url->user || *url->pwd) - _http_basic_auth(conn, "Authorization", url->user, url->pwd); + http_basic_auth(conn, "Authorization", url->user, url->pwd); else if ((p = getenv("HTTP_AUTH")) != NULL && *p != '\0') - _http_authorize(conn, "Authorization", p); + http_authorize(conn, "Authorization", p); else if (fetchAuthMethod && fetchAuthMethod(url) == 0) { - _http_basic_auth(conn, "Authorization", url->user, url->pwd); + http_basic_auth(conn, "Authorization", url->user, url->pwd); } else { - _http_seterr(HTTP_NEED_AUTH); + http_seterr(HTTP_NEED_AUTH); goto ouch; } } @@ -902,19 +921,19 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, /* other headers */ if ((p = getenv("HTTP_REFERER")) != NULL && *p != '\0') { if (strcasecmp(p, "auto") == 0) - _http_cmd(conn, "Referer: %s://%s%s", + http_cmd(conn, "Referer: %s://%s%s", url->scheme, host, url->doc); else - _http_cmd(conn, "Referer: %s", p); + http_cmd(conn, "Referer: %s", p); } if ((p = getenv("HTTP_USER_AGENT")) != NULL && *p != '\0') - _http_cmd(conn, "User-Agent: %s", p); + http_cmd(conn, "User-Agent: %s", p); else - _http_cmd(conn, "User-Agent: %s " _LIBFETCH_VER, getprogname()); + http_cmd(conn, "User-Agent: %s " _LIBFETCH_VER, getprogname()); if (url->offset > 0) - _http_cmd(conn, "Range: bytes=%lld-", (long long)url->offset); - _http_cmd(conn, "Connection: close"); - _http_cmd(conn, ""); + http_cmd(conn, "Range: bytes=%lld-", (long long)url->offset); + http_cmd(conn, "Connection: close"); + http_cmd(conn, ""); /* * Force the queued request to be dispatched. Normally, one @@ -931,9 +950,10 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, sizeof(val)); /* get reply */ - switch (_http_get_reply(conn)) { + switch (http_get_reply(conn)) { case HTTP_OK: case HTTP_PARTIAL: + case HTTP_NOT_MODIFIED: /* fine */ break; case HTTP_MOVED_PERM: @@ -950,12 +970,12 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, * We already sent out authorization code, * so there's nothing more we can do. */ - _http_seterr(conn->err); + http_seterr(conn->err); goto ouch; } /* try again, but send the password this time */ if (verbose) - _fetch_info("server requires authorization"); + fetch_info("server requires authorization"); break; case HTTP_NEED_PROXY_AUTH: /* @@ -963,7 +983,7 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, * our proxy authorization code, so there's * nothing more we can do. */ - _http_seterr(conn->err); + http_seterr(conn->err); goto ouch; case HTTP_BAD_RANGE: /* @@ -975,10 +995,10 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, case HTTP_PROTOCOL_ERROR: /* fall through */ case -1: - _fetch_syserr(); + fetch_syserr(); goto ouch; default: - _http_seterr(conn->err); + http_seterr(conn->err); if (!verbose) goto ouch; /* fall through so we can get the full error message */ @@ -986,21 +1006,21 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, /* get headers */ do { - switch ((h = _http_next_header(conn, &p))) { + switch ((h = http_next_header(conn, &p))) { case hdr_syserror: - _fetch_syserr(); + fetch_syserr(); goto ouch; case hdr_error: - _http_seterr(HTTP_PROTOCOL_ERROR); + http_seterr(HTTP_PROTOCOL_ERROR); goto ouch; case hdr_content_length: - _http_parse_length(p, &clength); + http_parse_length(p, &clength); break; case hdr_content_range: - _http_parse_range(p, &offset, &length, &size); + http_parse_range(p, &offset, &length, &size); break; case hdr_last_modified: - _http_parse_mtime(p, &mtime); + http_parse_mtime(p, &mtime); break; case hdr_location: if (!HTTP_REDIRECT(conn->err)) @@ -1008,7 +1028,7 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, if (new) free(new); if (verbose) - _fetch_info("%d redirect to %s", conn->err, p); + fetch_info("%d redirect to %s", conn->err, p); if (*p == '/') /* absolute path */ new = fetchMakeURL(url->scheme, url->host, url->port, p, @@ -1048,7 +1068,7 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, if (conn->err == HTTP_NEED_AUTH) { e = conn->err; need_auth = 1; - _fetch_close(conn); + fetch_close(conn); conn = NULL; continue; } @@ -1058,22 +1078,26 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, if (url->offset == size && url->length == 0) { /* asked for 0 bytes; fake it */ offset = url->offset; + clength = -1; conn->err = HTTP_OK; break; } else { - _http_seterr(conn->err); + http_seterr(conn->err); goto ouch; } } /* we have a hit or an error */ - if (conn->err == HTTP_OK || conn->err == HTTP_PARTIAL || HTTP_ERROR(conn->err)) + if (conn->err == HTTP_OK + || conn->err == HTTP_NOT_MODIFIED + || conn->err == HTTP_PARTIAL + || HTTP_ERROR(conn->err)) break; /* all other cases: we got a redirect */ e = conn->err; need_auth = 0; - _fetch_close(conn); + fetch_close(conn); conn = NULL; if (!new) { DEBUG(fprintf(stderr, "redirect with no new location\n")); @@ -1086,7 +1110,7 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, /* we failed, or ran out of retries */ if (conn == NULL) { - _http_seterr(e); + http_seterr(e); goto ouch; } @@ -1095,9 +1119,14 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, (long long)offset, (long long)length, (long long)size, (long long)clength)); + if (conn->err == HTTP_NOT_MODIFIED) { + http_seterr(HTTP_NOT_MODIFIED); + return (NULL); + } + /* check for inconsistencies */ if (clength != -1 && length != -1 && clength != length) { - _http_seterr(HTTP_PROTOCOL_ERROR); + http_seterr(HTTP_PROTOCOL_ERROR); goto ouch; } if (clength == -1) @@ -1105,7 +1134,7 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, if (clength != -1) length = offset + clength; if (length != -1 && size != -1 && length != size) { - _http_seterr(HTTP_PROTOCOL_ERROR); + http_seterr(HTTP_PROTOCOL_ERROR); goto ouch; } if (size == -1) @@ -1119,7 +1148,7 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, /* too far? */ if (URL->offset > 0 && offset > URL->offset) { - _http_seterr(HTTP_PROTOCOL_ERROR); + http_seterr(HTTP_PROTOCOL_ERROR); goto ouch; } @@ -1128,8 +1157,8 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, URL->length = clength; /* wrap it up in a FILE */ - if ((f = _http_funopen(conn, chunked)) == NULL) { - _fetch_syserr(); + if ((f = http_funopen(conn, chunked)) == NULL) { + fetch_syserr(); goto ouch; } @@ -1139,7 +1168,7 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, fetchFreeURL(purl); if (HTTP_ERROR(conn->err)) { - _http_print_html(stderr, f); + http_print_html(stderr, f); fclose(f); f = NULL; } @@ -1152,7 +1181,7 @@ ouch: if (purl) fetchFreeURL(purl); if (conn != NULL) - _fetch_close(conn); + fetch_close(conn); return (NULL); } @@ -1167,7 +1196,7 @@ ouch: FILE * fetchXGetHTTP(struct url *URL, struct url_stat *us, const char *flags) { - return (_http_request(URL, "GET", us, _http_get_proxy(flags), flags)); + return (http_request(URL, "GET", us, http_get_proxy(URL, flags), flags)); } /* @@ -1197,7 +1226,7 @@ fetchStatHTTP(struct url *URL, struct url_stat *us, const char *flags) { FILE *f; - f = _http_request(URL, "HEAD", us, _http_get_proxy(flags), flags); + f = http_request(URL, "HEAD", us, http_get_proxy(URL, flags), flags); if (f == NULL) return (-1); fclose(f); diff --git a/lib/libkvm/Makefile b/lib/libkvm/Makefile index 012b433025..2da0320fa5 100644 --- a/lib/libkvm/Makefile +++ b/lib/libkvm/Makefile @@ -2,7 +2,7 @@ # $FreeBSD: src/lib/libkvm/Makefile,v 1.9.2.1 2001/04/25 10:04:32 ru Exp $ # $DragonFly: src/lib/libkvm/Makefile,v 1.6 2008/10/28 17:23:45 swildner Exp $ -SYSDIR= ${.CURDIR}/../../sys/ +SYSDIR= ${.CURDIR}/../../sys .PATH: ${SYSDIR}/kern LIB= kvm @@ -11,6 +11,7 @@ SRCS= kvm.c kvm_${MACHINE_ARCH}.c kvm_file.c kvm_getloadavg.c \ kvm_getswapinfo.c kvm_proc.c kvm_util.c \ kern_kinfo.c INCS= kvm.h +WARNS?= 2 MAN= kvm.3 kvm_geterr.3 kvm_getfiles.3 kvm_getloadavg.3 kvm_getprocs.3 \ kvm_getswapinfo.3 kvm_nlist.3 kvm_open.3 kvm_read.3 diff --git a/lib/libkvm/kvm.c b/lib/libkvm/kvm.c index 4d1226a2f9..ee20cc03a8 100644 --- a/lib/libkvm/kvm.c +++ b/lib/libkvm/kvm.c @@ -371,7 +371,7 @@ kvm_read(kvm_t *kd, u_long kva, void *buf, size_t len) */ errno = 0; if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { - _kvm_err(kd, 0, "invalid address (%x)", kva); + _kvm_err(kd, 0, "invalid address (%lx)", kva); return (-1); } @@ -453,7 +453,7 @@ kvm_readstr(kvm_t *kd, u_long kva, char *buf, size_t *lenp) */ errno = 0; if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { - _kvm_err(kd, 0, "invalid address (%x)", kva); + _kvm_err(kd, 0, "invalid address (%lx)", kva); return NULL; } @@ -536,7 +536,7 @@ kvm_write(kvm_t *kd, u_long kva, const void *buf, size_t len) */ errno = 0; if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { - _kvm_err(kd, 0, "invalid address (%x)", kva); + _kvm_err(kd, 0, "invalid address (%lx)", kva); return (-1); } cc = write(kd->vmfd, buf, len); diff --git a/lib/libkvm/kvm_amd64.c b/lib/libkvm/kvm_amd64.c index d8324972f5..9e945c648b 100644 --- a/lib/libkvm/kvm_amd64.c +++ b/lib/libkvm/kvm_amd64.c @@ -136,7 +136,6 @@ _kvm_vatop(kvm_t *kd, u_long va, u_long *pa) pt_entry_t pte; u_long pdeindex; u_long pteindex; - int i; if (kvm_ishost(kd)) { _kvm_err(kd, 0, "vatop called in live kernel!"); diff --git a/lib/libkvm/kvm_i386.c b/lib/libkvm/kvm_i386.c index 5345456636..9f57168766 100644 --- a/lib/libkvm/kvm_i386.c +++ b/lib/libkvm/kvm_i386.c @@ -136,7 +136,6 @@ _kvm_vatop(kvm_t *kd, u_long va, u_long *pa) pt_entry_t pte; u_long pdeindex; u_long pteindex; - int i; if (kvm_ishost(kd)) { _kvm_err(kd, 0, "vatop called in live kernel!"); diff --git a/lib/libkvm/kvm_open.3 b/lib/libkvm/kvm_open.3 index 110eacc2bf..78ac33d480 100644 --- a/lib/libkvm/kvm_open.3 +++ b/lib/libkvm/kvm_open.3 @@ -37,7 +37,7 @@ .\" $FreeBSD: src/lib/libkvm/kvm_open.3,v 1.5.2.6 2001/12/17 10:08:30 ru Exp $ .\" $DragonFly: src/lib/libkvm/kvm_open.3,v 1.4 2006/05/26 19:39:38 swildner Exp $ .\" -.Dd April 19, 1994 +.Dd May 5, 2009 .Dt KVM_OPEN 3 .Os .Sh NAME @@ -64,8 +64,8 @@ and return a descriptor used to access kernel virtual memory via the .Xr kvm 3 -library routines. Both active kernels and crash dumps are accessible -through this interface. +library routines. Both active kernels (including vkernels) and crash +dumps are accessible through this interface. .Pp .Fa execfile is the executable image of the kernel being examined. @@ -77,7 +77,8 @@ as determined from .Xr getbootfile 3 . .Pp .Fa corefile -is the kernel memory device file. It can be either /dev/mem +is the kernel memory device file. It can be /dev/mem, the path to +the procfs mem file for a running vkernel (i.e. /proc/$pid/mem) or a crash dump core generated by .Xr savecore 8 . If diff --git a/lib/libthread_xu/Makefile b/lib/libthread_xu/Makefile index 02ffb4ef08..ca701114a5 100644 --- a/lib/libthread_xu/Makefile +++ b/lib/libthread_xu/Makefile @@ -13,7 +13,8 @@ CFLAGS+= -g # CFLAGS+=-DSYSTEM_SCOPE_ONLY -LDFLAGS=--version-script=${.CURDIR}/pthread.map +# XXX this breaks threaded applications +#LDFLAGS=-Wl,-version-script=${.CURDIR}/pthread.map # enable extra internal consistancy checks CFLAGS+=-D_PTHREADS_INVARIANTS diff --git a/libexec/rpc.rquotad/rquotad.c b/libexec/rpc.rquotad/rquotad.c index f321e7c55d..268a2f8324 100644 --- a/libexec/rpc.rquotad/rquotad.c +++ b/libexec/rpc.rquotad/rquotad.c @@ -26,7 +26,6 @@ #include #include -#include #include #include diff --git a/nrelease/Makefile b/nrelease/Makefile index 60c673dddb..27b3a46f76 100644 --- a/nrelease/Makefile +++ b/nrelease/Makefile @@ -32,7 +32,7 @@ PKGBIN_PKG_ADMIN?= ${PKGSRC_PREFIX}/sbin/pkg_admin PKGBIN_MKISOFS?= ${PKGSRC_PREFIX}/bin/mkisofs PKGSRC_PKG_PATH?= ${ISODIR}/packages PKGSRC_DB?= /var/db/pkg -PKGSRC_BOOTSTRAP_URL?= http://pkgbox.dragonflybsd.org/DragonFly-pkgsrc-packages/i386/1.12.0-RELEASE-BUILD +PKGSRC_BOOTSTRAP_URL?= http://avalon.dragonflybsd.org/DragonFly-pkgsrc-packages/i386/1.12.0-RELEASE-BUILD CVSUP_BOOTSTRAP_KIT?= cvsup-bootstrap-20070716 # We use env -i in the chroot, so that environment variables won't @@ -144,18 +144,18 @@ NRLOBJDIR?= /usr/obj ######################################################################### release: check clean buildworld1 buildkernel1 \ - buildiso srcs customizeiso mkaliases mklocatedb \ + buildiso srcs customizeiso mklocatedb \ mkiso mkimg quickrel: check clean buildworld2 buildkernel2 \ - buildiso srcs customizeiso mkaliases mklocatedb \ + buildiso srcs customizeiso mklocatedb \ mkiso mkimg -realquickrel: check clean buildiso srcs customizeiso \ - mkaliases mklocatedb \ +realquickrel: check clean \ + buildiso srcs customizeiso mklocatedb \ mkiso mkimg -restartpkgs: check customizeiso mkaliases mklocatedb mkiso mkimg +restartpkgs: check customizeiso mklocatedb mkiso mkimg quick: quickrel @@ -374,11 +374,6 @@ customizeiso: makewhatis ${ISOROOT}/usr/local/man makewhatis ${ISOROOT}/usr/pkg/man -# So a CD boot does not complain about a missing aliases database -# -mkaliases: - ${CHROOT_CMD} "newaliases" - # So locate works # mklocatedb: @@ -479,6 +474,6 @@ help all: .PHONY: quick realquick .PHONY: check buildworld1 buildworld2 .PHONY: buildkernel1 buildkernel2 buildiso customizeiso mklocatedb mkiso mkimg -.PHONY: clean realclean fetch help all mkaliases srcs +.PHONY: clean realclean fetch help all srcs .include diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index e7514bba99..ee59413ae5 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -3454,7 +3454,7 @@ scsireadcapacity(struct cam_device *device, int argc, char **argv, union ccb *ccb; int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten; struct scsi_read_capacity_data rcap; - struct scsi_read_capacity_data_long rcaplong; + struct scsi_read_capacity_data_16 rcaplong; uint64_t maxsector; uint32_t block_len; int retval; diff --git a/sbin/camcontrol/modeedit.c b/sbin/camcontrol/modeedit.c index 94384bba7d..071985e3b6 100644 --- a/sbin/camcontrol/modeedit.c +++ b/sbin/camcontrol/modeedit.c @@ -634,7 +634,7 @@ modepage_read(FILE *file) char *line; /* Pointer to static fgetln buffer. */ char *name; /* Name portion of the line buffer. */ char *value; /* Value portion of line buffer. */ - int length; /* Length of static fgetln buffer. */ + size_t length; /* Length of static fgetln buffer. */ #define ABORT_READ(message, param) do { \ warnx(message, param); \ diff --git a/sbin/hammer/cmd_stats.c b/sbin/hammer/cmd_stats.c index 5da13c8d35..d84f8255c8 100644 --- a/sbin/hammer/cmd_stats.c +++ b/sbin/hammer/cmd_stats.c @@ -44,7 +44,7 @@ void hammer_cmd_bstats(char **av, int ac) { int mibs[8][16]; - int lens[8]; + size_t lens[8]; int64_t stats[8]; int64_t copy[8]; size_t size; @@ -110,7 +110,7 @@ void hammer_cmd_iostats(char **av, int ac) { int mibs[8][16]; - int lens[8]; + size_t lens[8]; int64_t stats[8]; int64_t copy[8]; size_t size; diff --git a/sbin/hammer/hammer.8 b/sbin/hammer/hammer.8 index 616abb8bf1..e622a13f51 100644 --- a/sbin/hammer/hammer.8 +++ b/sbin/hammer/hammer.8 @@ -108,7 +108,7 @@ minimum delay after a batch ends before the next batch is allowed to start. The default is five seconds. .It Fl q -Decrease verbosement. +Decrease verboseness. May be specified multiple times. .It Fl r Specify recursion for those commands which support it. diff --git a/share/examples/etc/README.examples b/share/examples/etc/README.examples index 8bb473b154..3d30dbbfe8 100644 --- a/share/examples/etc/README.examples +++ b/share/examples/etc/README.examples @@ -28,7 +28,6 @@ fbtab - configuration file for login(1) ftpusers - user restriction file for ftpd(8) gettytab - defines port configuration for getty(8) group - group permissions file -host.conf - resolver services configuration file hosts - host name database hosts.allow - host access control configuration (see tcpd(8)) hosts.equiv - defines system-wide trusted hosts (see ruserok(3)) diff --git a/share/man/man4/aac.4 b/share/man/man4/aac.4 index a9ee42ec9d..cf47e88d37 100644 --- a/share/man/man4/aac.4 +++ b/share/man/man4/aac.4 @@ -22,66 +22,49 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/share/man/man4/aac.4,v 1.3.2.8 2001/09/27 22:01:38 scottl Exp $ +.\" $FreeBSD: src/share/man/man4/aac.4,v 1.31.2.1.2.1 2006/12/14 23:56:26 brueffer Exp $ .\" $DragonFly: src/share/man/man4/aac.4,v 1.8 2008/09/02 11:50:46 matthias Exp $ -.Dd September 2, 2008 +.Dd May 8, 2009 .Dt AAC 4 .Os .Sh NAME .Nm aac .Nd Adaptec AdvancedRAID Controller driver .Sh SYNOPSIS -.Cd options AAC_DEBUG=N +To compile this driver into the kernel, +place the following lines in your +kernel configuration file: +.Bd -ragged -offset indent .Cd device pci .Cd device aac +.Cd device aacp +.Pp +To compile in debugging code: +.Cd options AAC_DEBUG=N +.Ed +.Pp +Alternatively, to load the driver as a +module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +aac_load="YES" +.Ed .Sh DESCRIPTION The .Nm -driver provides support for the Adaptec AAC family SATA, SCSI Ultra2 -and Ultra160/320 RAID controllers. -These controllers support RAID 0, 1, 5, 10, and volume sets. -They have four channels in the add-in version -or 1-2 channels in the motherboard integrated version, -and are most often found relabeled by Dell or Hewlett-Packard. -Supported controllers include: -.Bl -bullet -.It -AAC-364 -.It -Adaptec SATA RAID 2410SA -.It -Adaptec SATA RAID 2810SA -.It -Adaptec SCSI RAID 2120S -.It -Adaptec SCSI RAID 2200S -.It -Adaptec SCSI RAID 5400S -.It -Dell CERC SATA RAID 2 -.It -Dell PERC 2/Si -.It -Dell PERC 2/QC -.It -Dell PERC 3/Si -.It -Dell PERC 3/Di -.It -Dell PERC 320/DC -.It -HP NetRAID 4M -.El +driver provides support for the Adaptec AAC family of SCSI Ultra2, Ultra160, +and Ultra320, SATA and SAS RAID controllers. .Pp Access to RAID containers is available via the .Pa /dev/aacd? device nodes. -Individual drives cannot be accessed -unless they are part of a container or volume set, -and non-fixed disks cannot be accessed. -Containers can be configured by using -either the on-board BIOS utility of the card, -or a Linux-based management application. +The +.Nm aacp +device enables the SCSI pass-thru interface and allows devices connected +to the card such as CD-ROMs to be available via the CAM +.Xr scsi 4 +subsystem. +Note that not all cards allow this interface to be enabled. .Pp The .Pa /dev/aac? @@ -91,8 +74,19 @@ The aliases .Pa /dev/afa? and .Pa /dev/hpn? -exist for the Dell and HP flavors, respectively, and are required for -the CLI management utility available from these vendors to work. +exist for compatibilty with the Dell and HP versions of management tools, +respectively. +If the kernel is compiled with the +.Dv COMPAT_LINUX +option, or the +.Pa aac_linux.ko +and +.Pa linux.ko +modules are loaded, the +Linux-compatible +.Xr ioctl 2 +interface for the management device will be enabled and will allow +Linux-based management applications to control the card. .Ss Tuning The read-only sysctl .Va hw.aac.iosize_max @@ -111,19 +105,112 @@ Note also that performance peaks at a value of 96K, and drops off dramatically at 128K, due to other limitations of the card. +.Sh HARDWARE +Controllers supported by the +.Nm +driver include: +.Pp +.Bl -bullet -compact +.It +Adaptec AAC-364 +.It +Adaptec SAS RAID 4000SAS +.It +Adaptec SAS RAID 4005SAS +.It +Adaptec SAS RAID 4800SAS +.It +Adaptec SAS RAID 4805SAS +.It +Adaptec SATA RAID 2020SA ZCR +.It +Adaptec SATA RAID 2025SA ZCR +.It +Adaptec SATA RAID 2026ZCR +.It +Adaptec SATA RAID 2410SA +.It +Adaptec SATA RAID 2420SA +.It +Adaptec SATA RAID 2610SA +.It +Adaptec SATA RAID 2620SA +.It +Adaptec SATA RAID 2810SA +.It +Adaptec SATA RAID 2820SA +.It +Adaptec SATA RAID 21610SA +.It +Adaptec SCSI RAID 2020ZCR +.It +Adaptec SCSI RAID 2025ZCR +.It +Adaptec SCSI RAID 2120S +.It +Adaptec SCSI RAID 2130S +.It +Adaptec SCSI RAID 2130SLP +.It +Adaptec SCSI RAID 2230SLP +.It +Adaptec SCSI RAID 2200S +.It +Adaptec SCSI RAID 2240S +.It +Adaptec SCSI RAID 3230S +.It +Adaptec SCSI RAID 3240S +.It +Adaptec SCSI RAID 5400S +.It +Dell CERC SATA RAID 2 +.It +Dell PERC 2/Si +.It +Dell PERC 2/QC +.It +Dell PERC 3/Si +.It +Dell PERC 3/Di +.It +Dell PERC 320/DC +.It +HP ML110 G2 (Adaptec SATA RAID 2610SA) +.It +HP NetRAID 4M +.It +IBM ServeRAID 8i +.It +IBM ServeRAID 8k +.It +ICP ICP5085BR SAS RAID +.It +ICP ICP9085LI SAS RAID +.It +ICP ICP9047MA SATA RAID +.It +ICP ICP9087MA SATA RAID +.It +ICP ICP9014RO SCSI RAID +.It +ICP ICP9024RO SCSI RAID +.It +Legend S220 +.It +Legend S230 +.El .Sh FILES -.Bl -tag -width /boot/modules/aac.ko -compact +.Bl -tag -width ".Pa /dev/aacd?" -compact .It Pa /dev/aac? aac management interface .It Pa /dev/aacd? disk/container interface -.It Pa /boot/modules/aac.ko -aac loadable module .El .Sh DIAGNOSTICS Compiling with .Dv AAC_DEBUG -set to a number between 0 and 4 +set to a number between 0 and 2 will enable increasingly verbose debug messages. .Pp The adapter can send status and alert messages asynchronously @@ -133,6 +220,7 @@ and are also queued for retrieval by a management application. .Sh SEE ALSO .Xr kld 4 , .Xr linux 4 , +.Xr scsi 4 , .Xr kldload 8 , .Xr loader 8 , .Xr sysctl 8 @@ -147,13 +235,11 @@ driver first appeared in .An Scott Long .Aq scottl@FreeBSD.org .Sh BUGS -This driver is not compatible with controllers that have version 1.x firmware. +This driver is not compatible with Dell controllers that have version 1.x +firmware. The firmware version is the same as the kernel version printed in the BIOS POST and driver attach messages. .Pp -This driver will not work on systems with more than 4GB of memory. -.Pp +.\"This driver will not work on systems with more than 4GB of memory. +.\".Pp The controller is not actually paused on suspend/resume. -.Pp -Unloading driver is not supported at this time. -.Pp diff --git a/share/man/man4/acpi.4 b/share/man/man4/acpi.4 index 068ff0239f..f7cee7bd79 100644 --- a/share/man/man4/acpi.4 +++ b/share/man/man4/acpi.4 @@ -213,6 +213,18 @@ Control-method batteries device. .It Li cpu .Pq Vt device Supports CPU power-saving and speed-setting functions. +.It Li cpu_cst +.Pq Vt device +Supports CPU power-saving. +Diabling +.Dq Li cpu , +will also disable this device. +.It Li cpu_pst +.Pq Vt device +Supports CPU speed-setting. +Diabling +.Dq Li cpu , +will also disable this device. .It Li ec .Pq Vt device Supports the ACPI Embedded Controller interface, used to communicate diff --git a/share/man/man4/ath_hal.4 b/share/man/man4/ath_hal.4 index 08de0c2b11..678198bcf4 100644 --- a/share/man/man4/ath_hal.4 +++ b/share/man/man4/ath_hal.4 @@ -1,7 +1,7 @@ .\"- -.\" Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting +.\" Copyright (c) 2002-2009 Sam Leffler, Errno Consulting .\" All rights reserved. -.\"" +.\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: @@ -12,9 +12,6 @@ .\" similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any .\" redistribution must be conditioned upon including a substantially .\" similar Disclaimer requirement for further binary redistribution. -.\" 3. Neither the names of the above-listed copyright holders nor the names -.\" of any contributors may be used to endorse or promote products derived -.\" from this software without specific prior written permission. .\" .\" NO WARRANTY .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @@ -29,10 +26,10 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF .\" THE POSSIBILITY OF SUCH DAMAGES. .\" -.\" $FreeBSD: /repoman/r/ncvs/src/share/man/man4/ath_hal.4,v 1.11 2005/01/15 12:49:11 ru Exp $ +.\" $FreeBSD: src/share/man/man4/ath_hal.4,v 1.13 2009/03/25 21:20:19 sam Exp $ .\" $DragonFly: src/share/man/man4/ath_hal.4,v 1.2 2008/11/17 11:55:19 swildner Exp $ .\" -.Dd November 17, 2008 +.Dd May 21, 2009 .Dt ATH_HAL 4 .Os .Sh NAME @@ -56,7 +53,9 @@ ath_hal_load="YES" The .Nm module provides hardware support for wireless network adapters based on -the Atheros AR5210, AR5211, and AR5212 chips. +the Atheros AR5210, AR5211, AR5212, AR5213, AR2413, AR2417, AR2425, +AR5413, AR5416, AR5418, AR5424, AR9160, and AR9280 chips (and companion +RF/baseband parts). This module is required by the .Xr ath 4 driver. @@ -121,16 +120,6 @@ module first appeared in .Fx 5.2 and was imported into .Dx 1.5 . -.Sh CAVEATS -The -.Nm -module is constructed from a binary component and -operating system-dependent source code. -Redistribution and use in source and binary forms, without -modification, are permitted provided that the conditions -set forth in -.Pa sys/contrib/dev/ath/COPYRIGHT -are observed. .Sh BUGS See .Xr ath 4 diff --git a/share/man/man4/smp.4 b/share/man/man4/smp.4 index 7ee4e9db95..c355f3a101 100644 --- a/share/man/man4/smp.4 +++ b/share/man/man4/smp.4 @@ -31,7 +31,8 @@ .Nm SMP .Nd description of the Symmetric MultiProcessor kernel .Sh SYNOPSIS -.Nm +.Cd options SMP +.Cd options APIC_IO .Sh DESCRIPTION The .Nm diff --git a/share/man/man5/Makefile b/share/man/man5/Makefile index 9463f1322b..dc8808b214 100644 --- a/share/man/man5/Makefile +++ b/share/man/man5/Makefile @@ -23,7 +23,6 @@ MAN= acct.5 \ gbk.5 \ group.5 \ hammer.5 \ - host.conf.5 \ hosts.5 \ hosts.equiv.5 \ hosts.lpd.5 \ diff --git a/share/man/man5/host.conf.5 b/share/man/man5/host.conf.5 deleted file mode 100644 index e4992b8a25..0000000000 --- a/share/man/man5/host.conf.5 +++ /dev/null @@ -1,119 +0,0 @@ -.\" Copyright (c) 2001 Giorgos Keramidas -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD: src/share/man/man5/host.conf.5,v 1.1.2.2 2002/02/12 10:12:13 ru Exp $ -.\" $DragonFly: src/share/man/man5/host.conf.5,v 1.4 2007/05/17 08:19:01 swildner Exp $ -.\" -.\" Note: The date here should be updated whenever a non-trivial -.\" change is made to the manual page. -.Dd December 6, 2001 -.Dt HOST.CONF 5 -.Os -.Sh NAME -.Nm host.conf -.Nd resolver services configuration file -.Sh SYNOPSIS -.Pa /etc/host.conf -.Sh DESCRIPTION -The -.Nm -file holds part of the configuration for the resolver of -.Dx . -It describes what services (eg. DNS or -.Xr yp 8 ) -the C library resolving routines -(like -.Xr gethostbyname 3 ) -will use, and their order of use, when resolving host names or addresses. -.Pp -The format of this file is human readable, and easy to modify with the -text editor of your choice. -Lines with -.Ql # -in the first column are comments and are ignored. -The rest of the lines may contain any number of service names, -separated by any number of colons -.Pq Ql \&: , -semicolons -.Pq Ql \&; , -commas -.Pq Ql \&, , -or whitespace (tab, space and newline characters). -.Ss Valid Service Names -Service names that are recognized as valid in -.Nm -are: -.Bl -tag -width ".Li yellowpages" -.It Li /etc/hosts -An alias for -.Ql hosts . -.It Li bind -This service makes the resolver use Internet Domain System (DNS) for -resolving hostnames and addresses. -The DNS resolver configuration is -described in -.Xr resolver 5 . -.It Li dns -An alias for -.Ql bind . -.It Li domain -An alias for -.Ql bind . -.It Li hosts -When this service name is used in -.Nm , -name and address lookups are done by using the local hosts database. -The local hosts database is described in -.Xr hosts 5 . -.It Li hosttable -An alias for -.Ql hosts . -.It Li htable -An alias for -.Ql hosts . -.It Li nis -When service name is used in -.Nm , -the resolver uses YP/NIS for making lookups of hostnames and -addresses. -The YP/NIS system is described in -.Xr yp 8 . -.It Li yellowpages -An alias for -.Ql nis . -.It Li yp -An alias for -.Ql nis . -.El -.Sh FILES -.Bl -tag -width ".Pa host.conf" -.It Pa host.conf -The services configuration file resides in -.Pa /etc . -.El -.Sh SEE ALSO -.Xr gethostbyname 3 , -.Xr hosts 5 , -.Xr resolver 5 , -.Xr yp 8 diff --git a/share/man/man7/pkgsrc.7 b/share/man/man7/pkgsrc.7 index cfab870ae3..ee8b65746c 100644 --- a/share/man/man7/pkgsrc.7 +++ b/share/man/man7/pkgsrc.7 @@ -28,7 +28,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd April 30, 2008 +.Dd May 9, 2009 .Dt PKGSRC 7 .Os .Sh NAME @@ -37,8 +37,9 @@ .Sh DESCRIPTION The .Nx -Packages Collection (pkgsrc) is a framework for building and -maintaining third-party software on +Packages Collection +.Nm ( ) +is a framework for building and maintaining third-party software on .Nx , .Dx and other @@ -50,6 +51,16 @@ and built easily on supported platforms. Tools are available to install ready-to-use packages and to perform various administrative tasks for the package system. .Pp +For building packages from source, +.Pa /usr/Makefile +offers a number of targets to checkout and update the +.Nm +and +.Nm pkgsrc-wip +trees. +.Sq Nm cd Pa /usr ; Nm make Ar help +gives a quick overview. +.Pp Note that due to compatibility issues .Xr bmake 1 has to be used instead of @@ -65,3 +76,5 @@ related tasks. .Xr pkg_search 1 .Pp .Pa http://www.NetBSD.org/docs/pkgsrc/ +.Pp +.Pa http://pkgsrc-wip.sourceforge.net/ diff --git a/share/man/man8/rc.sendmail.8 b/share/man/man8/rc.sendmail.8 index 88a6ed47e0..80c3368605 100644 --- a/share/man/man8/rc.sendmail.8 +++ b/share/man/man8/rc.sendmail.8 @@ -27,7 +27,7 @@ .\" $FreeBSD: src/share/man/man8/rc.sendmail.8,v 1.1.2.2 2002/05/22 17:01:33 gshapiro Exp $ .\" $DragonFly: src/share/man/man8/rc.sendmail.8,v 1.4 2008/05/02 02:05:06 swildner Exp $ .\" -.Dd March 30, 2002 +.Dd May 20, 2009 .Dt RC.SENDMAIL 8 .Os .Sh NAME @@ -252,6 +252,19 @@ sendmail_submit_enable="NO" sendmail_outbound_enable="NO" sendmail_msp_queue_enable="NO" .Ed +.Pp +Additionally, the setting of the +.Va sendmail_rebuild_aliases +variable determines whether +.Xr newaliases 1 +is run if necessary or not. +If set to +.Dq Li YES , +the +.Pa /etc/mail/aliases.db +file is automatically regenerated either if it is older than +.Pa /etc/mail/aliases +or non-existent. .Sh SEE ALSO .Xr rc.conf 5 , .Xr rc 8 , diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index c99ed6b084..8879e24f09 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -129,6 +129,7 @@ MAN= accept_filter.9 \ style.9 \ suser.9 \ SYSCALL_MODULE.9 \ + syscall.9 \ sysctl.9 \ sysctl_add_oid.9 \ sysctl_ctx_init.9 \ @@ -495,7 +496,6 @@ MLINKS+=microuptime.9 getmicrouptime.9 \ microuptime.9 nanouptime.9 MLINKS+=nlookup.9 naccess.9 \ nlookup.9 naccess_va.9 \ - nlookup.9 namei.9 \ nlookup.9 nlookup_done.9 \ nlookup.9 nlookup_init.9 \ nlookup.9 nlookup_init_raw.9 \ diff --git a/share/man/man9/nlookup.9 b/share/man/man9/nlookup.9 index 3cb8317300..ad46286650 100644 --- a/share/man/man9/nlookup.9 +++ b/share/man/man9/nlookup.9 @@ -30,7 +30,7 @@ .\" .\" $DragonFly: src/share/man/man9/nlookup.9,v 1.11 2008/02/09 09:45:03 swildner Exp $ .\" -.Dd August 6, 2005 +.Dd May 26, 2009 .Os .Dt NLOOKUP 9 .Sh NAME @@ -44,8 +44,7 @@ .Nm nlookup_mp , .Nm nreadsymlink , .Nm naccess , -.Nm naccess_va , -.Nm namei +.Nm naccess_va .Nd namecache API .Sh SYNOPSIS .In sys/types.h @@ -218,13 +217,11 @@ checks the requested access against the given .Fa vattr using .Fa cred . +.Sh FILES +.Pa sys/kern/vfs_nlookup.c .Sh SEE ALSO .Xr VFS 9 , .Xr vnode 9 -.Pp -.Pa src/sys/kern/vfs_nlookup.c .Sh AUTHORS This man page was written by .An Sascha Wildner . -.Sh BUGS -This man page needs further work. diff --git a/share/man/man9/syscall.9 b/share/man/man9/syscall.9 new file mode 100644 index 0000000000..fe9cc2ab47 --- /dev/null +++ b/share/man/man9/syscall.9 @@ -0,0 +1,161 @@ +.\" $OpenBSD: syscall.9,v 1.7 2007/05/31 19:20:01 jmc Exp $ +.\" +.\" Copyright (c) 2003 Michael Shalayeff +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd May 25, 2009 +.Dt SYSCALL 9 +.Os +.Sh NAME +.Nm syscall +.Nd "system calls overview" +.Sh DESCRIPTION +A system call is an explicit request to the kernel made via a software +interrupt by some program. +For example, +.Fn open +is a system call that is used when access to a file stored in filesystem +is needed. +In this sense, system calls provide the interface between a process and the +operating system. +.Pp +The kernel implements system calls through a set of switch tables +for each emulation type. +The list of currently supported system calls along with their codes resides in +.Pa sys/sys/syscall.h . +This file, and a couple others which will be examined later, are +automatically generated and should not be edited manually. +.Pp +The first step in adding a new system call is to edit the +.Pa sys/kern/syscall.masters +file. +The +.Dq master +file is a text file consisting of a list of lines for each +system call. +Lines may be split by the means of back slashing the end of the line. +Each line is a set of fields separated by whitespace: +.Pp +.D1 Cd number type namespace ... +.Pp +Where: +.Bl -tag -width namespace -compact +.It number +is the system call number; +.It namespace +is one of POSIX, BSD, NOHIDE; +.It type +is one of: +.Bl -tag -width NOPROTO -compact +.It STD +standard system call with full prototype and implementation; +.It OBSOL +obsolete, not included in the system; +.It UNIMPL +unimplemented, not included in the system, placeholder only; +.It NODEF +included, but don't define the syscall number; +.It NOARGS +included, but don't define the syscall args structure; +.It NOPROTO +implemented elsewhere; +.It COMPAT +a compatibility system call, only included if the corresponding +option is configured for the kernel. +.El +.El +.Pp +The rest of the line for the STD, NODEF, NOARGS, and COMPAT +types is: +.Pp +.D1 Cd { pseudo-proto } [alias] +.Pp +.Nm pseudo-proto +is a C-like prototype used to generate the system call argument list, +and alias is an optional name alias for the call. +The function in the prototype has to be defined somewhere in +the kernel sources as it will be used as an entry point for +the corresponding system call. +.Pp +For other types the rest of the line is a comment. +.Pp +To generate the header and code files from the +.Dq master +file, +.Li make sysent +has to be run from the directory containing the +.Dq master +file. +Please mind that the string +.Li sys_ +is prepended to all system call names, but not to the structures +holding the arguments. +So, if one has added the line: +.Bd -literal +503 STD BSD { int mycall(int x, int y); } +.Ed +.Pp +to the system call master file, the generated prototype would be: +.Bd -literal +int sys_mycall(struct mycall_args *uap); +.Ed +.Pp +It is customary to extract system call arguments with the +.Dv SCARG(uap, member) +macro, which is defined in +.Pa sys/sys/sysent.h +file. +Last, in order to return a value to userland, the +.Li uap->sysmsg_result +variable and friends of it are used, as defined in +.Pa sys/sys/sysmsg.h . +.Sh FILES +.Bl -tag -width sys/kern/syscalls.master -compact +.It Pa sys/kern/makesyscalls.sh +a +.Xr sh 1 +script for generating C files out of the syscall master file; +.It Pa sys/kern/syscalls.conf +a configuration file for the shell script above; +.It Pa sys/kern/syscalls.master +master files describing names and numbers for the system calls; +.It Pa sys/kern/syscalls.c +system call names lists; +.It Pa sys/kern/init_sysent.c +system call switch tables; +.It Pa sys/sys/sysproto.h +system call argument lists; +.It Pa sys/sys/syscall.h +system call numbers. +.It Pa sys/emulation/linux/i386 +Linux emulation system calls. +.El +.Sh SEE ALSO +.Xr ktrace 2 , +.Xr syscall 2 , +.Xr SYSCALL_MODULE 9 +.Sh HISTORY +The +.Nm +section manual page appeared in +.Dx 2.3 . diff --git a/share/misc/bsd-family-tree b/share/misc/bsd-family-tree index b5bac99a5f..a8042b7fc0 100644 --- a/share/misc/bsd-family-tree +++ b/share/misc/bsd-family-tree @@ -227,6 +227,8 @@ FreeBSD 5.2 | | | | | | | | | | | FreeBSD 7.1 | | | | | | | | | DragonFly 2.2.0 + | FreeBSD 7.2 | NetBSD 5.0 OpenBSD 4.5 | + | | | | | | | V | | | | | | | | | FreeBSD 8 -current | NetBSD -current OpenBSD -current | @@ -496,6 +498,9 @@ OpenBSD 4.4 2008-11-01 [OBD] FreeBSD 6.4 2008-11-28 [FBD] FreeBSD 7.1 2009-01-04 [FBD] DragonFly 2.2.0 2009-02-17 [DFB] +NetBSD 5.0 2009-04-29 [NBD] +OpenBSD 4.5 2009-05-01 [OBD] +FreeBSD 7.2 2009-05-04 [FBD] Bibliography ------------------------ @@ -556,4 +561,4 @@ Steven M. Schultz for providing 2.8BSD, 2.10BSD, 2.11BSD manual pages. Copyright (c) 1997-2007 Wolfram Schneider URL: http://cvsweb.freebsd.org/src/share/misc/bsd-family-tree -$FreeBSD: src/share/misc/bsd-family-tree,v 1.126 2009/02/18 19:05:27 maxim Exp $ +$FreeBSD: src/share/misc/bsd-family-tree,v 1.129 2009/05/05 20:54:26 maxim Exp $ diff --git a/share/zoneinfo/README b/share/zoneinfo/README index c0cc92853d..427b6a0151 100644 --- a/share/zoneinfo/README +++ b/share/zoneinfo/README @@ -1,4 +1,6 @@ -@(#)README 8.2 +@(#)README 8.3 +This file is in the public domain, so clarified as of +2009-05-17 by Arthur David Olson. "What time is it?" -- Richard Deacon as The King "Any time you want it to be." -- Frank Baxter as The Scientist diff --git a/share/zoneinfo/Theory b/share/zoneinfo/Theory index b842fb4b75..36b087eb4c 100644 --- a/share/zoneinfo/Theory +++ b/share/zoneinfo/Theory @@ -1,5 +1,6 @@ -@(#)Theory 8.2 - +@(#)Theory 8.3 +This file is in the public domain, so clarified as of +2009-05-17 by Arthur David Olson. ----- Outline ----- @@ -9,7 +10,6 @@ Calendrical issues Time and time zones on Mars - ----- Time and date functions ----- These time and date functions are upwards compatible with POSIX, diff --git a/share/zoneinfo/africa b/share/zoneinfo/africa index 80932d4686..3f92eb4745 100644 --- a/share/zoneinfo/africa +++ b/share/zoneinfo/africa @@ -1,5 +1,7 @@ -# @(#)africa 8.19 #
+# @(#)africa	8.21
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
 
 # This data is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
@@ -241,18 +243,18 @@ Rule	Egypt	2007	only	-	Sep	Thu>=1	23:00s	0	-
 # The following appeared in Red Hat bugzilla[1] (edited):
 #
 # > $ zdump -v /usr/share/zoneinfo/Africa/Cairo | grep 2009
-# > /usr/share/zoneinfo/Africa/Cairo  Thu Apr 23 21:59:59 2009 UTC =3D Thu =
+# > /usr/share/zoneinfo/Africa/Cairo  Thu Apr 23 21:59:59 2009 UTC = Thu =
 # Apr 23
-# > 23:59:59 2009 EET isdst=3D0 gmtoff=3D7200
-# > /usr/share/zoneinfo/Africa/Cairo  Thu Apr 23 22:00:00 2009 UTC =3D Fri =
+# > 23:59:59 2009 EET isdst=0 gmtoff=7200
+# > /usr/share/zoneinfo/Africa/Cairo  Thu Apr 23 22:00:00 2009 UTC = Fri =
 # Apr 24
-# > 01:00:00 2009 EEST isdst=3D1 gmtoff=3D10800
-# > /usr/share/zoneinfo/Africa/Cairo  Thu Aug 27 20:59:59 2009 UTC =3D Thu =
+# > 01:00:00 2009 EEST isdst=1 gmtoff=10800
+# > /usr/share/zoneinfo/Africa/Cairo  Thu Aug 27 20:59:59 2009 UTC = Thu =
 # Aug 27
-# > 23:59:59 2009 EEST isdst=3D1 gmtoff=3D10800
-# > /usr/share/zoneinfo/Africa/Cairo  Thu Aug 27 21:00:00 2009 UTC =3D Thu =
+# > 23:59:59 2009 EEST isdst=1 gmtoff=10800
+# > /usr/share/zoneinfo/Africa/Cairo  Thu Aug 27 21:00:00 2009 UTC = Thu =
 # Aug 27
-# > 23:00:00 2009 EET isdst=3D0 gmtoff=3D7200
+# > 23:00:00 2009 EET isdst=0 gmtoff=7200
 #
 # > end date should be Thu Sep 24 2009 (Last Thursday in September at 23:59=
 # :59)
@@ -260,11 +262,11 @@ Rule	Egypt	2007	only	-	Sep	Thu>=1	23:00s	0	-
 #
 # timeanddate[2] and another site I've found[3] also support that.
 #
-# [1] 
-# https://bugzilla.redhat.com/show_bug.cgi?id=3D492263
+# [1] 
+# https://bugzilla.redhat.com/show_bug.cgi?id=492263
 # 
-# [2] 
-# http://www.timeanddate.com/worldclock/clockchange.html?n=3D53
+# [2] 
+# http://www.timeanddate.com/worldclock/clockchange.html?n=53
 # 
 # [3] 
 # http://wwp.greenwichmeantime.com/time-zone/africa/egypt/
@@ -477,8 +479,8 @@ Zone Africa/Nouakchott	-1:03:48 -	LMT	1912
 
 # From Riad M. Hossen Ally (2008-08-03):
 # The Government of Mauritius weblink
-# 
-# http://www.gov.mu/portal/site/pmosite/menuitem.4ca0efdee47462e7440a600248a521ca/?content_id=3D4728ca68b2a5b110VgnVCM1000000a04a8c0RCRD
+# 
+# http://www.gov.mu/portal/site/pmosite/menuitem.4ca0efdee47462e7440a600248a521ca/?content_id=4728ca68b2a5b110VgnVCM1000000a04a8c0RCRD
 # 
 # Cabinet Decision of July 18th, 2008 states as follows:
 #
diff --git a/share/zoneinfo/antarctica b/share/zoneinfo/antarctica
index ef279cbeda..8511ab207e 100644
--- a/share/zoneinfo/antarctica
+++ b/share/zoneinfo/antarctica
@@ -1,5 +1,7 @@
-# @(#)antarctica	8.4
 # 
+# @(#)antarctica	8.5
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
 
 # From Paul Eggert (1999-11-15):
 # To keep things manageable, we list only locations occupied year-round; see
diff --git a/share/zoneinfo/asia b/share/zoneinfo/asia
index 2c3dc38b8f..de2ca39352 100644
--- a/share/zoneinfo/asia
+++ b/share/zoneinfo/asia
@@ -1,5 +1,7 @@
-# @(#)asia	8.30
 # 
+# @(#)asia	8.34
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
 
 # This data is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
@@ -125,6 +127,48 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
 			3:00	-	AST
 
 # Bangladesh
+# From Alexander Krivenyshev (2009-05-13):
+# According to newspaper Asian Tribune (May 6, 2009) Bangladesh may introduce
+# Daylight Saving Time from June 16 to Sept 30
+#
+# Bangladesh to introduce daylight saving time likely from June 16
+# 
+# http://www.asiantribune.com/?q=node/17288
+# 
+# or
+# 
+# http://www.worldtimezone.com/dst_news/dst_news_bangladesh02.html
+# 
+#
+# "... Bangladesh government has decided to switch daylight saving time from
+# June
+# 16 till September 30 in a bid to ensure maximum use of daylight to cope with
+# crippling power crisis. "
+#
+# The switch will remain in effect from June 16 to Sept 30 (2009) but if
+# implemented the next year, it will come in force from April 1, 2010
+
+# From Steffen Thorsen (2009-06-02):
+# They have finally decided now, but changed the start date to midnight between
+# the 19th and 20th, and they have not set the end date yet.
+#
+# Some sources:
+# 
+# http://in.reuters.com/article/southAsiaNews/idINIndia-40017620090601
+# 
+# 
+# http://bdnews24.com/details.php?id=85889&cid=2
+# 
+#
+# Our wrap-up:
+# 
+# http://www.timeanddate.com/news/time/bangladesh-daylight-saving-2009.html
+# 
+
+# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
+Rule	Bang	2009	only	-	Jan	1	0:00	0	-
+Rule	Bang	2009	only	-	Jun	20	0:00	1:00	S
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Dhaka	6:01:40 -	LMT	1890
 			5:53:20	-	HMT	1941 Oct    # Howrah Mean Time?
@@ -132,7 +176,8 @@ Zone	Asia/Dhaka	6:01:40 -	LMT	1890
 			5:30	-	IST	1942 Sep
 			6:30	-	BURT	1951 Sep 30
 			6:00	-	DACT	1971 Mar 26 # Dacca Time
-			6:00	-	BDT	# Bangladesh Time
+			6:00	-	BDT	2009 # Bangladesh Time
+			6:00	Bang	BD%sT
 
 # Bhutan
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -1107,7 +1152,7 @@ Rule	Jordan	1995	1998	-	Sep	Fri>=15	0:00s	0	-
 Rule	Jordan	1999	only	-	Jul	 1	0:00s	1:00	S
 Rule	Jordan	1999	2002	-	Sep	lastFri	0:00s	0	-
 Rule	Jordan	2000	2001	-	Mar	lastThu	0:00s	1:00	S
-Rule	Jordan	2002	max	-	Mar	lastFri	0:00s	1:00	S
+Rule	Jordan	2002	max	-	Mar	lastThu	24:00	1:00	S
 Rule	Jordan	2003	only	-	Oct	24	0:00s	0	-
 Rule	Jordan	2004	only	-	Oct	15	0:00s	0	-
 Rule	Jordan	2005	only	-	Sep	lastFri	0:00s	0	-
diff --git a/share/zoneinfo/australasia b/share/zoneinfo/australasia
index 41608cdc34..a3c2a898e6 100644
--- a/share/zoneinfo/australasia
+++ b/share/zoneinfo/australasia
@@ -1,5 +1,7 @@
-# @(#)australasia	8.9
 # 
+# @(#)australasia	8.11
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
 
 # This file also includes Pacific islands.
 
@@ -1119,6 +1121,27 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # From Paul Eggert (2007-07-23):
 # See "southeast Australia" above for 2008 and later.
 
+# From Steffen Thorsen (2009-04-28):
+# According to the official press release, South Australia's extended daylight
+# saving period will continue with the same rules as used during the 2008-2009
+# summer (southern hemisphere).
+#
+# From
+# 
+# http://www.safework.sa.gov.au/uploaded_files/DaylightDatesSet.pdf
+# 
+# The extended daylight saving period that South Australia has been trialling
+# for over the last year is now set to be ongoing.
+# Daylight saving will continue to start on the first Sunday in October each
+# year and finish on the first Sunday in April the following year.
+# Industrial Relations Minister, Paul Caica, says this provides South Australia
+# with a consistent half hour time difference with NSW, Victoria, Tasmania and
+# the ACT for all 52 weeks of the year...
+#
+# We have a wrap-up here:
+# 
+# http://www.timeanddate.com/news/time/south-australia-extends-dst.html
+# 
 ###############################################################################
 
 # New Zealand
diff --git a/share/zoneinfo/backward b/share/zoneinfo/backward
index e3f5429e73..c896968c9a 100644
--- a/share/zoneinfo/backward
+++ b/share/zoneinfo/backward
@@ -1,4 +1,7 @@
-# @(#)backward	8.7
+# 
+# @(#)backward	8.8
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
 
 # This file provides links between current names for time zones
 # and their old names.  Many names changed in late 1993.
diff --git a/share/zoneinfo/etcetera b/share/zoneinfo/etcetera
index cddbe8a294..5c93682985 100644
--- a/share/zoneinfo/etcetera
+++ b/share/zoneinfo/etcetera
@@ -1,4 +1,7 @@
-# @(#)etcetera	8.1
+# 
+# @(#)etcetera	8.2
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
 
 # These entries are mostly present for historical reasons, so that
 # people in areas not otherwise covered by the tz files could "zic -l"
diff --git a/share/zoneinfo/europe b/share/zoneinfo/europe
index 09f3e1e75c..3f39215bf6 100644
--- a/share/zoneinfo/europe
+++ b/share/zoneinfo/europe
@@ -1,5 +1,7 @@
-# @(#)europe	8.20
 # 
+# @(#)europe	8.21
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
 
 # This data is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
diff --git a/share/zoneinfo/factory b/share/zoneinfo/factory
index 946063c0dd..624ccc0c36 100644
--- a/share/zoneinfo/factory
+++ b/share/zoneinfo/factory
@@ -1,4 +1,7 @@
-# @(#)factory	8.1
+# 
+# @(#)factory	8.2
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
 
 # For companies who don't want to put time zone specification in
 # their installation procedures.  When users run date, they'll get the message.
diff --git a/share/zoneinfo/iso3166.tab b/share/zoneinfo/iso3166.tab
index 8d62399580..b8a2592c00 100644
--- a/share/zoneinfo/iso3166.tab
+++ b/share/zoneinfo/iso3166.tab
@@ -1,7 +1,9 @@
+# 
+# @(#)iso3166.tab	8.6
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
 # ISO 3166 alpha-2 country codes
 #
-# @(#)iso3166.tab	8.5
-#
 # From Paul Eggert (2006-09-27):
 #
 # This file contains a table with the following columns:
diff --git a/share/zoneinfo/leapseconds b/share/zoneinfo/leapseconds
index e3f776b337..bcd51a002a 100644
--- a/share/zoneinfo/leapseconds
+++ b/share/zoneinfo/leapseconds
@@ -1,4 +1,7 @@
-# @(#)leapseconds	8.7
+# 
+# @(#)leapseconds	8.8
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
 
 # Allowance for leapseconds added to each timezone file.
 
diff --git a/share/zoneinfo/northamerica b/share/zoneinfo/northamerica
index 7fd6ea6173..236922d754 100644
--- a/share/zoneinfo/northamerica
+++ b/share/zoneinfo/northamerica
@@ -1,5 +1,7 @@
-# @(#)northamerica	8.27
 # 
+# @(#)northamerica	8.28
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
 
 # also includes Central America and the Caribbean
 
diff --git a/share/zoneinfo/southamerica b/share/zoneinfo/southamerica
index a921d81154..fe28538281 100644
--- a/share/zoneinfo/southamerica
+++ b/share/zoneinfo/southamerica
@@ -1,5 +1,7 @@
-# @(#)southamerica	8.34
 # 
+# @(#)southamerica	8.36
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
 
 # This data is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
@@ -674,8 +676,8 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 
 # From Rodrigo Severo (2008-06-24):
 # Just correcting the URL:
-# 
-# https://www.in.gov.br/imprensa/visualiza/index.jsp?jornal=3Ddo&secao=3D1&pagina=3D1&data=3D25/04/2008
+# 
+# https://www.in.gov.br/imprensa/visualiza/index.jsp?jornal=do&secao=1&pagina=1&data=25/04/2008
 # 
 #
 # As a result of the above Decree I believe the America/Rio_Branco
diff --git a/share/zoneinfo/systemv b/share/zoneinfo/systemv
index 6cf9645de0..767388d6aa 100644
--- a/share/zoneinfo/systemv
+++ b/share/zoneinfo/systemv
@@ -1,4 +1,7 @@
-# @(#)systemv	8.1
+# 
+# @(#)systemv	8.2
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
 
 # Old rules, should the need arise.
 # No attempt is made to handle Newfoundland, since it cannot be expressed
diff --git a/share/zoneinfo/zone.tab b/share/zoneinfo/zone.tab
index 2609894802..18aff1bb5a 100644
--- a/share/zoneinfo/zone.tab
+++ b/share/zoneinfo/zone.tab
@@ -1,4 +1,7 @@
-# @(#)zone.tab	8.26
+# 
+# @(#)zone.tab	8.28
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
 #
 # TZ zone descriptions
 #
@@ -101,7 +104,7 @@ BR	-0640-06952	America/Eirunepe	W Amazonas
 BR	-0958-06748	America/Rio_Branco	Acre
 BS	+2505-07721	America/Nassau
 BT	+2728+08939	Asia/Thimphu
-BW	-2545+02555	Africa/Gaborone
+BW	-2439+02555	Africa/Gaborone
 BY	+5354+02734	Europe/Minsk
 BZ	+1730-08812	America/Belize
 CA	+4734-05243	America/St_Johns	Newfoundland Time, including SE Labrador
@@ -285,7 +288,7 @@ MY	+0310+10142	Asia/Kuala_Lumpur	peninsular Malaysia
 MY	+0133+11020	Asia/Kuching	Sabah & Sarawak
 MZ	-2558+03235	Africa/Maputo
 NA	-2234+01706	Africa/Windhoek
-NC	-2216+16530	Pacific/Noumea
+NC	-2216+16627	Pacific/Noumea
 NE	+1331+00207	Africa/Niamey
 NF	-2903+16758	Pacific/Norfolk
 NG	+0627+00324	Africa/Lagos
@@ -365,7 +368,7 @@ TK	-0922-17114	Pacific/Fakaofo
 TL	-0833+12535	Asia/Dili
 TM	+3757+05823	Asia/Ashgabat
 TN	+3648+01011	Africa/Tunis
-TO	-2110+17510	Pacific/Tongatapu
+TO	-2110-17510	Pacific/Tongatapu
 TR	+4101+02858	Europe/Istanbul
 TT	+1039-06131	America/Port_of_Spain
 TV	-0831+17913	Pacific/Funafuti
@@ -409,7 +412,7 @@ US	+211825-1575130	Pacific/Honolulu	Hawaii
 UY	-3453-05611	America/Montevideo
 UZ	+3940+06648	Asia/Samarkand	west Uzbekistan
 UZ	+4120+06918	Asia/Tashkent	east Uzbekistan
-VA	+4154+01227	Europe/Vatican
+VA	+415408+0122711	Europe/Vatican
 VC	+1309-06114	America/St_Vincent
 VE	+1030-06656	America/Caracas
 VG	+1827-06437	America/Tortola
diff --git a/sys/boot/common/loader.8 b/sys/boot/common/loader.8
index 0f3d1a4cdc..82be916382 100644
--- a/sys/boot/common/loader.8
+++ b/sys/boot/common/loader.8
@@ -441,6 +441,13 @@ The following
 .Nm
 tunables are available:
 .Bl -tag -width Va
+.It Va hw.irq.X.dest
+Set irqX's destination to the given CPUID,
+which starts from 0.
+If the specified value is larger than the last CPUID,
+then the first CPUID will be used.
+This variable should not be used if IO/APIC support is not compiled
+into kernel.
 .It Va hw.physmem
 Limit the amount of physical memory the system will use.
 By default the size is in bytes, but the
diff --git a/sys/bus/cam/cam_ccb.h b/sys/bus/cam/cam_ccb.h
index a4054b8158..0dfe490842 100644
--- a/sys/bus/cam/cam_ccb.h
+++ b/sys/bus/cam/cam_ccb.h
@@ -80,8 +80,8 @@ typedef enum {
 	CAM_PASS_ERR_RECOVER	= 0x00010000,/* Pass driver does err. recovery*/
 	CAM_DIS_DISCONNECT	= 0x00020000,/* Disable disconnect	      */
 	CAM_SG_LIST_PHYS	= 0x00040000,/* SG list has physical addrs.   */
-	CAM_MSG_BUF_PHYS	= 0x00080000,/* Message buffer ptr is physical*/
-	CAM_SNS_BUF_PHYS	= 0x00100000,/* Autosense data ptr is physical*/
+	CAM_POLLED		= 0x00080000,/* Requested that polling be used*/
+	CAM_UNUSED100000	= 0x00100000,
 	CAM_DATA_PHYS		= 0x00200000,/* SG/Buffer data ptrs are phys. */
 	CAM_CDB_PHYS		= 0x00400000,/* CDB poiner is physical	      */
 	CAM_ENG_SGLIST		= 0x00800000,/* SG list is for the HBA engine */
@@ -224,6 +224,7 @@ typedef enum {
 	XPORT_PPB,	/* Parallel Port Bus */
 	XPORT_ATA,	/* AT Attachment */
 	XPORT_SAS,	/* Serial Attached SCSI */
+	XPORT_AHCI,	/* SATA AHCI Attachment */
 } cam_xport;
 
 #define PROTO_VERSION_UNKNOWN (UINT_MAX - 1)
diff --git a/sys/bus/cam/cam_periph.h b/sys/bus/cam/cam_periph.h
index 9bf1d73e60..797f4f1d57 100644
--- a/sys/bus/cam/cam_periph.h
+++ b/sys/bus/cam/cam_periph.h
@@ -114,7 +114,6 @@ struct cam_periph {
 #define CAM_PERIPH_INVALID		0x08
 #define CAM_PERIPH_NEW_DEV_FOUND	0x10
 #define CAM_PERIPH_RECOVERY_INPROG	0x20
-#define CAM_PERIPH_POLLED		0x40
 	u_int32_t		 immediate_priority;
 	u_int32_t		 refcount;
 	SLIST_HEAD(, ccb_hdr)	 ccb_list;	/* For "immediate" requests */
diff --git a/sys/bus/cam/cam_queue.c b/sys/bus/cam/cam_queue.c
index c298175cdf..c2369f4e6d 100644
--- a/sys/bus/cam/cam_queue.c
+++ b/sys/bus/cam/cam_queue.c
@@ -68,7 +68,7 @@ camq_init(struct camq *camq, int size)
 	camq->array_size = size;
 	if (camq->array_size != 0) {
 		camq->queue_array = kmalloc(size * sizeof(cam_pinfo *), 
-					M_CAMQ, M_INTWAIT);
+					M_CAMQ, M_INTWAIT | M_ZERO);
 		/*
 		 * Heap algorithms like everything numbered from 1, so
 		 * offset our pointer into the heap array by one element.
@@ -118,7 +118,8 @@ camq_resize(struct camq *queue, int new_size)
 		panic("camq_resize: New queue size can't accommodate "
 		      "queued entries.");
 #endif
-	new_array = kmalloc(new_size * sizeof(cam_pinfo *), M_CAMQ, M_INTWAIT);
+	new_array = kmalloc(new_size * sizeof(cam_pinfo *), M_CAMQ,
+			    M_INTWAIT | M_ZERO);
 
 	/*
 	 * Heap algorithms like everything numbered from 1, so
@@ -160,6 +161,10 @@ camq_insert(struct camq *queue, cam_pinfo *new_entry)
  * Heap(1, num_elements) property and an index such that 1 <= index <=
  * num_elements, remove that entry and restore the Heap(1, num_elements-1)
  * property.
+ *
+ * When removing do not leave any junk pointers around in the array.
+ * This also ensures that CAMQ_GET_HEAD() returns NULL if the queue is
+ * empty.
  */
 cam_pinfo *
 camq_remove(struct camq *queue, int index)
@@ -174,6 +179,7 @@ camq_remove(struct camq *queue, int index)
 		queue->queue_array[index]->index = index;
 		heap_down(queue->queue_array, index, queue->entries - 1);
 	}
+	queue->queue_array[queue->entries] = NULL;
 	removed_entry->index = CAM_UNQUEUED_INDEX;
 	queue->entries--;
 	return (removed_entry);
diff --git a/sys/bus/cam/cam_xpt.c b/sys/bus/cam/cam_xpt.c
index 351314323e..f281fb7c8b 100644
--- a/sys/bus/cam/cam_xpt.c
+++ b/sys/bus/cam/cam_xpt.c
@@ -4416,9 +4416,11 @@ again:
 	 * Check for requeues, reissues asyncs if necessary
 	 */
 	if (CAMQ_GET_HEAD(&devq->send_queue))
-		kprintf("camq: devq send_queue still in use\n");
+		kprintf("camq: devq send_queue still in use (%d entries)\n",
+			devq->send_queue.entries);
 	if (CAMQ_GET_HEAD(&devq->alloc_queue))
-		kprintf("camq: devq alloc_queue still in use\n");
+		kprintf("camq: devq alloc_queue still in use (%d entries)\n",
+			devq->alloc_queue.entries);
 	if (CAMQ_GET_HEAD(&devq->send_queue) || 
 	    CAMQ_GET_HEAD(&devq->alloc_queue)) {
 		if (++retries < 5) {
@@ -4461,6 +4463,9 @@ again:
 	xpt_release_bus(bus_path.bus);
 	xpt_release_path(&bus_path);
 
+	/* Release the ref we got when the bus was registered */
+	cam_sim_release(ccbsim, 0);
+
 	return (CAM_REQ_CMP);
 }
 
@@ -4890,8 +4895,7 @@ xpt_done(union ccb *done_ccb)
 				}
 				spin_unlock_wr(&cam_simq_spin);
 			}
-			if ((done_ccb->ccb_h.path->periph->flags &
-			    CAM_PERIPH_POLLED) == 0)
+			if ((done_ccb->ccb_h.flags & CAM_POLLED) == 0)
 				setsoftcambio();
 			break;
 		default:
diff --git a/sys/bus/cam/scsi/scsi_all.c b/sys/bus/cam/scsi/scsi_all.c
index 0953eb925c..431976fb6e 100644
--- a/sys/bus/cam/scsi/scsi_all.c
+++ b/sys/bus/cam/scsi/scsi_all.c
@@ -3763,7 +3763,7 @@ void
 scsi_read_capacity_16(struct ccb_scsiio *csio, uint32_t retries,
 		      void (*cbfcnp)(struct cam_periph *, union ccb *),
 		      uint8_t tag_action, uint64_t lba, int reladr, int pmi,
-		      struct scsi_read_capacity_data_long *rcap_buf,
+		      struct scsi_read_capacity_data_16 *rcap_buf,
 		      uint8_t sense_len, uint32_t timeout)
 {
 	struct scsi_read_capacity_16 *scsi_cmd;
@@ -3780,7 +3780,7 @@ scsi_read_capacity_16(struct ccb_scsiio *csio, uint32_t retries,
 		      timeout);
 	scsi_cmd = (struct scsi_read_capacity_16 *)&csio->cdb_io.cdb_bytes;
 	bzero(scsi_cmd, sizeof(*scsi_cmd));
-	scsi_cmd->opcode = SERVICE_ACTION_IN;
+	scsi_cmd->opcode = READ_CAPACITY_16;
 	scsi_cmd->service_action = SRC16_SERVICE_ACTION;
 	scsi_u64to8b(lba, scsi_cmd->addr);
 	scsi_ulto4b(sizeof(*rcap_buf), scsi_cmd->alloc_len);
diff --git a/sys/bus/cam/scsi/scsi_all.h b/sys/bus/cam/scsi/scsi_all.h
index 136ad41431..13b20e047d 100644
--- a/sys/bus/cam/scsi/scsi_all.h
+++ b/sys/bus/cam/scsi/scsi_all.h
@@ -607,6 +607,7 @@ struct ata_pass_16 {
 #define	ATA_PASS_16		0x85
 #define READ_16			0x88
 #define WRITE_16		0x8a
+#define READ_CAPACITY_16	0x9e
 #define SERVICE_ACTION_IN	0x9e
 #define REPORT_LUNS		0xa0
 #define	ATA_PASS_12		0xa1
@@ -698,6 +699,7 @@ struct scsi_inquiry_data
 #define		SCSI_REV_2		2
 #define		SCSI_REV_SPC		3
 #define		SCSI_REV_SPC2		4
+#define		SCSI_REV_SPC3		5
 
 #define SID_ECMA	0x38
 #define SID_ISO		0xC0
@@ -792,6 +794,43 @@ struct scsi_vpd_unit_serial_number
 	u_int8_t serial_num[SVPD_SERIAL_NUM_SIZE];
 };
 
+struct scsi_vpd_unit_devid
+{
+	u_int8_t device;
+	u_int8_t page_code;
+#define SVPD_UNIT_DEVID	0x83
+	u_int8_t reserved;
+	u_int8_t length;
+	/* extended by variable array of scsi_vpd_devid_hdr */
+};
+
+struct scsi_vpd_devid_hdr {
+	u_int8_t pi_code;
+#define VPD_DEVID_PI(_f)	(((_f) >> 4) & 0xf0)
+#define VPD_DEVID_CODE(_f)	(((_f) >> 0) & 0x0f)
+#define VPD_DEVID_CODE_BINARY		0x1
+#define VPD_DEVID_CODE_ASCII		0x2
+#define VPD_DEVID_CODE_UTF8		0x3
+	u_int8_t flags;
+#define VPD_DEVID_PIV		0x80
+#define VPD_DEVID_ASSOC(_f)	((_f) & 0x30)
+#define VPD_DEVID_ASSOC_LU		0x00
+#define VPD_DEVID_ASSOC_PORT		0x10
+#define VPD_DEVID_ASSOC_TARG		0x20
+#define VPD_DEVID_TYPE(_f)	((_f) & 0x0f)
+#define VPD_DEVID_TYPE_VENDOR		0x0
+#define VPD_DEVID_TYPE_T10		0x1
+#define VPD_DEVID_TYPE_EUI64		0x2
+#define VPD_DEVID_TYPE_NAA		0x3
+#define VPD_DEVID_TYPE_RELATIVE		0x4
+#define VPD_DEVID_TYPE_PORT		0x5
+#define VPD_DEVID_TYPE_LU		0x6
+#define VPD_DEVID_TYPE_MD5		0x7
+#define VPD_DEVID_TYPE_NAME		0x8
+	u_int8_t reserved;
+	u_int8_t len;
+};
+
 struct scsi_read_capacity
 {
 	u_int8_t opcode;
@@ -820,10 +859,14 @@ struct scsi_read_capacity_data
 	u_int8_t length[4];
 };
 
-struct scsi_read_capacity_data_long
+struct scsi_read_capacity_data_16
 {
 	uint8_t addr[8];
 	uint8_t length[4];
+	u_int8_t p_type_prot;
+	u_int8_t logical_per_phys;
+	u_int8_t lowest_aligned[2];
+	u_int8_t reserved[16];
 };
 
 struct scsi_report_luns
@@ -865,7 +908,6 @@ struct scsi_report_luns_data {
 #define	RPL_LUNDATA_ATYP_LUN	0x80
 #define	RPL_LUNDATA_ATYP_EXTLUN	0xc0
 
-
 struct scsi_sense_data
 {
 	u_int8_t error_code;
@@ -1017,6 +1059,63 @@ typedef enum {
 	SSS_FLAG_PRINT_COMMAND	= 0x01
 } scsi_sense_string_flags;
 
+typedef union scsi_cdb {
+	struct scsi_generic		generic;
+	struct scsi_sense		sense;
+	struct scsi_test_unit_ready	test_unit_ready;
+	struct scsi_send_diag		send_diag;
+	struct scsi_inquiry		inquiry;
+	struct scsi_mode_sense_6	mode_sense_6;
+	struct scsi_mode_sense_10	mode_sense_10;
+	struct scsi_mode_select_6	mode_select_6;
+	struct scsi_mode_select_10	mode_select_10;
+	struct scsi_log_sense		log_sense;
+	struct scsi_log_select		log_select;
+	struct scsi_reserve		reserve;
+	struct scsi_release		release;
+	struct scsi_prevent		prevent;
+	struct scsi_sync_cache		sync_cache;
+	struct scsi_changedef		changedef;
+	struct scsi_read_buffer		read_buffer;
+	struct scsi_write_buffer	write_buffer;
+	struct scsi_rw_6		rw_6;
+	struct scsi_rw_10		rw_10;
+	struct scsi_rw_12		rw_12;
+	struct scsi_rw_16		rw_16;
+	struct scsi_start_stop_unit	start_stop_unit;
+	struct ata_pass_12 		ata_pass_12;
+	struct ata_pass_16 		ata_pass_16;
+	struct scsi_read_capacity	read_capacity;
+	struct scsi_read_capacity_16	read_capacity_16;
+	struct scsi_report_luns		report_luns;
+} *scsi_cdb_t;
+
+typedef union scsi_data {
+	struct scsi_mode_hdr_6			mode_hdr_6;
+	struct scsi_mode_hdr_10			mode_hdr_10;
+	struct scsi_mode_block_descr		mode_block_descr;
+	struct scsi_log_header			log_header;
+	struct scsi_log_param_header		log_param_header;
+	struct scsi_control_page		control_page;
+	struct scsi_cache_page			cache_page;
+	struct scsi_info_exceptions_page	info_exceptions_page;
+	struct scsi_proto_specific_page		proto_specific_page;
+	struct scsi_inquiry_data		inquiry_data;
+	struct scsi_vpd_supported_page_list	vpd_supported_page_list;
+	struct scsi_vpd_unit_serial_number	vpd_unit_serial_number;
+	struct scsi_vpd_unit_devid		vpd_unit_devid;
+	struct scsi_read_capacity_data		read_capacity_data;
+	struct scsi_read_capacity_data_16	read_capacity_data_16;
+	struct scsi_report_luns_data		report_luns_data;
+	struct scsi_sense_data			sense_data;
+	struct scsi_mode_header_6		mode_header_6;
+	struct scsi_mode_header_10		mode_header_10;
+	struct scsi_mode_page_header		mode_page_header;
+	struct scsi_mode_blk_desc		mode_blk_desc;
+	struct scsi_inquiry_pattern		inquiry_pattern;
+	struct scsi_static_inquiry_pattern	static_inquiry_pattern;
+} *scsi_data_t;
+
 struct ccb_scsiio;
 struct cam_periph;
 union  ccb;
@@ -1166,7 +1265,7 @@ void		scsi_read_capacity_16(struct ccb_scsiio *csio, uint32_t retries,
 				    void (*cbfcnp)(struct cam_periph *,
 				    union ccb *), uint8_t tag_action,
 				    uint64_t lba, int reladr, int pmi,
-				    struct scsi_read_capacity_data_long
+				    struct scsi_read_capacity_data_16
 				    *rcap_buf, uint8_t sense_len,
 				    uint32_t timeout);
 
diff --git a/sys/bus/cam/scsi/scsi_da.c b/sys/bus/cam/scsi/scsi_da.c
index 61949fb953..4a8714370b 100644
--- a/sys/bus/cam/scsi/scsi_da.c
+++ b/sys/bus/cam/scsi/scsi_da.c
@@ -1011,8 +1011,8 @@ dadump(struct dev_dump_args *ap)
 				va = pmap_kenter_temporary(trunc_page(0), i);
 		}
 
-		periph->flags |= CAM_PERIPH_POLLED;
 		xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
+		csio.ccb_h.flags |= CAM_POLLED;
 		csio.ccb_h.ccb_state = DA_CCB_DUMP;
 		scsi_read_write(&csio,
 				/*retries*/1,
@@ -1037,7 +1037,6 @@ dadump(struct dev_dump_args *ap)
 			else
 				kprintf("status == 0x%x, scsi status == 0x%x\n",
 				       csio.ccb_h.status, csio.scsi_status);
-			periph->flags |= CAM_PERIPH_POLLED;
 			return(EIO);
 		}
 		
@@ -1087,7 +1086,6 @@ dadump(struct dev_dump_args *ap)
 			}
 		}
 	}
-	periph->flags &= ~CAM_PERIPH_POLLED;
 	cam_periph_unlock(periph);
 	return (0);
 }
@@ -1604,10 +1602,10 @@ dastart(struct cam_periph *periph, union ccb *start_ccb)
 	case DA_STATE_PROBE2:
 	{
 		struct ccb_scsiio *csio;
-		struct scsi_read_capacity_data_long *rcaplong;
+		struct scsi_read_capacity_data_16 *rcaplong;
 
-		rcaplong = (struct scsi_read_capacity_data_long *)
-		kmalloc(sizeof(*rcaplong), M_SCSIDA, M_INTWAIT | M_ZERO);
+		rcaplong = kmalloc(sizeof(*rcaplong), M_SCSIDA,
+				   M_INTWAIT | M_ZERO);
 		if (rcaplong == NULL) {
 			kprintf("dastart: Couldn't allocate read_capacity\n");
 			/* da_free_periph??? */
@@ -1782,7 +1780,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
 	case DA_CCB_PROBE2:
 	{
 		struct	   scsi_read_capacity_data *rdcap;
-		struct     scsi_read_capacity_data_long *rcaplong;
+		struct     scsi_read_capacity_data_16 *rcaplong;
 		char	   announce_buf[80];
 
 		rdcap = NULL;
@@ -1790,7 +1788,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
 		if (softc->state == DA_STATE_PROBE)
 			rdcap =(struct scsi_read_capacity_data *)csio->data_ptr;
 		else
-			rcaplong = (struct scsi_read_capacity_data_long *)
+			rcaplong = (struct scsi_read_capacity_data_16 *)
 				    csio->data_ptr;
 		
 		if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
@@ -2051,7 +2049,7 @@ dagetcapacity(struct cam_periph *periph)
 	struct da_softc *softc;
 	union ccb *ccb;
 	struct scsi_read_capacity_data *rcap;
-	struct scsi_read_capacity_data_long *rcaplong;
+	struct scsi_read_capacity_data_16 *rcaplong;
 	uint32_t block_len;
 	uint64_t maxsector;
 	int error;
@@ -2096,7 +2094,7 @@ dagetcapacity(struct cam_periph *periph)
 	} else
 		goto done;
  
-	rcaplong = (struct scsi_read_capacity_data_long *)rcap;
+	rcaplong = (struct scsi_read_capacity_data_16 *)rcap;
  
 	scsi_read_capacity_16(&ccb->csio,
 			      /*retries*/ 4,
diff --git a/sys/bus/pci/pcidevs b/sys/bus/pci/pcidevs
index ca954bb8f4..0530fefb26 100644
--- a/sys/bus/pci/pcidevs
+++ b/sys/bus/pci/pcidevs
@@ -919,6 +919,7 @@ product ATI RADEON_IGP_320M	0x4336	Radeon IGP 320M
 product ATI RADEON_M6_U2	0x4337	Radeon Mobility M6
 product ATI MACH64_CT		0x4354	Mach64 CT
 product ATI MACH64_CX		0x4358	Mach64 CX
+product ATI SB600_SATA		0x4380  SB600 SATA
 product ATI RAGE_PRO_AGP	0x4742	3D Rage Pro (AGP)
 product ATI RAGE_PRO_AGP1X	0x4744	3D Rage Pro (AGP 1x)
 product ATI RAGE_PRO_PCI_B	0x4749	3D Rage Pro Turbo
@@ -2296,6 +2297,10 @@ product NVIDIA	MCP61_LAN1	0x03e5	MCP61 Lan
 product NVIDIA	MCP61_LAN2	0x03e6	MCP61 Lan
 product NVIDIA	MCP61_LAN3	0x03ee	MCP61 Lan
 product NVIDIA	MCP61_LAN4	0x03ef	MCP61 Lan
+product NVIDIA	MCP65_AHCI_1	0x044c	MCP65 AHCI
+product NVIDIA	MCP65_AHCI_2	0x044d	MCP65 AHCI
+product NVIDIA	MCP65_AHCI_3	0x044e	MCP65 AHCI
+product NVIDIA	MCP65_AHCI_4	0x044f	MCP65 AHCI
 product NVIDIA	MCP65_LAN1	0x0450	MCP65 Lan
 product NVIDIA	MCP65_LAN2	0x0451	MCP65 Lan
 product NVIDIA	MCP65_LAN3	0x0452	MCP65 Lan
@@ -2304,6 +2309,18 @@ product NVIDIA	MCP67_LAN1	0x054c	MCP67 Lan
 product NVIDIA	MCP67_LAN2	0x054d	MCP67 Lan
 product NVIDIA	MCP67_LAN3	0x054e	MCP67 Lan
 product NVIDIA	MCP67_LAN4	0x054f	MCP67 Lan
+product NVIDIA	MCP67_SATA	0x0550	MCP67 SATA
+product NVIDIA	MCP67_SATA2	0x0551	MCP67 SATA
+product NVIDIA	MCP67_SATA3	0x0552	MCP67 SATA
+product NVIDIA	MCP67_SATA4	0x0553	MCP67 SATA
+product NVIDIA	MCP67_AHCI_1	0x0554	MCP67 AHCI
+product NVIDIA	MCP67_AHCI_2	0x0555	MCP67 AHCI
+product NVIDIA	MCP67_AHCI_3	0x0556	MCP67 AHCI
+product NVIDIA	MCP67_AHCI_4	0x0557	MCP67 AHCI
+product NVIDIA	MCP67_AHCI_5	0x0558	MCP67 AHCI
+product NVIDIA	MCP67_AHCI_6	0x0559	MCP67 AHCI
+product NVIDIA	MCP67_AHCI_7	0x055a	MCP67 AHCI
+product NVIDIA	MCP67_AHCI_8	0x055b	MCP67 AHCI
 product NVIDIA	MCP77_LAN1	0x0760	MCP77 Lan
 product NVIDIA	MCP77_LAN2	0x0761	MCP77 Lan
 product NVIDIA	MCP77_LAN3	0x0762	MCP77 Lan
@@ -2312,10 +2329,35 @@ product NVIDIA	MCP73_LAN1	0x07dc	MCP73 Lan
 product NVIDIA	MCP73_LAN2	0x07dd	MCP73 Lan
 product NVIDIA	MCP73_LAN3	0x07de	MCP73 Lan
 product NVIDIA	MCP73_LAN4	0x07df	MCP73 Lan
+product NVIDIA	MCP73_AHCI_1	0x07f0	MCP73 AHCI
+product NVIDIA	MCP73_AHCI_2	0x07f1	MCP73 AHCI
+product NVIDIA	MCP73_AHCI_3	0x07f2	MCP73 AHCI
+product NVIDIA	MCP73_AHCI_4	0x07f3	MCP73 AHCI
+product NVIDIA	MCP73_AHCI_5	0x07f4	MCP73 AHCI
+product NVIDIA	MCP73_AHCI_6	0x07f5	MCP73 AHCI
+product NVIDIA	MCP73_AHCI_7	0x07f6	MCP73 AHCI
+product NVIDIA	MCP73_AHCI_8	0x07f7	MCP73 AHCI
+product NVIDIA	MCP73_AHCI_9	0x07f8	MCP73 AHCI
+product NVIDIA	MCP73_AHCI_10	0x07f9	MCP73 AHCI
+product NVIDIA	MCP73_AHCI_11	0x07fa	MCP73 AHCI
+product NVIDIA	MCP73_AHCI_12	0x07fb	MCP73 AHCI
 product NVIDIA	MCP79_LAN1	0x0ab0	MCP79 Lan
 product NVIDIA	MCP79_LAN2	0x0ab1	MCP79 Lan
 product NVIDIA	MCP79_LAN3	0x0ab2	MCP79 Lan
 product NVIDIA	MCP79_LAN4	0x0ab3	MCP79 Lan
+product NVIDIA	MCP77_AHCI_1	0x0ad0	MCP77 AHCI
+product NVIDIA	MCP77_AHCI_2	0x0ad1	MCP77 AHCI
+product NVIDIA	MCP77_AHCI_3	0x0ad2	MCP77 AHCI
+product NVIDIA	MCP77_AHCI_4	0x0ad3	MCP77 AHCI
+product NVIDIA	MCP77_AHCI_5	0x0ad4	MCP77 AHCI
+product NVIDIA	MCP77_AHCI_6	0x0ad5	MCP77 AHCI
+product NVIDIA	MCP77_AHCI_7	0x0ad6	MCP77 AHCI
+product NVIDIA	MCP77_AHCI_8	0x0ad7	MCP77 AHCI
+product NVIDIA	MCP77_AHCI_9	0x0ad8	MCP77 AHCI
+product NVIDIA	MCP77_AHCI_10	0x0ad9	MCP77 AHCI
+product NVIDIA	MCP77_AHCI_11	0x0ada	MCP77 AHCI
+product NVIDIA	MCP77_AHCI_12	0x0adb	MCP77 AHCI
+
 
 /* Nvidia Corporation & SGS-Thomson Microelectronics */
 product NVIDIA_SGS	RIVA128	0x0018	Riva 128
@@ -2909,6 +2951,7 @@ product VIATECH VT8237_SATA	0x3149	VT8237 Integrated SATA Controller
 product VIATECH VT8235		0x3177	VT8235 (Apollo KT400) PCI-ISA Bridge
 product VIATECH VT8377		0x3189	VT8377 Apollo KT400 CPU to PCI Bridge
 product VIATECH VT8237		0x3227	VT8237 (Apollo KT600) PCI-ISA Bridge
+product VIATECH VT8251_SATA	0x3349  VT8251 SATA
 product VIATECH VT86C100A	0x6100	VT86C100A (Rhine-II) 10/100 Ethernet
 product VIATECH VT8231		0x8231	VT8231 IDE Controller
 product VIATECH VT8363_PPB	0x8305	VT8363 KT133 PCI to AGP Bridge
diff --git a/sys/bus/pci/pcidevs.h b/sys/bus/pci/pcidevs.h
index f77d35f337..f3c60f02fc 100644
--- a/sys/bus/pci/pcidevs.h
+++ b/sys/bus/pci/pcidevs.h
@@ -921,6 +921,7 @@
 #define	PCI_PRODUCT_ATI_RADEON_M6_U2	0x4337		/* Radeon Mobility M6 */
 #define	PCI_PRODUCT_ATI_MACH64_CT	0x4354		/* Mach64 CT */
 #define	PCI_PRODUCT_ATI_MACH64_CX	0x4358		/* Mach64 CX */
+#define	PCI_PRODUCT_ATI_SB600_SATA	0x4380		/* SB600 SATA */
 #define	PCI_PRODUCT_ATI_RAGE_PRO_AGP	0x4742		/* 3D Rage Pro (AGP) */
 #define	PCI_PRODUCT_ATI_RAGE_PRO_AGP1X	0x4744		/* 3D Rage Pro (AGP 1x) */
 #define	PCI_PRODUCT_ATI_RAGE_PRO_PCI_B	0x4749		/* 3D Rage Pro Turbo */
@@ -2298,6 +2299,10 @@
 #define	PCI_PRODUCT_NVIDIA_MCP61_LAN2	0x03e6		/* MCP61 Lan */
 #define	PCI_PRODUCT_NVIDIA_MCP61_LAN3	0x03ee		/* MCP61 Lan */
 #define	PCI_PRODUCT_NVIDIA_MCP61_LAN4	0x03ef		/* MCP61 Lan */
+#define	PCI_PRODUCT_NVIDIA_MCP65_AHCI_1	0x044c		/* MCP65 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP65_AHCI_2	0x044d		/* MCP65 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP65_AHCI_3	0x044e		/* MCP65 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP65_AHCI_4	0x044f		/* MCP65 AHCI */
 #define	PCI_PRODUCT_NVIDIA_MCP65_LAN1	0x0450		/* MCP65 Lan */
 #define	PCI_PRODUCT_NVIDIA_MCP65_LAN2	0x0451		/* MCP65 Lan */
 #define	PCI_PRODUCT_NVIDIA_MCP65_LAN3	0x0452		/* MCP65 Lan */
@@ -2306,6 +2311,18 @@
 #define	PCI_PRODUCT_NVIDIA_MCP67_LAN2	0x054d		/* MCP67 Lan */
 #define	PCI_PRODUCT_NVIDIA_MCP67_LAN3	0x054e		/* MCP67 Lan */
 #define	PCI_PRODUCT_NVIDIA_MCP67_LAN4	0x054f		/* MCP67 Lan */
+#define	PCI_PRODUCT_NVIDIA_MCP67_SATA	0x0550		/* MCP67 SATA */
+#define	PCI_PRODUCT_NVIDIA_MCP67_SATA2	0x0551		/* MCP67 SATA */
+#define	PCI_PRODUCT_NVIDIA_MCP67_SATA3	0x0552		/* MCP67 SATA */
+#define	PCI_PRODUCT_NVIDIA_MCP67_SATA4	0x0553		/* MCP67 SATA */
+#define	PCI_PRODUCT_NVIDIA_MCP67_AHCI_1	0x0554		/* MCP67 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP67_AHCI_2	0x0555		/* MCP67 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP67_AHCI_3	0x0556		/* MCP67 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP67_AHCI_4	0x0557		/* MCP67 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP67_AHCI_5	0x0558		/* MCP67 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP67_AHCI_6	0x0559		/* MCP67 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP67_AHCI_7	0x055a		/* MCP67 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP67_AHCI_8	0x055b		/* MCP67 AHCI */
 #define	PCI_PRODUCT_NVIDIA_MCP77_LAN1	0x0760		/* MCP77 Lan */
 #define	PCI_PRODUCT_NVIDIA_MCP77_LAN2	0x0761		/* MCP77 Lan */
 #define	PCI_PRODUCT_NVIDIA_MCP77_LAN3	0x0762		/* MCP77 Lan */
@@ -2314,10 +2331,35 @@
 #define	PCI_PRODUCT_NVIDIA_MCP73_LAN2	0x07dd		/* MCP73 Lan */
 #define	PCI_PRODUCT_NVIDIA_MCP73_LAN3	0x07de		/* MCP73 Lan */
 #define	PCI_PRODUCT_NVIDIA_MCP73_LAN4	0x07df		/* MCP73 Lan */
+#define	PCI_PRODUCT_NVIDIA_MCP73_AHCI_1	0x07f0		/* MCP73 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP73_AHCI_2	0x07f1		/* MCP73 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP73_AHCI_3	0x07f2		/* MCP73 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP73_AHCI_4	0x07f3		/* MCP73 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP73_AHCI_5	0x07f4		/* MCP73 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP73_AHCI_6	0x07f5		/* MCP73 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP73_AHCI_7	0x07f6		/* MCP73 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP73_AHCI_8	0x07f7		/* MCP73 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP73_AHCI_9	0x07f8		/* MCP73 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP73_AHCI_10	0x07f9		/* MCP73 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP73_AHCI_11	0x07fa		/* MCP73 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP73_AHCI_12	0x07fb		/* MCP73 AHCI */
 #define	PCI_PRODUCT_NVIDIA_MCP79_LAN1	0x0ab0		/* MCP79 Lan */
 #define	PCI_PRODUCT_NVIDIA_MCP79_LAN2	0x0ab1		/* MCP79 Lan */
 #define	PCI_PRODUCT_NVIDIA_MCP79_LAN3	0x0ab2		/* MCP79 Lan */
 #define	PCI_PRODUCT_NVIDIA_MCP79_LAN4	0x0ab3		/* MCP79 Lan */
+#define	PCI_PRODUCT_NVIDIA_MCP77_AHCI_1	0x0ad0		/* MCP77 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP77_AHCI_2	0x0ad1		/* MCP77 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP77_AHCI_3	0x0ad2		/* MCP77 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP77_AHCI_4	0x0ad3		/* MCP77 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP77_AHCI_5	0x0ad4		/* MCP77 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP77_AHCI_6	0x0ad5		/* MCP77 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP77_AHCI_7	0x0ad6		/* MCP77 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP77_AHCI_8	0x0ad7		/* MCP77 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP77_AHCI_9	0x0ad8		/* MCP77 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP77_AHCI_10	0x0ad9		/* MCP77 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP77_AHCI_11	0x0ada		/* MCP77 AHCI */
+#define	PCI_PRODUCT_NVIDIA_MCP77_AHCI_12	0x0adb		/* MCP77 AHCI */
+
 
 /* Nvidia Corporation & SGS-Thomson Microelectronics */
 #define	PCI_PRODUCT_NVIDIA_SGS_RIVA128	0x0018		/* Riva 128 */
@@ -2911,6 +2953,7 @@
 #define	PCI_PRODUCT_VIATECH_VT8235	0x3177		/* VT8235 (Apollo KT400) PCI-ISA Bridge */
 #define	PCI_PRODUCT_VIATECH_VT8377	0x3189		/* VT8377 Apollo KT400 CPU to PCI Bridge */
 #define	PCI_PRODUCT_VIATECH_VT8237	0x3227		/* VT8237 (Apollo KT600) PCI-ISA Bridge */
+#define	PCI_PRODUCT_VIATECH_VT8251_SATA	0x3349		/* VT8251 SATA */
 #define	PCI_PRODUCT_VIATECH_VT86C100A	0x6100		/* VT86C100A (Rhine-II) 10/100 Ethernet */
 #define	PCI_PRODUCT_VIATECH_VT8231	0x8231		/* VT8231 IDE Controller */
 #define	PCI_PRODUCT_VIATECH_VT8363_PPB	0x8305		/* VT8363 KT133 PCI to AGP Bridge */
diff --git a/sys/bus/pci/pcidevs_data.h b/sys/bus/pci/pcidevs_data.h
index 16b6f8de37..458f36a8e1 100644
--- a/sys/bus/pci/pcidevs_data.h
+++ b/sys/bus/pci/pcidevs_data.h
@@ -1511,6 +1511,12 @@ const struct pci_knowndev pci_knowndevs[] = {
 	    "ATI Technologies",
 	    "Mach64 CX",
 	},
+	{
+	    PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB600_SATA,
+	    0,
+	    "ATI Technologies",
+	    "SB600 SATA",
+	},
 	{
 	    PCI_VENDOR_ATI, PCI_PRODUCT_ATI_RAGE_PRO_AGP,
 	    0,
@@ -8255,6 +8261,30 @@ const struct pci_knowndev pci_knowndevs[] = {
 	    "Nvidia Corporation",
 	    "MCP61 Lan",
 	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_AHCI_1,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP65 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_AHCI_2,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP65 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_AHCI_3,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP65 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_AHCI_4,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP65 AHCI",
+	},
 	{
 	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN1,
 	    0,
@@ -8303,6 +8333,78 @@ const struct pci_knowndev pci_knowndevs[] = {
 	    "Nvidia Corporation",
 	    "MCP67 Lan",
 	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_SATA,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP67 SATA",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_SATA2,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP67 SATA",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_SATA3,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP67 SATA",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_SATA4,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP67 SATA",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_1,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP67 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_2,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP67 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_3,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP67 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_4,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP67 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_5,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP67 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_6,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP67 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_7,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP67 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_8,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP67 AHCI",
+	},
 	{
 	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_LAN1,
 	    0,
@@ -8351,6 +8453,78 @@ const struct pci_knowndev pci_knowndevs[] = {
 	    "Nvidia Corporation",
 	    "MCP73 Lan",
 	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_1,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP73 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_2,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP73 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_3,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP73 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_4,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP73 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_5,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP73 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_6,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP73 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_7,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP73 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_8,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP73 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_9,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP73 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_10,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP73 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_11,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP73 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_12,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP73 AHCI",
+	},
 	{
 	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_LAN1,
 	    0,
@@ -8375,6 +8549,78 @@ const struct pci_knowndev pci_knowndevs[] = {
 	    "Nvidia Corporation",
 	    "MCP79 Lan",
 	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_1,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP77 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_2,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP77 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_3,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP77 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_4,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP77 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_5,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP77 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_6,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP77 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_7,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP77 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_8,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP77 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_9,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP77 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_10,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP77 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_11,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP77 AHCI",
+	},
+	{
+	    PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_12,
+	    0,
+	    "Nvidia Corporation",
+	    "MCP77 AHCI",
+	},
 	{
 	    PCI_VENDOR_NVIDIA_SGS, PCI_PRODUCT_NVIDIA_SGS_RIVA128,
 	    0,
@@ -11171,6 +11417,12 @@ const struct pci_knowndev pci_knowndevs[] = {
 	    "VIA Technologies",
 	    "VT8237 (Apollo KT600) PCI-ISA Bridge",
 	},
+	{
+	    PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8251_SATA,
+	    0,
+	    "VIA Technologies",
+	    "VT8251 SATA",
+	},
 	{
 	    PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT86C100A,
 	    0,
diff --git a/sys/bus/pci/pcireg.h b/sys/bus/pci/pcireg.h
index a1e8d403a4..98a0fdd3f6 100644
--- a/sys/bus/pci/pcireg.h
+++ b/sys/bus/pci/pcireg.h
@@ -28,6 +28,26 @@
  *
  */
 
+#ifndef _BUS_PCI_PCIREG_H_
+#define _BUS_PCI_PCIREG_H_
+
+#ifndef _SYS_TYPES_H_
+#include 
+#endif
+
+typedef u_int16_t pci_vendor_id_t;
+typedef u_int16_t pci_product_id_t;
+
+typedef u_int8_t pci_class_t;
+typedef u_int8_t pci_subclass_t;
+typedef u_int8_t pci_interface_t;
+typedef u_int8_t pci_revision_t;
+
+typedef u_int8_t pci_intr_pin_t;
+typedef u_int8_t pci_intr_line_t;
+
+typedef u_int32_t pcireg_t;		/* ~typical configuration space */
+
 /*
  * PCIM_xxx: mask to locate subfield in register
  * PCIR_xxx: config register offset
@@ -49,17 +69,19 @@
 
 /* PCI config header registers for all devices */
 
-#define PCIR_DEVVENDOR	0x00
-#define PCIR_VENDOR	0x00
-#define PCIR_DEVICE	0x02
-#define PCIR_COMMAND	0x04
+#define PCIR_DEVVENDOR		0x00
+#define PCIR_VENDOR		0x00
+#define PCIR_DEVICE		0x02
+
+#define PCIR_COMMAND		0x04
 #define PCIM_CMD_PORTEN		0x0001
 #define PCIM_CMD_MEMEN		0x0002
 #define PCIM_CMD_BUSMASTEREN	0x0004
 #define PCIM_CMD_MWRICEN	0x0010
 #define PCIM_CMD_PERRESPEN	0x0040
 #define	PCIM_CMD_SERRESPEN	0x0100
-#define PCIR_STATUS	0x06
+
+#define PCIR_STATUS		0x06
 #define PCIM_STATUS_CAPPRESENT	0x0010
 #define PCIM_STATUS_66CAPABLE	0x0020
 #define PCIM_STATUS_BACKTOBACK	0x0080
@@ -73,19 +95,22 @@
 #define PCIM_STATUS_RMABORT	0x2000
 #define PCIM_STATUS_SERR	0x4000
 #define PCIM_STATUS_PERR	0x8000
-#define PCIR_REVID	0x08
-#define PCIR_PROGIF	0x09
-#define PCIR_SUBCLASS	0x0a
-#define PCIR_CLASS	0x0b
-#define PCIR_CACHELNSZ	0x0c
-#define PCIR_LATTIMER	0x0d
-#define PCIR_HDRTYPE	0x0e
-#define PCIM_HDRTYPE	0x7f
+
+#define PCIR_REVID		0x08
+#define PCIR_PROGIF		0x09
+#define PCIR_SUBCLASS		0x0a
+#define PCIR_CLASS		0x0b
+#define PCIR_CACHELNSZ		0x0c
+#define PCIR_LATTIMER		0x0d
+
+#define PCIR_HDRTYPE		0x0e
+#define PCIM_HDRTYPE		0x7f
 #define PCIM_HDRTYPE_NORMAL     0x00
 #define PCIM_HDRTYPE_BRIDGE     0x01  
 #define PCIM_HDRTYPE_CARDBUS    0x02  
-#define PCIM_MFDEV	0x80
-#define PCIR_BIST	0x0f
+#define PCIM_MFDEV		0x80
+
+#define PCIR_BIST		0x0f
 
 /* Capability Register Offsets */
 #define PCICAP_ID	0x0
@@ -514,3 +539,5 @@
 #define	PCI_INTERRUPT_REG	0x3c
 
 #endif /* COMPAT_OLDPCI */
+
+#endif
diff --git a/sys/conf/files b/sys/conf/files
index 876cdf6416..fbcec20206 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -143,6 +143,10 @@ dev/disk/ata/atapi-cd.c			optional atapicd
 dev/disk/ata/atapi-fd.c			optional atapifd
 dev/disk/ata/atapi-tape.c		optional atapist
 dev/disk/ata/atapi-cam.c		optional atapicam
+dev/disk/ahci/ahci.c			optional ahci
+dev/disk/ahci/ahci_dragonfly.c		optional ahci
+dev/disk/ahci/ahci_attach.c		optional ahci
+dev/disk/ahci/ahci_cam.c		optional ahci
 dev/disk/nata/ata_if.m			optional nata
 dev/disk/nata/ata-all.c			optional nata
 dev/disk/nata/ata-card.c		optional nata pccard
@@ -180,8 +184,82 @@ dev/disk/aic7xxx/ahd_pci.c		optional ahd pci
 dev/disk/aic7xxx/aic79xx.c		optional ahd pci
 dev/disk/aic7xxx/aic79xx_osm.c		optional ahd pci
 dev/disk/aic7xxx/aic79xx_pci.c		optional ahd pci
-dev/netif/ath/hal/ah_osdep.c		optional ath_hal \
-	compile-with "${NORMAL_C} -I$S/dev/netif/ath/ath"
+dev/netif/ath/hal/ah_osdep.c				optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5211/ar5211_attach.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5211/ar5211_power.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5211/ar5211_keycache.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5211/ar5211_beacon.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5211/ar5211_recv.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5211/ar5211_misc.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5211/ar5211_xmit.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5211/ar5211_reset.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5211/ar5211_phy.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5211/ar5211_interrupts.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ah_regdomain.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ah_eeprom_v1.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ah_eeprom_v3.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_power.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal_adcgain.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_ani.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_attach.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_beacon.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_keycache.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar9160_attach.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_recv.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_gpio.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_eeprom.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_reset.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar2133.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal_adcdc.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_interrupts.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_xmit.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_misc.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_phy.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal_iq.c	optional ath_hal
+# XXX not yet
+# dev/netif/ath/hal/ath_hal/ar5312/ar5312_misc.c	optional ath_hal
+# dev/netif/ath/hal/ath_hal/ar5312/ar5312_interrupts.c	optional ath_hal
+# dev/netif/ath/hal/ath_hal/ar5312/ar5312_reset.c	optional ath_hal
+# dev/netif/ath/hal/ath_hal/ar5312/ar5312_eeprom.c	optional ath_hal
+# dev/netif/ath/hal/ath_hal/ar5312/ar5312_gpio.c	optional ath_hal
+# dev/netif/ath/hal/ath_hal/ar5312/ar5315_gpio.c	optional ath_hal
+# dev/netif/ath/hal/ath_hal/ar5312/ar5312_power.c	optional ath_hal
+# dev/netif/ath/hal/ath_hal/ar5312/ar5312_attach.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5212_rfgain.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5212_interrupts.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5212_ani.c		optional ath_hal
+# XXX not yet
+# dev/netif/ath/hal/ath_hal/ar5212/ar2316.c		optional ath_hal
+# dev/netif/ath/hal/ath_hal/ar5212/ar2317.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar2413.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5413.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5212_power.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar2425.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5212_recv.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5212_gpio.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5212_beacon.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5212_misc.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5212_xmit.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5212_eeprom.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5212_keycache.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5212_phy.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5212_attach.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5212_reset.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5111.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5212/ar5112.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ah.c				optional ath_hal
+dev/netif/ath/hal/ath_hal/ah_eeprom_v14.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5210/ar5210_misc.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5210/ar5210_xmit.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5210/ar5210_power.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5210/ar5210_keycache.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5210/ar5210_beacon.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5210/ar5210_reset.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5210/ar5210_interrupts.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5210/ar5210_attach.c	optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5210/ar5210_recv.c		optional ath_hal
+dev/netif/ath/hal/ath_hal/ar5210/ar5210_phy.c		optional ath_hal
 dev/netif/ath/rate_amrr/amrr.c		optional ath_rate_amrr \
 	compile-with "${NORMAL_C} -I$S/dev/netif/ath/ath"
 dev/netif/ath/rate_onoe/onoe.c		optional ath_rate_onoe \
diff --git a/sys/conf/kern.post.mk b/sys/conf/kern.post.mk
index 09c9de0276..82626045a2 100644
--- a/sys/conf/kern.post.mk
+++ b/sys/conf/kern.post.mk
@@ -225,7 +225,7 @@ ioconf.o:
 	${NORMAL_C}
 
 vers.c: $S/conf/newvers.sh $S/sys/param.h ${SYSTEM_DEP}
-	sh $S/conf/newvers.sh ${KERN_IDENT} ${IDENT}
+	sh $S/conf/newvers.sh $S/..
 
 # XXX strictly, everything depends on Makefile because changes to ${PROF}
 # only appear there, but we don't handle that.
diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk
index 675d43cf89..5d89d0dbd7 100644
--- a/sys/conf/kern.pre.mk
+++ b/sys/conf/kern.pre.mk
@@ -51,7 +51,7 @@ INCLUDES+= -I${.OBJDIR} -I"$S/${OSACPI_MI_DIR}" -I"$S/${ACPICA_DIR}/include"
 INCLUDES+= -I$S/contrib/ipfilter
 
 # ... and the same for Atheros HAL
-INCLUDES+= -I$S/dev/netif/ath/hal
+INCLUDES+= -I$S/dev/netif/ath/hal -I$S/dev/netif/ath/hal/ath_hal
 
 COPTS=	${INCLUDES} ${IDENT} -D_KERNEL -include opt_global.h
 CFLAGS=	${COPTFLAGS} ${CWARNFLAGS} ${DEBUG} ${COPTS}
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index 47c6ed47eb..a94a3bb304 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -35,6 +35,13 @@
 # $FreeBSD: src/sys/conf/newvers.sh,v 1.44.2.30 2003/04/04 07:02:46 murray Exp $
 # $DragonFly: src/sys/conf/newvers.sh,v 1.23 2008/07/14 04:01:44 dillon Exp $
 
+# The directory where the source resides
+#
+SRCDIR=$1
+if [ "${SRCDIR}" = "" ]; then
+    SRCDIR=$(dirname $0)/../..
+fi
+
 # Set the branch
 #
 BRANCH="DEVELOPMENT_2_3"
@@ -63,15 +70,13 @@ if [ "${REVISION}" != "${BRANCH}" ]; then
     REVISION=$(echo $REVISION | sed -e 's/_/./g')
 fi
 
-for chkdir in machine/../../.. .. ../.. ../../.. /usr/src; do
-    if [ -f ${chkdir}/sys/conf/subvers-${SHORTTAG} ]; then
-	SUBVER=$(tail -1 ${chkdir}/sys/conf/subvers-${SHORTTAG} | awk '{ print $1; }')
-	if [ "X${SUBVER}" != "X" ]; then
-	    REVISION="${REVISION}.${SUBVER}"
-	    break
-	fi
+if [ -f ${SRCDIR}/sys/conf/subvers-${SHORTTAG} ]; then
+    SUBVER=$(tail -1 ${SRCDIR}/sys/conf/subvers-${SHORTTAG} | awk '{ print $1; }')
+    if [ "X${SUBVER}" != "X" ]; then
+	REVISION="${REVISION}.${SUBVER}"
+	break
     fi
-done
+fi
 
 RELEASE="${REVISION}-${BRANCH}"
 VERSION="${TYPE} ${RELEASE}"
@@ -81,24 +86,19 @@ if [ "X${PARAMFILE}" != "X" ]; then
 		${PARAMFILE})
 else
 	RELDATE=$(awk '/__DragonFly_version.*propagated to newvers/ {print $3}' \
-		$(dirname $0)/../sys/param.h)
+		${SRCDIR}/sys/sys/param.h)
 fi
 
 
-b=share/examples/etc/bsd-style-copyright
 year=`date '+%Y'`
 # look for copyright template
-for bsd_copyright in ../$b ../../$b ../../../$b /usr/src/$b /usr/$b
-do
-	if [ -r "$bsd_copyright" ]; then
-		COPYRIGHT=`sed \
-		    -e "s/\[year\]/$year/" \
-		    -e 's/\[your name\]\.*/The DragonFly Project/' \
-		    -e '/\[id for your version control system, if any\]/d' \
-		    $bsd_copyright` 
-		break
-	fi
-done
+if [ -r ${SRCDIR}/share/examples/etc/bsd-style-copyright ]; then
+    COPYRIGHT=`sed \
+	-e "s/\[year\]/$year/" \
+	-e 's/\[your name\]\.*/The DragonFly Project/' \
+	-e '/\[id for your version control system, if any\]/d' \
+	${SRCDIR}/share/examples/etc/bsd-style-copyright`
+fi
 
 # no copyright found, use a dummy
 if [ X"$COPYRIGHT" = X ]; then
diff --git a/sys/conf/options b/sys/conf/options
index 34965eb9b6..4105cb6014 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -613,6 +613,9 @@ ATH_DIAGAPI		opt_ath.h
 ATH_RXBUF		opt_ath.h
 ATH_TXBUF		opt_ath.h
 
+# ...and its HAL
+AH_SUPPORT_AR5416	opt_ah.h
+
 # bce driver
 BCE_DEBUG		opt_bce.h
 BCE_NVRAM_WRITE_SUPPORT	opt_bce.h
diff --git a/sys/conf/subvers-DEVELOPMENT_2_1 b/sys/conf/subvers-DEVELOPMENT_2_1
deleted file mode 100644
index 70d9f80878..0000000000
--- a/sys/conf/subvers-DEVELOPMENT_2_1
+++ /dev/null
@@ -1,4 +0,0 @@
-# Subversion control for DragonFly 2.1.X-DEVELOPMENT
-# $DragonFly: src/sys/conf/subvers-DEVELOPMENT_2_1,v 1.1 2008/07/14 04:01:44 dillon Exp $
-0	-
-1	-
diff --git a/sys/conf/subvers-DEVELOPMENT_2_3 b/sys/conf/subvers-DEVELOPMENT_2_3
index 6d290b48e4..3a00df3f11 100644
--- a/sys/conf/subvers-DEVELOPMENT_2_3
+++ b/sys/conf/subvers-DEVELOPMENT_2_3
@@ -1,3 +1,4 @@
 # Subversion control for DragonFly 2.3.X-DEVELOPMENT
 #
 0	-
+1	-
diff --git a/sys/config/LINT b/sys/config/LINT
index 5fb4570e6b..6cc52bf20a 100644
--- a/sys/config/LINT
+++ b/sys/config/LINT
@@ -1269,6 +1269,11 @@ device	ips
 #device		atapist		# ATAPI tape drives
 #device		atapicam	# emulate ATAPI devices as SCSI ditto via CAM
 				# needs CAM to be present (scbus & pass)
+# AHCI driver, this will override NATA for AHCI devices,
+# both drivers may be included.
+#
+device		ahci
+
 # The 'NATA' set of drivers are set to replace the previous ATA drivers,
 # and this set of drivers is mutually exclusive with the old ones. This means,
 # you can't have both at the same time!
diff --git a/sys/contrib/dev/ath/COPYRIGHT b/sys/contrib/dev/ath/COPYRIGHT
deleted file mode 100644
index 3e2752f3f5..0000000000
--- a/sys/contrib/dev/ath/COPYRIGHT
+++ /dev/null
@@ -1,42 +0,0 @@
-All files contained in this distribution are covered by the following
-copyright unless explicitly identified otherwise.  Note that this
-copyright does _NOT_ contain a "or GPL" clause and does _NOT_ permit
-redistribution with changes.
-
-/*-
- * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting, Atheros
- * Communications, Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the following conditions are met:
- * 1. The materials contained herein are unmodified and are used
- *    unmodified.
- * 2. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following NO
- *    ''WARRANTY'' disclaimer below (''Disclaimer''), without
- *    modification.
- * 3. Redistributions in binary form must reproduce at minimum a
- *    disclaimer similar to the Disclaimer below and any redistribution
- *    must be conditioned upon including a substantially similar
- *    Disclaimer requirement for further binary redistribution.
- * 4. Neither the names of the above-listed copyright holders nor the
- *    names of any contributors may be used to endorse or promote
- *    product derived from this software without specific prior written
- *    permission.
- *
- * NO WARRANTY
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT,
- * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
- * FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGES.
- *
- * $Id: //depot/sw/branches/sam_hal/COPYRIGHT#1 $
- */
diff --git a/sys/contrib/dev/ath/README b/sys/contrib/dev/ath/README
deleted file mode 100644
index 5d3b7f5a10..0000000000
--- a/sys/contrib/dev/ath/README
+++ /dev/null
@@ -1,73 +0,0 @@
-$Id: //depot/sw/branches/sam_hal/README#2 $
-
-
-Atheros Hardware Access Layer (HAL)
-===================================
-
-* Copyright (c) 2002-2006 Sam Leffler.
-* Copyright (c) 2002-2006 Atheros Communications, Inc.
-* All rights reserved.
-
-Read the file COPYRIGHT for the complete copyright.
-
-This code manages much of the chip-specific operation of the Atheros
-driver.  The HAL is provided in a binary-only form in order to
-comply with local regulatory agency rules.  In the United States
-the FCC requires that a radio transmitter only be operated at power
-levels and on frequency channels for which it is approved.  The FCC
-requires that a software-defined radio cannot be configured by a
-user to operate outside the approved power levels and frequency
-channels.  This makes it difficult to open-source code that enforces
-limits on the power levels, frequency channels and other parameters
-of the radio transmitter.  See
-
-http://ftp.fcc.gov/Bureaus/Engineering_Technology/Orders/2001/fcc01264.pdf
-
-for the specific FCC regulation.  Because the module is provided
-in a binary-only form it is marked "Proprietary" on Linux; this
-means when you load it you will see messages that your system is
-now "tainted".
-
-If you wish to use this driver on a platform for which an ath_hal
-module is not already provided please contact the author.  Note that
-this is only necessary for new _architectures_; the HAL is not tied to
-any specific version of your operating system.
-
-
-Atheros Hardware
-================
-There are many generations of Atheros 802.11 wireless devices that
-are typically referred to by their programming model:
-
-5210	supports 11a only
-5211	supports both 11a and 11b
-5212	supports 11a, 11b, and 11g
-
-These parts have been incorporated in a variety of retail products
-including cardbus cards and mini-pci cards.  In addition many laptop
-vendors use Atheros mini-pci cards for their builtin wireless
-support.
-
-The Atheors PCI vendor id is 0x168c.  The file ah_devid.h lists most
-known PCI device id's but is not exhaustive.  Some vendors program
-their own vendor and/or device id's to aid in BIOS-locking mini-pci
-cards in laptops.
-
-Atheros SoC Hardware
-====================
-In addition to the cardbus/pci devices Atheros makes System on Chip
-(SoC) parts that integrate a MIPS cpu core and one or more MAC and
-radio parts.  Binary support for these parts is necessarily built
-for the embedded MIPS processor where the code is to be run.
-
-Caveats
-=======
-The binary hal builds provided here include no floating point and
-are operating system-independent.  However due to toolchain
-peculiarities the .o files may be wrongly rejected by development
-tools.  If that happens it may be possible to patch the file header
-so that the native toolchain will accept the files.  In particular
-this has been observed for various Linux MIPS installations for the
-SoC parts.  If you have issues consult the associated .inc file in
-the public directory; it explains exactly how the binary file was
-created (e.g. toolchain and compilation options).
diff --git a/sys/contrib/dev/ath/ah_desc.h b/sys/contrib/dev/ath/ah_desc.h
deleted file mode 100644
index 36e097c179..0000000000
--- a/sys/contrib/dev/ath/ah_desc.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*-
- * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting, Atheros
- * Communications, Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the following conditions are met:
- * 1. The materials contained herein are unmodified and are used
- *    unmodified.
- * 2. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following NO
- *    ''WARRANTY'' disclaimer below (''Disclaimer''), without
- *    modification.
- * 3. Redistributions in binary form must reproduce at minimum a
- *    disclaimer similar to the Disclaimer below and any redistribution
- *    must be conditioned upon including a substantially similar
- *    Disclaimer requirement for further binary redistribution.
- * 4. Neither the names of the above-listed copyright holders nor the
- *    names of any contributors may be used to endorse or promote
- *    product derived from this software without specific prior written
- *    permission.
- *
- * NO WARRANTY
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT,
- * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
- * FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGES.
- *
- * $Id: //depot/sw/branches/sam_hal/ah_desc.h#5 $
- */
-
-#ifndef _DEV_ATH_DESC_H
-#define _DEV_ATH_DESC_H
-
-/*
- * Transmit descriptor status.  This structure is filled
- * in only after the tx descriptor process method finds a
- * ``done'' descriptor; at which point it returns something
- * other than HAL_EINPROGRESS.
- *
- * Note that ts_antenna may not be valid for all h/w.  It
- * should be used only if non-zero.
- */
-struct ath_tx_status {
-	u_int16_t	ts_seqnum;	/* h/w assigned sequence number */
-	u_int16_t	ts_tstamp;	/* h/w assigned timestamp */
-	u_int8_t	ts_status;	/* frame status, 0 => xmit ok */
-	u_int8_t	ts_rate;	/* h/w transmit rate index */
-#define	HAL_TXSTAT_ALTRATE	0x80	/* alternate xmit rate used */
-	int8_t		ts_rssi;	/* tx ack RSSI */
-	u_int8_t	ts_shortretry;	/* # short retries */
-	u_int8_t	ts_longretry;	/* # long retries */
-	u_int8_t	ts_virtcol;	/* virtual collision count */
-	u_int8_t	ts_antenna;	/* antenna information */
-	u_int8_t	ts_finaltsi;	/* final transmit series index */
-};
-
-#define	HAL_TXERR_XRETRY	0x01	/* excessive retries */
-#define	HAL_TXERR_FILT		0x02	/* blocked by tx filtering */
-#define	HAL_TXERR_FIFO		0x04	/* fifo underrun */
-
-/*
- * Receive descriptor status.  This structure is filled
- * in only after the rx descriptor process method finds a
- * ``done'' descriptor; at which point it returns something
- * other than HAL_EINPROGRESS.
- *
- * If rx_status is zero, then the frame was received ok;
- * otherwise the error information is indicated and rs_phyerr
- * contains a phy error code if HAL_RXERR_PHY is set.  In general
- * the frame contents is undefined when an error occurred thought
- * for some errors (e.g. a decryption error), it may be meaningful.
- *
- * Note that the receive timestamp is expanded using the TSF to
- * 15 bits (regardless of what the h/w provides directly).
- *
- * rx_rssi is in units of dbm above the noise floor.  This value
- * is measured during the preamble and PLCP; i.e. with the initial
- * 4us of detection.  The noise floor is typically a consistent
- * -96dBm absolute power in a 20MHz channel.
- */
-struct ath_rx_status {
-	u_int16_t	rs_datalen;	/* rx frame length */
-	u_int16_t	rs_tstamp;	/* h/w assigned timestamp */
-	u_int8_t	rs_status;	/* rx status, 0 => recv ok */
-	u_int8_t	rs_phyerr;	/* phy error code */
-	int8_t		rs_rssi;	/* rx frame RSSI */
-	u_int8_t	rs_keyix;	/* key cache index */
-	u_int8_t	rs_rate;	/* h/w receive rate index */
-	u_int8_t	rs_antenna;	/* antenna information */
-	u_int8_t	rs_more;	/* more descriptors follow */
-};
-
-#define	HAL_RXERR_CRC		0x01	/* CRC error on frame */
-#define	HAL_RXERR_PHY		0x02	/* PHY error, rs_phyerr is valid */
-#define	HAL_RXERR_FIFO		0x04	/* fifo overrun */
-#define	HAL_RXERR_DECRYPT	0x08	/* non-Michael decrypt error */
-#define	HAL_RXERR_MIC		0x10	/* Michael MIC decrypt error */
-
-enum {
-	HAL_PHYERR_UNDERRUN		= 0,	/* Transmit underrun */
-	HAL_PHYERR_TIMING		= 1,	/* Timing error */
-	HAL_PHYERR_PARITY		= 2,	/* Illegal parity */
-	HAL_PHYERR_RATE			= 3,	/* Illegal rate */
-	HAL_PHYERR_LENGTH		= 4,	/* Illegal length */
-	HAL_PHYERR_RADAR		= 5,	/* Radar detect */
-	HAL_PHYERR_SERVICE		= 6,	/* Illegal service */
-	HAL_PHYERR_TOR			= 7,	/* Transmit override receive */
-	/* NB: these are specific to the 5212 */
-	HAL_PHYERR_OFDM_TIMING		= 17,	/* */
-	HAL_PHYERR_OFDM_SIGNAL_PARITY	= 18,	/* */
-	HAL_PHYERR_OFDM_RATE_ILLEGAL	= 19,	/* */
-	HAL_PHYERR_OFDM_LENGTH_ILLEGAL	= 20,	/* */
-	HAL_PHYERR_OFDM_POWER_DROP	= 21,	/* */
-	HAL_PHYERR_OFDM_SERVICE		= 22,	/* */
-	HAL_PHYERR_OFDM_RESTART		= 23,	/* */
-	HAL_PHYERR_CCK_TIMING		= 25,	/* */
-	HAL_PHYERR_CCK_HEADER_CRC	= 26,	/* */
-	HAL_PHYERR_CCK_RATE_ILLEGAL	= 27,	/* */
-	HAL_PHYERR_CCK_SERVICE		= 30,	/* */
-	HAL_PHYERR_CCK_RESTART		= 31,	/* */
-};
-
-/* value found in rs_keyix to mark invalid entries */
-#define	HAL_RXKEYIX_INVALID	((u_int8_t) -1)
-/* value used to specify no encryption key for xmit */
-#define	HAL_TXKEYIX_INVALID	((u_int) -1)
-
-/* XXX rs_antenna definitions */
-
-/*
- * Definitions for the software frame/packet descriptors used by
- * the Atheros HAL.  This definition obscures hardware-specific
- * details from the driver.  Drivers are expected to fillin the
- * portions of a descriptor that are not opaque then use HAL calls
- * to complete the work.  Status for completed frames is returned
- * in a device-independent format.
- */
-struct ath_desc {
-	/*
-	 * The following definitions are passed directly
-	 * the hardware and managed by the HAL.  Drivers
-	 * should not touch those elements marked opaque.
-	 */
-	u_int32_t	ds_link;	/* phys address of next descriptor */
-	u_int32_t	ds_data;	/* phys address of data buffer */
-	u_int32_t	ds_ctl0;	/* opaque DMA control 0 */
-	u_int32_t	ds_ctl1;	/* opaque DMA control 1 */
-	u_int32_t	ds_hw[4];	/* opaque h/w region */
-};
-
-struct ath_desc_status {
-	union {
-		struct ath_tx_status tx;/* xmit status */
-		struct ath_rx_status rx;/* recv status */
-	} ds_us;
-};
-
-#define	ds_txstat	ds_us.tx
-#define	ds_rxstat	ds_us.rx
-
-/* flags passed to tx descriptor setup methods */
-#define	HAL_TXDESC_CLRDMASK	0x0001	/* clear destination filter mask */
-#define	HAL_TXDESC_NOACK	0x0002	/* don't wait for ACK */
-#define	HAL_TXDESC_RTSENA	0x0004	/* enable RTS */
-#define	HAL_TXDESC_CTSENA	0x0008	/* enable CTS */
-#define	HAL_TXDESC_INTREQ	0x0010	/* enable per-descriptor interrupt */
-#define	HAL_TXDESC_VEOL		0x0020	/* mark virtual EOL */
-/* NB: this only affects frame, not any RTS/CTS */
-#define	HAL_TXDESC_DURENA	0x0040	/* enable h/w write of duration field */
-
-/* flags passed to rx descriptor setup methods */
-#define	HAL_RXDESC_INTREQ	0x0020	/* enable per-descriptor interrupt */
-#endif /* _DEV_ATH_DESC_H */
diff --git a/sys/contrib/dev/ath/ah_soc.h b/sys/contrib/dev/ath/ah_soc.h
deleted file mode 100644
index 0852bd386a..0000000000
--- a/sys/contrib/dev/ath/ah_soc.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*-
- * Copyright (c) 2006 Sam Leffler, Errno Consulting, Atheros
- * Communications, Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the following conditions are met:
- * 1. The materials contained herein are unmodified and are used
- *    unmodified.
- * 2. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following NO
- *    ''WARRANTY'' disclaimer below (''Disclaimer''), without
- *    modification.
- * 3. Redistributions in binary form must reproduce at minimum a
- *    disclaimer similar to the Disclaimer below and any redistribution
- *    must be conditioned upon including a substantially similar
- *    Disclaimer requirement for further binary redistribution.
- * 4. Neither the names of the above-listed copyright holders nor the
- *    names of any contributors may be used to endorse or promote
- *    product derived from this software without specific prior written
- *    permission.
- *
- * NO WARRANTY
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT,
- * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
- * FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGES.
- *
- * $Id: //depot/sw/branches/sam_hal/ah_soc.h#3 $
- */
-#ifndef _ATH_AH_SOC_H_
-#define _ATH_AH_SOC_H_
-/*
- * Atheros System on Chip (SoC) public definitions.
- */
-
-/*
- * This is board-specific data that is stored in a "known"
- * location in flash.  To find the start of this data search
- * back from the (aliased) end of flash by 0x1000 bytes at a
- * time until you find the string "5311", which marks the
- * start of Board Configuration.  Typically one gives up if
- * more than 500KB is searched.
- */
-struct ar531x_boarddata {
-	u_int32_t magic;             /* board data is valid */
-#define AR531X_BD_MAGIC 0x35333131   /* "5311", for all 531x platforms */
-	u_int16_t cksum;             /* checksum (starting with BD_REV 2) */
-	u_int16_t rev;               /* revision of this struct */
-#define BD_REV  4
-	char   boardName[64];        /* Name of board */
-	u_int16_t major;             /* Board major number */
-	u_int16_t minor;             /* Board minor number */
-	u_int32_t config;            /* Board configuration */
-#define BD_ENET0        0x00000001   /* ENET0 is stuffed */
-#define BD_ENET1        0x00000002   /* ENET1 is stuffed */
-#define BD_UART1        0x00000004   /* UART1 is stuffed */
-#define BD_UART0        0x00000008   /* UART0 is stuffed (dma) */
-#define BD_RSTFACTORY   0x00000010   /* Reset factory defaults stuffed */
-#define BD_SYSLED       0x00000020   /* System LED stuffed */
-#define BD_EXTUARTCLK   0x00000040   /* External UART clock */
-#define BD_CPUFREQ      0x00000080   /* cpu freq is valid in nvram */
-#define BD_SYSFREQ      0x00000100   /* sys freq is set in nvram */
-#define BD_WLAN0        0x00000200   /* Enable WLAN0 */
-#define BD_MEMCAP       0x00000400   /* CAP SDRAM @ memCap for testing */
-#define BD_DISWATCHDOG  0x00000800   /* disable system watchdog */
-#define BD_WLAN1        0x00001000   /* Enable WLAN1 (ar5212) */
-#define BD_ISCASPER     0x00002000   /* FLAG for AR2312 */
-#define BD_WLAN0_2G_EN  0x00004000   /* FLAG for radio0_2G */
-#define BD_WLAN0_5G_EN  0x00008000   /* FLAG for radio0_2G */
-#define BD_WLAN1_2G_EN  0x00020000   /* FLAG for radio0_2G */
-#define BD_WLAN1_5G_EN  0x00040000   /* FLAG for radio0_2G */
-	u_int16_t resetConfigGpio;   /* Reset factory GPIO pin */
-	u_int16_t sysLedGpio;        /* System LED GPIO pin */
-	
-	u_int32_t cpuFreq;           /* CPU core frequency in Hz */
-	u_int32_t sysFreq;           /* System frequency in Hz */
-	u_int32_t cntFreq;           /* Calculated C0_COUNT frequency */
-	
-	u_int8_t  wlan0Mac[6];
-	u_int8_t  enet0Mac[6];
-	u_int8_t  enet1Mac[6];
-	
-	u_int16_t pciId;             /* Pseudo PCIID for common code */
-	u_int16_t memCap;            /* cap bank1 in MB */
-	
-	/* version 3 */
-	u_int8_t  wlan1Mac[6];       /* (ar5212) */
-};
-
-/*
- * Board support data.  The driver is required to locate
- * and fill-in this information before passing a reference to
- * this structure as the HAL_BUS_TAG parameter supplied to
- * ath_hal_attach.
- */
-struct ar531x_config {
-	const struct ar531x_boarddata *board;	/* board config data */
-	const char	*radio;			/* radio config data */
-	int		unit;			/* unit number [0, 1] */
-	void		*tag;			/* bus space tag */
-};
-#endif	/* _ATH_AH_SOC_H_ */
diff --git a/sys/contrib/dev/ath/public/amd64-elf.hal.o.uu b/sys/contrib/dev/ath/public/amd64-elf.hal.o.uu
deleted file mode 100644
index 597aa760f5..0000000000
--- a/sys/contrib/dev/ath/public/amd64-elf.hal.o.uu
+++ /dev/null
@@ -1,5533 +0,0 @@
-/*-
- * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting, Atheros
- * Communications, Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the following conditions are met:
- * 1. The materials contained herein are unmodified and are used
- *    unmodified.
- * 2. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following NO
- *    ''WARRANTY'' disclaimer below (''Disclaimer''), without
- *    modification.
- * 3. Redistributions in binary form must reproduce at minimum a
- *    disclaimer similar to the Disclaimer below and any redistribution
- *    must be conditioned upon including a substantially similar
- *    Disclaimer requirement for further binary redistribution.
- * 4. Neither the names of the above-listed copyright holders nor the
- *    names of any contributors may be used to endorse or promote
- *    product derived from this software without specific prior written
- *    permission.
- *
- * NO WARRANTY
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT,
- * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
- * FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGES.
- *
- * $Id: //depot/sw/branches/sam_hal/public/x86_64-elf.hal.o.uu#6 $
- */
-#define	ATH_HAL_VERSION	"0.9.20.3"
-begin 644 hal.o
-M?T5,1@(!`0````````````$`/@`!`````````````````````````,C>`@``
-M`````````$```````$``$``-``^WQTC'P@````"#^%@/A/\```"#^%A_5X/X
-M&W\J@_@:#XW>````@_@2?Q>#^!$/C;4```"#^`M+2,?"`````#T3\```
-M=$)(Q\(`````/1OQ``!T-.LM2,?"`````.LI2,?"`````.L@2,?"`````.L7
-M2,?"`````.L.2,?"`````.L%N@````!(B=##2(/L"(GQ9H'_C!9T$V:!_R>G
-M=`RX`````&:!_[<0=0@/M_GHPO[__TB#Q`C#2(/L"`^WQST'`@``#X2*````
-M/0<"``!_((/X$G\,@_@1?6^#^`=T=.M_@_@3=%F#Z!J#^`)W">`,``&:)0@@/
-MMX)Z`P``9HE""HN"?`,``(E"+`^W@H`#``!FB4(P#[>"@@,``&:)0C(/MX*$
-M`P``9HE"-`^W@H8#``!FB4(V2(G02(/$",.)MX@#``"X`0```,-!5D%50515
-M4TF)_D&)U4&)S+L`````B?5)BT8@BT0%`$0AZ+H!````1#G@=!F_"@```.@`
-M````_\.!^^<#``!^U[H`````B=!;74%<05U!7L.Y`````+@`````.?!S$HT4
-M`(GX@^`!"=#1[__!.?%R[L-!B=(/M\%(C01`1`^W3(8FN`````!%A`$BH&0HU$TA6)T;H`````
-M]_'!X`0%D````.GR````2(._Z!,```!T04B+A^@3``#V0`-`=#1"C03-````
-M`(G`2&G`TTUB$$C!Z"")PL'J!D*-1-(5B=&Z`````/?QC03%2````.FG````
-M0HT$C0````")P$AIP---8A!(P>@@B<+!Z@9"C432%8G1N@````#W\8T$A20`
-M``#K=D*-!,T`````BH&0HU$TA6)T;H`````]_&-
-M!(46````ZT5"C02-`````(G`2&G`TTUB$$C!Z"")PL'J!D*-1-(5B=&Z````
-M`/?QP>`"C9"]````@\!<08'YYP,```]&PNL%N``````/M\##]D8"('0'N@(`
-M``#K1`^W1@(ET````+H#````/<````!T+P^W1@(ET````+H$````/=````!T
-M&O9&`A!T![H!````ZPWV1@,(#Y7`#[;0C122B=##2(/L&$B)7"0(2(EL)!")
-M]8G3A-)Y'K@.````@?ZT"0``#X0.`0``@?ZS"0``=E3IT````/;&`70QZ```
-M``"%P'0+C86S[/__@_@P=G+WPT`!```/A,8```"!_8@3```/AI<```#IM0``
-M`+@.````@?ZT"0``#X2Z````@?ZS"0``=R"-E9GV__](8\)(:BYS@@P>@"C02`*<6-@@@___^#_0)U/8V"#3___T@/
-MK\'K.H'])!,``'8(C85@\/__ZR&-A3#V__^ZS@@P>@$@\`/
-MZQ:-A7CL__^ZS@@P>@"2(M<)`A(BVPD$$B#Q!C#4XGS2(NW
-MZ!,``$B%]G03Z`````")P`^V@``````/K\/K`VO#%EO#4XGS2(NWZ!,``$B%
-M]G0=Z`````")P`^VD`````")V(G6N@````#W]HG!ZQ2)V+JCBRZZ2`^OPDC!
-MZ"")P<'I!(G(6\-!5D%505154TF)_DB)]8!^!``/A9$```!!O`````!)8\3&
-M1"@$_T'_Q$&#_!]^[T&\`````$0[90!];DECW$B-'%M(C5R=(`^V0P@/MDL+
-M#[;01(AD*@0*0PD/ML!$B&0H!$0/MNE!N`````!$B>FZ#@```$B)[DR)]^@`
-M````9HE##$&X`0```$2)Z;H.````2(GN3(GWZ`````!FB4,.0?_$1#ME`'R2
-M6UU!7$%=05[#3(V'D`,``(/^(@^'+P$``(GP_R3%``````^WA[@#``#K$4'V
-M0`,!#Y3`#[;`PT$/MT`*B0&X`````,-!#[=`".OQ0?9``@+K%T'V0`(!N@``
-M``"X#0````]$PL-!]@`$N@````"X#0````]%PL-!]@`(Z^Q!]@`0Z^:+AZ@#
-M``#KL8/Z`70=N`````"#^@$/@J\```"#^@)T$X/Z`W0:Z8P````/OX>L`P``
-MZX8/MX>N`P``Z7K___^+A[`#``#I;____T'V0`($ZY5!]D`"".N.0?9``0'K
-MAT'V0`(@ZX!!]D`"0.EV____@_H!=!^#^@%R!X/Z`G0>ZS5!@'@"`+H`````
-MN`T````/2,+#@[\$%````.L3#[>'`!0``.D0____@[\@%`````^%!?___[@-
-M````PT&+0!3I]/[__[@,````PTR)P(/^&70E@_X9=P>#_@]T">M*@_X>=#WK
-M0X/Z`W4^@_D$=SF)C[`#``#K&H/Z`70'@_H"=!;K)87)#Y7`#[;`B8<$%```
-MN`$```##9HF/`!0``.OQB8\@%```Z^E(A`01`G008D!28/!!(/I
-M!$2)P$B+5R"+!!!!B0%)@\$$08/`!(/I!$4YT'<%@_D#=]Y!_\.#^0=WM42)
-MR"G86\-328G23(G+@_X-="J#_@U_!H7V=`[K=H/^'70L@_X>=#KK:DB-AW@#
-M``!)B0!!QP$0````ZU!!BPE)BQ!,B=;H6/___XD#ZSY(C8<(%```28D`0<13_="V+412!^@$$``"X``0```]#T,=&&`$````Y5AAS%K@!`````<"#R`$Y
-MT'+WZP.+012)1AB#>1C_=#"+41B!^@$$``"X``0```]#T,=&'`$````Y5AQS
-M&K@!`````<"#R`$YT'+WB48`'06#[=!'F:#^!"Z#P````]#PF:)1B+K
-M!F;'1B(*`(M!((E&)(M!)(E&*(M!*(E&+(M!+(E&,(-Y!`1U#8-^!`%U!\=&
-M.`$```"X`0```,.#>@0`=0:X`````,.+0@R)1@B+`HD&BT((B48$BT(,B48(
-MBT(0B48,BT(4B480BT(8B484BT(UT-6:#?18`=25(B=Y,B>?H`````(G#2(GN
-M3(GG0?^4)&@#``!F`X0;`````.L(#[=%%F8#11B82(L<)$B+;"0(3(MD)!!(
-M@\08PT%7059!54%455-(@^P(28G]9L=$)`(``&;'1"0&``!FQP0D``!FQT0D
-M!```0;P`````1#NGX!,```^#MP```$ECQ$C!X`9*C:PHX`,``&:#?18`#XF-
-M````2(GN3(GOZ`````!!B<:)P$0/M[P```````^W719$`?M(B>Y,B>]!_Y5H
-M`P``C008]D4#`70G9CL$)'U19HD$)$B)[DR)[T'_E6@#``!F`T469D$IQV9$
-MB7PD!.LP9CM$)`)]*6:)1"0"1(GS2(GN3(GO0?^5:`,``&8#118/MY0;````
-M`&8IPF:)5"0&0?_$13NEX!,```^"2?___T&\`````$0/OW0D!`^_7"0&26/$
-M2,'@!DJ-K"C@`P``9H-]%@!Y'TB)[DR)[T'_E6@#``"8]D4#`70%1`'PZP(!
-MV&:)11A!_\1!@_P_?L)(@\0(6UU!7$%=05Y!7\.0D%.)T&:!/P$P=PE)Q\(`
-M````ZP=)Q\(`````OP````!$#[?`0;ED````#[?V2&/'00^W!$*)PD$/K]!$
-MBM12,'H(,'X!<'Z'RG09HD!2(/!`O_'@_\*
-M?L);PP^WUF:!_O\`=#=F@3\",'L9#[?&C02`
-MC80`[!,``.L*#[?&C02`9@7`$@^WP(G"B=##B?`/M]9F@?[_`'069H$_`C!W
-M!F8%8`GK!&8%_`@/M\")PHG0PT%505154TB#[`A(B?M)B?1F@3[_/W829H-^
-M+@!T"V:#?A8`#X1C`@``9D&!/"0",'9S0;U0`0``O0````!F08.\)'8!````
-M#X0_`@``00^W]4'_Q4B-5"0&2(G?_Y,H`P``N@````"%P`^$(@(``$ACU68/
-MMD0D!V9!B8148@$``&8/MD0D!F9!B8149`$``(/%`D$/MX0D=@$``#G%?*WI
-MJ0$``$&]`0$``$B-5"0&O@`!``!(B=__DR@#``"Z`````(7`#X3&`0``#[=$
-M)`:)PF;!Z@EF08F4)&(!``!FP>@"@^!_9D&)A"1D`0``#[=$)`;!X`6#X']F
-M08F$)&8!``!!#[?U0?_%2(U4)`9(B=__DR@#``"Z`````(7`#X1L`0``#[=$
-M)`:)PF;!Z@MF00F4)&8!``!FP>@$@^!_9D&)A"1H`0``#[=$)`;!X`.#X']F
-M08F$)&H!``!!#[?U0?_%2(U4)`9(B=__DR@#``"Z`````(7`#X02`0``#[=$
-M)`:)PF;!Z@UF00F4)&H!``!FP>@&@^!_9D&)A"1L`0``#[=$)`8!P(/@?V9!
-MB80D;@$``$$/M_5!_\5(C50D!DB)W_^3*`,``+H`````A<`/A+D````/MU0D
-M!HG09L'H#V9!"80D;@$``(G09L'H"(/@?V9!B80D<`$``&;1ZH/B?V9!B90D
-M<@$```^W1"0&P>`&@^!_9D&)A"1T`0``00^W]4B-5"0&2(G?_Y,H`P``N@``
-M``"%P'15#[=$)`9FP>@*9D$)A"1T`0``O0````!F08.\)'8!````="U%#[>L
-M)'8!``!(8]U!#[>T7&(!``!,B>?H&_W__V9!B81<8@$``/_%1#GM?-RZ`0``
-M`(G02(/$"%M=05Q!7<-!5%532(G3#[=N%$F)]`^WQ4B-/(!(C3RX2(U$``-(
-MP>@"2`''2,'G`N@`````2(G"N`````!(A=(/A*````!(B1,/M\5(C40``R7\
-M_P<`2(T$$$B)0Q!FB6L(0;@`````9H7M='1$#[?-26/02(L[2(MS$$AKRE1!
-M#[<$5&:)!`YFB017N0````!(:_)42&/!2(T$@$B-!(9(B<)(`U,09HE*!$@#
-M0Q!FQT`&``#_P8/Y`W[926/`2(M3$$AKP%1FQT0"!@0`2(M3$&;'1`)"`P!!
-M_\!%.9L=$)`:M
-MWKH`````N0````!$#[='"DR-3"0$1(G`T_BH`708N`````"#^@$/CQ8"``!(
-M8\)F08D,0?_"_\&#^0-^V`^W1A1FB4<(9H7`=0JX`````.GN`0``0;D`````
-M9H-_"``/A-@!``!,C50D!$ECT4AKPAI(C00P3(U`&$B+3Q!(:])4#[=`&&:)
-M!!%(BT\000^W0!)FB401`KD`````2&/!2(T$@$B-!()(`T<09L=`!@``_\&#
-M^0-^Y&9!@7H"K=YU<$ECT4AKTE1(#[=$)`1(C02`2(T$@D@#1Q!(C5`$9L="
-M`@0`00^W0`)FB4($9D$#0`9FB4(&9D$#0`IFB4((9D$#0`YFB4(*00^W0`1F
-MB4(,00^W0`AFB4(.00^W0`QFB4(000^W0!!FB4(2Z?P```!)8\E(:\E42`^W
-M1"0$2(T$@$B-!(%(`T<000^W4`)FB5`(20^W0@)(C02`2(T$@4@#1Q!FQT`(
-M%`!)#[="`DB-!(!(C02!2`-'$&;'0`HC`$D/MT("2(T$@$B-!(%(`T<09L=`
-M##\`2`^W1"0$2(T$@$B-%(%(`U<02(/"!&;'0@($``^W0@1F00-`!F:)0@9F
-M00-`"F:)0@AF00-`#F:)0@I!#[=`!&:)0@Q!#[=`"&:)0@Y!#[=`#&:)0A!!
-M#[=`$&:)0A))#[="`DB-!(!(C12!2`-7$$B#P@1FQT("`P!!#[=`%&:)0@Q!
-M#[=`%F:)0@Y!#[=`&&:)0A!!_\$/MT<(03G!#XPM_O__N`$```!(@\0(PT%7
-M059!54%455-(@>Q8`0``2(G]28GU0;Q0`0``0;\`````0;X`````08/_`0^$
-MK@```$&#_P%_"D6%_W04Z2`!``!!@_\"#X35````Z1$!``!F08-]%@`/A`0$
-M``!!@_X)#X\%`0``1(GF0?_$2(U4)`Y(B>__E2@#``"Z`````(7`#X3K`P``
-M@'PD#@`/A-D```!)8]X/MG0D#D'_QDR)[^@+^?__9HF$7#`!``!F#[9$)`^$
-MP`^$L````$ECW@^V\$'_QDR)[^CD^/__9HF$7#`!``!!@_X)?HSIC````&9!
-M@WT:``^$=0,``+L`````2&/#9D&!O$54`0``_P!T%TECUD$/MX1%5`$``&:)
-MA%0P`0``0?_&_\.#^P)^TNM+9D&#?1P`#X0T`P``NP````!(8\-F08&\14X!
-M``#_`'0726/600^WA$5.`0``9HF$5#`!``!!_\;_PX/[`G[2ZPJZ`````.D'
-M`P``OAP!``!(C7PD$.@`````9D2)="0DNP````!$.?,/C7T"``!(8\,/MY1$
-M,`$``&:)5$002&O`&F:)5`0H1(GF0?_$2(U4)`Y(B>__E2@#``"Z`````(7`
-M#X2J`@``2&/+2&O)&DB-A"10`0``2`'!#[=$)`X/MM!FP>@'@^`!P>`(9BG"
-M9HF1W/[__P^W1"0.B<)FP>H(9L'H#\'@"&8IPF:)D>#^__]$B>9!_\1(C50D
-M#DB)[_^5*`,``+H`````A<`/A#\"``!(8\M(:\D:2(V4)%`!``!(`=$/MT0D
-M#@^VT&;!Z`>#X`'!X`AF*<)FB9'D_O__#[=$)`Z)PF;!Z@AFP>@/P>`(9BG"
-M9HF1Z/[__T2)YD'_Q$B-5"0.2(GO_Y4H`P``N@````"%P`^$U`$``$ACTTAK
-MTAI(C80D4`$``$@!P@^W1"0.@^`?9HF"WO[__P^W1"0.9L'H!8/@'V:)@N+^
-M__\/MT0D#F;!Z`J#X!]FB8+F_O__1(GF0?_$2(U4)`Y(B>__E2@#``"Z````
-M`(7`#X1L`0``2&/+2&O)&DB-E"10`0``2`'1#[=$)`X/MM!FP>@'@^`!P>`(
-M9BG"9HF1[/[__P^W1"0.B<)FP>H(9L'H#\'@"&8IPF:)D>[^__]$B>9!_\1(
-MC50D#DB)[_^5*`,``+H`````A<`/A`$!``!(8\-(:\`:2(V4)%`!``!(C0P"
-M#[=$)`X/MM!FP>@'@^`!P>`(9BG"9HF1\/[__V9!@7T``D!V(`^W@>C^__]F
-MB8'J_O__9@^V1"0/@^`_9HF!VO[__^LW2&/#2&O`&DB-E"10`0``2`'0#[=4
-M)`Z)T6;!Z0AFP>H/P>((9BG19HF(ZO[__V;'@-K^__\!`/_#1#GS#XR#_?__
-M26/700^W1%5H9HE$)"9(C11228V4U6@-``!(C70D$$B)[^B%^/__N@````"%
-MP'0W26/72(T44DF-E-5H#0``2(UT)!!(B>_H1/G__[H`````A05_#55-(@^P(2(GUNP``
-M``!(8\-(C01`2(U$Q0!(B[AH#0``2(7_=!!(QX!H#0```````.@`````_\.#
-M^P)^T4B#Q`A;7<-)B=%!B?!FB7<4#[=7%KX`````]L(!N`$````/1?"-1@'V
-MP@(/1?"-1@'VP@0/1?"-1@'VP@@/1?"Y`````&9$.<%S(P^WP4$/MQ1!9HD4
-M1TAKP&9(`?AFB5`89HEP&O_!9D0YP7+=D,-!5T%6055!5%532(/L2$F)_4F)
-M]DB)5"00B4PD#$6)QT2(3"0+BVPD#$&\`````$6%P`^$K0````^W]?_%2(U4
-M)!Y,B>]!_Y4H`P``N@````"%P`^$M@4``(!\)!X`#X2!````@'PD"P!U%D$/
-MM]P/MG0D'D'_Q$R)]^C^\___ZQ1!#[?<#[9T)!Y!_\1,B??H+/3__V:)1%P@
-M9@^V1"0?A,!T08!\)`L`=11!#[?<#[;P0?_$3(GWZ,#S___K%$$/M]P/MG0D
-M'T'_Q$R)]^CN\___9HE$7"!!#[?$1#GX#X)3____2(U4)"!!#[?T2(M\)!#H
-MG_[__T2)^-'HBVPD#`'%0;P`````2(M$)!!F1#M@%`^#\00``$$/M\1(:\!F
-M2(M4)!!(C5P0&&:#>P(`#X31````#[?U_\5(C50D'DR)[T'_E2@#``"Z````
-M`(7`#X2X!```#[=$)!Z#X!]FB4,,#[=$)!YFP>@%@^!_9HE#!`^W1"0>9L'H
-M#&:)0SP/M_7_Q4B-5"0>3(GO0?^5*`,``+H`````A<`/A&X$```/MT0D'H/@
-M/V:)0Q0/MT0D'F;!Z`:#X`]FB4-$#[=$)!YFP>@*9HE#'`^W]?_%2(U4)!Y,
-MB>]!_Y4H`P``N@````"%P`^$)`0```^W1"0>@^`/9HE#3`^W1"0>9L'H!(/@
-M/V:)0R1F@WL"`0^&]0````^W1"0>9L'H"H/@'V:)0PX/MT0D'F;!Z`]FB4,&
-M#[?U_\5(C50D'DR)[T'_E2@#``"Z`````(7`#X2_`P``#[=$)!Z#X#\!P&8)
-M0P8/MT0D'F;!Z`:#X`]FB4,^#[=$)!YFP>@*9HE#%@^W]?_%2(U4)!Y,B>]!
-M_Y4H`P``N@````"%P`^$@^`/9HE#1@^W1"0>9L'H!(/@/V:)
-M0QX/MT0D'F;!Z`J#X`]FB4-.#[=$)!YFP>@.9HE#)@^W]?_%2(U4)!Y,B>]!
-M_Y4H`P``N@````"%P`^$&0,```^W1"0>@^`/P>`"9@E#)NM49H-[`@%U30^W
-M1"0>9L'H"H/@#V:)0U0/MT0D'F;!Z`YFB4,L#[?U_\5(C50D'DR)[T'_E2@#
-M``"Z`````(7`#X3#`@``#[=$)!Z#X`_!X`)F"4,L9H-[`@(/AL8````/MT0D
-M'F;!Z`2#X!]FB4,0#[=$)!YFP>@)9HE#"`^W]?_%2(U4)!Y,B>]!_Y4H`P``
-MN@````"%P`^$:P(```^W1"0>@^`/9HE#0`^W1"0>9L'H!(/@/V:)0Q@/MT0D
-M'F;!Z`J#X`]FB4-(#[=$)!YFP>@.9HE#(`^W]?_%2(U4)!Y,B>]!_Y4H`P``
-MN@````"%P`^$$0(```^W1"0>@^`/P>`"9@E#(`^W1"0>9L'H!(/@#V:)0U!F
-M#[9$)!^#X#]FB4,HZR1F@WL"`G4=#[=$)!YFP>@$@^`/9HE#5F8/MD0D'X/@
-M/V:)0RYF@WL"`P^&3`$```^W1"0>9L'H#F:)0Q(/M_7_Q4B-5"0>3(GO0?^5
-M*`,``+H`````A<`/A(8!```/MT0D'H/@!\'@`F8)0Q(/MT0D'F;!Z`.#X']F
-MB4,*#[=$)!YFP>@*@^`/9HE#0@^W1"0>9L'H#F:)0QH/M_7_Q4B-5"0>3(GO
-M0?^5*`,``+H`````A<`/A"D!```/MT0D'H/@#\'@`F8)0QH/MT0D'F;!Z`2#
-MX`]FB4-*9@^V1"0?@^`_9HE#(@^W1"0>9L'H#F:)0U(/M_7_Q4B-5"0>3(GO
-M0?^5*`,``+H`````A<`/A,\````/MT0D'H/@`\'@`F8)0U(/MT0D'F;!Z`*#
-MX#]FB4,J9@^V1"0?@^`/9HE#6@^W1"0>9L'H#&:)0S(/M_7_Q4B-5"0>3(GO
-M0?^5*`,``+H`````A0^W1"0>@^`#P>`$9@E#,NM09H-[`@-U20^W1"0>
-M9L'H#F:)0U@/M_7_Q4B-5"0>3(GO0?^5*`,``+H`````A@^`#
-MP>`"9@E#6`^W1"0>9L'H`H/@/V:)0S!!_\1(BT0D$&9$.V`4#X(/^___N@$`
-M``")T$B#Q$A;74%<05U!7D%?PU-(B?,/MT849HE'%`^W5Q:^`````/;"`;@!
-M````#T7PC48!]L("#T7PC48!]L($#T7PC48!]L((#T7P0;L`````9D0[6Q0/
-M@XX```!$#[?200^WPP^W%$-FB11'2&O`9D@!^&:)4!AFB7`<0;D`````N0``
-M``!!#[?#3&O`9@^WP4B-!$!)C03`2(T4!V:)2AY$B=#3^*@!=!AFQT(@!`!!
-M_\%F08/Y`74:9L="(`4`ZQ(/M\%(C01`28T$P&;'1`<@``#_P6:#^0-VLD'_
-MPV9$.UL4#X)V____6\-!5T%6055!5%532(/L$$B)-"1(B=5FQT0D"*W>2(U$
-M)`AFQT`"K=YFQT`$K=YFQT`&K=Y!O0````"[``````^WE(
-MB>I(B=Y,B??H%O?__X7`#X1&`0``3(VC:`T```^W0VAF08E$)!9(B>Y,B>?H
-M$OW__TR)XDB)[DR)]^C@_?__A<`/A!0!``!(#[=%&@^W5$3^#[=%%`^OPD:-
-M;"@%9H-[&@`/A((```"^%`0``$B)[^@`````#[=#:F:)119!N0$```!!N`0`
-M``!$B>E(B>I(B=Y,B??HB?;__X7`#X2Y````3(VC?!$```^W0VIF08E$)!9(
-MB>Y,B>?HA?S__TR)XDB)[DR)]^A3_?__A<`/A(<```!(#[=%&@^W5$3^#[=%
-M%`^OPD:-;"@"9H-['`!T9+X4!```2(GOZ``````/MT-L9HE%%D&Y`@```$&X
-M!````$2)Z4B)ZDB)WDR)]^@`]O__A)(B>Y,B??HSOS__X7`=`9!OP$```!(A>UT"$B)[^@`````
-M1(GX2(/$"%M=05Q!74%>05_#05=!5D%505154TB#[!A)B?Q)B?5F@3[_/W8.
-M9H-^+@%U!^A-\/__ZQQF08%]`/]/=AIF08-]+@)U$DR)[DR)Y^C*_?__B<+I
-MR@(``$&^`````&9!@7T``C!V![U0`0``ZP6]``$``$&#_@%T.$&#_@%_"D6%
-M]G0-Z8````!!@_X"=$[K>(/%!4$/MX5V`0``9HE$)!1)C9UX`0``28V58@$`
-M`.MB9D&#?1H`#X13`@``@\4W00^WA8`#``!FB40D%$F-G3X$``!)C96(`P``
-MZS9F08-]'``/A"<"``"#Q49!#[>%@`,``&:)1"0428V=H@,``$F-E8(#``#K
-M"KH`````Z0\"``!(B50D"$&_`````&:#?"04``^$Y@$``$ECQTB+5"0(#[<$
-M0F:)`XGN_\5(C50D%DR)YT'_E"0H`P``N@````"%P`^$R`$```^W1"069L'H
-M"F:)0P0/MT0D%F;!Z`2#X#]FB4,"#[=$)!;!X`*#X#]FB4,>B>[_Q4B-5"06
-M3(GG0?^4)"@#``"Z`````(7`#X1[`0``#[=$)!9FP>@.9@E#'F8/MD0D%X/@
-M/V:)0R`/MT0D%F;!Z`*#X#]FB4,B#[=$)!;!X`2#X#]FB4,DB>[_Q4B-5"06
-M3(GG0?^4)"@#``"Z`````(7`#X0A`0``#[=$)!9FP>@,9@E#)`^W1"069L'H
-M!H/@/V:)0R8/MT0D%H/@/V:)0RB)[O_%2(U4)!9,B>=!_Y0D*`,``+H`````
-MA<`/A-<````/MT0D%F;!Z`IFB4,J#[=$)!9FP>@$@^`_9HE#+`^W1"06P>`"
-M@^`_9HE#+HGN_\5(C50D%DR)YT'_E"0H`P``N@````"%P`^$B@````^W1"06
-M9L'H#F8)0RYF#[9$)!>#X#]FB4,P#[=$)!9FP>@"@^`_9HE#,DB-2P@/MU,$
-M#[=S`DR)[^CPYO__N0`````/MT,&B<8YP7T62&/1#[]$4QYKP#)FB413'O_!
-M.?%\ZDB#PS1!_\05_#05=!5D%505154TB#[!A)B?Y(B?5!O0````!F@7T`
-M_S]V"@^W121$C6"KZQ9F@7T``C!V"$&\4`$``.L&0;P``0``08/]`70Q08/]
-M`7\'187M=`KKMJ08/$5<=$)!`(````2(V=W`0``$B-A=H$``#K
-M6&:#?1H`#X2N`0``08/$9<=$)!`"````2(V=3@4``$B-A4P%``#K,6:#?1P`
-M#X2'`0``08/$:<=$)!`#````2(V=+@4``$B-A2P%``#K"KH`````Z7,!``!(
-MB40D"$B+1"0(9L<```!!OP````!$.WPD$`^-00$``$2)YD'_Q$B-5"063(GW
-M0?^6*`,``+H`````A<`/A#$!``!F@7T``C!V"&8/MD0D%^L)#[=$)!9FP>@)
-M9HE#"&:#>P@`#X3E````187M=0X/MW,(2(GOZ+/E___K#`^W_HZ>7_
-M_V:)0PAF@7T``C!V&@^W1"069L'H`H/@/V:)0P8/MT0D%L'@!.L8#[=$)!9F
-MP>@#@^`_9HE#!@^W1"06P>`#@^`_9HE#!$2)YD'_Q$B-5"063(GW0?^6*`,`
-M`+H`````A<`/A(,```!F@7T``C!V)`^W1"069L'H#&8)0P0/MT0D%F;!Z`:#
-MX#]FB4,"#[=$)!;K)0^W1"069L'H#68)0P0/MT0D%F;!Z`>#X#]FB4,"#[=$
-M)!9FT>B#X#]FB0-(BT0D"&;_`$B#PPI!_\=$.WPD$`^,O_[__T'_Q4&#_0(/
-MCMO]__^Z`0```(G02(/$&%M=05Q!74%>05_#05=!5D%505154TB#[!A)B?Y)
-MB?=,C:9D!0``9H$^_S]V"T0/MVXD08/%&NL59H$^`C!V"$&]OP$``.L&0;UO
-M`0``QT0D$`````!F08._!`$````/A*`#``!(8T0D$&9!@[Q'!@$```!U&F9!
-M@3\",'8)08/%".ED`P``08/%!^E;`P``9D&!/P(P#X;#````O0````!$B>Y!
-M_\5(C50D%DR)]T'_EB@#``"Z`````(7`#X1'`P``2&/%#[=4)!:)T6;!Z0AF
-M08D,Q&:!XO\`9D&)5,0(@\4"@_T'?KB]`````$2)[D'_Q4B-5"063(GW0?^6
-M*`,``+H`````A<`/A/H"``!(8]5F#[9$)!>#X#]F08E$U`(/MT0D%F;!Z`Z#
-MX`%!B434!`^W1"06@^`_9D&)1-0*#[=$)!9FP>@&@^`!08E$U`R#Q0*#_0=^
-ME.DM`@``1(GN0?_%2(U4)!9,B?=!_Y8H`P``N@````"%P`^$B0(```^W1"06
-MB<)FP>H)9D&)%"1FP>@"@^!_9D&)1"0(#[=$)!;!X`6#X']F08E$)!!$B>Y!
-M_\5(C50D%DR)]T'_EB@#``"Z`````(7`#X0Y`@``#[=$)!:)PF;!Z@MF00E4
-M)!!FP>@$@^!_9D&)1"08#[=$)!;!X`.#X']F08E$)"!$B>Y!_\5(C50D%DR)
-M]T'_EB@#``"Z`````(7`#X3H`0``#[=$)!:)PF;!Z@UF00E4)"!FP>@&@^!_
-M9D&)1"0H#[=$)!8!P(/@?V9!B40D,$2)[D'_Q4B-5"063(GW0?^6*`,``+H`
-M````A<`/A)@!```/MU0D%HG09L'H#V9!"40D,(G09L'H"(/@?V9!B40D.&;!
-MZ@*#XC]F08E4)`(/MT0D%L'@!(/@/V9!B40D"D2)[D'_Q4B-5"063(GW0?^6
-M*`,``+H`````A<`/A#@!```/MU0D%HG09L'H#&9!"40D"HG09L'H!H/@/V9!
-MB40D$H/B/V9!B50D&D2)[D'_Q4B-5"063(GW0?^6*`,``+H`````A<`/A.T`
-M```/MT0D%HG"9L'J"F9!B50D(F;!Z`2#X#]F08E$)"H/MT0D%L'@`H/@/V9!
-MB40D,D2)[D'_Q4B-5"063(GW0?^6*`,``+H`````A<`/A)P````/MT0D%HG"
-M9L'J#F9!"50D,F;!Z`B#X#]F08E$)#J]`````$AC1"002(E$)`A(8\5!@SS$
-M`'0_2(M4)`A!#[>$5P8!``"#X`=T!8/X`W422&/=00^W--Q,B?_HZ>#__^L0
-M2&/=00^W--Q,B?_H&^'__V9!B03<_\6#_0=^L$F#Q$#_1"0000^WAP0!```Y
-M1"00#XQ@_/__N@$```")T$B#Q!A;74%<05U!7D%?PT%6055!5%532(/L$$F)
-M_$B)\V;'1BH/`&;'1BP/`&:!/@(P=A))Q\8`````9L>&!`$``"``ZQ!)Q\8`
-M````9L>&!`$``!``2(U4)`Y!BS9,B>=!_Y0D*`,``,=$)`@`````A<`/A+0-
-M```/MU0D#HG09L'H#V:)0P:)T&;!Z`Z#X`%FB4,*B=!FP>@+@^`'9HE##(G0
-M9L'H!(/@?V:)0PYF@3O_/W8/B=!FP>@#@^`!9HE#".L&9L=#"`$`#[=4)`Z)
-MT&;!Z`*#X`%FB4,B#X`%FB4,:@^(!9HE3%D&+;@2)[O_%2(U4)`Y,
-MB>=!_Y0D*`,``,=$)`@`````A<`/A!4-``!F#[9$)`^(0QX/MD0D#HA#'V:!
-M._\_#X;4````B>[_Q4B-5"0.3(GG0?^4)"@#``#'1"0(`````(7`#X35#```
-M#[=4)`Z)T&;!Z`YFB4,NB=!FP>@-@^`!B8/(````B=!FP>@,@^`!B8/,````
-M9H'B_P]FB5,PB>[_Q4B-5"0.3(GG0?^4)"@#``#'1"0(`````(7`#X1[#```
-M#[=$)`Z)PF:!XO\/9HE3)&;!Z`Z#X`&(0R-F@3O_3W8U@\4"2(U4)`Z)[DR)
-MYT'_E"0H`P``QT0D"`````"%P`^$-0P```^W1"0.9L'H!&:)@]````!!O0``
-M``!)8\5!BVR&"(GN_\5(C50D#DR)YT'_E"0H`P``QT0D"`````"%P`^$\PL`
-M`$ECU68/MD0D#X/@?V:)1%,R#[=$)`YFP>@"@^`_9HE$4S@/MT0D#L'@!(/@
-M/V:)1%-TB>[_Q4B-5"0.3(GG0?^4)"@#``#'1"0(`````(7`#X2="P``26/5
-M#[=$)`YFP>@,9@E$4W0/MT0D#F;!Z`:#X#]FB413>@^W1"0.@^`_9HF$4X``
-M``")[O_%2(U4)`Y,B>=!_Y0D*`,``,=$)`@`````A<`/A$<+``!)8]4/MT0D
-M#F;!Z`IFB813A@````^W1"0.9L'H!(/@/V:)A%.,````#[=$)`[!X`*#X#]F
-MB813D@```(GN_\5(C50D#DR)YT'_E"0H`P``QT0D"`````"%P`^$Z`H``$EC
-MU0^W1"0.9L'H#F8)A%.2````9@^V1"0/@^`_9HF$4Y@````/MT0D#F;!Z`*#
-MX#]FB813G@````^W1"0.P>`$@^`_9HF$4Z0```")[O_%2(U4)`Y,B>=!_Y0D
-M*`,``,=$)`@`````A<`/A'@*``!)8]4/MT0D#F;!Z`QF"813I`````^W1"0.
-M9L'H!H/@/V:)A%.J````#[=$)`Z#X#]FB813L````(GN_\5(C50D#DR)YT'_
-ME"0H`P``QT0D"`````"%P`^$'`H``$ECU68/MD0D#XA$$U9!@_T!=$Y!@_T!
-M?PI%A>UT#>D'`0``08/]`G19ZW8/MT0D#HG"9L'J!8/B!V:)D_````!FP>@"
-M@^`'9HF#\@````^W1"0.`<"#X`=FB8/L````ZT`/MU0D#HG09L'H!(/@!V:)
-M@_0```"#X@=FB9/V````ZQ\/MU0D#HG09L'H!(/@!V:)@_@```"#X@=FB9/Z
-M````187M#X6`````B>[_Q4B-5"0.3(GG0?^4)"@#``#'1"0(`````(7`#X1.
-M"0``#[=4)`Z)T&;!Z`]F"8/L````B=!FP>@,@^`'9HF#[@```(G09L'H"8/@
-M!V:)@^@```")T&;!Z`:#X`=FB8/J````B=!FP>@#@^`'9HF#Y````(/B!V:)
-MD^8```")[O_%2(U4)`Y,B>=!_Y0D*`,``,=$)`@`````A<`/A,X(``!)8]5F
-M#[9$)`]FB413/F8/MD0D#F:)1%-$B>[_Q4B-5"0.3(GG0?^4)"@#``#'1"0(
-M`````(7`#X21"```26/59@^V1"0/9HE$4TIF#[9$)`YFB4134(GN_\5(C50D
-M#DR)YT'_E"0H`P``QT0D"`````"%P`^$5`@``$ECU68/MD0D#XA$$UEF#[9$
-M)`YFB4137(!\4UP`>0EF#0#_9HE$4UR)[O_%2(U4)`Y,B>=!_Y0D*`,``,=$
-M)`@`````A<`/A`@(``!)8]4/MT0D#F;!Z`5F)?\`9HE$4V(/MT0D#F;1Z(/@
-M#V:)1%-H#[=$)`Z#X`%FB413;F:!._\_=B]%A>UT"$&#_0)T%.LB#[=$)`YF
-MP>@-@^`!9HE#)NL0#[=$)`YFP>@-@^`!9HE#*&:!.P(P#X:D````B>[_Q4B-
-M5"0.3(GG0?^4)"@#``#'1"0(`````(7`#X1Q!P``26/5#[=$)`YFP>@&@^!_
-M9HF$4[8```!!@_T!=!5!@_T!?P=%A>UT3.M608/]`G0CZTX/MT0D#HG"@^('
-M9HF3_````&;!Z`.#X`=FB8,``0``ZRT/MT0D#HG"@^('9HF3_@```&;!Z`.#
-MX`=FB8,"`0``ZPP/MT0D#H/@/V:)0Q)F@3L#,`^&J````$ECU0^W1"0.9L'H
-M#6:)A%.\````B>[_Q4B-5"0.3(GG0?^4)"@#``#'1"0(`````(7`#X2N!@``
-M26/5#[=$)`[!X`.#X#AF"813O````$&#_0)U'P^W5"0.B=!FP>@#B$,B9H$[
-M!4!V"HG09L'H"V:)0RQ%A>UU06:!._\_#X8D!```#[=4)`Z)T&;!Z`B#X#]F
-MB8-&`0``9L'J`X/B'V:)DTH!``#K$4ECQ6;'A$.\````"@#&0R(/9H$[_S\/
-MAN,#``!!@_T!="-!@_T!?PY%A>T/A-`"``#IR0,``$&#_0(/A*<```#IN@,`
-M`(GN_\5(C50D#DR)YT'_E"0H`P``QT0D"`````"%P`^$U04```^V="0.2(G?
-MZ(G8__]FB8-4`0``#[9T)`](B=_H==C__V:)@U8!``")[DB-5"0.3(GG0?^4
-M)"@#``#'1"0(`````(7`#X2+!0``#[9T)`Y(B=_H/]C__V:)@U@!``!F@3L`
-M0`^&+0,``&8/MD0D#X/@/V:)@\0```#I&`,``(GN_\5(C50D#DR)YT'_E"0H
-M`P``QT0D"`````"%P`^$,P4```^V="0.2(G?Z.?7__]FB8-.`0``#[9T)`](
-MB=_HT]?__V:)@U`!``")[O_%2(U4)`Y,B>=!_Y0D*`,``,=$)`@`````A<`/
-MA.<$```/MT0D#HG"@^)_9HE3$&;!Z`>#X#]FB4,4B>[_Q4B-5"0.3(GG0?^4
-M)"@#``#'1"0(`````(7`#X2J!```#[9T)`Y(B=_H7M?__V:)@U(!``!F@3L`
-M0'809@^V1"0/@^`_9HF#Q@```(GN_\5(C50D#DR)YT'_E"0H`P``QT0D"```
-M``"%P`^$6P0```^W5"0.B=!FP>@%@^`_9HF#2`$``(/B'V:)DTP!``!F@3L!
-M0`^&\@$``(GN_\5(C50D#DR)YT'_E"0H`P``QT0D"`````"%P`^$#00``&8/
-MMD0D#F:)0RIF@3O_3P^&N0$```^W5"0.B=!FP>@(@^!_9HF#U@```&;!Z@]F
-MB9/:````B>[_Q4B-5"0.3(GG0?^4)"@#``#'1"0(`````(7`#X2T`P``#[=$
-M)`Z#X!\!P&8)@]H````/MU0D#HG09L'H!8/@/V:)@^(```!FP>H+B)/=````
-MB>Y(C50D#DR)YT'_E"0H`P``QT0D"`````"%P`^$8@,```^W1"0.@^`'P>`%
-M"(/=````#[=$)`YFP>@#B(/?````Z?X```!F@3L`0`^&\P```(GN_\5(C50D
-M#DR)YT'_E"0H`P``QT0D"`````"%P`^$#@,```^W5"0.B="#X#]FB8/"````
-M9H$[_T\/AK,```")T&;!Z`:#X']FB8/4````B=!FP>@-9HF#V````(GN_\5(
-MC50D#DR)YT'_E"0H`P``QT0D"`````"%P`^$L0(```^W1"0.@^`'P>`#9@F#
-MV`````^W5"0.B=!FP>@#@^`_9HF#X````&;!Z@F(D]P```")[DB-5"0.3(GG
-M0?^4)"@#``#'1"0(`````(7`#X1>`@``#[=$)`Z#X`'!X`<(@]P````/MT0D
-M#F;1Z(B#W@```$'_Q4&#_0(/CA/V__]F@3L",`^'B````$B-5"0.ONP```!,
-MB>=!_Y0D*`,``,=$)`@`````A<`/A`("```/MT0D#HG"@^('9HF3_````&;!
-MZ`.#X`=FB8,``0``2(U4)`Z^[0```$R)YT'_E"0H`P``QT0D"`````"%P`^$
-MO@$```^W1"0.B<*#X@=FB9/^````9L'H`X/@!V:)@P(!``!FQX-@`0``!`!F
-MQX->`0```0!FQX-<`0```0!FQX-:`0````!!BVX40;T`````9H.[!`$```!T
-M4XGN_\5(C50D#DR)YT'_E"0H`P``QT0D"`````"%P`^$0P$``$ECU68/MD0D
-M#V:)A%,&`0``9@^V1"0.9HF$4P@!``!!@\4"#[>#!`$``$$YQ7RM9H$[`E!V
-M=D&]`````$B-5"0.B>Y,B>=!_Y0D*`,``,=$)`@`````A<`/A.4```!)8]4/
-MMT0D#F:)A)..`P``C74%2(U4)`Y,B>=!_Y0D*`,``,=$)`@`````A<`/A+(`
-M``!)8]4/MT0D#F:)A).0`P``_\5!_\5!@_T$?I!F@3L",'@/9HE#%L=$)`@!````
-MBT0D"$B#Q!!;74%<05U!7L-(@^P82(E<)`A(B6PD$$B)_4B)\^BX\?__N@``
-M``"%P'1)2(G>2(GOZ*C2__^Z`````(7`=#5(B=Y(B>_H!>C__[H`````A2(GOZ%GM__^)PHG02(M<)`A(BVPD
-M$$B#Q!C#2(/L"&:!/O\_=@QF@WXN`74%Z*_<__](@\0(PP^W!V8[!G45#[=7
-M`H'B\,$```^W1@(E\,$``.L&#[<7#[<&*<*)T,,/MX>X`P``)?^_``##N@``
-M``!(8\)(@SS'`'0&N`````##_\*#^@%^Z;@!````PTB#[`CHR/___XG!9H7`
-M>3%F@>'_?[H`````2,?&`````$ACPDB-!(!F.0R&=`S_PH'Z@@```';IZR>X
-M`0```.LEN@````!(Q\8`````2&/"2,'@!68Y#`9TX/_"@_I*=NRX`````$B#
-MQ`C#4XGSN`$```!FA?9T9NA4____B<%FA+_?P``.=`/E,`/
-MML#K168]_P%T!6:%P'4'N`$```#K,[H`````2,?&`````$ACPDB-!(!(P>`"
-M9CLRH````2(F<)(@```!(B:PDD````$R)I"28````
-M3(FL)*````!(B?U!O0`````/M_[HG@```$B)PTB%P'0H2(GANG__``!(B<9(
-MB>_HM@$``(7`=!%(B>)(B=Y(B>_H)/___T&)Q42)Z$B+G"2(````2(NL))``
-M``!,BZ0DF````$R+K"2@````2('$J````,-32(G[Z-[]__\/M\"#^!)T)(/X
-M$G\&AN`````##55-(@^P(Z&/]__^)Q6:%P'D?B>N!X_]_``")W^BI____
-MB=I(A`%#[<$!KD!````.?AT#/_"@_I*=N6Y`````(G(PT%7059!
-M54%455-(@^P82(E\)!!)B?5)B<]!B=1!O@````!(QT0D"`````!(QP0D````
-M`&:#/@!U+^@S_/__B<-FA_H(O___X7`=0N)[^AI____
-MA05_#C4<_@___#T_'P?@&
-MB<+!X@:)^2G1N@$```!(T^)(F$@C%,9(A=(/E<`/ML##A,ET*K@`````.?!S
-M%DQCP$$X##AT&$&`/#@`=`;_P#GPAF)?\_9HF#
-MN@,``$B)W^CW"@``#[>[N@,``.C@^___2(G%N@````!(A<`/A`D&``!(C8PD
-M,`$``+I__P``2(G&2(G?Z.K\__^Z`````(7`#X3D!0``2(V,)+````"Z@```
-M`$B)[DB)W^C%_/__N@````"%P`^$OP4``/:$)#@!```%N`$```!$#T7H]H0D
-M.`$```*X`@```$0/1>A$.ZN\`P``=`=$B:N\`P``2(V4)#`!``!(B>Y(B=_H
-M\_G__XE$)$R#O"0(`@```'4)#[=M$&:);"1*QT0D1`````!!@_]!N$````!$
-M#T/X#[:#D@,``(G"P.H%B=�&)3"0TP.@&B<*#X@&)5"0X2,?%`````$B!
-M_0`````/@S,$```/MT0D4F8C10!FA<`/A!`$```/MT4`A40D3`^$`@0```^W
-M=0)(C4PD;DB-5"1L2(G?_Y,8`P``A<`/A.,#```/MT4`@_@$#X29````@_@$
-M?P^#^`%T8X/X`G0OZ<(#``"#^"`/A-L```"#^"!_#H/X"`^$G0```.FF`P``
-M@_A`#X3O````Z9@#``!(C8PD,`$``$B)3"0@2(/!,$B)3"0H2,=$)!``````
-M#[:$)#(!``"#R`/IA0```$B-E"0P`0``2(E4)"!(@\(@2(E4)"A(QT0D$```
-M```/MHPD,@$``.F)````2(V$)+````!(B40D($B#P%!(B40D*$C'1"00````
-M``^VE"2R````@\H!Z8H```!(C8PDL````$B)3"0@2(/!8$B)3"0H2,=$)!``
-M````#[:$)+(```"#R`*(1"0_ZUY(C90DL````$B)5"0@2(/"<$B)5"0H2,=$
-M)!``````#[:,)+(```"#R02(3"0_ZRY(C80D,`$``$B)1"0@2(/`0$B)1"0H
-M2,=$)!``````#[:4)#(!``"#R@2(5"0_2(M\)"CHY/;__X7`#X5N`@``QT0D
-M0`````!(BW0D*(M\)$#H`_S__X7`#X1!`@``2&-$)$!(P>`%2`-$)!!(B40D
-M&`^V2!A(BY0D\`$``(MT)%1(BWPD6.C[^___2(M,)!A$#[@8%=0N#?"0X``^$F`$``$$/M\5(BTPD
-M&`^V40!@`>0V#NXP#```%`0``OD````!(C7PD<.@`````
-M9D2);"1P#[=%`F:)1"1R2(M,)!@/ME$&@_H%=`^#^@IU$8#,0&:)1"1RZP=F
-M@4PD<@"`2(M4)!@/MD($B$0D=0^V0@6(A"2*````2(M,)""+01B)A"2,````
-M#[9$)#^)A"20````2(M"$$@C01`/MTPD$F)
-M1!0(2(N$)(````!)B404$$B+A"2(````28E$%!A(BX0DD````$F)1!0@2(N$
-M))@```!)B404*$B+A"2@````28E$%#!(BX0DJ````$F)1!0X_T0D1$B+5"08
-M9@^V0@=!`<5F1#MJ`@^&#/[___]$)$"#?"1`?P^.FOW__TB#Q01(@?T`````
-M#X+-^___@WPD1``/A+T```"#?"1$0;A`````#T)$)$2)1"1$2,?!`````+I`
-M````B<9,B>?HZ0(``(M,)$2)B^`3``"^`````#G.?3Y(8\Y(B(&00^W
-M!!1F08D$SD$/MT04`F9!B43.`D$/MD04!$&(1,X$00^V1!0%08A$S@7_QCMT
-M)$1\PHM4)$1,B?9(B=__DV`#``"^`````#MT)$1]*$ACQDB)P4C!X09!#[94
-MQ@9!B%0,!D$/MD3&!T&(1`P'_\8[="1$?-B+5"1$2(M$)&")$`^W@[H#``!F
-MB4,HA=(/E<`/MM")T$B+G"2X`0``2(NL),`!``!,BZ0DR`$``$R+K"30`0``
-M3(NT)-@!``!,B[PDX`$``$B!Q.@!``##4T0/MT8"08'@\,$``$B+C^@3``!(
-MA-I&3@````ZS=(B>Y(B=_H`````$B%P'0G1(M@(`^W10(EP````#W`
-M````=1-$B>"#X`^#^`%U"$&#Y/!!@\P"1(G@2(L<)$B+;"0(3(MD)!!(@\08
-MPTB#[`CH`````+H`````2(7`=`N+0!S!Z`*)PH/B`8G02(/$",-!5T%6055!
-M5%532(/L&(ET)!1!B=9(B4PD"$F)_8G03(T\./],)!1T3TB)!"1,B?U-.>]V
-M.46)]$B)ZTPIXTB)[DB)W_]4)`B%P'XB2(GI1(GV#[83#[8!B`-(_\.($4C_
-MP?_.=>Q,*>5,.>UWRDP#/"3_3"04=;5(@\086UU!7$%=05Y!7\-(@^P82(E<
-M)`A(B6PD$$B)^TB)_4B-5"0&OL$```#_ER@#``"Z`````(7`=%9F@7PD!O\_
-M=@>^R@```.L%OL\```!(C50D!$B)[_^5*`,``+H`````A@+@^`!ZP@/OT0D!,'H'XF#]!,``(N3]!,``(G02(M<)`A(BVPD
-M$$B#Q!C#4TB)^^@/\/__#[?`@_A(=%6#^$A_%8/X07\+@_A`?4:%P'0FZTJ#
-M^$/K.3V-@0``?Q$]B($``'TM@^A*@_@"=R_K(SV/@0``ZQH/MX.Z`P``/8@!
-M``!\&#V-`0``?@<]CP$``'4*2(G?Z/[^___K!;@`````6\-!5%532(/L$$F)
-M_(GS2(G]2(U4)`Z^P0```/^7*`,``(7`=%>Z`````$C'P0````!(8\)(C01`
-M2`'`9CD<`74T9H%\)`X"4'<'#[=$`0+K#$ACPDB-!$`/MT1!!&:)A;@#``!,
-MB>?HR/'__V:)A;H#``#K!__"@_H-=K5(@\006UU!7,-!5%532(/L$$F)_(GS
-M2(G]2(U4)`Z^P0```/^7*`,``(7`=%>Z`````$C'P0````!(8\)(C01`2`'`
-M9CD<`74T9H%\)`X"4'<'#[=$`0+K#$ACPDB-!$`/MT1!!&:)A;@#``!,B>?H
-M1/'__V:)A;H#``#K!__"@_H&=K5(@\006UU!7,-(@^P82(E<)`A(B6PD$$B)
-M^^AK_O__A`,``&;'@WH#`````&;'@ZP#```\`,>#L`,```````#'@^P4```#````
-MQX.L%0```````,>#L!4````'``#'@[05``#_____QX.X%0``_____\>#O!4`
-M`/____^^`````$B)W^@`````0;T#````A<`/A!H%``#'@WP#```!````2(M#
-M((N0($```&8/MM)FB9.``P``BY`8F```9HF3@@,``&;'@X8#`````,>`T)@`
-M`!8<``"]`````$F+1"0@QX"`F``````!`/_%@_T#=NI)BT0D((NX`)P``,'O
-M'+X$````Z`````#_P&9!B80DA`,``$F+5"0@1(NR$$```$2)\(/(`8F"$$``
-M`$B-5"0>OCT```!,B>?H`````$&]"````(7`#X19!```9H%\)!ZE6G0+0;T$
-M````Z44$``!(C50D'KX_````3(GGZ`````!!O0@```"%P`^$)00```^W1"0>
-M9HF#*A0``$B-5"0>OL$```!,B>?H`````$&]"````(7`#X3Y`P``#[=$)!YF
-MP>@,9HF#*!0``$&]!0```&:#^`$/A=D#``!!OP````"]`````$R-;"0@B>I)
-MC515`(VUP````$R)Y^@`````A<`/A*8#``")Z`^W1$0@03''_\6#_3]VTD&]
-M!P```$&!____```/A8@#``!(C50D'KZ_````3(GGZ`````!!O0@```"%P`^$
-M:`,``&8/MD0D'F9!B80DN`,``(M$)"1FB8,L%```#[=$)"9FB8,N%```#[9$
-M)"B(@S`4``!F#[9$)"F(@S$4```/MD0D*HB#,Q0``&8/MD0D*XB#,A0``&8/
-MMD0D+8B#-A0```^V1"0LB(,W%```9@^V1"0OB(,X%```#[9$)"Z(@SD4```/
-MMD0D,(/@`8B#-!0``(M$)#!FT>B#X`>(@S44``!)QX0D:`,```````"]````
-M`+\)````B>A(C13%`````$@IPDB-%)!(C10:2(VR.A0``(GY#[=$3"!FP>@*
-MB((Z%```#[=$3"!FP>@$@^`_B$8+#[=43"#!X@*#XCR-3P$/MT1,(&;!Z`X)
-MPHA6`0^V1$PA@^`_B$8,#[=$3"!FP>@"@^`_B$8"#[=43"#!X@2#XC"-3P(/
-MMT1,(&;!Z`P)PHA6#0^W1$P@9L'H!H/@/XA&`P^V1$P@@^`_B$8.C5<##[=$
-M5"!FP>@*B$8$#[=$5"!FP>@$@^`_B$8/#[=45"#!X@*#XCR-3P0/MT1,(&;!
-MZ`X)PHA6!0^V1$PA@^`_B$80#[=$3"!FP>@"@^`_B$8&#[=43"#!X@2#XC"-
-M3P4/MT1,(&;!Z`P)PHA6$0^W1$P@9L'H!H/@/XA&!P^V1$P@@^`_B$82C5<&
-M#[=$5"!FP>@*B$8(#[=$5"!FP>@$@^`_B$83#[=45"#!X@*#XCR-3P@"@^`_B$8*#[=43"#!X@2#
-MXC"-3P@/MT1,(&;!Z`P)PHA6%0^W1$P@9L'H!H/@/XA&%@^V1$P@@^`_B$87
-MC5<)#[=$5"!FP>@*B$88#[=$5"!FP>@$@^`_B$89#[=45"#!X@*#XCR-3PH/
-MMT1,(&;!Z`X)PHA6&@^V1$PA@^`_B$8;#[=$3"!FP>@"@^`_B$8<_\6#QPN#
-M_00/AN+]__],B>?H_0```$&_`````+T`````0;T?````1(GN*>Y(C50D'DR)
-MY^@`````A00''C50M`(G19@^V1"0?B(0+RQ0``/_"#[9$)!Z(
-MA!/+%```_\6#_0)VND6%_W0)08'__?\"`'4(0;T)````ZQ])BT0D($2)L!!`
-M``!,B>#K/$&]"````.L20;T(````28M$)"!$B;`00```2(7;=`A(B=_H````
-M`$B#?"0(`'0(2(M$)`A$B2BX`````$B!Q*@```!;74%<05U!7D%?PTB#[`CH
-M`````$B#Q`C#N`````#WQ@`!``!T#V;'`@`49L0`P``@TH$`6;'0@P`%&;'0@XV%8"/D`,```(/MD("9L=""`,`9L=""D``
-M@^">B$("@+\T%````'079L>'`!0`````QX<$%````0```(!*`H#'0A0/````
-MQX<@%````0```+@!````PY!(BU<@BT8$B8(L@```2(M7((M&#(F",(```$B+
-M5R"+1A")@C2```!(BU<@BT8(B8(X@```2(M7((L&B8(D@```PTB#["B)="0$
-M@[^,`P```70DB?`K!0````#!X`.)1"0,B?`K!0````#!X`.)1"00B70D".L8
-MQT0D#/_____'1"00_____\=$)`@!````B=`E__^``8D$)$B)YN@`````2(/$
-M*,-(BT<@QX`L@````````$B+5R"+@@2````-```0`"7__U__B8($@```2(M'
-M(,>`)(```/__``##28GX9H-^$@!T2$B+5R"+@@2````E__]__PT``"``B8($
-M@```2(M7(`^W1A")@BB```!(BU<@#[=&$HF"2(```$B+5R"+1A3!X`.)@C2`
-M``#K%4B+5R"+@@2````E__]?_XF"!(```$B+5R"+!HF"+(```$B+3R"+@22`
-M```E``"`_P^W5@@)PF:#?A@`=!$/MT88@\`$P>`0)0``?P`)PHF1)(```&:#
-MOX`#```#=CD/MT8:J`=T,4&+D+`5``"`YOAF@WX:!W<,P>`()0`'```)PNL#
-M@,X'08F0L!4``$B+1R")D!B```"0PY!(BT<@BX`(0```A<`/E<`/ML##2(M'
-M((M0'(/Z_W4,QP8`````N`````##B=`CA]04```ENM@%`8D&]\(@`'``=`<-
-M````0(D&]L(%=`.##@'WPL`%``!T`X,.0/9&`T!T!HF7"!0``+@!````PXN'
-MU!0``,-(B?E$BX?4%```187`>0M(BT<@QT`D`````(GR@>*ZV`4!B="#R`5`
-M]L8!#T700/;&0'0P@[G8%````'0#@\I`@[G<%````'0#@,X!@[G@%````'0#
-M@,J`@[GD%````'0#@,X$2(M'((E0((FQU!0``(7V>0M(BT<@QT`D`0```$2)
-MP,.0D)"X0````,.)\&:#_C]W'DC!X`4EX/\?`$B+5R"+A!`(%@>+@_Q\`2(M'(,>$
-M`@"0````````2(M'(,>$`@20````````2(M'(,>$`@B0````````2(M'(,>$
-M`@R0````````2(M'(,>$`A"0````````2(M'(,>$`A20````````2(M'(,>$
-M`AB0````````2(M'(,>$`AR0````````N`$```##N`````!F@_X_=WM(A=)T
-M/40/MD(%0<'@"`^V0@1!"<`/MDH#P>$8#[9"`L'@$`G!#[9"`<'@"`G!#[8"
-M"<'1Z42)P,'@'PG!0='HZPM!N`````"Y`````$B)\DC!X@6!XN#_'P!(BT<@
-MB8P"&)```$B+3R!$B<"`S(")A`H0($=PJX`````.DZ`0``9D&#>0(%=PA!O0````#K%F9!
-M@WD"#7<(0;T!````ZP9!O0,```!%#[99!$$/MD$%P>`(00G#00^V00;!X!!!
-M"<-!#[9!!\'@&$$)PT$QRT$/MD$)P>`(00^V40B)U0G%,`(00G"00^V00S!X!!!"<)!#[9!#<'@&$$)PD$QRD$/MD$/P>`(
-M00^V40Z)TPG#,`(00G`00^V01+!X!!!"`%2)A(BU<@1(F<
-M$`"0``!(BU<@B:P0!)```$B+5R!$B900")```$B+5R")G!`,D```2(M7($2)
-MA!`0D```2(M7($2)K!`4D```3(GBZ`````!(BUPD"$B+;"003(MD)!A,BVPD
-M($B#Q"C#D)!(@^P(2(GP2(VWRQ0``+H&````2(G'Z`````!(@\0(PTB#[`A(
-M@9,B>_H`````$B+'"1,BV0D"$R+;"002(/$&,-(BW\@C0PVN@,`
-M``#3XO?2BX<40```(<*X`@```-/@"<*)EQ1```"X`0```,-(BW\@C0PVN`,`
-M``#3X/?0BY<40```(=")AQ1```"X`0```,-(BW\@1(N'&$```+C^____B?'3
-MP$$AP(/B`=/B00G01(F'&$```+@!````PXGQN/____^#_@5W$DB+1R"+@!Q`
-M``"#X"_3Z(/@`<-(@^P(2(M'($2+B!1```!!B?!!P>`,`?:X`P```(GQT^!$
-M"<`-`(`!`/?002'!10G!08')`(```$2)R`T```$`A=)$#T7(2(M'($2)B!1`
-M``"+M]04``"!S@````'H`````$B#Q`C#2(M'((N0$$```(7V=`>#_@1T!^L-
-M@^*?ZPZ#XM^#RD#K!H/*((/BOTB+1R")D!!```##2(M'((N`!(```*D``(``
-M#Y7`#[;`_\##2(M'((N`!(```*D``(``=`>#_@)U!Y##@_X!=`](BU<@#0``
-M@`")@@2```"0P[@`````PX7V#Y3`#[;`PU532(/L"$B)^XG52(V_\!0``+H&
-M````Z`````!(BTL@#[:3\!0```^V@_$4``#!X`@)P@^V@_(4``#!X!`)P@^V
-M@_,4``#!X!@)PHF1"(```$B+2R`/MH/U%```P>`(#[:3]!0```G"B>@E_S\`
-M`,'@$`G"B9$,@```9H7M=1%(BU,@BX($@```#0``$`#K#TB+4R"+@@2````E
-M___O_XF"!(```$B#Q`A;7<-(BU<@B[)L@```BX)P@```BY)L@```C4@!.?(/
-M0L%(P>`@B=)("=##2(M'((N`;(```,-(BU<@BX(D@```#0````&)@B2```##
-M2(M'((N`9)@``(G!P>D3@>'_`0``]L4!=`:!\0#^__](BU<@BX)P@```BY)L
-M@```,=`QR,,/MY>``P``2(M'((N`($```"7_````.<(/E,`/MM")T,-(BT<@
-MBX"8@````09(BT<@BX"4@````48$2(M'((N`G(````%&#$B+1R"+@)"````!
-M1@A(BT<@BX"@@````480PTB#[!A(B1PD2(EL)`A,B60D$$B)_8GS28G\@_X(
-M=@Z^__\``.@`````.<-V$T''A"2T%0``_____[@`````ZQ^)WDB)[^@`````
-M2(M5((F"$(```(F=M!4``+@!````2(L<)$B+;"0(3(MD)!!(@\08PTB#[`A(
-MBT<@B[`0@```@>;__P``Z`````!(@\0(PTB#["A(B1PD2(EL)`A,B60D$$R)
-M;"083(ET)"!(B?U!B?:^_Q\``.@`````03G&=A''A;@5``#_____N`````#K
-M.$R+92!!BYPD%(```('C`.#__T2)]DB)[^@`````)?\?```)PT&)G"04@```
-M1(FUN!4``+@!````2(L<)$B+;"0(3(MD)!!,BVPD&$R+="0@2(/$*,-(@^P(
-M2(M'((NP%(```('F_Q\``.@`````2(/$",,/MH>O%0``@_`!@^`!PX7V="%(
-MBU<@BX($@```)?____Z)@@2```"!IZP5``#____^ZQ](BU<@BX($@```#0``
-M``&)@@2```"!CZP5```````!N`$```##2(/L*$B)'"1(B6PD"$R)9"003(EL
-M)!A,B70D($B)_4&)]K[_'P``Z`````!!.<9V$<>%O!4``/____^X`````.L[
-M3(ME($&+G"04@```@>/__P#@1(GV2(GOZ`````#!X!`E``#_'PG#08F<)!2`
-M``!$B;6\%0``N`$```!(BQPD2(ML)`A,BV0D$$R+;"083(MT)"!(@\0HPTB#
-M[`A(BT<@B[`4@```@>8``/\?P>X0Z`````!(@\0(P[@!````P\.X`````,/#
-MPTB#[`B#_@%U$872N@T```"X``````]%PNL%Z`````!(@\0(PTB#[`B#_@MT
-M#+@`````@_X>="/K'(G*@^(&B9>H`P``2(M'((F0:(```+@!````ZP7H````
-M`$B#Q`C#2(/L".@`````2(/$",.0D)!(BU<@BX($@```#0``!`")@@2```"%
-M]G052(M7((N"!$```"7___S_B8($0```PU532(/L"$B)^X7V=&5(BU<@BX($
-M0```)?___/^)@@1```"_T`<``.@`````O0H```!(BT,@BX`00```J0```0!T
-M);_(````Z`````!(BU,@BX($0```)?___/^)@@1```#_S77,ZP2%[74'N```
-M``#K&DB+4R"+@@2````E___[_XF"!(```+@!````2(/$"%M=PTB+5R"+@@2`
-M```-```$`(F"!(```(7V=!5(BU<@BX($0```)?___/^)@@1```##2(/L&$B)
-M'"1(B6PD"$R)9"00B?-(B?U!O`$```"#_@%T&(/^`7('@_X"=!?K'HG6Z`G_
-M__]!B<3K&8G6Z)#____K$(G6Z,7^___K![@`````ZPF)G>P4``!$B>!(BQPD
-M2(ML)`A,BV0D$$B#Q!C#2(M'((N`!$```"4```,`P>@0PY!3@_X!=`Y(Q\,`
-M````@_X"=!+K"4C'PP````#K![@`````ZPM(B=[H`````$B)V%O#D)"02(M'
-M((M`#,-(BT<@B7`,PTB+1R#'0`@$````PU532(/L"$B)_4B+1R#'0`@@````
-MNP````!(BT4@BT`(N@$```"H!'09OPH```#H`````/_#@?OG`P``?MRZ````
-M`(G02(/$"%M=PTB+5R"+@FB```"#X+^)@FB```##2(M7((N":(```(/(0(F"
-M:(```,-(BT<@B;!0@```2(M'((F05(```,.X`````(/^/W='@_X?=B!(BU<@
-M1(N"5(```(U.X+C^____T\!$(<")@E2```#K'4B+5R!$BX)0@```N/[___^)
-M\=/`1"'`B8)0@```N`$```##N`````"#_C]W1X/^'W8@2(M7($2+@E2```"-
-M3N"X`0```-/@1`G`B8)4@```ZQU(BT<@1(N`4(```+H!````B?'3XD0)PHF0
-M4(```+@!````PTB+1R"+@$R```##]\8``@``=`F!YO_]__^#SB!(BT<@B;!,
-M@```P\=&"`````")T"7_#P``B48,.=!T!K@`````P_;!('0'@4X,`"```,=&
-M%`````#'1A``````N`$```##]D84`74*N0\```#I"P$``/9!%`%U%$B+1R"+
-M0`RY#P```#G0#X3Q````#[=&$&8E_P]F08D!BTX4@>$`@/\/P>D/2(M'((N`
-M;(```(G"P>H*@>+__P``B=`E_Q\``#G(````#!Z`5!B$$%BT80)0``^`?!Z!-!
-MB$$&BT84]L0!=`XE`'X``,'H"4&(00?K!4'&00?_BT80)0"`!P#!Z`]!B$$(
-MBT80P>@.@^`!08A!"8M&$,'H#(/@`4&(00JY`````(G(PT%7059!54%455-(
-M@^P(2(G[08GV28G5B4PD!$V)QTF)_/9"`P%T,TB)UN@`````2(G%N@P```!(
-MA<`/A)D%``!!@_X&=!Y!@_X&=PA!@_X!=PCK$$&#_@AT"KH,````Z74%``!(
-MBT,@BX`00```@^!@B00D3(GN2(G?Z`````"Z`P```(7`#X1-!0``2(M+($$/
-MMI0DRQ0``$$/MH0DS!0``,'@"`G"00^VA"3-%```P>`0"<)!#[:$),X4``#!
-MX!@)PHF1`(```$B+2R!!#[:4)-`4``#!X@A!#[:$),\4```)T(F!!(```$2)
-M]DB)W^@!!0``08/^`70A08/^`7(.08/^!G0P08/^"'0JZT%(BT,@QT`H`0``
-M`.L+2(M#(,=`*`````!(BT,@QX`00```)!```.L92(M#(,=`*`````!(BT,@
-MQX`00```0!```$B+4R"+@A!````+!"2)@A!```!(BTL@00^VE"3P%```00^V
-MA"3Q%```P>`("<)!#[:$)/(4``#!X!`)PD$/MH0D\Q0``,'@&`G"B9$(@```
-M2(M+($$/MI0D]10``,'B"$$/MH0D]!0```G0B8$,@```2(M#(,<``````$B+
-M0R#'0`0`````2(M#(,=`#`````!(BT,@BU`$)-04````````2(M#((M0+,=`,`4```!(BT,@QT`T!0```$B+0R#'0$0(
-M````2(M#(,=`2`@```!(BT,@QT!0`````$B+0R#'0$P`````2(M#(,>`#$``
-M``````!(BT,@QT!``````$B+4R!!BX0DL!4``(F"&(```$B+0R#'@$B`````
-M````O@````!(B=_H`````$B+0R#'@%"`````````2(M#(,>`5(````````!(
-MBT,@QX!8@````````$B+0R#'@%R`````````2(M#(,>`8(````$```!(BT,@
-MQX!D@````0```$B+0R#'@&B`````````2(M#(,>`*(````````!(BT,@QX`L
-M@````````$B+0R#'@&R`````````2(M#(,>`,(```/____](BT,@QX`T@```
-M_____TB+0R#'@#B````!````O@````!(Q\<`````2&/&BQ3'@WPD!`!T#8V"
-M`(#__SW_#P``=A")T4B+4R!(8\:+1,<$B001_\:!_J8```!VS$R)[DB)W^@`
-M````N@,```"%P`^$.@(``$B+2R"+D2B8```P]D$/MH0D,10``,'@"`G"B9$H
-MF```2(MS($$/MI0D,A0``(G0P>`8P>(0"=!!#[:,)#,4``")RL'B"`G0")_P/__00^WA"0L%```9M'H)8`_```)PHF11)@`
-M`$B+2R"+D4B8``"!XO\/_/]!#[>$)"P4``#!X`HE`/`#``G"B9%(F```2(M+
-M((N19)@``('B_P_X_T$/MH0D,!0``,'@#"4`\`<`"<*)D628``!(BTL@BY$0
-MF0``@^+\00^WA"0L%```@^`#"<*)D1"9``!(B>Y(B=_H-`T``+H#````A<`/
-MA#`
-M')@```$```"_Z`,``.@`````2(M3((N"8)@``(/(`8F"8)@``+D`````N@$`
-M``"^8)@``$B)W^@`````2(GN2(G?Z`````"]`````(7`=1!F08--`@*Z`P``
-M`.FO````B>Y(B=_H`````/_%@_T"?N^#NP04````=`A(B=_H`````$B+4R"+
-M@B2````E__]__HF")(```$&#O"2T%0``_W0008NT)+05``!(B=_H`````$&#
-MO"2X%0``_W0008NT)+@5``!(B=_H`````$&#O"2\%0``_W0008NT)+P5``!(
-MB=_H`````(.[J`,```!T$$B+4R"+@Z@#``")@FB```!$B;.,`P``N`$```#K
-M#D&#/P!T`T&)%[@`````2(/$"%M=05Q!74%>05_#2(M'((N`!(```"7__P``
-M@_X!=#Z#_@%_!H7V=!^0PX/^!G0'@_X(=#J0PTB+5R`+AZP5```-``!1`.L/
-M2(M7(`N'K!4```T``%(`B8($@```PTB+5R`+AZP5```-```4`.OH2(M7(`N'
-MK!4```T``!``Z]=(@^P(B[>,`P``Z'W___](@\0(PTB#[`BZ"@```+X(````
-MZ&@#``!(@\0(PU-(B?NZ`0```+X`````Z`````"Z`````(7`=$:Z($X``+X/
-M````2(G?Z#4#``"Z`````(7`="N_Z`,``.@`````NB!.``"^'P```$B)W^@0
-M`P``OS0(``#H`````+H!````B=!;PTB#[!A(B5PD"$B);"002(G]2(GSN@$`
-M``"^`````.@`````N@````"%P`^$F0```$B+32"Z`````$B%VW0,]D,"$+@!
-M````#T70B9$$F```NB!.``"^#P```$B)[^B;`@``N@````"%P'1>O^@#``#H
-M`````+H@3@``OA\```!(B>_H=@(``+H`````A@E__]__XF")(```+^@#P``Z`````!(BU4@BX((F```#0````B)@@B8
-M``"_"@```.@`````3(GV2(GOZ&0)``"Z`````(7`#X1V`0``O^@#``#H````
-M`$B+52"+@@B8```E____]XF"")@``$B+12"+F%B8``!$BZ!_H`````$B+12")F%B8``!(BT4@1(F@7)@``$B+12"+5"0,B9!H
-MF```3(GV2(GOZ`````"%P'4?OX@3``#H`````$R)]DB)[^@`````A%]KC_____B<4/1>Y)BT0D((FP`$```.@`````@^,/B>J#X@^)V;X`0```
-M3(GGZ`````")PO;#!'4,28M$)"#'0!0`````B=!(BQPD2(ML)`A,BV0D$$B#
-MQ!C#OP````"Y"@````^VPD2-2`&-1`D#.,)U"TACP8`\,#]U>>M0C40)`P^V
-MP$$YP75+A@@P>@&`D0Q"P^VP%O#
-M@_X]N#P````/0_!FB;>L`P``N`$```##05=!5D%505154TB#[`A(B?M(B?=(
-MB=5(B=X/MX,N%```9L'H!(/@!XA"#P^V@RX4``"#X`>(0A`/MP=F+3(4N@``
-M``!F/98`#X>)`@``N0````")R&8/MH0&-A0``&8Y@[@#``!T!__!@_D#=N6Z
-M`````(/Y!`^$6P(```^W%X'J,A0``$ACPDAIP&=F9F9(P>@@P?@"P?H?*=")
-MPHU"_X/Z#`]#T(G2N*NJJJI(#Z_02,'J(4B-!-4`````2"G02(T$@DR-I#`Z
-M%```B9(B=_HH/W__T&)Q@^V50=(C4PD!$R)YDB)W^B)_?__B<*#
-MN[`#````#X0!`0``BX.P`P``#[>,```````/ME0D!P^WP8/``SG"?0?&1"0'
-M`^L$*$PD!P^V5"0'3(GF2(G?Z)7\__^(10X/MM!(C4PD`TR)YDB)W^@L_?__
-M08G%#[9$)`9(B=_H6OS__XA%"0^VT$B-
-M3"0#3(GF2(G?Z/'\__]!B<9(B=_HMOS__T&)Q@^V1"0'.D0D!'8%#[9$
-M)`2(1"0$#[;03(GF2(G?Z.3[__^(10@HT(A%`$2)Z$0H\(A%
-M`42)Z$0H^(A%`L9%!@#&104`QD4$`,9%`P"Z`0```(G02(/$"%M=05Q!74%>
-M05_#05154TB#['!(B?U)B?1(B>>Z1````$C'Q@````#H`````$B-7"10NA$`
-M``!(Q\8`````2(G?Z`````!(B=I,B>9(B>_HS_S__[H`````A<`/A&D"```/
-MMD0D7__(N@`````\!`^'50(```^V1"1@_\BZ`````#P$#X=!`@``0;P`````
-M00^WW`^V?!Q0O@4```#H`````(A$'%!!_\1F08/\!G;?0;P'````00^WW`^V
-M?!Q0O@8```#H`````(A$'%!!_\1F08/\#G;?#[9$)%'!X`4EX`````^V5"10
-M@^(?"=`)!"0/ME0D4\'B!X'B@`````^V1"12P>`"@^!\"<(/MD0D4<#H`X/@
-M`PG""50D!`^V5"14P>($@>+P````#[9$)%/0Z(/@#PG""50D"`^V5"16P>(&
-M@>+`````#[9$)%4!P(/@/@G"#[9$)%3`Z`2#X`$)P@E4)`P/ME0D5\'B`X'B
-M^`````^V1"16P.@"@^`'"<()5"00#[94)%G!X@>!XH`````/MD0D6`'`@^!^
-M"<(/MD0D5\#H!8/@`0G""50D%`^V5"1:P>(%@>+@````#[9$)%G0Z(/@'PG"
-M"50D&`^V5"1;P>(#@>+X````#[9$)%K`Z`.#X`<)P@E4)!P/ME0D7`'2@^)^
-M#[9$)%O`Z`6#X`$)P@E4)"`/MD0D7<'@!27@````"40D)`^V5"1>P>(#@>+X
-M````#[9$)%W`Z`.#X`<)P@E4)"@/MD0D7L#H!8/@`0E$)"P/MGPD7[X#````
-MZ`````#!X`\@P?\"P?@?
-M*<>^!0```.@``````<"#R$%(BU,@B8*`P)@```````!,B:/H
-M$P``N`$```!(BUPD"$R+9"002(/$&,-(BT<@BX!DF```P>@39B7_`?;$`70$
-M9C4`_IC#05154TB)_4F)]$B+1R"+D&"8``"#R@*)D&"8``"Y`````+H"````
-MOF"8``#H`````+H`````A#^+A_X>L4@_BX?@]F0<=$)!8``+H`````ZPMF08E$)!:Z`0```(G0
-M6UU!7,.X`````,.X`````,.02(/L"+@`````@_X"?QI(8\9(B<9(P>8$2"G&
-M2(VTM_@4``#H`````$B#Q`C#2(/L"$F)T+@`````@_X"?QU(8\9(B<)(P>($
-M2"G"2(V4E_@4``!,B<;H`````$B#Q`C#2(/L*$B)'"1(B6PD"$R)9"003(EL
-M)!A,B70D($F)_(GU28G52(GY@_X"=!.#_@)W!X/^`709ZSB#_@-T"NLQ0;X"
-M````ZPY!O@$```#K!D&^`````$ECUDB)T$C!X`1(*=!(C9R!^!0``(-[!`!T
-M![C_____ZTF^/````$B)W^@`````B6L$387M=2/'0PP+````QT,4`@```,=#
-M&/____]FQT,@"@!FQT,B"@#K#DR)ZD2)]DR)Y^@`````1(GP2(L<)$B+;"0(
-M3(MD)!!,BVPD&$R+="0@2(/$*,.X`````(/^`G=3B?)(B=!(P>`$2"G02(V$
-MA_@4``"#>`0`=0:X`````,/'0`0`````N/[___^)\=/`(8?8%```(8?<%```
-M(8?@%```(8?D%```(8?H%```N`$```##28GX2(N/Z!,``+@`````@_X"#X='
-M`@``B?)(B=!(P>`$2"G03(V,A_@4``!!@WD$`'4&N`````##08-Y!`%T!K@!
-M````P_9!`A`/A(````!(BT<@QX`0@```X`$``$B+1R#'@!2`````"``(2(M'
-M(,>`((```,^/W0%(BT\@08M1%(G0P>`$*=#!X!`%```/``W@`0``B8%`@```
-M2(M'(,>`1(```,`#K@5(BU<@BX)$F```@^"`@\@XB8)$F```2(M'(,>`!)@`
-M`",@`&_K?4B+1R#'@!"```!H`0``2(M'(,>`%(`````$``1(BT<@QX`@@```
-MIX_=`4B+5R!!BT$4:(400^W02+!X`0E\`````G"00^W02"#
-MX`\)PH'*`"`(`(F1'(```$'V00P!=!*X`0```(GQT^!!"8#8%```ZQ"X_O__
-M_XGQT\!!(8#8%```0?9!#`%T$K@!````B?'3X$$)@-P4``#K$+C^____B?'3
-MP$$A@-P4``!!]D$,`G02N`$```")\=/@00F`X!0``.L0N/[___^)\=/`02&`
-MX!0``$'V00P$=!*X`0```(GQT^!!"8#D%```ZQ"X_O___XGQT\!!(8#D%```
-M0?9!#`AT$K@!````B?'3X$$)@.@4``#K$+C^____B?'3P$$A@.@4``"X`0``
-M`,.)]DB)\$C!X`1(*?"+A(?\%```A;___]_2(GOZ`````!(BT4@BY!D@```A=MT#;@E````*=#1Z`'"
-MZQN#^@%V!/_*ZQ)$B>9(B>_H`````+@`````ZQI(BT4@B9!D@```1(GF2(GO
-MZ`````"X`0```$B+'"1(BVPD"$R+9"002(/$&,.)]DB)\$C!X`1(*?"+A(?\
-M%```@_@!=!&#^`%R/H/X`G0L@_@#=`_K,DB+1R#'0`@!````ZRM(BT<@QT`(
-M`@```$B+1R#'0"@.````ZQ-(BT<@QT`H"@```.L&N`````##N`$```##B?9(
-MB?!(P>`$2"GPBX2'_!0``(7`=!6#^`%U$$B+1R"+0!0E`'@``,'H"\.X````
-M`,-54TB#[`A(B?V)]DB)\$C!X`1(*?"+A(?\%```@_@!=`R#^`%R9H/X`G1+
-MZU](BT<@QT`("````+L`````2(M%((M`%/;$>'04OPH```#H`````/_#@?OG
-M`P``?N!(BT4@QT`(`````('[YP,```^>P`^VP.L;N0````"Z!````+XL````
-MZ`````#K!;@`````2(/$"%M=PT2+3"08BWPD*$&-0/U!P>`:@_@!N`````Q$
-M#T;`@>+_#P``BT0D",'@$@G"P>$,@>$`\`,`"@2B$(%BT$4)0#@'P#!Z`V(0@:+01`E``\``,'H"(A"!XM!$"7P````
-MP>@$B$((QD(*`,9""P"X`````,/#D(!.!`BX`````,.0D$B#[`A(BT<@QX#0
-MF```%AP``+H`````2(M'(,>`@)@``````0#_PH/Z!W[K2(M'((N``)P``(G'
-MP>\8B?K!Z@2)^(/@#\'@!(G7"<>^"````.@`````2(/$",-!5T%6055!5%53
-M2(/L&$F)]DF)UTB)3"0(3(D$)$&)_;^X,```Z`````!(B<-!O`(```!(A<`/
-MA#@$``!(B<6Z*!0``$C'Q@````!(B#C#````````#'@Y0P````!P``QX.8,```_____\>#G#```/_____'@Z`P
-M``#_____O@````!(B=_H`````$&\`P```(7`#X25`P``9H&[>`,``!OQ=29(
-MBT,@QX``H@```````$B+0R#'@'R8```9````O^@#``#H`````$B+12"+@"!`
-M```E_P```(G"P>H$B95\`P``@^`/9HF%@`,``(/J`D&\#0```(/Z`@^'+@,`
-M`$B+12"+@!B8``!FB86"`P``2(GOZ%X#``!!O`X```"%P`^$!P,``(.]?`,`
-M``-V$$B+12#'@`"8```'````ZPY(BT4@QX``F```1P```+_0!P``Z`````!(
-MB>_H__W__V:)A80#```/M\`E\````$&\#0```(/X$`^%L`(``$B-5"06OL$`
-M``!(B>_H`````$&\"````(7`#X20`@``9H%\)!;_+W<+0;P%````Z7P"```/
-MMT0D%F:)@R@4``!(BT4@BX`00```@^`8P>@#0;P*````@_@"#X51`@``2(U4
-M)!:^/P```$B)[^@`````0;P(````A<`/A#$"```/MT0D%F:)@RH4``!!O0``
-M``!!O`````!!C;0DP````$B-5"062(GOZ`````"%P`^$]@$```^W1"0603'%
-M0?_$08'\/P,``';/0;P'````08']__\```^%U0$``&;'@YX5```*`&;'@Z@7
-M```#`$&\`````$2)X$AKP#1FQX0#IA4```L`0?_$08/\"7;F0;P`````2,?!
-M`````$2)X`^W%$%FB91#L!<``&:)E$.J%P``2&O`-$@!V&;'@&P8```+`&;'
-M@-`7```+`$'_Q$&#_`)VQTB-LR@4``!(B>_H`````$&\"````(7`#X1``0``
-M@[U\`P```W9F9H.[0A0```!T7$B+12#'@`"8```'0```O]`'``#H`````$B)
-M[^@^_/__9HF%A@,``$B+12#'@`"8```'````O]`'``#H``````^WA88#```E
-M\````$&\#0```(/X(`^%TP```.L)9L>#0A0`````2(U4)!:^OP```$B)[^@`
-M````0;P(````A<`/A*@````/MT0D%F:)@RP4``!FB86X`P``2,>%:`,`````
-M``!(B>_H``(``$B)[^@`````0;T`````0;P`````0;X?````1(GV1"GF2(U4
-M)!9(B>_H`````(7`=$L/MT0D%D$!Q4.-%"2)T68/MD0D%XB$"_`M``#_P@^V
-M1"06B(03\"T``$'_Q$&#_`)VMT6%[70,2(GH08']_?\"`'4N0;P)````ZP9!
-MO`@```!(A=MT"$B)W^@`````2(,\)`!T!TB+!"1$B2"X`````$B#Q!A;74%<
-M05U!7D%?PU-(B?M(C;$)"`4```!````N`$```!(@\0(6UU!7$%=
-MPY"0D$B+5R"+1@2)@BB```!(BU<@BT8,B8(L@```2(M7((M&$(F",(```$B+
-M5R"+1@B)@C2```!(BU<@BP:)@B"```##2(/L*(ET)`2+AXP#``"#^`%T#X/X
-M`7(<@_@&=!>#^`AU,,=$)`S__P``QT0D$/__!P#K'HGP*P4`````P>`#B40D
-M#(GP*P4`````P>`#B40D$(U&`8E$)`B)T"7__X`!B00D2(GFZ`````!(@\0H
-MPTB+1R#'@"B`````````2(M7((N"!(````T```0`)?__S_^)@@2```!(BT<@
-MQX`@@```__\``,-)B?AF@WX2`'1#2(M7((N"!(````T``!``B8($@```2(M7
-M(`^W1A")@B2```!(BU<@#[=&$HF".(```$B+5R"+1A3!X`.)@C"```#K%4B+
-M5R"+@@2````E___O_XF"!(```$B+5R"+!HF"*(```$B+3R"+@2"````E``"`
-M_P^W5@@)PF:#?A@`=!$/MT88@\`$P>`0)0``?P`)PHF1((```$&+D)0P```P
-M]@^W1AK!X`@E`/\```G"08F0E#```$B+1R")D!B```!(BT\@BY$$0```9KH`
-M`(M&'(/H`\'@`R7__P``"<*)D01```##D)!(BT<@BX`(0```A<`/E<`/ML##
-M2(M'((N0P````(/Z_W4,QP8`````N`````##B=`ENM@%`8D&]\(```@`=`<-
-M````0(D&]L(%=`.##@'WPL`%``!T`X,.0/;"('0/@[\@%````'0&@0X```!`
-M]D8#0'1&B9<(%```2(M7((N"Q````(F'#!0``(N"R````(F'$!0``(N"S```
-M`(F'%!0``(N"T````(F'&!0``(N"U````(F''!0``+@!````PXN'_"T``,-(
-MB?E$BX?\+0``187`>1)(BT<@QT`D`````$B+1R"+0"2)\H'BNM@%`4#VQD!T
-M,(.Y`"X```!T`X/*0(.Y!"X```!T`X#.`8.Y""X```!T`X#*@(.Y#"X```!T
-M`X#.!(G0@\@'0/;&`0]%T(G0#0``"`#WQ@```$`/1=!(BT<@B9"@````B;'\
-M+0``A?9Y"TB+1R#'0"0!````1(G`P[B`````PXGP9H/^?W<>2,'@!27@_Q\`
-M2(M7((N$$!R(``"Z`0```&:%P'@%N@````")T,.)\K@`````9H/^?P^'AP``
-M`$C!X@6!XN#_'P!(BT<@QX0"`(@```````!(BT<@QX0"!(@```````!(BT<@
-MQX0""(@```````!(BT<@QX0"#(@```````!(BT<@QX0"$(@```````!(BT<@
-MQX0"%(@```````!(BT<@QX0"&(@```````!(BT<@QX0"'(@```````"X`0``
-M`,.X`````&:#_G]W>TB%TG0]1`^V0@5!P>`(#[9"!$$)P`^V2@/!X1@/MD("
-MP>`0"<$/MD(!P>`("<$/M@()P='I1(G`P>`?"<%!T>CK"T&X`````+D`````
-M2(GR2,'B!8'BX/\?`$B+1R")C`(8B```2(M/($2)P(#,@(F$"AR(``"X`0``
-M`,-!54%455-(@^P(28G128G,B?5%A<"Z`````+BJJJJJB<8/1/*X`````&:#
-M_7\/AWD!``!!#[8!@_@!=!*#^`%_!H7`=!'K1X/X!70ZZT!!O04```#K0F9!
-M@WD"!'8P9D&#>0(%=PA!O0````#K*F9!@WD"#7<(0;T!````ZQI!O0,```#K
-M$D&]!P```.L*N`````#I%`$``$4/MED$00^V007!X`A!"<-!#[9!!L'@$$$)
-MPT$/MD$'P>`800G#03'S00^V00G!X`A!#[91"(G3"<,Q\X'C__\``$4/ME$*
-M00^V00O!X`A!"<)!#[9!#,'@$$$)PD$/MD$-P>`800G"03'R00^V00_!X`A!
-M#[91#HG1"<$Q\8'A__\``$4/MD$000^V01'!X`A!"`800G`03'P9D&#>0(-=P=!@>#_````#[?UB?#!X`5(F$B+5R!$B9P0
-M`(@``$B+5R")G!`$B```2(M7($2)E!`(B```2(M7((F,$`R(``!(BU<@1(F$
-M$!"(``!(BU<@1(FL$!2(``!,B>+H`````$B#Q`A;74%<05W#D$B#[`A(B?!(
-MC;?P+0``N@8```!(BZ!@```$C'Q@````#H`````$B#Q`C#N`````##
-M2(/L&$B)7"0(2(EL)!!(B?M(B=5(BT<@B;``8```2(M'(,>`"&````$```"Y
-M`@```+H#````O@Q@``#H`````+H`````A?`!0``$&)W$&#Y!Q!P?P"@^,"T?M$B>;H`````$F+52"+@@"8``"`
-MS"")@@"8``!$B>9,B>_H`````#G8#Y7"#[;21(GF3(GOZ`````!(BQPD3(MD
-M)`A,BVPD$$B#Q!C#2(M_((N7%$```(T,-K@#````T^`)PHF7%$```+@!````
-MPTB+?R"+EQ1```"-##:X`P```-/@]]`APHF7%$```+@!````PTB+?R!$BX<8
-M0```N/[___^)\=/`02'`@^(!T^)!"=!$B8<80```N`$```##B?&X_____X/^
-M!7<22(M'((N`'$```(/@+]/H@^`!PTB#[`A(BT<@BX`40```)?Q__O^`S(")
-MP8')```!`(72#T7!2(M7((F"%$```(NW_"T``('.`````>@`````2(/$",-(
-MBU<@BX(00```)9__\?^#Y@<+!+4`````B8(00```PTB#[!A(B5PD"$B);"00
-M2(G[B=5(C;_V+0``N@8```#H`````$B+2R`/MI/V+0``#[:#]RT``,'@"`G"
-M#[:#^"T``,'@$`G"#[:#^2T``,'@&`G"B9$(@```2(M+(`^V@_LM``#!X`@/
-MMI/Z+0``"<*)Z"7_/P``P>`0"<*)D0R```!(BUPD"$B+;"002(/$&,-(BU<@
-MB[),@```BX)0@```BY),@```C4@!.?(/0L%(P>`@B=)("=##2(M'((N`3(``
-M`,-(BU<@BX(@@```#0````&)@B"```##2(M'((N`9)@``(G!P>D3@>'_`0``
-M]L4!=`:!\0#^__](BU<@BX)0@```BY),@```,=`QR,-(BT<@BX`@0```)?\`
-M``")PH/B#[D`````P>@$.8=\`P``=0YF.9>``P``=06Y`0```(G(PTB+1R"+
-M@)"````!!DB+1R"+@(R````!1@1(BT<@BX"4@````48,2(M'((N`B(````%&
-M"$B+1R"+@)B````!1A##2(/L&$B)'"1(B6PD"$R)9"002(G]B?-)B?R#_@AV
-M#K[__P``Z``````YPW8/08F<))@P``"X`````.L?B=Y(B>_H`````$B+52")
-M@G`0``")G9@P``"X`0```$B+'"1(BVPD"$R+9"002(/$&,-(@^P(2(M'((NP
-M_H`````"7_'P``"<-!B9PD%(```$2)M9PP
-M``"X`0```$B+'"1(BVPD"$R+9"003(ML)!A,BW0D($B#Q"C#2(/L"$B+1R"+
-ML!2```"!YO\?``#H`````$B#Q`C##[:'CS```(/P`8/@`<.%]G0A2(M7((N"
-M!(```"7____^B8($@```@:>,,```_____NL?2(M7((N"!(````T````!B8($
-M@```@8^,,````````;@!````PTB#["A(B1PD2(EL)`A,B60D$$R);"083(ET
-M)"!(B?U!B?:^_Q\``.@`````03G&=A''A:`P``#_____N`````#K.TR+92!!
-MBYPD%(```('C__\`X$2)]DB)[^@`````P>`0)0``_Q\)PT&)G"04@```1(FU
-MH#```+@!````2(L<)$B+;"0(3(MD)!!,BVPD&$R+="0@2(/$*,-(@^P(2(M'
-M((NP%(```('F``#_'\'N$.@`````2(/$",.X`0```,/#N`````##P\-(BT<@
-MBX`@`````2(/$",-(@^P(
-M@_X!=1:#^@%V"K@-````@_H%=0RX`````.L%Z`````!(@\0(PTB#[`B#_@MU
-M'(G*@^(&B9>H`P``2(M'((F02(```+@!````ZP7H`````$B#Q`C#2(/L".@`
-M````A<`/E<`/ML!(@\0(PY"0D%532(/L"$B)^X7V=&5(BU<@BX($0```)?__
-M_/^)@@1```"_"@```.@`````O0H```!(BT,@BX`00```J0```0!T);_(````
-MZ`````!(BU,@BX($0```)?___/^)@@1```#_S77,ZP2%[74'N`````#K&DB+
-M4R"+@@2````E___[_XF"!(```+@!````2(/$"%M=PTB+5R"+@@2````-```$
-M`(F"!(```(7V=!5(BU<@BX($0```)?___/^)@@1```##2(M7((N"!(````T`
-M``0`B8($@```A?9T%4B+5R"+@@1````E___\_XF"!$```,-(@^P82(D<)$B)
-M;"0(3(ED)!")\TB)_4&\`0```(/^`708@_X!<@>#_@)T%^L>B=;HVO[__T&)
-MQ.L9B=;H8?___^L0B=;HA____^L'N`````#K"8F=;#```$2)X$B+'"1(BVPD
-M"$R+9"002(/$&,-(BT<@BX`$0```)0```P#!Z!##D%.#_@)T)8/^`G<'@_X!
-M=`GK(H/^!'0+ZQM(Q\,`````ZQE(Q\,`````ZQ!(Q\,`````ZP>X`````.L+
-M2(G>Z`````!(B=A;PTB+1R"+0`S#2(M'((EP#,-(BT<@QT`(!````,-(@^P(
-M2(M'(,=`""````"Y`````+H$````O@@```#H`````(7`#Y7`#[;`2(/$",-(
-MBU<@BX)(@```@^#?B8)(@```PTB+5R"+@DB```"#R"")@DB```##2(M'((FP
-M0(```$B+1R")D$2```##N`````"#_C]W1X/^'W8@2(M7($2+@D2```"-3N"X
-M_O___]/`1"'`B8)$@```ZQU(BU<@1(N"0(```+C^____B?'3P$0AP(F"0(``
-M`+@!````P[@`````@_X_=T>#_A]V($B+5R!$BX)$@```C4[@N`$```#3X$0)
-MP(F"1(```.L=2(M'($2+@$"```"Z`0```(GQT^)$"<*)D$"```"X`0```,-(
-MBT<@BX`\@```PTB+1R")L#R```##QT8(`````(G0)?\/``")1@PYT'0&N```
-M``##]L$@=`>!3@P`(```QT84`````,=&$`````"X`0```,/V1A0!=0JY#P``
-M`.G(````]D$4`7442(M'((M`#+D/````.=`/A*X````/MT809B7_#V9!B0&+
-M1A0E`(#_#\'H#V9!B4$"0<9!!`"+1A2H`G4LJ`1T!T'&000!ZR'V1A00=`=!
-M@$D$".L408!)!`*+1A0EX````,'H!4&(006+1A`E``#X!\'H$T&(00:+1A3V
-MQ`%T#B4`?@``P>@)08A!!^L%0<9!!_^+1A`E`(`'`,'H#T&(00B+1A`E````
-M.,'H&T&(00F+1A#!Z`R#X`%!B$$*N0````")R,.0D)!!5T%6055!5%532(/L
-M>$B)_4&)]DB)TT&)S4R)1"0X28G\9L=$)!X``$&_`````,=$)!@`````QT0D
-M%``````/MT("]L0!=`>I@````.L,#[="`L'H!X/P`:@!=5(/MT,"J"!T!*A`
-MZPP/MT,"P>@&@_`!J`%U.$B)WDB)[^@`````2(E$)"BZ#````$B%P`^$ZP<`
-M`$&#_@9T'D&#_@9W"$&#_@%W".L008/^"'0*N@P```#IQP<``$6%[71P2(M%
-M((N03(```(E4)!B+B%"```")3"04@[U\`P```W8,BX!`$0``B40D0.L@OP``
-M``!(BTT@B?B-%+U`$0``BQ0*B52$0/_'@_\)=NE(BT0D*/9`!`)U!(!@!/Y(
-MBU0D*`^W0@)FB4,"#[9"!(A#!$B+12"+@%B```")1"00A<"X`0````]%1"00
-MB40D$$B+52"+@@2````E`````HE$)""+@A!````E8`#^`(E$)"2+BA1```")
-M3"0TBY(80```B50D,`^W_H`````+H#````A<`/A.4&```/MT,")?`!
-M```]P````'1!/<````!_"3V@````="KK/CU``0``=`D]4`$``'0+ZRYFQT0D
-M'@$`ZP=FQT0D'@(`0;\!````ZQ9FQT0D'@,`ZP=FQT0D'@0`0;\"````@[U\
-M`P```W802(M%(,>``)@```<```#K#DB+12#'@`"8``!'````@[U\`P```P^&
-M\P```(![`@`/B;H```!F08&\)"@4````,`^&J0```/9#`B!T'$$/MX0D)!4`
-M`(E$)`Q!#[>4)"@5``")5"0(ZQI!#[>,)"85``")3"0,00^WA"0J%0``B40D
-M"+X#````BWPD#.@`````B40D#+X#````BWPD".@`````B40D"$$/M_=(Q\$`
-M````BQ2Q@.(_BT0D#,'@!B7`````"<*)%+%(Q\<`````BPRW@^'PBU0D#,'J
-M`H/B`8M$)`@!P(/@#@G""=&)#+>_`````$G'P`````!!#[?WB?A(C01`08L,
-M@$B+52!(`?!!BP2`B001_\>#_QMVX4B)WDB)[^C$#```OP````!)Q\``````
-M2`^W="0>B?A(C02`08L,@$B+52!(`?!!BP2`B001_\>#_R)VX;\`````2)^$B-!$!!BPR`2(M5($@!\$&+!(")!!'_QX/_/W;AOP````!(
-MQ\8`````2!_ZH```!VT(.]?`,```-W1DB+52"+@AR````E__\/``T``-`!
-MB8(<@```2(M%(,=`7`````!(BT4@QX!XF```"````$B+52"+@DB```"`S`2)
-M@DB```!%A>UT54B+12"+5"08B9!,@```2(M%((M,)!2)B%"```"#O7P#```#
-M=A!(BU4@BT0D0(F"0!$``.L@OP````"-#+U`$0``2(M5((GXBT2$0(D$$?_'
-M@_\)=N5(BTT@00^VE"3P+0``00^VA"3Q+0``P>`("<)!#[:$)/(M``#!X!`)
-MPD$/MH0D\RT``,'@&`G"B9$`@```2(M-($$/MI0D]2T``,'B"$$/MH0D]"T`
-M``G0"T0D((F!!(```$2)]DB)[^AJ(0``2(M5((N"$$````M$)"2)@A!```!(
-MBT4@BU0D-(F0%$```$B+12"+3"0PB8@80```2(M%((M4)!")D%B```!(BTT@
-M00^VE"3V+0``00^VA"3W+0``P>`("<)!#[:$)/@M``#!X!`)PD$/MH0D^2T`
-M`,'@&`G"B9$(@```2(M-($$/MI0D^RT``,'B"$$/MH0D^BT```G0B8$,@```
-M2(M5($&+A"24,```B8(8@```2(M%(,>`@````/____^#O7P#```$=1=F@[V`
-M`P```7<-2(M5((M"%(#,!(E"%$B)WDB)[^@`````N@,```"%P`^$J`(``$&#
-M_@9T*(N%M`,``*@#=!Y(BTT@BY%$F0``@>+____?@^`!P>`="<*)D429``!(
-MB=Y(B>_H,PX``$B+="0H2(GOZ%\&``"Z`P```(7`#X15`@``9H&]>`,``!OQ
-M=12`>P(`>0Y(BT4@QX`(V````@4``$B+12#'@!R8```!````2(M%((N`%)D`
-M`"7_/P``]D,"('07P>`"B<"ZHXLNND@/K\)(P>@@P>@$ZQ*)P+K-S,S,2`^O
-MPDC!Z"#!Z`.->&3H`````$B+52"+@F"8``"#R`&)@F"8``"Y`````+H!````
-MOF"8``!(B>_H`````$B+="0H2(GOZ`````"%P'45]D,"('4%9H-+`@*Z`P``
-M`.F2`0``08.\)'0P````=!I(BT4@QX`@F0```/`!`$''A"1X,````0```+L`
-M````O@$```"-!)T`````2)A(BWT@B?*)V=/BB90X`!```/_#@_L)?M^[````
-M`(G>2(GOZ`````#_PX/["7[O2(M%(,>`I`````$``0!(BT4@QX"H`````0``
-M`$B+12#'@*P````!````2(M5((N"L!```(F"L!```$B+12#'@*````!E"0@`
-M0<>$)/PM``!E"0@`2(M5((N"K`````T```<`B8*L````08/^!G4?2(M5((N"
-MH````(#,$(F"H````$&!C"3\+0```!```(.]!!0```!T"$B)[^@`````2(M5
-M((N"((```"7__W_^B8(@@```08.\))@P``#_=!!!B[0DF#```$B)[^@`````
-M08.\))PP``#_=!!!B[0DG#```$B)[^@`````08.\)*`P``#_=!!!B[0DH#``
-M`$B)[^@`````@[VH`P```'002(M5((N%J`,``(F"2(```$2)M8P#``"X`0``
-M`.L12(M$)#B#.`!T`HD0N`````!(@\1X6UU!7$%=05Y!7\-(@^P(O@(```#H
-M5@,``$B#Q`C#4TB)^[H!````O@````#H`````+H`````A`!)@```````!(BT,@
-MQX``H@```P```$B+0R#'@'R8```9````ORP!``#H`````.F4````2(M#(,>`
-M!)@```````!F@[MX`P``$G5\2(M#(,>`?)@``!@```"_+`$``.@`````2(M#
-M(,>``*(```(```#K5$#VQ1!T$$B+0R#'@`28```#````ZPY(BT,@QX`$F```
-M`````&:#NW@#```2=29(BT,@QX!\F```&````+\L`0``Z`````!(BT,@QX``
-MH@```````+X3````2(G?Z+$!``"Z`````(7`=#2_-`@``.@`````N@$```"^
-M`````$B)W^@`````N@````"%P'0/O@````!(B=_H=@$``(G"B=!(BUPD"$B+
-M;"002(/$&,-(@^PH2(D<)$B);"0(3(ED)!!,B6PD&$R)="0@2(G[28GU28G6
-M28G\Z`````!(B<6X`````$B%[0^$"`$``(.[>#`````/A(0```!(BT,@BX`@
-MF0``J0```0!U<\>#>#````````!(BW,@B[X0G```BX84G```1(N&&)P``(GZ
-MT>J)P='I`Y(B=_H$P,`
-M`(7`=0UF08--`@)F@V4"_>LU2(GN2(G?Z`````"%P'4MOX@3``#H`````$B)
-M[DB)W^@`````A#`````/E,`/ML!!B0:X`0```$B+'"1(BVPD"$R+9"003(ML)!A,BW0D($B#
-MQ"C#2(/L&$B)'"1(B6PD"$R)9"0028G\B?.%]KC_____B<4/1>Y(BT<@BU`,
-MB;``0```OP\```#H`````(/C`XGJ@^(#B=F^`$```$R)Y^@`````B<+VPP%U
-M#$F+1"0@QT`4`````(G02(L<)$B+;"0(3(MD)!!(@\08PT%505154TB#[`A)
-MB?U)B?0/MU8"#[P2^
-M"````.@`````B<6!Y?\```#!Y06+`\'@!`G%#[=#".L%O0````!F/9``?P2H
-M`70?#[_X@^\8O@@```#H`````(G&@>;_````N`$```#K)@^_^(/O&(GXP>@?
-M`8"`<`)QH'.`00``$F+32!`
-M#[;%P>`(0`^VU@G0B8&@3``"X`0```$B#Q`A;74%<05W#2(M'((N`9)@``,'H$V8E_P'VQ`%T!&8U
-M`/Z8PT%455-(B?V)]TB+=2"+CF28``"!X0#P__^)^,'@"24`#@``"<&!XO\!
-M```)T8F.9)@``$B+52"+@F"8``"#R`*)@F"8``!!O#@```!`A/]T%D0/MN="
-MC03E`````$0IX$&)Q$'!Y`F[`````$B+12"+@&"8``"H`G011(GGZ`````#_
-MPX/[.W[CZP6#^SM^![@`````ZPE(B>_H1?___YA;74%H$=Q4/MY\,%0``
-M9HE<)!X/MX<.%0``ZV@/MP9F+8P49CWO`'<:#[>/$!4``&:)3"0>#[>?$A4`
-M`&:)7"0'%!4``&:)1"0>#[>/%A4``&:)3"0<
-MZR]F@3Y<%G8:#[>?&!4``&:)7"0>#[>'&A4``&:)1"0-EA0``&:)3"0@9H.]EA0````/E,!F1`^V^$@/MPPD
-M2,?&`````(L4CH'B____[P^WA805``#!X!P)PHD4CDC'Q@````"+%(Z!XO__
-M__L/MX6&%0``P>`:"<*)%(Y(Q\8`````BQ2.@^+W#[>%@A4``,'@`PG"B12.
-MZWX/MY\<%0``9HE<)!X/MX<>%0``9HE$)!Q$#[>WDA0```^WCY@4``!FB4PD
-M(&:#OY@4````ZS0/MY\@%0``9HE<)!X/MXWE!0```^W
-MCYH4``!FB4PD(&:#OYH4````#Y3`9D0/MOCK"K@`````Z3(!``!,#[`'00^WU\'B!@G0)<``
-M```)PT.)7*4`2B#X`,)PT.)7*4`@^/C#[=\)!R^
-M`P```.@`````P>`"@^`<"<-#B5RE`$C'P0````!"BQ2A@^+WBT0D(,'@`X/@
-M"`G"0HD4H;X`````2,?'`````$P/MR0D2&/&2(T$0(L,ATB+7"0X2(M3($P!
-MX(L$AXD$$?_&@_X8=MW'A80P````````N`$```!(@\1(6UU!7$%=05Y!7\-)
-MB?D/MT(")>`!```]P````'0K/<````!_##V@````=!;IP0```+H`````/4`!
-M``!T$>FP````N@$```#K!;H"````2&/210^WA%&B%```00^WA%&H%```P>`&
-M00G`00^WA%&N%```P>`,00G`00^WA%&T%```P>`200G`00^WA%&Z%```P>`8
-M00G`00^WC%'`%```00^WA%'&%```P>`&"<%!#[>$4`8"<&#_@%T#(/^`7(7@_X"=`?K"D2)P>L+
-M08G(ZP:X`````,-!B;%P,```2(M'($2)@&"9``!(BT<@B8ADF0``N`$```##
-M059!54%455-(B?U)B?5)B?P/MT8")>`!```]P````'1)/<````!_"3V@````
-M=#/K03U``0``=3I!O@````!(BT\@BY%$F0``@^+'#[>'B!4``,'@`X/@.`G"
-MB9%$F0``ZQI!O@$```#K$D&^`@```.L*N`````#IYP$``(.]?`,```-W%4B+
-M52"+@A"9``"#R`.)@A"9``#K6$B+32"+D1"9``"!X@;\__])8]Y!#[>$7)P4
-M``#!X`0)PH/*`8F1$)D``$&+M"1P,```3(GJ2(GOZ`````!(BU4@00^_A%R$
-M%```)?\!``"`S`*)@FB9``!(BTT@BY%$F```@>)_P/__26/V00^WA'1:%```
-MP>`')8`_```)PHF11)@``$B+32"+D4B8``"!XO\/_/]!#[>$=&`4``#!X`PE
-M`/`#``G"B9%(F```2(M-((N14)@``&:Z``!!#[Z$-($4``#!X`@E`/\```G"
-M00^VA#1^%```"<*)D5"8``!(BWT@00^WE'1R%```B=#!X!C!XA`)T$$/MXQT
-M>!0``(G*P>(("=`)R(F'-)@``$B+32"+D2B8```P]D$/MX1T9A0``,'@"`G"
-MB9$HF```2(M-((N19)@``('B_P_X_T$/MX1T;!0``,'@#"4`\`<`"<*)D628
-M``"^`@```&9!@;PD*!0```(P=QEF@;UZ`P``(A!U,T'V10)`="R^"````.LE
-M00^W10"#X!\/M\"%P'06@^@*@_@,=@Y)8\9!#[>$1-X4```!QDB+32"+D229
-M``"`X@&-!#8E]P````G"B9$DF0``N`$```!;74%<05U!7L.#_D"X/P````]"
-MQF:)AZP#``!(BT<@B;`\F0``N`$```##05=!5D%505154TB#["A)B?Q(B?5(
-MB?L/MT8")>`!```]P````'15/<````!_##V@````='OIJ@```#U``0``#X6?
-M````#[>'GA4``&:)1"0(2(V'BA4``$B)!"1(C8>@%0``2(E$)!!$#[>W`AD`
-M`$R-KP09``#I@P````^WAZ@7``!FB40D"$B-AZH7``!(B00D2(V'RA<``$B)
-M1"001`^WMU09``!,C:]6&0``ZT\/MX>H%P``9HE$)`A(C8>P%P``2(D$)$B-
-MAV88``!(B40D$$0/M[=T&0``3(VO=AD``.L;N`````#I@P```$B)T$C!X`9,
-MC;P8C!D``.M8#[=5`$B)YDR)Y^AR````0;\`````2(GN3(GGZ`````")Q[D`
-M````9H.[+!4```!T)P^WLRP5``!(8]%F@[Q3+A4```!T#`^WA%,N%0``.?AT
-MG?_!.?%\X$$/M\Y)B>A,B>I,B?Y,B>?H9@,``+@!````2(/$*%M=05Q!74%>
-M05_#05=!5D%505154TB#[!A(B7PD$$F)]T&)U6;'1"0.``!FQT0D##\`O@@!
-M``!(Q\<`````Z`````"^@````$C'QP````#H`````$G'Q@````!)Q\0`````
-MNP$```"]``````^WQ69!B1Q&_\/_Q6:#^S]V[F:)+0````!FQP4``````0!F
-MQP4`````/P"]`````&8[+0````!S)`^WW4$/MS1>3(GZ00^W_>C_!@``9D&)
-M!%S_Q68[+0````!RW$$/MS0D2`^W!0````!!#[=\1/Z]`````&8[+0````!S
-M>0^WQ69!.S1$?`I!#[CWT(G#9@,=`````'0F#[?300^W1%3^
-M9D$[!%1^"T$/MP149D&)1%3^_\5F.RT`````]`````&8[+0````!S(@^W
-M#0`````/M\5F03L\1'T*00^W/$1FB6PD#/_%9CG-M12,'H(,'X!,'Z'RG0:^@R0;T`````NP`````/O]6)UDACPDAIP!^%ZU%(
-MP>@@P?@$P?H?*=#_P(7`?CI(Q\$`````2&/&2&G`'X7K44C!Z"")Q\'_!(GX
-M*="-4`%!#[?%#[=T)`YFB31!0?_%_\,/M\,YT'SGNP````!(#[<%`````$B)
-MPF9!.VQ$_@^-R@```(/%,DB)UV9!.VQ4_GU1#[_-B`(#/\E__\`
-M``G"B?%(BVPD$$B+12")%`&#Q@3_PV:#^Q]VQDB#Q!A;74%<05U!7D%?PT%7
-M059!54%455-(@^QH2(E\)$!)B?1)B=9,B<5!B<](B7PD.&;'1"0V``!FQT0D
-M-```9L=$)#(``&;'1"0P``!FQT0D+C\`9L=$)!```$G'Q0````!!#[Y`!0'`
-M9HE$)"I!]D`#`703#[:'1A0``.L69HE<)#+I,@$``$B+5"0X#[:"1Q0```^^
-MT$B)[DB+?"1`Z`````"(1"0/387D#X2/````NP`````/M]-F08,\U`!T$D$/
-MMP349HE$5%#_PV:#^P=VXV:)7"0L#[?32(UT)%`/MWT`3(U$)$Y(C4PD3.CL
-M!0``NP````!F.UPD+',7BU0D3`^WPV8[5$10=`G_PV8[7"0LF````B<#_),4`````2`^W
-M1"0V2(T$@$$/MT1&!F:)1"0T2`^W1"0R2(T$@$$/MT1&!NMQ2`^W1"0V2(T$
-M@$$/MT1&!&:)1"0T2`^W1"0R2(T$@$$/MT1&!.M*2`^W1"0V2(T$@$$/MT1&
-M`F:)1"0T2`^W1"0R2(T$@$$/MT1&`NLC2`^W1"0V2(T$@$$/MP1&9HE$)#1(
-M#[=$)#)(C02`00^W!$9FB40D,$0/MT0D,`^W3"0T#[=4)$X/MW0D3`^W?0!!
-MN0````#H?@,``(G"#[=$)"YF.=`/1M#V10(0=!U(BTPD.&:!N2@4````,'8-
-M#[>!-A0``&8YT`]&T`^W\P^WR@^W1"0J#[Y4)`\IT#G(#T_!9D&)1'4`9H7;
-M=2U(BU0D0(N"L`,```^WA`````````8
-MB`0"<*)]\'G#@GZN#\```!F02-%
-M`@^WP,'@"`G"P>8&"?*X/P```&9!(T4`#[?`"<)!B9$TF0``2(M$)$!(BU`@
-MN#\```!F02-%#L'@&`G!1`G!N#\```!F02-%#,'@$`G!"?FX/P```&9!(T4*
-M#[?`P>`("<$)\;@_````9D$C10@/M\`)P8F*.)D``$$/MW4`2(M\)$#H````
-M`$$/MT4`2(M4)$!FB8*N`P``2(/$:%M=05Q!74%>05_#2(/L.$B)7"082(EL
-M)"!,B60D*$R);"0P2(G508G]B?,/M_8/M_](C4PD%NA"`0``AJ)W^B<`@``#[=T)!1,C40D#$B-3"0*2(GJB=_H@P(```^W
-M="0.#[=\)!)(C4PD"$B)ZNC*````#[=T)!`/MWPD$DB-3"0&2(GJZ+,```!$
-M#[=$)`8/MTPD"`^W5"00#[=T)`Y!N0````")W^CQ````08G$#[=T)`H/MWPD
-M%$B-3"0(2(GJZ'<````/MW0D#`^W?"042(U,)`9(B>KH8````$0/MT0D!@^W
-M3"0(#[=4)`P/MW0D"D&Y`````(G?Z)X````/M\!!#[?,#[=4)!0/MW0D$D&Y
-M`````$&)P$2)[^A\````#[?`2(M<)!A(BVPD($R+9"0H3(ML)#!(@\0XPTR+
-M2A!!N@````!F1#M2"'-)9D$Y.74U38U!"+@`````9D$[009S)69!.3!U$@^W
-MP$$/MT1!'F:)`;@!````PTF#P`+_P&9!.T$&(
-M,```P>`))0!^``"`S(")@C"9``#'AX0P```!````PTB#[!A(B1PD2(EL)`A,
-MB60D$$B)^TB-K]`M``"#?10`=0>X`````.MM@[^$,````75>2(M'((N`,)D`
-M`&:%P'A/P>@9B44$QX>$,````````$B)[N@*____A(L%`````/_(.09U!KC^____PXM&!(E&"#M&#'=5
-MBP4`````_\@Y!G-)2(%0``2(M&&`^W0`)FB8>&%0``2(M&
-M&`^W0`1FB8>$%0``2(M&&`^W0`9FB8>"%0``PTB)^4B+1R"+@`2````E__\`
-M`(/^`70^@_X!?P:%]G0?D,.#_@9T!X/^"'0ID,-(BU<@"X>,,```#0``@0#K
-M#TB+5R`+AXPP```-``!"`(F"!(```,-(BU<@"X&,,```#0``(`#KZ$B#[`B+
-MMXP#``#HB____TB#Q`C#2(/L&$B)'"1(B6PD"$R)9"002(G]B?/H`````$&)
-MQ(G&@>;___]_2(GOZ`````!(BT4@BU`PB=:!YO`#``#![@2%VW0-N"4````I
-M\-'H`<;K&X/^`78$_\[K$D2)YDB)[^@`````N`````#K*4B+32"!X@_\__^)
-M\,'@!"7P`P``"<*)43!$B>9(B>_H`````+@!````2(L<)$B+;"0(3(MD)!!(
-M@\08PTB#[`BX`````(/^"7\:2&/&2(G&2,'F!$@IQDB-M+<4+@``Z`````!(
-M@\0(PTB#[`A)B="X`````(/^"7\=2&/&2(G"2,'B!$@IPDB-E)<4+@``3(G&
-MZ`````!(@\0(PTB#["A(B1PD2(EL)`A,B60D$$R);"083(ET)"!)B?R)]4F)
-MU4B)^8/^`G03@_X"=P>#_@%T&>M(@_X#=`KK04&^"0```.L>0;X(````ZQ9!
-MO@````"#OQ@N````=`>X`````.MR26/62(G02,'@!$@IT$B-G($4+@``@WL$
-M`'0'N/_____K4+X\````2(G?Z`````"):P1-A>UU*L=##`L```#'0Q0"````
-MQT,8_____\=#'/\#``!FQT,@"@!FQT,B"@#K#DR)ZD2)]DR)Y^@`````1(GP
-M2(L<)$B+;"0(3(MD)!!,BVPD&$R+="0@2(/$*,-(BT\@BY<`+@``@>+_`P``
-MBX<(+@``P>`0)0``_P,)PHF1I````$B+3R"+EP0N``"!XO\#``"+APPN``#!
-MX!`E``#_`PG"B9&H````2(M/((N!K````"4`_/__BY<0+@``@>+_`P``"=")
-M@:P```##2(/L"+@`````@_X)=UZ)\DB)T$C!X`1(*=!,C82'%"X``$&#>`0`
-M=0>X`````.L\0<=`!`````"X_O___XGQT\`AAP`N```AAP0N```AAP@N```A
-MAPPN```AAQ`N``!,B<;H*?___[@!````2(/$",-(@^P(28GY08GR28G[2(N/
-MZ!,``+@`````@_X)#X>>`P``B?)(B=!(P>`$2"G03(V$AQ0N``!!@W@$``^$
-M>@,``$&#>!C_=3-(A`*)0#\#P`)PD&+0!3!X!0E``#P#PG"B10.C;>`$```28M)($$/
-MMT`BP>`$)?````!!#[=0((/B#PG0#0`@"`")!`Z-E\`)``!)BT$@QP0"``@`
-M`$&#N7P#```#=Q&-EP`1``!)BT$@QP0"`````4&#>"0`=$Q"C325`````(V^
-MP`@``$F+22!!BU`D@>+___\`08M`*,'@&`G"B10/@<;`"0``28M)((L$#HG"
-M@\H!08-X*`!T"(G"@P`^VP%M=05S#BWPD&(M,)"B!XO\/
-M``"+1"0(P>`2"<*+1"0@P>`9"<*)T`T````!]L$!#T3"B<*!R@```"#VP1`/
-M1-")T`T``$``]L$$#T3"B<*!R@``@`#VP2`/1<*)1@A$B<+!XAJ)T`T``(``
-M]L$"#T70B58,@___=!:)^,'@#24`X`\`"=")1@R!3@@```!`N`$```##N```
-M``##@4X(````(,.%R702BT8,"=")PH#.$$6%P`]$PNL=187`=`Q!BT$(B48(
-MB58,ZP_'1@@`````B="`S!")1@S'1A0`````QT80`````+@!````PTB)\?9&
-M%`%U!K@/````PXM&%"7^'P``T>AFB0(/MT829HE"`L9"!`"+1A"H`74@2B$(%BT$4)0#@
-M'P#!Z`V(0@:+01`E``\``(G&P>X(0(AR!XM!$"7P````P>@$B$((BT$0)0#P
-M``#!Z`R(0@G&0@H`QD(+`$"$]G0&C48!B$('@'H(`'0#_D((N`````##PY"`
-MCX`P```(@$X$"`^WAWXP``!FB08/MH>`,```B$8$#[:'@3```(A&!;@`````
-MPY!(BT<@QX"`0````/Q(DDB+1R#'@(!````D29(D2(M'(,>`@$```#D``"A(
-MBT<@QX"`0```)`@64TB+1R#'@(!```!Y!9CE2(M'(,>`@$```/_O'0!(BT<@
-MQX"`0```0+ZJ&DB+1R#'@(!```!451"^2(M'(,>`@$`````T)@``!8<``"Z`````$B+1R#'@("8``````$`
-M_\*#^@=^ZTB+1R"+@`"<``")Q\'O&(GZP>H$B?B#X`_!X`2)UPG'O@@```#H
-M`````$B#Q`C#2('LB````$B)_L=$)&#)____QT0D9,G____'1"1HR?___\=$
-M)&S)____QT0D<,+____'1"1`\O___\=$)$3R____QT0D2/+____'1"1,\O__
-M_\=$)%#T____QT0D(,#____'1"0DP/___\=$)"C`____QT0D+,#____'1"0P
-MNO___\<$)++____'1"0$LO___\=$)`BR____QT0D#++____'1"00L/___[D`
-M````2&/!BU2$8(F4ABA(``"+5(1`B92&/$@``(M4A"")E(902```BQ2$B92&
-M9$@``/_!@_D$?LN^`0```.@`````2('$B````,-(8_:)TDB--'(/MX1WMA<`
-M`,-!5T%6055!5%-(B?M!B?=)B=1)B#>@,`````9L>#K`,``#\`QX.P`P``````
-M`,>#K#$```````#'@[`Q````````QX.\,0``````",>#Q#$``($'``#'@\PQ
-M````````QX/0,0``/S\_`,>#U#$``&0```#'@]@Q```"````QX/P,0``____
-M_\>#]#$``/_____'@_@Q``#_____2(V[!"X``+H&````2,?&`````.@`````
-MQH/\,0```%M!7$%=05Y!7\.Y`````$G'P`````!)Q\$`````2@$08F&?`,``(G0@^`/9D&)
-MAH`#``!!#[:V@`,``$$/MKY\`P``Z!;___^%P`^$5P0``+X`````3(GWZ```
-M``"%P'4,QP0D`P```.FC!0``28M&((N`&)@``&9!B8:"`P``08.^?`,```ET
-M%4&#OGP#```*=1-F08.^@`,```-W"$B)W^C9^___2(G?Z`````"%P'4,QP0D
-M#@```.E2!0``@[M\`P``!'832(M3((N"$$```(#,$(F"$$```$B+0R#'@`"8
-M```'````2(G?Z`````!FB8.$`P``#[?`)?````"#^#`/A*(```"#^#!_#H/X
-M$`^$E````(/X(.L8@_A@#X2&````@_A@?P6#^%#K!3V@````='5F@[N$`P``
-M`'5K@[M\`P``!747@;N``P``"0!#`'4+9L>#A`,``$8`ZTN#NWP#```'=`F#
-MNWP#```+=0MFQX.$`P``40#K+H.[?`,```IT'(.[?`,```ET$X.[?`,```IU
-M'&:#NX`#```#=PEFQX.$`P``8@"#NWP#```*=$"#NWP#```)=#>#NWP#```*
-M=0IF@[N``P```W8D#[>3A`,``(G0)?````"#Z#"#^#]W#HG0@^`/@_@$#XZT
-M`@``2(U4)`:^P0```$B)W^@`````A<`/A/P#``!F@7PD!@$P=PS'!"0%````
-MZ>X#```/MT0D!F9!B88H%```2(M#((N0$$```(/B&,'J`X/Z`G0M@_H#=!R#
-MNWP#```)=!^#NWP#```*=0IF@[N``P```W8,QP0D"@```.F?`P``2(U4)`:^
-M/P```$B)W^@`````A<`/A'X#```/MT0D!F9!B88J%```2(U4)`:^'````$B)
-MW^@`````A<`/A%<#``!F@WPD!@!T/$0/MV0D!D&!Y/#_``!!P>0,2(U4)`:^
-M&P```$B)W^@`````A<`/A"0#```/MT0D!D$)Q$&![,````#K!D&\0`,``$&]
-M`````+T`````13GE&GA4```H`9D''
-MAJ@7```#`+T`````B>A(:\`T9D''A`:F%0``"P#_Q8/]"7;HO0````!(Q\8`
-M````2,?!`````(GH#[<41F9!B91&L!<```^W%$%F08F41JH7``!(:\`T3`'P
-M9L>`;!@```L`9L>`T!<```L`_\6#_0)VQ$F-MB@4``!(B=_H`````(7`#X0G
-M`@``9D&!OB@4```"4'=-@[M\`P``"G0<@[M\`P``"703@[M\`P``"G4R9H.[
-M@`,```-W*&9!QX:X%P``:`9F0<>&O!<``+`$9D''AL`7````@&9!QX:V%P``
-M`(!F08.^0A0```!T;0^W@X0#```E\````(/X$'5<2(M#(,>``)@```=```"_
-MT`<``.@`````2(G?Z`````!FB8.&`P``2(M#(,>``)@```<```"_T`<``.@`
-M````#[>#A@,``"7P````@_@@=`S'!"0-````Z5T!``!(C50D!KZ_````2(G?
-MZ`````"%P`^$/`$```^W1"0&9D&)ABP4``!FB8.X`P``2(G?Z`````"%P`^$
-M&`$``(.[?`,```IT'(.[?`,```ET$X.[?`,```IU%V:#NX`#```#=PU(B>9(
-MB=_H`````.M+@[M\`P``!W0)@[M\`P``"W4-2(GF2(G?Z`````#K+`^W@X0#
-M```E\````(/H,(/X/W<-2(GF2(G?Z`````#K"TB)YDB)W^@`````A<`/A)H`
-M``!)BX:P+@``2(F#:`,``$B)W^@`````0;T`````O0````!!O!\```!$B>8I
-M[DB-5"0&2(G?Z`````"%P'16#[=$)`9!`<6-5"T`B=%F#[9$)`=!B(0.^"T`
-M`/_"#[9$)`9!B(06^"T``/_%@_T"=KA%A>UT"4&!_?W_`@!U"<<$)`D```#K
-M%$B)W^AC]___2(G8ZR3'!"0(````387V=`A,B??H`````$V%_W0&BP0D08D'
-MN`````!(@\0(6UU!7$%=05Y!7\-32(G[Z`````!(@[MX+@```'0)2(G?_Y-X
-M+@``2(G?Z`````"Z`0```+X!````2(G?Z`````!(C;,H%```2(G?Z`````!(
-MB=_H`````%O#4TB#["#'1"0(`(```,=$)`P@F```QT0D$%55557'1"04JJJJ
-MJL=$)!AF9F9FQT0D')F9F9E!N@````!(C5PD"$F)XTECTDC!X@)$BPP31(G)
-M2(M'((L$`4&)!!-!N`````!$B<#!X!")QD0)QDB+1R")-`%(BT<@BQ0!N```
-M```Y\G5M0?_`08'X_P```'[20;@`````1(G)26/`BW2$$$B+1R")-`%(BT<@
-MBQ0!N``````YUG4Z0?_`08/X`W[926/"2,'@`HL,`TB+5R!!BP0#B0010?_"
-M08/Z`0^.8?___[]D````Z`````"X`0```$B#Q"!;PXGP]L0!=`QFQP(S$V;'
-M`=07ZR)`A/9Y(TBX``#_____``!(A8=`%```=!!FQP(("6;'`:P*N`$```##
-MN`````##055!5%532(/L"$B)_4F)_4F)_$B-GY`#``!FQT0D!@``9H&_*!0`
-M``!0=AU(C50D!K[)````_Y%+A0```$`9D''A3`4```!`$&#O"2,`P``!G1$9D&!O"1Z`P``
-M97!U-T$/MY0DN`,``(U"G&:#^`%W#HU"!69!B80DN`,``.L79D&#O"2X`P``
-M074+9D''A"2X`P``0P#'0P0`````9D&#O3X4````=!G'0P0!````9D&#O2X4
-M````=0?'0P0#````9D&#O4(4````=`2#2P0$9D&#O404````="MF08&\)'H#
-M```1#G0>BU,$B="#R`B)0P1F08.],!0```!U"(G0@\@HB4,$9L=#$`@)#[>%
-MA`,``"7P````@^@P@_@_=C>#O7P#```'="Z#O7P#```+="6#O7P#```*=!R#
-MO7P#```)=!.#O7P#```*=1)F@[V``P```W<(9L=#$L0)ZP9FQT,2K`IFQT,,
-M,Q-FQT,.U!`%#[93`8/BVPG"@\H(#[=$)`;1Z(/P
-M`8/@`0'`@^+]"<*(4P&#O7P#```&=@J)T(/($(A#`>L$@&,![X`+`V9!@[PD
-M@`,```%W"8.]?`,```MU9+H`````]D0D!@%U#/9#!`FX`0````]%T(TTE0``
-M```/MA.#XO,/MTPD!HG(P>@#@_`!@^`!P>`#"?()PH@3N@````#VP01U#/9#
-M!`FX`0````]%T,'B!`^V`X/@[PG0@\B@B`.`([^Z`````$&#O?`4````=`I!
-M@[WT%````'4%N@$````/MD,!@^#^"="(0P&`2P(/08.\)'P#```%=0QF08.\
-M)(`#```(=`M!@[PD?`,```5V!(!+`A`/MT0D!B7P`0``=`G!^`1FB4,(ZP9F
-MQT,("@!F]T0D!@#P=!4/MTPD!L'I#+@!````T^!FB4,*ZP9FQT,*@``/MX6$
-M`P``)?````"#Z#"#^#]W!H!+`F#K!(!C`I]F08.],A0```!T*DF-E"0`%```
-MO@\```!(B>__E2@#``"%P'000<>$)`04```!````@$L"@(.]?`,```0/EL`/
-MML!!B80D(!0``+H`````@[U\`P``!74*9H.]@`,```ET"8.]?`,```5V!;H!
-M````#[9#`X/@_@G0B$,#QT,4#P```+H!````B=!(@\0(6UU!7$%=PTB#[`A(
-MB>;H`````+@!````2(/$",.#_@%(Q\``````2,?"`````$@/1,)(B8?(````
-MPY!(@^P82(E<)`A(B6PD$$B)^TB)]4B+5R"+1@2)@BB```!(BU<@BT8,B8(L
-M@```2(M7((M&$(F",(```$B+5R"+1@B)@C2```#V1@,!="5(B>;H`````$B+
-M@^@3``!(QT`H`````$B+0R#'@""````````!2(M3((M%`(F"((```$B+7"0(
-M2(ML)!!(@\08PTB#["B)="0$BX>,`P``@_@!=`^#^`%R'(/X!G07@_@(=3#'
-M1"0,__\``,=$)!#__P<`ZQZ)\"L%`````,'@`XE$)`R)\"L%`````,'@`XE$
-M)!"-1@&)1"0(B=`E__^``8D$)$B)YN@`````2(/$*,-(BT<@QX`H@```````
-M`$B+5R"+@@2````-```$`"7__\__B8($@```2(M'(,>`((```/__``##28GX
-M9H-^$@!T0TB+5R"+@@2````-```0`(F"!(```$B+5R`/MT80B8(D@```2(M7
-M(`^W1A*)@CB```!(BU<@BT84P>`#B8(P@```ZQ5(BU<@BX($@```)?__[_^)
-M@@2```!(BU<@BP:)@BB```!(BT\@BX$@@```)0``@/\/MU8("<)F@WX8`'01
-M#[=&&(/`!,'@$"4``'\`"<*)D2"```!!BX#$,0``,.0/MU8:P>((@>(`_P``
-M"=!!B8#$,0``2(M7((F"&(```$0/MTX(1#E.''8$1(M.'$2+1@Q$.48<=@1$
-MBT8<13G!=06+3@3K`HL.2(M7((M&!(/H`\'@`R7__P<`#0``&`J)@M2```!(
-MBU<@C03-Z/___R7__P<`#0````J)@MB```!(BT\@00^WP42)PL'B$`G0B8'<
-M@```PTB#[!A(B5PD"$B);"002(G[2(G52(M'((FP`&```$B+1R#'@`A@```!
-M````N0(```"Z`P```+X,8```Z`````"Z`````(7`=!-(BT,@BX`$8```9HE%
-M`+H!````B=!(BUPD"$B+;"002(/$&,.0D)!(BW\@C0PVN`,```#3X(N7%$``
-M``G0B8<40```N`$```##2(M_((T,-K@#````T^#WT(N7%$```"'0B8<40```
-MN`$```##2(M_($2+AQA```"X_O___XGQT\!!(<"#X@'3XD$)T$2)AQA```"X
-M`0```,.)\;C_____@_X%=Q)(BT<@BX`<0```@^`OT^B#X`'#2(/L"$B+1R!$
-MBX@40```1(T$-K@#````1(G!T^`-`/`!`/?002'!P>8,00GQ08')`(```$2)
-MR`T```$`A=)$#T7(2(M'($2)B!1```"+MPPN``"!S@````'H`````$B#Q`C#
-M2(M'((N`"$```(/X`0^4P`^VP,-!N0````!)B?I(BT<@1(N`@````$'WP```
-M@`!T2XN0C````/?"`````;@``"``1`]%R$2)R`T``$``]\(````@1`]%R$2)
-MR`T``(``]\(````$1`]%R$2)R`T````"]\(````"1`]%R$B+1R!$BX#`````
-M08/X_W4,QP8`````N`````##1(G`);K8!0&)!D'WP```"`!T!PT```!`B09!
-M]L`%=`.##@%!]\#`!0``=%*##D!(BT<@BY#$````B=`E_P,``$$+@J1(``"!
-MX@``_P/!ZA`)PD&)DJ1(``!(BT<@BX#(````B<&!X?\#```)T24``/\#P>@0
-M"1)(BT<@QT`D`````$B+1R"+0"2)\H'BNM@%`;D`````0/;&0'0T
-M08.XO"X```!T`X/*0$&#N,`N````=`.`S@%!@[C$+@```'0#@,J`08.XR"X`
-M``!T`X#.!(G0@\@'0/;&`0]%T/?&``#@`G1&@:`P``
-MPXGP9CNWF@,``',>2,'@!27@_Q\`2(M7((N$$!R(``"Z`0```&:%P'@%N@``
-M``")T,-F.[>:`P``<@:X`````,-(B?!(P>`%)>#_'P!(BU<@BXP0%(@``,>$
-M$`"(````````2(M7(,>$$`2(````````2(M7(,>$$`B(````````2(M7(,>$
-M$`R(````````2(M7(,>$$!"(````````2(M7(,>$$!2(```'````2(M7(,>$
-M$!B(````````2(M7(,>$$!R(````````@_D$=5'VA[\Q```(=$B-1D!(P>`%
-M)>#_'P!(BU<@QX00`(@```````!(BU<@QX00!(@```````!(BU<@QX00"(@`
-M``````!(BU<@QX00#(@```````"X`0```,-F.[>:`P``<@:X`````,-(A=)T
-M/40/MD(%0<'@"`^V0@1!"<`/MDH#P>$8#[9"`L'@$`G!#[9"`<'@"`G!#[8"
-M"<'1Z42)P,'@'PG!0='HZPM!N`````"Y`````$B)\DC!X@6!XN#_'P!(BT<@
-MB8P"&(@``$B+3R!$B<"`S(")A`HP($
-M=BYF@WL"!7<(0;L`````ZREF@WL"#7<(0;L!````ZQI!NP,```#K$D&[!P``
-M`.L*N0````#ISP(``$0/MF,$#[9#!<'@"$$)Q`^V0P;!X!!!"<0/MD,'P>`8
-M00G$03'T#[9#"<'@"`^V4PA!B=9!"<9!,?9!@>;__P``1`^V0PH/MD,+P>`(
-M00G`#[9##,'@$$$)P`^V0PW!X!A!"`(#[93#D&)T4$)P4$Q
-M\4&!X?__```/MGL0#[9#$<'@"`G'#[9#$L'@$`G'#[9#$\'@&`G',?=F@WL"
-M#7<&@>?_````08/[!`^%LP$``/:%OS$```@/A*8!``!!C45`9HD$)$$/M_6)
-M\L'B!4ACTDB+32!$B>#WT(F$"@"(``!(BTT@1(GP]]")A`H$B```2(M%($2)
-MA`((B```2(M%($2)C`(,B```2(M%((F\`A"(``!(BT4@QX0"%(@```0```!,
-MB=)(B>_H``````^V`("<8/MD,6P>`0"<8/MD,7P>`8"<8/MDL8
-M#[9#&<'@"`G!#[9#&L'@$`G!#[9#&\'@&`G!0?:'P#$```1T0P^V0Q_!X`@/
-MME,>08G000G`#[9#'<'@"`^V4QQ!B=%!"<$/MGL@#[9#(<'@"`G'#[9#(L'@
-M$`G'#[9#(\'@&`G'ZQ&_`````$&Y`````$&X`````(L4)$C!X@6!XN#_'P!(
-MBT4@B;0"`(@``$B+12!$B80"!(@``$B+12")C`((B```2(M%($2)C`(,B```
-M2(M%((F\`A"(``!(BT4@QX0"%(@```<```!(BT4@QX0"&(@```````!(BT4@
-MQX0"'(@```````!,B>A(P>`%)>#_'P!(BU4@1(FD$`"(``!(BU4@1(FT$`2(
-M``#K74$/M_6)\,'@!4B82(M5($2)I!``B```2(M5($2)M!`$B```2(M5($2)
-MA!`(B```2(M5($2)C!`,B```2(M5((F\$!"(``!(BU4@1(F<$!2(``!,B=)(
-MB>_H`````+D!````B`("<(/MH,&+@``P>`0
-M"<(/MH,'+@``P>`8"<*)D>"```!(BTL@#[:3"2X``,'B"`^V@P@N```)T(F!
-MY(```+@!````6\-F.;>X`P``=0>X#````.L4@+\J%`````^8P`^VP(T$Q0,`
-M``!(A=)T`HD"N`````##2(GZN`````!F@[\^%````'04N`$```!F@[\N%```
-M`'4%N$,```!F@[]"%````'0#@\@$9H._1!0```!T&V:!NGH#```1#G00@\@(
-M9H._,!0```!U`X/((,-(@^P82(D<)$B);"0(3(ED)!!(B?L/MX<`%```08G$
-M08/D'$'!_`*)Q8/E`M']1(GF_Y=``P``2(M3((N"`)@``(#,((F"`)@``$2)
-MYDB)W_^32`,``(GJ.>AU"(7M#Y3`#[;01(GF2(G?_Y-8`P``2(L<)$B+;"0(
-M3(MD)!!(@\08PTB+5R"+@A!````EG__Q_X/F!PL$M0````")@A!```##2(/L
-M&$B)7"0(2(EL)!!(B?N)U4B-O_XM``"Z!@```.@`````2(M+(`^VD_XM```/
-MMH/_+0``P>`("<(/MH,`+@``P>`0"<(/MH,!+@``P>`8"<*)D0B```!(BTL@
-M#[:#`RX``,'@"`^VDP(N```)PHGH)?\_``#!X!`)PHF1#(```$B+7"0(2(ML
-M)!!(@\08PTB+5R"+LDR```"+@E"```"+DDR```"-2`$Y\@]"P4C!X"")TD@)
-MT,-(BT<@BX!,@```PTB+5R"+@B"````-`````8F"((```$B+5R")@B"```##
-M2(N'Z!,``$B%P'1I]D`"('1C0;@`````N@`````[%G,=2&/"#[9$,`2$P'D+
-M@^!_1#C`<@-!B<#_PCL6L,0``N`$```#K!>@`````2(/$",.X`0```,-(@^P82(D<)$B);"0(
-M3(ED)!!(B?V)\TF)_(/^!78.OO__``#H`````#G#=A-!QX0D\#$``/____^X
-M`````.L?B=Y(B>_H`````$B+52")@G`0``")G?`Q``"X`0```$B+'"1(BVPD
-M"$R+9"002(/$&,-(@^P(2(M'((NP_H````
-M`"7_/P``"<-!B9PD%(```$2)M?0Q``"X`0```$B+'"1(BVPD"$R+9"003(ML
-M)!A,BW0D($B#Q"C#2(/L"$B+1R"+L!2```"!YO\_``#H`````$B#Q`C##[:'
-MOS$``(/P`8/@`<.%]G0A2(M7((N"!(```"7____^B8($@```@:>\,0``____
-M_NL?2(M7((N"!(````T````!B8($@```@8^\,0```````;@!````PTB#["A(
-MB1PD2(EL)`A,B60D$$R);"083(ET)"!(B?U!B?:^_S\``.@`````03G&=A''
-MA?@Q``#_____N`````#K.TR+92!!BYPD%(```('C__\`P$2)]DB)[^@`````
-MP>`0)0``_S\)PT&)G"04@```1(FU^#$``+@!````2(L<)$B+;"0(3(MD)!!,
-MBVPD&$R+="0@2(/$*,-(@^P(2(M'((NP%(```('F``#_/\'N$.@`````2(/$
-M",-!B=")\;@,````9H/Y?W@/K_"--':!Q@0!
-M``!`#[;-#Z_(C01)C8P`K`T``.M72(N#Z!,``&:#>`(`>2A`#[;UB?C!Z`(/
-MK_"--':!QM(```!`#[;-#Z_(C01)C8P`2`T``.LA0`^V]0^O]XTT=H'&:`$`
-M`$`/MLT/K\^-!$F-C`!@#@``0`^VU0^OUXT44H'"Z`,``('B_S\``$B+0R")
-ML'`0``!(BT,@B8BP$```2(M+((G0P>`0"=")@12```!(BUPD"$B+;"002(/$
-M&,-(@^P(B[>,`P``Z`````!(@\0(P[@`````@_X&=!>`OTL4````=`Z#O]@Q
-M```!=P6X`0```,-32(G[Z`````"%P`^$00$``$B+0R#'@'"8```?````2(M3
-M(`^W@X0#```E\````(/H,(/X0!G`@^#\@\`8B8+XF0``2(M3((N"'(```"5_
-MP/__#(")@AR```!(BT,@QX`$@0``/0```$B+4R"+@A!```"#R`*)@A!```"#
-MNWP#```'="Z#NWP#```+="6#NWP#```*=!R#NWP#```)=!.#NWP#```*=5AF
-M@[N``P```W=.2(M#(,>`=)@``"8```!(BT,@QX!XF```#0```$B+0R#'@/"9
-M```'````2(M#(,>`])D``#\```!(BU,@BX(00```)?____P-`````NM'2(M#
-M(,>`=)@```H```!(BT,@QX!XF```#````$B+0R#'@/"9```#````2(M#(,>`
-M])D``"````!(BU,@BX(00```#0````.)@A!```#IR@```$B+4R"+@A!````E
-M_____(F"$$```$B+4R"+@A!```"#X/V)@A!```!(BT,@QX!PF```'P```$B+
-M0R#'@'28``!_````2(M#(,>`>)@```X```!(BT,@QX#PF0``#````$B+0R#'
-M@/29``#_````2(M3(`^W@X0#```E\````(/H,(/X0!G`@^#\@\`2B8+XF0``
-M2(MS((N&'(```"5_P/__#[>3A`,``('B\````(/J,(G!@3A`,``('B\````(/J,(G!@`>)@```X`
-M``!(BT,@QX#PF0``#````$B+0R#'@/29``#_````2(M3(`^W@X0#```E\```
-M`(/H,(/X0!G`@^#\@\`8B8+XF0``6\.Z`````$C'QP`````/MP:)P68[!0``
-M``!W"__"2&/"9CL,AW;U2&/"#[\$A0````##2(/L&$B)7"0(2(EL)!")TTB)
-MS4B)^4B-EY`#``"#_AT/AR("``")\/\DQ0````"#^P)T)H/[`@^"!`(``(/[
-M!`^"B0```(/[!0^&\@$``(/[?P^$Z0$``.MU]D(!(.DT`0``N`````"%VP^$
-MX@$``(/[`74.BX>\,0``P>@;Z70$``+@`````A=L/A&P!``"#^P$/A<4```!(BT<@
-MBX`(H@``P>@-Z?D```"+AZ@#``#I,@$``+@`````A=L/A#D!``"#^P$/A1\!
-M``"#O\PQ````ZR:%VW0'@_L!=`SK)F:#OSX4````ZQ%(N```_____P``2(6'
-M0!0```^4P`^VP.GV````N`$```#I[````+@`````A=L/A-\```"#^P%U/(N'
-MO#$``/?0P>@?Z@(ZV6#^P%T%K@`````@_L!L6#[9"#.L0
-M#[9"#>L*#[9""^L$#[9""HE%`+@`````ZPI(B>F)VN@`````2(M<)`A(BVPD
-M$$B#Q!C#2(/L"$F)^DR-CY`#``"#_AT/AW`!``")\/\DQ0````"%R70/@8^\
-M,0``````".E-`0``@:>\,0``____]^D^`0``0?9!`1!U"K@`````Z3D!``"%
-MR70)@Z?`,0``^^L'@X_`,0``!$B+5R!!BX+`,0``B8(@@0``Z0,!``!(BT<@
-MB[`(H@``B?*`SB")\(#DWX7)B=8/1/!(BT<@B;`(H@``Z=D```")CZ@#``!(
-MBT<@B8A(@```Z<0```"%R0^5P`^VP(F'S#$``.FQ````A(`/P``B<@E`#\``,'H"`G008F"T#$`
-M`$B+5R!!BX+0,0``B8+H@```ZS>X`````(/Z!G#I\`Q``#WN`$```#K!>@`````2(/$
-M",-(@^P(Z`````"%P`^5P`^VP$B#Q`C#D)!54TB#[`A(B?N%]G1E2(M7((N"
-M!$```"7___S_B8($0```OPH```#H`````+TH````2(M#((N`$$```*D```$`
-M="6_,@```.@`````2(M3((N"!$```"7___S_B8($0```_\UUS.L$A>UU![@`
-M````ZQI(BU,@BX($@```)?__^_^)@@2```"X`0```$B#Q`A;7<-(BU<@BX($
-M@```#0``!`")@@2```"%]G0:2(M7((N"!$```"7___S_#0```0")@@1```##
-M2(M7((N"!(````T```0`B8($@```A?9T&DB+5R"+@@1````E___\_PT```(`
-MB8($0```PTB#[!A(B1PD2(EL)`A,B60D$(GS2(G]0;P!````@_X!=!B#_@%R
-M!X/^`G07ZQZ)UNC0_O__08G$ZQF)UNA7____ZQ")UNB"____ZP>X`````.L)
-MB9VH,0``1(G@2(L<)$B+;"0(3(MD)!!(@\08PTB+1R"+@`1````E```#`,'H
-M$,.0D)!3@_X(#X2'````@_X(=R*#_@(/A((```"#_@)W"H/^`70XZ:````"#
-M_@1T7.F6````@?X``0``='.!_@`!``!W!X/^('1=ZW^!_@`"``!T98'^``0`
-M`'1FZVU(Q\,`````2(._Z!,```!T8TB+A^@3``#V0`-`=3U(BX?H$P``9H-X
-M`@!Y2.LV2,?#`````.L]2,?#`````.LT2,?#`````.LK2,?#`````.LB2,?#
-M`````.L92,?#`````.L02,?#`````.L'N`````#K"TB)WN@`````2(G86\.0
-M2(M'((M`#,-(BT<@B7`,PTB+1R#'0`@$````PTB#[`A(BT<@QT`((````+D`
-M````N@0```"^"````.@`````A<`/E<`/ML!(@\0(PU-(B?M(BU<@BX)(@```
-M@^#?B8)(@```Z`````"^`0```$B)W^@`````6\-(@^P(2(M7((N"2(```(/(
-M((F"2(```.@`````2(/$",-(BT<@B;!`@```2(M'((F01(```,.X`````(/^
-M/W='@_X?=B!(BU<@1(N"1(```(U.X+C^____T\!$(<")@D2```#K'4B+5R!$
-MBX)`@```N/[___^)\=/`1"'`B8)`@```N`$```##N`````"#_C]W1X/^'W8@
-M2(M7($2+@D2```"-3N"X`0```-/@1`G`B8)$@```ZQU(BT<@1(N`0(```+H!
-M````B?'3XD0)PHF00(```+@!````PTB+5R"+@CR```"+B@R!``")PH#.`O;!
-M(`]%PHG"@,X!]\$```("#T7"PTB+5R!`#[;&B8(\@```N`````#WQ@`"``"Z
-M(`````]%PHG"@@)08A`!^L%0<9`!_^+1A`E`(`/`,'H#T&(0`B+1A`E````\,'H
-M'$&(0`F+1A#!Z`R#X`%!B$`*BT84J`)U3J@$=`=!@$@$`>M#]D84$'0E08!(
-M!`(/MD8508A`!8._%#(```!U)X/X!70B3(G&Z`````#K&/9&%`AT!T&`2`0(
-MZPOV1A0@=`5!@$@$$+D`````BI@````.L,#[="
-M`L'H!X/P`:@!#X5D`@``00^W1"0"J"!T!*A`ZPY!#[=$)`+!Z`:#\`&H`0^%
-M0@(``+H!````O@````!(B>_H`````+H`````A<`/A*T,``!,B>9(B>_H````
-M`$B)1"08N@P```!(A<`/A'X,``"#?"1`!G0?@WPD0`9W#8-\)$`!#X?L`0``
-MZPN#?"1`"`^%WP$``,=$)!0`````@WPD/`!T*$B+12"+@$`1``")1"042(MT
-M)!A(B>_H`````+X`````2(GOZ`````"#O7P#```'="Z#O7P#```+="6#O7P#
-M```*=!R#O7P#```)=!.#O7P#```*=5UF@[V``P```W=3@WPD/`!T3$B#O>@3
-M````=$)(BXWH$P``00^W!"1F.P%T,4$/MU0D`H'B\`$```^W00(E\`$``#G"
-M=1A,B>9(B>_H`````+H!````A<`/A:@+``!(BT4@BX!8@```B40D$(7`N`$`
-M```/140D$(E$)!!(BU4@BX($@```)0``(`*)1"0(BX(00```)6``_@")1"0,
-MBX(40```B40D+(N2&$```(E4)"B+="1`2(GOZ`````!(B>_H`````$R)YDB)
-M[^@`````N@,```"%P`^$%PL``$$/MT0D`B7P`0``/4`!``!T3#U``0``?R`]
-MP````'1C/<````!_"3V@````=$OK;CW0````=%;K93W`"```=$,]P`@``'\'
-M/5`!``#K##U`"0``=`D]4`D``'0,ZT#'1"0$`0```.L(QT0D!`(```#'!"0!
-M````ZR_'1"0$`P```.L2QT0D!`0```#K",=$)`0%````QP0D`@```.L*N@P`
-M``#I;PH``$B+12#'@`"8```'````NP````!)Q\<`````1(MT)`1(8\-(C01`
-M08L,QTB+52!)C01&08L$AXD$$4'_Q4'VQ3]U"K\!````Z`````#_PX/[&';,
-MNP````!(8\.+%,4`````@WPD/`!T%HV"X'___X/X&'8QC8(L?___@_@(=B:)
-MT4B+52!(8\.+!,4`````B0010?_%0?;%/W4*OP$```#H`````/_#@?O#````
-M=JE$B>F+%"2+="0$2(GO2(M<)"#_DX`N``!!]D0D`T!U"69!@WPD`@!Y"TR)
-MYDB)[^@`````9H.]@@,``$$/ANT```!(BT4@QX`LF````J`"`&9!@3PDM`EU
-M+TB+1"0@#[:02A0```^W@%04```IPDACPDAIP&=F9F9(P>@@T?C!^A^)QF8I
-MUNL=2(M4)"`/MH)*%```2)A(:Y!#[=$)`(ET````#W`
-M````=3%(BTT@2(M<)"`/MI-*%```]]K!X@:!XL`/``")\,'@$O?8)0``_``)
-MPHF13)D``.L.2(M%(,>`3)D```````!(BU4@BX(HH@``@.3]B8(HH@``2(M5
-M((N"**(``"7_`_[_@,P(B8(HH@``2(M%(,>`8(````\```!F@[V"`P``0G8.
-M2(M%(,>`5*(```````!(BT4@QX!XF```#@```(.]?`,```IT'(.]?`,```ET
-M$X.]?`,```IU.F:#O8`#```#=S"Y`0```&9!@3PDG@ET"69!@3PDHPEU!;D`
-M````2(M5((N"3*(``#G(=`:)BDRB``!(C50D1$B+="082(GOZ`````"Z`P``
-M`(7`#X3W!P``@WPD0`9T$8.]M`,```!T"$B)[^@`````#[=4)`1(C4PD1$B+
-M="082(GO2(M<)"#_DY@N``"Z`P```(7`#X2U!P``0?9$)`)`=%^#O7P#```*
-M="R#O7P#```)=".#O7P#```*=0IF@[V``P```W802(M$)"!F@;@H%````E!V
-M'T$/MT0D`B6@````/:````!T#4B+="082(GOZ`````!,B>9(B>_H`````$B+
-M="082(GOZ`````"Z`P```(7`#X0T!P``@WPD/`!T#DB+12"+5"04B9!`$0``
-M2(M-($B+7"0@#[:3^"T```^V@_DM``#!X`@)P@^V@_HM``#!X!`)P@^V@_LM
-M``#!X!@)PHF1`(```$B+32`/MI/]+0``P>((#[:#_"T```G0"T0D"`N#O#$`
-M``T``(``B8$$@```BW0D0$B)[^@`````2(M-(`^VDP0N```/MH,%+@``P>`(
-M"<(/MH,&+@``P>`0"<(/MH,'+@``P>`8"<*)D>"```!(BTT@#[:3"2X``,'B
-M"`^V@P@N```)T(F!Y(```$B+52"+@A!````+1"0,B8(00```2(M%((M4)"R)
-MD!1```!(BT4@BTPD*(F(&$```$B+12"+7"00B9A8@```2(M-($B+1"0@#[:0
-M_BT```^V@/\M``#!X`@)PDB+7"0@#[:#`"X``,'@$`G"#[:#`2X``,'@&`G"
-MB9$(@```2(M-(`^VDP,N``#!X@@/MH,"+@``"=")@0R```!(BU4@BX/$,0``
-MB8(8@```2(M%(,>`@````/____](BW0D&$B)[^@`````N@,```"%P`^$B04`
-M``^VM?`3``"Z`0```$B)[^@`````3(GF2(GOZ``````/MX6$`P``)?````"#
-MZ#"#^#]W0$B+A>@3``#V0`-`=0=F@W@"`'DL2(N%Z!,``/9``T`/E,`/ML"#
-MP`Q(BTT@BY$DF```@^+P@^`/"<*)D228``!(BT4@BX`4F0``B<*!XO\_``!!
-M]D0D`B!T'8T$E0````")P+JCBRZZ2`^OPDC!Z"")PL'J!.L4B="ZS@@B<+!Z@-(BT4@QX`@3``#V0`-`=`:-?!)DZQI(
-MBX7H$P``9H-X`@!Y"8T\E60```#K`XUZ9.@`````2(M%($2+J`B8``#'@`B8
-M````.```NP$```!(BT4@BX`DG```J!!T(;_(````Z`````")V/_#@_@3?PY(
-MBT4@BX`DG```J!!UWTB+12!$B:@(F```2(M5((N"8)@``(/(`XF"8)@``$$/
-MMT0D`B6@````/:````!T1TB+1"0@@[BP,0```G0Y2(M5((N"()D``(#,\(F"
-M()D``$B+52"+@B"9```-```!`(F"()D``$B+5"0@QX*P,0```0```.L/2(M,
-M)"#'@;`Q````````2(GOZ`````"[`````+X!````C02=`````$B82(M]((GR
-MB=G3XHF4.``0``#_PX/["7[?2(M<)"#'@Z1(````````NP````!F@[V8`P``
-M`'07B=Y(B>_H`````/_##[>%F`,``#G#?.E(BT0D(,>`#"X``&4)"`"#?"1`
-M!G4*QX`,+@``91D(`$B+52!(BTPD((N!#"X``(F"H````$B+52"+@JP````-
-M```'`(F"K````(.]!!0```!T"$B)[^@`````N0````"Z`0```+Y@F```2(GO
-MZ`````"+="1`2(GOZ`````!(BU4@BX(@@```)?__?_Z)@B"```"#O7P#```%
-M=Q.#O7P#```%=29F@[V``P``!W8<2(M%(,>`&($``*H``0!(BT4@QX`<@0``
-M$#(``$B+12#'@`B!``!2````0?9$)`,!=`Y(BUPD(`^V@T84``#K#$B+5"0@
-M#[:"1Q0```^^T$R)YDB)[^@`````08G!2(M,)"!$BX'0,0``08/@/P^_@>PQ
-M``!$B<$IP4B+7"08#[Y3!HT$$#G11`]'P`^^0P4!P$$/OM&)QBG603GP=A!(
-MBU0D(`^_@NPQ``!$C00P2(M,)""+N=`Q``"!YP`_``#![P@/OX'L,0``B?DI
-MP4B+7"08#[Y3!HT$$#G1#T?X#[Y#!0'`00^^T2G0B<(YQW8/2(M,)"`/OX'L
-M,0``C3P02(M<)""+L]`Q``"!Y@``/P#![A`/OX/L,0``B?$IP4B+7"08#[Y3
-M!HT$$#G1#T?P#[Y#!0'`00^^T2G0B<(YQG8/2(M,)"`/OX'L,0``C30008/X
-M0+@_````1`]#P(/_0`]#^(/^0`]#\$2)PH/B/XGXP>`()0`_```)PHGPP>`0
-M)0``/P`)PDB+12")D.B```!(BUPD((.[P#$```!T$$B+52"+@\`Q``")@B"!
-M``!(BT0D((.X\#$``/]T#HNP\#$``$B)[^@`````2(M4)""#NO0Q``#_=`Z+
-MLO0Q``!(B>_H`````$B+3"0@@[GX,0``_W0.B['X,0``2(GOZ`````"#O:@#
-M````=!!(BU4@BX6H`P``B8)(@```BUPD0(F=C`,``(-\)#P`='%(BT0D&/9`
-M!`)U!(!@!/Y(BU0D&`^W0@)F08E$)`(/MD($08A$)`0/MD(%08A$)`4/MD(&
-M08A$)`8/MD('08A$)`=(BX7H$P``2,=`,`````!(BYWH$P``2(GOZ`````!(
-MB4,HO@$```!(B>_H`````+H!````ZQ%(BTPD,(,Y`'0"B1&Z`````(G02(/$
-M2%M=05Q!74%>05_#B[>T`P``0/;&`W0@2(M/((N11)D``('B____WXGP@^`!
-MP>`="<*)D429``")\(/@#'0KJ`1U%$B+5R"+@M"```"#X..)@M"```##2(M7
-M((N"T(```(/('(F"T(```)##2(/L"/^7D"X``(7`#Y7`#[;`2(/$",-!5T%6
-M055!5%532(/L"$B)_4F)]$&]`0```$F)_^@`````28G&NP````!F@[V8`P``
-M`'0;B=Y(B>_H`````(7`=1W_PP^WA9@#```YPW+EN@````!%A>T/A+L!``#K
-M"$&]`````.OH2(M%(,>`?)D```$```"[`````$B+12"+@""<``"%P'43OP4`
-M``#H`````/_#@_MC=N'K!8/[8W8*N@````#I;@$``$R)]DB)[^@`````N@``
-M``"%P`^$5@$``$B+12"+@!29```E_S\``$'V1@(@=!?!X`*)P+JCBRZZ2`^O
-MPDC!Z"#!Z`3K$HG`NLW,S,Q(#Z_"2,'H(,'H`XUX9.@`````2(GB3(GV2(GO
-MZ`````"Z`````(7`#X3T````2(M%(,>`?)D```````!!]D8"0'19@[U\`P``
-M"G0H@[U\`P``"70?@[U\`P``"G4*9H.]@`,```-V#&9!@;\H%````E!V'4$/
-MMT0D`B6@````/:````!T"TR)]DB)[^@`````3(GF2(GOZ`````!(BU4@BX)@
-MF```@\@"B8)@F```0?9&!`)U!4&`9@3^00^W1@)F08E$)`)!#[9&!$&(1"0$
-M00^V1@5!B$0D!4$/MD8&08A$)`9!#[9&!T&(1"0'2(N%Z!,``$C'0#``````
-M2(N=Z!,``$B)[^@`````2(E#*+X!````2(GOZ`````"Z`0```(G02(/$"%M=
-M05Q!74%>05_#2(M'((N`!(```"7___S_@_X!=$^#_@%_!H7V="F0PX/^!G0'
-M@_X(=#J0PTB+5R`-```!$(F"!(```$B+5R"+0A2#X-_K&4B+5R`-```"$(F"
-M!(```$B+5R"+0A2#R"")0A3#2(M7(`T````0B8($@```PTB#[`B^`@```.@>
-M!0``2(/$",-32(G[N@$```"^`````.@`````N@````"%P'0/OA,```!(B=_H
-M\`0``(G"B=!;PTB#["A(B5PD"$B);"003(ED)!A,B6PD($B)^TB)];X3````
-MZ,($``"Z`````(7`#X0``@``N@$```"^`````$B)W^@`````N@````"%P`^$
-MX0$``+X`````2(G?Z(D$``"Z`````(7`#X3'`0``2(7M#X2Y`0``@[M\`P``
-M"G0<@[M\`P``"703@[M\`P``"G4O9H.[@`,```-W)4&]"`````^W10*H('57
-M)=````"Y!````#W`````#X6L````ZT`/MX.$`P``)?````"#Z#"#^#]V$H.[
-M?`,```=T"8.[?`,```MU0T&]"`````^W10*H('4,)=`````]P````'4'N>L`
-M``#K8_9%`T!T![GJ`0``ZU9F@WT"`'D'N>H"``#K2+GJ````ZT%!O0`````/
-MMT4"J"!U#"70````/<````!U![FK````ZR#V10-`=`>YJ@$``.L39H-]`@!Y
-M![FJ`@``ZP6YJ@````^W10*H0'06J"!U#"70````/<````!U!D&#S03K#D2)
-MZ(/(`?9%`D!$#T3H1(GH@\@"]D4#`40/1.CV10(0#Y7`1`^VX$>-)&1(BT,@
-MBY!\F```#[=%`J@@=0PET````#W`````=3!(BT,@1(F@!)@``$B+0R!$B:@`
-MH@``.0/A&$"``"#N[`Q```"=`F#N[`Q````=0?'10`!````
-M08.]L#$```$/A4@!``!(BT,@BX`@F0``J0```0`/A3,!``!!QX6P,0``````
-M`,=%``$```"^`````$B+0R"+N!"<``"+B!2<``!$BX`8G```A?]T!(7)=1Q(
-MBU,@BX(@F0``#0```0")@B"9``#_QH/^"7[%B?C1Z(G*T>H!T(G.P>X'B<'!
-MZ0^\/___^L+@_X0N`\`
-M```/3?!(BTL@BY$@F0``@>(?^/__1(G`P>`%)>`'```)PHF1()D``$B+2R"+
-M@2"9``"#X.")\H/B'PG0B8$@F0``2(M3((N"()D``(#,"(F"()D``$''A;`Q
-M```"````0<=$)!`!````18A$)!1!B'0D%>M600^W1@(EH````#V@````=$5!
-M@[VP,0```G4[08-\)!``=3-(BU,@BX(@F0``@,SPB8(@F0``2(M3((N"()D`
-M``T```$`B8(@F0``0<>%L#$```$```!,B>9(B=_H`````$'V1"0"`G5W2(M3
-M((N"8)@``(/(`HF"8)@``$$/MU8"]L8!=1D/MX.$`P``)?````"#Z#"#^#]W
-M4_;"0'1.@[M\`P``!W1%@[M\`P``"W0\@[M\`P``"G0S@[M\`P``"70J@[M\
-M`P``"G4*9H.[@`,```-V%TB)W^C6'@``ZPUF08-.`@)F08-D)`+]N`$```!;
-M74%<05U!7L-(@^P82(D<)$B);"0(3(ED)!!(B?V)\X7VN/____]!B<1$#T7F
-M@[]\`P``"703@[]\`P``"G4-9H._@`,```-W`X/C[TB+12"+4`R)F`!```"_
-M#P```.@`````@^,#1(GB@^(#B=F^`$```$B)[^@`````08G$]L,!=2M(BT4@
-MQT`4`````+H!````O@````!(B>_H`````(7`=`I(BT4@BX#`````1(G@2(L<
-M)$B+;"0(3(MD)!!(@\08PTB+1R"+@&28``#!Z!-F)?\!]L0!=`1F-0#^F,,/
-MMT8")>`!```]P````'0I/<````!_"3V@````=!+K*3U``0``=2(/MX>$%```
-MZQ`/MX>&%```ZP(%```9HD"N`$```##N`````##2(/L*$B)7"002(EL
-M)!A,B60D($B)^TB)]4B+1R"+@&"8``!!O`````"H`G4TZ`````!!B<1(C50D
-M#DB)[DB)W^AL____A```8```````!(BU<@BX(`!@``@\@(B8(`!@``2(M'(,>`!`8```$"
-M$`!(BT<@QX`@!@```````+D`````2(M&((F(``0``$B+5B!(8\$/MH0'*#$`
-M`(F"!`0``/_!@_E_?MJ0PT%505154TB#[`A(B?U!B?2_`````$2-4O]!P>H#
-M1(U"_T&#X`=!B?%!NP````"%]GYFNP$```"--,T`````1XTL`4&#_0FX"```
-M`$0/0^B)V$2)Z=/@_\B)VD2)P=/B_\HQT(GQT^!$B=(C1)4`T^A$B<'3Z$2)
-MV=/@"<=$B>E$*<%!`$4:(4``!!#[>$
-M4:@4``#!X`9!"$4:X4``#!X`Q!"$4;04``#!X!)!"$
-M4;H4``#!X!A!",4<`4``!!#[>$4<84``#!X`8)P4$/MX11S!0``,'@
-M#`G!00^WA%'2%```P>`2"<%!#[>$4=@4``#!X!@)P8/^`70,@_X!#_@)T
-M!^L*1(G!ZPM!BT'08/E`0^W1@(E\`$``#U``0``=&0]
-M0`$``'\R/<`````/A-,````]P````'\0/:`````/A+D```#IQ````#W0````
-M#X2Q````Z;0````]P`@```^$H0```#W`"```?P<]4`$``.L,/4`)``!T"SU0
-M"0``#X6)````0;\`````#[>%A`,``"7P````@^@P@_@_=GF#O7P#```'='"#
-MO7P#```+=&>#O7P#```*=%Z#O7P#```)=%6#O7P#```*=0IF@[V``P```W9"
-M2(M-((N11)D``(/BQTF+A"3P+0``#[\`P>`#@^`X"<*)D429``#K&D&_`0``
-M`.L20;\"````ZPJX`````.D6`P``2(M-((N1$)D``('B!OS__TECWT$/MX1<
-MG!0``,'@!`G"@\H!B9$0F0``08NT)*PQ``!,B?)(B>_H`````$B+52!!#[^$
-M7(04```E_P$``(#,`HF":)D``&9!@;PD*!0``/]/=CE!]D8"$'0R26/%00^W
-MM$3\%```00^VO`0$%0``10^VA`0&%0``10^WC$0`%0``00^WA$0(%0``ZS-)
-M8\=!#[>T1%H4``!!#[:\!'X4``!)8\5%#[:$!($4``!%#[>,1&`4``!!#[>$
-M1.H4``!FB00D2(M-((N11)@``('B?\#__XGPP>`')8`_```)PHF11)@``$B+
-M32"+@5"8``"P`$`/MM<)T(F!4)@``$B+32"+D5"8```P]D2)P,'@""4`_P``
-M"<*)D5"8``!(BTT@BY%(F```@>+_#_S_1(G(P>`,)0#P`P`)PHF12)@``$B+
-M?2!)8_=!#[>4='(4``")T,'@&,'B$`G000^WC'1X%```B`("<*)D2B8``!(BTT@BY%DF```
-M@>+_#_C_00^WA'1L%```P>`,)0#P!P`)PHF19)@``+L"````9D&!O"0H%```
-M`C!W&6:!O7H#```B$'4K0?9&`D!T)+L(````ZQU,B?9(B>_H`````(7`=`Y)
-M8\=!#[>$1-X4```!PTB+32"+D229``"`X@&-!!LE_@````G"B9$DF0``08-^
-M$`!T#$$/OG8400^^?A7K%4ECQ4$/M[1$;A4``$$/M[Q$`X)D```````"X`0``
-M`$B#Q!A;74%<05U!7D%?PT%7059!54%455-(@^Q(28G]28GT2,=$)!``````
-M2,=$)#``````2,=$)#@`````9L=$)`P``,=$)`@`````QT0D!`````#'1"08
-M`0`"`,=$)!P"``$`9L=$)"`!`&;'1"0B`@!FQT0D)`$`#[=>`L'K!P^W!H/C
-M`70-C02`1(VT`"BF___K"XT$@$2-M`"80```9D&#?"0X`'0900^W1"0X9HE$
-M)`[K=F:!X?\_9HE,)`[K7V;'1"0.`(!!OU<```!!]D0D`A"XK@```$0/1?B]
-M``````^W]8G:3(GO0?^5<`,``(G!9CT`@'0G00^W_D$/M_>)^"GPB+___^/B9`,F0``28M%(,>`H)D```````!)BT4@QX"`F0```````$F+
-M52"+@H29```E``#P_XF"A)D``$F+12#'@)B9````````28M5((N"G)D``"4`
-M`/#_B8*``)D```````!)BT4@QX`$F0```````$F+12#'@`B9
-M````````28M5((N"#)D``"4`P/__B8(,F0``28M%(,>`B)D```````!)BT4@
-MQX",F0```````$F+12#'@)"9````````28M5((N"E)D``"4`P/__B8*4F0``
-MZ7L#```/MTPD#D$/M\8IP4$/MT0D`B7P`0``/=`````/A)P````]T````'\,
-M/<````!T1.FZ````/4`!``!T##U0`0``='OIIP```(G+P>,12&/#2&G`'X7K
-M44C!Z"")QL'^`XG8F2G6B70D"(GRP?H*B50D!.M!B@@B<;!_@.)T)DI
-MUHET)`AFQT0D##4,ZS&)RL'B$$ACPDAIP!^%ZU%(P>@@B<;!_@.)T)DIUHET
-M)`B)\L'Z"HE4)`1FQT0D#&H8:$$#[=4)`R)R(G3F??[B<&H#W0-
-M0;@$````3(U,)!CK"T&X`P```$R-3"0@O0````!F187`#X0*`0``B<_!_P1!
-MN@$```!)NP````#_____@_\<#X\M`@``#[?%C70X&8/^('+_
-M/P``"=")@0R9``!)BU4@BT0D,(F"B)D``$F+52"+1"0TB8*,F0``28M5((M$
-M)#B)@I"9``!)BTT@BX&4F0``)0#`__^+5"0\@>+_/P``"=")@929``!(@\1(
-M6UU!7$%=05Y!7\.Z````9/9&`A"X````R$@/1=#V1@-`=`5(T>KK"V:#?@(`
-M>01(P>H"2`^W#DB)T+H`````2/?Q2(G&0;D?````2(GP1(G)2-/HJ`%U!4G_
-MR77NN"8```!,*+__P$`P>`1"<*)EA28``!(BW<@BY84
-MF```@>+_'_[_1(G(P>`-)0#@`0`)PHF6%)@``,-(@^P(@_Y`N#\````/0_!F
-MB;>L`P``2(NWZ!,``$B-5"0$Z`````!(@\0(PT%505154TB#[!A(B?U)B?1)
-MB=5(B?N+MX!(``!(B[]X2```Z`````!(C;V$2```OB````#H``````^WC:P#
-M``!F@_E`N#\````/3$```````/
-MO\D/O]!(C40D%DB)!"1,C4PD%$&X`0```$R)YDB)[^BF`@``N@````"%P`^$
-MC`(``$V)Z$R)X4B-5"062(UT)!1(B>__DZ`N``"Z`````(7`#X1F`@``@[U\
-M`P``!W0V@[U\`P``"W0M@[U\`P``"G0D@[U\`P``"70;@[U\`P``"G4*9H.]
-M@`,```-V"&:#@Z)(```$0;@`````#[>3[#$``$ECP&8!E$.$2```9H.\0X1(
-M```_=@IFQX1#A$@``#\`0?_`08/X#W;79H.[5A0```$/A[L```!F@[V"`P``
-M07=D00^W1"0")=`````]P````'529D&!/"2T"74H#[:32A0```^W@U04```I
-MPDACPDAIP&=F9F9(P>@@T?C!^A]F*=#K%@^V@TH4``!(F$AIP&=F9F9(P>@@
-MT>@/M_!(B>_HX@<``$&X`````$*-#(4`````2&/)2(M]($EC\$B+@WA(```/
-MMU2P`L'B&('*``#_``^W!+#!X`@,_R7__P``"<*)E#F`H0``0?_`08/X'WZY
-M2(M-(`^WDXI(``"#XC_!XA@/MX.(2```@^`_P>`0"<(/MX.&2```@^`_P>`(
-M"<(/MX.$2```@^`_"<*)D329``!(BTT@#[>3DD@``(/B/\'B&`^W@Y!(``"#
-MX#_!X!`)P@^W@XY(``"#X#_!X`@)P@^W@XQ(``"#X#\)PHF1.)D``$B+32`/
-MMY.82```@^(_P>(8#[>#ED@``(/@/\'@$`G"#[>#HD@``(/@/\'@"`G"#[>#
-ME$@``(/@/PG"B9$TH@``2(M-(`^WDZ!(``"#XC_!XA@/MX.>2```@^`_P>`0
-M"<(/MX.<2```@^`_P>`("<(/MX.:2```@^`_"<*)D3BB``!(BT4@@[O,,0``
-M`'0'NG\```#K!;H_````B9`\F0``N@$```")T$B#Q!A;74%<05W#05=!5D%5
-M05154TB![+@```!(B;PDB````$F)]$2)1"1L3(E,)&!FB90DA@```&:)3"1P
-M2(G]2(GX2`6$2```2(E$)%AFQT0D0#\`9L=$)#`_`&;'1"00```/OD8%`$12X5``"#X`<,X$$YQG4]2&/#
-M2,'@!DB-M"B,&0``00^W/"3HB@8``(%\)`S@````=1-F.T0D0(M4)$`/1M!F
-MB50D0.L'9HE$)$#K#?_##[>%+!4``#G#?(M!#[=$)`(ET````#W`````#X6A
-M````08/E^$&#S0&[`````&:#O2P5````#X2/````9D4/MO5%#[;M18GO08/G
-M^$ACPV:#O$4N%0```'199D0YM$4N%0``=!(/MX1%+A4``(/@!PS@03G%=3Q(
-M8\-(P>`&2(VT*(P9``!!#[<\).C4!0``08'_X````'439CM$)#"+5"0P#T;0
-M9HE4)##K!V:)1"0PZQC_PP^WA2P5```YPWR,ZPF+7"1`9HE<)#!!]D0D`P%T
-M"0^VA484``#K!P^VA4<4```/OM!,B>9(B[PDB````.@`````B<-!]D0D`D`/
-MA-X!``!!@'PD`@!Y&$R-A"2@````#[>-5!D``$B-E589``#K%DR-A"2@````
-M#[>-`AD``$B-E009``!,B>9(B[PDB````.A'!@``#[=$)$`/MU0D+@^^RRG*
-M.<*)Q@].\D'V1"0"$'1`9H&]*!0````P=A$/O]8/MX4V%```.=")U@].\&:!
-MO2@4``#_/W8908!\)`(`>1$/O]8/MX4X%```.=")U@].\`^_U@^WA"2F````
-M.=`/3M!FB50D$`^WA"2&`````<")UF8IQK@`````#TCP9CET)'"+1"1P#T[P
-M@WPD;``/A-````!(BU0D6&:)<@AFB7(&9HER!&:)<@)FB3*)]XN$)*0```!F
-M.?!V`HGP2(M4)%AFB4(*#[>$)*(```!F.P)V`P^W`DB+5"189HE"#(N$)*``
-M``!F.P)V`P^W`DB+5"189HE"#HG!9H&]*!0``/\_=D(/O]9!@'PD`@!Y"0^W
-MA3P4``#K!P^WA3H4```YPGP:08!\)`(`>0D/MX4\%```ZPL/MX4Z%```ZP*)
-M\$B+5"18ZPA(BU0D6`^W`F:)0AY(BY0D\`````^_`HF%Z#$``.L4B?EK`,``&9!
-M@_Q`N#\```!$#TW@9D&#_#Y_#6;'1"02``!F187D=11!BX6P`P``#[>$````
-M``!FB40D$KT`````1#GU05_#05154TB#["")]4B)^T0/MZ=2%```2(VWA$@``$B)Y[H@````Z```
-M``!!N0@```!!#[?!9D0I)$2_`````$&Z`````$F)P&9"@SQ$`'D'9D+'!$0`
-M`&:#_PAU![\/````ZT=!#[?)#[\43`^W]P^WA'.$2```.<)U+F:#O'.$2```
-M`'4&9O\$3.L39D&#^C)V!V9"_P1$ZP5F0O\,1+\`````0?_"ZP+_QV:#_P]V
-MET$/M\%F@SQ$/WX&9L<$1#\`00^WP0^WA$.$2```*>BZ``````](PD$/M]%(
-M#[\,5$B+DWA(``!(F`^W!$)FB01*0?_!9D&#^0X/AC'___]!N0@```!!#[?1
-M#[<$5&:)A%.$2```0?_!9D&#^0YVYDB#Q"!;74%I]"DAC
-MPF8[3$00=?"+1"0,9CM$)`YU!F9$.>!T"DACPH-\PP0`=`I(8\(/MT3#`NL%
-MN#\````/M\!(@\0@6UU!7,-308G208G)#[?!00^WT`^OPKH`````A#[?'#[?6*=!KR&1!#[?"*=")PHG(B=.9]_N)P42)R&:%R7@Z1(G`
-M9H/Y9'\Q#[_)00^WT`^OT;AD````*M12,'H
-M(,'X!<'Z'V8IT`^WT(G06\-!5T%6055!5%532(/L*$F)]TB)U4R)!"1!B10^W
-MY$^-)*1-`>1&#[=$)09!#[?92(TI$B?;H>_[_
-M_TB+%"1FB4($1@^W1"4"#[=,'0)!#[<_1(GJ1(GVZ%G^__](BQ0D9HE"`D8/
-MMT0E``^W3!T`00^W/T2)ZD2)]N@W_O__2(L4)&:)`DB#Q"A;74%<05U!7D%?
-MPP^W_VO_9`^WTDB-%%8/MP9KP&2#Z`HYQW(:#[="_FO`9(/`"CG'=B`/MT+^
-M9D&)`&:)`<,/MP;K\P^W!F:)`0^W1@)F08D`PT@YUG,L1`^_SP^_!FO`9$0I
-MR(/`"8/X$G;2#[=&`FO`9(/H"CG'$
-M`P``)?````"#Z#"#^#]W-(L%`````(F'T"T``(G`2(T$P$B-!(4`````2(E"
-M(,="&`$```#'0@P4````QT(050```,.+!0````")`HG`2(T$P$B-!(4`````
-M2(E"(,="&`$```#'0@P4````QT(0(P```,-32(GZ2(GS#[>'A`,``"7P````
-M@^@P@_@_=U&^!P```/^7B"X``$B)Q[D`````NB0```"^`0```.@@Y/__0;D`
-M````0;AK````OP````"^:P```(/X`75Y0;A3````OE,```#'0Q`W````ZV6^
-M!P```/^2B"X``$B)Q[D`````NB4```"^!@```.C/X___0;D`````C4@$@_@_
-MNC(```!!B=!$#T7!ND````")UT$/1/F-=S)!C5$4@_@_00]%T8E3#(U.\8U6
-M!8/X/P]$T8E3$(M3!+@`````1#G*<@5$.<)V#3GZ<@0Y\G8%N`$```!;PP^_
-MA^PQ```#A^@Q``!(BU<@P>`))0!^``"`S(")@C"9``#'A[0Q```!````PTB#
-M[!A(B1PD2(EL)`A,B60D$$B)^TF)_$B-K]`M``"#?1@`=0JX`````.GA````
-M@[^T,0```0^%S@```$B+1R"+@#"9``!FA<`/B+L```")PL'J&8E5!"4``(`!
-MP>@7@_@"=1QF@[^"`P``078.#[>'4A0```'0B44$ZP2#100%00^WA"2$`P``
-M)?````"#Z#"#^#]W'TR)Y^B8`0``BT4$.T44<@@K112)103K!\=%!`````#'
-M@[0Q````````2(GN3(GGZ!?^__^%P'4\2(GN3(GGZ$H```"%P'0M2(GN3(GG
-MZ%,```"%P'X>QX.T,0```@```,>#R#$```$```#'@[`Q````````BX.T,0``
-M2(L<)$B+;"0(3(MD)!!(@\08P[@`````BU8$.U8,=@4[5A!R!;@!````PP^W
-MAX0#```E\````(/H,(/X/TC'P@````!(Q\``````2(G'2`]'^HL&2(T$P$B-
-M1(<(2(E&((M&!#M&$')3@SX`=0:X_____\.+1@2)1@@[1A!R-X,^`'0R_PZ+
-M%DB-%-)(C1272(M.((M"&"M!$`'`BTX(*<&)3@A(@\((2(E6(#M.$'(%@SX`
-M=@#C7O_@^<'187D?GI!NP$```!&C13M
-M`````+L(````08T,/(/Y";@(````#TW(1(G8T^")P8U1_T2)V(GYT^#_R#'0
-M08G%1(G10=/E1(G&1(GJ]](C5+4`1(G(B?G3X$2)T=/@1"'H"=")1+4`1HUD
-M)_B)V2GY0=/IOP````!!_\!%A>1_F4B#Q`A;74%<05W#05=!5D%505154TB#
-M[`A)B?])B?;V1@-`=`>^``(``.LB9H-^`@!Y![X`!```ZQ'V1@(0O@`!``"X
-M`@````]%\$R)_^@`````2(G%0;T`````1#LH?4A)8\5(C01`2(U$A2`/ME@(
-MP>,"2&/;38MG(`^V2`M!N`````"Z#@```$B)[DR)_^@`````#[?`0HF$(P"'
-M``!!_\5$.VT`?+A!]D8"$`^%M````+X(````3(G_Z`````!(B<5!O0````!$
-M.R@/C94```!)8\5(C01`3(UTA2!!#[9&"(T$A0"'``")1"0$08!^!0!U94&)
-MQ$F+7R!!#[9."T&X`````+H.````2(GN3(G_Z``````/M\!!B00<08!^"0!T
-M-4$/MD8)BU0D!(T4@D&)U$F+7R!!#[9."T&X`0```+H.````2(GN3(G_Z```
-M```/M\!!B00<0?_%1#MM``^,:____TB#Q`A;74%<05U!7D%?PTB+1R"+@!R`
-M```E@#\``/9&`T!T)$&Z!`$``$&[``"`'[X``!L`N1,```!!N*P-``!!N10`
-M``#K(D&ZT@```$&[``"`'[X``#8`N0D```!!N$@-``!!N0H```!(BU<@"<@)
-M\$0)V(F"'(```$B+1R!$B9!P$```2(M'($2)@+`0``!(BT\@BX'P$```)?\#
-M\/]$BR%
-MVW0/N"4````IZ-'H1(TD*.L,08U$)/^#_0)$#T/@03GL=!I)BTT@@>(/_/__
-M1(G@P>`$)?`#```)PHE1,$R)[^@`````03GL#Y7`#[;`2(M<)`A(BVPD$$R+
-M9"083(ML)"!(@\0HPTB#[`@/MX>8`P``N0`````YQGT<2&/&2(G&2,'F!$@I
-MQDB-M+?0+@``Z`````")P8G(2(/$",-(@^P(28G0#[>'F`,``+H`````.<9]
-M'TACQDB)PDC!X@1(*<)(C927T"X``$R)QN@`````B<*)T$B#Q`C#05=!5D%5
-M05154TB#[`A)B?U!B?1)B=9(B?Y(C8^0`P``0;\+````08/\`G0B08/\`G<+
-M08/\`715Z:0```!!@_P#=!I!@_P$="3IDP````^W:0C_S4&!S\``!0#K:0^W
-M:0B#[0)!@<_``04`ZUD/MVD(@^T#2&/52(G02,'@!$@IT(.\A]0N````=#OK
-M5+T`````#[=!"(G'.<5]'4ACU4B)T$C!X`1(*="#O(;4+@```'0&_\4Y_7SC
-M#[=!"+K_____.<5T?$ACU4B)T$C!X`1(*=!(C9R&T"X``(-[!`!T![K_____
-MZUJ^/````$B)W^@`````1(EC!$V%]G4N1(E[#,=#%`(```#'0QC_____QT,<
-M_P,``&;'0R`*`&;'0R(*`,=#-`````#K%$&+1C")0S1,B?*)[DR)[^@`````
-MB>J)T$B#Q`A;74%<05U!7D%?PTB+3R"+E[PN``"!XO\#``"+A\0N``#!X!`E
-M``#_`PG"B9&D````2(M/((N7P"X``('B_P,``(N'R"X``,'@$"4``/\#"<*)
-MD:@```!(BT\@BX&L````)0#\__^+E\PN``"!XO\#```)T(F!K````,-(@^P(
-M#[>'F`,``+H`````.<9S7HGR2(G02,'@!$@IT$R-A(?0+@``08-X!`!U![H`
-M````ZSQ!QT`$`````+C^____B?'3P"&'O"X``"&'P"X``"&'Q"X``"&'R"X`
-M`"&'S"X``$R)QN@C____N@$```")T$B#Q`C#4T&)\DF)^TB+C^@3```/MX>8
-M`P``N@`````YQ@^#L0,``(GR2(G02,'@!$@IT$R-A(?0+@``08-X!``/A(T#
-M``!!@W@8_W4S2(7)=!4/MT$"):````"Z'P```#V@````=`6Z#P```+@!````
-M.=!S#P'`@\@!.=!R]^L$08M`&$*-')4`````C;-`$```2(M/((G"@>+_`P``
-M08M`','@"B4`_`\`"<)!BT`4P>`4)0``\`\)PHD4#HVS@!```$B+3R!!#[=`
-M(L'@!"7P````00^W4""#X@\)T`T`(`@`B00.O@`(``!!N0`!``!!@W@D`'0Q
-MC;/`"```2(M/($&+4"2!XO___P!!BT`HP>`8"<*)%`Z^`0@``$&#>"@`=`6^
-M`0D``$&#>#``=!U"C0R5``D``$B+5R!!BT`P)?___P`-`````8D$$4*-#)7`
-M$```2(M7($&+0"PE__\/`$&#>"P`=`4-```0`(D$$4&#>#``=`V)\(#,`D'V
-M0`P@#T7P0?9`#$!T!H/F\(/.`D#VQ@]T*(GR@\I`B?"#X+]!]D`-`8G6#T3P
-MB?*#RB")\(/@WT&`>`P`B=8/2?!$B<@-```@`$'V0`X!1`]%R$2)R(#,`D'V
-M0`Z`1`]%R$'V0`X$=`E!@`*0HT,E0`)``!(BU<@#0````&)!!%!@#0`
-M=#A(BU<@0XU$$E")@@`+``!(BU<@08M`-(F"!`L``$B+1R#'@`@+```)````
-M2(M7((L$$8#,$(D$$4'V0`P!=!.X`0```$2)T=/@00F#O"X``.L1N/[___]$
-MB='3P$$A@[PN``!!]D`,`703N`$```!$B='3X$$)@\`N``#K$;C^____1(G1
-MT\!!(8/`+@``0?9`#`)T$[@!````1(G1T^!!"8/$+@``ZQ&X_O___T2)T=/`
-M02&#Q"X``$'V0`P$=!.X`0```$2)T=/@00F#R"X``.L1N/[___]$B='3P$$A
-M@\@N``!!]D`,"'03N`$```!$B='3X$$)@\PN``#K$;C^____1(G1T\!!(8/,
-M+@``3(G&Z$G[__^Z`0```(G06\.--+4`"```2(M'((L$!L.--+4`"```2(M'
-M((D4!K@!````PXGQ2(M7(+@!````T^")@D`(``"X`0```,.-!+4`"@``2(M7
-M((L$$(G'@^<#=1FX`0```(GQT^"+DD`(``"%PK@!````#T7XB?C#055!5%53
-M2(/L"$B)^T&)]$B+5R"X`0```(GQT^")@H`(``!!O>@#``!$B>9(B=_H````
-M`(7`=`^_9````.@`````0?_-=>)$B>9(B=_H`````(7`#X3R````@[M\`P``
-M!W0V@[M\`P``"W0M@[M\`P``"G0D@[M\`P``"70;@[M\`P``"@^%P0```&:#
-MNX`#```##X>S````O@````!(BT,@BY!,@```QX``@0``9``*`$B+2R#!Z@H/
-MM\(-```!`(F!_(```$B+0R"+@$R```#!Z`HYT'0'_\:#_@%VOTB+4R"+@DB`
-M```-``!``(F"2(```+_(````Z`````!(BU,@BX+\@```)?___O^)@OR```"]
-M9````.L._\UT&;\*````Z`````!$B>9(B=_H`````(7`=>-(BU,@BX)(@```
-M)?__O_^)@DB```!(BT,@QX"`"````````$6%[0^5P`^VP$B#Q`A;74%<05W#
-M1(M<)!A$BU0D*`^_A^PQ``!!`<%!@_E`N#\```!$#T/(@>+_#P``0<'A$$0)
-MRHG0#0``@`!!]L(@#T70BT0D(,'@&24````>"<*)T`T````!0?;"`0]$PHG"
-M@$9BU0D0,'B'8M$)$C!X!M!"`%"484187)=!U$BAFB0$/MT8:9HE!`L9!!`"+1ABH`74@5B$$+#[;`@_@!=""#
-M^`%_!H7`=`[K0(/X`G0=@_@#="7K-`^V0A2#X!_K*(M"%"7@`P``P>@%ZQB+
-M0A0E`'P``,'H"NL+BT(4)0"`#P#!Z`^#R("(006+0APE`.`?`,'H#8A!!HM"
-M&"7P````P>@$B$$'BT(8)0`/``#!Z`B(00@/MD$+@_@"=!^#^`)_!X/X`70C
-MZR^#^`-U*HM"$"4````/P>@8`$$(BT(0)0``\`#!Z!0`00B+0A`E```/`,'H
-M$`!!"(M"&"4`\```P>@,B$$)]D(?`0^4P+H"````*,*(40JX`````,.+!B.'
-MI$@``(D&]]`AAZ1(``##D)!32(G[2(VW3"X``.@`````2(M#(,>`)($`````
-M``!(BT,@QX`H@0```````$B+0R#'0$``````2(M#(,>`,($``````@!(BT,@
-MQX`X@0```````EO#4TB)^TB+1R#'0$`&````2(VW3"X``.@`````2(M#(,>`
-M)($```````!(BT,@QX`H@0```````%O#N0````!(8\%(:\!8#[>$!R@R``!F
-M.P9T+$ACP4AKP%A(C90'(#(``&:#>@@`=1D/MP9FB4((#[=&`F:)0@H/MD8$
-MB$(,B3`P``@^`!B8<4,@``2(V_*#(``+X`
-M%@``Z`````"^`````(.]?`,```9W$4ACQDAKP%C&A`,P,@``!^L/2&/&2&O`
-M6,:$`S`R```"2&/&2&O`6$B-#`-(C8$P,@``QT`,]`$``,=`$,@```#'0!3(
-M````2(V!0#(``,=`"&0```#'0!`H````QT`,!P```$B-@2`R``#&0!0`QD`5
-M``^V4!"(4!+&0!,`@[L4,@```'052(V!8#(``,=`#`S^OP#'0!`X_[\`_\:#
-M_C\/AE'___^#NQ0R````="A(BU4@BX-L,@``B8(L@0``2(M5((N#<#(``(F"
-M-($``$B)[^@`````QX,8,@``9````$6%Y'0)@XL0,@```>L'@Z,0,@``_EM=
-M05S#4TB)^X._%#(```!T(>@`````2(M#(,>`+($```````!(BT,@QX`T@0``
-M`````%O#2('LB````$B)7"1X2(FL)(````!(B?M(B?U,BX<@,@``N`````"#
-M_@8/AX`$``")\/\DQ0````")U[@`````@_H$#X=G!```2(M+((N14)@``('B
-M__\/\(G^BX2S*$@``,'@%"4``/`/"<*)D5"8``!(BTL@BY%)_@/__
-MBX2S4$@``,'@!R6`?P``"<*)D5R8``!(BTL@BY%+_?\#_BX2S/$@`
-M`,'@#R4`@#\`"<*)D5R8``!(BTL@BY%8F```@>+__P/\BX2S9$@``,'@$B4`
-M`/P#"<*)D5B8``!!#[9`"3G'=@C_@Q`N``#K#T$/MD`).<=S!O^#%"X``$&(
-M>`GIFP,``,=$)#A_````QT0D/#(```#'1"0P?P```,=$)#0H````QT0D*'\`
-M``#'1"0L30```,=$)"!_````QT0D)$````#'1"08'P```,=$)!P0````QT0D
-M$#\```#'1"04,````(72#Y7`#[;X2(MS((N6;)@``('B_S_@_XGY2,'A`HM$
-M##C!X`XE`,`?``G"B99LF```2(MS((N6;)@``('B__\?\(M$###!X!4E``#@
-M#PG"B99LF```2(MS((N6:)@``('B__\!_XM$#"C!X!$E``#^``G"B99HF```
-M2(MS((N6:)@``('B____@(M$#"#!X!@E````?PG"B99HF```2(MS((N&:)@`
-M`(/@X(M4#!B#XA\)T(F&:)@``$B+`()0`_```)
-MPHF6;)@``(7_=`](BU,@BX)LF```@\@!ZPU(BU,@BX)LF```@^#^B8)LF```
-MA?\/E,`/ML!!#[90##G0#X0E`@``A?]T"/^%("X``.L&_X4D+@``A?]!#Y1`
-M#.D'`@``QT0D"`@```#'1"0,!@```(72#Y7`#[;P2(M/((N!"*(``(/@P(GR
-MBU24"(/B/PG0B8$(H@``00^V0`TYQ@^$Q`$``(7V=`C_AR@N``#K!O^'+"X`
-M`$&(<`WIJ0$``,=$)&``````QT0D9`0```#'1"1H"````(G6N`````"#^@(/
-MAX8!``!(BT\@BY%8F```@>+_#_S_B?"+1(1@P>`,)0#P`P`)PHF16)@``$$/
-MMD`+.<9V"/^',"X``.L/00^V0`LYQG,&_X@`````2(G?Z`````")QH'F__[_
-M_TB)W^@`````ZVWVAQ`R```"=62#OQ0R````=#_H`````(G&@>;__O__2(G?
-MZ`````!(BU,@BX-L,@``B8(L@0``2(M3((N#<#(``(F"-($``$B)W^@`````
-MZQ7H`````(G&@$B+K"2`
-M````2('$B````,-32(GY2(N?(#(``,=#$`````"#OQ0R````='R!>Q0``,``
-M=@G'0T0`````ZPNX``#``"M#%(E#1(%['```P`!^"<=#2`````#K"[@``,``
-M*T,@'.T4D?@Z`?0L!=S`/ME4+_\+K&TB)W^@`````@^@"@_@!
-M=QB`?0L`=!*Z`````+X$````2(G?Z`````!(BUPD"$B+;"002(/$&,-!54%4
-M55-(@^P(2(G[08GU28G\2(NWZ!,``.C9]O__2)A(:\!82(VL&"@R``!(B:L@
-M,@``@[N,`P```74)@XL0,@```NL'@Z,0,@``_8.[C`,```$/A(<```!!_X0D
-M0"X``+H`````O@$```!(B=_H`````+H`````O@4```!(B=_H`````+H`````
-MO@0```!(B=_H`````+H`````O@(```!(B=_H`````+H`````O@,```!(B=_H
-M`````$B)W^@`````B<:!S@`!``!(B=_H`````$B)W^B]_/__Z2D!``"+@Q`R
-M``"#X`.#^`,/A1UT4`^V50F^`0```$B)W^@`````#[95"KX%````
-M2(G?Z`````"`?0P`#Y3"#[;2O@(```!(B=_H``````^V50V^`P```$B)W^@`
-M````#[95"^M,N@0```"^`0```$B)W^@`````#[95"+X%````2(G?Z`````"Z
-M`0```+X"````2(G?Z`````"Z`0```+X#````2(G?Z`````"Z`@```+X$````
-M2(G?Z`````!!@[PD%#(```!T/DB)W^@`````B<:!YO_^__](B=_H`````$B)
-MW^C-^___2(M#(,>`,($``````@!(BT,@QX`X@0```````NL@2(G?Z*?[__](
-MB=_H`````(G&@_H=_O__XM#0#M#''8(2(GO
-MZ'_\__](B>_HN/K__UM=05S#4TB)^TB+ER`R``"`?@41=1C_0CS_AS@N``"+
-M0CP[0A1V*^@S^___ZQR`?@49=1[_0D#_ASPN``"+0D`[0AQV#>@M_/__2(G?
-MZ&;Z__];PTB#[`A(BY<@,@``BX]@+@``B@'.T(H?RH[0B1^$H!Z#`!T#+H!````O@(```#K-X!Z"P!T#0^V4@O_RKX$
-M````ZR2`>@H`=`T/ME(*_\J^!0```.L1@'H)`'00#[92"?_*O@$```#H````
-M`$B#Q`C#2(M'($2+B.R```!$BY#P@```1(N`^(```$B+MR`R``"#?C@`=`9$
-M.48X=@VY`````/^'1"X``.LP1(G!*TXX1(G0*T8T1(G**U8P*<$IT4ACP4AI
-MP"DY4U](P>@@B0/A*\!``#H0O___XG%A`.($```````+I!0$`
-M`$$K5"1$B=!!*T0D/$$!A3@N``!!B50D/(G*02M4)$B)T$$K1"1`00&%/"X`
-M`$&)5"1`BX,0,@``@^`#@_@##X7!````08N%&#(``(T$@$$Y1"00=DU!BU0D
-M$(G000^O1"082&G`TTUB$$C!Z"#!Z`9!.40D/`^'@@```(G000^O1"0@2&G`
-MTTUB$$C!Z"#!Z`9!.40D0'=E2(G?Z'?]___K6T&+1"0003N%&#(``'9500^O
-M1"042&G`TTUB$$C!Z"#!Z`9!.40D/'8*2(G?Z$_X___K*$&+1"0000^O1"0<
-M2&G`TTUB$$C!Z"#!Z`9!.40D0'802(G?Z#WY__](B=_H=O?__TB+7"0(2(ML
-M)!!,BV0D&$R+;"0@2(/$*,.0D$B+A^@3```/MP!FB09(BX?H$P``@$@$"(!.
-M!`A(BX?H$P``#[=``F:)1@)(BX?H$P``#[9`!(A&!$B+A^@3```/MD`%B$8%
-MN`````##D)"005=!5D%505154TB#[`A)B?Q!B=>)R[T`````2`$"<4/
-MMTL(28M4)""+@@2B``!F08%]`+0)=06#R!#K"$F+5"0@@^#OB8($H@``ZP>)
-MP;T`````9H'YD`!_!?;!`70?#[_Y@^\8O@@```#H`````(G&@>;_````N`$`
-M``#K)@^_^8/O&(GXP>@?`8"
-M`<`)QH'.`00``$F+3"0@0`^VQ<'@"$`/MM8)T(F!G)@``$F+3"0@B>@E`/\`
-M`$B)\P^VUPG0B8'0F```38FL).@3``"X`0```$B#Q`A;74%<05W#2(N7X#$`
-M`(/^!W$F)_DB)="089HE4)!9)B?^]``````^W
-M1@(E\`$``#W`````#X2'`0``/<````!_$#V@````#X04`0``Z=$!```]0`$`
-M`'0+/5`!```/A;\!``!(BU0D&`^W`F8MH0]F/>H$=Q=!#[>'#!4``&:)1"0,
-M00^WEPX5``#K4$B+5"08#[<"9BV,%&8][P!W%T$/MX<0%0``9HE$)`Q!#[>7
-M$A4``.LG2(M4)!@/MP)F+7P59CW@`'<<00^WAQ05``!FB40D#$$/MY<6%0``
-M9HE4)`KK-DB+1"089H$X7!9V'$$/MY<8%0``9HE4)`Q!#[>'&A4``&:)1"0*
-MZPYFQT0D"@``9L=$)`P``$&\`````+X`````00^WEY`4``!FB50D%$$/MX>6
-M%```9HE$)!)F08._EA0````/E,!F#[;`9HE$)!!!#[>7Y!0``.F[````#[>'
-M'!4``&:)1"0,#[>7'A4``&:)5"0*#[>W)!4``$0/MZ'DA0``&:)
-M1"04#[>7F!0``&:)5"029H._F!0````/E,!F#[;`9HE$)!`/MX?F%```9HE$
-M)`[K:P^WER`5``!FB50D#`^WAR(5``!FB40D"@^WMR85``!$#[>G*A4```^W
-MEY04``!FB50D%`^WAYH4``!FB40D$F:#OYH4````#Y3`9@^VP&:)1"00#[>7
-MZ!0``&:)5"0.ZPJX`````.G,`P``NP````!(#[=,)!9(Q\<`````2&/#2(T4
-M0$B-%%&+%)>)5(0@_\.#^Q!VYTB+1"08@'@"`'DX2(U<)"!!N`````"Y=P``
-M`+H#````2(G?Z`````!!N`````"Y>@```+H#````1(GF2(G?Z`````"[````
-M`$ACPTB-%$"+#-4`````28M6((M$A"")!!'_Q4#VQ3]U"K\!````Z`````#_
-MPX/[$';.NP````!(8\.+#,4`````28M6((L$Q0````")!!'_Q4#VQ3]U"K\!
-M````Z`````#_PW32NP````!)Q\4`````3`^W9"062&/#2(T$0$&+3,4`28M6
-M($F-!$1!BT2%`(D$$?_%0/;%/W4*OP$```#H`````/_#=,Z[`````$G'Q0``
-M``!,#[=D)!9(8\-(C01`08M,Q0!)BU8@28T$1$&+1(4`B001_\5`]L4_=0J_
-M`0```.@`````_\-TSKL`````2`^W3"062,?&`````$ACPTB-%$!(C111BQ26
-MB52$(/_#@_L0=N=(BU0D&`^W0@(E0`$``#U``0``=45!#[>WA!4``$B-7"0@
-M0;@#````N3,```"Z`0```$B)W^@`````00^WMX85``!!N`,```"Y+0```+H!
-M````2(G?Z``````/MW0D$$B-7"0@0;@`````N5\```"Z`0```$B)W^@`````
-M#[=T)!1!N`````"Y8````+H$````2(G?Z``````/MW0D#$&X`````+EH````
-MN@,```!(B=_H``````^W="0*0;@`````N6L```"Z`P```$B)W^@`````NP``
-M``!(8\-(C11`BPS5`````$F+5B"+1(0@B001_\5`]L4_=0J_`0```.@`````
-M_\.#^Q!VSKL`````2`^W3"062,?&`````$ACPTB-%$!(C111BQ26B52$(/_#
-M@_L'=N`(`>`;V0`-`='1(BU0D
-M&/9"`T"Z'P```+@0````08G$1`]$XDB-7"0@0;@`````N1,```"Z!0```+X?
-M````2(G?Z`````!!N`````"Y&````+H%````1(GF2(G?Z`````!!N`````"Y
-M,0```+H"````O@,```!(B=_H`````+L`````2&/#2(T40(L,U0````!)BU8@
-MBT2$((D$$?_%0/;%/W4*OP$```#H`````/_#@_L'=LY!QX>T,0```````+@!
-M````2(/$>%M=05Q!74%>05_#4T&)TD&)R0^WP4$/M]`/K\*Z`````(7`=&F)
-MR&9!.?)T7@^WQP^WUBG0:\AD00^WPBG0B<*)R(G3F??[B<%$B&GA4``&:)
-M1"0828V&BA4``$B)1"0028V&H!4``.M-#[>'J!<``&:)1"082(V'L!<``$B)
-M1"002(V'9A@``.LL00^WAJ@7``!FB40D&$F-AJH7``!(B40D$$F-ALH7``#K
-M"K@`````Z<8"``!(B40D($B-7"0PO@@!``!(B=_H`````$R->PA,C:.(````
-MNP$```"]`````$ACQ69!B1Q'_\/_Q8/[/W[O9HEL)#9FQT0D,@$`9L=$)#0_
-M`+T`````9H-\)#8`="=(8]U!#[M12,'H(,'X!,'Z'RG0
-M_\`YPWTW2&/!2&G`'X7K44C!Z"")QL'^!(GP*="-2`%!#[?528N&>$@```^W
-M="0.9HDT4$'_Q?_#.````9D&#
-M_3\/A_@```"#Q3)(B==F03ML5/Y]40^_S8G.2&/300^_!%1!BAFB01*28N&>$@``(M4)`QF
-M.11(=@1FB11(0?_%2`^W5"0V9D$[;%3^?0UF08/]/P^&+____^LE9D&#_3]W
-M'D$/M\U)BY9X2```#[=$2OYFB01*0?_%9D&#_3]VXF9!QX;L,0````"X`0``
-M`$B!Q$@!``!;74%<05U!7D%?PTB#[#A(B5PD&$B);"0@3(ED)"A,B6PD,$B)
-MU4&)_8GS#[?V#[?_2(U,)!;H,`$``(7`=`H/MT0D%ND)`0``#[=5"$4/M^U,
-MC40D%$B-3"022(MU`$2)[^@`````#[=T)!(/M]M,C40D$$B-3"0.2(GJB=_H
-M4`$```^W="043(U$)`Q(C4PD"DB)ZHG?Z#KHN`````^W="00#[=\)!)(C4PD!DB)ZNBA````1`^W1"0&#[=,)`@/MU0D
-M$`^W="0.B=_H[/K__T&)Q`^W="0*#[=\)!1(C4PD"$B)ZNAK````#[=T)`P/
-MMWPD%$B-3"0&2(GJZ%0```!$#[=$)`8/MTPD"`^W5"0,#[=T)`J)W^B?^O__
-M#[?`00^WS`^W5"04#[=T)!)!B_H@_K__P^WP$B+7"082(ML)"!,BV0D
-M*$R+;"0P2(/$.,-,BTH00;L`````9H-Z"`!T469!.3EU.TV-00A!N@````!F
-M08-Y!@!T*69!.3!U$DECPD$/MT1!'F:)`;@!````PTF#P`)!_\)!#[=!!D$Y
-MPGS728/!-$'_PP^W0@A!.<-\K[@`````PTB#[`A!B?)(BW(00;D`````#[="
-M"(G"03G!?1)F1#D6=`Q(@\8T0?_!03G1?.X/MU8&2(/&"`^W_^@`````2(/$
-M",-32(G[2(._>$@```!T%TB+OWA(``#H`````$C'@WA(````````2(.[X#$`
-M``!T%TB+N^`Q``#H`````$C'@^`Q````````6\.X`0```,.Z`````$C'QP``
-M```/MP:)P68[!0````!W"__"2&/"9CL,AW;U2&/"#[\$A0````##2(/L&$B)
-M7"0(2(EL)!!(B?5(B?N_M````.@`````2(F#X#$``$B%P'0@QX.`2```@```
-M`+^`````Z`````!(B8-X2```2(7`=0['10`"````N`````#K74C'@W@N````
-M````2,>#@"X```````!(QX.(+@```````$C'@Y`N````````2,>#F"X`````
-M``!(QX.@+@```````$C'@Z@N````````2,>#L"X```````"X`0```$B+7"0(
-M2(ML)!!(@\08PY!!5T%6055!5%532(/L"$F)_$&)UXG+O0````!)Q\8`````
-M08GU2&/%2(T$0$&+#,9)BU0D($F-1$4`08L$AHD$$?_#]L,_=0J_`0```.@`
-M````_\6#_0]VS+T`````2&/%BPS%`````$F+5"0@BP3%`````(D$$?_#]L,_
-M=0J_`0```.@`````_\6#_41VS[T`````2A!BP2&B001_\/VPS]U"K\!````Z`````#_Q8/]/W;.2(/$"%M=
-M05Q!74%>05_#059!54%455-)B?Q(B?5!O@````!!O0````!F@3Z_$@^'XP``
-M``^W/HV'H@T?J)P<'Y'RG*C122.=!U(XV@@B<'!^0*)V)F)RRG30;X!````P>,"@>/_````O@@```")W^@`
-M````B<-)BU0D((N"!*(``&:!?0"T"74%@\@0ZPA)BU0D((/@[XF"!*(``.F#
-M`0``#[<6#[?":<#-S```P>@09L'H`HT$@(G19BG!9H/Y`G5*9H'Z.Q5W0XU"
-M_@^WP(T$@(V$`(!$__](8_A(:?\?A>M12,'O(,'_`\'X'RG'_\>^"````.@`
-M````B<.^`@```+\`````Z1`!```/MU4`#[?":<#-S```P>@09L'H!(T$@,'@
-M`F8YPG5#9H'Z_Q-V/`^WPBW`$@``2&/X2&G_9V9F9DC![R#!_P/!^!\IQ\'G
-M`KX(````Z`````")P[X"````OP,```#IK@````^W50`/M\)IP,W,``#!Z!!F
-MP>@#C02``X(28M4)"")\(/@?XF"V)@`
-M`$F)K"3H$P``N0$```")R%M=05Q!74%>PTB+E^`Q``"#_@=W)(GP_R3%````
-M`$B)T,-(C4($PTB-0@C#2(U"#,-(C8*L````P[@`````PT%7059!54%455-(
-M@^PH28G]28GV2(E,)!AFB50D)DF)_V;'1"04``!FQT0D$@``9L=$)!```&;'
-M1"0.``!(BZ_@,0``2(V'T"T``$B)!"1!O``````/MT8")?`!```]T`````^$
-M$@$``#W0````?QL]H`````^$V````#W`````#X3U````Z1D!```]4`$``'09
-M/5`!``!_!SU``0``ZP4]``@```^%^0```$$/MP9F+:$/9CWJ!'<700^WEPP5
-M``!FB50D%$$/MX<.%0``ZV=!#[<&9BV,%&8][P!W%T$/MY<0%0``9HE4)!1!
-M#[>'$A4``.M"00^W!F8M?!5F/>``=Q=!#[>7%!4``&:)5"0400^WAQ85``#K
-M'69!@3Y<%G8:00^WEQ@5``!FB50D%$$/MX<:%0``9HE$)!)!#[>WEA0``$$/
-MMY?D%```9HE4)!;K6P^WAR05``!FB40D$`^WER@5``!FB50D#@^WMY@4```/
-MMX?F%```ZR)!#[>7)A4``&:)5"0.9HE4)!!!#[>WFA0``$$/MX?H%```9HE$
-M)!;K"K@`````Z;,%``"Y`````$C'QP````!(8]&+!->)1)4`_\%T\KD`````
-M2`^W?"0F2T,0```````+@!````2(/$*%M=05Q!74%>
-M05_#05=!5D%505154TB!["@$``!(B70D0$B)5"0X2(E,)#!,B40D*$B)?"0@
-M#[>'A`,``"7P````@^@P@_@_=S)F@[^$`P``-70>9H._A`,``$5T%&:#OX0#
-M``!&=`IF@[^$`P``-G4*QT0D'`(```#K",=$)!P!````2(M4)#`/MT(")?`!
-M```]T````'1Q/=````!_$#V@````=$0]P````'10;X`````O0````!(BT0D$`^W4`I(C7PD6(G0B>G3^*@!=!F^`````$&#
-M_@$/ASD%``!$B?!FB2Q'0?_&_\6#_0-VUDB+1"00#[=0"$B+3"0P#[#X6)````2`^W1"182(T$@$F-;(4`1`^W909!
-M#[?<2`';2(UU"(G:2(V\)``#``#H`````$B-=1")VDB-O"3@`@``Z`````!!
-M#[]-`D$/M_Q,C40D8$B-E"3@`@``2(VT)``#``#H+04``+X`````A<`/A%X$
-M``!$B?=(P><'2(V,).`!``!(C3P/Z1,!``!(#[=$)%A(C02`28ULA0!$#[=E
-M!D$/M]Q(`=M(C74(B=I(C;PD``,``.@`````2(UU$(G:2(V\).`"``#H````
-M`$$/OTT"00^W_$R-1"1@2(V4).`"``!(C;0D``,``.BD!```O@````"%P`^$
-MU0,``$2)]TC!YP=(C80DX`$``$B-/`>Z@````$B-="1@Z`````!(#[=$)%I(
-MC02`28ULA0!$#[=E!D$/M]Q(`=M(C74(B=I(C;PD``,``.@`````2(UU$(G:
-M2(V\).`"``#H`````$$/OTT"00^W_$R-1"1@2(V4).`"``!(C;0D``,``.@1
-M!```O@````"%P`^$0@,``$2)\$C!X`=(C;P$X````+J`````2(UT)&#H````
-M`$'_QD'_QT0[?"14#X8D_O__BT0D4$B+3"002(L1#[<$0F:)1"0*BT0D5$0/
-MMRQ"BT0D5$&)QD0K="109H%\)%JMW@^%P````+T`````1(GP28G$2<'D!HGK
-M2HT$(T0/OX1$X`$```^_C%S@`0``2(M$)#`/MSA!#[?5#[=T)`KHM`(``&:)
-MA%R@`P``_\6#_3]VQ$B+5"0@2(NR>$@``$B-O"2@`P``Z`($``")PF;!Z`^-
-M!!!FT?A(BTPD0&:)`0^WA"0>!```B<)FP>H/`=!FT?AFB40D7@^WA"0>!```
-MB<)FP>H/`=!FT?A(BU0D.&:)`HM$)%A(BTPD*&:)`6:)00+I_@$``+T`````
-M1(GP28G'2<'G!D4/M_5$#[=L)`J)ZTZ-)#M&#[^$9.`!```/OXQ[HP0$``&:)A%P@`P``_\6#_3]VFX-\)!P"#X6$````2(M,
-M)"!(BY%X2```2(VT)"`#``!(C;PDH`,``$B-3"1.Z*T#``")PF;!Z`^-!!!F
-MT?A(BU0D0&:)`@^W1"1.B<)FP>H/`=!FT?AFB40D7@^WA"0>!```B<)FP>H/
-M`=!FT?A(BTPD.&:)`8M$)%A(BU0D*&:)`@^W1"1:9HE"`NGQ````#[=,)`YF
-M.XPDG@,``']PBT0D#&8[A"2>`P``?V)(BU0D($B+LGA(``!(C;PD(`,``.AC
-M`@``B<(/MT0D6DB+3"0H9HD!9HE!`HG09L'H#XT$$&;1^$B+5"1`9HD"#[>$
-M))X#``")PF;!Z@\!T&;1^&:)1"1>#[>$))X#``#K7TB+1"0@2(NP>$@``$B-
-MO"2@`P``Z`$"``")PHM$)%A(BTPD*&:)`6:)00*)T&;!Z`^-!!!FT?A(BU0D
-M0&:)`@^WA"0>!```B<)FP>H/`=!FT?AFB40D7@^WA"0>!```B<)FP>H/`=!F
-MT?A(BTPD.&:)`;@_````2(M4)#AF*P)(BTPD(&:)@>PQ``"^`0```(GP2('$
-M*`0``%M=05Q!74%>05_#08GZB?=!B=%!B>V)RD6)R$&Y/P```(U"_XG!9H/X/G"=)#[_1#[=$5@)FB016
-M9D'_R7GMZQ))#[_!9HD41D&#Z`)F0?_)>:)!#[_"PT%455-)B=-(B1^<@^_3#,"0@^_5#L"
-M*=$/MT4`1"G`#Z_!00^OU`'0F4'W_&:89HD'2(TT'DR)[^@1_O__1`^_\$P!
-M^TB)WDR)[^C__?__F$$IQ@^W10`/MQ,IT$2)]0^OZ$B)WDR)[^CA_?__F$$/
-MK\2-!"B90??\9ICK)4ACPDAKT%0/MT4`9CL$$W4B#[=$$P)FB0=(C30:3(GO
-MZ*S]__](BQ0D9HD"N@$```#K!;H`````B=!(@\0(6UU!7$%=05Y!7\-!5T%6
-M055!5%532(/L"$F)_DF)]$&)U4&_`0```+T`````.=5S0$ACW4F---Q(C4PD
-M!DB-5"0$3(GWZ,[]__^%P'06#[9$)`1!B$3#@"X```````!(QX.(+@```````$C'@Y`N````````2,>#F"X```````!(
-MQX.@+@```````$C'@Z@N````````2,>#L"X```````"X`0```$B+7"0(2(ML
-M)!!(@\08PY"0D$%7059!54%455-(@^P(28G\08G7B@@B<'!^0*)V)F)RRG3ZU@"C02`B=%F*<%F@_D"=4IF@?H[%7=#
-MC4+^#[?`C02`C80`@$3__TAC^$AI_Q^%ZU%(P>\@P?\#P?@?*@$C02`
-MP>`"9CG"=4-F@?K_$W8\#[?"+<`2``!(8_A(:?]G9F9F2,'O(,'_`\'X'RG'
-MP><"O@@```#H`````(G#O@(```"_`P```.FN````#[=5``^WPFG`S@09L'H
-M`HT$@+D`````9CG"#X6%````#[?"+<`2``!(8_A(:?]G9F9F2,'O(-'_P?@?
-M*<>^"````.@`````B<.^`@```+\!````Z`````!!B<6)WL'F!$*-!*T`````
-M"<9#C00V"<:!S@$0``!)BU0D($`/ML:)@IR8``#![@A)BU0D((GP@^!_B8+8
-MF```28FL).@3``"Y`0```(G(6UU!7$%=05[#05=!5D%505154TB#[`A)B?U!
-MB=9)B?^]`````$R+I^`Q```/MT8")?`!```]P````'0I/<````!_"3V@````
-M=`OK*SW0````=!+K(@^WMQP5```/MX<>%0``ZQQ!#[>W(!4``$$/MX/_!@_D"=N:[
-M`````$ACPXL,Q0````!)BU4@08L$A(D$$?_%0/;%/W4*OP$```#H`````/_#
-M=-6[`````$ACPTB-%$"+#-4`````28M5($&+1(0$B001_\5`]L4_=0J_`0``
-M`.@`````_\-TT+L`````2&/#2(T40(L,U0````!)BU4@08M$A`B)!!'_Q4#V
-MQ3]U"K\!````Z`````#_PW30NP````!(8\-(C11`BPS5`````$F+52!!BT2$
-M#(D$$?_%0/;%/W4*OP$```#H`````/_#@_L:=LV[`````$ACPTB-%$"+#-4`
-M````28M5($&+1(1XB001_\5`]L4_=0J_`0```.@`````_\.#^P)VS4''A[0Q
-M````````N`$```!(@\0(6UU!7$%=05Y!7\-(BY?@,0``@_X'=R&)\/\DQ0``
-M``!(B=##2(U"!,-(C4((PTB-0@S#2(U">,.X`````,-!B=$/M\),C11&#[_7
-M#[<&.<)]#D''``````#'`0````###[_700^W0OXYPGPH00^WP?_(ZPE,BH/`=!FT?AF0HE$!#A,C50D,$2)R8M$)$!!
-M#[?]2(T$0$B)PDC!X@1(`=!(C0Q)2,'A`D@!R$@!^$$/MW1&*F9#B30"BT0D
-M1$B-!$!(B<)(P>($2`'02`'(2`'X9D$[=$8J?@M!#[=$1BIF0XD$`D2+9"00
-M30'D0@^W1"0PB<)FP>H/`=!FT?AF0HE$)#!%#[?MBTPD0$AKR69$BM(`UPD"$0/OX1=``(```^_3%T`BT0D1$$/MQ1&BT0D
-M0$$/MS1&1(G_Z'K]__]FB81=``0``$'_Q4(/MT0D,&9"*T0D.`^WP$$YQ7*Q
-M_T0D$/]$)!2#?"04`P^&W/W__XM$)#A(BTPD(&:)`4&]`````,=$)!0`````
-M1#ML)!`/@_,!``!(C5PD,$R-7"0X1`^W9"0LBT0D$/_(.40D%'47BU0D%`^W
-M!%.#P`1,BW0D&&9!B016ZR>+3"04#[\$2XM4)!3_PD$/OQ13`=")PL'J'P'0
-MT?A(BU0D&&:)!$J^`````(-\)!0`=!^+1"04_\A(BTPD&`^W!$&+5"0400^_
-M%%,IT(G&1"GFBT0D%$C!X`4"+1"042,'@!TB-?`4`1`^WP8GP00^OP$2)ZD'_Q0^WCP`$``!F`<&X````
-M``])P4R+M"2(````9D&)!%;_QGC1BU0D%$B-!!)$#[\4`T$/OP0#02G"2(M,
-M)!@/MSQ11`'G*<=%B=%!.?I$#T?/00^_P4&)P#G&?3!(B=%(P>$&1(GH2&/6
-M2(T4"O_&#[>450`$``!,B[0DB````&9!B11&0?_%1#G&?->+1"0408U*_TC!
-MX`9(C0P!08U2_D@!T`^WE$T`!```B=%F*XQ%``0``+@!````#T3(1#G/=E8/
-MO\`&3(T4`D0/M\$/O_^)\$0IR$$/K\!"#[>,50`$
-M```!P42)ZD'_Q6:#^7^X?P````].P4B+C"2(````9HD$4?_&.?Y\R/]$)!1$
-MBW0D$$0Y="04#X(=_O__@WPD%`-W(HM$)!2+5"04_\I(BTPD&`^W%%%FB11!
-M_T0D%(-\)!0#=MY!@_U_=R!$B>A!C57_2(N<)(@````/MQ139HD40T'_Q4&#
-M_7]VX$B#Q$A;74%<05U!7D%?PT%6055!5%532(/L($B)_4B)RDF)_4B+GWA(
-M```/MT$")=`````]P````'0'/=````!U"4V-I;@I``#K(`^W00(EH````+D`
-M````/:`````/A28!``!,C:>D)0``2(M%((N`;*(``$&)QD&#Y@]!#[?.#[`.)0#````)PHF16*(``&:#?"06`'01#[=$)!;WV&9!B87L,0``
-MZPIF0<>%[#$`````OX"B``"^`````(T,M0````")R`^V%$.-00$/M@1#P>`(
-M"<*-00(/M@1#P>`0"<*#P0,/M@1+P>`8"<*)^4B+12")%`&#QP3_QH/^'W:\
-M2(MU($2)\H/B#P^W1"08P>`$)?`#```)PDB-3"08#[=!`L'@"B4`_```"<(/
-MMT$$P>`0)0``/P`)P@^W00;!X!8E``#`#PG"B99LH@``N0$```")R$B#Q"!;
-M74%<05U!7L-32(G[2(._>$@```!T%TB+OWA(``#H`````$C'@WA(````````
-M2(.[X#$```!T%TB+N^`Q``#H`````$C'@^`Q````````2(.[<"X```!T%TB+
-MNW`N``#H`````$C'@W`N````````6\.Z`````+D#````B<@IT$B-!$!(C03&
-M9H-X"`!T!0^_0!3#_\*#^@-VX;@`````P[H`````B=!(C0Q`#[=$S@AFA9,B>_HGO[__YB)1"0<2`-<)!!(B=Y,B>_HB?[__Y@I1"0<
-M#[=%``^W$RG0#Z]$)!R)1"0,2(G>3(GOZ&?^__^800^OQP-$)`R90??_9IAF
-M08D&3(GF3(GOZ!K^__]$#[_@2(G>3(GOZ`O^__^802G$#[=%``^W$RG01(GE
-M#Z_H2(G>3(GOZ.W]__^800^OQXT$*)E!]_]FF$B+5"0@9HD"ZS9(8\%(:]!F
-M#[=%`&8[!!-U+$@!TTB)WDR)[^CE_?__9D&)!DB)WDR)[^BG_?__2(MT)"!F
-MB0:Y`0```.L%N0````")R$B#Q"A;74%<05U!7D%?PT%7059!54%455-(@^P(
-M28G^28GT08G50;\!````O0`````YU7-`2&/=28TTW$B-3"0&2(U4)`1,B??H
-MH?W__X7`=!8/MD0D!$&(1-P&#[9$)`9!B$3URP$2)
-M^$B#Q`A;74%<05U!7D%?PTB#[!A(B5PD"$B);"002(GU2(G[OX0```#H````
-M`$B)@^`Q``!(A#@$@````!``"_``$``.@`````2(F#>$@``$B%P'06
-MOP`&``#H`````$B)@W`N``!(A#>"X`````
-M``!(QX.`+@```````$C'@X@N````````2,>#D"X```````!(QX.8+@``````
-M`$C'@Z`N````````2,>#J"X```````!(QX.P+@```````+@!````2(M<)`A(
-MBVPD$$B#Q!C#05=!5D%505154TB#[`A)B?Q!B=>)R[T`````2H@T?J)P<'Y'RG*C122N0`````YT`^%"@(``(V<-J#N__](8\-(:\@P?\#P?@?*@#C02``@09L'H`HT$
-M@+D`````9CG"#X6%````#[?"+<`2``!(8_A(:?]G9F9F2,'O(-'_P?@?*<>^
-M"````.@`````B<.^`@```+\!````Z`````!!B<6)WL'F!$*-!*T`````"<9#
-MC00V"<:!S@$0``!)BU0D($`/ML:)@IR8``#![@A)BU0D((GP@^!_B8+8F```
-M28FL).@3``"Y`0```(G(6UU!7$%=05[#05=!5D%505154TB#[`A)B?U!B==)
-MB?Y!N@````!FQT0D!@``0;D`````9L=$)`0``+T`````3(NGX#$```^W1@(E
-M\`$``#W0````#X3`````/=````!_&SV@````#X2=````/<`````/A*,```#I
-MM0```#U``0``=`L]4`$```^%HP````^W!F8MH0]F/>H$=Q)%#[>6#!4``$$/
-MMX8.%0``ZU4/MP9F+8P49CWO`'<210^WEA`5``!!#[>&$A4``.LV#[<&9BU\
-M%68]X`!W$D4/MY84%0``00^WAA85``#K%V:!/EP6=DE%#[>6&!4``$$/MX8:
-M%0``9HE$)`;K,D0/MX\<%0``#[>''A4``.L010^WCB`5``!!#[>&(A4``&:)
-M1"0$ZPJX`````.G)`@``N0````!(Q\<`````2&/1BP3708D$E/_!=/*Y````
-M`$$/M_])Q\``````2&/!2(T40$B-%%=!BQ2008E4A`3_P73HN0````!!#[?_
-M2H/`=!FT?AF0HE$!#A,C50D,$2)R8M$)$!!
-M#[?]2(T$0$B)PDC!X@1(`=!(C0Q)2,'A`D@!R$@!^$$/MW1&*F9#B30"BT0D
-M1$B-!$!(B<)(P>($2`'02`'(2`'X9D$[=$8J?@M!#[=$1BIF0XD$`D2+9"00
-M30'D0@^W1"0PB<)FP>H/`=!FT?AF0HE$)#!%#[?MBTPD0$AKR69$BM(`UPD"$0/OX1=``(```^_3%T`BT0D1$$/MQ1&BT0D
-M0$$/MS1&1(G_Z'K]__]FB81=``0``$'_Q4(/MT0D,&9"*T0D.`^WP$$YQ7*Q
-M_T0D$/]$)!2#?"04`P^&W/W__XM$)#A(BTPD(&:)`4&]`````,=$)!0`````
-M1#ML)!`/@_,!``!(C5PD,$R-7"0X1`^W9"0LBT0D$/_(.40D%'47BU0D%`^W
-M!%.#P`1,BW0D&&9!B016ZR>+3"04#[\$2XM4)!3_PD$/OQ13`=")PL'J'P'0
-MT?A(BU0D&&:)!$J^`````(-\)!0`=!^+1"04_\A(BTPD&`^W!$&+5"0400^_
-M%%,IT(G&1"GFBT0D%$C!X`4"+1"042,'@!TB-?`4`1`^WP8GP00^OP$2)ZD'_Q0^WCP`$``!F`<&X````
-M``])P4R+M"2(````9D&)!%;_QGC1BU0D%$B-!!)$#[\4`T$/OP0#02G"2(M,
-M)!@/MSQ11`'G*<=%B=%!.?I$#T?/00^_P4&)P#G&?3!(B=%(P>$&1(GH2&/6
-M2(T4"O_&#[>450`$``!,B[0DB````&9!B11&0?_%1#G&?->+1"0408U*_TC!
-MX`9(C0P!08U2_D@!T`^WE$T`!```B=%F*XQ%``0``+@!````#T3(1#G/=E8/
-MO\`&3(T4`D0/M\$/O_^)\$0IR$$/K\!"#[>,50`$
-M```!P42)ZD'_Q6:#^7^X?P````].P4B+C"2(````9HD$4?_&.?Y\R/]$)!1$
-MBW0D$$0Y="04#X(=_O__@WPD%`-W(HM$)!2+5"04_\I(BTPD&`^W%%%FB11!
-M_T0D%(-\)!0#=MY!@_U_=R!$B>A!C57_2(N<)(@````/MQ139HD40T'_Q4&#
-M_7]VX$B#Q$A;74%<05U!7D%?PT%6055!5%532(/L($B)_4B)SDF)_4B+GWA(
-M```/MT$")=`````]P````'0'/=````!U"4V-I;@I``#K(P^W00(EH````$B-
-MCZ0E``!(C9>0(0``/:````!)B`.)0#````)PHF16*(``&:#?"06`'01#[=$)!;WV&9!B87L
-M,0``ZPIF0<>%[#$`````OX"B``"^`````(T,M0````")R`^V%$.-00$/M@1#
-MP>`("<*-00(/M@1#P>`0"<*#P0,/M@1+P>`8"<*)^4B+12")%`&#QP3_QH/^
-M'W:\2(MU($2)\H/B#P^W1"08P>`$)?`#```)PDB-3"08#[=!`L'@"B4`_```
-M"<(/MT$$P>`0)0``/P`)P@^W00;!X!8E``#`#PG"B99LH@``N`$```!(@\0@
-M6UU!7$%=05[#4TB)^TB#OWA(````=!=(B[]X2```Z`````!(QX-X2```````
-M`$B#N^`Q````=!=(B[O@,0``Z`````!(QX/@,0```````$B#NW`N````=!=(
-MB[MP+@``Z`````!(QX-P+@```````%O#N@````"Y`P```(G(*=!(C01`2(T$
-MQF:#>`@`=`4/OT`4P__"@_H#=N&X`````,.Z`````(G02(T,0`^W1,X(9H7`
-M=`T/M\!(C02(#[]$1A+#_\*#^@-VW+@`````PT%7059!54%455-(@^P828G]
-M2(GU2(E4)!!(B4PD"$B)^DB+1"009L<````/MT8")=`````]P````'0'/=``
-M``!U"4B-@K@I``#K(P^W1@(EH````$B-CZ0E``!(@<*0(0``/:````!(B_H?O[__YA!#Z_&0HT$.)E!]_YFF$B+5"009HD"3(GF3(GOZ"W^__]$#[_@
-M2(G>3(GOZ![^__^802G$#[=%``^W$RG01(GE#Z_H2(G>3(GOZ`#^__^800^O
-MQHT$*)E!]_YFF.LR2&/!2&O09@^W10!F.P03=3!(`=-(B=Y,B>_H`/[__TB+
-M5"009HD"2(G>3(GOZ+[]__](BW0D"&:)!K@!````ZP6X`````$B#Q!A;74%<
-M05U!7D%?PT%7059!54%455-(@^P(28G^28GT08G50;\!````O0`````YU7-`
-M2&/=28TTW$B-3"0&2(U4)`1,B??HNOW__X7`=!8/MD0D!$&(1-P&#[9$)`9!
-MB$3URP$2)^$B#Q`A;74%<05U!7D%?PTB#[!A(B5PD
-M"$B);"002(GU2(G[OZP```#H`````$B)@^`Q``!(A#@$@````!``"_
-M``$``.@`````2(F#>$@``$B%P'06OP`&``#H`````$B)@W`N``!(A#>"X```````!(QX.`+@```````$C'@X@N````````
-M2,>#D"X```````!(QX.8+@```````$C'@Z`N````````2,>#J"X```````!(
-MQX.P+@```````+@!````2(M<)`A(BVPD$$B#Q!C#*%`6+%@H````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````H/^C_Y[_H/^C_Z#_````````!0`*`!0`'@`R`$8`50!:`%\`9```````
-M```````````*`!0`'@`H`#(`/`!&`%``6@!D``````````````#"````Q```
-M`,4```#0````V@```.0``````````````,(```##````U````/(````-`0``
-M*`$``,\```#*`````@!0(0$`0`$$`*``"`#``"``T`!``%`!````````````
-M````````````````````)`&8&0`F$`8`````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M________`````````````````````````)@``$<````(F`````````R8``"F
-MCH0)$)@```#@,CT4F```:P<``!R8````````()@````"`@(DF```#@X``"B8
-M```!`@(*+)@``/QO`P`PF````````#28```.#@``.)@```<````\F`````$"
-M`$"8`````&.)1)@``)P6)@```0`````F0````````29````````")D`````
-M```,F0````"``!"9```#`````)L````````$FP``(`````B;```0````#)L`
-M`#`````0FP``"````!2;```H````&)L``"@````)L``"T```!\FP``
-M`P```(";```C````A)L``!,```"(FP``,P```(R;```+````D)L``"L```"4
-MFP``!P```)B;```G````G)L``!<```"@FP``-P```*2;```/````J)L``"\`
-M``"LFP``+P```+";```O````M)L``"\```"XFP``+P```+R;```O````P)L`
-M`"\```#$FP``+P```,B;```O````S)L``"\```#0FP``+P```-2;```O````
-MV)L``"\```#Z&`!GNA@`:;H8`&FZ&`!0
-MF```X+0H#."T*`S@M"@,X+0H#%B8```N#8!^+@V`?BX-P'XN#8!^7)@``%Y=
-M-S%>73@%J($R8```\88025)@``%D(
-M``!HF```D$&:0&R8``"!L`P%<)@```\```!TF```@````'B8```,`````)D`
-M```````$F0````````B9````````#)D`````@``0F0```0```!R9```J"0``
-M()D````````DF0``!8H%`"B9```!````+)D````````PF0```````#29````
-M````.)D````````\F0``/P```$"9```$````2)D```````!,F0```````%"9
-M````````5)D``$SQ4%U8F0``&````%R9``".:DL`A*$``/\%_P:(H0``_P?_
-M!XRA``#_"/\(D*$``/\)_PF4H0``_PK_"IBA``#_"_\+G*$``/\,_PR@H0``
-M_PW_#:2A``#_#O\/J*$``/\2_Q*LH0``_Q/_%+"A``#_%?\6M*$``/\7_QFX
-MH0``_QK_&[RA``#_'?\>P*$``/\@_R/$H0``_R7_)\BA``#_*?\LS*$``/\O
-M_S'0H0``_S3_-]2A``#_.O\ZV*$``/\Z_SK`$``$":``"8`0``N`$``$2:``#8`0``^`$``$B:```8
-M````$@```$R:``!8````4@```%":``"8````D@```%2:``"D`0``?`$``%B:
-M``#D`0``O`$``%R:```D````_`$``&":``!D````"@```&2:``"D````2@``
-M`&B:``#D````B@```&R:```*`0``6@$``'":``!*`0``F@$``'2:``"*`0``
-MV@$``'B:``#*`0``#@```'R:```*````3@```(":``!*````C@```(2:``"*
-M````7@$``(B:``"Z`0``G@$``(R:``#Z`0``W@$``)":```Z````"0```)2:
-M``!Z````20```)B:``"&`0``B0```)R:``#&`0``>0$``*":```&````N0$`
-M`*2:``!&````^0$``*B:``"&````.0```*R:``#&````>0```+":``#&````
-MN0```+2:``#&````O0$``+B:``#&````_0$``+R:``#&````/0```,":``#&
-M````?0```,2:``#&````O0```,B:``#&````_0```,R:``#&````_0```-":
-M``#&````_0```-2:``#&````_0```-B:``#&````_0```-R:``#&````_0``
-M`.":``#&````_0```.2:``#&````_0```.B:``#&````_0```.R:``#&````
-M_0```/":``#&````_0```/2:``#&````_0```/B:``#&````_0```/R:``#&
-M````_0````$```!&````8`````$```!&````80````$```!&````8@````$`
-M``!&````8P````$```!&````9`````$```!&````90````$```!&````9@``
-M``$```!&````9P````$```!&````:`````$```!&````:0````$```!&````
-M:@````$```!&````:P````$```!&````;`````$```!&````=`````$```!&
-M````=`````$```!&````=`````$```!&````=`````$```!&````=`````$`
-M``!&````=`````$```!&````=`````$```!&````=`````$```!&````=0``
-M``$```!&````=@````$```!&````=P````$```!&````>`````$```!&````
-M>0````$```!&````>@````$```!&````>P````$```!&````?`````$```!&
-M````?0````$```!&````?@````$```!&````?P````$```!&````@`````$`
-M``!$````?`````$```!&````B`````$```!&````C`````$```!&````D```
-M``$```!&````E`````$```!&````F`````$```!&````G`````$```!&````
-MH`````$```!&````I`````$```!&````J`````$```!&````K`````$```!&
-M````L`````$```!&````M``````"!P```````````````````````````)X6
-M"P!B%@H`.A8)`!P6"`#J%0<`FA4%`$H5!``#%0(`610``````0````,`!@`)
-M`#\`````````````````````````````````````````````````````````
-M````````````````````````````````````````````````"0````0````$
-M``$``0`!``8```!&1S@`````````````````!`````$``0`$````1D!$```````"X$0```````/@1````
-M````.!(```````!X$@```````+@2````````^!(````````X$P```````'@3
-M````````N!,```````#X$P```````#@4````````>!0```````"X%```````
-M`/@4````````.!4```````!X%0```````+@5````````^!4````````X%@``
-M`````'@6````````N!8```````#X%@```````#@7````````>!<```````"X
-M%P```````/@7````````/!````````!\$````````+P0````````_!``````
-M```\$0```````'P1````````O!$```````#\$0```````#P2````````?!(`
-M``````"\$@```````/P2````````/!,```````!\$P```````+P3````````
-M_!,````````\%````````'P4````````!(`````````(@`````````R`````
-M````((`````````D@````````"B````P````+(```/__!P`P@```____`32`
-M```Q````.(`````````\@````````$B`````````5(````````!8@```````
-M`%R```"/QP\`P(```!HP@BK$@```X`''^"'`````0(#Y(<```0%!@?HAP``"`D*"^R'```,#0X/\(<`
-M`!`1$A/TAP``%!46%_B'```8&1H;_(<``!P='A\,F```&8Z$K1"8````X"A]
-M%)@``&N?"IP)D```$```!\F0``
-M`````!"B```S8X``%*(``!!L$``8H@``8$"<`""B``#&,(@!)*(````$```L
-MH@```````#2B```@("`@.*(``"`@("!`H@``(`I).$2B``"V>P``2*(``/P_
-M_P\`FP```````"B;```,````.)L``!(```!DFP``(0```(R;```M````G)L`
-M`#,```````,`!@`)`#\````#``8`"0`_``````````````````D````$````
-M!``!``$``0````````````8```!&1S@`````````````````!`````$``0``
-M``````````0```!&1S<``````````````````P`!``$``0````````````,`
-M``!&1S8`````````````````!````````0````````````$```!&1S4`````
-M````````````!``!``$```````````````````!&1S0`````````````````
-M!`````$``````````````/[___]&1S,``````````````````P`!``$`````
-M`````````/W___]&1S(`````````````````!````````````````````/S_
-M__]&1S$``````````````````@`!``$``````````````/K___]&1S``````
-M````````````````````````````````````````````````````````````
-M``````````````````````@````!`````P````````````````````8```!&
-M1S<``````````````````@````````````````````````!&1S8`````````
-M`````````0```````````````````/W___]&1S4`````````````````````
-M`````````````````/K___]&1S0````````````````````!``$`````````
-M`````/C___]&1S,````````````````````!``$````!``$``````/;___]&
-M1S(````````````````````!`````0`!``$``````//___]&1S$`````````
-M```````````!`````0`!`````0```/#___]&1S``````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M```````````````````P````%8```!6````5@```%8```!6````<@```IX^-
-M$L\/B`F5#^`$JP_@$L\/B`DHF````0`""@$``@H``0$%`0`""@$``@HTF```
-M#@X```X.```.#@``#@X```X.```XF```!P````<````+````"P````L```!(
-MF```6MH8`%K:&`!IRA@`:"TZ`W@M.@-X+3H#>"T
-MZ`U8F```+@V`?BX-@'XN3>A^+DWH?BX-@'Y9C@```$D```"8F@``A@$``(D```"`````$```!&````>0````$```!&````
-M>@````$```!&````>P````$```!&````?`````$```!&````?0````$```!&
-M````?@````$```!&````?P````$```!&````@`````$```!$````?`````$`
-M``!&````B`````$```!&````C`````$```!&````D`````$```!&````E```
-M``$```!&````F`````$```!&````G`````$```!&````H`````$```!&````
-MI`````$```!&````J`````$```!&````K`````$```!&````L`````$```!&
-M````M```````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M``````">%@8`8A8$`#H6`P`<%@(`ZA4!`)H5``!*%0```Q4!`%D4`P"X"P4`
-M````````````````````````````````,````!6````5@```%8```!6````5
-M@```'(```*>3C1+/$X@)E1/@!*L3X!+/$X@)*)@```$``@H!``(*``$"!0$`
-M`@H!``(*-)@```X.```.#@``#@X```X.```.#@``.)@```<````'````"P``
-M``L````+````2)@``&W:&`!MVA@`="TZ`W@M.@-6)@``"X-@'XN#8!^+@WH?BX-Z'XN#8!^7)@``%YF-S%>
-M9C9C)H``"L`
-M```2````?)H``&L```!2````@)H``*L```"2````A)H``*P!``"3`0``B)H`
-M`.P!``#3`0``C)H``"P````3````D)H``#H```!3````E)H``'H```"3````
-MF)H``+H```"4`0``G)H``+L!``#4`0``H)H``/L!```4````I)H``#L````Z
-M````J)H``'L```!Z````K)H``+L```"Z````L)H``+P!``"[`0``M)H``/P!
-M``#[`0``N)H``#P````[````O)H``'P```![````P)H``+P```"[````Q)H`
-M`/P```"\`0``R)H``/P```#\`0``S)H``/P````\````T)H``/P```!\````
-MU)H``/P```"\````V)H``/P```#\````W)H``/P```#\````X)H``/P```#\
-M````Y)H``/P```#\````Z)H``/P```#\````[)H``/P```#\````\)H``/P`
-M``#\````])H``/P```#\````^)H``/P```#\````_)H``/P```#\````U)@`
-M`"```````````````-"8```(!`8#"`0'`P@$!@,(!`8#"`0'`P``````````
-MW)@``,`@H`#`(*``P"#@`,`@X`#`(.``````````````````````````````
-M````G)@```````\````/````#P````\````/G)@`````````````````````
-M````````G)@`````@````(````"`````@````(``G)@`````*@```"H````J
-M````*@```"H`G)@``````0````$````!`````0````$`G)@`````````````
-M````````````````G)@`````&````!@````8````&````!@`G)@`````8```
-M`&````!N````;@```&X`G)@`````QP```,<```#'````QP```,<`G)@`````
-M2P```$L```!+````2P```$L`G)@`````2`0``$@$``!(!```2`0``$@$G)@`
-M````3````$P```!,````3````$P`G)@`````Y````.0```#D````Y````.0`
-MG)@`````````````````````````````G)@`````_````/P```#\````_```
-M`/P`G)@`````_P```/\```#_````_P```/\`G)@`````/P0``#\$```_!```
-M/P0``#\$G)@`````#`````P````,````#`````P`G)@`````&0(``!D"```9
-M`@``&0(``!D"G)@`````)````"0````D````)````"0`G)@`````M````+0`
-M``"T````M````+0`G)@`````F0```)D```"9````F0```)D`G)@`````4```
-M`%````!0````4````%``G)@`````*@```"H````J````*@```"H`G)@`````
-M$@```!(````2````$@```!(`G)@`````,L```#+````RP```,L```#+`G)@`
-M````=`$``'0!``!T`0``=`$``'0!G)@`````$0```!$````1````$0```!$`
-MG)@`````*(8``"B&```HA@``*(8``"B&G)@`````A#$``(0Q``"$,0``A#$`
-M`(0QG)@``(``\@"``/(`@`#R`(``\@"``/(`G)@``!D`)P`9`"<`&0`G`!D`
-M)P`9`"<`G)@```,````#`````P````,````#````G)@`````````````````
-M````````````G)@``+(```"R````L@```+(```"R````G)@``(0@L`"$(+``
-MA""P`(0@L`"$(+``G)@``*0E00"D)4$`I"5!`*0E00"D)4$`G)@``""2$0`@
-MDA$`()(1`""2$0`@DA$`G)@```!(&@``2!H``$@:``!(&@``2!H`V)@``#`"
-M"P`P`@L`,`(+`#`""P`P`@L`G)@``)0```"4````E````)0```"4````G)@`
-M`)$```"1````D0```)$```"1````G)@``!(````2````$@```!(````2````
-MG)@``(````"`````@````(````"`````G)@``-D```#9````V0```-D```#9
-M````G)@``&````!@````8````&````!@````G)@``/````#P````\````/``
-M``#P````G)@``*(```"B````H@```*(```"B````G)@``%(```!2````4@``
-M`%(```!2````G)@``-0```#4````U````-0```#4````G)@``,P4``#,%```
-MS!0``,P4``#,%```G)@``(P$``",!```C`0``(P$``",!```Q)@```,````#
-M`````P````,````#````````````````````````````````````````````
-M````````````````````````````````````````````````````````,```
-M`!4````5````%0```!4````5````'(```*>3C1+/$X@)E1/@!*L3X!+/$X@)
-M*)@```$``@H!``(*```"!0$``@H!``(*-)@````.````#@````X````.````
-M#@``.)@```(````"````"@````H````*````2)@``&W:&`!MVA@`9&H:`&1J
-M&@!D:AH`4)@``."TZ`W@M.@-VK#H#=JPF`S:L.@-6)@``"X-@'XN#8!^+@WH
-M?BX-R'XN#8!^7)@``%YF-S%>9C9C*(``,XYYQQ\H@``S@$7!0"C``````$8
-M!*,```(F`S`(HP``!CX'2`RC```*3`M6$*,```]@&F04HP``&VY/>!BC``!:
-M?(^&'*,``%N&SXX@HP``#Y=/G22C``"/H<^E**,``!^O7[4LHP``G[G?O3"C
-M```_QW_--*,``+_1_]4XHP```````#RC````````0*,```````!$HP``````
-M`$BC``#___\_3*,``/___S]0HP``____/U2C``#__P,`6*,``!^JJ'E`$``'2:````````N`$``'B:````````^`$``'R:````````.````(":````
-M````>````(2:````````F0$``(B:````````V0$``(R:````````&0```)":
-M````````60```)2:````````F0```)B:````````V0```)R:````````^0``
-M`*":````````^0```*2:````````^0```*B:````````^0```*R:````````
-M^0```+":````````^0```+2:````````^0```+B:````````^0```+R:````
-M````^0```,":````````^0```,2:````````^0```,B:````````^0```,R:
-M````````^0```-":````````^0```-2:````````^0```-B:````````^0``
-M`-R:````````^0```.":````````^0```.2:````````^0```.B:````````
-M^0```.R:````````^0```/":````````^0```/2:````````^0```/B:````
-M````^0```/R:````````^0```-28```@``````````````#0F```"!0``@@4
-M`0((%``""!0``@@4`0(``````````-R8``#`(*``P""@`,`@X`#`(.``P"#@
-M`````````````````````````````````)R8``````#P````\````/````#P
-M````\)R8`````````````````````````````)R8```````#`````P````,`
-M```#`````YR8`````````````````````````````)R8````````````````
-M`````````````)R8`````````````````````````````)R8````````````
-M`````````````````)R8`````````````````````````````)R8`````$!`
-M``!`0```0$```$!```!`0)R8``````5E```%90``!64```5E```%99R8````
-M`````````````````````````)R8`````````````````````````````)R8
-M`````$(```!"````0@```$(```!"`)R8`````+4```"U````M0```+4```"U
-M`)R8``````,````#`````P````,````#`)R8`````/<```#W````]P```/<`
-M``#W`)R8`````)T```"=````G0```)T```"=`)R8`````"(````B````(@``
-M`"(````B`)R8`````"($```B!```(@0``"($```B!)R8```8`",`&``C`!@`
-M(P`8`",`&``C`)R8`````"@````H`&``*`!@`"@`8``H`)R8``#``%``P`!0
-M`,,`4`##`%``PP!0`)R8``!_``0`?P`$`'\`!`!_``0`?P`$`)R8``!8!```
-M6`0``%@$``!8!```6`0``)R8`````````````````````````````)R8````
-MP````,````#`````P````,```-B8```P`D``,`)``#`"0``P`D``,`)`````
-M`````````````````````````````)R8````9````&0```!D````9````&0`
-M`)R8````"`````@````(````"`````@``,R8```.````#@````X````.````
-M#@``````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M```P````%0```!4````5````%0```!4````<@```IY.-$L\3B`F5$^`$JQ/@
-M$L\3B`DHF````0`""@$``@H``0(%`0`""@$``@HTF```#@X```X.```.#@``
-M#@X```X.```XF```!P````<````+````"P````L```!(F```8?H8`&'Z&`!C
-M&AH`8QH:`&,:&@!0F```X+28#."TF`S:L)@,VK"8#-JPF`Q8F```+@W(?BX-
-MR'XN#8#DQ7F`Y,5Y@.3%LF```@;`,
-M!8&P#`6!L`P%@;`,!8&P#`44F0``T`<``-`'``!,!```F`@``-`'``!$F0``
-M`!"X]P`0N/<`#;CW`!"X]P`0N/<$H@`````````````````````````````(
-MH@``B&>^UHAGOM:(9S[0B&<^T(AG/M`,H@``X,$N`.#!+@`@P2H`(,$J`"#!
-M*@`!MN3W@;;D]X&VY/>!MN3W@8HP``6GR/AEI\
-MCX9:?(^&6GR/AEI\CX8/G\^CCY_/HX^?SZ,HHP``
-M'Z]?M1^O7[4?KU^S'Z]?LQ^O7[,LHP``G[G?O9^YW[V?N=^[G[G?NY^YW[LP
-MHP``/\5_RS_%?\L_QW_+/\=_RS_'?\LTHP``O]'_U;_1_]6_T?_3O]'_T[_1
-M_],`````````````````````,!(``.`#``!H0```$````&"````/````G(``
-M``````"@@````````!B!````````'($````````@@0```````"2!````````
-M*($````````L@0```````#"!````````-($````````X@0```````#R!````
-M````0($``/D#`(!$@0````````B8````````+)@```"@```\F`````0@`$R8
-M```\(X02<)@``!\```!TF```@````'B8```.````6)D``/\?"`"`F0``````
-M`(29`````(`"H)D```````#@F0```````.29``"JJJJJZ)D``'AD1CSLF0``
-MJ@```/"9```,````])D``/\```#XF0``%````"BB``"U"0``/*(``*^)R)-,
-MH@```0```%"B````H```5*(```````!8H@``@%/'#%RB```!#P\/8*(```$/
-M:5]DH@``$8I!`&BB````````;*(``&K!,`QPH@``(`B"`'2B``"J?!L(>*(`
-M`,XYYQQ\H@``S@$7!3BC````````/*,```````!`HP```````$2C````````
-M2*,``/___S],HP``____/U"C``#___\_5*,``/__`P!8HP``'ZJH>5RC```/
-M0FP&8*,```*,``((&V%]\HP``@@3@?X"C``"Z>SQ_A*,``/!_,/,$FP```0``
-M``B;```"````#)L```,````0FP``!````!2;```%````&)L```@````)L``"@```!\FP``*0```(";```J````
-MA)L``"L```"(FP``+````)";```P````E)L``#$```"8FP``,@```*";```T
-M````I)L``#4```"HFP``-0```*R;```U````L)L``#4```"TFP``-0```+B;
-M```U````O)L``#4```#`FP``-0```,2;```U````R)L``#4```#,FP``-0``
-M`-";```U````U)L``#4```#8FP``-0```-R;```U````X)L``#4```#DFP``
-M-0```.B;```U````[)L``#4```#PFP``-0```/2;```U````^)L``!````#\
-MFP``&@````":``````````````2:``!`````0`````B:``"`````@`````R:
-M``"A`0``80$``!":``#A`0``H0$``!2:```A````X0$``!B:``!A````(0``
-M`!R:``"(`0``80```"":``#(`0``B`$``"2:```(````R`$``"B:``!(````
-M"````"R:``"(````2````#":``"I`0``B````#2:``#I`0``:0$``#B:```I
-M````J0$``#R:``!I````Z0$``$":``#0`0``*0```$2:```0````:0```$B:
-M``!0````D`$``$R:``"0````T`$``%":``"Q`0``$````%2:``#Q`0``4```
-M`%B:```Q````D````%R:``!Q````<0$``&":``"X`0``L0$``&2:``#X`0``
-M\0$``&B:```X````,0```&R:``!X````<0```'":``"9`0``F`$``'2:``#9
-M`0``V`$``'B:```9````&````'R:``!9````6````(":``"9````F````(2:
-M``#9````>0$``(B:``#Y````N0$``(R:``#Y````^0$``)":``#Y````.0``
-M`)2:``#Y````>0```)B:``#Y````N0```)R:``#Y````^0```*":``#Y````
-M^0```*2:``#Y````^0```*B:``#Y````^0```*R:``#Y````^0```+":``#Y
-M````^0```+2:``#Y````^0```+B:``#Y````^0```+R:``#Y````^0```,":
-M``#Y````^0```,2:``#Y````^0```,B:``#Y````^0```,R:``#Y````^0``
-M`-":``#Y````^0```-2:``#Y````^0```-B:``#Y````^0```-R:``#Y````
-M^0```.":``#Y````^0```.2:``#Y````^0```.B:``#Y````^0```.R:``#Y
-M````^0```/":``#Y````^0```/2:``#Y````^0```/B:``#Y````^0```/R:
-M``#Y````^0```-28```@``````````````#0F```"`````@````(````"```
-M``@``````````````-R8``#``*``P`"@`,``X`#``.``P`#@````````````
-M`````````````````````)R8```````S````,P```#,````S````,YR8````
-M```!`````0````$````!`````9R8`````````````````````````````)R8
-M`````````````````````````````)R8````````````````````````````
-M`)R8```````?````'P```!\````?````'YR8````````````````````````
-M`````)R8`````+@```"X````N````+@```"X`)R8`````+<```"W````MP``
-M`+<```"W`)R8`````(0```"$````A````(0```"$`)R8`````)@```"8````
-MF````)@```"8`)R8`````,````#`````P````,````#``)R8`````/\```#_
-M````_P```/\```#_`)R8`````/\```#_````_P```/\```#_`)R8`````/\`
-M``#_````_P```/\```#_`)R8`````/\```#_````_P```/\```#_`)R8````
-M`-<```#7````UP```-<```#7`)R8`````&$```!A````80```&$```!A`)R8
-M`````/X```#^````_@```/X```#^`)R8`````-X```#>````W@```-X```#>
-M`)R8`````'\```!_````?P```'\```!_`)R8`````#T$```]!```/00``#T$
-M```]!)R8`````'<```!W````=P```'<```!W`)R8`````$0```!$````1```
-M`$0```!$`)R8`````)@```"8````F````)@```"8`)R8``"``!``@``0`(``
-M$`"``!``@``0`)R8```TP`4`-,`%`#3`!0`TP`4`-,`%`)R8``#P`#$`\``Q
-M`/``,0#P`#$`\``Q`)R8```?`0P`'P$,`!\!#``?`0P`'P$,`)R8``!``%$`
-M0`!1`$``40!``%$`0`!1`)R8``#:`%``V@!0`-H`4`#:`%``V@!0`)R8````
-M`````````````````````````)R8``!$0```1$```$1```!$0```1$```)R8
-M`````````````````````````````)R8``#`8```P&```,!@``#`8```P&``
-M`)R8````+````"P````V````-@```"P``,B8```#!````P0```,$```#!```
-M`P0`````````````G)@```!D````9````&0```!D````9```G)@````(````
-M"`````@````(````"```S)@```X````.````#@````X````.````````````
-M````````````````````````````````````````````````````````````
-M`````````````````$%2-3(Q,`!!4C4R,3$`05(U,C$R`%)&-3$Q,0!21C4Q
-M,3(`4D8R-#$S`%)&-30Q,P!!=&AE``$``````````````%@;``">`0,``0`````````!````6!L``*P!
-M-P`!``````````$```!8&P``I@$#``$``````````0```%@;``"V`3<``0``
-M```````!````6!L``+@!-P`!``````````$```!8&P``N@$W``$`````````
-M`0```%@;``"^`2$``0````$````!````6!L``"<#`P`!``````````$```!8
-M&P``R@%=``$``````````````%@;``#6`3<``0`````````!````6!L``.0!
-M$``!`````0````$```!8&P``[`$P``$````!`````0```%@;``#X`0,``0``
-M```````!````6!L``!`"-P`!``````````$```!8&P``*@(B``$`````````
-M`0```%@;``!"`C<``0`````````!````6!L````"6P`!``````````$```!8
-M&P``2@(#``$``````````0```%@;``!/`A```0````$````!````6!L``%P"
-M4@`!``````````$```!8&P``8`([``$````!`````0```%@;``!H`C<``0``
-M```````!````6!L``&P"-P`!``````````$```!8&P``=@(0``$````!````
-M`0```%@;``!Z`@,``0`````````!````6!L``(("`P`!``````````$```!8
-M&P``@P(#``$``````````0```%@;``"J`B$``0`````````!````6!L``+X"
-M6P`!`````0````$```!8&P``OP(W``$``````````0```%@;``#!`C<``0``
-M```````!````6!L``,8".P`!``````````$```!8&P``U`(W``$`````````
-M`0```%@;``#P`C<``0`````````!````6!L``/0"-P`!``````````$```!8
-M&P``^`(#``$``````````0```%@;``">`%```0````$````!````6!L``/P"
-M`P`!``````````$```!8&P``#`,P``$``````````0```%@;```4`S8``0``
-M```````!````6!L``!@#-@`!``````````$```!8&P``)`,#``$`````````
-M`0```%@;```0`P,``0`````````!````6!L``#H#-P`!``````````$```!8
-M&P``2`,0``$````!`````0```,$6``!*`Q(``0````$````!````6!L``%H#
-M$0`!``````````$```!8&P``7`,Z``$````!`````0```%@;``!>`U8``0``
-M```````!````6!L``,`"`P`!``````````$```!8&P``=P,#``$`````````
-M`0```%@;``#,`@,``0`````````!````6!L````````S$ST3%P`*!0``````
-M````$``````````0`````````$<341,7``H%```````````0`````````!``
-M````````.!-T$Q<`%!0``````````!``````````!P````````!.$WL3&P8%
-M!0```````````0```````````````````%$3>1,>!@H%```````````!````
-M````````````````5A-T$R$&%`4```````````$```````````````````"K
-M$[`3%P`*!0``````````$``````````,`````````+`3V!,7`!04````````
-M```0``````````(`````````OQ._$Q<`"@4``````````!``````````#```
-M````````%'@4!084%````````````````````````````````#(4;A07`!04
-M```````````8``````````$`````````,A1N%!0`%!0``````````!@`````
-M`````0`````````\%'@4#P`4%```````````!0```````````````````#P4
-M>!01!A04```````````!``````````$`````````/!1X%!(`%!0`````````
-M``4````````````````````\%'@4%``4%```````````!0``````````````
-M`````#P4>!07`!04```````````%````````````````````/!1X%!<&%!0`
-M``````````$````````````````````\%,@4%`84%`(`````````!```````
-M`````````````'@4H!07`!04`0`````````%````````````````````C!2@
-M%!<`%!0#``````````4```````````````````",%,@4$@`4%`,`````````
-M!0```````````````````(P4R!04`!04!P`````````%@```````````````
-M````C!3(%!0&%!0#``````````$``````````@````````",%,@4%P84%`,`
-M`````````0`````````"`````````(P4R!07!A04`P`````````!````````
-M````````````C!3(%!X`%!0```````````````````````````````",%$06
-M!084%`,``````````````````````````````*`4R!01!A04`P`````````!
-M````````````````````?!7T%1X&%!0"``````````0`````````````````
-M``!\%406%`84%`,``````````0`````````$`````````'P51!8;`!04`P``
-M```````%````````````````````?!5$%AX`%!0#``````````4`````````
-M``````````!\%406%P`4%`<``````````8```````````````````'$6K187
-M`!04````````````````````````````````<1:M%AX&%!0`````````````
-M``````````````````!Q%JT6'@84%`(`````````!```````````````````
-M`'$6P18%!A04````````````````````````````````<1;!%A$`%!0`````
-M``````````````````````````!Q%L$6%``4%```````````````````````
-M`````````'$6P18>`!04````````````````````````````````<1;!%AX&
-M%!0``````````````````````P````````!Q%L$6'@84%```````````````
-M`````````````````#@3=!,>`!04````````````!```````````````````
-ML!/8$QX`%!0````````````$```````````````````R%&X4'@`4%`,`````
-M``````0``````````````````#P4>!0>`!04`P``````````!```````````
-M````````C!3(%!X`%!0#```````````$``````````````````!Q%L$6'@`4
-M%`````````````0``````````````````'P51!8>`!04`P``````````!```
-M````````````````C!3(%!X`%!0````````````````````````````````\
-M%'@4'@`4%````````````````````````````````,$6P18>`!04````````
-M````!```````````````````"A1:%`4&*"@`````````````````````````
-M``````""%-(4!08H*`$``````````````````````````````/H4%$84!08H*````````````````````````````````&X4
-MOA0%!B@H`0``````````````````````````````YA1>%04&*"@`````````
-M``````````````````````"&%286!08H*`$`````````````````````````
-M`````%`4>!01!B@H````````````````````````````````4!1X%!<&*"@`
-M``````````````````````````````!:%%H4$08H*```````````````````
-M`````````````%H46A07`"@H````````````````````````````````H!2@
-M%!<&*"@!``````````(```````````````````"@%*`4%`8H*`$`````````
-M`@```````````````````((4@A01`"@H`0`````````"````````````````
-M````JA2J%!0`*"@!``````````(```````````````````""%*H4%``H*`$`
-M`````````@```````````````````((4JA07!B@H`0`````````"````````
-M````````````I!4<%A0&*"@!``````````(```````````````````"`%J@6
-M%``H*````````````````````````````````(`6J!8>!B@H````````````
-M````````````````````A1:M%AX&*"@`````````````````````````````
-M``!:%((4#P`H*`,```````````0``````````````````*H4JA02`"@H`P``
-M````````!```````````````````I!4<%A0`*"@#```````````$````````
-M``````````"`%J@6%``H*`````````````0```````````````````@)1`D%
-M!A0%````````````````````````````````"`E$"10`%`4`````````````
-M``````````````````!L":@)!084!0``````````````````````````````
-M`&P)J`D4`!0%```````````@````````````````````;`FH"1X`%`4`````
-M``````````````````````````!L"9X)&P84!0``````````````````````
-M`````````&P)G@D4`!0%```````````@````````````````````@`F*"10`
-M%`4```````````````````````````````"9":@)%``4!0``````````````
-M`````````````````*,)J`D4`!0%```````````@(```````````````````
-MM`FT"04&%`4```````````````````````````````"T";0)%``4!0``````
-M````("@``````````````````-`)K`H%!A0%````````````````````````
-M````````"`E$"10`%`4```````````````````````````````!L"6P)%``4
-M!0```````````````````````````````'$)@`D4`!0%````````````````
-M````````````````A0F*"10`%`4```````````````````````````````"/
-M"9D)%``4!0```````````````````````````````)X)G@D4`!0%````````
-M````````````````````````HPFC"10`%`4````````````$``````"`````
-M``````"C":,)%``4!0```````````````````(```````````*@)J`D4`!0%
-M````````````!```````@```````````J`FH"10`%`4`````````````````
-M``"```````````"T";0)%``4!0````````````0``````(```````````+0)
-MM`D4`!0%````````````````````@```````````"`E$"04&%`4`````````
-M```````````````````````("40)%``4!0``````````````````````````
-M`````&P)J`D%!A0%````````````````````````````````;`FH"10`%`4`
-M`````````$````````````````````!L":@)'@`4!0``````````````````
-M`````````````&P)G@D;!A0%````````````````````````````````;`F>
-M"10`%`4``````````$````````````````````"`"8H)%``4!0``````````
-M`````````````````````)D)J`D4`!0%````````````````````````````
-M````T`FL"@4&%`4```````````````````````````````"C":@)%``4!0``
-M````````("````````````````````@)1`D4`!0%````````````````````
-M````````````;`EL"10`%`4```````````````````````````````!Q"8`)
-M%``4!0```````````````````````````````(4)B@D4`!0%````````````
-M````````````````````CPF9"10`%`4`````````````````````````````
-M``">"9X)%``4!0```````````````````````````````*,)HPD4`!0%````
-M````````!```````@```````````HPFC"10`%`4```````````````````"`
-M``````````"H":@)%``4!0````````````0``````(```````````*@)J`D4
-M`!0%````````````````````@```````````"`E$"04&*"@`````````````
-M``````````````````"%"84)!08H*```````````````````````````````
-M`(4)A0D4!B@H````````````````````````````````A0F%"1(&*"@`````
-M```````$``````````````````#0":P*!08H*```````````````````````
-M`````````/\!$````````0````````````````````````````````(`""``
-M`````````````/\`````````````````````$20`````````````````!10`
-M``````````````````4"```````````````````3````````````````````
-M4`$0``````````````````````````````````````````````$`````````
-M````````````````````````````````````````````````````````````
-M``````````````````````````````````````````````````!0`A``````
-M```````````````````````````````````````$````````````````````
-M````````````````````````````````````````````````````````````
-M`````````````````````````````````````````%`#$```````````````
-M````````````````````````````$`@`````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````4`00````````````````````````
-M````````````````@```@```````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M``````````````````````!0!1``````````````````````````````````
-M``````````!`````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M`````````````%`&,````````@`````````#`````````````````````(!`
-M`(`````````````````("0``````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````4`@P`````````````````````````````P`````````````$``$`````
-M````````````````````````````````````````````````````````````
-M``````````````````````````````````````````````````````!0"3``
-M``````(`````````!``````````#````````````!"`0````````````````
-M````````````````````````````````````````````````````````````
-M`````````````````````````````````````````````#`!,````````@``
-M```````$``````````,```````````!`@```"```````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````,`(P```````"``````````0`
-M`````````P``````````0```````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M```````````````````````````P`S````````(`````````!``````````#
-M````````````0`````@`````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M`````````````````#`$,````````@`````````$``````````,`````````
-M`$`@````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````,`4P```````"``````````0``````````P``````````$```````
-M````````````````````````````````````````````````````````````
-M```````````````````````````````````````````````````````````P
-M!C````````(`````````!``````````#````````````$0`!````````````
-M````````````````````````````````````````````````````````````
-M`````````````````````````````````````````````````!`!$```````
-M`````````````````````````````````"```0`"```````````````$$@``
-M````````````````$2``````````````````````````````````````````
-M````````````````````````````````````````(`$0````````````````
-M``````````````````````````("``0`````````````````````````````
-M```````2(```````````````````````````````````````````````````
-M``````````````````````````````!@`1````````$``````````P``````
-M```````````````@@$```@``````````````Q!```````````````````"$$
-M````````````````````````````````````````````````````````````
-M`````````````````````&4!$````````0`````````#````````````````
-M````.```````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````0`%```````````````````@``````````@``````````!```
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M``!``D``````````````````$``````````"`````````,<%````````````
-M````````````````````````````````````````````````````````````
-M`````````````````````````````````````````````````````$`#0```
-M````````````````@`````````(``````````(``````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````0`1````````$````
-M``````"``````````@``````````@$``````````````````````````````
-M````````````````````````````````````````````````````````````
-M``````````````````````````````````!`!4````````0``````````(``
-M```````"``````````"`0``"````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M`````````````````````````$`&0``````````````````(``````````(`
-M`````````(@`````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````0`=````````$``````````B``````````@``````````
-MA$``````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M``````!`"$````````0`````````"(`````````"``````````"$0``"````
-M````````````````````````````````````````````````````````````
-M`````````````````````````````````````````````````````````$`)
-M0```````````````````@`````````(`````````QX$`````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````0`M````````$
-M``````````"``````````@````````#'@4``````````````````````````
-M````````````````````````````````````````````````````````````
-M``````````````````````````````````````!0#?\`````````````````
-M````````````````````````````````````````````````````````````
-M``````````````````````````H````````````````````*````````````
-M`````````````````````````````#`*_P````````````````"`````````
-M``,`````````````````````````````````````````````````````````
-M``````````````````$````````````````````!```````````````````$
-M````````````````````,`LP```````````````````!`````````P``````
-M````````````````````````````````````````````````````````````
-M``````"`````````````````````@`````````````````````0`````````
-M```````````P##````````````````````(````````#````````````````
-M`````````````````````````````````````````````````````````!``
-M```````````````````0````````````````````!```````````````````
-M`!`*$```````````````````````````````````````````````````````
-M````````````````````````````````````````````````(```````````
-M`````````"`````````````````````$````````````````````0`I`````
-M`````````````&!X`````````@``````````````````````````````````
-M``````````````````````````````````````!`"@``````````````````
-M0`0```````````````````0```````````````````!0"D``````````````
-M````````````````````````````````````````````````````````````
-M``````````````````````````````@````````````````````(````````
-M````````````!````````````````````)D!,```````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````"`````````````````````@`````````````````
-M```$````````````````````8`#_```````#```````````$````````"```
-M`````````````.`#``````````````#``@``````````````````````````
-M````````````P*\``````````````````/`+``````````````````@`````
-M``````````````!F`/\```````,```````````0````````(````````````
-M````X`,``````````````,`"````````````````````````````````````
-M``#`!P``````````````````\`$`````````````````"```````````````
-M`````&<`_P```````P``````````!`````````@```````````````#@`P``
-M````````````P`(``````````````````````````````````````,`O````
-M``````````````#P"P`````````````````(````````````````````:`#_
-M```````#```````````$````````"````````````````.`#````````````
-M``#``@``````````````````````````````````````P%<`````````````
-M`````/`5``````````````````@```````````````````!A`/\```````,`
-M``````````0````````0````````````````X`,`````````````````````
-M``````````````````````````````````#`KP``````````````````\`L`
-M````````````````"````````````````````&(`_P```````P``````````
-M!````````!````````````````#@`P``````````````P`(`````````````
-M`````````````````````````,"O``````````````````#P"P``````````
-M```````(````````````````````8P#_```````#```````````$````````
-M"````````````````.`!``````````````#``@``````````````````````
-M````````````````P"\``````````````````/`+``````````````````@`
-M``````````````````!D`/\```````,```````````0````````0````````
-M```````(`!P``````````````,`"````````````````````````````````
-M``````#`!P``````````````````\`$`````````````````"```````````
-M`````````&4`_P```````P``````````!````````!````````````````"$
-M"````````````````````````````````````````````````````````,!7
-M``````````````````#P%0`````````````````(````````````````````
-M:0#_```````#```````````$````````$````````````````,`#````````
-M``````#``@``````````````````````````````````````P`<`````````
-M`````````/`!``````````````````@```````````````````!J`/\`````
-M``,```````````0````````0````````````````P`,`````````````````
-M``````````````````````````````````````#`+P``````````````````
-M\`L`````````````````"````````````````````)@!_P``````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````0`#P`/,`B('P`/,`00"``(,`B8&`
-M`(,`2`#R`/4`BH'R`/4`0P#V`/<`BX'V`/<`2@#Q`/0`C('Q`/0`2P"!`(0`
-MC8&!`(0`3`""`(4`CX&"`(4`````````````````B`'P`/,`B0&``(,`B@'R
-M`/4`BP'V`/<`C`'Q`/0`C0&!`(0`CP&"`(4`````````````````````````
-M``````@```````````````````````````````````````````````$"&D,`#8$````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M```````````````````````````````````````````(````````````````
-M```````````````````````````````!`MP%"P"#```````!`LH(#P`$````
-M```!`K@+"@"&`@`````!`I01#@`)`@`````!`G`7"0",!``````!`B@C#0`2
-M!``````!`N`N"``8!``````!`KPT#``;!```````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````!P``````````````````
-M`````````````````````````````0-P%PL`C````````0/@+@H`F`(`````
-M`0-01@X`)`(``````0/`70D`L`,``````0.@C`T`2`,``````0.`NP@`8`,`
-M`````0/PT@P`;`,`````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M``````````````````````````````````````@`````````````````````
-M``````````````````````````$#&!HP%C02.`X\"````````
-M`!0``````````0`!>!`,!PB0`0```````!P````<``````````````!L````
-M`````$$.$(,"````%````#P``````````````$0`````````%````%0`````
-M`````````"4`````````+````&P``````````````)X"````````0@X00@X8
-M00X@00XH1`XP@P6&!(P#C0(`)````)P``````````````.0`````````0@X0
-M00X800X@@P2&`XP"`!P```#$``````````````!C`@```````$0.$```````
-M/````.0``````````````(@$````````0@X00@X80@X@0@XH00XP00XX1PZ0
-M`X,'A@:,!8T$C@./`@```````"0````D`0````````````!$`````````$$.
-M$$$.&$0.((,#A@(````4````3`$`````````````:0`````````\````9`$`
-M````````````(`8```````!"#A!"#AA"#B!"#BA!#C!!#CA$#H`!@P>&!HP%
-MC02.`X\"````````'````*0!`````````````-P`````````00X0@P(````\
-M````Q`$`````````````:@$```````!"#A!"#AA"#B!"#BA!#C!!#CA$#DB#
-M!X8&C`6-!(X#CP(`````````/`````0"`````````````/$!````````0@X0
-M0@X80@X@0@XH00XP00XX1`Y`@P>&!HP%C02.`X\"`````````#P```!$`@``
-M```````````G`P```````$(.$$(.&$(.($(.*$$.,$$..$0.4(,'A@:,!8T$
-MC@./`@`````````\````A`(`````````````50(```````!"#A!"#AA"#B!"
-M#BA!#C!!#CA$#E"#!X8&C`6-!(X#CP(`````````/````,0"````````````
-M``\$````````0@X00@X80@X@0@XH00XP00XX1`Y0@P>&!HP%C02.`X\"````
-M`````#0````$`P`````````````O#@```````$(.$$(.&$(.($$.*$$.,$0.
-M0(,&A@6,!(T#C@(`````'````#P#`````````````'P`````````1`X@2H8"
-M@P,<````7`,`````````````'`````````!$#A```````!0``````````0`!
-M>!`,!PB0`0```````!0````<```````````````H`````````!0````T````
-M```````````-`````````!0```!,```````````````B`````````!P```!D
-M``````````````!K`````````$0.$```````'````(0``````````````'4`
-M````````00X0@P(````D````I```````````````=P````````!$#B!.C`*&
-M`X,$````````)````,P``````````````),`````````1PZP`6"-`HP#A@2#
-M!0```!P```#T``````````````!#`````````$$.$(,"````%````!0!````
-M`````````#8`````````)````"P!`````````````',`````````00X000X8
-M1`X@@P.&`@```!P```!4`0````````````!2`````````$0.$```````%```
-M`'0!`````````````#@`````````/````(P!`````````````+L!````````
-M0@X00@X80@X@0@XH00XP00XX1`Y0@P>&!HP%C02.`X\"`````````!0```#,
-M`0`````````````M`````````!0```#D`0`````````````P`````````"P`
-M``#\`0`````````````I!P```````$<.\`-PCP*.`XT$C`6&!H,'````````
-M`!P````L`@````````````"Y`````````$$.$(,"````'````$P"````````
-M`````"L`````````00X0@P(````D````;`(`````````````]`````````!$
-M#B!.C`*&`X,$````````'````)0"`````````````"4`````````1`X0````
-M```\````M`(`````````````AP````````!"#A!"#AA"#B!"#BA!#C!!#CA$
-M#E"#!X8&C`6-!(X#CP(`````````'````/0"`````````````)0`````````
-M1`X@2H8"@P,<````%`,`````````````=P````````!!#A"#`@```"P````T
-M`P````````````"$`````````$(.$$$.&$$.($0.,(,$A@.,`@```````"P`
-M``!D`P````````````"$`````````$(.$$$.&$$.($0.,(,$A@.,`@``````
-M`!P```"4`P````````````!<`````````$0.($J&`H,#%``````````!``%X
-M$`P'")`!````````/````!P``````````````"\&````````0@X00@X80@X@
-M0@XH00XP00XX1P[@`8,'A@:,!8T$C@./`@```````!P```!<````````````
-M```.`````````$0.$```````%````'P``````````````!T`````````%```
-M`)0```````````````8`````````%````*P``````````````&L`````````
-M%``````````!``%X$`P'")`!````````%````!P``````````````$$`````
-M````'````#0``````````````&0`````````1`XP```````4````5```````
-M````````-P`````````4````;```````````````ZP`````````4````````
-M``$``7@0#`<(D`$````````4````'```````````````$P`````````4````
-M-```````````````6P`````````4````3```````````````!P`````````4
-M````9```````````````A``````````4``````````$``7@0#`<(D`$`````
-M```4````'```````````````!@`````````4````-```````````````+@``
-M```````4````3```````````````F0`````````4````9```````````````
-MAP`````````D````?```````````````J@$```````!$#C!4C0*,`X8$@P4`
-M````%``````````!``%X$`P'")`!````````'````!P``````````````"``
-M````````1`X0```````<````/```````````````'P````````!$#A``````
-M`!P```!<```````````````=`````````$0.$```````%````'P`````````
-M``````8`````````'````)0``````````````&,`````````1`X@2H8"@P,4
-M````M```````````````,0`````````4````S```````````````!@``````
-M```D````Y```````````````6@````````!$#B!.C0*,`X,$````````%```
-M``P!`````````````"T`````````%````"0!`````````````"0`````````
-M%````#P!`````````````"P`````````%````%0!`````````````!\`````
-M````'````&P!`````````````&<`````````1`X0```````4````C`$`````
-M````````,P`````````4````I`$`````````````&``````````4````O`$`
-M````````````+@`````````4````U`$`````````````!@`````````4````
-M[`$`````````````"0`````````D````!`(`````````````K`````````!!
-M#A!!#AA$#B"#`X8"````%````"P"`````````````"@`````````%````$0"
-M``````````````L`````````%````%P"`````````````!8`````````%```
-M`'0"`````````````#4`````````%````(P"`````````````"$`````````
-M%````*0"`````````````$$`````````)````+P"`````````````'(`````
-M````1`X@3HP"A@.#!````````!P```#D`@`````````````>`````````$0.
-M$```````)`````0#`````````````)<`````````1`XP6(X"C0.,!(8%@P8`
-M`!P````L`P`````````````>`````````$0.$```````%````$P#````````
-M``````X`````````%````&0#`````````````$H`````````)````'P#````
-M`````````)H`````````1`XP6(X"C0.,!(8%@P8``!P```"D`P``````````
-M```A`````````$0.$```````%````,0#``````````````8`````````%```
-M`-P#``````````````$`````````%````/0#``````````````8`````````
-M%`````P$``````````````$`````````%````"0$``````````````$`````
-M````'````#P$`````````````"0`````````1`X0```````<````7`0`````
-M````````.P````````!$#A```````!P```!\!``````````````.````````
-M`$0.$```````%``````````!``%X$`P'")`!````````%````!P`````````
-M`````"\`````````)````#0``````````````),`````````00X000X81`X@
-M@P.&`@```!0```!<```````````````O`````````"0```!T````````````
-M``!O`````````$0.($Z,`H8#@P0````````4````G```````````````$P``
-M```````4``````````$``7@0#`<(D`$````````<````'```````````````
-M,0````````!!#A"#`@```!0``````````0`!>!`,!PB0`0```````!0````<
-M```````````````(`````````!0````T```````````````(`````````!0`
-M``!,```````````````,`````````"0```!D``````````````!+````````
-M`$$.$$$.&$0.((,#A@(````4````C```````````````%``````````4````
-MI```````````````%``````````4````O```````````````%0`````````4
-M````U```````````````4@`````````4````[```````````````4@``````
-M```4````!`$`````````````"P`````````4````'`$`````````````'```
-M```````4````-`$`````````````.P`````````4````3`$`````````````
-M'@$````````4``````````$``7@0#`<(D`$````````\````'```````````
-M````]@4```````!"#A!"#AA"#B!"#BA!#C!!#CA$#D"#!X8&C`6-!(X#CP(`
-M````````%````%P``````````````'0`````````'````'0`````````````
-M`!0`````````1`X0```````<````E```````````````&`````````!$#A``
-M`````!P```"T``````````````!F`````````$$.$(,"````'````-0`````
-M`````````-H`````````1`X@2H8"@P,\````]```````````````(P(`````
-M``!"#A!"#AA"#B!"#BA!#C!!#CA$#E"#!X8&C`6-!(X#CP(`````````)```
-M`#0!`````````````'0`````````1`X@3HP"A@.#!````````!0```!<`0``
-M``````````"M`````````!P```!T`0````````````#E`````````$$.$(,"
-M````%````)0!`````````````!@`````````/````*P!`````````````.@"
-M````````0@X00@X80@X@0@XH00XP00XX1`Y`@P>&!HP%C02.`X\"````````
-M`"P```#L`0````````````#*`@```````$(.$$$.&$$.($0.D`&#!(8#C`(`
-M`````!P````<`@````````````!T`````````$0.($J,`H,#%````#P"````
-M`````````!P`````````)````%0"`````````````(8`````````0@X000X8
-M00X@@P2&`XP"`!0```!\`@`````````````&`````````!0```"4`@``````
-M```````&`````````!0``````````0`!>!`,!PB0`0```````!P````<````
-M```````````M`````````$0.$```````'````#P``````````````#,`````
-M````1`X0```````D````7```````````````W0````````!$#C!8C@*-`XP$
-MA@6#!@``%````(0``````````````%X`````````%````)P`````````````
-M`&`"````````%````+0``````````````"D`````````%````,P`````````
-M`````$$`````````)````.0``````````````)(`````````1`X@3HP"A@.#
-M!````````!0````,`0````````````!G`````````!0````D`0``````````
-M```R`````````"0````\`0````````````"8`````````$$.$$$.&$0.((,#
-MA@(````4````9`$`````````````KP`````````4````?`$`````````````
-M!@`````````4````E`$`````````````"``````````4````K`$`````````
-M````2@`````````4````Q`$`````````````CP`````````4````W`$`````
-M`````````0`````````4``````````$``7@0#`<(D`$````````4````'```
-M````````````"@`````````4``````````$``7@0#`<(D`$````````<````
-M'```````````````6P````````!$#A```````#P````\``````````````"C
-M!````````$(.$$(.&$(.($(.*$$.,$$..$0.4(,'A@:,!8T$C@./`@``````
-M```<````?```````````````&@````````!!#A"#`@```!P```"<````````
-M``````#W`````````$$.$$0.,(,"%````+P``````````````#@`````````
-M%````-0```````````````8`````````+````.P``````````````/0`````
-M````0@X00@X800X@00XH1`XP@P6&!(P#C0(`%``````````!``%X$`P'")`!
-M````````%````!P``````````````$$`````````'````#0`````````````
-M`'``````````1`XP```````4````5```````````````-P`````````4````
-M;```````````````[@`````````4``````````$``7@0#`<(D`$````````4
-M````'```````````````$P`````````4````-```````````````K```````
-M```4````3```````````````!P`````````4````9```````````````G@``
-M```````4``````````$``7@0#`<(D`$````````4````'```````````````
-M!@`````````4````-```````````````+@`````````4````3```````````
-M````F0`````````4````9```````````````AP`````````L````?```````
-M````````MP$```````!"#A!"#AA!#B!!#BA$#C"#!88$C`.-`@`4````````
-M``$``7@0#`<(D`$````````<````'```````````````(`````````!$#A``
-M`````!P````\```````````````?`````````$0.$```````'````%P`````
-M`````````!T`````````1`X0```````4````?```````````````!@``````
-M```<````E```````````````;0````````!$#B!*A@*#`Q0```"T````````
-M```````Q`````````!0```#,```````````````Q`````````"0```#D````
-M``````````!X`````````$0.($Z-`HP#@P0````````4````#`$`````````
-M````(@`````````4````)`$`````````````)``````````4````/`$`````
-M````````+``````````4````5`$`````````````'P`````````<````;`$`
-M````````````0P````````!$#A```````!0```",`0`````````````@````
-M`````!P```"D`0````````````"1`````````$0.($J&`H,#%````,0!````
-M`````````"@`````````%````-P!``````````````L`````````%````/0!
-M`````````````!8`````````%`````P"`````````````#4`````````%```
-M`"0"`````````````#4`````````%````#P"`````````````$$`````````
-M)````%0"`````````````&X`````````1`X@3HP"A@.#!````````!P```!\
-M`@`````````````>`````````$0.$```````)````)P"`````````````)<`
-M````````1`XP6(X"C0.,!(8%@P8``!P```#$`@`````````````>````````
-M`$0.$```````%````.0"``````````````X`````````%````/P"````````
-M`````$H`````````)````!0#`````````````)H`````````1`XP6(X"C0.,
-M!(8%@P8``!P````\`P`````````````A`````````$0.$```````%````%P#
-M``````````````8`````````%````'0#``````````````$`````````%```
-M`(P#``````````````8`````````%````*0#``````````````$`````````
-M%````+P#``````````````$`````````%````-0#`````````````!``````
-M````%````.P#``````````````X`````````%`````0$``````````````X`
-M````````%````!P$``````````````<`````````'````#0$````````````
-M`"<`````````1`X0```````<````5`0`````````````*0````````!$#A``
-M`````!P```!T!``````````````O`````````$0.$```````'````)0$````
-M`````````!8`````````1`X0```````4``````````$``7@0#`<(D`$`````
-M```D````'```````````````DP````````!!#A!!#AA$#B"#`X8"````%```
-M`$0``````````````"\`````````%````%P``````````````"\`````````
-M)````'0``````````````&\`````````1`X@3HP"A@.#!````````!0```"<
-M```````````````3`````````!0``````````0`!>!`,!PB0`0```````!P`
-M```<``````````````!(`````````$$.$(,"````%``````````!``%X$`P'
-M")`!````````%````!P```````````````@`````````%````#0`````````
-M``````@`````````%````$P```````````````P`````````'````&0`````
-M`````````#``````````1`X0```````4````A```````````````%```````
-M```4````G```````````````%``````````4````M```````````````%0``
-M```````4````S```````````````4@`````````4````Y```````````````
-M4@`````````4````_```````````````"P`````````4````%`$`````````
-M````"P`````````4````+`$`````````````.P`````````4````1`$`````
-M````````VP`````````4``````````$``7@0#`<(D`$````````\````'```
-M````````````H`@```````!"#A!"#AA"#B!"#BA!#C!!#CA$#K`!@P>&!HP%
-MC02.`X\"````````'````%P``````````````!,`````````1`X0```````<
-M````?```````````````10````````!!#A"#`@```!P```"<````````````
-M``"I`0```````$0.($J&`H,#)````+P``````````````&,!````````1`XP
-M6(X"C0.,!(8%@P8``"0```#D``````````````!Y`````````$0.($Z,`H8#
-M@P0````````L````#`$``````````````0$```````!"#A!"#AA!#B!!#BA$
-M#C"#!88$C`.-`@`4````/`$`````````````'``````````D````5`$`````
-M````````I0````````!"#A!!#AA!#B"#!(8#C`(`%````'P!````````````
-M`$\`````````'````)0!`````````````&4`````````1`X@2H8"@P,D````
-MM`$`````````````MP````````!$#C!/C`*&`X,$````````%````-P!````
-M`````````$4`````````/````/0!`````````````$8#````````0@X00@X8
-M0@X@0@XH00XP00XX1`Z``8,'A@:,!8T$C@./`@```````!0````T`@``````
-M```````/`0```````#0```!,`@````````````!L`@```````$(.$$(.&$(.
-M($$.*$$.,(,&A@6,!(T#C@(`````````%````(0"`````````````"(`````
-M````/````)P"`````````````(`!````````0@X00@X80@X@0@XH00XP00XX
-M1`Y@@P>&!HP%C02.`X\"`````````#P```#<`@````````````!2`P``````
-M`$(.$$(.&$(.($(.*$$.,$$..$0.4(,'A@:,!8T$C@./`@`````````\````
-M'`,`````````````6P0```````!"#A!"#AA"#B!"#BA!#C!!#CA$#J`!@P>&
-M!HP%C02.`X\"````````)````%P#`````````````'(!````````1`Y`5(T"
-MC`.&!(,%`````!0```"$`P````````````!@`````````!P```"<`P``````
-M``````"E`````````$$.$(,"````%````+P#`````````````)T`````````
-M'````-0#`````````````$,`````````1`X0```````4````]`,`````````
-M````0@`````````4````#`0`````````````=P`````````4````)`0`````
-M````````)@`````````D````/`0`````````````J0````````!$#B!.C`*&
-M`X,$````````%````&0$`````````````!@`````````%````'P$````````
-M`````!8!````````%````)0$`````````````$(`````````%````*P$````
-M`````````&8`````````'````,0$`````````````!0`````````1`X0````
-M```4``````````$``7@0#`<(D`$````````D````'```````````````J0``
-M``````!$#B!.C`*&`X,$````````'````$0``````````````"T`````````
-M1`X0```````<````9```````````````,P````````!$#A```````"0```"$
-M``````````````#T`````````$0.,%B.`HT#C`2&!8,&```4````K```````
-M````````<``````````<````Q```````````````<0````````!$#A``````
-M`!P```#D``````````````#%`P```````$0.$```````%`````0!````````
-M``````\`````````%````!P!`````````````!0`````````%````#0!````
-M`````````!D`````````%````$P!`````````````#$`````````)````&0!
-M`````````````&0`````````0@X000X800X@@P2&`XP"`!0```",`0``````
-M``````"0`````````!0```"D`0`````````````&`````````!0```"\`0``
-M```````````(`````````!0```#4`0````````````!*`````````!0```#L
-M`0````````````"V`````````!0````$`@`````````````!`````````!0`
-M`````````0`!>!`,!PB0`0```````!0````<```````````````O````````
-M`!0``````````0`!>!`,!PB0`0```````!0````<``````````````"-````
-M`````!P````T``````````````!;`````````$0.$```````'````%0`````
-M`````````/4`````````1PZ0`0`````4````=```````````````$@``````
-M```T````C```````````````\`````````!"#A!"#AA"#B!"#BA!#C"#!HP%
-MC02.`X\"`````````!0```#$``````````````!%`````````#P```#<````
-M``````````"9!@```````$(.$$(.&$(.($(.*$$.,$$..$0.0(,'A@:,!8T$
-MC@./`@`````````<````'`$`````````````3P````````!!#A"#`@```!P`
-M```\`0````````````#W`````````$$.$$0.,(,"%````%P!````````````
-M`$$`````````+````'0!```````````````$````````0@X00@X800X@00XH
-M1`XP@P6&!(P#C0(`'````*0!`````````````!8`````````1`X0```````4
-M````Q`$`````````````'0`````````4``````````$``7@0#`<(D`$`````
-M```<````'```````````````CP````````!$#B!*A@*#`QP````\````````
-M``````!P`````````$0.,```````%````%P``````````````#<`````````
-M%````'0``````````````$(!````````%``````````!``%X$`P'")`!````
-M````'````!P``````````````&T`````````1`X@2H8"@P,4``````````$`
-M`7@0#`<(D`$````````4````'```````````````(@`````````4````-```
-M````````````)``````````4````3```````````````+``````````4````
-M9```````````````'P`````````<````?```````````````8P````````!$
-M#A```````!0``````````0`!>!`,!PB0`0```````!0````<````````````
-M```4`````````!0````T``````````````!S`0```````!0```!,````````
-M```````'`````````!0```!D```````````````-`0```````!0`````````
-M`0`!>!`,!PB0`0```````!0````<```````````````(`````````!0````T
-M```````````````Q`````````!0```!,``````````````#V`````````!0`
-M``!D``````````````"+`````````#P```!\``````````````"P`P``````
-M`$(.$$(.&$(.($(.*$$.,$$..$0.4(,'A@:,!8T$C@./`@`````````4````
-M``````$``7@0#`<(D`$````````<````'```````````````(`````````!$
-M#A```````!P````\```````````````?`````````$0.$```````'````%P`
-M`````````````"``````````1`X0```````<````?```````````````;@``
-M``````!!#A"#`@```!0```"<```````````````Q`````````!0```"T````
-M``````````!9`````````"0```#,``````````````"#`````````$0.($Z,
-M`H8#@P0````````4````]```````````````(``````````<````#`$`````
-M````````D0````````!$#B!*A@*#`Q0````L`0`````````````H````````
-M`!0```!$`0`````````````+`````````!0```!<`0`````````````@````
-M`````!0```!T`0````````````!W`````````!0```",`0`````````````U
-M`````````!0```"D`0`````````````U`````````!0```"\`0``````````
-M``!!`````````!0```#4`0`````````````&`````````!0```#L`0``````
-M```````0`````````!0````$`@`````````````.`````````!0````<`@``
-M```````````.`````````!0````T`@`````````````'`````````!P```!,
-M`@`````````````G`````````$0.$```````%````&P"``````````````8`
-M````````)````(0"`````````````'(`````````1`X@3HP"A@.#!```````
-M`!P```"L`@`````````````>`````````$0.$```````)````,P"````````
-M`````)<`````````1`XP6(X"C0.,!(8%@P8``!P```#T`@`````````````>
-M`````````$0.$```````%````!0#``````````````X`````````%````"P#
-M`````````````$H`````````)````$0#`````````````)H`````````1`XP
-M6(X"C0.,!(8%@P8``!P```!L`P`````````````A`````````$0.$```````
-M%````(P#`````````````$$`````````'````*0#`````````````"`@``````
-M`$$.$(,"````'````!P$`````````````.L`````````00X0@P(````4````
-M/`0`````````````,0`````````<````5`0`````````````80(```````!$
-M#B!*A@*#`QP```!T!`````````````"1`0```````$0.$```````'````)0$
-M`````````````!8`````````1`X0```````4``````````$``7@0#`<(D`$`
-M```````D````'```````````````DP````````!!#A!!#AA$#B"#`X8"````
-M%````$0``````````````#0`````````%````%P``````````````#0`````
-M````)````'0``````````````&\`````````1`X@3HP"A@.#!````````!0`
-M``"<```````````````3`````````!0``````````0`!>!`,!PB0`0``````
-M`!P````<``````````````#;`````````$$.$(,"````%``````````!``%X
-M$`P'")`!````````%````!P```````````````@`````````%````#0`````
-M``````````@`````````%````$P```````````````P`````````'````&0`
-M`````````````#``````````1`X0```````<````A```````````````*P``
-M``````!!#A"#`@```!P```"D```````````````A`````````$0.$```````
-M%````,0``````````````!4`````````%````-P``````````````%(`````
-M````%````/0``````````````%(`````````%`````P!`````````````"H`
-M````````%````"0!`````````````%H`````````%````#P!````````````
-M`#``````````'````%0!`````````````!$!````````1`X0```````4````
-M``````$``7@0#`<(D`$````````\````'```````````````30T```````!"
-M#A!"#AA"#B!"#BA!#C!!#CA$#H`!@P>&!HP%C02.`X\"````````%````%P`
-M`````````````&``````````'````'0``````````````!<`````````1`X0
-M```````\````E```````````````*0(```````!"#A!"#AA"#B!"#BA!#C!!
-M#CA$#D"#!X8&C`6-!(X#CP(`````````%````-0``````````````',`````
-M````'````.P``````````````!,`````````1`X0```````<````#`$`````
-M````````+P````````!!#A"#`@```"0````L`0````````````!0`@``````
-M`$0.,%2-`HP#A@2#!0`````T````5`$`````````````F@(```````!"#A!"
-M#AA"#B!!#BA!#C"#!H8%C`2-`XX"`````````"0```",`0````````````"\
-M`````````$0.($Z,`H8#@P0````````4````M`$`````````````'```````
-M```4````S`$`````````````3P`````````D````Y`$`````````````>0``
-M``````!$#C!/C`*&`X,$````````%`````P"`````````````(0`````````
-M+````"0"`````````````*L`````````0@X00@X800X@00XH1`XP@P6&!(P#
-MC0(`%````%0"`````````````#8!````````'````&P"`````````````'T`
-M````````00X0@P(````\````C`(`````````````4`0```````!"#A!"#AA"
-M#B!"#BA!#C!!#CA$#E"#!X8&C`6-!(X#CP(`````````/````,P"````````
-M`````,@%````````0@X00@X80@X@0@XH00XP00XX1`Z``8,'A@:,!8T$C@./
-M`@```````!0````,`P````````````#&`````````!P````D`P``````````
-M```L`````````$0.$```````+````$0#`````````````#4#````````0@X0
-M0@X800X@00XH1`Y`@P6&!(P#C0(`/````'0#`````````````'(%````````
-M0@X00@X80@X@0@XH00XP00XX1P[P`8,'A@:,!8T$C@./`@```````#P```"T
-M`P````````````#N`````````$(.$$(.&$(.($(.*$$.,$$..$0.4(,'A@:,
-M!8T$C@./`@`````````L````]`,`````````````)P$```````!"#A!!#AA!
-M#B!$#D"#!(8#C`(````````L````)`0`````````````I@````````!"#A!!
-M#AA!#B!$#D"#!(8#C`(````````<````5`0`````````````AP````````!!
-M#A"#`@```#P```!T!`````````````!8`0```````$(.$$(.&$(.($(.*$$.
-M,$$..$0.8(,'A@:,!8T$C@./`@`````````4````M`0`````````````>P``
-M```````4````S`0`````````````?P`````````<````Y`0`````````````
-M\@````````!!#A"#`@```!0````$!0`````````````M`````````"0````<
-M!0`````````````C`0```````$0.($Z,`H8#@P0````````4````1`4`````
-M````````&``````````4````7`4`````````````^P`````````D````=`4`
-M````````````N`````````!$#B!.C`*&`X,$````````+````)P%````````
-M`````+D`````````0@X00@X800X@00XH1`XP@P6&!(P#C0(`/````,P%````
-M`````````&P!````````0@X00@X80@X@0@XH00XP00XX1`Y`@P>&!HP%C02.
-M`X\"`````````!0````,!@````````````"@`````````!0``````````0`!
-M>!`,!PB0`0```````"0````<``````````````"M`````````$0.,%2-`HP#
-MA@2#!0`````<````1```````````````-P````````!$#A```````!P```!D
-M```````````````]`````````$0.$```````/````(0``````````````%0!
-M````````0@X00@X80@X@0@XH00XP00XX1`Y`@P>&!HP%C02.`X\"````````
-M`!0```#$``````````````!P`````````!P```#<``````````````!Y````
-M`````$0.$```````'````/P``````````````-<#````````00X0@P(````4
-M````'`$`````````````#P`````````4````-`$`````````````%```````
-M```4````3`$`````````````&0`````````4````9`$`````````````,0``
-M```````L````?`$`````````````;@$```````!"#A!"#AA!#B!!#BA$#C"#
-M!88$C`.-`@`4````K`$`````````````.0$````````4````Q`$`````````
-M````9P`````````4````W`$`````````````"``````````4````]`$`````
-M````````:0`````````4````#`(`````````````0@$````````4````)`(`
-M````````````$P`````````4``````````$``7@0#`<(D`$````````<````
-M'```````````````50````````!!#A"#`@```!P````\```````````````Y
-M`````````$$.$(,"````%````%P``````````````%4`````````%````'0`
-M``````````````@`````````'````(P``````````````!D`````````00X0
-M@P(````D````K```````````````-P$```````!"#A!!#AA!#B"#!(8#C`(`
-M'````-0``````````````#``````````00X0@P(````D````]```````````
-M````Q`0```````!'#I`!388"@P,`````````'````!P!`````````````*<`
-M````````00X0@P(````<````/`$`````````````&`$```````!$#B!*A@*#
-M`QP```!<`0````````````"H`````````$0.($J&`H,#+````'P!````````
-M`````!4"````````0@X00@X800X@00XH1`XP@P6&!(P#C0(`)````*P!````
-M`````````-$`````````0@X000X800X@@P2&`XP"`!P```#4`0``````````
-M``!/`````````$$.$(,"````'````/0!`````````````(8`````````1`X0
-M```````4````%`(`````````````>``````````D````+`(`````````````
-M"0(```````!$#C!4C0*,`X8$@P4`````%``````````!``%X$`P'")`!````
-M````%````!P``````````````$T`````````%``````````!``%X$`P'")`!
-M````````/````!P``````````````-\`````````0@X00@X80@X@0@XH00XP
-M00XX1`Y`@P>&!HP%C02.`X\"`````````"P```!<```````````````N`0``
-M`````$(.$$(.&$$.($$.*$0.,(,%A@2,`XT"`!0```",```````````````[
-M`````````#P```"D```````````````$!@```````$(.$$(.&$(.($(.*$$.
-M,$$..$0.L`&#!X8&C`6-!(X#CP(````````<````Y```````````````AP``
-M``````!!#A"#`@```#P````$`0````````````"R`P```````$(.$$(.&$(.
-M($(.*$$.,$$..$<.@`.#!X8&C`6-!(X#CP(````````D````1`$`````````
-M````8`$```````!$#D!4C0*,`X8$@P4`````%````&P!`````````````&@`
-M````````'````(0!`````````````$,`````````1`X0```````<````I`$`
-M````````````2`````````!!#A"#`@```!0```#$`0`````````````&````
-M`````!0```#<`0`````````````Q`````````!P```#T`0````````````#$
-M`````````$0.($J&`H,#%``````````!``%X$`P'")`!````````/````!P`
-M`````````````-\`````````0@X00@X80@X@0@XH00XP00XX1`Y`@P>&!HP%
-MC02.`X\"`````````#0```!<``````````````#@`@```````$(.$$(.&$(.
-M($$.*$$.,(,&A@6,!(T#C@(`````````%````)0``````````````#8`````
-M````/````*P``````````````'`'````````0@X00@X80@X@0@XH00XP00XX
-M1`Y@@P>&!HP%C02.`X\"`````````#P```#L``````````````#G!@``````
-M`$(.$$(.&$(.($(.*$$.,$$..$<.X`B#!X8&C`6-!(X#CP(````````4````
-M+`$`````````````/0`````````4````1`$`````````````<0`````````\
-M````7`$`````````````R`````````!"#A!"#AA"#B!"#BA!#C!!#CA$#D"#
-M!X8&C`6-!(X#CP(`````````%````)P!`````````````+8`````````)```
-M`+0!`````````````/L`````````0@X000X800X@@P2&`XP"`!P```#<`0``
-M``````````!(`````````$$.$(,"````%````/P!`````````````(4`````
-M````/````!0"`````````````/,!````````0@X00@X80@X@0@XH00XP00XX
-M1`Y`@P>&!HP%C02.`X\"`````````#P```!4`@````````````!X````````
-M`$(.$$(.&$(.($(.*$$.,$$..$0.0(,'A@:,!8T$C@./`@`````````<````
-ME`(`````````````S@````````!$#B!*A@*#`Q0``````````0`!>!`,!PB0
-M`0```````#P````<``````````````#B`````````$(.$$(.&$(.($(.*$$.
-M,$$..$0.0(,'A@:,!8T$C@./`@`````````T````7```````````````X`(`
-M``````!"#A!"#AA"#B!!#BA!#C"#!H8%C`2-`XX"`````````#P```"4````
-M``````````"B`@```````$(.$$(.&$(.($(.*$$.,$$..$0.0(,'A@:,!8T$
-MC@./`@`````````4````U```````````````,P`````````4````[```````
-M````````?0`````````\````!`$`````````````(P$```````!"#A!"#AA"
-M#B!"#BA!#C!!#CA$#E"#!X8&C`6-!(X#CP(`````````%````$0!````````
-M`````#T`````````/````%P!`````````````/$$````````0@X00@X80@X@
-M0@XH00XP00XX1`Z``8,'A@:,!8T$C@./`@```````#0```"<`0``````````
-M``"*`0```````$(.$$(.&$(.($$.*$$.,$0.4(,&A@6,!(T#C@(`````'```
-M`-0!`````````````&D`````````00X0@P(````4````]`$`````````````
-M+P`````````4````#`(`````````````+P`````````\````)`(`````````
-M````(`(```````!"#A!"#AA"#B!"#BA!#C!!#CA$#F"#!X8&C`6-!(X#CP(`
-M````````/````&0"`````````````'@`````````0@X00@X80@X@0@XH00XP
-M00XX1`Y`@P>&!HP%C02.`X\"`````````!P```"D`@````````````#:````
-M`````$0.($J&`H,#%``````````!``%X$`P'")`!````````/````!P`````
-M`````````-\`````````0@X00@X80@X@0@XH00XP00XX1`Y`@P>&!HP%C02.
-M`X\"`````````#0```!<``````````````"T`@```````$(.$$(.&$(.($$.
-M*$$.,(,&A@6,!(T#C@(`````````/````)0```````````````H$````````
-M0@X00@X80@X@0@XH00XP00XX1`Y`@P>&!HP%C02.`X\"`````````!0```#4
-M```````````````V`````````!0```#L``````````````!]`````````#P`
-M```$`0`````````````C`0```````$(.$$(.&$(.($(.*$$.,$$..$0.4(,'
-MA@:,!8T$C@./`@`````````4````1`$`````````````/0`````````\````
-M7`$`````````````\00```````!"#A!"#AA"#B!"#BA!#C!!#CA$#H`!@P>&
-M!HP%C02.`X\"````````-````)P!`````````````(L!````````0@X00@X8
-M0@X@00XH00XP1`Y0@P:&!8P$C0..`@`````<````U`$`````````````:0``
-M``````!!#A"#`@```!0```#T`0`````````````O`````````!0````,`@``
-M```````````O`````````#P````D`@`````````````'`@```````$(.$$(.
-M&$(.($(.*$$.,$$..$0.4(,'A@:,!8T$C@./`@`````````\````9`(`````
-M````````>`````````!"#A!"#AA"#B!"#BA!#C!!#CA$#D"#!X8&C`6-!(X#
-MCP(`````````'````*0"`````````````-H`````````1`X@2H8"@P,`````
-M````````````````````````````1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H
-M1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N
-M-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H
-M1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N
-M-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H
-M1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N
-M-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H
-M1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N
-M-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H
-M1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N
-M-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H
-M1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N
-M-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H
-M1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N
-M-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H
-M1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N
-M-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H
-M1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N
-M-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H
-M1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N
-M-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H1TY5*2`S+C,N-```1T-#.B`H
-M1TY5*2`S+C,N-```+G-Y;71A8@`N````
-M`````````````````0`````````!`````````$<````!`````P``````````
-M`````````&`Z`@``````!%<``````````````````"``````````````````
-M``!"````!``````````````````````````HD@,``````*@`````````#@``
-M``8````(`````````!@`````````4@````$````"````````````````````
-M:)$"```````@20``````````````````"````````````````````$T````$
-M`````````````````````````-"2`P``````<#(````````.````"`````@`
-M````````&`````````!<````"`````,```````````````````"@V@(`````
-M`+`!```````````````````@````````````````````80````$`````````
-M````````````````H-H"``````"H`P```````````````````0``````````
-M`````````&H````'`````````````````````````$C>`@``````````````
-M``````````````$````````````````````1`````P``````````````````
-M``````!(W@(``````'H````````````````````!````````````````````
-M`0````(`````````````````````````R.("``````!`)@````````\````)
-M````"``````````8``````````D````#``````````````````````````@)
-M`P``````Q1$```````````````````$`````````````````````````````
-M`````````````````````````````P`!````````````````````````````
-M`P`#`````````````````````````````P`%````````````````````````
-M`````P`&`````````````````````````````P`*````````````````````
-M`````````P`(`````````````````````````````P`+````````````````
-M`````````````P`,```````````````````````!````$@`!`&V(````````
-M<``````````,````$@`!`!5Y````````!@`````````7````$@`!`#OS````
-M````D0$````````B````$@`!`'E?````````EP`````````M````$@`!`!P(
-M`0``````*0(````````X````$@`!`+C)````````+P````````!#````$@`!
-M`+,2`0``````-@$```````!.````$@`!`)15````````ZP````````!9````
-M$@`!`*-,`0``````T0````````!D````$0`&`,`]````````I`$```````!O
-M````$@`!`+?W````````(0````````!Z````$@`!`()7````````+@``````
-M``"%````$@`!`-Q)````````]`````````"0````$0`&`&!.````````I`$`
-M``````";````$@`!`'[M````````(@````````"F````$@`!`$KI````````
-M$`````````"Q````$@`!`-C?````````"`````````"\````$@`!``#)````
-M````M@````````#'````$@`!`/33````````]P````````#2````$@`!`)T(
-M````````;P````````#=````$@`!`!&^````````J0````````#H````$@`!
-M`,^H````````MP````````#S````$@`!`.63````````2@````````#^````
-M$@`!`("7````````"``````````)`0``$@`!`!=]````````*0`````````4
-M`0``$@`!`*GP````````,0`````````?`0``$@`!`*C(````````!@``````
-M```J`0``$@`!`#S=````````%``````````U`0``$@`!`$4*`0``````````````(0`````````L`@``$@`!`*Z0````
-M````0P`````````W`@``$@`!`"^4````````F@````````!"`@``$@`!`'K!
-M````````,P````````!-`@``$@`!`+..````````'0````````!8`@``$@`!
-M`/WJ````````2@````````!C`@``$@`!``&`````````2@````````!N`@``
-M$@`!`"-<````````+`````````!Y`@``$@`!`$EY````````,P````````"$
-M`@``$@`!`*/E````````;@````````"/`@``$@`!`'R5````````+P``````
-M``":`@``$@`!`-'J````````'@````````"E`@``$@`!`*KI````````<@``
-M``````"P`@``$@`!`'7*````````6P````````"[`@``$@`!`,L*`0``````
-M+P````````#&`@``$@`!`'Q7````````!@````````#1`@``$@`!`$?K````
-M````F@````````#<`@``$@`!`.Q-````````+P8```````#G`@``$@`!`"R5
-M````````)P````````#R`@``$@`!`,_G````````*`````````#]`@``$@`!
-M`%P"````````40`````````(`P``$@`!`!SJ````````'@`````````3`P``
-M$@`!`,HN`0``````(P$````````>`P``$@`!`&K<````````)``````````I
-M`P``$@`!`(01`0``````A``````````T`P``$@`!`#Q>````````%@``````
-M```_`P``$@`!`)R+````````F0````````!*`P``$@`!`*6/````````>```
-M``````!5`P``$@`!`&UX````````'`````````!@`P``$@`!`(`T`0``````
-MK0````````!K`P``$@`!``9N````````(P(```````!V`P``$@`!`$YA````
-M`````0````````"!`P``$@`!`"TU`0``````-P````````",`P``$@`!`+=Z
-M````````8`(```````"7`P``$@`!`$,!````````#0$```````"F`P``$@`!
-M`'`?`0``````-0,```````"Q`P``$@`!`&3V````````VP````````"\`P``
-M$@`!``F5````````#@````````#'`P``$@`!`'$R`0``````;`$```````#2
-M`P``$@`!`+[O````````ZP````````#=`P``$@`!`$CW````````"```````
-M``#H`P``$@`!`%`"````````#`````````#S`P``$@`!`,J1````````"P``
-M``````#^`P``$@`!`*W!````````]``````````)!```$@`!`$W!````````
-M+0`````````4!```$@`!`(^B````````10`````````?!```$@`!`!M4````
-M````#@`````````J!```$@`!`%)>````````-0`````````U!```$@`!`,X"
-M````````U0$```````!+!```$@`!`*`0`0``````'`````````!6!```$@`!
-M`$N`````````CP````````!A!```$@`!`%M?````````'@````````!L!```
-M$@`!``2*````````$P````````!W!```$@`!`+@*`0``````$P````````""
-M!```$@`!`(RP````````(@````````"-!```$@`!`)+A````````L`,`````
-M``"8!```$@`!`,/>````````!P````````"C!```$@`!`$E8````````AP``
-M``````"N!```$@`!`-V(````````-P````````"Y!```$@`!`#-#`0``````
-M,`````````#$!```$@`!`!'@````````]@````````#/!```$@`!`/>4````
-M`````0````````#:!```$@`!`&Y<````````9P````````#E!```$@`!`)#`
-M````````%`````````#P!```$@`!``S-````````F08```````#[!```$@`!
-M`+@Q`0``````N0`````````&!0``$@`!`$3I````````!@`````````1!0``
-M$@`!`)2.````````'P`````````!0``$@`!`*73````````
-M3P````````!I!0``$@`!`%;'````````%`````````!T!0``$@`!`$U!`0``
-M````.0````````!_!0``$`````````````````````````",!0``$@`!`%EZ
-M````````7@````````"7!0``$@`!`-=D````````.P````````"B!0``$@`!
-M`#`_`0``````"`````````"M!0``$@`!`-M!`0``````"`````````"X!0``
-M$@`!`"+H````````=P````````##!0``$@`!`/<$````````1`$```````#4
-M!0``$@`!`-XW`0``````UP,```````#?!0``$@`!`*A>````````00``````
-M``#J!0``$@`!`*Q^````````F`````````#U!0``$@`!`/"4`````````0``
-M````````!@``$@`!`%KI````````#@`````````+!@``$@`!`'1-`0``````
-M3P`````````6!@``$@`!`%YD````````4@`````````A!@``$@`!`	````
-M````CP`````````L!@``$@`!`&Z+````````+@`````````W!@``$@`!`'VD
-M````````8P$```````!"!@``$@`!`(EX````````A@````````!-!@``$@`!
-M`+88`0``````R`4```````!8!@``$@`!`!7Y````````,`````````!C!@``
-M$@`!`,ST````````%@````````!N!@``$@`!`/Z8````````VP````````!Y
-M!@``$@`!`*#M````````'@(```````"$!@``$@`!`):2````````;@``````
-M``"/!@``$@`!`/F4````````$`````````":!@``$@`!`-KP````````80(`
-M``````"E!@``$@`!`*$U`0``````5`$```````"P!@``$@`!`&-#`0``````
-MQ`0```````"[!@``$@`!`%.5````````*0````````#&!@``$@`!`-R`````
-M````"@````````#1!@``$@`!`.Y6````````!P````````#
-M!P``$@`!`,[H````````-0`````````I!P``$0`&`.!1````````I`$`````
-M```T!P``$@`!`+3'````````9``````````_!P``$@`!`,Q0`0``````30``
-M``````!*!P``$@`!`#Q@````````2@````````!5!P``$@`!`)"7````````
-M#`````````!@!P``$@`!`!)E````````'@$```````!K!P``$@`!``4(`0``
-M````%P````````!V!P``$@`!`&3E````````'P````````"!!P``$@`!`#[G
-M````````D0````````",!P``$@`!`/Q!`0``````-P$```````"7!P``$@`!
-M`*YL````````&`````````"B!P``$@`!`'!C````````"`````````"M!P``
-M$@`!`%U=````````K`````````"X!P``$@`!`+MD````````'`````````##
-M!P``$@`!`)OF````````@P````````#.!P``$@`!`$H-`0``````F@(`````
-M``#9!P``$@`!`"(\`0``````;@$```````#D!P``$0`&`$!!````````I`$`
-M``````#O!P``$@`!`-!8````````J@$```````#Z!P``$@`!`$$^````````
-M0P`````````%"```$@`!`!QY````````+0`````````0"```$@`!`+!D````
-M````"P`````````;"```$``````````````````````````["```$@`!`#!F
-M````````]@4```````!&"```$0`&````````````"0````````!6"```$@`!
-M`.D3`0``````?0````````!A"```$@`!`!V0````````(@````````!L"```
-M$@`!``:A`0``````V@````````!W"```$@`!`.O4````````00````````""
-M"```$@`!``+H````````(`````````"-"```$@`!`$]A`````````0``````
-M``"8"```$@`!``L1`0``````>0````````"C"```$@`!`/&4````````!@``
-M``````"N"```$@`!`"27````````$P````````"Y"```$@`!`#6,````````
-MAP````````#$"```$@`!`'WI````````)P````````#/"```$```````````
-M``````````````#>"```$@`!`&.0````````+`````````#I"```$0`&`"!0
-M````````I`$```````#T"```$@`!`$[V````````$P````````#_"```$@`!
-M`%_:````````-P`````````*"0``$@`!`(:I````````10`````````5"0``
-M$@`!`)IL````````%``````````@"0``$@`!`"*3````````EP`````````K
-M"0``$@`!`,K>````````#0$````````V"0``$0`&`.!*````````I`$`````
-M``!!"0``$@`!`&KM````````%`````````!,"0``$@`!`**1````````*```
-M``````!7"0``$@`!`+OX````````6@````````!B"0``$@`!`(Y*`0``````
-M%0(```````!M"0``$@`!`+R,````````MP$```````!X"0``$@`!`.-C````
-M````%`````````"#"0``$@`!`$./````````,0````````"."0``$@`!`!&M
-M````````#P$```````"9"0``$@`!`"]R````````&`````````"D"0``$@`!
-M`.WW````````4@````````"O"0``$0`&`*!,````````I`$```````"Z"0``
-M$@`!`#^0````````)`````````#%"0``$@`!`!&1````````D0````````#0
-M"0``$@`!``E>````````*`````````#;"0``$@`!`,0[`0``````%```````
-M``#F"0``$`````````````````````````#U"0``$@`!`*[(````````"```
-M````````"@``$@`!`(/E````````(``````````+"@``$@`!`)Q:````````
-M'P`````````6"@``$@`!`._J````````#@`````````A"@``$@`!`.J4````
-M````!@`````````L"@``$@`!`$+F````````60`````````W"@``$0`&``!#
-M````````I`$```````!""@``$@`!`*V8````````"P````````!-"@``$@`!
-M`!>*````````K`````````!8"@``$@`!`!8!````````+0````````!F"@``
-M$0`&`(`_````````I`$```````!Q"@``$@`!`%N8````````4@````````!\
-M"@``$@`!`,.*````````!P````````"'"@``$0`&`"``````````0```````
-M``"9"@``$@`!``A=````````&`````````"D"@``$@`!`%1=````````"0``
-M``````"O"@``$@`!`.#?````````,0````````"Z"@``$@`!`+%B````````
-M;P````````#%"@``$@`!`,%.`0``````"0(```````#0"@``$@`!`"!C````
-M````$P````````#;"@``$@`!`->3````````#@````````#F"@``$@`!`(SW
-M````````*P````````#Q"@``$@`!`/A(````````N0````````#\"@``$@`!
-M`+4[`0``````#P`````````'"P``$@`!``F8````````4@`````````2"P``
-M$@`!`,F4````````(0`````````="P``$@`!`%SW````````,``````````H
-M"P``$@`!`&K'````````&0`````````S"P``$@`!`&0U`0``````/0``````
-M```^"P``$@`!`+F3````````'@````````!)"P``$@`!`'X>`0``````Q@``
-M``````!4"P``$@`!`,J*````````G@````````!?"P``$@`!`+;(````````
-M2@````````!J"P``$0`&`,!$````````I`$```````!U"P``$@`!`,]C````
-M````%`````````"`"P``$@`!`.-!`0``````&0````````"+"P``$@`!`)-6
-M````````6P````````"6"P``$@`!`#1C````````,0````````"A"P``$@`!
-M`(+#````````Q0,```````"L"P``$@`!`'1A````````.P````````"W"P``
-M$@`!`"Y@````````#@````````#""P``$@`!`);:````````0@$```````#-
-M"P``$@`!`-TS`0``````H`````````#8"P``$@`!`+B8````````"P``````
-M``#C"P``$@`!`+%)````````*P````````#N"P``$@`!`-G<````````8P``
-M``````#Y"P``$@`!`#@+````````:``````````$#```$@`!`%@'````````
-M10$````````/#```$@`!`$C<````````(@`````````:#```$@`!`(9@````
-M````F@`````````E#```$@`!`&AC````````"``````````P#```$@`!`"PM
-M`0``````?P`````````[#```$@`!`/];````````)`````````!&#```$@`!
-M`$0?`0``````+`````````!1#```$@`!`.0[````````'`````````!<#```
-M$@`!`*,$````````5`````````!G#```$@`!`!'F````````,0````````!R
-M#```$`````````````````````````""#```$@`!`*ZP````````@`$`````
-M``"-#```$@`!`(!6````````$P````````"8#```$@`!`,D^`0``````9P``
-M``````"C#```$@`!`$]<````````'P````````"N#```$@`!``?A````````
-MBP````````"Y#```$@`!`%62````````00````````#$#```$@`!`!C(````
-M````D`````````#/#```$`````````````````````````#O#```$@`!`*8&
-M````````L@````````#Z#```$@`!`-Y:````````8P`````````%#0``$@`!
-M`$%;````````,0`````````0#0``$@`!`'2/````````,0`````````;#0``
-M$@`!`+!7````````F0`````````F#0``$@`!`/&0````````(``````````Q
-M#0``$@`!`"S5``````````0````````\#0``$@`!`!>5````````#@``````
-M``!'#0``$@`!`$7Y````````$0$```````!2#0``$@`!`$%A````````!@``
-M``````!=#0``$@`!`'Q:````````(`````````!H#0``$@`!`$Y=````````
-M!@````````!S#0``$`````````````````````````"!#0``$@`!`'2.````
-M````(`````````",#0``$@`!`'`)````````E`````````"7#0``$@`!`%!A
-M````````)`````````"B#0``$@`!`/27````````%0````````"M#0``$@`!
-M`*N5````````%@````````"X#0``$@`!`"QM````````V@````````###0``
-M$@`!`/=C````````%0````````#.#0``$@`!`"!=````````+@````````#9
-M#0``$@`!`$3E````````(`````````#D#0``$@`!`%#W````````#```````
-M``#O#0``$@`!`*4'`0``````8`````````#Z#0``$@`!`(^0````````'P``
-M```````%#@``$@`!`+K<````````'P`````````0#@``$@`!`&84`0``````
-M4`0````````;#@``$@`!`#%>````````"P`````````F#@``$@`!`#B7````
-M````2``````````Q#@``$@`!`-61````````%@`````````\#@``$@`!`$1_
-M````````KP````````!'#@``$@`!`-:.````````;0````````!2#@``$@`!
-M`/B4`````````0````````!=#@``$@`!`'QY````````W0````````!H#@``
-M$0`&`*!3````````I`$```````!S#@``$@`!`-A:````````!@````````!^
-M#@``$@`!`-".````````!@````````")#@``$@`!`%U5````````-P``````
-M``"4#@``$@`!`/56````````A`````````"?#@``$@`!`([<````````+```
-M``````"J#@``$@`!`*`+````````<@````````"U#@``$@`!`.-``0``````
-M$P````````#`#@``$@`!`*3I````````!@````````#+#@``$@`!`""2````
-M````-0````````#6#@``$@`!`+$L`0``````>P````````#A#@``$@`!`+66
-M````````;P````````#L#@``$@`!`-R9````````H`@```````#W#@``$0`&
-M`&!5````````I`$````````"#P``$@`!`$+9````````'0`````````-#P``
-M$@`!`-);````````+0`````````8#P``$@`!`#L&````````)P`````````C
-M#P``$@`!`+M:````````'0`````````N#P``$@`!`*$_`0``````0@$`````
-M```Y#P``$@`!`&4W`0``````>0````````!$#P``$@`!`'AC````````#```
-M``````!/#P``$@`!``23````````'@````````!:#P``$@`!`$#W````````
-M"`````````!E#P``$@`!`(1C````````2P````````!P#P``$@`!`+A4````
-M````00````````![#P``$@`!`!!@````````'@````````"&#P``$@`!`.:%
-M````````&@````````"1#P``$@`!``0*````````-`$```````"<#P``$@`!
-M`+;)`````````0````````"G#P``$@`!`$!]````````00````````"R#P``
-M$@`!`,R7````````%`````````"]#P``$@`!`$AA````````!@````````#(
-M#P``$@`!`!'#````````<0````````#3#P``$@`!`-CW````````%0``````
-M``#>#P``$@`!`"M@`0``````Q`````````#I#P``$@`!`"!A````````(0``
-M``````#T#P``$@`!`-!*````````)0````````#_#P``$@`!`,]!````````
-M*0<````````5$```$@`!`)'X````````*@`````````@$```$@`!``QD````
-M````4@`````````K$```$@`!`%CZ````````30T````````V$```$@`!`%#=
-M````````````````
-M<@````````"Z$```$@`!`#*]````````0@````````#%$```$@`!`-_U````
-M````;P````````#0$```$@`!``/I````````00````````#;$```$@`!`.N1
-M````````-0````````#F$```$@`!`$.!````````HP0```````#Q$```$@`!
-M`"]U````````R@(```````#\$```$@`!`&CI````````#@`````````'$0``
-M$@`!`$?'````````#P`````````2$0``$@`!`)MY`0``````S@`````````=
-M$0``$@`!`)GH````````-0`````````H$0``$@`!`-C;````````;0``````
-M```S$0``$@`!`/H*`0``````4`(````````^$0``$@`!`-@[`0``````&0``
-M``````!)$0``$@`!`"R(````````00````````!4$0``$@`!`._9````````
-M<`````````!?$0``$@`!`');````````!@````````!J$0``$@`!`"65````
-M````!P````````!U$0``$@`!`'I^````````,@````````"`$0``$@`!`/?G
-M````````"P````````"+$0``$@`!`!GHP,#5B-3@T-@!Z>C`P,F1B,3%C`'IZ
-M,#)D8F8X-S4`>GHP,F1B8C%B,@!Z>C`R9&(R,#4S`'IZ,#`R9&)A-#(`>GHP
-M9F)B,64S9@!Z>C!B-SEE83DT`'IZ,#5B.&,V-6$`>GHP,#5B-#!A9`!Z>C`U
-M8CDT,F5D`'IZ,&0X9&,V,F,`>GHP,#$Y9C0W,`!Z>C`R9&0Y-#)D`'IZ,#)D
-M8F4W,V0`>GHP,#5B-CDR8@!Z>C!B-F0R,S(U`'IZ,#`U8C@U,V0`>GHP,#$V
-M9#DR90!Z>C!C9F(Q.#GHP,F1A8F)A8P!Z>C`R9&)C
-M.#4Q`'IZ,#`P8C9C-C@`>GHP,#!B-F)F.`!Z>C`P8C9C9C5E`'IZ,#$V93%D
-M9F0`>GHP8C9F-3!B.`!Z>C`V93!A-&9E`'IZ,#`V-V0R8C$`>GHP,#)D8F,V
-M,0!Z>C!B-F-A,S(U`'IZ,#`U8C9C9F0`>GHP,39E,&1F9`!Z>C`P,&(V9C8X
-M`&%T:%]H86Q?<')O8V5SGHP,F1B
-M9C%B,@!Z>C`P-6(X.&-B`'IZ,#,S96,X8F8`>GHP9&(T,C5C-0!A=&A?:&%L
-M7V1M85]B96%C;VY?C`P8C9F,38Q`'IZ,#9E,#!B
-M.&$`>GHP,F1B9F,Q9`!Z>C!D8S1E,SDP`'IZ,&1A9F5D.#8`>GHP,&(V93(W
-M80!Z>C`R9&)B86(R`'IZ,&(V9#%E9F8`>GHP,39D.3!D9`!Z>C`R9&)E.#4Q
-M`'IZ,#`U8C8T9F0`>GHP,#!B-F0U,@!Z>C!B-F,Y969F`'IZ,#$V93`P9&0`
-M>GHP,F1B9#@W-0!Z>C`R9&(S,6(R`'IZ,#!B-S`Y,C,`>GHP,&(V9#0U,`!Z
-M>C`P,&(V9#%D`'IZ,&(V8S(S,C4`>GHP,F1B9&%B,@!Z>C`P,#5B-C,R`'IZ
-M,#9D961D.3,`>GHP,#$V9&$U,`!Z>C`P,#8W9#,R`'IZ,#!B-F0Y,C,`>GHP
-M,#)D8C4Q8P!Z>C`Q-F1C8F9E`'IZ,#!B-S`Q-#4`>GHP,#$V9&8R8P!Z>C!B
-M-V9A9#-E`'IZ,#$V9#DY,C``>GHP,F1B,6)A8P!Z>C!D8S9E,SDP`'IZ,#5B
-M-S`Q93``>GHP,#!B-F(Q,`!Z>C!B-S`Y969F`'IZ,#$V9&8X.6(`871H7VAA
-M;%]A='1A8V@`>GHP-F4P9F,P9`!Z>C`Q-F1A8C)D`'IZ,#)D8C$S-60`>GHP
-M93`T-C@T8@!Z>C`Q-F4R.3%D`'IZ,#`P8C9F93@`>GHP,&-F8C-E,`!Z>C`P
-M,39D.30X`'IZ,#$V93(P.6(`>GHP8CC`P,&(V8SED`'IZ,#`P
-M-6(U83(`>GHP,F1B,3'1I;64`>GHP,F1B
-M-6)A8P!Z>C`P-6(X,3-D`'IZ,#!B-F,Y,C,`>GHP8C9B-3!B.`!Z>C`P-6(W
-M9CED`'IZ,&(W,#%D,#(`>GHP-F1F9C0T80!Z>C`R9&(U-S8S`'IZ,#9E96%F
-M-C``>GHP93`P-V-A,0!Z>C`P,F1A9C8R`'IZ,&(X,V%D,V4`>GHP,#!B-F(Y
-M,`!Z>C`Q-F0Y969A`'IZ,#$V9&4P-3$`>GHP,#`U8C9B,@!Z>C`U8C=F,3$T
-M`'IZ,#1A93`S,68`>GHP,F1B9&1F9`!Z>C`P-30W9F5D`'IZ,#!B-F)F-64`
-M>GHP,&(W,3C`P8CGHP,F1B,6%B,@!Z
-M>C`P,#5B-C(R`'IZ,#`P8C9F-S@`>GHP8C8Y8C`W8P!A=&A?:&%L7V9R964`
-M>GHP-6(W.6(Q8@!Z>C`P8CGHP8C5E,S$U,@!Z
-M>C`Q-F1F8F8Q`&%T:%]H86Q?;6AZ,FEE964`>GHP,39E,3@Y8@!Z>C!D8S)A
-M-6,U`'IZ,#`R9&,V,&(`>GHP-F1F,&(X80!Z>C`R9&(S,S5D`'IZ,&(V8S4S
-M830`>GHP9C4T9#%B,`!Z>C!B-F9D,S8S`'IZ,&0Y9&,V,F,`>GHP-6(W-#%E
-M,`!Z>C`R9&$Y8F%C`'IZ,&1C,C%D,V$`>GHP,&(W,3C`Q-F0Y9#0Q
-M`'IZ,#`U8C@T9F0`>GHP,#5B.&%B9`!Z>C`P8CGHP,F1B,S@W-0!Z>C`Q-F4S,#EB`'IZ,#`U8C8P8C(`>GHP,F1B,3@W-0!Z
-M>C`P,F1B.#0R`'IZ,#)D8C$W-C,`>GHP8C=D96$Y-`!Z>C`P8CGHP,#$V8V0S,@!Z>C`V9&4P8CAA`'IZ,#9D.61D.3,`>GHP
-M9&(S960X-@!Z>C`P-6(T.&5D`'IZ,#`R9&,X,&(`>GHP,#)D8F,T,@!Z>C`R
-M9&)A.#4Q`'IZ,#)D8C,S960`>GHP,#5B.#!F9`!Z>C`P-6(W9C)E`'IZ,#)D
-M8F9D9F0`>GHP,39E-C0X80!Z>C`P,F1A9F8R`'IZ,#`U8CGHP,#!B
-M-F5E.`!Z>C`Q-F4T-#AA`'IZ,#!B-F8V8F,`>GHP,39D83DR,`!Z>C`U8CGHP,#5B-#1A9`!Z>C`V9&1F-#1A`'IZ,&9A8S!C
-M.6(`>GHP8C9F.65F9@!Z>C`P8C9C-F)C`&%T:%]H86Q?861D:71I;VYA;%]S
-M=V)A7V)A8VMO9F8`>GHP,#`R9&(Y,@!A=&A?:&%L7W9EGHP,F1B
-M86,R90!Z>C`R9&(W.6%E`'IZ,#`Q-F4U,S(`>GHP8C9C9C`P.0!Z>C`P,39E
-M,3)C`'IZ,#`Q-F0Y930`>GHP,#`R9&%E80!Z>C`P-6(U8V(R`'IZ,#$V9&$R
-M-3$`>GHP-F8V868V,`!Z>C`V9&9D9#DS`&%T:%]H86Q?;6%L;&]C`'IZ,#`P
-M8C9D9#(`>GHP,F1D.3)A9`!Z>C`Q-F1B,C4Q`'IZ,&4Q,#=C83$`>GHP,&(V
-M8SC`Q-F1D,#4Q`'IZ,#)D8F0Q8C(`>GHP,F1C,3C!B-CDP
-M9#9D`'IZ,#$V9&8P-3$`>GHP,#$V9#DU,`!Z>C`P8CGHP-F1E9C0T80!Z>C`U8CAC,F5D`'IZ,#9F8CDT-V(`>GHP96)B,64S
-M9@!Z>C!B-F8Y9#`R`'IZ,&0Q-&0Q8C``>GHP8C0X,#,Q90!Z>C`Q-F1B8F9E
-M`'IZ,#$V934T.&$`>GHP,#$V9#@U,`!Z>C`P,&(V9F8X`&%T:%]H86Q?;65M
-M8W!Y`'IZ,#)D8F-B8F0`>GHP,39D83!D9`!Z>C`R9&)B9&9D`'IZ,#)D8C(X
-M-3$`>GHP,F1B9&,Q9`!Z>C`V9&(P8V8R`'IZ,#$V96(Y860`>GHP,&(V8V5B
-M8P!Z>C!D.30X-&$Q`&%T:%]H86Q?<')O8F4`>GHP,39E83EA9`!Z>C!F9#1D
-M,6(P`'IZ,#)D8C,W-C,`871H7VAA;%]B=6EL9&]P=',`>GHP,F1A9C,U9`!Z
-M>C`V9&1D9#DS`'IZ,&1A9&,V,F,`>GHP,39D9C(U,0!Z>C`P,&(V8S$P`'IZ
-M,#$V9#DR-3$`>GHP,F1B,#@U,0!Z>C!B-S(Q865D`'IZ,#8W8V9C864`>GHP
-M,#!B-F-F.`!Z>C!C.31D,6(P`'IZ,#)D869A8C(`>GHP-6(Y,F%E9`!Z>C`P
-M-6(X8V-B`'IZ,&(V9#EE9F8`>GHP,F1B,3%B,@!Z>C`R9&)F9F(Q`'IZ,#)D
-M8F8W-C,`>GHP,#5B-CAF9`!Z>C`P-6(T-&5D`'IZ,&(W,3%A960`>GHP8C5E
-M,S$V,`!Z>C!D.#0X-&$Q`'IZ,#$V9#AB,F0`>GHP,39E,#@Y8@!Z>C`R9&)B
-M.#GHP8C@Q96$Y-`!Z>C`Q-F1E8S%F`'IZ,#!B-F9E
-M8F,`>GHP93@Y-#DP-P!Z>C`P8C9E83=A`'IZ,#,S93AF8F8`>GHP8V9A-3@W
-M-0!Z>C`R9&(Y.6%E`'IZ,#)D8CEA8C(`>GHP,#!B-F)E.`!Z>C!D938X,S=F
-M`'IZ,#$V9&%B9F4`>GHP8CC`V-V0R-64R`'IZ,#$Y9C-A,#$`
-M>GHP-S`S.30W8@!A=&A?:&%L7VUE;7IEGHP-F1F9F,P9`!Z>C!B-CGHP,#!B-F0R,@!Z>C`V9F5A9C8P`'IZ,&1C-&$U
-M8S4`>GHP,&(W,&8W9`!A=&A?:&%L7W-W7V)E86-O;E]R97-P;VYS95]T:6UE
-M`'IZ,#EF-C1B-F$`>GHP,#5B-C4W80!Z>C`V9C,Y-#=B`'IZ,#9D83!C9C(`
-M>GHP8C=B860S90!Z>C`P8C9F.38Q`'IZ,&(V.3GHP,F1B9#,U9`!Z
-M>C`P-6(X.&9D`'IZ,#)D8F)C,60`>GHP,F1A9F1F9`!Z>C`V9#=D9#DS`&%T
-M:%]H86Q?9&5L87D`>GHP,F1B,61F9`!Z>C`V-V0R9C0Q`'IZ,#)D868X-S4`
-M>GHP8C=E9&4V9`!Z>C`Q-F0X9#0Q`'IZ,#`R9&%E.3(`>GHP8C=A9&4V9`!Z
-M>C`R9&)B,S5D`'IZ,#)D8C-D9F0`>GHP,F1B-3-E9`!Z>C`Q-F1C96%E`'IZ
-M,#`P8C9D83(`>GHP,#!B-F4R,@!Z>C`U8C@P,#0Q`'IZ,#`Q-F0X-#@`>GHP
-M,39D.6(R9`!Z>C`P,39E,#)C`'IZ,#!B-S`W-V0`>GHP,#5B-CDW80!Z>C`P
-M,39D864T`'IZ,#$V93$P.6(`>GHP,#5B-&$R9`!Z>C`Q-F1E,&1D`'IZ,#$V
-M9&8P9&0`>GHP9&8P-V-A,0!Z>C`R9&)D-S8S`'IZ,#`P8C9E-3(`>GHP-C=D
-M,&,T-P!Z>C`U8C9C-F1B`'IZ,&,S,35E8C4`>GHP9&(Q960X-@!Z>C`V9#0P
-M-F4P`'IZ,#$V93`R-3$`>GHP,#`R9&)B,@!Z>C`P,F1D.#9D`'IZ,#`Q-F4Q
-M-&0`>GHP,F1B-3EA90!Z>C`P-C=D,C(Q`'IZ,#$V9#@P9&0`>GHP,#5B.#DS
-M9`!Z>C`U8C@Q8C%B`'IZ,#)D8C$S960`>GHP,&(V9#$R,P!Z>C`P,&(V8V4X
-M`'IZ,#5B.&%A960`>GHP8C9E9#,V,P!Z>C`R9&%F,6(R`'IZ,#`P-6(U93(`
-M>GHP,S-E8F9B9@!Z>C`U8C8X-F1B`'IZ,#`P8C9E9C@`>GHP8CC`P-6(U.&(R`'IZ,#5B-V1B,6(`>GHP8C@R9&4V9`!Z>C`P,39D-S,R`'IZ
-M,#)D861A8C(`>GHP9C0U939E,P!A=&A?:&%L7VEN:71?8VAA;FYE;',`>GHP
-M,&(V9#9B8P!Z>C!C,31D,6(P`'IZ,#`P,F1B9#(`>GHP9&$T.#1A,0!Z>C`Q
-M-F4P8C@W`'IZ,#5B.3`R960`>GHP9&,R93,Y,`!Z>C!A-C!D,30U`'IZ,#)D
-M8F%B8F0`>GHP,#!B-F,Q9`!Z>C`U8CAE865D`'IZ,#`U8C=B.60`>GHP,#5B
-M-30T-@!Z>C`U8C8T-F1B`'IZ,#!B-F8Y,C,`>GHP9&0V.#,W9@!Z>C`Q-F4Q
-M,C4Q`'IZ,&1C-F$U8S4`>GHP,F1B,SC`P,#5B-CGHP,F1B9C,U9`!Z>C`P,&(V8SGHP,F1B-3

C`P-6(V9#=A`'IZ,#`R9&(R.3(`>GHP,#5B.3!C8@!Z>C!B-F8U,S8S -M`'IZ,#`U8C5C-#8`>GHP-F0Y,&-F,@!Z>C`V9#AD9#DS`'IZ,#$V9&9B.#<` -M>GHP,#$V9&$T.`!Z>C!B-C8S,6$X`'IZ,#`R9&(P.3(`871H7VAA;%]G971W -M:7)E;&5SP8````````+```` -M`@``````````````(0<````````"````9P```/S_________/@<````````" -M````9P```/S_________;0<````````+`````@````@`````````N0L````` -M```"````_@```/S_________V`L````````"````'P$``/S_________\`L` -M```````+`````@```"`!````````<@P````````"````'P$``/S_________ -M@`P````````+`````@```"`!````````[`P````````+`````@```"`!```` -M````=0T````````+`````@```#`!````````?@T````````+`````@```%`! -M````````!1$````````"````S@```/S_________FA4````````"````(0$` -M`/S_________W!@````````"````A````/S_________["$````````"```` -MS@```/S_________&"(````````"````(0$``/S_________I2(````````" -M````(0$``/S_________+B,````````"````(0$``/S_________F",````` -M```"````A````/S_________82T````````+`````@```)`!````````40````````+````!````&`4````````I40````````+````!````$`> -M````````U$0````````+````!````&`A````````!$4````````+````!``` -M```D````````-$4````````+````!``````;````````9D8````````"```` -M(0$``/S_________SD<````````+`````@```,@!````````^4<````````+ -M`````0`````\````````M4D````````"````_@```/S_________BDH````` -M```"````_@```/S_________U4H````````"````_@```/S_________LTP` -M```````+````!````"`]````````-TT````````+````!````(`]```````` -M%4X````````"````S@```/S_________-DX````````+`````@```.`!```` -M````/DX````````"````YP```/S_________NTX````````"````/`$``/S_ -M________.T\````````"````,````/S_________<$\````````"````*P$` -M`/S_________I$\````````"````*P$``/S_________T$\````````"```` -M*P$``/S_________(U`````````"````*P$``/S_________85`````````" -M````*P$``/S_________&U$````````+````?```````````````;E,````` -M```"````*P$``/S_________\%,````````"````A````/S_________(%0` -M```````"````A````/S_________#E4````````"````,@```/S_________ -M'54````````"````*0$``/S_________5%4````````"````9`$``/S_____ -M____75H````````"````<````/S_________DUH````````"````YP```/S_ -M________K5H````````"````YP```/S_________REH````````+`````@`` -M``@6````````SUH````````"````YP```/S_________$%L````````"```` -M2P```/S_________J%L````````"````)0$``/S_________NUL````````" -M````=0```/S_________S%P````````"````4`$``/S_________=5T````` -M```"````YP```/S_________#E\````````"````)@```/S_________+U\` -M```````"````7`$``/S_________<%\````````"````)@```/S_________ -MH5\````````"````)@```/S_________U%\````````"````7`$``/S_____ -M____)6`````````"````)@```/S_________KF`````````"````)@```/S_ -M________X6`````````"````7`$``/S_________.&$````````"````)@`` -M`/S_________:V$````````"````%P$``/S_________IF$````````"```` -M'````/S_________M&$````````"````.`$``/S_________%V(````````" -M````-@$``/S_________-V(````````"````-@$``/S_________/6,````` -M```+````\@``````````````2V,````````+````$@``````````````7&,` -M```````"````*@$``/S_________LV,````````"````-@$``/S_________ -M6V8````````"````_@```/S_________JV8````````"````/`$``/S_____ -M____O6@````````"````MP```/S_________?VD````````+`````@```"`6 -M````````OFD````````"````A@$``/S_________"&L````````"````-@$` -M`/S_________,FL````````"````2P```/S_________/6L````````"```` -ME0```/S_________8&L````````"````6````/S_________>&L````````" -M````?P```/S_________J&L````````"````@`$``/S_________PVL````` -M```"````#````/S_________WFL````````"````&0$``/S_________U6P` -M```````"````^0```/S_________`VT````````"````-@$``/S_________ -M'VT````````"````-@$``/S_________2VT````````"````^0```/S_____ -M____G6T````````"````-@$``/S_________PFT````````"````-@$``/S_ -M________U&T````````"````^0```/S_________(&X````````"````_@`` -M`/S_________9VX````````"````-@$``/S_________AFX````````"```` -M-@$``/S_________J&X````````"````-@$``/S_________'V\````````" -M````-@$``/S_________/F\````````"````-@$``/S_________:V\````` -M```"````-@$``/S_________E6\````````"````2P```/S_________PV\` -M```````"````E0```/S_________T6\````````"````-@$``/S_________ -MW&\````````"````E0```/S_________6G`````````"````-@$``/S_____ -M____<7`````````"````2P```/S_________VG,````````+`````@```'(; -M````````2'4````````+`````@```(`;````````374````````"````YP`` -M`/S_________7G4````````+`````@```&`;````````9G4````````"```` -MYP```/S_________PG4````````"````,````/S_________Z74````````" -M````,````/S_________=G<````````"````,````/S_________D7<````` -M```"````,````/S_________J7<````````"````,````/S_________,7@` -M```````"````,````/S_________MG@````````"````2P```/S_________ -MSG@````````"````-@$``/S_________UG@````````"````4P```/S_____ -M____0'D````````"````9P$``/S_________0$``/S_________GH0````````" -M````-@$``/S_________Q80````````"````-@$``/S__________80````` -M```"````20$``/S_________*84````````+````TP``````````````.84` -M```````"````@0$``/S_________7H4````````"````20$``/S_________ -MP(4````````"````9@$``/S_________\H4````````"````'@$``/S_____ -M____^H4````````"````A````/S_________Z(8````````"````-@$``/S_ -M________9(<````````"````W@```/S_________[H<````````"````20$` -M`/S_________I8@````````"````,@```/S_________M(@````````"```` -M*0$``/S_________U(@````````"````C@$``/S_________9(X````````" -M````S````/S_________BXX````````"````YP```/S_________I8X````` -M```"````YP```/S_________PHX````````+`````@```"`P````````QXX` -M```````"````YP```/S_________$H\````````"````2P```/S_________ -MU8\````````"````XP```/S_________\X\````````"````0@$``/S_____ -M____!I`````````"````.````/S_________Z)`````````"````!P$``/S_ -M________!I$````````+`````@```$`P````````,9$````````"````YP`` -M`/S_________NY(````````"````)@```/S_________V)(````````"```` -M7`$``/S_________&9,````````"````)@```/S_________2I,````````" -M````)@```/S_________?9,````````"````7`$``/S_________SI,````` -M```"````)@```/S_________5Y0````````"````)@```/S_________BI0` -M```````"````7`$``/S_________X90````````"````)@```/S_________ -M2I4````````"````WP```/S_________K(````````+````!0````@`````````@;(````````+````!0```(@````` -M````I+(````````"````!0````(`````````J[(````````"````!0```/S_ -M________M+(````````"````!0```/[_________PK(````````"````!0`` -M``(`````````YK(````````"````!0````(`````````];(````````"```` -M!0````(`````````![,````````"````!0````(`````````*K,````````" -M````!0````(`````````4+,````````"````!0````(`````````7K,````` -M```"````!0````(`````````9[,````````"````!0````(`````````U+,` -M```````+````!0```"`!````````%+0````````"````!0````(````````` -MPK0````````+````!0```"`!````````X;0````````"````!0````(````` -M````^[0````````+````!0```"`!`````````;4````````!````!0```!X! -M````````++4````````+````!0```"(!````````,[4````````+````!0`` -M`"`!````````T;4````````+````!0```*`!````````$[8````````"```` -M%`$``/S_________:K<````````+`````@```/@]````````D+@````````+ -M`````@```.@]````````M[D````````"````;0```/S_________.[T````` -M```"`````@```$`^````````5KT````````+`````@```$@^````````Z;X` -M```````+`````@```$@^````````%[\````````+`````@```$`^```````` -M'K\````````+`````@```$@^````````;+\````````"`````@```#P^```` -M````B;\````````"`````@```#P^````````EK\````````+`````@```$`^ -M````````G;\````````+`````@```$@^````````O,`````````"````]``` -M`/S_________S\`````````"````!P$``/S_________!L$````````"```` -M!P$``/S_________,<$````````"````!P$``/S_________<<$````````" -M````9P$``/S_________I,$````````"````%@$``/S_________/<(````` -M```"````(0$``/S_________?<(````````"````8P```/S_________Z,4` -M```````"````*0$``/S_________[L4````````"````,@```/S_________ -M_\4````````"````P````/S_________W<<````````"````=@$``/S_____ -M____Z\<````````"````-@$``/S_________Q\H````````"````,````/S_ -M________N0$``/S_________U-$````` -M```"````-@$``/S_________W-$````````"````1````/S_________^]$` -M```````"````-@$``/S_________*M(````````"````BP$``/S_________ -M3M(````````"````,`$``/S_________AM(````````"````Q0```/S_____ -M____I=(````````"````I@```/S_________QM(````````"````B0$``/S_ -M________T](````````"````;@$``/S_________\=(````````"````&P$` -M`/S_________%-,````````"````BP$``/S_________@M,````````"```` -M@0```/S_________JM,````````"````<@```/S_________Q=,````````" -M````10```/S_________U],````````"````@@$``/S_________YM,````` -M```"````'@$``/S_________[M,````````"````A````/S_________W-0` -M```````"````-@$``/S_________--D````````"````K````/S_________ -M2-D````````+`````0```"S9````````3]D````````+````C0$````````` -M````LMD````````"````K````/S_________)]H````````"````,@```/S_ -M________-MH````````"````*0$``/S_________5MH````````"````D@`` -M`/S_________%-P````````"````2P```/S_________,]T````````"```` -MU@```/S_________X.$````````+`````@```*A3````````EN,````````" -M````)@$``/S_________*.4````````"````)@$``/S_________6^4````` -M```"````YP```/S_________=>4````````"````YP```/S_________FN4` -M```````"````YP```/S_________M.4````````"````YP```/S_________ -M,^<````````+`````@```.!3````````7N<````````"````YP```/S_____ -M____F^D````````"````#P```/S_________S^D````````"````)@```/S_ -M________\.D````````"````7`$``/S_________,>H````````"````)@`` -M`/S_________8NH````````"````)@```/S_________E>H````````"```` -M7`$``/S_________YNH````````"````)@```/S_________;^L````````" -M````)@```/S_________HNL````````"````7`$``/S_________^>L````` -M```"````)@```/S_________C^P````````"````7`$``/S_________=>T` -M```````"````)0```/S_________I>T````````"````%P```/S_________ -MP^\````````"````%P```/S_________L?`````````+`````@````!4```` -M````O?`````````"`````@```/Q3````````U?`````````+`````@````)4 -M````````!?$````````+`````@```#!4````````W?(````````"````B``` -M`/S_________^/(````````+`````@```"!5````````*/,````````"```` -M%P$``/S_________5_,````````+`````@```(!5````````D_0````````+ -M`````@```&!5````````FO0````````"````GP```/S_________P_0````` -M```"````'````/S_________T?0````````"````.`$``/S_________#/4` -M```````"````-@$``/S_________+/4````````"````-@$``/S_________ -MP?8````````+````+0``````````````[_8````````+````J@`````````` -M````^/8````````+````3`$``````````````?<````````+````T``````` -M````````"O<````````+````%@``````````````$_<````````+````60$` -M````````````'/<````````+````UP``````````````)?<````````+```` -MX@``````````````-O<````````"````*@$``/S_________>_<````````" -M````2P```/S_________I/<````````"````,0```/S_________L?<````` -M```"````VP```/S_________S_<````````"````@P```/S_________+/H` -M```````"````D````/S_________UOH````````"````@@$``/S_________ -M[OH````````"````_@```/S_________4?L````````"````R0```/S_____ -M____7OL````````"````VP```/S_________V_L````````"````#0```/S_ -M________2/P````````"````7@```/S_________4/P````````"````30`` -M`/S_________6_P````````"````C`$``/S_________*OT````````+```` -M`@```(!6````````7/T````````"````-@$``/S__________\` -M```````"````6@```/S_________H/\````````"````00$``/S_________ -M)@`!```````"````E@```/S_________,0`!```````"````!@$``/S_____ -M____/@`!```````"````1`$``/S_________T@`!```````"````)0```/S_ -M________Z0$!```````"````L````/S_________"@(!```````"````-``` -M`/S_________%0(!```````"````70```/S_________]`(!```````"```` -M-@$``/S_________)@,!```````"````-@$``/S_________RP,!```````" -M````3P```/S_________'@0!```````"````BP```/S_________A@0!```` -M```"````N````/S_________G00!```````"````2P```/S_________J00! -M```````"````F@```/S_________-`4!```````"````%`$``/S_________ -MI08!```````"````0P```/S_________P08!```````"````+@```/S_____ -M____W08!```````"````1P```/S_________9P`!`!```````"````@@$``/S_________.1$!```````" -M````:````/S_________I!(!```````"````,````/S_________RA4!```` -M```"````#P```/S_________CQC,!```````"````9P```/S_ -M________MC,!```````"````9P```/S_________JC0!```````"````U@`` -M`/S_________!S4!```````"````U@```/S_________5S4!```````"```` -M9P$``/S_________E#4!```````"````%@$``/S_________DS8!```````" -M````(0$``/S_________WC8!```````"````5P```/S_________(SH!```` -M```"````*0$``/S_________*3H!```````"````,@```/S_________.#H! -M```````"````P````/S_________4CP!```````"````EP$``/S_________ -M8#P!```````"````-@$``/S_________<#P!```````"````EP$``/S_____ -M____'#T!```````"````-@$``/S_________1CT!```````"````-@$``/S_ -M________43T!```````"````EP$``/S_________!$$!```````"````@P$` -M`/S_________9$$!```````"````@P$``/S_________[T$!```````"```` -M@P$``/S_________)D(!```````"````(0$``/S_________"T,!```````" -M````,0```/S_________04,!```````"````@P```/S_________ET,!```` -M```+`````@```!!B````````@DTH!```````"````GP```/S__________DH! -M```````"````GP```/S_________$$L!```````"````GP```/S_________ -M(DL!```````"````GP```/S_________-$L!```````"````GP```/S_____ -M____1DL!```````"````GP```/S_________3DL!```````"````<@$``/S_ -M________7DL!```````"````V@```/S_________DTL!```````"````GP`` -M`/S_________I$L!```````"````GP```/S_________NTL!```````"```` -MGP```/S_________S$L!```````"````GP```/S_________Y$L!```````" -M````GP```/S_________]4L!```````"````GP```/S_________!TP!```` -M```"````GP```/S_________&4P!```````"````GP```/S_________*TP! -M```````"````GP```/S_________/DP!```````"````<@$``/S_________ -M3DP!```````"````V@```/S_________A$P!```````"````<@$``/S_____ -M____E$P!```````"````V@```/S_________U$P!```````"````@P$``/S_ -M________0$X!```````"````GP```/S_________.4\!```````"````@P$` -M`/S_________.E$!```````+`````@```&!B````````:E$!```````"```` -M-@$``/S_________@%$!```````+`````@```,!C````````C%$!```````+ -M`````@```,1C````````H%$!```````"````-@$``/S_________LU$!```` -M```+`````@```*!G````````X5$!```````"````-@$``/S_________$U(! -M```````"````B@```/S_________*E(!```````+`````@```$1N```````` -M-U(!```````"````,````/S_________F5(!```````"````,````/S_____ -M____P5(!```````"````,````/S_________.E,!```````+`````@```(AO -M````````FU4!```````+`````@````!F````````W%4!```````"````>``` -M`/S_________]U4!```````"````>````/S_________"E8!```````+```` -M`@````!F````````)U8!```````"````-@$``/S_________/58!```````+ -M`````@```*!J````````2%8!```````+`````@```*1J````````758!```` -M```"````-@$``/S_________;58!```````+`````@```+!J````````H58! -M```````"````-@$``/S_________L58!```````+`````@```-!J```````` -MY58!```````"````-@$``/S_________^U8!```````+`````@````!K```` -M````3E````/S_________;E````/S_ -M________D%````/S_________K5``` -M`/S_________RE````/S_________YU````/S_________^E````/S_________B%@!```````"````>````/S_________UE@! -M```````"````>````/S_________\5@!```````"````>````/S_________ -M#ED!```````"````>````/S_________(5D!```````+`````@```*!L```` -M````/ED!```````"````-@$``/S_________W%H!```````"````(0$``/S_ -M________^5T!```````"````5@$``/S_________HU\!```````"````5@$` -M`/S_________PE\!```````"````A````/S_________XU\!```````"```` -MA````/S_________`F`!```````+`````@```.!O````````#F`!```````" -M`````@```-QO````````)F`!```````+`````@```.)O````````16`!```` -M```"````S@```/S_________96`!```````"````S@```/S_________BF`! -M```````+`````0```*Q?`0``````E6`!```````+`````0```!Q1`0`````` -MH&`!```````+`````0```"E3`0``````JV`!```````+`````0```/M1`0`` -M````MF`!```````+`````0```&13`0``````P6`!```````+`````0```.]9 -M`0``````S&`!```````+`````0```/1?`0``````UV`!```````+`````0`` -M`/I?`0``````#F$!```````+`````@```"!P````````/F$!```````"```` -M-@$``/S_________5&$!```````+`````@```*!Q````````8&$!```````+ -M`````@```*1Q````````=&$!```````"````-@$``/S_________AV$!```` -M```+`````@```.!S````````M6$!```````"````-@$``/S_________IF(! -M```````"````,````/S_________+6,!```````"````,````/S_________ -MCV,!```````"````,````/S_________Z&,!```````"````,````/S_____ -M____0F0!```````"````,````/S_________4V0!```````"````,````/S_ -M________P&0!```````+`````@```#A\````````FV8!```````+`````@`` -M`.1V````````NV8!```````+`````@```/!V````````Y&8!```````+```` -M`@```!!W````````#6````/S_________9F````/S_________AV````/S_________MF````/S_________VF````/S__________F````/S_________ -M(F@!```````"````>````/S_________1F@!```````"````>````/S_____ -M____:F@!```````"````>````/S_________DF@!```````"````>````/S_ -M________Q6@!```````"````>````/S_________XF@!```````"````>``` -M`/S_________2&D!```````"````>````/S_________96D!```````"```` -M>````/S_________@FD!```````"````>````/S_________GVD!```````" -M````>````/S_________SVD!```````"````>````/S_________[&D!```` -M```"````>````/S_________"6H!```````"````>````/S_________)FH! -M```````"````>````/S_________0VH!```````"````>````/S_________ -M56H!```````+`````@````![````````GVH!```````"````>````/S_____ -M____P&H!```````"````>````/S_________"6L!```````"````>````/S_ -M________)&L!```````"````>````/S_________,VL!```````+`````@`` -M`.!V````````46L!```````"````-@$``/S_________:&L!```````+```` -M`@```/!V````````AFL!```````"````-@$``/S_________G6L!```````+ -M`````@```!!W````````NVL!```````"````-@$``/S_________TFL!```` -M```+`````@```$!W````````\&L!```````"````-@$``/S_________"FP! -M```````+`````@````![````````*VP!```````"````-@$``/S_________ -M@VX!```````"````YP```/S_________EFX!```````"````YP```/S_____ -M____#&\!```````"````YP```/S_________'V\!```````"````YP```/S_ -M________<6\!```````"````YP```/S_________GV\!```````"````YP`` -M`/S_________LF\!```````"````YP```/S_________`'`!```````"```` -MYP```/S_________>78!```````"````A````/S_________FG8!```````" -M````A````/S_________M7D!```````"````S@```/S_________U7D!```` -M```"````S@```/S_________!'H!```````+`````0```&-V`0``````#WH! -M```````+`````0```/!@`0``````&GH!```````+`````0```*]D`0`````` -M)7H!```````+`````0```,]A`0``````,'H!```````+`````0```.5D`0`` -M````.WH!```````+`````0```%5L`0``````1GH!```````+`````0```"-Y -M`0``````47H!```````+````(@``````````````BGH!```````+`````@`` -M`(!\````````NGH!```````"````-@$``/S_________T'H!```````+```` -M`@````!^````````W'H!```````+`````@````1^````````\'H!```````" -M````-@$``/S_________!GL!```````+`````@```&""````````-'L!```` -M```"````-@$``/S_________)7P!```````"````,````/S_________K'P! -M```````"````,````/S_________#GT!```````"````,````/S_________ -M9WT!```````"````,````/S_________P7T!```````"````,````/S_____ -M____TGT!```````"````,````/S_________LWX!```````+`````@```&2% -M````````T7X!```````+`````@```'"%````````^7X!```````+`````@`` -M`)"%````````(7\!```````+`````@```,"%````````7'\!```````"```` -M>````/S_________>7\!```````"````>````/S_________B7\!```````+ -M`````@```&"(````````LG\!```````+`````@```&"%````````SW\!```` -M```"````-@$``/S_________YG\!```````+`````@```'"%````````!(`! -M```````"````-@$``/S_________&X`!```````+`````@```)"%```````` -M.8`!```````"````-@$``/S_________4(`!```````+`````@```,"%```` -M````;H`!```````"````-@$``/S_________B(`!```````+`````@```&"( -M````````IH`!```````"````-@$``/S_________X8`!```````+`````@`` -M`*B(````````<8D!```````"````A````/S_________DHD!```````"```` -MA````/S_________LXD!```````"````A````/S_________U(P!```````" -M````S@```/S_________](P!```````"````S@```/S_________"HT!```` -M```"````S@```/S_________+XT!```````+`````0```%N)`0``````.HT! -M```````+`````0```&QZ`0``````18T!```````+`````0```-"``0`````` -M4(T!```````+`````0```$Y[`0``````6XT!```````+`````0```"Y^`0`` -M````9HT!```````+`````0```-&'`0``````<8T!```````+`````0```$*, -M`0``````?(T!```````+````(@``````````````LHT!```````+`````@`` -M``")````````XHT!```````"````-@$``/S_________^(T!```````+```` -M`@```."+````````!(X!```````+`````@```.2+````````&(X!```````" -M````-@$``/S_________*XX!```````+`````@```."/````````68X!```` -M```"````-@$``/S_________2H\!```````"````,````/S_________T8\! -M```````"````,````/S_________NI`!```````"````,````/S_________ -MRY`!```````"````,````/S_________89(!```````+`````@```.22```` -M````?Y(!```````+`````@```/"2````````IY(!```````+`````@```!"3 -M````````SY(!```````+`````@```$"3````````%9,!```````"````>``` -M`/S_________,I,!```````"````>````/S_________3Y,!```````"```` -M>````/S_________?9,!```````"````,````/S_________MY,!```````" -M````>````/S_________U),!```````"````>````/S_________Y),!```` -M```+`````@```,"6````````$)0!```````+`````@```."2````````+90! -M```````"````-@$``/S_________1)0!```````+`````@```/"2```````` -M8I0!```````"````-@$``/S_________>90!```````+`````@```!"3```` -M````EY0!```````"````-@$``/S_________KI0!```````+`````@```$"3 -M````````S)0!```````"````-@$``/S_________YI0!```````+`````@`` -M`,"6````````!Y4!```````"````-@$``/S_________0I4!```````+```` -M`@````B7````````UIT!```````"````A````/S_________]YT!```````" -M````A````/S_________&)X!```````"````A````/S_________(*$!```` -M```"````S@```/S_________0*$!```````"````S@```/S_________5J$! -M```````"````S@```/S_________>Z$!```````+`````0```,"=`0`````` -MAJ$!```````+`````0```)2-`0``````D:$!```````+`````0```#&5`0`` -M````G*$!```````+`````0```'..`0``````IZ$!```````+`````0```">1 -M`0``````LJ$!```````+`````0```#6<`0``````O:$!```````+`````0`` -M`(Z@`0``````R*$!```````+````(@``````````````"``````````!```` -M`0```'$'````````$``````````!`````0```(@(````````&``````````! -M`````0```(@(````````(``````````!`````0```(@(````````*``````` -M```!`````0```'H'````````,``````````!`````0```(@(````````.``` -M```````!`````0```(8'````````0``````````!`````0```),'```````` -M2``````````!`````0```)<(````````4``````````!`````0```)H'```` -M````6``````````!`````0```*$'````````8``````````!`````0```-(' -M````````:``````````!`````0```+0'````````<``````````!`````0`` -M`,8'````````>``````````!`````0```,P'````````@``````````!```` -M`0```-H'````````B``````````!`````0```)<(````````D``````````! -M`````0```)<(````````F``````````!`````0```!P(````````H``````` -M```!`````0```",(````````J``````````!`````0```(@(````````L``` -M```````!`````0```"H(````````N``````````!`````0```(@(```````` -MP``````````!`````0```#$(````````R``````````!`````0```#@(```` -M````T``````````!`````0```$((````````V``````````!`````0```)<( -M````````X``````````!`````0```)<(````````Z``````````!`````0`` -M`(@(````````\``````````!`````0```)<(````````^``````````!```` -M`0```'L(``````````$````````!`````0```)<(````````"`$````````! -M`````0```)<(````````$`$````````!`````0```)<(````````&`$````` -M```!`````0```(X(````````&`(````````!````#0$`````````````(`(` -M```````!````90``````````````*`(````````!````P0`````````````` -M,`(````````!````M```````````````.`(````````!````>P$````````` -M````0`(````````!````U```````````````2`(````````!````50`````` -M````````4`(````````!````X```````````````6`(````````!````H0`` -M````````````8`(````````!````>`$`````````````:`(````````!```` -M2P$`````````````<`(````````!````O@``````````````>`(````````! -M````/P``````````````@`(````````!````A0``````````````B`(````` -M```!````6```````````````D`(````````!````(0``````````````F`(` -M```````!````:0$`````````````H`(````````!````D@$````````````` -MJ`(````````!````+P``````````````L`(````````!````C0`````````` -M````N`(````````!````2`$`````````````P`(````````!````*@`````` -M````````R`(````````!````/0``````````````T`(````````!````:0`` -M````````````V`(````````!````?P$`````````````X`(````````!```` -M>@$`````````````Z`(````````!````&@$`````````````\`(````````! -M````M0``````````````^`(````````!````8`$```````````````,````` -M```!````8P$`````````````"`,````````!````"@$`````````````$`,` -M```````!````W0``````````````&`,````````!````/0$````````````` -M(`,````````!````D0``````````````*`,````````!`````,````` -M```!````-`$`````````````@`,````````!````Z@``````````````B`,` -M```````!````70$`````````````D`,````````!````30$````````````` -MF`,````````!````+`$`````````````H`,````````!````,P`````````` -M````J`,````````!````M@``````````````L`,````````!````6P$````` -M````````N`,````````!````'`$`````````````P`,````````!````)0$` -M````````````R`,````````!````/@``````````````T`,````````!```` -M=0``````````````V`,````````!````10$`````````````X`,````````! -M````Y0``````````````Z`,````````!````4```````````````\`,````` -M```!````-P``````````````^`,````````!````C`````````````````0` -M```````!````"@``````````````"`0````````!````]@`````````````` -M$`0````````!````/@$`````````````&`0````````!````-0$````````` -M````(`0````````!````]P``````````````*`0````````!````@`$````` -M````````,`0````````!````:@``````````````.`0````````!````#``` -M````````````0`0````````!````90$`````````````2`0````````!```` -MK0``````````````4`0````````!````$`$`````````````6`0````````! -M````&0$`````````````8`0````````!````;P$`````````````:`0````` -M```!````,P$`````````````<`0````````!````IP``````````````>`0` -M```````!````1@``````````````@`0````````!````+@$````````````` -MB`0````````!````%```````````````D`0````````!````O``````````` -M````F`0````````!````<```````````````H`0````````!````^0`````` -M````````J`0````````!````^P``````````````L`0````````!````4@$` -M````````````N`0````````!````9`$`````````````P`0````````!```` -M?@$`````````````R`0````````!````$```````````````T`0````````! -M````3P$`````````````V`0````````!````(P$`````````````X`0````` -M```!````#`$`````````````Z`0````````!````H@``````````````\`0` -M```````!````4`$`````````````^`0````````!`````0```"E4```````` -M``4````````!````D`$`````````````"`4````````!````*P$````````` -M````&`4````````!````6P$`````````````(`4````````!````'`$````` -M````````*`4````````!````)0$`````````````,`4````````!````/@`` -M````````````.`4````````!````=0``````````````0`4````````!```` -M`0```$94````````&!P````````!````1@$`````````````(!P````````! -M````9@$`````````````*!P````````!````6`$`````````````,!P````` -M```!````?0$`````````````.!P````````!````9```````````````0!P` -M```````!````=@``````````````2!P````````!````E``````````````` -M4!P````````!````;0``````````````6!P````````!````#@`````````` -M````8!P````````!````-@``````````````:!P````````!````8@`````` -M````````!P````````!````.@`` -M````````````@!P````````!````;`$`````````````B!P````````!```` -M#@$`````````````D!P````````!````B`$`````````````F!P````````! -M````@@``````````````H!P````````!````=@$`````````````J!P````` -M```!`````P$`````````````L!P````````!````JP``````````````N!P` -M```````!````*`$`````````````P!P````````!````(P`````````````` -MR!P````````!````"`$`````````````T!P````````!````&@`````````` -M````V!P````````!````:`$`````````````X!P````````!````Z``````` -M````````Z!P````````!````(```````````````\!P````````!````*P`` -M````````````^!P````````!````K@```````````````!T````````!```` -M?`$`````````````"!T````````!````:@$`````````````$!T````````! -M````=P$`````````````&!T````````!````.@$`````````````(!T````` -M```!````\P``````````````*!T````````!``````$`````````````,!T` -M```````!````[P``````````````.!T````````!````$P$````````````` -M0!T````````!````?@``````````````2!T````````!````F0`````````` -M````4!T````````!````=```````````````6!T````````!````2@$````` -M````````8!T````````!````H```````````````:!T````````!````00`` -M````````````!T````````!```` -M-P$`````````````@!T````````!````>@``````````````B!T````````! -M````.P``````````````D!T````````!````3@$`````````````F!T````` -M```!````W@``````````````H!T````````!````+P$`````````````J!T` -M```````!````Y```````````````L!T````````!````Q``````````````` -MN!T````````!````XP``````````````P!T````````!````0@$````````` -M````R!T````````!````SP``````````````T!T````````!````.``````` -M````````V!T````````!````80``````````````X!T````````!````V0`` -M````````````Z!T````````!````1P$`````````````\!T````````!```` -M50$`````````````^!T````````!````)P$``````````````!X````````! -M````'0``````````````"!X````````!````7```````````````$!X````` -M```!````,0$`````````````&!X````````!````D0$`````````````(!X` -M```````!````20``````````````*!X````````!````FP`````````````` -M,!X````````!````80$`````````````.!X````````!````U0`````````` -M````0!X````````!````!0$`````````````2!X````````!````'P`````` -M````````4!X````````!````_```````````````6!X````````!````.0`` -M````````````8!X````````!`````0$`````````````:!X````````!```` -M[```````````````!X````````! -M````*```````````````@!X````````!````40``````````````B!X````` -M```!````DP``````````````D!X````````!````W```````````````F!X` -M```````!````S```````````````H!X````````!````5P$````````````` -MJ!X````````!````RP``````````````L!X````````!````4@$````````` -M````N!X````````!````C@$`````````````P!X````````!````"0`````` -M````````R!X````````!````HP``````````````T!X````````!````<0`` -M````````````V!X````````!````:P``````````````X!X````````!```` -M\```````````````Z!X````````!````]```````````````\!X````````! -M````!P$`````````````^!X````````!`````0```/>&`````````!\````` -M```!````+0$`````````````"!\````````!````20$`````````````&!\` -M```````!````Q```````````````(!\````````!````XP`````````````` -M*!\````````!````0@$`````````````,!\````````!````SP`````````` -M````.!\````````!````.```````````````0!\````````!`````0```"^' -M````````^#T````````!`````0```&ZW`````````#X````````!`````0`` -M`&ZW````````"#X````````!`````0```)6W````````$#X````````!```` -M`0```)6W````````&#X````````!`````0```+RW````````(#X````````! -M`````0```+RW````````*#X````````!`````0```..W````````,#X````` -M```!`````0```..W````````F#\````````!````6P``````````````H#\` -M```````!````@0``````````````J#\````````!````=`$````````````` -ML#\````````!````;```````````````N#\````````!````10`````````` -M````P#\````````!````V```````````````R#\````````!````N0`````` -M````````T#\````````!````'0$`````````````V#\````````!````K``` -M````````````X#\````````!````5```````````````Z#\````````!```` -MG@``````````````\#\````````!````5P``````````````^#\````````! -M````!`$``````````````$`````````!````7P$`````````````"$`````` -M```!````BP``````````````$$`````````!````_P``````````````&$`` -M```````!````Y@``````````````($`````````!````EP$````````````` -M*$`````````!````C0$`````````````,$`````````!````N@`````````` -M````.$`````````!````?0``````````````0$`````````!````)`$````` -M````````2$`````````!````*0``````````````4$`````````!````7@$` -M````````````6$`````````!````4P$`````````````8$`````````!```` -MAP``````````````:$`````````!````8@$`````````````<$`````````! -M````7P``````````````>$`````````!````0`$`````````````@$`````` -M```!`````@$`````````````B$`````````!````_0``````````````D$`` -M```````!````$P``````````````F$`````````!````;0$````````````` -MH$`````````!````>P``````````````J$`````````!````X0`````````` -M````L$`````````!````<@$`````````````N$`````````!````V@`````` -M````````P$`````````!````EP``````````````R$`````````!````,@$` -M````````````T$`````````!````^@``````````````V$`````````!```` -M$0``````````````X$`````````!````G0``````````````Z$`````````! -M````"P``````````````\$`````````!````F```````````````^$`````` -M```!````/P$``````````````$$````````!````L0``````````````"$$` -M```````!````Z0``````````````$$$````````!````0``````````````` -M&$$````````!````(`$`````````````($$````````!````I``````````` -M````*$$````````!````L@``````````````,$$````````!````&`$````` -M````````.$$````````!````3@``````````````0$$````````!````0P$` -M````````````2$$````````!````40$`````````````4$$````````!```` -M%0$`````````````6$$````````!````DP$`````````````8$$````````! -M````2@``````````````:$$````````!````QP``````````````<$$````` -M```!````J0``````````````>$$````````!````@P$`````````````@$$` -M```````!````30``````````````B$$````````!````CP`````````````` -MD$$````````!````AP$`````````````F$$````````!````J``````````` -M````H$$````````!````S0``````````````J$$````````!````0P`````` -M````````L$$````````!````3```````````````N$$````````!````+@`` -M````````````P$$````````!````0@``````````````R$$````````!```` -M/```````````````T$$````````!````ZP``````````````V$$````````! -M````1P``````````````X$$````````!````@```````````````Z$$````` -M```!````-0``````````````\$$````````!````-```````````````^$$` -M```````!````&0```````````````$(````````!````$(````````!````Q@`````````````` -M@$(````````!````[0``````````````B$(````````!````BP$````````` -M````F$(````````!````&`$`````````````H$(````````!````3@`````` -M````````J$(````````!````0P$`````````````L$(````````!````40$` -M````````````N$(````````!````%0$`````````````P$(````````!```` -ME`$`````````````T$(````````!`````0```,7+````````J%,````````! -M`````0```"/B````````L%,````````!`````0```.3A````````N%,````` -M```!`````0```.SA````````P%,````````!`````0```%CB````````R%,` -M```````!`````0```/KA````````T%,````````!`````0```%#B```````` -M,%0````````!`````0```"+S````````.%0````````!`````0````GQ```` -M````0%0````````!`````0```#WQ````````2%0````````!`````0```%WQ -M````````4%0````````!`````0```"+S````````6%0````````!`````0`` -M`+/Q````````8%0````````!`````0```"+S````````:%0````````!```` -M`0```"+S````````<%0````````!`````0```"+S````````>%0````````! -M`````0```"+S````````@%0````````!`````0```"+S````````B%0````` -M```!`````0```-OQ````````D%0````````!`````0```"+S````````F%0` -M```````!`````0```"+S````````H%0````````!`````0```"+S```````` -MJ%0````````!`````0```"+S````````L%0````````!`````0```.;Q```` -M````N%0````````!`````0````7R````````P%0````````!`````0```"+S -M````````R%0````````!`````0```$#R````````T%0````````!`````0`` -M`&+R````````V%0````````!`````0```"+S````````X%0````````!```` -M`0```(7Q````````Z%0````````!`````0```"+S````````\%0````````! -M`````0```"+S````````^%0````````!`````0```"+S`````````%4````` -M```!`````0```)CR````````"%4````````!`````0```*/R````````$%4` -M```````!`````0```"+S````````&%4````````!`````0```+/R```````` -M(%4````````!`````0```!OS````````*%4````````!`````0```!OS```` -M````,%4````````!`````0```/SR````````.%4````````!`````0````+S -M````````0%4````````!`````0````CS````````2%4````````!`````0`` -M``[S````````4%4````````!`````0```!3S````````@%4````````!```` -M`0```,+T````````B%4````````!`````0```,+T````````D%4````````! -M`````0```%OS````````F%4````````!`````0```'WS````````H%4````` -M```!`````0```,+T````````J%4````````!`````0```+CS````````L%4` -M```````!`````0```,+T````````N%4````````!`````0```,+T```````` -MP%4````````!`````0```,+T````````R%4````````!`````0```,+T```` -M````T%4````````!`````0```,+T````````V%4````````!`````0```.+S -M````````X%4````````!`````0```,+T````````Z%4````````!`````0`` -M`,+T````````\%4````````!`````0```,+T````````^%4````````!```` -M`0```,+T`````````%8````````!`````0```/?S````````"%8````````! -M`````0```,+T````````$%8````````!`````0```,+T````````&%8````` -M```!`````0````KT````````(%8````````!`````0```*#T````````*%8` -M```````!`````0```,+T````````,%8````````!`````0```,+T```````` -M.%8````````!`````0```,+T````````0%8````````!`````0```,+T```` -M````2%8````````!`````0```,+T````````4%8````````!`````0```"ST -M````````6%8````````!`````0```"ST````````8%8````````!`````0`` -M`,+T````````:%8````````!`````0```(3T````````$&(````````!```` -M`0````U(`0``````&&(````````!`````0```)M#`0``````(&(````````! -M`````0```')$`0``````*&(````````!`````0````9&`0``````,&(````` -M```!`````0```&1&`0``````.&(````````!`````0```-M&`0``````0&(` -M```````!`````0```'9'`0``````B&\````````!`````0```#Y3`0`````` -MD&\````````!`````0```$)3`0``````F&\````````!`````0```$=3`0`` -M````H&\````````!`````0```$Q3`0``````J&\````````!`````0```%Y3 -M`0``````L&\````````!`````0```%Y3`0``````N&\````````!`````0`` -M`%%3`0``````P&\````````!`````0```%93`0``````.'P````````!```` -M`0```-]D`0``````0'P````````!`````0```,1D`0``````2'P````````! -M`````0```,AD`0``````4'P````````!`````0```,UD`0``````6'P````` -M```!`````0```-]D`0``````8'P````````!`````0```-]D`0``````:'P` -M```````!`````0```-)D`0``````<'P````````!`````0```-=D`0`````` -MJ(@````````!`````0```/V``0``````L(@````````!`````0```.6``0`` -M````N(@````````!`````0```.F``0``````P(@````````!`````0```.Z` -M`0``````R(@````````!`````0```/V``0``````T(@````````!`````0`` -M`/V``0``````V(@````````!`````0```/.``0``````X(@````````!```` -M`0```/B``0``````")<````````!`````0```&&5`0``````$)<````````! -M`````0```$:5`0``````&)<````````!`````0```$J5`0``````()<````` -M```!`````0```$^5`0``````*)<````````!`````0```&&5`0``````,)<` -M```````!`````0```&&5`0``````.)<````````!`````0```%25`0`````` -M0)<````````!`````0```%F5`0``````(``````````!`````P`````````` -M````*``````````!`````P````<`````````,``````````!`````P````X` -M````````.``````````!`````P```!4`````````0``````````!`````P`` -M`!P`````````2``````````!`````P```",`````````4``````````!```` -M`P```"H`````````(``````````!`````0``````````````.``````````! -M`````0```!8!````````6``````````!`````0```$,!````````>``````` -M```!`````0```%`"````````D``````````!`````0```%P"````````R``` -M```````!`````0```*T"````````X``````````!`````0```,X"```````` -M^``````````!`````0```*,$````````$`$````````!`````0```/<$```` -M````,`$````````!`````0```#L&````````4`$````````!`````0```&(& -M````````<`$````````!`````0```*8&````````J`$````````!`````0`` -M`%@'````````P`$````````!`````0```)T(````````V`$````````!```` -M`0````P)````````^`$````````!`````0```'`)````````&`(````````! -M`````0````0*````````,`(````````!`````0```#@+````````2`(````` -M```!`````0```*`+````````<`(````````!`````0```!(,````````R`(` -M```````!`````0```&@-````````Z`(````````!`````0```-0-```````` -M``,````````!`````0```!@.````````&`,````````!`````0```#T.```` -M````2`,````````!`````0```-L0````````<`,````````!`````0```+\1 -M````````D`,````````!`````0```"(4````````T`,````````!`````0`` -M`*H8````````^`,````````!`````0```.X8````````$`0````````!```` -M`0```%<9````````4`0````````!`````0```'`<````````!`````0```"T_````````F`<` -M```````!`````0```'\_````````L`<````````!`````0```+<_```````` -M\`<````````!`````0```')!````````"`@````````!`````0```)]!```` -M````(`@````````!`````0```,]!````````4`@````````!`````0```/A( -M````````<`@````````!`````0```+%)````````D`@````````!`````0`` -M`-Q)````````N`@````````!`````0```-!*````````V`@````````!```` -M`0```/5*````````&`D````````!`````0```'Q+````````.`D````````! -M`````0```!!,````````6`D````````!`````0```(=,````````B`D````` -M```!`````0````M-````````N`D````````!`````0```(]-````````\`D` -M```````!`````0```.Q-````````,`H````````!`````0```!M4```````` -M4`H````````!`````0```"E4````````:`H````````!`````0```$94```` -M````@`H````````!`````0```$Q4````````L`H````````!`````0```+A4 -M````````R`H````````!`````0```/E4````````Z`H````````!`````0`` -M`%U5``````````L````````!`````0```)15````````,`L````````!```` -M`0```(!6````````2`L````````!`````0```)-6````````8`L````````! -M`````0```.Y6````````>`L````````!`````0```/56````````J`L````` -M```!`````0```'Q7````````P`L````````!`````0```()7````````V`L` -M```````!`````0```+!7````````\`L````````!`````0```$E8```````` -M"`P````````!`````0```-!8````````2`P````````!`````0```'Q:```` -M````:`P````````!`````0```)Q:````````B`P````````!`````0```+M: -M````````J`P````````!`````0```-A:````````P`P````````!`````0`` -M`-Y:````````X`P````````!`````0```$%;````````^`P````````!```` -M`0```');````````$`T````````!`````0```'A;````````.`T````````! -M`````0```-);````````4`T````````!`````0```/];````````:`T````` -M```!`````0```"-<````````@`T````````!`````0```$]<````````F`T` -M```````!`````0```&Y<````````N`T````````!`````0```-5<```````` -MT`T````````!`````0````A=````````Z`T````````!`````0```"!=```` -M``````X````````!`````0```$Y=````````&`X````````!`````0```%1= -M````````,`X````````!`````0```%U=````````6`X````````!`````0`` -M``E>````````<`X````````!`````0```#%>````````B`X````````!```` -M`0```#Q>````````H`X````````!`````0```%)>````````N`X````````! -M`````0```(=>````````T`X````````!`````0```*A>````````Z`X````` -M```!`````0```.E>````````$`\````````!`````0```%M?````````,`\` -M```````!`````0```'E?````````6`\````````!`````0```!!@```````` -M>`\````````!`````0```"Y@````````D`\````````!`````0```#Q@```` -M````J`\````````!`````0```(9@````````T`\````````!`````0```"!A -M````````\`\````````!`````0```$%A````````"!`````````!`````0`` -M`$=A````````(!`````````!`````0```$AA````````.!`````````!```` -M`0```$YA````````4!`````````!`````0```$]A````````:!`````````! -M`````0```%!A````````B!`````````!`````0```'1A````````J!`````` -M```!`````0```*]A````````X!`````````!`````0```,!A````````^!`` -M```````!`````0```.]A````````(!$````````!`````0```()B```````` -M.!$````````!`````0```+%B````````8!$````````!`````0```"!C```` -M````D!$````````!`````0```#1C````````R!$````````!`````0```&AC -M````````X!$````````!`````0```'!C````````^!$````````!`````0`` -M`'AC````````$!(````````!`````0```(1C````````.!(````````!```` -M`0```,]C````````4!(````````!`````0```.-C````````:!(````````! -M`````0```/=C````````@!(````````!`````0````QD````````F!(````` -M```!`````0```%YD````````L!(````````!`````0```+!D````````R!(` -M```````!`````0```+MD````````X!(````````!`````0```-=D```````` -M^!(````````!`````0```!)E````````*!,````````!`````0```#!F```` -M````:!,````````!`````0```"9L````````@!,````````!`````0```)IL -M````````H!,````````!`````0```*YL````````P!,````````!`````0`` -M`,9L````````X!,````````!`````0```"QM`````````!0````````!```` -M`0````9N````````0!0````````!`````0```"EP````````:!0````````! -M`````0```)UP````````@!0````````!`````0```$IQ````````H!0````` -M```!`````0```"]R````````N!0````````!`````0```$=R````````^!0` -M```````!`````0```"]U````````*!4````````!`````0```/EW```````` -M2!4````````!`````0```&UX````````8!4````````!`````0```(EX```` -M````B!4````````!`````0````]Y````````H!4````````!`````0```!5Y -M````````T!4````````!`````0```!QY````````\!4````````!`````0`` -M`$EY````````$!8````````!`````0```'QY````````.!8````````!```` -M`0```%EZ````````4!8````````!`````0```+=Z````````:!8````````! -M`````0```!=]````````@!8````````!`````0```$!]````````F!8````` -M```!`````0```(%]````````P!8````````!`````0```!-^````````V!8` -M```````!`````0```'I^````````\!8````````!`````0```*Q^```````` -M&!<````````!`````0```$1_````````,!<````````!`````0```/-_```` -M````2!<````````!`````0```/E_````````8!<````````!`````0````&` -M````````>!<````````!`````0```$N`````````D!<````````!`````0`` -M`-J`````````P!<````````!`````0```-R`````````\!<````````!```` -M`0```.B`````````$!@````````!`````0```$.!````````4!@````````! -M`````0```.:%````````&````````J!@````````!`````0```"^'````````P!@` -M```````!`````0```#6'````````"!D````````!`````0```"R(```````` -M(!D````````!`````0```&V(````````0!D````````!`````0```-V(```` -M````6!D````````!`````0```!2)````````B!D````````!`````0````2* -M````````H!D````````!`````0```!>*````````N!D````````!`````0`` -M`,.*````````T!D````````!`````0```,J*`````````!H````````!```` -M`0```&B+````````&!H````````!`````0```&Z+````````,!H````````! -M`````0```)R+````````2!H````````!`````0```#6,````````8!H````` -M```!`````0```+R,````````J!H````````!`````0```'2.````````R!H` -M```````!`````0```)2.````````Z!H````````!`````0```+..```````` -M"!L````````!`````0```-".````````(!L````````!`````0```-:.```` -M````0!L````````!`````0```$./````````6!L````````!`````0```'2/ -M````````3````````B!T````````!`````0```.63````````H!T````````! -M`````0```"^4````````R!T````````!`````0```,F4````````Z!T````` -M```!`````0```.J4`````````!X````````!`````0```/"4````````&!X` -M```````!`````0```/&4````````,!X````````!`````0```/>4```````` -M2!X````````!`````0```/B4````````8!X````````!`````0```/F4```` -M````>!X````````!`````0````F5````````D!X````````!`````0```!>5 -M````````J!X````````!`````0```"65````````P!X````````!`````0`` -M`"R5````````X!X````````!`````0```%.5`````````!\````````!```` -M`0```'R5````````(!\````````!`````0```*N5````````6!\````````! -M`````0```,25````````@!\````````!`````0```%>6````````F!\````` -M```!`````0```(:6````````L!\````````!`````0```+66````````V!\` -M```````!`````0```"27````````""`````````!`````0```#B7```````` -M0"`````````!`````0```("7````````6"`````````!`````0```(B7```` -M````<"`````````!`````0```)"7````````B"`````````!`````0```)R7 -M````````J"`````````!`````0```,R7````````P"`````````!`````0`` -M`."7````````V"`````````!`````0```/27````````\"`````````!```` -M`0````F8````````""$````````!`````0```%N8````````("$````````! -M`````0```*V8````````."$````````!`````0```+B8````````4"$````` -M```!`````0```,.8````````:"$````````!`````0```/Z8````````F"$` -M```````!`````0```-R9````````V"$````````!`````0```'RB```````` -M^"$````````!`````0```(^B````````&"(````````!`````0```-2B```` -M````."(````````!`````0```'VD````````8"(````````!`````0```."E -M````````B"(````````!`````0```%FF````````N"(````````!`````0`` -M`%JG````````T"(````````!`````0```':G````````^"(````````!```` -M`0```!NH````````$",````````!`````0```&JH````````,",````````! -M`````0```,^H````````6",````````!`````0```(:I````````<",````` -M```!`````0```,NI````````L",````````!`````0```!&M````````R",` -M```````!`````0```""N`````````"0````````!`````0```(RP```````` -M&"0````````!`````0```*ZP````````6"0````````!`````0```"ZR```` -M````F"0````````!`````0```("U````````V"0````````!`````0```-NY -M`````````"4````````!`````0```$V[````````&"4````````!`````0`` -M`*V[````````."4````````!`````0```%*\````````4"4````````!```` -M`0```.^\````````<"4````````!`````0```#*]````````B"4````````! -M`````0```'2]````````H"4````````!`````0```.N]````````N"4````` -M```!`````0```!&^````````X"4````````!`````0```+J^````````^"4` -M```````!`````0```-*^````````$"8````````!`````0```.B_```````` -M*"8````````!`````0```"K`````````0"8````````!`````0```)#````` -M````>"8````````!`````0```*3`````````H"8````````!`````0```$W! -M````````P"8````````!`````0```'K!````````X"8````````!`````0`` -M`*W!````````""<````````!`````0```*'"````````("<````````!```` -M`0```!'#````````0"<````````!`````0```(+#````````8"<````````! -M`````0```$?'````````>"<````````!`````0```%;'````````D"<````` -M```!`````0```&K'````````J"<````````!`````0```(/'````````P"<` -M```````!`````0```+3'````````Z"<````````!`````0```!C(```````` -M`"@````````!`````0```*C(````````&"@````````!`````0```*[(```` -M````,"@````````!`````0```+;(````````2"@````````!`````0````#) -M````````8"@````````!`````0```+;)````````D"@````````!`````0`` -M`+C)````````P"@````````!`````0```.C)````````V"@````````!```` -M`0```'7*````````^"@````````!`````0```-#*````````&"D````````! -M`````0```,7+````````,"D````````!`````0```-?+````````:"D````` -M```!`````0```,?,````````@"D````````!`````0````S-````````P"D` -M```````!`````0```*73````````X"D````````!`````0```/33```````` -M`"H````````!`````0```.O4````````&"H````````!`````0```"S5```` -M````2"H````````!`````0```"S9````````:"H````````!`````0```$+9 -M````````F"H````````!`````0``` ````````N"H````````!`````0`` -M`._9````````V"H````````!`````0```%_:````````\"H````````!```` -M`0```);:````````("L````````!`````0```-C;````````6"L````````! -M`````0```$C<````````<"L````````!`````0```&K<````````B"L````` -M```!`````0```([<````````H"L````````!`````0```+K<````````N"L` -M```````!`````0```-G<````````\"L````````!`````0```#S=```````` -M""P````````!`````0```%#=````````("P````````!`````0```,/>```` -M````."P````````!`````0```,K>````````:"P````````!`````0```-C? -M````````@"P````````!`````0```.#?````````F"P````````!`````0`` -M`!'@````````L"P````````!`````0````?A````````R"P````````!```` -M`0```)+A````````("T````````!`````0```$3E````````0"T````````! -M`````0```&3E````````8"T````````!`````0```(/E````````@"T````` -M```!`````0```*/E````````H"T````````!`````0```!'F````````N"T` -M```````!`````0```$+F````````T"T````````!`````0```)OF```````` -M^"T````````!`````0```![G````````$"X````````!`````0```#[G```` -M````,"X````````!`````0```,_G````````2"X````````!`````0```/?G -M````````8"X````````!`````0````+H````````>"X````````!`````0`` -M`"+H````````D"X````````!`````0```)GH````````J"X````````!```` -M`0```,[H````````P"X````````!`````0````/I````````V"X````````! -M`````0```$3I````````\"X````````!`````0```$KI````````""\````` -M```!`````0```%KI````````("\````````!`````0```&CI````````."\` -M```````!`````0```';I````````4"\````````!`````0```'WI```````` -M<"\````````!`````0```*3I````````B"\````````!`````0```*KI```` -M````L"\````````!`````0```!SJ````````T"\````````!`````0```#KJ -M````````^"\````````!`````0```-'J````````&#`````````!`````0`` -M`._J````````,#`````````!`````0```/WJ````````2#`````````!```` -M`0```$?K````````<#`````````!`````0```.'K````````D#`````````! -M`````0````+L````````J#`````````!`````0```$/L````````R#`````` -M```!`````0```&KM````````Z#`````````!`````0```'[M`````````#$` -M```````!`````0```*#M````````(#$````````!`````0```+[O```````` -M0#$````````!`````0```*GP````````6#$````````!`````0```-KP```` -M````>#$````````!`````0```#OS````````F#$````````!`````0```,ST -M````````T#$````````!`````0```.3T````````^#$````````!`````0`` -M`'?U````````$#(````````!`````0```*OU````````*#(````````!```` -M`0```-_U````````4#(````````!`````0```$[V````````@#(````````! -M`````0```&3V````````N#(````````!`````0```$#W````````T#(````` -M```!`````0```$CW````````Z#(````````!`````0```%#W`````````#,` -M```````!`````0```%SW````````(#,````````!`````0```(SW```````` -M0#,````````!`````0```+?W````````8#,````````!`````0```-CW```` -M````>#,````````!`````0```.WW````````D#,````````!`````0```#_X -M````````J#,````````!`````0```)'X````````P#,````````!`````0`` -M`+OX````````V#,````````!`````0```!7Y````````\#,````````!```` -M`0```$7Y````````*#0````````!`````0```%CZ````````:#0````````! -M`````0```*4'`0``````@#0````````!`````0````4(`0``````H#0````` -M```!`````0```!P(`0``````X#0````````!`````0```$4*`0``````^#0` -M```````!`````0```+@*`0``````````````!`````0```,L*`0`````` -M.#4````````!`````0```/H*`0``````8#4````````!`````0```$H-`0`` -M````F#4````````!`````0```.0/`0``````P#4````````!`````0```*`0 -M`0``````V#4````````!`````0```+P0`0``````\#4````````!`````0`` -M``L1`0``````````````!`````0```(01`0``````,#8````````!```` -M`0````@2`0``````8#8````````!`````0```+,2`0``````>#8````````! -M`````0```.D3`0``````F#8````````!`````0```&84`0``````V#8````` -M```!`````0```+88`0``````&#<````````!`````0```'X>`0``````,#<` -M```````!`````0```$0?`0``````4#<````````!`````0```'`?`0`````` -M@#<````````!`````0```*4B`0``````P#<````````!`````0```!#L````` -M```!`````0```-@[`0``````D#L````````!`````0```/$[`0``````J#L` -M```````!`````0```"(\`0``````V#L````````!`````0```)`]`0`````` -M\#L````````!`````0```,D^`0``````"#P````````!`````0```#`_`0`` -M````(#P````````!`````0```#@_`0``````.#P````````!`````0```*$_ -M`0``````4#P````````!`````0```.-``0``````@#P````````!`````0`` -M`/A``0``````H#P````````!`````0```$U!`0``````P#P````````!```` -M`0```(9!`0``````V#P````````!`````0```-M!`0``````\#P````````! -M`````0```.-!`0``````$#T````````!`````0```/Q!`0``````.#T````` -M```!`````0```#-#`0``````6#T````````!`````0```&-#`0``````@#T` -M```````!`````0```"=(`0``````H#T````````!`````0```,Y(`0`````` -MP#T````````!`````0```.9)`0``````X#T````````!`````0```(Y*`0`` -M````$#X````````!`````0```*-,`0``````.#X````````!`````0```'1- -M`0``````6#X````````!`````0```,--`0``````>#X````````!`````0`` -M`$E.`0``````D#X````````!`````0```,%.`0``````T#X````````!```` -M`0```,Q0`0```````#\````````!`````0```!Q1`0``````0#\````````! -M`````0```/M1`0``````<#\````````!`````0```"E3`0``````B#\````` -M```!`````0```&13`0``````R#\````````!`````0```&A9`0``````Z#\` -M```````!`````0```.]9`0``````*$`````````!`````0```*%=`0`````` -M4$`````````!`````0````%?`0``````:$`````````!`````0```&E?`0`` -M````B$`````````!`````0```*Q?`0``````J$`````````!`````0```/1? -M`0``````P$`````````!`````0```/I?`0``````V$`````````!`````0`` -M`"M@`0``````$$$````````!`````0```/!@`0``````4$$````````!```` -M`0```,]A`0``````B$$````````!`````0```*]D`0``````H$$````````! -M`````0```.5D`0``````X$$````````!`````0```%5L`0``````($(````` -M```!`````0```#QS`0``````.$(````````!`````0```'ES`0``````4$(` -M```````!`````0```.IS`0``````D$(````````!`````0```+)T`0`````` -MJ$(````````!`````0```&AU`0``````T$(````````!`````0```&-V`0`` -M````\$(````````!`````0```*MV`0``````"$,````````!`````0```#!W -M`0``````2$,````````!`````0```"-Y`0``````B$,````````!`````0`` -M`)MY`0``````P$,````````!`````0```&QZ`0```````$0````````!```` -M`0```$Y[`0``````.$0````````!`````0```"Y^`0``````>$0````````! -M`````0```-"``0``````D$0````````!`````0````.!`0``````J$0````` -M```!`````0```("!`0``````Z$0````````!`````0```*."`0```````$4` -M```````!`````0```.""`0``````0$4````````!`````0```-&'`0`````` -M>$4````````!`````0```%N)`0``````F$4````````!`````0```,2)`0`` -M````L$4````````!`````0```/.)`0``````R$4````````!`````0```"** -M`0``````"$8````````!`````0```$*,`0``````2$8````````!`````0`` -M`+J,`0``````@$8````````!`````0```)2-`0``````P$8````````!```` -M`0```'..`0``````^$8````````!`````0```">1`0``````.$<````````! -M`````0```#&5`0``````4$<````````!`````0```&>5`0``````:$<````` -M```!`````0```.25`0``````J$<````````!`````0````>7`0``````P$<` -M```````!`````0```$27`0```````$@````````!`````0```#6<`0`````` -M.$@````````!`````0```,"=`0``````6$@````````!`````0```"F>`0`` -M````<$@````````!`````0```%B>`0``````B$@````````!`````0```(>> -M`0``````R$@````````!`````0```(Z@`0``````"$D````````!`````0`` -)``:A`0`````` -` -end diff --git a/sys/contrib/dev/ath/public/amd64-elf.inc b/sys/contrib/dev/ath/public/amd64-elf.inc deleted file mode 100644 index e7dae082e8..0000000000 --- a/sys/contrib/dev/ath/public/amd64-elf.inc +++ /dev/null @@ -1,63 +0,0 @@ -# -# Copyright (c) 2002-2006 Sam Leffler, Errno Consulting -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer, -# without modification. -# 2. Redistributions in binary form must reproduce at minimum a disclaimer -# similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any -# redistribution must be conditioned upon including a substantially -# similar Disclaimer requirement for further binary redistribution. -# 3. Neither the names of the above-listed copyright holders nor the names -# of any contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# Alternatively, this software may be distributed under the terms of the -# GNU General Public License ("GPL") version 2 as published by the Free -# Software Foundation. -# -# NO WARRANTY -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY -# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -# THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, -# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -# THE POSSIBILITY OF SUCH DAMAGES. -# -# $Id: //depot/sw/branches/sam_hal/public/x86_64-elf.inc#1 $ -# - -# -# Compilation configuration for building x86-64-elf. -# - -# -ifndef TOOLPREFIX -TOOLPREFIX= /pub/gnu/bin/x86_64-linux- -endif -# -CC= ${TOOLPREFIX}gcc -LD= ${TOOLPREFIX}ld -STRIP= ${TOOLPREFIX}strip -OBJCOPY=${TOOLPREFIX}objcopy -NM= ${TOOLPREFIX}nm - -COPTS+= -DAH_BYTE_ORDER=AH_LITTLE_ENDIAN -# -# NB: this should come from inttypes.h but can't until we cleanp -# the definition of va_list on linux -# -COPTS+= -DAH_WORDSIZE=64 -COPTS+= -mcmodel=kernel -mno-red-zone -ifndef CONFIG_FRAME_POINTER -COPTS+= -fomit-frame-pointer -endif diff --git a/sys/contrib/dev/ath/public/amd64-elf.opt_ah.h b/sys/contrib/dev/ath/public/amd64-elf.opt_ah.h deleted file mode 100644 index de94323995..0000000000 --- a/sys/contrib/dev/ath/public/amd64-elf.opt_ah.h +++ /dev/null @@ -1,7 +0,0 @@ -#define AH_SUPPORT_AR5210 1 -#define AH_SUPPORT_AR5211 1 -#define AH_SUPPORT_AR5212 1 -#define AH_SUPPORT_5111 1 -#define AH_SUPPORT_5112 1 -#define AH_SUPPORT_2413 1 -#define AH_SUPPORT_5413 1 diff --git a/sys/contrib/dev/ath/public/i386-elf.hal.o.uu b/sys/contrib/dev/ath/public/i386-elf.hal.o.uu deleted file mode 100644 index 45a31f1498..0000000000 --- a/sys/contrib/dev/ath/public/i386-elf.hal.o.uu +++ /dev/null @@ -1,4300 +0,0 @@ -/*- - * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting, Atheros - * Communications, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the following conditions are met: - * 1. The materials contained herein are unmodified and are used - * unmodified. - * 2. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following NO - * ''WARRANTY'' disclaimer below (''Disclaimer''), without - * modification. - * 3. Redistributions in binary form must reproduce at minimum a - * disclaimer similar to the Disclaimer below and any redistribution - * must be conditioned upon including a substantially similar - * Disclaimer requirement for further binary redistribution. - * 4. Neither the names of the above-listed copyright holders nor the - * names of any contributors may be used to endorse or promote - * product derived from this software without specific prior written - * permission. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, - * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE - * FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGES. - * - * $Id: //depot/sw/branches/sam_hal/public/i386-elf.hal.o.uu#6 $ - */ -#define ATH_HAL_VERSION "0.9.20.3" -begin 644 hal.o -M?T5,1@$!`0D```````````$``P`!``````````````!#^!$/C;\```"#^`M4 -M/100``!T5.M:B?8]$Q$``'1)/1,1``!_"3T2$0``=";K0;II````/1/P``!T -M/;I]````/1OQ``!T,>LGC78`NI$```#K);J>````ZQZZJP```.L7NKX```#K -M$+K1````ZPF0N@````"-=@")T,.0BU0D!(M$)`AF@?J,%G039H'Z)Z=T#+D` -M````9H'ZMQ!U#@^WP%#HN?[__X/$!(G!B#^!$/C8X```"#^`?````ZU&0/1,1``!T3CT3$0``?R(] -M!Q$``'1O/0<1``!_"3T4$```="WK=ST2$0``=$#K;HGV/1OQ``!T-3T;\0`` -M?PD]$_```'00ZU4]&?\``'5.B?:Z$P```(/L#%%35EXN&-!```&:#>`(`>2N)VL'B!+C336(0 -M]^+!Z@:-3/H5BH&C4SZ%8G(B=.Z`````/?SC02% -M)````.MLC13=`````+C336(0]^+!Z@:-3/H5B@"Z?\```"-DWCL__^XS@$@\`/ZQ60C9-X[/__N,W,S,SWXHG0 -MP>@"B?:#Q`Q;7E]=PU.+5"0(BUPD#(N"-!```(7`=!E04NC\____@\0(#[:` -M``````^OP^L'C78`:\,6D%O#B?93BU0D"(N"-!```(7`="504NC\____@\0( -M#[:0`````(M$)`R)T[H`````]_.)P>L3C78`N*.++KKW9"0,B='!Z02)]HG( -M6\-55U93@^P$BWPD'(!_!`!U<;L`````B?;&1!\$_T.#^Q]^];L`````@S\` -M?E6-=@"-!%N-=(<@BD8(BDX+#[;0B%P7!`I&"0^VP(AFM`0``#[9``H/@ -M`8/X`1G`]]"#X`WIEP$``(H`P.@"@^`!@_@!&<"#X`WI@@$``(H`P.@#@^`! -M@_@!&<"#X`WI;0$``(H`P.@$@^`!@_@!&<"#X`WI6`$``(N!^`$``(D&N``` -M``#I1@$``(/[`70:N`````"#^P$/@C,!``"#^P)T&H/[`W0HZS@/OX'\`0`` -MB0:X`````.D4`0``#[>!_@$``(D&N`````#I`0$``(N!``(``(D&N`````#I -M[P```+@-````Z>4```"0BD`"P.@"@^`!@_@!&<"#X`WIS@```(I``L#H`X/@ -M`8/X`1G`@^`-Z;@```"X#0```.FN````#[9``8/@`8/X`1G`@^`-Z9H```"* -M0`+`Z`6#X`&#^`$9P(/@#>F$````BD`"P.@&@^`!@_@!&<"#X`WK<8/[`70? -M@_L!<@>#^P)T(^LQBD`"P.@'#[;`@_@!&<"#X`WK38.Y3!````$9P(/@#>L_ -M#[>!2!```(D&N`````#K+[@-````ZRBX#0```.LA@[EH$````1G`@^`-ZQ.+ -M0!2)!K@`````ZP>X#````(GV6U[#D%93BW0D#(M$)!"+5"04BTPD&(M<)!R# -M^!ET+8/X&7<(@_@/=`OK89"#^!YT2^M9D(/Z`W53@_D$=TZ)C@`"``"X`0`` -M`.M0D(/Z`70'@_H"=!?K-(7)#Y7`#[;`B89,$```N`$```#K+F:)CD@0``"X -M`0```.L@D(F.:!```+@!````ZQ*-=@"%VW0&QP,,````N`````!;7L.)]E57 -M5E.+;"04BUPD((M,)!R_`````(/[!W8^B?:+1"08#[<4N`^W=+@"B=#!X!`) -M\(D!@\$$@^L$BT44BP00B0&#P02#P@2#ZP0Y\G<%@_L#=^9'@_L'=\2)R"M$ -M)!Q;7E]=PY!75E.+="00BTPD%(M\)!B+1"01#_=!2+01`]_P```'8%N/\```")0Q3K",=# -M%`(```"0@WD4_W0PBU$4@?H`!```=@6Z``0``,=#&`$````Y4QAS&K@!```` -MD-'@@\@!.=!R]XE#&.L&BT$4B4,8@WD8_W0PBU$8@?H`!```=@6Z``0``,=# -M'`$````Y4QQS'K@!````D-'@@\@!.=!R]XE#'.L*QT,<_P,``(UV`&:#>1P` -M=!5FBT$<9H/X#W8%N`\```!FB4,@ZP9FQT,@"@!F@WD>`'079HM!'F:#^`]V -M!;@/````9HE#(NL(B?9FQT,B"@"+02")0R2+022)0RB+02B)0RR+02R)0S"# -M>00$=1"#>P0!=0K'0S@!````C78`N`$```!;PY"+3"0(BU0D#+@`````@WH$ -M`'1;BT(,B4$(BP*)`8M""(E!!(M"#(E!"(M"$(E!#(M"%(E!$(M"&(E!%(M" -M'(E!&&:+0B!FB4$<9HM"(F:)01Z+0B2)02"+0BB)022+0BR)02B+0C")02RX -M`0```,.05U93BWPD$(M<)!2#[`A35^C\____B<:#Q!"X`````(7V=#)F@WX6 -M`'4B4U?H_/___XG#5E?_E\`!``!F`X0;E````)B#Q!#K#(UV`&:+1A9F`T88 -MF%M>7\.-=@!55U93@^P%E95_Y7``0``C00#@\00 -M]D8#`70M9CM$)!1]6&:)1"04@^P(5E7_E<`!``!F`T869HM4)!YF*<)FB50D -M*(/$$.LR9CM$)!9]*V:)1"06@^P(5E7_E<`!``!F`T86BTPD(&:+E`F4```` -M9BG"9HE4)"J#Q!!'.[TP$```#X)'____OP````")]HT$_0`````I^(VTQ3`" -M``!F@WX6`'DE@^P(5E7_E<`!``"8@\00]D8#`70&`T0D&.L%9@-$)!IFB488 -MD$>#_S]^OH/$'%M>7UW#D)!55U93@^P4BUPD-(M,)"R+5"0PQT0D#*````"+ -M1"0H9H$X`3!V",=$)`RV````O@`````/M^H/M_F-=@"+5"0,#[<$7UW#C78`BU0D"`^WPF:!^O\`=$2+1"0$9H$X`C!W*V:# -M^CYV$0^WPHT$@`4B%0``#[?`PXGV#[?"C02`C80`[!,```^WP,.-=@`/M\*- -M!(`%P!(```^WP,.0BU0D"`^WPF:!^O\`=!^+1"0$9H$X`C!W"XV"8`D```^W -MP,.0C8+\"```#[?`PXGV55=64X/L#(ML)""+="0D9H$^_S]V&F:#?BX`=!.Z -M`0```&:#?A8`#X13`@``C78`9H$^`C!V9[]0`0``NP````!F@[YV`0````^$ -M+`(``)"#[`2-1"0.4`^WQU!'5?^5H`$``(/$$(7`#X2]`0``9@^V1"0+9HF$ -M7F(!``!F#[9$)`IFB81>9`$``(/#`@^WAG8!```YV'^WZ:4!``"#[`2-1"0. -M4&@``0``OP$!``!5_Y6@`0``@\00N@````"%P`^$N0$``&:+1"0*B<)FP>H) -M9HF68@$``&;!Z`*#X']FB89D`0``#[=$)`K!X`6#X']FB89F`0``@^P$C40D -M#E`/M\=01U7_E:`!``"#Q!"Z`````(7`#X1C`0``9HM$)`J)PF;!Z@MF"99F -M`0``9L'H!(/@?V:)AF@!```/MT0D"L'@`X/@?V:)AFH!``"#[`2-1"0.4`^W -MQU!'5?^5H`$``(/$$+H`````A<`/A`T!``!FBT0D"HG"9L'J#68)EFH!``!F -MP>@&@^!_9HF&;`$```^W1"0*T>"#X']FB89N`0``@^P$C40D#E`/M\=01U7_ -ME:`!``"#Q!"Z`````(7`#X2X````9HM4)`J)T&;!Z`]F"89N`0``B=!FP>@( -M@^!_9HF&<`$``&;1ZH/B?V:)EG(!```/MT0D"L'@!H/@?V:)AG0!``"#[`2- -M1"0.4`^WQU!5_Y6@`0``@\00N@````"%P'18ZPF)]KH`````ZTUFBT0D"F;! -MZ`IF"89T`0``NP````!F@[YV`0```'0I#[>^=@$``(UV``^WA%YB`0``4%;H -M$?W__X/$"&:)A%YB`0``0SG??^&Z`0```(G0@\0,6UY?7<.)]E575E.#[!B+ -M1"0PBWPD-&:+4!1FB50D$HE$)!0/M\*-%("-%)"-1``#P>@"`<+!X@)2Z/S_ -M__^)P8/$$+@`````A`"9L=$$`8$`(M7"&;'1!!"`P!&#[=$)`8Y\'^+ -MN`$```"#Q`Q;7E]=PXGV55=64X/L!(ML)""+5"0<9HM"%F:)109FQP0DK=YF -MQT0D`JW>N@````"Y``````^WV(GFD(G8T_BH`70*@_H!?REFB0Q60D&#^0-^ -MZ(M4)!QFBT(49HE%!+@`````9H-]!``/A-4!``#K"K@`````Z-%(4`````B?:-!(F-!((#10AF -MQT`&``!!@_D#?NMF@7PD`JW>=68/MPPDC12_C127C02)P>`"C120`U4(@\($ -M9L="`@0`9HM#`F:)0@1F`T,&9HE"!F8#0PIFB4((9@-##F:)0@IFBT,$9HE" -M#&:+0PAFB4(.9HM##&:)0A!FBT,09HE"$NGA````B?:-!+^-!(>--(4````` -M#[<$)(T$@(T$A@-%"&:+4P)FB5`(#[=$)`*-!("-!(8#10AFQT`(%``/MT0D -M`HT$@(T$A@-%"&;'0`HC``^W1"0"C02`C02&`T4(9L=`##\`#[<,)(T$B8T4 -MA@-5"(/"!&;'0@($`&:+0@1F`T,&9HE"!F8#0PIFB4((9@-##F:)0@IFBT,$ -M9HE"#&:+0PAFB4(.9HM##&:)0A!FBT,09HE"$@^W3"0"C02)C12&`U4(@\($ -M9L="`@,`9HM#%&:)0@QFBT,69HE"#F:+0QAFB4(01P^W100Y^`^/3/[__[@! -M````@\0$6UY?7<.-=@!55U93@>Q<`0``OU`!``#'1"0(`````,=$)`0````` -M@WPD"`$/A-X```"#?"0(`7\/@WPD"`!T&.EC`0``C78`@WPD"`(/A`D!``#I -M4`$``(N$)'0!``!F@W@6``^$/@0``(-\)`0)#X\_`0``@^P$C40D$E!71_^T -M)'P!``"+E"2``0``_Y*@`0``@\00A<`/A!X$``"`?"0.``^$"P$``(M<)`0/ -MMD0D#O]$)`10_[0D>`$``.CU^/__@\0(9HF$7#`!``!F#[9$)`]FA<`/A-<` -M``"+7"0$#[;`_T0D!%#_M"1X`0``Z,/X__^#Q`AFB81<,`$``(-\)`0)#XYJ -M____Z:0```"+C"1T`0``9H-Y&@`/A(8#``"[`````)"+A"1T`0``9H&\6%0! -M``#_`'099HN$6%0!``"+3"0$9HF$3#`!``!!B4PD!$.#^P)^SNM8BX0D=`$` -M`&:#>!P`#X0Z`P``NP````"0BY0D=`$``&:!O%I.`0``_P!T&6:+A%I.`0`` -MBTPD!&:)A$PP`0``08E,)`1#@_L"?L[K#+@`````Z0H#``")]H/L"&@<`0`` -MC40D'%#H_/___XM$)!1FB40D-+L`````@\00.UPD!`^-7`(``(UL)`Z-=@!F -MBX1<,`$``&:)1%P0C11;C1239HE$5"B#[`155T?_M"1\`0``BY0D@`$``/^2 -MH`$``(/$$(7`#X27`@``C0Q;C0R+C4Q,(&:+1"0.#[;09L'H!X/@`<'@"&8I -MPF:)40QFBT0D#HG"9L'J"&;!Z`_!X`AF*<)FB5$0@^P$55='_[0D?`$``(N, -M)(`!``#_D:`!``"#Q!"%P`^$-@(``(T,6XT,BXV,3%`!``!FBT0D#@^VT&;! -MZ`>#X`'!X`AF*<)FB9'D_O__9HM$)`Z)PF;!Z@AFP>@/P>`(9BG"9HF1Z/[_ -M_X/L!%571_^T)'P!``"+E"2``0``_Y*@`0``@\00A<`/A,P!``"-%%N-%).- -M5%0@9HM$)`Z#X!]FB4(.9HM$)`YFP>@%@^`?9HE"$F:+1"0.9L'H"H/@'V:) -M0A:#[`155T?_M"1\`0``BXPD@`$``/^1H`$``(/$$(7`#X1Q`0``C0Q;C0R+ -MC4Q,,&:+1"0.#[;09L'H!X/@`<'@"&8IPF:)40QFBT0D#HG"9L'J"&;!Z`_! -MX`AF*<)FB5$.@^P$55='_[0D?`$``(N4)(`!``#_DJ`!``"#Q!"%P`^$$`$` -M`(T$6XT$@XVT1%`!``"-CN#^__]FBT0D#@^VT&;!Z`>#X`'!X`AF*<)FB5$0 -MBX0D=`$``&:!.`)`=AIFBT$(9HE!"F8/MD0D#X/@/V:)AMK^___K,HT$6XT$ -M@XV$1%`!``!FBU0D#HG19L'I"&;!Z@_!X@AF*=%FB8CJ_O__9L>`VO[__P$` -M0SM<)`0/C*O]__^+5"0(BXPD=`$``&:+1%%H9HE$)":#[`2-!%*-A(%D#0`` -M4(U$)!A0_[0D?`$``.A7^/__@\00AMS*I`/M\.+5"0<9HL,0F:) -M#$>-%("-%)*-%%"-%%=FB4H89HER&D-F.>MRUUM>7UW#B?955U93@^P\BVPD -M4(I$)&2(1"0-BW0D7+\`````@WPD8``/A,$```"0@^P$C40D$E`/M\901E7_ -ME:`!``"#Q!"%P`^$D@4``(!\)`X`#X26````@'PD#0!U'P^WWP^V1"0.1U#_ -M="18Z+SS__^#Q`AFB41<$.L=B?8/M]\/MD0D#D=0_W0D6.CQ\___@\0(9HE$ -M7!!F#[9$)`]FAP(`#X2_```` -M@^P$5P^WQE!&5?^5H`$``(/$$(7`#X1Y!```9HM$)`Z#X!]FB4,,9HM$)`YF -MP>@%@^!_9HE#!&:+1"0.9L'H#&:)0SR#[`17#[?&4$95_Y6@`0``@\00A<`/ -MA#4$``!FBT0D#H/@/V:)0Q1FBT0D#F;!Z`:#X`]FB4-$9HM$)`YFP>@*9HE# -M'(/L!%@*9HE#%H/L!%@.9HE#)H/L!%`"9@E#)NM2B?9F@WL"`75)9HM$)`YFP>@*@^`/ -M9HE#5&:+1"0.9L'H#F:)0RR#[`17#[?&4$95_Y6@`0``@\00A<`/A*8"```/ -MMT0D#H/@#\'@`F8)0RR)]F:#>P("#X:]````9HM$)`YFP>@$@^`?9HE#$&:+ -M1"0.9L'H"6:)0PB#[`17#[?&4$95_Y6@`0``@\00A<`/A%("``!FBT0D#H/@ -M#V:)0T!FBT0D#F;!Z`2#X#]FB4,89HM$)`YFP>@*@^`/9HE#2&:+1"0.9L'H -M#F:)0R"#[`17#[?&4$95_Y6@`0``@\00A<`/A/X!```/MT0D#H/@#\'@`F8) -M0R!FBT0D#F;!Z`2#X`]FB4-09@^V1"0/@^`_9HE#*.LGC78`9H-[`@)U'6:+ -M1"0.9L'H!(/@#V:)0U9F#[9$)`^#X#]FB4,N9H-[`@,/AC4!``!FBT0D#F;! -MZ`YFB4,2@^P$5P^WQE!&5?^5H`$``(/$$(7`#X1V`0``#[=$)`Z#X`?!X`)F -M"4,29HM$)`YFP>@#@^!_9HE#"F:+1"0.9L'H"H/@#V:)0T)FBT0D#F;!Z`YF -MB4,:@^P$5P^WQE!&5?^5H`$``(/$$(7`#X0?`0``#[=$)`Z#X`_!X`)F"4,: -M9HM$)`YFP>@$@^`/9HE#2F8/MD0D#X/@/V:)0R)FBT0D#F;!Z`YFB4-2@^P$ -M5P^WQE!&5?^5H`$``(/$$(7`#X3+````#[=$)`Z#X`/!X`)F"4-29HM$)`YF -MP>@"@^`_9HE#*F8/MD0D#X/@#V:)0UIFBT0D#F;!Z`QFB4,R@^P$5P^WQE!& -M5?^5H`$``(/$$(7`='L/MT0D#H/@`\'@!&8)0S+K39!F@WL"`W5%9HM$)`YF -MP>@.9HE#6(/L!%@"@^`_9HE#,(GV9O]$)`IFBU0D"HM$)%AF.5`4#X=0^___N`$` -M``"#Q#Q;7E]=PXUV`%575E.#[`R+5"0D9HM"%(ML)"!FB4449HM%%F:)1"0( -M9L=$)`8``*@!=`=FQT0D!@$`BT0D"&;1Z(/@`8/X`6:#7"0&_XM$)`AFP>@" -M@^`!@_@!9H-<)`;_BT0D"&;!Z`.#X`&#^`%F@UPD!O]FQT0D"@``BU0D)&:# -M>A0`#X;'````D`^W5"0*BVPD)&:+3%4`BT0D(&:)#%"-!)*-!("-!$*+5"0@ -MC01"9HE(&&:+;"0&9HEH'+\`````NP`````/MW0D"HT$MHT$@(T$1M'@B00D -M#[?+C01)BQ0DC03"BVPD((T4*&:)6AX/MT0D"-/XJ`%T%F;'0B`$`$=F@_\! -M=2AFQT(@!0#K()`/M].-%%*-!+:-!("-!$;1X(T4T(M$)"!FQT0"(```0V:# -M^P-VHF;_1"0*9HML)`J+5"0D9CEJ%`^'.O___X/$#%M>7UW#B?955U93@^PD -M9L=$)!BMWHU$)!AFQT`"K=YFQT`$K=YFQT`&K=['1"00`````&;'1"04``"+ -M1"1`#[=0%KL#````C70D&`^W1"04B=DIP8G0T_BH`704B=AF*T0D%(M,)!!F -MB01.08E,)!!F_T0D%&:#?"04`W;.BU0D/&:+0A2+3"1`9HE!%&;'1"06``!F -M@WD4``^&_P````^W5"06C022C02`C01"T>"+3"0\C10(C6H89HM2&(M,)$!F -MB50(&&;'1"04``"#?"00``^$K@````^W5"06C022C02`C01"T>")1"0,C78` -M#[=4)!0/MT14&(T$0(M,)`R-!,&+3"1`C70('@^_1%4,P>`"9HE&#F:+1%4$ -M9HE&!+\!````9H-^`@%V1@^W1"04B40D"&:+5@)FB50D!I`/M\^+1"0(C1R( -M#[]$731FBU1.#(T$0F:)1$X.9HM$3@)F`T1=#&:)1$X$1V8Y?"0&=\UF_T0D -M%`^W1"04.T0D$`^":?___V;_1"069HM,)!:+5"1`9CE*%`^'`?___[@!```` -M@\0D6UY?7<-55U93@^P7UW#55=64X/L'(M\)#"+1"0T9H$X_S]V&F:#>"X! -M=1.#[`A05^BI[___@\00Z2H#``"0BU0D-&:!.O]/=DUF@WHN`G5&@^P(4E?H -MZ/W__X/$$.D%`P``N`````#I^P(``+@`````Z?$"``"X`````.GG`@``N``` -M``#IW0(``+@`````Z=,"``")]L=$)!``````BTPD-&:!.0,P&?:#YK"!QE`! -M``"#?"00`71.@WPD$`%_#H-\)!``=!/IGP```(GV@WPD$`)T9.F1````@\8% -MBT0D-&:+@'8!``!FB40D&(M<)#2!PW@!``"+5"0T@<)B`0``B50D#.MOBTPD -M-&:#>1H`#X0]`@``@\8W9HN!@`,``&:)1"08B@* -M9HE#!&:+1"0:9L'H!(/@/V:)0P(/MT0D&L'@`H/@/V:)0QZ#[`155D97_Y>@ -M`0``@\00A<`/A'/^__]FBT0D&F;!Z`YF"4,>9@^V1"0;@^`_9HE#(&:+1"0: -M9L'H`H/@/V:)0R(/MT0D&L'@!(/@/V:)0R2#[`155D97_Y>@`0``@\00A<`/ -MA"S^__]FBT0D&F;!Z`QF"4,D9HM$)!IFP>@&@^`_9HE#)F:+1"0:@^`_9HE# -M*(/L!%561E?_EZ`!``"#Q!"%P`^$]?W__V:+1"0:9L'H"F:)0RIFBT0D&F;! -MZ`2#X#]FB4,L#[=$)!K!X`*#X#]FB4,N@^P$559&5_^7H`$``(/$$(7`#X2[ -M_?__9HM$)!IFP>@.9@E#+F8/MD0D&X/@/V:)0S!FBT0D&F;!Z`*#X#]FB4,R -MC4,(4`^W0P10#[=#`E#_="1`Z/;E__^Z`````(/$$`^W0P:)P8/X`'X:C78` -M#[]$4QZ-!("-!(#1X&:)1%,>0CG1?^F#PS3_1"04#[=$)!@[1"04#X\[_O__ -M_T0D$(-\)!`"#XX\_?__N`$```"#Q!Q;7E]=PXUV`%575E.#[!R+?"0TO0`` -M``!F@3__/W8)#[=')(UPJ^L09H$_`S`9]H/FL('&4`$``(/]`70S@_T!?P:% -M[70*ZWB#_0)T2^MQD(/&5<=$)!`(````C9_@)9HE#"&:#>P@`#X3Z````A>UU%`^W0PA05^C9Y/__@\0(9HE# -M".L2#[=#"%!7Z!GE__^#Q`AFB4,(9H$_`C!V(V:+1"0:9L'H`H/@/V:)0P8/ -MMT0D&L'@!(/@/V:)0P3K(8GV9HM$)!IFP>@#@^`_9HE#!@^W1"0:P>`#@^`_ -M9HE#!(/L!(U$)!Y05D;_="0\BU0D0/^2H`$``(/$$(7`#X2)````9H$_`C!V -M*V:+1"0:9L'H#&8)0P1FBT0D&F;!Z`:#X#]FB4,"9HM$)!J#X#]FB0/K+)!F -MBT0D&F;!Z`UF"4,$9HM$)!IFP>@'@^`_9HE#`F:+1"0:9M'H@^`_9HD#BT0D -M#&;_`(/#"O]$)!2+5"00.50D%`^,H?[__Y!%@_T"#X["_?__N`$```"#Q!Q; -M7E]=PY!55U93@^P,BVPD((MT)"2!QF0%``"+1"0D9H$X_S]V"0^W>"2#QQKK -M=[^_`0``BU0D)&:!.@(P=V?K7;@`````Z;D#``"X`````.FO`P``N`````#I -MI0,``+@`````Z9L#``"X`````.F1`P``N`````#IAP,``+@`````Z7T#``"X -M`````.ES`P``N`````#I:0,``(UV`+]O`0``C78`QT0D!`````"+3"0D9H.Y -M!`$````/A#\#``")]HM$)`2+5"0D9H.\0@8!````=1EF@3H",'8&@\<(ZP20 -M@\<'@\9`Z?D"``"0BTPD)&:!.0(P#X:M````NP````"#[`2-1"0.4%='5?^5 -MH`$``(/$$(7`#X0C____9HM$)`J)PF;!Z@AFB13>)?\```!FB43>"(/#`H/[ -M!W[#NP````")]H/L!(U4)`Y25T=5_Y6@`0``@\00A<`/A.G^__]F#[9$)`N# -MX#]FB43>`F:+1"0*9L'H#H/@`8E$W@1FBT0D"H/@/V:)1-X*9HM$)`IFP>@& -M@^`!B43>#(/#`H/[!WZAZ=D!``"#[`2-3"0.45='5?^5H`$``(/$$(7`#X2/ -M_O__9HM$)`J)PF;!Z@EFB19FP>@"@^!_9HE&"`^W1"0*P>`%@^!_9HE&$(/L -M!(U$)`Y05T=5_Y6@`0``@\00A<`/A%7^__]FBT0D"HG"9L'J"V8)5A!FP>@$ -M@^!_9HE&&`^W1"0*P>`#@^!_9HE&((/L!(U4)`Y25T=5_Y6@`0``@\00A<`/ -MA!K^__]FBT0D"HG"9L'J#68)5B!FP>@&@^!_9HE&*`^W1"0*T>"#X']FB48P -M@^P$C4PD#E%71U7_E:`!``"#Q!"%P`^$X/W__V:+5"0*B=!FP>@/9@E&,(G0 -M9L'H"(/@?V:)1CAFP>H"@^(_9HE6`@^W1"0*P>`$@^`_9HE&"H/L!(U$)`Y0 -M5T=5_Y6@`0``@\00A<`/A)C]__]FBU0D"HG09L'H#&8)1@J)T&;!Z`:#X#]F -MB482@^(_9HE6&H/L!(U4)`Y25T=5_Y6@`0``@\00A<`/A&/]__]FBT0D"HG" -M9L'J"F:)5B)FP>@$@^`_9HE&*@^W1"0*P>`"@^`_9HE&,H/L!(U,)`Y15T=5 -M_Y6@`0``@\00A<`/A"C]__]FBT0D"HG"9L'J#F8)5C)FP>@(@^`_9HE&.KL` -M````B?:#/-X`=$J+5"0$BTPD)`^WA%$&`0``@^`'=`6#^`-U&`^W!-Y0_W0D -M*.@.X/__@\0(9HD$WNL9D`^W!-Y0_W0D*.A*X/__@\0(9HD$WHUV`$.#^P=^ -MJH/&0(UV`/]$)`2+5"0D#[>"!`$``#M$)`0/C\/\__^X`0```(/$#%M>7UW# -MB?955U93@^P,BVPD((MT)"1FQT8J#P!FQT8L#P!F@3X",'82QP0DY````&;' -MA@0!```@`.L0QP0DS````&;'A@0!```0`(/L!(U$)`Y0BT0D"/\P5?^5H`$` -M`(/$$,=$)`0`````A<`/A"P.``!FBU0D"HG09L'H#V:)1@:)T&;!Z`Z#X`%F -MB48*B=!FP>@+@^`'9HE&#(G09L'H!(/@?V:)1@YF@3[_/W8/B=!FP>@#@^`! -M9HE&".L&9L=&"`$`9HM4)`J)T&;!Z`*#X`%FB48B#X`%FB48:@^(! -M9HE6%HL$)(M8!(/L!(U$)`Y04T-5_Y6@`0``@\00QT0D!`````"%P`^$BPT` -M`&:+5"0*B=!FP>@(B$8>B%8?9H$^_S\/AM<```"#[`2-1"0.4%-#5?^5H`$` -M`(/$$,=$)`0`````A<`/A$L-``!FBU0D"HG09L'H#F:)1BZ)T&;!Z`V#X`&) -MAL@```")T&;!Z`R#X`&)ALP```"!XO\/``!FB58P@^P$C40D#E!30U7_E:`! -M``"#Q!#'1"0$`````(7`#X3P#```9HM$)`J)PH'B_P\``&:)5B1FP>@.@^`! -MB$8C9H$^_T]V-H/#`H/L!(U$)`Y04U7_E:`!``"#Q!#'1"0$`````(7`#X2H -M#```9HM$)`IFP>@$9HF&T````+\`````BP0DBURX"(/L!(U$)`Y04T-5_Y6@ -M`0``@\00A<`/A`\+``!F#[9$)`N#X']FB41^,F:+1"0*9L'H`H/@/V:)1'XX -M#[=$)`K!X`2#X#]FB41^=(/L!(U$)`Y04T-5_Y6@`0``@\00A<`/A-$*``!F -MBT0D"F;!Z`QF"41^=&:+1"0*9L'H!H/@/V:)1'YZ9HM$)`J#X#]FB81^@``` -M`(/L!(U$)`Y04T-5_Y6@`0``@\00A<`/A),*``!FBT0D"F;!Z`IFB81^A@`` -M`&:+1"0*9L'H!(/@/V:)A'Z,````#[=$)`K!X`*#X#]FB81^D@```(/L!(U$ -M)`Y04T-5_Y6@`0``@\00A<`/A$P*``!FBT0D"F;!Z`YF"81^D@```&8/MD0D -M"X/@/V:)A'Z8````9HM$)`IFP>@"@^`_9HF$?IX````/MT0D"L'@!(/@/V:) -MA'ZD````@^P$C40D#E!30U7_E:`!``"#Q!"%P`^$]`D``&:+1"0*9L'H#&8) -MA'ZD````9HM$)`IFP>@&@^`_9HF$?JH```!FBT0D"H/@/V:)A'ZP````@^P$ -MC40D#E!30U7_E:`!``"#Q!"%P`^$L`D``&8/MD0D"XA$-U:#_P%T48/_`7\, -MA?]T#^G_````C78`@_\"=%SK>6:+1"0*B<)FP>H%@^('9HF6\````&;!Z`*# -MX`=FB8;R````#[=$)`K1X(/@!V:)ANP```#K0XUV`&:+5"0*B=!FP>@$@^`' -M9HF&]````(/B!V:)EO8```#K'V:+5"0*B=!FP>@$@^`'9HF&^````(/B!V:) -MEOH```"%_W5X@^P$C40D#E!30U7_E:`!``"#Q!"%P`^$_0@``&:+5"0*B=!F -MP>@/9@F&[````(G09L'H#(/@!V:)ANX```")T&;!Z`F#X`=FB8;H````B=!F -MP>@&@^`'9HF&Z@```(G09L'H`X/@!V:)AN0```"#X@=FB9;F````@^P$C40D -M#E!30U7_E:`!``"#Q!"%P`^$D@@``&8/MD0D"V:)1'X^9@^V1"0*9HE$?D2# -M[`2-1"0.4%-#5?^5H`$``(/$$(7`#X1M"```9@^V1"0+9HE$?DIF#[9$)`IF -MB41^4(/L!(U$)`Y04T-5_Y6@`0``@\00A<`/A$@(``!F#[9$)`N(1#=99@^V -M1"0*9HE$?ER$P'D*#0#___]FB41^7(/L!(U$)`Y04T-5_Y6@`0``@\00A<`/ -MA!8(``!FBT0D"F;!Z`4E_P```&:)1'YB9HM$)`IFT>B#X`]FB41^:&:+1"0* -M@^`!9HE$?FYF@3[_/W8RA?]T"H/_`G07ZR>-=@!FBT0D"F;!Z`V#X`%FB48F -MZQ)FBT0D"F;!Z`V#X`%FB48HB?9F@3X",`^&E0```(/L!(U$)`Y04T-5_Y6@ -M`0``@\00A<`/A),'``!FBT0D"F;!Z`:#X']FB81^M@```(/_`702@_\!?P:% -M_W1+ZU6#_P)T(^M.9HM$)`J)PH/B!V:)EOP```!FP>@#@^`'9HF&``$``.LM -M9HM$)`J)PH/B!V:)EOX```!FP>@#@^`'9HF&`@$``.L,9HM$)`J#X#]FB482 -M9H$^`S`/AID```!FBT0D"F;!Z`UFB81^O````(/L!(U$)`Y04T-5_Y6@`0`` -M@\00A<`/A.\&```/MT0D"L'@`X/@.&8)A'Z\````@_\"=2!FBU0D"HG09L'H -M`XA&(F:!/@5`=@N)T&;!Z`MFB48LD(7_=3YF@3[_/P^&R0,``&:+5"0*B=!F -MP>@(@^`_9HF&1@$``&;!Z@.#XA]FB99*`0``ZPYFQX1^O`````H`QD8B#V:! -M/O\_#X:+`P``@_\!=""#_P%_#87_#X21`@``Z70#``"#_P(/A)L```#I9@,` -M`(/L!(U$)`Y04T-5_Y6@`0``@\00A<`/A#8&```/MD0D"E!6Z%;8__^#Q`AF -MB894`0``#[9$)`M05NA`V/__@\0$9HF&5@$``(U$)`Y04U7_E:`!``"#Q!"% -MP`^$_P4```^V1"0*4%;H$MC__X/$"&:)AE@!``!F@3X`0`^&Y0(``&8/MD0D -M"X/@/V:)AL0```#IT`(``(/L!(U$)`Y04T-5_Y6@`0``@\00A<`/A+H%```/ -MMD0D"E!6Z,#7__^#Q`AFB89.`0``#[9$)`M05NBJU___@\0$9HF&4`$``(U$ -M)`Y04T-5_Y6@`0``@\00A<`/A((%``!FBT0D"HG"@^)_9HE6$&;!Z`>#X#]F -MB484@^P$C40D#E!30U7_E:`!``"#Q!"%P`^$6@4```^V1"0*4%;H1M?__X/$ -M"&:)AE(!``!F@3X`0'809@^V1"0+@^`_9HF&Q@```(/L!(U$)`Y04T-5_Y6@ -M`0``@\00A<`/A!L%``!FBU0D"HG09L'H!8/@/V:)AD@!``"#XA]FB99,`0`` -M9H$^`4`/AL@(@^!_9HF&U@```(G09L'H#V:)AMH` -M``"#[`2-1"0.4%-#5?^5H`$``(/$$(7`#X28!```#[=$)`J#X!_1X&8)AMH` -M``!FBU0D"HG09L'H!8/@/V:)AN(```!FP>H+B);=````@^P$C40D#E!35?^5 -MH`$``(/$$(7`#X17!```#[=$)`J#X`?!X`4(AMT```!FBT0D"F;!Z`.(AM\` -M``#IZ@```(GV9H$^`$`/AMT```"#[`2-1"0.4%-#5?^5H`$``(/$$(7`#X03 -M!```9HM4)`J)T(/@/V:)AL(```!F@3[_3P^&I0```(G09L'H!H/@?V:)AM0` -M``")T&;!Z`UFB8;8````@^P$C40D#E!30U7_E:`!``"#Q!"%P`^$R`,```^W -M1"0*@^`'P>`#9@F&V````&:+5"0*B=!FP>@#@^`_9HF&X````&;!Z@F(EMP` -M``"#[`2-1"0.4%-5_Y6@`0``@\00A<`/A(8#```/MT0D"H/@`<'@!PB&W``` -M`&:+1"0*9M'HB(;>````D$>#_P(/C@?W__]F@3X",`^'CP```(/L!(U$)`Y0 -M:.P```!5_Y6@`0``@\00QT0D!`````"%P`^$:`,``&:+1"0*B<*#X@=FB9;\ -M````9L'H`X/@!V:)A@`!``"#[`2-1"0.4&CM````5?^5H`$``(/$$,=$)`0` -M````A<`/A"(#``!FBT0D"HG"@^('9HF6_@```&;!Z`.#X`=FB88"`0``C78` -M9L>&8`$```0`9L>&7@$```$`9L>&7`$```$`9L>&6@$`````BP0DBU@4OP`` -M``!F@[X$`0```'1)C78`@^P$C40D#E!30U7_E:`!``"#Q!"%P`^$=`(``&8/ -MMD0D"V:)A'X&`0``9@^V1"0*9HF$?@@!``"#QP(/MX8$`0``.?A_NF:!/@)0 -M=F&_`````(GV@^P$C40D#E!35?^5H`$``(/$$(7`#X0K`@``9HM$)`IFB82^ -MC@,``(/L!(U$)`Y0C4,%4%7_E:`!``"#Q!"%P`^$"@(``&:+1"0*9HF$OI`# -M``!#1X/_!'ZF9H$^`C!W)F;'1ES*_V;'1E[__V;'1F#__W<29L=&1`\`9L=& -M1AP`9L=&2!P`9H$^_S]V*8/L!(U$)`Y0:,H```!5_Y6@`0``@\00QT0D!``` -M``"%P`^$NP$``.LG@^P$C40D#E!HSP```%7_E:`!``"#Q!#'1"0$`````(7` -M#X22`0``9HM$)`IFB4889H-^%@`/A70!``!F@3[_/P^&70$```^WP,'H"X/@ -M`6:)1A;I5P$``,=$)`0`````Z50!``#'1"0$`````.E'`0``QT0D!`````#I -M.@$``,=$)`0`````Z2T!``#'1"0$`````.D@`0``QT0D!`````#I$P$``,=$ -M)`0`````Z08!``#'1"0$`````.GY````QT0D!`````#I[````,=$)`0````` -MZ=\```#'1"0$`````.G2````QT0D!`````#IQ0```,=$)`0`````Z;@```#' -M1"0$`````.FK````QT0D!`````#IG@```,=$)`0`````Z9$```#'1"0$```` -M`.F$````QT0D!`````#K>L=$)`0`````ZW#'1"0$`````.MFQT0D!`````#K -M7,=$)`0`````ZU+'1"0$`````.M(QT0D!`````#K/L=$)`0`````ZS3'1"0$ -M`````.LJQT0D!`````#K(,=$)`0`````ZQ9FBT889L'H#V:)1A;'1"0$`0`` -M`(GVBT0D!(/$#%M>7UW#5E.#[`R+="08BUPD'%-6Z$CQ__^#Q!"Z`````(7` -M=%2#[`A35NANT?__@\00N@````"%P'0^@^P(4U;H5.?__X/$$+H`````APX/L#(M$)!1F@3C_/W8:9H-X+@%U$X/L"%#_="0'_?P``B?:-!))F.0R%X`@``'0+0H'Z@@```';JZR6X`0```,.X`0```,.- -M!-4`````*=!F.0R%0````'3G0H/Z2G;GN`````##D%.+7"0,N`$```!FA=MT -M14/M\.)RH'B_W\``#G0#Y3`#[;`ZTEF/?\! -M=`JZ`````&:%P'41N`$```#K,K@!````ZRN-=@"-!)+!X`)F.9C@"```=0EF -M.8CB"```=-Y"@?J"````=M^X`````(GV6\.)]E93@^P0BT0D'(MT)"!0_Y"< -M`0``B<.#Q!"H0G0+@WX(`'4%@^.]B?;VPR!T"X-^#`!U!8/CWXGV]L,(=`N# -M?@0`=06#X_>)]O;#`707BT0D&(/`&%#HFO[__X/$!(7`=`.#X_Z)V(/$!%M> -MPU575E.![)@```"+K"2L````OP`````/MX0DL````%#HE````(G#@\00A@_@2?PF%P'0=ZRN- -M=@`]_P$``'01/4J#``!U&HGVN`$```#K%I"X`0```&:!NPH"``!*`W0%N``` -M``!;PY"+3"0$N@````"-=@"-!)+!X`)F.8C@"```=0D%X`@``,.-=@!"@?J" -M````=M^X`````,.05E/_="0,Z'W]__^#Q`2)QF:%P'DCB?.!X_]_``!3Z*G_ -M__^#Q`2)VH7`=4?K"@^W5!`(ZSZ-=@"Z`````(UV`(T$U0`````IT,'@`F8Y -ML$````!U$[I0````9H-\$`@`=!H"$``#G8=2"%]G05 -M@^P$:GB-@:`A``!05NC\____@\00N`$```#K"T*#^C!VPK@`````@\0$6U[# -MC78`BTPD!+@`````A____@\0$A"0````#GP=1&!PD````")5"04NP$```") -M]D&#^4IW!H7;=,KK$+@`````A=L/A$(!``"-=@"`?"0:`'@0BU0D%`^W<@*+ -M>@B]`````(!\)!H`>1"+1"04#[=P!(MX#+T`````N0````"[`````(T$R8T4 -MA0`````/MX*`"```.?!U(XM$)#"+@-@!```[@H0(``!U$8'"@`@``(E4)!"[ -M`0```(GV08/Y`7<&A=MTONL$A=MT:(!\)!H`>"R+5"00BTH(NP````")^"'( -MB>HAVHG'BT0D$(M(#+L`````B?@)R`G:B<>)U8!\)!H`>2Z+5"00BTH0NP`` -M``")^"'(B>HAVHG'BT0D$(M(%+L`````B?@)R`G:B<>)U8GV@^P(_W0D1%;H -M@_W__XG#@\00N`````"%VW0\BU0D/(M"#(M:$(G"BW0D%"-6$(G9(TX4BT0D -M/(E0#(E($(M4)#1F]T("`/]U"8GN"?YT`XEX%+@!````@\0<6UY?7<.05U93 -MBU0D$(MT)!2)T(72>0.-0C^)Q\'_!HGXP>`&B=,IP[@!````N@````"(V0^E -MPM/@]L,@=`>)PK@`````(P3^(U3^!(G1"<$/E<`/ML!;7E_#5E.+3"0,BUPD -M$(MT)!2*5"08A-)T)K@`````.=AS$9`X%`%T%X`\`0!T!4`YV'+P.=AT"(@4 -M`?\&C78`6U[#D%575E.![(P!``"+G"2\`0``BX0DP`$``&:)1"0Z9L=$)#)8 -M&XN4)*`!``"!PC`"``")5"0HOP````#_M"2@`0``Z)[Y__^#Q`2Z`````(7` -M#X3>!@``_[0DH`$``.C"^___BXPDI`$``&:)@0H"``"#Q`1FAE`0``9CML)#X/AYH!``"+1"0(@'@&"G4+@WPD -M%``/A(4!``"+5"0(@'H&!74+@WPD&``/A'`!```/M\6+3"0(#[91!P'0T?@/ -MMU0D,H/""CG0#X]1`0``BYPDJ`$``#E<)"0/@WL!``"#>10`>0Z#O"3(`0`` -M``^$+`$``(MT)`R`?A0`>12+O"2@`0``@[_<`0``!@^$#@$``(/L"&HXC40D -M3%#H_/___V:);"10BU0D/&:+0@)FB40D4H/$$(M,)`@/ME$&@_H%=`^#^@IU -M$8#,0&:)1"1"ZP=F@4PD0@"`BUPD"(I#!(A$)$6*0P6(1"1:BW0D#(M&%(E$ -M)%P/MD0D'XE$)&"+2Q"+6Q2)R"-&#(G:(U80B=$)P70)9H%,)$(``NL'9H%D -M)$+__8M<)`B+2PB)WHM;#(G(BWPD#"-'!(G:(U<("="#^`$9P/?0@^`"B$0D -M1(M."(G((T<$@^`"N@````")T0G!=`6`3"1$"(M<)`SV0Q1`=`6`3"1$!(M\ -M)"3!YP,K?"0DBW0D*(T\_HU$)$#\N0X```")QO.E_T0D)(UV`(M\)`AF#[9' -M!P'%9CEO`@^#._[__XUV`/]$)""#?"0@?P^.Q?W__Y"#1"0L!(%\)"P<`0`` -M#X+E^___@WPD)``/A-X```"#?"0D0'8(QT0D)$````!H^#\``&HX_W0D+/]T -M)#3H_P(``(M4)#2+A"2P`0``B9`P$```N0````"#Q!`YT7U`C03-`````"G( -MP>`#BUPD*&:+%!B+M"2D`0``9HD4SF:+5!@"9HE4S@**5!@$B%3.!(I$&`6( -M1,X%03M,)"1\P(/L!/]T)"C_M"2L`0``_[0DK`$``(N\)+`!``#_E[P!``"Y -M`````(/$$#M,)"1]+HT$S0`````IR,'@`XN<)*0!``"*5,L&BW0D*(A4,`:* -M5,L'B%0P!T$[3"0D?-*+A"2L`0``BWPD)(DXBY0DH`$``&:+@@H"``!FB4(8 -MA?\/E<`/MM"0B="!Q(P!``!;7E]=PXUV`%575E.+3"04BUPD&`^W>P*!Y_#! -M``"+D300``"%TG0P9HL"9CL#=2@/MW("B?`E\,$``#GX=1GV0@0!=`VX```` -M`/?&`@```'5ZB=#K=HGVC:DP`@``BXDP$```A*+1"0,*-`/OM"$ -MP'D(N@````"-=@")T,.055=64XMT)!2+;"08O_\```!F@[X*`@````^%A0`` -M`%;H/_'__X/$!(G#B=@E\````(/X8'005N@H\?__@\0$9H'[F0%U7@^W10(E -MH````+_A````/:````!T?0^W10(ET````+_B````/<````!T:`^W10(ET``` -M`+_D````/=````!T4P^W10(E4`$``#U0`0``#Y3`#[;XC;Q_X````.LVB?95 -M5NC\____@\0(A@" -MB<*#X@&)T,.055=64X/L#(ML)"B+1"0@B40D!`'HB00DBT0D)$B)1"0(=$.+ -M/"2+1"0$.<=V+XGVB?XI[H/L"%=6_U0D/(/$$(7`?AF)^8GKBA:*`8@&1H@1 -M04MU\RGO.WPD!'?3`2PD_TPD"'6]@\0,6UY?7<.)]E93@^P(BW0D%(GSC40D -M!E!HP0```%;_EJ`!``"#Q!"Z`````(7`=%R#[`2-1"0$4&:!?"0*`$`9P(/@ -M!07*````4%;_EJ`!``"#Q!"Z`````(7`="]F@7PD`O\_=A(/MP0DP>@+@^`! -MB88\$```ZPT/OP0DP>@?B88\$```BY,\$```D(G0@\0$6U[#4X/L"(M<)!!3 -MZ%+O__^#Q`0/M\"#^$AT/X/X2'\:@_A!?PV#^$!],(7`=#KK8HGV@_A#="/K -M69`]C8$``'\1/8B!``!]$H/H2H/X`G="ZP@]CX$``'4YD(/L#%/H$____X/$ -M$.LO#[>#"@(``#V(`0``?!P]C0$``'X'/8\!``!U#H/L#%/HZ?[__X/$$.L% -MN`````"#Q`A;PXGV5U93@^P4BWPD)(M<)"B)_HU$)!)0:,$```!7_Y>@`0`` -M@\00A!F.9B@.```=39F@7PD#@)0=PEFBX"B.``` -MZPN-!%)FBX0`I#@``&:)A@@"``!7Z-3P__]FB88*`@``@\0$ZPA"@_H-=K:) -M]H/$$%M>7\.05U93@^P4BWPD)(MT)"B)^XU$)!)0:,$```!7_Y>@`0``@\00 -MA!F.;``.0``=39F@7PD#@)0=PEFBX`".0``ZPN- -M!%)FBX0`!#D``&:)@P@"``!7Z%#P__]FB8,*`@``@\0$ZP9"@_H&=K:#Q!!; -M7E_#C78`5E.#[!"+7"0<4^A-_O__@\00A#[`@/MX,(`@``4%/HOO[__X/$$.L5D(/L"`^W@PH"``!04^@K____@\00 -M@\0$6U[#D)!55U93@>RH````BZPDO````&@$$@``Z/S___^)PX/$$+X"```` -MA<`/A(`%``")QX/L!&AL$```:"`!``!0Z/S___^+A"3$````B4,,BX0DR``` -M`(E#$(N$),P```")0Q1FB:O(`0``9L>#R@$`````9L>#_`$``#P`QX,``@`` -M`````,>#,!$```,```#'@_`1````````QX/T$0````<``,>#^!$``/_____' -M@_P1``#_____QX,`$@``_____X/$"&H`4^C\____@\00O@,```"%P`^$TP0` -M`,>#S`$```$```"+0Q2+D"!```!F#[;29HF3T`$``(N0&)@``&:)D](!``!F -MQX/6`0````#'@-"8```6'```O@````"-=@"+1Q3'@("8``````$`1H/^`W;M -MBT<4BX``G```P>@<@^P(:@10Z/S___]`9HF'U`$``(M7%(N"$$```(E$)!B# -MR`&)@A!```"#Q`R-1"024&H]5^C\____@\00O@@```"%P`^$&`0``+X$```` -M9H%\)`ZE6@^%!@0``(/L!(U$)!)0:C]7Z/S___^#Q!"^"````(7`#X3F`P`` -M9HM$)`YFB8-N$```@^P$C40D$E!HP0```%?H_/___X/$$+X(````A<`/A+<# -M``!FBT0D#F;!Z`QFB8-L$```O@4```!F@_@!#X68`P``O0````"^`````(GV -M@^P$C41T%%"-AL````!05^C\____@\00A<`/A&0#```/MT1T$#'%1H/^/W;3 -MO@<```"!_?__```/A4X#``"#[`2-1"024&B_````5^C\____@\00O@@```"% -MP`^$*P,``&8/MD0D#F:)AP@"``"+1"049HF#A```(M$)!R(@WL0``!F#[9$)!^(@WP0``!FBT0D'HB#?1```(I$ -M)""#X`&(@W@0``"+1"0@9M'H@^`'B(-Y$```QX?``0```````+X`````O0D` -M``"-%/4`````*?*-%)8!VHV*?A```&:+1&P09L'H"HB"?A```&:+1&P09L'H -M!(/@/XA!"P^W1&P0P>`"@^`\9HM4;!)FP>H."="(00&*1&P3@^`_B$$,9HM$ -M;!)FP>@"@^`_B$$"#[=$;!+!X`2#X#!FBU1L%&;!Z@P)T(A!#6:+1&P49L'H -M!H/@/XA!`XI$;!2#X#^(00YFBT1L%F;!Z`J(001FBT1L%F;!Z`2#X#^(00\/ -MMT1L%L'@`H/@/&:+5&P89L'J#@G0B$$%BD1L&8/@/XA!$&:+1&P89L'H`H/@ -M/XA!!@^W1&P8P>`$@^`P9HM4;!IFP>H,"="(01%FBT1L&F;!Z`:#X#^(00>* -M1&P:@^`_B$$29HM$;!QFP>@*B$$(9HM$;!QFP>@$@^`_B$$3#[=$;!S!X`*# -MX#QFBU1L'F;!Z@X)T(A!"8I$;!^#X#^(011FBT1L'F;!Z`*#X#^(00H/MT1L -M'L'@!(/@,&:+5&P@9L'J#`G0B$$59HM$;"!FP>@&@^`_B$$6BD1L((/@/XA! -M%V:+1&PB9L'H"HA!&&:+1&PB9L'H!(/@/XA!&0^W1&PBP>`"@^`\9HM4;"1F -MP>H."="(01J*1&PE@^`_B$$;9HM$;"1FP>@"@^`_B$$<1H/%"X/^!`^&$O[_ -M_X/L#%?H`0$``+T`````O@````"#Q!"#[`2-1"024+@?````*?!05^C\____ -M@\00AUT"(']_?\"`'4'O@D```#K(HM'%(M4)`B)D!!```")^.M&O@@```#K%XGV -MO@@```"-=@"+1Q2+5"0(B9`00```A=MT#(/L#%/H_/___X/$$(.\),`````` -M=`F+A"3`````B3"X`````('$G````%M>7UW#@^P8_W0D'.C\____@\0`!```"BD("9L=""`,`9L=""D`` -M@^">B$("@+EX$````'079L>!2!``````QX%,$````0```(!*`H#'0A0/```` -MQX%H$````0```+@!````PY"0D%.+3"0(BUPD#(M1%(M#!(F"+(```(M1%(M# -M#(F",(```(M1%(M#$(F"-(```(M1%(M#"(F".(```(M1%(L#B8(D@```6\.) -M]H/L+(M,)#"+5"0TB50D!(.YW`$```%T)(G0*P4`````P>`#B40D#(G0*P4` -M````P>`#B40D$(E4)`CK&,=$)`S_____QT0D$/_____'1"0(`0```(M$)#@E -M__^``8D$)(G@4%'H_/___X/$-,.-=@"+5"0$BT(4QX`L@````````(M*%(N! -M!(````T``!``)?__7_^)@02```"+0A3'@"2```#__P``PU=64XM\)!"+3"04 -MB?YF@WD2`'1$BU<4BX($@```)?__?_\-```@`(F"!(```(M7%`^W01")@BB` -M``"+5Q0/MT$2B8)(@```BU<4BT$4P>`#B8(T@```ZQ2+5Q2+@@2````E__]? -M_XF"!(```(M7%(L!B8(L@```BU\4BX,D@```)0``@/\/MU$("<)F@WD8`'01 -M#[=!&(/`!,'@$"4``'\`"<*)DR2```!F@[_0`0```W8Y#[=!&J@'=#&+EO01 -M``"`YOAF@WD:!W<-P>`()0`'```)PNL$D(#.!XF6]!$``(M'%(F0&(```(GV -M6UY?PXM$)`2+0!2+@`A```"%P`^5P`^VP,.)]E93BW0D#(M,)!"+1A2+4!R# -M^O]U#\PXUV -M`(M$)`2+@!@1``##D%=64XMT)!"+7"04B?&+OA@1``"%_WD-BT84QT`D```` -M`(UV`(G:@>*ZV`4!]L,!=`.#R@7VPT!T,X.Y'!$```!T`X/*0(.Y(!$```!T -M`X#.`8.Y)!$```!T`X#*@(.Y*!$```!T!H#.!(UV`(M&%(E0((F9&!$``(7; -M>0R+1A3'0"0!````B?:)^%M>7\.0D+A`````PXGVBT0D"&:#^#]W'0^WP,'@ -M!8M4)`0#0A2+@!R0``"Z`0```&:%P'@%N@````")T,.0BTPD!(M$)`BZ```` -M`&:#^#\/AX$````/M\#!X`6)P@-1%,>"`)````````")P@-1%,>"!)`````` -M``")P@-1%,>"")````````")P@-1%,>"#)````````")P@-1%,>"$)`````` -M``")P@-1%,>"%)````````")P@-1%,>"&)`````````#013'@!R0```````` -MN@$```")T,.05U93BWPD$(M4)!B+="04N`````!F@_X_=VJ%TG0X#[9:!<'C -M"`^V0@0)PP^V2@/!X1@/MD("P>`0"<$/MD(!P>`("<$/M@()P='IB=C!X!\) -MP='KZPJ[`````+D`````#[?&P>`%B<(#5Q2)BAB0```#1Q2)VH#.@(F0')`` -M`+@!````6UY?PU575E.#[!"+="0LBT0D*&:)1"0.@WPD-`$9R??1@>&JJJJJ -MN`````!F@WPD#C\/AU`!``"X`````(`^``^%0@$``+@`````9H-^`@0/AC(! -M``#'!"0`````9H-^`@5V$&:#?@(.&=*#XOZ#P@.)%"0/MFX$#[9&!<'@"`G% -M#[9&!L'@$`G%#[9&!\'@&`G%,`(#[96"`G",+__P``B50D!`^V7A`/MD81P>`("<,/MD82P>`0"<,/MD83P>`8"<,Q -MRV:#?@(-=P:!X_\````/MTPD#HG(P>`%B<*+="0D`U84B:H`D```B<(#5A2+ -M="0(B;($D```B<*+="0D`U84B;H(D```B<(#5A2+="0$B;(,D```B<*+="0D -M`U84B9H0D````T84BQ0DB9`4D```_W0D,%%6Z/S___^#Q`R-=@"#Q!!;7E]= -MPX/L$&H&BT0D&`4/$0``4/]T)"#H_/___X/$',.#[!!J!O]T)!R+1"0@^87\.04XM$)`B+ -M6!2+3"0,T>&Z`P```-/B]]*+@Q1````APK@"````T^`)PHF3%$```+@!```` -M6\.-=@!3BT0D"(M8%(M,)`S1X;@#````T^#WT(N3%$```"'0B8,40```N`$` -M``!;PU.+3"0,BT0D"(M8%(N3&$```+C^____T\`APHM$)!"#X`'3X`G"B9,8 -M0```N`$```!;PY"+3"0(N/____^#^05W%8M$)`2+0!2+@!Q```"#X"_3Z(/@ -M`<-64X/L!(MT)!"+3"04BT84BY@40```BPXUV`%.+7"0(BTPD#(M#%(N0$$```(7)=`J#^01T#>L3 -MC78`@^*?ZQ&-=@"#XM^#RD#K!H/*((/BOXM#%(F0$$```%O#C78`BT0D!(M` -M%(N`!(```"4``(``@_@!&<"#P`+#D(M,)`2+5"0(BT$4BX`$@```J0``@`!T -M"(/Z`G4(PXGV@_H!=`Z+410-``"``(F"!(```,.X`````,.)]H-\)`@`#Y3` -M#[;`PU93@^P(BW0D%(M<)!QJ!O]T)!R-AC01``!0Z/S___^+3A0/MI8T$0`` -M#[:&-1$``,'@"`G"#[:&-A$``,'@$`G"#[:&-Q$``,'@&`G"B9$(@```@\00 -MBTX4#[:&.1$``,'@"`^VEC@1```)PHG8)?\_``#!X!`)PHF1#(```&:%VW49 -MBU84BX($@```#0``$`")@@2```#K%XUV`(M6%(N"!(```"7__^__B8($@``` -M@\0$6U[#B?93BT0D"(M`%(N(;(```(N0<(```(N8;(```#G+@](`N`````") -MV;L`````"<@)VEO#C78`BT0D!(M`%(N`;(```,.)]HM$)`2+4!2+@B2````- -M`````8F")(```,.-=@"+5"0$BT(4BX!DF```B<'!Z1.!X?\!``#VQ0%T!H'Q -M`/[__XM2%(N"<(```(N2;(```#'0,#^!$``/____^X -M`````.LC@^P(5E?H_/___XM7%(F"$(```(/$$(FW^!$``+@!````B?9;7E_# -M@^P4BU0D&(M"%(N`$(```"7__P``4%+H_/___X/$',-55U93@^P4BVPD*&C_ -M'P``5>C\____@\00.T0D)',1QX7\$0``_____[@`````ZSR+=12+GA2```"! -MXP#@__^#[`C_="0L5>C\____)?\?```)PXF>%(```(/$$(M$)"2)A?P1``"X -M`0```)"#Q`Q;7E]=PX/L%(M4)!B+0A2+@!2````E_Q\``%!2Z/S___^#Q!S# -MBT0D!`^V@/,1``"#\`&#X`'#B?:+1"0$B<&#?"0(`'0CBU`4BX($@```)?__ -M__Z)@@2```"!H?`1``#____^ZR&-=@"+4!2+@@2````-`````8F"!(```(&) -M\!$```````&X`0```,-55U93@^P4BVPD*&C_'P``5>C\____@\00.T0D)',1 -MQX4`$@``_____[@`````ZT"+=12+GA2```"!X___`."#[`C_="0L5>C\____ -MP>`0)0``_Q\)PXF>%(```(/$$(M$)"2)A0`2``"X`0```(GV@\0,6UY?7<.# -M[!2+5"08BT(4BX`4@```)0``_Q_!Z!!04NC\____@\0=#?K'XUV`(/B!HF3^`$``(M#%(F0:(```+@!````ZQF-=@"# -M[`S_="0L4O]T)"Q14^C\____@\0@@\0(6\.0@^P4_W0D+/]T)"S_="0L_W0D -M+/]T)"S_="0LZ/S___^#Q"S#BTPD!(M1%(N"!(````T```0`B8($@```@WPD -M"`!T%(M1%(N"!$```"7___S_B8($0```PU93@^P$BW0D$(-\)!0`='2+5A2+ -M@@1````E___\_XF"!$```(/L#&C0!P``Z/S___^["@```(/$$(UV`(M&%(N` -M$$```*D```$`="F#[`QHR````.C\____BU84BX($0```)?___/^)@@1```"# -MQ!!+=#Q!#K(XUV`%)0Z(G___^#Q`CK%%)0 -MZ*7^__^#Q`CK"+@`````ZPF0B9XP$0``B?A;7E_#BT0D!(M`%(N`!$```"4` -M``,`P>@0PY"04X/L"(M$)!2#^`%T#[L`````@_@"=!7K"XUV`+L`````ZPF0 -MN`````#K$Y"#[`A3_W0D'.C\____B=B#Q!"#Q`A;PY"+1"0$BT`4BT`,PY"+ -M1"0$BU`4BT0D"(E"#,.0BT0D!(M`%,=`"`0```##D%93@^P$BW0D$(M&%,=` -M""````"[`````(M&%(M`"*@$=0JX`0```.L>C78`@^P,:@KH_/___X/$$$.! -M^^<#``!^UK@`````@\0$6U[#C78`BT0D!(M0%(N":(```(/@OXF":(```,.0 -MBT0D!(M0%(N":(```(/(0(F":(```,.0BTPD!(M1%(M$)`B)@E"```"+412+ -M1"0,B8)4@```PY!3BU0D"(M,)`RX`````(/Y/W="@_D?=B"+4A2+FE2```"# -MZ2"X_O___]/`(=B)@E2```#K&XUV`(M2%(N:4(```+C^____T\`AV(F"4(`` -M`+@!````6\.04XM4)`B+3"0,N`````"#^3]W0H/Y'W8@BU(4BYI4@```@^D@ -MN`$```#3X`G8B8)4@```ZQN-=@"+4A2+FE"```"X`0```-/@"=B)@E"```"X -M`0```%O#D(M$)`2+0!2+@$R```##B?:+5"0(]L8"=`:`YOV#RB"+1"0$BT`4 -MB9!,@```PXUV`(M4)`R+3"0(QT$(`````(G0)?\/``")00RX`````#E1#'4A -M]D0D$"!T!X%)#``@``#'010`````QT$0`````+@!````PXUV`%=64XM\)!"+ -M="0HBUPD%(M$)!RZ#P```/9#%`$/A`4!``#V0!0!=16+1Q2+0`RZ#P```#M$ -M)!@/A.H```!FBT,0)?\/``!FB0:+2Q2!X0"`_P_!Z0^+1Q2+@&R```")PL'J -M"H'B__\``(G0)?\?```YR',0C8(`X/__)?__```)P>L#D`G1B<@E_W\``&:) -M1@+&1@0`BT,4J`)U.*@$=`C&1@0!ZRZ)]O9#%!!T!H!.!`CK(/9#%`AT!H!. -M!`3K%(!.!`*+0Q0EX````,'H!8A&!8GVBT,0)0``^`?!Z!.(1@:+0Q3VQ`%T -M#B4`?@``P>@)B$8'ZP60QD8'_XM#$"4`@`<`P>@/B$8(BT,0P>@.@^`!B$8) -MBT,0P>@,@^`!B$8*N@````")T%M>7\.0D)!55U93@^P,BWPD((ML)"R)?"0( -MN@P```"+1"0H]D`#`0^$P@4``(/L"/]T)#!7Z/S___^)1"04@\00N@P```"% -MP`^$H04``(-\)"0&="&#?"0D!G<)@WPD)`%W">L1@WPD)`AT"KH,````Z7D% -M``"+1Q2+@!!```")PX/C8(/L"/]T)#!7Z/S___^#Q!"Z`P```(7`#X1.!0`` -MBT\4BW0D"`^VE@\1```/MH80$0``P>`("<(/MH81$0``P>`0"<(/MH82$0`` -MP>`8"<*)D0"```"+3Q0/MI84$0``P>((#[:&$Q$```G0B8$$@```@^P(_W0D -M+%?H!04``(/$$(-\)"0!=$F#?"0D`7(I@WPD)`9T"8-\)"0(=$WK8HM'%,=` -M*`````"+1Q3'@!!```!`$```ZTF+1Q3'0"@!````BT<4QX`00```)!```.LP -MBT<4QT`H`````(M'%,>`$$```"00``#K%XM'%,=`*`````"+1Q3'@!!```!` -M$```BU<4BX(00```"=B)@A!```"+3Q2+1"0(#[:0-!$```^V@#41``#!X`@) -MPHM<)`@/MH,V$0``P>`0"<(/MH,W$0``P>`8"<*)D0B```"+3Q0/MI,Y$0`` -MP>((#[:#.!$```G0B8$,@```BT<4QP``````BT<4QT`$`````(M'%,=`#``` -M``"+1Q2+4!S'0"``````BT<4QT`D`````,>#&!$```````"+1Q2+4"S'0#`% -M````BT<4QT`T!0```(M'%,=`1`@```"+1Q3'0$@(````BT<4QT!0`````(M' -M%,=`3`````"+1Q3'@`Q`````````BT<4QT!``````(M7%(N#]!$``(F"&(`` -M`(M'%,>`2(````````"#[`AJ`%?H_/___XM'%,>`4(````````"#Q!"+1Q3' -M@%2`````````BT<4QX!8@````````(M'%,>`7(````````"+1Q3'@&"````! -M````BT<4QX!D@````0```(M'%,>`:(````````"+1Q3'@"B`````````BT<4 -MQX`L@````````(M'%,>`;(````````"+1Q3'@#"```#_____BT<4QX`T@``` -M_____XM'%,>`.(````$```"Y`````+Z@$0``BQS.A>UT#8V#`(#__SW_#P`` -M=@J+5Q2+1,X$B00:08'YI@```';9@^P(_W0D,%?H_/___X/$$+H#````A<`/ -MA$P"``"+3Q2+D2B8```P]HMT)`@/MH9U$```P>`("<*)D2B8``"+7Q0/MI9V -M$```B=#!X!C!XA`)T`^VCG<0``")RL'B"`G0"+_#_C_#[:&=!```,'@ -M#"4`\`<`"<*)D628``"+3Q2+D1"9``"#XOP/MX9P$```@^`#"<*)D1"9``"# -M[`C_="0,5^A$#0``@\00N@,```"%P`^$5`$``(7M="2+1"0$]D`$`G4$@&`$ -M_HM4)`1FBT("BTPD*&:)00**0@2(002+1Q3'@!R8```!````@^P,:.@#``#H -M_/___XM7%(N"8)@``(/(`8F"8)@``(/$$&H`:@%H8)@``%?H_/___X/$"/]T -M)`Q7Z/S___^#Q!"[`````(7`=1.+7"0H9H-+`@*Z`P```.G"````@^P(4U?H -M_/___X/$$$.#^P)^[8._3!````!T#(/L#%?H_/___X/$$(M7%(N")(```"7_ -M_W_^B8(D@```BW0D"(.^^!$``/]T$H/L"/^V^!$``%?H_/___X/$$(M$)`B# -MN/P1``#_=!*#[`C_L/P1``!7Z/S___^#Q!"+5"0(@[H`$@``_W02@^P(_[(` -M$@``5^C\____@\00@[_X`0```'0/BU<4BX?X`0``B8)H@```BTPD)(F/W`$` -M`+@!````ZQ"+7"0P@SL`=`*)$[@`````@\0,6UY?7<-3BUPD"(M4)`R+0Q2+ -M@`2````E__\``(/Z`71$@_H!?P>%TG0EZV60@_H&=`>#^@AT1NM8BU,4"X/P -M$0``#0``40")@@2```#K0HM3%`N#\!$```T``%(`B8($@```ZRR+4Q0+@_`1 -M```-```4`(F"!(```.L6B?:+4Q0+@_`1```-```0`(F"!(```%O#B?:+1"0$ -M_[#<`0``4.A@____@\0(PX/L$&H*:@C_="0PU575E.#[!2+ -M;"0H_W0D+%7H_/___XG'@\00N@````"%P`^$[0$``(M5%(N":(```(/(8(F" -M:(```(M5%(NR)(```(GP)?__?_^)@B2```"#[`QHH`\``.C\____BU44BX(( -MF```#0````B)@@B8``#'!"0*````Z/S___^#Q`A75>A."0``@\00N@````"% -MP`^$?@$``(/L#&CH`P``Z/S___^+512+@@B8```E____]XF"")@``(/$!(M% -M%(N86)@``(N07)@``(E4)!2+D&B8``")5"00B=J!R@``_`.)D%B8``"+512+ -M1"04)7\`P/\-@,`_`(F"7)@``(M5%(M$)!`E'P#^_PV`$0``B8)HF```:A3H -M_/___XM5%(N"")@```T````(B8((F```QP0D"@```.C\____BT44QX#4F``` -M(0```(M5%(N"")@``"7____WB8((F```QP0DZ`,``.C\____BU44BX)@F``` -M@\@!B8)@F```@\00:@!J`6A@F```5>C\____@\0(BT44B9A8F```BT44BU0D -M$(F07)@``(M%%(M4)`R)D&B8``!75>C\____@\00AC\____@\00A7UW#B?975E.+ -M?"00BW0D%(GPA?9U!;C_____B<.+1Q2)L`!```"#[`S_="0DZ/S___^#Y@^# -MXP]64V@`0```5^C\____B<*#Q"#WQ@0```!U"HM'%,=`%`````")T%M>7\.- -M=@!64X/L!(M,)!2*1"08B$0D`[L`````N@H````/ML"-<`&-=@"-1!(#.D0D -M`W4:@#P1/W0,#[8$$>F>````C78`NP$```#K<9"-1!(##[;`.<9U4872?DV` -M/!$_=#^`?`K_/W0X#[8<$0^V3`K_*@&C1P(#[;#ZT*-=@"[`0```.L5D(/[`74/@#P1/W0)#[8$ -M$>LFC78`2@^)9?___[H`````@#P1/W0&#[8$$>L+0H/Z"G[NN`$```"#Q`1; -M7L.-=@!55U93@^P$BUPD'(ML)"2*5"0@O_____^^_____[D`````B?:`/`L_ -M="HX%`MT3S@4"W,"BH/Y"GX-1`D# -MB$4`#[9$"POK68U$/@.(10`/MM(/M@PS*H/K]"!PN<#``"XTTUB$/?BB=#! -MZ`8"1#,+#[;`@\0$6UY?7<.-=@"+5"0(@_H\=@6Z/````(M$)`1FB9#\`0`` -MN`$```##D%575E.#[!"+;"0DBU0D*(M\)"R);"0$9HN%( -M1P^*A7(0``"#X`>(1Q!FBP(M,A0``+D`````9CV6``^'3`(``+L`````BTPD -M!&8/MH0+>A```&8YA0@"``!T!D.#^P-VY+D`````@_L$#X0=`@``#[<*@>DR -M%```N&=F9F;WZ<'Z`HG(P?@?B=$IP8/Y#(/1_[BKJJJJ]^&)T='IC03-```` -M`"G(C32!BT0D!(VT!GX0``"*1!X9B$<.BE0>&8I&%CC0=@*(T(A'"8I4'AF* -M1A&5!65>CI_?__ -MB,.-1"0>4`^V1PE05E7HUOW__XA$)".#Q""-1"0-4`^V1PA05E7HOOW__XA$ -M)!*-1"0<4`^V1P=05E7HJ?W__XC"@\0@@[T``@````^$]````(N%``(``&:+ -MC`#J%@``#[94)`\/M\&#P`,YPGT'QD0D#P/K!"A,)`\/MD0D#U!65>A^_/__ -MB$<.C40D%U`/MD<.4%95Z$[]__^(PXI4)"J*1"0K@\0<.-!V`HC0B$0D#@^V -MP%!65>A(_/__B$<)C40D%U`/MD<)4%95Z!C]__^(1"0?BE0D*8I$)"N#Q!PX -MT'8"B-"(1"0-#[;`4%95Z!#\__^(1PB-1"074`^V1PA05E7HX/S__XA$)!Z* -M5"0HBD0D*X/$'#C0=@*(T(A$)`P/ML!05E7HV/O__XA'!XU$)!=0#[9'!U!6 -M5>BH_/__B,*#Q!P/MD0D#]'@9HF%_@$``(I'#HA'"HA'"XA'#(A'#8C8*-"( -M!XC8*D0D`HA'`8C8*D0D`XA'`L9'!@#&1P4`QD<$`,9'`P"Y`0```(G(@\00 -M6UY?7<.-=@!75E.#['2+O"2$````:D1H`!<``(U$)`Q0Z/S___^#Q`QJ$6C8 -M%@``C5PD7%/H_/___U/_M"28````5^@<_?__@\0 -M@^P(:@4/MD0<7%#H_/___XA$'&"#Q!!&9H/^!G;?O@<```")]@^WWH/L"&H& -M#[9$'%Q0Z/S___^(1!Q@@\001F:#_@YVWP^V1"11P>`%)>`````/ME0D4(/B -M'PG0"00D#[94)%/!X@>!XH`````/MD0D4L'@`H/@?`G"BD0D4<#H`X/@`PG" -M"50D!`^V5"14P>($@>+P````BD0D4]#H@^`/"<()5"0(#[94)%;!X@:!XL`` -M```/MD0D5='@@^`^"<**1"14P.@$@^`!"<()5"0,#[94)%?!X@.!XO@```"* -M1"16P.@"@^`'"<()5"00#[94)%G!X@>!XH`````/MD0D6-'@@^!^"<**1"17 -MP.@%@^`!"<()5"04#[94)%K!X@6!XN````"*1"19T.B#X!\)P@E4)!@/ME0D -M6\'B`X'B^````(I$)%K`Z`.#X`<)P@E4)!P/ME0D7-'B@^)^BD0D6\#H!8/@ -M`0G""50D(`^V1"1=P>`%)>`````)1"0D#[94)%[!X@.!XO@```"*1"1=P.@# -M@^`'"<()5"0HBD0D7L#H!8/@`0E$)"R#[`AJ`P^V1"1K4.C\____P>`')8`` -M```)1"0P@\0(:@,/MD0D:U#H_/___]'H@^`#"40D-(/$"&H##[9$)&Q0Z/S_ -M___!X`*#X!P)1"0TO@````"#Q!")]HM'%`^WUHL4E(F0G)@``$9F@_X/=NJ+ -M1Q0/M]:+%)2)D-28``"Z`0```(GVB="#Q'!;7E_#C78`5E.#[`R+7"08BW0D -M'&H%#[<.@>D`%```N&=F9F;WZ8G0P?@"P?D?*`P)@```````")LS00``"X`0```(/$%%M>PY"+1"0$BT`4BX!D -MF```P>@3)?\!``#VQ`%T!34`_O__F,.-=@!75E.+="00BWPD%(M&%(N08)@` -M`(/*`HF08)@``&H`:@)H8)@``%;H_/___X/$$+H`````A#^+A_WNL4@_BX?@]FQT<6 -M``"Z`````.L+B?9FB4<6N@$```")T%M>7\.0N`````##B?:X`````,.0D%.# -M[`B+7"00BU0D%+@`````@_H"?QZ#[`3_="0P0`=4^#[`AJ/%/H -M_/___XES!(/$$(-\)"@`=23'0PP+````QT,4`@```,=#&/____]FQT,@"@!F -MQT,B"@#K$I"#[`3_="0L5U7H_/___X/$$(GX@\0,6UY?7<.04XM,)`R+5"0( -MNP````"#^0)W28T$28T$@(V$@CP1``"[`````(-X!`!T,<=`!`````"X_O__ -M_]/`(8(<$0``(8(@$0``(8(D$0``(8(H$0``(8(L$0``NP$```")V%O#55=6 -M4XMT)!2+3"08B?.+EC00``"X`````(/Y`@^'#@(``(T$28T$@(V\ACP1``"X -M`````(-_!``/A/(!``"X`0```(-_!`$/A>,!``#V0@(0='B+1A3'@!"```#@ -M`0``BT84QX`4@`````@`"(M&%,>`((```,^/W0&+5A2+1Q2-!$"-!(#!X!"- -M@```#P`-X`$``(F"0(```(M&%,>`1(```,`#K@6+5A2+@D28``"#X("#R#B) -M@D28``"+1A3'@`28```C(`!OZWJ+1A3'@!"```!H`0``BT84QX`4@`````0` -M!(M&%,>`((```*>/W0&+;A2+5Q2-!)*-!$*-!(*-!,4P`@``P>`+#3`"``") -MA4"```"+1A3'@$2```"8`]<$BU84BX)$F```@^"`@\@`$)?`````)P@^W -M1R"#X`\)PH'*`"`(`(F6'(```/9'#`%T#[@!````T^`)@QP1``#K#;C^____ -MT\`A@QP1``#V1PP!=`^X`0```-/@"8,@$0``ZPVX_O___]/`(8,@$0``]D<, -M`G0/N`$```#3X`F#)!$``.L-N/[____3P"&#)!$``/9'#`1T#[@!````T^`) -M@R@1``#K#;C^____T\`A@R@1``#V1PP(=`^X`0```-/@"8,L$0``ZPVX_O__ -M_]/`(8,L$0``N`$```"-=@!;7E]=PXUV`(M,)`2+1"0(C01`C02`NO____^# -MO(%`$0```74%BT$4BQ")T,.-=@"+5"0$BT0D"(M,)`R-!$"-!("+A()`$0`` -M@_@!=`Z#^`%R&8/X`W<4ZPJ)]HM"%(D(ZQ&0BT(4B4@$ZPBX`````,.)]K@! -M````PXGV5E.#[!"+="0<5NC\____B<.#Q`@E____?U!6Z/S___^+1A2+D&2` -M``"#Q!"#?"04`'0-N"4````IT-'H`<+K'(/Z`78#2NL4@^P(4U;H_/___[@` -M````@\00ZQN+1A2)D&2```"#[`A35NC\____N`$```"#Q!"#Q`1;7L.-=@"+ -M5"0$BT0D"(T$0(T$@(N$@D`1``"#^`)T.H/X`G<)@_@!=`SK.HGV@_@#=`_K -M,9"+0A3'0`@!````ZRR+0A3'0`@"````BT(4QT`H#@```.L6B?:+0A3'0"@* -M````ZPBX`````,.)]K@!````PXGVBTPD!(M$)`B-!$"-!("Z`````(.\@4`1 -M```!=1.+012+0!0E`'@``(G"P>H+C78`B=##D%93@^P$BW0D$(M$)!2-!$"- -M!("+A(9`$0``@_@!=`>#^`)T3>M>BT84QT`("````+L`````C78`BT84BT`4 -M]L1X=!:#[`QJ"NC\____@\000X'[YP,``'[?BT84QT`(`````('[YP,```^> -MP`^VP.L8:@!J!&HL5NC\____@\00ZP>)]K@`````@\0$6U[#D%=64XM4)""+ -M?"0PBW0D.(M,)!2-0OV[````#(/X`78%B=/!XQJ+1"08)?\/``"+5"0HP>(2 -M"="+5"0

(,@>(`\`,`"=`)V/?&`0```'0%#0````'WQA````!T!0T````@ -MB<*#?"0T`'0&@@2B$$%BT(4 -M)0#@'P#!Z`V(00:+0A`E``\``,'H"(A!!XM"$"7P````P>@$B$$(QD$*`,9! -M"P"X`````,.)]L.0D)"+1"0(@$@$"+@`````PY"0@^P,BTPD$(M!%,>`T)@` -M`!8<``"Z`````(UV`(M!%,>`@)@``````0!"@_H'?NV+012+@`"<``#!Z!B) -MPL'J!(/@#\'@!`G0@^P(:@A0Z/S___^#Q!S#D%575E.#[!B+;"0L:.PL``#H -M_/___XG#@\00O@(```"%P`^$.00``(G'@^P$:&P0``!H8!<``%#H_/___XM$ -M)#2)0PR+1"0XB4,0BT0D/(E#%&:)J\@!``!FQX/*`0````!FQX/\`0``/P#' -M@P`"````````QX.H+````````,>#Q"P```````#'@\PL````!P``QX/0+``` -M_____\>#U"P``/_____'@]@L``#_____@\0(:@!3Z/S___^#Q!"^`P```(7` -M#X25`P``9H&[R`$``!OQ=2J+0Q3'@`"B````````BT,4QX!\F```&0```(/L -M#&CH`P``Z/S___^#Q!"+1Q2+@"!````E_P```(G"P>H$B9?,`0``@^`/9HF' -MT`$``(/J`KX-````@_H"#X$@^H1 -M```+`$:#_@EVZKX`````NLPG``!FBP1R9HF$<_03``!FB81S[A,``(T$=HT$ -MAHT$@V;'@+`4```+`&;'@!04```+`$:#_@)VRX/L"(V#;!```%!7Z/S___^# -MQ!"^"````(7`#X1#`0``@[_,`0```W9K9H.[AA````!T88M'%,>``)@```=` -M``"#[`QHT`<``.C\____B3PDZ%;\__]FB8?6`0``BT<4QX``F```!P```,<$ -M)-`'``#H_/___P^WA]8!```E\````(/$$+X-````@_@@#X71````ZPEFQX.& -M$`````"#[`2-1"0.4&B_````5^C\____@\00O@@```"%P`^$HP```&:+1"0* -M9HF#Y`````(M4C!"+1A2)%!B+1A2+!!@YPG0*N`````#K.(UV -M`$&#^0-^W(T$O0````"+3A2+%"B+!`2)!!%'@_\!#XYY____@^P,:F3H_/__ -M_[@!````@\00@\0L6UY?7<.-=@"+5"0,BTPD$(M$)`CVQ`%T$V;'`C@39LX`0```,.-=@"$P'D@BT0D!&:#N(80````=!)FQP(("6;'`:P*N`$```## -MB?:X`````,.)]K@!````PXGV55=64X/L#(ML)"")[HGOC9W@`0``9H.]"`(` -M``%U%8/L!(U$)`Q0:A!5Z/S___^#Q!")]L=#!`````!F@[Z"$````'0;QT,$ -M`0```&:#OG(0````=0K'0P0#````C78`9H.^AA````!T!(-+!`1FQT,0"`EF -MQT,2K`IFQT,,.!-FQT,.U!>`"P.*0P*#R`-FQT,("@!FQT,*@`"#X)^(0P)F -M@[YV$````'0I@^P$C8=($```4&H/5>C\____@\00A'3!````$```"` -M2P*`B?;'0Q0-````QX=H$````0```+@!````@\0,6UY?7<.0D%.+3"0(BUPD -M#(M1%(M#!(F"*(```(M1%(M##(F"+(```(M1%(M#$(F",(```(M1%(M#"(F" -M-(```(M1%(L#B8(@@```6\.)]H/L+(M,)#"+5"0TB50D!(N!W`$``(/X`702 -M@_@!!0 -M4>C\____@\0TPXGVBU0D!(M"%,>`*(````````"+2A2+@02````-```$`"7_ -M_\__B8$$@```BT(4QX`@@```__\``,-75E.+3"00BUPD%(G/9H-[$@!T0(M1 -M%(N"!(````T``!``B8($@```BU$4#[=#$(F")(```(M1%`^W0Q*)@CB```"+ -M412+0Q3!X`.)@C"```#K%9"+412+@@2````E___O_XF"!(```(M1%(L#B8(H -M@```BW$4BX8@@```)0``@/\/MU,("<)F@WL8`'01#[=#&(/`!,'@$"4``'\` -M"<*)EB"```"+E\PL```P]@^W0QK!X`@E`/\```G"B9?,+```BT$4B9`8@``` -MBTD4BY$$0```@>(``/__BT,<@^@#P>`#)?__```)PHF1!$```%M>7\.0BT0D -M!(M`%(N`"$```(7`#Y7`#[;`PXGV4XM<)`B+3"0,BT,4BY#`````@_K_=1'' -M`0````"X`````.F1````D(G0);K8!0&)`??"```(`'0'#0```$")`?;"!70# -M@PD!]\+`!0``=`.#"4#VPB!T$(.[:!````!T!X$)````0)#V00-`=$6)DU`0 -M``"+4Q2+@L0```")@U00``"+@L@```")@U@0``"+@LP```")@UP0``"+@M`` -M``")@V`0``"+@M0```")@V00``"X`0```%O#B?:+1"0$BX`T*@``PY!75E.+ -M="00BUPD%(GQB[XT*@``A?]Y$8M&%,=`)`````"+1A2+0"20B=J!XKK8!0'V -MPT!T,X.Y."H```!T`X/*0(.Y/"H```!T`X#.`8.Y0"H```!T`X#*@(.Y1"H` -M``!T!H#.!(UV`/;#`70#@\H']\,```!`=`:!R@``"`"+1A2)D*````")F30J -M``"%VWD+BT84QT`D`0```)")^%M>7\.0D+B`````PXGVBT0D"&:#^']W'0^W -MP,'@!8M4)`0#0A2+@!R(``"Z`0```&:%P'@%N@````")T,.0BTPD!(M$)`BZ -M`````&:#^'\/AX$````/M\#!X`6)P@-1%,>"`(@```````")P@-1%,>"!(@` -M``````")P@-1%,>""(@```````")P@-1%,>"#(@```````")P@-1%,>"$(@` -M``````")P@-1%,>"%(@```````")P@-1%,>"&(@````````#013'@!R(```` -M````N@$```")T,.05U93BWPD$(M4)!B+="04N`````!F@_Y_=VJ%TG0X#[9: -M!<'C"`^V0@0)PP^V2@/!X1@/MD("P>`0"<$/MD(!P>`("<$/M@()P='IB=C! -MX!\)P='KZPJ[`````+D`````#[?&P>`%B<(#5Q2)BAB(```#1Q2)VH#.@(F0 -M'(@``+@!````6UY?PU575E.#[!"+?"0LBT0D*&:)1"0.@WPD-`$9R??1@>&J -MJJJJN`````!F@WPD#G\/AWP!```/M@>#^`%T%(/X`7\'A`(#[97"`G",+__P``B50D!`^V7Q`/MD<1P>`("<,/MD<2P>`0"<,/MD<3 -MP>`8"<,QRV:#?P(-=P:!X_\````/MTPD#HG(P>`%B<*+?"0D`U<4B:H`B``` -MB<(#5Q2+?"0(B;H$B```B<*+?"0D`U<4B;((B```B<(#5Q2+="0$B;(,B``` -MB<(#5Q2)FA"(```#1Q2+/"2)N!2(``#_="0P4?]T)"SH_/___X/$#(/$$%M> -M7UW#@^P0:@:+1"08!2@J``!0_W0D(.C\____@\0 -M@^8&X`P```-/@]]`APHF3%$```+@!````6\-3BTPD#(M$)`B+6!2+DQA` -M``"X_O___]/`(<*+1"00@^`!T^`)PHF3&$```+@!````6\.0BTPD"+C_____ -M@_D%=Q6+1"0$BT`4BX`<0```@^`OT^B#X`'#@^P,BTPD$(M!%(N0%$```('B -M_'_^_X#.@(-\)!@`=`:!R@```0"+012)D!1```"#[`B+@30J```-`````5!1 -MZ/S___^#Q!S#BT0D!(M(%(N!$$```"6?__'_BU0D"(/B!PL$E0`H``")@1!` -M``##D%93@^P(BUPD%(MT)!QJ!O]T)!R-@RXJ``!0Z/S___^+2Q0/MI,N*@`` -M#[:#+RH``,'@"`G"#[:#,"H``,'@$`G"#[:#,2H``,'@&`G"B9$(@```BTL4 -M#[:#,RH``,'@"`^VDS(J```)PH'F_S\``,'F$`GRB9$,@```@\046U[#4XM$ -M)`B+0!2+B$R```"+D%"```"+F$R````YRX/2`+@`````B=F[``````G("=I; -MPXUV`(M$)`2+0!2+@$R```##B?:+1"0$BU`4BX(@@```#0````&)@B"```## -MC78`BU0D!(M"%(N`9)@``(G!P>D3@>'_`0``]L4!=`:!\0#^__^+4A2+@E"` -M``"+DDR````QT#'(PY!3BU0D"(M"%(N`($```"7_````B<�^[`````,'H -M!#F"S`$``'4,9CF*T`$``'4#LP&0B=A;PXM,)`2+1"0(BU$4BY*0@````1"+ -M412+DHR````!4`2+412+DI2````!4`R+412+DHB````!4`B+412+DIB````! -M4!##5U93BWPD$(MT)!2)^X/^"'86@^P(:/__``!7Z/S___^#Q!`Y\',.D(FS -MT"P``+@`````ZR.#[`A65^C\____BU<4B8)P$```@\00B;?0+```N`$```") -M]EM>7\.#[!2+5"08BT(4BX!P$```)?__``!04NC\____@\0 -M%(```('C`.#__X/L"/]T)"Q5Z/S___\E_Q\```G#B9X4@```@\00BT0D)(F% -MU"P``+@!````D(/$#%M>7UW#@^P4BU0D&(M"%(N`%(```"7_'P``4%+H_/__ -M_X/$',.+1"0$#[:`QRP``(/P`8/@`<.)]HM$)`2)P8-\)`@`=".+4!2+@@2` -M```E_____HF"!(```(&AQ"P``/____[K(8UV`(M0%(N"!(````T````!B8($ -M@```@8G$+````````;@!````PU575E.#[!2+;"0H:/\?``!5Z/S___^#Q!`[ -M1"0D%(```('C__\`X(/L"/]T)"Q5 -MZ/S____!X!`E``#_'PG#B9X4@```@\00BT0D)(F%V"P``+@!````B?:#Q`Q; -M7E]=PX/L%(M4)!B+0A2+@!2````E``#_'\'H$%!2Z/S___^#Q!S#D+@!```` -MPXGVPXUV`+@`````PXGVPXUV`,.-=@"+1"0$BT`4BX`)@EB```##C78`BT0D -M!(N`J"P``,.0@^P,BU0D$(M,)!2+@C00``"%P'4+B8JH+```L`'K#Y"#[`10 -M45+H_/___X/$$(/$#,.)]H/L#(M$)!2+5"08@_@!=12#^@%V![`-@_H%=1JX -M`````.L3D/]T)!Q24/]T)!SH_/___X/$$(/$#,.)]H/L#(M$)!"+3"04BU0D -M'(/Y"W4<@^(&B9#X`0``BT`4B9!(@```N`$```#K&8UV`(/L#/]T)"Q2_W0D -M+%%0Z/S___^#Q""#Q`S#B?:#[!3_="0L_W0D+/]T)"S_="0L_W0D+/]T)"SH -M_/___X7`#Y7`#[;`@\0LPU93@^P$BW0D$(-\)!0`='"+5A2+@@1````E___\ -M_XF"!$```(/L#&H*Z/S___^["@```(/$$(GVBT84BX`00```J0```0!T*8/L -M#&C(````Z/S___^+5A2+@@1````E___\_XF"!$```(/$$$MUR>L'A=MU"XUV -M`+@`````ZQJ0BU84BX($@```)?__^_^)@@2```"X`0```(/$!%M>PY"+3"0$ -MBU$4BX($@```#0``!`")@@2```"#?"0(`'04BU$4BX($0```)?___/^)@@1` -M``##BTPD!(M1%(N"!(````T```0`B8($@```@WPD"`!T%(M1%(N"!$```"7_ -M__S_B8($0```PU=64XM$)!"+7"04BU0D&(G&OP$```"#^P%T(8/[`7((@_L" -M="/K+9"#[`A24.C&_O__B<>#Q!#K(XUV`%)0Z%7___^#Q`CK%%)0Z'W___^# -MQ`CK"+@`````ZPF0B9ZD+```B?A;7E_#BT0D!(M`%(N`!$```"4```,`P>@0 -MPY"04X/L"(M$)!2#^`)T)X/X`G<*@_@!=`WK(XUV`(/X!'0+ZQF0NP````#K -M&9"[`````.L1D+L`````ZPF0N`````#K$Y"#[`A3_W0D'.C\____B=B#Q!"# -MQ`A;PY"+1"0$BT`4BT`,PY"+1"0$BU`4BT0D"(E"#,.0BT0D!(M`%,=`"`0` -M``##D(/L#(M4)!"+0A3'0`@@````:@!J!&H(4NC\____A<`/E<`/ML"#Q!S# -MC78`BT0D!(M0%(N"2(```(/@WXF"2(```,.0BT0D!(M0%(N"2(```(/(((F" -M2(```,.0BTPD!(M1%(M$)`B)@D"```"+412+1"0,B8)$@```PY!3BU0D"(M, -M)`RX`````(/Y/W="@_D?=B"+4A2+FD2```"#Z2"X_O___]/`(=B)@D2```#K -M&XUV`(M2%(N:0(```+C^____T\`AV(F"0(```+@!````6\.04XM4)`B+3"0, -MN`````"#^3]W0H/Y'W8@BU(4BYI$@```@^D@N`$```#3X`G8B8)$@```ZQN- -M=@"+4A2+FD"```"X`0```-/@"=B)@D"```"X`0```%O#D(M$)`2+0!2+@#R` -M``##B?:+1"0$BU`4BT0D"(F"/(```,.)]HM4)`R+3"0(QT$(`````(G0)?\/ -M``")00RX`````#E1#'4A]D0D$"!T!X%)#``@``#'010`````QT$0`````+@! -M````PXUV`%.+3"0@BU0D#(M$)!2[#P```/9"%`$/A,4```#V0!0!=1F+1"0( -MBT`4BT`,NP\````[1"00#X2F````9HM"$"7_#P``9HD!BT(4)0"`_P_!Z`]F -MB4$"QD$$`(M"%*@"=2NH!'0'QD$$`>LAD/9"%!!T!H!)!`CK%(!)!`*+0A0E -MX````,'H!8A!!8GVBT(0)0``^`?!Z!.(00:+0A3VQ`%T#B4`?@``P>@)B$$' -MZP60QD$'_XM"$"4`@`<`P>@/B$$(BT(0)0```#C!Z!N(00F+0A#!Z`R#X`&( -M00J[`````(G86\.0D)!55U93@^QLBZPD@````(EL)"1FQT0D%@``9L=$)!0` -M`,=$)!``````QT0D#`````"+E"2(````#[="`HG"P>H'P>@(,="Z#````*@! -M#X1N"```BXPDB`````^W00*)PL'J!L'H!3'0N@P```"H`0^$3`@``(/L"/^T -M))````!5Z/S___^)1"0P@\00N@P```"%P`^$*`@``(.\)(0````&="J#O"2$ -M````!G<,@[PDA`````%W#.L4@[PDA`````AT"KH,````Z?0'``"#O"2,```` -M`'1SBT44BYA,@```B5PD$(N04(```(E4)`R#O0(`#XFG````BUPD)&:!NVP0````,`^&E````/9!`B!T%`^WNV@1```/ -MMX-L$0``B40D!.L6BU0D)`^WNFH1```/MXIN$0``B4PD!(/L"&H#5^C\____ -MB<>#Q`AJ`_]T)!#H_/___XE$)!0/MUPD)+DL0P``BQ29@.(_B?C!X`8EP``` -M``G"B129OCA#``"+#)Z#X?")^L'J`H/B`8M$)!31X(/@#@G""=&)#)Z#Q!"^ -M`````+\`0@``#[=<)!2-!':+312+%(4`0@```=B+!(>)!!%&@_X;=N6#[`C_ -MM"20````5>C_#```O@````"#Q!"_("@```^W7"06D(T$MHM-%(L4A2`H```! -MV(L$AXD$$4:#_B)VY;X`````OT`P```/MUPD%(GVC01VBTT4BQ2%0#````'8 -MBP2'B0011H/^/W;EO@````"[X"H``+_D*@``B?:+#/.#O"2,`````'0-C8$` -M@/__/?\/``!V"8M5%(L$]XD$"D:!_JH```!VU(.]S`$```-W1(M5%(N*'(`` -M`(G()?__#P`-``#0`8F"'(```(M%%,=`7`````"+113'@'B8```(````BU44 -MBX)(@```@,P$B8)(@```@[PDC`````!T5(M%%(M<)!")F$R```"+112+5"0, -MB9!0@```O@````"#O@M(P``BU44BX(00```"T0D -M+(F"$$```(/$$(M%%(M4)"R)D!1```"+112+3"0HB8@80```BT44BUPD"(F8 -M6(```(M-%(M$)"0/MI`N*@``#[:`+RH``,'@"`G"BUPD)`^V@S`J``#!X!`) -MP@^V@S$J``#!X!@)PHF1"(```(M-%`^VDS,J``#!X@@/MH,R*@``"=")@0R` -M``"+512+@\PL``")@AB```"+113'@(````#_____@[W,`0``!'469H.]T`$` -M``%W#(M5%(M"%(#,!(E"%(/L"/^T))````!5Z/S___^#Q!"Z`P```(7`#X31 -M`@``@[PDA`````9T)XN%!`(``*@#=!V+312+D429``"!XO___]^#X`'!X!T) -MPHF11)D``(/L"/^T))````!5Z,0.``"#Q`C_="0H5>A[!@``@\00N@,```"% -MP`^$`"-@```(%``"+ -M113'@!R8```!````BT44BX`4F0``B<&!X?\_``"+E"2(````]D("('05C12- -M`````+BCBRZZ]^*)T,'H!.L,N,W,S,SWX8G0P>@#@^P,@\!D4.C\____BU44 -MBX)@F```@\@!B8)@F```@\00:@!J`6A@F```5>C\____@\0(_W0D*%7H_/__ -M_X/$$(7`=1R+C"2(````]D$"('4%9H-)`@*Z`P```.FB`0``BUPD)(.[K"P` -M``!T%XM%%,>`()D```#P`0#'@[`L```!````NP````"^`0```(T\G0````"+ -M512)\(C9T^")A#H`$```0X/["7[CNP````"#[`A35>C\____@\000X/["7[M -MBT44QX"D`````0`!`(M%%,>`J`````$```"+113'@*P````!````BU44BX*P -M$```B8*P$```BT44QX"@````90D(`(M<)"3'@S0J``!E"0@`BU44BX*L```` -M#0``!P")@JP```"#O"2$````!G4C\____ -M@\00@[WX`0```'0/BU44BX7X`0``B8)(@```BYPDA````(F=W`$``+@!```` -MZQ6)]HN$))````"#.`!T`HD0N`````"#Q&Q;7E]=PY"#[!1J`O]T)!SH;@,` -M`(/$',.)]E.#[`R+7"04:@%J`%/H_/___X/$$+H`````A`?)@``!D```"#[`QH+`$``.C\ -M____@\00Z:(```")]HM#%,>`!)@```````!F@[O(`0``$@^%A0```(M#%,>` -M?)@``!@```"#[`QH+`$``.C\____BT,4QX``H@```@```(/$$.M9]\80```` -M=`^+0Q3'@`28```#````ZPV+0Q3'@`28````````9H.[R`$``!)U*XM#%,>` -M?)@``!@```"#[`QH+`$``.C\____BT,4QX``H@```````(/$$)"#[`AJ$U/H -MJ0$``(/$$+H`````A'L"P```````"+;Q2+A1"<``")1"04BX44G``` -MBY48G```B50D&(M4)!31ZHG!T>D!RHG!P>D&P>H'B50D#'0]A7UW#5U93BWPD$(MT)!2)\(7V=06X____ -M_XG#BT<4BU`,B;``0```@^P,:@_H_/___X/F`X/C`U93:`!```!7Z/S___^) -MPH/$(/?&`0```'4*BT<4QT`4`````(G06UY?PXGV55=64X/L$(ML)"@/MT4" -M4`^W10!0_W0D+.C\____@\00O@````"`?0(`>3P/O_B-''_!XP*-NR0T``"# -M[`AJ"/]W!.C\____B<:!YO\```#!Y@6+@R0T``#!X`0)QF:+1PB#Q!"-=@!F -M/9``?P2H`70B@^P(:@B8@^@84.C\____B<.!X_\```"X`0```(/$$.LID(/L -M"&H(F(/H&(G"P>H?`=#1^%#H_/___XG#@>/_````N`````"#Q!#!XP+1X`G# -M@(`\/__B=C!X`DE``X```G"#[]$)!@E_P$```G"B9%DF```BU<4 -MBX)@F```@\@"B8)@F```OC@```"$VW01#[;SC03U`````"GPB<;!Y@F[```` -M`(UV`(M'%(N`8)@``*@"=!2#[`Q6Z/S___^#Q!!#@_L[?N'K!8/[.WX'N``` -M``#K"E?H/?___YB#Q`1;7E_#D(M,)`R+5"0$BT0D"`^W0`(EX`$``#W````` -M=#`]P````'\)/:````!T%NLL/4`!``!U)6:+@L@0``!FB0'K(9!FBX+*$``` -M9HD!ZQ1FBX+,$```9HD!ZPBX`````,.)]K@!````PXGV5E.#[`2+7"00BW0D -M%(U$)`)05E/H?____X/$#+H`````AP`^VT(GVB="#Q`1;7L-75E.#[!"+7"0@ -MBW0D)(.[S`$```-W:8/L"%93Z/S___^#Q!"%P'18C40D#E!64^@(____@\0, -MN@````"%P'17OP````"#[`1J``^VAV@U``!04^@\_O__@\009CM$)`Y^"&;' -M1A8``.L$9HE&%D>#_P)VT8/_`P^6P`^VT.L8D(M3%(N"8)@``(/(`HF"8)@` -M`+H!````B="#Q!!;7E_#4[H`````BT0D#&:+`(G!9CL%@#4``'`!```]P`````^$Q@$``#W`````?Q`]H``` -M``^$9P$``.G\`0``/4`!```/A?$!``!FBP(MH0\``&8]Z@1W)8M4)"QFBY)0 -M$0``9HE4)`R+="0L9HNV4A$``&:)="0*Z9<```!FBP(MC!0``&8][P!W(HM$ -M)"QFBX!4$0``9HE$)`R+5"0L9HN25A$``&:)5"0*ZV=FBP(M?!4``&8]X`!W -M(HMT)"QFB[98$0``9HET)`R+1"0L9HN`6A$``&:)1"0*ZS=F@3I<%G8BBU0D -M+&:+DEP1``!FB50D#(MT)"QFB[9>$0``9HET)`KK#F;'1"0*``!FQT0D#``` -MBT0D+&:+J-00``!FBY#:$```9HE4)!!F@[C:$`````^4P&8/ML!FB40D#@^W -M3"0(NYQ#``"+%(N!XO___^^+="0L#[>&R!$``,'@'`G"B12+NZA#``"+%(N! -MXO____L/MX;*$0``P>`:"<*)%(N[7$0``(L4BX/B]P^WAL81``#!X`,)PHD4 -MB^FD````BT0D+&:+@&`1``!FB40D#(M4)"QFBY)B$0``9HE4)`J+="0L9HNN -MUA```&:+AMP0``!FB40D$&:#OMP0````#Y3`9@^VP&:)1"0.ZU>+5"0L9HN2 -M9!$``&:)5"0,BW0D+&:+MF81``!FB70D"HM$)"QFBZC8$```9HN0WA```&:) -M5"009H.XWA`````/E,!F#[;`9HE$)`[K"K@`````Z1,!```/MW0D"+_D0P`` -MBQRW@.,_@^P(:@0/M^U5Z/S____!X`__$,``(LC\____T>B#X`,) -MPXD&O"P```````"X`0```(/$/%M> -M7UW#B?955U93BWPD%(ML)!B)^XM$)!P/MT`")>`!```]P````'0J/<````!_ -M"SV@````=!3K(HGVO@`````]0`$``'0@ZQ*)]KX!````ZQ60O@(```#K#9"X -M`````.F[````B?8/MXQSYA````^WA'/L$```P>`&"<$/MX1S\A```,'@#`G! -M#[>$<_@0``#!X!()P0^WA'/^$```P>`8"<$/MY1S!!$```^WA',*$0``P>`& -M"<(/MX1S$!$``,'@#`G"#[>$`8"<*#_0%T -M#X/]`7(:@_T"=`GK"XUV`(G*ZPR)T>L(N`````#K'I")JZ@L``"+1Q2)B&"9 -M``"+1Q2)D&29``"X`0```%M>7UW#B?955U93BWPD%(G^BU0D&`^W0@(EX`$` -M`#W`````=$H]P````'\+/:````!T-.M"B?8]0`$``'4YO0````"+3Q2+D429 -M``"#XL`#@^`X"<*)D429``#K'9"]`0```.L5D+T"````ZPV0 -MN`````#ITP$``(GV@[_,`0```W<7BU<4BX(0F0``@\@#B8(0F0``ZU.-=@"+ -M3Q2+@1"9```E!OS__P^WE&[@$```P>($"="#R`&)@1"9``#_="08_[:H+``` -M5^C\____BU<4#[^$;L@0```E_P$``(#,`HF":)D``(/$#(M/%(N11)@``('B -M?\#__P^WA&Z>$```P>`')8`_```)PHF11)@``(M/%(N12)@``('B_P_\_P^W -MA&ZD$```P>`,)0#P`P`)PHF12)@``(M/%(N14)@``('B``#__P^^A#7%$``` -MP>`()0#_```)P@^VA#7"$```"<*)D5"8``"+7Q0/MY1NMA```(G0P>`8P>(0 -M"=`/MXQNO!```(G*P>(("=`)R(F#-)@``(M/%(N1*)@``##V#[>$;JH0``#! -MX`@)PHF1*)@``(M/%(N19)@``('B_P_X_P^WA&ZP$```P>`,)0#P!P`)PHF1 -M9)@``+L"````9H&^;!````(P=QQF@;_*`0``(A!U-8M$)!CV0`)`="NS".LG -MC78`BU0D&&:+`H/@'P^WP(7`=!.#Z`J#^`QV"P^WA&XB$0```<.0BT\4BY$D -MF0``@.(!C00;)?<````)PHF1))D``+@!````6UY?7<.)]HM,)`2+5"0(B="# -M^C]V!;@_````9HF!_`$``(M!%(F0/)D``+@!````PXGV55=64X/L+(M\)$2+ -M7"1`#[='`B7@`0``/<````!T5CW`````?PX]H````'1[Z:H```")]CU``0`` -M#X6=````9HN#XA$``&:)1"04C8/.$0``B40D$(V#Y!$``(E$)!@/MX-&%0`` -MB40D"(VK2!4``.F#````9HN#[!,``&:)1"04C8/N$P``B40D$(V##A0``(E$ -M)!@/MX.8%0``B40D"(VKFA4``.M09HN#[!,``&:)1"04C8/T$P``B40D$(V# -MJA0``(E$)!@/MX.X%0``B40D"(VKNA4``.L=D+@`````Z98```")T,'@!HV< -M&-`5``")7"0,ZV2#[`0/MP=0C40D&%#_="1,Z'<```#'1"0<`````(/$"%?_ -M="1,Z/S___^)QKH`````@\009H.[M1BM1]VPD'(G3P?L$BT0D -M')F)V"G0C5`!#[=$)")FBUPD)F:)'$%F_T0D(D)1"0,#[]$ -M10")RBG"B50D$(M$)`P/OU1%`BG1BT0D$`^OP87`?BI'BU0D&&8Y=%7^?AX/ -MM]`/M\!0#[>$$@@```#1X`^WP%`/MT15`E`/MT15`%`/M\90Z)$'``!`#[=4 -M)$*Y(`$``&;1Z&:)!%&#Q""+7"0D9CG8=@1FB1Q19O]$)"(/MQ4&````9CET -M5?X/CR?___]F@WPD(C]W)+L@`0``N1X!```/MU0D(F:+!%%FB0139O]$)")F -M@WPD(C]VYKF`H0``OP````"^(@$``+L@`0``#[?'#[<4AL'B&('*``#_``^W -M!(/!X`@,_R7__P``"<*+;"1`BT44B10(@\$$1V:#_Q]VS(/$+%M>7UW#55=6 -M4X/L/(MT)%R+1"10B40D&&;'1"06``!FQT0D%```9L=$)!(``&;'1"00``!F -MQT0D#C\`9L=$)`H``+^@`0``BU0D8`^^0@71X&:)1"0,]D(#`706BTPD4(J! -MBA```.L49HE<)!+I6`$``(M4)!B*@HL0``"#[`0/OL!0_W0D:/]T)%SH_/__ -M_XA$)!F#Q!"#?"14``^$HP```+L`````B?8/M].+3"149H,\T0!T$&:+!-%F -MB414($-F@_L'=N*)W8/L#(U$)"I0C40D+%`/M\-0C40D.%"+5"1\#[<"4.C= -M!@``NP````"#Q"!F.>MS%(M4)!P/M\-F.51$('0&0V8YZW+PBT0D'&8[1"0> -M=0Z+3"1@9HL!9CM$)!QT#@^WPXM4)%2#?,($`'01#[?#BTPD5&:+1,$"9HE$ -M)`Z[`````&8Y\W,#X2D_O__0V8Y\W+3 -MNP````")]HM,)&#V00)`#X36````9H/[!'!FBQ=F*<)FB50D"F:% -MTG\'9L=$)`H!``^WRP^_1"0*#[<43SG0?@*)T&:)!$]#9H/[!P^&D_W__P^W -M!XM4)!B)@L`L``"+3"10BUD4N0````"#X0'!X1ZX/P```&8C1P;!X!B)R@G" -MN#\```!F(T<$P>`0"<*X/P```&8C1P(/M\#!X`@)PK@_````9B,'#[?`"<*) -MDS29``"+1"10BU`4N#\```!F(T<.P>`8"<&X/P```&8C1PS!X!`)P;@_```` -M9B-'"@^WP,'@"`G!N#\```!F(T<(#[?`"<&)BCB9```/MP=0_W0D5.C\____ -M9HL'BU0D6&:)@OX!``"#Q$1;7E]=PXUV`%575E.#[!R+?"0XBW0D,(M<)#2- -M1"0:4%7UW#55=64XMT)!R+;"04BWPD&(M."+L````` -M9H-^!`!V1Y!F.2EU-XU1"+@`````9H-Y!@!V*&8Y.G47#[?`9HM401Z+1"0@ -M9HD0N`$```#K')"#P@)`9CE!!G?:B?:#P31#9CE>!'>ZN`````!;7E]=PU57 -M5E.#[`2+;"08BTPD'(M\)""+="0DBUPD*&;'1"0"9``/M\8/M],/K\*Z```` -M`(7`#X2C````@WPD+`!T!V;'1"0"`0!F.<]T=0^WQ0^WR2G(C02`C02`P>`" -M#[?7*0U``")D`PJ``"-!-4`````*="-!(7H-0``B4$8QT$4`0`` -M`,=!#!0```#'01`C````PY!75E.+5"04BT0D$(N`-!```/9``B!T);\````` -MNQP```"Y0````+YR````QT(,`````,="$'<```#K(Y"_`````+LR````N0`` -M``"^,@```,="#!0```#'0A`C````BU($N``````Y^G($.=IV#3G*<@0Y\G8% -MN`$```!;7E_#D(M$)`2+2!2+D,`L``#!X@F!X@!^``"`SH")D3"9``#'@+PL -M```!````PXGV5U93BWPD$(G[C;<,*@``N`````"#?A0`='2#O[PL```!=66+ -M1Q2+@#"9``!FA'O"P```````!65^@,____@\0(A#[`A65^A)`0``QX>\ -M+````@```(/$$(N#O"P``%M>7\.)]HM,)`BX`````(M1!#M1#'8%.U$0<@6X -M`0```,-64XM<)!"Z_____X-[%``/A/<```"+`XT4Q0`````IPHT4E>@U``") -M4QB+0P0[0Q!R8KK_____@SL`#X3,````BT,$B4,(.T,0("BTL8BX+P-0``*T$(T>"+2P@IP8E+"('"Z#4``(E3&#M+ -M$'('@SL`=<:)]KH!````ZWF0BT,$N@`````[0PQW:Z'@-0``2+K^____.0-T -M7(M#!(E#"#M##'=)H>`U``!(.0-S/XG&D(L#0(D#C13%`````"G"P>("BTL8 -MBX+P-0``*T$(T>"+2P@IP8E+"('"Z#4``(E3&#M+#'<'.3-RQXUV`+H"```` -MC78`B=!;7L.-=@"+3"0$BU0D"(-Z%`!T-XM"&&:+`&:)@@!P^L?C78`@_L!=@-+ZQ2#[`A6 -M5^C\____N`````"#Q!#K*HM/%('B#_S__XG8P>`$)?`#```)PHE1,(/L"%97 -MZ/S___^X`0```(/$$%M>7\.)]E.#[`B+7"00BU0D%+@`````@_H)?QZ#[`3_ -M="0+_ -M`P``BX%$*@``P>`0)0``_P,)PHF3J````(M9%(N#K````"4`_/__BY%(*@`` -M@>+_`P``"=")@ZP```!;PY!64XMT)`R+3"00N`````"#^0EW5(T$28T$@(V< -MADPJ``"X`````(-[!`!T/,=#!`````"X_O___]/`(88X*@``(88\*@``(89` -M*@``(89$*@``(89(*@``4U;H+?___[@!````@\0(D%M>PY!55U93BWPD&(ML -M)!2+E300``"X`````(/_"0^'U`,``(T$?XT$@(VTA4PJ``"X`0```(-^!``/ -MA+@#``"#?AC_=3:%TG05#[="`B6@````NA\````]H````'0%N@\```"X`0`` -M`#G0+_`P`` -MBT8

`*)0#\#P`)PHM&%,'@%"4``/`/"<*)E!E`$```BT0D%(M(%`^W1B+! -MX`0E\`````^W5B"#X@\)T`T`(`@`B809@!```(M4)!2+0A3'A!C`"0````@` -M`(.ZS`$```-W#HM"%,>$&``1```````!@WXD`'1.C0R]`````(M$)!2+6!2+ -M5B2!XO___P"+1BC!X!@)PHF4"\`(``"+5"04BUH4BX0+P`D``(G"@\H!@WXH -M`'0(B<*!R@$!``")E`O`"0``@WXP`'0BC0R]`````(M$)!2+4!2+1C`E____ -M``T````!B80*``D``(-^+`!T0XT,O0````"+1"04BU`4BT8L)?__#P`-```0 -M`(F$"L`0``#V1@P@=!N+1"04BU`4BX0*P`D``(#,`HF$"L`)``"-=@#V1@X! -M="&-#+T`````BT0D%(M0%(N$"@`1```-```@`(F$"@`1``#V1@Z`=!^-#+T` -M````BT0D%(M0%(N$"@`1``"`S`*)A`H`$0``BT8$@_@"=`J#^`-T4>G*```` -MC0R]`````(M$)!2+4!2+A`K`"0``#**)A`K`"0``BU0D%(.ZS`$```09VX'C -M`````8'#```E`(G*BTPD%(M!%(F<$``1``#I?@```(T,O0````"+1"04BU`4 -MBX0*P`D```UB`@``B80*P`D``*$`````*P4`````BY7(+```B=,IPRL=```` -M`,'C"HM$)!2+4!2)V`T````!B80*``D``(M4)!2#NLP!```$&=N!XP````&! -MPP``!`")RHM,)!2+012)G!#`"0``D/9&.`%T(8T,O0````"+1"04BU`4BX0* -M`!$```T``"0`B80*`!$``/9&#`%T$[@!````B?G3X`F%."H``.L1B?:X_O__ -M_XGYT\`AA3@J``#V1@P!=!.X`0```(GYT^`)A3PJ``#K$8GVN/[___^)^=/` -M(84\*@``]D8,`G03N`$```")^=/@"85`*@``ZQ&)]KC^____B?G3P"&%0"H` -M`/9&#`1T$[@!````B?G3X`F%1"H``.L1B?:X_O___XGYT\`AA40J``#V1@P( -M=!.X`0```(GYT^`)A4@J``#K$8GVN/[___^)^=/`(85(*@``5O]T)!CH-_O_ -M_[@!````@\0(C78`6UY?7<.-=@"+1"0(P>`"BU0D!(M2%(N$`@`(``##B?:+ -M5"0(P>("BT0D!(M(%(M$)`R)A!$`"```N`$```##D(M,)`B+1"0$BU`4N`$` -M``#3X(F"0`@``+@!````PXGV5E.+5"00P>("BT0D#(MP%(N$%@`*``")PX/C -M`W4:N`$```"*3"00T^"+ED`(``"%PG0%NP$```")V%M>PXUV`%=64XM\)!"+ -M="04BU<4N`$```")\=/@B8*`"```NP````")]E97Z/S___^#Q`B%P'06@^P, -M:@KH_/___X/$$$.!^P\G``!^W(M'%,>`@`@```````"!^P\G```/GL`/ML!; -M7E_#C78`5E.+="0LBUPD-(M,)!"+1"04)?\/``"+5"0DP>(2"="+5"0PP>(9 -M"=#VPP%T!0T````!]L,0=`4-````(/;#!'0%#0``0`#VPR!T!0T``(``B4$( -MBT0D'(G"P>(:]L,"=`:!R@``@`")40R#_O]T%HGPP>`-)0#@#P`)T(E!#(%) -M"````$"X`0```%M>PXGVN`````##B?:+1"0(@4@(````(,-3BTPD$(M<)!B+ -M5"0,@WPD%`!T%(M"#`G(A=MU`X#,$(E"#.LGC78`A=MT$(M$)!R+0`B)0@B) -M2@SK$9#'0@@`````B+0A`E\``` -M`,'H!(A!"(M"$"4`\```P>@,B$$)QD$*`,9!"P"$VW0&C4,!B$$'@'D(`'0# -M_D$(N`````!;PXGVPY"0D(M4)`2+3"0(@(JX+```"(!)!`AFBX*V+```9HD! -MBH*X+```B$$$BH*Y+```B$$%N`````##D)"0BU0D!(M"%,>`@$````#\2)*+ -M0A3'@(!````D29(DBT(4QX"`0```.0``*(M"%,>`@$```"0(%E.+0A3'@(!` -M``!Y!9CEBT(4QX"`0```_^\=`(M"%,>`@$```$"^JAJ+0A3'@(!```!451"^ -MBT(4QX"`0```!S`.`(M"%,>`A$````````##D(/L#(M,)!"+013'@-"8```6 -M'```N@````"-=@"+013'@("8``````$`0H/Z!W[MBT$4BX``G```P>@8B<+! -MZ@2#X`_!X`0)T(/L"&H(4.C\____@\0R<````BZPDL````(GK -MC7PD<+YX1P``_+D%````\Z6-?"10OHQ'``"Q!?.EC7PD,+Z@1P``L07SI8U\ -M)!"^M$<``+$%\Z6Z`````(M$E'")A),D1```BT244(F$DSA$``"+1)0PB823 -M3$0``(M$E!")A)-@1```0H/Z!'[.@^P(:@%5Z/S___^!Q*P```!;7E]=PXM$ -M)`C1X`-$)`R+5"0$#[>$0OH3``##D%93@^P(BUPD%(MT)!AH;!```&@`-P`` -M4^C\____BT0D*(E##(M$)"R)0Q"+1"0PB4,49HFSR`$``&;'@\H!`````&;' -M@_P!```_`,>#``(```````#'@[@M````````QX.\+0```````,>#R"T````` -M``C'@]`M``"!!P``QX/8+0```````,>#W"T``#\_/P#'@^`M``!D````QX/D -M+0```@```,>#]"T``/_____'@_@M``#_____QX/\+0``_____X/$#&H&:,A' -M``"-@S@J``!0Z/S____&@P`N````@\046U[#B?93BDPD"(I<)`RZ`````(GV -MC012.(C.1P``=1DXF,]'``!W$3B8T$<``'()N`$```#K#8GV0H/Z`W;6N``` -M``!;PXUV`%575E.#["B+;"1,BUPD/&B@1```Z/S___^)QH/$$(7`=1+'10`" -M````N`````#I&0<``)"#[`A5_W0D2/]T)$C_="1(#[?#4%;H_/___XGS@\0< -M:@%J`%;H_/___X/$$(7`=1#'1"04`P```.F[!@``C78`BT84BX`@0```#[;0 -MB=#!Z`2)ALP!``")T(/@#V:)AM`!```/ML!0#[:&S`$``%#H%/___X/$"(7` -M=0W'1"04#0```.EP!@``@^P(:@!6Z/S___^#Q!"%P'4.QT0D%`,```#I408` -M`)"+1A2+@!B8``!FB8;2`0``@[[,`0``"703@[[,`0``"G469H.^T`$```-W -M#%/H-OS__X/$!(UV`(/L#%/H_/___X/$$(7`=1#'1"04#@```.G[!0``C78` -M@[O,`0``!'82BU,4BX(00```@,P0B8(00```BT,4QX``F```!P```(/L#%/H -M_/___V:)@]0!``"#Q!`/M\`E\````(/X,`^$L````(/X,'\4@_@0#X2B```` -M@_@@#X29````ZR"#^&`/A(X```"#^&!_"X/X4`^$@````.L'/:````!T=V:# -MN]0!````=6V#N\P!```%=1B!N]`!```)`$,`=0QFQX/4`0``1@#K39"#N\P! -M```'=`F#N\P!```+=0MFQX/4`0``40#K+X.[S`$```IT'(.[S`$```ET$X.[ -MS`$```IU'6:#N]`!```#=PIFQX/4`0``8@"0@[O,`0``"G1+@[O,`0``"71" -M@[O,`0``"G4*9H.[T`$```-V+P^WD]0!``")T"7P````@^@P@_@_=QF)T(/@ -M#X/X!'\/QT0D%`T```#IJ@0``(GV@^P$C40D'E!HP0```%/H_/___X/$$(7` -M=0['1"04"````.F!!```D&:!?"0:`3!W#<=$)!0%````Z6H$``!FBT0D&F:) -MAFP0``"+0Q2+D!!```"#XAC!Z@.#^@)T.X/Z`W4-QT0D%`H```#I.`0``(.[ -MS`$```ET((.[S`$```IU"F:#N]`!```#=@W'1"04"@```.D/!```@^P$C40D -M'E!J/U/H_/___X/$$(7`=0W'1"04"````.GK`P``9HM$)!IFB89N$```@^P$ -MC40D'E!J'%/H_/___X/$$(7`=0W'1"04"````.F[`P``QT0D#$`#``!F@WPD -M&@!T1@^W1"0:)?#_``#!X`R)1"0,@^P$C40D'E!J&U/H_/___X/$$(7`=0W' -M1"04"````.EV`P``#[=$)!H)1"0,@6PD#,````#'1"00`````+\`````BT0D -M##G'4(V'P````%!3Z/S___^#Q!"%P`^$*`,```^W1"0:,40D -M$$<[?"0,$ANH1```+`$>#_PEVZK\`````N6Q'``"Z#_P)VQX/L"(V&;!```%!3Z/S___^#Q!"%P'4-QT0D%`@```#I -M<`(``&:!OFP0```"4'=)@[O,`0``"G0<@[O,`0``"703@[O,`0``"G4N9H.[ -MT`$```-W)&;'AOP3``!H!F;'A@`4``"P!&;'A@04````@&;'AOH3````@&:# -MOH80````='8/MX/4`0``)?````"#^!!U98M#%,>``)@```=```"#[`QHT`<` -M`.C\____B1PDZ/S___]FB8/6`0``BT,4QX``F```!P```,<$)-`'``#H_/__ -M_P^W@]8!```E\````(/$$(/X('0/QT0D%`T```#IG@$``(GV@^P$C40D'E!H -MOP```%/H_/___X/$$(7`=0W'1"04"````.EU`0``9HM$)!IFB89P$```9HF# -M"`(``(/L#%/H_/___X/$$(7`=0W'1"04"````.E%`0``@[O,`0``"G0<@[O, -M`0``"703@[O,`0``"G4=9H.[T`$```-W$X/L"(U$)!Q04^C\____@\00ZUV# -MN\P!```'=`F#N\P!```+=1.#[`B-1"0<4%/H_/___X/$$.LX#[>#U`$``"7P -M````@^@P@_@_=Q.#[`B-1"0<4%/H_/___X/$$.L1@^P(C40D'%!3Z/S___^# -MQ!"%P`^$J````(N&P"H``(F#P`$``(/L#%/H_/___\=$)"``````OP````"# -MQ!"#[`2-1"0>4+@?````*?A04^C\____@\00AY`````(M4 -MC!"+1A2)%!B+1A2+!!@YPG0*N`````#K.(UV`$&#^0-^W(T$O0````"+3A2+ -M%"B+!`2)!!%'@_\!#XYY____@^P,:F3H_/___[@!````@\00@\0L6UY?7<.- -M=@!3BTPD"(M4)!"+7"04BT0D#/;$`7029L<",Q-FQP/4%[@!````ZS60A,!Y -M*&:#N880````=0IF@[F($````'049L<""`EFQP.L"K@!````ZPN-=@"X```` -M`(UV`%O#B?955U93@^P,BWPD((G]B7PD!(VWX`$``&;'1"0*``!F@;]L$``` -M`%!V)X/L!(U$)`Y0:,D```!7_Y>@`0``@\00N@````"%P`^$O`,``(UV``^W -MA]0!```E\````(/X0'4+9L>%@A``````B?9F@WPD"@!U+(._S`$```=U(V:# -MO]`!```(=1EFQT0D"@4`9L>%%=!````$`BT0D!(.XW`$```9T -M0V:!N,H!``!E<'4X9HN0"`(``(U"G&:#^`%W$(U"!8M4)`1FB8((`@``ZQB+ -M1"0$9H.X"`(``$%U"F;'@`@"``!#`)#'1@0`````9H.]@A````!T&\=&!`$` -M``!F@[UR$````'4*QT8$`P```(UV`&:#O880````=`2#3@0$9H.]B!````!T -M+(M4)`1F@;K*`0``$0YT'8M6!(G0@\@(B48$9H.]=!````!U"(G0@\@HB48$ -M9L=&$`@)#[>'U`$``"7P````@^@P@_@_=CJ#O\P!```'=#&#O\P!```+="B# -MO\P!```*=!^#O\P!```)=!:#O\P!```*=15F@[_0`0```W<+C78`9L=&$L0) -MZPAFQT82K`J)]F;'1@PS$V;'1@[4%XI&`8/@OX/(@(A&`;@`````]D0D"@)U -M)(._S`$```5W$X._S`$```5U$F:#O]`!```#=@BX`0```(UV`,'@!8I6`8/B -MVPG"@\H(#[=$)`K1Z(/P`8/@`='@@^+]"<*(5@&#O\P!```&=@J(T(/($(A& -M`>L$@&8![X`.`XM$)`1F@[C0`0```7<+@[_,`0``"W5?B?:X`````/9$)`H! -M=0CV1@0)=`*P`8T`#B40D#(G0*P4`````P>`#B40D$(U"`8E$)`B+ -M1"0X)?__@`&)!"2#[`B-1"0(4%'H_/___X/$/,.0BU0D!(M"%,>`*(`````` -M``"+2A2+@02````-```$`"7__\__B8$$@```BT(4QX`@@```__\``,-55U93 -MBWPD%(M,)!B)_F:#>1(`=#^+5Q2+@@2````-```0`(F"!(```(M7%`^W01") -M@B2```"+5Q0/MT$2B8(X@```BU<4BT$4P>`#B8(P@```ZQ2+5Q2+@@2````E -M___O_XF"!(```(M7%(L!B8(H@```BU\4BX,@@```)0``@/\/MU$("<)F@WD8 -M`'01#[=!&(/`!,'@$"4``'\`"<*)DR"```"+AM`M```PY`^W41K!X@B!X@#_ -M```)T(F&T"T``(M7%(F"&(````^W<0@Y<1QV`XMQ'(M9##E9''8#BUD<.=YU -M!HMI!.L#D(LIBU<4BT$$@^@#P>`#)?__!P`-```8"HF"U(```(M7%(T$[>C_ -M__\E__\'``T````*B8+8@```BT\4B?`E__\``(G:P>(0"=")@=R```!;7E]= -MPU.#[`B+7"00BU,4BT0D%(F"`&```(M#%,>`"&````$```!J`FH#:`Q@``!3 -MZ/S___^#Q!"Z`````(7`=!6+0Q2+D`1@``"+1"089HD0N@$```")T(/$"%O# -MD)"04XM$)`B+6!2+3"0,T>&X`P```-/@BY,40```"=")@Q1```"X`0```%O# -MB?93BT0D"(M8%(M,)`S1X;@#````T^#WT(N3%$```"'0B8,40```N`$```!; -MPU.+3"0,BT0D"(M8%(N3&$```+C^____T\`APHM$)!"#X`'3X`G"B9,80``` -MN`$```!;PY"+3"0(N/____^#^05W%8M$)`2+0!2+@!Q```"#X"_3Z(/@`<-6 -M4X/L!(MT)!"+5"04BT84BY@40```C0P2N`,```#3X`T`\`$`]]`AP\'B#`G3 -M@,^`@WPD&`!T!H'+```!`(M&%(F8%$```(/L"(N&0"H```T````!4%;H_/__ -M_X/$%%M>PY"0BT0D!(M`%(N`"$```(/X`0^4P`^VP,.055=64X/L!(MT)!B+ -M?"0'_`P``"=$E -M``#_`\'H$`G(BQ0DB8*<1```]L,@=!"#OF@0````=`>!#P```$"0B>@+!XD' -MJ0```$!T18F>4!```(M6%(N"Q````(F&5!```(N"R````(F&6!```(N"S``` -M`(F&7!```(N"T````(F&8!```(N"U````(F&9!```+@!````@\0$6UY?7<.0 -MBT0D!(N`0"H``,.055=64XMT)!2+3"08B?.+KD`J``"%[7D0BT84QT`D```` -M`(M&%(M`)(G*@>*ZV`4!OP````#VP4!T,H.[R"H```!T`X/*0(.[S"H```!T -M`X#.`8.[T"H```!T`X#*@(.[U"H```!T!8#.!(GV]L$!=`.#R@?WP0``X`)T -M0('*``"``/?!```@`'0&@<\````!]\$``$``=`:!SP```"#WP0``@`!T!H'/ -M````!/?!`````G0(@<\````"B?;WP0```$!T!H'*```(`(M&%(F0H````(M6 -M%(N"K````"7___]("?B)@JP```")BT`J``"%R7D-BT84QT`D`0```(UV`(GH -M6UY?7<.0BT0D!`^W@.H!``##BU0D!(M$)`AF.8+J`0``=AD/M\#!X`4#0A2+ -M@!R(``"Z`0```&:%P'@%N@````")T,.)]E93BUPD#(MT)!"X`````&8YL^H! -M```/AMD````/M\;!X`6)P@-3%(N*%(@``,>"`(@```````")P@-3%,>"!(@` -M``````")P@-3%,>""(@```````")P@-3%,>"#(@```````")P@-3%,>"$(@` -M``````")P@-3%,>"%(@```<```")P@-3%,>"&(@````````#0Q3'@!R(```` -M````@_D$=4WV@\LM```(=$2-1D`/M\#!X`6)P@-3%,>"`(@```````")P@-3 -M%,>"!(@```````")P@-3%,>""(@````````#0Q3'@`R(````````D+@!```` -M6U[#5U93BWPD$(M4)!B+="04N`````!F.;?J`0``=FN%TG0X#[9:!<'C"`^V -M0@0)PP^V2@/!X1@/MD("P>`0"<$/MD(!P>`("<$/M@()P='IB=C!X!\)P='K -MZPN[`````+D`````D`^WQL'@!8G"`U<4B8H8B````T<4B=J`SH")D!R(``"X -M`0```%M>7\-55U93@^PHBUPD/(ML)$2+1"1`9HE$)":)7"0@C9/@`0``@WPD -M3`$9R??1@>&JJJJJO@````!F.4(*#X:D`P``#[9%`(/X!0^'EP```/\DA=Q' -M``#'1"00!0```.F/````O@````#V0@$@#X1T`P``QT0D$`8```#K=L=$)!`$ -M````]H/++0``"'1E#[=$)":#P$`/MU(*O@`````YT`^-0`,``.M*O@````!F -M@WT"!`^&+@,``,=$)!``````9H-]`@5V*V:#?0(.&=*#XOZ#P@.)5"00ZQC' -M1"00!P```.L.B?:^`````.GV`@``B?8/MGT$B7PD'`^V107!X`@)QXE\)!P/ -MMD4&P>`0"<>)?"0<#[9%!\'@&`G',<^)?"0<#[9%"<'@"`^V50@)PC'*@>+_ -M_P``B50D&`^V?0H/MD4+P>`("<`0"<`8"<;_````@WPD$`0/A<(%B=$#2Q2+1"0<]]")@0"(``")T0-+ -M%(M$)!CWT(F!!(@``(G0`T,4B;@(B```B=`#0Q2+3"04B8@,B```B=`#0Q2) -ML!"(```#4Q3'@A2(```$````_W0D2/]T)`13Z/S___\/MGT4#[9%%<'@"`G' -M#[9%%L'@$`G'#[9%%\'@&`G'#[9-&`^V11G!X`@)P0^V11K!X!`)P0^V11O! -MX!@)P8/$#(M$)"#V@,PM```$=$,/MD4?P>`(#[95'@G"B50D"`^V11W!X`@/ -MME4<"<*)5"0$#[9U(`^V12'!X`@)Q@^V12+!X!`)Q@^V12/!X!@)QNL5O@`` -M``#'1"0$`````,=$)`@`````#[=$)`[!X`6)P@-3%(FZ`(@``(G"`U,4BWPD -M"(FZ!(@``(G"`U,4B8H(B```B<(#4Q2+;"0$B:H,B```B<(#4Q2)LA"(``") -MP@-3%,>"%(@```<```")P@-3%,>"&(@````````#0Q3'@!R(````````#[=$ -M)";!X`6)P@-3%(M,)!R)B@"(```#0Q2+?"08B;@$B```ZVJ)]@^W3"0FB7UW#D)"#[!!J!HM$)!@%+"H``%#_="0@ -MZ/S___^#Q!S#@^P0:@;_="0PU.+1"0(BT`4BXA,@```BY!0 -M@```BYA,@```.+5A2+B@2```"$P'06T.@\`G<0B<@-`````HF" -M!(```.L1D(M6%(G()?____V)@@2```!;7L.0BU0D!(M"%(N`9)@``(G!P>D3 -M@>'_`0``]L4!=`:!\0#^__^+4A2+@E"```"+DDR````QT#'(PY!3BU0D"(M" -M%(N`($```"7_````B<�^[`````,'H!#F"S`$``'4,9CF*T`$``'4#LP&0 -MB=A;PXM,)`2+1"0(BU$4BY*0@````1"+412+DHR````!4`2+412+DI2````! -M4`R+412+DHB````!4`B+412+DIB````!4!##N`$```##B?:+1"0$BT`4BX`< -MG```)?\```##D(M$)`2+0!2+@%B```"#X`?#C78`BT0D!(M0%(M$)`B#X`>) -M@EB```##C78`BT0D!(N`N"T``,.0@^P,BU0D$(M,)!2+@C00``"%P'4+B8JX -M+0``L`'K#Y"#[`1045+H_/___X/$$(/$#,.)]K@!````PXGV5U93BWPD$(MT -M)!2)^X/^!786@^P(:/__``!7Z/S___^#Q!`Y\',2D,>#]"T``/____^X```` -M`.LC@^P(5E?H_/___XM7%(F"C\____@\00.T0D)',1QX7X+0``_____[@`````ZSR+=12+GA2```"!XP#` -M__^#[`C_="0L5>C\____)?\_```)PXF>%(```(/$$(M$)"2)A?@M``"X`0`` -M`)"#Q`Q;7E]=PX/L%(M4)!B+0A2+@!2````E_S\``%!2Z/S___^#Q!S#BT0D -M!`^V@,LM``"#\`&#X`'#B?:+1"0$B<&#?"0(`'0CBU`4BX($@```)?____Z) -M@@2```"!H<@M``#____^ZR&-=@"+4!2+@@2````-`````8F"!(```(&)R"T` -M``````&X`0```,-55U93@^P4BVPD*&C_/P``5>C\____@\00.T0D)',1QX7\ -M+0``_____[@`````ZT"+=12+GA2```"!X___`,"#[`C_="0L5>C\____P>`0 -M)0``_S\)PXF>%(```(/$$(M$)"2)A?PM``"X`0```(GV@\0,6UY?7<.#[!2+ -M5"08BT(4BX`4@```)0``_S_!Z!!04NC\____@\0`(`>2J)\`^V^(GHP>@"#Z_XC3Q_ -M@`0"=")@12```")]H/$#%M>7UW#@^P4BT0D&/^P -MW`$``%#H_/___X/$',.0BU0D!+@`````@WPD"`9T%("ZCQ````!T"X.ZY"T` -M``%W`K`!PXUV`%.+7"0(_W0D#%/H_/___X/$"(7`#X1"`0``BT,4QX!PF``` -M'P```(M3%`^W@]0!```E\````(/H,(/X0!G`@^#\@\`8B8+XF0``BU,4BX(< -M@```)7_`__\,@(F"'(```(M#%,>`!($``#T```"+4Q2+@A!```"#R`*)@A!` -M``"#N\P!```'=#"#N\P!```+=">#N\P!```*=!Z#N\P!```)=!6#N\P!```* -M=6!F@[O0`0```W=6B?:+0Q3'@'28```F````BT,4QX!XF```#0```(M#%,>` -M\)D```<```"+0Q3'@/29```_````BU,4BX(00```)?____P-`````HF"$$`` -M`.D7`0``B?:+0Q3'@'28```*````BT,4QX!XF```#````(M#%,>`\)D```,` -M``"+0Q3'@/29```@````BU,4BX(00```#0````.)@A!```#IR````(UV`(M3 -M%(N"$$```"7____\B8(00```BU,4BX(00```@^#]B8(00```BT,4QX!PF``` -M'P```(M#%,>`=)@``'\```"+0Q3'@'B8```.````BT,4QX#PF0``#````(M# -M%,>`])D``/\```"+4Q0/MX/4`0``)?````"#Z#"#^$`9P(/@_(/`$HF"^)D` -M`(M3%(N"'(```(G!@>%_P/__#[>#U`$``"7P````@^@P@_@_=PF)R`V`$P`` -MZP>)R`V`#P``B8(<@```6\.04XM<)`C_="0,4^C\____@\0(A<`/A-,```"+ -M4Q2+@A!````E_____(F"$$```(M3%(N"$$```(/@_8F"$$```(M#%,>`!($` -M``$```"+4Q2+@AR```")P8'A?\#__P^W@]0!```E\````(/H,(/X/W<*B<@- -M@!,``.L(D(G(#8`/``")@AR```"+0Q3'@'"8```?````BT,4QX!TF```?P`` -M`(M#%,>`>)@```X```"+0Q3'@/"9```,````BT,4QX#TF0``_P```(M3%`^W -M@]0!```E\````(/H,(/X0!G`@^#\@\`8B8+XF0``6\.0N@````"+1"0(9HL` -MB<%F.P4@2```=PRX($@``$)F.PR0=OD/OP25(D@``,-75E.+5"00BT0D%(MT -M)!B+?"0#_@%T -M%>LZ9H.Z@A`````/E,`/ML#I30$``&:#NH@0````=1.X`0```&:#NH80```` -M#X0P`0``N`````#I)@$``+@!````Z1P!``"X`````(7V#X0/`0``N`P```"# -M_@$/A0$!``"+@L@M``#WT,'H'^GQ````A?9T!X/^`708ZRB*00+`Z`2#X`&# -M^`$9P(/@#>G0````]H+,+0``"`^4P`^VP.F^````N`P```#IM````(N"W"T` -M`(/@/XD'N`````#IGP```(N"W"T``"4`/P``P>@(B0>X`````.F%````@_X! -M=!.X`````(/^`7)VL`R#_@9W;^L/]H(4+@```0^4P`^VP.M>@^P,4NC\____ -MB<*#Q!"X`0```(72=$>#_@9W+?\DM<1(```/MD()B0?K'@^V0@R)!^L6#[9" -M#8D'ZPX/MD(+B0?K!@^V0@J)![@`````ZPZ)]E=64%+H_/___X/$$%M>7\-5 -M5U93@^P,BWPD((M<)"2+;"0HBTPD+(G^C9?@`0``@_L=#X>$`0``_R2=_$@` -M`(7)=`R!C\@M```````(ZPJ!I\@M``#____WN`$```#I;`$``+@`````]D(! -M$`^$70$``(7)=`F#I\PM``#[ZP>#C\PM```$BU<4BX;,+0``B8(@@0``N`$` -M``#I,`$``(M'%(N0"*(``(7)=`6`SB#K`X#FWXM'%(F0"*(``+@!````Z0@! -M``")C_@!``"+1Q2)B$B```"X`0```.GO````A!(``!7Z/S___^#Q!#K-/9"`A!T&X7)=`F# -MC\PM```(ZP>#I\PM``#WN`$```#K$X/L#/]T)#Q155-7Z/S___^#Q""#Q`Q; -M7E]=PY"#[!3_="0L_W0D+/]T)"S_="0L_W0D+/]T)"SH_/___X7`#Y7`#[;` -M@\0LPU93@^P$BW0D$(-\)!0`=&R+5A2+@@1````E___\_XF"!$```(/L#&H* -MZ/S___^[*````(/$$(GVBT84BX`00```J0```0!T)H/L#&HRZ/S___^+5A2+ -M@@1````E___\_XF"!$```(/$$$MUS.L$A=MU"K@`````ZQR-=@"+5A2+@@2` -M```E___[_XF"!(```+@!````@\0$6U[#D(M,)`2+412+@@2````-```$`(F" -M!(```(-\)`@`=!F+412+@@1````E___\_PT```$`B8($0```PXUV`(M,)`2+ -M412+@@2````-```$`(F"!(```(-\)`@`=!F+412+@@1````E___\_PT```(` -MB8($0```PXUV`%=64XM$)!"+7"04BU0D&(G&OP$```"#^P%T(8/[`7((@_L" -M="/K+9"#[`A24.BZ_O__B<>#Q!#K(XUV`%)0Z$7___^#Q`CK%%)0Z'7___^# -MQ`CK"+@`````ZPF0B9ZT+0``B?A;7E_#BT0D!(M`%(N`!$```"4```,`P>@0 -MPY"04X/L"(M4)!"+1"04@_@(#X23````@_@(=R:#^`(/A(T```"#^`)W#(/X -M`70[Z:8```")]H/X!'1GZ9H```")]CT``0``='D]``$``'<*@_@@=&3I@``` -M`#T``@``=&@]``0``'1HZW"[`````(.Z-!````!T:HN"-!```/9``T!T![L` -M````ZU>+@C00``!F@W@"`'E*NP````#K0XUV`+L`````ZSF0NP````#K,9"[ -M`````.LINP````#K(HGVNP````#K&;L`````ZQ*[`````.L+C78`N`````#K -M$)"#[`A34NC\____B=B#Q!"#Q`A;PXM$)`2+0!2+0`S#D(M$)`2+4!2+1"0( -MB4(,PY"+1"0$BT`4QT`(!````,.0@^P,BU0D$(M"%,=`""````!J`&H$:@A2 -MZ/S___^%P`^5P`^VP(/$',.-=@!3@^P4BUPD'(M3%(N"2(```(/@WXF"2(`` -M`%/H_/___X/$"&H!4^C\____@\086\.#[!B+3"0C\____@\0@09HE! -M`L9!!`"+0A`E``#P#\'H%(A!!CR`=03&008`BT(4]L0!=!`E`/X``,'H"8A! -M!^L'C78`QD$'_XM"$"4`@`\`P>@/B$$(BT(0)0```/#!Z!R(00F+0A#!Z`R# -MX`&(00J+0A2H`G55J`1T"8!)!`'K2XUV`/9"%!!T*H!)!`(/MD(5B$$%@[X8 -M+@```'4N@_@%="F#[`A15NC\____@\00ZQJ)]O9"%`AT!H!)!`CK#/9"%"!T -M!H!)!!")]KL`````B=B#Q`1;7L.0D)!55U93@^P\BWPD4(G]O@````"+5"18 -M#[="`HG"P>H'P>@(,="Z#````*@!#X2W#```BTPD6`^W00*)PL'J!L'H!3'0 -MN@P```"H`0^$F`P``(/L!&H!:@!7Z/S___^#Q!"Z`````(7`#X2+#```@^P( -M_W0D8%?H_/___XE$)#R#Q!"Z#````(7`#X1:#```@WPD5`9T(8-\)%0&=PF# -M?"14`7<)ZQ&#?"14"'0*N@P```#I,@P``,=$)"@`````@WPD7`!T*(M'%(N` -M0!$``(E$)"B#[`C_="0T5^C\____@\0(:@!7Z/S___^#Q!"#O\P!```'="Z# -MO\P!```+="6#O\P!```*=!R#O\P!```)=!.#O\P!```*=5UF@[_0`0```W=3 -M@WPD7`!T3(._-!````!T0XN/-!```(M<)%AFBP-F.P%T,0^W4P*!XO`!```/ -MMT$")?`!```YPG4:@^P(4U?H_/___X/$$+H!````A<`/A8$+``"+1Q2+@%B` -M``")1"0DA``)@```<```"[`````(UV`(T$6XM/%(L4Q8!)``") -M5"0(BU0D&(T$0HL$A8!)``"+5"0(B0011O?&/P```'4-@^P,:@'H_/___X/$ -M$$.#^QAVOKL`````D(L,W>!+``"#?"1<`'06C8'@?___@_@8=B^-@2Q___^# -M^`AV)(M7%(L$W>1+``")!`I&]\8_````=0Z#[`QJ`>C\____@\00D$.!^\,` -M``!VKU;_="08_W0D(%?_E:@J``"#Q!"+3"18]D$#0'4'9H-Y`@!Y$(/L"/]T -M)&!7Z/S___^#Q!!F@[_2`0``00^&T0```(M'%,>`+)@```*@`@"+7"189H$[ -MM`EU)0^VC8X0```/MX68$```*<&X9V9F9O?IB=#1^,'Y'XG#9BG+ZQ(/MI6. -M$```N&=F9F;WZHG3T>N+="18#[=&`B70````/<````!U*XM/%`^VE8X0``#W -MVL'B!H'BP`\``(G8P>`2]]@E``#\``G"B9%,F0``ZPV+1Q3'@$R9```````` -MBU<4BX(HH@``@.3]B8(HH@``BU<4BX(HH@``)?\#_O^`S`B)@BBB``"+1Q3' -M@&"````/````9H._T@$``$)V#8M'%,>`5*(```````"+1Q3'@'B8```.```` -M@[_,`0``"G0<@[_,`0``"703@[_,`0``"G4Y9H._T`$```-W+[D!````BT0D -M6&:!.)X)=`=F@3BC"74%N0````"+5Q2+@DRB```YR'0&B8I,H@``@^P$C40D -M/%#_="0T5^C\____@\00N@,```"%P`^$R@<``(-\)%0&=!6#OP0"````=`R# -M[`Q7Z/S___^#Q!"-1"0X4`^W1"0<4/]T)#17_Y6T*@``@\00N@,```"%P`^$ -MB`<``(M4)%CV0@)`=&2#O\P!```*=">#O\P!```)=!Z#O\P!```*=0IF@[_0 -M`0```W8+9H&];!````)0=B2+3"18#[=!`B6@````/:````!T$(/L"/]T)#17 -MZ/S___^#Q!"#[`C_="1@5^C\____@\00@^P(_W0D-%?H_/___X/$$+H#```` -MA<`/A/T&``"#?"1<`'0-BT<4BUPD*(F80!$``(M/%`^VE2PJ```/MH4M*@`` -MP>`("<(/MH4N*@``P>`0"<(/MH4O*@``P>`8"<*)D0"```"+3Q0/MI4Q*@`` -MP>((#[:%,"H```G0"T0D'`N%R"T```T``(``B8$$@```@^P(_W0D7%?H_/__ -M_XM/%`^VE3@J```/MH4Y*@``P>`("<(/MH4Z*@``P>`0"<(/MH4[*@``P>`8 -M"<*)D>"```"#Q`B+3Q0/MI4]*@``P>((#[:%/"H```G0B8'D@```BU<4BX(0 -M0```"T0D*(F"$$```(M'%(MT)#R)L!1```"+1Q2+5"0XB9`80```BT<4BTPD -M+(F(6(```(M/%`^VE3(J```/MH4S*@``P>`("<(/MH4T*@``P>`0"<(/MH4U -M*@``P>`8"<*)D0B```"+3Q0/MI4W*@``P>((#[:%-BH```G0B8$,@```BU<4 -MBX70+0``B8(8@```BT<4QX"`````______]T)#17Z/S___^#Q!"Z`P```(7` -M#X1J!0``@^P$:@$/MH`(`>3"+AS00```/MT`" -M)0!```"#^`$9P/?0@\`-BT\4BY$DF```@^+P@^`/"<*)D228``"+1Q2+@!29 -M``")PH'B_S\``(M<)%CV0P(@=`_!X@*XHXLNNO?BP>H$ZPJXSH# -MBT<4QX``(`>16#[`R-!)5D````4.C\____@\00ZP^#[`R-0F10Z/S___^# -MQ!"+1Q2+L`B8``#'@`B8````.```NP$```"+1Q2+@"2<``"H$'0E@^P,:,@` -M``#H_/___X/$$(G80X/X$W\-BT<4BX`DG```J!!UVXM'%(FP")@``(M7%(N" -M8)@``(/(`XF"8)@``(MT)%@/MT8"):`````]H````'0[@[V\+0```G0RBU<4 -MBX(@F0``@,SPB8(@F0``BU<4BX(@F0``#0```0")@B"9``#'A;PM```!```` -MZPK'A;PM````````@^P,5^C\____NP````"#Q!"^`0```(T$G0````")1"0$ -MBU<4B?"(V=/@BTPD!(F$"@`0``!#@_L)?MO'A9Q$````````NP````!F@[_H -M`0```'09@^P(4U?H_/___X/$$$,/MX?H`0``.=A_Y\>%0"H``&4)"`"#?"14 -M!G4*QX5`*@``91D(`(M7%(N%0"H``(F"H````(M7%(N"K`````T```<`B8*L -M````@[],$````'0,@^P,5^C\____@\00:@!J`6A@F```5^C\____@\0(_W0D -M7%?H_/___XM7%(N"((```"7__W_^B8(@@```@\00@[_,`0``!7<3@[_,`0`` -M!74D9H._T`$```=V&HM'%,>`&($``*H``0"+1Q3'@!R!```0,@``BT<4QX`( -M@0``4@```(M<)%CV0P,!=`B*A8H0``#K!HJ%BQ```(/L!`^^P%#_="1@5^C\ -M____B$0D(XNUW"T``(/F/XET)!P/OXWP+0``B?`IR(M<)#P/OE,&@\00.=!V -M!@'*B50D#(MT)"P/OD8%T>`/OE0D$RG0B<([1"0,,`/P``P>L(#[^-\"T``(G8*!`(``/;#`W0?BTX4 -MBY%$F0``@>+____?B=B#X`'!X!T)PHF11)D``/;##'0O]L,$=1:+5A2+@M"` -M``"#X..)@M"```#K%HGVBU84BX+0@```@\@&Z`$``#G8=^.-=@"Z`````(7_#X2[`0``ZP>_`````.OJBT84 -MQX!\F0```0```+L`````BT84BX`@G```A7UW#B?:+3"0$BU0D -M"(M!%(N`!(```"7___S_@_H!=%&#^@%_"(72="O#C78`@_H&=`>#^@AT.L.0 -MBU$4#0```1")@@2```"+412+0A2#X-^)0A3#BU$4#0```A")@@2```"+412+ -M0A2#R"")0A3#B?:+410-````$(F"!(```,.0@^P4:@+_="0H```#K0+T`````#[='`J@@=0PE -MT````#W`````=0>YJP```.L@N:H!``#V1P-`=14/OT<"B<'!^1^!X0`"``"! -MP:H````/MT<"J$!T%:@@=0PET````#W`````=06#S03K"?9'`D!U`X/-`?9' -M`P%U`X/-`@^W1P*#X!"#^`$9]O?6@^8#BT,4BY!\F```#[='`J@@=0PET``` -M`#W`````=3&+0Q2)L`28``"+0Q2)J`"B```YRG1*BT,4B8A\F```@^P,:"P! -M``#H_/___X/$$.LO.D'P>@'B40D!`^$'P$``(/Y`0^.%@$` -M`(I$)`CWV`^^V(G8F?=\)`2)PX/XX'T'N^#____K"H/X'WX%NQ\```")^+H` -M````]_&->("#__!]![_P____ZPJ#_P]^!;\/````BT0D((M(%(N1()D``('B -M'_C__XG8P>`%)>`'```)PHF1()D``(M4)""+2A2+@2"9``"#X.")^H/B'PG0 -MB8$@F0``BTPD((M1%(N"()D``(#,"(F"()D``,>%O"T```(```#'1A`!```` -MB%X4B?B(1A7K69"+5"0D#[="`B6@````/:````!T1(.]O"T```)U.X-^$`!U -M-8M,)""+412+@B"9``"`S/")@B"9``"+412+@B"9```-```!`(F"()D``,>% -MO"T```$```"0@^P(5O]T)"SH_/___X/$$/9&`@(/A8X```"+1"0@BU`4BX)@ -MF```@\@"B8)@F```BTPD)`^W40+VQ@%U'XM,)"`/MX'4`0``)?````"#Z#"# -M^#]W8?;"0'17UW#D%=64XM\)!"+7"04B=B%VW4%N/__ -M__^)QH._S`$```ET$X._S`$```IU#6:#O]`!```#=P.#X^^+1Q2+4`R)F`!` -M``"#[`QJ#^C\____@^8#@^,#4U9H`$```%?H_/___XG&@\0@]L,!=2J+1Q3' -M0!0`````@^P$:@%J`%?H_/___X/$$(7`=`R+1Q2+@,````"-=@")\%M>7\.) -M]HM$)`2+0!2+@&28``#!Z!,E_P$``/;$`70%-0#^__^8PXUV`(M,)`R+5"0$ -MBT0D"`^W0`(EX`$``#W`````=#`]P````'\)/:````!T%NLL/4`!``!U)6:+ -M@L@0``!FB0'K(9!FBX+*$```9HD!ZQ1FBX+,$```9HD!ZPBX`````,.)]K@! -M````PXGV5U93@^P$BUPD%(M\)!B+0Q2+@&"8``"^`````*@"=3Q3Z/S___^) -MQHU$)`905U/H9/___X/$$(7`=!5F.W0D`GX39H-/`@*^`````.L'B?:^```` -M`&:)=Q:-=@`/O\:#Q`1;7E_#B?964XMT)`R)\_:&X`$```1T:XM&%,>`(`0` -M``$```"+1A3'@``&````````BU84BX(`!@``@\@(B8(`!@``BT84QX`$!@`` -M`0(0`(M&%,>`(`8```````"Y`````(M&%(F(``0``(M6%`^VA!DT+0``B8($ -M!```08/Y?W[@6U[#D%575E.#[`R+1"0HQT0D"`````"->/_![P-(@^`'B00D -MBW0D)+T`````A?9^9XM$)"S!X`.)1"0$BQPD`?.#^PAV!;L(````N`$```"( -MV=/@2+H!````B@PDT^)*,="*3"0$T^"+5"0@(P2ZT^B*#"33Z(GIT^`)1"0( -MB=@K!"0!Q8L$)(UT!OC'!"0`````1X7V?Z2#[`C_="0L_W0D%.C\____B40D -M&(M$)!B#Q!Q;7E]=PU575E.+?"04BVPD&(G^BT0D'`^W0`(EX`$``#W````` -M="H]P````'\+/:````!T%.LBB?:Z`````#U``0``="#K$HGVN@$```#K%9"Z -M`@```.L-D+@`````Z>4```")]@^WG%;F$```#[>$5NP0``#!X`8)PP^WA%;R -M$```P>`,"<,/MX16^!```,'@$@G##[>$5OX0``#!X!@)PP^WC%8$$0``#[>$ -M5@H1``#!X`8)P0^WA%80$0``P>`,"<$/MX16%A$``,'@$@G!#[>$5AP1``#! -MX!@)P8/]`70/@_T!L+C78`B=GK#(G+ZPBX`````.M(D#G9=12+ -M5Q2+@@BB``"`Y-^)@@BB``#K$HM7%(N""*(``(#,((F""*(``(FNN"T``(M' -M%(F88)D``(M'%(F(9)D``+@!````6UY?7<-3BT0D"(.XS`$```IT2H.XS`$` -M``ET08.XS`$```IU#&:#N-`!```#=BZ)]H.XS`$```=T(X.XS`$```MT&@^W -M@-0!```E\````(/H,+H@````@_@_=P:0NB@```"Y`````(M$)`P/MP")T[H` -M````]_.%TG0*C4+V@_@,=@*Q`8G(6\-55U93@^Q,BVPD8(GNBT0D9`^W>`+! -M[P>#YP$/MT`")?`!```]0`$``'1M/4`!``!_,CW`````#X3C````/<````!_ -M$#V@````#X3%````Z=@````]T`````^$P0```.G(````/<`(```/A+$````] -MP`@``'\./5`!``!T&^FJ````B?8]0`D``'0-/5`)```/A98```")]L=$)#P` -M````#[>%U`$``"7P````@^@P@_@_#X:`````@[W,`0``!W1W@[W,`0``"W1N -M@[W,`0``"G1E@[W,`0``"71<@[W,`0``"G4*9H.]T`$```-V28M-%(N11)D` -M`(/BQXN&*"H```^_`,'@`X/@.`G"B9%$F0``ZR3'1"0\`0```.L:B?;'1"0\ -M`@```.L.B?:X`````.D%`P``B?:+312+@1"9```E!OS__XM<)#P/MY1>X!`` -M`,'B!`G0@\@!B8$0F0``_W0D9/^VN"T``%7H_/___XM5%`^_A%[($```)?\! -M``"`S`*)@FB9``"#Q`QF@;YL$```_T]V08M$)&3V0`(0=#=FBX1^0!$``(J< -M-T@1``"*E#=*$0``B%0D(&:+C'Y$$0``9HE,)!!FBY1^3!$``&:)%"3K.8GV -MBTPD/&:+A$Z>$```BIPQPA```(J4-\40``"(5"0@9HN,?J00``!FB4PD$&:+ -ME'XN$0``9HD4)(M-%(N11)@``('B?\#__\'@!R6`/P``"<*)D428``"+312+ -M@5"8``"P``^VTPG0B8%0F```BTT4BY%0F```,/:*1"0@P>`()0#_```)PHF1 -M4)@``(M-%(N12)@``('B_P_\_XM$)!#!X`PE`/`#``G"B9%(F```BUT4BTPD -M/`^WE$ZV$```B=#!X!C!XA`)T`^WC$Z\$```B$7JH0``#!X`@)PHF1*)@``(M-%(N19)@``('B_P_X -M_P^WA%ZP$```P>`,)0#P!P`)PHF19)@``+L"````9H&^;!````(P=QEF@;W* -M`0``(A!U+HM$)&3V0`)`="2S".L@_W0D9%7H_/___X/$"(7`=`^+5"0\#[>$ -M5B(1```!PY"+312+D229``"`X@&-!!LE_@````G"B9$DF0``BTPD9(-Y$`!T -M"@^^010/OED5ZQ`/MX1^LA$```^WG'ZV$0``BTT4BY$@F0``@>(?^/__P>`% -M)>`'```)PHF1()D``(M-%(N!()D``(/@X(G:@^(?"=")@2"9``"+512+@B"9 -M``"`S`B)@B"9``!F@;YL$````$!V08M<)&0/MT,")=`````]T````'4+9H&^ -M;!```/]/=B*+312+D0RB``"!XO__`_^+!"3!X!(E``#\``G"B9$,H@``9H&^ -M;!````!0=@V+113'@."9````````N`$```"#Q$Q;7E]=PY!55U93@^QLQT0D -M,`````#'1"0T`````(U\)%#\N@0```"X`````(G1\ZMFQT0D)@``QT0D(``` -M``#'1"0<`````&;'1"0X`0"-1"0X9L=``@(`9L=`!`(`9L=`!@$`9L=$)$`! -M`&;'1"1"`@!FQT0D1`$`BYPDA`````^W:P+![0'_/P``9HE,)"KI@@```)!FQT0D*@"`N%<```"+C"2$```` -M]D$"$'0"L*Z^``````^W7"0HB5PD%`^WP(E$)!"#[`15#[?&4/^T)(P```"+ -ME"20````_Y+$`0``B<&#Q!!F/0"`="J+7"04BWPD$(G8*?B)RH'B_S\``#G0 -M?PN-!#LYT`^-=?___T9F@_X$=J]FBUPD*HN,)(0```!FB5DT9H%\)"H`@`^% -M&@$``(N$)(````"+4!2+@B"9``"I````0`^$I`0``(N"#)D``"7___\`B8(, -MF0``BY0D@````(M"%(N0()D``('B____CXF0#)D``(N,)(````"+013'@*"9 -M````````BT$4QX"`F0```````(M1%(N"A)D``"4``/#_B8*$F0``BT$4QX"8 -MF0```````(M1%(N"G)D``"4``/#_B8*` -M!)D```````"+013'@`B9````````BU$4BX(,F0``)0#`__^)@@R9``"+013' -M@(B9````````BT$4QX",F0```````(M!%,>`D)D```````"+412+@I29```E -M`,#__XF"E)D``.FF`P``D`^W3"0J#[=$)"@IP8N<)(0````/MT,")?`!```] -MT`````^$F@```#W0````?PP]P````'1*Z;<````]0`$``'0,/5`!``!T>>FD -M````B+_/P``"=")@PR9``"+412+1"10B8*(F0``BU$4BT0D5(F" -MC)D``(M1%(M$)%B)@I"9``"+612+@Y29```E`,#__XM4)%R!XO\_```)T(F# -ME)D``(/$;%M>7UW#C78`5U93BW0D$(M$)!2Z````9/9``A!T!;H```#(]D`# -M0'0$T>KK"F:#>`(`>0/!Z@(/MPB)T+H`````]_&)P[\?````B?:)V(GYT^BH -M`74#3W7SN"8````I^(G'N!<```")PBGZL`&(T=/@`=BZ&````"GZB-'3Z(M> -M%(N3%)@``('B__\!`,'@$0G"B9,4F```BUX4BY,4F```@>+_'_[_B?C!X`TE -M`.`!``G"B9,4F```6UY?PXUV`(/L#(M4)!"+1"04@_@_=@6X/P```&:)@OP! -M``"#[`2-1"0,4/^R-!```%+H_/___X/$',-55U93@^P4BVPD*(M<)"R)[_^U -M>$0``/^U=$0``.C\____@\0(:B"-A7Q$``!0Z/S___]FBY7\`0``@\009H/Z -M/WX%NC\```!F@_H^?PJY`````&:%TG4.BX4``@``9HN,``!2``"#[`2-1"0. -M4(U$)!!0:@$/O\)0#[_!4%-5Z(0"``"#Q""Z`````(7`#X1H`@``@^P,_W0D -M-%.-1"0>4(U$)"!05?^7N"H``(/$(+H`````A<`/A#\"``"#O$=WQ$ -M```_`$:#_@]VW6:#OYH0```!#X>F````9H.]T@$``$%W7`^W0P(ET````#W` -M````=4QF@3NT"74C#[:/CA````^WAY@0```IP;AG9F9F]^F)T-'XP?D?9BG( -MZQ(/MI>.$```N&=F9F;WZHG0T>B#[`@/M\!05>AT!P``@\00O@````"-'+4` -M````BTT4BX=T1```#[=4L`+!XAB!R@``_P`/MP2PP>`(#/\E__\```G"B909 -M@*$``$:#_A]^Q8M-%`^WEX)$``"#XC_!XA@/MX>`1```@^`_P>`0"<(/MX=^ -M1```@^`_P>`("<(/MX=\1```@^`_"<*)D329``"+310/MY>*1```@^(_P>(8 -M#[>'B$0``(/@/\'@$`G"#[>'AD0``(/@/\'@"`G"#[>'A$0``(/@/PG"B9$X -MF0``BTT4#[>7D$0``(/B/\'B&`^WAXY$``"#X#_!X!`)P@^WAYI$``"#X#_! -MX`@)P@^WAXQ$``"#X#\)PHF1-*(``(M-%`^WEYA$``"#XC_!XA@/MX>61``` -M@^`_P>`0"<(/MX>41```@^`_P>`("<(/MX>21```@^`_"<*)D3BB``"+512# -MO]@M```!&<"#X,"#P'^)@CR9``"Z`0```(G0@\0,6UY?7<.)]E575E.#[%2+ -M;"1LBT0D<&:)1"0FBU0D=&:)5"0DBW0D:(GQ@<%\1```B4PD(&;'1"0>/P!F -MQT0D'#\`#[Y%!='@9HE$)!J+A"2`````9L<`P?^+5"1\9L<"/P!5_W0D;.C\ -M____B$0D(;L`````@\00BTPD8&:#N7`1````#X2%````#[9\)!&)^(/@^(E$ -M)`R-=@!F@[Q>`&C80PT!4``(/L"%`/MT4`4.A^!@``@\00@7PD#.````!U#F8Y -M1"06=@YFB40D%NL'9HE$)!;K#$,/MX9P$0``.=A_C`^W10(ET````#W````` -M#X6B````@&0D$?B`3"01`;L`````9H.^`&C80PT!4``(/L"%`/MT4`4.C*!0``@\00@7PD".````!U#F8Y -M1"04=@YFB40D%.L'9HE$)!3K&$,/MX9P$0``.=A_C.L*9HM,)!9FB4PD%/9% -M`P%T"(J&BA```.L&BH:+$```@^P$#[[`4%7_="1LZ/S___^(1"0@@\00]D4" -M0`^$TP$``(!]`@!Y)H/L#(U$)#Q0#[>&F!4``%"-AIH5``!05?]T)'SH9P8` -M`(/$(.LD@^P,C40D/%`/MX9&%0``4(V&2!4``%!5_W0D?.A!!@``@\0@#[=4 -M)!(/OD0D$"G"#[=$)!8YPGX"B<*)T?9%`A!T0&:!OFP0````,'82#[>&>A`` -M``^_TCG0?@*)T(G!9H&^;!```/\_=AB`?0(`>1(/MX9\$```#[_1.=!^`HG0 -MB<$/MU0D-@^_P3G"?@*)PF:+1"0>T>")T68IP7D%N0````!F.TPD''X$BTPD -M'(-\)'``#X3-````BT0D&&:)2`AFB4@&9HE(!&:)2`)FB0B)SXM$)#1F.0T/MX:` -M$```.<-\#>L/#[>&?A```#G#?02)R.L6@'T"`'D)9HN&@!```.L'9HN&?A`` -M`(M,)!AFB4$>ZPN+3"089HL!9HE!'HM,)'@/OP&)ANPM``#K$HG/#[=$)#`/ -MO]$YT'X"B=")PHM$)'1FB1"+5"1X9HDZ#[=%`J@@=1`ET````#W`````#X4/ -M`0``@^P,C40D+%`/MX:X%0``4(V&NA4``%!5_W0D?.B"!```#[=,)#(/OD0D -M,"G!#[=$)#2#Q"`YP7X"B<$/MU0D)@^_P3G"?@*)PF:+1"0>T>")T68IP7D% -MN0````!F.TPD''X$BTPD'(-\)'``=&H/MT0D)@^_T3G0?@*)T(M4)!AFB4(0 -M#[=$)"0/O]$YT'X"B="+5"089HE"$HG#9HE"%`^W1"0B#[_1.=!^`HG0BU0D -M&&:)0A9FB4(8#[=4)"`/O\$YPGX"B<*+3"089HE1&HG09HE1'.L>#[=$)"0/ -MO]$YT'X"B=")PP^W1"0@#[_1.=!^`HG0BU0D=&8Y`GX#9HD"BTPD>&8Y&7T$ -M9HD9D(-\)'``=!B+5"1X#[\"B8;$+0``BTPD8&:)@?X!``"X`0```(/$3%M> -M7UW#55=64X/L$(ML)"3_="0L_W0D+%7_E;PJ``"#Q!"Z`````(7`#X2O```` -M9HN]_`$``&:#_S]^!;\_````9H/_/G\,9L=$)`8``&:%_W4>BX4``@``9HN$ -M``I2``!FB40D!NL)N@````#K;XGVO@`````[="0H@]^O__@\0@A#[>$77Q$```YPG4T9H.\77Q$````=0=F_T1,$.L69H-\)`PR=@=F_T1\ -M$.L'9O],?!")]KX`````9O]$)`SK`49F@_X/=HT/MT0D#F:#?$00/WX'9L=$ -M1!`_``^W1"0.#[><17Q$```K7"14>0:[`````)`/MT0D#@^_3$00BY5T1``` -M9HL$6F:)!$IF_T0D#F:#?"0.#@^&$____V;'1"0."``/MU0D#F:+1%009HF$ -M57Q$``!F_T0D#F:#?"0.#G;A@\0\6UY?7<.05U93@^P@BUPD-(M\)#"Z```` -M`)!F@SS3`'0/9HL$TV:)1%000H/Z!W[JB=:#[`R-1"0:4(U$)!Q0#[?"4(U$ -M)"A0#[?'4.C\____N@````"#Q"`Y\GT=BT0D$&8[1"0,=!*+1"0,B?9".?)] -M!V8Y1%00=?2+1"0,9CM$)`YU!68Y^'0,N#\```"#?-,$`'0%9HM$TP(/M\"# -MQ"!;7E_#D%575E.+;"04BTPD&(M\)!R+7"0@BW0D)`^WPP^WU@^OPKH````` -MA#.)\&:#^F1_*P^_T@^WS@^ORKAD````*=`/M],/K\(!P;@?A>M1]^F)T,'X -M!<'Y'V8IR)`/M]")T%M>7UW#B?955U93@^P\BVPD6(M\)%RZ``````^WQXG! -M@_@`?A2)]HT$DF:+1$4(9HE$5"!".=%_[H/L#(U$)"I0C40D+%`/M]]3C40D -M.%"+5"1P#[<"4.C\____O@````!FQT0D.@``N@````"#Q""#^P!^*XG8BWPD -M'&:+3"0>C78`9CE\5"!U!6:)5"0:9CE,5"!U!8G6ZP:00CG0?^,/M_:--+;1 -MY@^W3"X&#[=<)!J-')O1XP^W1"L&B40D#`^W?"0>#[=4)!R)5"04BT0D5`^W -M$%'_="005_]T)"!2Z([^__^#Q!2+5"1@9HE"!@^W1"X$B40D#`^W5"L$BT0D -M5`^W"/]T)`Q25_]T)"!1Z%[^__^#Q!2+5"1@9HE"!`^W1"X"B40D#`^W5"L" -MBT0D5`^W"/]T)`Q25_]T)"!1Z"[^__^#Q!2+5"1@9HE"`@^W!"X/MQ0KBUPD -M5`^W"U!25_]T)"!1Z`?^__^+5"1T9HD"@\106UY?7<-55U93BU0D&(ML)""+ -M?"0D#[=,)!2-!(F-!("-#(4`````#[=<)!R-'%H/MP*-!("-!("-!(7V____ -M.`"*?"#P`F#^!)VQ`^W0@*-!("-!("-!(7V____.7UW#C78`BTPD!(V1#"H```^W@=0!```E\````(/H,(/X/W"U`$``"7P````@^@P@_@_=TEJ`&HD:@&#[`QJ -M!U+_DJPJ``"#Q!10Z(+C__^]`````+YK````N0````"[:P```(/$$(/X`75T -M9KY3`+-3QT<0-P```.MEC78`:@!J)6H&@^P,:@=2_Y*L*@``@\044.@YX___ -MO0````"#Q!"^,@```(/X/W0#C7`$B>F#^#]T!;E`````C5DRB>J#^#]U!HU5 -M%(UV`(E7#(/X/W4(C4/QZP:-=@"-0P6)1Q"+5P2X`````#GJ<@0Y\G8-.7UW#D(M$)`0/OY#P+0```Y#L+0``BT@4P>()@>(` -M?@``@,Z`B9$PF0``QX#`+0```0```,.-=@!75E.+?"00B?N-MPPJ``"X```` -M`(-^&``/A.@```"#O\`M```!#X75````BT<4BX`PF0``9H7`#XC#````B<+! -MZAF)5@0E``"``<'H%X/X`G4<9H._T@$``$%V#@^WAY80```!T(E&!.L$@T8$ -M!0^WA]0!```E\````(/H,(/X/WQX/`+0```@```,>#U"T```$` -M``#'@[PM````````BX/`+0``6UY?PXGVBTPD"+@`````BU$$.U$,=@4[41!R -M!;@!````PU93BUPD$(M$)`P/MX#4`0``)?````"#Z#"^H%,``(/X/W8%OB!2 -M``"+`XT$P(U$A@B)0QR+0P0[0Q!R6+K_____@SL`#X2N````BT,$B4,(.T,0 -M#.P!T,HGVBQ-*B1.-%-*-%):+2QR+0A@K01#1X(M+""G!B4L(@\((B5,< -M.TL0<@>#.P!UTHGVN@$```#K99"+0P2Z`````#M##'=7BP9(NO[___\Y`W1+ -MBT,$B4,(.T,,=SB+!D@Y`W,QD(L30HD3C132C126BTL"+2P@I -MP8E+"(/""(E3'#M+#'<'BP9(.0-RT+H"````C78`B=!;7L.-=@!75E.+7"00 -MC;,,*@``QT84`````&H`:B1J`8/L#&H'4_^3K"H``(/$%%#H0>#__X/$$(/X -M`759BT8<#[\X:@!J(&H$@^P,:@=3_Y.L*@``@\044.@8X/__@\00@_\!=!J# -M_P%R#(/_`G05@_\#=!GK'\=&%`````#K%HE&%.L1C40`^XE&%.L(T>")1A2- -M=@!;7E_#55=64X/L%(MT)#"+7"0T5O]T)##H_/___XG%C7O_P>\#2X/C!X/$ -M$(7V?G*+1"0PP>`#B40D")"-##.#^0A^!;D(````N@$```#3XDJX`0```(C9 -MT^!(,<**3"0(T^*)T??1BT0D(",,N(E,)`2)Z(C9T^"*3"0(T^`AT`M$)`2+ -M5"0@B02ZC70>^+D(````*=G3[;L`````1X7V?YJ#Q`Q;7E]=PXGV55=64X/L -M#(M$)"3V0`-`=!N#[`AH``(``/]T)"SH_/___XG'@\00ZU"-=@"+5"0D9H-Z -M`@!Y&(/L"&@`!```_W0D+.C\____B<>#Q!#K*H/L"(M4)"P/MT("@^`0@_@! -M&<`E_@```(/``E#_="0LZ/S___^)QX/$$+T`````@S\`?CR0C41M`(U$AR`/ -MME@(P>,"BU0D((MR%(/L#&H`#[9`"U!J#E=2Z/S___\/M\")A!X`AP``@\0@ -M13DO?\6+1"0D]D`"$`^%KP```(/L"&H(_W0D+.C\____B<>]`````(/$$(,X -M``^.C@```(GVC41M`(UTAR`/MD8(C02%`(<``(E$)`B`?@4`=6.+5"0@BUH4 -M@^P,:@`/MD8+4&H.5U+H_/___P^WP(M4)"B)!!.#Q""`?@D`=#8/MD8)C02" -MB40D"(M$)""+6!2#[`QJ`0^V1@M0:@Y7_W0D/.C\____#[?`BU0D*(D$$X/$ -M()!%.2\/CW?___^-=@"#Q`Q;7E]=PU575E.#[`2+3"08BT$4BX`<@```B<.! -MXX`_``"+1"0<]D`#0'0>QP0D!`$``+X``!L`N!,```"_K`T``+T4````ZQR0 -MQP0DT@```+X``#8`N`D```"_2`T``+T*````BU$4"=@)\`T``(`?B8(<@``` -MBT$4BQ0DB9!P$```BT$4B;BP$```BTD4BX'P$```)?\#\/^)ZL'B"@G0B8'P -M$```@\0$6UY?7<.0D)!55U93@^P4BWPD*(N'0"H``"7___]_4%?H_/___XG% -MBT<4BU`PB=.!X_`#``#!ZP2)WH/$$(-\)"0`=!"X)0```"G8T>B--`/K"(GV -M@_L"@];_.=YT&(M/%('B#_S__XGPP>`$)?`#```)PHE1,(/L"%57Z/S___\Y -MW@^5P`^VP(/$'%M>7UW#5E.#[`2+3"00BU0D%`^W@>@!``"[`````#G0?B.# -M[`3_="0@!``"[`````#G0?B.#[`2-!%*-!("-A('<*@``4/]T -M)"!1Z/S___^)PX/$$(UV`(G8@\0$6U[#55=64X/L#(ML)""+?"0DB>F-E>`! -M``#'1"0("P```(/_`G0<@_\"=PN#_P%T5NF)````D(/_`W07@_\$="/K?`^W -M<@A.@4PD",``!0#K=9`/MW((@^X"@4PD",`!!0#K8P^W<@B#[@.-!':-!("Z -M_____X.\A>`J````#X7!````ZT&0O@`````/MT((B<.#^`!^%8T$=HT$@(.\ -M@>`J````=`5&.?-_ZP^W0@BZ_____SGP#X2(````ZPBZ_____^M_D(T$=HT$ -M@(V<@=PJ``"Z_____X-[!`!U9H/L"&H\4^C\____B7L$@\00@WPD*`!U-(M$ -M)`B)0PS'0Q0"````QT,8_____\=#'/\#``!FQT,@"@!FQT,B"@#'0S0````` -MZQN-=@"+5"0HBT(PB4,T@^P$4E95Z/S___^#Q!")\HG0@\0,6UY?7<-3BTPD -M"(M9%(N1R"H``('B_P,``(N!T"H``,'@$"4``/\#"<*)DZ0```"+612+D'Z`$``+X````` -M.7\.)]E575E.#[`B+;"0%Z`$``+H`````.<@/ -MAG4#``"-!$F-!("-G(7<*@``N@$```"#>P0`#X19`P``@WL8_W4SA?]T%0^W -M1P(EH````+H?````/:````!T!;H/````N`$````YT',/T>"#R`$YT'+WZP20 -MBT,8C3R-`````(G"@>+_`P``BT,

`*)0#\#P`)PHM#%,'@%"4``/`/"<*+ -M112)E#A`$```#[=#(L'@!"7P````#[=3((/B#PG0#0`@"`"+512)A#J`$``` -MQT0D!``(``#'!"0``0``@WLD`'0MBU,D@>+___\`BT,HP>`8"<*+112)E#C` -M"```@WLH`1G2L@"!P@$)``")5"0$@WLP`'0>C3R-`````(M5%(M#,"7___\` -M#0````&)A#H`"0``C3R-`````(M5%(M#+"7__P\`@WLL`'0%#0``$`")A#K` -M$```@WLP`'0.]D,,('0(@4PD!``"``#V0PQ`=`J#9"0$\(-,)`0"]D0D!`]T -M)?9##0%T!X-,)`1`ZP6#9"0$OX![#`!Y!X-,)`0@ZP:#9"0$WY#V0PX!=`>! -M#"0``"``]D,.@'0'@0PD``(``/9##@1T#($,)```!`#K$XUV`/9##@)T"H$, -M)````@"-=@#V0PX(=`>!#"0`0```]D,.$'0'@0PD```0`(M#!(/X`G0'@_@# -M=!/K5X%,)`2B````@0PD```E`.M&@TPD!&*#>S``=3.+%0`````K%0````"+ -MAN`M```IT"L%`````,'@"HT\C0````"+510-`````8F$.@`)``"!#"0```0` -MD/9#.`%T!X$,)```)`"-!(T`````BU44BWPD!(F\`L`)``"+512+/"2)O`(` -M$0``@WLT`'0ZBU44C40)4(F"``L``(M5%(M#-(F"!`L``(M%%,>`"`L```D` -M``"+512+A(K`"0``@,P0B82*P`D``/9##`%T#[@!````T^`)AL@J``#K#;C^ -M____T\`AAL@J``#V0PP!=!&X`0```-/@"8;,*@``ZP^)]KC^____T\`AALPJ -M``#V0PP"=!&X`0```-/@"8;0*@``ZP^)]KC^____T\`AAM`J``#V0PP$=!&X -M`0```-/@"8;4*@``ZP^)]KC^____T\`AAM0J``#V0PP(=!&X`0```-/@"8;8 -M*@``ZP^)]KC^____T\`AAM@J``!35>A\^___N@$```"#Q`B)T(/$"%M>7UW# -MB?:+1"0(P>`"BU0D!(M2%(N$`@`(``##B?:+5"0(P>("BT0D!(M(%(M$)`R) -MA!$`"```N`$```##D(M,)`B+1"0$BU`4N`$```#3X(F"0`@``+@!````PXGV -M5E.+5"00P>("BT0D#(MP%(N$%@`*``")PX/C`W4:N`$```"*3"00T^"+ED`( -M``"%PG0%NP$```")V%M>PXUV`%575E.#[`R+="0@BWPD)(M6%+@!````B?G3 -MX(F"@`@``+WH`P``B?975NC\____@\0(A)7 -M5NC\____@\0(A<`/A/(```"#OLP!```'=#:#OLP!```+="V#OLP!```*="2# -MOLP!```)=!N#OLP!```*#X7!````9H.^T`$```,/A[,```"[`````(M&%(N0 -M3(```,>``($``&0`"@"+3A3!Z@H/M\(-```!`(F!_(```(M&%(N`3(```,'H -M"CG0=`9#@_L!=L.+5A2+@DB````-``!``(F"2(```(/L#&C(````Z/S___^+ -M5A2+@OR````E___^_XF"_(```(/$$+MD````ZQ!+=!N#[`QJ"NC\____@\00 -M5U;H_/___X/$"(7`=>*+5A2+@DB````E__^__XF"2(```(M&%,>`@`@````` -M``"%[0^5P`^VP(/$#%M>7UW#D%575E.+;"0TBWPD/(MT)!B+1"04#[^`\"T` -M``-$)"B#^#]V!;@_````BU0D'('B_P\``,'@$`G"]\<@````=`:!R@``@`"+ -M1"0XP>`9)0```!X)T/?'`0```'0%#0````'WQQ````!T!0T````@B48(BUPD -M),'C%(M,)%#!X1F+5"1(P>(=BT0D3,'@&PG9"=$)P??'`@```'0&@`4"484N@$```")T%M>7UW#C78`4XM$)!2+3"0`4)0``\``+0A"`S(")0A"+1"00P>`%"4(4A`8)0````\+0A"` -MS(")0A"+1"08P>`*"4(4A=MT&(G8P>`<"T(0@,R`B4(0BT0D(,'@#PE"%+@! -M````6\.+1"0(@4@(````(,-3BT0D$(M,)!B+7"0AFB0$/MT(:9HE! -M`L9!!`"+0ABH`74=J`)T!,9!!`'V0A@(=`2`200"]D(8!'0%@$D$!)"+0APE -M``!@`,'H%8A!"P^VP(/X`70F@_@!?PF%P'01ZU>-=@"#^`)T)X/X`W0VZTB* -M0A2#X!^(007K/9"+0A0EX`,``,'H!8/(@(A!!>LID(M"%"4`?```P>@*@\B` -MB$$%ZQ60BT(4)0"`#P#!Z`^#R("(006-=@"+0APE`.`?`,'H#8A!!HM"&"7P -M````P>@$B$$'BT(8)0`/``#!Z`B(00@/MD$+@_@"="&#^`)_"(/X`70EZS&0 -M@_@#=2N+0A`E````#\'H&`!!")"+0A`E``#P`,'H%`!!"(M"$"4```\`P>@0 -M`$$(BT(8)0#P``#!Z`R(00F+0APE`````8/X`1G`@\`"B$$*N`````##D(M$ -M)`2+3"0(BQ$CD)Q$``")$??2(9"<1```PY!3@^P0BUPD&(V#@"H``%!3Z/S_ -M__^+0Q3'@"2!````````BT,4QX`H@0```````(M#%,=`0`````"+0Q3'@#"! -M``````(`BT,4QX`X@0```````H/$&%O#4X/L$(M<)!B+0Q3'0$`&````C8.` -M*@``4%/H_/___XM#%,>`)($```````"+0Q3'@"B!````````@\086\.)]E93 -MBW0D$(M<)`RZ`````)"-!)*-!$)FBX3#)"X``&8[!G4%B=#K/)"-!)*-!$*- -MC,,@+@``9H-Y!`!U'&:+!F:)001FBT8"9HE!!HI&!(A!"(G0ZPZ-=@!"@_H_ -M=K*X`````%M>PXGVBT0D!(N`("X``,.04X/L$(M<)!B-@X`J``!04^C\____ -MC8-$*@``@\086\-75E.+?"00B?X/MH?C`0``@^`!B8<8+@``@^P(:``6``"- -MAR0N``!0Z/S___^[`````(/$$(UV`(._S`$```9W$XT$FXT$0\:$QBPN```' -MZQ&-=@"-!)N-!$/&A,8L+@```HT$FXT$0XT,QL>!."X``/0!``#'@3PN``#( -M````QX%`+@``R````,>!1"X``&0```#'@4PN```H````QX%(+@``!P```(V! -M("X``,9`$`#&0!$`BE`,B%`.QD`/`(.^&"X```!T%,>!:"X```S^OP#'@6PN -M```X_[\`0X/[/P^&4O___X.^&"X```!T*HM7%(N&:"X``(F"+($``(M7%(N& -M;"X``(F"-($``(/L#%?H_/___X/$$,>&'"X``&0```"#?"04`'0)@XX4+@`` -M`>L'@Z84+@``_EM>7\.)]E.#[`B+7"00@[L8+@```'0G@^P,4^C\____BT,4 -MQX`L@0```````(/$$(M#%,>`-($```````"0@\0(6\.-=@!55U93@>R,```` -MBY0DI````(N<)*@```"+K"2@````BX4@+@``B40D%+@`````@_H&#X?Z!``` -M_R25,%4``(G>N`````"#^P0/A^,$``"+E"2@````BTH4BY%0F```@>+__P_P -MBX2=)$0``,'@%"4``/`/"<*)D5"8``"+O"2@````BT\4BY%)_@/__ -MBX2=3$0``,'@!R6`?P``"<*)D5R8``"+3Q2+D5R8``"!XO]_P/^+A)TX1``` -MP>`/)0"`/P`)PHF17)@``(M/%(N16)@``('B__\#_(N$G6!$``#!X!(E``#\ -M`PG"B9%8F```BU0D%`^V0@DYV',(_X5$*@``ZQ*+3"04#[9!"3G8=@;_A4@J -M``")\(M4)!2(0@GI!`0``,=$)$A_````C70D2,=&!#(```#'1"1`?P```,=$ -M)$0H````QT0D.'\```#'1"0\30```,=$)#!_````QT0D-$````#'1"0H'P`` -M`,=$)"P0````QT0D(#\```#'1"0D,````(7;#Y7`#[;`B40D$(N\)*````"+ -M3Q2+D6R8``"!XO\_X/^)P\'C`HL$,\'@#B4`P!\`"<*)D6R8``"+3Q2+D6R8 -M``"!XO__'_"+1!Q`P>`5)0``X`\)PHF1;)@``(M/%(N1:)@``('B__\!_XM$ -M'#C!X!$E``#^``G"B9%HF```BT\4BY%HF```@>+___^`BT0<,,'@&"4```!_ -M"<*)D6B8``"+3Q2+@6B8``"#X."+5!PH@^(?"=")@6B8``"+3Q2+D6R8``"` -MYL"+1!P@P>`()0`_```)PHF1;)@``(-\)!``=!2+5Q2+@FR8``"#R`&)@FR8 -M``#K&8N$)*````"+4!2+@FR8``"#X/Z)@FR8``"#?"00``^4P`^VP(M,)!0/ -MME$,.=`/A'0"``"#?"00`'0(_X54*@``ZP;_A5@J``"#?"00`(M\)!0/E$<, -MZ4T"``#'1"08"````(U4)!C'0@0&````A=L/E<`/MMB+A"2@````BT@4BX$( -MH@``@^#`BQ2:@^(_"=")@0BB``"+5"04#[9"#3G8#X0!`@``A=MT"/^%7"H` -M`.L&_X5@*@``BTPD%(A9#>GC`0``QT0D<`````#'1"1T!````,=$)'@(```` -MB=ZX`````(/[`@^'P`$``(N\)*````"+3Q2+D5B8``"!XO\/_/^+1)QPP>`, -M)0#P`P`)PHF16)@``(M4)!0/MD(+.=AS"/^%9"H``.L2BTPD%`^V00LYV'8& -M_X5H*@``B?"+5"04B$(+Z5T!``"-3"10B4PD#+X050``_+D(````BWPD#/.E -MB=ZX`````(/[!P^'.0$``(N$)*````"+2!2+D229``"`X@&+1)Q0T>`E_@`` -M``G"B9$DF0``BU0D%`^V0@HYV',(_X5,*@``ZQ*+3"04#[9!"CG8=@;_A5`J -M``")\(M4)!2(0@KIV@```(7;=4"#I10N``#]@^P,_[0DK````.C\____@\0$ -M_[0DK````.C\____@\0(@.3^4/^T)*P```#H_/___X/$$.F6````]H44+@`` -M`@^%B0```(.]&"X```!T5(/L#/^T)*P```#H_/___X/$"(#D_E#_M"2L```` -MZ/S___^+C"2P````BU$4BX5H+@``B8(L@0``BU$4BX5L+@``B8(T@0``B0PD -MZ/S___^#Q!#K)8/L#/^T)*P```#H_/___X/$"(#,`5#_M"2L````Z/S___^# -MQ!"#C10N```"N`$```"!Q(P```!;7E]=PU93@^P$BTPD$(G.BYD@+@``QT,0 -M`````(.Y&"X````/A(,```"!>Q0``,``=@K'0T0`````ZPR0N```P``K0Q2) -M0T2!>QP``,``?@S'0T@`````ZPZ-=@"X``#``"M#'(E#2(M1%(M#1(F"+($` -M`(M1%(M#2(F"-($``(M!%,>`,($``````@"+013'@#B!```````"@^P(C8:` -M*@``4%'H_/___X/$$,=#/`````#'0T``````@\0$6U[#5U93BW0D$(N^-!`` -M`(N&%"X``(/@`X/X`P^%+0$``(N>("X``(!["0-W&8/L!`^V0PE`4&H!5NC\ -M____@\00Z0@!``"*0PHZ0PAS&(/L!`^VP$!0:@56Z/S___^#Q!#IZ````(N. -ME"H``(G(@^!_@_@_=@B-07_!Z`?K"8N&E"H``,'H!SE#*'U(@'L,`'4B@^P$ -M:@!J`E;H_/___X/$#&H`:@56Z/S___^#Q!#IF@```(!["P$/AY````"#[`0/ -MMD,+0%!J!%;H_/___X/$$.MZ.4,D?3*`>PP`=!"#[`1J`6H"5NC\____@\00 -M@'L+`7=9@^P$#[9#"T!0:@16Z/S___^#Q!#K0X/L"%=6Z/S___^#Z`*#Q!"# -M^`%W+H![#`!U$(/L!&H`:@)6Z/S___^#Q!"`>PL`=!*#[`1J`&H$5NC\____ -M@\00B?9;7E_#5U93BUPD$(N[-!```(N#%"X``(/@`X/X`P^%E0```(NS("X` -M`(!^"0-W&8/L!`^V1@E`4&H!4^C\____@\00ZW.-=@"+DY0J``")T(/@?X/X -M/W8(C4)_P>@'ZPF+@Y0J``#!Z`#[`1J!&H!4^C\____@\0,#[9&"%!J!5/H_/___X/$#&H!:@)3Z/S___^# -MQ`QJ`6H#4^C\____@\0,:@)J!%/H_/___X/$$(._&"X```!T/8/L#%/H_/__ -M_X/$"(#D_E!3Z/S___^)'"3HGOO__XM#%,>`,($``````@"#Q!"+0Q3'@#B! -M```````"ZR.#[`Q3Z';[__^)'"3H_/___X/$"(#,`5!3Z/S___^#Q!")]EM> -M7\-75E.+="00BUPD%(GWBT84QX`D@0```````(M&%,>`*($```````"#[`B- -MAH`J``!05NC\____BP.)AI0J``"+0P2)AI@J``"+0PB)AIPJ``"+1A2+D"R! -M``"+B#2!``")T"4``,``@\00/0``P`!T#HG()0``P``]``#``'5ABY\@+@`` -M*U-$B=`K0SP!AVPJ``")4SR)RBM32(G0*T-``8=P*@``B5-`BT,\.T,4=@^# -M[`Q6Z%K[__^#Q!"-=@"+0T`[0QQV#(/L#%;HD_S__X/$$(/L#%;H>_K__X/$ -M$%M>7\-3@^P(BUPD$(M$)!2+DR`N``"`>`41=2C_0CS_@VPJ``"+0CP[0A1V -M0X/L#%/H_OK__XD<).@Z^O__@\00ZRV0@'@%&74F_T)`_X-P*@``BT)`.T(< -M=A6#[`Q3Z"#\__^)'"3H#/K__X/$$)"#Q`A;PXUV`%93@^P$BW0D$(N.("X` -M`(N6E"H``(G0@^!_@_@_=@F-0G_!Z`?K"I"+AI0J``#!Z`0L`=!:#[`0/MD$+2%!J!%;H_/___X/$$.LX@'D*`'06@^P$ -M#[9!"DA0:@56Z/S___^#Q!#K'(!Y"0!T%H/L!`^V00E(4&H!5NC\____@\00 -MB?:#Q`1;7L.)]E575E.+5"04BT(4B[CL@```BZCP@```B[#X@```BYH@+@`` -M@WLX`'0%.7,X=@ZY`````/^">"H``.LID(GQ*TLXB>@K0S2)^BM3,"G!*=&X -M*3E37_?IP?H.BS"):S2)R%M>7UW#55=64X/L#(M\ -M)""+5"0DB?V+GR`N``"+`HF'E"H``(M"!(F'F"H``(M""(F'G"H``(7;#X27 -M`0``5^A-____B<:#Q`2%P'D4_X=\*@``@^P,5^AI^/__@\00B?8!`,($``````@`Y2T@/ -MA@X!``"+1Q2+4TB)D#2!``"+1Q3'@#B!```````"Z?`````K4T2)T"M#/`&% -M;"H``(E3/(G**U-(B=`K0T`!A7`J``")4T"+AQ0N``"#X`.#^`,/A;H```"+ -MA1PN``"-!(`Y0Q!V1HM+$(G(#Z]#&+[336(0]^:)T,'H!CE#/'<>B<@/KT,@ -M]^:)T,'H!CE#0'<,@^P,5^AG_?__@\00@^P,5^A;]___@\00ZV:+0Q`[A1PN -M``!V6XG"#Z]3%+C336(0]^*)T,'H!CE#/'86@^P,5^CG]___B3PDZ"/W__^# -MQ!#K+HM#$`^O0QRZTTUB$/?BB=#!Z`8Y0T!V%H/L#%?H"?G__XD\).CU]O__ -M@\00B?:#Q`Q;7E]=PXM,)`2+5"0(BX$T$```9HL`9HD"BX$T$```@$@$"(!* -M!`B+@300``!FBT`"9HE"`HN!-!```(I`!(A"!(N!-!```(I`!8A"!;@````` -MPY"055=64X/L#(M\)""+;"0HBUPD++X`````C01VBT\4BQ3%8%4``(E4)`B+ -M5"0DC01"BP2%8%4``(M4)`B)!!%#]L,_=1"#[`QJ`>C\____@\00C78`1H/^ -M#7:^O@````"0BT\4BQ3UP%8``(L$]<16``")!!%#]L,_=0Z#[`QJ`>C\____ -M@\00D$:#_D=VTKX`````D(T$=HM/%(L4A:!:```!Z(L$A:!:``")!!%#]L,_ -M=0V#[`QJ`>C\____@\001H/^/W;.@\0,6UY?7<.)]E575E.#[!"+;"0DBU0D -M*`^W0@)0#[<"4%7H_/___X/$$(M<)"2`>P(`>6D/O_"-'';!XP*-LR1A``"# -M[`AJ"/]V!.C\____B<>!Y_\```#!YP6+@R1A``#!X`0)QV:+3@B+512+@@2B -M``"#Q!"+7"0D9H$[M`EU#(/($(F"!*(``.L8D(M5%(/@[XF"!*(``.L)B?:) -MP;\`````9H'YD`!_!?;!`70E@^P(:@@/O\&#Z!A0Z/S___^)PX'C_P```+@! -M````@\00ZRZ)]H/L"&H(#[_!@^@8B<+!ZA\!T-'X4.C\____B<.!X_\```"X -M`````(/$$(GVP>,"T>`)PX'+`00``(M-%(GX)?\```#!X`@/MM,)T(F!G)@` -M`(M-%(GX)0#_```/MM<)T(F!T)@``(M$)"2)A300``"X`0```(/$#%M>7UW# -MC78`BU0D"(M$)`2+@.@M``"#^@=W(?\DE6AB``")]H/`1,.#P$C#@\!,PX/` -M4,,%E````,.)]K@`````PXGV55=64X/L?(NL))````"+A"28````9HE$)!Z) -M;"08OP````"+E"24````#[="`B7P`0``/<`````/A.`!```]P````'\0/:`` -M```/A%,!``#I00(``#U``0``=`L]4`$```^%+P(``(N4))0```!FBP(MH0\` -M`&8]Z@1W)8M$)!AFBX!0$0``9HE$)`Z+5"089HN24A$``&:)5"0,Z:P```"+ -ME"24````9HL"+8P4``!F/>\`=R*+1"089HN`5!$``&:)1"0.BU0D&&:+DE81 -M``!FB50D#.MUBY0DE````&:+`BU\%0``9CW@`'$0``9HE$)`SK#F;'1"0,``!FQT0D#@``QT0D"`````"^ -M`````(M4)!AFBY+4$```9HE4)!:+1"089HN`VA```&:)1"04BU0D&&:#NMH0 -M````#Y3`9@^VP&:)1"029HN"*!$``&:)1"00Z?T```"+5"089HN28!$``&:) -M5"0.BT0D&&:+@&(1``!FB40D#(M4)!@/M[)H$0``#[>";!$``(E$)`AFBY+6 -M$```9HE4)!:+1"089HN`W!```&:)1"04BU0D&&:#NMP0````#Y3`9@^VP&:) -M1"029HN"*A$``&:)1"00Z8(```"+5"089HN29!$``&:)5"0.BT0D&&:+@&81 -M``!FB40D#(M4)!@/M[)J$0``#[>";A$``(E$)`AFBY+8$```9HE4)!:+1"08 -M9HN`WA```&:)1"04BU0D&&:#NMX0````#Y3`9@^VP&:)1"029HN"+!$``&:) -M1"00ZPJX`````.E5`P``NP`````/MU0D'KD`60``D(T$6XT$0HL$@8E$G"!# -M@_L0=NV+E"24````@'H"`'DJ@^P,:@!J=VH#5HU<)#Q3Z/S___^#Q!1J`&IZ -M:@/_="0@4^C\____@\0@NP````"0C01;BTT4BQ3%`%D``(M$G"")!!%']\<_ -M````=0^#[`QJ`>C\____@\00B?9#@_L0=LZ[`````(M-%(L4W:!=``"+!-VD -M70``B0011_?'/P```'4-@^P,:@'H_/___X/$$$-TT[L`````#[=T)!Z-!%N+ -M312+%,6H70``C01&BP2%J%T``(D$$4?WQS\```!U#8/L#&H!Z/S___^#Q!!# -M=,V[``````^W="0>C01;BTT4BQ3%P%T``(T$1HL$AC\____@\000W3-NP`````/MU0D'KG@70``C78`C01;C01"BP2! -MB42<($.#^Q!V[8N4))0````/MT(")4`!```]0`$``'4]@^P,:@-J,VH!BU0D -M,`^W@L@1``!0C5PD/%/H_/___X/$%&H#:BUJ`8M4)#`/MX+*$0``4%/H_/__ -M_X/$((/L#&H`:E]J`0^W1"0J4(U<)#Q3Z/S___^#Q!1J`&I@:@0/MT0D+E!3 -MZ/S___^#Q!1J`&IH:@,/MT0D)E!3Z/S___^#Q!1J`&IK:@,/MT0D)%!3Z/S_ -M__^[`````(/$()"-!%N+312+%,7@70``BT2<((D$$4?WQS\```!U#X/L#&H! -MZ/S___^#Q!")]D.#^Q!VSKL`````#[=4)!ZY@%\``(UV`(T$6XT$0HL$@8E$ -MG"!#@_L'=NV#[`QJ`&H=:@8/MT0D*%"-7"0\4^C\____@\04:@!J!&H!#[=$ -M)"Q04^C\____@\0@BX0DE````&:#>`(`>`;V0`-`=%2+E"24````#[="`B4` -M0```@_@!&=N#XP^#PQ"#[`QJ`&H3:@5J'XUT)#Q6Z/S___^#Q!1J`&H8:@53 -M5NC\____@\04:@!J,6H":@-6Z/S___^#Q""[`````(UV`(T$6XM-%(L4Q8!? -M``"+1)P@B0011_?'/P```'4/@^P,:@'H_/___X/$$(GV0X/[!W;.BT0D&,>` -MP"T```````"X`0```(/$?%M>7UW#C78`55=64XML)!2+3"08BWPD'(M<)""+ -M="0D#[?##[?6#Z_"N@````"%P'1AB=AF.<]T5P^WQ0^WR2G(C02`C02`P>`" -M#[?7*!FB40D&F;'1"04``"_ -M``````^_R(G.B`/M\`/MTQ]`@^W7'T`#[=T)!I24%%35N@W -M_/__@\040`^W3"04BUPD'(N3=$0``&;1Z&:)!$J+@W1$``!FBU0D%F8Y%$AV -M!&:)%$AF_T0D%`^W5"0V9HM,)!IF.4Q5_GX.9H-\)!0_#X8G____ZRUF@WPD -M%#]W)0^W3"04BUPD'(N3=$0``&:+1$K^9HD$2F;_1"049H-\)!0_=MN+1"0< -M9L>`\"T`````N`$```"!Q$P!``!;7E]=PXGV55=64X/L'(ML)#B+7"0PBW0D -M-(U$)!I050^WQE`/M\-0Z$(!``"#Q!"%P'0+#[=$)!KI*0$``)"#[`R-1"0D -M4(U$)"90#[=%!%#_=0`/M]N)7"0@4^C\____@\04C40D(%"-1"0B4%4/MT0D -M+E`/M_96Z'4!``"#Q!2-1"0<4(U$)!Y050^W1"0P4%;H6P$``(/$((U$)`Q0 -M50^W1"0:4`^W1"0B4.B]````C40D&E!5#[=$)"Q0#[=$)#)0Z*8```"#Q"`/ -MMT0D"@^W5"0,#[=,)!0/MUPD$E!245-6Z+7Z__^#Q!2)QXU$)`Q050^W1"06 -M4`^W1"0D4.AI````C40D&E!5#[=$)"A0#[=$)#10Z%(```"#Q"`/MT0D"@^W -M5"0,#[=,)!`/MUPD#E!245-6Z&'Z__^#Q!0/M\`/M]\/MU0D&`^W3"064%-2 -M4?]T)!3H0?K__X/$%`^WP(UV`(/$'%M>7UW#55=64X/L!(ML)""+1"089HE$ -M)`*+?"008` -M=">-=@!F.3IU$V:+5%D>BT0D)&:)$+@!````ZQV#P@)##[=!!CG8?]R#P31& -M#[=%!#GP?[2X`````(/$!%M>7UW#C78`5U93BT0D&(M\)!"+="04BU`(N0`` -M```/MT`$B<.#^`!^#XGV9CDR=`B#PC1!.#K"H``$!@`0#'@[`J``#T7@$`QX.T*@``?&`!`,>#N"H``!!G`0#' -M@[PJ``"`;0$`QX/`*@``B&T!`+@!````C78`@\0$6U[#D)!55U93@^P,BWPD -M((ML)"B+7"0LO@````"-!':+3Q2+%,7@8@``B50D"(M4)"2-!$*+!(7@8@`` -MBU0D"(D$$4/VPS]U$(/L#&H!Z/S___^#Q!"-=@!&@_X/=KZ^`````)"+3Q2+ -M%/5@9```BP3U9&0``(D$$4/VPS]U#H/L#&H!Z/S___^#Q!"01H/^1';2O@`` -M``"0C01VBT\4BQ2%H&8```'HBP2%H&8``(D$$4/VPS]U#8/L#&H!Z/S___^# -MQ!!&@_X_=LZ#Q`Q;7E]=PXGV55=64X/L#(ML)""+="0DQT0D"`````"_```` -M`&:!/K\2#X?-````#[<&B40D!"V0"```N@4```")TYGW^X72=2.+1"0$C9P` -MX.[__[AG9F9F]^O!^@*)V,'X'XG3*#Q!#I -MJ````&:+!KD*````N@````!F]_%FA=)U/X/L"&H(#[<.@>G`$@``N&=F9F;W -MZ8G0P?@"P?D?*#Q!#K5XUV`&:+ -M!KD%````N@````!F]_&X`````&:%TG5^@^P(:@@/MPZ!Z<`2``"X9V9F9O?I -MB=#1^,'Y'RG(4.C\____B<.#Q`AJ`FH!Z/S___^)QX/$$(UV`(G9P>$$C02] -M``````G!BT0D"-'@"<&!R0$0``"+510/ML&)@IR8``#!Z0B+512)R(/@?XF" -MV)@``(FU-!```+@!````@\0,6UY?7<.+5"0(BT0D!(N`Z"T``(/Z!W<=_R25 -MV&X``(GV@\`$PX/`",.#P`S#!:P```##B?:X`````,.)]E575E.#[!R+1"0X -M9HE$)!J+5"0PB50D%&;'1"00``!FQT0D#@``9L=$)`P``&;'1"0*``"+NN@M -M``"!P@PJ``")5"0$O0````"+5"0T#[="`B7P`0``/=`````/A&,!```]T``` -M`'\;/:`````/A!@!```]P`````^$1@$``.EO`0``/5`!``!T'CU0`0``?PP] -M0`$``'00Z54!```]``@```^%2@$``(M4)#1FBP(MH0\``&8]Z@1W)8M$)!1F -MBX!0$0``9HE$)!"+5"049HN24A$``&:)5"0.Z9,```"+5"0T9HL"+8P4``!F -M/>\`=R*+1"049HN`5!$``&:)1"00BU0D%&:+DE81``!FB50D#NM?BU0D-&:+ -M`BU\%0``9CW@`'$0``9HE$)`Z+ -M5"049HNRVA```&:+@B@1``!FB40D$NMQBU0D%&:+DF@1``!FB50D#(M$)!1F -MBX!L$0``9HE$)`J+5"049HNRW!```&:+@BH1``!FB40D$NLXBU0D%&:+DFH1 -M``!FB50D"F:)5"0,BT0D%&:+L-X0``!FBY`L$0``9HE4)!+K"K@`````Z?$$ -M``"Z`````+FD:0``BP31B0270G3WN@`````/MTPD&KNH:0``C012C01!BP2# -MB427!$)T\+H`````#[=,)!J[P&D``(T$4HT$08L$@XE$EPA"=/"Z``````^W -M3"0:N^!I``"-!%*-!$&+!(.)1)<,0H/Z)W;M@^P,:@!H+@$``&H!#[?&4(U? -M#%/H_/___X/$%&H`:`X!``!J`HM4)%0/MP)04^C\____@\04:@!H`0$``&H" -MBU0D5`^W0@)04^C\____@\0@BT0D-/9``D`/A+<```"#[`QJ`VBH````:@&+ -M5"0"U`$``"7P````@^@P@_@_=W5F -M@[K4`0``-70>9H.ZU`$``$5T%&:#NM0!``!&=`IF@[K4`0``-G5-@^P,:@)J -M6FH":@*-7PQ3Z/S___^#Q!1J`FI<:@)J`E/H_/___X/$%&H":EYJ`FH"4^C\ -M____@\04:@)H_@```&H!:@)3Z/S___^#Q""+1"0P9H.XT@$``$%V9(/L#&H! -M:!D!``!J`6H!C5\,4^C\____@\04:@-J`6H":@%3Z/S___^#Q!1J`VH#:@)J -M`5/H_/___X/$%&H#:(L```!J`6H!4^C\____@\04:@-HC````&H!:@%3Z/S_ -M__^#Q""Z``````^W3"0:NZ!M``"0C012C01!BP2#B827K````$*#^@QVZHM4 -M)#3V0@)`=".#[`QJ`&HE:@*+5"0C\ -M____@\00B?9#@_LG=LJ[`````)"-!%N+5"0PBTH4BQ3%H&T``(N$GZP```") -M!!%%]\4_````=1"#[`QJ`>C\____@\00C78`0X/[#';&BT0D%,>`P"T````` -M``"X`0```(/$'%M>7UW#C78`55=64X'L_`,``(N$)!`$``")1"08#[>`U`$` -M`"7P````@^@P@_@_=S:+5"089H.ZU`$``#5T'F:#NM0!``!%=!1F@[K4`0`` -M1G0*9H.ZU`$``#9U"L=$)!0"````ZPC'1"04`0```(N,)!P$```/MT$")?`! -M```]T````'1I/=````!_$#V@````=$$]P````'14ZVP]4`$``'07/5`!``!_ -M"3U``0``=`GK53T`"```=4Z+1"08!=`=``")1"0,BTPD&`^WD=00``#K/HM$ -M)!@%W!T``(E$)`R+3"08#[>1UA```.LDBT0D&`7H'0``B40D#(M,)!@/MY'8 -M$```ZPJY`````.GW!0``BTPD#`^W00:Y`````(7"#X3B!0``BY0D&`0```^_ -M`M'@9HE$)`2+C"04!```#[\!T>!FB40D!F;'1"0HK=YFQT0D*JW>QT0D"``` -M``"^`````(M$)`P/MU`&C5PD*(UV`(G0B?'3^*@!=!B#?"0(`0^'T00``(M$ -M)`AFB31#0(E$)`A&@_X#=MB#[`R-1"0P4(U$)#!0BU0D(`^W0@10_S*+C"0X -M!```#[#X67````#[=T)"B-'+:-')B#[`0/ -MMWL&C30_5HU#"%"-A"3<`@``4.C\____@\0,5H/#$%.-E"2\`@``4NC\____ -M@\0$C4PD/%&+5"0@#[]"`E"-C"3$`@``48V$).@"``!05^B*!0``@\0@A<`/ -MA/,#``"#[`1H@````(U4)#A2BT0D%,'@!XV$!+P!``!0Z/S___^#Q!#I*0$` -M``^W="0HC1RVBTPD$(TP:--#]6C4,(4(V$)-P"``!0Z/S___^# -MQ`Q6@\,04XV4)+P"``!2Z/S___^#Q`2-3"0\48M4)"`/OT("4(V,),0"``!1 -MC80DZ`(``%!7Z.\$``"#Q""%P`^$8@,``(/L!&B`````C50D.%*+1"04P>`' -MC80$O`$``%#H_/___P^W="0ZC1RVBTPD((TP:--#]6C4,(4(V$ -M)-P"``!0Z/S___^#Q`Q6@\,04XV4)+P"``!2Z/S___^#Q`2-3"0\48M4)"`/ -MOT("4(V,),0"``!1C80DZ`(``%!7Z%P$``"#Q""%P`^$V0(``(/L!&B````` -MC50D.%*+1"04P>`'C80$O````%#H_/___X/$$/]$)`A%.VPD)`^&#O[__XM, -M)""+1"0,BQ!FBQQ*BT0D)&:+/$(IR(E$)`AF@7PD*JW>#X6X````O@````"# -M[`R+1"04P>`&`?`/OX1$O`$``%`/OX1TP`$``%`/M\=0#[?#4(N4)#@$```/ -MMP)0Z.("``!FB81TD`,``(/$($:#_C]VN8/L"(M,)"#_L71$``"-A"1\`P`` -M4.AG!```B<)FP>@/C00"9M'XBY0D)`0``&:)`F:+A"3^`P``B<)FP>H/`=!F -MT?AFB40D/HN,)"@$``!FB0&+1"0XBY0D,`0``&:)`F:)0@*#Q!#I.`(``+X` -M````#[?O#[?[B?:#[`R+7"04P>,&`?,/OX14(M,)!S_L71$``"-A"3X`@``4(V$)'P#``!0Z#4$``")PF;!Z`^-!`)F -MT?B+E"0D!```9HD"9HM$)"Z)PF;!Z@\!T&;1^&:)1"0^9HN$)/X#``")PF;! -MZ@\!T&;1^(N,)"@$``!FB0&+1"0XBY0D,`0``&:)`F:+1"0Z9HE"`H/$$.DE -M`0``9HM,)`9F.8PD;@,```^,J0```(M$)`1F.80D;@,```^,EP```(/L"(M4 -M)"#_LG1$``"-A"3\`@``4.C#`@``B<)FBT0D.HN,)#`$``!FB0%FB4$"B=!F -MP>@/C00"9M'XBY0D)`0``&:)`F:+A"1^`P``B<)FP>H/`=!FT?AFB40D/HN, -M)"@$``!FB0&#Q!#ID0```+D`````Z:8```"Y`````.F<````N0````#ID@`` -M`+D`````Z8@```"#[`B+1"0@_[!T1```C80D?`,``%#H+`(``(G"BT0D.(N, -M)#`$``!FB0%FB4$"B=!FP>@/C00"9M'XBY0D)`0``&:)`F:+A"3^`P``B<)F -MP>H/`=!FT?AFB40D/HN,)"@$``!FB0&#Q!"X/P```(N4)!@$``!F*P*+3"08 -M9HF!\"T``+D!````B?___[@!```` -M@\0,6UY?7<-55U93@^P$BWPD&(ML)!P/OT=^#[\7*="#^'Y^#F:+1WZ#Z'YF -MB40D`NL(9HL'9HE$)`)FBW=^N3\````/OU=^B=!(.<)^%HG"C78`20^_P0^_ -M!$>^)RHGSOC\```")]HU"_XG!9H/X/G<=#[_"9CD<1WP4BQFA=)U&V:%]G@EB?8/O]9FBT15`F:)1%4`9DYY -M[^L0D`^_QF:)5$4`@^L"9DYYJ0^_1"0"@\0$6UY?7<-55U93@^P0BW0D)&;' -M1"0"0``/OT9^BTPD*`^_$2G0@_A^?@YFBVY^@^U^9HEL)`[K#(M$)"AFBP!F -MB40D#F:+5GYFB50D#+D_````#[]6?@^_1"0,2#G"?A.)PDD/O\$/OP1&.=!^ -M!6:%R7GOBVPD*&:+17Z+5"0P9HD"OS\```"+7"0,C78`BVPD,&8Y70!]#F:% -MR7499H-\)`)`=1&09L=$)`(``(MT)"BY/P```&:%R7X:#[_!9CD<1GP1B?9) -M9H7)?@D/O\%F.1Q&??%FA#@/O]>+3"0L9HM$40)F -MB0119D]Y[.LBD`^_[XEL)`1FBT0D`@G(BU0D+&:)!&J#ZP)F3P^);____P^_ -M1"0.@\006UY?7<.)]E.#[`B+7"00@[MT1````'0;@^P,_[-T1```Z/S____' -M@W1$````````@\00@[OH+0```'0;@^P,_[/H+0``Z/S____'@^@M```````` -M@\00@\0(6\.-=@!55U93BWPD&&:+=P2]`````+D!````B?:-!(F-'(`"B00D#[@/K\$/K]8!T)GW_F:8BU0D -M)&:)`HM$)`0!V%#_="0@Z-O]__\/O^@#7"0(4_]T)"CHROW__Y@IQ0^W%P^W -M`RG"B=#J"H``'!N`0#'@ZPJ -M``#H<0$`QX.P*@``0&\!`,>#M"H``"!R`0#'@[@J```8>0$`QX.\*@``X(8! -M`,>#P"H```````"X`0```)"#Q`1;7L.0D%575E.#[`R+?"0@BVPD*(MT)"R[ -M`````(T$6XM/%(L4Q0!O``")5"0(BU0D)(T$0HL$A0!O``"+5"0(B0011O?& -M/P```'4-@^P,:@'H_/___X/$$$.#^P]VOKL`````D(M/%(L4W8!P``"+!-V$ -M<```B0011O?&/P```'4/@^P,:@'H_/___X/$$(GV0X'[B@```';+NP````") -M]HT$6XM/%(L4A>!T```!Z(L$A>!T``")!!%&]\8_````=0Z#[`QJ`>C\____ -M@\00D$.#^S]VRH/$#%M>7UW#B?955U93@^P,BVPD((MT)"3'1"0(`````+\` -M````9H$^OQ(/A\T````/MP:)1"0$+9`(``"Z!0```(G3F??[A=)U(XM$)`2- -MG`#@[O__N&=F9F;WZ\'Z`HG8P?@?B=,IP^M%C78`#[<.C8%0]___N@4```") -MTYGW^[@`````A=(/A1P"``"-G`F@[O__N&=F9F;WZ\'Z`HG8P?@?B=,IP\=$ -M)`@!````P>,"@>/_````@^P(:@A3Z/S___^)PXM5%(N"!*(``(/$$&:!/K0) -M=1&#R!")@@2B``#I?P$``(UV`(M5%(/@[XF"!*(``.EK`0``C78`9HL.NP4` -M``"Z`````(G(9O?S9H/Z`G5,9H'Y.Q5W18/I`H/L"&H(#[?)C0R)C8P)@$3_ -M_[@?A>M1]^F)T,'X`\'Y'RG(0%#H_/___XG#@\0(:@)J`.C\____B<>#Q!#I -M!`$``&:+!KD4````N@````!F]_%FA=)U1V:!/O\3=D"#[`AJ"`^W#H'IP!(` -M`+AG9F9F]^F)T,'X`\'Y'RG(P>`"4.C\____B<.#Q`AJ`FH#Z/S___^)QX/$ -M$.FH````9HL&N0H```"Z`````&;W\6:%TG4_@^P(:@@/MPZ!Z<`2``"X9V9F -M9O?IB=#!^`+!^1\IR-'@4.C\____B<.#Q`AJ`FH"Z/S___^)QX/$$.M7C78` -M9HL&N04```"Z`````&;W\;@`````9H72=7Z#[`AJ"`^W#H'IP!(``+AG9F9F -M]^F)T-'XP?D?*`)P8')`1```(M5%`^VP8F"G)@``,'I"(M5%(G(@^!_ -MB8+8F```B;4T$```N`$```"#Q`Q;7E]=PU575E.#[`R+;"0@BT0D*&:)1"0* -MB6PD!+\`````B[7H+0``BT0D)`^W0`(E\`$``#W`````=#H]P````'\)/:`` -M``!T"^M+/=````!T(^M"BT0D!&:+@&`1``!FB40D`HM$)`1FBX!B$0``9HD$ -M).LKBT0D!&:+@&01``!FB40D`HM$)`1FBX!F$0``9HD$).L*N`````#IX0$` -M`+H`````N>1W``"+!-&)!)9"=/>Z``````^W3"0*N^AW``"-!%*-!$&+!(.) -M1)8$0G3PN@`````/MTPD"KL`>```C012C01!BP2#B426"$)T\+H`````#[=, -M)`J[('@``(T$4HT$08L$@XE$E@Q"@_H:=NV#[`QJ`&BH````:@,/MT0D&E"- -M7@Q3Z/S___^#Q!1J`&BE````:@,/MT0D&%!3Z/S___^Z`````(/$(`^W3"0* -MN\!Z``"-!%*-!$&+!(.)1)9X0H/Z`G;MNP````"+312+%-W@=P``BP2>B001 -M1_?'/P```'4-@^P,:@'H_/___X/$$$-TU[L`````C01;BTT4BQ3%Z'<``(M$ -MG@2)!!%']\<_````=0V#[`QJ`>C\____@\000W33NP````"-!%N+312+%,4` -M>```BT2>"(D$$4?WQS\```!U#8/L#&H!Z/S___^#Q!!#=-.[`````(GVC01; -MBTT4BQ3%('@``(M$G@R)!!%']\<_````=0^#[`QJ`>C\____@\00B?9#@_L: -M=LZ[`````(T$6XM-%(L4QP``B?:#P`3#@\`(PX/`#,.#P'C#N``` -M``##B?955U93BWPD&(ML)"2+3"0-=@")^3G?+5"04BT0D/`^W!%`/K_B+1"0X#[\44(G0 -M*7\.055=64X/L3(M$)&1F -MB40D+HM4)&QFB50D+(M$)&"+@*`J``")1"0HQT0D'`````"-1"1$4(U$)$10 -MBTPD<`^W011040^_1"0^4.AZ_?__QT0D.`````"#Q!2-=@"X`P```"M$)"2) -M1"0@BU0D0(T$0(T&:)!$Z)S='EC70D.&:+2BQFB4PU`(M4)$2-!)*- -M!("-!$*-!$,#1"1H9CM(+'X)9HM`+&:)1#4`BVPD'-'E9HM$+#B)PF;!Z@\! -MT&;1^&:)1"PXC40D,(E$)!2+5"1`#[?WBUPD((T,6\'A`HT$DHT$@(T$0HT$ -M`0'PBU0D:&:+7$(JBT0D%&:)7`4`BU0D1(T$DHT$@(T$0@'!C00QBU0D:&8[ -M7$(J?@YFBT1"*HM,)!1FB40-`(M<)!S1XV:+1!PPB<)FP>H/`=!FT?AFB40< -M,/]T)"@/M_]7BU0D2(T$DHT$@(T$0HM4)"B--%+!Y@.-!$8#1"1PC5`B4H/` -M+%`/OT0<0%`/OT0<3%#_="0TZ+3\__^+1"1$!0`"``!05XM4)&B-!)*-!("- -M!$*-!$8#A"2,````C5`B4H/`+%`/OT0<7%`/OT0<:%#_="10Z'7\__^_```` -M`(/$.&:+1!PP9CM$'#AT=@^W3"0NB4PD$(ML)!S1Y8GVBUPD','C!@'[BW0D -M*`^_C%X``@``#[\T7HM4)$2+1"1H#[<44(D4)(M$)$"+5"1H#[<$0E%6_W0D -M"%#_="0@Z%C]__^#Q!2+3"0H9HF$60`$``!'9HM$+#!F*T0L.`^WP#GX=YO_ -M1"0<_T0D)(-\)"0##X;(_?__BU0D.(M$)'!FB1"_`````,=$)"0`````.WPD -M'`^#[`$``(GVBT0D'$@[1"0D=1F+7"0D9HM$7#"#P`2+="1T9HD$7NLJC78` -MBU0D)-'B#[]$%#`/OU04.@'0B<+!ZA\!T-'XBU0D)(M,)'1FB011N0````"# -M?"0D`'0;BUPD)(MT)'0/MTQ>_@^_1%PX*<$/MT0D+"G!BU0D),'B!XM<)"AF -MBX0:`@0``(G#BW0D*&8KG#(`!```B=AFA=MU!;@!````B<.%R7DWBT0D),'@ -M!XM4)"B-+!`/M].)]HG0#Z_!B?M'O@````!F`X4`!```>`*)QHM$)'QFB318 -M07C=D(M$)"31X`^_5`0PB50D!`^_5`0X*50D!(M<)"2+="1T#[AV!(EL)!@/OT0D&(G#.`&`T0D!(M<)"AFBY1#_@,` -M`(G3BW0D*&8KG$;\`P``B=AFA=MU!;@!````B<,[;"08=E8/O\4YR'Y/BT0D -M),'@!@-$)`2+5"0HC01"B40D#)")R"M$)!@/M],/K\*+="0,9@.&_@,``(G^ -M1XG"9H/X?WX%NG\```"+1"1\9HD4<$$/O\4YR'_)D/]$)"2+5"0<.50D)`^" -M%O[__X-\)"0#=QZ-=@"+3"0DBUPD=&:+1$O^9HD$2T&)3"0D@_D#=N6#_W]W -M$XMT)'QFBT1^_F:)!'Y'@_]_=NV#Q$Q;7E]=PY!55U93@^PLBWPD0(M,)$R) -M_8NW=$0```^W00(ET````#W`````=`<]T````'4(C9WX)0``ZQ\/MT$"):`` -M``"Z`````#V@````#X4'`0``C9_D(0``BT<4BX!LH@``@^`/9HD$)%;_="14 -MC40D(%"-1"0B4`^W1"004%,/MP%05^B3^O__BT\4BY%8H@``@.8_#[=#'$C! -MX`XE`,````G"B9%8H@``@\0@9H-\)!8`=!!FBT0D%O?89HF%\"T``.L)9L>% -M\"T`````NX"B``"Y``````^V%,X/MD3.`L'@"`G"#[9$S@3!X!`)P@^V1,X& -MP>`8"<*+1Q2)%!B#PP1!@_D?=L^+7Q2+%"2#X@\/MT0D&,'@!"7P`P``"<*- -M3"08#[=!`L'@"B4`_```"<(/MT$$P>`0)0``/P`)P@^W00;!X!8E``#`#PG" -MB9-LH@``N@$```")T(/$+%M>7UW#4X/L"(M<)!"#NW1$````=!N#[`S_LW1$ -M``#H_/___\>#=$0```````"#Q!"#N^@M````=!N#[`S_L^@M``#H_/___\># -MZ"T```````"#Q!"#NZ`J````=!N#[`S_LZ`J``#H_/___\>#H"H```````"# -MQ!"#Q`A;PXUV`%.+7"0,N@````"Y`P```)")R"G0C01`C03#9H-X"`!T!P^_ -M0!3K#)!"@_H#=N*X`````%O#C78`4XM<)`RZ`````(GVC0Q29HM$RPAFA#J"H``!"( -M`0#'@ZPJ```#M"H``)2+`0#'@[@J``!PE0$`QX.\ -M*@``))H!`,>#P"H```````"X`0```)"#Q`1;7L.0D%575E.#[`R+?"0@BVPD -M)(MT)"R[`````(T$6XM/%(L4Q4![``"-1$4`BP2%0'L``(D$$4;WQC\```!U -M$(/L#&H!Z/S___^#Q!"-=@!#@_L==L:[`````)"+3Q2+%-T@?@``BP3=)'X` -M`(D$$4;WQC\```!U#X/L#&H!Z/S___^#Q!")]D.#^W]VSKL`````D(T$6XM/ -M%(L4A2""```#1"0HBP2%(((``(D$$4;WQC\```!U$(/L#&H!Z/S___^#Q!"- -M=@!#@_L_=L:#Q`Q;7E]=PXGV55=64X/L#(ML)""+="0DQT0D"`````"_```` -M`&:!/K\2#X?-````#[<&B40D!"V0"```N@4```")TYGW^X72=2.+1"0$C9P` -MX.[__[AG9F9F]^O!^@*)V,'X'XG3*C\____B<>#Q!#I -MJ````&:+!KD*````N@````!F]_%FA=)U/X/L"&H(#[<.@>G`$@``N&=F9F;W -MZ8G0P?@"P?D?*C\____B<>#Q!#K5XUV`&:+ -M!KD%````N@````!F]_&X`````&:%TG5^@^P(:@@/MPZ!Z<`2``"X9V9F9O?I -MB=#1^,'Y'RG(4.C\____B<.#Q`AJ`FH!Z/S___^)QX/$$(UV`(G9P>$$C02] -M``````G!BT0D"-'@"<&!R0$0``"+510/ML&)@IR8``#!Z0B+512)R(/@?XF" -MV)@``(FU-!```+@!````@\0,6UY?7<-55U93@^P@M``"+5"0T -M#[="`B7P`0``/=`````/A"4!```]T````'\;/:`````/A/$````]P`````^$ -M"`$``.DE`0``/4`!``!T"SU0`0``#X43`0``BU0D-&:+`BVA#P``9CWJ!'``=R*+1"049HN`6!$``&:)1"02BU0D%&:+DEH1 -M``!FB50D$.M[BT0D-&:!.%P6=G"+5"049HN27!$``&:)5"02BT0D%&:+@%X1 -M``!FB40D$.M.BU0D%&:+DF`1``!FB50D#HM$)!1FBX!B$0``9HE$)`SK+(M4 -M)!1FBY)D$0``9HE4)`Z+1"049HN`9A$``&:)1"0,ZPJX`````.E]`@``N@`` -M``"Y)(4``(L$T8D$ED)T][H`````#[=,)!J[*(4``(T$4HT$08L$@XE$E@1" -M=/"Z``````^W3"0:NT"%``"-!%*-!$&+!(.)1)8(0G3PN@`````/MTPD&KM@ -MA0``C012C01!BP2#B426#$*#^B1V[8M4)#2`>@(`#XF-````@^P,:@!H\0`` -M`&H##[=$)"90C5X,4^C\____@\04:@!H[@```&H##[=$)"104^C\____@\04 -M:@)H(P$``&H!:@%3Z/S___^#Q""#O[ -M`````(T$6XM-%(L4Q2B%``"+1)X$B0011_?'/P```'4-@^P,:@'H_/___X/$ -M$$-TT[L`````C01;BTT4BQ3%0(4``(M$G@B)!!%']\<_````=0V#[`QJ`>C\ -M____@\000W33NP````"-!%N+312+%,5@A0``BT2>#(D$$4?WQS\```!U#X/L -M#&H!Z/S___^#Q!")]D.#^R1VSKL`````C01;BTT4BQ3%X(@``(N$GJ````") -M!!%']\<_````=0V#[`QJ`>C\____@\000X/[`G;-BT0D%,>`P"T```````"X -M`0```(/$'%M>7UW#C78`BU0D"(M$)`2+@.@M``"#^@=W'?\DE2B)``")]H/` -M!,.#P`C#@\`,PP6@````PXGVN`````##B?955U93BWPD&(ML)"2+3"0-=@")^3G?+5"04 -MBT0D/`^W!%`/K_B+1"0X#[\44(G0*7\.055=64X/L3(M$)&1FB40D+HM4)&QFB50D+(M$)&"+@*`J``") -M1"0HQT0D'`````"-1"1$4(U$)$10BTPD<`^W011040^_1"0^4.AZ_?__QT0D -M.`````"#Q!2-=@"X`P```"M$)"2)1"0@BU0D0(T$0(T&:)!$Z)S='E -MC70D.&:+2BQFB4PU`(M4)$2-!)*-!("-!$*-!$,#1"1H9CM(+'X)9HM`+&:) -M1#4`BVPD'-'E9HM$+#B)PF;!Z@\!T&;1^&:)1"PXC40D,(E$)!2+5"1`#[?W -MBUPD((T,6\'A`HT$DHT$@(T$0HT$`0'PBU0D:&:+7$(JBT0D%&:)7`4`BU0D -M1(T$DHT$@(T$0@'!C00QBU0D:&8[7$(J?@YFBT1"*HM,)!1FB40-`(M<)!S1 -MXV:+1!PPB<)FP>H/`=!FT?AFB40<,/]T)"@/M_]7BU0D2(T$DHT$@(T$0HM4 -M)"B--%+!Y@.-!$8#1"1PC5`B4H/`+%`/OT0<0%`/OT0<3%#_="0TZ+3\__^+ -M1"1$!0`"``!05XM4)&B-!)*-!("-!$*-!$8#A"2,````C5`B4H/`+%`/OT0< -M7%`/OT0<:%#_="10Z'7\__^_`````(/$.&:+1!PP9CM$'#AT=@^W3"0NB4PD -M$(ML)!S1Y8GVBUPD','C!@'[BW0D*`^_C%X``@``#[\T7HM4)$2+1"1H#[<4 -M4(D4)(M$)$"+5"1H#[<$0E%6_W0D"%#_="0@Z%C]__^#Q!2+3"0H9HF$60`$ -M``!'9HM$+#!F*T0L.`^WP#GX=YO_1"0<_T0D)(-\)"0##X;(_?__BU0D.(M$ -M)'!FB1"_`````,=$)"0`````.WPD'`^#[`$``(GVBT0D'$@[1"0D=1F+7"0D -M9HM$7#"#P`2+="1T9HD$7NLJC78`BU0D)-'B#[]$%#`/OU04.@'0B<+!ZA\! -MT-'XBU0D)(M,)'1FB011N0````"#?"0D`'0;BUPD)(MT)'0/MTQ>_@^_1%PX -M*<$/MT0D+"G!BU0D),'B!XM<)"AFBX0:`@0``(G#BW0D*&8KG#(`!```B=AF -MA=MU!;@!````B<.%R7DWBT0D),'@!XM4)"B-+!`/M].)]HG0#Z_!B?M'O@`` -M``!F`X4`!```>`*)QHM$)'QFB31807C=D(M$)"31X`^_5`0PB50D!`^_5`0X -M*50D!(M<)"2+="1T#[AV!(EL)!@/OT0D -M&(G#.`&`T0D!(M<)"AFBY1#_@,``(G3BW0D*&8KG$;\`P``B=AFA=MU!;@! -M````B<,[;"08=E8/O\4YR'Y/BT0D),'@!@-$)`2+5"0HC01"B40D#)")R"M$ -M)!@/M],/K\*+="0,9@.&_@,``(G^1XG"9H/X?WX%NG\```"+1"1\9HD4<$$/ -MO\4YR'_)D/]$)"2+5"0<.50D)`^"%O[__X-\)"0#=QZ-=@"+3"0DBUPD=&:+ -M1$O^9HD$2T&)3"0D@_D#=N6#_W]W$XMT)'QFBT1^_F:)!'Y'@_]_=NV#Q$Q; -M7E]=PY!55U93@^PLBWPD0(M4)$R)_8NW=$0```^W0@(ET````#W`````=`<] -MT````'4(C9WX)0``ZQP/MT("):````"-G^0A```]H````'0&C9_0'0``BT<4 -MBX!LH@``@^`/9HD$)%;_="14C40D(%"-1"0B4`^W1"004%,/MP)05^B6^O__ -MBT\4BY%8H@``@.8_#[=#'$C!X`XE`,````G"B9%8H@``@\0@9H-\)!8`=!!F -MBT0D%O?89HF%\"T``.L)9L>%\"T`````NX"B``"Y`````(UV``^V%,X/MD3. -M`L'@"`G"#[9$S@3!X!`)P@^V1,X&P>`8"<*+1Q2)%!B#PP1!@_D?=L^+7Q2+ -M%"2#X@\/MT0D&,'@!"7P`P``"<*-3"08#[=!`L'@"B4`_```"<(/MT$$P>`0 -M)0``/P`)P@^W00;!X!8E``#`#PG"B9-LH@``N`$```"#Q"Q;7E]=PXGV4X/L -M"(M<)!"#NW1$````=!N#[`S_LW1$``#H_/___\>#=$0```````"#Q!"#N^@M -M````=!N#[`S_L^@M``#H_/___\>#Z"T```````"#Q!"#NZ`J````=!N#[`S_ -MLZ`J``#H_/___\>#H"H```````"#Q!"#Q`A;PXUV`%.+7"0,N@````"Y`P`` -M`)")R"G0C01`C03#9H-X"`!T!P^_0!3K#)!"@_H#=N*X`````%O#C78`4XM< -M)`RZ`````(GVC0Q29HM$RPAFA9]_UFF(M4)#AFB0+_ -M="08_W0D-.C*_?__#[_P@\0@4_]T)!SHNOW__Y@IQHM,)"0/MQ$/MP,IP@^O -M\E/_="0DZ)[]__^8#Z_%C00&F??]9IB+5"0T9HD"N@$```"#Q!#K38T$DHT$ -M@(T$0HT,`(M4)!QFBP*Z`````&8[!#EU+XT<.5/_="0#J"H``&R;`0#'@ZPJ```8HP$`QX.P*@``0)P!`,># -MM"H``.B>`0#'@[@J``!PJ@$`QX.\*@``)*\!`,>#P"H```````"X`0```)"# -MQ`1;7L.0D"A0%BQ8*```F`@``*L(``"K"```M0@``+\(``#8"```X@@``/(( -M``"]"@```@D``!<)``!L"0``+0D``$()``!7"0``?@D``+T*``"]"@``X`D` -M`/8)```,"@``%@H``,X(```J"@``0`H``%,*``"]"@``O0H``)P*``"]"@`` -MHPH``+T*``"]"@``O0H``+$*``"@_Z/_GO^@_Z/_H/\```4`"@`4`!X`,@!& -M`%4`6@!?`&0````*`!0`'@`H`#(`/`!&`%``6@!D`,(```#$````Q0```-`` -M``#:````Y````,(```##````U````/(````-`0``*`$``,\```#*`````@!0 -M(0$`0`$$`*``"`#``"``T`!``%`!`````"0!F!D`)A`&```````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M`````````````````````````````````````+Q8```````````````````` -M`````````````````````````.!8```````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M``````````````````````````````````````````````````````````#_ -M______\```````````````````"8``!'````")@````````,F```IHZ$"1"8 -M````X#(]%)@``&L'```9CHQ8)@```@=``!DF````,X!`&B8``"009I`<)@```\` -M``!TF```@````'B8```$`````)D````````$F0````````B9````````#)D` -M````@``0F0```P````";````````!)L``"`````(FP``$`````R;```P```` -M$)L```@````4FP``*````!B;```H````')L```0````@FP``)````"2;```4 -M````*)L``#0````LFP``#````#";```L````-)L```(````XFP``(@```#R; -M```2````0)L``#(```!$FP``"@```$B;```J````3)L```$```!0FP``(0`` -M`%2;```1````6)L``#$```!```` -M>)H``!@```!\F@``6````(":``"8````A)H```,```"(F@``!````(R:``!$ -M````D)H``(0```"4F@``$P```)B:```2````G)H``%(```"@F@``D@```*2: -M``#2````J)H``"L```"LF@``*@```+":``!J````M)H``*H```"XF@``&P`` -M`+R:```:````P)H``%H```#$F@``F@```,B:``#:````S)H```8```#0F@`` -M!@```-2:```&````V)H```8```#/C0[/CXT.E8]@`:>/C0X$ -MF`````````,``````````````""8`````@("``("`@`"`0(``@("))@```X. -M```.#@``!P<```X.```HF````0`""@$``@H```$%`0`""C28```.#@``#@X` -M``X.```.#@``.)@```<````'````"P````L```!$F```G!9R$Z467373!O -M(!#@;X"A``#_%/\%_Q3_!?\4_P7_&?\%U)@``!`````4````$````!`````` -M````#``````````H````G)R$A"P```!\?'Q\-`````4```!``````````$0` -M```(````2`````@```!,````$````%``````````5````!\`````"``````` -M``0(````````"`@````````,"````````!`(````````%`@````````8"``` -M`````!P(````````(`@````````D"````````#`2````````!(`````````( -M@`````````R`````````&(`````````D@````````"B````P````+(```/__ -M!P`P@```____`32````Q````.(`````````\@````````$"`````````1(`` -M``(```!(@````````%2`````````6(`````````(F`````````R8``"3D(0M -M$)@```#@,GT4F```:P\``!R8````````+)@``/YO`@`PF````````#R8```` -M`0(`0)@``'H!:B!,F```/&&$$E28``!9"```:)@``)!!FD!LF```@;`,!7"8 -M```/````=)@``(````!XF```#`````"9````````!)D````````(F0`````` -M``R9`````(``$)D```$````,H0``_PC_")"A``#_"?\)E*$` -M`/\*_PJ8H0``_PO_"YRA``#_#/\,H*$``/\-_PVDH0``_P[_#ZBA``#_$O\2 -MK*$``/\3_Q2PH0``_Q7_%K2A``#_%_\9N*$``/\:_QN\H0``_QW_'L"A``#_ -M(/\CQ*$``/\E_R?(H0``_RG_+,RA``#_+_\QT*$``/\T_S?4H0``_SK_.MBA -M``#_.O\ZW*$``/\Z_SK@H0``_SK_.N2A``#_.O\ZZ*$``/\Z_SKLH0``_SK_ -M.O"A``#_.O\Z]*$``/\Z_SKXH0``_SK_.ORA``#_.O\Z`)L````````$FP`` -M(`````B;```0````#)L``#`````0FP``"````!2;```H````&)L```0````< -MFP``)````"";```4````))L``#0````HFP``#````"R;```L````,)L```(` -M```TFP``(@```#B;```2````/)L``#(```!`FP``"@```$2;```J````2)L` -M``8```!,FP``)@```%";```6````5)L``#8```!8FP``#@```%R;```N```` -M8)L```$```!DFP``(0```&B;```1````;)L``#$```!PFP``"0```'2;```I -M````>)L```4```!\FP``)0```(";```5````A)L``#4```"(FP``#0```(R; -M```M````D)L```,```"4FP``(P```)B;```3````G)L``#,```"@FP``"P`` -M`*2;```K````J)L``"L```"LFP``*P```+";```K````M)L``"L```"XFP`` -M*P```+R;```K````P)L``"L```#$FP``*P```,B;```K````S)L``"L```#0 -MFP``*P```-2;```K````V)L``"L```#@```$D```"8F@``A@$``(D` -M``"%@L`8A8*`#H6"0`<%@@`ZA4'`)H5 -M!0!*%00``Q4"`%D4``````$````#``8`"0`_````@[\``(._``"MOP``K;\` -M`->_``#7OP```<````'````````````````````)````!`````0``0`!``$` -M!@```$9'.``````````````````$`````0`!``0```!&1S<````````````` -M`````P`!``$``0`#````1DL``$3L``#:ZP``..P````````````````````````@````(``` -M`$````!````````&````!@````8`GA8+`&(6"@`Z%@D`'!8(`.H5!P":%04` -M2A4$``,5`@!9%```N`L!``````"\_0``&_L``&#[``"$^P``O/T``.S[``"\ -M_0``O/T``+S]``"\_0``O/T``![\``"\_0``O/T``+S]``"\_0``,/P``%W\ -M``"\_0``K/P``-?\``"\_0``O/L``+S]``"\_0``O/T``!3]```I_0``O/T` -M`$/]``"S_0``L_T``(W]``"5_0``G?T``*7]``"M_0````````8````!```` -M`@````,````$````!0```'C_``!X_P``^_T``!_^``!X_P``6_X``'C_``!X -M_P``>/\``'C_``!X_P``@_X``'C_``!X_P``>/\``'C_``"<_@``>/\``'C_ -M``"T_@``5_\``'C_``!X_P``>/\``'C_``!X_P``V/X``-C^``!X_P``-_\` -M`````````````````$`0```/_"\`#_PO`!_\+P`/_"\`#_PO`$00```/_"\` -M#_PO`!_\+P`/_"\`#_PO`$@0```/_"\`#_PO`!_\+P`/_"\`#_PO`$P0```/ -M_"\`#_PO`!_\+P`/_"\`#_PO`%`0```/_"\`#_PO`!_\+P`/_"\`#_PO`%00 -M```/_"\`#_PO`!_\+P`/_"\`#_PO`%@0```/_"\`#_PO`!_\+P`/_"\`#_PO -M`%P0```/_"\`#_PO`!_\+P`/_"\`#_PO`&`0```/_"\`#_PO`!_\+P`/_"\` -M#_PO`&00```/_"\`#_PO`!_\+P`/_"\`#_PO`#`0```P`@``X`$``+````!@ -M`0``X`$``'`0``!H`0``X`$``+@!``",`0``X`$``+`0``!@#@``@!$``!P? -M```X/@``@!$``/`0``#@H```:$`!`(!8``#@L```:$`!`!2```#H`^@#X`;@ -M!B`$(`1`"$`(X`;@!@28`````````P```````````````P```""8`````@(" -M``("`@`"`0(``@("``("`B28```.#@``#@X```<'```.#@``#@X``$28```< -M%G(3)1QR$R(7!$```````"X$0```````/@1````````.!(```````!X$@```````+@2 -M````````^!(````````X$P```````'@3````````N!,```````#X$P`````` -M`#@4````````>!0```````"X%````````/@4````````.!4```````!X%0`` -M`````+@5````````^!4````````X%@```````'@6````````N!8```````#X -M%@```````#@7````````>!<```````"X%P```````/@7````````/!`````` -M``!\$````````+P0````````_!`````````\$0```````'P1````````O!$` -M``````#\$0```````#P2````````?!(```````"\$@```````/P2```````` -M/!,```````!\$P```````+P3````````_!,````````\%````````'P4```` -M````!(`````````(@`````````R`````````((`````````D@````````"B` -M```P````+(```/__!P`P@```____`32````Q````.(`````````\@``````` -M`$B`````````5(````````!8@````````%R```"/QP\`P(```!HP@BK$@``` -MX`''^"'`````0(#Y(<` -M``0%!@?HAP``"`D*"^R'```,#0X/\(<``!`1$A/TAP``%!46%_B'```8&1H; -M_(<``!P='A\,F```&8Z$K1"8````X"A]%)@``&N?"IP)D```$```!\F0```````!"B```S8X``%*(``!!L$``8 -MH@``8$"<`""B``#&,(@!)*(````$```LH@```````#2B```@("`@.*(``"`@ -M("!`H@``(`I).$2B``"V>P``2*(``/P__P\`FP```````"B;```,````.)L` -M`!(```!DFP``(0```(R;```M````G)L``#,```````,`!@`)`#\````#``8` -M"0`_``````````````````D````$````!``!``$``0````````````8```!& -M1S@`````````````````!`````$``0````````````0```!&1S<````````` -M`````````P`!``$``0````````````,```!&1S8`````````````````!``` -M`````0````````````$```!&1S4`````````````````!``!``$````````` -M``````````!&1S0`````````````````!`````$``````````````/[___]& -M1S,``````````````````P`!``$``````````````/W___]&1S(````````` -M````````!````````````````````/S___]&1S$``````````````````@`! -M``$``````````````/K___]&1S`````````````````````````````````` -M``````````````````````````````````````````````````````@````! -M`````P````````````````````8```!&1S<``````````````````@`````` -M``````````````````!&1S8``````````````````0`````````````````` -M`/W___]&1S4``````````````````````````````````````/K___]&1S0` -M```````````````````!``$``````````````/C___]&1S,````````````` -M```````!``$````!``$``````/;___]&1S(````````````````````!```` -M`0`!``$``````//___]&1S$````````````````````!`````0`!`````0`` -M`/#___]&1S`````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M`````@````0````&````"`````H````,````#@```!````"L5`$`OD\!`*A0 -M`0!?4@$`R5(!`$]3`0#24P$````````````````````````````P````%8`` -M`!6````5@```%8```!6````<@```IX^-$L\/B`F5#^`$JP_@$L\/B`DHF``` -M`0`""@$``@H``0$%`0`""@$``@HTF```#@X```X.```.#@``#@X```X.```X -MF```!P````<````+````"P````L```!(F```6MH8`%K:&`!IRA@`:"TZ`W@M.@-X+3H#>"TZ`U8F```+@V`?BX-@'XN3>A^+DWH -M?BX-@'Y9C@```$D```"8F@``A@$` -M`(D```""TZ`W@M.@-X+3H#>"TZ`U8F```+@V`?BX-@'XN#>A^+@WH?BX-@'Y9C^UHAGOM:(9S[0B&<^ -MT(AG/M`,H@``0`$L9$`!+&1@P4)D8,%"9&#!0F0@`` -M`),```"8F@``N@```)0!``"P```'H```"LF@``NP```+H```"PF@``O`$``+L!``"T -MF@``_`$``/L!``"XF@``/````#L```"\F@``?````'L```#`F@``O````+L` -M``#$F@``_````+P!``#(F@``_````/P!``#,F@``_````#P```#0F@``_``` -M`'P```#4F@``_````+P```#8F@``_````/P```# -M9C8#DQ7F8W,6R8``"!L`P%@;`,!8&P#`6!L`P%@;`,!129 -M``#0!P``T`<``$P$``"8"```T`<``$29````$+CW`!"X]P`-N/<`$+CW`!"X -M]P2B``````````````````````````````BB``"(9[[6B&>^UHAG/M"(9S[0 -MB&<^T`RB``!``2P`0`$L`$#!0@!`P4(`0,%"`!RB```*@(,8"H"#&`J`8Q@* -M@(,8"H"#&#`2``#@`P``8(````\````8@0```````!R!````````(($````` -M```D@0```````"B!````````+($````````P@0```````#2!````````.($` -M```````\@0```````$"!``"H``"`1($````````(F````````"R8````H``` -M/)@````$(`!,F```/".$$G"8```?````=)@``(````!XF```#@```%B9``#_ -M````@)D```````"$F0````"``J"9````````X)D```````#DF0``JJJJJNB9 -M``!X9$8\[)D``*H```#PF0``#````/29``#_````^)D``!0````HH@``M0D` -M`#RB``"OB<8#DQ7F`Y -M,5Y@.3%LF```@;`,!8&P#`6!L`P%@;`,!8&P#`44F0``T`<``-`'``!,!``` -MF`@``-`'``!$F0```!"X]P`0N/<`#;CW`!"X]P`0N/<$H@`````````````` -M```````````````(H@``B&>^UHAGOM:(9S[0B&<^T(AG/M`,H@``X,$N`.#! -M+@`@P2H`(,$J`"#!*@`!MN3W@;;D]X&VY/>!MN -M3W@8HP``6GR/AEI\CX9:?(^&6GR/AEI\CX8/G\^C -MCY_/HX^?SZ,HHP``'Z]?M1^O7[4?KU^S'Z]?LQ^O7[,LHP``G[G?O9^YW[V? -MN=^[G[G?NY^YW[LPHP``/\5_RS_%?\L_QW_+/\=_RS_'?\LTHP``O]'_U;_1 -M_]6_T?_3O]'_T[_1_],`````````````````````,!(``.`#``!H0```$``` -M`&"````/````G(````````"@@````````!B!````````'($````````@@0`` -M`````"2!````````*($````````L@0```````#"!````````-($````````X -M@0```````#R!````````0($``/D#`(!$@0````````B8````````+)@```"@ -M```\F`````0@`$R8```\(X02<)@``!\```!TF```@````'B8```.````6)D` -M`/\?"`"`F0```````(29`````(`"H)D```````#@F0```````.29``"JJJJJ -MZ)D``'AD1CSLF0``J@```/"9```,````])D``/\```#XF0``%````"BB``"U -M"0``/*(``*^)R)-,H@```0```%"B````H```5*(```````!8H@``@%/'#%RB -M```!#P\/8*(```$/:5]DH@``$8I!`&BB````````;*(``&K!,`QPH@``(`B" -M`'2B``"J?!L(>*(``,XYYQQ\H@``S@$7!3BC````````/*,```````!`HP`` -M`````$2C````````2*,``/___S],HP``____/U"C``#___\_5*,``/__`P!8 -MHP``'ZJH>5RC```/0FP&8*,```*,``((&V%]\HP``@@3@?X"C``"Z>SQ_A*,` -M`/!_,/,$FP```0````B;```"````#)L```,````0FP``!````!2;```%```` -M&)L```@````)L``"@```!\FP`` -M*0```(";```J````A)L``"L```"(FP``+````)";```P````E)L``#$```"8 -MFP``,@```*";```T````I)L``#4```"HFP``-0```*R;```U````L)L``#4` -M``"TFP``-0```+B;```U````O)L``#4```#`FP``-0```,2;```U````R)L` -M`#4```#,FP``-0```-";```U````U)L``#4```#8FP``-0```-R;```U```` -MX)L``#4```#DFP``-0```.B;```U````[)L``#4```#PFP``-0```/2;```U -M````^)L``!````#\FP``&@````":``````````````2:``!`````0`````B: -M``"`````@`````R:``"A`0``80$``!":``#A`0``H0$``!2:```A````X0$` -M`!B:``!A````(0```!R:``"(`0``80```"":``#(`0``B`$``"2:```(```` -MR`$``"B:``!(````"````"R:``"(````2````#":``"I`0``B````#2:``#I -M`0``:0$``#B:```I````J0$``#R:``!I````Z0$``$":``#0`0``*0```$2: -M```0````:0```$B:``!0````D`$``$R:``"0````T`$``%":``"Q`0``$``` -M`%2:``#Q`0``4````%B:```Q````D````%R:``!Q````<0$``&":``"X`0`` -ML0$``&2:``#X`0``\0$``&B:```X````,0```&R:``!X````<0```'":``"9 -M`0``F`$``'2:``#9`0``V`$``'B:```9````&````'R:``!9````6````(": -M``"9````F````(2:``#9````>0$``(B:``#Y````N0$``(R:``#Y````^0$` -M`)":``#Y````.0```)2:``#Y````>0```)B:``#Y````N0```)R:``#Y```` -M^0```*":``#Y````^0```*2:``#Y````^0```*B:``#Y````^0```*R:``#Y -M````^0```+":``#Y````^0```+2:``#Y````^0```+B:``#Y````^0```+R: -M``#Y````^0```,":``#Y````^0```,2:``#Y````^0```,B:``#Y````^0`` -M`,R:``#Y````^0```-":``#Y````^0```-2:``#Y````^0```-B:``#Y```` -M^0```-R:``#Y````^0```.":``#Y````^0```.2:``#Y````^0```.B:``#Y -M````^0```.R:``#Y````^0```/":``#Y````^0```/2:``#Y````^0```/B: -M``#Y````^0```/R:``#Y````^0```-28```@````T)@```@````(````"``` -M``@````(````W)@``,``H`#``*``P`#@`,``X`#``.````````````"````W@```-X```#>````W@"``$````` -M`````````%@;``">`0,``0`````````!````6!L``*P!-P`!``````````$` -M``!8&P``I@$#``$``````````0```%@;``"V`3<``0`````````!````6!L` -M`+@!-P`!``````````$```!8&P``N@$W``$``````````0```%@;``"^`2$` -M`0````$````!````6!L``"<#`P`!``````````$```!8&P``R@%=``$````` -M`````````%@;``#6`3<``0`````````!````6!L``.0!$``!`````0````$` -M``!8&P``[`$P``$````!`````0```%@;``#X`0,``0`````````!````6!L` -M`!`"-P`!``````````$```!8&P``*@(B``$``````````0```%@;``!"`C<` -M`0`````````!````6!L````"6P`!``````````$```!8&P``2@(#``$````` -M`````0```%@;``!/`A```0````$````!````6!L``%P"4@`!``````````$` -M``!8&P``8`([``$````!`````0```%@;``!H`C<``0`````````!````6!L` -M`&P"-P`!``````````$```!8&P``=@(0``$````!`````0```%@;``!Z`@,` -M`0`````````!````6!L``(("`P`!``````````$```!8&P``@P(#``$````` -M`````0```%@;``"J`B$``0`````````!````6!L``+X"6P`!`````0````$` -M``!8&P``OP(W``$``````````0```%@;``#!`C<``0`````````!````6!L` -M`,8".P`!``````````$```!8&P``U`(W``$``````````0```%@;``#P`C<` -M`0`````````!````6!L``/0"-P`!``````````$```!8&P``^`(#``$````` -M`````0```%@;``">`%```0````$````!````6!L``/P"`P`!``````````$` -M``!8&P``#`,P``$``````````0```%@;```4`S8``0`````````!````6!L` -M`!@#-@`!``````````$```!8&P``)`,#``$``````````0```%@;```0`P,` -M`0`````````!````6!L``#H#-P`!``````````$```!8&P``2`,0``$````! -M`````0```,$6``!*`Q(``0````$````!````6!L``%H#$0`!``````````$` -M``!8&P``7`,Z``$````!`````0```%@;``!>`U8``0`````````!````6!L` -M`,`"`P`!``````````$```!8&P``=P,#``$``````````0```%@;``#,`@,` -M`0`````````!````6!L````````S$ST3%P`*!0``````````$``````````0 -M````1Q-1$Q<`"@4``````````!``````````$````#@3=!,7`!04```````` -M```0``````````<```!.$WL3&P8%!0```````````0``````````````41-Y -M$QX&"@4```````````$``````````````%83=!,A!A0%```````````!```` -M``````````"K$[`3%P`*!0``````````$``````````,````L!/8$Q<`%!0` -M`````````!```````````@```+\3OQ,7``H%```````````0``````````P` -M````%'@4!084%```````````````````````````,A1N%!<`%!0````````` -M`!@``````````0```#(4;A04`!04```````````8``````````$````\%'@4 -M#P`4%```````````!0``````````````/!1X%!$&%!0```````````$````` -M`````0```#P4>!02`!04```````````%```````````````\%'@4%``4%``` -M````````!0``````````````/!1X%!<`%!0```````````4````````````` -M`#P4>!07!A04```````````!```````````````\%,@4%`84%`(````````` -M!```````````````>!2@%!<`%!0!``````````4``````````````(P4H!07 -M`!04`P`````````%``````````````",%,@4$@`4%`,`````````!0`````` -M````````C!3(%!0`%!0'``````````6``````````````(P4R!04!A04`P`` -M```````!``````````(```",%,@4%P84%`,``````````0`````````"```` -MC!3(%!<&%!0#``````````$``````````````(P4R!0>`!04```````````` -M``````````````",%$06!084%`,`````````````````````````H!3(%!$& -M%!0#``````````$``````````````'P5]!4>!A04`@`````````$```````` -M``````!\%406%`84%`,``````````0`````````$````?!5$%AL`%!0#```` -M``````4``````````````'P51!8>`!04`P`````````%``````````````!\ -M%406%P`4%`<``````````8``````````````<1:M%A<`%!0````````````` -M`````````````'$6K18>!A04``````````````````````````!Q%JT6'@84 -M%`(`````````!```````````````<1;!%@4&%!0````````````````````` -M`````'$6P181`!04``````````````````````````!Q%L$6%``4%``````` -M````````````````````<1;!%AX`%!0``````````````````````````'$6 -MP18>!A04``````````````````````,```!Q%L$6'@84%``````````````` -M````````````.!-T$QX`%!0````````````$`````````````+`3V!,>`!04 -M````````````!``````````````R%&X4'@`4%`,```````````0````````` -M````/!1X%!X`%!0#```````````$`````````````(P4R!0>`!04`P`````` -M````!`````````````!Q%L$6'@`4%`````````````0`````````````?!5$ -M%AX`%!0#```````````$`````````````(P4R!0>`!04```````````````` -M```````````\%'@4'@`4%```````````````````````````P1;!%AX`%!0` -M```````````$````````````````````````````````````````"A1:%`4& -M*"@``````````````````````````((4TA0%!B@H`0`````````````````` -M``````#Z%'(5!08H*```````````````````````````FA42%@4&*"@!```` -M`````````````````````!X41A0%!B@H``````````````````````````!N -M%+X4!08H*`$`````````````````````````YA1>%04&*"@````````````` -M`````````````(85)A8%!B@H`0````````````````````````!0%'@4$08H -M*```````````````````````````4!1X%!<&*"@````````````````````` -M`````%H46A01!B@H``````````````````````````!:%%H4%P`H*``````` -M````````````````````H!2@%!<&*"@!``````````(``````````````*`4 -MH!04!B@H`0`````````"``````````````""%((4$0`H*`$``````````@`` -M````````````JA2J%!0`*"@!``````````(``````````````((4JA04`"@H -M`0`````````"``````````````""%*H4%P8H*`$``````````@`````````` -M````I!4<%A0&*"@!``````````(``````````````(`6J!84`"@H```````` -M``````````````````"`%J@6'@8H*```````````````````````````A1:M -M%AX&*"@``````````````````````````%H4@A0/`"@H`P``````````!``` -M``````````"J%*H4$@`H*`,```````````0`````````````I!4<%A0`*"@# -M```````````$`````````````(`6J!84`"@H````````````!``````````` -M``````````````@)1`D%!A0%```````````````````````````("40)%``4 -M!0``````````````````````````;`FH"04&%`4````````````````````` -M`````&P)J`D4`!0%```````````@``````````````!L":@)'@`4!0`````` -M````````````````````;`F>"1L&%`4``````````````````````````&P) -MG@D4`!0%```````````@``````````````"`"8H)%``4!0`````````````` -M````````````F0FH"10`%`4``````````````````````````*,)J`D4`!0% -M```````````@(`````````````"T";0)!084!0`````````````````````` -M````M`FT"10`%`4``````````"`H`````````````-`)K`H%!A0%```````` -M```````````````````("40)%``4!0``````````````````````````;`EL -M"10`%`4``````````````````````````'$)@`D4`!0%```````````````` -M``````````"%"8H)%``4!0``````````````````````````CPF9"10`%`4` -M`````````````````````````)X)G@D4`!0%```````````````````````` -M``"C":,)%``4!0````````````0``````(``````HPFC"10`%`4````````` -M``````````"``````*@)J`D4`!0%````````````!```````@`````"H":@) -M%``4!0```````````````````(``````M`FT"10`%`4````````````$```` -M``"``````+0)M`D4`!0%````````````````````@```````````"`E$"04& -M%`4```````````````````````````@)1`D4`!0%```````````````````` -M``````!L":@)!084!0``````````````````````````;`FH"10`%`4````` -M`````$```````````````&P)J`D>`!0%``````````````````````````!L -M"9X)&P84!0``````````````````````````;`F>"10`%`4``````````$`` -M`````````````(`)B@D4`!0%``````````````````````````"9":@)%``4 -M!0``````````````````````````T`FL"@4&%`4````````````````````` -M`````*,)J`D4`!0%```````````@(``````````````("40)%``4!0`````` -M````````````````````;`EL"10`%`4``````````````````````````'$) -M@`D4`!0%``````````````````````````"%"8H)%``4!0`````````````` -M````````````CPF9"10`%`4``````````````````````````)X)G@D4`!0% -M``````````````````````````"C":,)%``4!0````````````0``````(`` -M````HPFC"10`%`4```````````````````"``````*@)J`D4`!0%```````` -M````!```````@`````"H":@)%``4!0```````````````````(`````````` -M```````````````````````("40)!08H*``````````````````````````` -MA0F%"04&*"@``````````````````````````(4)A0D4!B@H```````````` -M``````````````"%"84)$@8H*`````````````0`````````````T`FL"@4& -M*"@`````````````````````````````````````````````````````_P$0 -M``$```````````````````````````(`""```````````````/\````````` -M````````````$20`````````````````!10```````````````````4"```` -M```````````````3````````````````````4`$0```````````````````` -M```````````````!```````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````4`(0``````````````````````````````````0````` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````````````````````````4`,0 -M````````````````````````````````$`@````````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````4`00```````````````````` -M`````````(```(`````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````4`40`````````````````````````````````$`````` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````````````````````````4`8P -M``(``````````P```````````````(!``(`````````````````("0`````` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````4`@P```````````````````` -M```#````````!``!```````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````4`DP``(`````````!``````````#```````$(!`````` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````````````````````````,`$P -M``(`````````!``````````#``````!`@```"``````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````,`(P``(`````````!``````` -M```#`````$`````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````,`,P``(`````````!``````````#``````!`````"``` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````````````````````````,`0P -M``(`````````!``````````#`````$`@```````````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````,`4P``(`````````!``````` -M```#`````!`````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````,`8P``(`````````!``````````#```````1``$````` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````````````````````````$`$0 -M`````````````````````````````"```0`"```````````````$$@`````` -M````````````$2`````````````````````````````````````````````` -M````````````````````````````````````(`$0```````````````````` -M```````````"`@`$````````````````````````````````````$B`````` -M```````````````````````````````````````````````````````````` -M````````````````8`$0``$``````````P```````````````""`0``"```` -M``````````#$$```````````````````(00````````````````````````` -M````````````````````````````````````````````````````````90$0 -M``$``````````P``````````````.``````````````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````0`%`````````````"``````` -M```"``````0````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````0`)`````````````$``````````"````QP4````````` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````````````````````````0`-` -M`````````````(`````````"`````(`````````````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````0`1```0``````````(`````` -M```"`````(!````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````0`5```0``````````(`````````"`````(!```(````` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````````````````````````0`9` -M````````````"``````````"`````(@````````````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````0`=```0`````````"(`````` -M```"`````(1````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````0`A```0`````````"(`````````"`````(1```(````` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````````````````````````0`E` -M`````````````(`````````"````QX$````````````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````0`M```0``````````(`````` -M```"````QX%````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````4`W_```````````````````````````````````````` -M````````````````````````````````````````````````````"@`````` -M``````````````H`````````````````````````````````````````,`K_ -M````````````@``````````#```````````````````````````````````` -M``````````````````````````````````$````````````````````!```` -M```````````````$````````````````````,`LP``````````````$````` -M```#```````````````````````````````````````````````````````` -M````````````@````````````````````(`````````````````````$```` -M````````````````,`PP``````````````(````````#```````````````` -M````````````````````````````````````````````````````$``````` -M`````````````!`````````````````````$````````````````````$`H0 -M```````````````````````````````````````````````````````````` -M````````````````````````````````(````````````````````"`````` -M```````````````$````````````````````0`I`````````````8'@````` -M```"```````````````````````````````````````````````````````` -M````````````0`H``````````````````$`$```````````````````$```` -M````````````````4`I````````````````````````````````````````` -M````````````````````````````````````````````````````"``````` -M``````````````@````````````````````$````````````````````F0$P -M```````````````````````````````````````````````````````````` -M````````````````````````````````"`````````````````````@````` -M```````````````$````````````````````8`#_``,```````````0````` -M```(``````````#@`P``````````````P`(````````````````````````` -M`````````````,"O``````````````````#P"P`````````````````(```` -M````````````````9@#_``,```````````0````````(``````````#@`P`` -M````````````P`(``````````````````````````````````````,`'```` -M``````````````#P`0`````````````````(````````````````````9P#_ -M``,```````````0````````(``````````#@`P``````````````P`(````` -M`````````````````````````````````,`O``````````````````#P"P`` -M```````````````(````````````````````:`#_``,```````````0````` -M```(``````````#@`P``````````````P`(````````````````````````` -M`````````````,!7``````````````````#P%0`````````````````(```` -M````````````````80#_``,```````````0````````0``````````#@`P`` -M`````````````````````````````````````````````````````,"O```` -M``````````````#P"P`````````````````(````````````````````8@#_ -M``,```````````0````````0``````````#@`P``````````````P`(````` -M`````````````````````````````````,"O``````````````````#P"P`` -M```````````````(````````````````````8P#_``,```````````0````` -M```(``````````#@`0``````````````P`(````````````````````````` -M`````````````,`O``````````````````#P"P`````````````````(```` -M````````````````9`#_``,```````````0````````0``````````@`'``` -M````````````P`(``````````````````````````````````````,`'```` -M``````````````#P`0`````````````````(````````````````````90#_ -M``,```````````0````````0``````````"$"``````````````````````` -M`````````````````````````````````,!7``````````````````#P%0`` -M```````````````(````````````````````:0#_``,```````````0````` -M```0``````````#``P``````````````P`(````````````````````````` -M`````````````,`'``````````````````#P`0`````````````````(```` -M````````````````:@#_``,```````````0````````0``````````#``P`` -M`````````````````````````````````````````````````````,`O```` -M``````````````#P"P`````````````````(````````````````````F`'_ -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M``````````````````````````````````````````````!``/``\P"(@?`` -M\P!!`(``@P")@8``@P!(`/(`]0"*@?(`]0!#`/8`]P"+@?8`]P!*`/$`]`", -M@?$`]`!+`($`A`"-@8$`A`!,`((`A0"/@8(`A0````````````````"(`?`` -M\P")`8``@P"*`?(`]0"+`?8`]P",`?$`]`"-`8$`A`"/`8(`A0`````````` -M````````````````````"``````````````````````````````````````` -M`````````0)P%PL`C````````0(H(P\`$@```````0+@+@H`F`(``````0)0 -M1@X`)`(``````0+`70D`L`0``````0*@C`T`2`0``````0*`NP@`8`0````` -M`0+PT@P`;`0````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M``````````````````@````````````````````````````````````````` -M``````$#'0`+G)E;"YR;V1A=&$`+G)O9&%T82YS='(Q+C$`+G)E;"YD -M871A`"YB&0``'0````2``$`+0```"P3 -M`0`F`@``$@`!`#@```#,T@``-0```!(``0!#````V!T!`$@!```2``$`3@`` -M`$A:``#P````$@`!`%D```!D60$`Y````!(``0!D````0#D``*0!```1``8` -M;P```-`"`0`C````$@`!`'H```!@7```+P```!(``0"%````R$X``-\````2 -M``$`D````.!)``"D`0``$0`&`)L```"(]P``)0```!(``0"F````9/,``!,` -M```2``$`L0```)SI```,````$@`!`+P````(T@``O@```!(``0#'````<-T` -M`.4````2``$`T@```,@*``":````$@`!`-T```"DQ@``D@```!(``0#H```` -MY*\``*`````2``$`\P```+29``!4````$@`!`/X```#8G0``"P```!(``0`) -M`0``@((``"4````2``$`%`$``,3Z```L````$@`!`!\!``"0T0``!@```!(` -M`0`J`0``_.8``!<````2``$`-0$``%05`0![````$@`!`$`!``"````!(``0#<`@``S%(` -M`.`%```2``$`YP(```R;```R````$@`!`/("``#(\0``,0```!(``0#]`@`` -MP`(``%,````2``$`"`,``$ST```@````$@`!`!,#``",.@$`"@$``!(``0`> -M`P``%.8``"P````2``$`*0,``*0<`0!_````$@`!`#0#```\8P``&0```!(` -M`0`_`P``?)$``)L````2``$`2@,``("5``!;````$@`!`%4#``#X?0``(0`` -M`!(``0!@`P``($`!`(@````2``$`:P,``,AS```>`@``$@`!`'8#```D9@`` -M`0```!(``0"!`P``J$`!`$@````2``$`C`,``$B````U`@``$@`!`)<#``!0 -M`0``60$``!(``0"F`P``%"L!``8#```2``$`L0,``%0!`0#T````$@`!`+P# -M``#4F@``$0```!(``0#'`P``\#T!`(0!```2``$`T@,``-3Y``#O````$@`! -M`-T#``!4`@$`#P```!(``0#H`P``K`(``!0````2``$`\P,``+"7```.```` -M$@`!`/X#``!0R@``TP```!(``0`)!```V,D``#D````2``$`%`0``'2I``!3 -M````$@`!`!\$``"L6```$````!(``0`J!```6&,``#<````2``$`-00``$`# -M``#$`0``$@`!`$L$``"P&P$`(0```!(``0!6!```X(4``)H````2``$`800` -M`%AD```@````$@`!`&P$``#`CP``%@```!(``0!W!```T!4!`!(````2``$` -M@@0``,RW```J````$@`!`(T$``!@ZP``[@,``!(``0"8!```B.@```L````2 -M``$`HP0``"Q=``"(````$@`!`*X$``"4C@``.````!(``0"Y!```0$\!`#T` -M```2``$`Q`0``-SI``#X````$@`!`,\$``"XF@```0```!(``0#:!```,&$` -M`&4````2``$`Y00``"S)```4````$@`!`/`$``#`U0``5`<``!(``0#[!``` -M2#T!`*8````2``$`!@4``%SS```&````$@`!`!$%``!TE```(0```!(``0`< -M!0``;`,!`%<````2``$`)P4``*1^```&````$@`!`#(%```<20$`/0$``!(` -M`0`]!0``5)\``$4````2``$`2`4``#1@```_````$@`!`%,%``#@]0``(P`` -M`!(``0!>!0``%-T``%L````2``$`:04``!C0```?````$@`!`'0%```L30$` -M/@```!(``0!_!0`````````````0````C`4``.A_``!@````$@`!`)<%``!< -M:@``10```!(``0"B!0``T$H!``P````2``$`K04``-1-`0`+````$@`!`+@% -M```P\@``=P```!(``0##!0``8`4```@"```2``$`U`4``'!#`0"J`P``$@`! -M`-\%``"T8P``1````!(``0#J!0``&(0``(\````2``$`]04``*R:```!```` -M$@`!```&``!X\P``$0```!(``0`+!@``2%H!`'$````2``$`%@8``-1I``!7 -M````$@`!`"$&```$XP``B0```!(``0`L!@``3)$``"\````2``$`-P8``("K -M``!<`0``$@`!`$(&```08``+#W```C`@``$@`!`(0&``"0F```7````!(``0"/!@``P)H``!,````2 -M``$`F@8``/#Z``#<`@``$@`!`*4&```X00$`3`$``!(``0"P!@``@$\!`#P% -M```2``$`NP8``$";```Z````$@`!`,8&``"`A@``#@```!(``0#1!@``O%L` -M``L````2``$`W`8``,R.``#S````$@`!`.<&```@\0``)P```!(``0#R!@`` -MO&8``"0````2``$`_08``)":`0#:````$@`!``@'```89@```0```!(``0`3 -M!P``I/,```L````2``$`'@<``.#R```X````$@`!`"D'``!@30``I`$``!$` -M!@`T!P``F-```&4````2``$`/P<``-1=`0!.````$@`!`$H'```@90``5``` -M`!(``0!5!P``])T```\````2``$`8`<``*1J```M`0``$@`!`&L'```,$P$` -M'@```!(``0!V!P``;.\``"$````2``$`@0<``$CQ``"`````$@`!`(P'```` -M3@$`/@$``!(``0"7!P``>'(``!0````2``$`H@<``+QH```/````$@`!`*T' -M``!`8@``M@```!(``0"X!P``/&H``!T````2``$`PP<``+CP``!H````$@`! -M`,X'``!,&`$`QP(``!(``0#9!P``M$"```-)8` -M`#,````2``$`Z0@``*!+``"D`0``$0`&`/0(```\`0$`%@```!(``0#_"``` -M%.0``#@````2``$`"@D``(2P``!1````$@`!`!4)``!D<@``%````!(``0`@ -M"0``#)D``'0````2``$`*PD``)3H```'`0``$@`!`#8)``!@1@``I`$``!$` -M!@!!"0```0``$@`!`)D)```< -M>```'P```!(``0"D"0``%`,!`%<````2``$`KPD``"!(``"D`0``$0`&`+H) -M```(E@``+````!(``0#%"0``_)8``(`````2``$`T`D``/AB```Q````$@`! -M`-L)```T1P$`'P```!(``0#F"0`````````````0````]0D``)C1```,```` -M$@`!```*``"0[P``'````!(``0`+"@``7%\``"$````2``$`%@H```#U```2 -M````$@`!`"$*``"DF@``!@```!(``0`L"@``7/```%D````2``$`-PH``(`^ -M``"D`0``$0`&`$(*```PGP``#@```!(``0!-"@``V(\``+H````2``$`6`H` -M`!P!```S````$@`!`&8*````.P``I`$``!$`!@!Q"@``V)X``%<````2``$` -M?`H``)20```+````$@`!`(<*```@````(````!$`!@"9"@``W&$``!L````2 -M``$`I`H``#1B```,````$@`!`*\*``"HZ0``,@```!(``0"Z"@``[&<``&@` -M```2``$`Q0H``/Q;`0#8`0``$@`!`-`*``!4:```%@```!(``0#;"@``H)D` -M`!(````2``$`Y@H``*`"`0`P````$@`!`/$*``#$30``R0```!(``0#\"@`` -M'$``!7````$@`!`!(+``"`F@``(P```!(``0`= -M"P``=`(!`"D````2``$`*`L``#C0```>````$@`!`#,+``#P0`$`2````!(` -M`0`^"P``@)D``"`````2``$`20L``"@J`0"U````$@`!`%0+``"@D```H@`` -M`!(``0!?"P``I-$``&$````2``$`:@L``$!```"D`0``$0`&`'4+```L:0`` -M%P```!(``0"`"P``X$T!`"`````2``$`BPL``%!;``!I````$@`!`)8+``!L -M:```0P```!(``0"A"P``!,P``/D#```2``$`K`L``&!F``!;````$@`!`+<+ -M```,90``$@```!(``0#""P``3.0``$`!```2``$`S0L``'0_`0"I````$@`! -M`-@+``!`GP``$@```!(``0#C"P``D$X``#<````2``$`[@L``)CF``!B```` -M$@`!`/D+``#,#0``;P```!(``0`$#```<`@``%<"```2``$`#PP``.CE```J -M````$@`!`!H,``!T90``>````!(``0`E#```L&@```L````2``$`,`P``.PX -M`0!V````$@`!`#L,``"L8```+````!(``0!&#```X"H!`#0````2``$`40P` -M`,P_```L````$@`!`%P,```$!0``6@```!(``0!G#```(/```#L````2``$` -M<@P`````````````$````((,``#XMP``A`$``!(``0"-#```.%L``!8````2 -M``$`F`P``%Q*`0!T````$@`!`*,,```,80``)````!(``0"N#```U.H``(P` -M```2``$`N0P``$R8``!$````$@`!`,0,````T0``C@```!(``0#/#``````` -M```````0````[PP``.0'``"*````$@`!`/H,``"@7P``30```!(``0`%#0`` -M\%\``#L````2``$`$`T``%"5```O````$@`!`!L-``"07```FP```!(``0`F -M#0``U)8``"<````2``$`,0T``+C>```3!```$@`!`#P-``#HF@``%0```!(` -M`0!'#0``?`0!`"$!```2``$`4@T``!!F```&````$@`!`%T-``!`7P``'``` -M`!(``0!H#0``+&(```8````2``$`#P``M&T!`+H````2``$`Z0\``.QE```C```` -M$@`!`/0/``"H3P``)P```!(``0#_#P``@$8``$$'```2``$`%1```,0#`0`G -M````$@`!`"`0``!\:0``5P```!(``0`K$```H`4!``(-```2``$`-A```!3G -M``!S`0``$@`!`$$0``!8T```/0```!(``0!,$```2)X``!<````2``$`5Q`` -M`/2"``!]````$@`!`&(0``!0/P``?````!(``0!M$```<(4```P````2``$` -M>!```(QR``!S````$@`!`(,0```$G@``*0```!(``0".$```8*D``!(````2 -M``$`F1```*!9``!M````$@`!`*00``!\A@```0```!(``0"O$```^&,``&`` -M```2``$`NA```+C%```_````$@`!`,40``#4``$`:````!(``0#0$```&/,` -M`$0````2``$`VQ```-R7```W````$@`!`.80``#HA@``B@0``!(``0#Q$``` -MX'H``+D"```2``$`_!```(SS```5````$@`!``<1````T```%@```!(``0`2 -M$0``3(````$@`!`$D1``#,C0``1@`` -M`!(``0!4$0``D.,``(,````2``$`7Q$``"Q@```&````$@`!`&H1````FP`` -M"P```!(``0!U$0``Y(,``#,````2``$`@!$``/SQ```.````$@`!`(L1``!` -M,P$`XP```!(``0"6$0``R*D``+@!```2``$`H1$``+A!``!A````$@`!`+H1 -M``!T1P$`/0```!(``0``>GHP,#5B-3@T-@!Z>C`P,F1B,3%C`'IZ,#)D8F8X -M-S4`>GHP,F1B8C%B,@!Z>C`R9&(R,#4S`'IZ,#`R9&)A-#(`>GHP9F)B,64S -M9@!Z>C!B-SEE83DT`'IZ,#5B.&,V-6$`>GHP,#5B-#!A9`!Z>C`U8CDT,F5D -M`'IZ,&0X9&,V,F,`>GHP,#$Y9C0W,`!Z>C`R9&0Y-#)D`'IZ,#)D8F4W,V0` -M>GHP,#5B-CDR8@!Z>C!B-F0R,S(U`'IZ,#`U8C@U,V0`>GHP,#$V9#DR90!Z -M>C!C9F(Q.#GHP,F1A8F)A8P!Z>C`R9&)C.#4Q`'IZ -M,#`P8C9C-C@`>GHP,#!B-F)F.`!Z>C`P8C9C9C5E`'IZ,#$V93%D9F0`>GHP -M8C9F-3!B.`!Z>C`V93!A-&9E`'IZ,#`V-V0R8C$`>GHP,#)D8F,V,0!Z>C!B -M-F-A,S(U`'IZ,#`U8C9C9F0`>GHP,39E,&1F9`!Z>C`P,&(V9C8X`&%T:%]H -M86Q?<')O8V5SGHP,F1B9C%B,@!Z -M>C`P-6(X.&-B`'IZ,#,S96,X8F8`>GHP9&(T,C5C-0!A=&A?:&%L7V1M85]B -M96%C;VY?C`P8C9F,38Q`'IZ,#9E,#!B.&$`>GHP -M,F1B9F,Q9`!Z>C!D8S1E,SDP`'IZ,&1A9F5D.#8`>GHP,&(V93(W80!Z>C`R -M9&)B86(R`'IZ,&(V9#%E9F8`>GHP,39D.3!D9`!Z>C`R9&)E.#4Q`'IZ,#`U -M8C8T9F0`>GHP,#!B-F0U,@!Z>C!B-F,Y969F`'IZ,#$V93`P9&0`>GHP,F1B -M9#@W-0!Z>C`R9&(S,6(R`'IZ,#!B-S`Y,C,`>GHP,&(V9#0U,`!Z>C`P,&(V -M9#%D`'IZ,&(V8S(S,C4`>GHP,F1B9&%B,@!Z>C`P,#5B-C,R`'IZ,#9D961D -M.3,`>GHP,#$V9&$U,`!Z>C`P,#8W9#,R`'IZ,#!B-F0Y,C,`>GHP,#)D8C4Q -M8P!Z>C`Q-F1C8F9E`'IZ,#!B-S`Q-#4`>GHP,#$V9&8R8P!Z>C!B-V9A9#-E -M`'IZ,#$V9#DY,C``>GHP,F1B,6)A8P!Z>C!D8S9E,SDP`'IZ,#5B-S`Q93`` -M>GHP,#!B-F(Q,`!Z>C!B-S`Y969F`'IZ,#$V9&8X.6(`871H7VAA;%]A='1A -M8V@`>GHP-F4P9F,P9`!Z>C`Q-F1A8C)D`'IZ,#)D8C$S-60`>GHP93`T-C@T -M8@!Z>C`Q-F4R.3%D`'IZ,#`P8C9F93@`>GHP,&-F8C-E,`!Z>C`P,39D.30X -M`'IZ,#$V93(P.6(`>GHP8CC`P,&(V8SED`'IZ,#`P-6(U83(` -M>GHP,F1B,3'1I;64`>GHP,F1B-6)A8P!Z -M>C`P-6(X,3-D`'IZ,#!B-F,Y,C,`>GHP8C9B-3!B.`!Z>C`P-6(W9CED`'IZ -M,&(W,#%D,#(`>GHP-F1F9C0T80!Z>C`R9&(U-S8S`'IZ,#9E96%F-C``>GHP -M93`P-V-A,0!Z>C`P,F1A9C8R`'IZ,&(X,V%D,V4`>GHP,#!B-F(Y,`!Z>C`Q -M-F0Y969A`'IZ,#$V9&4P-3$`>GHP,#`U8C9B,@!Z>C`U8C=F,3$T`'IZ,#1A -M93`S,68`>GHP,F1B9&1F9`!Z>C`P-30W9F5D`'IZ,#!B-F)F-64`>GHP,&(W -M,3C`P8CGHP,F1B,6%B,@!Z>C`P,#5B -M-C(R`'IZ,#`P8C9F-S@`>GHP8C8Y8C`W8P!A=&A?:&%L7V9R964`>GHP-6(W -M.6(Q8@!Z>C`P8CGHP8C5E,S$U,@!Z>C`Q-F1F -M8F8Q`&%T:%]H86Q?;6AZ,FEE964`>GHP,39E,3@Y8@!Z>C!D8S)A-6,U`'IZ -M,#`R9&,V,&(`>GHP-F1F,&(X80!Z>C`R9&(S,S5D`'IZ,&(V8S4S830`>GHP -M9C4T9#%B,`!Z>C!B-F9D,S8S`'IZ,&0Y9&,V,F,`>GHP-6(W-#%E,`!Z>C`R -M9&$Y8F%C`'IZ,&1C,C%D,V$`>GHP,&(W,3C`Q-F0Y9#0Q`'IZ,#`U -M8C@T9F0`>GHP,#5B.&%B9`!Z>C`P8CGHP,F1B -M,S@W-0!Z>C`Q-F4S,#EB`'IZ,#`U8C8P8C(`>GHP,F1B,3@W-0!Z>C`P,F1B -M.#0R`'IZ,#)D8C$W-C,`>GHP8C=D96$Y-`!Z>C`P8CGHP,#$V8V0S,@!Z>C`V9&4P8CAA`'IZ,#9D.61D.3,`>GHP9&(S960X -M-@!Z>C`P-6(T.&5D`'IZ,#`R9&,X,&(`>GHP,#)D8F,T,@!Z>C`R9&)A.#4Q -M`'IZ,#)D8C,S960`>GHP,#5B.#!F9`!Z>C`P-6(W9C)E`'IZ,#)D8F9D9F0` -M>GHP,39E-C0X80!Z>C`P,F1A9F8R`'IZ,#`U8CGHP,#!B-F5E.`!Z -M>C`Q-F4T-#AA`'IZ,#!B-F8V8F,`>GHP,39D83DR,`!Z>C`U8CGHP,#5B-#1A9`!Z>C`V9&1F-#1A`'IZ,&9A8S!C.6(`>GHP -M8C9F.65F9@!Z>C`P8C9C-F)C`&%T:%]H86Q?861D:71I;VYA;%]S=V)A7V)A -M8VMO9F8`>GHP,#`R9&(Y,@!A=&A?:&%L7W9EGHP,F1B86,R90!Z -M>C`R9&(W.6%E`'IZ,#`Q-F4U,S(`>GHP8C9C9C`P.0!Z>C`P,39E,3)C`'IZ -M,#`Q-F0Y930`>GHP,#`R9&%E80!Z>C`P-6(U8V(R`'IZ,#$V9&$R-3$`>GHP -M-F8V868V,`!Z>C`V9&9D9#DS`&%T:%]H86Q?;6%L;&]C`'IZ,#`P8C9D9#(` -M>GHP,F1D.3)A9`!Z>C`Q-F1B,C4Q`'IZ,&4Q,#=C83$`>GHP,&(V8SC`Q-F1D,#4Q`'IZ,#)D8F0Q8C(`>GHP,F1C,3C!B-CDP9#9D`'IZ -M,#$V9&8P-3$`>GHP,#$V9#DU,`!Z>C`P8CGHP -M-F1E9C0T80!Z>C`U8CAC,F5D`'IZ,#9F8CDT-V(`>GHP96)B,64S9@!Z>C!B -M-F8Y9#`R`'IZ,&0Q-&0Q8C``>GHP8C0X,#,Q90!Z>C`Q-F1B8F9E`'IZ,#$V -M934T.&$`>GHP,#$V9#@U,`!Z>C`P,&(V9F8X`&%T:%]H86Q?;65M8W!Y`'IZ -M,#)D8F-B8F0`>GHP,39D83!D9`!Z>C`R9&)B9&9D`'IZ,#)D8C(X-3$`>GHP -M,F1B9&,Q9`!Z>C`V9&(P8V8R`'IZ,#$V96(Y860`>GHP,&(V8V5B8P!Z>C!D -M.30X-&$Q`&%T:%]H86Q?<')O8F4`>GHP,39E83EA9`!Z>C!F9#1D,6(P`'IZ -M,#)D8C,W-C,`871H7VAA;%]B=6EL9&]P=',`>GHP,F1A9C,U9`!Z>C`V9&1D -M9#DS`'IZ,&1A9&,V,F,`>GHP,39D9C(U,0!Z>C`P,&(V8S$P`'IZ,#$V9#DR -M-3$`>GHP,F1B,#@U,0!Z>C!B-S(Q865D`'IZ,#8W8V9C864`>GHP,#!B-F-F -M.`!Z>C!C.31D,6(P`'IZ,#)D869A8C(`>GHP-6(Y,F%E9`!Z>C`P-6(X8V-B -M`'IZ,&(V9#EE9F8`>GHP,F1B,3%B,@!Z>C`R9&)F9F(Q`'IZ,#)D8F8W-C,` -M>GHP,#5B-CAF9`!Z>C`P-6(T-&5D`'IZ,&(W,3%A960`>GHP8C5E,S$V,`!Z -M>C!D.#0X-&$Q`'IZ,#$V9#AB,F0`>GHP,39E,#@Y8@!Z>C`R9&)B.#GHP8C@Q96$Y-`!Z>C`Q-F1E8S%F`'IZ,#!B-F9E8F,`>GHP -M93@Y-#DP-P!Z>C`P8C9E83=A`'IZ,#,S93AF8F8`>GHP8V9A-3@W-0!Z>C`R -M9&(Y.6%E`'IZ,#)D8CEA8C(`>GHP,#!B-F)E.`!Z>C!D938X,S=F`'IZ,#$V -M9&%B9F4`>GHP8CC`V-V0R-64R`'IZ,#$Y9C-A,#$`>GHP-S`S -M.30W8@!A=&A?:&%L7VUE;7IEGHP-F1F9F,P9`!Z>C!B-CGHP,#!B-F0R,@!Z>C`V9F5A9C8P`'IZ,&1C-&$U8S4`>GHP -M,&(W,&8W9`!A=&A?:&%L7W-W7V)E86-O;E]R97-P;VYS95]T:6UE`'IZ,#EF -M-C1B-F$`>GHP,#5B-C4W80!Z>C`V9C,Y-#=B`'IZ,#9D83!C9C(`>GHP8C=B -M860S90!Z>C`P8C9F.38Q`'IZ,&(V.3GHP,F1B9#,U9`!Z>C`P-6(X -M.&9D`'IZ,#)D8F)C,60`>GHP,F1A9F1F9`!Z>C`V9#=D9#DS`&%T:%]H86Q? -M9&5L87D`>GHP,F1B,61F9`!Z>C`V-V0R9C0Q`'IZ,#)D868X-S4`>GHP8C=E -M9&4V9`!Z>C`Q-F0X9#0Q`'IZ,#`R9&%E.3(`>GHP8C=A9&4V9`!Z>C`R9&)B -M,S5D`'IZ,#)D8C-D9F0`>GHP,F1B-3-E9`!Z>C`Q-F1C96%E`'IZ,#`P8C9D -M83(`>GHP,#!B-F4R,@!Z>C`U8C@P,#0Q`'IZ,#`Q-F0X-#@`>GHP,39D.6(R -M9`!Z>C`P,39E,#)C`'IZ,#!B-S`W-V0`>GHP,#5B-CDW80!Z>C`P,39D864T -M`'IZ,#$V93$P.6(`>GHP,#5B-&$R9`!Z>C`Q-F1E,&1D`'IZ,#$V9&8P9&0` -M>GHP9&8P-V-A,0!Z>C`R9&)D-S8S`'IZ,#`P8C9E-3(`>GHP-C=D,&,T-P!Z -M>C`U8C9C-F1B`'IZ,&,S,35E8C4`>GHP9&(Q960X-@!Z>C`V9#0P-F4P`'IZ -M,#$V93`R-3$`>GHP,#`R9&)B,@!Z>C`P,F1D.#9D`'IZ,#`Q-F4Q-&0`>GHP -M,F1B-3EA90!Z>C`P-C=D,C(Q`'IZ,#$V9#@P9&0`>GHP,#5B.#DS9`!Z>C`U -M8C@Q8C%B`'IZ,#)D8C$S960`>GHP,&(V9#$R,P!Z>C`P,&(V8V4X`'IZ,#5B -M.&%A960`>GHP8C9E9#,V,P!Z>C`R9&%F,6(R`'IZ,#`P-6(U93(`>GHP,S-E -M8F9B9@!Z>C`U8C8X-F1B`'IZ,#`P8C9E9C@`>GHP8CC`P-6(U -M.&(R`'IZ,#5B-V1B,6(`>GHP8C@R9&4V9`!Z>C`P,39D-S,R`'IZ,#)D861A -M8C(`>GHP9C0U939E,P!A=&A?:&%L7VEN:71?8VAA;FYE;',`>GHP,&(V9#9B -M8P!Z>C!C,31D,6(P`'IZ,#`P,F1B9#(`>GHP9&$T.#1A,0!Z>C`Q-F4P8C@W -M`'IZ,#5B.3`R960`>GHP9&,R93,Y,`!Z>C!A-C!D,30U`'IZ,#)D8F%B8F0` -M>GHP,#!B-F,Q9`!Z>C`U8CAE865D`'IZ,#`U8C=B.60`>GHP,#5B-30T-@!Z -M>C`U8C8T-F1B`'IZ,#!B-F8Y,C,`>GHP9&0V.#,W9@!Z>C`Q-F4Q,C4Q`'IZ -M,&1C-F$U8S4`>GHP,F1B,SC`P,#5B-CGHP -M,F1B9C,U9`!Z>C`P,&(V8SGHP,F1B-3C`P -M-6(V9#=A`'IZ,#`R9&(R.3(`>GHP,#5B.3!C8@!Z>C!B-F8U,S8S`'IZ,#`U -M8C5C-#8`>GHP-F0Y,&-F,@!Z>C`V9#AD9#DS`'IZ,#$V9&9B.#<`>GHP,#$V -M9&$T.`!Z>C!B-C8S,6$X`'IZ,#`R9&(P.3(`871H7VAA;%]G971W:7)E;&5S -M40```$$``#I1````00``/U$```!!```!44```$$``!S2````0(``'M( -M```!`@``.4D```$$``!J20```00``)A)```!!```R4D```$$``#W20```00` -M`"5*```!!```94L```(?`0"93````0(``+Y,```!`0``F4X```+\``!O3P`` -M`OP``+%/```"_```H%$```$$``"R40```00``+]1```!!```)%(```$$```V -M4@```00``$-2```!!```XU(```+,```$4P```0(```I3```"Y0``DE,```(Z -M`0`25````BX``$!4```"*0$`@```0(``/IZ```"Y0``!'L```$"```.>P`` -M`N4``&M[```"+@``DWL```(N```7?0```BX``#-]```"+@``3'T```(N``#' -M?0```BX``$1^```"20``97X```(T`0!K?@```E$``.%^```"90$`'7\```(4 -M`0"7?P```A\!`-9_```"O```_X(```*@```0@P```DX!`$*#```"3@$`7X,` -M``).`0!AA````C0!`)&$```"20``WX8```(N``#YA@```LP``!J'```!`@`` -M((<```+E``"?AP```I,!`.&'```"-`$`=H@```(T`0"QB````D7```"Y0``K)@```(D``#+F````EH!``29```")```'ID` -M``(D``!4F0```EH!`)B9```")```&IH```(D``!0F@```EH!`)N:```")``` -M,YL```+=``!OFP```A4!`+N;```"&@``Y)L```(V`0`>G````C0!`$6<```" -M-`$`H9T```&Y``"IG0```0Y```!!0``S[D```$%``#>N0```04``.6Y```!!0``[KD` -M``$%``#\N0```04``!2Z```!!0``*[H```$%```XN@```04``$FZ```!!0`` -M;;H```$%``"0N@```04``)ZZ```!!0``J+H```$%```9NP```04``%J[```! -M!0``WKL```$%``#LNP```04``!*\```!!0``-;P```$%``!-O````04``%*\ -M```!!0``>[P```$%``"`O````04``/Z\```!!0``1[T```(2`0!_OP```0(` -M`+O````!`@``J\$```)K``#$Q0```0(``-K%```!`@``=\<```$"``"ZQP`` -M`0(``,W'```!`@``]L<```$"```0R````0(``#+(```!`@``1<@```$"``!, -MR0```O(``%W)```"!0$`FLD```(%`0#&R0```@4!``7*```"90$`0S@```3```*[.```!O@``O]`` -M``)T`0#0T````C0!`-O3```"+@``_-,```$"```-U````0(``!K4```!`@`` -M)]0```$"``!MU````K$``*?4```!`@``K=0```+E``!=U0```0(``&G5```" -MY0``D=4```$"``"9U0```0(``*'5```!`@``U=4```+,```*U@```B4``!G6 -M```"@`$`@]8```**`0#9U@```AD``"'7```"0@``4]@```*)`0#IV````HD! -M`!G9```"B0$`7MD```*)`0"MV0```HD!`!;:```!`@``&]H```$"``!DV@`` -M`G]P```*) -M`0#UW````G\``![=```"<```0=T```)#``!.W0```H`!`%[=```"'`$`9MT` -M``*"``!!W@```C0!`-GB```"J@``]N(```&+`0#_X@```0$``%'C```"J@`` -MU.,```$P``#CXP```24```))``#PY@```M0``+#K```! -M`@``D.T```(D`0`U[P```B0!`&3O```"Y0``@.\```+E``"D[P```N4``,+O -M```"Y0``//$```$"``!C\0```N4``-?S```"#0``"/0```(D```K]````EH! -M`&3T```")```?O0```(D``"T]````EH!`/CT```")```>O4```(D``"P]0`` -M`EH!`/OU```")```E_8```):`0!_]P```B,``+OW```"%0``W_D```(5``#5 -M^@```0(``-SZ```!`@``Z_H```$"```7^P```0(``&_]```"A@``B?T```$" -M``#!_0```A4!`/?]```!`@``2/\```$"``!._P```IT``(3_```"&@``L/\` -M``(V`0#J_P```C0!``X``0`"-`$`O0$!``$K``#7`0$``=4``.L!`0`!X``` -M]0$!``&H``#]`0$``4H!``4"`0`!S@``#`(!``$4```5`@$``5P8!``+'``"&!@$``MD` -M``,'`0`""P``;@5@$``IT``'A6`0`"G0``AU8!``(=`0"E5@$``IT``+M6`0`" -MG0```%`0`!`@``5UX! -M``$"``!N7@$``C0!`(I>`0`!`@``D5X!``$"``"D7@$``C0!`,%>`0`!`@`` -MREX!``$"``#=7@$``C0!``Y?`0`"B```*E\!``$"```W7P$``BX``$A?`0`! -M`@``J%\!``(N``#67P$``BX``%9@`0`!`@``)V,!``$"``!<8P$``G8``&]C -M`0`"=@``A6,!``$"``"?8P$``C0!`+EC`0`!`@``P&,!``$"``#68P$``C0! -M`/-C`0`!`@``_6,!``$"```39`$``C0!`#!D`0`!`@``.F0!``$"``!09`$` -M`C0!`&5D`0`!`@``L60!``)V``#,9`$``G8``.AD`0`"=@``_60!``)V```2 -M90$``G8``"=E`0`"=@``/64!``$"``!790$``C0!`'%E`0`!`@``H&4!``)V -M``"U90$``G8``/QE`0`"=@``#&8!``)V```=9@$``G8``#5F`0`!`@``3V8! -M``(T`0`1:`$``A\!`#IK`0`"5`$`&FT!``)4`0!#;0$``H(``&=M`0`"@@`` -MF6T!``$"``"@;0$``0(``*]M`0`!`@``QVT!``+,``#W;0$``LP``!9N`0`! -M`0``(&X!``$!```J;@$``0$``#1N`0`!`0``/FX!``$!``!(;@$``0$``%)N -M`0`!`0``7&X!``$!``"1;@$``0(``*-N`0`!`@``NFX!``(T`0#6;@$``0(` -M`-UN`0`!`@``\&X!``(T`0`-;P$``0(``!9O`0`!`@``*6\!``(T`0#V;P$` -M`BX``'QP`0`"+@``BG`!``(N``#8<`$``BX``.9P`0`"+@``+'$!``(N```Z -M<0$``BX``()Q`0`"+@``D'$!``(N``#^<0$``0(``")T`0`!`@``.G0!``$" -M``!9=`$``0(``'AT`0`!`@``I'0!``)V``"^=`$``G8``-ET`0`"=@``"'4! -M``)V```F=0$``G8``$1U`0`"=@``8G4!``)V``"`=0$``G8``)YU`0`"=@`` -MQG4!``)V``#>=0$``G8``/YU`0`"=@``%G8!``)V``!M=@$``G8``'YV`0`" -M=@``CW8!``)V``"C=@$``G8``,MV`0`"=@``W'8!``)V``#M=@$``G8```%W -M`0`"=@``%7`$``C0!`"1X`0`!`@``/G@!``(T`0!:>`$` -M`0(``'1X`0`"-`$`D7@!``$"``"K>`$``C0!`,UX`0`!`@``ZG@!``(T`0`V -M>P$``N4``$M[`0`"Y0``GGL!``+E``#1>P$``N4``.9[`0`"Y0``.7P!``+E -M``!D?`$``N4``'E\`0`"Y0``S'P!``+E``#G@P$``H(```N$`0`"@@``7X;`0`"-`$`!9P!``$"```0G`$``0(` -M`":<`0`"-`$`]IP!``(N``!\G0$``BX``(J=`0`"+@``V)T!``(N``#FG0$` -M`BX``"R>`0`"+@``.IX!``(N``""G@$``BX``)">`0`"+@``EJ`!``$"``"N -MH`$``0(``,V@`0`!`@``[*`!``$"```HH0$``G8``$"A`0`"=@``5*$!``)V -M``"(H0$``BX``)6A`0`"=@``M:$!``)V``#-H0$``G8``-^A`0`!`@``!*(! -M``$"```=H@$``C0!`#6B`0`!`@``3Z(!``(T`0!GH@$``0(``(&B`0`"-`$` -MF:(!``$"``"SH@$``C0!`-"B`0`!`@``[:(!``(T`0`NHP$``0(``.NK`0`" -M@@``#ZP!``*"```SK`$``H(``*.O`0`"S```TZ\!``+,``#UKP$``LP``!2P -M`0`!`0``'K`!``$!```HL`$``0$``#*P`0`!`0``/+`!``$!``!&L`$``0$` -M`%"P`0`!`0``6K`!``$@```(`````0$```P````!`0``$`````$!```4```` -M`0$``!@````!`0``'`````$!```@`````0$``"0````!`0``*`````$!```L -M`````0$``#`````!`0``-`````$!```X`````0$``#P````!`0``0`````$! -M``!$`````0$``$@````!`0``3`````$!``!0`````0$``%0````!`0``6``` -M``$!``!<`````0$``&`````!`0``9`````$!``!H`````0$``&P````!`0`` -M<`````$!``!T`````0$``'@````!`0``?`````$!``"``````0$``(0````! -M`0``B`````$!``",`````0$``)`````!`0``2`$```$+`0!,`0```6,``%`! -M```!OP``5`$```&R``!8`0```7D!`%P!```!T@``8`$```%3``!D`0```=X` -M`&@!```!GP``;`$```%V`0!P`0```4D!`'0!```!O```>`$```$]``!\`0`` -M`8,``(`!```!5@``A`$```$?``"(`0```6P$`F!<```%B``"<%P```70``*`7```!D@``I!<```%K``"H -M%P```0P``*P7```!-```L!<```%@``"T%P```6$``+@7```!.```O!<```%J -M`0#`%P```0P!`,07```!A@$`R!<```&```#,%P```70!`-`7```!`0$`U!<` -M``&I``#8%P```28!`-P7```!(0``X!<```$&`0#D%P```1@``.@7```!9@$` -M[!<```'F``#P%P```1X``/07```!*0``^!<```&L``#\%P```7H!```8```! -M:`$`!!@```%U`0`(&````3@!``P8```!\0``$!@```'^```4&````>T``!@8 -M```!$0$`'!@```%\```@&````9<``"08```!<@``*!@```%(`0`L&````9X` -M`#`8```!/P``-!@```$Y`0`X&````34!`#P8```!>```0!@```$Y``!$&``` -M`4P!`$@8```!W```3!@```$M`0!0&````>(``%08```!P@``6!@```'A``!< -M&````4`!`&`8```!S0``9!@```$V``!H&````5\``&P8```!UP``H``+08```! -MC```N!@```$F``"\&````4\``,`8```!D0``Q!@```':``#(&````X``/`8```!\@``]!@```$%`0#X&``` -M`0$``/P8```!*P$``!D```%'`0`(&0```<(```P9```!X0``$!D```%``0`4 -M&0```0``&PW -M```!E0$`<#<```&+`0!T-P```;@``'@W```!>P``?#<```$B`0"`-P```2<` -M`(0W```!7`$`B#<```%1`0",-P```84``)`W```!8`$`E#<```%=``"8-P`` -M`3X!`)PW```!``$`H#<```'[``"D-P```1$``*@W```!:P$`K#<```%Y``"P -M-P```=\``+0W```!<`$`N#<```'8``"\-P```94``,`W```!,`$`Q#<```'X -M``#(-P```0\``,PW```!FP``T#<```$)``#4-P```98``-@W```!/0$`W#<` -M``&O``#@-P```><``.0W```!/@``Z#<```$>`0#L-P```:(``/`W```!L``` -M]#<```$6`0#X-P```4P``/PW```!00$``#@```%/`0`$.````1,!``@X```! -MD0$`##@```%(```0.````<4``!0X```!IP``&#@```&!`0`<.````4L``"`X -M```!C0``)#@```&%`0`H.````:8``"PX```!RP``,#@```%!```T.````4H` -M`#@X```!+```/#@```%```!`.````3H``$0X```!Z0``2#@```%%``!,.``` -M`7X``%`X```!,P``5#@```$R``!8.````1<``%PX```!<0``8#@```'V``!D -M.````6P``&@X```!)`$`;#@```&``0!P.````<\``'0X```!4`$`>#@```&0 -M``!\.````8T!`(`X```!#P$`A#@```'0``"(.````2(``(PX```!&(```$!``!\8@```0$``(!B```!`0``A&(```$!``#8;@```0$``-QN```! -M`0``X&X```$!``#D;@```0$``.AN```!`0``[&X```$!``#P;@```0$``/1N -M```!`0``"'L```$!```,>P```0$``!![```!`0``%'L```$!```8>P```0$` -M`!Q[```!`0``('L```$!```D>P```0$``"B)```!`0``+(D```$!```PB0`` -M`0$``#2)```!`0``.(D```$!```\B0```0$``$")```!`0``1(D```$!```@ -M`````0,``"0````!`P``*`````$#```L`````0,``#`````!`P``-`````$# -*```X`````0,````` -` -end diff --git a/sys/contrib/dev/ath/public/i386-elf.inc b/sys/contrib/dev/ath/public/i386-elf.inc deleted file mode 100644 index 977a465218..0000000000 --- a/sys/contrib/dev/ath/public/i386-elf.inc +++ /dev/null @@ -1,58 +0,0 @@ -# -# Copyright (c) 2002-2006 Sam Leffler, Errno Consulting -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer, -# without modification. -# 2. Redistributions in binary form must reproduce at minimum a disclaimer -# similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any -# redistribution must be conditioned upon including a substantially -# similar Disclaimer requirement for further binary redistribution. -# 3. Neither the names of the above-listed copyright holders nor the names -# of any contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# Alternatively, this software may be distributed under the terms of the -# GNU General Public License ("GPL") version 2 as published by the Free -# Software Foundation. -# -# NO WARRANTY -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY -# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -# THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, -# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -# THE POSSIBILITY OF SUCH DAMAGES. -# -# $Id: //depot/sw/branches/sam_hal/public/i386-elf.inc#1 $ -# - -# -# Compilation configuration for building i386-elf. -# This assumes the build platform is also i386-elf. -# - -# -ifndef TOOLPREFIX -TOOLPREFIX= -endif -# -CC= ${TOOLPREFIX}gcc -LD= ${TOOLPREFIX}ld -STRIP= ${TOOLPREFIX}strip -OBJCOPY=${TOOLPREFIX}objcopy -NM= ${TOOLPREFIX}nm - -COPTS+= -DAH_BYTE_ORDER=AH_LITTLE_ENDIAN -ifndef CONFIG_FRAME_POINTER -COPTS+= -fomit-frame-pointer -endif diff --git a/sys/contrib/dev/ath/public/i386-elf.opt_ah.h b/sys/contrib/dev/ath/public/i386-elf.opt_ah.h deleted file mode 100644 index de94323995..0000000000 --- a/sys/contrib/dev/ath/public/i386-elf.opt_ah.h +++ /dev/null @@ -1,7 +0,0 @@ -#define AH_SUPPORT_AR5210 1 -#define AH_SUPPORT_AR5211 1 -#define AH_SUPPORT_AR5212 1 -#define AH_SUPPORT_5111 1 -#define AH_SUPPORT_5112 1 -#define AH_SUPPORT_2413 1 -#define AH_SUPPORT_5413 1 diff --git a/sys/contrib/dev/ath/version.h b/sys/contrib/dev/ath/version.h deleted file mode 100644 index 508eb898a8..0000000000 --- a/sys/contrib/dev/ath/version.h +++ /dev/null @@ -1,38 +0,0 @@ -/*- - * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/sw/branches/sam_hal/version.h#35 $ - */ -#define ATH_HAL_VERSION "0.9.20.3" diff --git a/sys/cpu/amd64/include/int_const.h b/sys/cpu/amd64/include/int_const.h new file mode 100644 index 0000000000..2efe6ba9f0 --- /dev/null +++ b/sys/cpu/amd64/include/int_const.h @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2001, 2002 Mike Barcroft + * Copyright (c) 2001 The NetBSD Foundation, Inc. All rights reserved. + * Copyright (c) 1990, 1993 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Klaus Klein. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _CPU_INT_CONST_H_ +#define _CPU_INT_CONST_H_ + +#define INT8_C(c) (c) +#define INT16_C(c) (c) +#define INT32_C(c) (c) +#define INT64_C(c) (c ## LL) + +#define UINT8_C(c) (c) +#define UINT16_C(c) (c) +#define UINT32_C(c) (c ## U) +#define UINT64_C(c) (c ## ULL) + +#define INTMAX_C(c) (c ## LL) +#define UINTMAX_C(c) (c ## ULL) + +#endif diff --git a/sys/cpu/amd64/include/stdint.h b/sys/cpu/amd64/include/int_limits.h similarity index 58% copy from sys/cpu/amd64/include/stdint.h copy to sys/cpu/amd64/include/int_limits.h index b6de20211d..340d0ff2e5 100644 --- a/sys/cpu/amd64/include/stdint.h +++ b/sys/cpu/amd64/include/int_limits.h @@ -34,122 +34,10 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/i386/include/_stdint.h,v 1.1 2002/07/29 17:41:07 mike Exp $ - * $DragonFly: src/sys/cpu/amd64/include/stdint.h,v 1.1 2007/08/21 19:40:24 corecode Exp $ - */ - -#ifndef _CPU_STDINT_H_ -#define _CPU_STDINT_H_ - -/* - * Basic types upon which most other types are built. - */ -typedef __signed char __int8_t; -typedef unsigned char __uint8_t; -typedef short __int16_t; -typedef unsigned short __uint16_t; -typedef int __int32_t; -typedef unsigned int __uint32_t; -typedef int __boolean_t; - -/* - * This mess is to override compiler options that might restrict long long - * and for lint which doesn't understand GNUC attributes. - */ -#if defined(lint) -typedef long __int64_t; -typedef unsigned long __uint64_t; -#elif defined(__GNUC__) -typedef int __attribute__((__mode__(__DI__))) __int64_t; -typedef unsigned int __attribute__((__mode__(__DI__))) __uint64_t; -#else -typedef long __int64_t; -typedef unsigned long __uint64_t; -#endif - -/* - * Standard type definitions. - */ -typedef __int64_t __intmax_t; -typedef __uint64_t __uintmax_t; - -typedef __int64_t __intptr_t; -typedef __uint64_t __uintptr_t; - -typedef __int64_t __ptrdiff_t; /* ptr1 - ptr2 */ - -typedef __int32_t __int_fast8_t; -typedef __int32_t __int_fast16_t; -typedef __int32_t __int_fast32_t; -typedef __int64_t __int_fast64_t; -typedef __int8_t __int_least8_t; -typedef __int16_t __int_least16_t; -typedef __int32_t __int_least32_t; -typedef __int64_t __int_least64_t; -typedef __uint32_t __uint_fast8_t; -typedef __uint32_t __uint_fast16_t; -typedef __uint32_t __uint_fast32_t; -typedef __uint64_t __uint_fast64_t; -typedef __uint8_t __uint_least8_t; -typedef __uint16_t __uint_least16_t; -typedef __uint32_t __uint_least32_t; -typedef __uint64_t __uint_least64_t; - -/* - * System types conveniently placed in this header file in order to put them - * in proximity with the limit macros below and for convenient access by - * other include files which need to pick and choose particular types but - * do not wish to overly pollute their namespaces. */ -typedef __uint64_t __size_t; -typedef __int64_t __ssize_t; -typedef long __time_t; -typedef int __timer_t; -typedef __int64_t __register_t; -typedef __uint64_t __u_register_t; -typedef __int32_t __sig_atomic_t; /* XXX */ -typedef unsigned long __clock_t; -typedef unsigned long __clockid_t; -typedef __uint32_t __socklen_t; -typedef volatile int __atomic_intr_t; - -/* - * Its convenient to put these here rather then create another header file. - */ -#define __offsetof(type, field) ((size_t)(&((type *)0)->field)) -#define __arysize(ary) (sizeof(ary)/sizeof((ary)[0])) - -#endif /* _CPU_STDINT_H_ */ - -/* - * OpenGroup stdint.h extensions. Since these are protected by a define we - * do not have to generate __ versions of them. - */ -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) -#ifndef _CPU_STDINT_H_STDC_CONSTANT_MACROS_ -#define _CPU_STDINT_H_STDC_CONSTANT_MACROS_ - -#define INT8_C(c) (c) -#define INT16_C(c) (c) -#define INT32_C(c) (c) -#define INT64_C(c) (c ## LL) - -#define UINT8_C(c) (c) -#define UINT16_C(c) (c) -#define UINT32_C(c) (c ## U) -#define UINT64_C(c) (c ## ULL) - -#define INTMAX_C(c) (c ## LL) -#define UINTMAX_C(c) (c ## ULL) - -#endif -#endif /* !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) */ - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) -#ifndef _CPU_STDINT_H_STDC_LIMIT_MAVROS_ -#define _CPU_STDINT_H_STDC_LIMIT_MAVROS_ +#ifndef _CPU_INT_LIMITS_H_ +#define _CPU_INT_LIMITS_H_ /* * ISO/IEC 9899:1999 @@ -251,5 +139,3 @@ typedef volatile int __atomic_intr_t; #define UINT_FAST64_MAX UINT64_MAX #endif -#endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */ - diff --git a/sys/cpu/amd64/include/stdint.h b/sys/cpu/amd64/include/stdint.h index b6de20211d..53d28b99ff 100644 --- a/sys/cpu/amd64/include/stdint.h +++ b/sys/cpu/amd64/include/stdint.h @@ -122,134 +122,3 @@ typedef volatile int __atomic_intr_t; #define __arysize(ary) (sizeof(ary)/sizeof((ary)[0])) #endif /* _CPU_STDINT_H_ */ - -/* - * OpenGroup stdint.h extensions. Since these are protected by a define we - * do not have to generate __ versions of them. - */ -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) -#ifndef _CPU_STDINT_H_STDC_CONSTANT_MACROS_ -#define _CPU_STDINT_H_STDC_CONSTANT_MACROS_ - -#define INT8_C(c) (c) -#define INT16_C(c) (c) -#define INT32_C(c) (c) -#define INT64_C(c) (c ## LL) - -#define UINT8_C(c) (c) -#define UINT16_C(c) (c) -#define UINT32_C(c) (c ## U) -#define UINT64_C(c) (c ## ULL) - -#define INTMAX_C(c) (c ## LL) -#define UINTMAX_C(c) (c ## ULL) - -#endif -#endif /* !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) */ - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) -#ifndef _CPU_STDINT_H_STDC_LIMIT_MAVROS_ -#define _CPU_STDINT_H_STDC_LIMIT_MAVROS_ - -/* - * ISO/IEC 9899:1999 - * 7.18.2.1 Limits of exact-width integer types - */ -/* Minimum values of exact-width signed integer types. */ -#define INT8_MIN (-0x7f-1) -#define INT16_MIN (-0x7fff-1) -#define INT32_MIN (-0x7fffffff-1) -#define INT64_MIN (-0x7fffffffffffffffLL-1) - -/* Maximum values of exact-width signed integer types. */ -#define INT8_MAX 0x7f -#define INT16_MAX 0x7fff -#define INT32_MAX 0x7fffffff -#define INT64_MAX 0x7fffffffffffffffLL - -/* Maximum values of exact-width unsigned integer types. */ -#define UINT8_MAX 0xff -#define UINT16_MAX 0xffff -#define UINT32_MAX 0xffffffffU -#define UINT64_MAX 0xffffffffffffffffULL - -/* - * ISO/IEC 9899:1999 - * 7.18.2.4 Limits of integer types capable of holding object pointers - */ -#define INTPTR_MIN INT64_MIN -#define INTPTR_MAX INT64_MAX -#define UINTPTR_MAX UINT64_MAX - -/* - * ISO/IEC 9899:1999 - * 7.18.2.5 Limits of greatest-width integer types - */ -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -/* - * ISO/IEC 9899:1999 - * 7.18.3 Limits of other integer types - */ -/* Limits of ptrdiff_t. */ -#define PTRDIFF_MIN INT64_MIN -#define PTRDIFF_MAX INT64_MAX - -/* Limits of sig_atomic_t. */ -#define SIG_ATOMIC_MIN INT32_MIN -#define SIG_ATOMIC_MAX INT32_MAX - -/* Limit of size_t. */ -#define SIZE_MAX UINT64_MAX - -/* NOTE: wchar and wint macros in sys/stdint.h */ - -/* - * ISO/IEC 9899:1999 - * 7.18.2.2 Limits of minimum-width integer types - */ -/* Minimum values of minimum-width signed integer types. */ -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST64_MIN INT64_MIN - -/* Maximum values of minimum-width signed integer types. */ -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MAX INT64_MAX - -/* Maximum values of minimum-width unsigned integer types. */ -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -/* - * ISO/IEC 9899:1999 - * 7.18.2.3 Limits of fastest minimum-width integer types - */ -/* Minimum values of fastest minimum-width signed integer types. */ -#define INT_FAST8_MIN INT32_MIN -#define INT_FAST16_MIN INT32_MIN -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST64_MIN INT64_MIN - -/* Maximum values of fastest minimum-width signed integer types. */ -#define INT_FAST8_MAX INT32_MAX -#define INT_FAST16_MAX INT32_MAX -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MAX INT64_MAX - -/* Maximum values of fastest minimum-width unsigned integer types. */ -#define UINT_FAST8_MAX UINT32_MAX -#define UINT_FAST16_MAX UINT32_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -#endif -#endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */ - diff --git a/sys/cpu/i386/include/int_const.h b/sys/cpu/i386/include/int_const.h new file mode 100644 index 0000000000..2efe6ba9f0 --- /dev/null +++ b/sys/cpu/i386/include/int_const.h @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2001, 2002 Mike Barcroft + * Copyright (c) 2001 The NetBSD Foundation, Inc. All rights reserved. + * Copyright (c) 1990, 1993 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Klaus Klein. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _CPU_INT_CONST_H_ +#define _CPU_INT_CONST_H_ + +#define INT8_C(c) (c) +#define INT16_C(c) (c) +#define INT32_C(c) (c) +#define INT64_C(c) (c ## LL) + +#define UINT8_C(c) (c) +#define UINT16_C(c) (c) +#define UINT32_C(c) (c ## U) +#define UINT64_C(c) (c ## ULL) + +#define INTMAX_C(c) (c ## LL) +#define UINTMAX_C(c) (c ## ULL) + +#endif diff --git a/sys/cpu/i386/include/stdint.h b/sys/cpu/i386/include/int_limits.h similarity index 57% copy from sys/cpu/i386/include/stdint.h copy to sys/cpu/i386/include/int_limits.h index 8ce9cfea6c..082c0141ce 100644 --- a/sys/cpu/i386/include/stdint.h +++ b/sys/cpu/i386/include/int_limits.h @@ -34,131 +34,10 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/i386/include/_stdint.h,v 1.1 2002/07/29 17:41:07 mike Exp $ - * $DragonFly: src/sys/cpu/i386/include/stdint.h,v 1.8 2007/07/29 22:20:10 pavalos Exp $ - */ - -#ifndef _CPU_STDINT_H_ -#define _CPU_STDINT_H_ - -/* - * Basic types upon which most other types are built. - */ -typedef __signed char __int8_t; -typedef unsigned char __uint8_t; -typedef short __int16_t; -typedef unsigned short __uint16_t; -typedef int __int32_t; -typedef unsigned int __uint32_t; -typedef int __boolean_t; - -/* - * This mess is to override compiler options that might restrict long long - * and for lint which doesn't understand GNUC attributes. - */ -#if defined(lint) -typedef long long __int64_t; -typedef unsigned long long __uint64_t; -#elif defined(__GNUC__) -typedef int __attribute__((__mode__(__DI__))) __int64_t; -typedef unsigned int __attribute__((__mode__(__DI__))) __uint64_t; -#else -typedef long long __int64_t; -typedef unsigned long long __uint64_t; -#endif - -/* - * Standard type definitions. - */ -typedef __int64_t __intmax_t; -typedef __uint64_t __uintmax_t; - -typedef __int32_t __intptr_t; -typedef __uint32_t __uintptr_t; - -typedef __int32_t __ptrdiff_t; /* ptr1 - ptr2 */ - -typedef __int32_t __int_fast8_t; -typedef __int32_t __int_fast16_t; -typedef __int32_t __int_fast32_t; -typedef __int64_t __int_fast64_t; -typedef __int8_t __int_least8_t; -typedef __int16_t __int_least16_t; -typedef __int32_t __int_least32_t; -typedef __int64_t __int_least64_t; -typedef __uint32_t __uint_fast8_t; -typedef __uint32_t __uint_fast16_t; -typedef __uint32_t __uint_fast32_t; -typedef __uint64_t __uint_fast64_t; -typedef __uint8_t __uint_least8_t; -typedef __uint16_t __uint_least16_t; -typedef __uint32_t __uint_least32_t; -typedef __uint64_t __uint_least64_t; - -/* - * System types conveniently placed in this header file in order to put them - * in proximity with the limit macros below and for convenient access by - * other include files which need to pick and choose particular types but - * do not wish to overly pollute their namespaces. - */ - -typedef __uint32_t __size_t; -typedef __int32_t __ssize_t; -typedef long __time_t; -typedef int __timer_t; -typedef __int32_t __register_t; -typedef __uint32_t __u_register_t; -typedef __int32_t __sig_atomic_t; -typedef unsigned long __clock_t; -typedef unsigned long __clockid_t; -typedef __uint32_t __socklen_t; -typedef volatile int __atomic_intr_t; -/* - * Its convenient to put these here rather then create another header file. - */ -#ifndef __cplusplus -#define __offsetof(type, field) ((__size_t)(&((type *)0)->field)) -#elif (__GNUC__ >= 4) -#define __offsetof(type, field) __builtin_offsetof(type, field) -#else -#define __offsetof(type, field) \ - (__offsetof__ (reinterpret_cast <__size_t> \ - (&reinterpret_cast \ - (static_cast (0)->field)))) -#endif - -#define __arysize(ary) (sizeof(ary)/sizeof((ary)[0])) - -#endif /* _CPU_STDINT_H_ */ - -/* - * OpenGroup stdint.h extensions. Since these are protected by a define we - * do not have to generate __ versions of them. */ -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) -#ifndef _CPU_STDINT_H_STDC_CONSTANT_MACROS_ -#define _CPU_STDINT_H_STDC_CONSTANT_MACROS_ - -#define INT8_C(c) (c) -#define INT16_C(c) (c) -#define INT32_C(c) (c) -#define INT64_C(c) (c ## LL) - -#define UINT8_C(c) (c) -#define UINT16_C(c) (c) -#define UINT32_C(c) (c ## U) -#define UINT64_C(c) (c ## ULL) -#define INTMAX_C(c) (c ## LL) -#define UINTMAX_C(c) (c ## ULL) - -#endif -#endif /* !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) */ - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) -#ifndef _CPU_STDINT_H_STDC_LIMIT_MAVROS_ -#define _CPU_STDINT_H_STDC_LIMIT_MAVROS_ +#ifndef _CPU_INT_LIMITS_H_ +#define _CPU_INT_LIMITS_H_ /* * ISO/IEC 9899:1999 @@ -213,6 +92,7 @@ typedef volatile int __atomic_intr_t; /* Limit of size_t. */ #define SIZE_MAX UINT32_MAX +/* XXX possibly should be removed from here */ /* Also possibly defined in */ /* Limits of wchar_t. */ #ifndef WCHAR_MIN @@ -275,5 +155,3 @@ typedef volatile int __atomic_intr_t; #define UINT_FAST64_MAX UINT64_MAX #endif -#endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */ - diff --git a/sys/cpu/i386/include/stdint.h b/sys/cpu/i386/include/stdint.h index 8ce9cfea6c..cd5d03c857 100644 --- a/sys/cpu/i386/include/stdint.h +++ b/sys/cpu/i386/include/stdint.h @@ -131,149 +131,3 @@ typedef volatile int __atomic_intr_t; #define __arysize(ary) (sizeof(ary)/sizeof((ary)[0])) #endif /* _CPU_STDINT_H_ */ - -/* - * OpenGroup stdint.h extensions. Since these are protected by a define we - * do not have to generate __ versions of them. - */ -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) -#ifndef _CPU_STDINT_H_STDC_CONSTANT_MACROS_ -#define _CPU_STDINT_H_STDC_CONSTANT_MACROS_ - -#define INT8_C(c) (c) -#define INT16_C(c) (c) -#define INT32_C(c) (c) -#define INT64_C(c) (c ## LL) - -#define UINT8_C(c) (c) -#define UINT16_C(c) (c) -#define UINT32_C(c) (c ## U) -#define UINT64_C(c) (c ## ULL) - -#define INTMAX_C(c) (c ## LL) -#define UINTMAX_C(c) (c ## ULL) - -#endif -#endif /* !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) */ - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) -#ifndef _CPU_STDINT_H_STDC_LIMIT_MAVROS_ -#define _CPU_STDINT_H_STDC_LIMIT_MAVROS_ - -/* - * ISO/IEC 9899:1999 - * 7.18.2.1 Limits of exact-width integer types - */ -/* Minimum values of exact-width signed integer types. */ -#define INT8_MIN (-0x7f-1) -#define INT16_MIN (-0x7fff-1) -#define INT32_MIN (-0x7fffffff-1) -#define INT64_MIN (-0x7fffffffffffffffLL-1) - -/* Maximum values of exact-width signed integer types. */ -#define INT8_MAX 0x7f -#define INT16_MAX 0x7fff -#define INT32_MAX 0x7fffffff -#define INT64_MAX 0x7fffffffffffffffLL - -/* Maximum values of exact-width unsigned integer types. */ -#define UINT8_MAX 0xff -#define UINT16_MAX 0xffff -#define UINT32_MAX 0xffffffffU -#define UINT64_MAX 0xffffffffffffffffULL - -/* - * ISO/IEC 9899:1999 - * 7.18.2.4 Limits of integer types capable of holding object pointers - */ -#define INTPTR_MIN INT32_MIN -#define INTPTR_MAX INT32_MAX -#define UINTPTR_MAX UINT32_MAX - -/* - * ISO/IEC 9899:1999 - * 7.18.2.5 Limits of greatest-width integer types - */ -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -/* - * ISO/IEC 9899:1999 - * 7.18.3 Limits of other integer types - */ -/* Limits of ptrdiff_t. */ -#define PTRDIFF_MIN INT32_MIN -#define PTRDIFF_MAX INT32_MAX - -/* Limits of sig_atomic_t. */ -#define SIG_ATOMIC_MIN INT32_MIN -#define SIG_ATOMIC_MAX INT32_MAX - -/* Limit of size_t. */ -#define SIZE_MAX UINT32_MAX - -/* Also possibly defined in */ -/* Limits of wchar_t. */ -#ifndef WCHAR_MIN -#define WCHAR_MIN INT32_MIN -#endif -#ifndef WCHAR_MAX -#define WCHAR_MAX INT32_MAX -#endif - -/* Limits of wint_t. */ -#ifndef WINT_MIN -#define WINT_MIN INT32_MIN -#endif -#ifndef WINT_MAX -#define WINT_MAX INT32_MAX -#endif - -/* - * ISO/IEC 9899:1999 - * 7.18.2.2 Limits of minimum-width integer types - */ -/* Minimum values of minimum-width signed integer types. */ -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST64_MIN INT64_MIN - -/* Maximum values of minimum-width signed integer types. */ -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MAX INT64_MAX - -/* Maximum values of minimum-width unsigned integer types. */ -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -/* - * ISO/IEC 9899:1999 - * 7.18.2.3 Limits of fastest minimum-width integer types - */ -/* Minimum values of fastest minimum-width signed integer types. */ -#define INT_FAST8_MIN INT32_MIN -#define INT_FAST16_MIN INT32_MIN -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST64_MIN INT64_MIN - -/* Maximum values of fastest minimum-width signed integer types. */ -#define INT_FAST8_MAX INT32_MAX -#define INT_FAST16_MAX INT32_MAX -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MAX INT64_MAX - -/* Maximum values of fastest minimum-width unsigned integer types. */ -#define UINT_FAST8_MAX UINT32_MAX -#define UINT_FAST16_MAX UINT32_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -#endif -#endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */ - diff --git a/sys/dev/acpica5/Makefile b/sys/dev/acpica5/Makefile index c30fb8d65a..33e8a5a4b2 100644 --- a/sys/dev/acpica5/Makefile +++ b/sys/dev/acpica5/Makefile @@ -62,7 +62,8 @@ SRCS+= utresrc.c utstate.c utxface.c # OSD layer # -SRCS+= acpi.c acpi_acad.c acpi_battery.c acpi_button.c acpi_cmbat.c acpi_cpu.c +SRCS+= acpi.c acpi_acad.c acpi_battery.c acpi_button.c acpi_cmbat.c +SRCS+= acpi_cpu.c acpi_cpu_cstate.c acpi_cpu_pstate.c SRCS+= acpi_ec.c acpi_isab.c acpi_lid.c SRCS+= acpi_package.c # The PCI part of ACPI5 doesn't work with the current infrastructure @@ -103,6 +104,8 @@ SRCS+= utcache.c SRCS+= OsdCache.c .endif +# Machine-specific code for P-State +SRCS+= acpi_pstate_machdep.c # Machine-specific code such as sleep/wakeup SRCS+= acpi_machdep.c acpi_wakecode.h acpi_wakeup.c .if ${MACHINE_ARCH} == "i386" diff --git a/sys/dev/acpica5/acpi.c b/sys/dev/acpica5/acpi.c index 4e570bd982..71ab4f1ce6 100644 --- a/sys/dev/acpica5/acpi.c +++ b/sys/dev/acpica5/acpi.c @@ -65,10 +65,6 @@ MALLOC_DEFINE(M_ACPIDEV, "acpidev", "ACPI devices"); #define _COMPONENT ACPI_BUS ACPI_MODULE_NAME("ACPI") -#ifdef SMP -extern void lapic_timer_fixup(void); -#endif - static d_open_t acpiopen; static d_close_t acpiclose; static d_ioctl_t acpiioctl; @@ -699,13 +695,7 @@ acpi_attach(device_t dev) out: ACPI_UNLOCK; -#ifdef SMP - /* - * See the comment near lapic_timer_fixup() in - * platform/pc32/apic/mpapic.c - */ - lapic_timer_fixup(); -#endif + cputimer_intr_pmfixup(); return_VALUE (error); } diff --git a/sys/dev/acpica5/acpi_cpu.c b/sys/dev/acpica5/acpi_cpu.c index 288a597d07..fbbc00f4cc 100644 --- a/sys/dev/acpica5/acpi_cpu.c +++ b/sys/dev/acpica5/acpi_cpu.c @@ -29,175 +29,66 @@ */ #include "opt_acpi.h" + #include #include #include -#include -#include -#include -#include -#include -#include +#include -#include -#include #include -#include #include -#include #include "acpi.h" #include "acpivar.h" - -/* - * Support for ACPI Processor devices, including C[1-3] sleep states. - */ - -/* Hooks for the ACPI CA debugging infrastructure */ -#define _COMPONENT ACPI_PROCESSOR -ACPI_MODULE_NAME("PROCESSOR") - -struct acpi_cx { - struct resource *p_lvlx; /* Register to read to enter state. */ - uint32_t type; /* C1-3 (C4 and up treated as C3). */ - uint32_t trans_lat; /* Transition latency (usec). */ - uint32_t power; /* Power consumed (mW). */ - int res_type; /* Resource type for p_lvlx. */ -}; -#define MAX_CX_STATES 8 - -struct acpi_cpu_softc { - device_t cpu_dev; - ACPI_HANDLE cpu_handle; - struct mdglobaldata *md; - uint32_t cpu_acpi_id; /* ACPI processor id */ - uint32_t cpu_p_blk; /* ACPI P_BLK location */ - uint32_t cpu_p_blk_len; /* P_BLK length (must be 6). */ - struct acpi_cx cpu_cx_states[MAX_CX_STATES]; - int cpu_cx_count; /* Number of valid Cx states. */ - int cpu_prev_sleep;/* Last idle sleep duration. */ - int cpu_features; /* Child driver supported features. */ - /* Runtime state. */ - int cpu_non_c3; /* Index of lowest non-C3 state. */ - u_int cpu_cx_stats[MAX_CX_STATES];/* Cx usage history. */ - /* Values for sysctl. */ - struct sysctl_ctx_list cpu_sysctl_ctx; - struct sysctl_oid *cpu_sysctl_tree; - int cpu_cx_lowest; - char cpu_cx_supported[64]; - int cpu_rid; -}; - -struct acpi_cpu_device { - struct resource_list ad_rl; -}; - -#define CPU_GET_REG(reg, width) \ - (bus_space_read_ ## width(rman_get_bustag((reg)), \ - rman_get_bushandle((reg)), 0)) -#define CPU_SET_REG(reg, width, val) \ - (bus_space_write_ ## width(rman_get_bustag((reg)), \ - rman_get_bushandle((reg)), 0, (val))) - -#define PM_USEC(x) ((x) >> 2) /* ~4 clocks per usec (3.57955 Mhz) */ +#include "acpi_cpu.h" #define ACPI_NOTIFY_CX_STATES 0x81 /* _CST changed. */ -#define CPU_QUIRK_NO_C3 (1<<0) /* C3-type states are not usable. */ -#define CPU_QUIRK_NO_BM_CTRL (1<<2) /* No bus mastering control. */ - -#define PCI_VENDOR_INTEL 0x8086 -#define PCI_DEVICE_82371AB_3 0x7113 /* PIIX4 chipset for quirks. */ -#define PCI_REVISION_A_STEP 0 -#define PCI_REVISION_B_STEP 1 -#define PCI_REVISION_4E 2 -#define PCI_REVISION_4M 3 -#define PIIX4_DEVACTB_REG 0x58 -#define PIIX4_BRLD_EN_IRQ0 (1<<0) -#define PIIX4_BRLD_EN_IRQ (1<<1) -#define PIIX4_BRLD_EN_IRQ8 (1<<5) -#define PIIX4_STOP_BREAK_MASK (PIIX4_BRLD_EN_IRQ0 | PIIX4_BRLD_EN_IRQ | PIIX4_BRLD_EN_IRQ8) -#define PIIX4_PCNTRL_BST_EN (1<<10) - -/* Platform hardware resource information. */ -static uint32_t cpu_smi_cmd; /* Value to write to SMI_CMD. */ -static uint8_t cpu_cst_cnt; /* Indicate we are _CST aware. */ -static int cpu_quirks; /* Indicate any hardware bugs. */ - -/* Runtime state. */ -static int cpu_disable_idle; /* Disable entry to idle function */ -static int cpu_cx_count; /* Number of valid Cx states */ - -/* Values for sysctl. */ -static struct sysctl_ctx_list cpu_sysctl_ctx; -static struct sysctl_oid *cpu_sysctl_tree; -static int cpu_cx_generic; -static int cpu_cx_lowest; - -/* C3 state transition */ -static int cpu_c3_ncpus; - -static device_t *cpu_devices; -static int cpu_ndevices; -static struct acpi_cpu_softc **cpu_softc; - static int acpi_cpu_probe(device_t dev); static int acpi_cpu_attach(device_t dev); -static int acpi_cpu_suspend(device_t dev); -static int acpi_cpu_resume(device_t dev); -static int acpi_pcpu_get_id(uint32_t idx, uint32_t *acpi_id, - uint32_t *cpu_id); -static struct resource_list *acpi_cpu_get_rlist(device_t dev, device_t child); -static device_t acpi_cpu_add_child(device_t bus, device_t parent, int order, - const char *name, int unit); -static int acpi_cpu_read_ivar(device_t dev, device_t child, int index, - uintptr_t *result); -static int acpi_cpu_shutdown(device_t dev); -static void acpi_cpu_cx_probe(struct acpi_cpu_softc *sc); -static void acpi_cpu_generic_cx_probe(struct acpi_cpu_softc *sc); -static int acpi_cpu_cx_cst(struct acpi_cpu_softc *sc); -static void acpi_cpu_startup(void *arg); -static void acpi_cpu_startup_cx(struct acpi_cpu_softc *sc); -static void acpi_cpu_cx_list(struct acpi_cpu_softc *sc); -static void acpi_cpu_idle(void); -static void acpi_cpu_notify(ACPI_HANDLE h, UINT32 notify, void *context); -static int acpi_cpu_quirks(void); -static int acpi_cpu_usage_sysctl(SYSCTL_HANDLER_ARGS); -static int acpi_cpu_set_cx_lowest(struct acpi_cpu_softc *sc, int val); -static int acpi_cpu_cx_lowest_sysctl(SYSCTL_HANDLER_ARGS); -static int acpi_cpu_global_cx_lowest_sysctl(SYSCTL_HANDLER_ARGS); +static struct resource_list * + acpi_cpu_get_rlist(device_t, device_t); +static struct resource * + acpi_cpu_alloc_resource(device_t, device_t, + int, int *, u_long, u_long, u_long, u_int); +static int acpi_cpu_release_resource(device_t, device_t, + int, int, struct resource *); -static void acpi_cpu_c1(void); /* XXX */ +static int acpi_cpu_get_id(uint32_t, uint32_t *, uint32_t *); +static void acpi_cpu_notify(ACPI_HANDLE, UINT32, void *); static device_method_t acpi_cpu_methods[] = { /* Device interface */ - DEVMETHOD(device_probe, acpi_cpu_probe), - DEVMETHOD(device_attach, acpi_cpu_attach), - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, acpi_cpu_shutdown), - DEVMETHOD(device_suspend, acpi_cpu_suspend), - DEVMETHOD(device_resume, acpi_cpu_resume), + DEVMETHOD(device_probe, acpi_cpu_probe), + DEVMETHOD(device_attach, acpi_cpu_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ - DEVMETHOD(bus_add_child, acpi_cpu_add_child), - DEVMETHOD(bus_read_ivar, acpi_cpu_read_ivar), - DEVMETHOD(bus_get_resource_list, acpi_cpu_get_rlist), - DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), - DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), - DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource), - DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), - DEVMETHOD(bus_driver_added, bus_generic_driver_added), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - {0, 0} + DEVMETHOD(bus_add_child, bus_generic_add_child), + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), + DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), + DEVMETHOD(bus_get_resource_list, acpi_cpu_get_rlist), + DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), + DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), + DEVMETHOD(bus_alloc_resource, acpi_cpu_alloc_resource), + DEVMETHOD(bus_release_resource, acpi_cpu_release_resource), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } }; static driver_t acpi_cpu_driver = { "cpu", acpi_cpu_methods, - sizeof(struct acpi_cpu_softc), + sizeof(struct acpi_cpux_softc) }; static devclass_t acpi_cpu_devclass; @@ -207,219 +98,130 @@ MODULE_DEPEND(cpu, acpi, 1, 1, 1); static int acpi_cpu_probe(device_t dev) { - int acpi_id, cpu_id; - ACPI_BUFFER buf; - ACPI_HANDLE handle; - ACPI_OBJECT *obj; - ACPI_STATUS status; + int acpi_id, cpu_id; + ACPI_BUFFER buf; + ACPI_HANDLE handle; + ACPI_STATUS status; + ACPI_OBJECT *obj; if (acpi_disabled("cpu") || acpi_get_type(dev) != ACPI_TYPE_PROCESSOR) - return (ENXIO); + return ENXIO; handle = acpi_get_handle(dev); - if (cpu_softc == NULL) - cpu_softc = kmalloc(sizeof(struct acpi_cpu_softc *) * - SMP_MAXCPU, M_TEMP /* XXX */, M_INTWAIT | M_ZERO); - /* Get our Processor object. */ + /* + * Get our Processor object. + */ buf.Pointer = NULL; buf.Length = ACPI_ALLOCATE_BUFFER; status = AcpiEvaluateObject(handle, NULL, NULL, &buf); if (ACPI_FAILURE(status)) { device_printf(dev, "probe failed to get Processor obj - %s\n", AcpiFormatException(status)); - return (ENXIO); + return ENXIO; } + obj = (ACPI_OBJECT *)buf.Pointer; if (obj->Type != ACPI_TYPE_PROCESSOR) { device_printf(dev, "Processor object has bad type %d\n", obj->Type); AcpiOsFree(obj); - return (ENXIO); + return ENXIO; } - /* - * Find the processor associated with our unit. We could use the - * ProcId as a key, however, some boxes do not have the same values - * in their Processor object as the ProcId values in the MADT. - */ acpi_id = obj->Processor.ProcId; AcpiOsFree(obj); - if (acpi_pcpu_get_id(device_get_unit(dev), &acpi_id, &cpu_id) != 0) - return (ENXIO); /* - * Check if we already probed this processor. We scan the bus twice - * so it's possible we've already seen this one. + * Find the processor associated with our unit. We could use the + * ProcId as a key, however, some boxes do not have the same values + * in their Processor object as the ProcId values in the MADT. */ - if (cpu_softc[cpu_id] != NULL) - return (ENXIO); + if (acpi_cpu_get_id(device_get_unit(dev), &acpi_id, &cpu_id) != 0) + return ENXIO; - /* Mark this processor as in-use and save our derived id for attach. */ - cpu_softc[cpu_id] = (void *)1; acpi_set_magic(dev, cpu_id); device_set_desc(dev, "ACPI CPU"); - return (0); + return 0; } static int acpi_cpu_attach(device_t dev) { - ACPI_BUFFER buf; - ACPI_OBJECT arg[4], *obj; - ACPI_OBJECT_LIST arglist; - struct mdglobaldata *md; - struct acpi_cpu_softc *sc; - struct acpi_softc *acpi_sc; - ACPI_STATUS status; - u_int features; - int cpu_id, drv_count, i; - driver_t **drivers; - uint32_t cap_set[3]; - - /* UUID needed by _OSC evaluation */ - static uint8_t cpu_oscuuid[16] = { 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, - 0xBE, 0x47, 0x9E, 0xBD, 0xD8, 0x70, - 0x58, 0x71, 0x39, 0x53 }; - - ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + struct acpi_cpux_softc *sc = device_get_softc(dev); + ACPI_HANDLE handle; + device_t child; + int cpu_id; + struct acpi_softc *acpi_sc; - sc = device_get_softc(dev); - sc->cpu_dev = dev; - sc->cpu_handle = acpi_get_handle(dev); + handle = acpi_get_handle(dev); cpu_id = acpi_get_magic(dev); - cpu_softc[cpu_id] = sc; - md = (struct mdglobaldata *)globaldata_find(device_get_unit(dev)); - sc->md = md; - cpu_smi_cmd = AcpiGbl_FADT.SmiCommand; - cpu_cst_cnt = AcpiGbl_FADT.CstControl; - buf.Pointer = NULL; - buf.Length = ACPI_ALLOCATE_BUFFER; - status = AcpiEvaluateObject(sc->cpu_handle, NULL, NULL, &buf); - if (ACPI_FAILURE(status)) { - device_printf(dev, "attach failed to get Processor obj - %s\n", - AcpiFormatException(status)); - return (ENXIO); - } - obj = (ACPI_OBJECT *)buf.Pointer; - sc->cpu_p_blk = obj->Processor.PblkAddress; - sc->cpu_p_blk_len = obj->Processor.PblkLength; - sc->cpu_acpi_id = obj->Processor.ProcId; - AcpiOsFree(obj); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "acpi_cpu%d: P_BLK at %#x/%d\n", - device_get_unit(dev), sc->cpu_p_blk, sc->cpu_p_blk_len)); - - /* - * If this is the first cpu we attach, create and initialize the generic - * resources that will be used by all acpi cpu devices. - */ - if (device_get_unit(dev) == 0) { - /* Assume we won't be using generic Cx mode by default */ - cpu_cx_generic = FALSE; - - /* Install hw.acpi.cpu sysctl tree */ - acpi_sc = acpi_device_get_parent_softc(dev); - sysctl_ctx_init(&cpu_sysctl_ctx); - cpu_sysctl_tree = SYSCTL_ADD_NODE(&cpu_sysctl_ctx, - SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "cpu", - CTLFLAG_RD, 0, "node for CPU children"); - - /* Queue post cpu-probing task handler */ - AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cpu_startup, NULL); - } - - sysctl_ctx_init(&sc->cpu_sysctl_ctx); - sc->cpu_sysctl_tree = SYSCTL_ADD_NODE(&sc->cpu_sysctl_ctx, - SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, - device_get_nameunit(dev), CTLFLAG_RD, - 0, ""); - - /* - * Before calling any CPU methods, collect child driver feature hints - * and notify ACPI of them. We support unified SMP power control - * so advertise this ourselves. Note this is not the same as independent - * SMP control where each CPU can have different settings. - */ - sc->cpu_features = ACPI_CAP_SMP_SAME | ACPI_CAP_SMP_SAME_C3; - if (devclass_get_drivers(acpi_cpu_devclass, &drivers, &drv_count) == 0) { - for (i = 0; i < drv_count; i++) { - if (ACPI_GET_FEATURES(drivers[i], &features) == 0) - sc->cpu_features |= features; - } - kfree(drivers, M_TEMP); - } + acpi_sc = acpi_device_get_parent_softc(dev); + if (cpu_id == 0) { + sysctl_ctx_init(&sc->glob_sysctl_ctx); + sc->glob_sysctl_tree = SYSCTL_ADD_NODE(&sc->glob_sysctl_ctx, + SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), + OID_AUTO, "cpu", CTLFLAG_RD, 0, + "node for CPU global settings"); + if (sc->glob_sysctl_tree == NULL) + return ENOMEM; + } + + sysctl_ctx_init(&sc->pcpu_sysctl_ctx); + sc->pcpu_sysctl_tree = SYSCTL_ADD_NODE(&sc->pcpu_sysctl_ctx, + SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), + OID_AUTO, device_get_nameunit(dev), CTLFLAG_RD, 0, + "node for per-CPU settings"); + if (sc->pcpu_sysctl_tree == NULL) { + sysctl_ctx_free(&sc->glob_sysctl_ctx); + return ENOMEM; + } + + child = BUS_ADD_CHILD(dev, dev, 0, "cpu_cst", -1); + if (child == NULL) + return ENXIO; + acpi_set_handle(child, handle); + acpi_set_magic(child, cpu_id); + sc->cpux_cst = child; + + child = BUS_ADD_CHILD(dev, dev, 0, "cpu_pst", -1); + if (child == NULL) + return ENXIO; + acpi_set_handle(child, handle); + acpi_set_magic(child, cpu_id); - /* - * CPU capabilities are specified as a buffer of 32-bit integers: - * revision, count, and one or more capabilities. The revision of - * "1" is not specified anywhere but seems to match Linux. - */ - if (sc->cpu_features) { - arglist.Pointer = arg; - arglist.Count = 1; - arg[0].Type = ACPI_TYPE_BUFFER; - arg[0].Buffer.Length = sizeof(cap_set); - arg[0].Buffer.Pointer = (uint8_t *)cap_set; - cap_set[0] = 1; /* revision */ - cap_set[1] = 1; /* number of capabilities integers */ - cap_set[2] = sc->cpu_features; - AcpiEvaluateObject(sc->cpu_handle, "_PDC", &arglist, NULL); - - /* - * On some systems we need to evaluate _OSC so that the ASL - * loads the _PSS and/or _PDC methods at runtime. - * - * TODO: evaluate failure of _OSC. - */ - arglist.Pointer = arg; - arglist.Count = 4; - arg[0].Type = ACPI_TYPE_BUFFER; - arg[0].Buffer.Length = sizeof(cpu_oscuuid); - arg[0].Buffer.Pointer = cpu_oscuuid; /* UUID */ - arg[1].Type = ACPI_TYPE_INTEGER; - arg[1].Integer.Value = 1; /* revision */ - arg[2].Type = ACPI_TYPE_INTEGER; - arg[2].Integer.Value = 1; /* count */ - arg[3].Type = ACPI_TYPE_BUFFER; - arg[3].Buffer.Length = sizeof(cap_set); /* Capabilities buffer */ - arg[3].Buffer.Pointer = (uint8_t *)cap_set; - cap_set[0] = 0; - AcpiEvaluateObject(sc->cpu_handle, "_OSC", &arglist, NULL); - } - - /* Probe for Cx state support. */ - acpi_cpu_cx_probe(sc); - - /* Finally, call identify and probe/attach for child devices. */ - bus_generic_probe(dev); bus_generic_attach(dev); - return (0); + AcpiInstallNotifyHandler(handle, ACPI_DEVICE_NOTIFY, acpi_cpu_notify, sc); + + return 0; } /* - * Disable any entry to the idle function during suspend and re-enable it - * during resume. + * All resources are assigned directly to us by acpi, + * so 'child' is bypassed here. */ -static int -acpi_cpu_suspend(device_t dev) +static struct resource_list * +acpi_cpu_get_rlist(device_t dev, device_t child __unused) { - int error; + return BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); +} - error = bus_generic_suspend(dev); - if (error) - return (error); - cpu_disable_idle = TRUE; - return (0); +static struct resource * +acpi_cpu_alloc_resource(device_t dev, device_t child __unused, + int type, int *rid, u_long start, u_long end, + u_long count, u_int flags) +{ + return BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, type, rid, + start, end, count, flags); } static int -acpi_cpu_resume(device_t dev) +acpi_cpu_release_resource(device_t dev, device_t child __unused, + int type, int rid, struct resource *r) { - - cpu_disable_idle = FALSE; - return (bus_generic_resume(dev)); + return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, type, rid, r); } /* @@ -427,10 +229,10 @@ acpi_cpu_resume(device_t dev) * pc_acpi_id from the most reliable source. */ static int -acpi_pcpu_get_id(uint32_t idx, uint32_t *acpi_id, uint32_t *cpu_id) +acpi_cpu_get_id(uint32_t idx, uint32_t *acpi_id, uint32_t *cpu_id) { struct mdglobaldata *md; - uint32_t i; + uint32_t i; KASSERT(acpi_id != NULL, ("Null acpi_id")); KASSERT(cpu_id != NULL, ("Null cpu_id")); @@ -451,797 +253,21 @@ acpi_pcpu_get_id(uint32_t idx, uint32_t *acpi_id, uint32_t *cpu_id) else if (md->gd_acpi_id != *acpi_id) *acpi_id = md->gd_acpi_id; *cpu_id = md->mi.gd_cpuid; - return (0); - } - } - - return (ESRCH); -} - -static struct resource_list * -acpi_cpu_get_rlist(device_t dev, device_t child) -{ - struct acpi_cpu_device *ad; - - ad = device_get_ivars(child); - if (ad == NULL) - return (NULL); - return (&ad->ad_rl); -} - -static device_t -acpi_cpu_add_child(device_t bus, device_t parent, int order, - const char *name, int unit) -{ - struct acpi_cpu_device *ad; - device_t child; - - if ((ad = kmalloc(sizeof(*ad), M_TEMP, M_NOWAIT | M_ZERO)) == NULL) - return (NULL); - - resource_list_init(&ad->ad_rl); - - child = device_add_child_ordered(parent, order, name, unit); - if (child != NULL) - device_set_ivars(child, ad); - else - kfree(ad, M_TEMP); - return (child); -} - -static int -acpi_cpu_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) -{ - struct acpi_cpu_softc *sc; - - sc = device_get_softc(dev); - switch (index) { - case ACPI_IVAR_HANDLE: - *result = (uintptr_t)sc->cpu_handle; - break; -#if 0 - case CPU_IVAR_PCPU: - *result = (uintptr_t)sc->cpu_pcpu; - break; -#endif - default: - return (ENOENT); - } - return (0); -} - -static int -acpi_cpu_shutdown(device_t dev) -{ - ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); - - /* Allow children to shutdown first. */ - bus_generic_shutdown(dev); - - /* - * Disable any entry to the idle function. There is a small race where - * an idle thread have passed this check but not gone to sleep. This - * is ok since device_shutdown() does not free the softc, otherwise - * we'd have to be sure all threads were evicted before returning. - */ - cpu_disable_idle = TRUE; - - return_VALUE (0); -} - -static void -acpi_cpu_cx_probe(struct acpi_cpu_softc *sc) -{ - ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); - - /* Use initial sleep value of 1 sec. to start with lowest idle state. */ - sc->cpu_prev_sleep = 1000000; - sc->cpu_cx_lowest = 0; - - /* - * Check for the ACPI 2.0 _CST sleep states object. If we can't find - * any, we'll revert to generic FADT/P_BLK Cx control method which will - * be handled by acpi_cpu_startup. We need to defer to after having - * probed all the cpus in the system before probing for generic Cx - * states as we may already have found cpus with valid _CST packages - */ - if (!cpu_cx_generic && acpi_cpu_cx_cst(sc) != 0) { - /* - * We were unable to find a _CST package for this cpu or there - * was an error parsing it. Switch back to generic mode. - */ - cpu_cx_generic = TRUE; - if (bootverbose) - device_printf(sc->cpu_dev, "switching to generic Cx mode\n"); - } - - /* - * TODO: _CSD Package should be checked here. - */ -} - -static void -acpi_cpu_generic_cx_probe(struct acpi_cpu_softc *sc) -{ - ACPI_GENERIC_ADDRESS gas; - struct acpi_cx *cx_ptr; - - sc->cpu_cx_count = 0; - cx_ptr = sc->cpu_cx_states; - - /* Use initial sleep value of 1 sec. to start with lowest idle state. */ - sc->cpu_prev_sleep = 1000000; - - /* C1 has been required since just after ACPI 1.0 */ - cx_ptr->type = ACPI_STATE_C1; - cx_ptr->trans_lat = 0; - cx_ptr++; - sc->cpu_cx_count++; - - /* - * The spec says P_BLK must be 6 bytes long. However, some systems - * use it to indicate a fractional set of features present so we - * take 5 as C2. Some may also have a value of 7 to indicate - * another C3 but most use _CST for this (as required) and having - * "only" C1-C3 is not a hardship. - */ - if (sc->cpu_p_blk_len < 5) - return; - - /* Validate and allocate resources for C2 (P_LVL2). */ - gas.SpaceId = ACPI_ADR_SPACE_SYSTEM_IO; - gas.BitWidth = 8; - if (AcpiGbl_FADT.C2Latency <= 100) { - gas.Address = sc->cpu_p_blk + 4; - cx_ptr->p_lvlx = acpi_bus_alloc_gas(sc->cpu_dev, &sc->cpu_rid, &gas, - RF_SHAREABLE); - if (cx_ptr->p_lvlx != NULL) { - sc->cpu_rid++; - cx_ptr->type = ACPI_STATE_C2; - cx_ptr->trans_lat = AcpiGbl_FADT.C2Latency; - cx_ptr++; - sc->cpu_cx_count++; - } - } - if (sc->cpu_p_blk_len < 6) - return; - - /* Validate and allocate resources for C3 (P_LVL3). */ - if (AcpiGbl_FADT.C3Latency <= 1000 && !(cpu_quirks & CPU_QUIRK_NO_C3)) { - gas.Address = sc->cpu_p_blk + 5; - cx_ptr->p_lvlx = acpi_bus_alloc_gas(sc->cpu_dev, &sc->cpu_rid, &gas, - RF_SHAREABLE); - if (cx_ptr->p_lvlx != NULL) { - sc->cpu_rid++; - cx_ptr->type = ACPI_STATE_C3; - cx_ptr->trans_lat = AcpiGbl_FADT.C3Latency; - cx_ptr++; - sc->cpu_cx_count++; - } - } -} - -/* - * Parse a _CST package and set up its Cx states. Since the _CST object - * can change dynamically, our notify handler may call this function - * to clean up and probe the new _CST package. - */ -static int -acpi_cpu_cx_cst(struct acpi_cpu_softc *sc) -{ - struct acpi_cx *cx_ptr; - ACPI_STATUS status; - ACPI_BUFFER buf; - ACPI_OBJECT *top; - ACPI_OBJECT *pkg; - uint32_t count; - int i; - - ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); - - buf.Pointer = NULL; - buf.Length = ACPI_ALLOCATE_BUFFER; - status = AcpiEvaluateObject(sc->cpu_handle, "_CST", NULL, &buf); - if (ACPI_FAILURE(status)) - return (ENXIO); - - /* _CST is a package with a count and at least one Cx package. */ - top = (ACPI_OBJECT *)buf.Pointer; - if (!ACPI_PKG_VALID(top, 2) || acpi_PkgInt32(top, 0, &count) != 0) { - device_printf(sc->cpu_dev, "invalid _CST package\n"); - AcpiOsFree(buf.Pointer); - return (ENXIO); - } - if (count != top->Package.Count - 1) { - device_printf(sc->cpu_dev, "invalid _CST state count (%d != %d)\n", - count, top->Package.Count - 1); - count = top->Package.Count - 1; - } - if (count > MAX_CX_STATES) { - device_printf(sc->cpu_dev, "_CST has too many states (%d)\n", count); - count = MAX_CX_STATES; - } - - /* Set up all valid states. */ - sc->cpu_cx_count = 0; - cx_ptr = sc->cpu_cx_states; - for (i = 0; i < count; i++) { - pkg = &top->Package.Elements[i + 1]; - if (!ACPI_PKG_VALID(pkg, 4) || - acpi_PkgInt32(pkg, 1, &cx_ptr->type) != 0 || - acpi_PkgInt32(pkg, 2, &cx_ptr->trans_lat) != 0 || - acpi_PkgInt32(pkg, 3, &cx_ptr->power) != 0) { - - device_printf(sc->cpu_dev, "skipping invalid Cx state package\n"); - continue; - } - - /* Validate the state to see if we should use it. */ - switch (cx_ptr->type) { - case ACPI_STATE_C1: - sc->cpu_non_c3 = i; - cx_ptr++; - sc->cpu_cx_count++; - continue; - case ACPI_STATE_C2: - if (cx_ptr->trans_lat > 100) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "acpi_cpu%d: C2[%d] not available.\n", - device_get_unit(sc->cpu_dev), i)); - continue; - } - sc->cpu_non_c3 = i; - break; - case ACPI_STATE_C3: - default: - if (cx_ptr->trans_lat > 1000 || - (cpu_quirks & CPU_QUIRK_NO_C3) != 0) { - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "acpi_cpu%d: C3[%d] not available.\n", - device_get_unit(sc->cpu_dev), i)); - continue; - } - break; - } - -#ifdef notyet - /* Free up any previous register. */ - if (cx_ptr->p_lvlx != NULL) { - bus_release_resource(sc->cpu_dev, 0, 0, cx_ptr->p_lvlx); - cx_ptr->p_lvlx = NULL; - } -#endif - - /* Allocate the control register for C2 or C3. */ - acpi_PkgGas(sc->cpu_dev, pkg, 0, &sc->cpu_rid, &cx_ptr->p_lvlx, - RF_SHAREABLE); - if (cx_ptr->p_lvlx) { - sc->cpu_rid++; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "acpi_cpu%d: Got C%d - %d latency\n", - device_get_unit(sc->cpu_dev), cx_ptr->type, - cx_ptr->trans_lat)); - cx_ptr++; - sc->cpu_cx_count++; - } - } - AcpiOsFree(buf.Pointer); - - return (0); -} - -/* - * Call this *after* all CPUs have been attached. - */ -static void -acpi_cpu_startup(void *arg) -{ - struct acpi_cpu_softc *sc; - int i; - - /* Get set of CPU devices */ - devclass_get_devices(acpi_cpu_devclass, &cpu_devices, &cpu_ndevices); - - /* - * Setup any quirks that might necessary now that we have probed - * all the CPUs - */ - acpi_cpu_quirks(); - - cpu_cx_count = 0; - if (cpu_cx_generic) { - /* - * We are using generic Cx mode, probe for available Cx states - * for all processors. - */ - for (i = 0; i < cpu_ndevices; i++) { - sc = device_get_softc(cpu_devices[i]); - acpi_cpu_generic_cx_probe(sc); - if (sc->cpu_cx_count > cpu_cx_count) - cpu_cx_count = sc->cpu_cx_count; + return 0; } - - /* - * Find the highest Cx state common to all CPUs - * in the system, taking quirks into account. - */ - for (i = 0; i < cpu_ndevices; i++) { - sc = device_get_softc(cpu_devices[i]); - if (sc->cpu_cx_count < cpu_cx_count) - cpu_cx_count = sc->cpu_cx_count; - } - } else { - /* - * We are using _CST mode, remove C3 state if necessary. - * Update the largest Cx state supported in the global cpu_cx_count. - * It will be used in the global Cx sysctl handler. - * As we now know for sure that we will be using _CST mode - * install our notify handler. - */ - for (i = 0; i < cpu_ndevices; i++) { - sc = device_get_softc(cpu_devices[i]); - if (cpu_quirks & CPU_QUIRK_NO_C3) { - sc->cpu_cx_count = sc->cpu_non_c3 + 1; - } - if (sc->cpu_cx_count > cpu_cx_count) - cpu_cx_count = sc->cpu_cx_count; - AcpiInstallNotifyHandler(sc->cpu_handle, ACPI_DEVICE_NOTIFY, - acpi_cpu_notify, sc); - } - } - - /* Perform Cx final initialization. */ - for (i = 0; i < cpu_ndevices; i++) { - sc = device_get_softc(cpu_devices[i]); - acpi_cpu_startup_cx(sc); - } - - /* Add a sysctl handler to handle global Cx lowest setting */ - SYSCTL_ADD_PROC(&cpu_sysctl_ctx, SYSCTL_CHILDREN(cpu_sysctl_tree), - OID_AUTO, "cx_lowest", CTLTYPE_STRING | CTLFLAG_RW, - NULL, 0, acpi_cpu_global_cx_lowest_sysctl, "A", - "Global lowest Cx sleep state to use"); - - /* Take over idling from cpu_idle_default(). */ - cpu_cx_lowest = 0; - cpu_disable_idle = FALSE; - cpu_idle_hook = acpi_cpu_idle; -} - -static void -acpi_cpu_cx_list(struct acpi_cpu_softc *sc) -{ - struct sbuf sb; - int i; - - /* - * Set up the list of Cx states - */ - sc->cpu_non_c3 = 0; - sbuf_new(&sb, sc->cpu_cx_supported, sizeof(sc->cpu_cx_supported), - SBUF_FIXEDLEN); - for (i = 0; i < sc->cpu_cx_count; i++) { - sbuf_printf(&sb, "C%d/%d ", i + 1, sc->cpu_cx_states[i].trans_lat); - if (sc->cpu_cx_states[i].type < ACPI_STATE_C3) - sc->cpu_non_c3 = i; - } - sbuf_trim(&sb); - sbuf_finish(&sb); -} - -static void -acpi_cpu_startup_cx(struct acpi_cpu_softc *sc) -{ - acpi_cpu_cx_list(sc); - - SYSCTL_ADD_STRING(&sc->cpu_sysctl_ctx, - SYSCTL_CHILDREN(sc->cpu_sysctl_tree), - OID_AUTO, "cx_supported", CTLFLAG_RD, - sc->cpu_cx_supported, 0, - "Cx/microsecond values for supported Cx states"); - SYSCTL_ADD_PROC(&sc->cpu_sysctl_ctx, - SYSCTL_CHILDREN(sc->cpu_sysctl_tree), - OID_AUTO, "cx_lowest", CTLTYPE_STRING | CTLFLAG_RW, - (void *)sc, 0, acpi_cpu_cx_lowest_sysctl, "A", - "lowest Cx sleep state to use"); - SYSCTL_ADD_PROC(&sc->cpu_sysctl_ctx, - SYSCTL_CHILDREN(sc->cpu_sysctl_tree), - OID_AUTO, "cx_usage", CTLTYPE_STRING | CTLFLAG_RD, - (void *)sc, 0, acpi_cpu_usage_sysctl, "A", - "percent usage for each Cx state"); - -#ifdef notyet - /* Signal platform that we can handle _CST notification. */ - if (!cpu_cx_generic && cpu_cst_cnt != 0) { - ACPI_LOCK(acpi); - AcpiOsWritePort(cpu_smi_cmd, cpu_cst_cnt, 8); - ACPI_UNLOCK(acpi); } -#endif + return ESRCH; } -/* - * Idle the CPU in the lowest state possible. This function is called with - * interrupts disabled. Note that once it re-enables interrupts, a task - * switch can occur so do not access shared data (i.e. the softc) after - * interrupts are re-enabled. - */ static void -acpi_cpu_idle(void) +acpi_cpu_notify(ACPI_HANDLE handler __unused, UINT32 notify, void *xsc) { - struct acpi_cpu_softc *sc; - struct acpi_cx *cx_next; - uint32_t start_time, end_time; - int bm_active, cx_next_idx, i; - - /* If disabled, return immediately. */ - if (cpu_disable_idle) { - ACPI_ENABLE_IRQS(); - return; - } - - /* - * Look up our CPU id to get our softc. If it's NULL, we'll use C1 - * since there is no ACPI processor object for this CPU. This occurs - * for logical CPUs in the HTT case. - */ - sc = cpu_softc[mdcpu->mi.gd_cpuid]; - if (sc == NULL) { - acpi_cpu_c1(); - return; - } - - /* Find the lowest state that has small enough latency. */ - cx_next_idx = 0; - for (i = sc->cpu_cx_lowest; i >= 0; i--) { - if (sc->cpu_cx_states[i].trans_lat * 3 <= sc->cpu_prev_sleep) { - cx_next_idx = i; - break; - } - } - - /* - * Check for bus master activity. If there was activity, clear - * the bit and use the lowest non-C3 state. Note that the USB - * driver polling for new devices keeps this bit set all the - * time if USB is loaded. - */ - if ((cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0) { - AcpiGetRegister(ACPI_BITREG_BUS_MASTER_STATUS, &bm_active); - if (bm_active != 0) { - AcpiSetRegister(ACPI_BITREG_BUS_MASTER_STATUS, 1); - cx_next_idx = min(cx_next_idx, sc->cpu_non_c3); - } - } - - /* Select the next state and update statistics. */ - cx_next = &sc->cpu_cx_states[cx_next_idx]; - sc->cpu_cx_stats[cx_next_idx]++; - KASSERT(cx_next->type != ACPI_STATE_C0, ("acpi_cpu_idle: C0 sleep")); - - /* - * Execute HLT (or equivalent) and wait for an interrupt. We can't - * calculate the time spent in C1 since the place we wake up is an - * ISR. Assume we slept half of quantum and return. - */ - if (cx_next->type == ACPI_STATE_C1) { - sc->cpu_prev_sleep = (sc->cpu_prev_sleep * 3 + 500000 / hz) / 4; - acpi_cpu_c1(); - return; - } - - /* - * For C3, disable bus master arbitration and enable bus master wake - * if BM control is available, otherwise flush the CPU cache. - */ - if (cx_next->type == ACPI_STATE_C3) { - if (atomic_fetchadd_int(&cpu_c3_ncpus, 1) == 0) { - /* - * When the first CPU enters C3 state, switch - * to an one shot timer, which could handle - * C3 state, i.e. the timer will not hang. - */ - cputimer_intr_switch(CPUTIMER_INTRT_C3); - } - - if ((cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0) { - AcpiSetRegister(ACPI_BITREG_ARB_DISABLE, 1); - AcpiSetRegister(ACPI_BITREG_BUS_MASTER_RLD, 1); - } else - ACPI_FLUSH_CPU_CACHE(); - } - - /* - * Read from P_LVLx to enter C2(+), checking time spent asleep. - * Use the ACPI timer for measuring sleep time. Since we need to - * get the time very close to the CPU start/stop clock logic, this - * is the only reliable time source. - */ - AcpiHwLowLevelRead(32, &start_time, &AcpiGbl_FADT.XPmTimerBlock); - CPU_GET_REG(cx_next->p_lvlx, 1); - - /* - * Read the end time twice. Since it may take an arbitrary time - * to enter the idle state, the first read may be executed before - * the processor has stopped. Doing it again provides enough - * margin that we are certain to have a correct value. - */ - AcpiHwLowLevelRead(32, &end_time, &AcpiGbl_FADT.XPmTimerBlock); - AcpiHwLowLevelRead(32, &end_time, &AcpiGbl_FADT.XPmTimerBlock); + struct acpi_cpux_softc *sc = xsc; - /* Enable bus master arbitration and disable bus master wakeup. */ - if (cx_next->type == ACPI_STATE_C3) { - if ((cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0) { - AcpiSetRegister(ACPI_BITREG_ARB_DISABLE, 0); - AcpiSetRegister(ACPI_BITREG_BUS_MASTER_RLD, 0); - } - - if (atomic_fetchadd_int(&cpu_c3_ncpus, -1) == 1) { - /* - * All of the CPUs exit C3 state, use a better - * one shot timer. - */ - cputimer_intr_switch(CPUTIMER_INTRT_FAST); - } - } - ACPI_ENABLE_IRQS(); - - /* Find the actual time asleep in microseconds. */ - end_time = acpi_TimerDelta(end_time, start_time); - sc->cpu_prev_sleep = (sc->cpu_prev_sleep * 3 + PM_USEC(end_time)) / 4; -} - -/* - * Re-evaluate the _CST object when we are notified that it changed. - * - * XXX Re-evaluation disabled until locking is done. - */ -static void -acpi_cpu_notify(ACPI_HANDLE h, UINT32 notify, void *context) -{ - struct acpi_cpu_softc *sc = (struct acpi_cpu_softc *)context; - struct acpi_cpu_softc *isc; - int i; - - if (notify != ACPI_NOTIFY_CX_STATES) - return; - - /* Update the list of Cx states. */ - acpi_cpu_cx_cst(sc); - acpi_cpu_cx_list(sc); - - /* Update the new lowest useable Cx state for all CPUs. */ - crit_enter(); - cpu_cx_count = 0; - for (i = 0; i < cpu_ndevices; i++) { - isc = device_get_softc(cpu_devices[i]); - if (isc->cpu_cx_count > cpu_cx_count) - cpu_cx_count = isc->cpu_cx_count; - } - crit_exit(); -} - -static int -acpi_cpu_quirks(void) -{ - device_t acpi_dev; - uint32_t val; - - ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); - - /* - * Bus mastering arbitration control is needed to keep caches coherent - * while sleeping in C3. If it's not present but a working flush cache - * instruction is present, flush the caches before entering C3 instead. - * Otherwise, just disable C3 completely. - */ - if (AcpiGbl_FADT.Pm2ControlBlock == 0 || - AcpiGbl_FADT.Pm2ControlLength == 0) { - if ((AcpiGbl_FADT.Flags & ACPI_FADT_WBINVD) && - (AcpiGbl_FADT.Flags & ACPI_FADT_WBINVD_FLUSH) == 0) { - cpu_quirks |= CPU_QUIRK_NO_BM_CTRL; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "acpi_cpu: no BM control, using flush cache method\n")); - } else { - cpu_quirks |= CPU_QUIRK_NO_C3; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "acpi_cpu: no BM control, C3 not available\n")); - } - } - - /* - * If we are using generic Cx mode, C3 on multiple CPUs requires using - * the expensive flush cache instruction. - */ - if (cpu_cx_generic && ncpus > 1) { - cpu_quirks |= CPU_QUIRK_NO_BM_CTRL; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "acpi_cpu: SMP, using flush cache mode for C3\n")); - } - - /* Look for various quirks of the PIIX4 part. */ - acpi_dev = pci_find_device(PCI_VENDOR_INTEL, PCI_DEVICE_82371AB_3); - if (acpi_dev != NULL) { - switch (pci_get_revid(acpi_dev)) { - /* - * Disable C3 support for all PIIX4 chipsets. Some of these parts - * do not report the BMIDE status to the BM status register and - * others have a livelock bug if Type-F DMA is enabled. Linux - * works around the BMIDE bug by reading the BM status directly - * but we take the simpler approach of disabling C3 for these - * parts. - * - * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA - * Livelock") from the January 2002 PIIX4 specification update. - * Applies to all PIIX4 models. - * - * Also, make sure that all interrupts cause a "Stop Break" - * event to exit from C2 state. - * Also, BRLD_EN_BM (ACPI_BITREG_BUS_MASTER_RLD in ACPI-speak) - * should be set to zero, otherwise it causes C2 to short-sleep. - * PIIX4 doesn't properly support C3 and bus master activity - * need not break out of C2. - */ - case PCI_REVISION_A_STEP: - case PCI_REVISION_B_STEP: - case PCI_REVISION_4E: - case PCI_REVISION_4M: - cpu_quirks |= CPU_QUIRK_NO_C3; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "acpi_cpu: working around PIIX4 bug, disabling C3\n")); - - val = pci_read_config(acpi_dev, PIIX4_DEVACTB_REG, 4); - if ((val & PIIX4_STOP_BREAK_MASK) != PIIX4_STOP_BREAK_MASK) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "acpi_cpu: PIIX4: enabling IRQs to generate Stop Break\n")); - val |= PIIX4_STOP_BREAK_MASK; - pci_write_config(acpi_dev, PIIX4_DEVACTB_REG, val, 4); - } - AcpiGetRegister(ACPI_BITREG_BUS_MASTER_RLD, &val); - if (val) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "acpi_cpu: PIIX4: reset BRLD_EN_BM\n")); - AcpiSetRegister(ACPI_BITREG_BUS_MASTER_RLD, 0); - } - break; - default: - break; - } - } - - return (0); -} - -static int -acpi_cpu_usage_sysctl(SYSCTL_HANDLER_ARGS) -{ - struct acpi_cpu_softc *sc; - struct sbuf sb; - char buf[128]; - int i; - uintmax_t fract, sum, whole; - - sc = (struct acpi_cpu_softc *) arg1; - sum = 0; - for (i = 0; i < sc->cpu_cx_count; i++) - sum += sc->cpu_cx_stats[i]; - sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN); - for (i = 0; i < sc->cpu_cx_count; i++) { - if (sum > 0) { - whole = (uintmax_t)sc->cpu_cx_stats[i] * 100; - fract = (whole % sum) * 100; - sbuf_printf(&sb, "%u.%02u%% ", (u_int)(whole / sum), - (u_int)(fract / sum)); - } else - sbuf_printf(&sb, "0.00%% "); - } - sbuf_printf(&sb, "last %dus", sc->cpu_prev_sleep); - sbuf_trim(&sb); - sbuf_finish(&sb); - sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req); - sbuf_delete(&sb); - - return (0); -} - -static int -acpi_cpu_set_cx_lowest(struct acpi_cpu_softc *sc, int val) -{ - int i; - - sc->cpu_cx_lowest = val; - - /* If not disabling, cache the new lowest non-C3 state. */ - sc->cpu_non_c3 = 0; - for (i = sc->cpu_cx_lowest; i >= 0; i--) { - if (sc->cpu_cx_states[i].type < ACPI_STATE_C3) { - sc->cpu_non_c3 = i; - break; - } - } - - /* Reset the statistics counters. */ - bzero(sc->cpu_cx_stats, sizeof(sc->cpu_cx_stats)); - return (0); -} - -static int -acpi_cpu_cx_lowest_sysctl(SYSCTL_HANDLER_ARGS) -{ - struct acpi_cpu_softc *sc; - char state[8]; - int val, error; - - sc = (struct acpi_cpu_softc *) arg1; - ksnprintf(state, sizeof(state), "C%d", sc->cpu_cx_lowest + 1); - error = sysctl_handle_string(oidp, state, sizeof(state), req); - if (error != 0 || req->newptr == NULL) - return (error); - if (strlen(state) < 2 || toupper(state[0]) != 'C') - return (EINVAL); - val = (int) strtol(state + 1, NULL, 10) - 1; - if (val < 0 || val > sc->cpu_cx_count - 1) - return (EINVAL); - - crit_enter(); - acpi_cpu_set_cx_lowest(sc, val); - crit_exit(); - - return (0); -} - -static int -acpi_cpu_global_cx_lowest_sysctl(SYSCTL_HANDLER_ARGS) -{ - struct acpi_cpu_softc *sc; - char state[8]; - int val, error, i; - - ksnprintf(state, sizeof(state), "C%d", cpu_cx_lowest + 1); - error = sysctl_handle_string(oidp, state, sizeof(state), req); - if (error != 0 || req->newptr == NULL) - return (error); - if (strlen(state) < 2 || toupper(state[0]) != 'C') - return (EINVAL); - val = (int) strtol(state + 1, NULL, 10) - 1; - if (val < 0 || val > cpu_cx_count - 1) - return (EINVAL); - cpu_cx_lowest = val; - - /* Update the new lowest useable Cx state for all CPUs. */ - crit_enter(); - for (i = 0; i < cpu_ndevices; i++) { - sc = device_get_softc(cpu_devices[i]); - acpi_cpu_set_cx_lowest(sc, val); + switch (notify) { + case ACPI_NOTIFY_CX_STATES: + if (sc->cpux_cst_notify != NULL) + sc->cpux_cst_notify(sc->cpux_cst); + break; } - crit_exit(); - - return (0); } - -/* - * Put the CPU in C1 in a machine-dependant way. - * XXX: shouldn't be here! - */ -static void -acpi_cpu_c1(void) -{ -#ifdef __ia64__ - ia64_call_pal_static(PAL_HALT_LIGHT, 0, 0, 0); -#else - splz(); -#ifdef SMP - if (!lwkt_runnable()) - __asm __volatile("sti; hlt"); - else - __asm __volatile("sti; pause"); -#else - if (!lwkt_runnable()) - __asm __volatile("sti; hlt"); - else - __asm __volatile("sti"); -#endif -#endif /* !__ia64__ */ -} - diff --git a/usr.bin/window/wwdata.c b/sys/dev/acpica5/acpi_cpu.h similarity index 52% copy from usr.bin/window/wwdata.c copy to sys/dev/acpica5/acpi_cpu.h index a7279452e4..4581dc13bf 100644 --- a/usr.bin/window/wwdata.c +++ b/sys/dev/acpica5/acpi_cpu.h @@ -1,9 +1,7 @@ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Edward Wang at The University of California, Berkeley. +/*- + * Copyright (c) 2003-2005 Nate Lawson (SDG) + * Copyright (c) 2001 Michael Smith + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -13,18 +11,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -33,8 +24,21 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)wwdata.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwdata.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwdata.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ + * $FreeBSD: src/sys/dev/acpica/acpi_cpu.c,v 1.72 2008/04/12 12:06:00 rpaulo Exp $ */ +#ifndef __ACPI_CPU_H__ +#define __ACPI_CPU_H__ + +struct acpi_cpux_softc { + device_t cpux_cst; + void (*cpux_cst_notify)(device_t); + + struct sysctl_ctx_list glob_sysctl_ctx; + struct sysctl_oid *glob_sysctl_tree; /* hw.acpi.cpu */ + + struct sysctl_ctx_list pcpu_sysctl_ctx; + struct sysctl_oid *pcpu_sysctl_tree; /* hw.acpi.cpuX */ +}; + +#endif /* !__ACPI_CPU_H__ */ diff --git a/sys/dev/acpica5/acpi_cpu.c b/sys/dev/acpica5/acpi_cpu_cstate.c similarity index 86% copy from sys/dev/acpica5/acpi_cpu.c copy to sys/dev/acpica5/acpi_cpu_cstate.c index 288a597d07..b539b942b5 100644 --- a/sys/dev/acpica5/acpi_cpu.c +++ b/sys/dev/acpica5/acpi_cpu_cstate.c @@ -48,6 +48,7 @@ #include "acpi.h" #include "acpivar.h" +#include "acpi_cpu.h" /* * Support for ACPI Processor devices, including C[1-3] sleep states. @@ -68,6 +69,7 @@ struct acpi_cx { struct acpi_cpu_softc { device_t cpu_dev; + struct acpi_cpux_softc *cpu_parent; ACPI_HANDLE cpu_handle; struct mdglobaldata *md; uint32_t cpu_acpi_id; /* ACPI processor id */ @@ -81,8 +83,6 @@ struct acpi_cpu_softc { int cpu_non_c3; /* Index of lowest non-C3 state. */ u_int cpu_cx_stats[MAX_CX_STATES];/* Cx usage history. */ /* Values for sysctl. */ - struct sysctl_ctx_list cpu_sysctl_ctx; - struct sysctl_oid *cpu_sysctl_tree; int cpu_cx_lowest; char cpu_cx_supported[64]; int cpu_rid; @@ -129,8 +129,6 @@ static int cpu_disable_idle; /* Disable entry to idle function */ static int cpu_cx_count; /* Number of valid Cx states */ /* Values for sysctl. */ -static struct sysctl_ctx_list cpu_sysctl_ctx; -static struct sysctl_oid *cpu_sysctl_tree; static int cpu_cx_generic; static int cpu_cx_lowest; @@ -141,13 +139,12 @@ static device_t *cpu_devices; static int cpu_ndevices; static struct acpi_cpu_softc **cpu_softc; -static int acpi_cpu_probe(device_t dev); -static int acpi_cpu_attach(device_t dev); +static int acpi_cpu_cst_probe(device_t dev); +static int acpi_cpu_cst_attach(device_t dev); static int acpi_cpu_suspend(device_t dev); static int acpi_cpu_resume(device_t dev); -static int acpi_pcpu_get_id(uint32_t idx, uint32_t *acpi_id, - uint32_t *cpu_id); -static struct resource_list *acpi_cpu_get_rlist(device_t dev, device_t child); +static struct resource_list *acpi_cpu_cst_get_rlist(device_t dev, + device_t child); static device_t acpi_cpu_add_child(device_t bus, device_t parent, int order, const char *name, int unit); static int acpi_cpu_read_ivar(device_t dev, device_t child, int index, @@ -160,7 +157,7 @@ static void acpi_cpu_startup(void *arg); static void acpi_cpu_startup_cx(struct acpi_cpu_softc *sc); static void acpi_cpu_cx_list(struct acpi_cpu_softc *sc); static void acpi_cpu_idle(void); -static void acpi_cpu_notify(ACPI_HANDLE h, UINT32 notify, void *context); +static void acpi_cpu_cst_notify(device_t); static int acpi_cpu_quirks(void); static int acpi_cpu_usage_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_cpu_set_cx_lowest(struct acpi_cpu_softc *sc, int val); @@ -169,10 +166,10 @@ static int acpi_cpu_global_cx_lowest_sysctl(SYSCTL_HANDLER_ARGS); static void acpi_cpu_c1(void); /* XXX */ -static device_method_t acpi_cpu_methods[] = { +static device_method_t acpi_cpu_cst_methods[] = { /* Device interface */ - DEVMETHOD(device_probe, acpi_cpu_probe), - DEVMETHOD(device_attach, acpi_cpu_attach), + DEVMETHOD(device_probe, acpi_cpu_cst_probe), + DEVMETHOD(device_attach, acpi_cpu_cst_attach), DEVMETHOD(device_detach, bus_generic_detach), DEVMETHOD(device_shutdown, acpi_cpu_shutdown), DEVMETHOD(device_suspend, acpi_cpu_suspend), @@ -181,7 +178,7 @@ static device_method_t acpi_cpu_methods[] = { /* Bus interface */ DEVMETHOD(bus_add_child, acpi_cpu_add_child), DEVMETHOD(bus_read_ivar, acpi_cpu_read_ivar), - DEVMETHOD(bus_get_resource_list, acpi_cpu_get_rlist), + DEVMETHOD(bus_get_resource_list, acpi_cpu_cst_get_rlist), DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource), @@ -194,83 +191,54 @@ static device_method_t acpi_cpu_methods[] = { {0, 0} }; -static driver_t acpi_cpu_driver = { - "cpu", - acpi_cpu_methods, +static driver_t acpi_cpu_cst_driver = { + "cpu_cst", + acpi_cpu_cst_methods, sizeof(struct acpi_cpu_softc), }; -static devclass_t acpi_cpu_devclass; -DRIVER_MODULE(cpu, acpi, acpi_cpu_driver, acpi_cpu_devclass, 0, 0); -MODULE_DEPEND(cpu, acpi, 1, 1, 1); +static devclass_t acpi_cpu_cst_devclass; +DRIVER_MODULE(cpu_cst, cpu, acpi_cpu_cst_driver, acpi_cpu_cst_devclass, 0, 0); +MODULE_DEPEND(cpu_cst, acpi, 1, 1, 1); static int -acpi_cpu_probe(device_t dev) +acpi_cpu_cst_probe(device_t dev) { - int acpi_id, cpu_id; - ACPI_BUFFER buf; - ACPI_HANDLE handle; - ACPI_OBJECT *obj; - ACPI_STATUS status; + int cpu_id; - if (acpi_disabled("cpu") || acpi_get_type(dev) != ACPI_TYPE_PROCESSOR) + if (acpi_disabled("cpu_cst") || acpi_get_type(dev) != ACPI_TYPE_PROCESSOR) return (ENXIO); - handle = acpi_get_handle(dev); + cpu_id = acpi_get_magic(dev); + if (cpu_softc == NULL) cpu_softc = kmalloc(sizeof(struct acpi_cpu_softc *) * SMP_MAXCPU, M_TEMP /* XXX */, M_INTWAIT | M_ZERO); - /* Get our Processor object. */ - buf.Pointer = NULL; - buf.Length = ACPI_ALLOCATE_BUFFER; - status = AcpiEvaluateObject(handle, NULL, NULL, &buf); - if (ACPI_FAILURE(status)) { - device_printf(dev, "probe failed to get Processor obj - %s\n", - AcpiFormatException(status)); - return (ENXIO); - } - obj = (ACPI_OBJECT *)buf.Pointer; - if (obj->Type != ACPI_TYPE_PROCESSOR) { - device_printf(dev, "Processor object has bad type %d\n", obj->Type); - AcpiOsFree(obj); - return (ENXIO); - } - - /* - * Find the processor associated with our unit. We could use the - * ProcId as a key, however, some boxes do not have the same values - * in their Processor object as the ProcId values in the MADT. - */ - acpi_id = obj->Processor.ProcId; - AcpiOsFree(obj); - if (acpi_pcpu_get_id(device_get_unit(dev), &acpi_id, &cpu_id) != 0) - return (ENXIO); - /* * Check if we already probed this processor. We scan the bus twice * so it's possible we've already seen this one. */ - if (cpu_softc[cpu_id] != NULL) + if (cpu_softc[cpu_id] != NULL) { + device_printf(dev, "CPU%d cstate already exist\n", cpu_id); return (ENXIO); + } /* Mark this processor as in-use and save our derived id for attach. */ cpu_softc[cpu_id] = (void *)1; - acpi_set_magic(dev, cpu_id); - device_set_desc(dev, "ACPI CPU"); + device_set_desc(dev, "ACPI CPU C-State"); return (0); } static int -acpi_cpu_attach(device_t dev) +acpi_cpu_cst_attach(device_t dev) { ACPI_BUFFER buf; ACPI_OBJECT arg[4], *obj; ACPI_OBJECT_LIST arglist; struct mdglobaldata *md; struct acpi_cpu_softc *sc; - struct acpi_softc *acpi_sc; ACPI_STATUS status; u_int features; int cpu_id, drv_count, i; @@ -286,6 +254,7 @@ acpi_cpu_attach(device_t dev) sc = device_get_softc(dev); sc->cpu_dev = dev; + sc->cpu_parent = device_get_softc(device_get_parent(dev)); sc->cpu_handle = acpi_get_handle(dev); cpu_id = acpi_get_magic(dev); cpu_softc[cpu_id] = sc; @@ -318,23 +287,10 @@ acpi_cpu_attach(device_t dev) /* Assume we won't be using generic Cx mode by default */ cpu_cx_generic = FALSE; - /* Install hw.acpi.cpu sysctl tree */ - acpi_sc = acpi_device_get_parent_softc(dev); - sysctl_ctx_init(&cpu_sysctl_ctx); - cpu_sysctl_tree = SYSCTL_ADD_NODE(&cpu_sysctl_ctx, - SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "cpu", - CTLFLAG_RD, 0, "node for CPU children"); - /* Queue post cpu-probing task handler */ AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cpu_startup, NULL); } - sysctl_ctx_init(&sc->cpu_sysctl_ctx); - sc->cpu_sysctl_tree = SYSCTL_ADD_NODE(&sc->cpu_sysctl_ctx, - SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, - device_get_nameunit(dev), CTLFLAG_RD, - 0, ""); - /* * Before calling any CPU methods, collect child driver feature hints * and notify ACPI of them. We support unified SMP power control @@ -342,7 +298,8 @@ acpi_cpu_attach(device_t dev) * SMP control where each CPU can have different settings. */ sc->cpu_features = ACPI_CAP_SMP_SAME | ACPI_CAP_SMP_SAME_C3; - if (devclass_get_drivers(acpi_cpu_devclass, &drivers, &drv_count) == 0) { + if (devclass_get_drivers(acpi_cpu_cst_devclass, + &drivers, &drv_count) == 0) { for (i = 0; i < drv_count; i++) { if (ACPI_GET_FEATURES(drivers[i], &features) == 0) sc->cpu_features |= features; @@ -422,44 +379,8 @@ acpi_cpu_resume(device_t dev) return (bus_generic_resume(dev)); } -/* - * Find the nth present CPU and return its pc_cpuid as well as set the - * pc_acpi_id from the most reliable source. - */ -static int -acpi_pcpu_get_id(uint32_t idx, uint32_t *acpi_id, uint32_t *cpu_id) -{ - struct mdglobaldata *md; - uint32_t i; - - KASSERT(acpi_id != NULL, ("Null acpi_id")); - KASSERT(cpu_id != NULL, ("Null cpu_id")); - for (i = 0; i < ncpus; i++) { - if ((smp_active_mask & (1 << i)) == 0) - continue; - md = (struct mdglobaldata *)globaldata_find(i); - KASSERT(md != NULL, ("no pcpu data for %d", i)); - if (idx-- == 0) { - /* - * If pc_acpi_id was not initialized (e.g., a non-APIC UP box) - * override it with the value from the ASL. Otherwise, if the - * two don't match, prefer the MADT-derived value. Finally, - * return the pc_cpuid to reference this processor. - */ - if (md->gd_acpi_id == 0xffffffff) - md->gd_acpi_id = *acpi_id; - else if (md->gd_acpi_id != *acpi_id) - *acpi_id = md->gd_acpi_id; - *cpu_id = md->mi.gd_cpuid; - return (0); - } - } - - return (ESRCH); -} - static struct resource_list * -acpi_cpu_get_rlist(device_t dev, device_t child) +acpi_cpu_cst_get_rlist(device_t dev, device_t child) { struct acpi_cpu_device *ad; @@ -741,7 +662,7 @@ acpi_cpu_startup(void *arg) int i; /* Get set of CPU devices */ - devclass_get_devices(acpi_cpu_devclass, &cpu_devices, &cpu_ndevices); + devclass_get_devices(acpi_cpu_cst_devclass, &cpu_devices, &cpu_ndevices); /* * Setup any quirks that might necessary now that we have probed @@ -786,8 +707,7 @@ acpi_cpu_startup(void *arg) } if (sc->cpu_cx_count > cpu_cx_count) cpu_cx_count = sc->cpu_cx_count; - AcpiInstallNotifyHandler(sc->cpu_handle, ACPI_DEVICE_NOTIFY, - acpi_cpu_notify, sc); + sc->cpu_parent->cpux_cst_notify = acpi_cpu_cst_notify; } } @@ -795,13 +715,19 @@ acpi_cpu_startup(void *arg) for (i = 0; i < cpu_ndevices; i++) { sc = device_get_softc(cpu_devices[i]); acpi_cpu_startup_cx(sc); - } - /* Add a sysctl handler to handle global Cx lowest setting */ - SYSCTL_ADD_PROC(&cpu_sysctl_ctx, SYSCTL_CHILDREN(cpu_sysctl_tree), - OID_AUTO, "cx_lowest", CTLTYPE_STRING | CTLFLAG_RW, - NULL, 0, acpi_cpu_global_cx_lowest_sysctl, "A", - "Global lowest Cx sleep state to use"); + if (sc->cpu_parent->glob_sysctl_tree != NULL) { + struct acpi_cpux_softc *cpux = sc->cpu_parent; + + /* Add a sysctl handler to handle global Cx lowest setting */ + SYSCTL_ADD_PROC(&cpux->glob_sysctl_ctx, + SYSCTL_CHILDREN(cpux->glob_sysctl_tree), + OID_AUTO, "cx_lowest", + CTLTYPE_STRING | CTLFLAG_RW, NULL, 0, + acpi_cpu_global_cx_lowest_sysctl, "A", + "Global lowest Cx sleep state to use"); + } + } /* Take over idling from cpu_idle_default(). */ cpu_cx_lowest = 0; @@ -833,20 +759,22 @@ acpi_cpu_cx_list(struct acpi_cpu_softc *sc) static void acpi_cpu_startup_cx(struct acpi_cpu_softc *sc) { + struct acpi_cpux_softc *cpux = sc->cpu_parent; + acpi_cpu_cx_list(sc); - SYSCTL_ADD_STRING(&sc->cpu_sysctl_ctx, - SYSCTL_CHILDREN(sc->cpu_sysctl_tree), + SYSCTL_ADD_STRING(&cpux->pcpu_sysctl_ctx, + SYSCTL_CHILDREN(cpux->pcpu_sysctl_tree), OID_AUTO, "cx_supported", CTLFLAG_RD, sc->cpu_cx_supported, 0, "Cx/microsecond values for supported Cx states"); - SYSCTL_ADD_PROC(&sc->cpu_sysctl_ctx, - SYSCTL_CHILDREN(sc->cpu_sysctl_tree), + SYSCTL_ADD_PROC(&cpux->pcpu_sysctl_ctx, + SYSCTL_CHILDREN(cpux->pcpu_sysctl_tree), OID_AUTO, "cx_lowest", CTLTYPE_STRING | CTLFLAG_RW, (void *)sc, 0, acpi_cpu_cx_lowest_sysctl, "A", "lowest Cx sleep state to use"); - SYSCTL_ADD_PROC(&sc->cpu_sysctl_ctx, - SYSCTL_CHILDREN(sc->cpu_sysctl_tree), + SYSCTL_ADD_PROC(&cpux->pcpu_sysctl_ctx, + SYSCTL_CHILDREN(cpux->pcpu_sysctl_tree), OID_AUTO, "cx_usage", CTLTYPE_STRING | CTLFLAG_RD, (void *)sc, 0, acpi_cpu_usage_sysctl, "A", "percent usage for each Cx state"); @@ -936,15 +864,6 @@ acpi_cpu_idle(void) * if BM control is available, otherwise flush the CPU cache. */ if (cx_next->type == ACPI_STATE_C3) { - if (atomic_fetchadd_int(&cpu_c3_ncpus, 1) == 0) { - /* - * When the first CPU enters C3 state, switch - * to an one shot timer, which could handle - * C3 state, i.e. the timer will not hang. - */ - cputimer_intr_switch(CPUTIMER_INTRT_C3); - } - if ((cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0) { AcpiSetRegister(ACPI_BITREG_ARB_DISABLE, 1); AcpiSetRegister(ACPI_BITREG_BUS_MASTER_RLD, 1); @@ -976,14 +895,6 @@ acpi_cpu_idle(void) AcpiSetRegister(ACPI_BITREG_ARB_DISABLE, 0); AcpiSetRegister(ACPI_BITREG_BUS_MASTER_RLD, 0); } - - if (atomic_fetchadd_int(&cpu_c3_ncpus, -1) == 1) { - /* - * All of the CPUs exit C3 state, use a better - * one shot timer. - */ - cputimer_intr_switch(CPUTIMER_INTRT_FAST); - } } ACPI_ENABLE_IRQS(); @@ -998,15 +909,12 @@ acpi_cpu_idle(void) * XXX Re-evaluation disabled until locking is done. */ static void -acpi_cpu_notify(ACPI_HANDLE h, UINT32 notify, void *context) +acpi_cpu_cst_notify(device_t dev) { - struct acpi_cpu_softc *sc = (struct acpi_cpu_softc *)context; + struct acpi_cpu_softc *sc = device_get_softc(dev); struct acpi_cpu_softc *isc; int i; - if (notify != ACPI_NOTIFY_CX_STATES) - return; - /* Update the list of Cx states. */ acpi_cpu_cx_cst(sc); acpi_cpu_cx_list(sc); @@ -1148,9 +1056,50 @@ acpi_cpu_usage_sysctl(SYSCTL_HANDLER_ARGS) static int acpi_cpu_set_cx_lowest(struct acpi_cpu_softc *sc, int val) { - int i; + int i, old_lowest, error = 0; + uint32_t old_type, type; + + get_mplock(); + + old_lowest = atomic_swap_int(&sc->cpu_cx_lowest, val); + + old_type = sc->cpu_cx_states[old_lowest].type; + type = sc->cpu_cx_states[val].type; + if (old_type == ACPI_STATE_C3 && type != ACPI_STATE_C3) { + KKASSERT(cpu_c3_ncpus > 0); + if (atomic_fetchadd_int(&cpu_c3_ncpus, -1) == 1) { + /* + * All of the CPUs exit C3 state, use a better + * one shot timer. + */ + error = cputimer_intr_select_caps(CPUTIMER_INTR_CAP_NONE); + KKASSERT(!error); + cputimer_intr_restart(); + } + } else if (type == ACPI_STATE_C3 && old_type != ACPI_STATE_C3) { + if (atomic_fetchadd_int(&cpu_c3_ncpus, 1) == 0) { + /* + * When the first CPU enters C3 state, switch + * to an one shot timer, which could handle + * C3 state, i.e. the timer will not hang. + */ + error = cputimer_intr_select_caps(CPUTIMER_INTR_CAP_PS); + if (!error) { + cputimer_intr_restart(); + } else { + kprintf("no suitable intr cuptimer found\n"); + + /* Restore */ + sc->cpu_cx_lowest = old_lowest; + atomic_fetchadd_int(&cpu_c3_ncpus, -1); + } + } + } - sc->cpu_cx_lowest = val; + rel_mplock(); + + if (error) + return error; /* If not disabling, cache the new lowest non-C3 state. */ sc->cpu_non_c3 = 0; @@ -1185,10 +1134,10 @@ acpi_cpu_cx_lowest_sysctl(SYSCTL_HANDLER_ARGS) return (EINVAL); crit_enter(); - acpi_cpu_set_cx_lowest(sc, val); + error = acpi_cpu_set_cx_lowest(sc, val); crit_exit(); - return (0); + return error; } static int @@ -1213,11 +1162,15 @@ acpi_cpu_global_cx_lowest_sysctl(SYSCTL_HANDLER_ARGS) crit_enter(); for (i = 0; i < cpu_ndevices; i++) { sc = device_get_softc(cpu_devices[i]); - acpi_cpu_set_cx_lowest(sc, val); + error = acpi_cpu_set_cx_lowest(sc, val); + if (error) { + KKASSERT(i == 0); + break; + } } crit_exit(); - return (0); + return error; } /* @@ -1244,4 +1197,3 @@ acpi_cpu_c1(void) #endif #endif /* !__ia64__ */ } - diff --git a/sys/dev/acpica5/acpi_cpu_pstate.c b/sys/dev/acpica5/acpi_cpu_pstate.c new file mode 100644 index 0000000000..6a35221f4d --- /dev/null +++ b/sys/dev/acpica5/acpi_cpu_pstate.c @@ -0,0 +1,994 @@ +/* + * Copyright (c) 2009 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Sepherosa Ziehau + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "opt_acpi.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "acpi.h" +#include "acpivar.h" +#include "acpi_cpu.h" +#include "acpi_cpu_pstate.h" + +#define ACPI_NPSTATE_MAX 16 + +#define ACPI_PSS_PX_NENTRY 6 + +#define ACPI_PSD_COORD_SWALL 0xfc +#define ACPI_PSD_COORD_SWANY 0xfd +#define ACPI_PSD_COORD_HWALL 0xfe +#define ACPI_PSD_COORD_VALID(coord) \ + ((coord) == ACPI_PSD_COORD_SWALL || \ + (coord) == ACPI_PSD_COORD_SWANY || \ + (coord) == ACPI_PSD_COORD_HWALL) + +struct acpi_pst_softc; +LIST_HEAD(acpi_pst_list, acpi_pst_softc); + +struct netmsg_acpi_pst { + struct netmsg nmsg; + + const ACPI_RESOURCE_GENERIC_REGISTER *ctrl; + const ACPI_RESOURCE_GENERIC_REGISTER *status; +}; + +struct acpi_pst_domain { + uint32_t pd_dom; + uint32_t pd_coord; + uint32_t pd_nproc; + LIST_ENTRY(acpi_pst_domain) pd_link; + + uint32_t pd_flags; + + int pd_state; + int pd_sstart; + struct acpi_pst_list pd_pstlist; + + struct sysctl_ctx_list pd_sysctl_ctx; + struct sysctl_oid *pd_sysctl_tree; +}; +LIST_HEAD(acpi_pst_domlist, acpi_pst_domain); + +#define ACPI_PSTDOM_FLAG_STUB 0x1 /* stub domain, no _PSD */ +#define ACPI_PSTDOM_FLAG_DEAD 0x2 /* domain can't be started */ + +struct acpi_pst_softc { + device_t pst_dev; + struct acpi_cpux_softc *pst_parent; + struct acpi_pst_domain *pst_domain; + ACPI_RESOURCE_GENERIC_REGISTER pst_creg; + ACPI_RESOURCE_GENERIC_REGISTER pst_sreg; + + int pst_state; + int pst_sstart; + int pst_cpuid; + + ACPI_HANDLE pst_handle; + + LIST_ENTRY(acpi_pst_softc) pst_link; +}; + +static int acpi_pst_probe(device_t dev); +static int acpi_pst_attach(device_t dev); + +static void acpi_pst_postattach(void *); +static struct acpi_pst_domain * + acpi_pst_domain_create(device_t, ACPI_OBJECT *); +static struct acpi_pst_domain * + acpi_pst_domain_find(uint32_t); +static struct acpi_pst_domain * + acpi_pst_domain_alloc(uint32_t, uint32_t, uint32_t); +static int acpi_pst_domain_set_pstate(struct acpi_pst_domain *, int); + +static int acpi_pst_check_csr(struct acpi_pst_softc *); +static int acpi_pst_check_pstates(struct acpi_pst_softc *); +static int acpi_pst_set_pstate(struct acpi_pst_softc *, + const struct acpi_pstate *); +static const struct acpi_pstate * + acpi_pst_get_pstate(struct acpi_pst_softc *); + +static void acpi_pst_check_csr_handler(struct netmsg *); +static void acpi_pst_check_pstates_handler(struct netmsg *); +static void acpi_pst_set_pstate_handler(struct netmsg *); +static void acpi_pst_get_pstate_handler(struct netmsg *); + +static int acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS); +static int acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS); +static int acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS); +static int acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS); + +static struct acpi_pst_domlist acpi_pst_domains = + LIST_HEAD_INITIALIZER(acpi_pst_domains); + +static int acpi_pst_global_state; + +static int acpi_npstates; +static struct acpi_pstate *acpi_pstates; + +static const struct acpi_pst_md *acpi_pst_md; + +static device_method_t acpi_pst_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, acpi_pst_probe), + DEVMETHOD(device_attach, acpi_pst_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus interface */ + DEVMETHOD(bus_add_child, bus_generic_add_child), + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), + DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), + DEVMETHOD(bus_get_resource_list, bus_generic_get_resource_list), + DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), + DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t acpi_pst_driver = { + "cpu_pst", + acpi_pst_methods, + sizeof(struct acpi_pst_softc) +}; + +static devclass_t acpi_pst_devclass; +DRIVER_MODULE(cpu_pst, cpu, acpi_pst_driver, acpi_pst_devclass, 0, 0); +MODULE_DEPEND(cpu_pst, acpi, 1, 1, 1); + +static __inline int +acpi_pst_freq2index(int freq) +{ + int i; + + for (i = 0; i < acpi_npstates; ++i) { + if (acpi_pstates[i].st_freq == freq) + return i; + } + return -1; +} + +static int +acpi_pst_probe(device_t dev) +{ + ACPI_BUFFER buf; + ACPI_HANDLE handle; + ACPI_STATUS status; + ACPI_OBJECT *obj; + + if (acpi_disabled("cpu_pst") || + acpi_get_type(dev) != ACPI_TYPE_PROCESSOR) + return ENXIO; + + if (acpi_pst_md == NULL) + acpi_pst_md = acpi_pst_md_probe(); + + handle = acpi_get_handle(dev); + + /* + * Check _PCT package + */ + buf.Pointer = NULL; + buf.Length = ACPI_ALLOCATE_BUFFER; + status = AcpiEvaluateObject(handle, "_PCT", NULL, &buf); + if (ACPI_FAILURE(status)) { + device_printf(dev, "Can't get _PCT package - %s\n", + AcpiFormatException(status)); + return ENXIO; + } + + obj = (ACPI_OBJECT *)buf.Pointer; + if (!ACPI_PKG_VALID_EQ(obj, 2)) { + device_printf(dev, "Invalid _PCT package\n"); + AcpiOsFree(obj); + return ENXIO; + } + AcpiOsFree(obj); + + /* + * Check _PSS package + */ + buf.Pointer = NULL; + buf.Length = ACPI_ALLOCATE_BUFFER; + status = AcpiEvaluateObject(handle, "_PSS", NULL, &buf); + if (ACPI_FAILURE(status)) { + device_printf(dev, "Can't get _PSS package - %s\n", + AcpiFormatException(status)); + return ENXIO; + } + + obj = (ACPI_OBJECT *)buf.Pointer; + if (!ACPI_PKG_VALID(obj, 1)) { + device_printf(dev, "Invalid _PSS package\n"); + AcpiOsFree(obj); + return ENXIO; + } + AcpiOsFree(obj); + + device_set_desc(dev, "ACPI CPU P-State"); + return 0; +} + +static int +acpi_pst_attach(device_t dev) +{ + struct acpi_pst_softc *sc = device_get_softc(dev), *pst; + struct acpi_pst_domain *dom = NULL; + ACPI_BUFFER buf; + ACPI_STATUS status; + ACPI_OBJECT *obj, *reg; + struct acpi_pstate *pstate, *p; + int i, npstate; + + sc->pst_dev = dev; + sc->pst_parent = device_get_softc(device_get_parent(dev)); + sc->pst_handle = acpi_get_handle(dev); + sc->pst_cpuid = acpi_get_magic(dev); + + /* + * If there is a _PSD, then we create procossor domain + * accordingly. If there is no _PSD, we just fake a + * default processor domain0. + */ + buf.Pointer = NULL; + buf.Length = ACPI_ALLOCATE_BUFFER; + status = AcpiEvaluateObject(sc->pst_handle, "_PSD", NULL, &buf); + if (!ACPI_FAILURE(status)) { + obj = (ACPI_OBJECT *)buf.Pointer; + if (ACPI_PKG_VALID_EQ(obj, 1)) { + dom = acpi_pst_domain_create(dev, + &obj->Package.Elements[0]); + if (dom == NULL) { + AcpiOsFree(obj); + return ENXIO; + } + } else { + device_printf(dev, "Invalid _PSD package\n"); + AcpiOsFree(obj); + return ENXIO; + } + + /* Free _PSD */ + AcpiOsFree(buf.Pointer); + } else { + /* Create a stub one processor domain */ + dom = acpi_pst_domain_alloc(0, ACPI_PSD_COORD_SWANY, 1); + dom->pd_flags |= ACPI_PSTDOM_FLAG_STUB; + } + + /* Make sure that adding us will not overflow our domain */ + i = 0; + LIST_FOREACH(pst, &dom->pd_pstlist, pst_link) + ++i; + if (i == dom->pd_nproc) { + device_printf(dev, "Domain%u already contains %d P-States, " + "invalid _PSD package\n", + dom->pd_dom, dom->pd_nproc); + return ENXIO; + } + + /* + * Get control/status registers from _PCT + */ + buf.Pointer = NULL; + buf.Length = ACPI_ALLOCATE_BUFFER; + status = AcpiEvaluateObject(sc->pst_handle, "_PCT", NULL, &buf); + if (ACPI_FAILURE(status)) { + device_printf(dev, "Can't get _PCT package - %s\n", + AcpiFormatException(status)); + return ENXIO; + } + + obj = (ACPI_OBJECT *)buf.Pointer; + if (!ACPI_PKG_VALID_EQ(obj, 2)) { + device_printf(dev, "Invalid _PCT package\n"); + AcpiOsFree(obj); + return ENXIO; + } + + /* Save control register */ + reg = &obj->Package.Elements[0]; + if (reg->Type != ACPI_TYPE_BUFFER || reg->Buffer.Pointer == NULL || + reg->Buffer.Length < sizeof(sc->pst_creg) + 3) + return ENXIO; + memcpy(&sc->pst_creg, reg->Buffer.Pointer + 3, sizeof(sc->pst_creg)); + if (bootverbose) { + device_printf(dev, "control reg %d %llx\n", + sc->pst_creg.SpaceId, sc->pst_creg.Address); + } + + /* Save status register */ + reg = &obj->Package.Elements[1]; + if (reg->Type != ACPI_TYPE_BUFFER || reg->Buffer.Pointer == NULL || + reg->Buffer.Length < sizeof(sc->pst_sreg) + 3) + return ENXIO; + memcpy(&sc->pst_sreg, reg->Buffer.Pointer + 3, sizeof(sc->pst_sreg)); + if (bootverbose) { + device_printf(dev, "status reg %d %llx\n", + sc->pst_sreg.SpaceId, sc->pst_sreg.Address); + } + + /* Free _PCT */ + AcpiOsFree(obj); + + /* + * Create P-State table according to _PSS + */ + buf.Pointer = NULL; + buf.Length = ACPI_ALLOCATE_BUFFER; + status = AcpiEvaluateObject(sc->pst_handle, "_PSS", NULL, &buf); + if (ACPI_FAILURE(status)) { + device_printf(dev, "Can't get _PSS package - %s\n", + AcpiFormatException(status)); + return ENXIO; + } + + obj = (ACPI_OBJECT *)buf.Pointer; + if (!ACPI_PKG_VALID(obj, 1)) { + device_printf(dev, "Invalid _PSS package\n"); + AcpiOsFree(obj); + return ENXIO; + } + + /* Don't create too many P-States */ + npstate = obj->Package.Count; + if (npstate > ACPI_NPSTATE_MAX) { + device_printf(dev, "Too many P-States, %d->%d\n", + npstate, ACPI_NPSTATE_MAX); + npstate = ACPI_NPSTATE_MAX; + } + + /* + * If we have already created P-State table, + * we must make sure that number of entries + * is consistent. + */ + if (acpi_pstates != NULL && acpi_npstates != npstate) { + device_printf(dev, "Inconsistent # of P-States " + "cross Processor objects\n"); + AcpiOsFree(obj); + return ENXIO; + } + + /* + * Create a temporary P-State table + */ + pstate = kmalloc(sizeof(*pstate) * npstate, M_TEMP, M_WAITOK); + for (i = 0, p = pstate; i < npstate; ++i, ++p) { + ACPI_OBJECT *pkg; + uint32_t *ptr[ACPI_PSS_PX_NENTRY] = { + &p->st_freq, &p->st_power, &p->st_xsit_lat, + &p->st_bm_lat, &p->st_cval, &p->st_sval + }; + int j; + + pkg = &obj->Package.Elements[i]; + if (!ACPI_PKG_VALID(pkg, ACPI_PSS_PX_NENTRY)) { + device_printf(dev, "Invalud _PSS P%d\n", i); + AcpiOsFree(obj); + kfree(pstate, M_TEMP); + return ENXIO; + } + for (j = 0; j < ACPI_PSS_PX_NENTRY; ++j) { + if (acpi_PkgInt32(pkg, j, ptr[j]) != 0) { + device_printf(dev, "Can't extract " + "_PSS P%d %dth entry\n", i, j); + AcpiOsFree(obj); + kfree(pstate, M_TEMP); + return ENXIO; + } + } + } + + /* Free _PSS */ + AcpiOsFree(obj); + + if (acpi_pstates == NULL) { + /* + * If no P-State table is created yet, + * save the temporary one we just created. + */ + acpi_pstates = pstate; + acpi_npstates = npstate; + pstate = NULL; + + if (bootverbose) { + for (i = 0; i < acpi_npstates; ++i) { + device_printf(dev, + "freq %u, pwr %u, xlat %u, blat %u, " + "cv %08x, sv %08x\n", + acpi_pstates[i].st_freq, + acpi_pstates[i].st_power, + acpi_pstates[i].st_xsit_lat, + acpi_pstates[i].st_bm_lat, + acpi_pstates[i].st_cval, + acpi_pstates[i].st_sval); + } + } + } else { + /* + * Make sure that P-State tables are same + * for all processors. + */ + if (memcmp(pstate, acpi_pstates, + sizeof(*pstate) * npstate) != 0) { + device_printf(dev, "Inconsistent _PSS " + "cross Processor objects\n"); + kfree(pstate, M_TEMP); + return ENXIO; + } + kfree(pstate, M_TEMP); + } + + /* By default, we start from P-State table's first entry */ + sc->pst_sstart = 0; + + /* + * Adjust the usable first entry of P-State table, + * if there is _PPC object. + */ + buf.Pointer = NULL; + buf.Length = ACPI_ALLOCATE_BUFFER; + status = AcpiEvaluateObject(sc->pst_handle, "_PPC", NULL, &buf); + if (!ACPI_FAILURE(status)) { + obj = (ACPI_OBJECT *)buf.Pointer; + if (obj->Type == ACPI_TYPE_INTEGER) { + if (obj->Integer.Value >= acpi_npstates) { + device_printf(dev, "Invalid _PPC value\n"); + AcpiOsFree(obj); + return ENXIO; + } + sc->pst_sstart = obj->Integer.Value; + if (bootverbose) + device_printf(dev, "_PPC %d\n", sc->pst_sstart); + + /* TODO: Install notifiy handler */ + } else { + device_printf(dev, "Invalid _PPC object\n"); + AcpiOsFree(obj); + return ENXIO; + } + + /* Free _PPC */ + AcpiOsFree(obj); + } + + sc->pst_state = sc->pst_sstart; + + /* Link us with the domain */ + sc->pst_domain = dom; + LIST_INSERT_HEAD(&dom->pd_pstlist, sc, pst_link); + + if (device_get_unit(dev) == 0) + AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_pst_postattach, NULL); + + return 0; +} + +static struct acpi_pst_domain * +acpi_pst_domain_create(device_t dev, ACPI_OBJECT *obj) +{ + struct acpi_pst_domain *dom; + uint32_t val, domain, coord, nproc; + + if (!ACPI_PKG_VALID_EQ(obj, 5)) { + device_printf(dev, "Invalid _PSD package\n"); + return NULL; + } + + /* NumberOfEntries */ + if (acpi_PkgInt32(obj, 0, &val) != 0 || val != 5) { + device_printf(dev, "Invalid _PSD NumberOfEntries\n"); + return NULL; + } + + /* Revision */ + if (acpi_PkgInt32(obj, 1, &val) != 0 || val != 0) { + device_printf(dev, "Invalid _PSD Revision\n"); + return NULL; + } + + if (acpi_PkgInt32(obj, 2, &domain) != 0 || + acpi_PkgInt32(obj, 3, &coord) != 0 || + acpi_PkgInt32(obj, 4, &nproc) != 0) { + device_printf(dev, "Can't extract _PSD package\n"); + return NULL; + } + + /* + * If NumProcessors is greater than MAXCPU, + * then we will never start all CPUs within + * this domain, and power state transition + * will never happen, so we just bail out + * here. + */ + if (nproc > MAXCPU) { + device_printf(dev, "Unsupported _PSD NumProcessors (%d)\n", + nproc); + return NULL; + } else if (nproc == 0) { + device_printf(dev, "_PSD NumProcessors are zero\n"); + return NULL; + } + + if (!ACPI_PSD_COORD_VALID(coord)) { + device_printf(dev, "Invalid _PSD CoordType (%#x)\n", coord); + return NULL; + } + + dom = acpi_pst_domain_find(domain); + if (dom != NULL) { + if (dom->pd_coord != coord || dom->pd_nproc != nproc) { + device_printf(dev, "Inconsistent _PSD information " + "cross Processor objects\n"); + return NULL; + } + return dom; + } + + dom = acpi_pst_domain_alloc(domain, coord, nproc); + if (bootverbose) + device_printf(dev, "create domain%u\n", dom->pd_dom); + + return dom; +} + +static struct acpi_pst_domain * +acpi_pst_domain_find(uint32_t domain) +{ + struct acpi_pst_domain *dom; + + LIST_FOREACH(dom, &acpi_pst_domains, pd_link) { + if (dom->pd_flags & ACPI_PSTDOM_FLAG_STUB) + continue; + if (dom->pd_dom == domain) + return dom; + } + return NULL; +} + +static struct acpi_pst_domain * +acpi_pst_domain_alloc(uint32_t domain, uint32_t coord, uint32_t nproc) +{ + struct acpi_pst_domain *dom; + + dom = kmalloc(sizeof(*dom), M_DEVBUF, M_WAITOK | M_ZERO); + dom->pd_dom = domain; + dom->pd_coord = coord; + dom->pd_nproc = nproc; + dom->pd_state = 0; /* XXX */ + dom->pd_sstart = 0; /* XXX */ + LIST_INIT(&dom->pd_pstlist); + + LIST_INSERT_HEAD(&acpi_pst_domains, dom, pd_link); + + return dom; +} + +static int +acpi_pst_domain_set_pstate(struct acpi_pst_domain *dom, int i) +{ + const struct acpi_pstate *pstate; + struct acpi_pst_softc *sc; + int done, error; + + KKASSERT(i >= 0 && i < acpi_npstates); + pstate = &acpi_pstates[i]; + + done = 0; + LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) { + if (!done) { + error = acpi_pst_set_pstate(sc, pstate); + if (error) { + device_printf(sc->pst_dev, "can't set " + "freq %d\n", pstate->st_freq); + /* XXX error cleanup? */ + } + if (dom->pd_coord == ACPI_PSD_COORD_SWANY) + done = 1; + } + sc->pst_state = i; + } + dom->pd_state = i; + + return 0; +} + +static void +acpi_pst_postattach(void *arg __unused) +{ + struct acpi_pst_domain *dom; + struct acpi_cpux_softc *cpux; + device_t *devices; + int i, ndevices, error, has_domain; + + devices = NULL; + ndevices = 0; + error = devclass_get_devices(acpi_pst_devclass, &devices, &ndevices); + if (error) + return; + + if (ndevices == 0) + return; + + cpux = NULL; + for (i = 0; i < ndevices; ++i) { + cpux = device_get_softc(device_get_parent(devices[i])); + if (cpux->glob_sysctl_tree != NULL) + break; + } + kfree(devices, M_TEMP); + KKASSERT(cpux != NULL); + + if (acpi_pst_md == NULL) + kprintf("ACPI: no P-State CPU driver\n"); + + has_domain = 0; + LIST_FOREACH(dom, &acpi_pst_domains, pd_link) { + struct acpi_pst_softc *sc; + char buf[32]; + + /* + * Make sure that all processors belonging to this + * domain are located. + */ + i = 0; + LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) + ++i; + if (i != dom->pd_nproc) { + kprintf("ACPI: domain%u misses processors, " + "should be %d, got %d\n", dom->pd_dom, + dom->pd_nproc, i); + dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD; + continue; + } + + /* + * Validate P-State configurations for this domain + */ + LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) { + error = acpi_pst_check_csr(sc); + if (error) + break; + + error = acpi_pst_check_pstates(sc); + if (error) + break; + } + if (sc != NULL) { + kprintf("ACPI: domain%u P-State configuration " + "check failed\n", dom->pd_dom); + dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD; + continue; + } + + has_domain = 1; + + ksnprintf(buf, sizeof(buf), "px_dom%u", dom->pd_dom); + + sysctl_ctx_init(&dom->pd_sysctl_ctx); + dom->pd_sysctl_tree = + SYSCTL_ADD_NODE(&dom->pd_sysctl_ctx, + SYSCTL_CHILDREN(cpux->glob_sysctl_tree), + OID_AUTO, buf, CTLFLAG_RD, 0, + "P-State domain"); + if (dom->pd_sysctl_tree == NULL) { + kprintf("ACPI: Can't create sysctl tree for domain%u", + dom->pd_dom); + continue; + } + + SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx, + SYSCTL_CHILDREN(dom->pd_sysctl_tree), + OID_AUTO, "available", + CTLTYPE_STRING | CTLFLAG_RD, + dom, 0, acpi_pst_sysctl_freqs, "A", + "available frequencies"); + + SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx, + SYSCTL_CHILDREN(dom->pd_sysctl_tree), + OID_AUTO, "members", + CTLTYPE_STRING | CTLFLAG_RD, + dom, 0, acpi_pst_sysctl_members, "A", + "member cpus"); + + if (acpi_pst_md != NULL && + acpi_pst_md->pmd_set_pstate != NULL) { + SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx, + SYSCTL_CHILDREN(dom->pd_sysctl_tree), + OID_AUTO, "select", + CTLTYPE_UINT | CTLFLAG_RW, + dom, 0, acpi_pst_sysctl_select, + "IU", "select freq"); + } + } + + if (has_domain && acpi_pst_md != NULL && + acpi_pst_md->pmd_set_pstate != NULL) { + SYSCTL_ADD_PROC(&cpux->glob_sysctl_ctx, + SYSCTL_CHILDREN(cpux->glob_sysctl_tree), + OID_AUTO, "px_global", + CTLTYPE_UINT | CTLFLAG_RW, + NULL, 0, acpi_pst_sysctl_global, + "IU", "select freq for all domains"); + } +} + +static int +acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS) +{ + struct acpi_pst_domain *dom = arg1; + int i, error; + + error = 0; + for (i = 0; i < acpi_npstates; ++i) { + if (error == 0 && i) + error = SYSCTL_OUT(req, " ", 1); + if (error == 0) { + const char *pat; + char buf[32]; + + if (i < dom->pd_sstart) + pat = "(%u)"; + else + pat = "%u"; + + ksnprintf(buf, sizeof(buf), pat, + acpi_pstates[i].st_freq); + error = SYSCTL_OUT(req, buf, strlen(buf)); + } + } + return error; +} + +static int +acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS) +{ + struct acpi_pst_domain *dom = arg1; + struct acpi_pst_softc *sc; + int loop, error; + + loop = error = 0; + LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) { + char buf[32]; + + if (error == 0 && loop) + error = SYSCTL_OUT(req, " ", 1); + if (error == 0) { + ksnprintf(buf, sizeof(buf), "cpu%d", sc->pst_cpuid); + error = SYSCTL_OUT(req, buf, strlen(buf)); + } + + if (error == 0 && acpi_pst_md && acpi_pst_md->pmd_get_pstate) { + const struct acpi_pstate *pstate; + const char *str; + + pstate = acpi_pst_get_pstate(sc); + if (pstate == NULL) { + str = "(*)"; + } else { + ksnprintf(buf, sizeof(buf), "(%d)", + pstate->st_freq); + str = buf; + } + error = SYSCTL_OUT(req, str, strlen(str)); + } + ++loop; + } + return error; +} + +static int +acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS) +{ + struct acpi_pst_domain *dom = arg1; + int error, i, freq; + + KKASSERT(dom->pd_state >= 0 && dom->pd_state < acpi_npstates); + + freq = acpi_pstates[dom->pd_state].st_freq; + + error = sysctl_handle_int(oidp, &freq, 0, req); + if (error || req->newptr == NULL) + return error; + + i = acpi_pst_freq2index(freq); + if (i < 0) + return EINVAL; + + acpi_pst_domain_set_pstate(dom, i); + return 0; +} + +static int +acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS) +{ + struct acpi_pst_domain *dom; + int error, i, freq; + + KKASSERT(acpi_pst_global_state >= 0 && + acpi_pst_global_state < acpi_npstates); + + freq = acpi_pstates[acpi_pst_global_state].st_freq; + + error = sysctl_handle_int(oidp, &freq, 0, req); + if (error || req->newptr == NULL) + return error; + + i = acpi_pst_freq2index(freq); + if (i < 0) + return EINVAL; + + LIST_FOREACH(dom, &acpi_pst_domains, pd_link) { + /* Skip dead domain */ + if (dom->pd_flags & ACPI_PSTDOM_FLAG_DEAD) + continue; + acpi_pst_domain_set_pstate(dom, i); + } + acpi_pst_global_state = i; + + return 0; +} + +static void +acpi_pst_check_csr_handler(struct netmsg *nmsg) +{ + struct netmsg_acpi_pst *msg = (struct netmsg_acpi_pst *)nmsg; + int error; + + error = acpi_pst_md->pmd_check_csr(msg->ctrl, msg->status); + lwkt_replymsg(&nmsg->nm_lmsg, error); +} + +static int +acpi_pst_check_csr(struct acpi_pst_softc *sc) +{ + struct netmsg_acpi_pst msg; + + if (acpi_pst_md == NULL) + return 0; + + netmsg_init(&msg.nmsg, &curthread->td_msgport, + MSGF_MPSAFE | MSGF_PRIORITY, + acpi_pst_check_csr_handler); + msg.ctrl = &sc->pst_creg; + msg.status = &sc->pst_sreg; + + return lwkt_domsg(cpu_portfn(sc->pst_cpuid), &msg.nmsg.nm_lmsg, 0); +} + +static void +acpi_pst_check_pstates_handler(struct netmsg *nmsg) +{ + int error; + + error = acpi_pst_md->pmd_check_pstates(acpi_pstates, acpi_npstates); + lwkt_replymsg(&nmsg->nm_lmsg, error); +} + +static int +acpi_pst_check_pstates(struct acpi_pst_softc *sc) +{ + struct netmsg nmsg; + + if (acpi_pst_md == NULL) + return 0; + + netmsg_init(&nmsg, &curthread->td_msgport, + MSGF_MPSAFE | MSGF_PRIORITY, + acpi_pst_check_pstates_handler); + + return lwkt_domsg(cpu_portfn(sc->pst_cpuid), &nmsg.nm_lmsg, 0); +} + +static void +acpi_pst_set_pstate_handler(struct netmsg *nmsg) +{ + struct netmsg_acpi_pst *msg = (struct netmsg_acpi_pst *)nmsg; + int error; + + error = acpi_pst_md->pmd_set_pstate(msg->ctrl, msg->status, + nmsg->nm_lmsg.u.ms_resultp); + lwkt_replymsg(&nmsg->nm_lmsg, error); +} + +static int +acpi_pst_set_pstate(struct acpi_pst_softc *sc, const struct acpi_pstate *pstate) +{ + struct netmsg_acpi_pst msg; + + KKASSERT(acpi_pst_md != NULL); + + if (bootverbose) { + device_printf(sc->pst_dev, "set pstate, freq %d\n", + pstate->st_freq); + } + + netmsg_init(&msg.nmsg, &curthread->td_msgport, + MSGF_MPSAFE | MSGF_PRIORITY, + acpi_pst_set_pstate_handler); + msg.nmsg.nm_lmsg.u.ms_resultp = __DECONST(void *, pstate); + msg.ctrl = &sc->pst_creg; + msg.status = &sc->pst_sreg; + + return lwkt_domsg(cpu_portfn(sc->pst_cpuid), &msg.nmsg.nm_lmsg, 0); +} + +static void +acpi_pst_get_pstate_handler(struct netmsg *nmsg) +{ + struct netmsg_acpi_pst *msg = (struct netmsg_acpi_pst *)nmsg; + const struct acpi_pstate *pstate; + + pstate = acpi_pst_md->pmd_get_pstate(msg->status, acpi_pstates, + acpi_npstates); + nmsg->nm_lmsg.u.ms_resultp = __DECONST(void *, pstate); + lwkt_replymsg(&nmsg->nm_lmsg, 0); +} + +static const struct acpi_pstate * +acpi_pst_get_pstate(struct acpi_pst_softc *sc) +{ + struct netmsg_acpi_pst msg; + + if (acpi_pst_md == NULL) + return 0; + + netmsg_init(&msg.nmsg, &curthread->td_msgport, + MSGF_MPSAFE | MSGF_PRIORITY, + acpi_pst_get_pstate_handler); + msg.status = &sc->pst_sreg; + + lwkt_domsg(cpu_portfn(sc->pst_cpuid), &msg.nmsg.nm_lmsg, 0); + return msg.nmsg.nm_lmsg.u.ms_resultp; +} diff --git a/sys/platform/vkernel/include/cothread.h b/sys/dev/acpica5/acpi_cpu_pstate.h similarity index 64% copy from sys/platform/vkernel/include/cothread.h copy to sys/dev/acpica5/acpi_cpu_pstate.h index 850fddafdd..8df0dcf9ed 100644 --- a/sys/platform/vkernel/include/cothread.h +++ b/sys/dev/acpica5/acpi_cpu_pstate.h @@ -1,13 +1,13 @@ /* - * Copyright (c) 2008 The DragonFly Project. All rights reserved. - * + * Copyright (c) 2009 The DragonFly Project. All rights reserved. + * * This code is derived from software contributed to The DragonFly Project - * by Matthew Dillon - * + * by Sepherosa Ziehau + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -17,7 +17,7 @@ * 3. Neither the name of The DragonFly Project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific, prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -30,34 +30,37 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $DragonFly: src/sys/platform/vkernel/include/cothread.h,v 1.2 2008/03/27 04:28:07 dillon Exp $ */ -#ifndef _MACHINE_COTHREAD_H_ -#define _MACHINE_COTHREAD_H_ +#ifndef __ACPI_CPU_PSTATE_H__ +#define __ACPI_CPU_PSTATE_H__ -#include - -struct cothread { - pthread_t pthr; - pthread_t pintr; - void *arg; - void (*thr_func)(struct cothread *); - void (*thr_intr)(struct cothread *); - pthread_mutex_t mutex; - pthread_cond_t cond; +struct acpi_pstate { + uint32_t st_freq; + uint32_t st_power; + uint32_t st_xsit_lat; + uint32_t st_bm_lat; + uint32_t st_cval; + uint32_t st_sval; }; -typedef struct cothread *cothread_t; +struct acpi_pst_md { + int (*pmd_check_csr) + (const ACPI_RESOURCE_GENERIC_REGISTER *, + const ACPI_RESOURCE_GENERIC_REGISTER *); + int (*pmd_check_pstates) + (const struct acpi_pstate *, int); + + int (*pmd_set_pstate) + (const ACPI_RESOURCE_GENERIC_REGISTER *, + const ACPI_RESOURCE_GENERIC_REGISTER *, + const struct acpi_pstate *); + + const struct acpi_pstate *(*pmd_get_pstate) + (const ACPI_RESOURCE_GENERIC_REGISTER *, + const struct acpi_pstate *, int); +}; -cothread_t cothread_create(void (*thr_func)(cothread_t cotd), - void (*thr_intr)(cothread_t cotd), - void *arg, const char *name); -void cothread_intr(cothread_t cotd); -void cothread_signal(cothread_t cotd); -void cothread_wait(cothread_t cotd); -void cothread_lock(cothread_t cotd); -void cothread_unlock(cothread_t cotd); +const struct acpi_pst_md *acpi_pst_md_probe(void); -#endif +#endif /* !__ACPI_CPU_PSTATE_H__ */ diff --git a/sys/dev/acpica5/acpivar.h b/sys/dev/acpica5/acpivar.h index 120afd11d1..422a55f7af 100644 --- a/sys/dev/acpica5/acpivar.h +++ b/sys/dev/acpica5/acpivar.h @@ -361,9 +361,12 @@ void acpi_ec_ecdt_probe(device_t); int acpi_acad_get_acline(int *); /* Package manipulation convenience functions. */ -#define ACPI_PKG_VALID(pkg, size) \ - ((pkg) != NULL && (pkg)->Type == ACPI_TYPE_PACKAGE && \ - (pkg)->Package.Count >= (size)) +#define _ACPI_PKG_VALID(pkg) \ + ((pkg) != NULL && (pkg)->Type == ACPI_TYPE_PACKAGE) +#define ACPI_PKG_VALID(pkg, size) \ + (_ACPI_PKG_VALID((pkg)) && (pkg)->Package.Count >= (size)) +#define ACPI_PKG_VALID_EQ(pkg, size) \ + (_ACPI_PKG_VALID((pkg)) && (pkg)->Package.Count == (size)) int acpi_PkgInt(ACPI_OBJECT *res, int idx, ACPI_INTEGER *dst); int acpi_PkgInt32(ACPI_OBJECT *res, int idx, uint32_t *dst); int acpi_PkgStr(ACPI_OBJECT *res, int idx, void *dst, size_t size); diff --git a/sys/dev/disk/Makefile b/sys/dev/disk/Makefile index d0079584d2..983cfd562f 100644 --- a/sys/dev/disk/Makefile +++ b/sys/dev/disk/Makefile @@ -3,7 +3,7 @@ .include "${.CURDIR}/../../platform/${MACHINE_PLATFORM}/Makefile.inc" -SUBDIR= aha aic aic7xxx ccd ispfw md ncv nsp sbp stg trm vn vpo +SUBDIR= aha ahci aic aic7xxx ccd ispfw md ncv nsp sbp stg trm vn vpo .for dir in ${SUBDIR} .if empty(DEV_SUPPORT:Mdisk) && \ diff --git a/sys/dev/disk/ahci/Makefile b/sys/dev/disk/ahci/Makefile new file mode 100644 index 0000000000..401f6904c8 --- /dev/null +++ b/sys/dev/disk/ahci/Makefile @@ -0,0 +1,10 @@ +# Native AHCI driver, ported from OpenBSD +# +KMOD= ahci + +.PATH: ${.CURDIR} + +SRCS= ahci_dragonfly.c ahci_attach.c ahci_cam.c ahci.c \ + bus_if.h device_if.h pci_if.h opt_scsi.h opt_cam.h + +.include diff --git a/sys/dev/disk/ahci/TODO b/sys/dev/disk/ahci/TODO new file mode 100644 index 0000000000..b2e5dbb603 --- /dev/null +++ b/sys/dev/disk/ahci/TODO @@ -0,0 +1,25 @@ + +DELAY's might tsleep, so interrupts might run. fix poll loop to detect +completion via other interrupts. + +Locking serialize_enter/exit. Lots of recursion. Needs help. Use +lockmgr()? Needs to be converted to per-port locking, also. + +Port multiplier support. + +Simulate various mode pages (serial number access and so forth). + +------ Misc probe info -------- + + port +, +6 ports, 32 tags/port, gen 1 (1.5Gbps) and 2 (3Gbps) + +ahci0: AHCI 1.2 capabilities 0xe3229f05 +, 6 ports, 32 tags/port, gen 1 (1.5Gbps) and 2 (3Gbps) + + +Chipsets supporting FBSS (FIS-Based Switching): + SB800 + S5000 (w/ ESB2) + (add more) diff --git a/sys/dev/disk/ahci/ahci.c b/sys/dev/disk/ahci/ahci.c new file mode 100644 index 0000000000..cb3b128106 --- /dev/null +++ b/sys/dev/disk/ahci/ahci.c @@ -0,0 +1,1981 @@ +/* + * Copyright (c) 2006 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * Copyright (c) 2009 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $OpenBSD: ahci.c,v 1.147 2009/02/16 21:19:07 miod Exp $ + */ + +#include "ahci.h" + +int ahci_port_init(struct ahci_port *ap); +int ahci_port_start(struct ahci_port *, int); +int ahci_port_stop(struct ahci_port *, int); +int ahci_port_clo(struct ahci_port *); + +int ahci_port_signature_detect(struct ahci_port *ap); +int ahci_load_prdt(struct ahci_ccb *); +void ahci_unload_prdt(struct ahci_ccb *); +static void ahci_load_prdt_callback(void *info, bus_dma_segment_t *segs, + int nsegs, int error); +int ahci_poll(struct ahci_ccb *, int, void (*)(void *)); +void ahci_start(struct ahci_ccb *); + +static void ahci_ata_cmd_timeout_unserialized(void *arg); +static void ahci_ata_cmd_timeout(void *arg); + +void ahci_issue_pending_ncq_commands(struct ahci_port *); +void ahci_issue_pending_commands(struct ahci_port *, int); + +struct ahci_ccb *ahci_get_ccb(struct ahci_port *); +void ahci_put_ccb(struct ahci_ccb *); + +struct ahci_ccb *ahci_get_err_ccb(struct ahci_port *); +void ahci_put_err_ccb(struct ahci_ccb *); + +int ahci_port_read_ncq_error(struct ahci_port *, int *); + +struct ahci_dmamem *ahci_dmamem_alloc(struct ahci_softc *, bus_dma_tag_t tag); +void ahci_dmamem_free(struct ahci_softc *, struct ahci_dmamem *); +static void ahci_dmamem_saveseg(void *info, bus_dma_segment_t *segs, int nsegs, int error); + +void ahci_empty_done(struct ahci_ccb *ccb); +void ahci_ata_cmd_done(struct ahci_ccb *ccb); + +/* Wait for all bits in _b to be cleared */ +#define ahci_pwait_clr(_ap, _r, _b) \ + ahci_pwait_eq((_ap), AHCI_PWAIT_TIMEOUT, (_r), (_b), 0) +#define ahci_pwait_clr_to(_ap, _to, _r, _b) \ + ahci_pwait_eq((_ap), _to, (_r), (_b), 0) + +/* Wait for all bits in _b to be set */ +#define ahci_pwait_set(_ap, _r, _b) \ + ahci_pwait_eq((_ap), AHCI_PWAIT_TIMEOUT, (_r), (_b), (_b)) +#define ahci_pwait_set_to(_ap, _to, _r, _b) \ + ahci_pwait_eq((_ap), _to, (_r), (_b), (_b)) + +#define AHCI_PWAIT_TIMEOUT 1000 + +/* + * Initialize the global AHCI hardware. This code does not set up any of + * its ports. + */ +int +ahci_init(struct ahci_softc *sc) +{ + u_int32_t cap, pi; + + DPRINTF(AHCI_D_VERBOSE, " GHC 0x%b", + ahci_read(sc, AHCI_REG_GHC), AHCI_FMT_GHC); + + /* save BIOS initialised parameters, enable staggered spin up */ + cap = ahci_read(sc, AHCI_REG_CAP); + cap &= AHCI_REG_CAP_SMPS; + cap |= AHCI_REG_CAP_SSS; + pi = ahci_read(sc, AHCI_REG_PI); + + if (AHCI_REG_GHC_AE & ahci_read(sc, AHCI_REG_GHC)) { + /* reset the controller */ + ahci_write(sc, AHCI_REG_GHC, AHCI_REG_GHC_HR); + if (ahci_wait_ne(sc, AHCI_REG_GHC, AHCI_REG_GHC_HR, + AHCI_REG_GHC_HR) != 0) { + device_printf(sc->sc_dev, + "unable to reset controller\n"); + return (1); + } + } + + /* enable ahci (global interrupts disabled) */ + ahci_write(sc, AHCI_REG_GHC, AHCI_REG_GHC_AE); + + /* restore parameters */ + ahci_write(sc, AHCI_REG_CAP, cap); + ahci_write(sc, AHCI_REG_PI, pi); + + return (0); +} + +/* + * Allocate and initialize an AHCI port. + */ +int +ahci_port_alloc(struct ahci_softc *sc, u_int port) +{ + struct ahci_port *ap; + struct ahci_ccb *ccb; + u_int64_t dva; + u_int32_t cmd; + struct ahci_cmd_hdr *hdr; + struct ahci_cmd_table *table; + int rc = ENOMEM; + int error; + int i; + + ap = kmalloc(sizeof(*ap), M_DEVBUF, M_WAITOK | M_ZERO); + if (ap == NULL) { + device_printf(sc->sc_dev, + "unable to allocate memory for port %d\n", + port); + goto reterr; + } + + ksnprintf(ap->ap_name, sizeof(ap->ap_name), "%s%d.%d", + device_get_name(sc->sc_dev), + device_get_unit(sc->sc_dev), + port); + sc->sc_ports[port] = ap; + + if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, + AHCI_PORT_REGION(port), AHCI_PORT_SIZE, &ap->ap_ioh) != 0) { + device_printf(sc->sc_dev, + "unable to create register window for port %d\n", + port); + goto freeport; + } + + ap->ap_sc = sc; + ap->ap_num = port; + TAILQ_INIT(&ap->ap_ccb_free); + TAILQ_INIT(&ap->ap_ccb_pending); + lockinit(&ap->ap_ccb_lock, "ahcipo", 0, 0); + + /* Disable port interrupts */ + ahci_pwrite(ap, AHCI_PREG_IE, 0); + + /* Sec 10.1.2 - deinitialise port if it is already running */ + cmd = ahci_pread(ap, AHCI_PREG_CMD); + if ((cmd & (AHCI_PREG_CMD_ST | AHCI_PREG_CMD_CR | + AHCI_PREG_CMD_FRE | AHCI_PREG_CMD_FR)) || + (ahci_pread(ap, AHCI_PREG_SCTL) & AHCI_PREG_SCTL_DET)) { + int r; + + r = ahci_port_stop(ap, 1); + if (r) { + device_printf(sc->sc_dev, + "unable to disable %s, ignoring port %d\n", + ((r == 2) ? "CR" : "FR"), port); + rc = ENXIO; + goto freeport; + } + + /* Write DET to zero */ + ahci_pwrite(ap, AHCI_PREG_SCTL, 0); + } + + /* Allocate RFIS */ + ap->ap_dmamem_rfis = ahci_dmamem_alloc(sc, sc->sc_tag_rfis); + if (ap->ap_dmamem_rfis == NULL) { + kprintf("NORFIS\n"); + goto nomem; + } + + /* Setup RFIS base address */ + ap->ap_rfis = (struct ahci_rfis *) AHCI_DMA_KVA(ap->ap_dmamem_rfis); + dva = AHCI_DMA_DVA(ap->ap_dmamem_rfis); + ahci_pwrite(ap, AHCI_PREG_FBU, (u_int32_t)(dva >> 32)); + ahci_pwrite(ap, AHCI_PREG_FB, (u_int32_t)dva); + + /* Enable FIS reception and activate port. */ + cmd = ahci_pread(ap, AHCI_PREG_CMD) & ~AHCI_PREG_CMD_ICC; + cmd |= AHCI_PREG_CMD_FRE | AHCI_PREG_CMD_POD | AHCI_PREG_CMD_SUD; + ahci_pwrite(ap, AHCI_PREG_CMD, cmd | AHCI_PREG_CMD_ICC_ACTIVE); + + /* Check whether port activated. Skip it if not. */ + cmd = ahci_pread(ap, AHCI_PREG_CMD) & ~AHCI_PREG_CMD_ICC; + if ((cmd & AHCI_PREG_CMD_FRE) == 0) { + kprintf("NOT-ACTIVATED\n"); + rc = ENXIO; + goto freeport; + } + + /* Allocate a CCB for each command slot */ + ap->ap_ccbs = kmalloc(sizeof(struct ahci_ccb) * sc->sc_ncmds, M_DEVBUF, + M_WAITOK | M_ZERO); + if (ap->ap_ccbs == NULL) { + device_printf(sc->sc_dev, + "unable to allocate command list for port %d\n", + port); + goto freeport; + } + + /* Command List Structures and Command Tables */ + ap->ap_dmamem_cmd_list = ahci_dmamem_alloc(sc, sc->sc_tag_cmdh); + ap->ap_dmamem_cmd_table = ahci_dmamem_alloc(sc, sc->sc_tag_cmdt); + if (ap->ap_dmamem_cmd_table == NULL || + ap->ap_dmamem_cmd_list == NULL) { +nomem: + device_printf(sc->sc_dev, + "unable to allocate DMA memory for port %d\n", + port); + goto freeport; + } + + /* Setup command list base address */ + dva = AHCI_DMA_DVA(ap->ap_dmamem_cmd_list); + ahci_pwrite(ap, AHCI_PREG_CLBU, (u_int32_t)(dva >> 32)); + ahci_pwrite(ap, AHCI_PREG_CLB, (u_int32_t)dva); + + /* Split CCB allocation into CCBs and assign to command header/table */ + hdr = AHCI_DMA_KVA(ap->ap_dmamem_cmd_list); + table = AHCI_DMA_KVA(ap->ap_dmamem_cmd_table); + for (i = 0; i < sc->sc_ncmds; i++) { + ccb = &ap->ap_ccbs[i]; + + error = bus_dmamap_create(sc->sc_tag_data, BUS_DMA_ALLOCNOW, + &ccb->ccb_dmamap); + if (error) { + device_printf(sc->sc_dev, + "unable to create dmamap for port %d " + "ccb %d\n", port, i); + goto freeport; + } + + callout_init(&ccb->ccb_timeout); + ccb->ccb_slot = i; + ccb->ccb_port = ap; + ccb->ccb_cmd_hdr = &hdr[i]; + ccb->ccb_cmd_table = &table[i]; + dva = AHCI_DMA_DVA(ap->ap_dmamem_cmd_table) + + ccb->ccb_slot * sizeof(struct ahci_cmd_table); + ccb->ccb_cmd_hdr->ctba_hi = htole32((u_int32_t)(dva >> 32)); + ccb->ccb_cmd_hdr->ctba_lo = htole32((u_int32_t)dva); + + ccb->ccb_xa.fis = + (struct ata_fis_h2d *)ccb->ccb_cmd_table->cfis; + ccb->ccb_xa.packetcmd = ccb->ccb_cmd_table->acmd; + ccb->ccb_xa.tag = i; + + ccb->ccb_xa.ata_put_xfer = ahci_ata_put_xfer; + + ccb->ccb_xa.state = ATA_S_COMPLETE; + ahci_put_ccb(ccb); + } + + /* Wait for ICC change to complete */ + ahci_pwait_clr(ap, AHCI_PREG_CMD, AHCI_PREG_CMD_ICC); + + /* + * Do device-related port initialization. A failure here does not + * cause the port to be deallocated as we want to receive future + * hot-plug events. + */ + ahci_port_init(ap); + return(0); +freeport: + ahci_port_free(sc, port); +reterr: + return (rc); +} + +/* + * [re]initialize an idle port. No CCBs should be active. + * + * This function is called during the initial port allocation sequence + * and is also called on hot-plug insertion. We take no chances and + * use a portreset instead of a softreset. + * + * Returns 0 if a device is successfully detected. + */ +int +ahci_port_init(struct ahci_port *ap) +{ + int rc; + + /* + * Hard-reset the port. + */ + rc = ahci_port_portreset(ap); + + switch (rc) { + case ENODEV: + /* + * We had problems talking to the device on the port. + */ + switch (ahci_pread(ap, AHCI_PREG_SSTS) & AHCI_PREG_SSTS_DET) { + case AHCI_PREG_SSTS_DET_DEV_NE: + kprintf("%s: Device not communicating\n", PORTNAME(ap)); + break; + case AHCI_PREG_SSTS_DET_PHYOFFLINE: + kprintf("%s: PHY offline\n", PORTNAME(ap)); + break; + default: + kprintf("%s: No device detected\n", PORTNAME(ap)); + break; + } + break; + + case EBUSY: + /* + * The device on the port is still telling us its busy. + * + * We try a softreset on the device. + */ + kprintf("%s: Device on port did not come ready, TFD: 0x%b\n", + PORTNAME(ap), + ahci_pread(ap, AHCI_PREG_TFD), AHCI_PFMT_TFD_STS); + + /* Try a soft reset to clear busy */ + rc = ahci_port_softreset(ap); + if (rc) { + kprintf("%s: Unable to clear busy device\n", + PORTNAME(ap)); + } else { + kprintf("%s: Successfully reset busy device\n", + PORTNAME(ap)); + } + break; + + default: + break; + } + + /* + * Enable command transfers on the port if a device was detected. + * Otherwise leave them disabled but leave the port structure + * intact so we get hot-plug interrupts. + */ + if (rc == 0) { + if (ahci_port_start(ap, 0)) { + kprintf("%s: failed to start command DMA on port, " + "disabling\n", PORTNAME(ap)); + rc = ENXIO; /* couldn't start port */ + } + } + + /* Flush interrupts for port */ + ahci_pwrite(ap, AHCI_PREG_IS, ahci_pread(ap, AHCI_PREG_IS)); + ahci_write(ap->ap_sc, AHCI_REG_IS, 1 << ap->ap_num); + + /* Enable port interrupts */ + ahci_pwrite(ap, AHCI_PREG_IE, + AHCI_PREG_IE_TFEE | AHCI_PREG_IE_HBFE | + AHCI_PREG_IE_IFE | AHCI_PREG_IE_OFE | + AHCI_PREG_IE_DPE | AHCI_PREG_IE_UFE | + AHCI_PREG_IE_PCE | AHCI_PREG_IE_PRCE | +#ifdef AHCI_COALESCE + ((sc->sc_ccc_ports & (1 << port)) ? + 0 : (AHCI_PREG_IE_SDBE | AHCI_PREG_IE_DHRE)) +#else + AHCI_PREG_IE_SDBE | AHCI_PREG_IE_DHRE +#endif + ); + return(rc); +} + +/* + * De-initialize and detach a port. + */ +void +ahci_port_free(struct ahci_softc *sc, u_int port) +{ + struct ahci_port *ap = sc->sc_ports[port]; + struct ahci_ccb *ccb; + + /* Ensure port is disabled and its interrupts are flushed */ + if (ap->ap_sc) { + ahci_pwrite(ap, AHCI_PREG_CMD, 0); + ahci_pwrite(ap, AHCI_PREG_IE, 0); + ahci_pwrite(ap, AHCI_PREG_IS, ahci_pread(ap, AHCI_PREG_IS)); + ahci_write(sc, AHCI_REG_IS, 1 << port); + } + + if (ap->ap_ccbs) { + while ((ccb = ahci_get_ccb(ap)) != NULL) { + if (ccb->ccb_dmamap) { + bus_dmamap_destroy(sc->sc_tag_data, + ccb->ccb_dmamap); + ccb->ccb_dmamap = NULL; + } + } + kfree(ap->ap_ccbs, M_DEVBUF); + ap->ap_ccbs = NULL; + } + + if (ap->ap_dmamem_cmd_list) { + ahci_dmamem_free(sc, ap->ap_dmamem_cmd_list); + ap->ap_dmamem_cmd_list = NULL; + } + if (ap->ap_dmamem_rfis) { + ahci_dmamem_free(sc, ap->ap_dmamem_rfis); + ap->ap_dmamem_rfis = NULL; + } + if (ap->ap_dmamem_cmd_table) { + ahci_dmamem_free(sc, ap->ap_dmamem_cmd_table); + ap->ap_dmamem_cmd_table = NULL; + } + + /* bus_space(9) says we dont free the subregions handle */ + + kfree(ap, M_DEVBUF); + sc->sc_ports[port] = NULL; +} + +/* + * Start high-level command processing on the port + */ +int +ahci_port_start(struct ahci_port *ap, int fre_only) +{ + u_int32_t r; + + /* Turn on FRE (and ST) */ + r = ahci_pread(ap, AHCI_PREG_CMD) & ~AHCI_PREG_CMD_ICC; + r |= AHCI_PREG_CMD_FRE; + if (!fre_only) + r |= AHCI_PREG_CMD_ST; + ahci_pwrite(ap, AHCI_PREG_CMD, r); + +#ifdef AHCI_COALESCE + /* (Re-)enable coalescing on the port. */ + if (ap->ap_sc->sc_ccc_ports & (1 << ap->ap_num)) { + ap->ap_sc->sc_ccc_ports_cur |= (1 << ap->ap_num); + ahci_write(ap->ap_sc, AHCI_REG_CCC_PORTS, + ap->ap_sc->sc_ccc_ports_cur); + } +#endif + + if (!(ap->ap_sc->sc_flags & AHCI_F_IGN_FR)) { + /* Wait for FR to come on */ + if (ahci_pwait_set(ap, AHCI_PREG_CMD, AHCI_PREG_CMD_FR)) + return (2); + } + + /* Wait for CR to come on */ + if (!fre_only && ahci_pwait_set(ap, AHCI_PREG_CMD, AHCI_PREG_CMD_CR)) + return (1); + + return (0); +} + +/* + * Stop high-level command processing on a port + */ +int +ahci_port_stop(struct ahci_port *ap, int stop_fis_rx) +{ + u_int32_t r; + +#ifdef AHCI_COALESCE + /* Disable coalescing on the port while it is stopped. */ + if (ap->ap_sc->sc_ccc_ports & (1 << ap->ap_num)) { + ap->ap_sc->sc_ccc_ports_cur &= ~(1 << ap->ap_num); + ahci_write(ap->ap_sc, AHCI_REG_CCC_PORTS, + ap->ap_sc->sc_ccc_ports_cur); + } +#endif + + /* Turn off ST (and FRE) */ + r = ahci_pread(ap, AHCI_PREG_CMD) & ~AHCI_PREG_CMD_ICC; + r &= ~AHCI_PREG_CMD_ST; + if (stop_fis_rx) + r &= ~AHCI_PREG_CMD_FRE; + ahci_pwrite(ap, AHCI_PREG_CMD, r); + + /* Wait for CR to go off */ + if (ahci_pwait_clr(ap, AHCI_PREG_CMD, AHCI_PREG_CMD_CR)) + return (1); + + /* Wait for FR to go off */ + if (stop_fis_rx && ahci_pwait_clr(ap, AHCI_PREG_CMD, AHCI_PREG_CMD_FR)) + return (2); + + return (0); +} + +/* + * AHCI command list override -> forcibly clear TFD.STS.{BSY,DRQ} + */ +int +ahci_port_clo(struct ahci_port *ap) +{ + struct ahci_softc *sc = ap->ap_sc; + u_int32_t cmd; + + /* Only attempt CLO if supported by controller */ + if ((ahci_read(sc, AHCI_REG_CAP) & AHCI_REG_CAP_SCLO) == 0) + return (1); + + /* Issue CLO */ + cmd = ahci_pread(ap, AHCI_PREG_CMD) & ~AHCI_PREG_CMD_ICC; +#ifdef DIAGNOSTIC + if (cmd & AHCI_PREG_CMD_ST) { + kprintf("%s: CLO requested while port running\n", + PORTNAME(ap)); + } +#endif + ahci_pwrite(ap, AHCI_PREG_CMD, cmd | AHCI_PREG_CMD_CLO); + + /* Wait for completion */ + if (ahci_pwait_clr(ap, AHCI_PREG_CMD, AHCI_PREG_CMD_CLO)) { + kprintf("%s: CLO did not complete\n", PORTNAME(ap)); + return (1); + } + + return (0); +} + +/* + * AHCI soft reset, Section 10.4.1 + * + * This function keeps port communications intact and attempts to generate + * a reset to the connected device. + */ +int +ahci_port_softreset(struct ahci_port *ap) +{ + struct ahci_ccb *ccb = NULL; + struct ahci_cmd_hdr *cmd_slot; + u_int8_t *fis; + int rc = EIO; + u_int32_t cmd; + + DPRINTF(AHCI_D_VERBOSE, "%s: soft reset\n", PORTNAME(ap)); + + crit_enter(); + + /* Save previous command register state */ + cmd = ahci_pread(ap, AHCI_PREG_CMD) & ~AHCI_PREG_CMD_ICC; + + /* Idle port */ + if (ahci_port_stop(ap, 0)) { + kprintf("%s: failed to stop port, cannot softreset\n", + PORTNAME(ap)); + goto err; + } + + /* Request CLO if device appears hung */ + if (ahci_pread(ap, AHCI_PREG_TFD) & + (AHCI_PREG_TFD_STS_BSY | AHCI_PREG_TFD_STS_DRQ)) { + ahci_port_clo(ap); + } + + /* Clear port errors to permit TFD transfer */ + ahci_pwrite(ap, AHCI_PREG_SERR, ahci_pread(ap, AHCI_PREG_SERR)); + + /* Restart port */ + if (ahci_port_start(ap, 0)) { + kprintf("%s: failed to start port, cannot softreset\n", + PORTNAME(ap)); + goto err; + } + + /* Check whether CLO worked */ + if (ahci_pwait_clr(ap, AHCI_PREG_TFD, + AHCI_PREG_TFD_STS_BSY | AHCI_PREG_TFD_STS_DRQ)) { + kprintf("%s: CLO %s, need port reset\n", + PORTNAME(ap), + (ahci_read(ap->ap_sc, AHCI_REG_CAP) & AHCI_REG_CAP_SCLO) + ? "failed" : "unsupported"); + rc = EBUSY; + goto err; + } + + /* + * Prep first D2H command with SRST feature & clear busy/reset flags + * + * It is unclear which other fields in the FIS are used. Just zero + * everything. + */ + ccb = ahci_get_err_ccb(ap); + cmd_slot = ccb->ccb_cmd_hdr; + bzero(ccb->ccb_cmd_table, sizeof(struct ahci_cmd_table)); + + fis = ccb->ccb_cmd_table->cfis; + bzero(fis, sizeof(ccb->ccb_cmd_table->cfis)); + fis[0] = 0x27; /* Host to device */ + fis[15] = 0x04; /* SRST DEVCTL */ + + cmd_slot->prdtl = 0; + cmd_slot->flags = htole16(5); /* FIS length: 5 DWORDS */ + cmd_slot->flags |= htole16(AHCI_CMD_LIST_FLAG_C); /* Clear busy on OK */ + cmd_slot->flags |= htole16(AHCI_CMD_LIST_FLAG_R); /* Reset */ + cmd_slot->flags |= htole16(AHCI_CMD_LIST_FLAG_W); /* Write */ + + ccb->ccb_xa.state = ATA_S_PENDING; + ccb->ccb_xa.flags = 0; + if (ahci_poll(ccb, hz, NULL) != 0) { + kprintf("%s: First FIS failed\n", PORTNAME(ap)); + goto err; + } + + /* + * Prep second D2H command to read status and complete reset sequence + * AHCI 10.4.1 and "Serial ATA Revision 2.6". I can't find the ATA + * Rev 2.6 and it is unclear how the second FIS should be set up + * from the AHCI document. + * + * Give the device 1/10 of a second before sending the second + * FIS. + * + * It is unclear which other fields in the FIS are used. Just zero + * everything. + */ + bzero(fis, sizeof(ccb->ccb_cmd_table->cfis)); + fis[0] = 0x27; /* Host to device */ + fis[15] = 0; + + cmd_slot->prdtl = 0; + cmd_slot->flags = htole16(5); /* FIS length: 5 DWORDS */ + cmd_slot->flags |= htole16(AHCI_CMD_LIST_FLAG_W); + + ccb->ccb_xa.state = ATA_S_PENDING; + ccb->ccb_xa.flags = 0; + if (ahci_poll(ccb, hz, NULL) != 0) { + kprintf("%s: Second FIS failed\n", PORTNAME(ap)); + goto err; + } + + if (ahci_pwait_clr(ap, AHCI_PREG_TFD, AHCI_PREG_TFD_STS_BSY | + AHCI_PREG_TFD_STS_DRQ | AHCI_PREG_TFD_STS_ERR)) { + kprintf("%s: device didn't come ready after reset, TFD: 0x%b\n", + PORTNAME(ap), + ahci_pread(ap, AHCI_PREG_TFD), AHCI_PFMT_TFD_STS); + rc = EBUSY; + goto err; + } + + /* + * If the softreset is trying to clear a BSY condition after a + * normal portreset we assign the port type. + * + * If the softreset is being run first as part of the ccb error + * processing code then report if the device signature changed + * unexpectedly. + */ + if (ap->ap_ata.ap_type == ATA_PORT_T_NONE) { + ap->ap_ata.ap_type = ahci_port_signature_detect(ap); + } else { + if (ahci_port_signature_detect(ap) != ap->ap_ata.ap_type) { + kprintf("%s: device signature unexpectedly changed\n", + PORTNAME(ap)); + rc = EBUSY; + } + } + + rc = 0; +err: + if (ccb != NULL) { + /* Abort our command, if it failed, by stopping command DMA. */ + if (rc != 0 && (ap->ap_active & (1 << ccb->ccb_slot))) { + kprintf("%s: stopping the port, softreset slot " + "%d was still active.\n", + PORTNAME(ap), + ccb->ccb_slot); + ahci_port_stop(ap, 0); + } + ccb->ccb_xa.state = ATA_S_ERROR; + ahci_put_err_ccb(ccb); + } + + /* Restore saved CMD register state */ + ahci_pwrite(ap, AHCI_PREG_CMD, cmd); + + crit_exit(); + + return (rc); +} + +/* + * AHCI port reset, Section 10.4.2 + * + * This function does a hard reset of the port. Note that the device + * connected to the port could still end-up hung. + */ +int +ahci_port_portreset(struct ahci_port *ap) +{ + u_int32_t cmd, r; + int rc; + + DPRINTF(AHCI_D_VERBOSE, "%s: port reset\n", PORTNAME(ap)); + + /* Save previous command register state */ + cmd = ahci_pread(ap, AHCI_PREG_CMD) & ~AHCI_PREG_CMD_ICC; + + /* Clear ST, ignoring failure */ + ahci_port_stop(ap, 0); + + /* Perform device detection */ + ap->ap_ata.ap_type = ATA_PORT_T_NONE; + ahci_pwrite(ap, AHCI_PREG_SCTL, 0); + DELAY(10000); + r = AHCI_PREG_SCTL_IPM_DISABLED | AHCI_PREG_SCTL_DET_INIT; + + if (AhciForceGen1 & (1 << ap->ap_num)) { + kprintf("%s: Force 1.5Gbits\n", PORTNAME(ap)); + r |= AHCI_PREG_SCTL_SPD_GEN1; + } else { + r |= AHCI_PREG_SCTL_SPD_ANY; + } + ahci_pwrite(ap, AHCI_PREG_SCTL, r); + DELAY(10000); /* wait at least 1ms for COMRESET to be sent */ + r &= ~AHCI_PREG_SCTL_DET_INIT; + r |= AHCI_PREG_SCTL_DET_NONE; + ahci_pwrite(ap, AHCI_PREG_SCTL, r); + DELAY(10000); + + /* Wait for device to be detected and communications established */ + if (ahci_pwait_eq(ap, 1000, + AHCI_PREG_SSTS, AHCI_PREG_SSTS_DET, + AHCI_PREG_SSTS_DET_DEV)) { + rc = ENODEV; + goto err; + } + + /* Clear SERR (incl X bit), so TFD can update */ + ahci_pwrite(ap, AHCI_PREG_SERR, ahci_pread(ap, AHCI_PREG_SERR)); + + /* + * Wait for device to become ready + * + * This can take more then a second, give it 3 seconds. + */ + if (ahci_pwait_clr_to(ap, 3000, + AHCI_PREG_TFD, AHCI_PREG_TFD_STS_BSY | + AHCI_PREG_TFD_STS_DRQ | AHCI_PREG_TFD_STS_ERR)) { + rc = EBUSY; + kprintf("%s: Device will not come ready 0x%b\n", + PORTNAME(ap), + ahci_pread(ap, AHCI_PREG_TFD), AHCI_PFMT_TFD_STS); + goto err; + } + + ap->ap_ata.ap_type = ahci_port_signature_detect(ap); + rc = 0; +err: + /* Restore preserved port state */ + ahci_pwrite(ap, AHCI_PREG_CMD, cmd); + + return (rc); +} + +/* + * Figure out what type of device is connected to the port, ATAPI or + * DISK. + */ +int +ahci_port_signature_detect(struct ahci_port *ap) +{ + u_int32_t sig; + + sig = ahci_pread(ap, AHCI_PREG_SIG); + if ((sig & 0xffff0000) == (SATA_SIGNATURE_ATAPI & 0xffff0000)) { + return(ATA_PORT_T_ATAPI); + } else { + return(ATA_PORT_T_DISK); + } +} + +/* + * Load the DMA descriptor table for a CCB's buffer. + */ +int +ahci_load_prdt(struct ahci_ccb *ccb) +{ + struct ahci_port *ap = ccb->ccb_port; + struct ahci_softc *sc = ap->ap_sc; + struct ata_xfer *xa = &ccb->ccb_xa; + struct ahci_prdt *prdt = ccb->ccb_cmd_table->prdt; + bus_dmamap_t dmap = ccb->ccb_dmamap; + struct ahci_cmd_hdr *cmd_slot = ccb->ccb_cmd_hdr; + int error; + + if (xa->datalen == 0) { + ccb->ccb_cmd_hdr->prdtl = 0; + return (0); + } + + error = bus_dmamap_load(sc->sc_tag_data, dmap, + xa->data, xa->datalen, + ahci_load_prdt_callback, + &prdt, + ((xa->flags & ATA_F_NOWAIT) ? + BUS_DMA_NOWAIT : BUS_DMA_WAITOK)); + if (error != 0) { + kprintf("%s: error %d loading dmamap\n", PORTNAME(ap), error); + return (1); + } + if (xa->flags & ATA_F_PIO) + prdt->flags |= htole32(AHCI_PRDT_FLAG_INTR); + + cmd_slot->prdtl = htole16(prdt - ccb->ccb_cmd_table->prdt + 1); + + bus_dmamap_sync(sc->sc_tag_data, dmap, + (xa->flags & ATA_F_READ) ? + BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); + + return (0); + +#ifdef DIAGNOSTIC +diagerr: + bus_dmamap_unload(sc->sc_tag_data, dmap); + return (1); +#endif +} + +/* + * Callback from BUSDMA system to load the segment list. The passed segment + * list is a temporary structure. + */ +static +void +ahci_load_prdt_callback(void *info, bus_dma_segment_t *segs, int nsegs, + int error) +{ + struct ahci_prdt *prd = *(void **)info; + u_int64_t addr; + + KKASSERT(nsegs <= AHCI_MAX_PRDT); + + while (nsegs) { + addr = segs->ds_addr; + prd->dba_hi = htole32((u_int32_t)(addr >> 32)); + prd->dba_lo = htole32((u_int32_t)addr); +#ifdef DIAGNOSTIC + KKASSERT((addr & 1) == 0); + KKASSERT((segs->ds_len & 1) == 0); +#endif + prd->flags = htole32(segs->ds_len - 1); + --nsegs; + if (nsegs) + ++prd; + ++segs; + } + *(void **)info = prd; /* return last valid segment */ +} + +void +ahci_unload_prdt(struct ahci_ccb *ccb) +{ + struct ahci_port *ap = ccb->ccb_port; + struct ahci_softc *sc = ap->ap_sc; + struct ata_xfer *xa = &ccb->ccb_xa; + bus_dmamap_t dmap = ccb->ccb_dmamap; + + if (xa->datalen != 0) { + bus_dmamap_sync(sc->sc_tag_data, dmap, + (xa->flags & ATA_F_READ) ? + BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); + + bus_dmamap_unload(sc->sc_tag_data, dmap); + + if (ccb->ccb_xa.flags & ATA_F_NCQ) + xa->resid = 0; + else + xa->resid = xa->datalen - + le32toh(ccb->ccb_cmd_hdr->prdbc); + } +} + +/* + * Start a command and poll for completion. + * + * NOTE: If the caller specifies a NULL timeout function the caller is + * responsible for clearing hardware state on failure, but we will + * deal with removing the ccb from any pending queue. + * + * NOTE: NCQ should never be used with this function. + */ +int +ahci_poll(struct ahci_ccb *ccb, int timeout, void (*timeout_fn)(void *)) +{ + struct ahci_port *ap = ccb->ccb_port; + u_int32_t slot_mask = 1 << ccb->ccb_slot; + + crit_enter(); + ahci_start(ccb); + do { + if (ahci_port_intr(ap, AHCI_PREG_CI_ALL_SLOTS) & slot_mask) { + crit_exit(); + return (0); + } + if (ccb->ccb_xa.state != ATA_S_ONCHIP && + ccb->ccb_xa.state != ATA_S_PENDING) { + break; + } + DELAY(1000000 / hz); + } while (--timeout > 0); + + if (ccb->ccb_xa.state != ATA_S_ONCHIP && + ccb->ccb_xa.state != ATA_S_PENDING) { + kprintf("%s: Warning poll completed unexpectedly for slot %d\n", + PORTNAME(ap), ccb->ccb_slot); + crit_exit(); + return (0); + } + + kprintf("%s: Poll timed-out for slot %d state %d\n", + PORTNAME(ap), ccb->ccb_slot, ccb->ccb_xa.state); + + if (timeout_fn != NULL) { + timeout_fn(ccb); + } else { + if (ccb->ccb_xa.state == ATA_S_PENDING) + TAILQ_REMOVE(&ap->ap_ccb_pending, ccb, ccb_entry); + ccb->ccb_xa.state = ATA_S_TIMEOUT; + } + crit_exit(); + + return (1); +} + +void +ahci_start(struct ahci_ccb *ccb) +{ + struct ahci_port *ap = ccb->ccb_port; + struct ahci_softc *sc = ap->ap_sc; + + KKASSERT(ccb->ccb_xa.state == ATA_S_PENDING); + + /* Zero transferred byte count before transfer */ + ccb->ccb_cmd_hdr->prdbc = 0; + + /* Sync command list entry and corresponding command table entry */ + bus_dmamap_sync(sc->sc_tag_cmdh, + AHCI_DMA_MAP(ap->ap_dmamem_cmd_list), + BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(sc->sc_tag_cmdt, + AHCI_DMA_MAP(ap->ap_dmamem_cmd_table), + BUS_DMASYNC_PREWRITE); + + /* Prepare RFIS area for write by controller */ + bus_dmamap_sync(sc->sc_tag_rfis, + AHCI_DMA_MAP(ap->ap_dmamem_rfis), + BUS_DMASYNC_PREREAD); + + if (ccb->ccb_xa.flags & ATA_F_NCQ) { + /* Issue NCQ commands only when there are no outstanding + * standard commands. */ + if (ap->ap_active != 0 || !TAILQ_EMPTY(&ap->ap_ccb_pending)) + TAILQ_INSERT_TAIL(&ap->ap_ccb_pending, ccb, ccb_entry); + else { + KKASSERT(ap->ap_active_cnt == 0); + ap->ap_sactive |= (1 << ccb->ccb_slot); + ccb->ccb_xa.state = ATA_S_ONCHIP; + ahci_pwrite(ap, AHCI_PREG_SACT, 1 << ccb->ccb_slot); + ahci_pwrite(ap, AHCI_PREG_CI, 1 << ccb->ccb_slot); + } + } else { + /* + * Wait for all NCQ commands to finish before issuing standard + * command. + */ + if (ap->ap_sactive != 0 || ap->ap_active_cnt == 2) + TAILQ_INSERT_TAIL(&ap->ap_ccb_pending, ccb, ccb_entry); + else if (ap->ap_active_cnt < 2) { + ap->ap_active |= 1 << ccb->ccb_slot; + ccb->ccb_xa.state = ATA_S_ONCHIP; + ahci_pwrite(ap, AHCI_PREG_CI, 1 << ccb->ccb_slot); + ap->ap_active_cnt++; + } + } +} + +void +ahci_issue_pending_ncq_commands(struct ahci_port *ap) +{ + struct ahci_ccb *nextccb; + u_int32_t sact_change = 0; + + KKASSERT(ap->ap_active_cnt == 0); + + nextccb = TAILQ_FIRST(&ap->ap_ccb_pending); + if (nextccb == NULL || !(nextccb->ccb_xa.flags & ATA_F_NCQ)) + return; + + /* Start all the NCQ commands at the head of the pending list. */ + do { + TAILQ_REMOVE(&ap->ap_ccb_pending, nextccb, ccb_entry); + sact_change |= 1 << nextccb->ccb_slot; + nextccb->ccb_xa.state = ATA_S_ONCHIP; + nextccb = TAILQ_FIRST(&ap->ap_ccb_pending); + } while (nextccb && (nextccb->ccb_xa.flags & ATA_F_NCQ)); + + ap->ap_sactive |= sact_change; + ahci_pwrite(ap, AHCI_PREG_SACT, sact_change); + ahci_pwrite(ap, AHCI_PREG_CI, sact_change); + + return; +} + +void +ahci_issue_pending_commands(struct ahci_port *ap, int last_was_ncq) +{ + struct ahci_ccb *nextccb; + + nextccb = TAILQ_FIRST(&ap->ap_ccb_pending); + if (nextccb && (nextccb->ccb_xa.flags & ATA_F_NCQ)) { + KKASSERT(last_was_ncq == 0); /* otherwise it should have + * been started already. */ + + /* Issue NCQ commands only when there are no outstanding + * standard commands. */ + ap->ap_active_cnt--; + if (ap->ap_active == 0) + ahci_issue_pending_ncq_commands(ap); + else + KKASSERT(ap->ap_active_cnt == 1); + } else if (nextccb) { + if (ap->ap_sactive != 0 || last_was_ncq) + KKASSERT(ap->ap_active_cnt == 0); + + /* Wait for all NCQ commands to finish before issuing standard + * command. */ + if (ap->ap_sactive != 0) + return; + + /* Keep up to 2 standard commands on-chip at a time. */ + do { + TAILQ_REMOVE(&ap->ap_ccb_pending, nextccb, ccb_entry); + ap->ap_active |= 1 << nextccb->ccb_slot; + nextccb->ccb_xa.state = ATA_S_ONCHIP; + ahci_pwrite(ap, AHCI_PREG_CI, 1 << nextccb->ccb_slot); + if (last_was_ncq) + ap->ap_active_cnt++; + if (ap->ap_active_cnt == 2) + break; + KKASSERT(ap->ap_active_cnt == 1); + nextccb = TAILQ_FIRST(&ap->ap_ccb_pending); + } while (nextccb && !(nextccb->ccb_xa.flags & ATA_F_NCQ)); + } else if (!last_was_ncq) { + KKASSERT(ap->ap_active_cnt == 1 || ap->ap_active_cnt == 2); + + /* Standard command finished, none waiting to start. */ + ap->ap_active_cnt--; + } else { + KKASSERT(ap->ap_active_cnt == 0); + + /* NCQ command finished. */ + } +} + +void +ahci_intr(void *arg) +{ + struct ahci_softc *sc = arg; + u_int32_t is, ack = 0; + int port; + + /* Read global interrupt status */ + is = ahci_read(sc, AHCI_REG_IS); + if (is == 0 || is == 0xffffffff) + return; + ack = is; + +#ifdef AHCI_COALESCE + /* Check coalescing interrupt first */ + if (is & sc->sc_ccc_mask) { + DPRINTF(AHCI_D_INTR, "%s: command coalescing interrupt\n", + DEVNAME(sc)); + is &= ~sc->sc_ccc_mask; + is |= sc->sc_ccc_ports_cur; + } +#endif + + /* Process interrupts for each port */ + while (is) { + port = ffs(is) - 1; + if (sc->sc_ports[port]) { + ahci_port_intr(sc->sc_ports[port], + AHCI_PREG_CI_ALL_SLOTS); + } + is &= ~(1 << port); + } + + /* Finally, acknowledge global interrupt */ + ahci_write(sc, AHCI_REG_IS, ack); +} + +u_int32_t +ahci_port_intr(struct ahci_port *ap, u_int32_t ci_mask) +{ + struct ahci_softc *sc = ap->ap_sc; + u_int32_t is, ci_saved, ci_masked, processed = 0; + int slot, need_restart = 0; + struct ahci_ccb *ccb = NULL; + volatile u_int32_t *active; +#ifdef DIAGNOSTIC + u_int32_t tmp; +#endif + + is = ahci_pread(ap, AHCI_PREG_IS); + + /* Ack port interrupt only if checking all command slots. */ + if (ci_mask == AHCI_PREG_CI_ALL_SLOTS) + ahci_pwrite(ap, AHCI_PREG_IS, is); + + if (is) + DPRINTF(AHCI_D_INTR, "%s: interrupt: %b\n", PORTNAME(ap), + is, AHCI_PFMT_IS); + + if (ap->ap_sactive) { + /* Active NCQ commands - use SActive instead of CI */ + KKASSERT(ap->ap_active == 0); + KKASSERT(ap->ap_active_cnt == 0); + ci_saved = ahci_pread(ap, AHCI_PREG_SACT); + active = &ap->ap_sactive; + } else { + /* Save CI */ + ci_saved = ahci_pread(ap, AHCI_PREG_CI); + active = &ap->ap_active; + } + + /* Command failed. See AHCI 1.1 spec 6.2.2.1 and 6.2.2.2. */ + if (is & AHCI_PREG_IS_TFES) { + u_int32_t tfd, serr; + int err_slot; + + tfd = ahci_pread(ap, AHCI_PREG_TFD); + serr = ahci_pread(ap, AHCI_PREG_SERR); + + if (ap->ap_sactive == 0) { + /* Errored slot is easy to determine from CMD. */ + err_slot = AHCI_PREG_CMD_CCS(ahci_pread(ap, + AHCI_PREG_CMD)); + ccb = &ap->ap_ccbs[err_slot]; + + /* Preserve received taskfile data from the RFIS. */ + memcpy(&ccb->ccb_xa.rfis, ap->ap_rfis->rfis, + sizeof(struct ata_fis_d2h)); + } else + err_slot = -1; /* Must extract error from log page */ + + DPRINTF(AHCI_D_VERBOSE, "%s: errored slot %d, TFD: %b, SERR:" + " %b, DIAG: %b\n", PORTNAME(ap), err_slot, tfd, + AHCI_PFMT_TFD_STS, AHCI_PREG_SERR_ERR(serr), + AHCI_PFMT_SERR_ERR, AHCI_PREG_SERR_DIAG(serr), + AHCI_PFMT_SERR_DIAG); + + /* Turn off ST to clear CI and SACT. */ + ahci_port_stop(ap, 0); + need_restart = 1; + + /* Clear SERR to enable capturing new errors. */ + ahci_pwrite(ap, AHCI_PREG_SERR, serr); + + /* Acknowledge the interrupts we can recover from. */ + ahci_pwrite(ap, AHCI_PREG_IS, AHCI_PREG_IS_TFES | + AHCI_PREG_IS_IFS); + is = ahci_pread(ap, AHCI_PREG_IS); + + /* If device hasn't cleared its busy status, try to idle it. */ + if (tfd & (AHCI_PREG_TFD_STS_BSY | AHCI_PREG_TFD_STS_DRQ)) { + kprintf("%s: attempting to idle device\n", + PORTNAME(ap)); + if (ahci_port_softreset(ap)) { + kprintf("%s: failed to soft reset device\n", + PORTNAME(ap)); + if (ahci_port_portreset(ap)) { + kprintf("%s: failed to port reset " + "device, give up on it\n", + PORTNAME(ap)); + goto fatal; + } + } + + /* Had to reset device, can't gather extended info. */ + } else if (ap->ap_sactive) { + /* Recover the NCQ error from log page 10h. */ + ahci_port_read_ncq_error(ap, &err_slot); + if (err_slot < 0) + goto failall; + + DPRINTF(AHCI_D_VERBOSE, "%s: NCQ errored slot %d\n", + PORTNAME(ap), err_slot); + + ccb = &ap->ap_ccbs[err_slot]; + } else { + /* Didn't reset, could gather extended info from log. */ + } + + /* + * If we couldn't determine the errored slot, reset the port + * and fail all the active slots. + */ + if (err_slot == -1) { + if (ahci_port_softreset(ap) != 0 && + ahci_port_portreset(ap) != 0) { + kprintf("%s: couldn't reset after NCQ error, " + "disabling device.\n", + PORTNAME(ap)); + goto fatal; + } + kprintf("%s: couldn't recover NCQ error, failing " + "all outstanding commands.\n", + PORTNAME(ap)); + goto failall; + } + + /* Clear the failed command in saved CI so completion runs. */ + ci_saved &= ~(1 << err_slot); + + /* Note the error in the ata_xfer. */ + KKASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP); + ccb->ccb_xa.state = ATA_S_ERROR; + +#ifdef DIAGNOSTIC + /* There may only be one outstanding standard command now. */ + if (ap->ap_sactive == 0) { + tmp = ci_saved; + if (tmp) { + slot = ffs(tmp) - 1; + tmp &= ~(1 << slot); + KKASSERT(tmp == 0); + } + } +#endif + } + + /* + * Port change (hot-plug). + * + * A PCS interrupt will occur on hot-plug once communication is + * established. + * + * A PRCS interrupt will occur on hot-unplug (and possibly also + * on hot-plug). + * + * We can then check the CPS (Cold Presence State) bit to determine + * if a device is plugged in or not and do the right thing. + */ + if (is & (AHCI_PREG_IS_PCS | AHCI_PREG_IS_PRCS)) { + ahci_pwrite(ap, AHCI_PREG_SERR, + (AHCI_PREG_SERR_DIAG_N | AHCI_PREG_SERR_DIAG_X) << 16); + + switch (ahci_pread(ap, AHCI_PREG_SSTS) & AHCI_PREG_SSTS_DET) { + case AHCI_PREG_SSTS_DET_DEV: + if (ap->ap_ata.ap_type == ATA_PORT_T_NONE) { + kprintf("%s: HOTPLUG - Device inserted\n", + PORTNAME(ap)); + if (ahci_port_init(ap) == 0) + ahci_cam_changed(ap, 1); + } + break; + default: + if (ap->ap_ata.ap_type != ATA_PORT_T_NONE) { + kprintf("%s: HOTPLUG - Device removed\n", + PORTNAME(ap)); + ahci_port_portreset(ap); + ahci_cam_changed(ap, 0); + } + break; + } + } + + /* Check for remaining errors - they are fatal. */ + if (is & (AHCI_PREG_IS_TFES | AHCI_PREG_IS_HBFS | AHCI_PREG_IS_IFS | + AHCI_PREG_IS_OFS | AHCI_PREG_IS_UFS)) { + u_int32_t serr = ahci_pread(ap, AHCI_PREG_SERR); + kprintf("%s: unrecoverable errors (IS: %b, SERR: %b %b), " + "disabling port.\n", + PORTNAME(ap), + is, AHCI_PFMT_IS, + AHCI_PREG_SERR_ERR(serr), AHCI_PFMT_SERR_ERR, + AHCI_PREG_SERR_DIAG(serr), AHCI_PFMT_SERR_DIAG + ); + /* XXX try recovery first */ + goto fatal; + } + + /* Fail all outstanding commands if we know the port won't recover. */ + if (ap->ap_state == AP_S_FATAL_ERROR) { +fatal: + ap->ap_state = AP_S_FATAL_ERROR; +failall: + + /* Ensure port is shut down. */ + ahci_port_stop(ap, 1); + + /* Error all the active slots. */ + ci_masked = ci_saved & *active; + while (ci_masked) { + slot = ffs(ci_masked) - 1; + ccb = &ap->ap_ccbs[slot]; + ci_masked &= ~(1 << slot); + ccb->ccb_xa.state = ATA_S_ERROR; + } + + /* Run completion for all active slots. */ + ci_saved &= ~*active; + + /* + * Don't restart the port if our problems were deemed fatal. + * + * Also acknowlege all fatal interrupt sources to prevent + * a livelock. + */ + if (ap->ap_state == AP_S_FATAL_ERROR) { + need_restart = 0; + ahci_pwrite(ap, AHCI_PREG_IS, + AHCI_PREG_IS_TFES | AHCI_PREG_IS_HBFS | + AHCI_PREG_IS_IFS | AHCI_PREG_IS_OFS | + AHCI_PREG_IS_UFS); + } + } + + /* + * CCB completion is detected by noticing its slot's bit in CI has + * changed to zero some time after we activated it. + * If we are polling, we may only be interested in particular slot(s). + */ + ci_masked = ~ci_saved & *active & ci_mask; + while (ci_masked) { + slot = ffs(ci_masked) - 1; + ccb = &ap->ap_ccbs[slot]; + ci_masked &= ~(1 << slot); + + DPRINTF(AHCI_D_INTR, "%s: slot %d is complete%s\n", + PORTNAME(ap), slot, ccb->ccb_xa.state == ATA_S_ERROR ? + " (error)" : ""); + + bus_dmamap_sync(sc->sc_tag_cmdh, + AHCI_DMA_MAP(ap->ap_dmamem_cmd_list), + BUS_DMASYNC_POSTWRITE); + + bus_dmamap_sync(sc->sc_tag_cmdt, + AHCI_DMA_MAP(ap->ap_dmamem_cmd_table), + BUS_DMASYNC_POSTWRITE); + + bus_dmamap_sync(sc->sc_tag_rfis, + AHCI_DMA_MAP(ap->ap_dmamem_rfis), + BUS_DMASYNC_POSTREAD); + + *active &= ~(1 << ccb->ccb_slot); + ccb->ccb_done(ccb); + + processed |= 1 << ccb->ccb_slot; + } + + if (need_restart) { + /* Restart command DMA on the port */ + ahci_port_start(ap, 0); + + /* Re-enable outstanding commands on port. */ + if (ci_saved) { +#ifdef DIAGNOSTIC + tmp = ci_saved; + while (tmp) { + slot = ffs(tmp) - 1; + tmp &= ~(1 << slot); + ccb = &ap->ap_ccbs[slot]; + KKASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP); + KKASSERT((!!(ccb->ccb_xa.flags & ATA_F_NCQ)) == + (!!ap->ap_sactive)); + } +#endif + DPRINTF(AHCI_D_VERBOSE, "%s: ahci_port_intr " + "re-enabling%s slots %08x\n", PORTNAME(ap), + ap->ap_sactive ? " NCQ" : "", ci_saved); + + if (ap->ap_sactive) + ahci_pwrite(ap, AHCI_PREG_SACT, ci_saved); + ahci_pwrite(ap, AHCI_PREG_CI, ci_saved); + } + } + + return (processed); +} + +struct ahci_ccb * +ahci_get_ccb(struct ahci_port *ap) +{ + struct ahci_ccb *ccb; + + lockmgr(&ap->ap_ccb_lock, LK_EXCLUSIVE); + ccb = TAILQ_FIRST(&ap->ap_ccb_free); + if (ccb != NULL) { + KKASSERT(ccb->ccb_xa.state == ATA_S_PUT); + TAILQ_REMOVE(&ap->ap_ccb_free, ccb, ccb_entry); + ccb->ccb_xa.state = ATA_S_SETUP; + } + lockmgr(&ap->ap_ccb_lock, LK_RELEASE); + + return (ccb); +} + +void +ahci_put_ccb(struct ahci_ccb *ccb) +{ + struct ahci_port *ap = ccb->ccb_port; + +#ifdef DIAGNOSTIC + if (ccb->ccb_xa.state != ATA_S_COMPLETE && + ccb->ccb_xa.state != ATA_S_TIMEOUT && + ccb->ccb_xa.state != ATA_S_ERROR) { + kprintf("%s: invalid ata_xfer state %02x in ahci_put_ccb, " + "slot %d\n", + PORTNAME(ccb->ccb_port), ccb->ccb_xa.state, + ccb->ccb_slot); + } +#endif + + ccb->ccb_xa.state = ATA_S_PUT; + lockmgr(&ap->ap_ccb_lock, LK_EXCLUSIVE); + TAILQ_INSERT_TAIL(&ap->ap_ccb_free, ccb, ccb_entry); + lockmgr(&ap->ap_ccb_lock, LK_RELEASE); +} + +struct ahci_ccb * +ahci_get_err_ccb(struct ahci_port *ap) +{ + struct ahci_ccb *err_ccb; + u_int32_t sact; + + /* No commands may be active on the chip. */ + sact = ahci_pread(ap, AHCI_PREG_SACT); + if (sact != 0) + kprintf("ahci_get_err_ccb but SACT %08x != 0?\n", sact); + KKASSERT(ahci_pread(ap, AHCI_PREG_CI) == 0); + +#ifdef DIAGNOSTIC + KKASSERT(ap->ap_err_busy == 0); + ap->ap_err_busy = 1; +#endif + /* Save outstanding command state. */ + ap->ap_err_saved_active = ap->ap_active; + ap->ap_err_saved_active_cnt = ap->ap_active_cnt; + ap->ap_err_saved_sactive = ap->ap_sactive; + + /* + * Pretend we have no commands outstanding, so that completions won't + * run prematurely. + */ + ap->ap_active = ap->ap_active_cnt = ap->ap_sactive = 0; + + /* + * Grab a CCB to use for error recovery. This should never fail, as + * we ask atascsi to reserve one for us at init time. + */ + err_ccb = ahci_get_ccb(ap); + KKASSERT(err_ccb != NULL); + err_ccb->ccb_xa.flags = 0; + err_ccb->ccb_done = ahci_empty_done; + + return err_ccb; +} + +void +ahci_put_err_ccb(struct ahci_ccb *ccb) +{ + struct ahci_port *ap = ccb->ccb_port; + u_int32_t sact; + u_int32_t ci; + +#ifdef DIAGNOSTIC + KKASSERT(ap->ap_err_busy); +#endif + /* + * No commands may be active on the chip + */ + sact = ahci_pread(ap, AHCI_PREG_SACT); + if (sact) { + panic("ahci_port_err_ccb(%d) but SACT %08x != 0\n", + ccb->ccb_slot, sact); + } + ci = ahci_pread(ap, AHCI_PREG_CI); + if (ci) { + panic("ahci_put_err_ccb(%d) but CI %08x != 0\n", + ccb->ccb_slot, ci); + } + + /* Done with the CCB */ + ahci_put_ccb(ccb); + + /* Restore outstanding command state */ + ap->ap_sactive = ap->ap_err_saved_sactive; + ap->ap_active_cnt = ap->ap_err_saved_active_cnt; + ap->ap_active = ap->ap_err_saved_active; + +#ifdef DIAGNOSTIC + ap->ap_err_busy = 0; +#endif +} + +int +ahci_port_read_ncq_error(struct ahci_port *ap, int *err_slotp) +{ + struct ahci_ccb *ccb; + struct ahci_cmd_hdr *cmd_slot; + u_int32_t cmd; + struct ata_fis_h2d *fis; + int rc = EIO; + + DPRINTF(AHCI_D_VERBOSE, "%s: read log page\n", PORTNAME(ap)); + + /* Save command register state. */ + cmd = ahci_pread(ap, AHCI_PREG_CMD) & ~AHCI_PREG_CMD_ICC; + + /* Port should have been idled already. Start it. */ + KKASSERT((cmd & AHCI_PREG_CMD_CR) == 0); + ahci_port_start(ap, 0); + + /* Prep error CCB for READ LOG EXT, page 10h, 1 sector. */ + ccb = ahci_get_err_ccb(ap); + ccb->ccb_xa.flags = ATA_F_NOWAIT | ATA_F_READ | ATA_F_POLL; + ccb->ccb_xa.data = ap->ap_err_scratch; + ccb->ccb_xa.datalen = 512; + cmd_slot = ccb->ccb_cmd_hdr; + bzero(ccb->ccb_cmd_table, sizeof(struct ahci_cmd_table)); + + fis = (struct ata_fis_h2d *)ccb->ccb_cmd_table->cfis; + fis->type = ATA_FIS_TYPE_H2D; + fis->flags = ATA_H2D_FLAGS_CMD; + fis->command = ATA_C_READ_LOG_EXT; + fis->lba_low = 0x10; /* queued error log page (10h) */ + fis->sector_count = 1; /* number of sectors (1) */ + fis->sector_count_exp = 0; + fis->lba_mid = 0; /* starting offset */ + fis->lba_mid_exp = 0; + fis->device = 0; + + cmd_slot->flags = htole16(5); /* FIS length: 5 DWORDS */ + + if (ahci_load_prdt(ccb) != 0) { + rc = ENOMEM; /* XXX caller must abort all commands */ + goto err; + } + + ccb->ccb_xa.state = ATA_S_PENDING; + if (ahci_poll(ccb, hz, NULL) != 0) + goto err; + + rc = 0; +err: + /* Abort our command, if it failed, by stopping command DMA. */ + if (rc != 0 && (ap->ap_active & (1 << ccb->ccb_slot))) { + kprintf("%s: log page read failed, slot %d was still active.\n", + PORTNAME(ap), ccb->ccb_slot); + ahci_port_stop(ap, 0); + } + + /* Done with the error CCB now. */ + ahci_unload_prdt(ccb); + ahci_put_err_ccb(ccb); + + /* Extract failed register set and tags from the scratch space. */ + if (rc == 0) { + struct ata_log_page_10h *log; + int err_slot; + + log = (struct ata_log_page_10h *)ap->ap_err_scratch; + if (log->err_regs.type & ATA_LOG_10H_TYPE_NOTQUEUED) { + /* Not queued bit was set - wasn't an NCQ error? */ + kprintf("%s: read NCQ error page, but not an NCQ " + "error?\n", + PORTNAME(ap)); + rc = ESRCH; + } else { + /* Copy back the log record as a D2H register FIS. */ + *err_slotp = err_slot = log->err_regs.type & + ATA_LOG_10H_TYPE_TAG_MASK; + + ccb = &ap->ap_ccbs[err_slot]; + memcpy(&ccb->ccb_xa.rfis, &log->err_regs, + sizeof(struct ata_fis_d2h)); + ccb->ccb_xa.rfis.type = ATA_FIS_TYPE_D2H; + ccb->ccb_xa.rfis.flags = 0; + } + } + + /* Restore saved CMD register state */ + ahci_pwrite(ap, AHCI_PREG_CMD, cmd); + + return (rc); +} + +/* + * Allocate memory for various structures DMAd by hardware. The maximum + * number of segments for these tags is 1 so the DMA memory will have a + * single physical base address. + */ +struct ahci_dmamem * +ahci_dmamem_alloc(struct ahci_softc *sc, bus_dma_tag_t tag) +{ + struct ahci_dmamem *adm; + int error; + + adm = kmalloc(sizeof(*adm), M_DEVBUF, M_INTWAIT | M_ZERO); + + error = bus_dmamem_alloc(tag, (void **)&adm->adm_kva, + BUS_DMA_ZERO, &adm->adm_map); + if (error == 0) { + adm->adm_tag = tag; + error = bus_dmamap_load(tag, adm->adm_map, + adm->adm_kva, + bus_dma_tag_getmaxsize(tag), + ahci_dmamem_saveseg, &adm->adm_busaddr, + 0); + } + if (error) { + if (adm->adm_map) { + bus_dmamap_destroy(tag, adm->adm_map); + adm->adm_map = NULL; + adm->adm_tag = NULL; + adm->adm_kva = NULL; + } + kfree(adm, M_DEVBUF); + adm = NULL; + } + return (adm); +} + +static +void +ahci_dmamem_saveseg(void *info, bus_dma_segment_t *segs, int nsegs, int error) +{ + KKASSERT(error == 0); + KKASSERT(nsegs == 1); + *(bus_addr_t *)info = segs->ds_addr; +} + + +void +ahci_dmamem_free(struct ahci_softc *sc, struct ahci_dmamem *adm) +{ + if (adm->adm_map) { + bus_dmamap_unload(adm->adm_tag, adm->adm_map); + bus_dmamap_destroy(adm->adm_tag, adm->adm_map); + adm->adm_map = NULL; + adm->adm_tag = NULL; + adm->adm_kva = NULL; + } + kfree(adm, M_DEVBUF); +} + +u_int32_t +ahci_read(struct ahci_softc *sc, bus_size_t r) +{ + bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4, + BUS_SPACE_BARRIER_READ); + return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, r)); +} + +void +ahci_write(struct ahci_softc *sc, bus_size_t r, u_int32_t v) +{ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v); + bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4, + BUS_SPACE_BARRIER_WRITE); +} + +int +ahci_wait_ne(struct ahci_softc *sc, bus_size_t r, u_int32_t mask, + u_int32_t target) +{ + int i; + + for (i = 0; i < 1000; i++) { + if ((ahci_read(sc, r) & mask) != target) + return (0); + DELAY(1000); + } + + return (1); +} + +u_int32_t +ahci_pread(struct ahci_port *ap, bus_size_t r) +{ + bus_space_barrier(ap->ap_sc->sc_iot, ap->ap_ioh, r, 4, + BUS_SPACE_BARRIER_READ); + return (bus_space_read_4(ap->ap_sc->sc_iot, ap->ap_ioh, r)); +} + +void +ahci_pwrite(struct ahci_port *ap, bus_size_t r, u_int32_t v) +{ + bus_space_write_4(ap->ap_sc->sc_iot, ap->ap_ioh, r, v); + bus_space_barrier(ap->ap_sc->sc_iot, ap->ap_ioh, r, 4, + BUS_SPACE_BARRIER_WRITE); +} + +int +ahci_pwait_eq(struct ahci_port *ap, int timeout, + bus_size_t r, u_int32_t mask, u_int32_t target) +{ + int i; + + for (i = 0; i < timeout; i++) { + if ((ahci_pread(ap, r) & mask) == target) + return (0); + DELAY(1000); + } + + return (1); +} + +struct ata_xfer * +ahci_ata_get_xfer(struct ahci_port *ap) +{ + /*struct ahci_softc *sc = ap->ap_sc;*/ + struct ahci_ccb *ccb; + + ccb = ahci_get_ccb(ap); + if (ccb == NULL) { + DPRINTF(AHCI_D_XFER, "%s: ahci_ata_get_xfer: NULL ccb\n", + PORTNAME(ap)); + return (NULL); + } + + DPRINTF(AHCI_D_XFER, "%s: ahci_ata_get_xfer got slot %d\n", + PORTNAME(ap), ccb->ccb_slot); + + ccb->ccb_xa.fis->type = ATA_FIS_TYPE_H2D; + + return (&ccb->ccb_xa); +} + +void +ahci_ata_put_xfer(struct ata_xfer *xa) +{ + struct ahci_ccb *ccb = (struct ahci_ccb *)xa; + + DPRINTF(AHCI_D_XFER, "ahci_ata_put_xfer slot %d\n", ccb->ccb_slot); + + ahci_put_ccb(ccb); +} + +int +ahci_ata_cmd(struct ata_xfer *xa) +{ + struct ahci_ccb *ccb = (struct ahci_ccb *)xa; + struct ahci_cmd_hdr *cmd_slot; + + KKASSERT(xa->state == ATA_S_SETUP); + +#if 0 + kprintf("ahci_ata_cmd xa->flags %08x type %08x cmd=%08x\n", + xa->flags, + xa->fis->type, + xa->fis->command); +#endif + + if (ccb->ccb_port->ap_state == AP_S_FATAL_ERROR) + goto failcmd; + + ccb->ccb_done = ahci_ata_cmd_done; + + cmd_slot = ccb->ccb_cmd_hdr; + cmd_slot->flags = htole16(5); /* FIS length (in DWORDs) */ + + if (xa->flags & ATA_F_WRITE) + cmd_slot->flags |= htole16(AHCI_CMD_LIST_FLAG_W); + + if (xa->flags & ATA_F_PACKET) + cmd_slot->flags |= htole16(AHCI_CMD_LIST_FLAG_A); + + if (ahci_load_prdt(ccb) != 0) + goto failcmd; + + xa->state = ATA_S_PENDING; + + if (xa->flags & ATA_F_POLL) { + ahci_poll(ccb, xa->timeout, ahci_ata_cmd_timeout); + return (ATA_COMPLETE); + } + + crit_enter(); + xa->flags |= ATA_F_TIMEOUT_RUNNING; + callout_reset(&ccb->ccb_timeout, xa->timeout, + ahci_ata_cmd_timeout_unserialized, ccb); + ahci_start(ccb); + crit_exit(); + return (ATA_QUEUED); + +failcmd: + crit_enter(); + xa->state = ATA_S_ERROR; + xa->complete(xa); + crit_exit(); + return (ATA_ERROR); +} + +void +ahci_ata_cmd_done(struct ahci_ccb *ccb) +{ + struct ata_xfer *xa = &ccb->ccb_xa; + + if (xa->flags & ATA_F_TIMEOUT_RUNNING) { + xa->flags &= ~ATA_F_TIMEOUT_RUNNING; + callout_stop(&ccb->ccb_timeout); + } + + if (xa->state == ATA_S_ONCHIP || xa->state == ATA_S_ERROR) + ahci_issue_pending_commands(ccb->ccb_port, + xa->flags & ATA_F_NCQ); + + ahci_unload_prdt(ccb); + + if (xa->state == ATA_S_ONCHIP) + xa->state = ATA_S_COMPLETE; +#ifdef DIAGNOSTIC + else if (xa->state != ATA_S_ERROR && xa->state != ATA_S_TIMEOUT) + kprintf("%s: invalid ata_xfer state %02x in ahci_ata_cmd_done, " + "slot %d\n", + PORTNAME(ccb->ccb_port), xa->state, ccb->ccb_slot); +#endif + if (xa->state != ATA_S_TIMEOUT) + xa->complete(xa); +} + +static void +ahci_ata_cmd_timeout_unserialized(void *arg) +{ + struct ahci_ccb *ccb = arg; + struct ahci_port *ap = ccb->ccb_port; + + lwkt_serialize_enter(&ap->ap_sc->sc_serializer); + ahci_ata_cmd_timeout(arg); + lwkt_serialize_exit(&ap->ap_sc->sc_serializer); +} + +static void +ahci_ata_cmd_timeout(void *arg) +{ + struct ahci_ccb *ccb = arg; + struct ata_xfer *xa = &ccb->ccb_xa; + struct ahci_port *ap = ccb->ccb_port; + volatile u_int32_t *active; + int ccb_was_started, ncq_cmd; + + crit_enter(); + kprintf("CMD TIMEOUT port-cmd-reg 0x%b\n" + "\tactive=%08x sactive=%08x\n" + "\t sact=%08x ci=%08x\n", + ahci_pread(ap, AHCI_PREG_CMD), AHCI_PFMT_CMD, + ap->ap_active, ap->ap_sactive, + ahci_pread(ap, AHCI_PREG_SACT), + ahci_pread(ap, AHCI_PREG_CI)); + + /* + * NOTE: Timeout will not be running if the command was polled. + */ + KKASSERT(xa->flags & (ATA_F_POLL|ATA_F_TIMEOUT_RUNNING)); + xa->flags &= ~ATA_F_TIMEOUT_RUNNING; + ncq_cmd = (xa->flags & ATA_F_NCQ); + active = ncq_cmd ? &ap->ap_sactive : &ap->ap_active; + + if (ccb->ccb_xa.state == ATA_S_PENDING) { + DPRINTF(AHCI_D_TIMEOUT, "%s: command for slot %d timed out " + "before it got on chip\n", PORTNAME(ap), ccb->ccb_slot); + TAILQ_REMOVE(&ap->ap_ccb_pending, ccb, ccb_entry); + ccb_was_started = 0; + } else if (ccb->ccb_xa.state == ATA_S_ONCHIP && ahci_port_intr(ap, + 1 << ccb->ccb_slot)) { + DPRINTF(AHCI_D_TIMEOUT, "%s: final poll of port completed " + "command in slot %d\n", PORTNAME(ap), ccb->ccb_slot); + goto ret; + } else if (ccb->ccb_xa.state != ATA_S_ONCHIP) { + DPRINTF(AHCI_D_TIMEOUT, "%s: command slot %d already " + "handled%s\n", PORTNAME(ap), ccb->ccb_slot, + (*active & (1 << ccb->ccb_slot)) ? + " but slot is still active?" : "."); + goto ret; + } else if ((ahci_pread(ap, ncq_cmd ? AHCI_PREG_SACT : AHCI_PREG_CI) & + (1 << ccb->ccb_slot)) == 0 && + (*active & (1 << ccb->ccb_slot))) { + DPRINTF(AHCI_D_TIMEOUT, "%s: command slot %d completed but " + "IRQ handler didn't detect it. Why?\n", PORTNAME(ap), + ccb->ccb_slot); + *active &= ~(1 << ccb->ccb_slot); + ccb->ccb_done(ccb); + goto ret; + } else { + ccb_was_started = 1; + } + + /* Complete the slot with a timeout error. */ + ccb->ccb_xa.state = ATA_S_TIMEOUT; + *active &= ~(1 << ccb->ccb_slot); + DPRINTF(AHCI_D_TIMEOUT, "%s: run completion (1)\n", PORTNAME(ap)); + ccb->ccb_done(ccb); /* This won't issue pending commands or run the + atascsi completion. */ + + /* Reset port to abort running command. */ + if (ccb_was_started) { + DPRINTF(AHCI_D_TIMEOUT, "%s: resetting port to abort%s command " + "in slot %d, active %08x\n", PORTNAME(ap), ncq_cmd ? " NCQ" + : "", ccb->ccb_slot, *active); + if (ahci_port_softreset(ap) != 0 && ahci_port_portreset(ap) + != 0) { + kprintf("%s: failed to reset port during timeout " + "handling, disabling it\n", + PORTNAME(ap)); + ap->ap_state = AP_S_FATAL_ERROR; + } + + /* Restart any other commands that were aborted by the reset. */ + if (*active) { + DPRINTF(AHCI_D_TIMEOUT, "%s: re-enabling%s slots " + "%08x\n", PORTNAME(ap), ncq_cmd ? " NCQ" : "", + *active); + if (ncq_cmd) + ahci_pwrite(ap, AHCI_PREG_SACT, *active); + ahci_pwrite(ap, AHCI_PREG_CI, *active); + } + } + + /* Issue any pending commands now. */ + DPRINTF(AHCI_D_TIMEOUT, "%s: issue pending\n", PORTNAME(ap)); + if (ccb_was_started) + ahci_issue_pending_commands(ap, ncq_cmd); + else if (ap->ap_active == 0) + ahci_issue_pending_ncq_commands(ap); + + /* Complete the timed out ata_xfer I/O (may generate new I/O). */ + DPRINTF(AHCI_D_TIMEOUT, "%s: run completion (2)\n", PORTNAME(ap)); + xa->complete(xa); + + DPRINTF(AHCI_D_TIMEOUT, "%s: splx\n", PORTNAME(ap)); +ret: + crit_exit(); +} + +void +ahci_empty_done(struct ahci_ccb *ccb) +{ + ccb->ccb_xa.state = ATA_S_COMPLETE; +} diff --git a/sys/dev/disk/ahci/ahci.h b/sys/dev/disk/ahci/ahci.h new file mode 100644 index 0000000000..5cb5e3afc0 --- /dev/null +++ b/sys/dev/disk/ahci/ahci.h @@ -0,0 +1,471 @@ +/* + * Copyright (c) 2006 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: ahci.c,v 1.147 2009/02/16 21:19:07 miod Exp $ + */ + +#if defined(__DragonFly__) +#include "ahci_dragonfly.h" +#else +#error "build for OS unknown" +#endif +#include "atascsi.h" + +/* change to AHCI_DEBUG for dmesg spam */ +#define NO_AHCI_DEBUG + +#ifdef AHCI_DEBUG +#define DPRINTF(m, f...) do { if ((ahcidebug & (m)) == (m)) kprintf(f); } \ + while (0) +#define AHCI_D_TIMEOUT 0x00 +#define AHCI_D_VERBOSE 0x01 +#define AHCI_D_INTR 0x02 +#define AHCI_D_XFER 0x08 +int ahcidebug = AHCI_D_VERBOSE; +#else +#define DPRINTF(m, f...) +#endif + +#define AHCI_PCI_BAR 0x24 +#define AHCI_PCI_ATI_SB600_MAGIC 0x40 +#define AHCI_PCI_ATI_SB600_LOCKED 0x01 +#define AHCI_PCI_INTERFACE 0x01 + +#define AHCI_REG_CAP 0x000 /* HBA Capabilities */ +#define AHCI_REG_CAP_NP(_r) (((_r) & 0x1f)+1) /* Number of Ports */ +#define AHCI_REG_CAP_SXS (1<<5) /* External SATA */ +#define AHCI_REG_CAP_EMS (1<<6) /* Enclosure Mgmt */ +#define AHCI_REG_CAP_CCCS (1<<7) /* Cmd Coalescing */ +#define AHCI_REG_CAP_NCS(_r) ((((_r) & 0x1f00)>>8)+1) /* NCmds*/ +#define AHCI_REG_CAP_PSC (1<<13) /* Partial State Capable */ +#define AHCI_REG_CAP_SSC (1<<14) /* Slumber State Capable */ +#define AHCI_REG_CAP_PMD (1<<15) /* PIO Multiple DRQ Block */ +#define AHCI_REG_CAP_FBSS (1<<16) /* FIS-Based Switching */ +#define AHCI_REG_CAP_SPM (1<<17) /* Port Multiplier */ +#define AHCI_REG_CAP_SAM (1<<18) /* AHCI Only mode */ +#define AHCI_REG_CAP_SNZO (1<<19) /* Non Zero DMA Offsets */ +#define AHCI_REG_CAP_ISS (0xf<<20) /* Interface Speed Support */ +#define AHCI_REG_CAP_ISS_G1 (0x1<<20) /* Gen 1 (1.5 Gbps) */ +#define AHCI_REG_CAP_ISS_G1_2 (0x2<<20) /* Gen 1 and 2 (3 Gbps) */ +#define AHCI_REG_CAP_SCLO (1<<24) /* Cmd List Override */ +#define AHCI_REG_CAP_SAL (1<<25) /* Activity LED */ +#define AHCI_REG_CAP_SALP (1<<26) /* Aggressive Link Pwr Mgmt */ +#define AHCI_REG_CAP_SSS (1<<27) /* Staggered Spinup */ +#define AHCI_REG_CAP_SMPS (1<<28) /* Mech Presence Switch */ +#define AHCI_REG_CAP_SSNTF (1<<29) /* SNotification Register */ +#define AHCI_REG_CAP_SNCQ (1<<30) /* Native Cmd Queuing */ +#define AHCI_REG_CAP_S64A (1<<31) /* 64bit Addressing */ +#define AHCI_FMT_CAP "\020" "\040S64A" "\037NCQ" "\036SSNTF" \ + "\035SMPS" "\034SSS" "\033SALP" "\032SAL" \ + "\031SCLO" "\024SNZO" "\023SAM" "\022SPM" \ + "\021FBSS" "\020PMD" "\017SSC" "\016PSC" \ + "\010CCCS" "\007EMS" "\006SXS" + +#define AHCI_REG_GHC 0x004 /* Global HBA Control */ +#define AHCI_REG_GHC_HR (1<<0) /* HBA Reset */ +#define AHCI_REG_GHC_IE (1<<1) /* Interrupt Enable */ +#define AHCI_REG_GHC_MRSM (1<<2) /* MSI Revert to Single Msg */ +#define AHCI_REG_GHC_AE (1<<31) /* AHCI Enable */ +#define AHCI_FMT_GHC "\020" "\040AE" "\003MRSM" "\002IE" "\001HR" + +#define AHCI_REG_IS 0x008 /* Interrupt Status */ +#define AHCI_REG_PI 0x00c /* Ports Implemented */ + +#define AHCI_REG_VS 0x010 /* AHCI Version */ +#define AHCI_REG_VS_0_95 0x00000905 /* 0.95 */ +#define AHCI_REG_VS_1_0 0x00010000 /* 1.0 */ +#define AHCI_REG_VS_1_1 0x00010100 /* 1.1 */ +#define AHCI_REG_VS_1_2 0x00010200 /* 1.2 */ + +#define AHCI_REG_CCC_CTL 0x014 /* Coalescing Control */ +#define AHCI_REG_CCC_CTL_INT(_r) (((_r) & 0xf8) >> 3) /* CCC INT slot */ + +#define AHCI_REG_CCC_PORTS 0x018 /* Coalescing Ports */ +#define AHCI_REG_EM_LOC 0x01c /* Enclosure Mgmt Location */ +#define AHCI_REG_EM_CTL 0x020 /* Enclosure Mgmt Control */ + +#define AHCI_PORT_REGION(_p) (0x100 + ((_p) * 0x80)) +#define AHCI_PORT_SIZE 0x80 + +#define AHCI_PREG_CLB 0x00 /* Cmd List Base Addr */ +#define AHCI_PREG_CLBU 0x04 /* Cmd List Base Hi Addr */ +#define AHCI_PREG_FB 0x08 /* FIS Base Addr */ +#define AHCI_PREG_FBU 0x0c /* FIS Base Hi Addr */ + +#define AHCI_PREG_IS 0x10 /* Interrupt Status */ +#define AHCI_PREG_IS_DHRS (1<<0) /* Device to Host FIS */ +#define AHCI_PREG_IS_PSS (1<<1) /* PIO Setup FIS */ +#define AHCI_PREG_IS_DSS (1<<2) /* DMA Setup FIS */ +#define AHCI_PREG_IS_SDBS (1<<3) /* Set Device Bits FIS */ +#define AHCI_PREG_IS_UFS (1<<4) /* Unknown FIS */ +#define AHCI_PREG_IS_DPS (1<<5) /* Descriptor Processed */ +#define AHCI_PREG_IS_PCS (1<<6) /* Port Change */ +#define AHCI_PREG_IS_DMPS (1<<7) /* Device Mechanical Presence */ +#define AHCI_PREG_IS_PRCS (1<<22) /* PhyRdy Change */ +#define AHCI_PREG_IS_IPMS (1<<23) /* Incorrect Port Multiplier */ +#define AHCI_PREG_IS_OFS (1<<24) /* Overflow */ +#define AHCI_PREG_IS_INFS (1<<26) /* Interface Non-fatal Error */ +#define AHCI_PREG_IS_IFS (1<<27) /* Interface Fatal Error */ +#define AHCI_PREG_IS_HBDS (1<<28) /* Host Bus Data Error */ +#define AHCI_PREG_IS_HBFS (1<<29) /* Host Bus Fatal Error */ +#define AHCI_PREG_IS_TFES (1<<30) /* Task File Error */ +#define AHCI_PREG_IS_CPDS (1<<31) /* Cold Presence Detect */ +#define AHCI_PFMT_IS "\20" "\040CPDS" "\037TFES" "\036HBFS" \ + "\035HBDS" "\034IFS" "\033INFS" "\031OFS" \ + "\030IPMS" "\027PRCS" "\010DMPS" "\006DPS" \ + "\007PCS" "\005UFS" "\004SDBS" "\003DSS" \ + "\002PSS" "\001DHRS" + +#define AHCI_PREG_IE 0x14 /* Interrupt Enable */ +#define AHCI_PREG_IE_DHRE (1<<0) /* Device to Host FIS */ +#define AHCI_PREG_IE_PSE (1<<1) /* PIO Setup FIS */ +#define AHCI_PREG_IE_DSE (1<<2) /* DMA Setup FIS */ +#define AHCI_PREG_IE_SDBE (1<<3) /* Set Device Bits FIS */ +#define AHCI_PREG_IE_UFE (1<<4) /* Unknown FIS */ +#define AHCI_PREG_IE_DPE (1<<5) /* Descriptor Processed */ +#define AHCI_PREG_IE_PCE (1<<6) /* Port Change */ +#define AHCI_PREG_IE_DMPE (1<<7) /* Device Mechanical Presence */ +#define AHCI_PREG_IE_PRCE (1<<22) /* PhyRdy Change */ +#define AHCI_PREG_IE_IPME (1<<23) /* Incorrect Port Multiplier */ +#define AHCI_PREG_IE_OFE (1<<24) /* Overflow */ +#define AHCI_PREG_IE_INFE (1<<26) /* Interface Non-fatal Error */ +#define AHCI_PREG_IE_IFE (1<<27) /* Interface Fatal Error */ +#define AHCI_PREG_IE_HBDE (1<<28) /* Host Bus Data Error */ +#define AHCI_PREG_IE_HBFE (1<<29) /* Host Bus Fatal Error */ +#define AHCI_PREG_IE_TFEE (1<<30) /* Task File Error */ +#define AHCI_PREG_IE_CPDE (1<<31) /* Cold Presence Detect */ +#define AHCI_PFMT_IE "\20" "\040CPDE" "\037TFEE" "\036HBFE" \ + "\035HBDE" "\034IFE" "\033INFE" "\031OFE" \ + "\030IPME" "\027PRCE" "\010DMPE" "\007PCE" \ + "\006DPE" "\005UFE" "\004SDBE" "\003DSE" \ + "\002PSE" "\001DHRE" + +#define AHCI_PREG_CMD 0x18 /* Command and Status */ +#define AHCI_PREG_CMD_ST (1<<0) /* Start */ +#define AHCI_PREG_CMD_SUD (1<<1) /* Spin Up Device */ +#define AHCI_PREG_CMD_POD (1<<2) /* Power On Device */ +#define AHCI_PREG_CMD_CLO (1<<3) /* Command List Override */ +#define AHCI_PREG_CMD_FRE (1<<4) /* FIS Receive Enable */ +#define AHCI_PREG_CMD_CCS(_r) (((_r) >> 8) & 0x1f) /* Curr CmdSlot# */ +#define AHCI_PREG_CMD_MPSS (1<<13) /* Mech Presence State */ +#define AHCI_PREG_CMD_FR (1<<14) /* FIS Receive Running */ +#define AHCI_PREG_CMD_CR (1<<15) /* Command List Running */ +#define AHCI_PREG_CMD_CPS (1<<16) /* Cold Presence State */ +#define AHCI_PREG_CMD_PMA (1<<17) /* Port Multiplier Attached */ +#define AHCI_PREG_CMD_HPCP (1<<18) /* Hot Plug Capable */ +#define AHCI_PREG_CMD_MPSP (1<<19) /* Mech Presence Switch */ +#define AHCI_PREG_CMD_CPD (1<<20) /* Cold Presence Detection */ +#define AHCI_PREG_CMD_ESP (1<<21) /* External SATA Port */ +#define AHCI_PREG_CMD_ATAPI (1<<24) /* Device is ATAPI */ +#define AHCI_PREG_CMD_DLAE (1<<25) /* Drv LED on ATAPI Enable */ +#define AHCI_PREG_CMD_ALPE (1<<26) /* Aggro Pwr Mgmt Enable */ +#define AHCI_PREG_CMD_ASP (1<<27) /* Aggro Slumber/Partial */ +#define AHCI_PREG_CMD_ICC 0xf0000000 /* Interface Comm Ctrl */ +#define AHCI_PREG_CMD_ICC_SLUMBER 0x60000000 +#define AHCI_PREG_CMD_ICC_PARTIAL 0x20000000 +#define AHCI_PREG_CMD_ICC_ACTIVE 0x10000000 +#define AHCI_PREG_CMD_ICC_IDLE 0x00000000 +#define AHCI_PFMT_CMD "\020" "\034ASP" "\033ALPE" "\032DLAE" \ + "\031ATAPI" "\026ESP" "\025CPD" "\024MPSP" \ + "\023HPCP" "\022PMA" "\021CPS" "\020CR" \ + "\017FR" "\016MPSS" "\005FRE" "\004CLO" \ + "\003POD" "\002SUD" "\001ST" + +#define AHCI_PREG_TFD 0x20 /* Task File Data*/ +#define AHCI_PREG_TFD_STS 0xff +#define AHCI_PREG_TFD_STS_ERR (1<<0) +#define AHCI_PREG_TFD_STS_DRQ (1<<3) +#define AHCI_PREG_TFD_STS_BSY (1<<7) +#define AHCI_PREG_TFD_ERR 0xff00 + +#define AHCI_PFMT_TFD_STS "\20" "\010BSY" "\004DRQ" "\001ERR" +#define AHCI_PREG_SIG 0x24 /* Signature */ + +#define AHCI_PREG_SSTS 0x28 /* SATA Status */ +#define AHCI_PREG_SSTS_DET 0xf /* Device Detection */ +#define AHCI_PREG_SSTS_DET_NONE 0x0 +#define AHCI_PREG_SSTS_DET_DEV_NE 0x1 +#define AHCI_PREG_SSTS_DET_DEV 0x3 +#define AHCI_PREG_SSTS_DET_PHYOFFLINE 0x4 +#define AHCI_PREG_SSTS_SPD 0xf0 /* Current Interface Speed */ +#define AHCI_PREG_SSTS_SPD_NONE 0x00 +#define AHCI_PREG_SSTS_SPD_GEN1 0x10 +#define AHCI_PREG_SSTS_SPD_GEN2 0x20 +#define AHCI_PREG_SSTS_IPM 0xf00 /* Interface Power Management */ +#define AHCI_PREG_SSTS_IPM_NONE 0x000 +#define AHCI_PREG_SSTS_IPM_ACTIVE 0x100 +#define AHCI_PREG_SSTS_IPM_PARTIAL 0x200 +#define AHCI_PREG_SSTS_IPM_SLUMBER 0x600 + +#define AHCI_PREG_SCTL 0x2c /* SATA Control */ +#define AHCI_PREG_SCTL_DET 0xf /* Device Detection */ +#define AHCI_PREG_SCTL_DET_NONE 0x0 +#define AHCI_PREG_SCTL_DET_INIT 0x1 +#define AHCI_PREG_SCTL_DET_DISABLE 0x4 +#define AHCI_PREG_SCTL_SPD 0xf0 /* Speed Allowed */ +#define AHCI_PREG_SCTL_SPD_ANY 0x00 +#define AHCI_PREG_SCTL_SPD_GEN1 0x10 +#define AHCI_PREG_SCTL_SPD_GEN2 0x20 +#define AHCI_PREG_SCTL_IPM 0xf00 /* Interface Power Management */ +#define AHCI_PREG_SCTL_IPM_NONE 0x000 +#define AHCI_PREG_SCTL_IPM_NOPARTIAL 0x100 +#define AHCI_PREG_SCTL_IPM_NOSLUMBER 0x200 +#define AHCI_PREG_SCTL_IPM_DISABLED 0x300 + +#define AHCI_PREG_SERR 0x30 /* SATA Error */ +#define AHCI_PREG_SERR_ERR(_r) ((_r) & 0xffff) +#define AHCI_PREG_SERR_ERR_I (1<<0) /* Recovered Data Integrity */ +#define AHCI_PREG_SERR_ERR_M (1<<1) /* Recovered Communications */ +#define AHCI_PREG_SERR_ERR_T (1<<8) /* Transient Data Integrity */ +#define AHCI_PREG_SERR_ERR_C (1<<9) /* Persistent Comm/Data */ +#define AHCI_PREG_SERR_ERR_P (1<<10) /* Protocol */ +#define AHCI_PREG_SERR_ERR_E (1<<11) /* Internal */ +#define AHCI_PFMT_SERR_ERR "\020" "\014E" "\013P" "\012C" "\011T" "\002M" \ + "\001I" +#define AHCI_PREG_SERR_DIAG(_r) (((_r) >> 16) & 0xffff) +#define AHCI_PREG_SERR_DIAG_N (1<<0) /* PhyRdy Change */ +#define AHCI_PREG_SERR_DIAG_I (1<<1) /* Phy Internal Error */ +#define AHCI_PREG_SERR_DIAG_W (1<<2) /* Comm Wake */ +#define AHCI_PREG_SERR_DIAG_B (1<<3) /* 10B to 8B Decode Error */ +#define AHCI_PREG_SERR_DIAG_D (1<<4) /* Disparity Error */ +#define AHCI_PREG_SERR_DIAG_C (1<<5) /* CRC Error */ +#define AHCI_PREG_SERR_DIAG_H (1<<6) /* Handshake Error */ +#define AHCI_PREG_SERR_DIAG_S (1<<7) /* Link Sequence Error */ +#define AHCI_PREG_SERR_DIAG_T (1<<8) /* Transport State Trans Err */ +#define AHCI_PREG_SERR_DIAG_F (1<<9) /* Unknown FIS Type */ +#define AHCI_PREG_SERR_DIAG_X (1<<10) /* Exchanged */ +#define AHCI_PFMT_SERR_DIAG "\020" "\013X" "\012F" "\011T" "\010S" "\007H" \ + "\006C" "\005D" "\004B" "\003W" "\002I" \ + "\001N" + +#define AHCI_PREG_SACT 0x34 /* SATA Active */ +#define AHCI_PREG_CI 0x38 /* Command Issue */ +#define AHCI_PREG_CI_ALL_SLOTS 0xffffffff +#define AHCI_PREG_SNTF 0x3c /* SNotification */ + +struct ahci_cmd_hdr { + u_int16_t flags; +#define AHCI_CMD_LIST_FLAG_CFL 0x001f /* Command FIS Length */ +#define AHCI_CMD_LIST_FLAG_A (1<<5) /* ATAPI */ +#define AHCI_CMD_LIST_FLAG_W (1<<6) /* Write */ +#define AHCI_CMD_LIST_FLAG_P (1<<7) /* Prefetchable */ +#define AHCI_CMD_LIST_FLAG_R (1<<8) /* Reset */ +#define AHCI_CMD_LIST_FLAG_B (1<<9) /* BIST */ +#define AHCI_CMD_LIST_FLAG_C (1<<10) /* Clear Busy upon R_OK */ +#define AHCI_CMD_LIST_FLAG_PMP 0xf000 /* Port Multiplier Port */ + u_int16_t prdtl; /* sgl len */ + + u_int32_t prdbc; /* transferred byte count */ + + u_int32_t ctba_lo; + u_int32_t ctba_hi; + + u_int32_t reserved[4]; +} __packed; + +struct ahci_rfis { + u_int8_t dsfis[28]; + u_int8_t reserved1[4]; + u_int8_t psfis[24]; + u_int8_t reserved2[8]; + u_int8_t rfis[24]; + u_int8_t reserved3[4]; + u_int8_t sdbfis[4]; + u_int8_t ufis[64]; + u_int8_t reserved4[96]; +} __packed; + +struct ahci_prdt { + u_int32_t dba_lo; + u_int32_t dba_hi; + u_int32_t reserved; + u_int32_t flags; +#define AHCI_PRDT_FLAG_INTR (1<<31) /* interrupt on completion */ +} __packed; + +/* + * The base command table structure is 128 bytes. Each prdt is 16 bytes. + * We need to accomodate MAXPHYS (128K) which is at least 32 entries, + * plus one for page slop. + * + * Making the ahci_cmd_table 1024 bytes (a reasonable power of 2) + * thus requires MAX_PRDT to be set to 56. + */ +#define AHCI_MAX_PRDT 56 + +#if MAXPHYS / PAGE_SIZE + 1 > AHCI_MAX_PRDT +#error "AHCI_MAX_PRDT is not big enough" +#endif + +struct ahci_cmd_table { + u_int8_t cfis[64]; /* Command FIS */ + u_int8_t acmd[16]; /* ATAPI Command */ + u_int8_t reserved[48]; + + struct ahci_prdt prdt[AHCI_MAX_PRDT]; +} __packed; + +#define AHCI_MAX_PORTS 32 + +struct ahci_dmamem { + bus_dma_tag_t adm_tag; + bus_dmamap_t adm_map; + bus_dma_segment_t adm_seg; + bus_addr_t adm_busaddr; + caddr_t adm_kva; +}; +#define AHCI_DMA_MAP(_adm) ((_adm)->adm_map) +#define AHCI_DMA_DVA(_adm) ((_adm)->adm_busaddr) +#define AHCI_DMA_KVA(_adm) ((void *)(_adm)->adm_kva) + +struct ahci_softc; +struct ahci_port; +struct ahci_device; + +struct ahci_ccb { + /* ATA xfer associated with this CCB. Must be 1st struct member. */ + struct ata_xfer ccb_xa; + struct callout ccb_timeout; + + int ccb_slot; + struct ahci_port *ccb_port; + + bus_dmamap_t ccb_dmamap; + struct ahci_cmd_hdr *ccb_cmd_hdr; + struct ahci_cmd_table *ccb_cmd_table; + + void (*ccb_done)(struct ahci_ccb *); + + TAILQ_ENTRY(ahci_ccb) ccb_entry; +}; + +struct ahci_port { + struct ahci_softc *ap_sc; + bus_space_handle_t ap_ioh; + + int ap_num; + int ap_flags; +#define AP_F_BUS_REGISTERED 0x0001 +#define AP_F_CAM_ATTACHED 0x0002 + struct cam_sim *ap_sim; + struct cam_path *ap_path; + + struct ahci_rfis *ap_rfis; + struct ahci_dmamem *ap_dmamem_rfis; + + struct ahci_dmamem *ap_dmamem_cmd_list; + struct ahci_dmamem *ap_dmamem_cmd_table; + + volatile u_int32_t ap_active; + volatile u_int32_t ap_active_cnt; + volatile u_int32_t ap_sactive; + struct ahci_ccb *ap_ccbs; + + TAILQ_HEAD(, ahci_ccb) ap_ccb_free; + TAILQ_HEAD(, ahci_ccb) ap_ccb_pending; + struct lock ap_ccb_lock; + + struct ata_port ap_ata; + + u_int32_t ap_state; +#define AP_S_NORMAL 0 +#define AP_S_FATAL_ERROR 1 + + /* For error recovery. */ +#ifdef DIAGNOSTIC + int ap_err_busy; +#endif + u_int32_t ap_err_saved_sactive; + u_int32_t ap_err_saved_active; + u_int32_t ap_err_saved_active_cnt; + + u_int8_t ap_err_scratch[512]; + + char ap_name[16]; +}; + +#define PORTNAME(_ap) ((_ap)->ap_name) + +struct ahci_softc { + device_t sc_dev; + const struct ahci_device *sc_ad; /* special casing */ + struct lwkt_serialize sc_serializer; + + struct resource *sc_irq; /* bus resources */ + struct resource *sc_regs; /* bus resources */ + bus_space_tag_t sc_iot; /* split from sc_regs */ + bus_space_handle_t sc_ioh; /* split from sc_regs */ + + int sc_rid_irq; /* saved bus RIDs */ + int sc_rid_regs; + u_int32_t sc_cap; /* capabilities */ + + void *sc_irq_handle; /* installed irq vector */ + + bus_dma_tag_t sc_tag_rfis; /* bus DMA tags */ + bus_dma_tag_t sc_tag_cmdh; + bus_dma_tag_t sc_tag_cmdt; + bus_dma_tag_t sc_tag_data; + + int sc_flags; +#define AHCI_F_NO_NCQ (1<<0) +#define AHCI_F_IGN_FR (1<<1) + + u_int sc_ncmds; + + struct ahci_port *sc_ports[AHCI_MAX_PORTS]; + +#ifdef AHCI_COALESCE + u_int32_t sc_ccc_mask; + u_int32_t sc_ccc_ports; + u_int32_t sc_ccc_ports_cur; +#endif +}; +#define DEVNAME(_s) ((_s)->sc_dev.dv_xname) + +struct ahci_device { + pci_vendor_id_t ad_vendor; + pci_product_id_t ad_product; + int (*ad_attach)(device_t dev); + int (*ad_detach)(device_t dev); + char *name; +}; + +const struct ahci_device *ahci_lookup_device(device_t dev); +int ahci_init(struct ahci_softc *); +int ahci_port_alloc(struct ahci_softc *, u_int); +void ahci_port_free(struct ahci_softc *, u_int); +int ahci_port_softreset(struct ahci_port *); +int ahci_port_portreset(struct ahci_port *); + +u_int32_t ahci_read(struct ahci_softc *, bus_size_t); +void ahci_write(struct ahci_softc *, bus_size_t, u_int32_t); +int ahci_wait_ne(struct ahci_softc *, bus_size_t, u_int32_t, u_int32_t); +u_int32_t ahci_pread(struct ahci_port *, bus_size_t); +void ahci_pwrite(struct ahci_port *, bus_size_t, u_int32_t); +int ahci_pwait_eq(struct ahci_port *, int, bus_size_t, + u_int32_t, u_int32_t); +void ahci_intr(void *); +u_int32_t ahci_port_intr(struct ahci_port *, u_int32_t); + +int ahci_cam_attach(struct ahci_port *ap); +void ahci_cam_changed(struct ahci_port *ap, int found); +void ahci_cam_detach(struct ahci_port *ap); + +struct ata_xfer *ahci_ata_get_xfer(struct ahci_port *ap); +void ahci_ata_put_xfer(struct ata_xfer *xa); +int ahci_ata_cmd(struct ata_xfer *xa); + +extern u_int32_t AhciForceGen1; diff --git a/sys/dev/disk/ahci/ahci_attach.c b/sys/dev/disk/ahci/ahci_attach.c new file mode 100644 index 0000000000..4bc1aba98f --- /dev/null +++ b/sys/dev/disk/ahci/ahci_attach.c @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2006 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * Copyright (c) 2009 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $OpenBSD: ahci.c,v 1.147 2009/02/16 21:19:07 miod Exp $ + */ + +#include "ahci.h" + +static int ahci_vt8251_attach(device_t); +static int ahci_ati_sb600_attach(device_t); +static int ahci_nvidia_mcp_attach(device_t); +static int ahci_pci_attach(device_t); +static int ahci_pci_detach(device_t); + +static const struct ahci_device ahci_devices[] = { + { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8251_SATA, + ahci_vt8251_attach, ahci_pci_detach, "ViaTech-VT8251-SATA" }, + { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB600_SATA, + ahci_ati_sb600_attach, ahci_pci_detach, "ATI-SB600-SATA" }, + { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_AHCI_2, + ahci_nvidia_mcp_attach, ahci_pci_detach, "NVidia-MCP65-SATA" }, + { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_1, + ahci_nvidia_mcp_attach, ahci_pci_detach, "NVidia-MCP67-SATA" }, + { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_5, + ahci_nvidia_mcp_attach, ahci_pci_detach, "NVidia-MCP77-SATA" }, + { 0, 0, + ahci_pci_attach, ahci_pci_detach, "AHCI-PCI-SATA" } +}; + +u_int32_t AhciForceGen1 = 0; /* XXX add sysctl/kenv support */ + +/* + * Match during probe and attach. The device does not yet have a softc. + */ +const struct ahci_device * +ahci_lookup_device(device_t dev) +{ + const struct ahci_device *ad; + u_int16_t vendor = pci_get_vendor(dev); + u_int16_t product = pci_get_device(dev); + u_int8_t class = pci_get_class(dev); + u_int8_t subclass = pci_get_subclass(dev); + u_int8_t progif = pci_read_config(dev, PCIR_PROGIF, 1); + + for (ad = &ahci_devices[0]; ad->ad_vendor; ++ad) { + if (ad->ad_vendor == vendor && ad->ad_product == product) + return (ad); + } + + /* + * Last ad is the default match if the PCI device matches SATA. + */ + if (class == PCIC_STORAGE && subclass == PCIS_STORAGE_SATA && + progif == PCIP_STORAGE_SATA_AHCI_1_0) { + kprintf("match generic sata\n"); + return (ad); + } + + return (NULL); +} + +/* + * Attach functions. They all eventually fall through to ahci_pci_attach(). + */ +static int +ahci_vt8251_attach(device_t dev) +{ + struct ahci_softc *sc = device_get_softc(dev); + + sc->sc_flags |= AHCI_F_NO_NCQ; + return (ahci_pci_attach(dev)); +} + +static int +ahci_ati_sb600_attach(device_t dev) +{ + struct ahci_softc *sc = device_get_softc(dev); + pcireg_t magic; + u_int8_t subclass = pci_get_subclass(dev); + u_int8_t revid; + + if (subclass == PCIS_STORAGE_IDE) { + revid = pci_read_config(dev, PCIR_REVID, 1); + magic = pci_read_config(dev, AHCI_PCI_ATI_SB600_MAGIC, 4); + pci_write_config(dev, AHCI_PCI_ATI_SB600_MAGIC, + magic | AHCI_PCI_ATI_SB600_LOCKED, 4); + pci_write_config(dev, PCIR_REVID, + (PCIC_STORAGE << 24) | + (PCIS_STORAGE_SATA << 16) | + (PCIP_STORAGE_SATA_AHCI_1_0 << 8) | + revid, 4); + pci_write_config(dev, AHCI_PCI_ATI_SB600_MAGIC, magic, 4); + } + + sc->sc_flags |= AHCI_F_IGN_FR; + return (ahci_pci_attach(dev)); +} + +static int +ahci_nvidia_mcp_attach(device_t dev) +{ + struct ahci_softc *sc = device_get_softc(dev); + + sc->sc_flags |= AHCI_F_IGN_FR; + return (ahci_pci_attach(dev)); +} + +static int +ahci_pci_attach(device_t dev) +{ + struct ahci_softc *sc = device_get_softc(dev); + const char *gen; + u_int32_t cap, pi, reg; + bus_addr_t addr; + int i; + int error; + const char *revision; + + /* + * Map the AHCI controller's IRQ and BAR(5) (hardware registers) + */ + sc->sc_dev = dev; + sc->sc_rid_irq = AHCI_IRQ_RID; + sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_rid_irq, + RF_SHAREABLE | RF_ACTIVE); + lwkt_serialize_init(&sc->sc_serializer); + lwkt_serialize_enter(&sc->sc_serializer); + if (sc->sc_irq == NULL) { + device_printf(dev, "unable to map interrupt\n"); + lwkt_serialize_exit(&sc->sc_serializer); + ahci_pci_detach(dev); + return (ENXIO); + } + + /* + * When mapping the register window store the tag and handle + * separately so we can use the tag with per-port bus handle + * sub-spaces. + */ + sc->sc_rid_regs = PCIR_BAR(5); + sc->sc_regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->sc_rid_regs, RF_ACTIVE); + if (sc->sc_regs == NULL) { + device_printf(dev, "unable to map registers\n"); + lwkt_serialize_exit(&sc->sc_serializer); + ahci_pci_detach(dev); + return (ENXIO); + } + sc->sc_iot = rman_get_bustag(sc->sc_regs); + sc->sc_ioh = rman_get_bushandle(sc->sc_regs); + + /* + * Initialize the chipset and then set the interrupt vector up + */ + error = ahci_init(sc); + if (error) { + lwkt_serialize_exit(&sc->sc_serializer); + ahci_pci_detach(dev); + return (ENXIO); + } + + /* + * Get the AHCI capabilities and max number of concurrent + * command tags and set up the DMA tags. + */ + cap = ahci_read(sc, AHCI_REG_CAP); + if (sc->sc_flags & AHCI_F_NO_NCQ) + cap &= ~AHCI_REG_CAP_SNCQ; + sc->sc_cap = cap; + sc->sc_ncmds = AHCI_REG_CAP_NCS(cap); + + addr = (cap & AHCI_REG_CAP_S64A) ? + BUS_SPACE_MAXADDR : BUS_SPACE_MAXADDR_32BIT; + + /* + * DMA tags for allocation of DMA memory buffers, lists, and so + * forth. These are typically per-port. + */ + error = 0; + error += bus_dma_tag_create( + NULL, /* parent tag */ + 256, /* alignment */ + PAGE_SIZE, /* boundary */ + addr, /* loaddr? */ + BUS_SPACE_MAXADDR, /* hiaddr */ + NULL, /* filter */ + NULL, /* filterarg */ + sizeof(struct ahci_rfis), /* [max]size */ + 1, /* maxsegs */ + sizeof(struct ahci_rfis), /* maxsegsz */ + 0, /* flags */ + &sc->sc_tag_rfis); /* return tag */ + + error += bus_dma_tag_create( + NULL, /* parent tag */ + 32, /* alignment */ + 4096 * 1024, /* boundary */ + addr, /* loaddr? */ + BUS_SPACE_MAXADDR, /* hiaddr */ + NULL, /* filter */ + NULL, /* filterarg */ + sc->sc_ncmds * sizeof(struct ahci_cmd_hdr), + 1, /* maxsegs */ + sc->sc_ncmds * sizeof(struct ahci_cmd_hdr), + 0, /* flags */ + &sc->sc_tag_cmdh); /* return tag */ + + /* + * NOTE: ahci_cmd_table is sized to a power of 2 + */ + error += bus_dma_tag_create( + NULL, /* parent tag */ + sizeof(struct ahci_cmd_table), /* alignment */ + 4096 * 1024, /* boundary */ + addr, /* loaddr? */ + BUS_SPACE_MAXADDR, /* hiaddr */ + NULL, /* filter */ + NULL, /* filterarg */ + sc->sc_ncmds * sizeof(struct ahci_cmd_table), + 1, /* maxsegs */ + sc->sc_ncmds * sizeof(struct ahci_cmd_table), + 0, /* flags */ + &sc->sc_tag_cmdt); /* return tag */ + + /* + * The data tag is used for later dmamaps and not immediately + * allocated. + */ + error += bus_dma_tag_create( + NULL, /* parent tag */ + 4, /* alignment */ + 0, /* boundary */ + addr, /* loaddr? */ + BUS_SPACE_MAXADDR, /* hiaddr */ + NULL, /* filter */ + NULL, /* filterarg */ + 4096 * 1024, /* maxiosize */ + AHCI_MAX_PRDT, /* maxsegs */ + 65536, /* maxsegsz */ + 0, /* flags */ + &sc->sc_tag_data); /* return tag */ + + if (error) { + device_printf(dev, "unable to create dma tags\n"); + lwkt_serialize_exit(&sc->sc_serializer); + ahci_pci_detach(dev); + return (ENXIO); + } + + switch (cap & AHCI_REG_CAP_ISS) { + case AHCI_REG_CAP_ISS_G1: + gen = "1 (1.5Gbps)"; + break; + case AHCI_REG_CAP_ISS_G1_2: + gen = "1 (1.5Gbps) and 2 (3Gbps)"; + break; + default: + gen = "unknown"; + break; + } + + /* check the revision */ + reg = ahci_read(sc, AHCI_REG_VS); + switch (reg) { + case AHCI_REG_VS_0_95: + revision = "AHCI 0.95"; + break; + case AHCI_REG_VS_1_0: + revision = "AHCI 1.0"; + break; + case AHCI_REG_VS_1_1: + revision = "AHCI 1.1"; + break; + case AHCI_REG_VS_1_2: + revision = "AHCI 1.2"; + break; + default: + device_printf(sc->sc_dev, + "Warning: Unknown AHCI revision 0x%08x\n", reg); + revision = "AHCI "; + break; + } + + device_printf(dev, + "%s capabilities 0x%b, %d ports, %d tags/port, gen %s\n", + revision, + cap, AHCI_FMT_CAP, + AHCI_REG_CAP_NP(cap), sc->sc_ncmds, gen); + + pi = ahci_read(sc, AHCI_REG_PI); + DPRINTF(AHCI_D_VERBOSE, "%s: ports implemented: 0x%08x\n", + DEVNAME(sc), pi); + +#ifdef AHCI_COALESCE + /* Naive coalescing support - enable for all ports. */ + if (cap & AHCI_REG_CAP_CCCS) { + u_int16_t ccc_timeout = 20; + u_int8_t ccc_numcomplete = 12; + u_int32_t ccc_ctl; + + /* disable coalescing during reconfiguration. */ + ccc_ctl = ahci_read(sc, AHCI_REG_CCC_CTL); + ccc_ctl &= ~0x00000001; + ahci_write(sc, AHCI_REG_CCC_CTL, ccc_ctl); + + sc->sc_ccc_mask = 1 << AHCI_REG_CCC_CTL_INT(ccc_ctl); + if (pi & sc->sc_ccc_mask) { + /* A conflict with the implemented port list? */ + printf("%s: coalescing interrupt/implemented port list " + "conflict, PI: %08x, ccc_mask: %08x\n", + DEVNAME(sc), pi, sc->sc_ccc_mask); + sc->sc_ccc_mask = 0; + goto noccc; + } + + /* ahci_port_start will enable each port when it starts. */ + sc->sc_ccc_ports = pi; + sc->sc_ccc_ports_cur = 0; + + /* program thresholds and enable overall coalescing. */ + ccc_ctl &= ~0xffffff00; + ccc_ctl |= (ccc_timeout << 16) | (ccc_numcomplete << 8); + ahci_write(sc, AHCI_REG_CCC_CTL, ccc_ctl); + ahci_write(sc, AHCI_REG_CCC_PORTS, 0); + ahci_write(sc, AHCI_REG_CCC_CTL, ccc_ctl | 1); + } +noccc: +#endif + /* + * Allocate per-port resources + * + * Ignore attach errors, leave the port intact for + * rescan and continue the loop. + */ + for (i = 0; error == 0 && i < AHCI_MAX_PORTS; i++) { + if ((pi & (1 << i)) == 0) { + /* dont allocate stuff if the port isnt implemented */ + continue; + } + error = ahci_port_alloc(sc, i); + if (error == 0) { + ahci_cam_attach(sc->sc_ports[i]); + } + if (error == ENODEV) + error = 0; + } + + /* + * Setup the interrupt vector and enable interrupts. Note that + * since the irq may be shared we do not set it up until we are + * ready to go. + */ + if (error == 0) { + error = bus_setup_intr(dev, sc->sc_irq, 0, ahci_intr, sc, + &sc->sc_irq_handle, &sc->sc_serializer); + } + + if (error) { + device_printf(dev, "unable to install interrupt\n"); + lwkt_serialize_exit(&sc->sc_serializer); + ahci_pci_detach(dev); + return (ENXIO); + } + ahci_write(sc, AHCI_REG_GHC, AHCI_REG_GHC_AE | AHCI_REG_GHC_IE); + lwkt_serialize_exit(&sc->sc_serializer); + + return(0); +} + +/* + * Device unload / detachment + */ +static int +ahci_pci_detach(device_t dev) +{ + struct ahci_softc *sc = device_get_softc(dev); + struct ahci_port *ap; + int i; + + /* + * Disable the controller and de-register the interrupt, if any. + * + * XXX interlock serializer against interrupt + */ + lwkt_serialize_handler_disable(&sc->sc_serializer); + if (sc->sc_regs) { + ahci_write(sc, AHCI_REG_GHC, 0); + } + if (sc->sc_irq_handle) { + bus_teardown_intr(dev, sc->sc_irq, sc->sc_irq_handle); + sc->sc_irq_handle = NULL; + } + + /* + * Free port structures and DMA memory + */ + for (i = 0; i < AHCI_MAX_PORTS; i++) { + ap = sc->sc_ports[i]; + if (ap) { + ahci_cam_detach(ap); + ahci_port_free(sc, i); + } + } + + /* + * Clean up the bus space + */ + if (sc->sc_irq) { + bus_release_resource(dev, SYS_RES_IRQ, + sc->sc_rid_irq, sc->sc_irq); + sc->sc_irq = NULL; + } + if (sc->sc_regs) { + bus_release_resource(dev, SYS_RES_MEMORY, + sc->sc_rid_regs, sc->sc_regs); + sc->sc_regs = NULL; + } + + if (sc->sc_tag_rfis) { + bus_dma_tag_destroy(sc->sc_tag_rfis); + sc->sc_tag_rfis = NULL; + } + if (sc->sc_tag_cmdh) { + bus_dma_tag_destroy(sc->sc_tag_cmdh); + sc->sc_tag_cmdh = NULL; + } + if (sc->sc_tag_cmdt) { + bus_dma_tag_destroy(sc->sc_tag_cmdt); + sc->sc_tag_cmdt = NULL; + } + if (sc->sc_tag_data) { + bus_dma_tag_destroy(sc->sc_tag_data); + sc->sc_tag_data = NULL; + } + + return (0); +} diff --git a/sys/dev/disk/ahci/ahci_cam.c b/sys/dev/disk/ahci/ahci_cam.c new file mode 100644 index 0000000000..337cbdf102 --- /dev/null +++ b/sys/dev/disk/ahci/ahci_cam.c @@ -0,0 +1,1412 @@ +/* + * Copyright (c) 2009 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * Copyright (c) 2007 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: atascsi.c,v 1.64 2009/02/16 21:19:06 miod Exp $ + * $DragonFly$ + */ +/* + * Implement each SATA port as its own SCSI bus on CAM. This way we can + * implement future port multiplier features as individual devices on the + * bus. + * + * Much of the cdb<->xa conversion code was taken from OpenBSD, the rest + * was written natively for DragonFly. + */ + +#include "ahci.h" + +const char *ScsiTypeArray[32] = { + "DIRECT", + "SEQUENTIAL", + "PRINTER", + "PROCESSOR", + "WORM", + "CDROM", + "SCANNER", + "OPTICAL", + "CHANGER", + "COMM", + "ASC0", + "ASC1", + "STORARRAY", + "ENCLOSURE", + "RBC", + "OCRW", + "0x10", + "OSD", + "ADC", + "0x13", + "0x14", + "0x15", + "0x16", + "0x17", + "0x18", + "0x19", + "0x1A", + "0x1B", + "0x1C", + "0x1D", + "0x1E", + "NODEVICE" +}; + +static void ahci_xpt_action(struct cam_sim *sim, union ccb *ccb); +static void ahci_xpt_poll(struct cam_sim *sim); +static void ahci_xpt_scsi_disk_io(struct cam_sim *sim, union ccb *ccb); +static void ahci_xpt_scsi_atapi_io(struct cam_sim *sim, union ccb *ccb); + +static void ahci_ata_complete_disk_rw(struct ata_xfer *xa); +static void ahci_ata_complete_disk_synchronize_cache(struct ata_xfer *xa); +static void ahci_atapi_complete_cmd(struct ata_xfer *xa); +static void ahci_ata_dummy_sense(struct scsi_sense_data *sense_data); +static void ahci_ata_atapi_sense(struct ata_fis_d2h *rfis, + struct scsi_sense_data *sense_data); + +static int ahci_cam_probe(struct ahci_port *ap); +static int ahci_cam_probe_disk(struct ahci_port *ap); +static int ahci_cam_probe_atapi(struct ahci_port *ap); +static void ahci_ata_dummy_done(struct ata_xfer *xa); +static void ata_fix_identify(struct ata_identify *id); +static void ahci_cam_rescan(struct ahci_port *ap); + +int +ahci_cam_attach(struct ahci_port *ap) +{ + struct cam_devq *devq; + struct cam_sim *sim; + int error; + int unit; + + /* + * We want at least one ccb to be available for error processing + * so don't let CAM use more then ncmds - 1. + */ + unit = device_get_unit(ap->ap_sc->sc_dev); + if (ap->ap_sc->sc_ncmds > 1) + devq = cam_simq_alloc(ap->ap_sc->sc_ncmds - 1); + else + devq = cam_simq_alloc(ap->ap_sc->sc_ncmds); + if (devq == NULL) { + return (ENOMEM); + } + sim = cam_sim_alloc(ahci_xpt_action, ahci_xpt_poll, "ahci", + (void *)ap, unit, &sim_mplock, 1, 1, devq); + cam_simq_release(devq); + if (sim == NULL) { + return (ENOMEM); + } + ap->ap_sim = sim; + error = xpt_bus_register(ap->ap_sim, ap->ap_num); + if (error != CAM_SUCCESS) { + ahci_cam_detach(ap); + return (EINVAL); + } + ap->ap_flags |= AP_F_BUS_REGISTERED; + error = xpt_create_path(&ap->ap_path, NULL, cam_sim_path(sim), + CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); + if (error != CAM_REQ_CMP) { + ahci_cam_detach(ap); + return (ENOMEM); + } + + error = ahci_cam_probe(ap); + if (error) { + ahci_cam_detach(ap); + return (EIO); + } + ap->ap_flags |= AP_F_CAM_ATTACHED; + + ahci_cam_rescan(ap); + + return(0); +} + +void +ahci_cam_changed(struct ahci_port *ap, int found) +{ + struct cam_path *tmppath; + + if (ap->ap_sim == NULL) + return; + if (xpt_create_path(&tmppath, NULL, cam_sim_path(ap->ap_sim), + 0, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + return; + } + if (found) { + ahci_cam_probe(ap); + /* + * XXX calling AC_FOUND_DEVICE with inquiry data is + * basically a NOP. For now just tell CAM to + * rescan the bus. + */ + xpt_async(AC_FOUND_DEVICE, tmppath, NULL); + ahci_cam_rescan(ap); + } else { + xpt_async(AC_LOST_DEVICE, tmppath, NULL); + } + xpt_free_path(tmppath); +} + +void +ahci_cam_detach(struct ahci_port *ap) +{ + int error; + + if ((ap->ap_flags & AP_F_CAM_ATTACHED) == 0) + return; + get_mplock(); + if (ap->ap_sim) { + xpt_freeze_simq(ap->ap_sim, 1); + } + if (ap->ap_path) { + xpt_free_path(ap->ap_path); + ap->ap_path = NULL; + } + if (ap->ap_flags & AP_F_BUS_REGISTERED) { + error = xpt_bus_deregister(cam_sim_path(ap->ap_sim)); + KKASSERT(error == CAM_REQ_CMP); + ap->ap_flags &= ~AP_F_BUS_REGISTERED; + } + if (ap->ap_sim) { + cam_sim_free(ap->ap_sim); + ap->ap_sim = NULL; + } + rel_mplock(); + ap->ap_flags &= ~AP_F_CAM_ATTACHED; +} + +/* + * Once the AHCI port has been attched we need to probe for a device or + * devices on the port and setup various options. + */ +static int +ahci_cam_probe(struct ahci_port *ap) +{ + struct ata_xfer *xa; + u_int64_t capacity; + u_int64_t capacity_bytes; + int model_len; + int status; + int error; + int devncqdepth; + int i; + const char *wcstr; + const char *rastr; + const char *scstr; + const char *type; + + if (ap->ap_ata.ap_type == ATA_PORT_T_NONE) + return (EIO); + + /* + * Issue identify, saving the result + */ + xa = ahci_ata_get_xfer(ap); + xa->complete = ahci_ata_dummy_done; + xa->data = &ap->ap_ata.ap_identify; + xa->datalen = sizeof(ap->ap_ata.ap_identify); + xa->fis->flags = ATA_H2D_FLAGS_CMD; + if (ap->ap_ata.ap_type == ATA_PORT_T_ATAPI) { + xa->fis->command = ATA_C_ATAPI_IDENTIFY; + type = "ATAPI"; + } else { + xa->fis->command = ATA_C_IDENTIFY; + type = "DISK"; + } + xa->fis->features = 0; + xa->fis->device = 0; + xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL; + xa->timeout = hz; + + status = ahci_ata_cmd(xa); + if (status != ATA_COMPLETE) { + kprintf("%s: Detected %s device but unable to IDENTIFY\n", + PORTNAME(ap), type); + ahci_ata_put_xfer(xa); + return(EIO); + } + if (xa->state != ATA_S_COMPLETE) { + kprintf("%s: Detected %s device but unable to IDENTIFY " + " xa->state=%d\n", + PORTNAME(ap), type, xa->state); + ahci_ata_put_xfer(xa); + return(EIO); + } + ahci_ata_put_xfer(xa); + + ata_fix_identify(&ap->ap_ata.ap_identify); + + /* + * Read capacity using SATA probe info. + */ + if (le16toh(ap->ap_ata.ap_identify.cmdset83) & 0x0400) { + /* LBA48 feature set supported */ + capacity = 0; + for (i = 3; i >= 0; --i) { + capacity <<= 16; + capacity += + le16toh(ap->ap_ata.ap_identify.addrsecxt[i]); + } + } else { + capacity = le16toh(ap->ap_ata.ap_identify.addrsec[1]); + capacity <<= 16; + capacity += le16toh(ap->ap_ata.ap_identify.addrsec[0]); + } + ap->ap_ata.ap_capacity = capacity; + ap->ap_ata.ap_features |= ATA_PORT_F_PROBED; + + capacity_bytes = capacity * 512; + + /* + * Negotiate NCQ, throw away any ata_xfer's beyond the negotiated + * number of slots and limit the number of CAM ccb's to one less + * so we always have a slot available for recovery. + * + * NCQ is not used if ap_ncqdepth is 1 or the host controller does + * not support it, and in that case the driver can handle extra + * ccb's. + * + * Remember at least one extra CCB needs to be reserved for the + * error ccb. + */ + if ((ap->ap_sc->sc_cap & AHCI_REG_CAP_SNCQ) && + (le16toh(ap->ap_ata.ap_identify.satacap) & (1 << 8))) { + ap->ap_ata.ap_ncqdepth = (le16toh(ap->ap_ata.ap_identify.qdepth) & 0x1F) + 1; + devncqdepth = ap->ap_ata.ap_ncqdepth; + if (ap->ap_ata.ap_ncqdepth > ap->ap_sc->sc_ncmds) + ap->ap_ata.ap_ncqdepth = ap->ap_sc->sc_ncmds; + if (ap->ap_ata.ap_ncqdepth > 1) { + for (i = 0; i < ap->ap_sc->sc_ncmds; ++i) { + xa = ahci_ata_get_xfer(ap); + if (xa->tag < ap->ap_ata.ap_ncqdepth) { + xa->state = ATA_S_COMPLETE; + ahci_ata_put_xfer(xa); + } + } + if (ap->ap_ata.ap_ncqdepth >= ap->ap_sc->sc_ncmds) { + cam_devq_resize(ap->ap_sim->devq, + ap->ap_ata.ap_ncqdepth - 1); + } + } + } else { + devncqdepth = 0; + } + + /* + * Make the model string a bit more presentable + */ + for (model_len = 40; model_len; --model_len) { + if (ap->ap_ata.ap_identify.model[model_len-1] == ' ') + continue; + if (ap->ap_ata.ap_identify.model[model_len-1] == 0) + continue; + break; + } + + /* + * Generate informatiive strings. + * + * NOTE: We do not automatically set write caching, lookahead, + * or the security state for ATAPI devices. + */ + if (ap->ap_ata.ap_identify.cmdset82 & ATA_IDENTIFY_WRITECACHE) { + if (ap->ap_ata.ap_identify.features85 & ATA_IDENTIFY_WRITECACHE) + wcstr = "enabled"; + else if (ap->ap_ata.ap_type == ATA_PORT_T_ATAPI) + wcstr = "disabled"; + else + wcstr = "enabling"; + } else { + wcstr = "notsupp"; + } + + if (ap->ap_ata.ap_identify.cmdset82 & ATA_IDENTIFY_LOOKAHEAD) { + if (ap->ap_ata.ap_identify.features85 & ATA_IDENTIFY_LOOKAHEAD) + rastr = "enabled"; + else if (ap->ap_ata.ap_type == ATA_PORT_T_ATAPI) + rastr = "disabled"; + else + rastr = "enabling"; + } else { + rastr = "notsupp"; + } + + if (ap->ap_ata.ap_identify.cmdset82 & ATA_IDENTIFY_SECURITY) { + if (ap->ap_ata.ap_identify.securestatus & ATA_SECURE_FROZEN) + scstr = "frozen"; + else if (ap->ap_ata.ap_type == ATA_PORT_T_ATAPI) + scstr = "unfrozen"; + else + scstr = "freezing"; + } else { + scstr = "notsupp"; + } + + kprintf("%s: Found %s \"%*.*s %8.8s\" serial=\"%20.20s\"\n" + "%s: tags=%d/%d satacaps=%04x satafeat=%04x " + "capacity=%lld.%02dMB\n" + "%s: f85=%04x f86=%04x f87=%04x WC=%s RA=%s SEC=%s\n", + PORTNAME(ap), + type, + model_len, model_len, + ap->ap_ata.ap_identify.model, + ap->ap_ata.ap_identify.firmware, + ap->ap_ata.ap_identify.serial, + + PORTNAME(ap), + devncqdepth, ap->ap_sc->sc_ncmds, + ap->ap_ata.ap_identify.satacap, + ap->ap_ata.ap_identify.satafsup, + (long long)capacity_bytes / (1024 * 1024), + (int)(capacity_bytes % (1024 * 1024)) * 100 / (1024 * 1024), + + PORTNAME(ap), + ap->ap_ata.ap_identify.features85, + ap->ap_ata.ap_identify.features86, + ap->ap_ata.ap_identify.features87, + wcstr, + rastr, + scstr + ); + + /* + * Additional type-specific probing + */ + switch(ap->ap_ata.ap_type) { + case ATA_PORT_T_DISK: + error = ahci_cam_probe_disk(ap); + break; + default: + error = ahci_cam_probe_atapi(ap); + break; + } + return (0); +} + +/* + * DISK-specific probe after initial ident + */ +static int +ahci_cam_probe_disk(struct ahci_port *ap) +{ + struct ata_xfer *xa; + int status; + + /* + * Enable write cache if supported + * + * NOTE: "WD My Book" external disk devices have a very poor + * daughter board between the the ESATA and the HD. Sending + * any ATA_C_SET_FEATURES commands will break the hardware port + * with a fatal protocol error. However, this device also + * indicates that WRITECACHE is already on and READAHEAD is + * not supported so we avoid the issue. + */ + if ((ap->ap_ata.ap_identify.cmdset82 & ATA_IDENTIFY_WRITECACHE) && + (ap->ap_ata.ap_identify.features85 & ATA_IDENTIFY_WRITECACHE) == 0) { + xa = ahci_ata_get_xfer(ap); + xa->complete = ahci_ata_dummy_done; + xa->fis->command = ATA_C_SET_FEATURES; + /*xa->fis->features = ATA_SF_WRITECACHE_EN;*/ + xa->fis->features = ATA_SF_LOOKAHEAD_EN; + xa->fis->flags = ATA_H2D_FLAGS_CMD; + xa->fis->device = 0; + xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL; + xa->timeout = hz; + xa->datalen = 0; + status = ahci_ata_cmd(xa); + if (status == ATA_COMPLETE) + ap->ap_ata.ap_features |= ATA_PORT_F_WCACHE; + ahci_ata_put_xfer(xa); + } + + /* + * Enable readahead if supported + */ + if ((ap->ap_ata.ap_identify.cmdset82 & ATA_IDENTIFY_LOOKAHEAD) && + (ap->ap_ata.ap_identify.features85 & ATA_IDENTIFY_LOOKAHEAD) == 0) { + xa = ahci_ata_get_xfer(ap); + xa->complete = ahci_ata_dummy_done; + xa->fis->command = ATA_C_SET_FEATURES; + xa->fis->features = ATA_SF_LOOKAHEAD_EN; + xa->fis->flags = ATA_H2D_FLAGS_CMD; + xa->fis->device = 0; + xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL; + xa->timeout = hz; + xa->datalen = 0; + status = ahci_ata_cmd(xa); + if (status == ATA_COMPLETE) + ap->ap_ata.ap_features |= ATA_PORT_F_RAHEAD; + ahci_ata_put_xfer(xa); + } + + /* + * FREEZE LOCK the device so malicious users can't lock it on us. + * As there is no harm in issuing this to devices that don't + * support the security feature set we just send it, and don't bother + * checking if the device sends a command abort to tell us it doesn't + * support it + */ + if ((ap->ap_ata.ap_identify.cmdset82 & ATA_IDENTIFY_SECURITY) && + (ap->ap_ata.ap_identify.securestatus & ATA_SECURE_FROZEN) == 0) { + xa = ahci_ata_get_xfer(ap); + xa->complete = ahci_ata_dummy_done; + xa->fis->command = ATA_C_SEC_FREEZE_LOCK; + xa->fis->flags = ATA_H2D_FLAGS_CMD; + xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL; + xa->timeout = hz; + xa->datalen = 0; + status = ahci_ata_cmd(xa); + if (status == ATA_COMPLETE) + ap->ap_ata.ap_features |= ATA_PORT_F_FRZLCK; + ahci_ata_put_xfer(xa); + } + + return (0); +} + +/* + * ATAPI-specific probe after initial ident + */ +static int +ahci_cam_probe_atapi(struct ahci_port *ap) +{ + return(0); +} + +#if 0 + /* + * Keep this old code around for a little bit, it is another way + * to probe an ATAPI device by using a ATAPI (SCSI) INQUIRY + */ + struct ata_xfer *xa; + int status; + int devncqdepth; + struct scsi_inquiry_data *inq_data; + struct scsi_inquiry *inq_cmd; + + inq_data = kmalloc(sizeof(*inq_data), M_TEMP, M_WAITOK | M_ZERO); + + /* + * Issue identify, saving the result + */ + xa = ahci_ata_get_xfer(ap); + xa->complete = ahci_ata_dummy_done; + xa->data = inq_data; + xa->datalen = sizeof(*inq_data); + xa->flags = ATA_F_READ | ATA_F_PACKET | ATA_F_PIO | ATA_F_POLL; + xa->timeout = hz; + + xa->fis->flags = ATA_H2D_FLAGS_CMD; + xa->fis->command = ATA_C_PACKET; + xa->fis->device = 0; + xa->fis->sector_count = xa->tag << 3; + xa->fis->features = ATA_H2D_FEATURES_DMA | + ((xa->flags & ATA_F_WRITE) ? + ATA_H2D_FEATURES_DIR_WRITE : ATA_H2D_FEATURES_DIR_READ); + xa->fis->lba_mid = 0x00; + xa->fis->lba_high = 0x20; + + inq_cmd = (void *)xa->packetcmd; + inq_cmd->opcode = INQUIRY; + inq_cmd->length = SHORT_INQUIRY_LENGTH; + + status = ahci_ata_cmd(xa); + if (status != ATA_COMPLETE) { + kprintf("%s: Detected ATAPI device but unable to INQUIRY\n", + PORTNAME(ap)); + ahci_ata_put_xfer(xa); + kfree(inq_data, M_TEMP); + return(EIO); + } + if (xa->state != ATA_S_COMPLETE) { + kprintf("%s: Detected ATAPI device but unable to INQUIRY " + " xa->state=%d\n", + PORTNAME(ap), xa->state); + ahci_ata_put_xfer(xa); + kfree(inq_data, M_TEMP); + return(EIO); + } + ahci_ata_put_xfer(xa); + + ap->ap_ata.ap_features |= ATA_PORT_F_PROBED; + + /* + * XXX Negotiate NCQ with ATAPI? How do we do this? + */ + + devncqdepth = 0; + + kprintf("%s: Found ATAPI %s \"%8.8s %16.16s\" rev=\"%4.4s\"\n" + "%s: tags=%d/%d\n", + PORTNAME(ap), + ScsiTypeArray[SID_TYPE(inq_data)], + inq_data->vendor, + inq_data->product, + inq_data->revision, + + PORTNAME(ap), + devncqdepth, ap->ap_sc->sc_ncmds + ); + kfree(inq_data, M_TEMP); +#endif + +/* + * Fix byte ordering so buffers can be accessed as + * strings. + */ +static void +ata_fix_identify(struct ata_identify *id) +{ + u_int16_t *swap; + int i; + + swap = (u_int16_t *)id->serial; + for (i = 0; i < sizeof(id->serial) / sizeof(u_int16_t); i++) + swap[i] = bswap16(swap[i]); + + swap = (u_int16_t *)id->firmware; + for (i = 0; i < sizeof(id->firmware) / sizeof(u_int16_t); i++) + swap[i] = bswap16(swap[i]); + + swap = (u_int16_t *)id->model; + for (i = 0; i < sizeof(id->model) / sizeof(u_int16_t); i++) + swap[i] = bswap16(swap[i]); +} + +/* + * Dummy done callback for xa. + */ +static void +ahci_ata_dummy_done(struct ata_xfer *xa) +{ +} + +/* + * Initiate a bus scan. + * + * An asynchronous bus scan is used to avoid reentrancy issues + */ +static void +ahci_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb) +{ + kfree(ccb, M_TEMP); +} + +static void +ahci_cam_rescan(struct ahci_port *ap) +{ + struct cam_path *path; + union ccb *ccb; + int status; + + ccb = kmalloc(sizeof(*ccb), M_TEMP, M_WAITOK | M_ZERO); + status = xpt_create_path(&path, xpt_periph, cam_sim_path(ap->ap_sim), + CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); + if (status != CAM_REQ_CMP) + return; + + xpt_setup_ccb(&ccb->ccb_h, path, 5); /* 5 = low priority */ + ccb->ccb_h.func_code = XPT_SCAN_BUS | XPT_FC_QUEUED; + ccb->ccb_h.cbfcnp = ahci_cam_rescan_callback; + ccb->crcn.flags = CAM_FLAG_NONE; + xpt_action(ccb); + + /* scan is now underway */ +} + +/* + * Action function - dispatch command + */ +static +void +ahci_xpt_action(struct cam_sim *sim, union ccb *ccb) +{ + struct ahci_port *ap; + struct ccb_hdr *ccbh; + int unit; + + /* XXX lock */ + ap = cam_sim_softc(sim); + KKASSERT(ap != NULL); + ccbh = &ccb->ccb_h; + unit = cam_sim_unit(sim); + + /* + * Non-zero target and lun ids will be used for future + * port multiplication(?). A target wildcard indicates only + * the general bus is being probed. + * + * XXX What do we do with a LUN wildcard? + */ + if (ccbh->target_id != CAM_TARGET_WILDCARD) { + if (ap->ap_ata.ap_type == ATA_PORT_T_NONE) { + ccbh->status = CAM_REQ_INVALID; + xpt_done(ccb); + return; + } + if (ccbh->target_id) { + ccbh->status = CAM_DEV_NOT_THERE; + xpt_done(ccb); + return; + } + if (ccbh->target_lun != CAM_LUN_WILDCARD && ccbh->target_lun) { + ccbh->status = CAM_DEV_NOT_THERE; + xpt_done(ccb); + return; + } + } + + /* + * Switch on the meta XPT command + */ + switch(ccbh->func_code) { + case XPT_PATH_INQ: + ccb->cpi.version_num = 1; + ccb->cpi.hba_inquiry = 0; + ccb->cpi.target_sprt = 0; + ccb->cpi.hba_misc = 0; + ccb->cpi.hba_eng_cnt = 0; + bzero(ccb->cpi.vuhba_flags, sizeof(ccb->cpi.vuhba_flags)); + ccb->cpi.max_target = 7; + ccb->cpi.max_lun = 0; + ccb->cpi.async_flags = 0; + ccb->cpi.hpath_id = 0; + ccb->cpi.initiator_id = 7; + ccb->cpi.unit_number = cam_sim_unit(sim); + ccb->cpi.bus_id = cam_sim_bus(sim); + ccb->cpi.base_transfer_speed = 150000; + ccb->cpi.transport = XPORT_AHCI; + ccb->cpi.transport_version = 1; + ccb->cpi.protocol = PROTO_SCSI; + ccb->cpi.protocol_version = SCSI_REV_2; + + /* + * Non-zero target and lun ids will be used for future + * port multiplication(?). A target wildcard indicates only + * the general bus is being probed. + * + * XXX What do we do with a LUN wildcard? + */ + if (ccbh->target_id != CAM_TARGET_WILDCARD) { + switch(ahci_pread(ap, AHCI_PREG_SSTS) & + AHCI_PREG_SSTS_SPD) { + case AHCI_PREG_SSTS_SPD_GEN1: + ccb->cpi.base_transfer_speed = 150000; + break; + case AHCI_PREG_SSTS_SPD_GEN2: + ccb->cpi.base_transfer_speed = 300000; + break; + default: + /* unknown */ + ccb->cpi.base_transfer_speed = 1000; + break; + } + /* XXX check attached, set base xfer speed */ + } + ccbh->status = CAM_REQ_CMP; + xpt_done(ccb); + break; + case XPT_RESET_DEV: + lwkt_serialize_enter(&ap->ap_sc->sc_serializer); + ahci_port_softreset(ap); + lwkt_serialize_exit(&ap->ap_sc->sc_serializer); + + ccbh->status = CAM_REQ_CMP; + xpt_done(ccb); + break; + case XPT_RESET_BUS: + lwkt_serialize_enter(&ap->ap_sc->sc_serializer); + ahci_port_portreset(ap); + ahci_port_softreset(ap); + lwkt_serialize_exit(&ap->ap_sc->sc_serializer); + + xpt_async(AC_BUS_RESET, ap->ap_path, NULL); + + ccbh->status = CAM_REQ_CMP; + xpt_done(ccb); + break; + case XPT_SET_TRAN_SETTINGS: + ccbh->status = CAM_FUNC_NOTAVAIL; + xpt_done(ccb); + break; + case XPT_GET_TRAN_SETTINGS: + ccb->cts.protocol = PROTO_SCSI; + ccb->cts.protocol_version = SCSI_REV_2; + ccb->cts.transport = XPORT_AHCI; + ccb->cts.transport_version = XPORT_VERSION_UNSPECIFIED; + ccb->cts.proto_specific.valid = 0; + ccb->cts.xport_specific.valid = 0; + ccbh->status = CAM_REQ_CMP; + xpt_done(ccb); + break; + case XPT_CALC_GEOMETRY: + cam_calc_geometry(&ccb->ccg, 1); + xpt_done(ccb); + break; + case XPT_SCSI_IO: + switch(ap->ap_ata.ap_type) { + case ATA_PORT_T_DISK: + ahci_xpt_scsi_disk_io(sim, ccb); + break; + case ATA_PORT_T_ATAPI: + ahci_xpt_scsi_atapi_io(sim, ccb); + break; + default: + ccbh->status = CAM_REQ_INVALID; + xpt_done(ccb); + break; + } + break; + default: + ccbh->status = CAM_REQ_INVALID; + xpt_done(ccb); + break; + } +} + +/* + * Poll function. + * + * Generally this function gets called heavily when interrupts might be + * non-operational, during a halt/reboot or panic. + */ +static +void +ahci_xpt_poll(struct cam_sim *sim) +{ + struct ahci_port *ap; + + ap = cam_sim_softc(sim); + crit_enter(); + lwkt_serialize_enter(&ap->ap_sc->sc_serializer); + ahci_port_intr(ap, AHCI_PREG_CI_ALL_SLOTS); + lwkt_serialize_exit(&ap->ap_sc->sc_serializer); + crit_exit(); +} + +/* + * Convert the SCSI command in ccb to an ata_xfer command in xa + * for ATA_PORT_T_DISK operations. Set the completion function + * to convert the response back, then dispatch to the OpenBSD AHCI + * layer. + * + * AHCI DISK commands only support a limited command set, and we + * fake additional commands to make it play nice with the CAM subsystem. + */ +static +void +ahci_xpt_scsi_disk_io(struct cam_sim *sim, union ccb *ccb) +{ + struct ahci_port *ap; + struct ccb_hdr *ccbh; + struct ccb_scsiio *csio; + struct ata_xfer *xa; + struct ata_fis_h2d *fis; + scsi_cdb_t cdb; + union scsi_data *rdata; + int rdata_len; + u_int64_t capacity; + u_int64_t lba; + u_int32_t count; + + ap = cam_sim_softc(sim); + ccbh = &ccb->csio.ccb_h; + csio = &ccb->csio; + xa = ahci_ata_get_xfer(ap); + rdata = (void *)csio->data_ptr; + rdata_len = csio->dxfer_len; + + /* + * Build the FIS or process the csio to completion. + */ + cdb = (void *)((ccbh->flags & CAM_CDB_POINTER) ? + csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes); + + switch(cdb->generic.opcode) { + case REQUEST_SENSE: + /* + * Auto-sense everything, so explicit sense requests + * return no-sense. + */ + ccbh->status = CAM_SCSI_STATUS_ERROR; + break; + case INQUIRY: + /* + * Inquiry supported features + * + * [opcode, byte2, page_code, length, control] + */ + if (cdb->inquiry.byte2 & SI_EVPD) { + switch(cdb->inquiry.page_code) { + case SVPD_SUPPORTED_PAGE_LIST: + /* XXX atascsi_disk_vpd_supported */ + case SVPD_UNIT_SERIAL_NUMBER: + /* XXX atascsi_disk_vpd_serial */ + case SVPD_UNIT_DEVID: + /* XXX atascsi_disk_vpd_ident */ + default: + ccbh->status = CAM_FUNC_NOTAVAIL; + break; + } + } else { + bzero(rdata, rdata_len); + if (rdata_len < SHORT_INQUIRY_LENGTH) { + ccbh->status = CAM_CCB_LEN_ERR; + break; + } + if (rdata_len > sizeof(rdata->inquiry_data)) + rdata_len = sizeof(rdata->inquiry_data); + rdata->inquiry_data.device = T_DIRECT; + rdata->inquiry_data.version = SCSI_REV_SPC2; + rdata->inquiry_data.response_format = 2; + rdata->inquiry_data.additional_length = 32; + bcopy("SATA ", rdata->inquiry_data.vendor, 8); + bcopy(ap->ap_ata.ap_identify.model, + rdata->inquiry_data.product, + sizeof(rdata->inquiry_data.product)); + bcopy(ap->ap_ata.ap_identify.firmware, + rdata->inquiry_data.revision, + sizeof(rdata->inquiry_data.revision)); + ccbh->status = CAM_REQ_CMP; + } + break; + case READ_CAPACITY_16: + if (cdb->read_capacity_16.service_action != SRC16_SERVICE_ACTION) { + ccbh->status = CAM_REQ_INVALID; + break; + } + if (rdata_len < sizeof(rdata->read_capacity_data_16)) { + ccbh->status = CAM_CCB_LEN_ERR; + break; + } + /* fall through */ + case READ_CAPACITY: + if (rdata_len < sizeof(rdata->read_capacity_data)) { + ccbh->status = CAM_CCB_LEN_ERR; + break; + } + + capacity = ap->ap_ata.ap_capacity; + + bzero(rdata, rdata_len); + if (cdb->generic.opcode == READ_CAPACITY) { + rdata_len = sizeof(rdata->read_capacity_data); + if (capacity > 0xFFFFFFFFU) + capacity = 0xFFFFFFFFU; + bzero(&rdata->read_capacity_data, rdata_len); + scsi_ulto4b((u_int32_t)capacity - 1, + rdata->read_capacity_data.addr); + scsi_ulto4b(512, rdata->read_capacity_data.length); + } else { + rdata_len = sizeof(rdata->read_capacity_data_16); + bzero(&rdata->read_capacity_data_16, rdata_len); + scsi_u64to8b(capacity - 1, + rdata->read_capacity_data_16.addr); + scsi_ulto4b(512, rdata->read_capacity_data_16.length); + } + ccbh->status = CAM_REQ_CMP; + break; + case SYNCHRONIZE_CACHE: + /* + * Synchronize cache. Specification says this can take + * greater then 30 seconds so give it at least 45. + */ + fis = xa->fis; + xa->datalen = 0; + xa->flags = ATA_F_READ; + xa->complete = ahci_ata_complete_disk_synchronize_cache; + if (xa->timeout < 45 * hz) + xa->timeout = 45 * hz; + fis->flags = ATA_H2D_FLAGS_CMD; + fis->command = ATA_C_FLUSH_CACHE; + fis->device = 0; + break; + case TEST_UNIT_READY: + case START_STOP_UNIT: + case PREVENT_ALLOW: + /* + * Just silently return success + */ + ccbh->status = CAM_REQ_CMP; + rdata_len = 0; + break; + case ATA_PASS_12: + case ATA_PASS_16: + /* + * XXX implement pass-through + */ + ccbh->status = CAM_FUNC_NOTAVAIL; + break; + default: + switch(cdb->generic.opcode) { + case READ_6: + lba = scsi_3btoul(cdb->rw_6.addr) & 0x1FFFFF; + count = cdb->rw_6.length ? cdb->rw_6.length : 0x100; + xa->flags = ATA_F_READ; + break; + case READ_10: + lba = scsi_4btoul(cdb->rw_10.addr); + count = scsi_2btoul(cdb->rw_10.length); + xa->flags = ATA_F_READ; + break; + case READ_12: + lba = scsi_4btoul(cdb->rw_12.addr); + count = scsi_4btoul(cdb->rw_12.length); + xa->flags = ATA_F_READ; + break; + case READ_16: + lba = scsi_8btou64(cdb->rw_16.addr); + count = scsi_4btoul(cdb->rw_16.length); + xa->flags = ATA_F_READ; + break; + case WRITE_6: + lba = scsi_3btoul(cdb->rw_6.addr) & 0x1FFFFF; + count = cdb->rw_6.length ? cdb->rw_6.length : 0x100; + xa->flags = ATA_F_WRITE; + break; + case WRITE_10: + lba = scsi_4btoul(cdb->rw_10.addr); + count = scsi_2btoul(cdb->rw_10.length); + xa->flags = ATA_F_WRITE; + break; + case WRITE_12: + lba = scsi_4btoul(cdb->rw_12.addr); + count = scsi_4btoul(cdb->rw_12.length); + xa->flags = ATA_F_WRITE; + break; + case WRITE_16: + lba = scsi_8btou64(cdb->rw_16.addr); + count = scsi_4btoul(cdb->rw_16.length); + xa->flags = ATA_F_WRITE; + break; + default: + ccbh->status = CAM_REQ_INVALID; + break; + } + if (ccbh->status != CAM_REQ_INPROG) + break; + + fis = xa->fis; + fis->flags = ATA_H2D_FLAGS_CMD; + fis->lba_low = (u_int8_t)lba; + fis->lba_mid = (u_int8_t)(lba >> 8); + fis->lba_high = (u_int8_t)(lba >> 16); + fis->device = ATA_H2D_DEVICE_LBA; + + if (ap->ap_ata.ap_ncqdepth > 1 && + (ap->ap_sc->sc_cap & AHCI_REG_CAP_SNCQ) && + (ccbh->flags & CAM_POLLED) == 0) { + /* + * Use NCQ - always uses 48 bit addressing + */ + xa->flags |= ATA_F_NCQ; + fis->command = (xa->flags & ATA_F_WRITE) ? + ATA_C_WRITE_FPDMA : ATA_C_READ_FPDMA; + fis->lba_low_exp = (u_int8_t)(lba >> 24); + fis->lba_mid_exp = (u_int8_t)(lba >> 32); + fis->lba_high_exp = (u_int8_t)(lba >> 40); + fis->sector_count = xa->tag << 3; + fis->features = (u_int8_t)count; + fis->features_exp = (u_int8_t)(count >> 8); + } else if (count > 0x100 || lba > 0xFFFFFFFFU) { + /* + * Use LBA48 + */ + fis->command = (xa->flags & ATA_F_WRITE) ? + ATA_C_WRITEDMA_EXT : ATA_C_READDMA_EXT; + fis->lba_low_exp = (u_int8_t)(lba >> 24); + fis->lba_mid_exp = (u_int8_t)(lba >> 32); + fis->lba_high_exp = (u_int8_t)(lba >> 40); + fis->sector_count = (u_int8_t)count; + fis->sector_count_exp = (u_int8_t)(count >> 8); + } else { + /* + * Use LBA + * + * NOTE: 256 sectors is supported, stored as 0. + */ + fis->command = (xa->flags & ATA_F_WRITE) ? + ATA_C_WRITEDMA : ATA_C_READDMA; + fis->device |= (u_int8_t)(lba >> 24) & 0x0F; + fis->sector_count = (u_int8_t)count; + } + + xa->data = csio->data_ptr; + xa->datalen = csio->dxfer_len; + xa->complete = ahci_ata_complete_disk_rw; + xa->timeout = ccbh->timeout * hz / 1000; + if (ccbh->flags & CAM_POLLED) + xa->flags |= ATA_F_POLL; + break; + } + + /* + * If the request is still in progress the xa and FIS have + * been set up and must be dispatched. Otherwise the request + * is complete. + */ + if (ccbh->status == CAM_REQ_INPROG) { + KKASSERT(xa->complete != NULL); + xa->atascsi_private = ccb; + ccb->ccb_h.sim_priv.entries[0].ptr = ap; + lwkt_serialize_enter(&ap->ap_sc->sc_serializer); + ahci_ata_cmd(xa); + lwkt_serialize_exit(&ap->ap_sc->sc_serializer); + } else { + ahci_ata_put_xfer(xa); + xpt_done(ccb); + } +} + +/* + * Convert the SCSI command in ccb to an ata_xfer command in xa + * for ATA_PORT_T_ATAPI operations. Set the completion function + * to convert the response back, then dispatch to the OpenBSD AHCI + * layer. + */ +static +void +ahci_xpt_scsi_atapi_io(struct cam_sim *sim, union ccb *ccb) +{ + struct ahci_port *ap; + struct ccb_hdr *ccbh; + struct ccb_scsiio *csio; + struct ata_xfer *xa; + struct ata_fis_h2d *fis; + scsi_cdb_t cdbs; + scsi_cdb_t cdbd; + int flags; + + ap = cam_sim_softc(sim); + ccbh = &ccb->csio.ccb_h; + csio = &ccb->csio; + + switch (ccbh->flags & CAM_DIR_MASK) { + case CAM_DIR_IN: + flags = ATA_F_PACKET | ATA_F_READ; + break; + case CAM_DIR_OUT: + flags = ATA_F_PACKET | ATA_F_WRITE; + break; + case CAM_DIR_NONE: + flags = ATA_F_PACKET; + break; + default: + ccbh->status = CAM_REQ_INVALID; + xpt_done(ccb); + return; + /* NOT REACHED */ + } + + /* + * The command has to fit in the packet command buffer. + */ + if (csio->cdb_len < 6 || csio->cdb_len > 16) { + ccbh->status = CAM_CCB_LEN_ERR; + xpt_done(ccb); + return; + } + + /* + * Initialize the XA and FIS. + */ + xa = ahci_ata_get_xfer(ap); + fis = xa->fis; + + xa->flags = flags; + xa->data = csio->data_ptr; + xa->datalen = csio->dxfer_len; + xa->timeout = ccbh->timeout * hz / 1000; + if (ccbh->flags & CAM_POLLED) + xa->flags |= ATA_F_POLL; + + fis->flags = ATA_H2D_FLAGS_CMD; + fis->command = ATA_C_PACKET; + fis->device = 0; + fis->sector_count = xa->tag << 3; + fis->features = ATA_H2D_FEATURES_DMA | + ((xa->flags & ATA_F_WRITE) ? + ATA_H2D_FEATURES_DIR_WRITE : ATA_H2D_FEATURES_DIR_READ); + fis->lba_mid = 0x00; + fis->lba_high = 0x20; + + /* + * Copy the cdb to the packetcmd buffer in the FIS using a + * convenient pointer in the xa. + */ + cdbs = (void *)((ccbh->flags & CAM_CDB_POINTER) ? + csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes); + bcopy(cdbs, xa->packetcmd, csio->cdb_len); + +#if 0 + kprintf("opcode %d cdb_len %d dxfer_len %d\n", + cdbs->generic.opcode, + csio->cdb_len, csio->dxfer_len); +#endif + + /* + * Some ATAPI commands do not actually follow the SCSI standard. + */ + cdbd = (void *)xa->packetcmd; + + switch(cdbd->generic.opcode) { + case INQUIRY: + /* + * Some ATAPI devices can't handle SI_EVPD being set + * for a basic inquiry (page_code == 0). + * + * Some ATAPI devices can't handle long inquiry lengths, + * don't ask me why. Truncate the inquiry length. + */ + if ((cdbd->inquiry.byte2 & SI_EVPD) && + cdbd->inquiry.page_code == 0) { + cdbd->inquiry.byte2 &= ~SI_EVPD; + } + if (cdbd->inquiry.page_code == 0 && + cdbd->inquiry.length > SHORT_INQUIRY_LENGTH) { + cdbd->inquiry.length = SHORT_INQUIRY_LENGTH; + } + break; + case READ_6: + case WRITE_6: + /* + * Convert *_6 to *_10 commands. Most ATAPI devices + * cannot handle the SCSI READ_6 and WRITE_6 commands. + */ + cdbd->rw_10.opcode |= 0x20; + cdbd->rw_10.byte2 = 0; + cdbd->rw_10.addr[0] = cdbs->rw_6.addr[0] & 0x1F; + cdbd->rw_10.addr[1] = cdbs->rw_6.addr[1]; + cdbd->rw_10.addr[2] = cdbs->rw_6.addr[2]; + cdbd->rw_10.addr[3] = 0; + cdbd->rw_10.reserved = 0; + cdbd->rw_10.length[0] = 0; + cdbd->rw_10.length[1] = cdbs->rw_6.length; + cdbd->rw_10.control = cdbs->rw_6.control; + break; + default: + break; + } + + /* + * And dispatch + */ + xa->complete = ahci_atapi_complete_cmd; + xa->atascsi_private = ccb; + ccb->ccb_h.sim_priv.entries[0].ptr = ap; + ahci_ata_cmd(xa); +} + +/* + * Completion function for ATA_PORT_T_DISK cache synchronization. + */ +static +void +ahci_ata_complete_disk_synchronize_cache(struct ata_xfer *xa) +{ + union ccb *ccb = xa->atascsi_private; + struct ccb_hdr *ccbh = &ccb->ccb_h; + struct ahci_port *ap = ccb->ccb_h.sim_priv.entries[0].ptr; + + switch(xa->state) { + case ATA_S_COMPLETE: + ccbh->status = CAM_REQ_CMP; + ccb->csio.scsi_status = SCSI_STATUS_OK; + break; + case ATA_S_ERROR: + kprintf("%s: synchronize_cache: error\n", PORTNAME(ap)); + ccbh->status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; + ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; + ahci_ata_dummy_sense(&ccb->csio.sense_data); + break; + case ATA_S_TIMEOUT: + kprintf("%s: synchronize_cache: timeout\n", PORTNAME(ap)); + ccbh->status = CAM_CMD_TIMEOUT; + break; + default: + kprintf("%s: synchronize_cache: unknown state %d\n", + PORTNAME(ap), xa->state); + ccbh->status = CAM_REQ_CMP_ERR; + break; + } + ahci_ata_put_xfer(xa); + lwkt_serialize_exit(&ap->ap_sc->sc_serializer); + xpt_done(ccb); + lwkt_serialize_enter(&ap->ap_sc->sc_serializer); +} + +/* + * Completion function for ATA_PORT_T_DISK I/O + */ +static +void +ahci_ata_complete_disk_rw(struct ata_xfer *xa) +{ + union ccb *ccb = xa->atascsi_private; + struct ccb_hdr *ccbh = &ccb->ccb_h; + struct ahci_port *ap = ccb->ccb_h.sim_priv.entries[0].ptr; + + switch(xa->state) { + case ATA_S_COMPLETE: + ccbh->status = CAM_REQ_CMP; + ccb->csio.scsi_status = SCSI_STATUS_OK; + break; + case ATA_S_ERROR: + kprintf("%s: disk_rw: error\n", PORTNAME(ap)); + ccbh->status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; + ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; + ahci_ata_dummy_sense(&ccb->csio.sense_data); + break; + case ATA_S_TIMEOUT: + kprintf("%s: disk_rw: timeout\n", PORTNAME(ap)); + ccbh->status = CAM_CMD_TIMEOUT; + break; + default: + kprintf("%s: disk_rw: unknown state %d\n", + PORTNAME(ap), xa->state); + ccbh->status = CAM_REQ_CMP_ERR; + break; + } + ccb->csio.resid = xa->resid; + ahci_ata_put_xfer(xa); + lwkt_serialize_exit(&ap->ap_sc->sc_serializer); + xpt_done(ccb); + lwkt_serialize_enter(&ap->ap_sc->sc_serializer); +} + +/* + * Completion function for ATA_PORT_T_ATAPI I/O + * + * Sense data is returned in the rfis. + */ +static +void +ahci_atapi_complete_cmd(struct ata_xfer *xa) +{ + union ccb *ccb = xa->atascsi_private; + struct ccb_hdr *ccbh = &ccb->ccb_h; + struct ahci_port *ap = ccb->ccb_h.sim_priv.entries[0].ptr; + scsi_cdb_t cdb; + + cdb = (void *)((ccb->ccb_h.flags & CAM_CDB_POINTER) ? + ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes); + + switch(xa->state) { + case ATA_S_COMPLETE: + ccbh->status = CAM_REQ_CMP; + ccb->csio.scsi_status = SCSI_STATUS_OK; + break; + case ATA_S_ERROR: + kprintf("%s: cmd %d: error\n", + PORTNAME(ap), cdb->generic.opcode); + ccbh->status = CAM_SCSI_STATUS_ERROR; + ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; + ahci_ata_atapi_sense(&xa->rfis, &ccb->csio.sense_data); + break; + case ATA_S_TIMEOUT: + kprintf("%s: cmd %d: timeout\n", + PORTNAME(ap), cdb->generic.opcode); + ccbh->status = CAM_CMD_TIMEOUT; + break; + default: + kprintf("%s: cmd %d: unknown state %d\n", + PORTNAME(ap), cdb->generic.opcode, xa->state); + ccbh->status = CAM_REQ_CMP_ERR; + break; + } + ccb->csio.resid = xa->resid; + ahci_ata_put_xfer(xa); + lwkt_serialize_exit(&ap->ap_sc->sc_serializer); + xpt_done(ccb); + lwkt_serialize_enter(&ap->ap_sc->sc_serializer); +} + +/* + * Construct dummy sense data for errors on DISKs + */ +static +void +ahci_ata_dummy_sense(struct scsi_sense_data *sense_data) +{ + sense_data->error_code = SSD_ERRCODE_VALID | SSD_CURRENT_ERROR; + sense_data->segment = 0; + sense_data->flags = SSD_KEY_MEDIUM_ERROR; + sense_data->info[0] = 0; + sense_data->info[1] = 0; + sense_data->info[2] = 0; + sense_data->info[3] = 0; + sense_data->extra_len = 0; +} + +/* + * Construct atapi sense data for errors on ATAPI + * + * The ATAPI sense data is stored in the passed rfis and must be converted + * to SCSI sense data. + */ +static +void +ahci_ata_atapi_sense(struct ata_fis_d2h *rfis, + struct scsi_sense_data *sense_data) +{ + sense_data->error_code = SSD_ERRCODE_VALID | SSD_CURRENT_ERROR; + sense_data->segment = 0; + sense_data->flags = (rfis->error & 0xF0) >> 4; + if (rfis->error & 0x04) + sense_data->flags |= SSD_KEY_ILLEGAL_REQUEST; + if (rfis->error & 0x02) + sense_data->flags |= SSD_EOM; + if (rfis->error & 0x01) + sense_data->flags |= SSD_ILI; + sense_data->info[0] = 0; + sense_data->info[1] = 0; + sense_data->info[2] = 0; + sense_data->info[3] = 0; + sense_data->extra_len = 0; +} diff --git a/sys/dev/disk/ahci/ahci_dragonfly.c b/sys/dev/disk/ahci/ahci_dragonfly.c new file mode 100644 index 0000000000..ae4ee856a0 --- /dev/null +++ b/sys/dev/disk/ahci/ahci_dragonfly.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2009 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Primary device and CAM interface to OpenBSD AHCI driver, for DragonFly + */ + +#include "ahci.h" + +/* + * Device bus methods + */ + +static int ahci_probe (device_t dev); +static int ahci_attach (device_t dev); +static int ahci_detach (device_t dev); +#if 0 +static int ahci_shutdown (device_t dev); +static int ahci_suspend (device_t dev); +static int ahci_resume (device_t dev); +#endif + +static device_method_t ahci_methods[] = { + DEVMETHOD(device_probe, ahci_probe), + DEVMETHOD(device_attach, ahci_attach), + DEVMETHOD(device_detach, ahci_detach), +#if 0 + DEVMETHOD(device_shutdown, ahci_shutdown), + DEVMETHOD(device_suspend, ahci_suspend), + DEVMETHOD(device_resume, ahci_resume), +#endif + + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + {0, 0} +}; + +static devclass_t ahci_devclass; + +static driver_t ahci_driver = { + "ahci", + ahci_methods, + sizeof(struct ahci_softc) +}; + +MODULE_DEPEND(ahci, cam, 1, 1, 1); +DRIVER_MODULE(ahci, pci, ahci_driver, ahci_devclass, 0, 0); + +/* + * Device bus method procedures + */ +static int +ahci_probe (device_t dev) +{ + const struct ahci_device *ad; + + ad = ahci_lookup_device(dev); + if (ad) { + device_set_desc(dev, ad->name); + return(-5); /* higher priority the NATA */ + } + return(ENXIO); +} + +static int +ahci_attach (device_t dev) +{ + struct ahci_softc *sc = device_get_softc(dev); + int error; + + sc->sc_ad = ahci_lookup_device(dev); + if (sc->sc_ad == NULL) + return(ENXIO); + error = sc->sc_ad->ad_attach(dev); + return (error); +} + +static int +ahci_detach (device_t dev) +{ + struct ahci_softc *sc = device_get_softc(dev); + int error = 0; + + if (sc->sc_ad) { + error = sc->sc_ad->ad_detach(dev); + sc->sc_ad = NULL; + } + return(error); +} + +#if 0 + +static int +ahci_shutdown (device_t dev) +{ + return (0); +} + +static int +ahci_suspend (device_t dev) +{ + return (0); +} + +static int +ahci_resume (device_t dev) +{ + return (0); +} + +#endif diff --git a/sys/platform/vkernel/include/cothread.h b/sys/dev/disk/ahci/ahci_dragonfly.h similarity index 66% copy from sys/platform/vkernel/include/cothread.h copy to sys/dev/disk/ahci/ahci_dragonfly.h index 850fddafdd..5058bb2f04 100644 --- a/sys/platform/vkernel/include/cothread.h +++ b/sys/dev/disk/ahci/ahci_dragonfly.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 The DragonFly Project. All rights reserved. + * Copyright (c) 2009 The DragonFly Project. All rights reserved. * * This code is derived from software contributed to The DragonFly Project * by Matthew Dillon @@ -30,34 +30,43 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $DragonFly: src/sys/platform/vkernel/include/cothread.h,v 1.2 2008/03/27 04:28:07 dillon Exp $ */ -#ifndef _MACHINE_COTHREAD_H_ -#define _MACHINE_COTHREAD_H_ - -#include - -struct cothread { - pthread_t pthr; - pthread_t pintr; - void *arg; - void (*thr_func)(struct cothread *); - void (*thr_intr)(struct cothread *); - pthread_mutex_t mutex; - pthread_cond_t cond; -}; - -typedef struct cothread *cothread_t; - -cothread_t cothread_create(void (*thr_func)(cothread_t cotd), - void (*thr_intr)(cothread_t cotd), - void *arg, const char *name); -void cothread_intr(cothread_t cotd); -void cothread_signal(cothread_t cotd); -void cothread_wait(cothread_t cotd); -void cothread_lock(cothread_t cotd); -void cothread_unlock(cothread_t cotd); - -#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +#include + +#define AHCI_CDEV_MAJOR 188 + +#define AHCI_IRQ_RID 0 diff --git a/sys/dev/disk/ahci/atascsi.h b/sys/dev/disk/ahci/atascsi.h new file mode 100644 index 0000000000..5041b6613c --- /dev/null +++ b/sys/dev/disk/ahci/atascsi.h @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2007 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: atascsi.h,v 1.33 2009/02/16 21:19:06 miod Exp $ + */ + +struct atascsi; +struct scsi_link; + +/* + * ATA commands + */ + +#define ATA_C_READDMA_EXT 0x25 +#define ATA_C_READ_LOG_EXT 0x2f +#define ATA_C_WRITEDMA_EXT 0x35 +#define ATA_C_READ_FPDMA 0x60 +#define ATA_C_WRITE_FPDMA 0x61 +#define ATA_C_PACKET 0xa0 +#define ATA_C_ATAPI_IDENTIFY 0xa1 +#define ATA_C_READDMA 0xc8 +#define ATA_C_WRITEDMA 0xca +#define ATA_C_FLUSH_CACHE 0xe7 +#define ATA_C_FLUSH_CACHE_EXT 0xea /* lba48 */ +#define ATA_C_IDENTIFY 0xec +#define ATA_C_SET_FEATURES 0xef +#define ATA_C_SEC_FREEZE_LOCK 0xf5 + +/* + * ATA SET FEATURES subcommands + */ +#define ATA_SF_WRITECACHE_EN 0x02 +#define ATA_SF_LOOKAHEAD_EN 0xaa + +struct ata_identify { + u_int16_t config; /* 0 */ + u_int16_t ncyls; /* 1 */ + u_int16_t reserved1; /* 2 */ + u_int16_t nheads; /* 3 */ + u_int16_t track_size; /* 4 */ + u_int16_t sector_size; /* 5 */ + u_int16_t nsectors; /* 6 */ + u_int16_t reserved2[3]; /* 7 vendor unique */ + u_int8_t serial[20]; /* 10 */ + u_int16_t buffer_type; /* 20 */ + u_int16_t buffer_size; /* 21 */ + u_int16_t ecc; /* 22 */ + u_int8_t firmware[8]; /* 23 */ + u_int8_t model[40]; /* 27 */ + u_int16_t multi; /* 47 */ + u_int16_t dwcap; /* 48 */ + u_int16_t cap; /* 49 */ + u_int16_t reserved3; /* 50 */ + u_int16_t piomode; /* 51 */ + u_int16_t dmamode; /* 52 */ + u_int16_t validinfo; /* 53 */ + u_int16_t curcyls; /* 54 */ + u_int16_t curheads; /* 55 */ + u_int16_t cursectrk; /* 56 */ + u_int16_t curseccp[2]; /* 57 */ + u_int16_t mult2; /* 59 */ + u_int16_t addrsec[2]; /* 60 */ + u_int16_t worddma; /* 62 */ + u_int16_t dworddma; /* 63 */ + u_int16_t advpiomode; /* 64 */ + u_int16_t minmwdma; /* 65 */ + u_int16_t recmwdma; /* 66 */ + u_int16_t minpio; /* 67 */ + u_int16_t minpioflow; /* 68 */ + u_int16_t reserved4[2]; /* 69 */ + u_int16_t typtime[2]; /* 71 */ + u_int16_t reserved5[2]; /* 73 */ + u_int16_t qdepth; /* 75 */ + u_int16_t satacap; /* 76 */ + u_int16_t reserved6; /* 77 */ + u_int16_t satafsup; /* 78 */ + u_int16_t satafen; /* 79 */ + u_int16_t majver; /* 80 */ + u_int16_t minver; /* 81 */ + u_int16_t cmdset82; /* 82 */ + u_int16_t cmdset83; /* 83 */ + u_int16_t cmdset84; /* 84 */ + u_int16_t features85; /* 85 */ + u_int16_t features86; /* 86 */ + u_int16_t features87; /* 87 */ +#define ATA_ID_F87_WWN (1<<8) + u_int16_t ultradma; /* 88 */ + u_int16_t erasetime; /* 89 */ + u_int16_t erasetimex; /* 90 */ + u_int16_t apm; /* 91 */ + u_int16_t masterpw; /* 92 */ + u_int16_t hwreset; /* 93 */ + u_int16_t acoustic; /* 94 */ + u_int16_t stream_min; /* 95 */ + u_int16_t stream_xfer_d; /* 96 */ + u_int16_t stream_lat; /* 97 */ + u_int16_t streamperf[2]; /* 98 */ + u_int16_t addrsecxt[4]; /* 100 */ + u_int16_t stream_xfer_p; /* 104 */ + u_int16_t padding1; /* 105 */ + u_int16_t phys_sect_sz; /* 106 */ + u_int16_t seek_delay; /* 107 */ + u_int16_t naa_ieee_oui; /* 108 */ + u_int16_t ieee_oui_uid; /* 109 */ + u_int16_t uid_mid; /* 110 */ + u_int16_t uid_low; /* 111 */ + u_int16_t resv_wwn[4]; /* 112 */ + u_int16_t incits; /* 116 */ + u_int16_t words_lsec[2]; /* 117 */ + u_int16_t cmdset119; /* 119 */ + u_int16_t features120; /* 120 */ + u_int16_t padding2[6]; + u_int16_t rmsn; /* 127 */ + u_int16_t securestatus; /* 128 */ +#define ATA_SECURE_LOCKED (1<<2) +#define ATA_SECURE_FROZEN (1<<3) + u_int16_t vendor[31]; /* 129 */ + u_int16_t padding3[16]; /* 160 */ + u_int16_t curmedser[30]; /* 176 */ + u_int16_t sctsupport; /* 206 */ + u_int16_t padding4[48]; /* 207 */ + u_int16_t integrity; /* 255 */ +} __packed; + +/* + * IDENTIFY DEVICE data + */ +#define ATA_IDENTIFY_SECURITY (1 << 1) +#define ATA_IDENTIFY_WRITECACHE (1 << 5) +#define ATA_IDENTIFY_LOOKAHEAD (1 << 6) + +/* + * Frame Information Structures + */ + +#define ATA_FIS_LENGTH 20 + +struct ata_fis_h2d { + u_int8_t type; +#define ATA_FIS_TYPE_H2D 0x27 + u_int8_t flags; +#define ATA_H2D_FLAGS_CMD (1<<7) + u_int8_t command; + u_int8_t features; +#define ATA_H2D_FEATURES_DMA (1<<0) +#define ATA_H2D_FEATURES_DIR (1<<2) +#define ATA_H2D_FEATURES_DIR_READ (1<<2) +#define ATA_H2D_FEATURES_DIR_WRITE (0<<2) + + u_int8_t lba_low; + u_int8_t lba_mid; + u_int8_t lba_high; + u_int8_t device; +#define ATA_H2D_DEVICE_LBA 0x40 + + u_int8_t lba_low_exp; + u_int8_t lba_mid_exp; + u_int8_t lba_high_exp; + u_int8_t features_exp; + + u_int8_t sector_count; + u_int8_t sector_count_exp; + u_int8_t reserved0; + u_int8_t control; +#define ATA_FIS_CONTROL_SRST 0x04 + + u_int8_t reserved1; + u_int8_t reserved2; + u_int8_t reserved3; + u_int8_t reserved4; +} __packed; + +struct ata_fis_d2h { + u_int8_t type; +#define ATA_FIS_TYPE_D2H 0x34 + u_int8_t flags; +#define ATA_D2H_FLAGS_INTR (1<<6) + u_int8_t status; + u_int8_t error; + + u_int8_t lba_low; + u_int8_t lba_mid; + u_int8_t lba_high; + u_int8_t device; + + u_int8_t lba_low_exp; + u_int8_t lba_mid_exp; + u_int8_t lba_high_exp; + u_int8_t reserved0; + + u_int8_t sector_count; + u_int8_t sector_count_exp; + u_int8_t reserved1; + u_int8_t reserved2; + + u_int8_t reserved3; + u_int8_t reserved4; + u_int8_t reserved5; + u_int8_t reserved6; +} __packed; + +/* + * SATA log page 10h - + * looks like a D2H FIS, with errored tag number in first byte. + */ +struct ata_log_page_10h { + struct ata_fis_d2h err_regs; +#define ATA_LOG_10H_TYPE_NOTQUEUED 0x80 +#define ATA_LOG_10H_TYPE_TAG_MASK 0x1f + u_int8_t reserved[256 - sizeof(struct ata_fis_d2h)]; + u_int8_t vendor_specific[255]; + u_int8_t checksum; +} __packed; + +/* + * SATA registers + */ + +#define SATA_SStatus_DET 0x00f +#define SATA_SStatus_DET_NODEV 0x000 +#define SATA_SStatus_DET_NOPHY 0x001 +#define SATA_SStatus_DET_DEV 0x003 +#define SATA_SStatus_DET_OFFLINE 0x008 + +#define SATA_SStatus_SPD 0x0f0 +#define SATA_SStatus_SPD_NONE 0x000 +#define SATA_SStatus_SPD_1_5 0x010 +#define SATA_SStatus_SPD_3_0 0x020 + +#define SATA_SStatus_IPM 0xf00 +#define SATA_SStatus_IPM_NODEV 0x000 +#define SATA_SStatus_IPM_ACTIVE 0x100 +#define SATA_SStatus_IPM_PARTIAL 0x200 +#define SATA_SStatus_IPM_SLUMBER 0x600 + +#define SATA_SIGNATURE_PORT_MULTIPLIER 0x96690101 +#define SATA_SIGNATURE_ATAPI 0xeb140101 +#define SATA_SIGNATURE_DISK 0x00000101 + +/* + * ATA interface + */ + +struct ata_port { + struct ata_identify ap_identify; /* only if ATA_PORT_T_DISK */ + struct atascsi *ap_as; + int ap_type; +#define ATA_PORT_T_NONE 0 +#define ATA_PORT_T_DISK 1 +#define ATA_PORT_T_ATAPI 2 + int ap_features; +#define ATA_PORT_F_PROBED (1 << 0) +#define ATA_PORT_F_WCACHE (1 << 1) +#define ATA_PORT_F_RAHEAD (1 << 2) +#define ATA_PORT_F_FRZLCK (1 << 3) + int ap_ncqdepth; + u_int64_t ap_capacity; /* only if ATA_PORT_T_DISK */ +}; + +struct ata_xfer { + struct ata_fis_h2d *fis; + struct ata_fis_d2h rfis; + u_int8_t *packetcmd; + u_int8_t tag; + + void *data; + size_t datalen; + size_t resid; + + void (*complete)(struct ata_xfer *); + u_int timeout; + + int flags; +#define ATA_F_READ (1<<0) +#define ATA_F_WRITE (1<<1) +#define ATA_F_NOWAIT (1<<2) +#define ATA_F_POLL (1<<3) +#define ATA_F_PIO (1<<4) +#define ATA_F_PACKET (1<<5) +#define ATA_F_NCQ (1<<6) +#define ATA_F_TIMEOUT_RUNNING (1<<7) +#define ATA_FMT_FLAGS "\020" "\010TRUNNING" \ + "\007NCQ" "\006PACKET" \ + "\005PIO" "\004POLL" "\003NOWAIT" \ + "\002WRITE" "\001READ" + + volatile int state; +#define ATA_S_SETUP 0 +#define ATA_S_PENDING 1 +#define ATA_S_COMPLETE 2 +#define ATA_S_ERROR 3 +#define ATA_S_TIMEOUT 4 +#define ATA_S_ONCHIP 5 +#define ATA_S_PUT 6 + + void *atascsi_private; + + void (*ata_put_xfer)(struct ata_xfer *); +}; + +#define ATA_QUEUED 0 +#define ATA_COMPLETE 1 +#define ATA_ERROR 2 diff --git a/sys/dev/disk/nata/ata-queue.c b/sys/dev/disk/nata/ata-queue.c index 7daa84487c..d98e85ee9e 100644 --- a/sys/dev/disk/nata/ata-queue.c +++ b/sys/dev/disk/nata/ata-queue.c @@ -724,7 +724,7 @@ ata_cmd2str(struct ata_request *request) case 0x5b: return ("CLOSE_TRACK/SESSION"); case 0x5c: return ("READ_BUFFER_CAPACITY"); case 0x5d: return ("SEND_CUE_SHEET"); - case 0x96: return ("SERVICE_ACTION_IN"); + case 0x96: return ("READ_CAPACITY_16"); case 0xa1: return ("BLANK_CMD"); case 0xa3: return ("SEND_KEY"); case 0xa4: return ("REPORT_KEY"); diff --git a/sys/dev/disk/nata/atapi-fd.c b/sys/dev/disk/nata/atapi-fd.c index a2072e3059..9b5be6d50c 100644 --- a/sys/dev/disk/nata/atapi-fd.c +++ b/sys/dev/disk/nata/atapi-fd.c @@ -341,7 +341,7 @@ afd_sense(device_t dev) struct afd_capabilities capabilities; int8_t ccb1[16] = { ATAPI_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int8_t ccb2[16] = { ATAPI_SERVICE_ACTION_IN, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, + int8_t ccb2[16] = { ATAPI_READ_CAPACITY_16, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, sizeof(struct afd_capacity_big) & 0xff, 0, 0 }; int8_t ccb3[16] = { ATAPI_MODE_SENSE_BIG, 0, ATAPI_REWRITEABLE_CAP_PAGE, 0, 0, 0, 0, sizeof(struct afd_capabilities) >> 8, diff --git a/sys/dev/drm/drmP.h b/sys/dev/drm/drmP.h index 23ec340ec1..109ac64033 100644 --- a/sys/dev/drm/drmP.h +++ b/sys/dev/drm/drmP.h @@ -737,10 +737,10 @@ extern int drm_debug_flag; /* Device setup support (drm_drv.c) */ int drm_probe(device_t kdev, drm_pci_id_list_t *idlist); int drm_attach(device_t kdev, drm_pci_id_list_t *idlist); -void drm_close(void *data); int drm_detach(device_t kdev); d_ioctl_t drm_ioctl; d_open_t drm_open; +d_close_t drm_close; d_read_t drm_read; d_poll_t drm_poll; d_mmap_t drm_mmap; diff --git a/sys/dev/drm/drm_drv.c b/sys/dev/drm/drm_drv.c index fab780590f..987b431768 100644 --- a/sys/dev/drm/drm_drv.c +++ b/sys/dev/drm/drm_drv.c @@ -122,6 +122,7 @@ static drm_ioctl_desc_t drm_ioctls[256] = { static struct dev_ops drm_cdevsw = { { "drm", 145, D_TRACKCLOSE }, .d_open = drm_open, + .d_close = drm_close, .d_read = drm_read, .d_ioctl = drm_ioctl, .d_poll = drm_poll, @@ -602,12 +603,16 @@ int drm_open(struct dev_open_args *ap) return retcode; } -void drm_close(void *data) +int drm_close(struct dev_close_args *ap) { - struct drm_file *file_priv = data; - struct drm_device *dev = file_priv->dev; + struct cdev *kdev = ap->a_head.a_dev; + struct drm_file *file_priv; + struct drm_device *dev; int retcode = 0; + dev = DRIVER_SOFTC(minor(kdev)); + file_priv = drm_find_file_by_proc(dev, curthread); + DRM_DEBUG("open_count = %d\n", dev->open_count); DRM_LOCK(); @@ -694,6 +699,8 @@ done: } DRM_UNLOCK(); + + return (0); } /* drm_ioctl is called whenever a process performs an ioctl on /dev/drm. diff --git a/sys/dev/drm/drm_pciids.h b/sys/dev/drm/drm_pciids.h index 32ae901b73..bf66f14a67 100644 --- a/sys/dev/drm/drm_pciids.h +++ b/sys/dev/drm/drm_pciids.h @@ -534,6 +534,7 @@ {0x8086, 0x2E02, CHIP_I9XX|CHIP_I965, "Intel Integrated Graphics Device"}, \ {0x8086, 0x2E12, CHIP_I9XX|CHIP_I965, "Intel Q45/Q43"}, \ {0x8086, 0x2E22, CHIP_I9XX|CHIP_I965, "Intel G45/G43"}, \ + {0x8086, 0x2E32, CHIP_I9XX|CHIP_I965, "Intel G41"}, \ {0, 0, 0, NULL} #define imagine_PCI_IDS \ diff --git a/sys/dev/drm/i915_drv.h b/sys/dev/drm/i915_drv.h index d02b6383cc..e6a4e22915 100644 --- a/sys/dev/drm/i915_drv.h +++ b/sys/dev/drm/i915_drv.h @@ -642,7 +642,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); (dev)->pci_device == 0x2A42 || \ (dev)->pci_device == 0x2E02 || \ (dev)->pci_device == 0x2E12 || \ - (dev)->pci_device == 0x2E22) + (dev)->pci_device == 0x2E22 || \ + (dev)->pci_device == 0x2E32) #define IS_I965GM(dev) ((dev)->pci_device == 0x2A02) @@ -651,6 +652,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define IS_G4X(dev) ((dev)->pci_device == 0x2E02 || \ (dev)->pci_device == 0x2E12 || \ (dev)->pci_device == 0x2E22 || \ + (dev)->pci_device == 0x2E32 || \ IS_GM45(dev)) #define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \ diff --git a/sys/dev/netif/ath/Makefile.inc b/sys/dev/netif/ath/Makefile.inc index 869317105a..2f0a8def00 100644 --- a/sys/dev/netif/ath/Makefile.inc +++ b/sys/dev/netif/ath/Makefile.inc @@ -1,5 +1,5 @@ # $DragonFly: src/sys/dev/netif/ath/Makefile.inc,v 1.2 2007/02/22 05:17:09 sephe Exp $ -HAL = ${.CURDIR}/../../../../contrib/dev/ath +HAL = ${.CURDIR}/../hal/ath_hal HALOSDEP= ${.CURDIR}/../hal CFLAGS += -I${HALOSDEP} diff --git a/sys/dev/netif/ath/ath/Makefile b/sys/dev/netif/ath/ath/Makefile index b2585c336d..91690fb212 100644 --- a/sys/dev/netif/ath/ath/Makefile +++ b/sys/dev/netif/ath/ath/Makefile @@ -39,7 +39,7 @@ KMOD = if_ath SRCS = if_ath.c if_ath_pci.c -SRCS += device_if.h bus_if.h pci_if.h opt_ath.h +SRCS += device_if.h bus_if.h pci_if.h opt_ath.h opt_ah.h KMODDEPS = wlan ath_hal ath_rate diff --git a/sys/dev/netif/ath/ath/if_ath.c b/sys/dev/netif/ath/ath/if_ath.c index 905c54e995..d242bb569f 100644 --- a/sys/dev/netif/ath/ath/if_ath.c +++ b/sys/dev/netif/ath/ath/if_ath.c @@ -82,8 +82,8 @@ #endif #include -#include -#include /* XXX for softled */ +#include +#include /* XXX for softled */ /* unaligned little endian access */ #define LE_READ_2(p) \ @@ -4338,6 +4338,7 @@ ath_chan_change(struct ath_softc *sc, struct ieee80211_channel *chan) * for channels requiring DFS and not previously visited * and/or with a recent radar detection. */ +#if 0 static void ath_dfswait(void *arg) { @@ -4373,6 +4374,7 @@ ath_dfswait(void *arg) back: lwkt_serialize_exit(ifp->if_serializer); } +#endif /* * Set/change channels. If the channel is really being changed, @@ -4446,6 +4448,7 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) ic->ic_ibss_chan = chan; ath_chan_change(sc, chan); +#if 0 /* * Handle DFS required waiting period to determine * if channel is clear of radar traffic. @@ -4465,6 +4468,7 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) } #undef DFS_NOT_CLEAR } +#endif /* * Re-enable interrupts. diff --git a/sys/dev/netif/ath/ath/if_ath_pci.c b/sys/dev/netif/ath/ath/if_ath_pci.c index 49a8f4d46a..9c3285ac35 100644 --- a/sys/dev/netif/ath/ath/if_ath_pci.c +++ b/sys/dev/netif/ath/ath/if_ath_pci.c @@ -62,7 +62,7 @@ #include #include -#include +#include static int ath_pci_probe(device_t); static int ath_pci_attach(device_t); diff --git a/sys/dev/netif/ath/ath/if_athvar.h b/sys/dev/netif/ath/ath/if_athvar.h index 7e48b3da13..b859042214 100644 --- a/sys/dev/netif/ath/ath/if_athvar.h +++ b/sys/dev/netif/ath/ath/if_athvar.h @@ -43,8 +43,8 @@ #ifndef _DEV_ATH_ATHVAR_H #define _DEV_ATH_ATHVAR_H -#include -#include +#include +#include #include #include #include diff --git a/sys/dev/netif/ath/hal/Makefile b/sys/dev/netif/ath/hal/Makefile index 2bb4c3a290..e81564c5a9 100644 --- a/sys/dev/netif/ath/hal/Makefile +++ b/sys/dev/netif/ath/hal/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting +# Copyright (c) 2002-2008 Sam Leffler, Errno Consulting # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -12,13 +12,6 @@ # similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any # redistribution must be conditioned upon including a substantially # similar Disclaimer requirement for further binary redistribution. -# 3. Neither the names of the above-listed copyright holders nor the names -# of any contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# Alternatively, this software may be distributed under the terms of the -# GNU General Public License ("GPL") version 2 as published by the Free -# Software Foundation. # # NO WARRANTY # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @@ -33,32 +26,92 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # THE POSSIBILITY OF SUCH DAMAGES. # -# $FreeBSD: src/sys/modules/ath_hal/Makefile,v 1.4 2005/01/18 03:28:08 sam Exp $ -# $DragonFly: src/sys/dev/netif/ath/hal/Makefile,v 1.3 2007/02/22 05:17:09 sephe Exp $ +# $FreeBSD: src/sys/modules/ath/Makefile,v 1.5.2.1.2.1 2009/04/15 03:14:26 kensmith Exp $ # +ATH_RATE?= sample # tx rate control algorithm + +HAL=${.CURDIR}/ath_hal +.PATH: ${.CURDIR} +.PATH: ${HAL} +KMOD= ath_hal +#SRCS= if_ath.c if_ath_pci.c +#SRCS = ah_osdep.c +#SRCS += bus_if.h device_if.h pci_if.h opt_ah.h +# NB: v3 eeprom support used by both AR5211 and AR5212; just include it +SRCS= ah_osdep.c ah_osdep.h ah.c ah_regdomain.c ah_eeprom_v3.c +SRCS+= device_if.h bus_if.h pci_if.h opt_inet.h opt_ath.h opt_ah.h + # -# Hardware Access Layer (HAL) for the Atheros Wireless NIC driver. +# AR5210 support; these are first generation 11a-only devices. +# +.PATH: ${HAL}/ar5210 +.PATH: ${HAL} +SRCS+= ah_eeprom_v1.c \ + ar5210_attach.c ar5210_beacon.c ar5210_interrupts.c \ + ar5210_keycache.c ar5210_misc.c ar5210_phy.c ar5210_power.c \ + ar5210_recv.c ar5210_reset.c ar5210_xmit.c + # -# This module contains the hardware-specific bits for the network -# interface driver. It is built as a separate module to simplify -# maintenance and isolate the bits that are not (currently) distributed -# in source form. +# AR5211 support; these are second generation 11b/g/a devices +# (but 11g was OFDM only and is not supported). # +.PATH: ${HAL}/ar5211 +SRCS+= ar5211_attach.c ar5211_beacon.c ar5211_interrupts.c \ + ar5211_keycache.c ar5211_misc.c ar5211_phy.c ar5211_power.c \ + ar5211_recv.c ar5211_reset.c ar5211_xmit.c -.include +# +# AR5212 support; this covers all other pci/cardbus legacy parts. +# +.PATH: ${HAL}/ar5212 +SRCS+= ar5212_ani.c ar5212_attach.c ar5212_beacon.c ar5212_eeprom.c \ + ar5212_gpio.c ar5212_interrupts.c ar5212_keycache.c ar5212_misc.c \ + ar5212_phy.c ar5212_power.c ar5212_recv.c ar5212_reset.c \ + ar5212_rfgain.c ar5212_xmit.c +# RF backends +SRCS+= ar5111.c +SRCS+= ar5112.c +SRCS+= ar2413.c +SRCS+= ar2425.c +SRCS+= ar5413.c -.PATH: ${HAL}/public +# +# AR5416, AR9160 support; these are 11n parts but only really +# supported (right now) operating in legacy mode. Note enabling +# this support requires defining AH_SUPPORT_AR5416 in opt_ah.h +# so the 11n tx/rx descriptor format is handled. +# +# NB: 9160 depends on 5416 but 5416 does not require 9160 +# +.PATH: ${HAL}/ar5416 +SRCS+= ah_eeprom_v14.c \ + ar5416_ani.c ar5416_attach.c ar5416_beacon.c ar5416_cal.c \ + ar5416_cal_iq.c ar5416_cal_adcgain.c ar5416_cal_adcdc.c \ + ar5416_eeprom.c ar5416_gpio.c ar5416_interrupts.c ar5416_keycache.c \ + ar5416_misc.c ar5416_phy.c ar5416_power.c ar5416_recv.c \ + ar5416_reset.c ar5416_xmit.c +SRCS+= ar9160_attach.c +# RF backend for 5416 and 9160 +SRCS+= ar2133.c -KMOD = ath_hal -SRCS = ah_osdep.c -SRCS += bus_if.h device_if.h pci_if.h opt_ah.h -OBJS = hal.o +# NB: rate control is bound to the driver by symbol names so only pick one +#.if ${ATH_RATE} == "sample" +#.PATH: ${.CURDIR}/../../dev/ath/ath_rate/sample +#SRCS+= sample.c opt_wlan.h +#.elif ${ATH_RATE} == "onoe" +#.PATH: ${.CURDIR}/../../dev/ath/ath_rate/onoe +#SRCS+= onoe.c +#.elif ${ATH_RATE} == "amrr" +#.PATH: ${.CURDIR}/../../dev/ath/ath_rate/amrr +#SRCS+= amrr.c +#.endif -hal.o: ${MACHINE_ARCH}-elf.hal.o.uu - uudecode -p < ${HAL}/public/${MACHINE_ARCH}-elf.hal.o.uu > ${.TARGET} +CFLAGS+= -I. -I${HAL} -opt_ah.h: ${MACHINE_ARCH}-elf.opt_ah.h - cp ${.ALLSRC} ${.TARGET} +.if !defined(BUILDING_WITH_KERNEL) +opt_ah.h: + echo '#define AH_SUPPORT_AR5416 1' > opt_ah.h +.endif .include diff --git a/sys/dev/netif/ath/hal/ah_osdep.c b/sys/dev/netif/ath/hal/ah_osdep.c index 6a7674a58b..1b838b5c55 100644 --- a/sys/dev/netif/ath/hal/ah_osdep.c +++ b/sys/dev/netif/ath/hal/ah_osdep.c @@ -43,16 +43,23 @@ #include #include #include -#include #include #include #include #include - +#include #include /* XXX for ether_sprintf */ -#include +#include + +#define ath_hal_version "081128" +/* + * Linker set writearounds for chip and RF backend registration. + */ +#define OS_DATA_SET(set, item) DATA_SET(set, item) +#define OS_SET_DECLARE(set, ptype) SET_DECLARE(set, ptype) +#define OS_SET_FOREACH(pvar, set) SET_FOREACH(pvar, set) /* * WiSoC boards overload the bus tag with information about the @@ -190,7 +197,7 @@ HALDEBUGn(struct ath_hal *ah, u_int level, const char* fmt, ...) */ #include #include -#include +#include static struct alq *ath_hal_alq; static int ath_hal_alq_emitdev; /* need to emit DEVICE record */ @@ -426,13 +433,7 @@ ath_hal_modevent(module_t mod, int type, void *unused) switch (type) { case MOD_LOAD: - kprintf("ath_hal: %s (", ath_hal_version); - sep = ""; - for (i = 0; ath_hal_buildopts[i] != NULL; i++) { - kprintf("%s%s", sep, ath_hal_buildopts[i]); - sep = ", "; - } - kprintf(")\n"); + kprintf("ath_hal: %s\n", ath_hal_version); return 0; case MOD_UNLOAD: return 0; diff --git a/sys/dev/netif/ath/hal/ah_osdep.h b/sys/dev/netif/ath/hal/ah_osdep.h index d1fbe303fa..f29c531cd8 100644 --- a/sys/dev/netif/ath/hal/ah_osdep.h +++ b/sys/dev/netif/ath/hal/ah_osdep.h @@ -44,7 +44,15 @@ #include #include #include +#include +#include +/* + * Linker set writearounds for chip and RF backend registration. + */ +#define OS_DATA_SET(set, item) DATA_SET(set, item) +#define OS_SET_DECLARE(set, ptype) SET_DECLARE(set, ptype) +#define OS_SET_FOREACH(pvar, set) SET_FOREACH(pvar, set) /* * Delay n microseconds. */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ah.c b/sys/dev/netif/ath/hal/ath_hal/ah.c new file mode 100644 index 0000000000..fafeffa012 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ah.c @@ -0,0 +1,884 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: src/sys/dev/ath/ath_hal/ah.c,v 1.2.2.1.2.1 2009/04/15 03:14:26 kensmith Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +/* linker set of registered chips */ +OS_SET_DECLARE(ah_chips, struct ath_hal_chip); + +/* + * Check the set of registered chips to see if any recognize + * the device as one they can support. + */ +const char* +ath_hal_probe(uint16_t vendorid, uint16_t devid) +{ + struct ath_hal_chip * const *pchip; + + OS_SET_FOREACH(pchip, ah_chips) { + const char *name = (*pchip)->probe(vendorid, devid); + if (name != AH_NULL) + return name; + } + return AH_NULL; +} + +/* + * Attach detects device chip revisions, initializes the hwLayer + * function list, reads EEPROM information, + * selects reset vectors, and performs a short self test. + * Any failures will return an error that should cause a hardware + * disable. + */ +struct ath_hal* +ath_hal_attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *error) +{ + struct ath_hal_chip * const *pchip; + + OS_SET_FOREACH(pchip, ah_chips) { + struct ath_hal_chip *chip = *pchip; + struct ath_hal *ah; + + /* XXX don't have vendorid, assume atheros one works */ + if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL) + continue; + ah = chip->attach(devid, sc, st, sh, error); + if (ah != AH_NULL) { + /* copy back private state to public area */ + ah->ah_devid = AH_PRIVATE(ah)->ah_devid; + ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid; + ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion; + ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev; + ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev; + ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev; + ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev; + return ah; + } + } + return AH_NULL; +} + +/* linker set of registered RF backends */ +OS_SET_DECLARE(ah_rfs, struct ath_hal_rf); + +/* + * Check the set of registered RF backends to see if + * any recognize the device as one they can support. + */ +struct ath_hal_rf * +ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode) +{ + struct ath_hal_rf * const *prf; + + OS_SET_FOREACH(prf, ah_rfs) { + struct ath_hal_rf *rf = *prf; + if (rf->probe(ah)) + return rf; + } + *ecode = HAL_ENOTSUPP; + return AH_NULL; +} + +/* + * Poll the register looking for a specific value. + */ +HAL_BOOL +ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val) +{ +#define AH_TIMEOUT 1000 + int i; + + for (i = 0; i < AH_TIMEOUT; i++) { + if ((OS_REG_READ(ah, reg) & mask) == val) + return AH_TRUE; + OS_DELAY(10); + } + HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO, + "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", + __func__, reg, OS_REG_READ(ah, reg), mask, val); + return AH_FALSE; +#undef AH_TIMEOUT +} + +/* + * Reverse the bits starting at the low bit for a value of + * bit_count in size + */ +uint32_t +ath_hal_reverseBits(uint32_t val, uint32_t n) +{ + uint32_t retval; + int i; + + for (i = 0, retval = 0; i < n; i++) { + retval = (retval << 1) | (val & 1); + val >>= 1; + } + return retval; +} + +/* + * Compute the time to transmit a frame of length frameLen bytes + * using the specified rate, phy, and short preamble setting. + */ +uint16_t +ath_hal_computetxtime(struct ath_hal *ah, + const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix, + HAL_BOOL shortPreamble) +{ + uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime; + uint32_t kbps; + + kbps = rates->info[rateix].rateKbps; + /* + * index can be invalid duting dynamic Turbo transitions. + */ + if(kbps == 0) return 0; + switch (rates->info[rateix].phy) { + + case IEEE80211_T_CCK: +#define CCK_SIFS_TIME 10 +#define CCK_PREAMBLE_BITS 144 +#define CCK_PLCP_BITS 48 + phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS; + if (shortPreamble && rates->info[rateix].shortPreamble) + phyTime >>= 1; + numBits = frameLen << 3; + txTime = CCK_SIFS_TIME + phyTime + + ((numBits * 1000)/kbps); + break; +#undef CCK_SIFS_TIME +#undef CCK_PREAMBLE_BITS +#undef CCK_PLCP_BITS + + case IEEE80211_T_OFDM: +#define OFDM_SIFS_TIME 16 +#define OFDM_PREAMBLE_TIME 20 +#define OFDM_PLCP_BITS 22 +#define OFDM_SYMBOL_TIME 4 + +#define OFDM_SIFS_TIME_HALF 32 +#define OFDM_PREAMBLE_TIME_HALF 40 +#define OFDM_PLCP_BITS_HALF 22 +#define OFDM_SYMBOL_TIME_HALF 8 + +#define OFDM_SIFS_TIME_QUARTER 64 +#define OFDM_PREAMBLE_TIME_QUARTER 80 +#define OFDM_PLCP_BITS_QUARTER 22 +#define OFDM_SYMBOL_TIME_QUARTER 16 + + if (AH_PRIVATE(ah)->ah_curchan && + IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) { + bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000; + HALASSERT(bitsPerSymbol != 0); + + numBits = OFDM_PLCP_BITS + (frameLen << 3); + numSymbols = howmany(numBits, bitsPerSymbol); + txTime = OFDM_SIFS_TIME_QUARTER + + OFDM_PREAMBLE_TIME_QUARTER + + (numSymbols * OFDM_SYMBOL_TIME_QUARTER); + } else if (AH_PRIVATE(ah)->ah_curchan && + IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) { + bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_HALF) / 1000; + HALASSERT(bitsPerSymbol != 0); + + numBits = OFDM_PLCP_BITS + (frameLen << 3); + numSymbols = howmany(numBits, bitsPerSymbol); + txTime = OFDM_SIFS_TIME_HALF + + OFDM_PREAMBLE_TIME_HALF + + (numSymbols * OFDM_SYMBOL_TIME_HALF); + } else { /* full rate channel */ + bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000; + HALASSERT(bitsPerSymbol != 0); + + numBits = OFDM_PLCP_BITS + (frameLen << 3); + numSymbols = howmany(numBits, bitsPerSymbol); + txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME + + (numSymbols * OFDM_SYMBOL_TIME); + } + break; + +#undef OFDM_SIFS_TIME +#undef OFDM_PREAMBLE_TIME +#undef OFDM_PLCP_BITS +#undef OFDM_SYMBOL_TIME + + case IEEE80211_T_TURBO: +#define TURBO_SIFS_TIME 8 +#define TURBO_PREAMBLE_TIME 14 +#define TURBO_PLCP_BITS 22 +#define TURBO_SYMBOL_TIME 4 + /* we still save OFDM rates in kbps - so double them */ + bitsPerSymbol = ((kbps << 1) * TURBO_SYMBOL_TIME) / 1000; + HALASSERT(bitsPerSymbol != 0); + + numBits = TURBO_PLCP_BITS + (frameLen << 3); + numSymbols = howmany(numBits, bitsPerSymbol); + txTime = TURBO_SIFS_TIME + TURBO_PREAMBLE_TIME + + (numSymbols * TURBO_SYMBOL_TIME); + break; +#undef TURBO_SIFS_TIME +#undef TURBO_PREAMBLE_TIME +#undef TURBO_PLCP_BITS +#undef TURBO_SYMBOL_TIME + + default: + HALDEBUG(ah, HAL_DEBUG_PHYIO, + "%s: unknown phy %u (rate ix %u)\n", + __func__, rates->info[rateix].phy, rateix); + txTime = 0; + break; + } + return txTime; +} + +static __inline int +mapgsm(u_int freq, u_int flags) +{ + freq *= 10; + if (flags & CHANNEL_QUARTER) + freq += 5; + else if (flags & CHANNEL_HALF) + freq += 10; + else + freq += 20; + return (freq - 24220) / 5; +} + +static __inline int +mappsb(u_int freq, u_int flags) +{ + return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5; +} + +/* + * Convert GHz frequency to IEEE channel number. + */ +int +ath_hal_mhz2ieee(struct ath_hal *ah, u_int freq, u_int flags) +{ + if (flags & CHANNEL_2GHZ) { /* 2GHz band */ + if (freq == 2484) + return 14; + if (freq < 2484) { + if (ath_hal_isgsmsku(ah)) + return mapgsm(freq, flags); + return ((int)freq - 2407) / 5; + } else + return 15 + ((freq - 2512) / 20); + } else if (flags & CHANNEL_5GHZ) {/* 5Ghz band */ + if (ath_hal_ispublicsafetysku(ah) && + IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) { + return mappsb(freq, flags); + } else if ((flags & CHANNEL_A) && (freq <= 5000)) { + return (freq - 4000) / 5; + } else { + return (freq - 5000) / 5; + } + } else { /* either, guess */ + if (freq == 2484) + return 14; + if (freq < 2484) { + if (ath_hal_isgsmsku(ah)) + return mapgsm(freq, flags); + return ((int)freq - 2407) / 5; + } + if (freq < 5000) { + if (ath_hal_ispublicsafetysku(ah) && + IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) { + return mappsb(freq, flags); + } else if (freq > 4900) { + return (freq - 4000) / 5; + } else { + return 15 + ((freq - 2512) / 20); + } + } + return (freq - 5000) / 5; + } +} + +typedef enum { + WIRELESS_MODE_11a = 0, + WIRELESS_MODE_TURBO = 1, + WIRELESS_MODE_11b = 2, + WIRELESS_MODE_11g = 3, + WIRELESS_MODE_108g = 4, + + WIRELESS_MODE_MAX +} WIRELESS_MODE; + +static WIRELESS_MODE +ath_hal_chan2wmode(struct ath_hal *ah, const HAL_CHANNEL *chan) +{ + if (IS_CHAN_CCK(chan)) + return WIRELESS_MODE_11b; + if (IS_CHAN_G(chan)) + return WIRELESS_MODE_11g; + if (IS_CHAN_108G(chan)) + return WIRELESS_MODE_108g; + if (IS_CHAN_TURBO(chan)) + return WIRELESS_MODE_TURBO; + return WIRELESS_MODE_11a; +} + +/* + * Convert between microseconds and core system clocks. + */ + /* 11a Turbo 11b 11g 108g */ +static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 }; + +u_int +ath_hal_mac_clks(struct ath_hal *ah, u_int usecs) +{ + const HAL_CHANNEL *c = (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan; + u_int clks; + + /* NB: ah_curchan may be null when called attach time */ + if (c != AH_NULL) { + clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)]; + if (IS_CHAN_HT40(c)) + clks <<= 1; + else if (IS_CHAN_HALF_RATE(c)) + clks >>= 1; + else if (IS_CHAN_QUARTER_RATE(c)) + clks >>= 2; + } else + clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b]; + return clks; +} + +u_int +ath_hal_mac_usec(struct ath_hal *ah, u_int clks) +{ + const HAL_CHANNEL *c = (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan; + u_int usec; + + /* NB: ah_curchan may be null when called attach time */ + if (c != AH_NULL) { + usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)]; + if (IS_CHAN_HT40(c)) + usec >>= 1; + else if (IS_CHAN_HALF_RATE(c)) + usec <<= 1; + else if (IS_CHAN_QUARTER_RATE(c)) + usec <<= 2; + } else + usec = clks / CLOCK_RATE[WIRELESS_MODE_11b]; + return usec; +} + +/* + * Setup a h/w rate table's reverse lookup table and + * fill in ack durations. This routine is called for + * each rate table returned through the ah_getRateTable + * method. The reverse lookup tables are assumed to be + * initialized to zero (or at least the first entry). + * We use this as a key that indicates whether or not + * we've previously setup the reverse lookup table. + * + * XXX not reentrant, but shouldn't matter + */ +void +ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + int i; + + if (rt->rateCodeToIndex[0] != 0) /* already setup */ + return; + for (i = 0; i < N(rt->rateCodeToIndex); i++) + rt->rateCodeToIndex[i] = (uint8_t) -1; + for (i = 0; i < rt->rateCount; i++) { + uint8_t code = rt->info[i].rateCode; + uint8_t cix = rt->info[i].controlRate; + + HALASSERT(code < N(rt->rateCodeToIndex)); + rt->rateCodeToIndex[code] = i; + HALASSERT((code | rt->info[i].shortPreamble) < + N(rt->rateCodeToIndex)); + rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i; + /* + * XXX for 11g the control rate to use for 5.5 and 11 Mb/s + * depends on whether they are marked as basic rates; + * the static tables are setup with an 11b-compatible + * 2Mb/s rate which will work but is suboptimal + */ + rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt, + WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE); + rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt, + WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE); + } +#undef N +} + +HAL_STATUS +ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t *result) +{ + const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + switch (type) { + case HAL_CAP_REG_DMN: /* regulatory domain */ + *result = AH_PRIVATE(ah)->ah_currentRD; + return HAL_OK; + case HAL_CAP_CIPHER: /* cipher handled in hardware */ + case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ + return HAL_ENOTSUPP; + case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ + return HAL_ENOTSUPP; + case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */ + return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO; + case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */ + return HAL_ENOTSUPP; + case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */ + return HAL_ENOTSUPP; + case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */ + *result = pCap->halKeyCacheSize; + return HAL_OK; + case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */ + *result = pCap->halTotalQueues; + return HAL_OK; + case HAL_CAP_VEOL: /* hardware supports virtual EOL */ + return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */ + return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK; + case HAL_CAP_COMPRESSION: + return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_BURST: + return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_FASTFRAME: + return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_DIAG: /* hardware diagnostic support */ + *result = AH_PRIVATE(ah)->ah_diagreg; + return HAL_OK; + case HAL_CAP_TXPOW: /* global tx power limit */ + switch (capability) { + case 0: /* facility is supported */ + return HAL_OK; + case 1: /* current limit */ + *result = AH_PRIVATE(ah)->ah_powerLimit; + return HAL_OK; + case 2: /* current max tx power */ + *result = AH_PRIVATE(ah)->ah_maxPowerLevel; + return HAL_OK; + case 3: /* scale factor */ + *result = AH_PRIVATE(ah)->ah_tpScale; + return HAL_OK; + } + return HAL_ENOTSUPP; + case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */ + return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ + return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ + return HAL_ENOTSUPP; + case HAL_CAP_RFSILENT: /* rfsilent support */ + switch (capability) { + case 0: /* facility is supported */ + return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP; + case 1: /* current setting */ + return AH_PRIVATE(ah)->ah_rfkillEnabled ? + HAL_OK : HAL_ENOTSUPP; + case 2: /* rfsilent config */ + *result = AH_PRIVATE(ah)->ah_rfsilent; + return HAL_OK; + } + return HAL_ENOTSUPP; + case HAL_CAP_11D: +#ifdef AH_SUPPORT_11D + return HAL_OK; +#else + return HAL_ENOTSUPP; +#endif + case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ + return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_HT: + return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */ + *result = pCap->halTxChainMask; + return HAL_OK; + case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */ + *result = pCap->halRxChainMask; + return HAL_OK; + case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */ + *result = pCap->halTstampPrecision; + return HAL_OK; + default: + return HAL_EINVAL; + } +} + +HAL_BOOL +ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t setting, HAL_STATUS *status) +{ + + switch (type) { + case HAL_CAP_TXPOW: + switch (capability) { + case 3: + if (setting <= HAL_TP_SCALE_MIN) { + AH_PRIVATE(ah)->ah_tpScale = setting; + return AH_TRUE; + } + break; + } + break; + case HAL_CAP_RFSILENT: /* rfsilent support */ + /* + * NB: allow even if halRfSilentSupport is false + * in case the EEPROM is misprogrammed. + */ + switch (capability) { + case 1: /* current setting */ + AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0); + return AH_TRUE; + case 2: /* rfsilent config */ + /* XXX better done per-chip for validation? */ + AH_PRIVATE(ah)->ah_rfsilent = setting; + return AH_TRUE; + } + break; + case HAL_CAP_REG_DMN: /* regulatory domain */ + AH_PRIVATE(ah)->ah_currentRD = setting; + return AH_TRUE; + case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ + AH_PRIVATE(ah)->ah_rxornIsFatal = setting; + return AH_TRUE; + default: + break; + } + if (status) + *status = HAL_EINVAL; + return AH_FALSE; +} + +/* + * Common support for getDiagState method. + */ + +static u_int +ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs, + void *dstbuf, int space) +{ + uint32_t *dp = dstbuf; + int i; + + for (i = 0; space >= 2*sizeof(uint32_t); i++) { + u_int r = regs[i].start; + u_int e = regs[i].end; + *dp++ = (r<<16) | e; + space -= sizeof(uint32_t); + do { + *dp++ = OS_REG_READ(ah, r); + r += sizeof(uint32_t); + space -= sizeof(uint32_t); + } while (r <= e && space >= sizeof(uint32_t)); + } + return (char *) dp - (char *) dstbuf; +} + +HAL_BOOL +ath_hal_getdiagstate(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize) +{ + switch (request) { + case HAL_DIAG_REVS: + *result = &AH_PRIVATE(ah)->ah_devid; + *resultsize = sizeof(HAL_REVS); + return AH_TRUE; + case HAL_DIAG_REGS: + *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize); + return AH_TRUE; + case HAL_DIAG_FATALERR: + *result = &AH_PRIVATE(ah)->ah_fatalState[0]; + *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState); + return AH_TRUE; + case HAL_DIAG_EEREAD: + if (argsize != sizeof(uint16_t)) + return AH_FALSE; + if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result)) + return AH_FALSE; + *resultsize = sizeof(uint16_t); + return AH_TRUE; +#ifdef AH_PRIVATE_DIAG + case HAL_DIAG_SETKEY: { + const HAL_DIAG_KEYVAL *dk; + + if (argsize != sizeof(HAL_DIAG_KEYVAL)) + return AH_FALSE; + dk = (const HAL_DIAG_KEYVAL *)args; + return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix, + &dk->dk_keyval, dk->dk_mac, dk->dk_xor); + } + case HAL_DIAG_RESETKEY: + if (argsize != sizeof(uint16_t)) + return AH_FALSE; + return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args); +#ifdef AH_SUPPORT_WRITE_EEPROM + case HAL_DIAG_EEWRITE: { + const HAL_DIAG_EEVAL *ee; + if (argsize != sizeof(HAL_DIAG_EEVAL)) + return AH_FALSE; + ee = (const HAL_DIAG_EEVAL *)args; + return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data); + } +#endif /* AH_SUPPORT_WRITE_EEPROM */ +#endif /* AH_PRIVATE_DIAG */ + case HAL_DIAG_11NCOMPAT: + if (argsize == 0) { + *resultsize = sizeof(uint32_t); + *((uint32_t *)(*result)) = + AH_PRIVATE(ah)->ah_11nCompat; + } else if (argsize == sizeof(uint32_t)) { + AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args; + } else + return AH_FALSE; + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Set the properties of the tx queue with the parameters + * from qInfo. + */ +HAL_BOOL +ath_hal_setTxQProps(struct ath_hal *ah, + HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo) +{ + uint32_t cw; + + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: inactive queue\n", __func__); + return AH_FALSE; + } + /* XXX validate parameters */ + qi->tqi_ver = qInfo->tqi_ver; + qi->tqi_subtype = qInfo->tqi_subtype; + qi->tqi_qflags = qInfo->tqi_qflags; + qi->tqi_priority = qInfo->tqi_priority; + if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT) + qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255); + else + qi->tqi_aifs = INIT_AIFS; + if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) { + cw = AH_MIN(qInfo->tqi_cwmin, 1024); + /* make sure that the CWmin is of the form (2^n - 1) */ + qi->tqi_cwmin = 1; + while (qi->tqi_cwmin < cw) + qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1; + } else + qi->tqi_cwmin = qInfo->tqi_cwmin; + if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) { + cw = AH_MIN(qInfo->tqi_cwmax, 1024); + /* make sure that the CWmax is of the form (2^n - 1) */ + qi->tqi_cwmax = 1; + while (qi->tqi_cwmax < cw) + qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1; + } else + qi->tqi_cwmax = INIT_CWMAX; + /* Set retry limit values */ + if (qInfo->tqi_shretry != 0) + qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15); + else + qi->tqi_shretry = INIT_SH_RETRY; + if (qInfo->tqi_lgretry != 0) + qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15); + else + qi->tqi_lgretry = INIT_LG_RETRY; + qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod; + qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit; + qi->tqi_burstTime = qInfo->tqi_burstTime; + qi->tqi_readyTime = qInfo->tqi_readyTime; + + switch (qInfo->tqi_subtype) { + case HAL_WME_UPSD: + if (qi->tqi_type == HAL_TX_QUEUE_DATA) + qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS; + break; + default: + break; /* NB: silence compiler */ + } + return AH_TRUE; +} + +HAL_BOOL +ath_hal_getTxQProps(struct ath_hal *ah, + HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi) +{ + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: inactive queue\n", __func__); + return AH_FALSE; + } + + qInfo->tqi_qflags = qi->tqi_qflags; + qInfo->tqi_ver = qi->tqi_ver; + qInfo->tqi_subtype = qi->tqi_subtype; + qInfo->tqi_qflags = qi->tqi_qflags; + qInfo->tqi_priority = qi->tqi_priority; + qInfo->tqi_aifs = qi->tqi_aifs; + qInfo->tqi_cwmin = qi->tqi_cwmin; + qInfo->tqi_cwmax = qi->tqi_cwmax; + qInfo->tqi_shretry = qi->tqi_shretry; + qInfo->tqi_lgretry = qi->tqi_lgretry; + qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod; + qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit; + qInfo->tqi_burstTime = qi->tqi_burstTime; + qInfo->tqi_readyTime = qi->tqi_readyTime; + return AH_TRUE; +} + + /* 11a Turbo 11b 11g 108g */ +static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 }; + +/* + * Read the current channel noise floor and return. + * If nf cal hasn't finished, channel noise floor should be 0 + * and we return a nominal value based on band and frequency. + * + * NB: This is a private routine used by per-chip code to + * implement the ah_getChanNoise method. + */ +int16_t +ath_hal_getChanNoise(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + HAL_CHANNEL_INTERNAL *ichan; + + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->channel, chan->channelFlags); + return 0; + } + if (ichan->rawNoiseFloor == 0) { + WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan); + + HALASSERT(mode < WIRELESS_MODE_MAX); + return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan); + } else + return ichan->rawNoiseFloor + ichan->noiseFloorAdjust; +} + +/* + * Process all valid raw noise floors into the dBm noise floor values. + * Though our device has no reference for a dBm noise floor, we perform + * a relative minimization of NF's based on the lowest NF found across a + * channel scan. + */ +void +ath_hal_process_noisefloor(struct ath_hal *ah) +{ + HAL_CHANNEL_INTERNAL *c; + int16_t correct2, correct5; + int16_t lowest2, lowest5; + int i; + + /* + * Find the lowest 2GHz and 5GHz noise floor values after adjusting + * for statistically recorded NF/channel deviation. + */ + correct2 = lowest2 = 0; + correct5 = lowest5 = 0; + for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) { + WIRELESS_MODE mode; + int16_t nf; + + c = &AH_PRIVATE(ah)->ah_channels[i]; + if (c->rawNoiseFloor >= 0) + continue; + mode = ath_hal_chan2wmode(ah, (HAL_CHANNEL *) c); + HALASSERT(mode < WIRELESS_MODE_MAX); + nf = c->rawNoiseFloor + NOISE_FLOOR[mode] + + ath_hal_getNfAdjust(ah, c); + if (IS_CHAN_5GHZ(c)) { + if (nf < lowest5) { + lowest5 = nf; + correct5 = NOISE_FLOOR[mode] - + (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c)); + } + } else { + if (nf < lowest2) { + lowest2 = nf; + correct2 = NOISE_FLOOR[mode] - + (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c)); + } + } + } + + /* Correct the channels to reach the expected NF value */ + for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) { + c = &AH_PRIVATE(ah)->ah_channels[i]; + if (c->rawNoiseFloor >= 0) + continue; + /* Apply correction factor */ + c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) + + (IS_CHAN_5GHZ(c) ? correct5 : correct2); + HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u/0x%x raw nf %d adjust %d\n", + c->channel, c->channelFlags, c->rawNoiseFloor, + c->noiseFloorAdjust); + } +} + +/* + * INI support routines. + */ + +int +ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, + int col, int regWr) +{ + int r; + + for (r = 0; r < ia->rows; r++) { + OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), + HAL_INI_VAL(ia, r, col)); + DMA_YIELD(regWr); + } + return regWr; +} + +void +ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col) +{ + int r; + + for (r = 0; r < ia->rows; r++) + data[r] = HAL_INI_VAL(ia, r, col); +} + +int +ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, + const uint32_t data[], int regWr) +{ + int r; + + for (r = 0; r < ia->rows; r++) { + OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]); + DMA_YIELD(regWr); + } + return regWr; +} diff --git a/sys/contrib/dev/ath/ah.h b/sys/dev/netif/ath/hal/ath_hal/ah.h similarity index 69% rename from sys/contrib/dev/ath/ah.h rename to sys/dev/netif/ath/hal/ath_hal/ah.h index 411acbe51b..709a100c3c 100644 --- a/sys/contrib/dev/ath/ah.h +++ b/sys/dev/netif/ath/hal/ath_hal/ah.h @@ -1,39 +1,20 @@ -/*- - * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting, Atheros - * Communications, Inc. All rights reserved. +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. * - * Redistribution and use in source and binary forms are permitted - * provided that the following conditions are met: - * 1. The materials contained herein are unmodified and are used - * unmodified. - * 2. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following NO - * ''WARRANTY'' disclaimer below (''Disclaimer''), without - * modification. - * 3. Redistributions in binary form must reproduce at minimum a - * disclaimer similar to the Disclaimer below and any redistribution - * must be conditioned upon including a substantially similar - * Disclaimer requirement for further binary redistribution. - * 4. Neither the names of the above-listed copyright holders nor the - * names of any contributors may be used to endorse or promote - * product derived from this software without specific prior written - * permission. + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, - * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE - * FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGES. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: //depot/sw/branches/sam_hal/ah.h#19 $ + * $Id: ah.h,v 1.15 2008/11/15 03:43:50 sam Exp $ */ #ifndef _ATH_AH_H_ @@ -46,7 +27,6 @@ * follow must call back into the HAL through interface, supplying the * reference as the first parameter. */ - /* * Bus i/o type definitions. We define a platform-independent * set of types that are mapped to platform-dependent data for @@ -55,12 +35,10 @@ * require type coercion to work. Larger data can be stored * elsewhere and a reference passed for the bus tag and/or handle. */ -typedef void* HAL_SOFTC; /* pointer to driver/OS state */ -typedef void* HAL_BUS_TAG; /* opaque bus i/o id tag */ -typedef void* HAL_BUS_HANDLE; /* opaque bus i/o handle */ - +typedef void* HAL_SOFTC; /* pointer to driver/OS state */ +typedef void* HAL_BUS_TAG; /* opaque bus i/o id tag */ +typedef void* HAL_BUS_HANDLE; /* opaque bus i/o handle */ #include "ah_osdep.h" - /* * __ahdecl is analogous to _cdecl; it defines the calling * convention used within the HAL. For most systems this @@ -122,17 +100,22 @@ typedef enum { HAL_CAP_BSSIDMASK = 18, /* hardware supports bssid mask */ HAL_CAP_MCAST_KEYSRCH = 19, /* hardware has multicast key search */ HAL_CAP_TSF_ADJUST = 20, /* hardware has beacon tsf adjust */ - HAL_CAP_XR = 21, /* hardware has XR support */ + /* 21 was HAL_CAP_XR */ HAL_CAP_WME_TKIPMIC = 22, /* hardware can support TKIP MIC when WMM is turned on */ - HAL_CAP_CHAN_HALFRATE = 23, /* hardware can support half rate channels */ - HAL_CAP_CHAN_QUARTERRATE = 24, /* hardware can support quarter rate channels */ + /* 23 was HAL_CAP_CHAN_HALFRATE */ + /* 24 was HAL_CAP_CHAN_QUARTERRATE */ HAL_CAP_RFSILENT = 25, /* hardware has rfsilent support */ HAL_CAP_TPC_ACK = 26, /* ack txpower with per-packet tpc */ HAL_CAP_TPC_CTS = 27, /* cts txpower with per-packet tpc */ HAL_CAP_11D = 28, /* 11d beacon support for changing cc */ HAL_CAP_INTMIT = 29, /* interference mitigation */ HAL_CAP_RXORN_FATAL = 30, /* HAL_INT_RXORN treated as fatal */ + HAL_CAP_HT = 31, /* hardware can support HT */ + HAL_CAP_TX_CHAINMASK = 32, /* mask of TX chains supported */ + HAL_CAP_RX_CHAINMASK = 33, /* mask of RX chains supported */ HAL_CAP_RXTSTAMP_PREC = 34, /* rx desc tstamp precision (bits) */ + HAL_CAP_BB_HANG = 35, /* can baseband hang */ + HAL_CAP_MAC_HANG = 36, /* can MAC hang */ } HAL_CAPABILITY_TYPE; /* @@ -176,7 +159,6 @@ typedef enum { HAL_WME_AC_VI = 2, /* video access category */ HAL_WME_AC_VO = 3, /* voice access category */ HAL_WME_UPSD = 4, /* uplink power save */ - HAL_XR_DATA = 5, /* uplink power save */ } HAL_TX_QUEUE_SUBTYPE; /* @@ -264,26 +246,26 @@ typedef enum { } HAL_TX_QUEUE_FLAGS; typedef struct { - u_int32_t tqi_ver; /* hal TXQ version */ + uint32_t tqi_ver; /* hal TXQ version */ HAL_TX_QUEUE_SUBTYPE tqi_subtype; /* subtype if applicable */ HAL_TX_QUEUE_FLAGS tqi_qflags; /* flags (see above) */ - u_int32_t tqi_priority; /* (not used) */ - u_int32_t tqi_aifs; /* aifs */ - u_int32_t tqi_cwmin; /* cwMin */ - u_int32_t tqi_cwmax; /* cwMax */ - u_int16_t tqi_shretry; /* rts retry limit */ - u_int16_t tqi_lgretry; /* long retry limit (not used)*/ - u_int32_t tqi_cbrPeriod; /* CBR period (us) */ - u_int32_t tqi_cbrOverflowLimit; /* threshold for CBROVF int */ - u_int32_t tqi_burstTime; /* max burst duration (us) */ - u_int32_t tqi_readyTime; /* frame schedule time (us) */ - u_int32_t tqi_compBuf; /* comp buffer phys addr */ + uint32_t tqi_priority; /* (not used) */ + uint32_t tqi_aifs; /* aifs */ + uint32_t tqi_cwmin; /* cwMin */ + uint32_t tqi_cwmax; /* cwMax */ + uint16_t tqi_shretry; /* rts retry limit */ + uint16_t tqi_lgretry; /* long retry limit (not used)*/ + uint32_t tqi_cbrPeriod; /* CBR period (us) */ + uint32_t tqi_cbrOverflowLimit; /* threshold for CBROVF int */ + uint32_t tqi_burstTime; /* max burst duration (us) */ + uint32_t tqi_readyTime; /* frame schedule time (us) */ + uint32_t tqi_compBuf; /* comp buffer phys addr */ } HAL_TXQ_INFO; #define HAL_TQI_NONVAL 0xffff /* token to use for aifs, cwmin, cwmax */ -#define HAL_TXQ_USEDEFAULT ((u_int32_t) -1) +#define HAL_TXQ_USEDEFAULT ((uint32_t) -1) /* compression definitions */ #define HAL_COMP_BUF_MAX_SIZE 9216 /* 9K */ @@ -304,7 +286,8 @@ typedef enum { HAL_PKT_TYPE_BEACON = 3, HAL_PKT_TYPE_PROBE_RESP = 4, HAL_PKT_TYPE_CHIRP = 5, - HAL_PKT_TYPE_GRP_POLL = 6, + HAL_PKT_TYPE_GRP_POLL = 6, + HAL_PKT_TYPE_AMPDU = 7, } HAL_PKT_TYPE; /* Rx Filter Frame Types */ @@ -315,10 +298,10 @@ typedef enum { HAL_RX_FILTER_CONTROL = 0x00000008, /* Allow control frames */ HAL_RX_FILTER_BEACON = 0x00000010, /* Allow beacon frames */ HAL_RX_FILTER_PROM = 0x00000020, /* Promiscuous mode */ - HAL_RX_FILTER_XRPOLL = 0x00000040, /* Allow XR poll frmae */ HAL_RX_FILTER_PROBEREQ = 0x00000080, /* Allow probe request frames */ HAL_RX_FILTER_PHYERR = 0x00000100, /* Allow phy errors */ - HAL_RX_FILTER_PHYRADAR = 0x00000200, /* Allow phy radar errors*/ + HAL_RX_FILTER_PHYRADAR = 0x00000200, /* Allow phy radar errors */ + HAL_RX_FILTER_COMPBAR = 0x00000400, /* Allow compressed BAR */ } HAL_RX_FILTER; typedef enum { @@ -357,6 +340,9 @@ typedef enum { HAL_INT_DTIMSYNC= 0x00800000, /* Non-common mapping */ HAL_INT_GPIO = 0x01000000, HAL_INT_CABEND = 0x02000000, /* Non-common mapping */ + HAL_INT_TSFOOR = 0x04000000, /* Non-common mapping */ + HAL_INT_CST = 0x10000000, /* Non-common mapping */ + HAL_INT_GTT = 0x20000000, /* Non-common mapping */ HAL_INT_FATAL = 0x40000000, /* Non-common mapping */ #define HAL_INT_GLOBAL 0x80000000 /* Set/clear IER */ HAL_INT_BMISC = HAL_INT_TIM @@ -389,27 +375,29 @@ typedef enum { * Channels are specified by frequency. */ typedef struct { - u_int16_t channel; /* setting in Mhz */ - u_int16_t channelFlags; /* see below */ - u_int8_t privFlags; + uint32_t channelFlags; /* see below */ + uint16_t channel; /* setting in Mhz */ + uint8_t privFlags; int8_t maxRegTxPower; /* max regulatory tx power in dBm */ int8_t maxTxPower; /* max true tx power in 0.5 dBm */ int8_t minTxPower; /* min true tx power in 0.5 dBm */ } HAL_CHANNEL; /* channelFlags */ -#define CHANNEL_CW_INT 0x0002 /* CW interference detected on channel */ -#define CHANNEL_TURBO 0x0010 /* Turbo Channel */ -#define CHANNEL_CCK 0x0020 /* CCK channel */ -#define CHANNEL_OFDM 0x0040 /* OFDM channel */ -#define CHANNEL_2GHZ 0x0080 /* 2 GHz spectrum channel. */ -#define CHANNEL_5GHZ 0x0100 /* 5 GHz spectrum channel */ -#define CHANNEL_PASSIVE 0x0200 /* Only passive scan allowed in the channel */ -#define CHANNEL_DYN 0x0400 /* dynamic CCK-OFDM channel */ -#define CHANNEL_XR 0x0800 /* XR channel */ -#define CHANNEL_STURBO 0x2000 /* Static turbo, no 11a-only usage */ -#define CHANNEL_HALF 0x4000 /* Half rate channel */ -#define CHANNEL_QUARTER 0x8000 /* Quarter rate channel */ +#define CHANNEL_CW_INT 0x00002 /* CW interference detected on channel */ +#define CHANNEL_TURBO 0x00010 /* Turbo Channel */ +#define CHANNEL_CCK 0x00020 /* CCK channel */ +#define CHANNEL_OFDM 0x00040 /* OFDM channel */ +#define CHANNEL_2GHZ 0x00080 /* 2 GHz spectrum channel */ +#define CHANNEL_5GHZ 0x00100 /* 5 GHz spectrum channel */ +#define CHANNEL_PASSIVE 0x00200 /* Only passive scan allowed in the channel */ +#define CHANNEL_DYN 0x00400 /* dynamic CCK-OFDM channel */ +#define CHANNEL_STURBO 0x02000 /* Static turbo, no 11a-only usage */ +#define CHANNEL_HALF 0x04000 /* Half rate channel */ +#define CHANNEL_QUARTER 0x08000 /* Quarter rate channel */ +#define CHANNEL_HT20 0x10000 /* 11n 20MHZ channel */ +#define CHANNEL_HT40PLUS 0x20000 /* 11n 40MHZ channel w/ ext chan above */ +#define CHANNEL_HT40MINUS 0x40000 /* 11n 40MHZ channel w/ ext chan below */ /* privFlags */ #define CHANNEL_INTERFERENCE 0x01 /* Software use: channel interference @@ -431,9 +419,15 @@ typedef struct { #define CHANNEL_ST (CHANNEL_T|CHANNEL_STURBO) #define CHANNEL_108G (CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO) #define CHANNEL_108A CHANNEL_T -#define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR) +#define CHANNEL_G_HT20 (CHANNEL_G|CHANNEL_HT20) +#define CHANNEL_A_HT20 (CHANNEL_A|CHANNEL_HT20) +#define CHANNEL_G_HT40PLUS (CHANNEL_G|CHANNEL_HT40PLUS) +#define CHANNEL_G_HT40MINUS (CHANNEL_G|CHANNEL_HT40MINUS) +#define CHANNEL_A_HT40PLUS (CHANNEL_A|CHANNEL_HT40PLUS) +#define CHANNEL_A_HT40MINUS (CHANNEL_A|CHANNEL_HT40MINUS) #define CHANNEL_ALL \ - (CHANNEL_OFDM|CHANNEL_CCK| CHANNEL_2GHZ | CHANNEL_5GHZ | CHANNEL_TURBO) + (CHANNEL_OFDM | CHANNEL_CCK| CHANNEL_2GHZ | CHANNEL_5GHZ | \ + CHANNEL_TURBO | CHANNEL_HT20 | CHANNEL_HT40PLUS | CHANNEL_HT40MINUS) #define CHANNEL_ALL_NOTURBO (CHANNEL_ALL &~ CHANNEL_TURBO) #define HAL_ANTENNA_MIN_MODE 0 @@ -442,15 +436,15 @@ typedef struct { #define HAL_ANTENNA_MAX_MODE 3 typedef struct { - u_int32_t ackrcv_bad; - u_int32_t rts_bad; - u_int32_t rts_good; - u_int32_t fcs_bad; - u_int32_t beacons; + uint32_t ackrcv_bad; + uint32_t rts_bad; + uint32_t rts_good; + uint32_t fcs_bad; + uint32_t beacons; } HAL_MIB_STATS; -typedef u_int16_t HAL_CTRY_CODE; /* country code */ -typedef u_int16_t HAL_REG_DOMAIN; /* regulatory domain code */ +typedef uint16_t HAL_CTRY_CODE; /* country code */ +typedef uint16_t HAL_REG_DOMAIN; /* regulatory domain code */ enum { CTRY_DEBUG = 0x1ff, /* debug country code */ @@ -467,38 +461,85 @@ enum { #else HAL_MODE_11G = 0x008, /* XXX historical */ #endif - HAL_MODE_108G = 0x020, /* 11a+Turbo channels */ - HAL_MODE_108A = 0x040, /* 11g+Turbo channels */ - HAL_MODE_XR = 0x100, /* XR channels */ - HAL_MODE_11A_HALF_RATE = 0x200, /* 11A half rate channels */ - HAL_MODE_11A_QUARTER_RATE = 0x400, /* 11A quarter rate channels */ - HAL_MODE_ALL = 0xfff + HAL_MODE_108G = 0x020, /* 11g+Turbo channels */ + HAL_MODE_108A = 0x040, /* 11a+Turbo channels */ + HAL_MODE_11A_HALF_RATE = 0x200, /* 11a half width channels */ + HAL_MODE_11A_QUARTER_RATE = 0x400, /* 11a quarter width channels */ + HAL_MODE_11G_HALF_RATE = 0x800, /* 11g half width channels */ + HAL_MODE_11G_QUARTER_RATE = 0x1000, /* 11g quarter width channels */ + HAL_MODE_11NG_HT20 = 0x008000, + HAL_MODE_11NA_HT20 = 0x010000, + HAL_MODE_11NG_HT40PLUS = 0x020000, + HAL_MODE_11NG_HT40MINUS = 0x040000, + HAL_MODE_11NA_HT40PLUS = 0x080000, + HAL_MODE_11NA_HT40MINUS = 0x100000, + HAL_MODE_ALL = 0xffffff }; typedef struct { int rateCount; /* NB: for proper padding */ - u_int8_t rateCodeToIndex[32]; /* back mapping */ + uint8_t rateCodeToIndex[144]; /* back mapping */ struct { - u_int8_t valid; /* valid for rate control use */ - u_int8_t phy; /* CCK/OFDM/XR */ - u_int16_t rateKbps; /* transfer rate in kbs */ - u_int8_t rateCode; /* rate for h/w descriptors */ - u_int8_t shortPreamble; /* mask for enabling short + uint8_t valid; /* valid for rate control use */ + uint8_t phy; /* CCK/OFDM/XR */ + uint32_t rateKbps; /* transfer rate in kbs */ + uint8_t rateCode; /* rate for h/w descriptors */ + uint8_t shortPreamble; /* mask for enabling short * preamble in CCK rate code */ - u_int8_t dot11Rate; /* value for supported rates + uint8_t dot11Rate; /* value for supported rates * info element of MLME */ - u_int8_t controlRate; /* index of next lower basic + uint8_t controlRate; /* index of next lower basic * rate; used for dur. calcs */ - u_int16_t lpAckDuration; /* long preamble ACK duration */ - u_int16_t spAckDuration; /* short preamble ACK duration*/ + uint16_t lpAckDuration; /* long preamble ACK duration */ + uint16_t spAckDuration; /* short preamble ACK duration*/ } info[32]; } HAL_RATE_TABLE; typedef struct { u_int rs_count; /* number of valid entries */ - u_int8_t rs_rates[32]; /* rates */ + uint8_t rs_rates[32]; /* rates */ } HAL_RATE_SET; +/* + * 802.11n specific structures and enums + */ +typedef enum { + HAL_CHAINTYPE_TX = 1, /* Tx chain type */ + HAL_CHAINTYPE_RX = 2, /* RX chain type */ +} HAL_CHAIN_TYPE; + +typedef struct { + u_int Tries; + u_int Rate; + u_int PktDuration; + u_int ChSel; + u_int RateFlags; +#define HAL_RATESERIES_RTS_CTS 0x0001 /* use rts/cts w/this series */ +#define HAL_RATESERIES_2040 0x0002 /* use ext channel for series */ +#define HAL_RATESERIES_HALFGI 0x0004 /* use half-gi for series */ +} HAL_11N_RATE_SERIES; + +typedef enum { + HAL_HT_MACMODE_20 = 0, /* 20 MHz operation */ + HAL_HT_MACMODE_2040 = 1, /* 20/40 MHz operation */ +} HAL_HT_MACMODE; + +typedef enum { + HAL_HT_PHYMODE_20 = 0, /* 20 MHz operation */ + HAL_HT_PHYMODE_2040 = 1, /* 20/40 MHz operation */ +} HAL_HT_PHYMODE; + +typedef enum { + HAL_HT_EXTPROTSPACING_20 = 0, /* 20 MHz spacing */ + HAL_HT_EXTPROTSPACING_25 = 1, /* 25 MHz spacing */ +} HAL_HT_EXTPROTSPACING; + + +typedef enum { + HAL_RX_CLEAR_CTL_LOW = 0x1, /* force control channel to appear busy */ + HAL_RX_CLEAR_EXT_LOW = 0x2, /* force extension channel to appear busy */ +} HAL_HT_RXCLEAR; + /* * Antenna switch control. By default antenna selection * enables multiple (2) antenna use. To force use of the @@ -519,12 +560,12 @@ typedef enum { } HAL_OPMODE; typedef struct { - u_int8_t kv_type; /* one of HAL_CIPHER */ - u_int8_t kv_pad; - u_int16_t kv_len; /* length in bits */ - u_int8_t kv_val[16]; /* enough for 128-bit keys */ - u_int8_t kv_mic[8]; /* TKIP MIC key */ - u_int8_t kv_txmic[8]; /* TKIP TX MIC key (optional) */ + uint8_t kv_type; /* one of HAL_CIPHER */ + uint8_t kv_pad; + uint16_t kv_len; /* length in bits */ + uint8_t kv_val[16]; /* enough for 128-bit keys */ + uint8_t kv_mic[8]; /* TKIP MIC key */ + uint8_t kv_txmic[8]; /* TKIP TX MIC key (optional) */ } HAL_KEYVAL; typedef enum { @@ -552,31 +593,35 @@ enum { * coexist with a PCF-capable AP. */ typedef struct { - u_int32_t bs_nexttbtt; /* next beacon in TU */ - u_int32_t bs_nextdtim; /* next DTIM in TU */ - u_int32_t bs_intval; /* beacon interval+flags */ + uint32_t bs_nexttbtt; /* next beacon in TU */ + uint32_t bs_nextdtim; /* next DTIM in TU */ + uint32_t bs_intval; /* beacon interval+flags */ #define HAL_BEACON_PERIOD 0x0000ffff /* beacon interval period */ #define HAL_BEACON_ENA 0x00800000 /* beacon xmit enable */ #define HAL_BEACON_RESET_TSF 0x01000000 /* clear TSF */ - u_int32_t bs_dtimperiod; - u_int16_t bs_cfpperiod; /* CFP period in TU */ - u_int16_t bs_cfpmaxduration; /* max CFP duration in TU */ - u_int32_t bs_cfpnext; /* next CFP in TU */ - u_int16_t bs_timoffset; /* byte offset to TIM bitmap */ - u_int16_t bs_bmissthreshold; /* beacon miss threshold */ - u_int32_t bs_sleepduration; /* max sleep duration */ + uint32_t bs_dtimperiod; + uint16_t bs_cfpperiod; /* CFP period in TU */ + uint16_t bs_cfpmaxduration; /* max CFP duration in TU */ + uint32_t bs_cfpnext; /* next CFP in TU */ + uint16_t bs_timoffset; /* byte offset to TIM bitmap */ + uint16_t bs_bmissthreshold; /* beacon miss threshold */ + uint32_t bs_sleepduration; /* max sleep duration */ } HAL_BEACON_STATE; /* * Like HAL_BEACON_STATE but for non-station mode setup. - * NB: see above flag definitions + * NB: see above flag definitions for bt_intval. */ typedef struct { - u_int32_t bt_intval; /* beacon interval+flags */ - u_int32_t bt_nexttbtt; /* next beacon in TU */ - u_int32_t bt_nextatim; /* next ATIM in TU */ - u_int32_t bt_nextdba; /* next DBA in 1/8th TU */ - u_int32_t bt_nextswba; /* next SWBA in 1/8th TU */ + uint32_t bt_intval; /* beacon interval+flags */ + uint32_t bt_nexttbtt; /* next beacon in TU */ + uint32_t bt_nextatim; /* next ATIM in TU */ + uint32_t bt_nextdba; /* next DBA in 1/8th TU */ + uint32_t bt_nextswba; /* next SWBA in 1/8th TU */ + uint32_t bt_flags; /* timer enables */ +#define HAL_BEACON_TBTT_EN 0x00000001 +#define HAL_BEACON_DBA_EN 0x00000002 +#define HAL_BEACON_SWBA_EN 0x00000004 } HAL_BEACON_TIMERS; /* @@ -584,9 +629,9 @@ typedef struct { * optimizing signal quality and other operational aspects. */ typedef struct { - u_int32_t ns_avgbrssi; /* average beacon rssi */ - u_int32_t ns_avgrssi; /* average data rssi */ - u_int32_t ns_avgtxrssi; /* average tx rssi */ + uint32_t ns_avgbrssi; /* average beacon rssi */ + uint32_t ns_avgrssi; /* average data rssi */ + uint32_t ns_avgtxrssi; /* average tx rssi */ } HAL_NODE_STATS; #define HAL_RSSI_EP_MULTIPLIER (1<<7) /* pow2 to optimize out * and / */ @@ -606,22 +651,22 @@ struct ath_rx_status; * ABI version number. */ struct ath_hal { - u_int32_t ah_magic; /* consistency check magic number */ - u_int32_t ah_abi; /* HAL ABI version */ -#define HAL_ABI_VERSION 0x06102600 /* YYMMDDnn */ - u_int16_t ah_devid; /* PCI device ID */ - u_int16_t ah_subvendorid; /* PCI subvendor ID */ + uint32_t ah_magic; /* consistency check magic number */ + uint32_t ah_abi; /* HAL ABI version */ +#define HAL_ABI_VERSION 0x08112800 /* YYMMDDnn */ + uint16_t ah_devid; /* PCI device ID */ + uint16_t ah_subvendorid; /* PCI subvendor ID */ HAL_SOFTC ah_sc; /* back pointer to driver/os state */ HAL_BUS_TAG ah_st; /* params for register r+w */ HAL_BUS_HANDLE ah_sh; HAL_CTRY_CODE ah_countryCode; - u_int32_t ah_macVersion; /* MAC version id */ - u_int16_t ah_macRev; /* MAC revision */ - u_int16_t ah_phyRev; /* PHY revision */ + uint32_t ah_macVersion; /* MAC version id */ + uint16_t ah_macRev; /* MAC revision */ + uint16_t ah_phyRev; /* PHY revision */ /* NB: when only one radio is present the rev is in 5Ghz */ - u_int16_t ah_analog5GhzRev;/* 5GHz radio revision */ - u_int16_t ah_analog2GhzRev;/* 2GHz radio revision */ + uint16_t ah_analog5GhzRev;/* 5GHz radio revision */ + uint16_t ah_analog2GhzRev;/* 2GHz radio revision */ const HAL_RATE_TABLE *__ahdecl(*ah_getRateTable)(struct ath_hal *, u_int mode); @@ -634,11 +679,12 @@ struct ath_hal { HAL_BOOL __ahdecl(*ah_phyDisable)(struct ath_hal *); HAL_BOOL __ahdecl(*ah_disable)(struct ath_hal *); void __ahdecl(*ah_setPCUConfig)(struct ath_hal *); - HAL_BOOL __ahdecl(*ah_perCalibration)(struct ath_hal*, HAL_CHANNEL *, HAL_BOOL *); - HAL_BOOL __ahdecl(*ah_setTxPowerLimit)(struct ath_hal *, u_int32_t); - - /* DFS support */ - HAL_BOOL __ahdecl(*ah_radarWait)(struct ath_hal *, HAL_CHANNEL *); + HAL_BOOL __ahdecl(*ah_perCalibration)(struct ath_hal*, HAL_CHANNEL *, + HAL_BOOL *); + HAL_BOOL __ahdecl(*ah_perCalibrationN)(struct ath_hal *, HAL_CHANNEL *, + u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); + HAL_BOOL __ahdecl(*ah_resetCalValid)(struct ath_hal *, HAL_CHANNEL *); + HAL_BOOL __ahdecl(*ah_setTxPowerLimit)(struct ath_hal *, uint32_t); /* Transmit functions */ HAL_BOOL __ahdecl(*ah_updateTxTrigLevel)(struct ath_hal*, @@ -651,9 +697,9 @@ struct ath_hal { HAL_TXQ_INFO *qInfo); HAL_BOOL __ahdecl(*ah_releaseTxQueue)(struct ath_hal *ah, u_int q); HAL_BOOL __ahdecl(*ah_resetTxQueue)(struct ath_hal *ah, u_int q); - u_int32_t __ahdecl(*ah_getTxDP)(struct ath_hal*, u_int); - HAL_BOOL __ahdecl(*ah_setTxDP)(struct ath_hal*, u_int, u_int32_t txdp); - u_int32_t __ahdecl(*ah_numTxPending)(struct ath_hal *, u_int q); + uint32_t __ahdecl(*ah_getTxDP)(struct ath_hal*, u_int); + HAL_BOOL __ahdecl(*ah_setTxDP)(struct ath_hal*, u_int, uint32_t txdp); + uint32_t __ahdecl(*ah_numTxPending)(struct ath_hal *, u_int q); HAL_BOOL __ahdecl(*ah_startTxDma)(struct ath_hal*, u_int); HAL_BOOL __ahdecl(*ah_stopTxDma)(struct ath_hal*, u_int); HAL_BOOL __ahdecl(*ah_setupTxDesc)(struct ath_hal *, struct ath_desc *, @@ -673,29 +719,29 @@ struct ath_hal { HAL_BOOL lastSeg, const struct ath_desc *); HAL_STATUS __ahdecl(*ah_procTxDesc)(struct ath_hal *, struct ath_desc *, struct ath_tx_status *); - void __ahdecl(*ah_getTxIntrQueue)(struct ath_hal *, u_int32_t *); + void __ahdecl(*ah_getTxIntrQueue)(struct ath_hal *, uint32_t *); void __ahdecl(*ah_reqTxIntrDesc)(struct ath_hal *, struct ath_desc*); /* Receive Functions */ - u_int32_t __ahdecl(*ah_getRxDP)(struct ath_hal*); - void __ahdecl(*ah_setRxDP)(struct ath_hal*, u_int32_t rxdp); + uint32_t __ahdecl(*ah_getRxDP)(struct ath_hal*); + void __ahdecl(*ah_setRxDP)(struct ath_hal*, uint32_t rxdp); void __ahdecl(*ah_enableReceive)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_stopDmaReceive)(struct ath_hal*); void __ahdecl(*ah_startPcuReceive)(struct ath_hal*); void __ahdecl(*ah_stopPcuReceive)(struct ath_hal*); void __ahdecl(*ah_setMulticastFilter)(struct ath_hal*, - u_int32_t filter0, u_int32_t filter1); + uint32_t filter0, uint32_t filter1); HAL_BOOL __ahdecl(*ah_setMulticastFilterIndex)(struct ath_hal*, - u_int32_t index); + uint32_t index); HAL_BOOL __ahdecl(*ah_clrMulticastFilterIndex)(struct ath_hal*, - u_int32_t index); - u_int32_t __ahdecl(*ah_getRxFilter)(struct ath_hal*); - void __ahdecl(*ah_setRxFilter)(struct ath_hal*, u_int32_t); + uint32_t index); + uint32_t __ahdecl(*ah_getRxFilter)(struct ath_hal*); + void __ahdecl(*ah_setRxFilter)(struct ath_hal*, uint32_t); HAL_BOOL __ahdecl(*ah_setupRxDesc)(struct ath_hal *, struct ath_desc *, - u_int32_t size, u_int flags); + uint32_t size, u_int flags); HAL_STATUS __ahdecl(*ah_procRxDesc)(struct ath_hal *, - struct ath_desc *, u_int32_t phyAddr, - struct ath_desc *next, u_int64_t tsf, + struct ath_desc *, uint32_t phyAddr, + struct ath_desc *next, uint64_t tsf, struct ath_rx_status *); void __ahdecl(*ah_rxMonitor)(struct ath_hal *, const HAL_NODE_STATS *, HAL_CHANNEL *); @@ -704,31 +750,31 @@ struct ath_hal { /* Misc Functions */ HAL_STATUS __ahdecl(*ah_getCapability)(struct ath_hal *, - HAL_CAPABILITY_TYPE, u_int32_t capability, - u_int32_t *result); + HAL_CAPABILITY_TYPE, uint32_t capability, + uint32_t *result); HAL_BOOL __ahdecl(*ah_setCapability)(struct ath_hal *, - HAL_CAPABILITY_TYPE, u_int32_t capability, - u_int32_t setting, HAL_STATUS *); + HAL_CAPABILITY_TYPE, uint32_t capability, + uint32_t setting, HAL_STATUS *); HAL_BOOL __ahdecl(*ah_getDiagState)(struct ath_hal *, int request, - const void *args, u_int32_t argsize, - void **result, u_int32_t *resultsize); - void __ahdecl(*ah_getMacAddress)(struct ath_hal *, u_int8_t *); - HAL_BOOL __ahdecl(*ah_setMacAddress)(struct ath_hal *, const u_int8_t*); - void __ahdecl(*ah_getBssIdMask)(struct ath_hal *, u_int8_t *); - HAL_BOOL __ahdecl(*ah_setBssIdMask)(struct ath_hal *, const u_int8_t*); + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize); + void __ahdecl(*ah_getMacAddress)(struct ath_hal *, uint8_t *); + HAL_BOOL __ahdecl(*ah_setMacAddress)(struct ath_hal *, const uint8_t*); + void __ahdecl(*ah_getBssIdMask)(struct ath_hal *, uint8_t *); + HAL_BOOL __ahdecl(*ah_setBssIdMask)(struct ath_hal *, const uint8_t*); HAL_BOOL __ahdecl(*ah_setRegulatoryDomain)(struct ath_hal*, - u_int16_t, HAL_STATUS *); + uint16_t, HAL_STATUS *); void __ahdecl(*ah_setLedState)(struct ath_hal*, HAL_LED_STATE); void __ahdecl(*ah_writeAssocid)(struct ath_hal*, - const u_int8_t *bssid, u_int16_t assocId); - HAL_BOOL __ahdecl(*ah_gpioCfgOutput)(struct ath_hal *, u_int32_t gpio); - HAL_BOOL __ahdecl(*ah_gpioCfgInput)(struct ath_hal *, u_int32_t gpio); - u_int32_t __ahdecl(*ah_gpioGet)(struct ath_hal *, u_int32_t gpio); + const uint8_t *bssid, uint16_t assocId); + HAL_BOOL __ahdecl(*ah_gpioCfgOutput)(struct ath_hal *, uint32_t gpio); + HAL_BOOL __ahdecl(*ah_gpioCfgInput)(struct ath_hal *, uint32_t gpio); + uint32_t __ahdecl(*ah_gpioGet)(struct ath_hal *, uint32_t gpio); HAL_BOOL __ahdecl(*ah_gpioSet)(struct ath_hal *, - u_int32_t gpio, u_int32_t val); - void __ahdecl(*ah_gpioSetIntr)(struct ath_hal*, u_int, u_int32_t); - u_int32_t __ahdecl(*ah_getTsf32)(struct ath_hal*); - u_int64_t __ahdecl(*ah_getTsf64)(struct ath_hal*); + uint32_t gpio, uint32_t val); + void __ahdecl(*ah_gpioSetIntr)(struct ath_hal*, u_int, uint32_t); + uint32_t __ahdecl(*ah_getTsf32)(struct ath_hal*); + uint64_t __ahdecl(*ah_getTsf64)(struct ath_hal*); void __ahdecl(*ah_resetTsf)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_detectCardPresent)(struct ath_hal*); void __ahdecl(*ah_updateMibCounters)(struct ath_hal*, @@ -739,6 +785,8 @@ struct ath_hal { HAL_ANT_SETTING __ahdecl(*ah_getAntennaSwitch)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_setAntennaSwitch)(struct ath_hal*, HAL_ANT_SETTING); + HAL_BOOL __ahdecl(*ah_setSifsTime)(struct ath_hal*, u_int); + u_int __ahdecl(*ah_getSifsTime)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_setSlotTime)(struct ath_hal*, u_int); u_int __ahdecl(*ah_getSlotTime)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_setAckTimeout)(struct ath_hal*, u_int); @@ -747,19 +795,19 @@ struct ath_hal { u_int __ahdecl(*ah_getAckCTSRate)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_setCTSTimeout)(struct ath_hal*, u_int); u_int __ahdecl(*ah_getCTSTimeout)(struct ath_hal*); - HAL_BOOL __ahdecl(*ah_setDecompMask)(struct ath_hal*, u_int16_t, int); - void __ahdecl(*ah_setCoverageClass)(struct ath_hal*, u_int8_t, int); + HAL_BOOL __ahdecl(*ah_setDecompMask)(struct ath_hal*, uint16_t, int); + void __ahdecl(*ah_setCoverageClass)(struct ath_hal*, uint8_t, int); /* Key Cache Functions */ - u_int32_t __ahdecl(*ah_getKeyCacheSize)(struct ath_hal*); - HAL_BOOL __ahdecl(*ah_resetKeyCacheEntry)(struct ath_hal*, u_int16_t); + uint32_t __ahdecl(*ah_getKeyCacheSize)(struct ath_hal*); + HAL_BOOL __ahdecl(*ah_resetKeyCacheEntry)(struct ath_hal*, uint16_t); HAL_BOOL __ahdecl(*ah_isKeyCacheEntryValid)(struct ath_hal *, - u_int16_t); + uint16_t); HAL_BOOL __ahdecl(*ah_setKeyCacheEntry)(struct ath_hal*, - u_int16_t, const HAL_KEYVAL *, - const u_int8_t *, int); + uint16_t, const HAL_KEYVAL *, + const uint8_t *, int); HAL_BOOL __ahdecl(*ah_setKeyCacheEntryMac)(struct ath_hal*, - u_int16_t, const u_int8_t *); + uint16_t, const uint8_t *); /* Power Management Functions */ HAL_BOOL __ahdecl(*ah_setPowerMode)(struct ath_hal*, @@ -767,13 +815,12 @@ struct ath_hal { HAL_POWER_MODE __ahdecl(*ah_getPowerMode)(struct ath_hal*); int16_t __ahdecl(*ah_getChanNoise)(struct ath_hal *, HAL_CHANNEL *); - /* Beacon Management Functions */ void __ahdecl(*ah_setBeaconTimers)(struct ath_hal*, const HAL_BEACON_TIMERS *); /* NB: deprecated, use ah_setBeaconTimers instead */ void __ahdecl(*ah_beaconInit)(struct ath_hal *, - u_int32_t nexttbtt, u_int32_t intval); + uint32_t nexttbtt, uint32_t intval); void __ahdecl(*ah_setStationBeaconTimers)(struct ath_hal*, const HAL_BEACON_STATE *); void __ahdecl(*ah_resetStationBeaconTimers)(struct ath_hal*); @@ -790,7 +837,7 @@ struct ath_hal { * and return a printable description for any Atheros hardware. * AH_NULL is returned if the ID's do not describe Atheros hardware. */ -extern const char *__ahdecl ath_hal_probe(u_int16_t vendorid, u_int16_t devid); +extern const char *__ahdecl ath_hal_probe(uint16_t vendorid, uint16_t devid); /* * Attach the HAL for use with the specified device. The device is @@ -805,17 +852,9 @@ extern const char *__ahdecl ath_hal_probe(u_int16_t vendorid, u_int16_t devid); * null (AH_NULL) reference will be returned and a status code will * be returned if the status parameter is non-zero. */ -extern struct ath_hal * __ahdecl ath_hal_attach(u_int16_t devid, HAL_SOFTC, +extern struct ath_hal * __ahdecl ath_hal_attach(uint16_t devid, HAL_SOFTC, HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS* status); -/* - * Set the Vendor ID for Vendor SKU's which can modify the - * channel properties returned by ath_hal_init_channels. - * Return AH_TRUE if set succeeds - */ - -extern HAL_BOOL __ahdecl ath_hal_setvendor(struct ath_hal *, u_int32_t ); - /* * Return a list of channels available for use with the hardware. * The list is based on what the hardware is capable of, the specified @@ -829,8 +868,8 @@ extern HAL_BOOL __ahdecl ath_hal_setvendor(struct ath_hal *, u_int32_t ); */ extern HAL_BOOL __ahdecl ath_hal_init_channels(struct ath_hal *, HAL_CHANNEL *chans, u_int maxchans, u_int *nchans, - u_int8_t *regclassids, u_int maxregids, u_int *nregids, - HAL_CTRY_CODE cc, u_int16_t modeSelect, + uint8_t *regclassids, u_int maxregids, u_int *nregids, + HAL_CTRY_CODE cc, u_int modeSelect, HAL_BOOL enableOutdoor, HAL_BOOL enableExtendedChannels); /* @@ -844,18 +883,12 @@ extern void __ahdecl ath_hal_process_noisefloor(struct ath_hal *ah); */ extern u_int __ahdecl ath_hal_getwirelessmodes(struct ath_hal*, HAL_CTRY_CODE); -/* - * Return rate table for specified mode (11a, 11b, 11g, etc). - */ -extern const HAL_RATE_TABLE * __ahdecl ath_hal_getratetable(struct ath_hal *, - u_int mode); - /* * Calculate the transmit duration of a frame. */ -extern u_int16_t __ahdecl ath_hal_computetxtime(struct ath_hal *, - const HAL_RATE_TABLE *rates, u_int32_t frameLen, - u_int16_t rateix, HAL_BOOL shortPreamble); +extern uint16_t __ahdecl ath_hal_computetxtime(struct ath_hal *, + const HAL_RATE_TABLE *rates, uint32_t frameLen, + uint16_t rateix, HAL_BOOL shortPreamble); /* * Return if device is public safety. @@ -863,17 +896,13 @@ extern u_int16_t __ahdecl ath_hal_computetxtime(struct ath_hal *, extern HAL_BOOL __ahdecl ath_hal_ispublicsafetysku(struct ath_hal *); /* - * Convert between IEEE channel number and channel frequency - * using the specified channel flags; e.g. CHANNEL_2GHZ. + * Return if device is operating in 900 MHz band. */ -extern int __ahdecl ath_hal_mhz2ieee(struct ath_hal *, u_int mhz, u_int flags); +extern HAL_BOOL ath_hal_isgsmsku(struct ath_hal *); /* - * Return a version string for the HAL release. - */ -extern char ath_hal_version[]; -/* - * Return a NULL-terminated array of build/configuration options. + * Convert between IEEE channel number and channel frequency + * using the specified channel flags; e.g. CHANNEL_2GHZ. */ -extern const char* ath_hal_buildopts[]; +extern int __ahdecl ath_hal_mhz2ieee(struct ath_hal *, u_int mhz, u_int flags); #endif /* _ATH_AH_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ah_debug.h b/sys/dev/netif/ath/hal/ath_hal/ah_debug.h new file mode 100644 index 0000000000..e3b15ad1a7 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ah_debug.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ah_debug.h,v 1.1 2008/10/12 16:44:34 sam Exp $ + */ +#ifndef _ATH_AH_DEBUG_H_ +#define _ATH_AH_DEBUG_H_ +/* + * Atheros Device Hardware Access Layer (HAL). + * + * Debug mask definitions. + */ +enum { + HAL_DEBUG_REGDOMAIN = 0x00000001, /* regulatory handling */ + HAL_DEBUG_ATTACH = 0x00000002, /* work done in attach */ + HAL_DEBUG_RESET = 0x00000004, /* reset work */ + HAL_DEBUG_NFCAL = 0x00000008, /* noise floor calibration */ + HAL_DEBUG_PERCAL = 0x00000010, /* periodic calibration */ + HAL_DEBUG_ANI = 0x00000020, /* ANI operation */ + HAL_DEBUG_PHYIO = 0x00000040, /* phy i/o operations */ + HAL_DEBUG_REGIO = 0x00000080, /* register i/o operations */ + HAL_DEBUG_RFPARAM = 0x00000100, + HAL_DEBUG_TXQUEUE = 0x00000200, /* tx queue handling */ + HAL_DEBUG_TX = 0x00000400, + HAL_DEBUG_TXDESC = 0x00000800, + HAL_DEBUG_RX = 0x00001000, + HAL_DEBUG_RXDESC = 0x00002000, + HAL_DEBUG_KEYCACHE = 0x00004000, /* keycache handling */ + HAL_DEBUG_EEPROM = 0x00008000, + HAL_DEBUG_BEACON = 0x00010000, /* beacon setup work */ + HAL_DEBUG_POWER = 0x00020000, /* power management */ + HAL_DEBUG_INTERRUPT = 0x00000080, /* interrupt handling */ + + HAL_DEBUG_ANY = 0xffffffff +}; +#endif /* _ATH_AH_DEBUG_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ah_decode.h b/sys/dev/netif/ath/hal/ath_hal/ah_decode.h new file mode 100644 index 0000000000..bd595aea8d --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ah_decode.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ah_decode.h,v 1.4 2008/11/10 04:08:00 sam Exp $ + */ +#ifndef _ATH_AH_DECODE_H_ +#define _ATH_AH_DECODE_H_ +/* + * Register tracing support. + * + * Setting hw.ath.hal.alq=1 enables tracing of all register reads and + * writes to the file /tmp/ath_hal.log. The file format is a simple + * fixed-size array of records. When done logging set hw.ath.hal.alq=0 + * and then decode the file with the arcode program (that is part of the + * HAL). If you start+stop tracing the data will be appended to an + * existing file. + */ +struct athregrec { + uint32_t op : 8, + reg : 24; + uint32_t val; +}; + +enum { + OP_READ = 0, /* register read */ + OP_WRITE = 1, /* register write */ + OP_DEVICE = 2, /* device identification */ + OP_MARK = 3, /* application marker */ +}; + +enum { + AH_MARK_RESET, /* ar*Reset entry, bChannelChange */ + AH_MARK_RESET_LINE, /* ar*_reset.c, line %d */ + AH_MARK_RESET_DONE, /* ar*Reset exit, error code */ + AH_MARK_CHIPRESET, /* ar*ChipReset, channel num */ + AH_MARK_PERCAL, /* ar*PerCalibration, channel num */ + AH_MARK_SETCHANNEL, /* ar*SetChannel, channel num */ + AH_MARK_ANI_RESET, /* ar*AniReset, opmode */ + AH_MARK_ANI_POLL, /* ar*AniReset, listen time */ + AH_MARK_ANI_CONTROL, /* ar*AniReset, cmd */ +}; +#endif /* _ATH_AH_DECODE_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ah_desc.h b/sys/dev/netif/ath/hal/ath_hal/ah_desc.h new file mode 100644 index 0000000000..4f36d6144f --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ah_desc.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ah_desc.h,v 1.5 2008/11/10 04:08:00 sam Exp $ + */ + +#ifndef _DEV_ATH_DESC_H +#define _DEV_ATH_DESC_H + +#include "opt_ah.h" /* NB: required for AH_SUPPORT_AR5416 */ +#define AH_SUPPORT_AR5416 1 /* XXX has to be 1 to compile */ + +/* + * Transmit descriptor status. This structure is filled + * in only after the tx descriptor process method finds a + * ``done'' descriptor; at which point it returns something + * other than HAL_EINPROGRESS. + * + * Note that ts_antenna may not be valid for all h/w. It + * should be used only if non-zero. + */ +struct ath_tx_status { + uint16_t ts_seqnum; /* h/w assigned sequence number */ + uint16_t ts_tstamp; /* h/w assigned timestamp */ + uint8_t ts_status; /* frame status, 0 => xmit ok */ + uint8_t ts_rate; /* h/w transmit rate index */ +#define HAL_TXSTAT_ALTRATE 0x80 /* alternate xmit rate used */ + int8_t ts_rssi; /* tx ack RSSI */ + uint8_t ts_shortretry; /* # short retries */ + uint8_t ts_longretry; /* # long retries */ + uint8_t ts_virtcol; /* virtual collision count */ + uint8_t ts_antenna; /* antenna information */ + uint8_t ts_finaltsi; /* final transmit series index */ +#ifdef AH_SUPPORT_AR5416 + /* 802.11n status */ + uint8_t ts_flags; /* misc flags */ + int8_t ts_rssi_ctl[3]; /* tx ack RSSI [ctl, chain 0-2] */ + int8_t ts_rssi_ext[3]; /* tx ack RSSI [ext, chain 0-2] */ +/* #define ts_rssi ts_rssi_combined */ + uint32_t ts_ba_low; /* blockack bitmap low */ + uint32_t ts_ba_high; /* blockack bitmap high */ + uint32_t ts_evm0; /* evm bytes */ + uint32_t ts_evm1; + uint32_t ts_evm2; +#endif /* AH_SUPPORT_AR5416 */ +}; + +/* bits found in ts_status */ +#define HAL_TXERR_XRETRY 0x01 /* excessive retries */ +#define HAL_TXERR_FILT 0x02 /* blocked by tx filtering */ +#define HAL_TXERR_FIFO 0x04 /* fifo underrun */ +#define HAL_TXERR_XTXOP 0x08 /* txop exceeded */ +#define HAL_TXERR_TIMER_EXPIRED 0x10 /* Tx timer expired */ + +/* bits found in ts_flags */ +#define HAL_TX_BA 0x01 /* Block Ack seen */ +#define HAL_TX_AGGR 0x02 /* Aggregate */ +#define HAL_TX_DESC_CFG_ERR 0x10 /* Error in 20/40 desc config */ +#define HAL_TX_DATA_UNDERRUN 0x20 /* Tx buffer underrun */ +#define HAL_TX_DELIM_UNDERRUN 0x40 /* Tx delimiter underrun */ + +/* + * Receive descriptor status. This structure is filled + * in only after the rx descriptor process method finds a + * ``done'' descriptor; at which point it returns something + * other than HAL_EINPROGRESS. + * + * If rx_status is zero, then the frame was received ok; + * otherwise the error information is indicated and rs_phyerr + * contains a phy error code if HAL_RXERR_PHY is set. In general + * the frame contents is undefined when an error occurred thought + * for some errors (e.g. a decryption error), it may be meaningful. + * + * Note that the receive timestamp is expanded using the TSF to + * at least 15 bits (regardless of what the h/w provides directly). + * Newer hardware supports a full 32-bits; use HAL_CAP_32TSTAMP to + * find out if the hardware is capable. + * + * rx_rssi is in units of dbm above the noise floor. This value + * is measured during the preamble and PLCP; i.e. with the initial + * 4us of detection. The noise floor is typically a consistent + * -96dBm absolute power in a 20MHz channel. + */ +struct ath_rx_status { + uint16_t rs_datalen; /* rx frame length */ + uint8_t rs_status; /* rx status, 0 => recv ok */ + uint8_t rs_phyerr; /* phy error code */ + int8_t rs_rssi; /* rx frame RSSI (combined for 11n) */ + uint8_t rs_keyix; /* key cache index */ + uint8_t rs_rate; /* h/w receive rate index */ + uint8_t rs_more; /* more descriptors follow */ + uint32_t rs_tstamp; /* h/w assigned timestamp */ + uint32_t rs_antenna; /* antenna information */ +#ifdef AH_SUPPORT_AR5416 + /* 802.11n status */ + int8_t rs_rssi_ctl[3]; /* rx frame RSSI [ctl, chain 0-2] */ + int8_t rs_rssi_ext[3]; /* rx frame RSSI [ext, chain 0-2] */ + uint8_t rs_isaggr; /* is part of the aggregate */ + uint8_t rs_moreaggr; /* more frames in aggr to follow */ + uint8_t rs_num_delims; /* number of delims in aggr */ + uint8_t rs_flags; /* misc flags */ + uint32_t rs_evm0; /* evm bytes */ + uint32_t rs_evm1; + uint32_t rs_evm2; +#endif /* AH_SUPPORT_AR5416 */ +}; + +/* bits found in rs_status */ +#define HAL_RXERR_CRC 0x01 /* CRC error on frame */ +#define HAL_RXERR_PHY 0x02 /* PHY error, rs_phyerr is valid */ +#define HAL_RXERR_FIFO 0x04 /* fifo overrun */ +#define HAL_RXERR_DECRYPT 0x08 /* non-Michael decrypt error */ +#define HAL_RXERR_MIC 0x10 /* Michael MIC decrypt error */ + +/* bits found in rs_flags */ +#define HAL_RX_MORE 0x01 /* more descriptors follow */ +#define HAL_RX_MORE_AGGR 0x02 /* more frames in aggr */ +#define HAL_RX_GI 0x04 /* full gi */ +#define HAL_RX_2040 0x08 /* 40 Mhz */ +#define HAL_RX_DELIM_CRC_PRE 0x10 /* crc error in delimiter pre */ +#define HAL_RX_DELIM_CRC_POST 0x20 /* crc error in delim after */ +#define HAL_RX_DECRYPT_BUSY 0x40 /* decrypt was too slow */ +#define HAL_RX_HI_RX_CHAIN 0x80 /* SM power save: hi Rx chain control */ + +enum { + HAL_PHYERR_UNDERRUN = 0, /* Transmit underrun */ + HAL_PHYERR_TIMING = 1, /* Timing error */ + HAL_PHYERR_PARITY = 2, /* Illegal parity */ + HAL_PHYERR_RATE = 3, /* Illegal rate */ + HAL_PHYERR_LENGTH = 4, /* Illegal length */ + HAL_PHYERR_RADAR = 5, /* Radar detect */ + HAL_PHYERR_SERVICE = 6, /* Illegal service */ + HAL_PHYERR_TOR = 7, /* Transmit override receive */ + /* NB: these are specific to the 5212 */ + HAL_PHYERR_OFDM_TIMING = 17, /* */ + HAL_PHYERR_OFDM_SIGNAL_PARITY = 18, /* */ + HAL_PHYERR_OFDM_RATE_ILLEGAL = 19, /* */ + HAL_PHYERR_OFDM_LENGTH_ILLEGAL = 20, /* */ + HAL_PHYERR_OFDM_POWER_DROP = 21, /* */ + HAL_PHYERR_OFDM_SERVICE = 22, /* */ + HAL_PHYERR_OFDM_RESTART = 23, /* */ + HAL_PHYERR_CCK_TIMING = 25, /* */ + HAL_PHYERR_CCK_HEADER_CRC = 26, /* */ + HAL_PHYERR_CCK_RATE_ILLEGAL = 27, /* */ + HAL_PHYERR_CCK_SERVICE = 30, /* */ + HAL_PHYERR_CCK_RESTART = 31, /* */ +}; + +/* value found in rs_keyix to mark invalid entries */ +#define HAL_RXKEYIX_INVALID ((uint8_t) -1) +/* value used to specify no encryption key for xmit */ +#define HAL_TXKEYIX_INVALID ((u_int) -1) + +/* XXX rs_antenna definitions */ + +/* + * Definitions for the software frame/packet descriptors used by + * the Atheros HAL. This definition obscures hardware-specific + * details from the driver. Drivers are expected to fillin the + * portions of a descriptor that are not opaque then use HAL calls + * to complete the work. Status for completed frames is returned + * in a device-independent format. + */ +#ifdef AH_SUPPORT_AR5416 +#define HAL_DESC_HW_SIZE 20 +#else +#define HAL_DESC_HW_SIZE 4 +#endif /* AH_SUPPORT_AR5416 */ + +struct ath_desc { + /* + * The following definitions are passed directly + * the hardware and managed by the HAL. Drivers + * should not touch those elements marked opaque. + */ + uint32_t ds_link; /* phys address of next descriptor */ + uint32_t ds_data; /* phys address of data buffer */ + uint32_t ds_ctl0; /* opaque DMA control 0 */ + uint32_t ds_ctl1; /* opaque DMA control 1 */ + uint32_t ds_hw[HAL_DESC_HW_SIZE]; /* opaque h/w region */ +}; + +struct ath_desc_status { + union { + struct ath_tx_status tx;/* xmit status */ + struct ath_rx_status rx;/* recv status */ + } ds_us; +}; + +#define ds_txstat ds_us.tx +#define ds_rxstat ds_us.rx + +/* flags passed to tx descriptor setup methods */ +#define HAL_TXDESC_CLRDMASK 0x0001 /* clear destination filter mask */ +#define HAL_TXDESC_NOACK 0x0002 /* don't wait for ACK */ +#define HAL_TXDESC_RTSENA 0x0004 /* enable RTS */ +#define HAL_TXDESC_CTSENA 0x0008 /* enable CTS */ +#define HAL_TXDESC_INTREQ 0x0010 /* enable per-descriptor interrupt */ +#define HAL_TXDESC_VEOL 0x0020 /* mark virtual EOL */ +/* NB: this only affects frame, not any RTS/CTS */ +#define HAL_TXDESC_DURENA 0x0040 /* enable h/w write of duration field */ +#define HAL_TXDESC_EXT_ONLY 0x0080 /* send on ext channel only (11n) */ +#define HAL_TXDESC_EXT_AND_CTL 0x0100 /* send on ext + ctl channels (11n) */ +#define HAL_TXDESC_VMF 0x0200 /* virtual more frag */ + +/* flags passed to rx descriptor setup methods */ +#define HAL_RXDESC_INTREQ 0x0020 /* enable per-descriptor interrupt */ +#endif /* _DEV_ATH_DESC_H */ diff --git a/sys/contrib/dev/ath/ah_devid.h b/sys/dev/netif/ath/hal/ath_hal/ah_devid.h similarity index 53% rename from sys/contrib/dev/ath/ah_devid.h rename to sys/dev/netif/ath/hal/ath_hal/ah_devid.h index c4bd28c2c2..0844c77361 100644 --- a/sys/contrib/dev/ath/ah_devid.h +++ b/sys/dev/netif/ath/hal/ath_hal/ah_devid.h @@ -1,39 +1,20 @@ -/*- - * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting, Atheros - * Communications, Inc. All rights reserved. +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. * - * Redistribution and use in source and binary forms are permitted - * provided that the following conditions are met: - * 1. The materials contained herein are unmodified and are used - * unmodified. - * 2. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following NO - * ''WARRANTY'' disclaimer below (''Disclaimer''), without - * modification. - * 3. Redistributions in binary form must reproduce at minimum a - * disclaimer similar to the Disclaimer below and any redistribution - * must be conditioned upon including a substantially similar - * Disclaimer requirement for further binary redistribution. - * 4. Neither the names of the above-listed copyright holders nor the - * names of any contributors may be used to endorse or promote - * product derived from this software without specific prior written - * permission. + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, - * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE - * FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGES. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: //depot/sw/branches/sam_hal/ah_devid.h#2 $ + * $Id: ah_devid.h,v 1.4 2008/10/06 18:32:46 sam Exp $ */ #ifndef _DEV_ATH_DEVID_H_ @@ -70,7 +51,8 @@ #define AR5212_AR2313_REV8 0x0058 /* AR2313 WMAC (AP43-030) */ #define AR5212_AR2315_REV6 0x0086 /* AR2315 WMAC (AP51-Light) */ #define AR5212_AR2315_REV7 0x0087 /* AR2315 WMAC (AP51-Full) */ -#define AR5212_AR2317_REV1 0x0091 /* AR2317 WMAC (AP61) */ +#define AR5212_AR2317_REV1 0x0090 /* AR2317 WMAC (AP61-Light) */ +#define AR5212_AR2317_REV2 0x0091 /* AR2317 WMAC (AP61-Full) */ /* AR5212 compatible devid's also attach to 5212 */ #define AR5212_DEVID_0014 0x0014 @@ -82,17 +64,20 @@ #define AR5212_AR2413 0x001a /* AR2413 aka Griffin-lite */ #define AR5212_AR5413 0x001b /* Eagle */ #define AR5212_AR5424 0x001c /* Condor (PCI express) */ +#define AR5212_AR2417 0x001d /* Nala, PCI */ #define AR5212_DEVID_FF19 0xff19 /* XXX PCI express */ /* AR5213 */ #define AR5213_SREV_1_0 0x0055 #define AR5213_SREV_REG 0x4020 -/* AR5416 */ -#define AR5416_DEVID_EMU_PCI 0xff1d /* PCI Owl Emulation*/ -#define AR5416_DEVID_EMU_PCIE 0xff1c /* PCIe Owl Emulation*/ -#define AR5416_DEVID 0x0023 /* PCI (MB/CB) */ -#define AR5418_DEVID 0x0024 /* PCI Express (XB) */ +/* AR5416 compatible devid's */ +#define AR5416_DEVID_PCI 0x0023 /* AR5416 PCI (MB/CB) Owl */ +#define AR5416_DEVID_PCIE 0x0024 /* AR5416 PCI-E (XB) Owl */ +#define AR9160_DEVID_PCI 0x0027 /* AR9160 PCI Sowl */ +#define AR9280_DEVID_PCI 0x0029 /* AR9280 PCI Merlin */ +#define AR9280_DEVID_PCIE 0x002a /* AR9280 PCI-E Merlin */ +#define AR9285_DEVID_PCIE 0x002b /* AR9285 PCI-E Kite */ #define AR_SUBVENDOR_ID_NOG 0x0e11 /* No 11G subvendor ID */ #define AR_SUBVENDOR_ID_NEW_A 0x7065 /* Update device to new RD */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ah_eeprom.h b/sys/dev/netif/ath/hal/ath_hal/ah_eeprom.h new file mode 100644 index 0000000000..0adfcd144d --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ah_eeprom.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ah_eeprom.h,v 1.11 2008/11/27 22:32:48 sam Exp $ + */ +#ifndef _ATH_AH_EEPROM_H_ +#define _ATH_AH_EEPROM_H_ + +#define AR_EEPROM_VER1 0x1000 /* Version 1.0; 5210 only */ +/* + * Version 3 EEPROMs are all 16K. + * 3.1 adds turbo limit, antenna gain, 16 CTL's, 11g info, + * and 2.4Ghz ob/db for B & G + * 3.2 has more accurate pcdac intercepts and analog chip + * calibration. + * 3.3 adds ctl in-band limit, 32 ctl's, and frequency + * expansion + * 3.4 adds xr power, gainI, and 2.4 turbo params + */ +#define AR_EEPROM_VER3 0x3000 /* Version 3.0; start of 16k EEPROM */ +#define AR_EEPROM_VER3_1 0x3001 /* Version 3.1 */ +#define AR_EEPROM_VER3_2 0x3002 /* Version 3.2 */ +#define AR_EEPROM_VER3_3 0x3003 /* Version 3.3 */ +#define AR_EEPROM_VER3_4 0x3004 /* Version 3.4 */ +#define AR_EEPROM_VER4 0x4000 /* Version 4.x */ +#define AR_EEPROM_VER4_0 0x4000 /* Version 4.0 */ +#define AR_EEPROM_VER4_1 0x4001 /* Version 4.0 */ +#define AR_EEPROM_VER4_2 0x4002 /* Version 4.0 */ +#define AR_EEPROM_VER4_3 0x4003 /* Version 4.0 */ +#define AR_EEPROM_VER4_6 0x4006 /* Version 4.0 */ +#define AR_EEPROM_VER4_7 0x3007 /* Version 4.7 */ +#define AR_EEPROM_VER4_9 0x4009 /* EEPROM EAR futureproofing */ +#define AR_EEPROM_VER5 0x5000 /* Version 5.x */ +#define AR_EEPROM_VER5_0 0x5000 /* Adds new 2413 cal powers and added params */ +#define AR_EEPROM_VER5_1 0x5001 /* Adds capability values */ +#define AR_EEPROM_VER5_3 0x5003 /* Adds spur mitigation table */ +#define AR_EEPROM_VER5_4 0x5004 +/* + * Version 14 EEPROMs came in with AR5416. + * 14.2 adds txFrameToPaOn, txFrameToDataStart, ht40PowerInc + * 14.3 adds bswAtten, bswMargin, swSettle, and base OpFlags for HT20/40 + */ +#define AR_EEPROM_VER14 0xE000 /* Version 14.x */ +#define AR_EEPROM_VER14_1 0xE001 /* Adds 11n support */ +#define AR_EEPROM_VER14_2 0xE002 +#define AR_EEPROM_VER14_3 0xE003 +#define AR_EEPROM_VER14_7 0xE007 +#define AR_EEPROM_VER14_9 0xE009 +#define AR_EEPROM_VER14_16 0xE010 +#define AR_EEPROM_VER14_17 0xE011 +#define AR_EEPROM_VER14_19 0xE013 + +enum { + AR_EEP_RFKILL, /* use ath_hal_eepromGetFlag */ + AR_EEP_AMODE, /* use ath_hal_eepromGetFlag */ + AR_EEP_BMODE, /* use ath_hal_eepromGetFlag */ + AR_EEP_GMODE, /* use ath_hal_eepromGetFlag */ + AR_EEP_TURBO5DISABLE, /* use ath_hal_eepromGetFlag */ + AR_EEP_TURBO2DISABLE, /* use ath_hal_eepromGetFlag */ + AR_EEP_ISTALON, /* use ath_hal_eepromGetFlag */ + AR_EEP_32KHZCRYSTAL, /* use ath_hal_eepromGetFlag */ + AR_EEP_MACADDR, /* uint8_t* */ + AR_EEP_COMPRESS, /* use ath_hal_eepromGetFlag */ + AR_EEP_FASTFRAME, /* use ath_hal_eepromGetFlag */ + AR_EEP_AES, /* use ath_hal_eepromGetFlag */ + AR_EEP_BURST, /* use ath_hal_eepromGetFlag */ + AR_EEP_MAXQCU, /* uint16_t* */ + AR_EEP_KCENTRIES, /* uint16_t* */ + AR_EEP_NFTHRESH_5, /* int16_t* */ + AR_EEP_NFTHRESH_2, /* int16_t* */ + AR_EEP_REGDMN_0, /* uint16_t* */ + AR_EEP_REGDMN_1, /* uint16_t* */ + AR_EEP_OPCAP, /* uint16_t* */ + AR_EEP_OPMODE, /* uint16_t* */ + AR_EEP_RFSILENT, /* uint16_t* */ + AR_EEP_OB_5, /* uint8_t* */ + AR_EEP_DB_5, /* uint8_t* */ + AR_EEP_OB_2, /* uint8_t* */ + AR_EEP_DB_2, /* uint8_t* */ + AR_EEP_TXMASK, /* uint8_t* */ + AR_EEP_RXMASK, /* uint8_t* */ + AR_EEP_RXGAIN_TYPE, /* uint8_t* */ + AR_EEP_TXGAIN_TYPE, /* uint8_t* */ + AR_EEP_OL_PWRCTRL, /* use ath_hal_eepromGetFlag */ + AR_EEP_FSTCLK_5G, /* use ath_hal_eepromGetFlag */ + AR_EEP_ANTGAINMAX_5, /* int8_t* */ + AR_EEP_ANTGAINMAX_2, /* int8_t* */ + AR_EEP_WRITEPROTECT, /* use ath_hal_eepromGetFlag */ +}; + +typedef struct { + uint16_t rdEdge; + uint16_t twice_rdEdgePower; + HAL_BOOL flag; +} RD_EDGES_POWER; + +/* XXX should probably be version-dependent */ +#define SD_NO_CTL 0xf0 +#define NO_CTL 0xff +#define CTL_MODE_M 0x0f +#define CTL_11A 0 +#define CTL_11B 1 +#define CTL_11G 2 +#define CTL_TURBO 3 +#define CTL_108G 4 +#define CTL_2GHT20 5 +#define CTL_5GHT20 6 +#define CTL_2GHT40 7 +#define CTL_5GHT40 8 + +#define AR_NO_SPUR 0x8000 + +/* XXX exposed to chip code */ +#define MAX_RATE_POWER 63 + +HAL_STATUS ath_hal_v1EepromAttach(struct ath_hal *ah); +HAL_STATUS ath_hal_legacyEepromAttach(struct ath_hal *ah); +HAL_STATUS ath_hal_v14EepromAttach(struct ath_hal *ah); +HAL_STATUS ath_hal_v4kEepromAttach(struct ath_hal *ah); +#endif /* _ATH_AH_EEPROM_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v1.c b/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v1.c new file mode 100644 index 0000000000..91f895c248 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v1.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ah_eeprom_v1.c,v 1.1 2008/11/11 02:40:11 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_eeprom_v1.h" + +static HAL_STATUS +v1EepromGet(struct ath_hal *ah, int param, void *val) +{ + HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + uint32_t sum; + uint16_t eeval; + uint8_t *macaddr; + int i; + + switch (param) { + case AR_EEP_MACADDR: /* Get MAC Address */ + sum = 0; + macaddr = val; + for (i = 0; i < 3; i++) { + if (!ath_hal_eepromRead(ah, AR_EEPROM_MAC(i), &eeval)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read EEPROM location %u\n", + __func__, i); + return HAL_EEREAD; + } + sum += eeval; + macaddr[2*i + 0] = eeval >> 8; + macaddr[2*i + 1] = eeval & 0xff; + } + if (sum == 0 || sum == 0xffff*3) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad mac address %s\n", + __func__, ath_hal_ether_sprintf(macaddr)); + return HAL_EEBADMAC; + } + return HAL_OK; + case AR_EEP_REGDMN_0: + *(uint16_t *) val = ee->ee_regDomain[0]; + return HAL_OK; + case AR_EEP_RFKILL: + HALASSERT(val == AH_NULL); + return ee->ee_rfKill ? HAL_OK : HAL_EIO; + case AR_EEP_WRITEPROTECT: + HALASSERT(val == AH_NULL); + return (ee->ee_protect & AR_EEPROM_PROTOTECT_WP_128_191) ? + HAL_OK : HAL_EIO; + default: + HALASSERT(0); + return HAL_EINVAL; + } +} + +static HAL_BOOL +v1EepromSet(struct ath_hal *ah, int param, int v) +{ + return HAL_EINVAL; +} + +static HAL_BOOL +v1EepromDiag(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, void **result, uint32_t *resultsize) +{ + HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (request) { + case HAL_DIAG_EEPROM: + *result = ee; + *resultsize = sizeof(*ee); + return AH_TRUE; + } + return AH_FALSE; +} + +static uint16_t +v1EepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz) +{ + return AR_NO_SPUR; +} + +/* + * Reclaim any EEPROM-related storage. + */ +static void +v1EepromDetach(struct ath_hal *ah) +{ + HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + + ath_hal_free(ee); + AH_PRIVATE(ah)->ah_eeprom = AH_NULL; +} + +HAL_STATUS +ath_hal_v1EepromAttach(struct ath_hal *ah) +{ + HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t athvals[AR_EEPROM_ATHEROS_MAX]; /* XXX off stack */ + uint16_t protect, version, eeval; + uint32_t sum; + int i, loc; + + HALASSERT(ee == AH_NULL); + + if (!ath_hal_eepromRead(ah, AR_EEPROM_MAGIC, &eeval)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read EEPROM magic number\n", __func__); + return HAL_EEREAD; + } + if (eeval != 0x5aa5) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid EEPROM magic number 0x%x\n", __func__, eeval); + return HAL_EEMAGIC; + } + + if (!ath_hal_eepromRead(ah, AR_EEPROM_PROTECT, &protect)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read EEPROM protection bits; read locked?\n", + __func__); + return HAL_EEREAD; + } + HALDEBUG(ah, HAL_DEBUG_ATTACH, "EEPROM protect 0x%x\n", protect); + /* XXX check proper access before continuing */ + + if (!ath_hal_eepromRead(ah, AR_EEPROM_VERSION, &version)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unable to read EEPROM version\n", __func__); + return HAL_EEREAD; + } + if (((version>>12) & 0xf) != 1) { + /* + * This code only groks the version 1 EEPROM layout. + */ + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unsupported EEPROM version 0x%x found\n", + __func__, version); + return HAL_EEVERSION; + } + + /* + * Read the Atheros EEPROM entries and calculate the checksum. + */ + sum = 0; + for (i = 0; i < AR_EEPROM_ATHEROS_MAX; i++) { + if (!ath_hal_eepromRead(ah, AR_EEPROM_ATHEROS(i), &athvals[i])) + return HAL_EEREAD; + sum ^= athvals[i]; + } + if (sum != 0xffff) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad EEPROM checksum 0x%x\n", + __func__, sum); + return HAL_EEBADSUM; + } + + /* + * Valid checksum, fetch the regulatory domain and save values. + */ + if (!ath_hal_eepromRead(ah, AR_EEPROM_REG_DOMAIN, &eeval)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read regdomain from EEPROM\n", __func__); + return HAL_EEREAD; + } + + ee = ath_hal_malloc(sizeof(HAL_EEPROM_v1)); + if (ee == AH_NULL) { + /* XXX message */ + return HAL_ENOMEM; + } + + ee->ee_version = version; + ee->ee_protect = protect; + ee->ee_antenna = athvals[2]; + ee->ee_biasCurrents = athvals[3]; + ee->ee_thresh62 = athvals[4] & 0xff; + ee->ee_xlnaOn = (athvals[4] >> 8) & 0xff; + ee->ee_xpaOn = athvals[5] & 0xff; + ee->ee_xpaOff = (athvals[5] >> 8) & 0xff; + ee->ee_regDomain[0] = (athvals[6] >> 8) & 0xff; + ee->ee_regDomain[1] = athvals[6] & 0xff; + ee->ee_regDomain[2] = (athvals[7] >> 8) & 0xff; + ee->ee_regDomain[3] = athvals[7] & 0xff; + ee->ee_rfKill = athvals[8] & 0x1; + ee->ee_devType = (athvals[8] >> 1) & 0x7; + + for (i = 0, loc = AR_EEPROM_ATHEROS_TP_SETTINGS; i < AR_CHANNELS_MAX; i++, loc += AR_TP_SETTINGS_SIZE) { + struct tpcMap *chan = &ee->ee_tpc[i]; + + /* Copy pcdac and gain_f values from EEPROM */ + chan->pcdac[0] = (athvals[loc] >> 10) & 0x3F; + chan->gainF[0] = (athvals[loc] >> 4) & 0x3F; + chan->pcdac[1] = ((athvals[loc] << 2) & 0x3C) + | ((athvals[loc+1] >> 14) & 0x03); + chan->gainF[1] = (athvals[loc+1] >> 8) & 0x3F; + chan->pcdac[2] = (athvals[loc+1] >> 2) & 0x3F; + chan->gainF[2] = ((athvals[loc+1] << 4) & 0x30) + | ((athvals[loc+2] >> 12) & 0x0F); + chan->pcdac[3] = (athvals[loc+2] >> 6) & 0x3F; + chan->gainF[3] = athvals[loc+2] & 0x3F; + chan->pcdac[4] = (athvals[loc+3] >> 10) & 0x3F; + chan->gainF[4] = (athvals[loc+3] >> 4) & 0x3F; + chan->pcdac[5] = ((athvals[loc+3] << 2) & 0x3C) + | ((athvals[loc+4] >> 14) & 0x03); + chan->gainF[5] = (athvals[loc+4] >> 8) & 0x3F; + chan->pcdac[6] = (athvals[loc+4] >> 2) & 0x3F; + chan->gainF[6] = ((athvals[loc+4] << 4) & 0x30) + | ((athvals[loc+5] >> 12) & 0x0F); + chan->pcdac[7] = (athvals[loc+5] >> 6) & 0x3F; + chan->gainF[7] = athvals[loc+5] & 0x3F; + chan->pcdac[8] = (athvals[loc+6] >> 10) & 0x3F; + chan->gainF[8] = (athvals[loc+6] >> 4) & 0x3F; + chan->pcdac[9] = ((athvals[loc+6] << 2) & 0x3C) + | ((athvals[loc+7] >> 14) & 0x03); + chan->gainF[9] = (athvals[loc+7] >> 8) & 0x3F; + chan->pcdac[10] = (athvals[loc+7] >> 2) & 0x3F; + chan->gainF[10] = ((athvals[loc+7] << 4) & 0x30) + | ((athvals[loc+8] >> 12) & 0x0F); + + /* Copy Regulatory Domain and Rate Information from EEPROM */ + chan->rate36 = (athvals[loc+8] >> 6) & 0x3F; + chan->rate48 = athvals[loc+8] & 0x3F; + chan->rate54 = (athvals[loc+9] >> 10) & 0x3F; + chan->regdmn[0] = (athvals[loc+9] >> 4) & 0x3F; + chan->regdmn[1] = ((athvals[loc+9] << 2) & 0x3C) + | ((athvals[loc+10] >> 14) & 0x03); + chan->regdmn[2] = (athvals[loc+10] >> 8) & 0x3F; + chan->regdmn[3] = (athvals[loc+10] >> 2) & 0x3F; + } + + AH_PRIVATE(ah)->ah_eeprom = ee; + AH_PRIVATE(ah)->ah_eeversion = version; + AH_PRIVATE(ah)->ah_eepromDetach = v1EepromDetach; + AH_PRIVATE(ah)->ah_eepromGet = v1EepromGet; + AH_PRIVATE(ah)->ah_eepromSet = v1EepromSet; + AH_PRIVATE(ah)->ah_getSpurChan = v1EepromGetSpurChan; + AH_PRIVATE(ah)->ah_eepromDiag = v1EepromDiag; + return HAL_OK; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v1.h b/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v1.h new file mode 100644 index 0000000000..2c235896ea --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v1.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ah_eeprom_v1.h,v 1.1 2008/11/11 02:40:11 sam Exp $ + */ +#ifndef _ATH_AH_EEPROM_V1_H_ +#define _ATH_AH_EEPROM_V1_H_ + +#include "ah_eeprom.h" + +/* + * EEPROM defines for Version 1 Crete EEPROM. + * + * The EEPROM is segmented into three sections: + * + * PCI/Cardbus default configuration settings + * Cardbus CIS tuples and vendor-specific data + * Atheros-specific data + * + * EEPROM entries are read 32-bits at a time through the PCI bus + * interface but are all 16-bit values. + * + * Access to the Atheros-specific data is controlled by protection + * bits and the data is checksum'd. The driver reads the Atheros + * data from the EEPROM at attach and caches it in its private state. + * This data includes the local regulatory domain, channel calibration + * settings, and phy-related configuration settings. + */ +#define AR_EEPROM_MAC(i) (0x1f-(i))/* MAC address word */ +#define AR_EEPROM_MAGIC 0x3d /* magic number */ +#define AR_EEPROM_PROTECT 0x3f /* Atheros segment protect register */ +#define AR_EEPROM_PROTOTECT_WP_128_191 0x80 +#define AR_EEPROM_REG_DOMAIN 0xbf /* Current regulatory domain register */ +#define AR_EEPROM_ATHEROS_BASE 0xc0 /* Base of Atheros-specific data */ +#define AR_EEPROM_ATHEROS_MAX 64 /* 64x2=128 bytes of EEPROM settings */ +#define AR_EEPROM_ATHEROS(n) (AR_EEPROM_ATHEROS_BASE+(n)) +#define AR_EEPROM_VERSION AR_EEPROM_ATHEROS(1) +#define AR_EEPROM_ATHEROS_TP_SETTINGS 0x09 /* Transmit power settings */ +#define AR_REG_DOMAINS_MAX 4 /* # of Regulatory Domains */ +#define AR_CHANNELS_MAX 5 /* # of Channel calibration groups */ +#define AR_TP_SETTINGS_SIZE 11 /* # locations/Channel group */ +#define AR_TP_SCALING_ENTRIES 11 /* # entries in transmit power dBm->pcdac */ + +/* + * NB: we store the rfsilent select+polarity data packed + * with the encoding used in later parts so values + * returned to applications are consistent. + */ +#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c +#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 +#define AR_EEPROM_RFSILENT_POLARITY 0x0002 +#define AR_EEPROM_RFSILENT_POLARITY_S 1 + +#define AR_I2DBM(x) ((uint8_t)((x * 2) + 3)) + +/* + * Transmit power and channel calibration settings. + */ +struct tpcMap { + uint8_t pcdac[AR_TP_SCALING_ENTRIES]; + uint8_t gainF[AR_TP_SCALING_ENTRIES]; + uint8_t rate36; + uint8_t rate48; + uint8_t rate54; + uint8_t regdmn[AR_REG_DOMAINS_MAX]; +}; + +/* + * Information retrieved from EEPROM. + */ +typedef struct { + uint16_t ee_version; /* Version field */ + uint16_t ee_protect; /* EEPROM protect field */ + uint16_t ee_antenna; /* Antenna Settings */ + uint16_t ee_biasCurrents; /* OB, DB */ + uint8_t ee_thresh62; /* thresh62 */ + uint8_t ee_xlnaOn; /* External LNA timing */ + uint8_t ee_xpaOff; /* Extern output stage timing */ + uint8_t ee_xpaOn; /* Extern output stage timing */ + uint8_t ee_rfKill; /* Single low bit signalling if RF Kill is implemented */ + uint8_t ee_devType; /* Type: PCI, miniPCI, CB */ + uint8_t ee_regDomain[AR_REG_DOMAINS_MAX]; + /* calibrated reg domains */ + struct tpcMap ee_tpc[AR_CHANNELS_MAX]; +} HAL_EEPROM_v1; +#endif /* _ATH_AH_EEPROM_V1_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v14.c b/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v14.c new file mode 100644 index 0000000000..0340323a7a --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v14.c @@ -0,0 +1,404 @@ +/* + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: src/sys/dev/ath/ath_hal/ah_eeprom_v14.c,v 1.3.2.1.2.1 2009/04/15 03:14:26 kensmith Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_eeprom_v14.h" + +static HAL_STATUS +v14EepromGet(struct ath_hal *ah, int param, void *val) +{ +#define CHAN_A_IDX 0 +#define CHAN_B_IDX 1 +#define IS_VERS(op, v) ((pBase->version & AR5416_EEP_VER_MINOR_MASK) op (v)) + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + const MODAL_EEP_HEADER *pModal = ee->ee_base.modalHeader; + const BASE_EEP_HEADER *pBase = &ee->ee_base.baseEepHeader; + uint32_t sum; + uint8_t *macaddr; + int i; + + switch (param) { + case AR_EEP_NFTHRESH_5: + *(int16_t *)val = pModal[0].noiseFloorThreshCh[0]; + return HAL_OK; + case AR_EEP_NFTHRESH_2: + *(int16_t *)val = pModal[1].noiseFloorThreshCh[0]; + return HAL_OK; + case AR_EEP_MACADDR: /* Get MAC Address */ + sum = 0; + macaddr = val; + for (i = 0; i < 6; i++) { + macaddr[i] = pBase->macAddr[i]; + sum += pBase->macAddr[i]; + } + if (sum == 0 || sum == 0xffff*3) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad mac address %s\n", + __func__, ath_hal_ether_sprintf(macaddr)); + return HAL_EEBADMAC; + } + return HAL_OK; + case AR_EEP_REGDMN_0: + return pBase->regDmn[0]; + case AR_EEP_REGDMN_1: + return pBase->regDmn[1]; + case AR_EEP_OPCAP: + return pBase->deviceCap; + case AR_EEP_OPMODE: + return pBase->opCapFlags; + case AR_EEP_RFSILENT: + return pBase->rfSilent; + case AR_EEP_OB_5: + return pModal[CHAN_A_IDX].ob; + case AR_EEP_DB_5: + return pModal[CHAN_A_IDX].db; + case AR_EEP_OB_2: + return pModal[CHAN_B_IDX].ob; + case AR_EEP_DB_2: + return pModal[CHAN_B_IDX].db; + case AR_EEP_TXMASK: + return pBase->txMask; + case AR_EEP_RXMASK: + return pBase->rxMask; + case AR_EEP_RXGAIN_TYPE: + return IS_VERS(>=, AR5416_EEP_MINOR_VER_17) ? + pBase->rxGainType : AR5416_EEP_RXGAIN_ORIG; + case AR_EEP_TXGAIN_TYPE: + return IS_VERS(>=, AR5416_EEP_MINOR_VER_19) ? + pBase->txGainType : AR5416_EEP_TXGAIN_ORIG; + case AR_EEP_FSTCLK_5G: + return IS_VERS(>, AR5416_EEP_MINOR_VER_16) ? + pBase->fastClk5g : AH_TRUE; + case AR_EEP_OL_PWRCTRL: + HALASSERT(val == AH_NULL); + return pBase->openLoopPwrCntl ? HAL_OK : HAL_EIO; + case AR_EEP_AMODE: + HALASSERT(val == AH_NULL); + return pBase->opCapFlags & AR5416_OPFLAGS_11A ? + HAL_OK : HAL_EIO; + case AR_EEP_BMODE: + case AR_EEP_GMODE: + HALASSERT(val == AH_NULL); + return pBase->opCapFlags & AR5416_OPFLAGS_11G ? + HAL_OK : HAL_EIO; + case AR_EEP_32KHZCRYSTAL: + case AR_EEP_COMPRESS: + case AR_EEP_FASTFRAME: /* XXX policy decision, h/w can do it */ + case AR_EEP_WRITEPROTECT: /* NB: no write protect bit */ + HALASSERT(val == AH_NULL); + /* fall thru... */ + case AR_EEP_MAXQCU: /* NB: not in opCapFlags */ + case AR_EEP_KCENTRIES: /* NB: not in opCapFlags */ + return HAL_EIO; + case AR_EEP_AES: + case AR_EEP_BURST: + case AR_EEP_RFKILL: + case AR_EEP_TURBO5DISABLE: + case AR_EEP_TURBO2DISABLE: + HALASSERT(val == AH_NULL); + return HAL_OK; + case AR_EEP_ANTGAINMAX_2: + *(int8_t *) val = ee->ee_antennaGainMax[1]; + return HAL_OK; + case AR_EEP_ANTGAINMAX_5: + *(int8_t *) val = ee->ee_antennaGainMax[0]; + return HAL_OK; + default: + HALASSERT(0); + return HAL_EINVAL; + } +#undef IS_VERS +#undef CHAN_A_IDX +#undef CHAN_B_IDX +} + +static HAL_BOOL +v14EepromSet(struct ath_hal *ah, int param, int v) +{ + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (param) { + case AR_EEP_ANTGAINMAX_2: + ee->ee_antennaGainMax[1] = (int8_t) v; + return HAL_OK; + case AR_EEP_ANTGAINMAX_5: + ee->ee_antennaGainMax[0] = (int8_t) v; + return HAL_OK; + } + return HAL_EINVAL; +} + +static HAL_BOOL +v14EepromDiag(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, void **result, uint32_t *resultsize) +{ + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (request) { + case HAL_DIAG_EEPROM: + *result = &ee->ee_base; + *resultsize = sizeof(ee->ee_base); + return AH_TRUE; + } + return AH_FALSE; +} + +/* Do structure specific swaps if Eeprom format is non native to host */ +static void +eepromSwap(struct ar5416eeprom *ee) +{ + uint32_t integer, i, j; + uint16_t word; + MODAL_EEP_HEADER *pModal; + + /* convert Base Eep header */ + word = __bswap16(ee->baseEepHeader.length); + ee->baseEepHeader.length = word; + + word = __bswap16(ee->baseEepHeader.checksum); + ee->baseEepHeader.checksum = word; + + word = __bswap16(ee->baseEepHeader.version); + ee->baseEepHeader.version = word; + + word = __bswap16(ee->baseEepHeader.regDmn[0]); + ee->baseEepHeader.regDmn[0] = word; + + word = __bswap16(ee->baseEepHeader.regDmn[1]); + ee->baseEepHeader.regDmn[1] = word; + + word = __bswap16(ee->baseEepHeader.rfSilent); + ee->baseEepHeader.rfSilent = word; + + word = __bswap16(ee->baseEepHeader.blueToothOptions); + ee->baseEepHeader.blueToothOptions = word; + + word = __bswap16(ee->baseEepHeader.deviceCap); + ee->baseEepHeader.deviceCap = word; + + /* convert Modal Eep header */ + for (j = 0; j < 2; j++) { + pModal = &ee->modalHeader[j]; + + /* XXX linux/ah_osdep.h only defines __bswap32 for BE */ + integer = __bswap32(pModal->antCtrlCommon); + pModal->antCtrlCommon = integer; + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + integer = __bswap32(pModal->antCtrlChain[i]); + pModal->antCtrlChain[i] = integer; + } + + for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { + word = __bswap16(pModal->spurChans[i].spurChan); + pModal->spurChans[i].spurChan = word; + } + } +} + +static uint16_t +v14EepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz) +{ + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + + HALASSERT(0 <= ix && ix < AR5416_EEPROM_MODAL_SPURS); + return ee->ee_base.modalHeader[is2GHz].spurChans[ix].spurChan; +} + +/************************************************************************** + * fbin2freq + * + * Get channel value from binary representation held in eeprom + * RETURNS: the frequency in MHz + */ +static uint16_t +fbin2freq(uint8_t fbin, HAL_BOOL is2GHz) +{ + /* + * Reserved value 0xFF provides an empty definition both as + * an fbin and as a frequency - do not convert + */ + if (fbin == AR5416_BCHAN_UNUSED) + return fbin; + return (uint16_t)((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); +} + +/* + * Copy EEPROM Conformance Testing Limits contents + * into the allocated space + */ +/* USE CTLS from chain zero */ +#define CTL_CHAIN 0 + +static void +v14EepromReadCTLInfo(struct ath_hal *ah, HAL_EEPROM_v14 *ee) +{ + RD_EDGES_POWER *rep = ee->ee_rdEdgesPower; + int i, j; + + HALASSERT(AR5416_NUM_CTLS <= sizeof(ee->ee_rdEdgesPower)/NUM_EDGES); + + for (i = 0; ee->ee_base.ctlIndex[i] != 0 && i < AR5416_NUM_CTLS; i++) { + for (j = 0; j < NUM_EDGES; j ++) { + /* XXX Confirm this is the right thing to do when an invalid channel is stored */ + if (ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].bChannel == AR5416_BCHAN_UNUSED) { + rep[j].rdEdge = 0; + rep[j].twice_rdEdgePower = 0; + rep[j].flag = 0; + } else { + rep[j].rdEdge = fbin2freq( + ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].bChannel, + (ee->ee_base.ctlIndex[i] & CTL_MODE_M) != CTL_11A); + rep[j].twice_rdEdgePower = MS(ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].tPowerFlag, CAL_CTL_EDGES_POWER); + rep[j].flag = MS(ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].tPowerFlag, CAL_CTL_EDGES_FLAG) != 0; + } + } + rep += NUM_EDGES; + } + ee->ee_numCtls = i; + HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, + "%s Numctls = %u\n",__func__,i); +} + +/* + * Reclaim any EEPROM-related storage. + */ +static void +v14EepromDetach(struct ath_hal *ah) +{ + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + + ath_hal_free(ee); + AH_PRIVATE(ah)->ah_eeprom = AH_NULL; +} + +#define owl_get_eep_ver(_ee) \ + (((_ee)->ee_base.baseEepHeader.version >> 12) & 0xF) +#define owl_get_eep_rev(_ee) \ + (((_ee)->ee_base.baseEepHeader.version) & 0xFFF) + +HAL_STATUS +ath_hal_v14EepromAttach(struct ath_hal *ah) +{ +#define NW(a) (sizeof(a) / sizeof(uint16_t)) + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t *eep_data, magic; + HAL_BOOL need_swap; + u_int w, off, len; + uint32_t sum; + + HALASSERT(ee == AH_NULL); + + if (!ath_hal_eepromRead(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s Error reading Eeprom MAGIC\n", __func__); + return HAL_EEREAD; + } + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s Eeprom Magic = 0x%x\n", + __func__, magic); + if (magic != AR5416_EEPROM_MAGIC) { + HALDEBUG(ah, HAL_DEBUG_ANY, "Bad magic number\n"); + return HAL_EEMAGIC; + } + + ee = ath_hal_malloc(sizeof(HAL_EEPROM_v14)); + if (ee == AH_NULL) { + /* XXX message */ + return HAL_ENOMEM; + } + + eep_data = (uint16_t *)&ee->ee_base; + for (w = 0; w < NW(struct ar5416eeprom); w++) { + off = owl_eep_start_loc + w; /* NB: AP71 starts at 0 */ + if (!ath_hal_eepromRead(ah, off, &eep_data[w])) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s eeprom read error at offset 0x%x\n", + __func__, off); + return HAL_EEREAD; + } + } + /* Convert to eeprom native eeprom endian format */ + if (isBigEndian()) { + for (w = 0; w < NW(struct ar5416eeprom); w++) + eep_data[w] = __bswap16(eep_data[w]); + } + + /* + * At this point, we're in the native eeprom endian format + * Now, determine the eeprom endian by looking at byte 26?? + */ + need_swap = ((ee->ee_base.baseEepHeader.eepMisc & AR5416_EEPMISC_BIG_ENDIAN) != 0) ^ isBigEndian(); + if (need_swap) { + HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, + "Byte swap EEPROM contents.\n"); + len = __bswap16(ee->ee_base.baseEepHeader.length); + } else { + len = ee->ee_base.baseEepHeader.length; + } + len = AH_MIN(len, sizeof(struct ar5416eeprom)) / sizeof(uint16_t); + + /* Apply the checksum, done in native eeprom format */ + /* XXX - Need to check to make sure checksum calculation is done + * in the correct endian format. Right now, it seems it would + * cast the raw data to host format and do the calculation, which may + * not be correct as the calculation may need to be done in the native + * eeprom format + */ + sum = 0; + for (w = 0; w < len; w++) + sum ^= eep_data[w]; + /* Check CRC - Attach should fail on a bad checksum */ + if (sum != 0xffff) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "Bad EEPROM checksum 0x%x (Len=%u)\n", sum, len); + return HAL_EEBADSUM; + } + + if (need_swap) + eepromSwap(&ee->ee_base); /* byte swap multi-byte data */ + + /* swap words 0+2 so version is at the front */ + magic = eep_data[0]; + eep_data[0] = eep_data[2]; + eep_data[2] = magic; + + HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, + "%s Eeprom Version %u.%u\n", __func__, + owl_get_eep_ver(ee), owl_get_eep_rev(ee)); + + /* NB: must be after all byte swapping */ + if (owl_get_eep_ver(ee) != AR5416_EEP_VER) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "Bad EEPROM version 0x%x\n", owl_get_eep_ver(ee)); + return HAL_EEBADSUM; + } + + v14EepromReadCTLInfo(ah, ee); /* Get CTLs */ + + AH_PRIVATE(ah)->ah_eeprom = ee; + AH_PRIVATE(ah)->ah_eeversion = ee->ee_base.baseEepHeader.version; + AH_PRIVATE(ah)->ah_eepromDetach = v14EepromDetach; + AH_PRIVATE(ah)->ah_eepromGet = v14EepromGet; + AH_PRIVATE(ah)->ah_eepromSet = v14EepromSet; + AH_PRIVATE(ah)->ah_getSpurChan = v14EepromGetSpurChan; + AH_PRIVATE(ah)->ah_eepromDiag = v14EepromDiag; + return HAL_OK; +#undef NW +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v14.h b/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v14.h new file mode 100644 index 0000000000..90e2c7479b --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v14.h @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ah_eeprom_v14.h,v 1.3 2008/11/10 04:08:00 sam Exp $ + */ +#ifndef _AH_EEPROM_V14_H_ +#define _AH_EEPROM_V14_H_ + +#include "ah_eeprom.h" + +/* reg_off = 4 * (eep_off) */ +#define AR5416_EEPROM_S 2 +#define AR5416_EEPROM_OFFSET 0x2000 +#define AR5416_EEPROM_START_ADDR 0x503f1200 +#define AR5416_EEPROM_MAX 0xae0 /* Ignore for the moment used only on the flash implementations */ +#define AR5416_EEPROM_MAGIC 0xa55a +#define AR5416_EEPROM_MAGIC_OFFSET 0x0 + +#define owl_get_ntxchains(_txchainmask) \ + (((_txchainmask >> 2) & 1) + ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) + +#ifdef __LINUX_ARM_ARCH__ /* AP71 */ +#define owl_eep_start_loc 0 +#else +#define owl_eep_start_loc 256 +#endif + +/* End temp defines */ + +#define AR5416_EEP_NO_BACK_VER 0x1 +#define AR5416_EEP_VER 0xE +#define AR5416_EEP_VER_MINOR_MASK 0xFFF +// Adds modal params txFrameToPaOn, txFrametoDataStart, ht40PowerInc +#define AR5416_EEP_MINOR_VER_2 0x2 +// Adds modal params bswAtten, bswMargin, swSettle and base OpFlags for HT20/40 Disable +#define AR5416_EEP_MINOR_VER_3 0x3 +#define AR5416_EEP_MINOR_VER_7 0x7 +#define AR5416_EEP_MINOR_VER_9 0x9 +#define AR5416_EEP_MINOR_VER_16 0x10 +#define AR5416_EEP_MINOR_VER_17 0x11 +#define AR5416_EEP_MINOR_VER_19 0x13 + +// 16-bit offset location start of calibration struct +#define AR5416_EEP_START_LOC 256 +#define AR5416_NUM_5G_CAL_PIERS 8 +#define AR5416_NUM_2G_CAL_PIERS 4 +#define AR5416_NUM_5G_20_TARGET_POWERS 8 +#define AR5416_NUM_5G_40_TARGET_POWERS 8 +#define AR5416_NUM_2G_CCK_TARGET_POWERS 3 +#define AR5416_NUM_2G_20_TARGET_POWERS 4 +#define AR5416_NUM_2G_40_TARGET_POWERS 4 +#define AR5416_NUM_CTLS 24 +#define AR5416_NUM_BAND_EDGES 8 +#define AR5416_NUM_PD_GAINS 4 +#define AR5416_PD_GAINS_IN_MASK 4 +#define AR5416_PD_GAIN_ICEPTS 5 +#define AR5416_EEPROM_MODAL_SPURS 5 +#define AR5416_MAX_RATE_POWER 63 +#define AR5416_NUM_PDADC_VALUES 128 +#define AR5416_NUM_RATES 16 +#define AR5416_BCHAN_UNUSED 0xFF +#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64 +#define AR5416_EEPMISC_BIG_ENDIAN 0x01 +#define FREQ2FBIN(x,y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) +#define AR5416_MAX_CHAINS 3 +#define AR5416_ANT_16S 25 + +#define AR5416_NUM_ANT_CHAIN_FIELDS 7 +#define AR5416_NUM_ANT_COMMON_FIELDS 4 +#define AR5416_SIZE_ANT_CHAIN_FIELD 3 +#define AR5416_SIZE_ANT_COMMON_FIELD 4 +#define AR5416_ANT_CHAIN_MASK 0x7 +#define AR5416_ANT_COMMON_MASK 0xf +#define AR5416_CHAIN_0_IDX 0 +#define AR5416_CHAIN_1_IDX 1 +#define AR5416_CHAIN_2_IDX 2 + +#define AR5416_OPFLAGS_11A 0x01 +#define AR5416_OPFLAGS_11G 0x02 +#define AR5416_OPFLAGS_5G_HT40 0x04 +#define AR5416_OPFLAGS_2G_HT40 0x08 +#define AR5416_OPFLAGS_5G_HT20 0x10 +#define AR5416_OPFLAGS_2G_HT20 0x20 + +/* RF silent fields in EEPROM */ +#define EEP_RFSILENT_ENABLED 0x0001 /* enabled/disabled */ +#define EEP_RFSILENT_ENABLED_S 0 +#define EEP_RFSILENT_POLARITY 0x0002 /* polarity */ +#define EEP_RFSILENT_POLARITY_S 1 +#define EEP_RFSILENT_GPIO_SEL 0x001c /* gpio PIN */ +#define EEP_RFSILENT_GPIO_SEL_S 2 + +/* Rx gain type values */ +#define AR5416_EEP_RXGAIN_23dB_BACKOFF 0 +#define AR5416_EEP_RXGAIN_13dB_BACKOFF 1 +#define AR5416_EEP_RXGAIN_ORIG 2 + +/* Tx gain type values */ +#define AR5416_EEP_TXGAIN_ORIG 0 +#define AR5416_EEP_TXGAIN_HIGH_POWER 1 + +typedef struct spurChanStruct { + uint16_t spurChan; + uint8_t spurRangeLow; + uint8_t spurRangeHigh; +} __packed SPUR_CHAN; + +typedef struct CalTargetPowerLegacy { + uint8_t bChannel; + uint8_t tPow2x[4]; +} __packed CAL_TARGET_POWER_LEG; + +typedef struct CalTargetPowerHt { + uint8_t bChannel; + uint8_t tPow2x[8]; +} __packed CAL_TARGET_POWER_HT; + +typedef struct CalCtlEdges { + uint8_t bChannel; + uint8_t tPowerFlag; /* [0..5] tPower [6..7] flag */ +#define CAL_CTL_EDGES_POWER 0x3f +#define CAL_CTL_EDGES_POWER_S 0 +#define CAL_CTL_EDGES_FLAG 0xc0 +#define CAL_CTL_EDGES_FLAG_S 6 +} __packed CAL_CTL_EDGES; + +/* + * NB: The format in EEPROM has words 0 and 2 swapped (i.e. version + * and length are swapped). We reverse their position after reading + * the data into host memory so the version field is at the same + * offset as in previous EEPROM layouts. This makes utilities that + * inspect the EEPROM contents work without looking at the PCI device + * id which may or may not be reliable. + */ +typedef struct BaseEepHeader { + uint16_t version; /* NB: length in EEPROM */ + uint16_t checksum; + uint16_t length; /* NB: version in EEPROM */ + uint8_t opCapFlags; + uint8_t eepMisc; + uint16_t regDmn[2]; + uint8_t macAddr[6]; + uint8_t rxMask; + uint8_t txMask; + uint16_t rfSilent; + uint16_t blueToothOptions; + uint16_t deviceCap; + uint32_t binBuildNumber; + uint8_t deviceType; + uint8_t pwdclkind; + uint8_t fastClk5g; + uint8_t divChain; + uint8_t rxGainType; + uint8_t dacHiPwrMode; /* use the DAC high power mode (MB91) */ + uint8_t openLoopPwrCntl;/* 1: use open loop power control, + 0: use closed loop power control */ + uint8_t dacLpMode; + uint8_t txGainType; /* high power tx gain table support */ + uint8_t rcChainMask; /* "1" if the card is an HB93 1x2 */ + uint8_t futureBase[24]; +} __packed BASE_EEP_HEADER; // 64 B + +typedef struct ModalEepHeader { + uint32_t antCtrlChain[AR5416_MAX_CHAINS]; // 12 + uint32_t antCtrlCommon; // 4 + int8_t antennaGainCh[AR5416_MAX_CHAINS]; // 3 + uint8_t switchSettling; // 1 + uint8_t txRxAttenCh[AR5416_MAX_CHAINS]; // 3 + uint8_t rxTxMarginCh[AR5416_MAX_CHAINS]; // 3 + uint8_t adcDesiredSize; // 1 + int8_t pgaDesiredSize; // 1 + uint8_t xlnaGainCh[AR5416_MAX_CHAINS]; // 3 + uint8_t txEndToXpaOff; // 1 + uint8_t txEndToRxOn; // 1 + uint8_t txFrameToXpaOn; // 1 + uint8_t thresh62; // 1 + uint8_t noiseFloorThreshCh[AR5416_MAX_CHAINS]; // 3 + uint8_t xpdGain; // 1 + uint8_t xpd; // 1 + int8_t iqCalICh[AR5416_MAX_CHAINS]; // 1 + int8_t iqCalQCh[AR5416_MAX_CHAINS]; // 1 + uint8_t pdGainOverlap; // 1 + uint8_t ob; // 1 + uint8_t db; // 1 + uint8_t xpaBiasLvl; // 1 + uint8_t pwrDecreaseFor2Chain; // 1 + uint8_t pwrDecreaseFor3Chain; // 1 -> 48 B + uint8_t txFrameToDataStart; // 1 + uint8_t txFrameToPaOn; // 1 + uint8_t ht40PowerIncForPdadc; // 1 + uint8_t bswAtten[AR5416_MAX_CHAINS]; // 3 + uint8_t bswMargin[AR5416_MAX_CHAINS]; // 3 + uint8_t swSettleHt40; // 1 + uint8_t xatten2Db[AR5416_MAX_CHAINS]; // 3 -> New for AR9280 (0xa20c/b20c 11:6) + uint8_t xatten2Margin[AR5416_MAX_CHAINS]; // 3 -> New for AR9280 (0xa20c/b20c 21:17) + uint8_t ob_ch1; // 1 -> ob and db become chain specific from AR9280 + uint8_t db_ch1; // 1 + uint8_t flagBits; // 1 +#define AR5416_EEP_FLAG_USEANT1 0x01 /* +1 configured antenna */ +#define AR5416_EEP_FLAG_FORCEXPAON 0x02 /* force XPA bit for 5G */ +#define AR5416_EEP_FLAG_LOCALBIAS 0x04 /* enable local bias */ +#define AR5416_EEP_FLAG_FEMBANDSELECT 0x08 /* FEM band select used */ +#define AR5416_EEP_FLAG_XLNABUFIN 0x10 +#define AR5416_EEP_FLAG_XLNAISEL 0x60 +#define AR5416_EEP_FLAG_XLNAISEL_S 5 +#define AR5416_EEP_FLAG_XLNABUFMODE 0x80 + uint8_t miscBits; // [0..1]: bb_tx_dac_scale_cck + uint16_t xpaBiasLvlFreq[3]; // 3 + uint8_t futureModal[6]; // 6 + + SPUR_CHAN spurChans[AR5416_EEPROM_MODAL_SPURS]; // 20 B +} __packed MODAL_EEP_HEADER; // == 100 B + +typedef struct calDataPerFreqOpLoop { + uint8_t pwrPdg[2][5]; /* power measurement */ + uint8_t vpdPdg[2][5]; /* pdadc voltage at power measurement */ + uint8_t pcdac[2][5]; /* pcdac used for power measurement */ + uint8_t empty[2][5]; /* future use */ +} __packed CAL_DATA_PER_FREQ_OP_LOOP; + +typedef struct CalCtlData { + CAL_CTL_EDGES ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; +} __packed CAL_CTL_DATA; + +typedef struct calDataPerFreq { + uint8_t pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; + uint8_t vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; +} __packed CAL_DATA_PER_FREQ; + +struct ar5416eeprom { + BASE_EEP_HEADER baseEepHeader; // 64 B + uint8_t custData[64]; // 64 B + MODAL_EEP_HEADER modalHeader[2]; // 200 B + uint8_t calFreqPier5G[AR5416_NUM_5G_CAL_PIERS]; + uint8_t calFreqPier2G[AR5416_NUM_2G_CAL_PIERS]; + CAL_DATA_PER_FREQ calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS]; + CAL_DATA_PER_FREQ calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS]; + CAL_TARGET_POWER_LEG calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS]; + CAL_TARGET_POWER_HT calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS]; + CAL_TARGET_POWER_HT calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS]; + CAL_TARGET_POWER_LEG calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS]; + CAL_TARGET_POWER_LEG calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS]; + CAL_TARGET_POWER_HT calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS]; + CAL_TARGET_POWER_HT calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS]; + uint8_t ctlIndex[AR5416_NUM_CTLS]; + CAL_CTL_DATA ctlData[AR5416_NUM_CTLS]; + uint8_t padding; +} __packed; + +typedef struct { + struct ar5416eeprom ee_base; +#define NUM_EDGES 8 + uint16_t ee_numCtls; + RD_EDGES_POWER ee_rdEdgesPower[NUM_EDGES*AR5416_NUM_CTLS]; + /* XXX these are dynamically calculated for use by shared code */ + int8_t ee_antennaGainMax[2]; +} HAL_EEPROM_v14; +#endif /* _AH_EEPROM_V14_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v3.c b/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v3.c new file mode 100644 index 0000000000..dbee98993c --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v3.c @@ -0,0 +1,1876 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: src/sys/dev/ath/ath_hal/ah_eeprom_v3.c,v 1.2.2.1.2.1 2009/04/15 03:14:26 kensmith Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_eeprom_v3.h" + +static void +getPcdacInterceptsFromPcdacMinMax(HAL_EEPROM *ee, + uint16_t pcdacMin, uint16_t pcdacMax, uint16_t *vp) +{ + static const uint16_t intercepts3[] = + { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 }; + static const uint16_t intercepts3_2[] = + { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; + const uint16_t *ip = ee->ee_version < AR_EEPROM_VER3_2 ? + intercepts3 : intercepts3_2; + int i; + + /* loop for the percentages in steps or 5 */ + for (i = 0; i < NUM_INTERCEPTS; i++ ) + *vp++ = (ip[i] * pcdacMax + (100 - ip[i]) * pcdacMin) / 100; +} + +/* + * Get channel value from binary representation held in eeprom + */ +static uint16_t +fbin2freq(HAL_EEPROM *ee, uint16_t fbin) +{ + if (fbin == CHANNEL_UNUSED) /* reserved value, don't convert */ + return fbin; + return ee->ee_version <= AR_EEPROM_VER3_2 ? + (fbin > 62 ? 5100 + 10*62 + 5*(fbin-62) : 5100 + 10*fbin) : + 4800 + 5*fbin; +} + +static uint16_t +fbin2freq_2p4(HAL_EEPROM *ee, uint16_t fbin) +{ + if (fbin == CHANNEL_UNUSED) /* reserved value, don't convert */ + return fbin; + return ee->ee_version <= AR_EEPROM_VER3_2 ? + 2400 + fbin : + 2300 + fbin; +} + +/* + * Now copy EEPROM frequency pier contents into the allocated space + */ +static HAL_BOOL +readEepromFreqPierInfo(struct ath_hal *ah, HAL_EEPROM *ee) +{ +#define EEREAD(_off) do { \ + if (!ath_hal_eepromRead(ah, _off, &eeval)) \ + return AH_FALSE; \ +} while (0) + uint16_t eeval, off; + int i; + + if (ee->ee_version >= AR_EEPROM_VER4_0 && + ee->ee_eepMap && !ee->ee_Amode) { + /* + * V4.0 EEPROMs with map type 1 have frequency pier + * data only when 11a mode is supported. + */ + return AH_TRUE; + } + if (ee->ee_version >= AR_EEPROM_VER3_3) { + off = GROUPS_OFFSET3_3 + GROUP1_OFFSET; + for (i = 0; i < ee->ee_numChannels11a; i += 2) { + EEREAD(off++); + ee->ee_channels11a[i] = (eeval >> 8) & FREQ_MASK_3_3; + ee->ee_channels11a[i+1] = eeval & FREQ_MASK_3_3; + } + } else { + off = GROUPS_OFFSET3_2 + GROUP1_OFFSET; + + EEREAD(off++); + ee->ee_channels11a[0] = (eeval >> 9) & FREQ_MASK; + ee->ee_channels11a[1] = (eeval >> 2) & FREQ_MASK; + ee->ee_channels11a[2] = (eeval << 5) & FREQ_MASK; + + EEREAD(off++); + ee->ee_channels11a[2] |= (eeval >> 11) & 0x1f; + ee->ee_channels11a[3] = (eeval >> 4) & FREQ_MASK; + ee->ee_channels11a[4] = (eeval << 3) & FREQ_MASK; + + EEREAD(off++); + ee->ee_channels11a[4] |= (eeval >> 13) & 0x7; + ee->ee_channels11a[5] = (eeval >> 6) & FREQ_MASK; + ee->ee_channels11a[6] = (eeval << 1) & FREQ_MASK; + + EEREAD(off++); + ee->ee_channels11a[6] |= (eeval >> 15) & 0x1; + ee->ee_channels11a[7] = (eeval >> 8) & FREQ_MASK; + ee->ee_channels11a[8] = (eeval >> 1) & FREQ_MASK; + ee->ee_channels11a[9] = (eeval << 6) & FREQ_MASK; + + EEREAD(off++); + ee->ee_channels11a[9] |= (eeval >> 10) & 0x3f; + } + + for (i = 0; i < ee->ee_numChannels11a; i++) + ee->ee_channels11a[i] = fbin2freq(ee, ee->ee_channels11a[i]); + + return AH_TRUE; +#undef EEREAD +} + +/* + * Rev 4 Eeprom 5112 Power Extract Functions + */ + +/* + * Allocate the power information based on the number of channels + * recorded by the calibration. These values are then initialized. + */ +static HAL_BOOL +eepromAllocExpnPower5112(struct ath_hal *ah, + const EEPROM_POWER_5112 *pCalDataset, + EEPROM_POWER_EXPN_5112 *pPowerExpn) +{ + uint16_t numChannels = pCalDataset->numChannels; + const uint16_t *pChanList = pCalDataset->pChannels; + void *data; + int i, j; + + /* Allocate the channel and Power Data arrays together */ + data = ath_hal_malloc( + roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t)) + + sizeof(EXPN_DATA_PER_CHANNEL_5112) * numChannels); + if (data == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s unable to allocate raw data struct (gen3)\n", __func__); + return AH_FALSE; + } + pPowerExpn->pChannels = data; + pPowerExpn->pDataPerChannel = (void *)(((char *)data) + + roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t))); + + pPowerExpn->numChannels = numChannels; + for (i = 0; i < numChannels; i++) { + pPowerExpn->pChannels[i] = + pPowerExpn->pDataPerChannel[i].channelValue = + pChanList[i]; + for (j = 0; j < NUM_XPD_PER_CHANNEL; j++) { + pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].xpd_gain = j; + pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].numPcdacs = 0; + } + pPowerExpn->pDataPerChannel[i].pDataPerXPD[0].numPcdacs = 4; + pPowerExpn->pDataPerChannel[i].pDataPerXPD[3].numPcdacs = 3; + } + return AH_TRUE; +} + +/* + * Expand the dataSet from the calibration information into the + * final power structure for 5112 + */ +static HAL_BOOL +eepromExpandPower5112(struct ath_hal *ah, + const EEPROM_POWER_5112 *pCalDataset, + EEPROM_POWER_EXPN_5112 *pPowerExpn) +{ + int ii, jj, kk; + int16_t maxPower_t4; + EXPN_DATA_PER_XPD_5112 *pExpnXPD; + /* ptr to array of info held per channel */ + const EEPROM_DATA_PER_CHANNEL_5112 *pCalCh; + uint16_t xgainList[2], xpdMask; + + pPowerExpn->xpdMask = pCalDataset->xpdMask; + + xgainList[0] = 0xDEAD; + xgainList[1] = 0xDEAD; + + kk = 0; + xpdMask = pPowerExpn->xpdMask; + for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) { + if (((xpdMask >> jj) & 1) > 0) { + if (kk > 1) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: too many xpdGains in dataset: %u\n", + __func__, kk); + return AH_FALSE; + } + xgainList[kk++] = jj; + } + } + + pPowerExpn->numChannels = pCalDataset->numChannels; + if (pPowerExpn->numChannels == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no channels\n", __func__); + return AH_FALSE; + } + + for (ii = 0; ii < pPowerExpn->numChannels; ii++) { + pCalCh = &pCalDataset->pDataPerChannel[ii]; + pPowerExpn->pDataPerChannel[ii].channelValue = + pCalCh->channelValue; + pPowerExpn->pDataPerChannel[ii].maxPower_t4 = + pCalCh->maxPower_t4; + maxPower_t4 = pPowerExpn->pDataPerChannel[ii].maxPower_t4; + + for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) + pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj].numPcdacs = 0; + if (xgainList[1] == 0xDEAD) { + jj = xgainList[0]; + pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj]; + pExpnXPD->numPcdacs = 4; + pExpnXPD->pcdac[0] = pCalCh->pcd1_xg0; + pExpnXPD->pcdac[1] = (uint16_t) + (pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0); + pExpnXPD->pcdac[2] = (uint16_t) + (pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0); + pExpnXPD->pcdac[3] = (uint16_t) + (pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0); + + pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0; + pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0; + pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0; + pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0; + + } else { + pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[0]].pcdac[0] = pCalCh->pcd1_xg0; + pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[0] = 20; + pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[1] = 35; + pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[2] = 63; + + jj = xgainList[0]; + pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj]; + pExpnXPD->numPcdacs = 4; + pExpnXPD->pcdac[1] = (uint16_t) + (pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0); + pExpnXPD->pcdac[2] = (uint16_t) + (pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0); + pExpnXPD->pcdac[3] = (uint16_t) + (pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0); + pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0; + pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0; + pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0; + pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0; + + jj = xgainList[1]; + pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj]; + pExpnXPD->numPcdacs = 3; + + pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg3; + pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg3; + pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg3; + } + } + return AH_TRUE; +} + +static HAL_BOOL +readEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee) +{ +#define EEREAD(_off) do { \ + if (!ath_hal_eepromRead(ah, _off, &eeval)) \ + return AH_FALSE; \ +} while (0) + const uint16_t dbmmask = 0xff; + const uint16_t pcdac_delta_mask = 0x1f; + const uint16_t pcdac_mask = 0x3f; + const uint16_t freqmask = 0xff; + + int i, mode, numPiers; + uint32_t off; + uint16_t eeval; + uint16_t freq[NUM_11A_EEPROM_CHANNELS]; + EEPROM_POWER_5112 eePower; + + HALASSERT(ee->ee_version >= AR_EEPROM_VER4_0); + off = GROUPS_OFFSET3_3; + for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { + numPiers = 0; + switch (mode) { + case headerInfo11A: + if (!ee->ee_Amode) /* no 11a calibration data */ + continue; + while (numPiers < NUM_11A_EEPROM_CHANNELS) { + EEREAD(off++); + if ((eeval & freqmask) == 0) + break; + freq[numPiers++] = fbin2freq(ee, + eeval & freqmask); + + if (((eeval >> 8) & freqmask) == 0) + break; + freq[numPiers++] = fbin2freq(ee, + (eeval>>8) & freqmask); + } + break; + case headerInfo11B: + if (!ee->ee_Bmode) /* no 11b calibration data */ + continue; + for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) + if (ee->ee_calPier11b[i] != CHANNEL_UNUSED) + freq[numPiers++] = ee->ee_calPier11b[i]; + break; + case headerInfo11G: + if (!ee->ee_Gmode) /* no 11g calibration data */ + continue; + for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) + if (ee->ee_calPier11g[i] != CHANNEL_UNUSED) + freq[numPiers++] = ee->ee_calPier11g[i]; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", + __func__, mode); + return AH_FALSE; + } + + OS_MEMZERO(&eePower, sizeof(eePower)); + eePower.numChannels = numPiers; + + for (i = 0; i < numPiers; i++) { + eePower.pChannels[i] = freq[i]; + eePower.pDataPerChannel[i].channelValue = freq[i]; + + EEREAD(off++); + eePower.pDataPerChannel[i].pwr1_xg0 = (int16_t) + ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); + eePower.pDataPerChannel[i].pwr2_xg0 = (int16_t) + (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256); + + EEREAD(off++); + eePower.pDataPerChannel[i].pwr3_xg0 = (int16_t) + ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); + eePower.pDataPerChannel[i].pwr4_xg0 = (int16_t) + (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256); + + EEREAD(off++); + eePower.pDataPerChannel[i].pcd2_delta_xg0 = (uint16_t) + (eeval & pcdac_delta_mask); + eePower.pDataPerChannel[i].pcd3_delta_xg0 = (uint16_t) + ((eeval >> 5) & pcdac_delta_mask); + eePower.pDataPerChannel[i].pcd4_delta_xg0 = (uint16_t) + ((eeval >> 10) & pcdac_delta_mask); + + EEREAD(off++); + eePower.pDataPerChannel[i].pwr1_xg3 = (int16_t) + ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); + eePower.pDataPerChannel[i].pwr2_xg3 = (int16_t) + (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256); + + EEREAD(off++); + eePower.pDataPerChannel[i].pwr3_xg3 = (int16_t) + ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); + if (ee->ee_version >= AR_EEPROM_VER4_3) { + eePower.pDataPerChannel[i].maxPower_t4 = + eePower.pDataPerChannel[i].pwr4_xg0; + eePower.pDataPerChannel[i].pcd1_xg0 = (uint16_t) + ((eeval >> 8) & pcdac_mask); + } else { + eePower.pDataPerChannel[i].maxPower_t4 = (int16_t) + (((eeval >> 8) & dbmmask) - + ((eeval >> 15) & 0x1)*256); + eePower.pDataPerChannel[i].pcd1_xg0 = 1; + } + } + eePower.xpdMask = ee->ee_xgain[mode]; + + if (!eepromAllocExpnPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: did not allocate power struct\n", __func__); + return AH_FALSE; + } + if (!eepromExpandPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: did not expand power struct\n", __func__); + return AH_FALSE; + } + } + return AH_TRUE; +#undef EEREAD +} + +static void +freeEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee) +{ + int mode; + void *data; + + for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { + EEPROM_POWER_EXPN_5112 *pPowerExpn = + &ee->ee_modePowerArray5112[mode]; + data = pPowerExpn->pChannels; + if (data != AH_NULL) { + pPowerExpn->pChannels = AH_NULL; + ath_hal_free(data); + } + } +} + +static void +ar2413SetupEEPROMDataset(EEPROM_DATA_STRUCT_2413 *pEEPROMDataset2413, + uint16_t myNumRawChannels, uint16_t *pMyRawChanList) +{ + uint16_t i, channelValue; + uint32_t xpd_mask; + uint16_t numPdGainsUsed; + + pEEPROMDataset2413->numChannels = myNumRawChannels; + + xpd_mask = pEEPROMDataset2413->xpd_mask; + numPdGainsUsed = 0; + if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++; + if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++; + if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++; + if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++; + + for (i = 0; i < myNumRawChannels; i++) { + channelValue = pMyRawChanList[i]; + pEEPROMDataset2413->pChannels[i] = channelValue; + pEEPROMDataset2413->pDataPerChannel[i].channelValue = channelValue; + pEEPROMDataset2413->pDataPerChannel[i].numPdGains = numPdGainsUsed; + } +} + +static HAL_BOOL +ar2413ReadCalDataset(struct ath_hal *ah, HAL_EEPROM *ee, + EEPROM_DATA_STRUCT_2413 *pCalDataset, + uint32_t start_offset, uint32_t maxPiers, uint8_t mode) +{ +#define EEREAD(_off) do { \ + if (!ath_hal_eepromRead(ah, _off, &eeval)) \ + return AH_FALSE; \ +} while (0) + const uint16_t dbm_I_mask = 0x1F; /* 5-bits. 1dB step. */ + const uint16_t dbm_delta_mask = 0xF; /* 4-bits. 0.5dB step. */ + const uint16_t Vpd_I_mask = 0x7F; /* 7-bits. 0-128 */ + const uint16_t Vpd_delta_mask = 0x3F; /* 6-bits. 0-63 */ + const uint16_t freqmask = 0xff; + + uint16_t ii, eeval; + uint16_t idx, numPiers; + uint16_t freq[NUM_11A_EEPROM_CHANNELS]; + + idx = start_offset; + for (numPiers = 0; numPiers < maxPiers;) { + EEREAD(idx++); + if ((eeval & freqmask) == 0) + break; + if (mode == headerInfo11A) + freq[numPiers++] = fbin2freq(ee, (eeval & freqmask)); + else + freq[numPiers++] = fbin2freq_2p4(ee, (eeval & freqmask)); + + if (((eeval >> 8) & freqmask) == 0) + break; + if (mode == headerInfo11A) + freq[numPiers++] = fbin2freq(ee, (eeval >> 8) & freqmask); + else + freq[numPiers++] = fbin2freq_2p4(ee, (eeval >> 8) & freqmask); + } + ar2413SetupEEPROMDataset(pCalDataset, numPiers, &freq[0]); + + idx = start_offset + (maxPiers / 2); + for (ii = 0; ii < pCalDataset->numChannels; ii++) { + EEPROM_DATA_PER_CHANNEL_2413 *currCh = + &(pCalDataset->pDataPerChannel[ii]); + + if (currCh->numPdGains > 0) { + /* + * Read the first NUM_POINTS_OTHER_PDGAINS pwr + * and Vpd values for pdgain_0 + */ + EEREAD(idx++); + currCh->pwr_I[0] = eeval & dbm_I_mask; + currCh->Vpd_I[0] = (eeval >> 5) & Vpd_I_mask; + currCh->pwr_delta_t2[0][0] = + (eeval >> 12) & dbm_delta_mask; + + EEREAD(idx++); + currCh->Vpd_delta[0][0] = eeval & Vpd_delta_mask; + currCh->pwr_delta_t2[1][0] = + (eeval >> 6) & dbm_delta_mask; + currCh->Vpd_delta[1][0] = + (eeval >> 10) & Vpd_delta_mask; + + EEREAD(idx++); + currCh->pwr_delta_t2[2][0] = eeval & dbm_delta_mask; + currCh->Vpd_delta[2][0] = (eeval >> 4) & Vpd_delta_mask; + } + + if (currCh->numPdGains > 1) { + /* + * Read the first NUM_POINTS_OTHER_PDGAINS pwr + * and Vpd values for pdgain_1 + */ + currCh->pwr_I[1] = (eeval >> 10) & dbm_I_mask; + currCh->Vpd_I[1] = (eeval >> 15) & 0x1; + + EEREAD(idx++); + /* upper 6 bits */ + currCh->Vpd_I[1] |= (eeval & 0x3F) << 1; + currCh->pwr_delta_t2[0][1] = + (eeval >> 6) & dbm_delta_mask; + currCh->Vpd_delta[0][1] = + (eeval >> 10) & Vpd_delta_mask; + + EEREAD(idx++); + currCh->pwr_delta_t2[1][1] = eeval & dbm_delta_mask; + currCh->Vpd_delta[1][1] = (eeval >> 4) & Vpd_delta_mask; + currCh->pwr_delta_t2[2][1] = + (eeval >> 10) & dbm_delta_mask; + currCh->Vpd_delta[2][1] = (eeval >> 14) & 0x3; + + EEREAD(idx++); + /* upper 4 bits */ + currCh->Vpd_delta[2][1] |= (eeval & 0xF) << 2; + } else if (currCh->numPdGains == 1) { + /* + * Read the last pwr and Vpd values for pdgain_0 + */ + currCh->pwr_delta_t2[3][0] = + (eeval >> 10) & dbm_delta_mask; + currCh->Vpd_delta[3][0] = (eeval >> 14) & 0x3; + + EEREAD(idx++); + /* upper 4 bits */ + currCh->Vpd_delta[3][0] |= (eeval & 0xF) << 2; + + /* 4 words if numPdGains == 1 */ + } + + if (currCh->numPdGains > 2) { + /* + * Read the first NUM_POINTS_OTHER_PDGAINS pwr + * and Vpd values for pdgain_2 + */ + currCh->pwr_I[2] = (eeval >> 4) & dbm_I_mask; + currCh->Vpd_I[2] = (eeval >> 9) & Vpd_I_mask; + + EEREAD(idx++); + currCh->pwr_delta_t2[0][2] = + (eeval >> 0) & dbm_delta_mask; + currCh->Vpd_delta[0][2] = (eeval >> 4) & Vpd_delta_mask; + currCh->pwr_delta_t2[1][2] = + (eeval >> 10) & dbm_delta_mask; + currCh->Vpd_delta[1][2] = (eeval >> 14) & 0x3; + + EEREAD(idx++); + /* upper 4 bits */ + currCh->Vpd_delta[1][2] |= (eeval & 0xF) << 2; + currCh->pwr_delta_t2[2][2] = + (eeval >> 4) & dbm_delta_mask; + currCh->Vpd_delta[2][2] = (eeval >> 8) & Vpd_delta_mask; + } else if (currCh->numPdGains == 2) { + /* + * Read the last pwr and Vpd values for pdgain_1 + */ + currCh->pwr_delta_t2[3][1] = + (eeval >> 4) & dbm_delta_mask; + currCh->Vpd_delta[3][1] = (eeval >> 8) & Vpd_delta_mask; + + /* 6 words if numPdGains == 2 */ + } + + if (currCh->numPdGains > 3) { + /* + * Read the first NUM_POINTS_OTHER_PDGAINS pwr + * and Vpd values for pdgain_3 + */ + currCh->pwr_I[3] = (eeval >> 14) & 0x3; + + EEREAD(idx++); + /* upper 3 bits */ + currCh->pwr_I[3] |= ((eeval >> 0) & 0x7) << 2; + currCh->Vpd_I[3] = (eeval >> 3) & Vpd_I_mask; + currCh->pwr_delta_t2[0][3] = + (eeval >> 10) & dbm_delta_mask; + currCh->Vpd_delta[0][3] = (eeval >> 14) & 0x3; + + EEREAD(idx++); + /* upper 4 bits */ + currCh->Vpd_delta[0][3] |= (eeval & 0xF) << 2; + currCh->pwr_delta_t2[1][3] = + (eeval >> 4) & dbm_delta_mask; + currCh->Vpd_delta[1][3] = (eeval >> 8) & Vpd_delta_mask; + currCh->pwr_delta_t2[2][3] = (eeval >> 14) & 0x3; + + EEREAD(idx++); + /* upper 2 bits */ + currCh->pwr_delta_t2[2][3] |= ((eeval >> 0) & 0x3) << 2; + currCh->Vpd_delta[2][3] = (eeval >> 2) & Vpd_delta_mask; + currCh->pwr_delta_t2[3][3] = + (eeval >> 8) & dbm_delta_mask; + currCh->Vpd_delta[3][3] = (eeval >> 12) & 0xF; + + EEREAD(idx++); + /* upper 2 bits */ + currCh->Vpd_delta[3][3] |= ((eeval >> 0) & 0x3) << 4; + + /* 12 words if numPdGains == 4 */ + } else if (currCh->numPdGains == 3) { + /* read the last pwr and Vpd values for pdgain_2 */ + currCh->pwr_delta_t2[3][2] = (eeval >> 14) & 0x3; + + EEREAD(idx++); + /* upper 2 bits */ + currCh->pwr_delta_t2[3][2] |= ((eeval >> 0) & 0x3) << 2; + currCh->Vpd_delta[3][2] = (eeval >> 2) & Vpd_delta_mask; + + /* 9 words if numPdGains == 3 */ + } + } + return AH_TRUE; +#undef EEREAD +} + +static void +ar2413SetupRawDataset(RAW_DATA_STRUCT_2413 *pRaw, EEPROM_DATA_STRUCT_2413 *pCal) +{ + uint16_t i, j, kk, channelValue; + uint16_t xpd_mask; + uint16_t numPdGainsUsed; + + pRaw->numChannels = pCal->numChannels; + + xpd_mask = pRaw->xpd_mask; + numPdGainsUsed = 0; + if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++; + if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++; + if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++; + if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++; + + for (i = 0; i < pCal->numChannels; i++) { + channelValue = pCal->pChannels[i]; + + pRaw->pChannels[i] = channelValue; + + pRaw->pDataPerChannel[i].channelValue = channelValue; + pRaw->pDataPerChannel[i].numPdGains = numPdGainsUsed; + + kk = 0; + for (j = 0; j < MAX_NUM_PDGAINS_PER_CHANNEL; j++) { + pRaw->pDataPerChannel[i].pDataPerPDGain[j].pd_gain = j; + if ((xpd_mask >> j) & 0x1) { + pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_OTHER_PDGAINS; + kk++; + if (kk == 1) { + /* + * lowest pd_gain corresponds + * to highest power and thus, + * has one more point + */ + pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_LAST_PDGAIN; + } + } else { + pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = 0; + } + } + } +} + +static HAL_BOOL +ar2413EepromToRawDataset(struct ath_hal *ah, + EEPROM_DATA_STRUCT_2413 *pCal, RAW_DATA_STRUCT_2413 *pRaw) +{ + uint16_t ii, jj, kk, ss; + RAW_DATA_PER_PDGAIN_2413 *pRawXPD; + /* ptr to array of info held per channel */ + EEPROM_DATA_PER_CHANNEL_2413 *pCalCh; + uint16_t xgain_list[MAX_NUM_PDGAINS_PER_CHANNEL]; + uint16_t xpd_mask; + uint32_t numPdGainsUsed; + + HALASSERT(pRaw->xpd_mask == pCal->xpd_mask); + + xgain_list[0] = 0xDEAD; + xgain_list[1] = 0xDEAD; + xgain_list[2] = 0xDEAD; + xgain_list[3] = 0xDEAD; + + numPdGainsUsed = 0; + xpd_mask = pRaw->xpd_mask; + for (jj = 0; jj < MAX_NUM_PDGAINS_PER_CHANNEL; jj++) { + if ((xpd_mask >> (MAX_NUM_PDGAINS_PER_CHANNEL-jj-1)) & 1) + xgain_list[numPdGainsUsed++] = MAX_NUM_PDGAINS_PER_CHANNEL-jj-1; + } + + pRaw->numChannels = pCal->numChannels; + for (ii = 0; ii < pRaw->numChannels; ii++) { + pCalCh = &(pCal->pDataPerChannel[ii]); + pRaw->pDataPerChannel[ii].channelValue = pCalCh->channelValue; + + /* numVpd has already been setup appropriately for the relevant pdGains */ + for (jj = 0; jj < numPdGainsUsed; jj++) { + /* use jj for calDataset and ss for rawDataset */ + ss = xgain_list[jj]; + pRawXPD = &(pRaw->pDataPerChannel[ii].pDataPerPDGain[ss]); + HALASSERT(pRawXPD->numVpd >= 1); + + pRawXPD->pwr_t4[0] = (uint16_t)(4*pCalCh->pwr_I[jj]); + pRawXPD->Vpd[0] = pCalCh->Vpd_I[jj]; + + for (kk = 1; kk < pRawXPD->numVpd; kk++) { + pRawXPD->pwr_t4[kk] = (int16_t)(pRawXPD->pwr_t4[kk-1] + 2*pCalCh->pwr_delta_t2[kk-1][jj]); + pRawXPD->Vpd[kk] = (uint16_t)(pRawXPD->Vpd[kk-1] + pCalCh->Vpd_delta[kk-1][jj]); + } + /* loop over Vpds */ + } + /* loop over pd_gains */ + } + /* loop over channels */ + return AH_TRUE; +} + +static HAL_BOOL +readEepromRawPowerCalInfo2413(struct ath_hal *ah, HAL_EEPROM *ee) +{ + /* NB: index is 1 less than numPdgains */ + static const uint16_t wordsForPdgains[] = { 4, 6, 9, 12 }; + EEPROM_DATA_STRUCT_2413 *pCal = AH_NULL; + RAW_DATA_STRUCT_2413 *pRaw; + int numEEPROMWordsPerChannel; + uint32_t off; + HAL_BOOL ret = AH_FALSE; + + HALASSERT(ee->ee_version >= AR_EEPROM_VER5_0); + HALASSERT(ee->ee_eepMap == 2); + + pCal = ath_hal_malloc(sizeof(EEPROM_DATA_STRUCT_2413)); + if (pCal == AH_NULL) + goto exit; + + off = ee->ee_eepMap2PowerCalStart; + if (ee->ee_Amode) { + OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413)); + pCal->xpd_mask = ee->ee_xgain[headerInfo11A]; + if (!ar2413ReadCalDataset(ah, ee, pCal, off, + NUM_11A_EEPROM_CHANNELS_2413, headerInfo11A)) { + goto exit; + } + pRaw = &ee->ee_rawDataset2413[headerInfo11A]; + pRaw->xpd_mask = ee->ee_xgain[headerInfo11A]; + ar2413SetupRawDataset(pRaw, pCal); + if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) { + goto exit; + } + /* setup offsets for mode_11a next */ + numEEPROMWordsPerChannel = wordsForPdgains[ + pCal->pDataPerChannel[0].numPdGains - 1]; + off += pCal->numChannels * numEEPROMWordsPerChannel + 5; + } + if (ee->ee_Bmode) { + OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413)); + pCal->xpd_mask = ee->ee_xgain[headerInfo11B]; + if (!ar2413ReadCalDataset(ah, ee, pCal, off, + NUM_2_4_EEPROM_CHANNELS_2413 , headerInfo11B)) { + goto exit; + } + pRaw = &ee->ee_rawDataset2413[headerInfo11B]; + pRaw->xpd_mask = ee->ee_xgain[headerInfo11B]; + ar2413SetupRawDataset(pRaw, pCal); + if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) { + goto exit; + } + /* setup offsets for mode_11g next */ + numEEPROMWordsPerChannel = wordsForPdgains[ + pCal->pDataPerChannel[0].numPdGains - 1]; + off += pCal->numChannels * numEEPROMWordsPerChannel + 2; + } + if (ee->ee_Gmode) { + OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413)); + pCal->xpd_mask = ee->ee_xgain[headerInfo11G]; + if (!ar2413ReadCalDataset(ah, ee, pCal, off, + NUM_2_4_EEPROM_CHANNELS_2413, headerInfo11G)) { + goto exit; + } + pRaw = &ee->ee_rawDataset2413[headerInfo11G]; + pRaw->xpd_mask = ee->ee_xgain[headerInfo11G]; + ar2413SetupRawDataset(pRaw, pCal); + if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) { + goto exit; + } + } + ret = AH_TRUE; + exit: + if (pCal != AH_NULL) + ath_hal_free(pCal); + return ret; +} + +/* + * Now copy EEPROM Raw Power Calibration per frequency contents + * into the allocated space + */ +static HAL_BOOL +readEepromRawPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee) +{ +#define EEREAD(_off) do { \ + if (!ath_hal_eepromRead(ah, _off, &eeval)) \ + return AH_FALSE; \ +} while (0) + uint16_t eeval, nchan; + uint32_t off; + int i, j, mode; + + if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1) + return readEepromRawPowerCalInfo5112(ah, ee); + if (ee->ee_version >= AR_EEPROM_VER5_0 && ee->ee_eepMap == 2) + return readEepromRawPowerCalInfo2413(ah, ee); + + /* + * Group 2: read raw power data for all frequency piers + * + * NOTE: Group 2 contains the raw power calibration + * information for each of the channels that + * we recorded above. + */ + for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { + uint16_t *pChannels = AH_NULL; + DATA_PER_CHANNEL *pChannelData = AH_NULL; + + off = ee->ee_version >= AR_EEPROM_VER3_3 ? + GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2; + switch (mode) { + case headerInfo11A: + off += GROUP2_OFFSET; + nchan = ee->ee_numChannels11a; + pChannelData = ee->ee_dataPerChannel11a; + pChannels = ee->ee_channels11a; + break; + case headerInfo11B: + if (!ee->ee_Bmode) + continue; + off += GROUP3_OFFSET; + nchan = ee->ee_numChannels2_4; + pChannelData = ee->ee_dataPerChannel11b; + pChannels = ee->ee_channels11b; + break; + case headerInfo11G: + if (!ee->ee_Gmode) + continue; + off += GROUP4_OFFSET; + nchan = ee->ee_numChannels2_4; + pChannelData = ee->ee_dataPerChannel11g; + pChannels = ee->ee_channels11g; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", + __func__, mode); + return AH_FALSE; + } + for (i = 0; i < nchan; i++) { + pChannelData->channelValue = pChannels[i]; + + EEREAD(off++); + pChannelData->pcdacMax = (uint16_t)((eeval >> 10) & PCDAC_MASK); + pChannelData->pcdacMin = (uint16_t)((eeval >> 4) & PCDAC_MASK); + pChannelData->PwrValues[0] = (uint16_t)((eeval << 2) & POWER_MASK); + + EEREAD(off++); + pChannelData->PwrValues[0] |= (uint16_t)((eeval >> 14) & 0x3); + pChannelData->PwrValues[1] = (uint16_t)((eeval >> 8) & POWER_MASK); + pChannelData->PwrValues[2] = (uint16_t)((eeval >> 2) & POWER_MASK); + pChannelData->PwrValues[3] = (uint16_t)((eeval << 4) & POWER_MASK); + + EEREAD(off++); + pChannelData->PwrValues[3] |= (uint16_t)((eeval >> 12) & 0xf); + pChannelData->PwrValues[4] = (uint16_t)((eeval >> 6) & POWER_MASK); + pChannelData->PwrValues[5] = (uint16_t)(eeval & POWER_MASK); + + EEREAD(off++); + pChannelData->PwrValues[6] = (uint16_t)((eeval >> 10) & POWER_MASK); + pChannelData->PwrValues[7] = (uint16_t)((eeval >> 4) & POWER_MASK); + pChannelData->PwrValues[8] = (uint16_t)((eeval << 2) & POWER_MASK); + + EEREAD(off++); + pChannelData->PwrValues[8] |= (uint16_t)((eeval >> 14) & 0x3); + pChannelData->PwrValues[9] = (uint16_t)((eeval >> 8) & POWER_MASK); + pChannelData->PwrValues[10] = (uint16_t)((eeval >> 2) & POWER_MASK); + + getPcdacInterceptsFromPcdacMinMax(ee, + pChannelData->pcdacMin, pChannelData->pcdacMax, + pChannelData->PcdacValues) ; + + for (j = 0; j < pChannelData->numPcdacValues; j++) { + pChannelData->PwrValues[j] = (uint16_t)( + PWR_STEP * pChannelData->PwrValues[j]); + /* Note these values are scaled up. */ + } + pChannelData++; + } + } + return AH_TRUE; +#undef EEREAD +} + +/* + * Copy EEPROM Target Power Calbration per rate contents + * into the allocated space + */ +static HAL_BOOL +readEepromTargetPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee) +{ +#define EEREAD(_off) do { \ + if (!ath_hal_eepromRead(ah, _off, &eeval)) \ + return AH_FALSE; \ +} while (0) + uint16_t eeval, enable24; + uint32_t off; + int i, mode, nchan; + + enable24 = ee->ee_Bmode || ee->ee_Gmode; + for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { + TRGT_POWER_INFO *pPowerInfo; + uint16_t *pNumTrgtChannels; + + off = ee->ee_version >= AR_EEPROM_VER4_0 ? + ee->ee_targetPowersStart - GROUP5_OFFSET : + ee->ee_version >= AR_EEPROM_VER3_3 ? + GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2; + switch (mode) { + case headerInfo11A: + off += GROUP5_OFFSET; + nchan = NUM_TEST_FREQUENCIES; + pPowerInfo = ee->ee_trgtPwr_11a; + pNumTrgtChannels = &ee->ee_numTargetPwr_11a; + break; + case headerInfo11B: + if (!enable24) + continue; + off += GROUP6_OFFSET; + nchan = 2; + pPowerInfo = ee->ee_trgtPwr_11b; + pNumTrgtChannels = &ee->ee_numTargetPwr_11b; + break; + case headerInfo11G: + if (!enable24) + continue; + off += GROUP7_OFFSET; + nchan = 3; + pPowerInfo = ee->ee_trgtPwr_11g; + pNumTrgtChannels = &ee->ee_numTargetPwr_11g; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", + __func__, mode); + return AH_FALSE; + } + *pNumTrgtChannels = 0; + for (i = 0; i < nchan; i++) { + EEREAD(off++); + if (ee->ee_version >= AR_EEPROM_VER3_3) { + pPowerInfo->testChannel = (eeval >> 8) & 0xff; + } else { + pPowerInfo->testChannel = (eeval >> 9) & 0x7f; + } + + if (pPowerInfo->testChannel != 0) { + /* get the channel value and read rest of info */ + if (mode == headerInfo11A) { + pPowerInfo->testChannel = fbin2freq(ee, pPowerInfo->testChannel); + } else { + pPowerInfo->testChannel = fbin2freq_2p4(ee, pPowerInfo->testChannel); + } + + if (ee->ee_version >= AR_EEPROM_VER3_3) { + pPowerInfo->twicePwr6_24 = (eeval >> 2) & POWER_MASK; + pPowerInfo->twicePwr36 = (eeval << 4) & POWER_MASK; + } else { + pPowerInfo->twicePwr6_24 = (eeval >> 3) & POWER_MASK; + pPowerInfo->twicePwr36 = (eeval << 3) & POWER_MASK; + } + + EEREAD(off++); + if (ee->ee_version >= AR_EEPROM_VER3_3) { + pPowerInfo->twicePwr36 |= (eeval >> 12) & 0xf; + pPowerInfo->twicePwr48 = (eeval >> 6) & POWER_MASK; + pPowerInfo->twicePwr54 = eeval & POWER_MASK; + } else { + pPowerInfo->twicePwr36 |= (eeval >> 13) & 0x7; + pPowerInfo->twicePwr48 = (eeval >> 7) & POWER_MASK; + pPowerInfo->twicePwr54 = (eeval >> 1) & POWER_MASK; + } + (*pNumTrgtChannels)++; + } + pPowerInfo++; + } + } + return AH_TRUE; +#undef EEREAD +} + +/* + * Now copy EEPROM Coformance Testing Limits contents + * into the allocated space + */ +static HAL_BOOL +readEepromCTLInfo(struct ath_hal *ah, HAL_EEPROM *ee) +{ +#define EEREAD(_off) do { \ + if (!ath_hal_eepromRead(ah, _off, &eeval)) \ + return AH_FALSE; \ +} while (0) + RD_EDGES_POWER *rep; + uint16_t eeval; + uint32_t off; + int i, j; + + rep = ee->ee_rdEdgesPower; + + off = GROUP8_OFFSET + + (ee->ee_version >= AR_EEPROM_VER4_0 ? + ee->ee_targetPowersStart - GROUP5_OFFSET : + ee->ee_version >= AR_EEPROM_VER3_3 ? + GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2); + for (i = 0; i < ee->ee_numCtls; i++) { + if (ee->ee_ctl[i] == 0) { + /* Move offset and edges */ + off += (ee->ee_version >= AR_EEPROM_VER3_3 ? 8 : 7); + rep += NUM_EDGES; + continue; + } + if (ee->ee_version >= AR_EEPROM_VER3_3) { + for (j = 0; j < NUM_EDGES; j += 2) { + EEREAD(off++); + rep[j].rdEdge = (eeval >> 8) & FREQ_MASK_3_3; + rep[j+1].rdEdge = eeval & FREQ_MASK_3_3; + } + for (j = 0; j < NUM_EDGES; j += 2) { + EEREAD(off++); + rep[j].twice_rdEdgePower = + (eeval >> 8) & POWER_MASK; + rep[j].flag = (eeval >> 14) & 1; + rep[j+1].twice_rdEdgePower = eeval & POWER_MASK; + rep[j+1].flag = (eeval >> 6) & 1; + } + } else { + EEREAD(off++); + rep[0].rdEdge = (eeval >> 9) & FREQ_MASK; + rep[1].rdEdge = (eeval >> 2) & FREQ_MASK; + rep[2].rdEdge = (eeval << 5) & FREQ_MASK; + + EEREAD(off++); + rep[2].rdEdge |= (eeval >> 11) & 0x1f; + rep[3].rdEdge = (eeval >> 4) & FREQ_MASK; + rep[4].rdEdge = (eeval << 3) & FREQ_MASK; + + EEREAD(off++); + rep[4].rdEdge |= (eeval >> 13) & 0x7; + rep[5].rdEdge = (eeval >> 6) & FREQ_MASK; + rep[6].rdEdge = (eeval << 1) & FREQ_MASK; + + EEREAD(off++); + rep[6].rdEdge |= (eeval >> 15) & 0x1; + rep[7].rdEdge = (eeval >> 8) & FREQ_MASK; + + rep[0].twice_rdEdgePower = (eeval >> 2) & POWER_MASK; + rep[1].twice_rdEdgePower = (eeval << 4) & POWER_MASK; + + EEREAD(off++); + rep[1].twice_rdEdgePower |= (eeval >> 12) & 0xf; + rep[2].twice_rdEdgePower = (eeval >> 6) & POWER_MASK; + rep[3].twice_rdEdgePower = eeval & POWER_MASK; + + EEREAD(off++); + rep[4].twice_rdEdgePower = (eeval >> 10) & POWER_MASK; + rep[5].twice_rdEdgePower = (eeval >> 4) & POWER_MASK; + rep[6].twice_rdEdgePower = (eeval << 2) & POWER_MASK; + + EEREAD(off++); + rep[6].twice_rdEdgePower |= (eeval >> 14) & 0x3; + rep[7].twice_rdEdgePower = (eeval >> 8) & POWER_MASK; + } + + for (j = 0; j < NUM_EDGES; j++ ) { + if (rep[j].rdEdge != 0 || rep[j].twice_rdEdgePower != 0) { + if ((ee->ee_ctl[i] & CTL_MODE_M) == CTL_11A || + (ee->ee_ctl[i] & CTL_MODE_M) == CTL_TURBO) { + rep[j].rdEdge = fbin2freq(ee, rep[j].rdEdge); + } else { + rep[j].rdEdge = fbin2freq_2p4(ee, rep[j].rdEdge); + } + } + } + rep += NUM_EDGES; + } + return AH_TRUE; +#undef EEREAD +} + +/* + * Read the individual header fields for a Rev 3 EEPROM + */ +static HAL_BOOL +readHeaderInfo(struct ath_hal *ah, HAL_EEPROM *ee) +{ +#define EEREAD(_off) do { \ + if (!ath_hal_eepromRead(ah, _off, &eeval)) \ + return AH_FALSE; \ +} while (0) + static const uint32_t headerOffset3_0[] = { + 0x00C2, /* 0 - Mode bits, device type, max turbo power */ + 0x00C4, /* 1 - 2.4 and 5 antenna gain */ + 0x00C5, /* 2 - Begin 11A modal section */ + 0x00D0, /* 3 - Begin 11B modal section */ + 0x00DA, /* 4 - Begin 11G modal section */ + 0x00E4 /* 5 - Begin CTL section */ + }; + static const uint32_t headerOffset3_3[] = { + 0x00C2, /* 0 - Mode bits, device type, max turbo power */ + 0x00C3, /* 1 - 2.4 and 5 antenna gain */ + 0x00D4, /* 2 - Begin 11A modal section */ + 0x00F2, /* 3 - Begin 11B modal section */ + 0x010D, /* 4 - Begin 11G modal section */ + 0x0128 /* 5 - Begin CTL section */ + }; + + static const uint32_t regCapOffsetPre4_0 = 0x00CF; + static const uint32_t regCapOffsetPost4_0 = 0x00CA; + + const uint32_t *header; + uint32_t off; + uint16_t eeval; + int i; + + /* initialize cckOfdmGainDelta for < 4.2 eeprom */ + ee->ee_cckOfdmGainDelta = CCK_OFDM_GAIN_DELTA; + ee->ee_scaledCh14FilterCckDelta = TENX_CH14_FILTER_CCK_DELTA_INIT; + + if (ee->ee_version >= AR_EEPROM_VER3_3) { + header = headerOffset3_3; + ee->ee_numCtls = NUM_CTLS_3_3; + } else { + header = headerOffset3_0; + ee->ee_numCtls = NUM_CTLS; + } + HALASSERT(ee->ee_numCtls <= NUM_CTLS_MAX); + + EEREAD(header[0]); + ee->ee_turbo5Disable = (eeval >> 15) & 0x01; + ee->ee_rfKill = (eeval >> 14) & 0x01; + ee->ee_deviceType = (eeval >> 11) & 0x07; + ee->ee_turbo2WMaxPower5 = (eeval >> 4) & 0x7F; + if (ee->ee_version >= AR_EEPROM_VER4_0) + ee->ee_turbo2Disable = (eeval >> 3) & 0x01; + else + ee->ee_turbo2Disable = 1; + ee->ee_Gmode = (eeval >> 2) & 0x01; + ee->ee_Bmode = (eeval >> 1) & 0x01; + ee->ee_Amode = (eeval & 0x01); + + off = header[1]; + EEREAD(off++); + ee->ee_antennaGainMax[0] = (int8_t)((eeval >> 8) & 0xFF); + ee->ee_antennaGainMax[1] = (int8_t)(eeval & 0xFF); + if (ee->ee_version >= AR_EEPROM_VER4_0) { + EEREAD(off++); + ee->ee_eepMap = (eeval>>14) & 0x3; + ee->ee_disableXr5 = (eeval>>13) & 0x1; + ee->ee_disableXr2 = (eeval>>12) & 0x1; + ee->ee_earStart = eeval & 0xfff; + + EEREAD(off++); + ee->ee_targetPowersStart = eeval & 0xfff; + ee->ee_exist32kHzCrystal = (eeval>>14) & 0x1; + + if (ee->ee_version >= AR_EEPROM_VER5_0) { + off += 2; + EEREAD(off); + ee->ee_eepMap2PowerCalStart = (eeval >> 4) & 0xfff; + /* Properly cal'ed 5.0 devices should be non-zero */ + } + } + + /* Read the moded sections of the EEPROM header in the order A, B, G */ + for (i = headerInfo11A; i <= headerInfo11G; i++) { + /* Set the offset via the index */ + off = header[2 + i]; + + EEREAD(off++); + ee->ee_switchSettling[i] = (eeval >> 8) & 0x7f; + ee->ee_txrxAtten[i] = (eeval >> 2) & 0x3f; + ee->ee_antennaControl[0][i] = (eeval << 4) & 0x3f; + + EEREAD(off++); + ee->ee_antennaControl[0][i] |= (eeval >> 12) & 0x0f; + ee->ee_antennaControl[1][i] = (eeval >> 6) & 0x3f; + ee->ee_antennaControl[2][i] = eeval & 0x3f; + + EEREAD(off++); + ee->ee_antennaControl[3][i] = (eeval >> 10) & 0x3f; + ee->ee_antennaControl[4][i] = (eeval >> 4) & 0x3f; + ee->ee_antennaControl[5][i] = (eeval << 2) & 0x3f; + + EEREAD(off++); + ee->ee_antennaControl[5][i] |= (eeval >> 14) & 0x03; + ee->ee_antennaControl[6][i] = (eeval >> 8) & 0x3f; + ee->ee_antennaControl[7][i] = (eeval >> 2) & 0x3f; + ee->ee_antennaControl[8][i] = (eeval << 4) & 0x3f; + + EEREAD(off++); + ee->ee_antennaControl[8][i] |= (eeval >> 12) & 0x0f; + ee->ee_antennaControl[9][i] = (eeval >> 6) & 0x3f; + ee->ee_antennaControl[10][i] = eeval & 0x3f; + + EEREAD(off++); + ee->ee_adcDesiredSize[i] = (int8_t)((eeval >> 8) & 0xff); + switch (i) { + case headerInfo11A: + ee->ee_ob4 = (eeval >> 5) & 0x07; + ee->ee_db4 = (eeval >> 2) & 0x07; + ee->ee_ob3 = (eeval << 1) & 0x07; + break; + case headerInfo11B: + ee->ee_obFor24 = (eeval >> 4) & 0x07; + ee->ee_dbFor24 = eeval & 0x07; + break; + case headerInfo11G: + ee->ee_obFor24g = (eeval >> 4) & 0x07; + ee->ee_dbFor24g = eeval & 0x07; + break; + } + + if (i == headerInfo11A) { + EEREAD(off++); + ee->ee_ob3 |= (eeval >> 15) & 0x01; + ee->ee_db3 = (eeval >> 12) & 0x07; + ee->ee_ob2 = (eeval >> 9) & 0x07; + ee->ee_db2 = (eeval >> 6) & 0x07; + ee->ee_ob1 = (eeval >> 3) & 0x07; + ee->ee_db1 = eeval & 0x07; + } + + EEREAD(off++); + ee->ee_txEndToXLNAOn[i] = (eeval >> 8) & 0xff; + ee->ee_thresh62[i] = eeval & 0xff; + + EEREAD(off++); + ee->ee_txEndToXPAOff[i] = (eeval >> 8) & 0xff; + ee->ee_txFrameToXPAOn[i] = eeval & 0xff; + + EEREAD(off++); + ee->ee_pgaDesiredSize[i] = (int8_t)((eeval >> 8) & 0xff); + ee->ee_noiseFloorThresh[i] = eeval & 0xff; + if (ee->ee_noiseFloorThresh[i] & 0x80) { + ee->ee_noiseFloorThresh[i] = 0 - + ((ee->ee_noiseFloorThresh[i] ^ 0xff) + 1); + } + + EEREAD(off++); + ee->ee_xlnaGain[i] = (eeval >> 5) & 0xff; + ee->ee_xgain[i] = (eeval >> 1) & 0x0f; + ee->ee_xpd[i] = eeval & 0x01; + if (ee->ee_version >= AR_EEPROM_VER4_0) { + switch (i) { + case headerInfo11A: + ee->ee_fixedBias5 = (eeval >> 13) & 0x1; + break; + case headerInfo11G: + ee->ee_fixedBias2 = (eeval >> 13) & 0x1; + break; + } + } + + if (ee->ee_version >= AR_EEPROM_VER3_3) { + EEREAD(off++); + ee->ee_falseDetectBackoff[i] = (eeval >> 6) & 0x7F; + switch (i) { + case headerInfo11B: + ee->ee_ob2GHz[0] = eeval & 0x7; + ee->ee_db2GHz[0] = (eeval >> 3) & 0x7; + break; + case headerInfo11G: + ee->ee_ob2GHz[1] = eeval & 0x7; + ee->ee_db2GHz[1] = (eeval >> 3) & 0x7; + break; + case headerInfo11A: + ee->ee_xrTargetPower5 = eeval & 0x3f; + break; + } + } + if (ee->ee_version >= AR_EEPROM_VER3_4) { + ee->ee_gainI[i] = (eeval >> 13) & 0x07; + + EEREAD(off++); + ee->ee_gainI[i] |= (eeval << 3) & 0x38; + if (i == headerInfo11G) { + ee->ee_cckOfdmPwrDelta = (eeval >> 3) & 0xFF; + if (ee->ee_version >= AR_EEPROM_VER4_6) + ee->ee_scaledCh14FilterCckDelta = + (eeval >> 11) & 0x1f; + } + if (i == headerInfo11A && + ee->ee_version >= AR_EEPROM_VER4_0) { + ee->ee_iqCalI[0] = (eeval >> 8 ) & 0x3f; + ee->ee_iqCalQ[0] = (eeval >> 3 ) & 0x1f; + } + } else { + ee->ee_gainI[i] = 10; + ee->ee_cckOfdmPwrDelta = TENX_OFDM_CCK_DELTA_INIT; + } + if (ee->ee_version >= AR_EEPROM_VER4_0) { + switch (i) { + case headerInfo11B: + EEREAD(off++); + ee->ee_calPier11b[0] = + fbin2freq_2p4(ee, eeval&0xff); + ee->ee_calPier11b[1] = + fbin2freq_2p4(ee, (eeval >> 8)&0xff); + EEREAD(off++); + ee->ee_calPier11b[2] = + fbin2freq_2p4(ee, eeval&0xff); + if (ee->ee_version >= AR_EEPROM_VER4_1) + ee->ee_rxtxMargin[headerInfo11B] = + (eeval >> 8) & 0x3f; + break; + case headerInfo11G: + EEREAD(off++); + ee->ee_calPier11g[0] = + fbin2freq_2p4(ee, eeval & 0xff); + ee->ee_calPier11g[1] = + fbin2freq_2p4(ee, (eeval >> 8) & 0xff); + + EEREAD(off++); + ee->ee_turbo2WMaxPower2 = eeval & 0x7F; + ee->ee_xrTargetPower2 = (eeval >> 7) & 0x3f; + + EEREAD(off++); + ee->ee_calPier11g[2] = + fbin2freq_2p4(ee, eeval & 0xff); + if (ee->ee_version >= AR_EEPROM_VER4_1) + ee->ee_rxtxMargin[headerInfo11G] = + (eeval >> 8) & 0x3f; + + EEREAD(off++); + ee->ee_iqCalI[1] = (eeval >> 5) & 0x3F; + ee->ee_iqCalQ[1] = eeval & 0x1F; + + if (ee->ee_version >= AR_EEPROM_VER4_2) { + EEREAD(off++); + ee->ee_cckOfdmGainDelta = + (uint8_t)(eeval & 0xFF); + if (ee->ee_version >= AR_EEPROM_VER5_0) { + ee->ee_switchSettlingTurbo[1] = + (eeval >> 8) & 0x7f; + ee->ee_txrxAttenTurbo[1] = + (eeval >> 15) & 0x1; + EEREAD(off++); + ee->ee_txrxAttenTurbo[1] |= + (eeval & 0x1F) << 1; + ee->ee_rxtxMarginTurbo[1] = + (eeval >> 5) & 0x3F; + ee->ee_adcDesiredSizeTurbo[1] = + (eeval >> 11) & 0x1F; + EEREAD(off++); + ee->ee_adcDesiredSizeTurbo[1] |= + (eeval & 0x7) << 5; + ee->ee_pgaDesiredSizeTurbo[1] = + (eeval >> 3) & 0xFF; + } + } + break; + case headerInfo11A: + if (ee->ee_version >= AR_EEPROM_VER4_1) { + EEREAD(off++); + ee->ee_rxtxMargin[headerInfo11A] = + eeval & 0x3f; + if (ee->ee_version >= AR_EEPROM_VER5_0) { + ee->ee_switchSettlingTurbo[0] = + (eeval >> 6) & 0x7f; + ee->ee_txrxAttenTurbo[0] = + (eeval >> 13) & 0x7; + EEREAD(off++); + ee->ee_txrxAttenTurbo[0] |= + (eeval & 0x7) << 3; + ee->ee_rxtxMarginTurbo[0] = + (eeval >> 3) & 0x3F; + ee->ee_adcDesiredSizeTurbo[0] = + (eeval >> 9) & 0x7F; + EEREAD(off++); + ee->ee_adcDesiredSizeTurbo[0] |= + (eeval & 0x1) << 7; + ee->ee_pgaDesiredSizeTurbo[0] = + (eeval >> 1) & 0xFF; + } + } + break; + } + } + } + if (ee->ee_version < AR_EEPROM_VER3_3) { + /* Version 3.1+ specific parameters */ + EEREAD(0xec); + ee->ee_ob2GHz[0] = eeval & 0x7; + ee->ee_db2GHz[0] = (eeval >> 3) & 0x7; + + EEREAD(0xed); + ee->ee_ob2GHz[1] = eeval & 0x7; + ee->ee_db2GHz[1] = (eeval >> 3) & 0x7; + } + + /* Initialize corner cal (thermal tx gain adjust parameters) */ + ee->ee_cornerCal.clip = 4; + ee->ee_cornerCal.pd90 = 1; + ee->ee_cornerCal.pd84 = 1; + ee->ee_cornerCal.gSel = 0; + + /* + * Read the conformance test limit identifiers + * These are used to match regulatory domain testing needs with + * the RD-specific tests that have been calibrated in the EEPROM. + */ + off = header[5]; + for (i = 0; i < ee->ee_numCtls; i += 2) { + EEREAD(off++); + ee->ee_ctl[i] = (eeval >> 8) & 0xff; + ee->ee_ctl[i+1] = eeval & 0xff; + } + + if (ee->ee_version < AR_EEPROM_VER5_3) { + /* XXX only for 5413? */ + ee->ee_spurChans[0][1] = AR_SPUR_5413_1; + ee->ee_spurChans[1][1] = AR_SPUR_5413_2; + ee->ee_spurChans[2][1] = AR_NO_SPUR; + ee->ee_spurChans[0][0] = AR_NO_SPUR; + } else { + /* Read spur mitigation data */ + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { + EEREAD(off); + ee->ee_spurChans[i][0] = eeval; + EEREAD(off+AR_EEPROM_MODAL_SPURS); + ee->ee_spurChans[i][1] = eeval; + off++; + } + } + + /* for recent changes to NF scale */ + if (ee->ee_version <= AR_EEPROM_VER3_2) { + ee->ee_noiseFloorThresh[headerInfo11A] = -54; + ee->ee_noiseFloorThresh[headerInfo11B] = -1; + ee->ee_noiseFloorThresh[headerInfo11G] = -1; + } + /* to override thresh62 for better 2.4 and 5 operation */ + if (ee->ee_version <= AR_EEPROM_VER3_2) { + ee->ee_thresh62[headerInfo11A] = 15; /* 11A */ + ee->ee_thresh62[headerInfo11B] = 28; /* 11B */ + ee->ee_thresh62[headerInfo11G] = 28; /* 11G */ + } + + /* Check for regulatory capabilities */ + if (ee->ee_version >= AR_EEPROM_VER4_0) { + EEREAD(regCapOffsetPost4_0); + } else { + EEREAD(regCapOffsetPre4_0); + } + + ee->ee_regCap = eeval; + + if (ee->ee_Amode == 0) { + /* Check for valid Amode in upgraded h/w */ + if (ee->ee_version >= AR_EEPROM_VER4_0) { + ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A)?1:0; + } else { + ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0)?1:0; + } + } + + if (ee->ee_version >= AR_EEPROM_VER5_1) + EEREAD(AR_EEPROM_CAPABILITIES_OFFSET); + else + eeval = 0; + ee->ee_opCap = eeval; + + EEREAD(AR_EEPROM_REG_DOMAIN); + ee->ee_regdomain = eeval; + + return AH_TRUE; +#undef EEREAD +} + +/* + * Now verify and copy EEPROM contents into the allocated space + */ +static HAL_BOOL +legacyEepromReadContents(struct ath_hal *ah, HAL_EEPROM *ee) +{ + /* Read the header information here */ + if (!readHeaderInfo(ah, ee)) + return AH_FALSE; +#if 0 + /* Require 5112 devices to have EEPROM 4.0 EEP_MAP set */ + if (IS_5112(ah) && !ee->ee_eepMap) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5112 devices must have EEPROM 4.0 with the " + "EEP_MAP set\n", __func__); + return AH_FALSE; + } +#endif + /* + * Group 1: frequency pier locations readback + * check that the structure has been populated + * with enough space to hold the channels + * + * NOTE: Group 1 contains the 5 GHz channel numbers + * that have dBm->pcdac calibrated information. + */ + if (!readEepromFreqPierInfo(ah, ee)) + return AH_FALSE; + + /* + * Group 2: readback data for all frequency piers + * + * NOTE: Group 2 contains the raw power calibration + * information for each of the channels that we + * recorded above. + */ + if (!readEepromRawPowerCalInfo(ah, ee)) + return AH_FALSE; + + /* + * Group 5: target power values per rate + * + * NOTE: Group 5 contains the recorded maximum power + * in dB that can be attained for the given rate. + */ + /* Read the power per rate info for test channels */ + if (!readEepromTargetPowerCalInfo(ah, ee)) + return AH_FALSE; + + /* + * Group 8: Conformance Test Limits information + * + * NOTE: Group 8 contains the values to limit the + * maximum transmit power value based on any + * band edge violations. + */ + /* Read the RD edge power limits */ + return readEepromCTLInfo(ah, ee); +} + +static HAL_STATUS +legacyEepromGet(struct ath_hal *ah, int param, void *val) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint8_t *macaddr; + uint16_t eeval; + uint32_t sum; + int i; + + switch (param) { + case AR_EEP_OPCAP: + *(uint16_t *) val = ee->ee_opCap; + return HAL_OK; + case AR_EEP_REGDMN_0: + *(uint16_t *) val = ee->ee_regdomain; + return HAL_OK; + case AR_EEP_RFSILENT: + if (!ath_hal_eepromRead(ah, AR_EEPROM_RFSILENT, &eeval)) + return HAL_EEREAD; + *(uint16_t *) val = eeval; + return HAL_OK; + case AR_EEP_MACADDR: + sum = 0; + macaddr = val; + for (i = 0; i < 3; i++) { + if (!ath_hal_eepromRead(ah, AR_EEPROM_MAC(2-i), &eeval)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read EEPROM location %u\n", + __func__, i); + return HAL_EEREAD; + } + sum += eeval; + macaddr[2*i] = eeval >> 8; + macaddr[2*i + 1] = eeval & 0xff; + } + if (sum == 0 || sum == 0xffff*3) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: mac address read failed: %s\n", __func__, + ath_hal_ether_sprintf(macaddr)); + return HAL_EEBADMAC; + } + return HAL_OK; + case AR_EEP_RFKILL: + HALASSERT(val == AH_NULL); + return ee->ee_rfKill ? HAL_OK : HAL_EIO; + case AR_EEP_AMODE: + HALASSERT(val == AH_NULL); + return ee->ee_Amode ? HAL_OK : HAL_EIO; + case AR_EEP_BMODE: + HALASSERT(val == AH_NULL); + return ee->ee_Bmode ? HAL_OK : HAL_EIO; + case AR_EEP_GMODE: + HALASSERT(val == AH_NULL); + return ee->ee_Gmode ? HAL_OK : HAL_EIO; + case AR_EEP_TURBO5DISABLE: + HALASSERT(val == AH_NULL); + return ee->ee_turbo5Disable ? HAL_OK : HAL_EIO; + case AR_EEP_TURBO2DISABLE: + HALASSERT(val == AH_NULL); + return ee->ee_turbo2Disable ? HAL_OK : HAL_EIO; + case AR_EEP_ISTALON: /* Talon detect */ + HALASSERT(val == AH_NULL); + return (ee->ee_version >= AR_EEPROM_VER5_4 && + ath_hal_eepromRead(ah, 0x0b, &eeval) && eeval == 1) ? + HAL_OK : HAL_EIO; + case AR_EEP_32KHZCRYSTAL: + HALASSERT(val == AH_NULL); + return ee->ee_exist32kHzCrystal ? HAL_OK : HAL_EIO; + case AR_EEP_COMPRESS: + HALASSERT(val == AH_NULL); + return (ee->ee_opCap & AR_EEPROM_EEPCAP_COMPRESS_DIS) == 0 ? + HAL_OK : HAL_EIO; + case AR_EEP_FASTFRAME: + HALASSERT(val == AH_NULL); + return (ee->ee_opCap & AR_EEPROM_EEPCAP_FASTFRAME_DIS) == 0 ? + HAL_OK : HAL_EIO; + case AR_EEP_AES: + HALASSERT(val == AH_NULL); + return (ee->ee_opCap & AR_EEPROM_EEPCAP_AES_DIS) == 0 ? + HAL_OK : HAL_EIO; + case AR_EEP_BURST: + HALASSERT(val == AH_NULL); + return (ee->ee_opCap & AR_EEPROM_EEPCAP_BURST_DIS) == 0 ? + HAL_OK : HAL_EIO; + case AR_EEP_MAXQCU: + if (ee->ee_opCap & AR_EEPROM_EEPCAP_MAXQCU) { + *(uint16_t *) val = + MS(ee->ee_opCap, AR_EEPROM_EEPCAP_MAXQCU); + return HAL_OK; + } else + return HAL_EIO; + case AR_EEP_KCENTRIES: + if (ee->ee_opCap & AR_EEPROM_EEPCAP_KC_ENTRIES) { + *(uint16_t *) val = + 1 << MS(ee->ee_opCap, AR_EEPROM_EEPCAP_KC_ENTRIES); + return HAL_OK; + } else + return HAL_EIO; + case AR_EEP_ANTGAINMAX_5: + *(int8_t *) val = ee->ee_antennaGainMax[0]; + return HAL_OK; + case AR_EEP_ANTGAINMAX_2: + *(int8_t *) val = ee->ee_antennaGainMax[1]; + return HAL_OK; + case AR_EEP_WRITEPROTECT: + HALASSERT(val == AH_NULL); + return (ee->ee_protect & AR_EEPROM_PROTECT_WP_128_191) ? + HAL_OK : HAL_EIO; + } + return HAL_EINVAL; +} + +static HAL_BOOL +legacyEepromSet(struct ath_hal *ah, int param, int v) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (param) { + case AR_EEP_AMODE: + ee->ee_Amode = v; + return HAL_OK; + case AR_EEP_BMODE: + ee->ee_Bmode = v; + return HAL_OK; + case AR_EEP_GMODE: + ee->ee_Gmode = v; + return HAL_OK; + case AR_EEP_TURBO5DISABLE: + ee->ee_turbo5Disable = v; + return HAL_OK; + case AR_EEP_TURBO2DISABLE: + ee->ee_turbo2Disable = v; + return HAL_OK; + case AR_EEP_COMPRESS: + if (v) + ee->ee_opCap &= ~AR_EEPROM_EEPCAP_COMPRESS_DIS; + else + ee->ee_opCap |= AR_EEPROM_EEPCAP_COMPRESS_DIS; + return HAL_OK; + case AR_EEP_FASTFRAME: + if (v) + ee->ee_opCap &= ~AR_EEPROM_EEPCAP_FASTFRAME_DIS; + else + ee->ee_opCap |= AR_EEPROM_EEPCAP_FASTFRAME_DIS; + return HAL_OK; + case AR_EEP_AES: + if (v) + ee->ee_opCap &= ~AR_EEPROM_EEPCAP_AES_DIS; + else + ee->ee_opCap |= AR_EEPROM_EEPCAP_AES_DIS; + return HAL_OK; + case AR_EEP_BURST: + if (v) + ee->ee_opCap &= ~AR_EEPROM_EEPCAP_BURST_DIS; + else + ee->ee_opCap |= AR_EEPROM_EEPCAP_BURST_DIS; + return HAL_OK; + } + return HAL_EINVAL; +} + +static HAL_BOOL +legacyEepromDiag(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, void **result, uint32_t *resultsize) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const EEPROM_POWER_EXPN_5112 *pe; + + switch (request) { + case HAL_DIAG_EEPROM: + *result = ee; + *resultsize = sizeof(*ee); + return AH_TRUE; + case HAL_DIAG_EEPROM_EXP_11A: + case HAL_DIAG_EEPROM_EXP_11B: + case HAL_DIAG_EEPROM_EXP_11G: + pe = &ee->ee_modePowerArray5112[ + request - HAL_DIAG_EEPROM_EXP_11A]; + *result = pe->pChannels; + *resultsize = (*result == AH_NULL) ? 0 : + roundup(sizeof(uint16_t) * pe->numChannels, + sizeof(uint32_t)) + + sizeof(EXPN_DATA_PER_CHANNEL_5112) * pe->numChannels; + return AH_TRUE; + } + return AH_FALSE; +} + +static uint16_t +legacyEepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + + HALASSERT(0 <= ix && ix < AR_EEPROM_MODAL_SPURS); + return ee->ee_spurChans[ix][is2GHz]; +} + +/* + * Reclaim any EEPROM-related storage. + */ +static void +legacyEepromDetach(struct ath_hal *ah) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + + if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1) + return freeEepromRawPowerCalInfo5112(ah, ee); + ath_hal_free(ee); + AH_PRIVATE(ah)->ah_eeprom = AH_NULL; +} + +/* + * These are not valid 2.4 channels, either we change 'em + * or we need to change the coding to accept them. + */ +static const uint16_t channels11b[] = { 2412, 2447, 2484 }; +static const uint16_t channels11g[] = { 2312, 2412, 2484 }; + +HAL_STATUS +ath_hal_legacyEepromAttach(struct ath_hal *ah) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint32_t sum, eepMax; + uint16_t eeversion, eeprotect, eeval; + u_int i; + + HALASSERT(ee == AH_NULL); + + if (!ath_hal_eepromRead(ah, AR_EEPROM_VERSION, &eeversion)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unable to read EEPROM version\n", __func__); + return HAL_EEREAD; + } + if (eeversion < AR_EEPROM_VER3) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM version " + "%u (0x%x) found\n", __func__, eeversion, eeversion); + return HAL_EEVERSION; + } + + if (!ath_hal_eepromRead(ah, AR_EEPROM_PROTECT, &eeprotect)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cannot read EEPROM protection " + "bits; read locked?\n", __func__); + return HAL_EEREAD; + } + HALDEBUG(ah, HAL_DEBUG_ATTACH, "EEPROM protect 0x%x\n", eeprotect); + /* XXX check proper access before continuing */ + + /* + * Read the Atheros EEPROM entries and calculate the checksum. + */ + if (!ath_hal_eepromRead(ah, AR_EEPROM_SIZE_UPPER, &eeval)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read EEPROM upper size\n" , __func__); + return HAL_EEREAD; + } + if (eeval != 0) { + eepMax = (eeval & AR_EEPROM_SIZE_UPPER_MASK) << + AR_EEPROM_SIZE_ENDLOC_SHIFT; + if (!ath_hal_eepromRead(ah, AR_EEPROM_SIZE_LOWER, &eeval)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read EEPROM lower size\n" , __func__); + return HAL_EEREAD; + } + eepMax = (eepMax | eeval) - AR_EEPROM_ATHEROS_BASE; + } else + eepMax = AR_EEPROM_ATHEROS_MAX; + sum = 0; + for (i = 0; i < eepMax; i++) { + if (!ath_hal_eepromRead(ah, AR_EEPROM_ATHEROS(i), &eeval)) { + return HAL_EEREAD; + } + sum ^= eeval; + } + if (sum != 0xffff) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad EEPROM checksum 0x%x\n", + __func__, sum); + return HAL_EEBADSUM; + } + + ee = ath_hal_malloc(sizeof(HAL_EEPROM)); + if (ee == AH_NULL) { + /* XXX message */ + return HAL_ENOMEM; + } + + ee->ee_protect = eeprotect; + ee->ee_version = eeversion; + + ee->ee_numChannels11a = NUM_11A_EEPROM_CHANNELS; + ee->ee_numChannels2_4 = NUM_2_4_EEPROM_CHANNELS; + + for (i = 0; i < NUM_11A_EEPROM_CHANNELS; i ++) + ee->ee_dataPerChannel11a[i].numPcdacValues = NUM_PCDAC_VALUES; + + /* the channel list for 2.4 is fixed, fill this in here */ + for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) { + ee->ee_channels11b[i] = channels11b[i]; + /* XXX 5211 requires a hack though we don't support 11g */ + if (ah->ah_magic == 0x19570405) + ee->ee_channels11g[i] = channels11b[i]; + else + ee->ee_channels11g[i] = channels11g[i]; + ee->ee_dataPerChannel11b[i].numPcdacValues = NUM_PCDAC_VALUES; + ee->ee_dataPerChannel11g[i].numPcdacValues = NUM_PCDAC_VALUES; + } + + if (!legacyEepromReadContents(ah, ee)) { + /* XXX message */ + ath_hal_free(ee); + return HAL_EEREAD; /* XXX */ + } + + AH_PRIVATE(ah)->ah_eeprom = ee; + AH_PRIVATE(ah)->ah_eeversion = eeversion; + AH_PRIVATE(ah)->ah_eepromDetach = legacyEepromDetach; + AH_PRIVATE(ah)->ah_eepromGet = legacyEepromGet; + AH_PRIVATE(ah)->ah_eepromSet = legacyEepromSet; + AH_PRIVATE(ah)->ah_getSpurChan = legacyEepromGetSpurChan; + AH_PRIVATE(ah)->ah_eepromDiag = legacyEepromDiag; + return HAL_OK; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v3.h b/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v3.h new file mode 100644 index 0000000000..9f30c72509 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ah_eeprom_v3.h @@ -0,0 +1,462 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ah_eeprom_v3.h,v 1.2 2008/11/10 04:08:00 sam Exp $ + */ +#ifndef _ATH_AH_EEPROM_V3_H_ +#define _ATH_AH_EEPROM_V3_H_ + +#include "ah_eeprom.h" + +/* EEPROM defines for Version 2 & 3 AR5211 chips */ +#define AR_EEPROM_RFSILENT 0x0f /* RF Silent/Clock Run Enable */ +#define AR_EEPROM_MAC(i) (0x1d+(i)) /* MAC address word */ +#define AR_EEPROM_MAGIC 0x3d /* magic number */ +#define AR_EEPROM_PROTECT 0x3f /* EEPROM protect bits */ +#define AR_EEPROM_PROTECT_PCIE 0x01 /* EEPROM protect bits for Condor/Swan*/ +#define AR_EEPROM_REG_DOMAIN 0xbf /* current regulatory domain */ +#define AR_EEPROM_ATHEROS_BASE 0xc0 /* Base of Atheros-specific data */ +#define AR_EEPROM_ATHEROS(i) (AR_EEPROM_ATHEROS_BASE+(i)) +#define AR_EEPROM_ATHEROS_MAX (0x400-AR_EEPROM_ATHEROS_BASE) +#define AR_EEPROM_VERSION AR_EEPROM_ATHEROS(1) + +/* FLASH(EEPROM) Defines for AR531X chips */ +#define AR_EEPROM_SIZE_LOWER 0x1b /* size info -- lower */ +#define AR_EEPROM_SIZE_UPPER 0x1c /* size info -- upper */ +#define AR_EEPROM_SIZE_UPPER_MASK 0xfff0 +#define AR_EEPROM_SIZE_UPPER_SHIFT 4 +#define AR_EEPROM_SIZE_ENDLOC_SHIFT 12 +#define AR_EEPROM_ATHEROS_MAX_LOC 0x400 +#define AR_EEPROM_ATHEROS_MAX_OFF (AR_EEPROM_ATHEROS_MAX_LOC-AR_EEPROM_ATHEROS_BASE) + +/* regulatory capabilities offsets */ +#define AR_EEPROM_REG_CAPABILITIES_OFFSET 0xCA +#define AR_EEPROM_REG_CAPABILITIES_OFFSET_PRE4_0 0xCF /* prior to 4.0 */ + +/* regulatory capabilities */ +#define AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND 0x0040 +#define AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN 0x0080 +#define AR_EEPROM_EEREGCAP_EN_KK_U2 0x0100 +#define AR_EEPROM_EEREGCAP_EN_KK_MIDBAND 0x0200 +#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD 0x0400 +#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A 0x0800 + +/* regulatory capabilities prior to eeprom version 4.0 */ +#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD_PRE4_0 0x4000 +#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0 0x8000 + +/* + * AR2413 (includes AR5413) + */ +#define AR_EEPROM_SERIAL_NUM_OFFSET 0xB0 /* EEPROM serial number */ +#define AR_EEPROM_SERIAL_NUM_SIZE 12 /* EEPROM serial number size */ +#define AR_EEPROM_CAPABILITIES_OFFSET 0xC9 /* EEPROM Location of capabilities */ + +#define AR_EEPROM_EEPCAP_COMPRESS_DIS 0x0001 +#define AR_EEPROM_EEPCAP_AES_DIS 0x0002 +#define AR_EEPROM_EEPCAP_FASTFRAME_DIS 0x0004 +#define AR_EEPROM_EEPCAP_BURST_DIS 0x0008 +#define AR_EEPROM_EEPCAP_MAXQCU 0x01F0 +#define AR_EEPROM_EEPCAP_MAXQCU_S 4 +#define AR_EEPROM_EEPCAP_HEAVY_CLIP_EN 0x0200 +#define AR_EEPROM_EEPCAP_KC_ENTRIES 0xF000 +#define AR_EEPROM_EEPCAP_KC_ENTRIES_S 12 + +/* XXX used to index various EEPROM-derived data structures */ +enum { + headerInfo11A = 0, + headerInfo11B = 1, + headerInfo11G = 2, +}; + +#define GROUPS_OFFSET3_2 0x100 /* groups offset for ver3.2 and earlier */ +#define GROUPS_OFFSET3_3 0x150 /* groups offset for ver3.3 */ +/* relative offset of GROUPi to GROUPS_OFFSET */ +#define GROUP1_OFFSET 0x0 +#define GROUP2_OFFSET 0x5 +#define GROUP3_OFFSET 0x37 +#define GROUP4_OFFSET 0x46 +#define GROUP5_OFFSET 0x55 +#define GROUP6_OFFSET 0x65 +#define GROUP7_OFFSET 0x69 +#define GROUP8_OFFSET 0x6f + +/* RF silent fields in EEPROM */ +#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c +#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 +#define AR_EEPROM_RFSILENT_POLARITY 0x0002 +#define AR_EEPROM_RFSILENT_POLARITY_S 1 + +/* Protect Bits RP is read protect, WP is write protect */ +#define AR_EEPROM_PROTECT_RP_0_31 0x0001 +#define AR_EEPROM_PROTECT_WP_0_31 0x0002 +#define AR_EEPROM_PROTECT_RP_32_63 0x0004 +#define AR_EEPROM_PROTECT_WP_32_63 0x0008 +#define AR_EEPROM_PROTECT_RP_64_127 0x0010 +#define AR_EEPROM_PROTECT_WP_64_127 0x0020 +#define AR_EEPROM_PROTECT_RP_128_191 0x0040 +#define AR_EEPROM_PROTECT_WP_128_191 0x0080 +#define AR_EEPROM_PROTECT_RP_192_207 0x0100 +#define AR_EEPROM_PROTECT_WP_192_207 0x0200 +#define AR_EEPROM_PROTECT_RP_208_223 0x0400 +#define AR_EEPROM_PROTECT_WP_208_223 0x0800 +#define AR_EEPROM_PROTECT_RP_224_239 0x1000 +#define AR_EEPROM_PROTECT_WP_224_239 0x2000 +#define AR_EEPROM_PROTECT_RP_240_255 0x4000 +#define AR_EEPROM_PROTECT_WP_240_255 0x8000 + +#define AR_EEPROM_MODAL_SPURS 5 +#define AR_SPUR_5413_1 1640 /* Freq 2464 */ +#define AR_SPUR_5413_2 1200 /* Freq 2420 */ + +/* + * EEPROM fixed point conversion scale factors. + * NB: if you change one be sure to keep the other in sync. + */ +#define EEP_SCALE 100 /* conversion scale to avoid fp arith */ +#define EEP_DELTA 10 /* SCALE/10, to avoid arith divide */ + +#define PWR_MIN 0 +#define PWR_MAX 3150 /* 31.5 * SCALE */ +#define PWR_STEP 50 /* 0.5 * SCALE */ +/* Keep 2 above defines together */ + +#define NUM_11A_EEPROM_CHANNELS 10 +#define NUM_2_4_EEPROM_CHANNELS 3 +#define NUM_PCDAC_VALUES 11 +#define NUM_TEST_FREQUENCIES 8 +#define NUM_EDGES 8 +#define NUM_INTERCEPTS 11 +#define FREQ_MASK 0x7f +#define FREQ_MASK_3_3 0xff /* expanded in version 3.3 */ +#define PCDAC_MASK 0x3f +#define POWER_MASK 0x3f +#define NON_EDGE_FLAG_MASK 0x40 +#define CHANNEL_POWER_INFO 8 +#define OBDB_UNSET 0xffff +#define CHANNEL_UNUSED 0xff +#define SCALE_OC_DELTA(_x) (((_x) * 2) / 10) + +/* Used during pcdac table construction */ +#define PCDAC_START 1 +#define PCDAC_STOP 63 +#define PCDAC_STEP 1 +#define PWR_TABLE_SIZE 64 +#define MAX_RATE_POWER 63 + +/* Used during power/rate table construction */ +#define NUM_CTLS 16 +#define NUM_CTLS_3_3 32 /* expanded in version 3.3 */ +#define NUM_CTLS_MAX NUM_CTLS_3_3 + +typedef struct fullPcdacStruct { + uint16_t channelValue; + uint16_t pcdacMin; + uint16_t pcdacMax; + uint16_t numPcdacValues; + uint16_t PcdacValues[64]; + /* power is 32bit since in dest it is scaled */ + int16_t PwrValues[64]; +} FULL_PCDAC_STRUCT; + +typedef struct dataPerChannel { + uint16_t channelValue; + uint16_t pcdacMin; + uint16_t pcdacMax; + uint16_t numPcdacValues; + uint16_t PcdacValues[NUM_PCDAC_VALUES]; + /* NB: power is 32bit since in dest it is scaled */ + int16_t PwrValues[NUM_PCDAC_VALUES]; +} DATA_PER_CHANNEL; + +/* points to the appropriate pcdac structs in the above struct based on mode */ +typedef struct pcdacsEeprom { + const uint16_t *pChannelList; + uint16_t numChannels; + const DATA_PER_CHANNEL *pDataPerChannel; +} PCDACS_EEPROM; + +typedef struct trgtPowerInfo { + uint16_t twicePwr54; + uint16_t twicePwr48; + uint16_t twicePwr36; + uint16_t twicePwr6_24; + uint16_t testChannel; +} TRGT_POWER_INFO; + +typedef struct trgtPowerAllModes { + uint16_t numTargetPwr_11a; + TRGT_POWER_INFO trgtPwr_11a[NUM_TEST_FREQUENCIES]; + uint16_t numTargetPwr_11g; + TRGT_POWER_INFO trgtPwr_11g[3]; + uint16_t numTargetPwr_11b; + TRGT_POWER_INFO trgtPwr_11b[2]; +} TRGT_POWER_ALL_MODES; + +typedef struct cornerCalInfo { + uint16_t gSel; + uint16_t pd84; + uint16_t pd90; + uint16_t clip; +} CORNER_CAL_INFO; + +/* + * EEPROM version 4 definitions + */ +#define NUM_XPD_PER_CHANNEL 4 +#define NUM_POINTS_XPD0 4 +#define NUM_POINTS_XPD3 3 +#define IDEAL_10dB_INTERCEPT_2G 35 +#define IDEAL_10dB_INTERCEPT_5G 55 + +#define TENX_OFDM_CCK_DELTA_INIT 15 /* power 1.5 dbm */ +#define TENX_CH14_FILTER_CCK_DELTA_INIT 15 /* power 1.5 dbm */ +#define CCK_OFDM_GAIN_DELTA 15 + +#define NUM_TARGET_POWER_LOCATIONS_11B 4 +#define NUM_TARGET_POWER_LOCATIONS_11G 6 + + +typedef struct { + uint16_t xpd_gain; + uint16_t numPcdacs; + uint16_t pcdac[NUM_POINTS_XPD0]; + int16_t pwr_t4[NUM_POINTS_XPD0]; /* or gainF */ +} EXPN_DATA_PER_XPD_5112; + +typedef struct { + uint16_t channelValue; + int16_t maxPower_t4; + EXPN_DATA_PER_XPD_5112 pDataPerXPD[NUM_XPD_PER_CHANNEL]; +} EXPN_DATA_PER_CHANNEL_5112; + +typedef struct { + uint16_t *pChannels; + uint16_t numChannels; + uint16_t xpdMask; /* mask of permitted xpd_gains */ + EXPN_DATA_PER_CHANNEL_5112 *pDataPerChannel; +} EEPROM_POWER_EXPN_5112; + +typedef struct { + uint16_t channelValue; + uint16_t pcd1_xg0; + int16_t pwr1_xg0; + uint16_t pcd2_delta_xg0; + int16_t pwr2_xg0; + uint16_t pcd3_delta_xg0; + int16_t pwr3_xg0; + uint16_t pcd4_delta_xg0; + int16_t pwr4_xg0; + int16_t maxPower_t4; + int16_t pwr1_xg3; /* pcdac = 20 */ + int16_t pwr2_xg3; /* pcdac = 35 */ + int16_t pwr3_xg3; /* pcdac = 63 */ + /* XXX - Should be pwr1_xg2, etc to agree with documentation */ +} EEPROM_DATA_PER_CHANNEL_5112; + +typedef struct { + uint16_t pChannels[NUM_11A_EEPROM_CHANNELS]; + uint16_t numChannels; + uint16_t xpdMask; /* mask of permitted xpd_gains */ + EEPROM_DATA_PER_CHANNEL_5112 pDataPerChannel[NUM_11A_EEPROM_CHANNELS]; +} EEPROM_POWER_5112; + +/* + * EEPROM version 5 definitions (Griffin, et. al.). + */ +#define NUM_2_4_EEPROM_CHANNELS_2413 4 +#define NUM_11A_EEPROM_CHANNELS_2413 10 +#define PWR_TABLE_SIZE_2413 128 + +/* Used during pdadc construction */ +#define MAX_NUM_PDGAINS_PER_CHANNEL 4 +#define NUM_PDGAINS_PER_CHANNEL 2 +#define NUM_POINTS_LAST_PDGAIN 5 +#define NUM_POINTS_OTHER_PDGAINS 4 +#define XPD_GAIN1_GEN5 3 +#define XPD_GAIN2_GEN5 1 +#define MAX_PWR_RANGE_IN_HALF_DB 64 +#define PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB 4 + +typedef struct { + uint16_t pd_gain; + uint16_t numVpd; + uint16_t Vpd[NUM_POINTS_LAST_PDGAIN]; + int16_t pwr_t4[NUM_POINTS_LAST_PDGAIN]; /* or gainF */ +} RAW_DATA_PER_PDGAIN_2413; + +typedef struct { + uint16_t channelValue; + int16_t maxPower_t4; + uint16_t numPdGains; /* # Pd Gains per channel */ + RAW_DATA_PER_PDGAIN_2413 pDataPerPDGain[MAX_NUM_PDGAINS_PER_CHANNEL]; +} RAW_DATA_PER_CHANNEL_2413; + +/* XXX: assumes NUM_11A_EEPROM_CHANNELS_2413 >= NUM_2_4_EEPROM_CHANNELS_2413 ??? */ +typedef struct { + uint16_t pChannels[NUM_11A_EEPROM_CHANNELS_2413]; + uint16_t numChannels; + uint16_t xpd_mask; /* mask of permitted xpd_gains */ + RAW_DATA_PER_CHANNEL_2413 pDataPerChannel[NUM_11A_EEPROM_CHANNELS_2413]; +} RAW_DATA_STRUCT_2413; + +typedef struct { + uint16_t channelValue; + uint16_t numPdGains; + uint16_t Vpd_I[MAX_NUM_PDGAINS_PER_CHANNEL]; + int16_t pwr_I[MAX_NUM_PDGAINS_PER_CHANNEL]; + uint16_t Vpd_delta[NUM_POINTS_LAST_PDGAIN] + [MAX_NUM_PDGAINS_PER_CHANNEL]; + int16_t pwr_delta_t2[NUM_POINTS_LAST_PDGAIN] + [MAX_NUM_PDGAINS_PER_CHANNEL]; + int16_t maxPower_t4; +} EEPROM_DATA_PER_CHANNEL_2413; + +typedef struct { + uint16_t pChannels[NUM_11A_EEPROM_CHANNELS_2413]; + uint16_t numChannels; + uint16_t xpd_mask; /* mask of permitted xpd_gains */ + EEPROM_DATA_PER_CHANNEL_2413 pDataPerChannel[NUM_11A_EEPROM_CHANNELS_2413]; +} EEPROM_DATA_STRUCT_2413; + +/* + * Information retrieved from EEPROM. + */ +typedef struct { + uint16_t ee_version; /* Version field */ + uint16_t ee_protect; /* EEPROM protect field */ + uint16_t ee_regdomain; /* Regulatory domain */ + + /* General Device Parameters */ + uint16_t ee_turbo5Disable; + uint16_t ee_turbo2Disable; + uint16_t ee_rfKill; + uint16_t ee_deviceType; + uint16_t ee_turbo2WMaxPower5; + uint16_t ee_turbo2WMaxPower2; + uint16_t ee_xrTargetPower5; + uint16_t ee_xrTargetPower2; + uint16_t ee_Amode; + uint16_t ee_regCap; + uint16_t ee_Bmode; + uint16_t ee_Gmode; + int8_t ee_antennaGainMax[2]; + uint16_t ee_xtnd5GSupport; + uint8_t ee_cckOfdmPwrDelta; + uint8_t ee_exist32kHzCrystal; + uint16_t ee_targetPowersStart; + uint16_t ee_fixedBias5; + uint16_t ee_fixedBias2; + uint16_t ee_cckOfdmGainDelta; + uint16_t ee_scaledCh14FilterCckDelta; + uint16_t ee_eepMap; + uint16_t ee_earStart; + + /* 5 GHz / 2.4 GHz CKK / 2.4 GHz OFDM common parameters */ + uint16_t ee_switchSettling[3]; + uint16_t ee_txrxAtten[3]; + uint16_t ee_txEndToXLNAOn[3]; + uint16_t ee_thresh62[3]; + uint16_t ee_txEndToXPAOff[3]; + uint16_t ee_txFrameToXPAOn[3]; + int8_t ee_adcDesiredSize[3]; /* 8-bit signed value */ + int8_t ee_pgaDesiredSize[3]; /* 8-bit signed value */ + int16_t ee_noiseFloorThresh[3]; + uint16_t ee_xlnaGain[3]; + uint16_t ee_xgain[3]; + uint16_t ee_xpd[3]; + uint16_t ee_antennaControl[11][3]; + uint16_t ee_falseDetectBackoff[3]; + uint16_t ee_gainI[3]; + uint16_t ee_rxtxMargin[3]; + + /* new parameters added for the AR2413 */ + HAL_BOOL ee_disableXr5; + HAL_BOOL ee_disableXr2; + uint16_t ee_eepMap2PowerCalStart; + uint16_t ee_capField; + + uint16_t ee_switchSettlingTurbo[2]; + uint16_t ee_txrxAttenTurbo[2]; + int8_t ee_adcDesiredSizeTurbo[2]; + int8_t ee_pgaDesiredSizeTurbo[2]; + uint16_t ee_rxtxMarginTurbo[2]; + + /* 5 GHz parameters */ + uint16_t ee_ob1; + uint16_t ee_db1; + uint16_t ee_ob2; + uint16_t ee_db2; + uint16_t ee_ob3; + uint16_t ee_db3; + uint16_t ee_ob4; + uint16_t ee_db4; + + /* 2.4 GHz parameters */ + uint16_t ee_obFor24; + uint16_t ee_dbFor24; + uint16_t ee_obFor24g; + uint16_t ee_dbFor24g; + uint16_t ee_ob2GHz[2]; + uint16_t ee_db2GHz[2]; + uint16_t ee_numCtls; + uint16_t ee_ctl[NUM_CTLS_MAX]; + uint16_t ee_iqCalI[2]; + uint16_t ee_iqCalQ[2]; + uint16_t ee_calPier11g[NUM_2_4_EEPROM_CHANNELS]; + uint16_t ee_calPier11b[NUM_2_4_EEPROM_CHANNELS]; + + /* corner calibration information */ + CORNER_CAL_INFO ee_cornerCal; + + uint16_t ee_opCap; + + /* 11a info */ + uint16_t ee_channels11a[NUM_11A_EEPROM_CHANNELS]; + uint16_t ee_numChannels11a; + DATA_PER_CHANNEL ee_dataPerChannel11a[NUM_11A_EEPROM_CHANNELS]; + + uint16_t ee_numChannels2_4; + uint16_t ee_channels11g[NUM_2_4_EEPROM_CHANNELS]; + uint16_t ee_channels11b[NUM_2_4_EEPROM_CHANNELS]; + uint16_t ee_spurChans[AR_EEPROM_MODAL_SPURS][2]; + + /* 11g info */ + DATA_PER_CHANNEL ee_dataPerChannel11g[NUM_2_4_EEPROM_CHANNELS]; + + /* 11b info */ + DATA_PER_CHANNEL ee_dataPerChannel11b[NUM_2_4_EEPROM_CHANNELS]; + + TRGT_POWER_ALL_MODES ee_tpow; + + RD_EDGES_POWER ee_rdEdgesPower[NUM_EDGES*NUM_CTLS_MAX]; + + union { + EEPROM_POWER_EXPN_5112 eu_modePowerArray5112[3]; + RAW_DATA_STRUCT_2413 eu_rawDataset2413[3]; + } ee_u; +} HAL_EEPROM; + +/* write-around defines */ +#define ee_numTargetPwr_11a ee_tpow.numTargetPwr_11a +#define ee_trgtPwr_11a ee_tpow.trgtPwr_11a +#define ee_numTargetPwr_11g ee_tpow.numTargetPwr_11g +#define ee_trgtPwr_11g ee_tpow.trgtPwr_11g +#define ee_numTargetPwr_11b ee_tpow.numTargetPwr_11b +#define ee_trgtPwr_11b ee_tpow.trgtPwr_11b +#define ee_modePowerArray5112 ee_u.eu_modePowerArray5112 +#define ee_rawDataset2413 ee_u.eu_rawDataset2413 +#endif /* _ATH_AH_EEPROM_V3_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ah_internal.h b/sys/dev/netif/ath/hal/ath_hal/ah_internal.h new file mode 100644 index 0000000000..fabfd1c162 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ah_internal.h @@ -0,0 +1,787 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: src/sys/dev/ath/ath_hal/ah_internal.h,v 1.2.2.1.2.1 2009/04/15 03:14:26 kensmith Exp $ + */ +#ifndef _ATH_AH_INTERAL_H_ +#define _ATH_AH_INTERAL_H_ +/* + * Atheros Device Hardware Access Layer (HAL). + * + * Internal definitions. + */ +#define AH_NULL 0 +#define AH_MIN(a,b) ((a)<(b)?(a):(b)) +#define AH_MAX(a,b) ((a)>(b)?(a):(b)) + +#ifndef NBBY +#define NBBY 8 /* number of bits/byte */ +#endif + +#ifndef roundup +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */ +#endif +#ifndef howmany +#define howmany(x, y) (((x)+((y)-1))/(y)) +#endif + +#ifndef offsetof +#define offsetof(type, field) ((size_t)(&((type *)0)->field)) +#endif + +typedef struct { + uint16_t start; /* first register */ + uint16_t end; /* ending register or zero */ +} HAL_REGRANGE; + +/* + * Transmit power scale factor. + * + * NB: This is not public because we want to discourage the use of + * scaling; folks should use the tx power limit interface. + */ +typedef enum { + HAL_TP_SCALE_MAX = 0, /* no scaling (default) */ + HAL_TP_SCALE_50 = 1, /* 50% of max (-3 dBm) */ + HAL_TP_SCALE_25 = 2, /* 25% of max (-6 dBm) */ + HAL_TP_SCALE_12 = 3, /* 12% of max (-9 dBm) */ + HAL_TP_SCALE_MIN = 4, /* min, but still on */ +} HAL_TP_SCALE; + +typedef enum { + HAL_CAP_RADAR = 0, /* Radar capability */ + HAL_CAP_AR = 1, /* AR capability */ +} HAL_PHYDIAG_CAPS; + +/* + * Each chip or class of chips registers to offer support. + */ +struct ath_hal_chip { + const char *name; + const char *(*probe)(uint16_t vendorid, uint16_t devid); + struct ath_hal *(*attach)(uint16_t devid, HAL_SOFTC, + HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS *error); +}; +#ifndef AH_CHIP +#define AH_CHIP(_name, _probe, _attach) \ +static struct ath_hal_chip name##_chip = { \ + .name = #_name, \ + .probe = _probe, \ + .attach = _attach \ +}; \ +OS_DATA_SET(ah_chips, name##_chip) +#endif + +/* + * Each RF backend registers to offer support; this is mostly + * used by multi-chip 5212 solutions. Single-chip solutions + * have a fixed idea about which RF to use. + */ +struct ath_hal_rf { + const char *name; + HAL_BOOL (*probe)(struct ath_hal *ah); + HAL_BOOL (*attach)(struct ath_hal *ah, HAL_STATUS *ecode); +}; +#ifndef AH_RF +#define AH_RF(_name, _probe, _attach) \ +static struct ath_hal_rf _name##_rf = { \ + .name = __STRING(_name), \ + .probe = _probe, \ + .attach = _attach \ +}; \ +OS_DATA_SET(ah_rfs, _name##_rf) +#endif + +struct ath_hal_rf *ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode); + +/* + * Internal form of a HAL_CHANNEL. Note that the structure + * must be defined such that you can cast references to a + * HAL_CHANNEL so don't shuffle the first two members. + */ +typedef struct { + uint32_t channelFlags; + uint16_t channel; /* NB: must be first for casting */ + uint8_t privFlags; + int8_t maxRegTxPower; + int8_t maxTxPower; + int8_t minTxPower; /* as above... */ + + HAL_BOOL bssSendHere; + uint8_t gainI; + HAL_BOOL iqCalValid; + uint8_t calValid; /* bitmask of cal types */ + int8_t iCoff; + int8_t qCoff; + int16_t rawNoiseFloor; + int16_t noiseFloorAdjust; + int8_t antennaMax; + uint32_t regDmnFlags; /* Flags for channel use in reg */ + uint32_t conformanceTestLimit; /* conformance test limit from reg domain */ + uint16_t mainSpur; /* cached spur value for this cahnnel */ +} HAL_CHANNEL_INTERNAL; + +typedef struct { + uint32_t halChanSpreadSupport : 1, + halSleepAfterBeaconBroken : 1, + halCompressSupport : 1, + halBurstSupport : 1, + halFastFramesSupport : 1, + halChapTuningSupport : 1, + halTurboGSupport : 1, + halTurboPrimeSupport : 1, + halMicAesCcmSupport : 1, + halMicCkipSupport : 1, + halMicTkipSupport : 1, + halTkipMicTxRxKeySupport : 1, + halCipherAesCcmSupport : 1, + halCipherCkipSupport : 1, + halCipherTkipSupport : 1, + halPSPollBroken : 1, + halVEOLSupport : 1, + halBssIdMaskSupport : 1, + halMcastKeySrchSupport : 1, + halTsfAddSupport : 1, + halChanHalfRate : 1, + halChanQuarterRate : 1, + halHTSupport : 1, + halRfSilentSupport : 1, + halHwPhyCounterSupport : 1, + halWowSupport : 1, + halWowMatchPatternExact : 1, + halAutoSleepSupport : 1, + halFastCCSupport : 1, + halBtCoexSupport : 1; + uint32_t halRxStbcSupport : 1, + halTxStbcSupport : 1, + halGTTSupport : 1, + halCSTSupport : 1, + halRifsRxSupport : 1, + halRifsTxSupport : 1, + halExtChanDfsSupport : 1, + halForcePpmSupport : 1, + halEnhancedPmSupport : 1, + halMbssidAggrSupport : 1; + uint32_t halWirelessModes; + uint16_t halTotalQueues; + uint16_t halKeyCacheSize; + uint16_t halLow5GhzChan, halHigh5GhzChan; + uint16_t halLow2GhzChan, halHigh2GhzChan; + int halTstampPrecision; + int halRtsAggrLimit; + uint8_t halTxChainMask; + uint8_t halRxChainMask; + uint8_t halNumGpioPins; + uint8_t halNumAntCfg2GHz; + uint8_t halNumAntCfg5GHz; +} HAL_CAPABILITIES; + +/* + * The ``private area'' follows immediately after the ``public area'' + * in the data structure returned by ath_hal_attach. Private data are + * used by device-independent code such as the regulatory domain support. + * In general, code within the HAL should never depend on data in the + * public area. Instead any public data needed internally should be + * shadowed here. + * + * When declaring a device-specific ath_hal data structure this structure + * is assumed to at the front; e.g. + * + * struct ath_hal_5212 { + * struct ath_hal_private ah_priv; + * ... + * }; + * + * It might be better to manage the method pointers in this structure + * using an indirect pointer to a read-only data structure but this would + * disallow class-style method overriding. + */ +struct ath_hal_private { + struct ath_hal h; /* public area */ + + /* NB: all methods go first to simplify initialization */ + HAL_BOOL (*ah_getChannelEdges)(struct ath_hal*, + uint16_t channelFlags, + uint16_t *lowChannel, uint16_t *highChannel); + u_int (*ah_getWirelessModes)(struct ath_hal*); + HAL_BOOL (*ah_eepromRead)(struct ath_hal *, u_int off, + uint16_t *data); + HAL_BOOL (*ah_eepromWrite)(struct ath_hal *, u_int off, + uint16_t data); + HAL_BOOL (*ah_gpioCfgOutput)(struct ath_hal *, uint32_t gpio); + HAL_BOOL (*ah_gpioCfgInput)(struct ath_hal *, uint32_t gpio); + uint32_t (*ah_gpioGet)(struct ath_hal *, uint32_t gpio); + HAL_BOOL (*ah_gpioSet)(struct ath_hal *, + uint32_t gpio, uint32_t val); + void (*ah_gpioSetIntr)(struct ath_hal*, u_int, uint32_t); + HAL_BOOL (*ah_getChipPowerLimits)(struct ath_hal *, + HAL_CHANNEL *, uint32_t); + int16_t (*ah_getNfAdjust)(struct ath_hal *, + const HAL_CHANNEL_INTERNAL*); + void (*ah_getNoiseFloor)(struct ath_hal *, + int16_t nfarray[]); + + void *ah_eeprom; /* opaque EEPROM state */ + uint16_t ah_eeversion; /* EEPROM version */ + void (*ah_eepromDetach)(struct ath_hal *); + HAL_STATUS (*ah_eepromGet)(struct ath_hal *, int, void *); + HAL_BOOL (*ah_eepromSet)(struct ath_hal *, int, int); + uint16_t (*ah_getSpurChan)(struct ath_hal *, int, HAL_BOOL); + HAL_BOOL (*ah_eepromDiag)(struct ath_hal *, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize); + + /* + * Device revision information. + */ + uint16_t ah_devid; /* PCI device ID */ + uint16_t ah_subvendorid; /* PCI subvendor ID */ + uint32_t ah_macVersion; /* MAC version id */ + uint16_t ah_macRev; /* MAC revision */ + uint16_t ah_phyRev; /* PHY revision */ + uint16_t ah_analog5GhzRev; /* 2GHz radio revision */ + uint16_t ah_analog2GhzRev; /* 5GHz radio revision */ + + + HAL_OPMODE ah_opmode; /* operating mode from reset */ + HAL_CAPABILITIES ah_caps; /* device capabilities */ + uint32_t ah_diagreg; /* user-specified AR_DIAG_SW */ + int16_t ah_powerLimit; /* tx power cap */ + uint16_t ah_maxPowerLevel; /* calculated max tx power */ + u_int ah_tpScale; /* tx power scale factor */ + uint32_t ah_11nCompat; /* 11n compat controls */ + + /* + * State for regulatory domain handling. + */ + HAL_REG_DOMAIN ah_currentRD; /* Current regulatory domain */ + HAL_CTRY_CODE ah_countryCode; /* current country code */ + HAL_CHANNEL_INTERNAL ah_channels[256]; /* calculated channel list */ + u_int ah_nchan; /* valid channels in list */ + HAL_CHANNEL_INTERNAL *ah_curchan; /* current channel */ + + uint8_t ah_coverageClass; /* coverage class */ + HAL_BOOL ah_regdomainUpdate; /* regdomain is updated? */ + /* + * RF Silent handling; setup according to the EEPROM. + */ + uint16_t ah_rfsilent; /* GPIO pin + polarity */ + HAL_BOOL ah_rfkillEnabled; /* enable/disable RfKill */ + /* + * Diagnostic support for discriminating HIUERR reports. + */ + uint32_t ah_fatalState[6]; /* AR_ISR+shadow regs */ + int ah_rxornIsFatal; /* how to treat HAL_INT_RXORN */ +}; + +#define AH_PRIVATE(_ah) ((struct ath_hal_private *)(_ah)) + +#define ath_hal_getChannelEdges(_ah, _cf, _lc, _hc) \ + AH_PRIVATE(_ah)->ah_getChannelEdges(_ah, _cf, _lc, _hc) +#define ath_hal_getWirelessModes(_ah) \ + AH_PRIVATE(_ah)->ah_getWirelessModes(_ah) +#define ath_hal_eepromRead(_ah, _off, _data) \ + AH_PRIVATE(_ah)->ah_eepromRead(_ah, _off, _data) +#define ath_hal_eepromWrite(_ah, _off, _data) \ + AH_PRIVATE(_ah)->ah_eepromWrite(_ah, _off, _data) +#define ath_hal_gpioCfgOutput(_ah, _gpio) \ + AH_PRIVATE(_ah)->ah_gpioCfgOutput(_ah, _gpio) +#define ath_hal_gpioCfgInput(_ah, _gpio) \ + AH_PRIVATE(_ah)->ah_gpioCfgInput(_ah, _gpio) +#define ath_hal_gpioGet(_ah, _gpio) \ + AH_PRIVATE(_ah)->ah_gpioGet(_ah, _gpio) +#define ath_hal_gpioSet(_ah, _gpio, _val) \ + AH_PRIVATE(_ah)->ah_gpioGet(_ah, _gpio, _val) +#define ath_hal_gpioSetIntr(_ah, _gpio, _ilevel) \ + AH_PRIVATE(_ah)->ah_gpioSetIntr(_ah, _gpio, _ilevel) +#define ath_hal_getpowerlimits(_ah, _chans, _nchan) \ + AH_PRIVATE(_ah)->ah_getChipPowerLimits(_ah, _chans, _nchan) +#define ath_hal_getNfAdjust(_ah, _c) \ + AH_PRIVATE(_ah)->ah_getNfAdjust(_ah, _c) +#define ath_hal_getNoiseFloor(_ah, _nfArray) \ + AH_PRIVATE(_ah)->ah_getNoiseFloor(_ah, _nfArray) + +#define ath_hal_eepromDetach(_ah) \ + AH_PRIVATE(_ah)->ah_eepromDetach(_ah) +#define ath_hal_eepromGet(_ah, _param, _val) \ + AH_PRIVATE(_ah)->ah_eepromGet(_ah, _param, _val) +#define ath_hal_eepromSet(_ah, _param, _val) \ + AH_PRIVATE(_ah)->ah_eepromSet(_ah, _param, _val) +#define ath_hal_eepromGetFlag(_ah, _param) \ + (AH_PRIVATE(_ah)->ah_eepromGet(_ah, _param, AH_NULL) == HAL_OK) +#define ath_hal_getSpurChan(_ah, _ix, _is2G) \ + AH_PRIVATE(_ah)->ah_getSpurChan(_ah, _ix, _is2G) +#define ath_hal_eepromDiag(_ah, _request, _a, _asize, _r, _rsize) \ + AH_PRIVATE(_ah)->ah_eepromDiag(_ah, _request, _a, _asize, _r, _rsize) + +#if !defined(_NET_IF_IEEE80211_H_) && !defined(_NET80211__IEEE80211_H_) +/* + * Stuff that would naturally come from _ieee80211.h + */ +#define IEEE80211_ADDR_LEN 6 + +#define IEEE80211_WEP_KEYLEN 5 /* 40bit */ +#define IEEE80211_WEP_IVLEN 3 /* 24bit */ +#define IEEE80211_WEP_KIDLEN 1 /* 1 octet */ +#define IEEE80211_WEP_CRCLEN 4 /* CRC-32 */ + +#define IEEE80211_CRC_LEN 4 + +#define IEEE80211_MTU 1500 +#define IEEE80211_MAX_LEN (2300 + IEEE80211_CRC_LEN + \ + (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN)) + +enum { + IEEE80211_T_DS, /* direct sequence spread spectrum */ + IEEE80211_T_FH, /* frequency hopping */ + IEEE80211_T_OFDM, /* frequency division multiplexing */ + IEEE80211_T_TURBO, /* high rate DS */ + IEEE80211_T_HT, /* HT - full GI */ +}; +#define IEEE80211_T_CCK IEEE80211_T_DS /* more common nomenclatur */ +#endif /* _NET_IF_IEEE80211_H_ */ + +/* NB: these are defined privately until XR support is announced */ +enum { + ATHEROS_T_XR = IEEE80211_T_HT+1, /* extended range */ +}; + +#define HAL_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001 + +#define INIT_AIFS 2 +#define INIT_CWMIN 15 +#define INIT_CWMIN_11B 31 +#define INIT_CWMAX 1023 +#define INIT_SH_RETRY 10 +#define INIT_LG_RETRY 10 +#define INIT_SSH_RETRY 32 +#define INIT_SLG_RETRY 32 + +typedef struct { + uint32_t tqi_ver; /* HAL TXQ verson */ + HAL_TX_QUEUE tqi_type; /* hw queue type*/ + HAL_TX_QUEUE_SUBTYPE tqi_subtype; /* queue subtype, if applicable */ + HAL_TX_QUEUE_FLAGS tqi_qflags; /* queue flags */ + uint32_t tqi_priority; + uint32_t tqi_aifs; /* aifs */ + uint32_t tqi_cwmin; /* cwMin */ + uint32_t tqi_cwmax; /* cwMax */ + uint16_t tqi_shretry; /* frame short retry limit */ + uint16_t tqi_lgretry; /* frame long retry limit */ + uint32_t tqi_cbrPeriod; + uint32_t tqi_cbrOverflowLimit; + uint32_t tqi_burstTime; + uint32_t tqi_readyTime; + uint32_t tqi_physCompBuf; + uint32_t tqi_intFlags; /* flags for internal use */ +} HAL_TX_QUEUE_INFO; + +extern HAL_BOOL ath_hal_setTxQProps(struct ath_hal *ah, + HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo); +extern HAL_BOOL ath_hal_getTxQProps(struct ath_hal *ah, + HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi); + +typedef enum { + HAL_ANI_PRESENT, /* is ANI support present */ + HAL_ANI_NOISE_IMMUNITY_LEVEL, /* set level */ + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, /* enable/disable */ + HAL_ANI_CCK_WEAK_SIGNAL_THR, /* enable/disable */ + HAL_ANI_FIRSTEP_LEVEL, /* set level */ + HAL_ANI_SPUR_IMMUNITY_LEVEL, /* set level */ + HAL_ANI_MODE = 6, /* 0 => manual, 1 => auto (XXX do not change) */ + HAL_ANI_PHYERR_RESET, /* reset phy error stats */ +} HAL_ANI_CMD; + +#define HAL_SPUR_VAL_MASK 0x3FFF +#define HAL_SPUR_CHAN_WIDTH 87 +#define HAL_BIN_WIDTH_BASE_100HZ 3125 +#define HAL_BIN_WIDTH_TURBO_100HZ 6250 +#define HAL_MAX_BINS_ALLOWED 28 + +/* + * A = 5GHZ|OFDM + * T = 5GHZ|OFDM|TURBO + * + * IS_CHAN_A(T) will return TRUE. This is probably + * not the default behavior we want. We should migrate to a better mask -- + * perhaps CHANNEL_ALL. + * + * For now, IS_CHAN_G() masks itself with CHANNEL_108G. + * + */ + +#define IS_CHAN_A(_c) (((_c)->channelFlags & CHANNEL_A) == CHANNEL_A) +#define IS_CHAN_B(_c) (((_c)->channelFlags & CHANNEL_B) == CHANNEL_B) +#define IS_CHAN_G(_c) (((_c)->channelFlags & (CHANNEL_108G|CHANNEL_G)) == CHANNEL_G) +#define IS_CHAN_108G(_c)(((_c)->channelFlags & CHANNEL_108G) == CHANNEL_108G) +#define IS_CHAN_T(_c) (((_c)->channelFlags & CHANNEL_T) == CHANNEL_T) +#define IS_CHAN_PUREG(_c) \ + (((_c)->channelFlags & CHANNEL_PUREG) == CHANNEL_PUREG) + +#define IS_CHAN_TURBO(_c) (((_c)->channelFlags & CHANNEL_TURBO) != 0) +#define IS_CHAN_CCK(_c) (((_c)->channelFlags & CHANNEL_CCK) != 0) +#define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0) +#define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0) +#define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0) +#define IS_CHAN_PASSIVE(_c) (((_c)->channelFlags & CHANNEL_PASSIVE) != 0) +#define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0) +#define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0) + +#define IS_CHAN_IN_PUBLIC_SAFETY_BAND(_c) ((_c) > 4940 && (_c) < 4990) + +#define CHANNEL_HT40 (CHANNEL_HT40PLUS | CHANNEL_HT40MINUS) +#define CHANNEL_HT (CHANNEL_HT20 | CHANNEL_HT40) +#define IS_CHAN_HT(_c) (((_c)->channelFlags & CHANNEL_HT) != 0) +#define IS_CHAN_HT20(_c) (((_c)->channelFlags & CHANNEL_HT) == CHANNEL_HT20) +#define IS_CHAN_HT40(_c) (((_c)->channelFlags & CHANNEL_HT40) != 0) + +/* + * Deduce if the host cpu has big- or litt-endian byte order. + */ +static __inline__ int +isBigEndian(void) +{ + union { + int32_t i; + char c[4]; + } u; + u.i = 1; + return (u.c[0] == 0); +} + +/* unalligned little endian access */ +#define LE_READ_2(p) \ + ((uint16_t) \ + ((((const uint8_t *)(p))[0] ) | (((const uint8_t *)(p))[1]<< 8))) +#define LE_READ_4(p) \ + ((uint32_t) \ + ((((const uint8_t *)(p))[0] ) | (((const uint8_t *)(p))[1]<< 8) |\ + (((const uint8_t *)(p))[2]<<16) | (((const uint8_t *)(p))[3]<<24))) + +/* + * Register manipulation macros that expect bit field defines + * to follow the convention that an _S suffix is appended for + * a shift count, while the field mask has no suffix. + */ +#define SM(_v, _f) (((_v) << _f##_S) & (_f)) +#define MS(_v, _f) (((_v) & (_f)) >> _f##_S) +#define OS_REG_RMW_FIELD(_a, _r, _f, _v) \ + OS_REG_WRITE(_a, _r, \ + (OS_REG_READ(_a, _r) &~ (_f)) | (((_v) << _f##_S) & (_f))) +#define OS_REG_SET_BIT(_a, _r, _f) \ + OS_REG_WRITE(_a, _r, OS_REG_READ(_a, _r) | (_f)) +#define OS_REG_CLR_BIT(_a, _r, _f) \ + OS_REG_WRITE(_a, _r, OS_REG_READ(_a, _r) &~ (_f)) + +/* + * Regulatory domain support. + */ + +/* + * Return the max allowed antenna gain based on the current + * regulatory domain. + */ +extern u_int ath_hal_getantennareduction(struct ath_hal *, + HAL_CHANNEL *, u_int twiceGain); +/* + * Return the test group for the specific channel based on + * the current regulator domain. + */ +extern u_int ath_hal_getctl(struct ath_hal *, HAL_CHANNEL *); +/* + * Return whether or not a noise floor check is required + * based on the current regulatory domain for the specified + * channel. + */ +extern u_int ath_hal_getnfcheckrequired(struct ath_hal *, HAL_CHANNEL *); + +/* + * Map a public channel definition to the corresponding + * internal data structure. This implicitly specifies + * whether or not the specified channel is ok to use + * based on the current regulatory domain constraints. + */ +extern HAL_CHANNEL_INTERNAL *ath_hal_checkchannel(struct ath_hal *, + const HAL_CHANNEL *); + +/* system-configurable parameters */ +extern int ath_hal_dma_beacon_response_time; /* in TU's */ +extern int ath_hal_sw_beacon_response_time; /* in TU's */ +extern int ath_hal_additional_swba_backoff; /* in TU's */ + +/* wait for the register contents to have the specified value */ +extern HAL_BOOL ath_hal_wait(struct ath_hal *, u_int reg, + uint32_t mask, uint32_t val); + +/* return the first n bits in val reversed */ +extern uint32_t ath_hal_reverseBits(uint32_t val, uint32_t n); + +/* printf interfaces */ +extern void ath_hal_printf(struct ath_hal *, const char*, ...) + __printflike(2,3); +extern void ath_hal_vprintf(struct ath_hal *, const char*, __va_list) + __printflike(2, 0); +extern const char* ath_hal_ether_sprintf(const uint8_t *mac); + +/* allocate and free memory */ +extern void *ath_hal_malloc(size_t); +extern void ath_hal_free(void *); + +/* common debugging interfaces */ +#ifdef AH_DEBUG +#include "ah_debug.h" +extern int ath_hal_debug; +extern void HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) + __printflike(3,4); +#else +#define HALDEBUG(_ah, __m, _fmt, ...) +#endif /* AH_DEBUG */ + +/* + * Register logging definitions shared with ardecode. + */ +#include "ah_decode.h" + +/* + * Common assertion interface. Note: it is a bad idea to generate + * an assertion failure for any recoverable event. Instead catch + * the violation and, if possible, fix it up or recover from it; either + * with an error return value or a diagnostic messages. System software + * does not panic unless the situation is hopeless. + */ +#ifdef AH_ASSERT +extern void ath_hal_assert_failed(const char* filename, + int lineno, const char* msg); + +#define HALASSERT(_x) do { \ + if (!(_x)) { \ + ath_hal_assert_failed(__FILE__, __LINE__, #_x); \ + } \ +} while (0) +#else +#define HALASSERT(_x) +#endif /* AH_ASSERT */ + +/* + * Convert between microseconds and core system clocks. + */ +extern u_int ath_hal_mac_clks(struct ath_hal *ah, u_int usecs); +extern u_int ath_hal_mac_usec(struct ath_hal *ah, u_int clks); + +/* + * Generic get/set capability support. Each chip overrides + * this routine to support chip-specific capabilities. + */ +extern HAL_STATUS ath_hal_getcapability(struct ath_hal *ah, + HAL_CAPABILITY_TYPE type, uint32_t capability, + uint32_t *result); +extern HAL_BOOL ath_hal_setcapability(struct ath_hal *ah, + HAL_CAPABILITY_TYPE type, uint32_t capability, + uint32_t setting, HAL_STATUS *status); + +/* + * Diagnostic interface. This is an open-ended interface that + * is opaque to applications. Diagnostic programs use this to + * retrieve internal data structures, etc. There is no guarantee + * that calling conventions for calls other than HAL_DIAG_REVS + * are stable between HAL releases; a diagnostic application must + * use the HAL revision information to deal with ABI/API differences. + * + * NB: do not renumber these, certain codes are publicly used. + */ +enum { + HAL_DIAG_REVS = 0, /* MAC/PHY/Radio revs */ + HAL_DIAG_EEPROM = 1, /* EEPROM contents */ + HAL_DIAG_EEPROM_EXP_11A = 2, /* EEPROM 5112 power exp for 11a */ + HAL_DIAG_EEPROM_EXP_11B = 3, /* EEPROM 5112 power exp for 11b */ + HAL_DIAG_EEPROM_EXP_11G = 4, /* EEPROM 5112 power exp for 11g */ + HAL_DIAG_ANI_CURRENT = 5, /* ANI current channel state */ + HAL_DIAG_ANI_OFDM = 6, /* ANI OFDM timing error stats */ + HAL_DIAG_ANI_CCK = 7, /* ANI CCK timing error stats */ + HAL_DIAG_ANI_STATS = 8, /* ANI statistics */ + HAL_DIAG_RFGAIN = 9, /* RfGain GAIN_VALUES */ + HAL_DIAG_RFGAIN_CURSTEP = 10, /* RfGain GAIN_OPTIMIZATION_STEP */ + HAL_DIAG_PCDAC = 11, /* PCDAC table */ + HAL_DIAG_TXRATES = 12, /* Transmit rate table */ + HAL_DIAG_REGS = 13, /* Registers */ + HAL_DIAG_ANI_CMD = 14, /* ANI issue command (XXX do not change!) */ + HAL_DIAG_SETKEY = 15, /* Set keycache backdoor */ + HAL_DIAG_RESETKEY = 16, /* Reset keycache backdoor */ + HAL_DIAG_EEREAD = 17, /* Read EEPROM word */ + HAL_DIAG_EEWRITE = 18, /* Write EEPROM word */ + /* 19 was HAL_DIAG_TXCONT, 20-23 were for radar */ + HAL_DIAG_REGREAD = 24, /* Reg reads */ + HAL_DIAG_REGWRITE = 25, /* Reg writes */ + HAL_DIAG_GET_REGBASE = 26, /* Get register base */ + HAL_DIAG_RDWRITE = 27, /* Write regulatory domain */ + HAL_DIAG_RDREAD = 28, /* Get regulatory domain */ + HAL_DIAG_FATALERR = 29, /* Read cached interrupt state */ + HAL_DIAG_11NCOMPAT = 30, /* 11n compatibility tweaks */ + HAL_DIAG_ANI_PARAMS = 31, /* ANI noise immunity parameters */ + HAL_DIAG_CHECK_HANGS = 32, /* check h/w hangs */ +}; + +enum { + HAL_BB_HANG_DFS = 0x0001, + HAL_BB_HANG_RIFS = 0x0002, + HAL_BB_HANG_RX_CLEAR = 0x0004, + HAL_BB_HANG_UNKNOWN = 0x0080, + + HAL_MAC_HANG_SIG1 = 0x0100, + HAL_MAC_HANG_SIG2 = 0x0200, + HAL_MAC_HANG_UNKNOWN = 0x8000, + + HAL_BB_HANGS = HAL_BB_HANG_DFS + | HAL_BB_HANG_RIFS + | HAL_BB_HANG_RX_CLEAR + | HAL_BB_HANG_UNKNOWN, + HAL_MAC_HANGS = HAL_MAC_HANG_SIG1 + | HAL_MAC_HANG_SIG2 + | HAL_MAC_HANG_UNKNOWN, +}; + +/* + * Device revision information. + */ +typedef struct { + uint16_t ah_devid; /* PCI device ID */ + uint16_t ah_subvendorid; /* PCI subvendor ID */ + uint32_t ah_macVersion; /* MAC version id */ + uint16_t ah_macRev; /* MAC revision */ + uint16_t ah_phyRev; /* PHY revision */ + uint16_t ah_analog5GhzRev; /* 2GHz radio revision */ + uint16_t ah_analog2GhzRev; /* 5GHz radio revision */ +} HAL_REVS; + +/* + * Argument payload for HAL_DIAG_SETKEY. + */ +typedef struct { + HAL_KEYVAL dk_keyval; + uint16_t dk_keyix; /* key index */ + uint8_t dk_mac[IEEE80211_ADDR_LEN]; + int dk_xor; /* XOR key data */ +} HAL_DIAG_KEYVAL; + +/* + * Argument payload for HAL_DIAG_EEWRITE. + */ +typedef struct { + uint16_t ee_off; /* eeprom offset */ + uint16_t ee_data; /* write data */ +} HAL_DIAG_EEVAL; + + +typedef struct { + u_int offset; /* reg offset */ + uint32_t val; /* reg value */ +} HAL_DIAG_REGVAL; + +/* + * 11n compatibility tweaks. + */ +#define HAL_DIAG_11N_SERVICES 0x00000003 +#define HAL_DIAG_11N_SERVICES_S 0 +#define HAL_DIAG_11N_TXSTOMP 0x0000000c +#define HAL_DIAG_11N_TXSTOMP_S 2 + +typedef struct { + int maxNoiseImmunityLevel; /* [0..4] */ + int totalSizeDesired[5]; + int coarseHigh[5]; + int coarseLow[5]; + int firpwr[5]; + + int maxSpurImmunityLevel; /* [0..7] */ + int cycPwrThr1[8]; + + int maxFirstepLevel; /* [0..2] */ + int firstep[3]; + + uint32_t ofdmTrigHigh; + uint32_t ofdmTrigLow; + int32_t cckTrigHigh; + int32_t cckTrigLow; + int32_t rssiThrLow; + int32_t rssiThrHigh; + + int period; /* update listen period */ +} HAL_ANI_PARAMS; + +extern HAL_BOOL ath_hal_getdiagstate(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize); + +/* + * Setup a h/w rate table for use. + */ +extern void ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt); + +/* + * Common routine for implementing getChanNoise api. + */ +extern int16_t ath_hal_getChanNoise(struct ath_hal *ah, HAL_CHANNEL *chan); + +/* + * Initialization support. + */ +typedef struct { + const uint32_t *data; + int rows, cols; +} HAL_INI_ARRAY; + +#define HAL_INI_INIT(_ia, _data, _cols) do { \ + (_ia)->data = (const uint32_t *)(_data); \ + (_ia)->rows = sizeof(_data) / sizeof((_data)[0]); \ + (_ia)->cols = (_cols); \ +} while (0) +#define HAL_INI_VAL(_ia, _r, _c) \ + ((_ia)->data[((_r)*(_ia)->cols) + (_c)]) + +/* + * OS_DELAY() does a PIO READ on the PCI bus which allows + * other cards' DMA reads to complete in the middle of our reset. + */ +#define DMA_YIELD(x) do { \ + if ((++(x) % 64) == 0) \ + OS_DELAY(1); \ +} while (0) + +#define HAL_INI_WRITE_ARRAY(ah, regArray, col, regWr) do { \ + int r; \ + for (r = 0; r < N(regArray); r++) { \ + OS_REG_WRITE(ah, (regArray)[r][0], (regArray)[r][col]); \ + DMA_YIELD(regWr); \ + } \ +} while (0) + +#define HAL_INI_WRITE_BANK(ah, regArray, bankData, regWr) do { \ + int r; \ + for (r = 0; r < N(regArray); r++) { \ + OS_REG_WRITE(ah, (regArray)[r][0], (bankData)[r]); \ + DMA_YIELD(regWr); \ + } \ +} while (0) + +extern int ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, + int col, int regWr); +extern void ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, + int col); +extern int ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, + const uint32_t data[], int regWr); + +#define WLAN_CTRL_FRAME_SIZE (2+2+6+4) /* ACK+FCS */ +#endif /* _ATH_AH_INTERAL_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ah_regdomain.c b/sys/dev/netif/ath/hal/ath_hal/ah_regdomain.c new file mode 100644 index 0000000000..d021c28ed6 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ah_regdomain.c @@ -0,0 +1,2861 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2005-2006 Atheros Communications, Inc. + * All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ah_regdomain.c,v 1.24 2008/11/27 22:29:27 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_eeprom.h" +#include "ah_devid.h" + +/* + * XXX this code needs a audit+review + */ + +/* used throughout this file... */ +#define N(a) (sizeof (a) / sizeof (a[0])) + +#define HAL_MODE_11A_TURBO HAL_MODE_108A +#define HAL_MODE_11G_TURBO HAL_MODE_108G + +/* 10MHz is half the 11A bandwidth used to determine upper edge freq + of the outdoor channel */ +#define HALF_MAXCHANBW 10 + +/* + * BMLEN defines the size of the bitmask used to hold frequency + * band specifications. Note this must agree with the BM macro + * definition that's used to setup initializers. See also further + * comments below. + */ +#define BMLEN 2 /* 2 x 64 bits in each channel bitmask */ +typedef uint64_t chanbmask_t[BMLEN]; + +#define W0(_a) \ + (((_a) >= 0 && (_a) < 64 ? (((uint64_t) 1)<<(_a)) : (uint64_t) 0)) +#define W1(_a) \ + (((_a) > 63 && (_a) < 128 ? (((uint64_t) 1)<<((_a)-64)) : (uint64_t) 0)) +#define BM1(_fa) { W0(_fa), W1(_fa) } +#define BM2(_fa, _fb) { W0(_fa) | W0(_fb), W1(_fa) | W1(_fb) } +#define BM3(_fa, _fb, _fc) \ + { W0(_fa) | W0(_fb) | W0(_fc), W1(_fa) | W1(_fb) | W1(_fc) } +#define BM4(_fa, _fb, _fc, _fd) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd), \ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) } +#define BM5(_fa, _fb, _fc, _fd, _fe) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe), \ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) } +#define BM6(_fa, _fb, _fc, _fd, _fe, _ff) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff), \ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) } +#define BM7(_fa, _fb, _fc, _fd, _fe, _ff, _fg) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff) | \ + W0(_fg),\ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) | \ + W1(_fg) } +#define BM8(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff) | \ + W0(_fg) | W0(_fh) , \ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) | \ + W1(_fg) | W1(_fh) } + +/* + * Country/Region Codes + * Numbering from ISO 3166 + */ +enum { + CTRY_ALBANIA = 8, /* Albania */ + CTRY_ALGERIA = 12, /* Algeria */ + CTRY_ARGENTINA = 32, /* Argentina */ + CTRY_ARMENIA = 51, /* Armenia */ + CTRY_AUSTRALIA = 36, /* Australia */ + CTRY_AUSTRIA = 40, /* Austria */ + CTRY_AZERBAIJAN = 31, /* Azerbaijan */ + CTRY_BAHRAIN = 48, /* Bahrain */ + CTRY_BELARUS = 112, /* Belarus */ + CTRY_BELGIUM = 56, /* Belgium */ + CTRY_BELIZE = 84, /* Belize */ + CTRY_BOLIVIA = 68, /* Bolivia */ + CTRY_BRAZIL = 76, /* Brazil */ + CTRY_BRUNEI_DARUSSALAM = 96, /* Brunei Darussalam */ + CTRY_BULGARIA = 100, /* Bulgaria */ + CTRY_CANADA = 124, /* Canada */ + CTRY_CHILE = 152, /* Chile */ + CTRY_CHINA = 156, /* People's Republic of China */ + CTRY_COLOMBIA = 170, /* Colombia */ + CTRY_COSTA_RICA = 188, /* Costa Rica */ + CTRY_CROATIA = 191, /* Croatia */ + CTRY_CYPRUS = 196, + CTRY_CZECH = 203, /* Czech Republic */ + CTRY_DENMARK = 208, /* Denmark */ + CTRY_DOMINICAN_REPUBLIC = 214, /* Dominican Republic */ + CTRY_ECUADOR = 218, /* Ecuador */ + CTRY_EGYPT = 818, /* Egypt */ + CTRY_EL_SALVADOR = 222, /* El Salvador */ + CTRY_ESTONIA = 233, /* Estonia */ + CTRY_FAEROE_ISLANDS = 234, /* Faeroe Islands */ + CTRY_FINLAND = 246, /* Finland */ + CTRY_FRANCE = 250, /* France */ + CTRY_FRANCE2 = 255, /* France2 */ + CTRY_GEORGIA = 268, /* Georgia */ + CTRY_GERMANY = 276, /* Germany */ + CTRY_GREECE = 300, /* Greece */ + CTRY_GUATEMALA = 320, /* Guatemala */ + CTRY_HONDURAS = 340, /* Honduras */ + CTRY_HONG_KONG = 344, /* Hong Kong S.A.R., P.R.C. */ + CTRY_HUNGARY = 348, /* Hungary */ + CTRY_ICELAND = 352, /* Iceland */ + CTRY_INDIA = 356, /* India */ + CTRY_INDONESIA = 360, /* Indonesia */ + CTRY_IRAN = 364, /* Iran */ + CTRY_IRAQ = 368, /* Iraq */ + CTRY_IRELAND = 372, /* Ireland */ + CTRY_ISRAEL = 376, /* Israel */ + CTRY_ITALY = 380, /* Italy */ + CTRY_JAMAICA = 388, /* Jamaica */ + CTRY_JAPAN = 392, /* Japan */ + CTRY_JAPAN1 = 393, /* Japan (JP1) */ + CTRY_JAPAN2 = 394, /* Japan (JP0) */ + CTRY_JAPAN3 = 395, /* Japan (JP1-1) */ + CTRY_JAPAN4 = 396, /* Japan (JE1) */ + CTRY_JAPAN5 = 397, /* Japan (JE2) */ + CTRY_JAPAN6 = 399, /* Japan (JP6) */ + + CTRY_JAPAN7 = 4007, /* Japan (J7) */ + CTRY_JAPAN8 = 4008, /* Japan (J8) */ + CTRY_JAPAN9 = 4009, /* Japan (J9) */ + + CTRY_JAPAN10 = 4010, /* Japan (J10) */ + CTRY_JAPAN11 = 4011, /* Japan (J11) */ + CTRY_JAPAN12 = 4012, /* Japan (J12) */ + + CTRY_JAPAN13 = 4013, /* Japan (J13) */ + CTRY_JAPAN14 = 4014, /* Japan (J14) */ + CTRY_JAPAN15 = 4015, /* Japan (J15) */ + + CTRY_JAPAN16 = 4016, /* Japan (J16) */ + CTRY_JAPAN17 = 4017, /* Japan (J17) */ + CTRY_JAPAN18 = 4018, /* Japan (J18) */ + + CTRY_JAPAN19 = 4019, /* Japan (J19) */ + CTRY_JAPAN20 = 4020, /* Japan (J20) */ + CTRY_JAPAN21 = 4021, /* Japan (J21) */ + + CTRY_JAPAN22 = 4022, /* Japan (J22) */ + CTRY_JAPAN23 = 4023, /* Japan (J23) */ + CTRY_JAPAN24 = 4024, /* Japan (J24) */ + + CTRY_JORDAN = 400, /* Jordan */ + CTRY_KAZAKHSTAN = 398, /* Kazakhstan */ + CTRY_KENYA = 404, /* Kenya */ + CTRY_KOREA_NORTH = 408, /* North Korea */ + CTRY_KOREA_ROC = 410, /* South Korea */ + CTRY_KOREA_ROC2 = 411, /* South Korea */ + CTRY_KOREA_ROC3 = 412, /* South Korea */ + CTRY_KUWAIT = 414, /* Kuwait */ + CTRY_LATVIA = 428, /* Latvia */ + CTRY_LEBANON = 422, /* Lebanon */ + CTRY_LIBYA = 434, /* Libya */ + CTRY_LIECHTENSTEIN = 438, /* Liechtenstein */ + CTRY_LITHUANIA = 440, /* Lithuania */ + CTRY_LUXEMBOURG = 442, /* Luxembourg */ + CTRY_MACAU = 446, /* Macau */ + CTRY_MACEDONIA = 807, /* the Former Yugoslav Republic of Macedonia */ + CTRY_MALAYSIA = 458, /* Malaysia */ + CTRY_MALTA = 470, /* Malta */ + CTRY_MEXICO = 484, /* Mexico */ + CTRY_MONACO = 492, /* Principality of Monaco */ + CTRY_MOROCCO = 504, /* Morocco */ + CTRY_NETHERLANDS = 528, /* Netherlands */ + CTRY_NEW_ZEALAND = 554, /* New Zealand */ + CTRY_NICARAGUA = 558, /* Nicaragua */ + CTRY_NORWAY = 578, /* Norway */ + CTRY_OMAN = 512, /* Oman */ + CTRY_PAKISTAN = 586, /* Islamic Republic of Pakistan */ + CTRY_PANAMA = 591, /* Panama */ + CTRY_PARAGUAY = 600, /* Paraguay */ + CTRY_PERU = 604, /* Peru */ + CTRY_PHILIPPINES = 608, /* Republic of the Philippines */ + CTRY_POLAND = 616, /* Poland */ + CTRY_PORTUGAL = 620, /* Portugal */ + CTRY_PUERTO_RICO = 630, /* Puerto Rico */ + CTRY_QATAR = 634, /* Qatar */ + CTRY_ROMANIA = 642, /* Romania */ + CTRY_RUSSIA = 643, /* Russia */ + CTRY_SAUDI_ARABIA = 682, /* Saudi Arabia */ + CTRY_SINGAPORE = 702, /* Singapore */ + CTRY_SLOVAKIA = 703, /* Slovak Republic */ + CTRY_SLOVENIA = 705, /* Slovenia */ + CTRY_SOUTH_AFRICA = 710, /* South Africa */ + CTRY_SPAIN = 724, /* Spain */ + CTRY_SR9 = 5000, /* Ubiquiti SR9 (900MHz/GSM) */ + CTRY_SWEDEN = 752, /* Sweden */ + CTRY_SWITZERLAND = 756, /* Switzerland */ + CTRY_SYRIA = 760, /* Syria */ + CTRY_TAIWAN = 158, /* Taiwan */ + CTRY_THAILAND = 764, /* Thailand */ + CTRY_TRINIDAD_Y_TOBAGO = 780, /* Trinidad y Tobago */ + CTRY_TUNISIA = 788, /* Tunisia */ + CTRY_TURKEY = 792, /* Turkey */ + CTRY_UAE = 784, /* U.A.E. */ + CTRY_UKRAINE = 804, /* Ukraine */ + CTRY_UNITED_KINGDOM = 826, /* United Kingdom */ + CTRY_UNITED_STATES = 840, /* United States */ + CTRY_UNITED_STATES_FCC49 = 842, /* United States (Public Safety)*/ + CTRY_URUGUAY = 858, /* Uruguay */ + CTRY_UZBEKISTAN = 860, /* Uzbekistan */ + CTRY_VENEZUELA = 862, /* Venezuela */ + CTRY_VIET_NAM = 704, /* Viet Nam */ + CTRY_XR9 = 5001, /* Ubiquiti XR9 (900MHz/GSM) */ + CTRY_GZ901 = 5002, /* Zcomax GZ-901 (900MHz/GSM) */ + CTRY_YEMEN = 887, /* Yemen */ + CTRY_ZIMBABWE = 716 /* Zimbabwe */ +}; + + +/* + * Mask to check whether a domain is a multidomain or a single domain + */ +#define MULTI_DOMAIN_MASK 0xFF00 + +/* + * Enumerated Regulatory Domain Information 8 bit values indicate that + * the regdomain is really a pair of unitary regdomains. 12 bit values + * are the real unitary regdomains and are the only ones which have the + * frequency bitmasks and flags set. + */ +enum { + /* + * The following regulatory domain definitions are + * found in the EEPROM. Each regulatory domain + * can operate in either a 5GHz or 2.4GHz wireless mode or + * both 5GHz and 2.4GHz wireless modes. + * In general, the value holds no special + * meaning and is used to decode into either specific + * 2.4GHz or 5GHz wireless mode for that particular + * regulatory domain. + */ + NO_ENUMRD = 0x00, + NULL1_WORLD = 0x03, /* For 11b-only countries (no 11a allowed) */ + NULL1_ETSIB = 0x07, /* Israel */ + NULL1_ETSIC = 0x08, + FCC1_FCCA = 0x10, /* USA */ + FCC1_WORLD = 0x11, /* Hong Kong */ + FCC4_FCCA = 0x12, /* USA - Public Safety */ + FCC5_FCCB = 0x13, /* USA w/ 1/2 and 1/4 width channels */ + + FCC2_FCCA = 0x20, /* Canada */ + FCC2_WORLD = 0x21, /* Australia & HK */ + FCC2_ETSIC = 0x22, + FRANCE_RES = 0x31, /* Legacy France for OEM */ + FCC3_FCCA = 0x3A, /* USA & Canada w/5470 band, 11h, DFS enabled */ + FCC3_WORLD = 0x3B, /* USA & Canada w/5470 band, 11h, DFS enabled */ + + ETSI1_WORLD = 0x37, + ETSI3_ETSIA = 0x32, /* France (optional) */ + ETSI2_WORLD = 0x35, /* Hungary & others */ + ETSI3_WORLD = 0x36, /* France & others */ + ETSI4_WORLD = 0x30, + ETSI4_ETSIC = 0x38, + ETSI5_WORLD = 0x39, + ETSI6_WORLD = 0x34, /* Bulgaria */ + ETSI_RESERVED = 0x33, /* Reserved (Do not used) */ + + MKK1_MKKA = 0x40, /* Japan (JP1) */ + MKK1_MKKB = 0x41, /* Japan (JP0) */ + APL4_WORLD = 0x42, /* Singapore */ + MKK2_MKKA = 0x43, /* Japan with 4.9G channels */ + APL_RESERVED = 0x44, /* Reserved (Do not used) */ + APL2_WORLD = 0x45, /* Korea */ + APL2_APLC = 0x46, + APL3_WORLD = 0x47, + MKK1_FCCA = 0x48, /* Japan (JP1-1) */ + APL2_APLD = 0x49, /* Korea with 2.3G channels */ + MKK1_MKKA1 = 0x4A, /* Japan (JE1) */ + MKK1_MKKA2 = 0x4B, /* Japan (JE2) */ + MKK1_MKKC = 0x4C, /* Japan (MKK1_MKKA,except Ch14) */ + + APL3_FCCA = 0x50, + APL1_WORLD = 0x52, /* Latin America */ + APL1_FCCA = 0x53, + APL1_APLA = 0x54, + APL1_ETSIC = 0x55, + APL2_ETSIC = 0x56, /* Venezuela */ + APL5_WORLD = 0x58, /* Chile */ + APL6_WORLD = 0x5B, /* Singapore */ + APL7_FCCA = 0x5C, /* Taiwan 5.47 Band */ + APL8_WORLD = 0x5D, /* Malaysia 5GHz */ + APL9_WORLD = 0x5E, /* Korea 5GHz */ + + /* + * World mode SKUs + */ + WOR0_WORLD = 0x60, /* World0 (WO0 SKU) */ + WOR1_WORLD = 0x61, /* World1 (WO1 SKU) */ + WOR2_WORLD = 0x62, /* World2 (WO2 SKU) */ + WOR3_WORLD = 0x63, /* World3 (WO3 SKU) */ + WOR4_WORLD = 0x64, /* World4 (WO4 SKU) */ + WOR5_ETSIC = 0x65, /* World5 (WO5 SKU) */ + + WOR01_WORLD = 0x66, /* World0-1 (WW0-1 SKU) */ + WOR02_WORLD = 0x67, /* World0-2 (WW0-2 SKU) */ + EU1_WORLD = 0x68, /* Same as World0-2 (WW0-2 SKU), except active scan ch1-13. No ch14 */ + + WOR9_WORLD = 0x69, /* World9 (WO9 SKU) */ + WORA_WORLD = 0x6A, /* WorldA (WOA SKU) */ + + MKK3_MKKB = 0x80, /* Japan UNI-1 even + MKKB */ + MKK3_MKKA2 = 0x81, /* Japan UNI-1 even + MKKA2 */ + MKK3_MKKC = 0x82, /* Japan UNI-1 even + MKKC */ + + MKK4_MKKB = 0x83, /* Japan UNI-1 even + UNI-2 + MKKB */ + MKK4_MKKA2 = 0x84, /* Japan UNI-1 even + UNI-2 + MKKA2 */ + MKK4_MKKC = 0x85, /* Japan UNI-1 even + UNI-2 + MKKC */ + + MKK5_MKKB = 0x86, /* Japan UNI-1 even + UNI-2 + mid-band + MKKB */ + MKK5_MKKA2 = 0x87, /* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */ + MKK5_MKKC = 0x88, /* Japan UNI-1 even + UNI-2 + mid-band + MKKC */ + + MKK6_MKKB = 0x89, /* Japan UNI-1 even + UNI-1 odd MKKB */ + MKK6_MKKA2 = 0x8A, /* Japan UNI-1 even + UNI-1 odd + MKKA2 */ + MKK6_MKKC = 0x8B, /* Japan UNI-1 even + UNI-1 odd + MKKC */ + + MKK7_MKKB = 0x8C, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */ + MKK7_MKKA2 = 0x8D, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */ + MKK7_MKKC = 0x8E, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */ + + MKK8_MKKB = 0x8F, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */ + MKK8_MKKA2 = 0x90, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */ + MKK8_MKKC = 0x91, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */ + + /* Following definitions are used only by s/w to map old + * Japan SKUs. + */ + MKK3_MKKA = 0xF0, /* Japan UNI-1 even + MKKA */ + MKK3_MKKA1 = 0xF1, /* Japan UNI-1 even + MKKA1 */ + MKK3_FCCA = 0xF2, /* Japan UNI-1 even + FCCA */ + MKK4_MKKA = 0xF3, /* Japan UNI-1 even + UNI-2 + MKKA */ + MKK4_MKKA1 = 0xF4, /* Japan UNI-1 even + UNI-2 + MKKA1 */ + MKK4_FCCA = 0xF5, /* Japan UNI-1 even + UNI-2 + FCCA */ + MKK9_MKKA = 0xF6, /* Japan UNI-1 even + 4.9GHz */ + MKK10_MKKA = 0xF7, /* Japan UNI-1 even + UNI-2 + 4.9GHz */ + + /* + * Regulator domains ending in a number (e.g. APL1, + * MK1, ETSI4, etc) apply to 5GHz channel and power + * information. Regulator domains ending in a letter + * (e.g. APLA, FCCA, etc) apply to 2.4GHz channel and + * power information. + */ + APL1 = 0x0150, /* LAT & Asia */ + APL2 = 0x0250, /* LAT & Asia */ + APL3 = 0x0350, /* Taiwan */ + APL4 = 0x0450, /* Jordan */ + APL5 = 0x0550, /* Chile */ + APL6 = 0x0650, /* Singapore */ + APL8 = 0x0850, /* Malaysia */ + APL9 = 0x0950, /* Korea (South) ROC 3 */ + + ETSI1 = 0x0130, /* Europe & others */ + ETSI2 = 0x0230, /* Europe & others */ + ETSI3 = 0x0330, /* Europe & others */ + ETSI4 = 0x0430, /* Europe & others */ + ETSI5 = 0x0530, /* Europe & others */ + ETSI6 = 0x0630, /* Europe & others */ + ETSIA = 0x0A30, /* France */ + ETSIB = 0x0B30, /* Israel */ + ETSIC = 0x0C30, /* Latin America */ + + FCC1 = 0x0110, /* US & others */ + FCC2 = 0x0120, /* Canada, Australia & New Zealand */ + FCC3 = 0x0160, /* US w/new middle band & DFS */ + FCC4 = 0x0165, /* US Public Safety */ + FCC5 = 0x0166, /* US w/ 1/2 and 1/4 width channels */ + FCCA = 0x0A10, + FCCB = 0x0A11, /* US w/ 1/2 and 1/4 width channels */ + + APLD = 0x0D50, /* South Korea */ + + MKK1 = 0x0140, /* Japan (UNI-1 odd)*/ + MKK2 = 0x0240, /* Japan (4.9 GHz + UNI-1 odd) */ + MKK3 = 0x0340, /* Japan (UNI-1 even) */ + MKK4 = 0x0440, /* Japan (UNI-1 even + UNI-2) */ + MKK5 = 0x0540, /* Japan (UNI-1 even + UNI-2 + mid-band) */ + MKK6 = 0x0640, /* Japan (UNI-1 odd + UNI-1 even) */ + MKK7 = 0x0740, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */ + MKK8 = 0x0840, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */ + MKK9 = 0x0940, /* Japan (UNI-1 even + 4.9 GHZ) */ + MKK10 = 0x0B40, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ + MKKA = 0x0A40, /* Japan */ + MKKC = 0x0A50, + + NULL1 = 0x0198, + WORLD = 0x0199, + SR9_WORLD = 0x0298, + XR9_WORLD = 0x0299, + GZ901_WORLD = 0x029a, + DEBUG_REG_DMN = 0x01ff, +}; + +#define WORLD_SKU_MASK 0x00F0 +#define WORLD_SKU_PREFIX 0x0060 + +enum { /* conformance test limits */ + FCC = 0x10, + MKK = 0x40, + ETSI = 0x30, +}; + +/* + * The following are flags for different requirements per reg domain. + * These requirements are either inhereted from the reg domain pair or + * from the unitary reg domain if the reg domain pair flags value is 0 + */ +enum { + NO_REQ = 0x00000000, /* NB: must be zero */ + DISALLOW_ADHOC_11A = 0x00000001, + DISALLOW_ADHOC_11A_TURB = 0x00000002, + NEED_NFC = 0x00000004, + ADHOC_PER_11D = 0x00000008, /* Start Ad-Hoc mode */ + ADHOC_NO_11A = 0x00000010, + LIMIT_FRAME_4MS = 0x00000020, /* 4msec limit on frame length*/ + NO_HOSTAP = 0x00000040, /* No HOSTAP mode opereation */ +}; + +/* + * The following describe the bit masks for different passive scan + * capability/requirements per regdomain. + */ +#define NO_PSCAN 0x0ULL /* NB: must be zero */ +#define PSCAN_FCC 0x0000000000000001ULL +#define PSCAN_FCC_T 0x0000000000000002ULL +#define PSCAN_ETSI 0x0000000000000004ULL +#define PSCAN_MKK1 0x0000000000000008ULL +#define PSCAN_MKK2 0x0000000000000010ULL +#define PSCAN_MKKA 0x0000000000000020ULL +#define PSCAN_MKKA_G 0x0000000000000040ULL +#define PSCAN_ETSIA 0x0000000000000080ULL +#define PSCAN_ETSIB 0x0000000000000100ULL +#define PSCAN_ETSIC 0x0000000000000200ULL +#define PSCAN_WWR 0x0000000000000400ULL +#define PSCAN_MKKA1 0x0000000000000800ULL +#define PSCAN_MKKA1_G 0x0000000000001000ULL +#define PSCAN_MKKA2 0x0000000000002000ULL +#define PSCAN_MKKA2_G 0x0000000000004000ULL +#define PSCAN_MKK3 0x0000000000008000ULL +#define PSCAN_DEFER 0x7FFFFFFFFFFFFFFFULL +#define IS_ECM_CHAN 0x8000000000000000ULL + +/* + * THE following table is the mapping of regdomain pairs specified by + * an 8 bit regdomain value to the individual unitary reg domains + */ +typedef struct { + HAL_REG_DOMAIN regDmnEnum; /* 16 bit reg domain pair */ + HAL_REG_DOMAIN regDmn5GHz; /* 5GHz reg domain */ + HAL_REG_DOMAIN regDmn2GHz; /* 2GHz reg domain */ + uint32_t flags5GHz; /* Requirements flags (AdHoc + disallow, noise floor cal needed, + etc) */ + uint32_t flags2GHz; /* Requirements flags (AdHoc + disallow, noise floor cal needed, + etc) */ + uint64_t pscanMask; /* Passive Scan flags which + can override unitary domain + passive scan flags. This + value is used as a mask on + the unitary flags*/ + uint16_t singleCC; /* Country code of single country if + a one-on-one mapping exists */ +} REG_DMN_PAIR_MAPPING; + +static REG_DMN_PAIR_MAPPING regDomainPairs[] = { + {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {NULL1_WORLD, NULL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {NULL1_ETSIB, NULL1, ETSIB, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {NULL1_ETSIC, NULL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + + {FCC2_FCCA, FCC2, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC2_WORLD, FCC2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC2_ETSIC, FCC2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC3_FCCA, FCC3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC3_WORLD, FCC3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC4_FCCA, FCC4, FCCA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {FCC5_FCCB, FCC5, FCCB, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + + {ETSI1_WORLD, ETSI1, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {ETSI2_WORLD, ETSI2, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {ETSI3_WORLD, ETSI3, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {ETSI4_WORLD, ETSI4, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {ETSI5_WORLD, ETSI5, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {ETSI6_WORLD, ETSI6, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + + {ETSI3_ETSIA, ETSI3, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {FRANCE_RES, ETSI3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + + {FCC1_WORLD, FCC1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC1_FCCA, FCC1, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL1_WORLD, APL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL2_WORLD, APL2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL3_WORLD, APL3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL4_WORLD, APL4, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL5_WORLD, APL5, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL6_WORLD, APL6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL8_WORLD, APL8, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL9_WORLD, APL9, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + + {APL3_FCCA, APL3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL1_ETSIC, APL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL2_ETSIC, APL2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL2_APLD, APL2, APLD, NO_REQ, NO_REQ, PSCAN_DEFER, }, + + {MKK1_MKKA, MKK1, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA, CTRY_JAPAN }, + {MKK1_MKKB, MKK1, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN1 }, + {MKK1_FCCA, MKK1, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN2 }, + {MKK1_MKKA1, MKK1, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN4 }, + {MKK1_MKKA2, MKK1, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN5 }, + {MKK1_MKKC, MKK1, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN6 }, + + /* MKK2 */ + {MKK2_MKKA, MKK2, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK2 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN3 }, + + /* MKK3 */ + {MKK3_MKKA, MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC , PSCAN_MKKA, 0 }, + {MKK3_MKKB, MKK3, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN7 }, + {MKK3_MKKA1, MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, 0 }, + {MKK3_MKKA2,MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN8 }, + {MKK3_MKKC, MKK3, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, CTRY_JAPAN9 }, + {MKK3_FCCA, MKK3, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, 0 }, + + /* MKK4 */ + {MKK4_MKKB, MKK4, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN10 }, + {MKK4_MKKA1, MKK4, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, 0 }, + {MKK4_MKKA2, MKK4, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 |PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN11 }, + {MKK4_MKKC, MKK4, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN12 }, + {MKK4_FCCA, MKK4, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, 0 }, + + /* MKK5 */ + {MKK5_MKKB, MKK5, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN13 }, + {MKK5_MKKA2,MKK5, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN14 }, + {MKK5_MKKC, MKK5, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN15 }, + + /* MKK6 */ + {MKK6_MKKB, MKK6, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN16 }, + {MKK6_MKKA2, MKK6, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN17 }, + {MKK6_MKKC, MKK6, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN18 }, + + /* MKK7 */ + {MKK7_MKKB, MKK7, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN19 }, + {MKK7_MKKA2, MKK7, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN20 }, + {MKK7_MKKC, MKK7, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN21 }, + + /* MKK8 */ + {MKK8_MKKB, MKK8, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN22 }, + {MKK8_MKKA2,MKK8, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN23 }, + {MKK8_MKKC, MKK8, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 , CTRY_JAPAN24 }, + + {MKK9_MKKA, MKK9, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, 0 }, + {MKK10_MKKA, MKK10, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, 0 }, + + /* These are super domains */ + {WOR0_WORLD, WOR0_WORLD, WOR0_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {WOR1_WORLD, WOR1_WORLD, WOR1_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {WOR2_WORLD, WOR2_WORLD, WOR2_WORLD, DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {WOR3_WORLD, WOR3_WORLD, WOR3_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {WOR4_WORLD, WOR4_WORLD, WOR4_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {WOR5_ETSIC, WOR5_ETSIC, WOR5_ETSIC, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {WOR01_WORLD, WOR01_WORLD, WOR01_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {WOR02_WORLD, WOR02_WORLD, WOR02_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {EU1_WORLD, EU1_WORLD, EU1_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {WOR9_WORLD, WOR9_WORLD, WOR9_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {WORA_WORLD, WORA_WORLD, WORA_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {SR9_WORLD, NULL1, SR9_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_SR9 }, + {XR9_WORLD, NULL1, XR9_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_XR9 }, + {GZ901_WORLD, NULL1, GZ901_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_GZ901 }, +}; + +/* + * The following tables are the master list for all different freqeuncy + * bands with the complete matrix of all possible flags and settings + * for each band if it is used in ANY reg domain. + */ + +#define DEF_REGDMN FCC1_FCCA +#define DEF_DMN_5 FCC1 +#define DEF_DMN_2 FCCA +#define COUNTRY_ERD_FLAG 0x8000 +#define WORLDWIDE_ROAMING_FLAG 0x4000 +#define SUPER_DOMAIN_MASK 0x0fff +#define COUNTRY_CODE_MASK 0x3fff + +#define YES AH_TRUE +#define NO AH_FALSE + +typedef struct { + HAL_CTRY_CODE countryCode; + HAL_REG_DOMAIN regDmnEnum; + HAL_BOOL allow11g; + HAL_BOOL allow11aTurbo; + HAL_BOOL allow11gTurbo; + HAL_BOOL allow11ng20; + HAL_BOOL allow11ng40; + HAL_BOOL allow11na20; + HAL_BOOL allow11na40; + uint16_t outdoorChanStart; +} COUNTRY_CODE_TO_ENUM_RD; + +static COUNTRY_CODE_TO_ENUM_RD allCountries[] = { + {CTRY_DEBUG, NO_ENUMRD, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_DEFAULT, DEF_REGDMN, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_ALBANIA, NULL1_WORLD, YES, NO, YES, YES, NO, NO, NO, 7000 }, + {CTRY_ALGERIA, NULL1_WORLD, YES, NO, YES, YES, NO, NO, NO, 7000 }, + {CTRY_ARGENTINA, APL3_WORLD, NO, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_ARMENIA, ETSI4_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 }, + {CTRY_AUSTRALIA, FCC2_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_AUSTRIA, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_AZERBAIJAN, ETSI4_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_BAHRAIN, APL6_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_BELARUS, NULL1_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_BELGIUM, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_BELIZE, APL1_ETSIC, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_BOLIVIA, APL1_ETSIC, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_BRAZIL, FCC3_WORLD, YES, NO, NO, YES, NO, YES, NO, 7000 }, + {CTRY_BRUNEI_DARUSSALAM,APL1_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_BULGARIA, ETSI6_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_CANADA, FCC2_FCCA, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_CHILE, APL6_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_CHINA, APL1_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_COLOMBIA, FCC1_FCCA, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_COSTA_RICA, NULL1_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_CROATIA, ETSI3_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_CYPRUS, ETSI1_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_CZECH, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_DENMARK, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_DOMINICAN_REPUBLIC,FCC1_FCCA, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_ECUADOR, NULL1_WORLD, NO, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_EGYPT, ETSI3_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_EL_SALVADOR, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 }, + {CTRY_ESTONIA, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_FINLAND, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_FRANCE, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_FRANCE2, ETSI3_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_GEORGIA, ETSI4_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_GERMANY, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_GREECE, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_GUATEMALA, FCC1_FCCA, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_GZ901, GZ901_WORLD, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_HONDURAS, NULL1_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_HONG_KONG, FCC2_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_HUNGARY, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_ICELAND, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_INDIA, APL6_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_INDONESIA, APL1_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_IRAN, APL1_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_IRELAND, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_ISRAEL, NULL1_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_ITALY, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_JAPAN, MKK1_MKKA, YES, NO, NO, YES, NO, YES, NO, 7000 }, + {CTRY_JAPAN1, MKK1_MKKB, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_JAPAN2, MKK1_FCCA, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_JAPAN3, MKK2_MKKA, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_JAPAN4, MKK1_MKKA1, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_JAPAN5, MKK1_MKKA2, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_JAPAN6, MKK1_MKKC, YES, NO, NO, NO, NO, NO, NO, 7000 }, + + {CTRY_JAPAN7, MKK3_MKKB, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_JAPAN8, MKK3_MKKA2, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_JAPAN9, MKK3_MKKC, YES, NO, NO, NO, NO, NO, NO, 7000 }, + + {CTRY_JAPAN10, MKK4_MKKB, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_JAPAN11, MKK4_MKKA2, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_JAPAN12, MKK4_MKKC, YES, NO, NO, NO, NO, NO, NO, 7000 }, + + {CTRY_JAPAN13, MKK5_MKKB, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_JAPAN14, MKK5_MKKA2, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_JAPAN15, MKK5_MKKC, YES, NO, NO, NO, NO, NO, NO, 7000 }, + + {CTRY_JAPAN16, MKK6_MKKB, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_JAPAN17, MKK6_MKKA2, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_JAPAN18, MKK6_MKKC, YES, NO, NO, NO, NO, NO, NO, 7000 }, + + {CTRY_JAPAN19, MKK7_MKKB, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_JAPAN20, MKK7_MKKA2, YES, NO, NO, YES, NO, YES, NO, 7000 }, + {CTRY_JAPAN21, MKK7_MKKC, YES, NO, NO, NO, NO, NO, NO, 7000 }, + + {CTRY_JAPAN22, MKK8_MKKB, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_JAPAN23, MKK8_MKKA2, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_JAPAN24, MKK8_MKKC, YES, NO, NO, NO, NO, NO, NO, 7000 }, + + {CTRY_JORDAN, APL4_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_KAZAKHSTAN, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 }, + {CTRY_KOREA_NORTH, APL2_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_KOREA_ROC, APL2_WORLD, YES, NO, NO, YES, NO, YES, NO, 7000 }, + {CTRY_KOREA_ROC2, APL2_WORLD, YES, NO, NO, YES, NO, YES, NO, 7000 }, + {CTRY_KOREA_ROC3, APL9_WORLD, YES, NO, NO, YES, NO, YES, NO, 7000 }, + {CTRY_KUWAIT, NULL1_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_LATVIA, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_LEBANON, NULL1_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_LIECHTENSTEIN,ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_LITHUANIA, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_LUXEMBOURG, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_MACAU, FCC2_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_MACEDONIA, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 }, + {CTRY_MALAYSIA, APL8_WORLD, YES, NO, NO, YES, NO, YES, NO, 7000 }, + {CTRY_MALTA, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_MEXICO, FCC1_FCCA, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_MONACO, ETSI4_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_MOROCCO, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 }, + {CTRY_NETHERLANDS, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_NEW_ZEALAND, FCC2_ETSIC, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_NORWAY, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_OMAN, APL6_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_PAKISTAN, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 }, + {CTRY_PANAMA, FCC1_FCCA, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_PERU, APL1_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_PHILIPPINES, FCC3_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_POLAND, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_PORTUGAL, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_PUERTO_RICO, FCC1_FCCA, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_QATAR, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 }, + {CTRY_ROMANIA, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 }, + {CTRY_RUSSIA, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 }, + {CTRY_SAUDI_ARABIA,FCC2_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_SINGAPORE, APL6_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_SLOVAKIA, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_SLOVENIA, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_SOUTH_AFRICA,FCC3_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_SPAIN, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_SR9, SR9_WORLD, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_SWEDEN, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_SWITZERLAND, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_SYRIA, NULL1_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_TAIWAN, APL3_FCCA, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_THAILAND, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 }, + {CTRY_TRINIDAD_Y_TOBAGO,ETSI4_WORLD,YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_TUNISIA, ETSI3_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_TURKEY, ETSI3_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_UKRAINE, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 }, + {CTRY_UAE, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 }, + {CTRY_UNITED_KINGDOM, ETSI1_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_UNITED_STATES, FCC1_FCCA, YES, YES, YES, YES,YES, YES,YES, 5825 }, + {CTRY_UNITED_STATES_FCC49,FCC4_FCCA,YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_URUGUAY, FCC1_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_UZBEKISTAN, FCC3_FCCA, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_VENEZUELA, APL2_ETSIC, YES, NO, YES, YES,YES, YES, NO, 7000 }, + {CTRY_VIET_NAM, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 }, + {CTRY_XR9, XR9_WORLD, YES, NO, NO, NO, NO, NO, NO, 7000 }, + {CTRY_YEMEN, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 }, + {CTRY_ZIMBABWE, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 } +}; + +/* Bit masks for DFS per regdomain */ +enum { + NO_DFS = 0x0000000000000000ULL, /* NB: must be zero */ + DFS_FCC3 = 0x0000000000000001ULL, + DFS_ETSI = 0x0000000000000002ULL, + DFS_MKK4 = 0x0000000000000004ULL, +}; + +#define AFTER(x) ((x)+1) + +/* + * Frequency band collections are defined using bitmasks. Each bit + * in a mask is the index of an entry in one of the following tables. + * Bitmasks are BMLEN*64 bits so if a table grows beyond that the bit + * vectors must be enlarged or the tables split somehow (e.g. split + * 1/2 and 1/4 rate channels into a separate table). + * + * Beware of ordering; the indices are defined relative to the preceding + * entry so if things get off there will be confusion. A good way to + * check the indices is to collect them in a switch statement in a stub + * function so the compiler checks for duplicates. + */ + +typedef struct { + uint16_t lowChannel; /* Low channel center in MHz */ + uint16_t highChannel; /* High Channel center in MHz */ + uint8_t powerDfs; /* Max power (dBm) for channel + range when using DFS */ + uint8_t antennaMax; /* Max allowed antenna gain */ + uint8_t channelBW; /* Bandwidth of the channel */ + uint8_t channelSep; /* Channel separation within + the band */ + uint64_t useDfs; /* Use DFS in the RegDomain + if corresponding bit is set */ + uint64_t usePassScan; /* Use Passive Scan in the RegDomain + if corresponding bit is set */ + uint8_t regClassId; /* Regulatory class id */ +} REG_DMN_FREQ_BAND; + +/* + * 5GHz 11A channel tags + */ +static REG_DMN_FREQ_BAND regDmn5GhzFreq[] = { + { 4915, 4925, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16 }, +#define F1_4915_4925 0 + { 4935, 4945, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16 }, +#define F1_4935_4945 AFTER(F1_4915_4925) + { 4920, 4980, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 7 }, +#define F1_4920_4980 AFTER(F1_4935_4945) + { 4942, 4987, 27, 6, 5, 5, NO_DFS, PSCAN_FCC, 0 }, +#define F1_4942_4987 AFTER(F1_4920_4980) + { 4945, 4985, 30, 6, 10, 5, NO_DFS, PSCAN_FCC, 0 }, +#define F1_4945_4985 AFTER(F1_4942_4987) + { 4950, 4980, 33, 6, 20, 5, NO_DFS, PSCAN_FCC, 0 }, +#define F1_4950_4980 AFTER(F1_4945_4985) + { 5035, 5040, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12 }, +#define F1_5035_5040 AFTER(F1_4950_4980) + { 5040, 5080, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 2 }, +#define F1_5040_5080 AFTER(F1_5035_5040) + { 5055, 5055, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12 }, +#define F1_5055_5055 AFTER(F1_5040_5080) + + { 5120, 5240, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F1_5120_5240 AFTER(F1_5055_5055) + { 5120, 5240, 5, 6, 10, 10, NO_DFS, NO_PSCAN, 0 }, +#define F2_5120_5240 AFTER(F1_5120_5240) + { 5120, 5240, 5, 6, 5, 5, NO_DFS, NO_PSCAN, 0 }, +#define F3_5120_5240 AFTER(F2_5120_5240) + + { 5170, 5230, 23, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1 }, +#define F1_5170_5230 AFTER(F3_5120_5240) + { 5170, 5230, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1 }, +#define F2_5170_5230 AFTER(F1_5170_5230) + + { 5180, 5240, 15, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F1_5180_5240 AFTER(F2_5170_5230) + { 5180, 5240, 17, 6, 20, 20, NO_DFS, PSCAN_FCC, 1 }, +#define F2_5180_5240 AFTER(F1_5180_5240) + { 5180, 5240, 18, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F3_5180_5240 AFTER(F2_5180_5240) + { 5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F4_5180_5240 AFTER(F3_5180_5240) + { 5180, 5240, 23, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F5_5180_5240 AFTER(F4_5180_5240) + { 5180, 5240, 23, 6, 20, 20, NO_DFS, PSCAN_FCC, 0 }, +#define F6_5180_5240 AFTER(F5_5180_5240) + { 5180, 5240, 17, 6, 20, 10, NO_DFS, PSCAN_FCC, 1 }, +#define F7_5180_5240 AFTER(F6_5180_5240) + { 5180, 5240, 17, 6, 20, 5, NO_DFS, PSCAN_FCC, 1 }, +#define F8_5180_5240 AFTER(F7_5180_5240) + + { 5180, 5320, 20, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 }, +#define F1_5180_5320 AFTER(F8_5180_5240) + + { 5240, 5280, 23, 0, 20, 20, DFS_FCC3, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F1_5240_5280 AFTER(F1_5180_5320) + + { 5260, 5280, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F1_5260_5280 AFTER(F1_5240_5280) + + { 5260, 5320, 18, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F1_5260_5320 AFTER(F1_5260_5280) + + { 5260, 5320, 20, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_FCC | PSCAN_ETSI | PSCAN_MKK3 , 0 }, +#define F2_5260_5320 AFTER(F1_5260_5320) + + { 5260, 5320, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 }, +#define F3_5260_5320 AFTER(F2_5260_5320) + { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 }, +#define F4_5260_5320 AFTER(F3_5260_5320) + { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0 }, +#define F5_5260_5320 AFTER(F4_5260_5320) + { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F6_5260_5320 AFTER(F5_5260_5320) + { 5260, 5320, 23, 6, 20, 10, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 }, +#define F7_5260_5320 AFTER(F6_5260_5320) + { 5260, 5320, 23, 6, 20, 5, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 }, +#define F8_5260_5320 AFTER(F7_5260_5320) + + { 5260, 5700, 5, 6, 20, 20, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0 }, +#define F1_5260_5700 AFTER(F8_5260_5320) + { 5260, 5700, 5, 6, 10, 10, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0 }, +#define F2_5260_5700 AFTER(F1_5260_5700) + { 5260, 5700, 5, 6, 5, 5, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0 }, +#define F3_5260_5700 AFTER(F2_5260_5700) + + { 5280, 5320, 17, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0 }, +#define F1_5280_5320 AFTER(F3_5260_5700) + + { 5500, 5620, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 }, +#define F1_5500_5620 AFTER(F1_5280_5320) + + { 5500, 5700, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 4 }, +#define F1_5500_5700 AFTER(F1_5500_5620) + { 5500, 5700, 27, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F2_5500_5700 AFTER(F1_5500_5700) + { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F3_5500_5700 AFTER(F2_5500_5700) + { 5500, 5700, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_MKK3 | PSCAN_FCC, 0 }, +#define F4_5500_5700 AFTER(F3_5500_5700) + + { 5745, 5805, 23, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F1_5745_5805 AFTER(F4_5500_5700) + { 5745, 5805, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F2_5745_5805 AFTER(F1_5745_5805) + { 5745, 5805, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 }, +#define F3_5745_5805 AFTER(F2_5745_5805) + { 5745, 5825, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F1_5745_5825 AFTER(F3_5745_5805) + { 5745, 5825, 17, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F2_5745_5825 AFTER(F1_5745_5825) + { 5745, 5825, 20, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F3_5745_5825 AFTER(F2_5745_5825) + { 5745, 5825, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F4_5745_5825 AFTER(F3_5745_5825) + { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 3 }, +#define F5_5745_5825 AFTER(F4_5745_5825) + { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F6_5745_5825 AFTER(F5_5745_5825) + { 5745, 5825, 5, 6, 10, 10, NO_DFS, NO_PSCAN, 0 }, +#define F7_5745_5825 AFTER(F6_5745_5825) + { 5745, 5825, 5, 6, 5, 5, NO_DFS, NO_PSCAN, 0 }, +#define F8_5745_5825 AFTER(F7_5745_5825) + { 5745, 5825, 30, 6, 20, 10, NO_DFS, NO_PSCAN, 3 }, +#define F9_5745_5825 AFTER(F8_5745_5825) + { 5745, 5825, 30, 6, 20, 5, NO_DFS, NO_PSCAN, 3 }, +#define F10_5745_5825 AFTER(F9_5745_5825) + + /* + * Below are the world roaming channels + * All WWR domains have no power limit, instead use the card's CTL + * or max power settings. + */ + { 4920, 4980, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, +#define W1_4920_4980 AFTER(F10_5745_5825) + { 5040, 5080, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, +#define W1_5040_5080 AFTER(W1_4920_4980) + { 5170, 5230, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 }, +#define W1_5170_5230 AFTER(W1_5040_5080) + { 5180, 5240, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 }, +#define W1_5180_5240 AFTER(W1_5170_5230) + { 5260, 5320, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 }, +#define W1_5260_5320 AFTER(W1_5180_5240) + { 5745, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, +#define W1_5745_5825 AFTER(W1_5260_5320) + { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 }, +#define W1_5500_5700 AFTER(W1_5745_5825) + { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define W2_5260_5320 AFTER(W1_5500_5700) + { 5180, 5240, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define W2_5180_5240 AFTER(W2_5260_5320) + { 5825, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, +#define W2_5825_5825 AFTER(W2_5180_5240) +}; + +/* + * 5GHz Turbo (dynamic & static) tags + */ +static REG_DMN_FREQ_BAND regDmn5GhzTurboFreq[] = { + { 5130, 5210, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_5130_5210 0 + { 5250, 5330, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0}, +#define T1_5250_5330 AFTER(T1_5130_5210) + { 5370, 5490, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_5370_5490 AFTER(T1_5250_5330) + { 5530, 5650, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0}, +#define T1_5530_5650 AFTER(T1_5370_5490) + + { 5150, 5190, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_5150_5190 AFTER(T1_5530_5650) + { 5230, 5310, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0}, +#define T1_5230_5310 AFTER(T1_5150_5190) + { 5350, 5470, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_5350_5470 AFTER(T1_5230_5310) + { 5510, 5670, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0}, +#define T1_5510_5670 AFTER(T1_5350_5470) + + { 5200, 5240, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_5200_5240 AFTER(T1_5510_5670) + { 5200, 5240, 23, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T2_5200_5240 AFTER(T1_5200_5240) + { 5210, 5210, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_5210_5210 AFTER(T2_5200_5240) + { 5210, 5210, 23, 0, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T2_5210_5210 AFTER(T1_5210_5210) + + { 5280, 5280, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, +#define T1_5280_5280 AFTER(T2_5210_5210) + { 5280, 5280, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, +#define T2_5280_5280 AFTER(T1_5280_5280) + { 5250, 5250, 17, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, +#define T1_5250_5250 AFTER(T2_5280_5280) + { 5290, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, +#define T1_5290_5290 AFTER(T1_5250_5250) + { 5250, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, +#define T1_5250_5290 AFTER(T1_5290_5290) + { 5250, 5290, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, +#define T2_5250_5290 AFTER(T1_5250_5290) + + { 5540, 5660, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, +#define T1_5540_5660 AFTER(T2_5250_5290) + { 5760, 5800, 20, 0, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_5760_5800 AFTER(T1_5540_5660) + { 5760, 5800, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T2_5760_5800 AFTER(T1_5760_5800) + + { 5765, 5805, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_5765_5805 AFTER(T2_5760_5800) + + /* + * Below are the WWR frequencies + */ + { 5210, 5250, 15, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0}, +#define WT1_5210_5250 AFTER(T1_5765_5805) + { 5290, 5290, 18, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0}, +#define WT1_5290_5290 AFTER(WT1_5210_5250) + { 5540, 5660, 20, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0}, +#define WT1_5540_5660 AFTER(WT1_5290_5290) + { 5760, 5800, 20, 0, 40, 40, NO_DFS, PSCAN_WWR, 0}, +#define WT1_5760_5800 AFTER(WT1_5540_5660) +}; + +/* + * 2GHz 11b channel tags + */ +static REG_DMN_FREQ_BAND regDmn2GhzFreq[] = { + { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F1_2312_2372 0 + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F2_2312_2372 AFTER(F1_2312_2372) + + { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F1_2412_2472 AFTER(F2_2312_2372) + { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0}, +#define F2_2412_2472 AFTER(F1_2412_2472) + { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F3_2412_2472 AFTER(F2_2412_2472) + + { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F1_2412_2462 AFTER(F3_2412_2472) + { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0}, +#define F2_2412_2462 AFTER(F1_2412_2462) + + { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F1_2432_2442 AFTER(F2_2412_2462) + + { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F1_2457_2472 AFTER(F1_2432_2442) + + { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0}, +#define F1_2467_2472 AFTER(F1_2457_2472) + + { 2484, 2484, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F1_2484_2484 AFTER(F1_2467_2472) + { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2, 0}, +#define F2_2484_2484 AFTER(F1_2484_2484) + + { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F1_2512_2732 AFTER(F2_2484_2484) + + /* + * WWR have powers opened up to 20dBm. + * Limits should often come from CTL/Max powers + */ + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define W1_2312_2372 AFTER(F1_2512_2732) + { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define W1_2412_2412 AFTER(W1_2312_2372) + { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define W1_2417_2432 AFTER(W1_2412_2412) + { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define W1_2437_2442 AFTER(W1_2417_2432) + { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define W1_2447_2457 AFTER(W1_2437_2442) + { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define W1_2462_2462 AFTER(W1_2447_2457) + { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, +#define W1_2467_2467 AFTER(W1_2462_2462) + { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, +#define W2_2467_2467 AFTER(W1_2467_2467) + { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, +#define W1_2472_2472 AFTER(W2_2467_2467) + { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, +#define W2_2472_2472 AFTER(W1_2472_2472) + { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, +#define W1_2484_2484 AFTER(W2_2472_2472) + { 2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, +#define W2_2484_2484 AFTER(W1_2484_2484) +}; + +/* + * 2GHz 11g channel tags + */ +static REG_DMN_FREQ_BAND regDmn2Ghz11gFreq[] = { + { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define G1_2312_2372 0 + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define G2_2312_2372 AFTER(G1_2312_2372) + { 2312, 2372, 5, 6, 10, 5, NO_DFS, NO_PSCAN, 0}, +#define G3_2312_2372 AFTER(G2_2312_2372) + { 2312, 2372, 5, 6, 5, 5, NO_DFS, NO_PSCAN, 0}, +#define G4_2312_2372 AFTER(G3_2312_2372) + + { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define G1_2412_2472 AFTER(G4_2312_2372) + { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0}, +#define G2_2412_2472 AFTER(G1_2412_2472) + { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define G3_2412_2472 AFTER(G2_2412_2472) + { 2412, 2472, 5, 6, 10, 5, NO_DFS, NO_PSCAN, 0}, +#define G4_2412_2472 AFTER(G3_2412_2472) + { 2412, 2472, 5, 6, 5, 5, NO_DFS, NO_PSCAN, 0}, +#define G5_2412_2472 AFTER(G4_2412_2472) + + { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define G1_2412_2462 AFTER(G5_2412_2472) + { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0}, +#define G2_2412_2462 AFTER(G1_2412_2462) + { 2412, 2462, 27, 6, 10, 5, NO_DFS, NO_PSCAN, 0}, +#define G3_2412_2462 AFTER(G2_2412_2462) + { 2412, 2462, 27, 6, 5, 5, NO_DFS, NO_PSCAN, 0}, +#define G4_2412_2462 AFTER(G3_2412_2462) + + { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define G1_2432_2442 AFTER(G4_2412_2462) + + { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define G1_2457_2472 AFTER(G1_2432_2442) + + { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define G1_2512_2732 AFTER(G1_2457_2472) + { 2512, 2732, 5, 6, 10, 5, NO_DFS, NO_PSCAN, 0}, +#define G2_2512_2732 AFTER(G1_2512_2732) + { 2512, 2732, 5, 6, 5, 5, NO_DFS, NO_PSCAN, 0}, +#define G3_2512_2732 AFTER(G2_2512_2732) + + { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0 }, +#define G1_2467_2472 AFTER(G3_2512_2732) + + /* + * WWR open up the power to 20dBm + */ + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define WG1_2312_2372 AFTER(G1_2467_2472) + { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define WG1_2412_2412 AFTER(WG1_2312_2372) + { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define WG1_2417_2432 AFTER(WG1_2412_2412) + { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define WG1_2437_2442 AFTER(WG1_2417_2432) + { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define WG1_2447_2457 AFTER(WG1_2437_2442) + { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define WG1_2462_2462 AFTER(WG1_2447_2457) + { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, +#define WG1_2467_2467 AFTER(WG1_2462_2462) + { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, +#define WG2_2467_2467 AFTER(WG1_2467_2467) + { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, +#define WG1_2472_2472 AFTER(WG2_2467_2467) + { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, +#define WG2_2472_2472 AFTER(WG1_2472_2472) + + /* + * Mapping for 900MHz cards like Ubiquiti SR9 and XR9 + * and ZComax GZ-901. + */ + { 2422, 2437, 30, 0, 5, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S1_907_922_5 AFTER(WG2_2472_2472) + { 2422, 2437, 30, 0, 10, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S1_907_922_10 AFTER(S1_907_922_5) + { 2427, 2432, 30, 0, 20, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S1_912_917 AFTER(S1_907_922_10) + { 2427, 2442, 30, 0, 5, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S2_907_922_5 AFTER(S1_912_917) + { 2427, 2442, 30, 0, 10, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S2_907_922_10 AFTER(S2_907_922_5) + { 2432, 2437, 30, 0, 20, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S2_912_917 AFTER(S2_907_922_10) + { 2452, 2467, 30, 0, 5, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S1_908_923_5 AFTER(S2_912_917) + { 2457, 2467, 30, 0, 10, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S1_913_918_10 AFTER(S1_908_923_5) + { 2457, 2467, 30, 0, 20, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S1_913_918 AFTER(S1_913_918_10) +}; + +/* + * 2GHz Dynamic turbo tags + */ +static REG_DMN_FREQ_BAND regDmn2Ghz11gTurboFreq[] = { + { 2312, 2372, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_2312_2372 0 + { 2437, 2437, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_2437_2437 AFTER(T1_2312_2372) + { 2437, 2437, 20, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T2_2437_2437 AFTER(T1_2437_2437) + { 2437, 2437, 18, 6, 40, 40, NO_DFS, PSCAN_WWR, 0}, +#define T3_2437_2437 AFTER(T2_2437_2437) + { 2512, 2732, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_2512_2732 AFTER(T3_2437_2437) +}; + +typedef struct regDomain { + uint16_t regDmnEnum; /* value from EnumRd table */ + uint8_t conformanceTestLimit; + uint32_t flags; /* Requirement flags (AdHoc disallow, + noise floor cal needed, etc) */ + uint64_t dfsMask; /* DFS bitmask for 5Ghz tables */ + uint64_t pscan; /* Bitmask for passive scan */ + chanbmask_t chan11a; /* 11a channels */ + chanbmask_t chan11a_turbo; /* 11a static turbo channels */ + chanbmask_t chan11a_dyn_turbo; /* 11a dynamic turbo channels */ + chanbmask_t chan11a_half; /* 11a 1/2 width channels */ + chanbmask_t chan11a_quarter; /* 11a 1/4 width channels */ + chanbmask_t chan11b; /* 11b channels */ + chanbmask_t chan11g; /* 11g channels */ + chanbmask_t chan11g_turbo; /* 11g dynamic turbo channels */ + chanbmask_t chan11g_half; /* 11g 1/2 width channels */ + chanbmask_t chan11g_quarter; /* 11g 1/4 width channels */ +} REG_DOMAIN; + +static REG_DOMAIN regDomains[] = { + + {.regDmnEnum = DEBUG_REG_DMN, + .conformanceTestLimit = FCC, + .dfsMask = DFS_FCC3, + .chan11a = BM3(F1_5120_5240, F1_5260_5700, F1_5745_5825), + .chan11a_half = BM3(F2_5120_5240, F2_5260_5700, F7_5745_5825), + .chan11a_quarter = BM3(F3_5120_5240, F3_5260_5700, F8_5745_5825), + .chan11a_turbo = BM8(T1_5130_5210, + T1_5250_5330, + T1_5370_5490, + T1_5530_5650, + T1_5150_5190, + T1_5230_5310, + T1_5350_5470, + T1_5510_5670), + .chan11a_dyn_turbo = BM4(T1_5200_5240, + T1_5280_5280, + T1_5540_5660, + T1_5765_5805), + .chan11b = BM4(F1_2312_2372, + F1_2412_2472, + F1_2484_2484, + F1_2512_2732), + .chan11g = BM3(G1_2312_2372, G1_2412_2472, G1_2512_2732), + .chan11g_turbo = BM3(T1_2312_2372, T1_2437_2437, T1_2512_2732), + .chan11g_half = BM3(G2_2312_2372, G4_2412_2472, G2_2512_2732), + .chan11g_quarter = BM3(G3_2312_2372, G5_2412_2472, G3_2512_2732), + }, + + {.regDmnEnum = APL1, + .conformanceTestLimit = FCC, + .chan11a = BM1(F4_5745_5825), + }, + + {.regDmnEnum = APL2, + .conformanceTestLimit = FCC, + .chan11a = BM1(F1_5745_5805), + }, + + {.regDmnEnum = APL3, + .conformanceTestLimit = FCC, + .chan11a = BM2(F1_5280_5320, F2_5745_5805), + }, + + {.regDmnEnum = APL4, + .conformanceTestLimit = FCC, + .chan11a = BM2(F4_5180_5240, F3_5745_5825), + }, + + {.regDmnEnum = APL5, + .conformanceTestLimit = FCC, + .chan11a = BM1(F2_5745_5825), + }, + + {.regDmnEnum = APL6, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_FCC_T | PSCAN_FCC, + .chan11a = BM3(F4_5180_5240, F2_5260_5320, F3_5745_5825), + .chan11a_turbo = BM3(T2_5210_5210, T1_5250_5290, T1_5760_5800), + }, + + {.regDmnEnum = APL8, + .conformanceTestLimit = ETSI, + .flags = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, + .chan11a = BM2(F6_5260_5320, F4_5745_5825), + }, + + {.regDmnEnum = APL9, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(F1_5180_5320, F1_5500_5620, F3_5745_5805), + }, + + {.regDmnEnum = ETSI1, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(W2_5180_5240, F2_5260_5320, F2_5500_5700), + }, + + {.regDmnEnum = ETSI2, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM1(F3_5180_5240), + }, + + {.regDmnEnum = ETSI3, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM2(W2_5180_5240, F2_5260_5320), + }, + + {.regDmnEnum = ETSI4, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM2(F3_5180_5240, F1_5260_5320), + }, + + {.regDmnEnum = ETSI5, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM1(F1_5180_5240), + }, + + {.regDmnEnum = ETSI6, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(F5_5180_5240, F1_5260_5280, F3_5500_5700), + }, + + {.regDmnEnum = FCC1, + .conformanceTestLimit = FCC, + .chan11a = BM3(F2_5180_5240, F4_5260_5320, F5_5745_5825), + .chan11a_turbo = BM3(T1_5210_5210, T2_5250_5290, T2_5760_5800), + .chan11a_dyn_turbo = BM3(T1_5200_5240, T1_5280_5280, T1_5765_5805), + }, + + {.regDmnEnum = FCC2, + .conformanceTestLimit = FCC, + .chan11a = BM3(F6_5180_5240, F5_5260_5320, F6_5745_5825), + .chan11a_dyn_turbo = BM3(T2_5200_5240, T1_5280_5280, T1_5765_5805), + }, + + {.regDmnEnum = FCC3, + .conformanceTestLimit = FCC, + .dfsMask = DFS_FCC3, + .pscan = PSCAN_FCC | PSCAN_FCC_T, + .chan11a = BM4(F2_5180_5240, + F3_5260_5320, + F1_5500_5700, + F5_5745_5825), + .chan11a_turbo = BM4(T1_5210_5210, + T1_5250_5250, + T1_5290_5290, + T2_5760_5800), + .chan11a_dyn_turbo = BM3(T1_5200_5240, T2_5280_5280, T1_5540_5660), + }, + + {.regDmnEnum = FCC4, + .conformanceTestLimit = FCC, + .dfsMask = DFS_FCC3, + .pscan = PSCAN_FCC | PSCAN_FCC_T, + .chan11a = BM1(F1_4950_4980), + .chan11a_half = BM1(F1_4945_4985), + .chan11a_quarter = BM1(F1_4942_4987), + }, + + /* FCC1 w/ 1/2 and 1/4 width channels */ + {.regDmnEnum = FCC5, + .conformanceTestLimit = FCC, + .chan11a = BM3(F2_5180_5240, F4_5260_5320, F5_5745_5825), + .chan11a_turbo = BM3(T1_5210_5210, T2_5250_5290, T2_5760_5800), + .chan11a_dyn_turbo = BM3(T1_5200_5240, T1_5280_5280, T1_5765_5805), + .chan11a_half = BM3(F7_5180_5240, F7_5260_5320, F9_5745_5825), + .chan11a_quarter = BM3(F8_5180_5240, F8_5260_5320,F10_5745_5825), + }, + + {.regDmnEnum = MKK1, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKK1, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM1(F1_5170_5230), + }, + + {.regDmnEnum = MKK2, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKK2, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(F1_4920_4980, F1_5040_5080, F1_5170_5230), + .chan11a_half = BM4(F1_4915_4925, + F1_4935_4945, + F1_5035_5040, + F1_5055_5055), + }, + + /* UNI-1 even */ + {.regDmnEnum = MKK3, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM1(F4_5180_5240), + }, + + /* UNI-1 even + UNI-2 */ + {.regDmnEnum = MKK4, + .conformanceTestLimit = MKK, + .dfsMask = DFS_MKK4, + .pscan = PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM2(F4_5180_5240, F2_5260_5320), + }, + + /* UNI-1 even + UNI-2 + mid-band */ + {.regDmnEnum = MKK5, + .conformanceTestLimit = MKK, + .dfsMask = DFS_MKK4, + .pscan = PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(F4_5180_5240, F2_5260_5320, F4_5500_5700), + }, + + /* UNI-1 odd + even */ + {.regDmnEnum = MKK6, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKK1, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM2(F2_5170_5230, F4_5180_5240), + }, + + /* UNI-1 odd + UNI-1 even + UNI-2 */ + {.regDmnEnum = MKK7, + .conformanceTestLimit = MKK, + .dfsMask = DFS_MKK4, + .pscan = PSCAN_MKK1 | PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(F1_5170_5230, F4_5180_5240, F2_5260_5320), + }, + + /* UNI-1 odd + UNI-1 even + UNI-2 + mid-band */ + {.regDmnEnum = MKK8, + .conformanceTestLimit = MKK, + .dfsMask = DFS_MKK4, + .pscan = PSCAN_MKK1 | PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM4(F1_5170_5230, + F4_5180_5240, + F2_5260_5320, + F4_5500_5700), + }, + + /* UNI-1 even + 4.9 GHZ */ + {.regDmnEnum = MKK9, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM7(F1_4915_4925, + F1_4935_4945, + F1_4920_4980, + F1_5035_5040, + F1_5055_5055, + F1_5040_5080, + F4_5180_5240), + }, + + /* UNI-1 even + UNI-2 + 4.9 GHZ */ + {.regDmnEnum = MKK10, + .conformanceTestLimit = MKK, + .dfsMask = DFS_MKK4, + .pscan = PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM8(F1_4915_4925, + F1_4935_4945, + F1_4920_4980, + F1_5035_5040, + F1_5055_5055, + F1_5040_5080, + F4_5180_5240, + F2_5260_5320), + }, + + /* Defined here to use when 2G channels are authorised for country K2 */ + {.regDmnEnum = APLD, + .conformanceTestLimit = NO_CTL, + .chan11b = BM2(F2_2312_2372,F2_2412_2472), + .chan11g = BM2(G2_2312_2372,G2_2412_2472), + }, + + {.regDmnEnum = ETSIA, + .conformanceTestLimit = NO_CTL, + .pscan = PSCAN_ETSIA, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11b = BM1(F1_2457_2472), + .chan11g = BM1(G1_2457_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = ETSIB, + .conformanceTestLimit = ETSI, + .pscan = PSCAN_ETSIB, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11b = BM1(F1_2432_2442), + .chan11g = BM1(G1_2432_2442), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = ETSIC, + .conformanceTestLimit = ETSI, + .pscan = PSCAN_ETSIC, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11b = BM1(F3_2412_2472), + .chan11g = BM1(G3_2412_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = FCCA, + .conformanceTestLimit = FCC, + .chan11b = BM1(F1_2412_2462), + .chan11g = BM1(G1_2412_2462), + .chan11g_turbo = BM1(T2_2437_2437), + }, + + /* FCCA w/ 1/2 and 1/4 width channels */ + {.regDmnEnum = FCCB, + .conformanceTestLimit = FCC, + .chan11b = BM1(F1_2412_2462), + .chan11g = BM1(G1_2412_2462), + .chan11g_turbo = BM1(T2_2437_2437), + .chan11g_half = BM1(G3_2412_2462), + .chan11g_quarter = BM1(G4_2412_2462), + }, + + {.regDmnEnum = MKKA, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKKA | PSCAN_MKKA_G + | PSCAN_MKKA1 | PSCAN_MKKA1_G + | PSCAN_MKKA2 | PSCAN_MKKA2_G, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11b = BM3(F2_2412_2462, F1_2467_2472, F2_2484_2484), + .chan11g = BM2(G2_2412_2462, G1_2467_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = MKKC, + .conformanceTestLimit = MKK, + .chan11b = BM1(F2_2412_2472), + .chan11g = BM1(G2_2412_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = WORLD, + .conformanceTestLimit = ETSI, + .chan11b = BM1(F2_2412_2472), + .chan11g = BM1(G2_2412_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = WOR0_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_PER_11D, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM8(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467, + W1_2484_2484), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437) + }, + + {.regDmnEnum = WOR01_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_PER_11D, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM5(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2417_2432, + W1_2447_2457), + .chan11g = BM5(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2417_2432, + WG1_2447_2457), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR02_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_PER_11D, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = EU1_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_PER_11D, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W2_2472_2472, + W1_2417_2432, + W1_2447_2457, + W2_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG2_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG2_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR1_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_NO_11A, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11b = BM8(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467, + W1_2484_2484), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437) + }, + + {.regDmnEnum = WOR2_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_NO_11A, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM8(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467, + W1_2484_2484), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR3_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_PER_11D, + .chan11a = BM4(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR4_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_NO_11A, + .chan11a = BM4(W2_5260_5320, + W2_5180_5240, + F2_5745_5805, + W2_5825_5825), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM5(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2417_2432, + W1_2447_2457), + .chan11g = BM5(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2417_2432, + WG1_2447_2457), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR5_ETSIC, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_NO_11A, + .chan11a = BM3(W1_5260_5320, W2_5180_5240, F6_5745_5825), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W2_2472_2472, + W1_2417_2432, + W1_2447_2457, + W2_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG2_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG2_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR9_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_NO_11A, + .chan11a = BM4(W1_5260_5320, + W1_5180_5240, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM5(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2417_2432, + W1_2447_2457), + .chan11g = BM5(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2417_2432, + WG1_2447_2457), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WORA_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_NO_11A, + .chan11a = BM4(W1_5260_5320, + W1_5180_5240, + W1_5745_5825, + W1_5500_5700), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = SR9_WORLD, + .conformanceTestLimit = NO_CTL, + .pscan = PSCAN_FCC | PSCAN_FCC_T, + .chan11g = BM1(S1_912_917), + .chan11g_half = BM1(S1_907_922_10), + .chan11g_quarter = BM1(S1_907_922_5), + }, + + {.regDmnEnum = XR9_WORLD, + .conformanceTestLimit = NO_CTL, + .pscan = PSCAN_FCC | PSCAN_FCC_T, + .chan11g = BM1(S2_912_917), + .chan11g_half = BM1(S2_907_922_10), + .chan11g_quarter = BM1(S2_907_922_5), + }, + + {.regDmnEnum = GZ901_WORLD, + .conformanceTestLimit = NO_CTL, + .pscan = PSCAN_FCC | PSCAN_FCC_T, + .chan11g = BM1(S1_913_918), + .chan11g_half = BM1(S1_913_918_10), + .chan11g_quarter = BM1(S1_908_923_5), + }, + + {.regDmnEnum = NULL1, + .conformanceTestLimit = NO_CTL, + } +}; + +struct cmode { + u_int mode; + u_int flags; +}; + +static const struct cmode modes[] = { + { HAL_MODE_TURBO, CHANNEL_ST}, /* NB: 11a Static Turbo */ + { HAL_MODE_11A, CHANNEL_A}, + { HAL_MODE_11B, CHANNEL_B}, + { HAL_MODE_11G, CHANNEL_G}, + { HAL_MODE_11G_TURBO, CHANNEL_108G}, + { HAL_MODE_11A_TURBO, CHANNEL_108A}, + { HAL_MODE_11A_QUARTER_RATE, CHANNEL_A | CHANNEL_QUARTER}, + { HAL_MODE_11A_HALF_RATE, CHANNEL_A | CHANNEL_HALF}, + { HAL_MODE_11G_QUARTER_RATE, CHANNEL_G | CHANNEL_QUARTER}, + { HAL_MODE_11G_HALF_RATE, CHANNEL_G | CHANNEL_HALF}, + { HAL_MODE_11NG_HT20, CHANNEL_G_HT20}, + { HAL_MODE_11NG_HT40PLUS, CHANNEL_G_HT40PLUS}, + { HAL_MODE_11NG_HT40MINUS, CHANNEL_G_HT40MINUS}, + { HAL_MODE_11NA_HT20, CHANNEL_A_HT20}, + { HAL_MODE_11NA_HT40PLUS, CHANNEL_A_HT40PLUS}, + { HAL_MODE_11NA_HT40MINUS, CHANNEL_A_HT40MINUS}, +}; + +static int +chansort(const void *a, const void *b) +{ +#define CHAN_FLAGS (CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER) + const HAL_CHANNEL_INTERNAL *ca = a; + const HAL_CHANNEL_INTERNAL *cb = b; + + return (ca->channel == cb->channel) ? + (ca->channelFlags & CHAN_FLAGS) - + (cb->channelFlags & CHAN_FLAGS) : + ca->channel - cb->channel; +#undef CHAN_FLAGS +} +typedef int ath_hal_cmp_t(const void *, const void *); +static void ath_hal_sort(void *a, size_t n, size_t es, ath_hal_cmp_t *cmp); +static COUNTRY_CODE_TO_ENUM_RD* findCountry(HAL_CTRY_CODE countryCode); +static HAL_BOOL getWmRD(struct ath_hal *ah, COUNTRY_CODE_TO_ENUM_RD *country, uint16_t channelFlag, REG_DOMAIN *rd); + + +static uint16_t +getEepromRD(struct ath_hal *ah) +{ + return AH_PRIVATE(ah)->ah_currentRD &~ WORLDWIDE_ROAMING_FLAG; +} + +/* + * Test to see if the bitmask array is all zeros + */ +static HAL_BOOL +isChanBitMaskZero(const uint64_t *bitmask) +{ +#if BMLEN > 2 +#error "add more cases" +#endif +#if BMLEN > 1 + if (bitmask[1] != 0) + return AH_FALSE; +#endif + return (bitmask[0] == 0); +} + +/* + * Return whether or not the regulatory domain/country in EEPROM + * is acceptable. + */ +static HAL_BOOL +isEepromValid(struct ath_hal *ah) +{ + uint16_t rd = getEepromRD(ah); + int i; + + if (rd & COUNTRY_ERD_FLAG) { + uint16_t cc = rd &~ COUNTRY_ERD_FLAG; + for (i = 0; i < N(allCountries); i++) + if (allCountries[i].countryCode == cc) + return AH_TRUE; + } else { + for (i = 0; i < N(regDomainPairs); i++) + if (regDomainPairs[i].regDmnEnum == rd) + return AH_TRUE; + } + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: invalid regulatory domain/country code 0x%x\n", __func__, rd); + return AH_FALSE; +} + +/* + * Returns whether or not the specified country code + * is allowed by the EEPROM setting + */ +static HAL_BOOL +isCountryCodeValid(struct ath_hal *ah, HAL_CTRY_CODE cc) +{ + uint16_t rd; + + /* Default setting requires no checks */ + if (cc == CTRY_DEFAULT) + return AH_TRUE; +#ifdef AH_DEBUG_COUNTRY + if (cc == CTRY_DEBUG) + return AH_TRUE; +#endif + rd = getEepromRD(ah); + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: EEPROM regdomain 0x%x\n", + __func__, rd); + + if (rd & COUNTRY_ERD_FLAG) { + /* EEP setting is a country - config shall match */ + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: EEPROM setting is country code %u\n", __func__, + rd &~ COUNTRY_ERD_FLAG); + return (cc == (rd & ~COUNTRY_ERD_FLAG)); + } else if (rd == DEBUG_REG_DMN || rd == NO_ENUMRD) { + /* Set to Debug or AllowAnyCountry mode - allow any setting */ + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: rd %d allowed\n", + __func__, rd); + return AH_TRUE; +#ifdef AH_SUPPORT_11D + } else if ((rd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) { + int i; + for (i=0; i < N(allCountries); i++) { + if (cc == allCountries[i].countryCode) + return AH_TRUE; + } +#endif + } else { + int i; + for (i = 0; i < N(allCountries); i++) { + if (cc == allCountries[i].countryCode && + allCountries[i].regDmnEnum == rd) + return AH_TRUE; + } + } + return AH_FALSE; +} + +/* + * Return the mask of available modes based on the hardware + * capabilities and the specified country code and reg domain. + */ +static u_int +ath_hal_getwmodesnreg(struct ath_hal *ah, + const COUNTRY_CODE_TO_ENUM_RD *country, const REG_DOMAIN *rd5GHz) +{ +#define HAL_MODE_11G_ALL \ + (HAL_MODE_11G | HAL_MODE_11G_TURBO | HAL_MODE_11G_QUARTER_RATE | \ + HAL_MODE_11G_HALF_RATE) +#define HAL_MODE_11A_ALL \ + (HAL_MODE_11A | HAL_MODE_11A_TURBO | HAL_MODE_TURBO | \ + HAL_MODE_11A_QUARTER_RATE | HAL_MODE_11A_HALF_RATE) + u_int modesAvail; + + /* Get modes that HW is capable of */ + modesAvail = ath_hal_getWirelessModes(ah); + + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: wireless modes 0x%x cc %u rd %u\n", + __func__, modesAvail, country->countryCode, country->regDmnEnum); + + /* Check country regulations for allowed modes */ + if (!country->allow11g && (modesAvail & HAL_MODE_11G_ALL)) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: disallow all 11g\n", __func__); + modesAvail &= ~HAL_MODE_11G_ALL; + } + if (isChanBitMaskZero(rd5GHz->chan11a) && + (modesAvail & HAL_MODE_11A_ALL)) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: disallow all 11a\n", __func__); + modesAvail &= ~HAL_MODE_11A_ALL; + } + if ((modesAvail & (HAL_MODE_11A_TURBO | HAL_MODE_TURBO)) && + !country->allow11aTurbo) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: disallow 11aTurbo\n", __func__); + modesAvail &= ~(HAL_MODE_11A_TURBO | HAL_MODE_TURBO); + } + if ((modesAvail & HAL_MODE_11G_TURBO) && !country->allow11gTurbo) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: disallow 11gTurbo\n", __func__); + modesAvail &= ~HAL_MODE_11G_TURBO; + } + + /* Check 11n operation */ + if ((modesAvail & HAL_MODE_11NG_HT20) && !country->allow11ng20) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: disallow 11g HT20\n", __func__); + modesAvail &= ~HAL_MODE_11NG_HT20; + } + if ((modesAvail & HAL_MODE_11NA_HT20) && !country->allow11na20) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: disallow 11a HT20\n", __func__); + modesAvail &= ~HAL_MODE_11NA_HT20; + } + if ((modesAvail & HAL_MODE_11NG_HT40PLUS) && !country->allow11ng40) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: disallow 11g HT40+\n", __func__); + modesAvail &= ~HAL_MODE_11NG_HT40PLUS; + } + if ((modesAvail & HAL_MODE_11NG_HT40MINUS) && !country->allow11ng40) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: disallow 11g HT40-\n", __func__); + modesAvail &= ~HAL_MODE_11NG_HT40MINUS; + } + if ((modesAvail & HAL_MODE_11NA_HT40PLUS) && !country->allow11na40) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: disallow 11a HT40+\n", __func__); + modesAvail &= ~HAL_MODE_11NA_HT40PLUS; + } + if ((modesAvail & HAL_MODE_11NA_HT40MINUS) && !country->allow11na40) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: disallow 11a HT40-\n", __func__); + modesAvail &= ~HAL_MODE_11NA_HT40MINUS; + } + + return modesAvail; +#undef HAL_MODE_11A_ALL +#undef HAL_MODE_11G_ALL +} + +/* + * Return the mask of available modes based on the hardware + * capabilities and the specified country code. + */ + +u_int +ath_hal_getwirelessmodes(struct ath_hal *ah, HAL_CTRY_CODE cc) +{ + COUNTRY_CODE_TO_ENUM_RD *country = AH_NULL; + u_int mode = 0; + REG_DOMAIN rd; + + country = findCountry(cc); + if (country != AH_NULL) { + if (getWmRD(ah, country, ~CHANNEL_2GHZ, &rd)) + mode = ath_hal_getwmodesnreg(ah, country, &rd); + } + return mode; +} + +/* + * Return if device is public safety. + */ +HAL_BOOL +ath_hal_ispublicsafetysku(struct ath_hal *ah) +{ + uint16_t rd = getEepromRD(ah); + + switch (rd) { + case FCC4_FCCA: + case CTRY_UNITED_STATES_FCC49 | COUNTRY_ERD_FLAG: + return AH_TRUE; + case DEBUG_REG_DMN: + case NO_ENUMRD: + if (AH_PRIVATE(ah)->ah_countryCode == CTRY_UNITED_STATES_FCC49) + return AH_TRUE; + break; + } + return AH_FALSE; +} + +/* + * Return if device is actually operating in 900 MHz band. + */ +HAL_BOOL +ath_hal_isgsmsku(struct ath_hal *ah) +{ + uint16_t rd = getEepromRD(ah); + + switch (rd) { + case SR9_WORLD: + case XR9_WORLD: + case GZ901_WORLD: + case CTRY_SR9 | COUNTRY_ERD_FLAG: + case CTRY_XR9 | COUNTRY_ERD_FLAG: + case CTRY_GZ901 | COUNTRY_ERD_FLAG: + return AH_TRUE; + case DEBUG_REG_DMN: + case NO_ENUMRD: + return AH_PRIVATE(ah)->ah_countryCode == CTRY_SR9 + || AH_PRIVATE(ah)->ah_countryCode == CTRY_XR9 + || AH_PRIVATE(ah)->ah_countryCode == CTRY_GZ901 + ; + } + return AH_FALSE; +} + +/* + * Find the pointer to the country element in the country table + * corresponding to the country code + */ +static COUNTRY_CODE_TO_ENUM_RD* +findCountry(HAL_CTRY_CODE countryCode) +{ + int i; + + for (i = 0; i < N(allCountries); i++) { + if (allCountries[i].countryCode == countryCode) + return &allCountries[i]; + } + return AH_NULL; /* Not found */ +} + +/* + * Calculate a default country based on the EEPROM setting. + */ +static HAL_CTRY_CODE +getDefaultCountry(struct ath_hal *ah) +{ + uint16_t rd; + int i; + + rd = getEepromRD(ah); + if (rd & COUNTRY_ERD_FLAG) { + COUNTRY_CODE_TO_ENUM_RD *country = AH_NULL; + uint16_t cc = rd & ~COUNTRY_ERD_FLAG; + + country = findCountry(cc); + if (country != AH_NULL) + return cc; + } + /* + * Check reg domains that have only one country + */ + for (i = 0; i < N(regDomainPairs); i++) + if (regDomainPairs[i].regDmnEnum == rd) { + if (regDomainPairs[i].singleCC != 0) + return regDomainPairs[i].singleCC; + else + i = N(regDomainPairs); + } + return CTRY_DEFAULT; +} + +static HAL_BOOL +isValidRegDmn(int regDmn, REG_DOMAIN *rd) +{ + int i; + + for (i = 0; i < N(regDomains); i++) { + if (regDomains[i].regDmnEnum == regDmn) { + if (rd != AH_NULL) { + OS_MEMCPY(rd, ®Domains[i], + sizeof(REG_DOMAIN)); + } + return AH_TRUE; + } + } + return AH_FALSE; +} + +static HAL_BOOL +isValidRegDmnPair(int regDmnPair) +{ + int i; + + if (regDmnPair == NO_ENUMRD) + return AH_FALSE; + for (i = 0; i < N(regDomainPairs); i++) { + if (regDomainPairs[i].regDmnEnum == regDmnPair) + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Return the Wireless Mode Regulatory Domain based + * on the country code and the wireless mode. + */ +static HAL_BOOL +getWmRD(struct ath_hal *ah, COUNTRY_CODE_TO_ENUM_RD *country, + uint16_t channelFlag, REG_DOMAIN *rd) +{ + int regDmn; + REG_DMN_PAIR_MAPPING *regPair; + uint64_t flags; + + if (country->countryCode == CTRY_DEFAULT) { + uint16_t rdnum = getEepromRD(ah); + + if ((rdnum & COUNTRY_ERD_FLAG) == 0) { + if (isValidRegDmn(rdnum, AH_NULL) || + isValidRegDmnPair(rdnum)) + regDmn = rdnum; + else + regDmn = country->regDmnEnum; + } else + regDmn = country->regDmnEnum; + } else + regDmn = country->regDmnEnum; + regPair = AH_NULL; + flags = NO_REQ; + if ((regDmn & MULTI_DOMAIN_MASK) == 0) { + int i; + + for (i = 0; i < N(regDomainPairs); i++) { + if (regDomainPairs[i].regDmnEnum == regDmn) { + regPair = ®DomainPairs[i]; + break; + } + } + if (regPair == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: Failed to find reg domain pair %u\n", + __func__, regDmn); + return AH_FALSE; + } + if (channelFlag & CHANNEL_2GHZ) { + regDmn = regPair->regDmn2GHz; + flags = regPair->flags2GHz; + } else { + regDmn = regPair->regDmn5GHz; + flags = regPair->flags5GHz; + } + } + + /* + * We either started with a unitary reg domain or we've found the + * unitary reg domain of the pair + */ + if (isValidRegDmn(regDmn, rd)) { + if (regPair != AH_NULL) + rd->pscan &= regPair->pscanMask; + if ((country->regDmnEnum & MULTI_DOMAIN_MASK) == 0 && + flags != NO_REQ) + rd->flags = flags; + return AH_TRUE; + } else { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: Failed to find unitary reg domain %u\n", __func__, + country->regDmnEnum); + return AH_FALSE; + } +} + +static HAL_BOOL +IS_BIT_SET(int bit, const uint64_t bitmask[]) +{ + int byteOffset, bitnum; + uint64_t val; + + byteOffset = bit/64; + bitnum = bit - byteOffset*64; + val = ((uint64_t) 1) << bitnum; + return (bitmask[byteOffset] & val) != 0; +} + +/* Add given regclassid into regclassids array upto max of maxregids */ +static void +ath_add_regclassid(uint8_t *regclassids, u_int maxregids, + u_int *nregids, uint8_t regclassid) +{ + int i; + + /* Is regclassid valid? */ + if (regclassid == 0) + return; + + for (i = 0; i < maxregids; i++) { + if (regclassids[i] == regclassid) /* already present */ + return; + if (regclassids[i] == 0) { /* free slot */ + regclassids[i] = regclassid; + (*nregids)++; + return; + } + } +} + +/* + * Setup the channel list based on the information in the EEPROM and + * any supplied country code. Note that we also do a bunch of EEPROM + * verification here and setup certain regulatory-related access + * control data used later on. + */ + +HAL_BOOL +ath_hal_init_channels(struct ath_hal *ah, + HAL_CHANNEL *chans, u_int maxchans, u_int *nchans, + uint8_t *regclassids, u_int maxregids, u_int *nregids, + HAL_CTRY_CODE cc, u_int modeSelect, + HAL_BOOL enableOutdoor, HAL_BOOL enableExtendedChannels) +{ +#define CHANNEL_HALF_BW 10 +#define CHANNEL_QUARTER_BW 5 + u_int modesAvail; + uint16_t maxChan; + COUNTRY_CODE_TO_ENUM_RD *country = AH_NULL; + REG_DOMAIN rd5GHz, rd2GHz; + const struct cmode *cm; + HAL_CHANNEL_INTERNAL *ichans = &AH_PRIVATE(ah)->ah_channels[0]; + int next, b; + uint8_t ctl; + + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u mode 0x%x%s%s\n", + __func__, cc, modeSelect, enableOutdoor? " Enable outdoor" : " ", + enableExtendedChannels ? " Enable ecm" : ""); + + /* + * Validate the EEPROM setting and setup defaults + */ + if (!isEepromValid(ah)) { + /* + * Don't return any channels if the EEPROM has an + * invalid regulatory domain/country code setting. + */ + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: invalid EEPROM contents\n",__func__); + return AH_FALSE; + } + + AH_PRIVATE(ah)->ah_countryCode = getDefaultCountry(ah); + +#ifndef AH_SUPPORT_11D + if (AH_PRIVATE(ah)->ah_countryCode == CTRY_DEFAULT) { +#endif + /* + * We now have enough state to validate any country code + * passed in by the caller. + */ + if (!isCountryCodeValid(ah, cc)) { + /* NB: Atheros silently ignores invalid country codes */ + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: invalid country code %d\n", __func__, cc); + return AH_FALSE; + } + AH_PRIVATE(ah)->ah_countryCode = cc & COUNTRY_CODE_MASK; +#ifndef AH_SUPPORT_11D + } +#endif + + /* Get pointers to the country element and the reg domain elements */ + country = findCountry(AH_PRIVATE(ah)->ah_countryCode); + + if (country == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "NULL Country!, cc= %d\n", + AH_PRIVATE(ah)->ah_countryCode); + return AH_FALSE; + } + + if (!getWmRD(ah, country, ~CHANNEL_2GHZ, &rd5GHz)) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: no unitary 5GHz regdomain for country %u\n", + __func__, AH_PRIVATE(ah)->ah_countryCode); + return AH_FALSE; + } + if (!getWmRD(ah, country, CHANNEL_2GHZ, &rd2GHz)) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: no unitary 2GHz regdomain for country %u\n", + __func__, AH_PRIVATE(ah)->ah_countryCode); + return AH_FALSE; + } + + modesAvail = ath_hal_getwmodesnreg(ah, country, &rd5GHz); + maxChan = !enableOutdoor ? country->outdoorChanStart : 7000; + + if (maxchans > N(AH_PRIVATE(ah)->ah_channels)) + maxchans = N(AH_PRIVATE(ah)->ah_channels); + next = 0; + for (cm = modes; cm < &modes[N(modes)]; cm++) { + uint16_t c, c_hi, c_lo; + uint64_t *channelBM = AH_NULL; + REG_DOMAIN *rd = AH_NULL; + REG_DMN_FREQ_BAND *fband = AH_NULL,*freqs; + int low_adj, hi_adj, channelSep, lastc; + + if ((cm->mode & modeSelect) == 0) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: skip mode 0x%x flags 0x%x\n", + __func__, cm->mode, cm->flags); + continue; + } + if ((cm->mode & modesAvail) == 0) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: !avail mode 0x%x (0x%x) flags 0x%x\n", + __func__, modesAvail, cm->mode, cm->flags); + continue; + } + if (!ath_hal_getChannelEdges(ah, cm->flags, &c_lo, &c_hi)) { + /* channel not supported by hardware, skip it */ + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: channels 0x%x not supported by hardware\n", + __func__,cm->flags); + continue; + } + switch (cm->mode) { + case HAL_MODE_TURBO: + rd = &rd5GHz; + channelBM = rd->chan11a_turbo; + freqs = ®Dmn5GhzTurboFreq[0]; + ctl = rd->conformanceTestLimit | CTL_TURBO; + break; + case HAL_MODE_11A: + case HAL_MODE_11A_HALF_RATE: + case HAL_MODE_11A_QUARTER_RATE: + case HAL_MODE_11NA_HT20: + case HAL_MODE_11NA_HT40PLUS: + case HAL_MODE_11NA_HT40MINUS: + rd = &rd5GHz; + if (cm->mode == HAL_MODE_11A_HALF_RATE) + channelBM = rd->chan11a_half; + else if (cm->mode == HAL_MODE_11A_QUARTER_RATE) + channelBM = rd->chan11a_quarter; + else + channelBM = rd->chan11a; + freqs = ®Dmn5GhzFreq[0]; + ctl = rd->conformanceTestLimit; + break; + case HAL_MODE_11B: + rd = &rd2GHz; + channelBM = rd->chan11b; + freqs = ®Dmn2GhzFreq[0]; + ctl = rd->conformanceTestLimit | CTL_11B; + break; + case HAL_MODE_11G: + case HAL_MODE_11G_HALF_RATE: + case HAL_MODE_11G_QUARTER_RATE: + case HAL_MODE_11NG_HT20: + case HAL_MODE_11NG_HT40PLUS: + case HAL_MODE_11NG_HT40MINUS: + rd = &rd2GHz; + if (cm->mode == HAL_MODE_11G_HALF_RATE) + channelBM = rd->chan11g_half; + else if (cm->mode == HAL_MODE_11G_QUARTER_RATE) + channelBM = rd->chan11g_quarter; + else + channelBM = rd->chan11g; + freqs = ®Dmn2Ghz11gFreq[0]; + ctl = rd->conformanceTestLimit | CTL_11G; + break; + case HAL_MODE_11G_TURBO: + rd = &rd2GHz; + channelBM = rd->chan11g_turbo; + freqs = ®Dmn2Ghz11gTurboFreq[0]; + ctl = rd->conformanceTestLimit | CTL_108G; + break; + case HAL_MODE_11A_TURBO: + rd = &rd5GHz; + channelBM = rd->chan11a_dyn_turbo; + freqs = ®Dmn5GhzTurboFreq[0]; + ctl = rd->conformanceTestLimit | CTL_108G; + break; + default: + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: Unkonwn HAL mode 0x%x\n", __func__, cm->mode); + continue; + } + if (isChanBitMaskZero(channelBM)) + continue; + /* + * Setup special handling for HT40 channels; e.g. + * 5G HT40 channels require 40Mhz channel separation. + */ + hi_adj = (cm->mode == HAL_MODE_11NA_HT40PLUS || + cm->mode == HAL_MODE_11NG_HT40PLUS) ? -20 : 0; + low_adj = (cm->mode == HAL_MODE_11NA_HT40MINUS || + cm->mode == HAL_MODE_11NG_HT40MINUS) ? 20 : 0; + channelSep = (cm->mode == HAL_MODE_11NA_HT40PLUS || + cm->mode == HAL_MODE_11NA_HT40MINUS) ? 40 : 0; + + for (b = 0; b < 64*BMLEN; b++) { + if (!IS_BIT_SET(b, channelBM)) + continue; + fband = &freqs[b]; + lastc = 0; + + ath_add_regclassid(regclassids, maxregids, + nregids, fband->regClassId); + + for (c = fband->lowChannel + low_adj; + c <= fband->highChannel + hi_adj; + c += fband->channelSep) { + HAL_CHANNEL_INTERNAL icv; + + if (!(c_lo <= c && c <= c_hi)) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: c %u out of range [%u..%u]\n", + __func__, c, c_lo, c_hi); + continue; + } + if (((c+fband->channelSep)/2) > (maxChan+HALF_MAXCHANBW)) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: c %u > maxChan %u\n", + __func__, c, maxChan); + continue; + } + if (next >= maxchans){ + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: too many channels for channel table\n", + __func__); + goto done; + } + if ((fband->usePassScan & IS_ECM_CHAN) && + !enableExtendedChannels) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "Skipping ecm channel\n"); + continue; + } + /* XXX needs to be in ath_hal_checkchannel */ + if ((rd->flags & NO_HOSTAP) && + (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP)) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "Skipping HOSTAP channel\n"); + continue; + } + /* + * Make sure that channel separation + * meets the requirement. + */ + if (lastc && channelSep && + (c-lastc) < channelSep) + continue; + + OS_MEMZERO(&icv, sizeof(icv)); + icv.channel = c; + icv.channelFlags = cm->flags; + icv.maxRegTxPower = fband->powerDfs; + icv.antennaMax = fband->antennaMax; + icv.regDmnFlags = rd->flags; + icv.conformanceTestLimit = ctl; + if (fband->usePassScan & rd->pscan) + icv.channelFlags |= CHANNEL_PASSIVE; + else + icv.channelFlags &= ~CHANNEL_PASSIVE; + lastc = c; + if (fband->useDfs & rd->dfsMask) { + /* DFS and HT40 don't mix */ + if (cm->mode == HAL_MODE_11NA_HT40PLUS || + cm->mode == HAL_MODE_11NA_HT40MINUS) + continue; + icv.privFlags = CHANNEL_DFS; + } else + icv.privFlags = 0; + if (rd->flags & LIMIT_FRAME_4MS) + icv.privFlags |= CHANNEL_4MS_LIMIT; + + ichans[next++] = icv; + } + } + } +done: + if (next != 0) { + int i; + + /* XXX maxchans set above so this cannot happen? */ + if (next > N(AH_PRIVATE(ah)->ah_channels)) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: too many channels %u; truncating to %u\n", + __func__, next, + (int) N(AH_PRIVATE(ah)->ah_channels)); + next = N(AH_PRIVATE(ah)->ah_channels); + } + + /* + * Keep a private copy of the channel list so we can + * constrain future requests to only these channels + */ + ath_hal_sort(ichans, next, sizeof(HAL_CHANNEL_INTERNAL), + chansort); + AH_PRIVATE(ah)->ah_nchan = next; + + /* + * Copy the channel list to the public channel list + */ + for (i = 0; i < next; i++) { + chans[i].channel = ichans[i].channel; + chans[i].channelFlags = ichans[i].channelFlags; + chans[i].privFlags = ichans[i].privFlags; + chans[i].maxRegTxPower = ichans[i].maxRegTxPower; + } + /* + * Retrieve power limits. + */ + ath_hal_getpowerlimits(ah, chans, next); + for (i = 0; i < next; i++) { + ichans[i].maxTxPower = chans[i].maxTxPower; + ichans[i].minTxPower = chans[i].minTxPower; + } + } + *nchans = next; + /* XXX copy private setting to public area */ + ah->ah_countryCode = AH_PRIVATE(ah)->ah_countryCode; + return (next != 0); +#undef CHANNEL_HALF_BW +#undef CHANNEL_QUARTER_BW +} + +/* + * Return whether or not the specified channel is ok to use + * based on the current regulatory domain constraints and + * DFS interference. + */ +HAL_CHANNEL_INTERNAL * +ath_hal_checkchannel(struct ath_hal *ah, const HAL_CHANNEL *c) +{ +#define CHAN_FLAGS (CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER) + HAL_CHANNEL_INTERNAL *base, *cc; + /* NB: be wary of user-specified channel flags */ + int flags = c->channelFlags & CHAN_FLAGS; + int n, lim, d; + + /* + * Check current channel to avoid the lookup. + */ + cc = AH_PRIVATE(ah)->ah_curchan; + if (cc != AH_NULL && cc->channel == c->channel && + (cc->channelFlags & CHAN_FLAGS) == flags) { + if ((cc->privFlags & CHANNEL_INTERFERENCE) && + (cc->channelFlags & CHANNEL_DFS)) + return AH_NULL; + else + return cc; + } + + /* binary search based on known sorting order */ + base = AH_PRIVATE(ah)->ah_channels; + n = AH_PRIVATE(ah)->ah_nchan; + /* binary search based on known sorting order */ + for (lim = n; lim != 0; lim >>= 1) { + cc = &base[lim>>1]; + d = c->channel - cc->channel; + if (d == 0) { + if ((cc->channelFlags & CHAN_FLAGS) == flags) { + if ((cc->privFlags & CHANNEL_INTERFERENCE) && + (cc->channelFlags & CHANNEL_DFS)) + return AH_NULL; + else + return cc; + } + d = flags - (cc->channelFlags & CHAN_FLAGS); + } + if (d > 0) { + base = cc + 1; + lim--; + } + } + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: no match for %u/0x%x\n", + __func__, c->channel, c->channelFlags); + return AH_NULL; +#undef CHAN_FLAGS +} + +/* + * Return the max allowed antenna gain and apply any regulatory + * domain specific changes. + * + * NOTE: a negative reduction is possible in RD's that only + * measure radiated power (e.g., ETSI) which would increase + * that actual conducted output power (though never beyond + * the calibrated target power). + */ +u_int +ath_hal_getantennareduction(struct ath_hal *ah, HAL_CHANNEL *chan, u_int twiceGain) +{ + HAL_CHANNEL_INTERNAL *ichan=AH_NULL; + int8_t antennaMax; + + if ((ichan = ath_hal_checkchannel(ah, chan)) != AH_NULL) { + antennaMax = twiceGain - ichan->antennaMax*2; + return (antennaMax < 0) ? 0 : antennaMax; + } else { + /* Failed to find the correct index - may be a debug channel */ + return 0; + } +} + + +/* XXX - maybe move ctl decision into channel set area or + into the tables so no decision is needed in the code */ + +#define isWwrSKU(_ah) \ + ((getEepromRD((_ah)) & WORLD_SKU_MASK) == WORLD_SKU_PREFIX || \ + getEepromRD(_ah) == WORLD) + + +/* + * Return the test group from the specified channel from + * the regulatory table. + * + * TODO: CTL for 11B CommonMode when regulatory domain is unknown + */ +u_int +ath_hal_getctl(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + u_int ctl = NO_CTL; + HAL_CHANNEL_INTERNAL *ichan; + + /* Special CTL to signify WWR SKU without a known country */ + if (AH_PRIVATE(ah)->ah_countryCode == CTRY_DEFAULT && isWwrSKU(ah)) { + if (IS_CHAN_B(chan)) { + ctl = SD_NO_CTL | CTL_11B; + } else if (IS_CHAN_G(chan)) { + ctl = SD_NO_CTL | CTL_11G; + } else if (IS_CHAN_108G(chan)) { + ctl = SD_NO_CTL | CTL_108G; + } else if (IS_CHAN_T(chan)) { + ctl = SD_NO_CTL | CTL_TURBO; + } else { + ctl = SD_NO_CTL | CTL_11A; + } + } else { + if ((ichan = ath_hal_checkchannel(ah, chan)) != AH_NULL) { + ctl = ichan->conformanceTestLimit; + /* limit 11G OFDM power */ + if (IS_CHAN_PUREG(chan) && + (ctl & CTL_MODE_M) == CTL_11B) + ctl = (ctl &~ CTL_MODE_M) | CTL_11G; + } + } + return ctl; +} + +/* + * Return whether or not a noise floor check is required in + * the current regulatory domain for the specified channel. + */ +HAL_BOOL +ath_hal_getnfcheckrequired(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + HAL_CHANNEL_INTERNAL *ichan; + + if ((ichan = ath_hal_checkchannel(ah, chan)) != AH_NULL) + return ((ichan->regDmnFlags & NEED_NFC) ? AH_TRUE : AH_FALSE); + return AH_FALSE; +} + +/* + * Insertion sort. + */ +#define swap(_a, _b, _size) { \ + uint8_t *s = _b; \ + int i = _size; \ + do { \ + uint8_t tmp = *_a; \ + *_a++ = *s; \ + *s++ = tmp; \ + } while (--i); \ + _a -= _size; \ +} + +static void +ath_hal_sort(void *a, size_t n, size_t size, ath_hal_cmp_t *cmp) +{ + uint8_t *aa = a; + uint8_t *ai, *t; + + for (ai = aa+size; --n >= 1; ai += size) + for (t = ai; t > aa; t -= size) { + uint8_t *u = t - size; + if (cmp(u, t) <= 0) + break; + swap(u, t, size); + } +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ah_soc.h b/sys/dev/netif/ath/hal/ath_hal/ah_soc.h new file mode 100644 index 0000000000..50fbc62c45 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ah_soc.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ah_soc.h,v 1.4 2008/11/10 04:08:00 sam Exp $ + */ +#ifndef _ATH_AH_SOC_H_ +#define _ATH_AH_SOC_H_ +/* + * Atheros System on Chip (SoC) public definitions. + */ + +/* + * This is board-specific data that is stored in a "known" + * location in flash. To find the start of this data search + * back from the (aliased) end of flash by 0x1000 bytes at a + * time until you find the string "5311", which marks the + * start of Board Configuration. Typically one gives up if + * more than 500KB is searched. + */ +struct ar531x_boarddata { + uint32_t magic; /* board data is valid */ +#define AR531X_BD_MAGIC 0x35333131 /* "5311", for all 531x platforms */ + uint16_t cksum; /* checksum (starting with BD_REV 2) */ + uint16_t rev; /* revision of this struct */ +#define BD_REV 4 + char boardName[64]; /* Name of board */ + uint16_t major; /* Board major number */ + uint16_t minor; /* Board minor number */ + uint32_t config; /* Board configuration */ +#define BD_ENET0 0x00000001 /* ENET0 is stuffed */ +#define BD_ENET1 0x00000002 /* ENET1 is stuffed */ +#define BD_UART1 0x00000004 /* UART1 is stuffed */ +#define BD_UART0 0x00000008 /* UART0 is stuffed (dma) */ +#define BD_RSTFACTORY 0x00000010 /* Reset factory defaults stuffed */ +#define BD_SYSLED 0x00000020 /* System LED stuffed */ +#define BD_EXTUARTCLK 0x00000040 /* External UART clock */ +#define BD_CPUFREQ 0x00000080 /* cpu freq is valid in nvram */ +#define BD_SYSFREQ 0x00000100 /* sys freq is set in nvram */ +#define BD_WLAN0 0x00000200 /* Enable WLAN0 */ +#define BD_MEMCAP 0x00000400 /* CAP SDRAM @ memCap for testing */ +#define BD_DISWATCHDOG 0x00000800 /* disable system watchdog */ +#define BD_WLAN1 0x00001000 /* Enable WLAN1 (ar5212) */ +#define BD_ISCASPER 0x00002000 /* FLAG for AR2312 */ +#define BD_WLAN0_2G_EN 0x00004000 /* FLAG for radio0_2G */ +#define BD_WLAN0_5G_EN 0x00008000 /* FLAG for radio0_2G */ +#define BD_WLAN1_2G_EN 0x00020000 /* FLAG for radio0_2G */ +#define BD_WLAN1_5G_EN 0x00040000 /* FLAG for radio0_2G */ + uint16_t resetConfigGpio; /* Reset factory GPIO pin */ + uint16_t sysLedGpio; /* System LED GPIO pin */ + + uint32_t cpuFreq; /* CPU core frequency in Hz */ + uint32_t sysFreq; /* System frequency in Hz */ + uint32_t cntFreq; /* Calculated C0_COUNT frequency */ + + uint8_t wlan0Mac[6]; + uint8_t enet0Mac[6]; + uint8_t enet1Mac[6]; + + uint16_t pciId; /* Pseudo PCIID for common code */ + uint16_t memCap; /* cap bank1 in MB */ + + /* version 3 */ + uint8_t wlan1Mac[6]; /* (ar5212) */ +}; + +/* + * Board support data. The driver is required to locate + * and fill-in this information before passing a reference to + * this structure as the HAL_BUS_TAG parameter supplied to + * ath_hal_attach. + */ +struct ar531x_config { + const struct ar531x_boarddata *board; /* board config data */ + const char *radio; /* radio config data */ + int unit; /* unit number [0, 1] */ + void *tag; /* bus space tag */ +}; +#endif /* _ATH_AH_SOC_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210.h b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210.h new file mode 100644 index 0000000000..857cf3c316 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210.h @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5210.h,v 1.8 2008/11/11 02:40:13 sam Exp $ + */ +#ifndef _ATH_AR5210_H_ +#define _ATH_AR5210_H_ + +#define AR5210_MAGIC 0x19980124 + +#if 0 +/* + * RTS_ENABLE includes LONG_PKT because they essentially + * imply the same thing, and are set or not set together + * for this chip + */ +#define AR5210_TXD_CTRL_A_HDR_LEN(_val) (((_val) ) & 0x0003f) +#define AR5210_TXD_CTRL_A_TX_RATE(_val) (((_val) << 6) & 0x003c0) +#define AR5210_TXD_CTRL_A_RTS_ENABLE ( 0x00c00) +#define AR5210_TXD_CTRL_A_CLEAR_DEST_MASK(_val) (((_val) << 12) & 0x01000) +#define AR5210_TXD_CTRL_A_ANT_MODE(_val) (((_val) << 13) & 0x02000) +#define AR5210_TXD_CTRL_A_PKT_TYPE(_val) (((_val) << 14) & 0x1c000) +#define AR5210_TXD_CTRL_A_INT_REQ ( 0x20000) +#define AR5210_TXD_CTRL_A_KEY_VALID ( 0x40000) +#define AR5210_TXD_CTRL_B_KEY_ID(_val) (((_val) ) & 0x0003f) +#define AR5210_TXD_CTRL_B_RTS_DURATION(_val) (((_val) << 6) & 0x7ffc0) +#endif + +#define INIT_CONFIG_STATUS 0x00000000 +#define INIT_ACKTOPS 0x00000008 +#define INIT_BCON_CNTRL_REG 0x00000000 +#define INIT_SLOT_TIME 0x00000168 +#define INIT_SLOT_TIME_TURBO 0x000001e0 /* More aggressive turbo slot timing = 6 us */ +#define INIT_ACK_CTS_TIMEOUT 0x04000400 +#define INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800 + +#define INIT_USEC 0x27 +#define INIT_USEC_TURBO 0x4f +#define INIT_USEC_32 0x1f +#define INIT_TX_LATENCY 0x36 +#define INIT_RX_LATENCY 0x1D +#define INIT_TRANSMIT_LATENCY \ + ((INIT_RX_LATENCY << AR_USEC_RX_LATENCY_S) | \ + (INIT_TX_LATENCY << AR_USEC_TX_LATENCY_S) | \ + (INIT_USEC_32 << 7) | INIT_USEC ) +#define INIT_TRANSMIT_LATENCY_TURBO \ + ((INIT_RX_LATENCY << AR_USEC_RX_LATENCY_S) | \ + (INIT_TX_LATENCY << AR_USEC_TX_LATENCY_S) | \ + (INIT_USEC_32 << 7) | INIT_USEC_TURBO) + +#define INIT_SIFS 0x230 /* = 16 us - 2 us */ +#define INIT_SIFS_TURBO 0x1E0 /* More aggressive turbo SIFS timing - 8 us - 2 us */ + +/* + * Various fifo fill before Tx start, in 64-byte units + * i.e. put the frame in the air while still DMAing + */ +#define MIN_TX_FIFO_THRESHOLD 0x1 +#define MAX_TX_FIFO_THRESHOLD ((IEEE80211_MAX_LEN / 64) + 1) + +#define INIT_NEXT_CFP_START 0xffffffff + +#define INIT_BEACON_PERIOD 0xffff +#define INIT_BEACON_EN 0 /* this should be set by AP only when it's ready */ +#define INIT_BEACON_CONTROL \ + ((INIT_RESET_TSF << 24) | (INIT_BEACON_EN << 23) | \ + (INIT_TIM_OFFSET<<16) | INIT_BEACON_PERIOD) + +#define INIT_RSSI_THR 0x00000700 /* Missed beacon counter initialized to max value of 7 */ +#define INIT_ProgIFS 0x398 /* PIFS - 2us */ +#define INIT_ProgIFS_TURBO 0x3C0 +#define INIT_EIFS 0xd70 +#define INIT_EIFS_TURBO 0x1ae0 +#define INIT_CARR_SENSE_EN 1 +#define INIT_PROTO_TIME_CNTRL ( (INIT_CARR_SENSE_EN << 26) | (INIT_EIFS << 12) | \ + (INIT_ProgIFS) ) +#define INIT_PROTO_TIME_CNTRL_TURBO ( (INIT_CARR_SENSE_EN << 26) | (INIT_EIFS_TURBO << 12) | \ + (INIT_ProgIFS_TURBO) ) + +#define AR5210_MAX_RATE_POWER 60 + +#undef HAL_NUM_TX_QUEUES /* from ah.h */ +#define HAL_NUM_TX_QUEUES 3 + +struct ath_hal_5210 { + struct ath_hal_private ah_priv; /* base definitions */ + + uint8_t ah_macaddr[IEEE80211_ADDR_LEN]; + /* + * Runtime state. + */ + uint32_t ah_maskReg; /* shadow of IMR+IER regs */ + uint32_t ah_txOkInterruptMask; + uint32_t ah_txErrInterruptMask; + uint32_t ah_txDescInterruptMask; + uint32_t ah_txEolInterruptMask; + uint32_t ah_txUrnInterruptMask; + HAL_POWER_MODE ah_powerMode; + uint8_t ah_bssid[IEEE80211_ADDR_LEN]; + HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES]; /* beacon+cab+data */ + /* + * Station mode support. + */ + uint32_t ah_staId1Defaults; /* STA_ID1 default settings */ + uint32_t ah_rssiThr; /* RSSI_THR settings */ + + u_int ah_sifstime; /* user-specified sifs time */ + u_int ah_slottime; /* user-specified slot time */ + u_int ah_acktimeout; /* user-specified ack timeout */ + u_int ah_ctstimeout; /* user-specified cts timeout */ +}; +#define AH5210(ah) ((struct ath_hal_5210 *)(ah)) + +struct ath_hal; + +extern void ar5210Detach(struct ath_hal *ah); +extern HAL_BOOL ar5210Reset(struct ath_hal *, HAL_OPMODE, + HAL_CHANNEL *, HAL_BOOL bChannelChange, HAL_STATUS *); +extern void ar5210SetPCUConfig(struct ath_hal *); +extern HAL_BOOL ar5210PhyDisable(struct ath_hal *); +extern HAL_BOOL ar5210Disable(struct ath_hal *); +extern HAL_BOOL ar5210ChipReset(struct ath_hal *, HAL_CHANNEL *); +extern HAL_BOOL ar5210PerCalibration(struct ath_hal *, HAL_CHANNEL *, HAL_BOOL *); +extern HAL_BOOL ar5210PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan, + u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); +extern HAL_BOOL ar5210ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan); +extern int16_t ar5210GetNoiseFloor(struct ath_hal *); +extern int16_t ar5210GetNfAdjust(struct ath_hal *, + const HAL_CHANNEL_INTERNAL *); +extern HAL_BOOL ar5210SetTxPowerLimit(struct ath_hal *, uint32_t limit); +extern HAL_BOOL ar5210SetTransmitPower(struct ath_hal *, HAL_CHANNEL *); +extern HAL_BOOL ar5210CalNoiseFloor(struct ath_hal *, HAL_CHANNEL_INTERNAL *); +extern HAL_BOOL ar5210ResetDma(struct ath_hal *, HAL_OPMODE); + +extern HAL_BOOL ar5210SetTxQueueProps(struct ath_hal *ah, int q, + const HAL_TXQ_INFO *qInfo); +extern HAL_BOOL ar5210GetTxQueueProps(struct ath_hal *ah, int q, + HAL_TXQ_INFO *qInfo); +extern int ar5210SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo); +extern HAL_BOOL ar5210ReleaseTxQueue(struct ath_hal *ah, u_int q); +extern HAL_BOOL ar5210ResetTxQueue(struct ath_hal *ah, u_int q); +extern uint32_t ar5210GetTxDP(struct ath_hal *, u_int); +extern HAL_BOOL ar5210SetTxDP(struct ath_hal *, u_int, uint32_t txdp); +extern HAL_BOOL ar5210UpdateTxTrigLevel(struct ath_hal *, HAL_BOOL); +extern uint32_t ar5210NumTxPending(struct ath_hal *, u_int); +extern HAL_BOOL ar5210StartTxDma(struct ath_hal *, u_int); +extern HAL_BOOL ar5210StopTxDma(struct ath_hal *, u_int); +extern HAL_BOOL ar5210SetupTxDesc(struct ath_hal *, struct ath_desc *, + u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower, + u_int txRate0, u_int txRetries0, + u_int keyIx, u_int antMode, u_int flags, + u_int rtsctsRate, u_int rtsctsDuration, + u_int compicvLen, u_int compivLen, u_int comp); +extern HAL_BOOL ar5210SetupXTxDesc(struct ath_hal *, struct ath_desc *, + u_int txRate1, u_int txRetries1, + u_int txRate2, u_int txRetries2, + u_int txRate3, u_int txRetries3); +extern HAL_BOOL ar5210FillTxDesc(struct ath_hal *, struct ath_desc *, + u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg, + const struct ath_desc *ds0); +extern HAL_STATUS ar5210ProcTxDesc(struct ath_hal *, + struct ath_desc *, struct ath_tx_status *); +extern void ar5210GetTxIntrQueue(struct ath_hal *ah, uint32_t *); +extern void ar5210IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *); + +extern uint32_t ar5210GetRxDP(struct ath_hal *); +extern void ar5210SetRxDP(struct ath_hal *, uint32_t rxdp); +extern void ar5210EnableReceive(struct ath_hal *); +extern HAL_BOOL ar5210StopDmaReceive(struct ath_hal *); +extern void ar5210StartPcuReceive(struct ath_hal *); +extern void ar5210StopPcuReceive(struct ath_hal *); +extern void ar5210SetMulticastFilter(struct ath_hal *, + uint32_t filter0, uint32_t filter1); +extern HAL_BOOL ar5210ClrMulticastFilterIndex(struct ath_hal *, uint32_t); +extern HAL_BOOL ar5210SetMulticastFilterIndex(struct ath_hal *, uint32_t); +extern uint32_t ar5210GetRxFilter(struct ath_hal *); +extern void ar5210SetRxFilter(struct ath_hal *, uint32_t); +extern HAL_BOOL ar5210SetupRxDesc(struct ath_hal *, struct ath_desc *, + uint32_t, u_int flags); +extern HAL_STATUS ar5210ProcRxDesc(struct ath_hal *, struct ath_desc *, + uint32_t, struct ath_desc *, uint64_t, + struct ath_rx_status *); + +extern void ar5210GetMacAddress(struct ath_hal *, uint8_t *); +extern HAL_BOOL ar5210SetMacAddress(struct ath_hal *ah, const uint8_t *); +extern void ar5210GetBssIdMask(struct ath_hal *, uint8_t *); +extern HAL_BOOL ar5210SetBssIdMask(struct ath_hal *, const uint8_t *); +extern HAL_BOOL ar5210EepromRead(struct ath_hal *, u_int off, uint16_t *data); +extern HAL_BOOL ar5210EepromWrite(struct ath_hal *, u_int off, uint16_t data); +extern HAL_BOOL ar5210SetRegulatoryDomain(struct ath_hal *, + uint16_t, HAL_STATUS *); +extern u_int ar5210GetWirelessModes(struct ath_hal *ah); +extern void ar5210EnableRfKill(struct ath_hal *); +extern HAL_BOOL ar5210GpioCfgInput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5210GpioCfgOutput(struct ath_hal *, uint32_t gpio); +extern uint32_t ar5210GpioGet(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5210GpioSet(struct ath_hal *, uint32_t gpio, uint32_t); +extern void ar5210Gpio0SetIntr(struct ath_hal *, u_int, uint32_t ilevel); +extern void ar5210SetLedState(struct ath_hal *, HAL_LED_STATE); +extern u_int ar5210GetDefAntenna(struct ath_hal *); +extern void ar5210SetDefAntenna(struct ath_hal *, u_int); +extern HAL_ANT_SETTING ar5210GetAntennaSwitch(struct ath_hal *); +extern HAL_BOOL ar5210SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); +extern void ar5210WriteAssocid(struct ath_hal *, + const uint8_t *bssid, uint16_t assocId); +extern uint32_t ar5210GetTsf32(struct ath_hal *); +extern uint64_t ar5210GetTsf64(struct ath_hal *); +extern void ar5210ResetTsf(struct ath_hal *); +extern uint32_t ar5210GetRandomSeed(struct ath_hal *); +extern HAL_BOOL ar5210DetectCardPresent(struct ath_hal *); +extern void ar5210UpdateMibCounters(struct ath_hal *, HAL_MIB_STATS *); +extern void ar5210EnableHwEncryption(struct ath_hal *); +extern void ar5210DisableHwEncryption(struct ath_hal *); +extern HAL_RFGAIN ar5210GetRfgain(struct ath_hal *); +extern HAL_BOOL ar5210SetSifsTime(struct ath_hal *, u_int); +extern u_int ar5210GetSifsTime(struct ath_hal *); +extern HAL_BOOL ar5210SetSlotTime(struct ath_hal *, u_int); +extern u_int ar5210GetSlotTime(struct ath_hal *); +extern HAL_BOOL ar5210SetAckTimeout(struct ath_hal *, u_int); +extern u_int ar5210GetAckTimeout(struct ath_hal *); +extern HAL_BOOL ar5210SetAckCTSRate(struct ath_hal *, u_int); +extern u_int ar5210GetAckCTSRate(struct ath_hal *); +extern HAL_BOOL ar5210SetCTSTimeout(struct ath_hal *, u_int); +extern u_int ar5210GetCTSTimeout(struct ath_hal *); +extern HAL_BOOL ar5210SetDecompMask(struct ath_hal *, uint16_t, int); +void ar5210SetCoverageClass(struct ath_hal *, uint8_t, int); +extern HAL_STATUS ar5210GetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, + uint32_t, uint32_t *); +extern HAL_BOOL ar5210SetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, + uint32_t, uint32_t, HAL_STATUS *); +extern HAL_BOOL ar5210GetDiagState(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize); + +extern u_int ar5210GetKeyCacheSize(struct ath_hal *); +extern HAL_BOOL ar5210IsKeyCacheEntryValid(struct ath_hal *, uint16_t); +extern HAL_BOOL ar5210ResetKeyCacheEntry(struct ath_hal *, uint16_t entry); +extern HAL_BOOL ar5210SetKeyCacheEntry(struct ath_hal *, uint16_t entry, + const HAL_KEYVAL *, const uint8_t *mac, int xorKey); +extern HAL_BOOL ar5210SetKeyCacheEntryMac(struct ath_hal *, + uint16_t, const uint8_t *); + +extern HAL_BOOL ar5210SetPowerMode(struct ath_hal *, uint32_t powerRequest, + int setChip); +extern HAL_POWER_MODE ar5210GetPowerMode(struct ath_hal *); + +extern void ar5210SetBeaconTimers(struct ath_hal *, + const HAL_BEACON_TIMERS *); +extern void ar5210BeaconInit(struct ath_hal *, uint32_t, uint32_t); +extern void ar5210SetStaBeaconTimers(struct ath_hal *, + const HAL_BEACON_STATE *); +extern void ar5210ResetStaBeaconTimers(struct ath_hal *); + +extern HAL_BOOL ar5210IsInterruptPending(struct ath_hal *); +extern HAL_BOOL ar5210GetPendingInterrupts(struct ath_hal *, HAL_INT *); +extern HAL_INT ar5210GetInterrupts(struct ath_hal *); +extern HAL_INT ar5210SetInterrupts(struct ath_hal *, HAL_INT ints); + +extern const HAL_RATE_TABLE *ar5210GetRateTable(struct ath_hal *, u_int mode); + +extern HAL_BOOL ar5210AniControl(struct ath_hal *, HAL_ANI_CMD, int ); +extern void ar5210AniPoll(struct ath_hal *, const HAL_NODE_STATS *, HAL_CHANNEL *); +extern void ar5210MibEvent(struct ath_hal *, const HAL_NODE_STATS *); +#endif /* _ATH_AR5210_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_attach.c b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_attach.c new file mode 100644 index 0000000000..7259f09f84 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_attach.c @@ -0,0 +1,384 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5210_attach.c,v 1.9 2008/11/11 02:40:13 sam Exp $ + */ +#include +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" +#include "ar5210/ar5210phy.h" + +#include "ah_eeprom_v1.h" + +static HAL_BOOL ar5210GetChannelEdges(struct ath_hal *, + uint16_t flags, uint16_t *low, uint16_t *high); +static HAL_BOOL ar5210GetChipPowerLimits(struct ath_hal *ah, + HAL_CHANNEL *chans, uint32_t nchans); + +static const struct ath_hal_private ar5210hal = {{ + .ah_magic = AR5210_MAGIC, + .ah_abi = HAL_ABI_VERSION, + .ah_countryCode = CTRY_DEFAULT, + + .ah_getRateTable = ar5210GetRateTable, + .ah_detach = ar5210Detach, + + /* Reset Functions */ + .ah_reset = ar5210Reset, + .ah_phyDisable = ar5210PhyDisable, + .ah_disable = ar5210Disable, + .ah_setPCUConfig = ar5210SetPCUConfig, + .ah_perCalibration = ar5210PerCalibration, + .ah_perCalibrationN = ar5210PerCalibrationN, + .ah_resetCalValid = ar5210ResetCalValid, + .ah_setTxPowerLimit = ar5210SetTxPowerLimit, + .ah_getChanNoise = ath_hal_getChanNoise, + + /* Transmit functions */ + .ah_updateTxTrigLevel = ar5210UpdateTxTrigLevel, + .ah_setupTxQueue = ar5210SetupTxQueue, + .ah_setTxQueueProps = ar5210SetTxQueueProps, + .ah_getTxQueueProps = ar5210GetTxQueueProps, + .ah_releaseTxQueue = ar5210ReleaseTxQueue, + .ah_resetTxQueue = ar5210ResetTxQueue, + .ah_getTxDP = ar5210GetTxDP, + .ah_setTxDP = ar5210SetTxDP, + .ah_numTxPending = ar5210NumTxPending, + .ah_startTxDma = ar5210StartTxDma, + .ah_stopTxDma = ar5210StopTxDma, + .ah_setupTxDesc = ar5210SetupTxDesc, + .ah_setupXTxDesc = ar5210SetupXTxDesc, + .ah_fillTxDesc = ar5210FillTxDesc, + .ah_procTxDesc = ar5210ProcTxDesc, + .ah_getTxIntrQueue = ar5210GetTxIntrQueue, + .ah_reqTxIntrDesc = ar5210IntrReqTxDesc, + + /* RX Functions */ + .ah_getRxDP = ar5210GetRxDP, + .ah_setRxDP = ar5210SetRxDP, + .ah_enableReceive = ar5210EnableReceive, + .ah_stopDmaReceive = ar5210StopDmaReceive, + .ah_startPcuReceive = ar5210StartPcuReceive, + .ah_stopPcuReceive = ar5210StopPcuReceive, + .ah_setMulticastFilter = ar5210SetMulticastFilter, + .ah_setMulticastFilterIndex = ar5210SetMulticastFilterIndex, + .ah_clrMulticastFilterIndex = ar5210ClrMulticastFilterIndex, + .ah_getRxFilter = ar5210GetRxFilter, + .ah_setRxFilter = ar5210SetRxFilter, + .ah_setupRxDesc = ar5210SetupRxDesc, + .ah_procRxDesc = ar5210ProcRxDesc, + .ah_rxMonitor = ar5210AniPoll, + .ah_procMibEvent = ar5210MibEvent, + + /* Misc Functions */ + .ah_getCapability = ar5210GetCapability, + .ah_setCapability = ar5210SetCapability, + .ah_getDiagState = ar5210GetDiagState, + .ah_getMacAddress = ar5210GetMacAddress, + .ah_setMacAddress = ar5210SetMacAddress, + .ah_getBssIdMask = ar5210GetBssIdMask, + .ah_setBssIdMask = ar5210SetBssIdMask, + .ah_setRegulatoryDomain = ar5210SetRegulatoryDomain, + .ah_setLedState = ar5210SetLedState, + .ah_writeAssocid = ar5210WriteAssocid, + .ah_gpioCfgInput = ar5210GpioCfgInput, + .ah_gpioCfgOutput = ar5210GpioCfgOutput, + .ah_gpioGet = ar5210GpioGet, + .ah_gpioSet = ar5210GpioSet, + .ah_gpioSetIntr = ar5210Gpio0SetIntr, + .ah_getTsf32 = ar5210GetTsf32, + .ah_getTsf64 = ar5210GetTsf64, + .ah_resetTsf = ar5210ResetTsf, + .ah_detectCardPresent = ar5210DetectCardPresent, + .ah_updateMibCounters = ar5210UpdateMibCounters, + .ah_getRfGain = ar5210GetRfgain, + .ah_getDefAntenna = ar5210GetDefAntenna, + .ah_setDefAntenna = ar5210SetDefAntenna, + .ah_getAntennaSwitch = ar5210GetAntennaSwitch, + .ah_setAntennaSwitch = ar5210SetAntennaSwitch, + .ah_setSifsTime = ar5210SetSifsTime, + .ah_getSifsTime = ar5210GetSifsTime, + .ah_setSlotTime = ar5210SetSlotTime, + .ah_getSlotTime = ar5210GetSlotTime, + .ah_setAckTimeout = ar5210SetAckTimeout, + .ah_getAckTimeout = ar5210GetAckTimeout, + .ah_setAckCTSRate = ar5210SetAckCTSRate, + .ah_getAckCTSRate = ar5210GetAckCTSRate, + .ah_setCTSTimeout = ar5210SetCTSTimeout, + .ah_getCTSTimeout = ar5210GetCTSTimeout, + .ah_setDecompMask = ar5210SetDecompMask, + .ah_setCoverageClass = ar5210SetCoverageClass, + + /* Key Cache Functions */ + .ah_getKeyCacheSize = ar5210GetKeyCacheSize, + .ah_resetKeyCacheEntry = ar5210ResetKeyCacheEntry, + .ah_isKeyCacheEntryValid = ar5210IsKeyCacheEntryValid, + .ah_setKeyCacheEntry = ar5210SetKeyCacheEntry, + .ah_setKeyCacheEntryMac = ar5210SetKeyCacheEntryMac, + + /* Power Management Functions */ + .ah_setPowerMode = ar5210SetPowerMode, + .ah_getPowerMode = ar5210GetPowerMode, + + /* Beacon Functions */ + .ah_setBeaconTimers = ar5210SetBeaconTimers, + .ah_beaconInit = ar5210BeaconInit, + .ah_setStationBeaconTimers = ar5210SetStaBeaconTimers, + .ah_resetStationBeaconTimers = ar5210ResetStaBeaconTimers, + + /* Interrupt Functions */ + .ah_isInterruptPending = ar5210IsInterruptPending, + .ah_getPendingInterrupts = ar5210GetPendingInterrupts, + .ah_getInterrupts = ar5210GetInterrupts, + .ah_setInterrupts = ar5210SetInterrupts }, + + .ah_getChannelEdges = ar5210GetChannelEdges, + .ah_getWirelessModes = ar5210GetWirelessModes, + .ah_eepromRead = ar5210EepromRead, +#ifdef AH_SUPPORT_WRITE_EEPROM + .ah_eepromWrite = ar5210EepromWrite, +#endif + .ah_gpioCfgInput = ar5210GpioCfgInput, + .ah_gpioCfgOutput = ar5210GpioCfgOutput, + .ah_gpioGet = ar5210GpioGet, + .ah_gpioSet = ar5210GpioSet, + .ah_gpioSetIntr = ar5210Gpio0SetIntr, + .ah_getChipPowerLimits = ar5210GetChipPowerLimits, +}; + +static HAL_BOOL ar5210FillCapabilityInfo(struct ath_hal *ah); + +/* + * Attach for an AR5210 part. + */ +static struct ath_hal * +ar5210Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, + HAL_STATUS *status) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + struct ath_hal_5210 *ahp; + struct ath_hal *ah; + uint32_t revid, pcicfg; + uint16_t eeval; + HAL_STATUS ecode; + int i; + + HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, + "%s: devid 0x%x sc %p st %p sh %p\n", __func__, devid, + sc, (void*) st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp = ath_hal_malloc(sizeof (struct ath_hal_5210)); + if (ahp == AH_NULL) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: no memory for state block\n", __func__); + ecode = HAL_ENOMEM; + goto bad; + } + ah = &ahp->ah_priv.h; + /* set initial values */ + OS_MEMCPY(&ahp->ah_priv, &ar5210hal, sizeof(struct ath_hal_private)); + ah->ah_sc = sc; + ah->ah_st = st; + ah->ah_sh = sh; + + ah->ah_devid = devid; /* NB: for AH_DEBUG_ALQ */ + AH_PRIVATE(ah)->ah_devid = devid; + AH_PRIVATE(ah)->ah_subvendorid = 0; /* XXX */ + + AH_PRIVATE(ah)->ah_powerLimit = AR5210_MAX_RATE_POWER; + AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */ + + ahp->ah_powerMode = HAL_PM_UNDEFINED; + ahp->ah_staId1Defaults = 0; + ahp->ah_rssiThr = INIT_RSSI_THR; + ahp->ah_sifstime = (u_int) -1; + ahp->ah_slottime = (u_int) -1; + ahp->ah_acktimeout = (u_int) -1; + ahp->ah_ctstimeout = (u_int) -1; + + if (!ar5210ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + + /* Read Revisions from Chips */ + AH_PRIVATE(ah)->ah_macVersion = 1; + AH_PRIVATE(ah)->ah_macRev = OS_REG_READ(ah, AR_SREV) & 0xff; + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIPID); + AH_PRIVATE(ah)->ah_analog2GhzRev = 0; + + /* Read Radio Chip Rev Extract */ + OS_REG_WRITE(ah, (AR_PHY_BASE + (0x34 << 2)), 0x00001c16); + for (i = 0; i < 4; i++) + OS_REG_WRITE(ah, (AR_PHY_BASE + (0x20 << 2)), 0x00010000); + revid = (OS_REG_READ(ah, AR_PHY_BASE + (256 << 2)) >> 28) & 0xf; + + /* Chip labelling is 1 greater than revision register for AR5110 */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ath_hal_reverseBits(revid, 4) + 1; + + /* + * Read all the settings from the EEPROM and stash + * ones we'll use later. + */ + pcicfg = OS_REG_READ(ah, AR_PCICFG); + OS_REG_WRITE(ah, AR_PCICFG, pcicfg | AR_PCICFG_EEPROMSEL); + ecode = ath_hal_v1EepromAttach(ah); + if (ecode != HAL_OK) { + goto eebad; + } + ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read regulatory domain from EEPROM\n", + __func__); + goto eebad; + } + AH_PRIVATE(ah)->ah_currentRD = eeval; + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error getting mac address from EEPROM\n", __func__); + goto eebad; + } + OS_REG_WRITE(ah, AR_PCICFG, pcicfg); /* disable EEPROM access */ + + AH_PRIVATE(ah)->ah_getNfAdjust = ar5210GetNfAdjust; + + /* + * Got everything we need now to setup the capabilities. + */ + (void) ar5210FillCapabilityInfo(ah); + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); + + return ah; +eebad: + OS_REG_WRITE(ah, AR_PCICFG, pcicfg); /* disable EEPROM access */ +bad: + if (ahp) + ath_hal_free(ahp); + if (status) + *status = ecode; + return AH_NULL; +#undef N +} + +void +ar5210Detach(struct ath_hal *ah) +{ + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__); + + HALASSERT(ah != AH_NULL); + HALASSERT(ah->ah_magic == AR5210_MAGIC); + + ath_hal_eepromDetach(ah); + ath_hal_free(ah); +} + +/* + * Store the channel edges for the requested operational mode + */ +static HAL_BOOL +ar5210GetChannelEdges(struct ath_hal *ah, + uint16_t flags, uint16_t *low, uint16_t *high) +{ + if (flags & CHANNEL_5GHZ) { + *low = 5120; + *high = 5430; + return AH_TRUE; + } else { + return AH_FALSE; + } +} + +static HAL_BOOL +ar5210GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, uint32_t nchans) +{ + HAL_CHANNEL *chan; + int i; + + /* XXX fill in, this is just a placeholder */ + for (i = 0; i < nchans; i++) { + chan = &chans[i]; + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: no min/max power for %u/0x%x\n", + __func__, chan->channel, chan->channelFlags); + chan->maxTxPower = AR5210_MAX_RATE_POWER; + chan->minTxPower = 0; + } + return AH_TRUE; +} + +/* + * Fill all software cached or static hardware state information. + */ +static HAL_BOOL +ar5210FillCapabilityInfo(struct ath_hal *ah) +{ + struct ath_hal_private *ahpriv = AH_PRIVATE(ah); + HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; + + pCap->halWirelessModes |= HAL_MODE_11A; + + pCap->halLow5GhzChan = 5120; + pCap->halHigh5GhzChan = 5430; + + pCap->halSleepAfterBeaconBroken = AH_TRUE; + pCap->halPSPollBroken = AH_FALSE; + + pCap->halTotalQueues = HAL_NUM_TX_QUEUES; + pCap->halKeyCacheSize = 64; + + /* XXX not needed */ + pCap->halChanHalfRate = AH_FALSE; + pCap->halChanQuarterRate = AH_FALSE; + + if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL)) { + /* + * Setup initial rfsilent settings based on the EEPROM + * contents. Pin 0, polarity 0 is fixed; record this + * using the EEPROM format found in later parts. + */ + ahpriv->ah_rfsilent = SM(0, AR_EEPROM_RFSILENT_GPIO_SEL) + | SM(0, AR_EEPROM_RFSILENT_POLARITY); + ahpriv->ah_rfkillEnabled = AH_TRUE; + pCap->halRfSilentSupport = AH_TRUE; + } + + pCap->halTstampPrecision = 15; /* NB: s/w extended from 13 */ + + ahpriv->ah_rxornIsFatal = AH_TRUE; + return AH_TRUE; +} + +static const char* +ar5210Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID && + (devid == AR5210_PROD || devid == AR5210_DEFAULT)) + return "Atheros 5210"; + return AH_NULL; +} +AH_CHIP(AR5210, ar5210Probe, ar5210Attach); diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_beacon.c b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_beacon.c new file mode 100644 index 0000000000..680e2ded80 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_beacon.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5210_beacon.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" +#include "ar5210/ar5210desc.h" + +/* + * Initialize all of the hardware registers used to send beacons. + */ +void +ar5210SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt) +{ + + OS_REG_WRITE(ah, AR_TIMER0, bt->bt_nexttbtt); + OS_REG_WRITE(ah, AR_TIMER1, bt->bt_nextdba); + OS_REG_WRITE(ah, AR_TIMER2, bt->bt_nextswba); + OS_REG_WRITE(ah, AR_TIMER3, bt->bt_nextatim); + /* + * Set the Beacon register after setting all timers. + */ + OS_REG_WRITE(ah, AR_BEACON, bt->bt_intval); +} + +/* + * Legacy api to Initialize all of the beacon registers. + */ +void +ar5210BeaconInit(struct ath_hal *ah, + uint32_t next_beacon, uint32_t beacon_period) +{ + HAL_BEACON_TIMERS bt; + + bt.bt_nexttbtt = next_beacon; + + if (AH_PRIVATE(ah)->ah_opmode != HAL_M_STA) { + bt.bt_nextdba = (next_beacon - + ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */ + bt.bt_nextswba = (next_beacon - + ath_hal_sw_beacon_response_time) << 3; /* 1/8 TU */ + /* + * The SWBA interrupt is not used for beacons in ad hoc mode + * as we don't yet support ATIMs. So since the beacon never + * changes, the beacon descriptor is set up once and read + * into a special HW buffer, from which it will be + * automagically retrieved at each DMA Beacon Alert (DBA). + */ + + /* Set the ATIM window */ + bt.bt_nextatim = next_beacon + 0; /* NB: no ATIMs */ + } else { + bt.bt_nextdba = ~0; + bt.bt_nextswba = ~0; + bt.bt_nextatim = 1; + } + bt.bt_intval = beacon_period & + (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN); + ar5210SetBeaconTimers(ah, &bt); +} + +void +ar5210ResetStaBeaconTimers(struct ath_hal *ah) +{ + uint32_t val; + + OS_REG_WRITE(ah, AR_TIMER0, 0); /* no beacons */ + val = OS_REG_READ(ah, AR_STA_ID1); + val |= AR_STA_ID1_NO_PSPOLL; /* XXX */ + /* tell the h/w that the associated AP is not PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + val & ~(AR_STA_ID1_DEFAULT_ANTENNA | AR_STA_ID1_PCF)); + OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_PERIOD); +} + +/* + * Set all the beacon related bits on the h/w for stations + * i.e. initializes the corresponding h/w timers; + * also tells the h/w whether to anticipate PCF beacons + * + * dtim_count and cfp_count from the current beacon - their current + * values aren't necessarily maintained in the device struct + */ +void +ar5210SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: setting beacon timers\n", __func__); + + HALASSERT(bs->bs_intval != 0); + /* if the AP will do PCF */ + if (bs->bs_cfpmaxduration != 0) { + /* tell the h/w that the associated AP is PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + (OS_REG_READ(ah, AR_STA_ID1) &~ AR_STA_ID1_DEFAULT_ANTENNA) + | AR_STA_ID1_PCF); + + /* set CFP_PERIOD(1.024ms) register */ + OS_REG_WRITE(ah, AR_CFP_PERIOD, bs->bs_cfpperiod); + + /* set CFP_DUR(1.024ms) register to max cfp duration */ + OS_REG_WRITE(ah, AR_CFP_DUR, bs->bs_cfpmaxduration); + + /* set TIMER2(128us) to anticipated time of next CFP */ + OS_REG_WRITE(ah, AR_TIMER2, bs->bs_cfpnext << 3); + } else { + /* tell the h/w that the associated AP is not PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + OS_REG_READ(ah, AR_STA_ID1) &~ (AR_STA_ID1_DEFAULT_ANTENNA | AR_STA_ID1_PCF)); + } + + /* + * Set TIMER0(1.024ms) to the anticipated time of the next beacon. + */ + OS_REG_WRITE(ah, AR_TIMER0, bs->bs_nexttbtt); + + /* + * Start the beacon timers by setting the BEACON register + * to the beacon interval; also write the tim offset which + * we should know by now. The code, in ar5211WriteAssocid, + * also sets the tim offset once the AID is known which can + * be left as such for now. + */ + OS_REG_WRITE(ah, AR_BEACON, + (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_PERIOD|AR_BEACON_TIM)) + | SM(bs->bs_intval, AR_BEACON_PERIOD) + | SM(bs->bs_timoffset ? bs->bs_timoffset + 4 : 0, AR_BEACON_TIM) + ); + + /* + * Configure the BMISS interrupt. Note that we + * assume the caller blocks interrupts while enabling + * the threshold. + */ + + /* + * Interrupt works only on Crete. + */ + if (AH_PRIVATE(ah)->ah_macRev < AR_SREV_CRETE) + return; + /* + * Counter is only 3-bits. + * Count of 0 with BMISS interrupt enabled will hang the system + * with too many interrupts + */ + if (AH_PRIVATE(ah)->ah_macRev >= AR_SREV_CRETE && + (bs->bs_bmissthreshold&7) == 0) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: invalid beacon miss threshold %u\n", + __func__, bs->bs_bmissthreshold); +#endif + return; + } +#define BMISS_MAX (AR_RSSI_THR_BM_THR >> AR_RSSI_THR_BM_THR_S) + /* + * Configure the BMISS interrupt. Note that we + * assume the caller blocks interrupts while enabling + * the threshold. + * + * NB: the beacon miss count field is only 3 bits which + * is much smaller than what's found on later parts; + * clamp overflow values as a safeguard. + */ + ahp->ah_rssiThr = (ahp->ah_rssiThr &~ AR_RSSI_THR_BM_THR) + | SM(bs->bs_bmissthreshold > BMISS_MAX ? + BMISS_MAX : bs->bs_bmissthreshold, + AR_RSSI_THR_BM_THR); + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); +#undef BMISS_MAX +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_interrupts.c b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_interrupts.c new file mode 100644 index 0000000000..ccc233232a --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_interrupts.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5210_interrupts.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" + +/* + * Return non-zero if an interrupt is pending. + */ +HAL_BOOL +ar5210IsInterruptPending(struct ath_hal *ah) +{ + return (OS_REG_READ(ah, AR_INTPEND) ? AH_TRUE : AH_FALSE); +} + +/* + * Read the Interrupt Status Register value and return + * an abstracted bitmask of the data found in the ISR. + * Note that reading the ISR clear pending interrupts. + */ +HAL_BOOL +ar5210GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) +{ +#define AR_FATAL_INT \ + (AR_ISR_MCABT_INT | AR_ISR_SSERR_INT | AR_ISR_DPERR_INT | AR_ISR_RXORN_INT) + struct ath_hal_5210 *ahp = AH5210(ah); + uint32_t isr; + + isr = OS_REG_READ(ah, AR_ISR); + if (isr == 0xffffffff) { + *masked = 0; + return AH_FALSE; + } + + /* + * Mask interrupts that have no device-independent + * representation; these are added back below. We + * also masked with the abstracted IMR to insure no + * status bits leak through that weren't requested + * (e.g. RXNOFRM) and that might confuse the caller. + */ + *masked = (isr & HAL_INT_COMMON) & ahp->ah_maskReg; + + if (isr & AR_FATAL_INT) + *masked |= HAL_INT_FATAL; + if (isr & (AR_ISR_RXOK_INT | AR_ISR_RXERR_INT)) + *masked |= HAL_INT_RX; + if (isr & (AR_ISR_TXOK_INT | AR_ISR_TXDESC_INT | AR_ISR_TXERR_INT | AR_ISR_TXEOL_INT)) + *masked |= HAL_INT_TX; + + /* + * On fatal errors collect ISR state for debugging. + */ + if (*masked & HAL_INT_FATAL) { + AH_PRIVATE(ah)->ah_fatalState[0] = isr; + } + + return AH_TRUE; +#undef AR_FATAL_INT +} + +HAL_INT +ar5210GetInterrupts(struct ath_hal *ah) +{ + return AH5210(ah)->ah_maskReg; +} + +HAL_INT +ar5210SetInterrupts(struct ath_hal *ah, HAL_INT ints) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + uint32_t omask = ahp->ah_maskReg; + uint32_t mask; + + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n", + __func__, omask, ints); + + /* + * Disable interrupts here before reading & modifying + * the mask so that the ISR does not modify the mask + * out from under us. + */ + if (omask & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + } + + mask = ints & HAL_INT_COMMON; + if (ints & HAL_INT_RX) + mask |= AR_IMR_RXOK_INT | AR_IMR_RXERR_INT; + if (ints & HAL_INT_TX) { + if (ahp->ah_txOkInterruptMask) + mask |= AR_IMR_TXOK_INT; + if (ahp->ah_txErrInterruptMask) + mask |= AR_IMR_TXERR_INT; + if (ahp->ah_txDescInterruptMask) + mask |= AR_IMR_TXDESC_INT; + if (ahp->ah_txEolInterruptMask) + mask |= AR_IMR_TXEOL_INT; + } + + /* Write the new IMR and store off our SW copy. */ + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask); + OS_REG_WRITE(ah, AR_IMR, mask); + ahp->ah_maskReg = ints; + + /* Re-enable interrupts as appropriate. */ + if (ints & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE); + } + + return omask; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_keycache.c b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_keycache.c new file mode 100644 index 0000000000..9594ce3d94 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_keycache.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5210_keycache.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" + +#define AR_KEYTABLE_SIZE 64 +#define KEY_XOR 0xaa + +/* + * Return the size of the hardware key cache. + */ +u_int +ar5210GetKeyCacheSize(struct ath_hal *ah) +{ + return AR_KEYTABLE_SIZE; +} + +/* + * Return the size of the hardware key cache. + */ +HAL_BOOL +ar5210IsKeyCacheEntryValid(struct ath_hal *ah, uint16_t entry) +{ + if (entry < AR_KEYTABLE_SIZE) { + uint32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry)); + if (val & AR_KEYTABLE_VALID) + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Clear the specified key cache entry. + */ +HAL_BOOL +ar5210ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry) +{ + if (entry < AR_KEYTABLE_SIZE) { + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Sets the mac part of the specified key cache entry and mark it valid. + */ +HAL_BOOL +ar5210SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac) +{ + uint32_t macHi, macLo; + + if (entry < AR_KEYTABLE_SIZE) { + /* + * Set MAC address -- shifted right by 1. MacLo is + * the 4 MSBs, and MacHi is the 2 LSBs. + */ + if (mac != AH_NULL) { + macHi = (mac[5] << 8) | mac[4]; + macLo = (mac[3] << 24)| (mac[2] << 16) + | (mac[1] << 8) | mac[0]; + macLo >>= 1; + macLo |= (macHi & 1) << 31; /* carry */ + macHi >>= 1; + } else { + macLo = macHi = 0; + } + + OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), + macHi | AR_KEYTABLE_VALID); + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Sets the contents of the specified key cache entry. + */ +HAL_BOOL +ar5210SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, + const HAL_KEYVAL *k, const uint8_t *mac, int xorKey) +{ + uint32_t key0, key1, key2, key3, key4; + uint32_t keyType; + uint32_t xorMask= xorKey ? + (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0; + + if (entry >= AR_KEYTABLE_SIZE) + return AH_FALSE; + if (k->kv_type != HAL_CIPHER_WEP) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cipher %u not supported\n", + __func__, k->kv_type); + return AH_FALSE; + } + + /* NB: only WEP supported */ + if (k->kv_len < 40 / NBBY) + return AH_FALSE; + if (k->kv_len <= 40 / NBBY) + keyType = AR_KEYTABLE_TYPE_40; + else if (k->kv_len <= 104 / NBBY) + keyType = AR_KEYTABLE_TYPE_104; + else + keyType = AR_KEYTABLE_TYPE_128; + + key0 = LE_READ_4(k->kv_val+0) ^ xorMask; + key1 = (LE_READ_2(k->kv_val+4) ^ xorMask) & 0xffff; + key2 = LE_READ_4(k->kv_val+6) ^ xorMask; + key3 = (LE_READ_2(k->kv_val+10) ^ xorMask) & 0xffff; + key4 = LE_READ_4(k->kv_val+12) ^ xorMask; + if (k->kv_len <= 104 / NBBY) + key4 &= 0xff; + + /* + * Note: WEP key cache hardware requires that each double-word + * pair be written in even/odd order (since the destination is + * a 64-bit register). Don't reorder these writes w/o + * understanding this! + */ + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); + return ar5210SetKeyCacheEntryMac(ah, entry, mac); +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_misc.c b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_misc.c new file mode 100644 index 0000000000..a6739171cf --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_misc.c @@ -0,0 +1,642 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5210_misc.c,v 1.6 2008/11/27 22:29:37 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" +#include "ar5210/ar5210phy.h" + +#include "ah_eeprom_v1.h" + +#define AR_NUM_GPIO 6 /* 6 GPIO bits */ +#define AR_GPIOD_MASK 0x2f /* 6-bit mask */ + +void +ar5210GetMacAddress(struct ath_hal *ah, uint8_t *mac) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); +} + +HAL_BOOL +ar5210SetMacAddress(struct ath_hal *ah, const uint8_t *mac) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); + return AH_TRUE; +} + +void +ar5210GetBssIdMask(struct ath_hal *ah, uint8_t *mask) +{ + static const uint8_t ones[IEEE80211_ADDR_LEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + OS_MEMCPY(mask, ones, IEEE80211_ADDR_LEN); +} + +HAL_BOOL +ar5210SetBssIdMask(struct ath_hal *ah, const uint8_t *mask) +{ + return AH_FALSE; +} + +/* + * Read 16 bits of data from the specified EEPROM offset. + */ +HAL_BOOL +ar5210EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) +{ + (void) OS_REG_READ(ah, AR_EP_AIR(off)); /* activate read op */ + if (!ath_hal_wait(ah, AR_EP_STA, + AR_EP_STA_RDCMPLT | AR_EP_STA_RDERR, AR_EP_STA_RDCMPLT)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: read failed for entry 0x%x\n", + __func__, AR_EP_AIR(off)); + return AH_FALSE; + } + *data = OS_REG_READ(ah, AR_EP_RDATA) & 0xffff; + return AH_TRUE; +} + +#ifdef AH_SUPPORT_WRITE_EEPROM +/* + * Write 16 bits of data to the specified EEPROM offset. + */ +HAL_BOOL +ar5210EepromWrite(struct ath_hal *ah, u_int off, uint16_t data) +{ + return AH_FALSE; +} +#endif /* AH_SUPPORT_WRITE_EEPROM */ + +/* + * Attempt to change the cards operating regulatory domain to the given value + */ +HAL_BOOL +ar5210SetRegulatoryDomain(struct ath_hal *ah, + uint16_t regDomain, HAL_STATUS *status) +{ + HAL_STATUS ecode; + + if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { + ecode = HAL_EINVAL; + goto bad; + } + /* + * Check if EEPROM is configured to allow this; must + * be a proper version and the protection bits must + * permit re-writing that segment of the EEPROM. + */ + if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { + ecode = HAL_EEWRITE; + goto bad; + } + ecode = HAL_EIO; /* disallow all writes */ +bad: + if (status) + *status = ecode; + return AH_FALSE; +} + +/* + * Return the wireless modes (a,b,g,t) supported by hardware. + * + * This value is what is actually supported by the hardware + * and is unaffected by regulatory/country code settings. + * + */ +u_int +ar5210GetWirelessModes(struct ath_hal *ah) +{ + /* XXX could enable turbo mode but can't do all rates */ + return HAL_MODE_11A; +} + +/* + * Called if RfKill is supported (according to EEPROM). Set the interrupt and + * GPIO values so the ISR and can disable RF on a switch signal + */ +void +ar5210EnableRfKill(struct ath_hal *ah) +{ + uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent; + int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL); + int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY); + + /* + * If radio disable switch connection to GPIO bit 0 is enabled + * program GPIO interrupt. + * If rfkill bit on eeprom is 1, setupeeprommap routine has already + * verified that it is a later version of eeprom, it has a place for + * rfkill bit and it is set to 1, indicating that GPIO bit 0 hardware + * connection is present. + */ + ar5210Gpio0SetIntr(ah, select, (ar5210GpioGet(ah, select) == polarity)); +} + +/* + * Configure GPIO Output lines + */ +HAL_BOOL +ar5210GpioCfgOutput(struct ath_hal *ah, uint32_t gpio) +{ + HALASSERT(gpio < AR_NUM_GPIO); + + OS_REG_WRITE(ah, AR_GPIOCR, + (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio)) + | AR_GPIOCR_OUT1(gpio)); + + return AH_TRUE; +} + +/* + * Configure GPIO Input lines + */ +HAL_BOOL +ar5210GpioCfgInput(struct ath_hal *ah, uint32_t gpio) +{ + HALASSERT(gpio < AR_NUM_GPIO); + + OS_REG_WRITE(ah, AR_GPIOCR, + (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio)) + | AR_GPIOCR_IN(gpio)); + + return AH_TRUE; +} + +/* + * Once configured for I/O - set output lines + */ +HAL_BOOL +ar5210GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) +{ + uint32_t reg; + + HALASSERT(gpio < AR_NUM_GPIO); + + reg = OS_REG_READ(ah, AR_GPIODO); + reg &= ~(1 << gpio); + reg |= (val&1) << gpio; + + OS_REG_WRITE(ah, AR_GPIODO, reg); + return AH_TRUE; +} + +/* + * Once configured for I/O - get input lines + */ +uint32_t +ar5210GpioGet(struct ath_hal *ah, uint32_t gpio) +{ + if (gpio < AR_NUM_GPIO) { + uint32_t val = OS_REG_READ(ah, AR_GPIODI); + val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1; + return val; + } else { + return 0xffffffff; + } +} + +/* + * Set the GPIO 0 Interrupt + */ +void +ar5210Gpio0SetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) +{ + uint32_t val = OS_REG_READ(ah, AR_GPIOCR); + + /* Clear the bits that we will modify. */ + val &= ~(AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA | + AR_GPIOCR_ALL(gpio)); + + val |= AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_ENA; + if (ilevel) + val |= AR_GPIOCR_INT_SELH; + + /* Don't need to change anything for low level interrupt. */ + OS_REG_WRITE(ah, AR_GPIOCR, val); + + /* Change the interrupt mask. */ + ar5210SetInterrupts(ah, AH5210(ah)->ah_maskReg | HAL_INT_GPIO); +} + +/* + * Change the LED blinking pattern to correspond to the connectivity + */ +void +ar5210SetLedState(struct ath_hal *ah, HAL_LED_STATE state) +{ + uint32_t val; + + val = OS_REG_READ(ah, AR_PCICFG); + switch (state) { + case HAL_LED_INIT: + val &= ~(AR_PCICFG_LED_PEND | AR_PCICFG_LED_ACT); + break; + case HAL_LED_RUN: + /* normal blink when connected */ + val &= ~AR_PCICFG_LED_PEND; + val |= AR_PCICFG_LED_ACT; + break; + default: + val |= AR_PCICFG_LED_PEND; + val &= ~AR_PCICFG_LED_ACT; + break; + } + OS_REG_WRITE(ah, AR_PCICFG, val); +} + +/* + * Return 1 or 2 for the corresponding antenna that is in use + */ +u_int +ar5210GetDefAntenna(struct ath_hal *ah) +{ + uint32_t val = OS_REG_READ(ah, AR_STA_ID1); + return (val & AR_STA_ID1_DEFAULT_ANTENNA ? 2 : 1); +} + +void +ar5210SetDefAntenna(struct ath_hal *ah, u_int antenna) +{ + uint32_t val = OS_REG_READ(ah, AR_STA_ID1); + + if (antenna != (val & AR_STA_ID1_DEFAULT_ANTENNA ? 2 : 1)) { + /* + * Antenna change requested, force a toggle of the default. + */ + OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_DEFAULT_ANTENNA); + } +} + +HAL_ANT_SETTING +ar5210GetAntennaSwitch(struct ath_hal *ah) +{ + return HAL_ANT_VARIABLE; +} + +HAL_BOOL +ar5210SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) +{ + /* XXX not sure how to fix antenna */ + return (settings == HAL_ANT_VARIABLE); +} + +/* + * Change association related fields programmed into the hardware. + * Writing a valid BSSID to the hardware effectively enables the hardware + * to synchronize its TSF to the correct beacons and receive frames coming + * from that BSSID. It is called by the SME JOIN operation. + */ +void +ar5210WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + /* XXX save bssid for possible re-use on reset */ + OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); + OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); + OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | + ((assocId & 0x3fff)<> 19) & 0x1ff; + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + return (OS_REG_READ(ah, AR_TSF_U32) ^ + OS_REG_READ(ah, AR_TSF_L32) ^ nf); +} + +/* + * Detect if our card is present + */ +HAL_BOOL +ar5210DetectCardPresent(struct ath_hal *ah) +{ + /* + * Read the Silicon Revision register and compare that + * to what we read at attach time. If the same, we say + * a card/device is present. + */ + return (AH_PRIVATE(ah)->ah_macRev == (OS_REG_READ(ah, AR_SREV) & 0xff)); +} + +/* + * Update MIB Counters + */ +void +ar5210UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats) +{ + stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); + stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); + stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); + stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); + stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); +} + +HAL_BOOL +ar5210SetSifsTime(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + if (us > ath_hal_mac_usec(ah, 0x7ff)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n", + __func__, us); + ahp->ah_sifstime = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_RMW_FIELD(ah, AR_IFS0, AR_IFS0_SIFS, + ath_hal_mac_clks(ah, us)); + ahp->ah_sifstime = us; + return AH_TRUE; + } +} + +u_int +ar5210GetSifsTime(struct ath_hal *ah) +{ + u_int clks = OS_REG_READ(ah, AR_IFS0) & 0x7ff; + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +HAL_BOOL +ar5210SetSlotTime(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n", + __func__, us); + ahp->ah_slottime = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_WRITE(ah, AR_SLOT_TIME, ath_hal_mac_clks(ah, us)); + ahp->ah_slottime = us; + return AH_TRUE; + } +} + +u_int +ar5210GetSlotTime(struct ath_hal *ah) +{ + u_int clks = OS_REG_READ(ah, AR_SLOT_TIME) & 0xffff; + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +HAL_BOOL +ar5210SetAckTimeout(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n", + __func__, us); + ahp->ah_acktimeout = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_RMW_FIELD(ah, AR_TIME_OUT, + AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us)); + ahp->ah_acktimeout = us; + return AH_TRUE; + } +} + +u_int +ar5210GetAckTimeout(struct ath_hal *ah) +{ + u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +u_int +ar5210GetAckCTSRate(struct ath_hal *ah) +{ + return ((AH5210(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0); +} + +HAL_BOOL +ar5210SetAckCTSRate(struct ath_hal *ah, u_int high) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + if (high) { + OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); + ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB; + } else { + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); + ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB; + } + return AH_TRUE; +} + +HAL_BOOL +ar5210SetCTSTimeout(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n", + __func__, us); + ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_RMW_FIELD(ah, AR_TIME_OUT, + AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); + ahp->ah_ctstimeout = us; + return AH_TRUE; + } +} + +u_int +ar5210GetCTSTimeout(struct ath_hal *ah) +{ + u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +HAL_BOOL +ar5210SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) +{ + /* nothing to do */ + return AH_TRUE; +} + +void +ar5210SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) +{ +} + +/* + * Control Adaptive Noise Immunity Parameters + */ +HAL_BOOL +ar5210AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) +{ + return AH_FALSE; +} + +void +ar5210AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats, HAL_CHANNEL *chan) +{ +} + +void +ar5210MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats) +{ +} + +#define AR_DIAG_SW_DIS_CRYPTO (AR_DIAG_SW_DIS_ENC | AR_DIAG_SW_DIS_DEC) + +HAL_STATUS +ar5210GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t *result) +{ + + switch (type) { + case HAL_CAP_CIPHER: /* cipher handled in hardware */ + return (capability == HAL_CIPHER_WEP ? HAL_OK : HAL_ENOTSUPP); + default: + return ath_hal_getcapability(ah, type, capability, result); + } +} + +HAL_BOOL +ar5210SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t setting, HAL_STATUS *status) +{ + + switch (type) { + case HAL_CAP_DIAG: /* hardware diagnostic support */ + /* + * NB: could split this up into virtual capabilities, + * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly + * seems worth the additional complexity. + */ +#ifdef AH_DEBUG + AH_PRIVATE(ah)->ah_diagreg = setting; +#else + AH_PRIVATE(ah)->ah_diagreg = setting & 0x6; /* ACK+CTS */ +#endif + OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); + return AH_TRUE; + case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ + return AH_FALSE; /* NB: disallow */ + default: + return ath_hal_setcapability(ah, type, capability, + setting, status); + } +} + +HAL_BOOL +ar5210GetDiagState(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize) +{ +#ifdef AH_PRIVATE_DIAG + uint32_t pcicfg; + HAL_BOOL ok; + + switch (request) { + case HAL_DIAG_EEPROM: + /* XXX */ + break; + case HAL_DIAG_EEREAD: + if (argsize != sizeof(uint16_t)) + return AH_FALSE; + pcicfg = OS_REG_READ(ah, AR_PCICFG); + OS_REG_WRITE(ah, AR_PCICFG, pcicfg | AR_PCICFG_EEPROMSEL); + ok = ath_hal_eepromRead(ah, *(const uint16_t *)args, *result); + OS_REG_WRITE(ah, AR_PCICFG, pcicfg); + if (ok) + *resultsize = sizeof(uint16_t); + return ok; + } +#endif + return ath_hal_getdiagstate(ah, request, + args, argsize, result, resultsize); +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_phy.c b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_phy.c new file mode 100644 index 0000000000..14dc384a95 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_phy.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5210_phy.c,v 1.3 2008/11/10 01:19:37 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5210/ar5210.h" + +/* shorthands to compact tables for readability */ +#define OFDM IEEE80211_T_OFDM +#define TURBO IEEE80211_T_TURBO + +HAL_RATE_TABLE ar5210_11a_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80|12), 0 }, +/* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 0 }, +/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, (0x80|48), 4 }, +/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 4 }, +/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 4 }, +/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 4 } + }, +}; + +HAL_RATE_TABLE ar5210_turbo_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, TURBO, 6000, 0x0b, 0x00, (0x80|12), 0 }, +/* 9 Mb */ { AH_TRUE, TURBO, 9000, 0x0f, 0x00, 18, 0 }, +/* 12 Mb */ { AH_TRUE, TURBO, 12000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, TURBO, 18000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, TURBO, 24000, 0x09, 0x00, (0x80|48), 4 }, +/* 36 Mb */ { AH_TRUE, TURBO, 36000, 0x0d, 0x00, 72, 4 }, +/* 48 Mb */ { AH_TRUE, TURBO, 48000, 0x08, 0x00, 96, 4 }, +/* 54 Mb */ { AH_TRUE, TURBO, 54000, 0x0c, 0x00, 108, 4 } + }, +}; + +#undef OFDM +#undef TURBO + +const HAL_RATE_TABLE * +ar5210GetRateTable(struct ath_hal *ah, u_int mode) +{ + HAL_RATE_TABLE *rt; + switch (mode) { + case HAL_MODE_11A: + rt = &ar5210_11a_table; + break; + case HAL_MODE_TURBO: + rt = &ar5210_turbo_table; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", + __func__, mode); + return AH_NULL; + } + ath_hal_setupratetable(ah, rt); + return rt; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_power.c b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_power.c new file mode 100644 index 0000000000..c2771f2735 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_power.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5210_power.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" + +/* + * Notify Power Mgt is disabled in self-generated frames. + * If requested, set Power Mode of chip to auto/normal. + */ +static void +ar5210SetPowerModeAuto(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SV); + if (setChip) + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_ALLOW); +} + +/* + * Notify Power Mgt is enabled in self-generated frames. + * If requested, force chip awake. + * + * Returns A_OK if chip is awake or successfully forced awake. + * + * WARNING WARNING WARNING + * There is a problem with the chip where sometimes it will not wake up. + */ +static HAL_BOOL +ar5210SetPowerModeAwake(struct ath_hal *ah, int setChip) +{ +#define POWER_UP_TIME 2000 + uint32_t val; + int i; + + if (setChip) { + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_WAKE); + OS_DELAY(2000); /* Give chip the chance to awake */ + + for (i = POWER_UP_TIME / 200; i != 0; i--) { + val = OS_REG_READ(ah, AR_PCICFG); + if ((val & AR_PCICFG_SPWR_DN) == 0) + break; + OS_DELAY(200); + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, + AR_SCR_SLE_WAKE); + } + if (i == 0) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n", + __func__, POWER_UP_TIME/20); +#endif + return AH_FALSE; + } + } + + OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SV); + return AH_TRUE; +#undef POWER_UP_TIME +} + +/* + * Notify Power Mgt is disabled in self-generated frames. + * If requested, force chip to sleep. + */ +static void +ar5210SetPowerModeSleep(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SV); + if (setChip) + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_SLP); +} + +HAL_BOOL +ar5210SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) +{ + struct ath_hal_5210 *ahp = AH5210(ah); +#ifdef AH_DEBUG + static const char* modes[] = { + "AWAKE", + "FULL-SLEEP", + "NETWORK SLEEP", + "UNDEFINED" + }; +#endif + int status = AH_TRUE; + + HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__, + modes[ahp->ah_powerMode], modes[mode], + setChip ? "set chip " : ""); + switch (mode) { + case HAL_PM_AWAKE: + status = ar5210SetPowerModeAwake(ah, setChip); + break; + case HAL_PM_FULL_SLEEP: + ar5210SetPowerModeSleep(ah, setChip); + break; + case HAL_PM_NETWORK_SLEEP: + ar5210SetPowerModeAuto(ah, setChip); + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n", + __func__, mode); + return AH_FALSE; + } + ahp->ah_powerMode = mode; + return status; +} + +HAL_POWER_MODE +ar5210GetPowerMode(struct ath_hal *ah) +{ + /* Just so happens the h/w maps directly to the abstracted value */ + return MS(OS_REG_READ(ah, AR_SCR), AR_SCR_SLE); +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_recv.c b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_recv.c new file mode 100644 index 0000000000..489c55ae28 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_recv.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5210_recv.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" +#include "ar5210/ar5210desc.h" + +/* + * Get the RXDP. + */ +uint32_t +ar5210GetRxDP(struct ath_hal *ah) +{ + return OS_REG_READ(ah, AR_RXDP); +} + +/* + * Set the RxDP. + */ +void +ar5210SetRxDP(struct ath_hal *ah, uint32_t rxdp) +{ + OS_REG_WRITE(ah, AR_RXDP, rxdp); +} + + +/* + * Set Receive Enable bits. + */ +void +ar5210EnableReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_CR, AR_CR_RXE); +} + +/* + * Stop Receive at the DMA engine + */ +HAL_BOOL +ar5210StopDmaReceive(struct ath_hal *ah) +{ + int i; + + OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */ + for (i = 0; i < 1000; i++) { + if ((OS_REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) + return AH_TRUE; + OS_DELAY(10); + } +#ifdef AH_DEBUG + ath_hal_printf(ah, "ar5210: dma receive failed to stop in 10ms\n"); + ath_hal_printf(ah, "AR_CR=0x%x\n", OS_REG_READ(ah, AR_CR)); + ath_hal_printf(ah, "AR_DIAG_SW=0x%x\n", OS_REG_READ(ah, AR_DIAG_SW)); +#endif + return AH_FALSE; +} + +/* + * Start Transmit at the PCU engine (unpause receive) + */ +void +ar5210StartPcuReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_DIAG_SW, + OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_RX)); +} + +/* + * Stop Transmit at the PCU engine (pause receive) + */ +void +ar5210StopPcuReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_DIAG_SW, + OS_REG_READ(ah, AR_DIAG_SW) | AR_DIAG_SW_DIS_RX); +} + +/* + * Set multicast filter 0 (lower 32-bits) + * filter 1 (upper 32-bits) + */ +void +ar5210SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1) +{ + OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0); + OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1); +} + +/* + * Clear multicast filter by index + */ +HAL_BOOL +ar5210ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix) +{ + uint32_t val; + + if (ix >= 64) + return AH_FALSE; + if (ix >= 32) { + val = OS_REG_READ(ah, AR_MCAST_FIL1); + OS_REG_WRITE(ah, AR_MCAST_FIL1, (val &~ (1<<(ix-32)))); + } else { + val = OS_REG_READ(ah, AR_MCAST_FIL0); + OS_REG_WRITE(ah, AR_MCAST_FIL0, (val &~ (1<= 64) + return AH_FALSE; + if (ix >= 32) { + val = OS_REG_READ(ah, AR_MCAST_FIL1); + OS_REG_WRITE(ah, AR_MCAST_FIL1, (val | (1<<(ix-32)))); + } else { + val = OS_REG_READ(ah, AR_MCAST_FIL0); + OS_REG_WRITE(ah, AR_MCAST_FIL0, (val | (1<ds_ctl0 = 0; + ads->ds_ctl1 = size & AR_BufLen; + if (ads->ds_ctl1 != size) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: buffer size %u too large\n", + __func__, size); + return AH_FALSE; + } + if (flags & HAL_RXDESC_INTREQ) + ads->ds_ctl1 |= AR_RxInterReq; + ads->ds_status0 = ads->ds_status1 = 0; + + return AH_TRUE; +} + +/* + * Process an RX descriptor, and return the status to the caller. + * Copy some hardware specific items into the software portion + * of the descriptor. + * + * NB: the caller is responsible for validating the memory contents + * of the descriptor (e.g. flushing any cached copy). + */ +HAL_STATUS +ar5210ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, + uint32_t pa, struct ath_desc *nds, uint64_t tsf, + struct ath_rx_status *rs) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + struct ar5210_desc *ands = AR5210DESC(nds); + uint32_t now, rstamp; + + if ((ads->ds_status1 & AR_Done) == 0) + return HAL_EINPROGRESS; + /* + * Given the use of a self-linked tail be very sure that the hw is + * done with this descriptor; the hw may have done this descriptor + * once and picked it up again...make sure the hw has moved on. + */ + if ((ands->ds_status1 & AR_Done) == 0 && OS_REG_READ(ah, AR_RXDP) == pa) + return HAL_EINPROGRESS; + + rs->rs_datalen = ads->ds_status0 & AR_DataLen; + rstamp = MS(ads->ds_status1, AR_RcvTimestamp); + /* + * Convert timestamp. The value in the + * descriptor is bits [10..22] of the TSF. + */ + now = (OS_REG_READ(ah, AR_TSF_L32) >> 10) & 0xffff; + if ((now & 0x1fff) < rstamp) + rstamp |= (now - 0x2000) & 0xffff; + else + rstamp |= now; + /* NB: keep only 15 bits for consistency w/ other chips */ + rs->rs_tstamp = rstamp & 0x7fff; + rs->rs_status = 0; + if ((ads->ds_status1 & AR_FrmRcvOK) == 0) { + if (ads->ds_status1 & AR_CRCErr) + rs->rs_status |= HAL_RXERR_CRC; + else if (ads->ds_status1 & AR_DecryptCRCErr) + rs->rs_status |= HAL_RXERR_DECRYPT; + else if (ads->ds_status1 & AR_FIFOOverrun) + rs->rs_status |= HAL_RXERR_FIFO; + else { + rs->rs_status |= HAL_RXERR_PHY; + rs->rs_phyerr = + (ads->ds_status1 & AR_PHYErr) >> AR_PHYErr_S; + } + } + /* XXX what about KeyCacheMiss? */ + rs->rs_rssi = MS(ads->ds_status0, AR_RcvSigStrength); + if (ads->ds_status1 & AR_KeyIdxValid) + rs->rs_keyix = MS(ads->ds_status1, AR_KeyIdx); + else + rs->rs_keyix = HAL_RXKEYIX_INVALID; + /* NB: caller expected to do rate table mapping */ + rs->rs_rate = MS(ads->ds_status0, AR_RcvRate); + rs->rs_antenna = (ads->ds_status0 & AR_RcvAntenna) ? 1 : 0; + rs->rs_more = (ads->ds_status0 & AR_More) ? 1 : 0; + + return HAL_OK; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_reset.c b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_reset.c new file mode 100644 index 0000000000..40c6768247 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_reset.c @@ -0,0 +1,1003 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5210_reset.c,v 1.8 2008/11/11 17:25:16 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" +#include "ar5210/ar5210phy.h" + +#include "ah_eeprom_v1.h" + +typedef struct { + uint32_t Offset; + uint32_t Value; +} REGISTER_VAL; + +static const REGISTER_VAL ar5k0007_init[] = { +#include "ar5210/ar5k_0007.ini" +}; + +/* Default Power Settings for channels outside of EEPROM range */ +static const uint8_t ar5k0007_pwrSettings[17] = { +/* gain delta pc dac */ +/* 54 48 36 24 18 12 9 54 48 36 24 18 12 9 6 ob db */ + 9, 9, 0, 0, 0, 0, 0, 2, 2, 6, 6, 6, 6, 6, 6, 2, 2 +}; + +/* + * The delay, in usecs, between writing AR_RC with a reset + * request and waiting for the chip to settle. If this is + * too short then the chip does not come out of sleep state. + * Note this value was empirically derived and may be dependent + * on the host machine (don't know--the problem was identified + * on an IBM 570e laptop; 10us delays worked on other systems). + */ +#define AR_RC_SETTLE_TIME 20000 + +static HAL_BOOL ar5210SetResetReg(struct ath_hal *, + uint32_t resetMask, u_int delay); +static HAL_BOOL ar5210SetChannel(struct ath_hal *, HAL_CHANNEL_INTERNAL *); +static void ar5210SetOperatingMode(struct ath_hal *, int opmode); + +/* + * Places the device in and out of reset and then places sane + * values in the registers based on EEPROM config, initialization + * vectors (as determined by the mode), and station configuration + * + * bChannelChange is used to preserve DMA/PCU registers across + * a HW Reset during channel change. + */ +HAL_BOOL +ar5210Reset(struct ath_hal *ah, HAL_OPMODE opmode, + HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status) +{ +#define N(a) (sizeof (a) /sizeof (a[0])) +#define FAIL(_code) do { ecode = _code; goto bad; } while (0) + struct ath_hal_5210 *ahp = AH5210(ah); + const HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + HAL_CHANNEL_INTERNAL *ichan; + HAL_STATUS ecode; + uint32_t ledstate; + int i, q; + + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s: opmode %u channel %u/0x%x %s channel\n", __func__, + opmode, chan->channel, chan->channelFlags, + bChannelChange ? "change" : "same"); + + if ((chan->channelFlags & CHANNEL_5GHZ) == 0) { + /* Only 11a mode */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: channel not 5Ghz\n", __func__); + FAIL(HAL_EINVAL); + } + /* + * Map public channel to private. + */ + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->channel, chan->channelFlags); + FAIL(HAL_EINVAL); + } + switch (opmode) { + case HAL_M_STA: + case HAL_M_IBSS: + case HAL_M_HOSTAP: + case HAL_M_MONITOR: + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n", + __func__, opmode); + FAIL(HAL_EINVAL); + break; + } + + ledstate = OS_REG_READ(ah, AR_PCICFG) & + (AR_PCICFG_LED_PEND | AR_PCICFG_LED_ACT); + + if (!ar5210ChipReset(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", + __func__); + FAIL(HAL_EIO); + } + + OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr)); + OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)); + ar5210SetOperatingMode(ah, opmode); + + switch (opmode) { + case HAL_M_HOSTAP: + OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG); + OS_REG_WRITE(ah, AR_PCICFG, + AR_PCICFG_LED_ACT | AR_PCICFG_LED_BCTL); + break; + case HAL_M_IBSS: + OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG | AR_BCR_BCMD); + OS_REG_WRITE(ah, AR_PCICFG, + AR_PCICFG_CLKRUNEN | AR_PCICFG_LED_PEND | AR_PCICFG_LED_BCTL); + break; + case HAL_M_STA: + OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG); + OS_REG_WRITE(ah, AR_PCICFG, + AR_PCICFG_CLKRUNEN | AR_PCICFG_LED_PEND | AR_PCICFG_LED_BCTL); + break; + case HAL_M_MONITOR: + OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG); + OS_REG_WRITE(ah, AR_PCICFG, + AR_PCICFG_LED_ACT | AR_PCICFG_LED_BCTL); + break; + } + + /* Restore previous led state */ + OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | ledstate); + + OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); + OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4)); + + OS_REG_WRITE(ah, AR_TXDP0, 0); + OS_REG_WRITE(ah, AR_TXDP1, 0); + OS_REG_WRITE(ah, AR_RXDP, 0); + + /* + * Initialize interrupt state. + */ + (void) OS_REG_READ(ah, AR_ISR); /* cleared on read */ + OS_REG_WRITE(ah, AR_IMR, 0); + OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + ahp->ah_maskReg = 0; + + (void) OS_REG_READ(ah, AR_BSR); /* cleared on read */ + OS_REG_WRITE(ah, AR_TXCFG, AR_DMASIZE_128B); + OS_REG_WRITE(ah, AR_RXCFG, AR_DMASIZE_128B); + + OS_REG_WRITE(ah, AR_TOPS, 8); /* timeout prescale */ + OS_REG_WRITE(ah, AR_RXNOFRM, 8); /* RX no frame timeout */ + OS_REG_WRITE(ah, AR_RPGTO, 0); /* RX frame gap timeout */ + OS_REG_WRITE(ah, AR_TXNOFRM, 0); /* TX no frame timeout */ + + OS_REG_WRITE(ah, AR_SFR, 0); + OS_REG_WRITE(ah, AR_MIBC, 0); /* unfreeze ctrs + clr state */ + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); + OS_REG_WRITE(ah, AR_CFP_DUR, 0); + + ar5210SetRxFilter(ah, 0); /* nothing for now */ + OS_REG_WRITE(ah, AR_MCAST_FIL0, 0); /* multicast filter */ + OS_REG_WRITE(ah, AR_MCAST_FIL1, 0); /* XXX was 2 */ + + OS_REG_WRITE(ah, AR_TX_MASK0, 0); + OS_REG_WRITE(ah, AR_TX_MASK1, 0); + OS_REG_WRITE(ah, AR_CLR_TMASK, 1); + OS_REG_WRITE(ah, AR_TRIG_LEV, 1); /* minimum */ + + OS_REG_WRITE(ah, AR_DIAG_SW, 0); + + OS_REG_WRITE(ah, AR_CFP_PERIOD, 0); + OS_REG_WRITE(ah, AR_TIMER0, 0); /* next beacon time */ + OS_REG_WRITE(ah, AR_TSF_L32, 0); /* local clock */ + OS_REG_WRITE(ah, AR_TIMER1, ~0); /* next DMA beacon alert */ + OS_REG_WRITE(ah, AR_TIMER2, ~0); /* next SW beacon alert */ + OS_REG_WRITE(ah, AR_TIMER3, 1); /* next ATIM window */ + + /* Write the INI values for PHYreg initialization */ + for (i = 0; i < N(ar5k0007_init); i++) { + uint32_t reg = ar5k0007_init[i].Offset; + /* On channel change, don't reset the PCU registers */ + if (!(bChannelChange && (0x8000 <= reg && reg < 0x9000))) + OS_REG_WRITE(ah, reg, ar5k0007_init[i].Value); + } + + /* Setup the transmit power values for cards since 0x0[0-2]05 */ + if (!ar5210SetTransmitPower(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error init'ing transmit power\n", __func__); + FAIL(HAL_EIO); + } + + OS_REG_WRITE(ah, AR_PHY(10), + (OS_REG_READ(ah, AR_PHY(10)) & 0xFFFF00FF) | + (ee->ee_xlnaOn << 8)); + OS_REG_WRITE(ah, AR_PHY(13), + (ee->ee_xpaOff << 24) | (ee->ee_xpaOff << 16) | + (ee->ee_xpaOn << 8) | ee->ee_xpaOn); + OS_REG_WRITE(ah, AR_PHY(17), + (OS_REG_READ(ah, AR_PHY(17)) & 0xFFFFC07F) | + ((ee->ee_antenna >> 1) & 0x3F80)); + OS_REG_WRITE(ah, AR_PHY(18), + (OS_REG_READ(ah, AR_PHY(18)) & 0xFFFC0FFF) | + ((ee->ee_antenna << 10) & 0x3F000)); + OS_REG_WRITE(ah, AR_PHY(25), + (OS_REG_READ(ah, AR_PHY(25)) & 0xFFF80FFF) | + ((ee->ee_thresh62 << 12) & 0x7F000)); + OS_REG_WRITE(ah, AR_PHY(68), + (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFFFC) | + (ee->ee_antenna & 0x3)); + + if (!ar5210SetChannel(ah, ichan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set channel\n", + __func__); + FAIL(HAL_EIO); + } + if (bChannelChange) { + if (!(ichan->privFlags & CHANNEL_DFS)) + ichan->privFlags &= ~CHANNEL_INTERFERENCE; + chan->channelFlags = ichan->channelFlags; + chan->privFlags = ichan->privFlags; + } + + /* Activate the PHY */ + OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ENABLE); + + OS_DELAY(1000); /* Wait a bit (1 msec) */ + + /* calibrate the HW and poll the bit going to 0 for completion */ + OS_REG_WRITE(ah, AR_PHY_AGCCTL, + OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_CAL); + (void) ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_CAL, 0); + + /* Perform noise floor calibration and set status */ + if (!ar5210CalNoiseFloor(ah, ichan)) { + chan->channelFlags |= CHANNEL_CW_INT; + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: noise floor calibration failed\n", __func__); + FAIL(HAL_EIO); + } + + for (q = 0; q < HAL_NUM_TX_QUEUES; q++) + ar5210ResetTxQueue(ah, q); + + if (AH_PRIVATE(ah)->ah_rfkillEnabled) + ar5210EnableRfKill(ah); + + /* + * Writing to AR_BEACON will start timers. Hence it should be + * the last register to be written. Do not reset tsf, do not + * enable beacons at this point, but preserve other values + * like beaconInterval. + */ + OS_REG_WRITE(ah, AR_BEACON, + (OS_REG_READ(ah, AR_BEACON) & + ~(AR_BEACON_EN | AR_BEACON_RESET_TSF))); + + /* Restore user-specified slot time and timeouts */ + if (ahp->ah_sifstime != (u_int) -1) + ar5210SetSifsTime(ah, ahp->ah_sifstime); + if (ahp->ah_slottime != (u_int) -1) + ar5210SetSlotTime(ah, ahp->ah_slottime); + if (ahp->ah_acktimeout != (u_int) -1) + ar5210SetAckTimeout(ah, ahp->ah_acktimeout); + if (ahp->ah_ctstimeout != (u_int) -1) + ar5210SetCTSTimeout(ah, ahp->ah_ctstimeout); + if (AH_PRIVATE(ah)->ah_diagreg != 0) + OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); + + AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */ + + HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__); + + return AH_TRUE; +bad: + if (*status) + *status = ecode; + return AH_FALSE; +#undef FAIL +#undef N +} + +static void +ar5210SetOperatingMode(struct ath_hal *ah, int opmode) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + uint32_t val; + + val = OS_REG_READ(ah, AR_STA_ID1) & 0xffff; + switch (opmode) { + case HAL_M_HOSTAP: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_AP + | AR_STA_ID1_NO_PSPOLL + | AR_STA_ID1_DESC_ANTENNA + | ahp->ah_staId1Defaults); + break; + case HAL_M_IBSS: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_ADHOC + | AR_STA_ID1_NO_PSPOLL + | AR_STA_ID1_DESC_ANTENNA + | ahp->ah_staId1Defaults); + break; + case HAL_M_STA: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_NO_PSPOLL + | AR_STA_ID1_PWR_SV + | ahp->ah_staId1Defaults); + break; + case HAL_M_MONITOR: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_NO_PSPOLL + | ahp->ah_staId1Defaults); + break; + } +} + +void +ar5210SetPCUConfig(struct ath_hal *ah) +{ + ar5210SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode); +} + +/* + * Places the PHY and Radio chips into reset. A full reset + * must be called to leave this state. The PCI/MAC/PCU are + * not placed into reset as we must receive interrupt to + * re-enable the hardware. + */ +HAL_BOOL +ar5210PhyDisable(struct ath_hal *ah) +{ + return ar5210SetResetReg(ah, AR_RC_RPHY, 10); +} + +/* + * Places all of hardware into reset + */ +HAL_BOOL +ar5210Disable(struct ath_hal *ah) +{ +#define AR_RC_HW (AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC) + if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + + /* + * Reset the HW - PCI must be reset after the rest of the + * device has been reset + */ + if (!ar5210SetResetReg(ah, AR_RC_HW, AR_RC_SETTLE_TIME)) + return AH_FALSE; + OS_DELAY(1000); + (void) ar5210SetResetReg(ah, AR_RC_HW | AR_RC_RPCI, AR_RC_SETTLE_TIME); + OS_DELAY(2100); /* 8245 @ 96Mhz hangs with 2000us. */ + + return AH_TRUE; +#undef AR_RC_HW +} + +/* + * Places the hardware into reset and then pulls it out of reset + */ +HAL_BOOL +ar5210ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan) +{ +#define AR_RC_HW (AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC) + + HALDEBUG(ah, HAL_DEBUG_RESET, "%s turbo %s\n", __func__, + chan && IS_CHAN_TURBO(chan) ? "enabled" : "disabled"); + + if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + + /* Place chip in turbo before reset to cleanly reset clocks */ + OS_REG_WRITE(ah, AR_PHY_FRCTL, + chan && IS_CHAN_TURBO(chan) ? AR_PHY_TURBO_MODE : 0); + + /* + * Reset the HW. + * PCI must be reset after the rest of the device has been reset. + */ + if (!ar5210SetResetReg(ah, AR_RC_HW, AR_RC_SETTLE_TIME)) + return AH_FALSE; + OS_DELAY(1000); + if (!ar5210SetResetReg(ah, AR_RC_HW | AR_RC_RPCI, AR_RC_SETTLE_TIME)) + return AH_FALSE; + OS_DELAY(2100); /* 8245 @ 96Mhz hangs with 2000us. */ + + /* + * Bring out of sleep mode (AGAIN) + * + * WARNING WARNING WARNING + * + * There is a problem with the chip where it doesn't always indicate + * that it's awake, so initializePowerUp() will fail. + */ + if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + + /* Clear warm reset reg */ + return ar5210SetResetReg(ah, 0, 10); +#undef AR_RC_HW +} + +enum { + FIRPWR_M = 0x03fc0000, + FIRPWR_S = 18, + KCOARSEHIGH_M = 0x003f8000, + KCOARSEHIGH_S = 15, + KCOARSELOW_M = 0x00007f80, + KCOARSELOW_S = 7, + ADCSAT_ICOUNT_M = 0x0001f800, + ADCSAT_ICOUNT_S = 11, + ADCSAT_THRESH_M = 0x000007e0, + ADCSAT_THRESH_S = 5 +}; + +/* + * Recalibrate the lower PHY chips to account for temperature/environment + * changes. + */ +HAL_BOOL +ar5210PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan, u_int chainMask, + HAL_BOOL longCal, HAL_BOOL *isCalDone) +{ + uint32_t regBeacon; + uint32_t reg9858, reg985c, reg9868; + HAL_CHANNEL_INTERNAL *ichan; + + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->channel, chan->channelFlags); + return AH_FALSE; + } + /* Disable tx and rx */ + OS_REG_WRITE(ah, AR_DIAG_SW, + OS_REG_READ(ah, AR_DIAG_SW) | (AR_DIAG_SW_DIS_TX | AR_DIAG_SW_DIS_RX)); + + /* Disable Beacon Enable */ + regBeacon = OS_REG_READ(ah, AR_BEACON); + OS_REG_WRITE(ah, AR_BEACON, regBeacon & ~AR_BEACON_EN); + + /* Delay 4ms to ensure that all tx and rx activity has ceased */ + OS_DELAY(4000); + + /* Disable AGC to radio traffic */ + OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) | 0x08000000); + /* Wait for the AGC traffic to cease. */ + OS_DELAY(10); + + /* Change Channel to relock synth */ + if (!ar5210SetChannel(ah, ichan)) + return AH_FALSE; + + /* wait for the synthesizer lock to stabilize */ + OS_DELAY(1000); + + /* Re-enable AGC to radio traffic */ + OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) & (~0x08000000)); + + /* + * Configure the AGC so that it is highly unlikely (if not + * impossible) for it to send any gain changes to the analog + * chip. We store off the current values so that they can + * be rewritten below. Setting the following values: + * firpwr = -1 + * Kcoursehigh = -1 + * Kcourselow = -127 + * ADCsat_icount = 2 + * ADCsat_thresh = 12 + */ + reg9858 = OS_REG_READ(ah, 0x9858); + reg985c = OS_REG_READ(ah, 0x985c); + reg9868 = OS_REG_READ(ah, 0x9868); + + OS_REG_WRITE(ah, 0x9858, (reg9858 & ~FIRPWR_M) | + ((-1 << FIRPWR_S) & FIRPWR_M)); + OS_REG_WRITE(ah, 0x985c, + (reg985c & ~(KCOARSEHIGH_M | KCOARSELOW_M)) | + ((-1 << KCOARSEHIGH_S) & KCOARSEHIGH_M) | + ((-127 << KCOARSELOW_S) & KCOARSELOW_M)); + OS_REG_WRITE(ah, 0x9868, + (reg9868 & ~(ADCSAT_ICOUNT_M | ADCSAT_THRESH_M)) | + ((2 << ADCSAT_ICOUNT_S) & ADCSAT_ICOUNT_M) | + ((12 << ADCSAT_THRESH_S) & ADCSAT_THRESH_M)); + + /* Wait for AGC changes to be enacted */ + OS_DELAY(20); + + /* + * We disable RF mix/gain stages for the PGA to avoid a + * race condition that will occur with receiving a frame + * and performing the AGC calibration. This will be + * re-enabled at the end of offset cal. We turn off AGC + * writes during this write as it will go over the analog bus. + */ + OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) | 0x08000000); + OS_DELAY(10); /* wait for the AGC traffic to cease */ + OS_REG_WRITE(ah, 0x98D4, 0x21); + OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) & (~0x08000000)); + + /* wait to make sure that additional AGC traffic has quiesced */ + OS_DELAY(1000); + + /* AGC calibration (this was added to make the NF threshold check work) */ + OS_REG_WRITE(ah, AR_PHY_AGCCTL, + OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_CAL); + if (!ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_CAL, 0)) + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: AGC calibration timeout\n", + __func__); + + /* Rewrite our AGC values we stored off earlier (return AGC to normal operation) */ + OS_REG_WRITE(ah, 0x9858, reg9858); + OS_REG_WRITE(ah, 0x985c, reg985c); + OS_REG_WRITE(ah, 0x9868, reg9868); + + /* Perform noise floor and set status */ + if (!ar5210CalNoiseFloor(ah, ichan)) { + /* + * Delay 5ms before retrying the noise floor - + * just to make sure. We're in an error + * condition here + */ + HALDEBUG(ah, HAL_DEBUG_NFCAL | HAL_DEBUG_PERCAL, + "%s: Performing 2nd Noise Cal\n", __func__); + OS_DELAY(5000); + if (!ar5210CalNoiseFloor(ah, ichan)) + chan->channelFlags |= CHANNEL_CW_INT; + } + + /* Clear tx and rx disable bit */ + OS_REG_WRITE(ah, AR_DIAG_SW, + OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_TX | AR_DIAG_SW_DIS_RX)); + + /* Re-enable Beacons */ + OS_REG_WRITE(ah, AR_BEACON, regBeacon); + + *isCalDone = AH_TRUE; + + return AH_TRUE; +} + +HAL_BOOL +ar5210PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) +{ + return ar5210PerCalibrationN(ah, chan, 0x1, AH_TRUE, isIQdone); +} + +HAL_BOOL +ar5210ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + return AH_TRUE; +} + +/* + * Writes the given reset bit mask into the reset register + */ +static HAL_BOOL +ar5210SetResetReg(struct ath_hal *ah, uint32_t resetMask, u_int delay) +{ + uint32_t mask = resetMask ? resetMask : ~0; + HAL_BOOL rt; + + OS_REG_WRITE(ah, AR_RC, resetMask); + /* need to wait at least 128 clocks when reseting PCI before read */ + OS_DELAY(delay); + + resetMask &= AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC; + mask &= AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC; + rt = ath_hal_wait(ah, AR_RC, mask, resetMask); + if ((resetMask & AR_RC_RMAC) == 0) { + if (isBigEndian()) { + /* + * Set CFG, little-endian for register + * and descriptor accesses. + */ + mask = INIT_CONFIG_STATUS | + AR_CFG_SWTD | AR_CFG_SWRD | AR_CFG_SWRG; + OS_REG_WRITE(ah, AR_CFG, LE_READ_4(&mask)); + } else + OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS); + } + return rt; +} + + +/* + * Returns: the pcdac value + */ +static uint8_t +getPcdac(struct ath_hal *ah, const struct tpcMap *pRD, uint8_t dBm) +{ + int32_t i; + int useNextEntry = AH_FALSE; + uint32_t interp; + + for (i = AR_TP_SCALING_ENTRIES - 1; i >= 0; i--) { + /* Check for exact entry */ + if (dBm == AR_I2DBM(i)) { + if (pRD->pcdac[i] != 63) + return pRD->pcdac[i]; + useNextEntry = AH_TRUE; + } else if (dBm + 1 == AR_I2DBM(i) && i > 0) { + /* Interpolate for between entry with a logish scale */ + if (pRD->pcdac[i] != 63 && pRD->pcdac[i-1] != 63) { + interp = (350 * (pRD->pcdac[i] - pRD->pcdac[i-1])) + 999; + interp = (interp / 1000) + pRD->pcdac[i-1]; + return interp; + } + useNextEntry = AH_TRUE; + } else if (useNextEntry == AH_TRUE) { + /* Grab the next lowest */ + if (pRD->pcdac[i] != 63) + return pRD->pcdac[i]; + } + } + + /* Return the lowest Entry if we haven't returned */ + for (i = 0; i < AR_TP_SCALING_ENTRIES; i++) + if (pRD->pcdac[i] != 63) + return pRD->pcdac[i]; + + /* No value to return from table */ +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: empty transmit power table?\n", __func__); +#endif + return 1; +} + +/* + * Find or interpolates the gainF value from the table ptr. + */ +static uint8_t +getGainF(struct ath_hal *ah, const struct tpcMap *pRD, + uint8_t pcdac, uint8_t *dBm) +{ + uint32_t interp; + int low, high, i; + + low = high = -1; + + for (i = 0; i < AR_TP_SCALING_ENTRIES; i++) { + if(pRD->pcdac[i] == 63) + continue; + if (pcdac == pRD->pcdac[i]) { + *dBm = AR_I2DBM(i); + return pRD->gainF[i]; /* Exact Match */ + } + if (pcdac > pRD->pcdac[i]) + low = i; + if (pcdac < pRD->pcdac[i]) { + high = i; + if (low == -1) { + *dBm = AR_I2DBM(i); + /* PCDAC is lower than lowest setting */ + return pRD->gainF[i]; + } + break; + } + } + if (i >= AR_TP_SCALING_ENTRIES && low == -1) { + /* No settings were found */ +#ifdef AH_DEBUG + ath_hal_printf(ah, + "%s: no valid entries in the pcdac table: %d\n", + __func__, pcdac); +#endif + return 63; + } + if (i >= AR_TP_SCALING_ENTRIES) { + /* PCDAC setting was above the max setting in the table */ + *dBm = AR_I2DBM(low); + return pRD->gainF[low]; + } + /* Only exact if table has no missing entries */ + *dBm = (low + high) + 3; + + /* + * Perform interpolation between low and high values to find gainF + * linearly scale the pcdac between low and high + */ + interp = ((pcdac - pRD->pcdac[low]) * 1000) / + (pRD->pcdac[high] - pRD->pcdac[low]); + /* + * Multiply the scale ratio by the gainF difference + * (plus a rnd up factor) + */ + interp = ((interp * (pRD->gainF[high] - pRD->gainF[low])) + 999) / 1000; + + /* Add ratioed gain_f to low gain_f value */ + return interp + pRD->gainF[low]; +} + +HAL_BOOL +ar5210SetTxPowerLimit(struct ath_hal *ah, uint32_t limit) +{ + AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, AR5210_MAX_RATE_POWER); + /* XXX flush to h/w */ + return AH_TRUE; +} + +/* + * Get TXPower values and set them in the radio + */ +static HAL_BOOL +setupPowerSettings(struct ath_hal *ah, HAL_CHANNEL *chan, uint8_t cp[17]) +{ + const HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + uint8_t gainFRD, gainF36, gainF48, gainF54; + uint8_t dBmRD, dBm36, dBm48, dBm54, dontcare; + uint32_t rd, group; + const struct tpcMap *pRD; + + /* Set OB/DB Values regardless of channel */ + cp[15] = (ee->ee_biasCurrents >> 4) & 0x7; + cp[16] = ee->ee_biasCurrents & 0x7; + + if (chan->channel < 5170 || chan->channel > 5320) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u\n", + __func__, chan->channel); + return AH_FALSE; + } + + HALASSERT(ee->ee_version >= AR_EEPROM_VER1 && + ee->ee_version < AR_EEPROM_VER3); + + /* Match regulatory domain */ + for (rd = 0; rd < AR_REG_DOMAINS_MAX; rd++) + if (AH_PRIVATE(ah)->ah_currentRD == ee->ee_regDomain[rd]) + break; + if (rd == AR_REG_DOMAINS_MAX) { +#ifdef AH_DEBUG + ath_hal_printf(ah, + "%s: no calibrated regulatory domain matches the " + "current regularly domain (0x%0x)\n", __func__, + AH_PRIVATE(ah)->ah_currentRD); +#endif + return AH_FALSE; + } + group = ((chan->channel - 5170) / 10); + + if (group > 11) { + /* Pull 5.29 into the 5.27 group */ + group--; + } + + /* Integer divide will set group from 0 to 4 */ + group = group / 3; + pRD = &ee->ee_tpc[group]; + + /* Set PC DAC Values */ + cp[14] = pRD->regdmn[rd]; + cp[9] = AH_MIN(pRD->regdmn[rd], pRD->rate36); + cp[8] = AH_MIN(pRD->regdmn[rd], pRD->rate48); + cp[7] = AH_MIN(pRD->regdmn[rd], pRD->rate54); + + /* Find Corresponding gainF values for RD, 36, 48, 54 */ + gainFRD = getGainF(ah, pRD, pRD->regdmn[rd], &dBmRD); + gainF36 = getGainF(ah, pRD, cp[9], &dBm36); + gainF48 = getGainF(ah, pRD, cp[8], &dBm48); + gainF54 = getGainF(ah, pRD, cp[7], &dBm54); + + /* Power Scale if requested */ + if (AH_PRIVATE(ah)->ah_tpScale != HAL_TP_SCALE_MAX) { + static const uint16_t tpcScaleReductionTable[5] = + { 0, 3, 6, 9, AR5210_MAX_RATE_POWER }; + uint16_t tpScale; + + tpScale = tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale]; + if (dBmRD < tpScale+3) + dBmRD = 3; /* min */ + else + dBmRD -= tpScale; + cp[14] = getPcdac(ah, pRD, dBmRD); + gainFRD = getGainF(ah, pRD, cp[14], &dontcare); + dBm36 = AH_MIN(dBm36, dBmRD); + cp[9] = getPcdac(ah, pRD, dBm36); + gainF36 = getGainF(ah, pRD, cp[9], &dontcare); + dBm48 = AH_MIN(dBm48, dBmRD); + cp[8] = getPcdac(ah, pRD, dBm48); + gainF48 = getGainF(ah, pRD, cp[8], &dontcare); + dBm54 = AH_MIN(dBm54, dBmRD); + cp[7] = getPcdac(ah, pRD, dBm54); + gainF54 = getGainF(ah, pRD, cp[7], &dontcare); + } + /* Record current dBm at rate 6 */ + AH_PRIVATE(ah)->ah_maxPowerLevel = 2*dBmRD; + + cp[13] = cp[12] = cp[11] = cp[10] = cp[14]; + + /* Set GainF Values */ + cp[0] = gainFRD - gainF54; + cp[1] = gainFRD - gainF48; + cp[2] = gainFRD - gainF36; + /* 9, 12, 18, 24 have no gain_delta from 6 */ + cp[3] = cp[4] = cp[5] = cp[6] = 0; + return AH_TRUE; +} + +/* + * Places the device in and out of reset and then places sane + * values in the registers based on EEPROM config, initialization + * vectors (as determined by the mode), and station configuration + */ +HAL_BOOL +ar5210SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL *chan) +{ +#define N(a) (sizeof (a) / sizeof (a[0])) + static const uint32_t pwr_regs_start[17] = { + 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xf0000000, + 0xcc000000, 0x00000000, 0x00000000, + 0x00000000, 0x0a000000, 0x000000e2, + 0x0a000020, 0x01000002, 0x01000018, + 0x40000000, 0x00000418 + }; + uint16_t i; + uint8_t cp[sizeof(ar5k0007_pwrSettings)]; + uint32_t pwr_regs[17]; + + OS_MEMCPY(pwr_regs, pwr_regs_start, sizeof(pwr_regs)); + OS_MEMCPY(cp, ar5k0007_pwrSettings, sizeof(cp)); + + /* Check the EEPROM tx power calibration settings */ + if (!setupPowerSettings(ah, chan, cp)) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: unable to setup power settings\n", + __func__); +#endif + return AH_FALSE; + } + if (cp[15] < 1 || cp[15] > 5) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: OB out of range (%u)\n", + __func__, cp[15]); +#endif + return AH_FALSE; + } + if (cp[16] < 1 || cp[16] > 5) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: DB out of range (%u)\n", + __func__, cp[16]); +#endif + return AH_FALSE; + } + + /* reverse bits of the transmit power array */ + for (i = 0; i < 7; i++) + cp[i] = ath_hal_reverseBits(cp[i], 5); + for (i = 7; i < 15; i++) + cp[i] = ath_hal_reverseBits(cp[i], 6); + + /* merge transmit power values into the register - quite gross */ + pwr_regs[0] |= ((cp[1] << 5) & 0xE0) | (cp[0] & 0x1F); + pwr_regs[1] |= ((cp[3] << 7) & 0x80) | ((cp[2] << 2) & 0x7C) | + ((cp[1] >> 3) & 0x03); + pwr_regs[2] |= ((cp[4] << 4) & 0xF0) | ((cp[3] >> 1) & 0x0F); + pwr_regs[3] |= ((cp[6] << 6) & 0xC0) | ((cp[5] << 1) & 0x3E) | + ((cp[4] >> 4) & 0x01); + pwr_regs[4] |= ((cp[7] << 3) & 0xF8) | ((cp[6] >> 2) & 0x07); + pwr_regs[5] |= ((cp[9] << 7) & 0x80) | ((cp[8] << 1) & 0x7E) | + ((cp[7] >> 5) & 0x01); + pwr_regs[6] |= ((cp[10] << 5) & 0xE0) | ((cp[9] >> 1) & 0x1F); + pwr_regs[7] |= ((cp[11] << 3) & 0xF8) | ((cp[10] >> 3) & 0x07); + pwr_regs[8] |= ((cp[12] << 1) & 0x7E) | ((cp[11] >> 5) & 0x01); + pwr_regs[9] |= ((cp[13] << 5) & 0xE0); + pwr_regs[10] |= ((cp[14] << 3) & 0xF8) | ((cp[13] >> 3) & 0x07); + pwr_regs[11] |= ((cp[14] >> 5) & 0x01); + + /* Set OB */ + pwr_regs[8] |= (ath_hal_reverseBits(cp[15], 3) << 7) & 0x80; + pwr_regs[9] |= (ath_hal_reverseBits(cp[15], 3) >> 1) & 0x03; + + /* Set DB */ + pwr_regs[9] |= (ath_hal_reverseBits(cp[16], 3) << 2) & 0x1C; + + /* Write the registers */ + for (i = 0; i < N(pwr_regs)-1; i++) + OS_REG_WRITE(ah, 0x0000989c, pwr_regs[i]); + /* last write is a flush */ + OS_REG_WRITE(ah, 0x000098d4, pwr_regs[i]); + + return AH_TRUE; +#undef N +} + +/* + * Takes the MHz channel value and sets the Channel value + * + * ASSUMES: Writes enabled to analog bus before AGC is active + * or by disabling the AGC. + */ +static HAL_BOOL +ar5210SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + uint32_t data; + + /* Set the Channel */ + data = ath_hal_reverseBits((chan->channel - 5120)/10, 5); + data = (data << 1) | 0x41; + OS_REG_WRITE(ah, AR_PHY(0x27), data); + OS_REG_WRITE(ah, AR_PHY(0x30), 0); + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +} + +int16_t +ar5210GetNoiseFloor(struct ath_hal *ah) +{ + int16_t nf; + + nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff; + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + return nf; +} + +#define NORMAL_NF_THRESH (-72) +/* + * Peform the noisefloor calibration and check for + * any constant channel interference + * + * Returns: TRUE for a successful noise floor calibration; else FALSE + */ +HAL_BOOL +ar5210CalNoiseFloor(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + int32_t nf, nfLoops; + + /* Calibrate the noise floor */ + OS_REG_WRITE(ah, AR_PHY_AGCCTL, + OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_NF); + + /* Do not read noise floor until it has done the first update */ + if (!ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_NF, 0)) { +#ifdef ATH_HAL_DEBUG + ath_hal_printf(ah, " -PHY NF Reg state: 0x%x\n", + OS_REG_READ(ah, AR_PHY_AGCCTL)); + ath_hal_printf(ah, " -MAC Reset Reg state: 0x%x\n", + OS_REG_READ(ah, AR_RC)); + ath_hal_printf(ah, " -PHY Active Reg state: 0x%x\n", + OS_REG_READ(ah, AR_PHY_ACTIVE)); +#endif /* ATH_HAL_DEBUG */ + return AH_FALSE; + } + + nf = 0; + /* Keep checking until the floor is below the threshold or the nf is done */ + for (nfLoops = 0; ((nfLoops < 21) && (nf > NORMAL_NF_THRESH)); nfLoops++) { + OS_DELAY(1000); /* Sleep for 1 ms */ + nf = ar5210GetNoiseFloor(ah); + } + + if (nf > NORMAL_NF_THRESH) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Bad noise cal %d\n", + __func__, nf); + chan->rawNoiseFloor = 0; + return AH_FALSE; + } + chan->rawNoiseFloor = nf; + return AH_TRUE; +} + +/* + * Adjust NF based on statistical values for 5GHz frequencies. + */ +int16_t +ar5210GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) +{ + return 0; +} + +HAL_RFGAIN +ar5210GetRfgain(struct ath_hal *ah) +{ + return HAL_RFGAIN_INACTIVE; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_xmit.c b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_xmit.c new file mode 100644 index 0000000000..7ce9c8353a --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210_xmit.c @@ -0,0 +1,623 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5210_xmit.c,v 1.5 2008/11/10 04:08:02 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" +#include "ar5210/ar5210phy.h" +#include "ar5210/ar5210desc.h" + +/* + * Set the properties of the tx queue with the parameters + * from qInfo. The queue must previously have been setup + * with a call to ar5210SetupTxQueue. + */ +HAL_BOOL +ar5210SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], qInfo); +} + +/* + * Return the properties for the specified tx queue. + */ +HAL_BOOL +ar5210GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + return ath_hal_getTxQProps(ah, qInfo, &ahp->ah_txq[q]); +} + +/* + * Allocate and initialize a tx DCU/QCU combination. + */ +int +ar5210SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_TX_QUEUE_INFO *qi; + int q; + + switch (type) { + case HAL_TX_QUEUE_BEACON: + q = 2; + break; + case HAL_TX_QUEUE_CAB: + q = 1; + break; + case HAL_TX_QUEUE_DATA: + q = 0; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad tx queue type %u\n", + __func__, type); + return -1; + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + + qi = &ahp->ah_txq[q]; + if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n", + __func__, q); + return -1; + } + OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO)); + qi->tqi_type = type; + if (qInfo == AH_NULL) { + /* by default enable OK+ERR+DESC+URN interrupts */ + qi->tqi_qflags = + HAL_TXQ_TXOKINT_ENABLE + | HAL_TXQ_TXERRINT_ENABLE + | HAL_TXQ_TXDESCINT_ENABLE + | HAL_TXQ_TXURNINT_ENABLE + ; + qi->tqi_aifs = INIT_AIFS; + qi->tqi_cwmin = HAL_TXQ_USEDEFAULT; /* NB: do at reset */ + qi->tqi_shretry = INIT_SH_RETRY; + qi->tqi_lgretry = INIT_LG_RETRY; + } else + (void) ar5210SetTxQueueProps(ah, q, qInfo); + /* NB: must be followed by ar5210ResetTxQueue */ + return q; +} + +/* + * Free a tx DCU/QCU combination. + */ +HAL_BOOL +ar5210ReleaseTxQueue(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_TX_QUEUE_INFO *qi; + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + return AH_FALSE; + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: release queue %u\n", __func__, q); + + qi->tqi_type = HAL_TX_QUEUE_INACTIVE; + ahp->ah_txOkInterruptMask &= ~(1 << q); + ahp->ah_txErrInterruptMask &= ~(1 << q); + ahp->ah_txDescInterruptMask &= ~(1 << q); + ahp->ah_txEolInterruptMask &= ~(1 << q); + ahp->ah_txUrnInterruptMask &= ~(1 << q); + + return AH_TRUE; +#undef N +} + +HAL_BOOL +ar5210ResetTxQueue(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan; + HAL_TX_QUEUE_INFO *qi; + uint32_t cwMin; + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + return AH_FALSE; + } + + /* + * Ignore any non-data queue(s). + */ + if (qi->tqi_type != HAL_TX_QUEUE_DATA) + return AH_TRUE; + + /* Set turbo mode / base mode parameters on or off */ + if (IS_CHAN_TURBO(chan)) { + OS_REG_WRITE(ah, AR_SLOT_TIME, INIT_SLOT_TIME_TURBO); + OS_REG_WRITE(ah, AR_TIME_OUT, INIT_ACK_CTS_TIMEOUT_TURBO); + OS_REG_WRITE(ah, AR_USEC, INIT_TRANSMIT_LATENCY_TURBO); + OS_REG_WRITE(ah, AR_IFS0, + ((INIT_SIFS_TURBO + qi->tqi_aifs * INIT_SLOT_TIME_TURBO) + << AR_IFS0_DIFS_S) + | INIT_SIFS_TURBO); + OS_REG_WRITE(ah, AR_IFS1, INIT_PROTO_TIME_CNTRL_TURBO); + OS_REG_WRITE(ah, AR_PHY(17), + (OS_REG_READ(ah, AR_PHY(17)) & ~0x7F) | 0x38); + OS_REG_WRITE(ah, AR_PHY_FRCTL, + AR_PHY_SERVICE_ERR | AR_PHY_TXURN_ERR | + AR_PHY_ILLLEN_ERR | AR_PHY_ILLRATE_ERR | + AR_PHY_PARITY_ERR | AR_PHY_TIMING_ERR | + 0x2020 | + AR_PHY_TURBO_MODE | AR_PHY_TURBO_SHORT); + } else { + OS_REG_WRITE(ah, AR_SLOT_TIME, INIT_SLOT_TIME); + OS_REG_WRITE(ah, AR_TIME_OUT, INIT_ACK_CTS_TIMEOUT); + OS_REG_WRITE(ah, AR_USEC, INIT_TRANSMIT_LATENCY); + OS_REG_WRITE(ah, AR_IFS0, + ((INIT_SIFS + qi->tqi_aifs * INIT_SLOT_TIME) + << AR_IFS0_DIFS_S) + | INIT_SIFS); + OS_REG_WRITE(ah, AR_IFS1, INIT_PROTO_TIME_CNTRL); + OS_REG_WRITE(ah, AR_PHY(17), + (OS_REG_READ(ah, AR_PHY(17)) & ~0x7F) | 0x1C); + OS_REG_WRITE(ah, AR_PHY_FRCTL, + AR_PHY_SERVICE_ERR | AR_PHY_TXURN_ERR | + AR_PHY_ILLLEN_ERR | AR_PHY_ILLRATE_ERR | + AR_PHY_PARITY_ERR | AR_PHY_TIMING_ERR | 0x1020); + } + + if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) + cwMin = INIT_CWMIN; + else + cwMin = qi->tqi_cwmin; + + /* Set cwmin and retry limit values */ + OS_REG_WRITE(ah, AR_RETRY_LMT, + (cwMin << AR_RETRY_LMT_CW_MIN_S) + | SM(INIT_SLG_RETRY, AR_RETRY_LMT_SLG_RETRY) + | SM(INIT_SSH_RETRY, AR_RETRY_LMT_SSH_RETRY) + | SM(qi->tqi_lgretry, AR_RETRY_LMT_LG_RETRY) + | SM(qi->tqi_shretry, AR_RETRY_LMT_SH_RETRY) + ); + + if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE) + ahp->ah_txOkInterruptMask |= 1 << q; + else + ahp->ah_txOkInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE) + ahp->ah_txErrInterruptMask |= 1 << q; + else + ahp->ah_txErrInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE) + ahp->ah_txDescInterruptMask |= 1 << q; + else + ahp->ah_txDescInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE) + ahp->ah_txEolInterruptMask |= 1 << q; + else + ahp->ah_txEolInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE) + ahp->ah_txUrnInterruptMask |= 1 << q; + else + ahp->ah_txUrnInterruptMask &= ~(1 << q); + + return AH_TRUE; +} + +/* + * Get the TXDP for the "main" data queue. Needs to be extended + * for multiple Q functionality + */ +uint32_t +ar5210GetTxDP(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_TX_QUEUE_INFO *qi; + + HALASSERT(q < HAL_NUM_TX_QUEUES); + + qi = &ahp->ah_txq[q]; + switch (qi->tqi_type) { + case HAL_TX_QUEUE_DATA: + return OS_REG_READ(ah, AR_TXDP0); + case HAL_TX_QUEUE_INACTIVE: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", + __func__, q); + /* fall thru... */ + default: + break; + } + return 0xffffffff; +} + +/* + * Set the TxDP for the "main" data queue. + */ +HAL_BOOL +ar5210SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_TX_QUEUE_INFO *qi; + + HALASSERT(q < HAL_NUM_TX_QUEUES); + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u 0x%x\n", + __func__, q, txdp); + qi = &ahp->ah_txq[q]; + switch (qi->tqi_type) { + case HAL_TX_QUEUE_DATA: +#ifdef AH_DEBUG + /* + * Make sure that TXE is deasserted before setting the + * TXDP. If TXE is still asserted, setting TXDP will + * have no effect. + */ + if (OS_REG_READ(ah, AR_CR) & AR_CR_TXE0) + ath_hal_printf(ah, "%s: TXE asserted; AR_CR=0x%x\n", + __func__, OS_REG_READ(ah, AR_CR)); +#endif + OS_REG_WRITE(ah, AR_TXDP0, txdp); + break; + case HAL_TX_QUEUE_BEACON: + case HAL_TX_QUEUE_CAB: + OS_REG_WRITE(ah, AR_TXDP1, txdp); + break; + case HAL_TX_QUEUE_INACTIVE: + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + /* fall thru... */ + default: + return AH_FALSE; + } + return AH_TRUE; +} + +/* + * Update Tx FIFO trigger level. + * + * Set bIncTrigLevel to TRUE to increase the trigger level. + * Set bIncTrigLevel to FALSE to decrease the trigger level. + * + * Returns TRUE if the trigger level was updated + */ +HAL_BOOL +ar5210UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel) +{ + uint32_t curTrigLevel; + HAL_INT ints = ar5210GetInterrupts(ah); + + /* + * Disable chip interrupts. This is because halUpdateTxTrigLevel + * is called from both ISR and non-ISR contexts. + */ + (void) ar5210SetInterrupts(ah, ints &~ HAL_INT_GLOBAL); + curTrigLevel = OS_REG_READ(ah, AR_TRIG_LEV); + if (bIncTrigLevel){ + /* increase the trigger level */ + curTrigLevel = curTrigLevel + + ((MAX_TX_FIFO_THRESHOLD - curTrigLevel) / 2); + } else { + /* decrease the trigger level if not already at the minimum */ + if (curTrigLevel > MIN_TX_FIFO_THRESHOLD) { + /* decrease the trigger level */ + curTrigLevel--; + } else { + /* no update to the trigger level */ + /* re-enable chip interrupts */ + ar5210SetInterrupts(ah, ints); + return AH_FALSE; + } + } + /* Update the trigger level */ + OS_REG_WRITE(ah, AR_TRIG_LEV, curTrigLevel); + /* re-enable chip interrupts */ + ar5210SetInterrupts(ah, ints); + return AH_TRUE; +} + +/* + * Set Transmit Enable bits for the specified queues. + */ +HAL_BOOL +ar5210StartTxDma(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_TX_QUEUE_INFO *qi; + + HALASSERT(q < HAL_NUM_TX_QUEUES); + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + qi = &ahp->ah_txq[q]; + switch (qi->tqi_type) { + case HAL_TX_QUEUE_DATA: + OS_REG_WRITE(ah, AR_CR, AR_CR_TXE0); + break; + case HAL_TX_QUEUE_CAB: + OS_REG_WRITE(ah, AR_CR, AR_CR_TXE1); /* enable altq xmit */ + OS_REG_WRITE(ah, AR_BCR, + AR_BCR_TQ1V | AR_BCR_BDMAE | AR_BCR_TQ1FV); + break; + case HAL_TX_QUEUE_BEACON: + /* XXX add CR_BCR_BCMD if IBSS mode */ + OS_REG_WRITE(ah, AR_BCR, AR_BCR_TQ1V | AR_BCR_BDMAE); + break; + case HAL_TX_QUEUE_INACTIVE: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", + __func__, q); + /* fal thru... */ + default: + return AH_FALSE; + } + return AH_TRUE; +} + +uint32_t +ar5210NumTxPending(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_TX_QUEUE_INFO *qi; + uint32_t v; + + HALASSERT(q < HAL_NUM_TX_QUEUES); + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + qi = &ahp->ah_txq[q]; + switch (qi->tqi_type) { + case HAL_TX_QUEUE_DATA: + v = OS_REG_READ(ah, AR_CFG); + return MS(v, AR_CFG_TXCNT); + case HAL_TX_QUEUE_INACTIVE: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", + __func__, q); + /* fall thru... */ + default: + break; + } + return 0; +} + +/* + * Stop transmit on the specified queue + */ +HAL_BOOL +ar5210StopTxDma(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_TX_QUEUE_INFO *qi; + + HALASSERT(q < HAL_NUM_TX_QUEUES); + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + qi = &ahp->ah_txq[q]; + switch (qi->tqi_type) { + case HAL_TX_QUEUE_DATA: { + int i; + OS_REG_WRITE(ah, AR_CR, AR_CR_TXD0); + for (i = 0; i < 1000; i++) { + if ((OS_REG_READ(ah, AR_CFG) & AR_CFG_TXCNT) == 0) + break; + OS_DELAY(10); + } + OS_REG_WRITE(ah, AR_CR, 0); + return (i < 1000); + } + case HAL_TX_QUEUE_BEACON: + return ath_hal_wait(ah, AR_BSR, AR_BSR_TXQ1F, 0); + case HAL_TX_QUEUE_INACTIVE: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", + __func__, q); + /* fall thru... */ + default: + break; + } + return AH_FALSE; +} + +/* + * Descriptor Access Functions + */ + +#define VALID_PKT_TYPES \ + ((1<ds_ctl0 = (pktLen & AR_FrameLen) + | (txRate0 << AR_XmitRate_S) + | ((hdrLen << AR_HdrLen_S) & AR_HdrLen) + | frtype + | (flags & HAL_TXDESC_CLRDMASK ? AR_ClearDestMask : 0) + | (flags & HAL_TXDESC_INTREQ ? AR_TxInterReq : 0) + | (antMode ? AR_AntModeXmit : 0) + ; + if (keyIx != HAL_TXKEYIX_INVALID) { + ads->ds_ctl1 = (keyIx << AR_EncryptKeyIdx_S) & AR_EncryptKeyIdx; + ads->ds_ctl0 |= AR_EncryptKeyValid; + } else + ads->ds_ctl1 = 0; + if (flags & HAL_TXDESC_RTSENA) { + ads->ds_ctl0 |= AR_RTSCTSEnable; + ads->ds_ctl1 |= rtsctsDuration & AR_RTSDuration; + } + return AH_TRUE; +} + +HAL_BOOL +ar5210SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int txRate1, u_int txTries1, + u_int txRate2, u_int txTries2, + u_int txRate3, u_int txTries3) +{ + (void) ah; (void) ds; + (void) txRate1; (void) txTries1; + (void) txRate2; (void) txTries2; + (void) txRate3; (void) txTries3; + return AH_FALSE; +} + +void +ar5210IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *ds) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + + ads->ds_ctl0 |= AR_TxInterReq; +} + +HAL_BOOL +ar5210FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg, + const struct ath_desc *ds0) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + + HALASSERT((segLen &~ AR_BufLen) == 0); + + if (firstSeg) { + /* + * First descriptor, don't clobber xmit control data + * setup by ar5210SetupTxDesc. + */ + ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_More); + } else if (lastSeg) { /* !firstSeg && lastSeg */ + /* + * Last descriptor in a multi-descriptor frame, + * copy the transmit parameters from the first + * frame for processing on completion. + */ + ads->ds_ctl0 = AR5210DESC_CONST(ds0)->ds_ctl0; + ads->ds_ctl1 = segLen; + } else { /* !firstSeg && !lastSeg */ + /* + * Intermediate descriptor in a multi-descriptor frame. + */ + ads->ds_ctl0 = 0; + ads->ds_ctl1 = segLen | AR_More; + } + ads->ds_status0 = ads->ds_status1 = 0; + return AH_TRUE; +} + +/* + * Processing of HW TX descriptor. + */ +HAL_STATUS +ar5210ProcTxDesc(struct ath_hal *ah, + struct ath_desc *ds, struct ath_tx_status *ts) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + + if ((ads->ds_status1 & AR_Done) == 0) + return HAL_EINPROGRESS; + + /* Update software copies of the HW status */ + ts->ts_seqnum = ads->ds_status1 & AR_SeqNum; + ts->ts_tstamp = MS(ads->ds_status0, AR_SendTimestamp); + ts->ts_status = 0; + if ((ads->ds_status0 & AR_FrmXmitOK) == 0) { + if (ads->ds_status0 & AR_ExcessiveRetries) + ts->ts_status |= HAL_TXERR_XRETRY; + if (ads->ds_status0 & AR_Filtered) + ts->ts_status |= HAL_TXERR_FILT; + if (ads->ds_status0 & AR_FIFOUnderrun) + ts->ts_status |= HAL_TXERR_FIFO; + } + ts->ts_rate = MS(ads->ds_ctl0, AR_XmitRate); + ts->ts_rssi = MS(ads->ds_status1, AR_AckSigStrength); + ts->ts_shortretry = MS(ads->ds_status0, AR_ShortRetryCnt); + ts->ts_longretry = MS(ads->ds_status0, AR_LongRetryCnt); + ts->ts_antenna = 0; /* NB: don't know */ + ts->ts_finaltsi = 0; + + return HAL_OK; +} + +/* + * Determine which tx queues need interrupt servicing. + * STUB. + */ +void +ar5210GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs) +{ + return; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210desc.h b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210desc.h new file mode 100644 index 0000000000..d7d382ccfa --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210desc.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5210desc.h,v 1.5 2008/11/10 04:08:02 sam Exp $ + */ +#ifndef _DEV_ATH_AR5210DESC_H +#define _DEV_ATH_AR5210DESC_H + +#include "ah_desc.h" + +/* + * Defintions for the DMA descriptors used by the Atheros + * AR5210/AR5211 and AR5110 Wireless Lan controller parts. + */ + +/* DMA descriptors */ +struct ar5210_desc { + uint32_t ds_link; /* link pointer */ + uint32_t ds_data; /* data buffer pointer */ + uint32_t ds_ctl0; /* DMA control 0 */ + uint32_t ds_ctl1; /* DMA control 1 */ + uint32_t ds_status0; /* DMA status 0 */ + uint32_t ds_status1; /* DMA status 1 */ +} __packed; +#define AR5210DESC(_ds) ((struct ar5210_desc *)(_ds)) +#define AR5210DESC_CONST(_ds) ((const struct ar5210_desc *)(_ds)) + +/* TX ds_ctl0 */ +#define AR_FrameLen 0x00000fff /* frame length */ +#define AR_HdrLen 0x0003f000 /* header length */ +#define AR_HdrLen_S 12 +#define AR_XmitRate 0x003c0000 /* txrate */ +#define AR_XmitRate_S 18 +#define AR_Rate_6M 0xb +#define AR_Rate_9M 0xf +#define AR_Rate_12M 0xa +#define AR_Rate_18M 0xe +#define AR_Rate_24M 0x9 +#define AR_Rate_36M 0xd +#define AR_Rate_48M 0x8 +#define AR_Rate_54M 0xc +#define AR_RTSCTSEnable 0x00400000 /* RTS/CTS enable */ +#define AR_LongPkt 0x00800000 /* long packet indication */ +#define AR_ClearDestMask 0x01000000 /* Clear destination mask bit */ +#define AR_AntModeXmit 0x02000000 /* TX antenna seslection */ +#define AR_FrmType 0x1c000000 /* frame type indication */ +#define AR_Frm_Normal 0x00000000 /* normal frame */ +#define AR_Frm_ATIM 0x04000000 /* ATIM frame */ +#define AR_Frm_PSPOLL 0x08000000 /* PS poll frame */ +#define AR_Frm_NoDelay 0x0c000000 /* no delay data */ +#define AR_Frm_PIFS 0x10000000 /* PIFS data */ +#define AR_TxInterReq 0x20000000 /* TX interrupt request */ +#define AR_EncryptKeyValid 0x40000000 /* EncryptKeyIdx is valid */ + +/* TX ds_ctl1 */ +#define AR_BufLen 0x00000fff /* data buffer length */ +#define AR_More 0x00001000 /* more desc in this frame */ +#define AR_EncryptKeyIdx 0x0007e000 /* ecnrypt key table index */ +#define AR_EncryptKeyIdx_S 13 +#define AR_RTSDuration 0xfff80000 /* lower 13bit of duration */ + +/* RX ds_ctl1 */ +/* AR_BufLen 0x00000fff data buffer length */ +#define AR_RxInterReq 0x00002000 /* RX interrupt request */ + +/* TX ds_status0 */ +#define AR_FrmXmitOK 0x00000001 /* TX success */ +#define AR_ExcessiveRetries 0x00000002 /* excessive retries */ +#define AR_FIFOUnderrun 0x00000004 /* TX FIFO underrun */ +#define AR_Filtered 0x00000008 /* TX filter indication */ +/* NB: the spec has the Short+Long retry counts reversed */ +#define AR_LongRetryCnt 0x000000f0 /* long retry count */ +#define AR_LongRetryCnt_S 4 +#define AR_ShortRetryCnt 0x00000f00 /* short retry count */ +#define AR_ShortRetryCnt_S 8 +#define AR_SendTimestamp 0xffff0000 /* TX timestamp */ +#define AR_SendTimestamp_S 16 + +/* RX ds_status0 */ +#define AR_DataLen 0x00000fff /* RX data length */ +/* AR_More 0x00001000 more desc in this frame */ +#define AR_RcvAntenna 0x00004000 /* received on ant 1 */ +#define AR_RcvRate 0x00078000 /* reception rate */ +#define AR_RcvRate_S 15 +#define AR_RcvSigStrength 0x07f80000 /* receive signal strength */ +#define AR_RcvSigStrength_S 19 + +/* TX ds_status1 */ +#define AR_Done 0x00000001 /* descripter complete */ +#define AR_SeqNum 0x00001ffe /* TX sequence number */ +#define AR_AckSigStrength 0x001fe000 /* strength of ACK */ +#define AR_AckSigStrength_S 13 + +/* RX ds_status1 */ +/* AR_Done 0x00000001 descripter complete */ +#define AR_FrmRcvOK 0x00000002 /* frame reception success */ +#define AR_CRCErr 0x00000004 /* CRC error */ +#define AR_FIFOOverrun 0x00000008 /* RX FIFO overrun */ +#define AR_DecryptCRCErr 0x00000010 /* Decryption CRC fiailure */ +#define AR_PHYErr 0x000000e0 /* PHY error */ +#define AR_PHYErr_S 5 +#define AR_PHYErr_NoErr 0x00000000 /* No error */ +#define AR_PHYErr_Tim 0x00000020 /* Timing error */ +#define AR_PHYErr_Par 0x00000040 /* Parity error */ +#define AR_PHYErr_Rate 0x00000060 /* Illegal rate */ +#define AR_PHYErr_Len 0x00000080 /* Illegal length */ +#define AR_PHYErr_QAM 0x000000a0 /* 64 QAM rate */ +#define AR_PHYErr_Srv 0x000000c0 /* Service bit error */ +#define AR_PHYErr_TOR 0x000000e0 /* Transmit override receive */ +#define AR_KeyIdxValid 0x00000100 /* decryption key index valid */ +#define AR_KeyIdx 0x00007e00 /* Decryption key index */ +#define AR_KeyIdx_S 9 +#define AR_RcvTimestamp 0x0fff8000 /* timestamp */ +#define AR_RcvTimestamp_S 15 +#define AR_KeyCacheMiss 0x10000000 /* key cache miss indication */ + +#endif /* _DEV_ATH_AR5210DESC_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210phy.h b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210phy.h new file mode 100644 index 0000000000..6211613d8e --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210phy.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5210phy.h,v 1.4 2008/11/10 01:19:37 sam Exp $ + */ +#ifndef _DEV_ATH_AR5210PHY_H +#define _DEV_ATH_AR5210PHY_H + +/* + * Definitions for the PHY on the Atheros AR5210 parts. + */ + +/* PHY Registers */ +#define AR_PHY_BASE 0x9800 /* PHY register base */ +#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) + +#define AR_PHY_FRCTL 0x9804 /* PHY frame control */ +#define AR_PHY_TURBO_MODE 0x00000001 /* PHY turbo mode */ +#define AR_PHY_TURBO_SHORT 0x00000002 /* PHY turbo short symbol */ +#define AR_PHY_TIMING_ERR 0x01000000 /* Detect PHY timing error */ +#define AR_PHY_PARITY_ERR 0x02000000 /* Detect signal parity err */ +#define AR_PHY_ILLRATE_ERR 0x04000000 /* Detect PHY illegal rate */ +#define AR_PHY_ILLLEN_ERR 0x08000000 /* Detect PHY illegal length */ +#define AR_PHY_SERVICE_ERR 0x20000000 /* Detect PHY nonzero service */ +#define AR_PHY_TXURN_ERR 0x40000000 /* DetectPHY TX underrun */ +#define AR_PHY_FRCTL_BITS \ + "\20\1TURBO_MODE\2TURBO_SHORT\30TIMING_ERR\31PARITY_ERR\32ILLRATE_ERR"\ + "\33ILLEN_ERR\35SERVICE_ERR\36TXURN_ERR" + +#define AR_PHY_AGC 0x9808 /* PHY AGC command */ +#define AR_PHY_AGC_DISABLE 0x08000000 /* Disable PHY AGC */ +#define AR_PHY_AGC_BITS "\20\33DISABLE" + +#define AR_PHY_CHIPID 0x9818 /* PHY chip revision */ + +#define AR_PHY_ACTIVE 0x981c /* PHY activation */ +#define AR_PHY_ENABLE 0x00000001 /* activate PHY */ +#define AR_PHY_DISABLE 0x00000002 /* deactivate PHY */ +#define AR_PHY_ACTIVE_BITS "\20\1ENABLE\2DISABLE" + +#define AR_PHY_AGCCTL 0x9860 /* PHY calibration and noise floor */ +#define AR_PHY_AGC_CAL 0x00000001 /* PHY internal calibration */ +#define AR_PHY_AGC_NF 0x00000002 /* calc PHY noise-floor */ +#define AR_PHY_AGCCTL_BITS "\20\1CAL\2NF" + +#endif /* _DEV_ATH_AR5210PHY_H */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210reg.h b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210reg.h new file mode 100644 index 0000000000..dc49fcdd1d --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5210reg.h @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5210reg.h,v 1.4 2008/11/10 01:19:37 sam Exp $ + */ +#ifndef _DEV_ATH_AR5210REG_H +#define _DEV_ATH_AR5210REG_H + +/* + * Register defintions for the Atheros AR5210/5110 MAC/Basedband + * Processor for IEEE 802.11a 5-GHz Wireless LANs. + */ + +#ifndef PCI_VENDOR_ATHEROS +#define PCI_VENDOR_ATHEROS 0x168c +#endif +#define PCI_PRODUCT_ATHEROS_AR5210 0x0007 +#define PCI_PRODUCT_ATHEROS_AR5210_OLD 0x0004 + +/* DMA Registers */ +#define AR_TXDP0 0x0000 /* TX queue pointer 0 register */ +#define AR_TXDP1 0x0004 /* TX queue pointer 1 register */ +#define AR_CR 0x0008 /* Command register */ +#define AR_RXDP 0x000c /* RX queue descriptor ptr register */ +#define AR_CFG 0x0014 /* Configuration and status register */ +#define AR_ISR 0x001c /* Interrupt status register */ +#define AR_IMR 0x0020 /* Interrupt mask register */ +#define AR_IER 0x0024 /* Interrupt global enable register */ +#define AR_BCR 0x0028 /* Beacon control register */ +#define AR_BSR 0x002c /* Beacon status register */ +#define AR_TXCFG 0x0030 /* TX configuration register */ +#define AR_RXCFG 0x0034 /* RX configuration register */ +#define AR_MIBC 0x0040 /* MIB control register */ +#define AR_TOPS 0x0044 /* Timeout prescale register */ +#define AR_RXNOFRM 0x0048 /* RX no frame timeout register */ +#define AR_TXNOFRM 0x004c /* TX no frame timeout register */ +#define AR_RPGTO 0x0050 /* RX frame gap timeout register */ +#define AR_RFCNT 0x0054 /* RX frame count limit register */ +#define AR_MISC 0x0058 /* Misc control and status register */ +#define AR_RC 0x4000 /* Reset control */ +#define AR_SCR 0x4004 /* Sleep control */ +#define AR_INTPEND 0x4008 /* Interrupt pending */ +#define AR_SFR 0x400c /* Force sleep */ +#define AR_PCICFG 0x4010 /* PCI configuration */ +#define AR_GPIOCR 0x4014 /* GPIO configuration */ +#define AR_GPIODO 0x4018 /* GPIO data output */ +#define AR_GPIODI 0x401c /* GPIO data input */ +#define AR_SREV 0x4020 /* Silicon revision */ +/* EEPROM Access Registers */ +#define AR_EP_AIR_BASE 0x6000 /* EEPROM access initiation regs base */ +#define AR_EP_AIR(n) (AR_EP_AIR_BASE + (n)*4) +#define AR_EP_RDATA 0x6800 /* EEPROM read data register */ +#define AR_EP_STA 0x6c00 /* EEPROM access status register */ +/* PCU Registers */ +#define AR_STA_ID0 0x8000 /* Lower 32bits of MAC address */ +#define AR_STA_ID1 0x8004 /* Upper 16bits of MAC address */ +#define AR_BSS_ID0 0x8008 /* Lower 32bits of BSSID */ +#define AR_BSS_ID1 0x800c /* Upper 16bits of BSSID */ +#define AR_SLOT_TIME 0x8010 /* Length of a back-off */ +#define AR_TIME_OUT 0x8014 /* Timeout to wait for ACK and CTS */ +#define AR_RSSI_THR 0x8018 /* Beacon RSSI warning threshold */ +#define AR_RETRY_LMT 0x801c /* Short and long frame retry limit */ +#define AR_USEC 0x8020 /* Transmit latency */ +#define AR_BEACON 0x8024 /* Beacon control */ +#define AR_CFP_PERIOD 0x8028 /* CFP period */ +#define AR_TIMER0 0x802c /* Next beacon time */ +#define AR_TIMER1 0x8030 /* Next DMA beacon alert time */ +#define AR_TIMER2 0x8034 /* Next software beacon alert time */ +#define AR_TIMER3 0x8038 /* Next ATIM window time */ +#define AR_IFS0 0x8040 /* Protocol timers */ +#define AR_IFS1 0x8044 /* Protocol time and control */ +#define AR_CFP_DUR 0x8048 /* Maximum CFP duration */ +#define AR_RX_FILTER 0x804c /* Receive filter */ +#define AR_MCAST_FIL0 0x8050 /* Lower 32bits of mcast filter mask */ +#define AR_MCAST_FIL1 0x8054 /* Upper 16bits of mcast filter mask */ +#define AR_TX_MASK0 0x8058 /* Lower 32bits of TX mask */ +#define AR_TX_MASK1 0x805c /* Upper 16bits of TX mask */ +#define AR_CLR_TMASK 0x8060 /* Clear TX mask */ +#define AR_TRIG_LEV 0x8064 /* Minimum FIFO fill level before TX */ +#define AR_DIAG_SW 0x8068 /* PCU control */ +#define AR_TSF_L32 0x806c /* Lower 32bits of local clock */ +#define AR_TSF_U32 0x8070 /* Upper 32bits of local clock */ +#define AR_LAST_TSTP 0x8080 /* Lower 32bits of last beacon tstamp */ +#define AR_RETRY_CNT 0x8084 /* Current short or long retry cnt */ +#define AR_BACKOFF 0x8088 /* Back-off status */ +#define AR_NAV 0x808c /* Current NAV value */ +#define AR_RTS_OK 0x8090 /* RTS success counter */ +#define AR_RTS_FAIL 0x8094 /* RTS failure counter */ +#define AR_ACK_FAIL 0x8098 /* ACK failure counter */ +#define AR_FCS_FAIL 0x809c /* FCS failure counter */ +#define AR_BEACON_CNT 0x80a0 /* Valid beacon counter */ +#define AR_KEYTABLE_0 0x9000 /* Encryption key table */ +#define AR_KEYTABLE(n) (AR_KEYTABLE_0 + ((n)*32)) + +#define AR_CR_TXE0 0x00000001 /* TX queue 0 enable */ +#define AR_CR_TXE1 0x00000002 /* TX queue 1 enable */ +#define AR_CR_RXE 0x00000004 /* RX enable */ +#define AR_CR_TXD0 0x00000008 /* TX queue 0 disable */ +#define AR_CR_TXD1 0x00000010 /* TX queue 1 disable */ +#define AR_CR_RXD 0x00000020 /* RX disable */ +#define AR_CR_SWI 0x00000040 /* software interrupt */ +#define AR_CR_BITS \ + "\20\1TXE0\2TXE1\3RXE\4TXD0\5TXD1\6RXD\7SWI" + +#define AR_CFG_SWTD 0x00000001 /* BE for TX desc */ +#define AR_CFG_SWTB 0x00000002 /* BE for TX data */ +#define AR_CFG_SWRD 0x00000004 /* BE for RX desc */ +#define AR_CFG_SWRB 0x00000008 /* BE for RX data */ +#define AR_CFG_SWRG 0x00000010 /* BE for registers */ +#define AR_CFG_EEBS 0x00000200 /* EEPROM busy */ +#define AR_CFG_TXCNT 0x00007800 /* number of TX desc in Q */ +#define AR_CFG_TXCNT_S 11 +#define AR_CFG_TXFSTAT 0x00008000 /* TX DMA status */ +#define AR_CFG_TXFSTRT 0x00010000 /* re-enable TX DMA */ +#define AR_CFG_BITS \ + "\20\1SWTD\2SWTB\3SWRD\4SWRB\5SWRG\14EEBS\17TXFSTAT\20TXFSTRT" + +#define AR_ISR_RXOK_INT 0x00000001 /* RX frame OK */ +#define AR_ISR_RXDESC_INT 0x00000002 /* RX intr request */ +#define AR_ISR_RXERR_INT 0x00000004 /* RX error */ +#define AR_ISR_RXNOFRM_INT 0x00000008 /* no frame received */ +#define AR_ISR_RXEOL_INT 0x00000010 /* RX desc empty */ +#define AR_ISR_RXORN_INT 0x00000020 /* RX fifo overrun */ +#define AR_ISR_TXOK_INT 0x00000040 /* TX frame OK */ +#define AR_ISR_TXDESC_INT 0x00000080 /* TX intr request */ +#define AR_ISR_TXERR_INT 0x00000100 /* TX error */ +#define AR_ISR_TXNOFRM_INT 0x00000200 /* no frame transmitted */ +#define AR_ISR_TXEOL_INT 0x00000400 /* TX desc empty */ +#define AR_ISR_TXURN_INT 0x00000800 /* TX fifo underrun */ +#define AR_ISR_MIB_INT 0x00001000 /* MIB interrupt */ +#define AR_ISR_SWI_INT 0x00002000 /* software interrupt */ +#define AR_ISR_RXPHY_INT 0x00004000 /* PHY RX error */ +#define AR_ISR_RXKCM_INT 0x00008000 /* Key cache miss */ +#define AR_ISR_SWBA_INT 0x00010000 /* software beacon alert */ +#define AR_ISR_BRSSI_INT 0x00020000 /* beacon threshold */ +#define AR_ISR_BMISS_INT 0x00040000 /* beacon missed */ +#define AR_ISR_MCABT_INT 0x00100000 /* master cycle abort */ +#define AR_ISR_SSERR_INT 0x00200000 /* SERR on PCI */ +#define AR_ISR_DPERR_INT 0x00400000 /* Parity error on PCI */ +#define AR_ISR_GPIO_INT 0x01000000 /* GPIO interrupt */ +#define AR_ISR_BITS \ + "\20\1RXOK\2RXDESC\3RXERR\4RXNOFM\5RXEOL\6RXORN\7TXOK\10TXDESC"\ + "\11TXERR\12TXNOFRM\13TXEOL\14TXURN\15MIB\16SWI\17RXPHY\20RXKCM"\ + "\21SWBA\22BRSSI\23BMISS\24MCABT\25SSERR\26DPERR\27GPIO" + +#define AR_IMR_RXOK_INT 0x00000001 /* RX frame OK */ +#define AR_IMR_RXDESC_INT 0x00000002 /* RX intr request */ +#define AR_IMR_RXERR_INT 0x00000004 /* RX error */ +#define AR_IMR_RXNOFRM_INT 0x00000008 /* no frame received */ +#define AR_IMR_RXEOL_INT 0x00000010 /* RX desc empty */ +#define AR_IMR_RXORN_INT 0x00000020 /* RX fifo overrun */ +#define AR_IMR_TXOK_INT 0x00000040 /* TX frame OK */ +#define AR_IMR_TXDESC_INT 0x00000080 /* TX intr request */ +#define AR_IMR_TXERR_INT 0x00000100 /* TX error */ +#define AR_IMR_TXNOFRM_INT 0x00000200 /* no frame transmitted */ +#define AR_IMR_TXEOL_INT 0x00000400 /* TX desc empty */ +#define AR_IMR_TXURN_INT 0x00000800 /* TX fifo underrun */ +#define AR_IMR_MIB_INT 0x00001000 /* MIB interrupt */ +#define AR_IMR_SWI_INT 0x00002000 /* software interrupt */ +#define AR_IMR_RXPHY_INT 0x00004000 /* PHY RX error */ +#define AR_IMR_RXKCM_INT 0x00008000 /* Key cache miss */ +#define AR_IMR_SWBA_INT 0x00010000 /* software beacon alert */ +#define AR_IMR_BRSSI_INT 0x00020000 /* beacon threshold */ +#define AR_IMR_BMISS_INT 0x00040000 /* beacon missed */ +#define AR_IMR_MCABT_INT 0x00100000 /* master cycle abort */ +#define AR_IMR_SSERR_INT 0x00200000 /* SERR on PCI */ +#define AR_IMR_DPERR_INT 0x00400000 /* Parity error on PCI */ +#define AR_IMR_GPIO_INT 0x01000000 /* GPIO interrupt */ +#define AR_IMR_BITS AR_ISR_BITS + +#define AR_IER_DISABLE 0x00000000 /* pseudo-flag */ +#define AR_IER_ENABLE 0x00000001 /* global interrupt enable */ +#define AR_IER_BITS "\20\1ENABLE" + +#define AR_BCR_BCMD 0x00000001 /* ad hoc beacon mode */ +#define AR_BCR_BDMAE 0x00000002 /* beacon DMA enable */ +#define AR_BCR_TQ1FV 0x00000004 /* use TXQ1 for non-beacon */ +#define AR_BCR_TQ1V 0x00000008 /* TXQ1 valid for beacon */ +#define AR_BCR_BCGET 0x00000010 /* force a beacon fetch */ +#define AR_BCR_BITS "\20\1BCMD\2BDMAE\3TQ1FV\4TQ1V\5BCGET" + +#define AR_BSR_BDLYSW 0x00000001 /* software beacon delay */ +#define AR_BSR_BDLYDMA 0x00000002 /* DMA beacon delay */ +#define AR_BSR_TXQ1F 0x00000004 /* TXQ1 fetch */ +#define AR_BSR_ATIMDLY 0x00000008 /* ATIM delay */ +#define AR_BSR_SNPBCMD 0x00000100 /* snapshot of BCMD */ +#define AR_BSR_SNPBDMAE 0x00000200 /* snapshot of BDMAE */ +#define AR_BSR_SNPTQ1FV 0x00000400 /* snapshot of TQ1FV */ +#define AR_BSR_SNPTQ1V 0x00000800 /* snapshot of TQ1V */ +#define AR_BSR_SNAPPEDBCRVALID 0x00001000 /* snapshot of BCR are valid */ +#define AR_BSR_SWBA_CNT 0x00ff0000 /* software beacon alert cnt */ +#define AR_BSR_BITS \ + "\20\1BDLYSW\2BDLYDMA\3TXQ1F\4ATIMDLY\11SNPBCMD\12SNPBDMAE"\ + "\13SNPTQ1FV\14SNPTQ1V\15SNAPPEDBCRVALID" + +#define AR_TXCFG_SDMAMR 0x00000007 /* DMA burst size 2^(2+x) */ +#define AR_TXCFG_TXFSTP 0x00000008 /* Stop TX DMA on filtered */ +#define AR_TXCFG_TXFULL 0x00000070 /* TX DMA desc Q full thresh */ +#define AR_TXCFG_TXCONT_EN 0x00000080 /* Enable continuous TX mode */ +#define AR_TXCFG_BITS "\20\3TXFSTP\7TXCONT_EN" + +#define AR_RXCFG_SDMAMW 0x00000007 /* DMA burst size 2^(2+x) */ +#define AR_RXCFG_ZLFDMA 0x00000010 /* enable zero length DMA */ + +/* DMA sizes used for both AR_TXCFG_SDMAMR and AR_RXCFG_SDMAMW */ +#define AR_DMASIZE_4B 0 /* DMA size 4 bytes */ +#define AR_DMASIZE_8B 1 /* DMA size 8 bytes */ +#define AR_DMASIZE_16B 2 /* DMA size 16 bytes */ +#define AR_DMASIZE_32B 3 /* DMA size 32 bytes */ +#define AR_DMASIZE_64B 4 /* DMA size 64 bytes */ +#define AR_DMASIZE_128B 5 /* DMA size 128 bytes */ +#define AR_DMASIZE_256B 6 /* DMA size 256 bytes */ +#define AR_DMASIZE_512B 7 /* DMA size 512 bytes */ + +#define AR_MIBC_COW 0x00000001 /* counter overflow warning */ +#define AR_MIBC_FMC 0x00000002 /* freeze MIB counters */ +#define AR_MIBC_CMC 0x00000004 /* clear MIB counters */ +#define AR_MIBC_MCS 0x00000008 /* MIB counter strobe */ + +#define AR_RFCNT_RFCL 0x0000000f /* RX frame count limit */ + +#define AR_MISC_LED_DECAY 0x001c0000 /* LED decay rate */ +#define AR_MISC_LED_BLINK 0x00e00000 /* LED blink rate */ + +#define AR_RC_RPCU 0x00000001 /* PCU Warm Reset */ +#define AR_RC_RDMA 0x00000002 /* DMA Warm Reset */ +#define AR_RC_RMAC 0x00000004 /* MAC Warm Reset */ +#define AR_RC_RPHY 0x00000008 /* PHY Warm Reset */ +#define AR_RC_RPCI 0x00000010 /* PCI Core Warm Reset */ +#define AR_RC_BITS "\20\1RPCU\2RDMA\3RMAC\4RPHY\5RPCI" + +#define AR_SCR_SLDUR 0x0000ffff /* sleep duration */ +#define AR_SCR_SLE 0x00030000 /* sleep enable */ +#define AR_SCR_SLE_S 16 +#define AR_SCR_SLE_WAKE 0x00000000 /* force wake */ +#define AR_SCR_SLE_SLP 0x00010000 /* force sleep */ +#define AR_SCR_SLE_ALLOW 0x00020000 /* allow to control sleep */ +#define AR_SCR_BITS "\20\20SLE_SLP\21SLE_ALLOW" + +#define AR_INTPEND_IP 0x00000001 /* interrupt pending */ +#define AR_INTPEND_BITS "\20\1IP" + +#define AR_SFR_SF 0x00000001 /* force sleep immediately */ + +#define AR_PCICFG_EEPROMSEL 0x00000001 /* EEPROM access enable */ +#define AR_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable */ +#define AR_PCICFG_LED_PEND 0x00000020 /* LED for assoc pending */ +#define AR_PCICFG_LED_ACT 0x00000040 /* LED for assoc active */ +#define AR_PCICFG_SL_INTEN 0x00000800 /* Enable sleep intr */ +#define AR_PCICFG_LED_BCTL 0x00001000 /* LED blink for local act */ +#define AR_PCICFG_SL_INPEN 0x00002800 /* sleep even intr pending */ +#define AR_PCICFG_SPWR_DN 0x00010000 /* sleep indication */ +#define AR_PCICFG_BITS \ + "\20\1EEPROMSEL\3CLKRUNEN\5LED_PEND\6LED_ACT\13SL_INTEN"\ + "\14LED_BCTL\20SPWR_DN" + +#define AR_GPIOCR_IN(n) (0<<((n)*2)) /* input-only */ +#define AR_GPIOCR_OUT0(n) (1<<((n)*2)) /* output-only if GPIODO = 0 */ +#define AR_GPIOCR_OUT1(n) (2<<((n)*2)) /* output-only if GPIODO = 1 */ +#define AR_GPIOCR_OUT(n) (3<<((n)*2)) /* always output */ +#define AR_GPIOCR_ALL(n) (3<<((n)*2)) /* all bits for pin */ +#define AR_GPIOCR_INT_SEL(n) ((n)<<12) /* GPIO interrupt pin select */ +#define AR_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO interrupt */ +#define AR_GPIOCR_INT_SELL 0x00000000 /* Interrupt if pin is low */ +#define AR_GPIOCR_INT_SELH 0x00010000 /* Interrupt if pin is high */ + +#define AR_SREV_CRETE 4 /* Crete 1st version */ +#define AR_SREV_CRETE_MS 5 /* Crete FCS version */ +#define AR_SREV_CRETE_23 8 /* Crete version 2.3 */ + +#define AR_EP_STA_RDERR 0x00000001 /* read error */ +#define AR_EP_STA_RDCMPLT 0x00000002 /* read complete */ +#define AR_EP_STA_WRERR 0x00000004 /* write error */ +#define AR_EP_STA_WRCMPLT 0x00000008 /* write complete */ +#define AR_EP_STA_BITS \ + "\20\1RDERR\2RDCMPLT\3WRERR\4WRCMPLT" + +#define AR_STA_ID1_AP 0x00010000 /* Access Point Operation */ +#define AR_STA_ID1_ADHOC 0x00020000 /* ad hoc Operation */ +#define AR_STA_ID1_PWR_SV 0x00040000 /* power save report enable */ +#define AR_STA_ID1_NO_KEYSRCH 0x00080000 /* key table search disable */ +#define AR_STA_ID1_NO_PSPOLL 0x00100000 /* auto PS-POLL disable */ +#define AR_STA_ID1_PCF 0x00200000 /* PCF observation enable */ +#define AR_STA_ID1_DESC_ANTENNA 0x00400000 /* use antenna in TX desc */ +#define AR_STA_ID1_DEFAULT_ANTENNA 0x00800000 /* toggle default antenna */ +#define AR_STA_ID1_ACKCTS_6MB 0x01000000 /* use 6Mbps for ACK/CTS */ +#define AR_STA_ID1_BITS \ + "\20\20AP\21ADHOC\22PWR_SV\23NO_KEYSRCH\24NO_PSPOLL\25PCF"\ + "\26DESC_ANTENNA\27DEFAULT_ANTENNA\30ACKCTS_6MB" + +#define AR_BSS_ID1_AID 0xffff0000 /* association ID */ +#define AR_BSS_ID1_AID_S 16 + +#define AR_TIME_OUT_ACK 0x00001fff /* ACK timeout */ +#define AR_TIME_OUT_ACK_S 0 +#define AR_TIME_OUT_CTS 0x1fff0000 /* CTS timeout */ +#define AR_TIME_OUT_CTS_S 16 + +#define AR_RSSI_THR_BM_THR 0x00000700 /* missed beacon threshold */ +#define AR_RSSI_THR_BM_THR_S 8 + +#define AR_RETRY_LMT_SH_RETRY 0x0000000f /* short frame retry limit */ +#define AR_RETRY_LMT_SH_RETRY_S 0 +#define AR_RETRY_LMT_LG_RETRY 0x000000f0 /* long frame retry limit */ +#define AR_RETRY_LMT_LG_RETRY_S 4 +#define AR_RETRY_LMT_SSH_RETRY 0x00003f00 /* short station retry limit */ +#define AR_RETRY_LMT_SSH_RETRY_S 8 +#define AR_RETRY_LMT_SLG_RETRY 0x000fc000 /* long station retry limit */ +#define AR_RETRY_LMT_SLG_RETRY_S 14 +#define AR_RETRY_LMT_CW_MIN 0x3ff00000 /* minimum contention window */ +#define AR_RETRY_LMT_CW_MIN_S 20 + +#define AR_USEC_1 0x0000007f /* number of clk in 1us */ +#define AR_USEC_1_S 0 +#define AR_USEC_32 0x00003f80 /* number of 32MHz clk in 1us */ +#define AR_USEC_32_S 7 +#define AR_USEC_TX_LATENCY 0x000fc000 /* transmit latency in us */ +#define AR_USEC_TX_LATENCY_S 14 +#define AR_USEC_RX_LATENCY 0x03f00000 /* receive latency in us */ +#define AR_USEC_RX_LATENCY_S 20 + +#define AR_BEACON_PERIOD 0x0000ffff /* beacon period in TU/ms */ +#define AR_BEACON_PERIOD_S 0 +#define AR_BEACON_TIM 0x007f0000 /* byte offset */ +#define AR_BEACON_TIM_S 16 +#define AR_BEACON_EN 0x00800000 /* beacon transmission enable */ +#define AR_BEACON_RESET_TSF 0x01000000 /* TSF reset oneshot */ +#define AR_BEACON_BITS "\20\27ENABLE\30RESET_TSF" + +#define AR_IFS0_SIFS 0x000007ff /* SIFS in core clock cycles */ +#define AR_IFS0_SIFS_S 0 +#define AR_IFS0_DIFS 0x007ff800 /* DIFS in core clock cycles */ +#define AR_IFS0_DIFS_S 11 + +#define AR_IFS1_PIFS 0x00000fff /* Programmable IFS */ +#define AR_IFS1_PIFS_S 0 +#define AR_IFS1_EIFS 0x03fff000 /* EIFS in core clock cycles */ +#define AR_IFS1_EIFS_S 12 +#define AR_IFS1_CS_EN 0x04000000 /* carrier sense enable */ + +#define AR_RX_FILTER_UNICAST 0x00000001 /* unicast frame enable */ +#define AR_RX_FILTER_MULTICAST 0x00000002 /* multicast frame enable */ +#define AR_RX_FILTER_BROADCAST 0x00000004 /* broadcast frame enable */ +#define AR_RX_FILTER_CONTROL 0x00000008 /* control frame enable */ +#define AR_RX_FILTER_BEACON 0x00000010 /* beacon frame enable */ +#define AR_RX_FILTER_PROMISCUOUS 0x00000020 /* promiscuous receive enable */ +#define AR_RX_FILTER_BITS \ + "\20\1UCAST\2MCAST\3BCAST\4CONTROL\5BEACON\6PROMISC" + +#define AR_DIAG_SW_DIS_WEP_ACK 0x00000001 /* disable ACK if no key found*/ +#define AR_DIAG_SW_DIS_ACK 0x00000002 /* disable ACK generation */ +#define AR_DIAG_SW_DIS_CTS 0x00000004 /* disable CTS generation */ +#define AR_DIAG_SW_DIS_ENC 0x00000008 /* encryption disable */ +#define AR_DIAG_SW_DIS_DEC 0x00000010 /* decryption disable */ +#define AR_DIAG_SW_DIS_TX 0x00000020 /* TX disable */ +#define AR_DIAG_SW_DIS_RX 0x00000040 /* RX disable */ +#define AR_DIAG_SW_LOOP_BACK 0x00000080 /* TX data loopback enable */ +#define AR_DIAG_SW_CORR_FCS 0x00000100 /* corrupt FCS enable */ +#define AR_DIAG_SW_CHAN_INFO 0x00000200 /* channel information enable */ +#define AR_DIAG_SW_EN_SCRAM_SEED 0x00000400 /* use fixed scrambler seed */ +#define AR_DIAG_SW_SCVRAM_SEED 0x0003f800 /* fixed scrambler seed */ +#define AR_DIAG_SW_DIS_SEQ_INC 0x00040000 /* seq increment disable */ +#define AR_DIAG_SW_FRAME_NV0 0x00080000 /* accept frame vers != 0 */ +#define AR_DIAG_SW_BITS \ + "\20\1DIS_WEP_ACK\2DIS_ACK\3DIS_CTS\4DIS_ENC\5DIS_DEC\6DIS_TX"\ + "\7DIS_RX\10LOOP_BACK\11CORR_FCS\12CHAN_INFO\13EN_SCRAM_SEED"\ + "\22DIS_SEQ_INC\24FRAME_NV0" + +#define AR_RETRY_CNT_SSH 0x0000003f /* current short retry count */ +#define AR_RETRY_CNT_SLG 0x00000fc0 /* current long retry count */ + +#define AR_BACKOFF_CW 0x000003ff /* current contention window */ +#define AR_BACKOFF_CNT 0x03ff0000 /* backoff count */ + +#define AR_KEYTABLE_KEY0(n) (AR_KEYTABLE(n) + 0) /* key bit 0-31 */ +#define AR_KEYTABLE_KEY1(n) (AR_KEYTABLE(n) + 4) /* key bit 32-47 */ +#define AR_KEYTABLE_KEY2(n) (AR_KEYTABLE(n) + 8) /* key bit 48-79 */ +#define AR_KEYTABLE_KEY3(n) (AR_KEYTABLE(n) + 12) /* key bit 80-95 */ +#define AR_KEYTABLE_KEY4(n) (AR_KEYTABLE(n) + 16) /* key bit 96-127 */ +#define AR_KEYTABLE_TYPE(n) (AR_KEYTABLE(n) + 20) /* key type */ +#define AR_KEYTABLE_TYPE_40 0x00000000 /* 40 bit key */ +#define AR_KEYTABLE_TYPE_104 0x00000001 /* 104 bit key */ +#define AR_KEYTABLE_TYPE_128 0x00000003 /* 128 bit key */ +#define AR_KEYTABLE_MAC0(n) (AR_KEYTABLE(n) + 24) /* MAC address 1-32 */ +#define AR_KEYTABLE_MAC1(n) (AR_KEYTABLE(n) + 28) /* MAC address 33-47 */ +#define AR_KEYTABLE_VALID 0x00008000 /* key and MAC address valid */ + +#endif /* _DEV_ATH_AR5210REG_H */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5k_0007.ini b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5k_0007.ini new file mode 100644 index 0000000000..b0285e9223 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5210/ar5k_0007.ini @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5k_0007.ini,v 1.2 2008/11/10 01:19:37 sam Exp $ + */ + + /* crete register init */ + { 0x00009800, 0x00000047 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0x09848ea6 }, + { 0x00009810, 0x3d32e000 }, + { 0x00009814, 0x0000076b }, + { 0x0000981c, 0x00000000 }, + { 0x00009820, 0x02020200 }, + { 0x00009824, 0x00000e0e }, + { 0x00009828, 0x0a020201 }, + { 0x0000982c, 0x00036ffc }, + { 0x00009830, 0x00000000 }, + { 0x00009834, 0x00000e0e }, + { 0x00009838, 0x00000007 }, + { 0x0000983c, 0x00020100 }, + { 0x00009840, 0x89630000 }, + { 0x00009844, 0x1372169c }, + { 0x00009848, 0x0018b633 }, + { 0x0000984c, 0x1284613c }, + { 0x00009850, 0x0de8b8e0 }, + { 0x00009854, 0x00074859 }, + { 0x00009858, 0x7e80beba }, + { 0x0000985c, 0x313a665e }, + { 0x00009860, 0x00001d08 }, + { 0x00009864, 0x0001ce00 }, + { 0x00009868, 0x409a4190 }, + { 0x00009870, 0x0000000f }, + { 0x00009874, 0x00000080 }, + { 0x00009878, 0x00000004 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00800000 }, + { 0x00009910, 0x00000003 }, + + + /* bb gain table */ + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000020 }, + { 0x00009b08, 0x00000010 }, + { 0x00009b0c, 0x00000030 }, + { 0x00009b10, 0x00000008 }, + { 0x00009b14, 0x00000028 }, + { 0x00009b18, 0x00000028 }, + { 0x00009b1c, 0x00000004 }, + { 0x00009b20, 0x00000024 }, + { 0x00009b24, 0x00000014 }, + { 0x00009b28, 0x00000034 }, + { 0x00009b2c, 0x0000000c }, + { 0x00009b30, 0x0000002c }, + { 0x00009b34, 0x00000002 }, + { 0x00009b38, 0x00000022 }, + { 0x00009b3c, 0x00000012 }, + { 0x00009b40, 0x00000032 }, + { 0x00009b44, 0x0000000a }, + { 0x00009b48, 0x0000002a }, + { 0x00009b4c, 0x00000001 }, + { 0x00009b50, 0x00000021 }, + { 0x00009b54, 0x00000011 }, + { 0x00009b58, 0x00000031 }, + { 0x00009b5c, 0x00000009 }, + { 0x00009b60, 0x00000029 }, + { 0x00009b64, 0x00000005 }, + { 0x00009b68, 0x00000025 }, + { 0x00009b6c, 0x00000015 }, + { 0x00009b70, 0x00000035 }, + { 0x00009b74, 0x0000000d }, + { 0x00009b78, 0x0000002d }, + { 0x00009b7c, 0x00000003 }, + { 0x00009b80, 0x00000023 }, + { 0x00009b84, 0x00000013 }, + { 0x00009b88, 0x00000033 }, + { 0x00009b8c, 0x0000000b }, + { 0x00009b90, 0x0000002b }, + { 0x00009b94, 0x00000007 }, + { 0x00009b98, 0x00000027 }, + { 0x00009b9c, 0x00000017 }, + { 0x00009ba0, 0x00000037 }, + { 0x00009ba4, 0x0000000f }, + { 0x00009ba8, 0x0000002f }, + { 0x00009bac, 0x0000002f }, + { 0x00009bb0, 0x0000002f }, + { 0x00009bb4, 0x0000002f }, + { 0x00009bb8, 0x0000002f }, + { 0x00009bbc, 0x0000002f }, + { 0x00009bc0, 0x0000002f }, + { 0x00009bc4, 0x0000002f }, + { 0x00009bc8, 0x0000002f }, + { 0x00009bcc, 0x0000002f }, + { 0x00009bd0, 0x0000002f }, + { 0x00009bd4, 0x0000002f }, + { 0x00009bd8, 0x0000002f }, + { 0x00009bdc, 0x0000002f }, + { 0x00009be0, 0x0000002f }, + { 0x00009be4, 0x0000002f }, + { 0x00009be8, 0x0000002f }, + { 0x00009bec, 0x0000002f }, + { 0x00009bf0, 0x0000002f }, + { 0x00009bf4, 0x0000002f }, + { 0x00009bf8, 0x0000002f }, + { 0x00009bfc, 0x0000002f }, + + /* rf gain table */ + { 0x00009a00, 0x0000001d }, + { 0x00009a04, 0x0000005d }, + { 0x00009a08, 0x0000009d }, + { 0x00009a0c, 0x000000dd }, + { 0x00009a10, 0x0000011d }, + { 0x00009a14, 0x00000021 }, + { 0x00009a18, 0x00000061 }, + { 0x00009a1c, 0x000000a1 }, + { 0x00009a20, 0x000000e1 }, + { 0x00009a24, 0x00000031 }, + { 0x00009a28, 0x00000071 }, + { 0x00009a2c, 0x000000b1 }, + { 0x00009a30, 0x0000001c }, + { 0x00009a34, 0x0000005c }, + { 0x00009a38, 0x00000029 }, + { 0x00009a3c, 0x00000069 }, + { 0x00009a40, 0x000000a9 }, + { 0x00009a44, 0x00000020 }, + { 0x00009a48, 0x00000019 }, + { 0x00009a4c, 0x00000059 }, + { 0x00009a50, 0x00000099 }, + { 0x00009a54, 0x00000030 }, + { 0x00009a58, 0x00000005 }, + { 0x00009a5c, 0x00000025 }, + { 0x00009a60, 0x00000065 }, + { 0x00009a64, 0x000000a5 }, + { 0x00009a68, 0x00000028 }, + { 0x00009a6c, 0x00000068 }, + { 0x00009a70, 0x0000001f }, + { 0x00009a74, 0x0000001e }, + { 0x00009a78, 0x00000018 }, + { 0x00009a7c, 0x00000058 }, + { 0x00009a80, 0x00000098 }, + { 0x00009a84, 0x00000003 }, + { 0x00009a88, 0x00000004 }, + { 0x00009a8c, 0x00000044 }, + { 0x00009a90, 0x00000084 }, + { 0x00009a94, 0x00000013 }, + { 0x00009a98, 0x00000012 }, + { 0x00009a9c, 0x00000052 }, + { 0x00009aa0, 0x00000092 }, + { 0x00009aa4, 0x000000d2 }, + { 0x00009aa8, 0x0000002b }, + { 0x00009aac, 0x0000002a }, + { 0x00009ab0, 0x0000006a }, + { 0x00009ab4, 0x000000aa }, + { 0x00009ab8, 0x0000001b }, + { 0x00009abc, 0x0000001a }, + { 0x00009ac0, 0x0000005a }, + { 0x00009ac4, 0x0000009a }, + { 0x00009ac8, 0x000000da }, + { 0x00009acc, 0x00000006 }, + { 0x00009ad0, 0x00000006 }, + { 0x00009ad4, 0x00000006 }, + { 0x00009ad8, 0x00000006 }, + { 0x00009adc, 0x00000006 }, + { 0x00009ae0, 0x00000006 }, + { 0x00009ae4, 0x00000006 }, + { 0x00009ae8, 0x00000006 }, + { 0x00009aec, 0x00000006 }, + { 0x00009af0, 0x00000006 }, + { 0x00009af4, 0x00000006 }, + { 0x00009af8, 0x00000006 }, + { 0x00009afc, 0x00000006 }, + + /* fez register init */ + { 0x000098d4, 0x00000020 }, + { 0x000098cc, 0x00000004 }, + { 0x000098c8, 0x00060106 }, + { 0x0000989c, 0x0000006d }, + { 0x000098c0, 0x00000000 }, + { 0x000098d0, 0x00000014 }, diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211.h b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211.h new file mode 100644 index 0000000000..e71d78c653 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211.h @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5211.h,v 1.8 2008/11/10 22:08:47 sam Exp $ + */ +#ifndef _ATH_AR5211_H_ +#define _ATH_AR5211_H_ + +#include "ah_eeprom.h" + +#define AR5211_MAGIC 0x19570405 + +/* Classes for WME streams */ +#define AC_BK 0 +#define AC_BE 1 +#define AC_VI 2 +#define AC_VO 3 + +/* DCU Transmit Filter macros */ +#define CALC_MMR(dcu, idx) \ + ( (4 * dcu) + (idx < 32 ? 0 : (idx < 64 ? 1 : (idx < 96 ? 2 : 3))) ) +#define TXBLK_FROM_MMR(mmr) \ + (AR_D_TXBLK_BASE + ((mmr & 0x1f) << 6) + ((mmr & 0x20) >> 3)) +#define CALC_TXBLK_ADDR(dcu, idx) (TXBLK_FROM_MMR(CALC_MMR(dcu, idx))) +#define CALC_TXBLK_VALUE(idx) (1 << (idx & 0x1f)) + +/* MAC register values */ + +#define INIT_INTERRUPT_MASK \ + ( AR_IMR_TXERR | AR_IMR_TXOK | AR_IMR_RXORN | \ + AR_IMR_RXERR | AR_IMR_RXOK | AR_IMR_TXURN | \ + AR_IMR_HIUERR ) +#define INIT_BEACON_CONTROL \ + ( (INIT_RESET_TSF << 24) | (INIT_BEACON_EN << 23) | \ + (INIT_TIM_OFFSET << 16) | INIT_BEACON_PERIOD ) + +#define INIT_CONFIG_STATUS 0x00000000 +#define INIT_RSSI_THR 0x00000700 /* Missed beacon counter initialized to 0x7 (max is 0xff) */ +#define INIT_IQCAL_LOG_COUNT_MAX 0xF +#define INIT_BCON_CNTRL_REG 0x00000000 + +#define INIT_BEACON_PERIOD 0xffff +#define INIT_TIM_OFFSET 0 +#define INIT_BEACON_EN 0 /* this should be set by AP only when it's ready */ +#define INIT_RESET_TSF 0 + +/* + * Various fifo fill before Tx start, in 64-byte units + * i.e. put the frame in the air while still DMAing + */ +#define MIN_TX_FIFO_THRESHOLD 0x1 +#define MAX_TX_FIFO_THRESHOLD ((IEEE80211_MAX_LEN / 64) + 1) +#define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD + +/* + * Gain support. + */ +typedef struct _gainOptStep { + int16_t paramVal[4]; + int32_t stepGain; + int8_t stepName[16]; +} GAIN_OPTIMIZATION_STEP; + +typedef struct { + uint32_t numStepsInLadder; + uint32_t defaultStepNum; + GAIN_OPTIMIZATION_STEP optStep[10]; +} GAIN_OPTIMIZATION_LADDER; + +typedef struct { + uint32_t currStepNum; + uint32_t currGain; + uint32_t targetGain; + uint32_t loTrig; + uint32_t hiTrig; + uint32_t active; + const GAIN_OPTIMIZATION_STEP *currStep; +} GAIN_VALUES; + +enum { + RFGAIN_INACTIVE, + RFGAIN_READ_REQUESTED, + RFGAIN_NEED_CHANGE +}; + +/* + * Header Info - general parameters and + * values set for each chipset board solution + * that are programmed every reset + */ +struct ath_hal_5211 { + struct ath_hal_private ah_priv; /* base class */ + + GAIN_VALUES ah_gainValues; + + uint8_t ah_macaddr[IEEE80211_ADDR_LEN]; + uint8_t ah_bssid[IEEE80211_ADDR_LEN]; + + /* + * Runtime state. + */ + uint32_t ah_maskReg; /* copy of AR_IMR */ + uint32_t ah_txOkInterruptMask; + uint32_t ah_txErrInterruptMask; + uint32_t ah_txDescInterruptMask; + uint32_t ah_txEolInterruptMask; + uint32_t ah_txUrnInterruptMask; + HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES]; + HAL_POWER_MODE ah_powerMode; + HAL_ANT_SETTING ah_diversityControl; /* antenna setting */ + uint32_t ah_calibrationTime; + HAL_BOOL ah_bIQCalibration; + HAL_CHANNEL ah_curchan; /* XXX */ + int ah_rfgainState; + uint32_t ah_tx6PowerInHalfDbm; /* power output for 6Mb tx */ + uint32_t ah_staId1Defaults; /* STA_ID1 default settings */ + uint32_t ah_beaconInterval; + uint32_t ah_rssiThr; /* RSSI_THR settings */ + + u_int ah_sifstime; /* user-specified sifs time */ + u_int ah_slottime; /* user-specified slot time */ + u_int ah_acktimeout; /* user-specified ack timeout */ + u_int ah_ctstimeout; /* user-specified cts timeout */ + /* + * RF Silent handling. + */ + uint32_t ah_gpioSelect; /* GPIO pin to use */ + uint32_t ah_polarity; /* polarity to disable RF */ + uint32_t ah_gpioBit; /* after init, prev value */ +}; +#define AH5211(ah) ((struct ath_hal_5211 *)(ah)) + +struct ath_hal; + +extern struct ath_hal *ar5211Attach(uint16_t, HAL_SOFTC, + HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS *); +extern void ar5211Detach(struct ath_hal *); + +extern HAL_BOOL ar5211Reset(struct ath_hal *, HAL_OPMODE, + HAL_CHANNEL *, HAL_BOOL bChannelChange, HAL_STATUS *); +extern HAL_BOOL ar5211PhyDisable(struct ath_hal *); +extern HAL_BOOL ar5211Disable(struct ath_hal *); +extern HAL_BOOL ar5211ChipReset(struct ath_hal *, uint16_t); +extern HAL_BOOL ar5211PerCalibration(struct ath_hal *, HAL_CHANNEL *, HAL_BOOL *); +extern HAL_BOOL ar5211PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan, + u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); +extern HAL_BOOL ar5211ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan); +extern HAL_BOOL ar5211SetTxPowerLimit(struct ath_hal *, uint32_t limit); +extern HAL_BOOL ar5211SetTransmitPower(struct ath_hal *, HAL_CHANNEL *); +extern HAL_BOOL ar5211CalNoiseFloor(struct ath_hal *, HAL_CHANNEL_INTERNAL *); +extern HAL_BOOL ar5211SetAntennaSwitchInternal(struct ath_hal *, + HAL_ANT_SETTING, const HAL_CHANNEL *); +extern int16_t ar5211GetNfAdjust(struct ath_hal *, + const HAL_CHANNEL_INTERNAL *); +extern HAL_BOOL ar5211ResetDma(struct ath_hal *, HAL_OPMODE); +extern void ar5211InitializeGainValues(struct ath_hal *); +extern HAL_RFGAIN ar5211GetRfgain(struct ath_hal *); +extern void ar5211SetPCUConfig(struct ath_hal *); + +extern HAL_BOOL ar5211SetTxQueueProps(struct ath_hal *ah, int q, + const HAL_TXQ_INFO *qInfo); +extern HAL_BOOL ar5211GetTxQueueProps(struct ath_hal *ah, int q, + HAL_TXQ_INFO *qInfo); +extern int ar5211SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo); +extern HAL_BOOL ar5211ReleaseTxQueue(struct ath_hal *ah, u_int q); +extern HAL_BOOL ar5211ResetTxQueue(struct ath_hal *ah, u_int q); +extern uint32_t ar5211GetTxDP(struct ath_hal *, u_int); +extern HAL_BOOL ar5211SetTxDP(struct ath_hal *, u_int, uint32_t txdp); +extern HAL_BOOL ar5211UpdateTxTrigLevel(struct ath_hal *, HAL_BOOL); +extern HAL_BOOL ar5211StartTxDma(struct ath_hal *, u_int); +extern HAL_BOOL ar5211StopTxDma(struct ath_hal *, u_int); +extern uint32_t ar5211NumTxPending(struct ath_hal *, u_int qnum); +extern HAL_BOOL ar5211IsTxQueueStopped(struct ath_hal *, u_int); +extern HAL_BOOL ar5211GetTransmitFilterIndex(struct ath_hal *, uint32_t); +extern HAL_BOOL ar5211SetupTxDesc(struct ath_hal *, struct ath_desc *, + u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower, + u_int txRate0, u_int txTries0, + u_int keyIx, u_int antMode, u_int flags, + u_int rtsctsRate, u_int rtsctsDuration, + u_int compicvLen, u_int compivLen, u_int comp); +extern HAL_BOOL ar5211SetupXTxDesc(struct ath_hal *, struct ath_desc *, + u_int txRate1, u_int txRetries1, + u_int txRate2, u_int txRetries2, + u_int txRate3, u_int txRetries3); +extern HAL_BOOL ar5211FillTxDesc(struct ath_hal *, struct ath_desc *, + u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg, + const struct ath_desc *ds0); +extern HAL_STATUS ar5211ProcTxDesc(struct ath_hal *, + struct ath_desc *, struct ath_tx_status *); +extern void ar5211GetTxIntrQueue(struct ath_hal *ah, uint32_t *); +extern void ar5211IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *); + +extern uint32_t ar5211GetRxDP(struct ath_hal *); +extern void ar5211SetRxDP(struct ath_hal *, uint32_t rxdp); +extern void ar5211EnableReceive(struct ath_hal *); +extern HAL_BOOL ar5211StopDmaReceive(struct ath_hal *); +extern void ar5211StartPcuReceive(struct ath_hal *); +extern void ar5211StopPcuReceive(struct ath_hal *); +extern void ar5211SetMulticastFilter(struct ath_hal *, + uint32_t filter0, uint32_t filter1); +extern HAL_BOOL ar5211ClrMulticastFilterIndex(struct ath_hal *, uint32_t); +extern HAL_BOOL ar5211SetMulticastFilterIndex(struct ath_hal *, uint32_t); +extern uint32_t ar5211GetRxFilter(struct ath_hal *); +extern void ar5211SetRxFilter(struct ath_hal *, uint32_t); +extern HAL_BOOL ar5211SetupRxDesc(struct ath_hal *, struct ath_desc *, + uint32_t, u_int flags); +extern HAL_STATUS ar5211ProcRxDesc(struct ath_hal *, struct ath_desc *, + uint32_t, struct ath_desc *, uint64_t, + struct ath_rx_status *); + +extern void ar5211GetMacAddress(struct ath_hal *, uint8_t *); +extern HAL_BOOL ar5211SetMacAddress(struct ath_hal *ah, const uint8_t *); +extern void ar5211GetBssIdMask(struct ath_hal *, uint8_t *); +extern HAL_BOOL ar5211SetBssIdMask(struct ath_hal *, const uint8_t *); +extern HAL_BOOL ar5211EepromRead(struct ath_hal *, u_int off, uint16_t *data); +extern HAL_BOOL ar5211EepromWrite(struct ath_hal *, u_int off, uint16_t data); +extern HAL_BOOL ar5211SetRegulatoryDomain(struct ath_hal *, + uint16_t, HAL_STATUS *); +extern u_int ar5211GetWirelessModes(struct ath_hal *); +extern void ar5211EnableRfKill(struct ath_hal *); +extern uint32_t ar5211GpioGet(struct ath_hal *, uint32_t gpio); +extern void ar5211GpioSetIntr(struct ath_hal *, u_int, uint32_t ilevel); +extern HAL_BOOL ar5211GpioCfgOutput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5211GpioCfgInput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5211GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val); +extern void ar5211SetLedState(struct ath_hal *, HAL_LED_STATE); +extern u_int ar5211AntennaGet(struct ath_hal *); +extern void ar5211WriteAssocid(struct ath_hal *, + const uint8_t *bssid, uint16_t assocId); +extern uint64_t ar5211GetTsf64(struct ath_hal *); +extern uint32_t ar5211GetTsf32(struct ath_hal *); +extern void ar5211ResetTsf(struct ath_hal *); +extern uint32_t ar5211GetMaxTurboRate(struct ath_hal *); +extern uint32_t ar5211GetRandomSeed(struct ath_hal *); +extern HAL_BOOL ar5211DetectCardPresent(struct ath_hal *); +extern void ar5211UpdateMibCounters(struct ath_hal *, HAL_MIB_STATS *); +extern void ar5211EnableHwEncryption(struct ath_hal *); +extern void ar5211DisableHwEncryption(struct ath_hal *); +extern HAL_BOOL ar5211SetSlotTime(struct ath_hal *, u_int); +extern u_int ar5211GetSlotTime(struct ath_hal *); +extern HAL_BOOL ar5211SetAckTimeout(struct ath_hal *, u_int); +extern u_int ar5211GetAckTimeout(struct ath_hal *); +extern HAL_BOOL ar5211SetAckCTSRate(struct ath_hal *, u_int); +extern u_int ar5211GetAckCTSRate(struct ath_hal *); +extern HAL_BOOL ar5211SetCTSTimeout(struct ath_hal *, u_int); +extern u_int ar5211GetCTSTimeout(struct ath_hal *); +extern HAL_BOOL ar5211SetSifsTime(struct ath_hal *, u_int); +extern u_int ar5211GetSifsTime(struct ath_hal *); +extern HAL_BOOL ar5211SetDecompMask(struct ath_hal *, uint16_t, int); +extern void ar5211SetCoverageClass(struct ath_hal *, uint8_t, int); +extern uint32_t ar5211GetCurRssi(struct ath_hal *); +extern u_int ar5211GetDefAntenna(struct ath_hal *); +extern void ar5211SetDefAntenna(struct ath_hal *ah, u_int antenna); +extern HAL_ANT_SETTING ar5211GetAntennaSwitch(struct ath_hal *); +extern HAL_BOOL ar5211SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); +extern HAL_STATUS ar5211GetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, + uint32_t, uint32_t *); +extern HAL_BOOL ar5211SetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, + uint32_t, uint32_t, HAL_STATUS *); +extern HAL_BOOL ar5211GetDiagState(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize); + +extern u_int ar5211GetKeyCacheSize(struct ath_hal *); +extern HAL_BOOL ar5211IsKeyCacheEntryValid(struct ath_hal *, uint16_t); +extern HAL_BOOL ar5211ResetKeyCacheEntry(struct ath_hal *, uint16_t entry); +extern HAL_BOOL ar5211SetKeyCacheEntry(struct ath_hal *, uint16_t entry, + const HAL_KEYVAL *, const uint8_t *mac, + int xorKey); +extern HAL_BOOL ar5211SetKeyCacheEntryMac(struct ath_hal *, + uint16_t, const uint8_t *); + +extern HAL_BOOL ar5211SetPowerMode(struct ath_hal *, uint32_t powerRequest, + int setChip); +extern HAL_POWER_MODE ar5211GetPowerMode(struct ath_hal *); + +extern void ar5211SetBeaconTimers(struct ath_hal *, + const HAL_BEACON_TIMERS *); +extern void ar5211BeaconInit(struct ath_hal *, uint32_t, uint32_t); +extern void ar5211SetStaBeaconTimers(struct ath_hal *, + const HAL_BEACON_STATE *); +extern void ar5211ResetStaBeaconTimers(struct ath_hal *); + +extern HAL_BOOL ar5211IsInterruptPending(struct ath_hal *); +extern HAL_BOOL ar5211GetPendingInterrupts(struct ath_hal *, HAL_INT *); +extern HAL_INT ar5211GetInterrupts(struct ath_hal *); +extern HAL_INT ar5211SetInterrupts(struct ath_hal *, HAL_INT ints); + +extern const HAL_RATE_TABLE *ar5211GetRateTable(struct ath_hal *, u_int mode); + +extern HAL_BOOL ar5211AniControl(struct ath_hal *, HAL_ANI_CMD, int ); +extern void ar5211AniPoll(struct ath_hal *, const HAL_NODE_STATS *, HAL_CHANNEL *); +extern void ar5211MibEvent(struct ath_hal *, const HAL_NODE_STATS *); +#endif /* _ATH_AR5211_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_attach.c b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_attach.c new file mode 100644 index 0000000000..74b139be85 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_attach.c @@ -0,0 +1,516 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5211_attach.c,v 1.11 2008/11/27 22:29:52 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" +#include "ar5211/ar5211phy.h" + +#include "ah_eeprom_v3.h" + +static HAL_BOOL ar5211GetChannelEdges(struct ath_hal *ah, + uint16_t flags, uint16_t *low, uint16_t *high); +static HAL_BOOL ar5211GetChipPowerLimits(struct ath_hal *ah, + HAL_CHANNEL *chans, uint32_t nchans); + +static const struct ath_hal_private ar5211hal = {{ + .ah_magic = AR5211_MAGIC, + .ah_abi = HAL_ABI_VERSION, + .ah_countryCode = CTRY_DEFAULT, + + .ah_getRateTable = ar5211GetRateTable, + .ah_detach = ar5211Detach, + + /* Reset Functions */ + .ah_reset = ar5211Reset, + .ah_phyDisable = ar5211PhyDisable, + .ah_disable = ar5211Disable, + .ah_setPCUConfig = ar5211SetPCUConfig, + .ah_perCalibration = ar5211PerCalibration, + .ah_perCalibrationN = ar5211PerCalibrationN, + .ah_resetCalValid = ar5211ResetCalValid, + .ah_setTxPowerLimit = ar5211SetTxPowerLimit, + .ah_getChanNoise = ath_hal_getChanNoise, + + /* Transmit functions */ + .ah_updateTxTrigLevel = ar5211UpdateTxTrigLevel, + .ah_setupTxQueue = ar5211SetupTxQueue, + .ah_setTxQueueProps = ar5211SetTxQueueProps, + .ah_getTxQueueProps = ar5211GetTxQueueProps, + .ah_releaseTxQueue = ar5211ReleaseTxQueue, + .ah_resetTxQueue = ar5211ResetTxQueue, + .ah_getTxDP = ar5211GetTxDP, + .ah_setTxDP = ar5211SetTxDP, + .ah_numTxPending = ar5211NumTxPending, + .ah_startTxDma = ar5211StartTxDma, + .ah_stopTxDma = ar5211StopTxDma, + .ah_setupTxDesc = ar5211SetupTxDesc, + .ah_setupXTxDesc = ar5211SetupXTxDesc, + .ah_fillTxDesc = ar5211FillTxDesc, + .ah_procTxDesc = ar5211ProcTxDesc, + .ah_getTxIntrQueue = ar5211GetTxIntrQueue, + .ah_reqTxIntrDesc = ar5211IntrReqTxDesc, + + /* RX Functions */ + .ah_getRxDP = ar5211GetRxDP, + .ah_setRxDP = ar5211SetRxDP, + .ah_enableReceive = ar5211EnableReceive, + .ah_stopDmaReceive = ar5211StopDmaReceive, + .ah_startPcuReceive = ar5211StartPcuReceive, + .ah_stopPcuReceive = ar5211StopPcuReceive, + .ah_setMulticastFilter = ar5211SetMulticastFilter, + .ah_setMulticastFilterIndex = ar5211SetMulticastFilterIndex, + .ah_clrMulticastFilterIndex = ar5211ClrMulticastFilterIndex, + .ah_getRxFilter = ar5211GetRxFilter, + .ah_setRxFilter = ar5211SetRxFilter, + .ah_setupRxDesc = ar5211SetupRxDesc, + .ah_procRxDesc = ar5211ProcRxDesc, + .ah_rxMonitor = ar5211AniPoll, + .ah_procMibEvent = ar5211MibEvent, + + /* Misc Functions */ + .ah_getCapability = ar5211GetCapability, + .ah_setCapability = ar5211SetCapability, + .ah_getDiagState = ar5211GetDiagState, + .ah_getMacAddress = ar5211GetMacAddress, + .ah_setMacAddress = ar5211SetMacAddress, + .ah_getBssIdMask = ar5211GetBssIdMask, + .ah_setBssIdMask = ar5211SetBssIdMask, + .ah_setRegulatoryDomain = ar5211SetRegulatoryDomain, + .ah_setLedState = ar5211SetLedState, + .ah_writeAssocid = ar5211WriteAssocid, + .ah_gpioCfgInput = ar5211GpioCfgInput, + .ah_gpioCfgOutput = ar5211GpioCfgOutput, + .ah_gpioGet = ar5211GpioGet, + .ah_gpioSet = ar5211GpioSet, + .ah_gpioSetIntr = ar5211GpioSetIntr, + .ah_getTsf32 = ar5211GetTsf32, + .ah_getTsf64 = ar5211GetTsf64, + .ah_resetTsf = ar5211ResetTsf, + .ah_detectCardPresent = ar5211DetectCardPresent, + .ah_updateMibCounters = ar5211UpdateMibCounters, + .ah_getRfGain = ar5211GetRfgain, + .ah_getDefAntenna = ar5211GetDefAntenna, + .ah_setDefAntenna = ar5211SetDefAntenna, + .ah_getAntennaSwitch = ar5211GetAntennaSwitch, + .ah_setAntennaSwitch = ar5211SetAntennaSwitch, + .ah_setSifsTime = ar5211SetSifsTime, + .ah_getSifsTime = ar5211GetSifsTime, + .ah_setSlotTime = ar5211SetSlotTime, + .ah_getSlotTime = ar5211GetSlotTime, + .ah_setAckTimeout = ar5211SetAckTimeout, + .ah_getAckTimeout = ar5211GetAckTimeout, + .ah_setAckCTSRate = ar5211SetAckCTSRate, + .ah_getAckCTSRate = ar5211GetAckCTSRate, + .ah_setCTSTimeout = ar5211SetCTSTimeout, + .ah_getCTSTimeout = ar5211GetCTSTimeout, + .ah_setDecompMask = ar5211SetDecompMask, + .ah_setCoverageClass = ar5211SetCoverageClass, + + /* Key Cache Functions */ + .ah_getKeyCacheSize = ar5211GetKeyCacheSize, + .ah_resetKeyCacheEntry = ar5211ResetKeyCacheEntry, + .ah_isKeyCacheEntryValid = ar5211IsKeyCacheEntryValid, + .ah_setKeyCacheEntry = ar5211SetKeyCacheEntry, + .ah_setKeyCacheEntryMac = ar5211SetKeyCacheEntryMac, + + /* Power Management Functions */ + .ah_setPowerMode = ar5211SetPowerMode, + .ah_getPowerMode = ar5211GetPowerMode, + + /* Beacon Functions */ + .ah_setBeaconTimers = ar5211SetBeaconTimers, + .ah_beaconInit = ar5211BeaconInit, + .ah_setStationBeaconTimers = ar5211SetStaBeaconTimers, + .ah_resetStationBeaconTimers = ar5211ResetStaBeaconTimers, + + /* Interrupt Functions */ + .ah_isInterruptPending = ar5211IsInterruptPending, + .ah_getPendingInterrupts = ar5211GetPendingInterrupts, + .ah_getInterrupts = ar5211GetInterrupts, + .ah_setInterrupts = ar5211SetInterrupts }, + + .ah_getChannelEdges = ar5211GetChannelEdges, + .ah_getWirelessModes = ar5211GetWirelessModes, + .ah_eepromRead = ar5211EepromRead, +#ifdef AH_SUPPORT_WRITE_EEPROM + .ah_eepromWrite = ar5211EepromWrite, +#endif + .ah_gpioCfgInput = ar5211GpioCfgInput, + .ah_gpioCfgOutput = ar5211GpioCfgOutput, + .ah_gpioGet = ar5211GpioGet, + .ah_gpioSet = ar5211GpioSet, + .ah_gpioSetIntr = ar5211GpioSetIntr, + .ah_getChipPowerLimits = ar5211GetChipPowerLimits, +}; + +static HAL_BOOL ar5211ChipTest(struct ath_hal *); +static HAL_BOOL ar5211FillCapabilityInfo(struct ath_hal *ah); + +/* + * Return the revsion id for the radio chip. This + * fetched via the PHY. + */ +static uint32_t +ar5211GetRadioRev(struct ath_hal *ah) +{ + uint32_t val; + int i; + + OS_REG_WRITE(ah, (AR_PHY_BASE + (0x34 << 2)), 0x00001c16); + for (i = 0; i < 8; i++) + OS_REG_WRITE(ah, (AR_PHY_BASE + (0x20 << 2)), 0x00010000); + val = (OS_REG_READ(ah, AR_PHY_BASE + (256 << 2)) >> 24) & 0xff; + val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); + return ath_hal_reverseBits(val, 8); +} + +/* + * Attach for an AR5211 part. + */ +struct ath_hal * +ar5211Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + struct ath_hal_5211 *ahp; + struct ath_hal *ah; + uint32_t val; + uint16_t eeval; + HAL_STATUS ecode; + + HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + __func__, sc, (void*) st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp = ath_hal_malloc(sizeof (struct ath_hal_5211)); + if (ahp == AH_NULL) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot allocate memory for state block\n", __func__); + ecode = HAL_ENOMEM; + goto bad; + } + ah = &ahp->ah_priv.h; + /* set initial values */ + OS_MEMCPY(&ahp->ah_priv, &ar5211hal, sizeof(struct ath_hal_private)); + ah->ah_sc = sc; + ah->ah_st = st; + ah->ah_sh = sh; + + ah->ah_devid = devid; /* NB: for AH_DEBUG_ALQ */ + AH_PRIVATE(ah)->ah_devid = devid; + AH_PRIVATE(ah)->ah_subvendorid = 0; /* XXX */ + + AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER; + AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */ + + ahp->ah_diversityControl = HAL_ANT_VARIABLE; + ahp->ah_staId1Defaults = 0; + ahp->ah_rssiThr = INIT_RSSI_THR; + ahp->ah_sifstime = (u_int) -1; + ahp->ah_slottime = (u_int) -1; + ahp->ah_acktimeout = (u_int) -1; + ahp->ah_ctstimeout = (u_int) -1; + + if (!ar5211ChipReset(ah, AH_FALSE)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + ecode = HAL_EIO; + goto bad; + } + if (AH_PRIVATE(ah)->ah_devid == AR5211_FPGA11B) { + /* set it back to OFDM mode to be able to read analog rev id */ + OS_REG_WRITE(ah, AR5211_PHY_MODE, AR5211_PHY_MODE_OFDM); + OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_44); + OS_DELAY(1000); + } + + /* Read Revisions from Chips */ + val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID_M; + AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S; + AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION_M; + + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_MAUI_2 || + AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_OAHU) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Mac Chip Rev 0x%x is not supported by this driver\n", + __func__, AH_PRIVATE(ah)->ah_macVersion); + ecode = HAL_ENOTSUPP; + goto bad; + } + + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); + + if (!ar5211ChipTest(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", + __func__); + ecode = HAL_ESELFTEST; + goto bad; + } + + /* Set correct Baseband to analog shift setting to access analog chips. */ + if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) { + OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007); + } else { + OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000047); + } + OS_DELAY(2000); + + /* Read Radio Chip Rev Extract */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ar5211GetRadioRev(ah); + if ((AH_PRIVATE(ah)->ah_analog5GhzRev & 0xf0) != RAD5_SREV_MAJOR) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5G Radio Chip Rev 0x%02X is not supported by this " + "driver\n", __func__, AH_PRIVATE(ah)->ah_analog5GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; + } + + val = (OS_REG_READ(ah, AR_PCICFG) & AR_PCICFG_EEPROM_SIZE_M) >> + AR_PCICFG_EEPROM_SIZE_S; + if (val != AR_PCICFG_EEPROM_SIZE_16K) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM size " + "%u (0x%x) found\n", __func__, val, val); + ecode = HAL_EESIZE; + goto bad; + } + ecode = ath_hal_legacyEepromAttach(ah); + if (ecode != HAL_OK) { + goto bad; + } + + /* If Bmode and AR5211, verify 2.4 analog exists */ + if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU && + ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) { + /* Set correct Baseband to analog shift setting to access analog chips. */ + OS_REG_WRITE(ah, AR_PHY_BASE, 0x00004007); + OS_DELAY(2000); + AH_PRIVATE(ah)->ah_analog2GhzRev = ar5211GetRadioRev(ah); + + /* Set baseband for 5GHz chip */ + OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007); + OS_DELAY(2000); + if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != RAD2_SREV_MAJOR) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 2G Radio Chip Rev 0x%x is not supported by " + "this driver\n", __func__, + AH_PRIVATE(ah)->ah_analog2GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; + } + } else { + ath_hal_eepromSet(ah, AR_EEP_BMODE, AH_FALSE); + } + + ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read regulatory domain from EEPROM\n", + __func__); + goto bad; + } + AH_PRIVATE(ah)->ah_currentRD = eeval; + AH_PRIVATE(ah)->ah_getNfAdjust = ar5211GetNfAdjust; + + /* + * Got everything we need now to setup the capabilities. + */ + (void) ar5211FillCapabilityInfo(ah); + + /* Initialize gain ladder thermal calibration structure */ + ar5211InitializeGainValues(ah); + + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error getting mac address from EEPROM\n", __func__); + goto bad; + } + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); + + return ah; +bad: + if (ahp) + ar5211Detach((struct ath_hal *) ahp); + if (status) + *status = ecode; + return AH_NULL; +#undef N +} + +void +ar5211Detach(struct ath_hal *ah) +{ + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__); + + HALASSERT(ah != AH_NULL); + HALASSERT(ah->ah_magic == AR5211_MAGIC); + + ath_hal_eepromDetach(ah); + ath_hal_free(ah); +} + +static HAL_BOOL +ar5211ChipTest(struct ath_hal *ah) +{ + uint32_t regAddr[2] = { AR_STA_ID0, AR_PHY_BASE+(8 << 2) }; + uint32_t regHold[2]; + uint32_t patternData[4] = + { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 }; + int i, j; + + /* Test PHY & MAC registers */ + for (i = 0; i < 2; i++) { + uint32_t addr = regAddr[i]; + uint32_t wrData, rdData; + + regHold[i] = OS_REG_READ(ah, addr); + for (j = 0; j < 0x100; j++) { + wrData = (j << 16) | j; + OS_REG_WRITE(ah, addr, wrData); + rdData = OS_REG_READ(ah, addr); + if (rdData != wrData) { + HALDEBUG(ah, HAL_DEBUG_ANY, +"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", + __func__, addr, wrData, rdData); + return AH_FALSE; + } + } + for (j = 0; j < 4; j++) { + wrData = patternData[j]; + OS_REG_WRITE(ah, addr, wrData); + rdData = OS_REG_READ(ah, addr); + if (wrData != rdData) { + HALDEBUG(ah, HAL_DEBUG_ANY, +"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", + __func__, addr, wrData, rdData); + return AH_FALSE; + } + } + OS_REG_WRITE(ah, regAddr[i], regHold[i]); + } + OS_DELAY(100); + return AH_TRUE; +} + +/* + * Store the channel edges for the requested operational mode + */ +static HAL_BOOL +ar5211GetChannelEdges(struct ath_hal *ah, + uint16_t flags, uint16_t *low, uint16_t *high) +{ + if (flags & CHANNEL_5GHZ) { + *low = 4920; + *high = 6100; + return AH_TRUE; + } + if (flags & CHANNEL_2GHZ && ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) { + *low = 2312; + *high = 2732; + return AH_TRUE; + } + return AH_FALSE; +} + +static HAL_BOOL +ar5211GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, uint32_t nchans) +{ + HAL_CHANNEL *chan; + int i; + + /* XXX fill in, this is just a placeholder */ + for (i = 0; i < nchans; i++) { + chan = &chans[i]; + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: no min/max power for %u/0x%x\n", + __func__, chan->channel, chan->channelFlags); + chan->maxTxPower = MAX_RATE_POWER; + chan->minTxPower = 0; + } + return AH_TRUE; +} + +/* + * Fill all software cached or static hardware state information. + */ +static HAL_BOOL +ar5211FillCapabilityInfo(struct ath_hal *ah) +{ + struct ath_hal_private *ahpriv = AH_PRIVATE(ah); + HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; + + /* Construct wireless mode from EEPROM */ + pCap->halWirelessModes = 0; + if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { + pCap->halWirelessModes |= HAL_MODE_11A; + if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) + pCap->halWirelessModes |= HAL_MODE_TURBO; + } + if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) + pCap->halWirelessModes |= HAL_MODE_11B; + + pCap->halLow2GhzChan = 2312; + pCap->halHigh2GhzChan = 2732; + pCap->halLow5GhzChan = 4920; + pCap->halHigh5GhzChan = 6100; + + pCap->halChanSpreadSupport = AH_TRUE; + pCap->halSleepAfterBeaconBroken = AH_TRUE; + pCap->halPSPollBroken = AH_TRUE; + pCap->halVEOLSupport = AH_TRUE; + + pCap->halTotalQueues = HAL_NUM_TX_QUEUES; + pCap->halKeyCacheSize = 128; + + /* XXX not needed */ + pCap->halChanHalfRate = AH_FALSE; + pCap->halChanQuarterRate = AH_FALSE; + + if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) && + ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) { + /* NB: enabled by default */ + ahpriv->ah_rfkillEnabled = AH_TRUE; + pCap->halRfSilentSupport = AH_TRUE; + } + + pCap->halTstampPrecision = 13; + + /* XXX might be ok w/ some chip revs */ + ahpriv->ah_rxornIsFatal = AH_TRUE; + return AH_TRUE; +} + +static const char* +ar5211Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID) { + if (devid == AR5211_DEVID || devid == AR5311_DEVID || + devid == AR5211_DEFAULT) + return "Atheros 5211"; + if (devid == AR5211_FPGA11B) + return "Atheros 5211 (FPGA)"; + } + return AH_NULL; +} +AH_CHIP(AR5211, ar5211Probe, ar5211Attach); diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_beacon.c b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_beacon.c new file mode 100644 index 0000000000..74207a322a --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_beacon.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5211_beacon.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" +#include "ar5211/ar5211desc.h" + +/* + * Routines used to initialize and generated beacons for the AR5211/AR5311. + */ + +/* + * Initialize all of the hardware registers used to send beacons. + */ +void +ar5211SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt) +{ + + OS_REG_WRITE(ah, AR_TIMER0, bt->bt_nexttbtt); + OS_REG_WRITE(ah, AR_TIMER1, bt->bt_nextdba); + OS_REG_WRITE(ah, AR_TIMER2, bt->bt_nextswba); + OS_REG_WRITE(ah, AR_TIMER3, bt->bt_nextatim); + /* + * Set the Beacon register after setting all timers. + */ + OS_REG_WRITE(ah, AR_BEACON, bt->bt_intval); +} + +/* + * Legacy api to initialize all of the beacon registers. + */ +void +ar5211BeaconInit(struct ath_hal *ah, + uint32_t next_beacon, uint32_t beacon_period) +{ + HAL_BEACON_TIMERS bt; + + bt.bt_nexttbtt = next_beacon; + /* + * TIMER1: in AP/adhoc mode this controls the DMA beacon + * alert timer; otherwise it controls the next wakeup time. + * TIMER2: in AP mode, it controls the SBA beacon alert + * interrupt; otherwise it sets the start of the next CFP. + */ + switch (AH_PRIVATE(ah)->ah_opmode) { + case HAL_M_STA: + case HAL_M_MONITOR: + bt.bt_nextdba = 0xffff; + bt.bt_nextswba = 0x7ffff; + break; + case HAL_M_IBSS: + case HAL_M_HOSTAP: + bt.bt_nextdba = (next_beacon - + ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */ + bt.bt_nextswba = (next_beacon - + ath_hal_sw_beacon_response_time) << 3; /* 1/8 TU */ + break; + } + /* + * Set the ATIM window + * Our hardware does not support an ATIM window of 0 + * (beacons will not work). If the ATIM windows is 0, + * force it to 1. + */ + bt.bt_nextatim = next_beacon + 1; + bt.bt_intval = beacon_period & + (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN); + ar5211SetBeaconTimers(ah, &bt); +} + +void +ar5211ResetStaBeaconTimers(struct ath_hal *ah) +{ + uint32_t val; + + OS_REG_WRITE(ah, AR_TIMER0, 0); /* no beacons */ + val = OS_REG_READ(ah, AR_STA_ID1); + val |= AR_STA_ID1_PWR_SAV; /* XXX */ + /* tell the h/w that the associated AP is not PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + val & ~(AR_STA_ID1_DEFAULT_ANTENNA | AR_STA_ID1_PCF)); + OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_PERIOD); +} + +/* + * Set all the beacon related bits on the h/w for stations + * i.e. initializes the corresponding h/w timers; + * also tells the h/w whether to anticipate PCF beacons + */ +void +ar5211SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: setting beacon timers\n", __func__); + + HALASSERT(bs->bs_intval != 0); + /* if the AP will do PCF */ + if (bs->bs_cfpmaxduration != 0) { + /* tell the h/w that the associated AP is PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + OS_REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PCF); + + /* set CFP_PERIOD(1.024ms) register */ + OS_REG_WRITE(ah, AR_CFP_PERIOD, bs->bs_cfpperiod); + + /* set CFP_DUR(1.024ms) register to max cfp duration */ + OS_REG_WRITE(ah, AR_CFP_DUR, bs->bs_cfpmaxduration); + + /* set TIMER2(128us) to anticipated time of next CFP */ + OS_REG_WRITE(ah, AR_TIMER2, bs->bs_cfpnext << 3); + } else { + /* tell the h/w that the associated AP is not PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + OS_REG_READ(ah, AR_STA_ID1) &~ AR_STA_ID1_PCF); + } + + /* + * Set TIMER0(1.024ms) to the anticipated time of the next beacon. + */ + OS_REG_WRITE(ah, AR_TIMER0, bs->bs_nexttbtt); + + /* + * Start the beacon timers by setting the BEACON register + * to the beacon interval; also write the tim offset which + * we should know by now. The code, in ar5211WriteAssocid, + * also sets the tim offset once the AID is known which can + * be left as such for now. + */ + OS_REG_WRITE(ah, AR_BEACON, + (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_PERIOD|AR_BEACON_TIM)) + | SM(bs->bs_intval, AR_BEACON_PERIOD) + | SM(bs->bs_timoffset ? bs->bs_timoffset + 4 : 0, AR_BEACON_TIM) + ); + + /* + * Configure the BMISS interrupt. Note that we + * assume the caller blocks interrupts while enabling + * the threshold. + */ + HALASSERT(bs->bs_bmissthreshold <= MS(0xffffffff, AR_RSSI_THR_BM_THR)); + ahp->ah_rssiThr = (ahp->ah_rssiThr &~ AR_RSSI_THR_BM_THR) + | SM(bs->bs_bmissthreshold, AR_RSSI_THR_BM_THR); + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); + + /* + * Set the sleep duration in 1/8 TU's. + */ +#define SLEEP_SLOP 3 + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLDUR, + (bs->bs_sleepduration - SLEEP_SLOP) << 3); +#undef SLEEP_SLOP +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_interrupts.c b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_interrupts.c new file mode 100644 index 0000000000..26035b8b11 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_interrupts.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5211_interrupts.c,v 1.6 2008/11/27 22:29:52 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" + +/* + * Checks to see if an interrupt is pending on our NIC + * + * Returns: TRUE if an interrupt is pending + * FALSE if not + */ +HAL_BOOL +ar5211IsInterruptPending(struct ath_hal *ah) +{ + return OS_REG_READ(ah, AR_INTPEND) != 0; +} + +/* + * Reads the Interrupt Status Register value from the NIC, thus deasserting + * the interrupt line, and returns both the masked and unmasked mapped ISR + * values. The value returned is mapped to abstract the hw-specific bit + * locations in the Interrupt Status Register. + * + * Returns: A hardware-abstracted bitmap of all non-masked-out + * interrupts pending, as well as an unmasked value + */ +HAL_BOOL +ar5211GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) +{ + uint32_t isr; + + isr = OS_REG_READ(ah, AR_ISR_RAC); + if (isr == 0xffffffff) { + *masked = 0; + return AH_FALSE; + } + + *masked = isr & HAL_INT_COMMON; + + if (isr & AR_ISR_HIUERR) + *masked |= HAL_INT_FATAL; + if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) + *masked |= HAL_INT_RX; + if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | AR_ISR_TXEOL)) + *masked |= HAL_INT_TX; + /* + * Receive overrun is usually non-fatal on Oahu/Spirit. + * BUT on some parts rx could fail and the chip must be reset. + * So we force a hardware reset in all cases. + */ + if ((isr & AR_ISR_RXORN) && AH_PRIVATE(ah)->ah_rxornIsFatal) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: receive FIFO overrun interrupt\n", __func__); + *masked |= HAL_INT_FATAL; + } + + /* + * On fatal errors collect ISR state for debugging. + */ + if (*masked & HAL_INT_FATAL) { + AH_PRIVATE(ah)->ah_fatalState[0] = isr; + AH_PRIVATE(ah)->ah_fatalState[1] = OS_REG_READ(ah, AR_ISR_S0_S); + AH_PRIVATE(ah)->ah_fatalState[2] = OS_REG_READ(ah, AR_ISR_S1_S); + AH_PRIVATE(ah)->ah_fatalState[3] = OS_REG_READ(ah, AR_ISR_S2_S); + AH_PRIVATE(ah)->ah_fatalState[4] = OS_REG_READ(ah, AR_ISR_S3_S); + AH_PRIVATE(ah)->ah_fatalState[5] = OS_REG_READ(ah, AR_ISR_S4_S); + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: fatal error, ISR_RAC=0x%x ISR_S2_S=0x%x\n", + __func__, isr, AH_PRIVATE(ah)->ah_fatalState[3]); + } + return AH_TRUE; +} + +HAL_INT +ar5211GetInterrupts(struct ath_hal *ah) +{ + return AH5211(ah)->ah_maskReg; +} + +/* + * Atomically enables NIC interrupts. Interrupts are passed in + * via the enumerated bitmask in ints. + */ +HAL_INT +ar5211SetInterrupts(struct ath_hal *ah, HAL_INT ints) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + uint32_t omask = ahp->ah_maskReg; + uint32_t mask; + + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n", + __func__, omask, ints); + + /* + * Disable interrupts here before reading & modifying + * the mask so that the ISR does not modify the mask + * out from under us. + */ + if (omask & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + /* XXX??? */ + (void) OS_REG_READ(ah, AR_IER); /* flush write to HW */ + } + + mask = ints & HAL_INT_COMMON; + if (ints & HAL_INT_TX) { + if (ahp->ah_txOkInterruptMask) + mask |= AR_IMR_TXOK; + if (ahp->ah_txErrInterruptMask) + mask |= AR_IMR_TXERR; + if (ahp->ah_txDescInterruptMask) + mask |= AR_IMR_TXDESC; + if (ahp->ah_txEolInterruptMask) + mask |= AR_IMR_TXEOL; + } + if (ints & HAL_INT_RX) + mask |= AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXDESC; + if (ints & HAL_INT_FATAL) { + /* + * NB: ar5212Reset sets MCABT+SSERR+DPERR in AR_IMR_S2 + * so enabling HIUERR enables delivery. + */ + mask |= AR_IMR_HIUERR; + } + + /* Write the new IMR and store off our SW copy. */ + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask); + OS_REG_WRITE(ah, AR_IMR, mask); + ahp->ah_maskReg = ints; + + /* Re-enable interrupts as appropriate. */ + if (ints & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE); + } + + return omask; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_keycache.c b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_keycache.c new file mode 100644 index 0000000000..61f579a452 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_keycache.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5211_keycache.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" + +/* + * Chips-specific key cache routines. + */ + +#define AR_KEYTABLE_SIZE 128 +#define KEY_XOR 0xaa + +/* + * Return the size of the hardware key cache. + */ +uint32_t +ar5211GetKeyCacheSize(struct ath_hal *ah) +{ + return AR_KEYTABLE_SIZE; +} + +/* + * Return true if the specific key cache entry is valid. + */ +HAL_BOOL +ar5211IsKeyCacheEntryValid(struct ath_hal *ah, uint16_t entry) +{ + if (entry < AR_KEYTABLE_SIZE) { + uint32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry)); + if (val & AR_KEYTABLE_VALID) + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Clear the specified key cache entry + */ +HAL_BOOL +ar5211ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry) +{ + if (entry < AR_KEYTABLE_SIZE) { + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Sets the mac part of the specified key cache entry and mark it valid. + */ +HAL_BOOL +ar5211SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac) +{ + uint32_t macHi, macLo; + + if (entry >= AR_KEYTABLE_SIZE) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n", + __func__, entry); + return AH_FALSE; + } + + /* + * Set MAC address -- shifted right by 1. MacLo is + * the 4 MSBs, and MacHi is the 2 LSBs. + */ + if (mac != AH_NULL) { + macHi = (mac[5] << 8) | mac[4]; + macLo = (mac[3] << 24)| (mac[2] << 16) + | (mac[1] << 8) | mac[0]; + macLo >>= 1; + macLo |= (macHi & 1) << 31; /* carry */ + macHi >>= 1; + } else { + macLo = macHi = 0; + } + + OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID); + return AH_TRUE; +} + +/* + * Sets the contents of the specified key cache entry. + */ +HAL_BOOL +ar5211SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, + const HAL_KEYVAL *k, const uint8_t *mac, + int xorKey) +{ + uint32_t key0, key1, key2, key3, key4; + uint32_t keyType; + uint32_t xorMask= xorKey ? + (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0; + + if (entry >= AR_KEYTABLE_SIZE) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n", + __func__, entry); + return AH_FALSE; + } + switch (k->kv_type) { + case HAL_CIPHER_AES_OCB: + keyType = AR_KEYTABLE_TYPE_AES; + break; + case HAL_CIPHER_WEP: + if (k->kv_len < 40 / NBBY) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: WEP key length %u too small\n", + __func__, k->kv_len); + return AH_FALSE; + } + if (k->kv_len <= 40 / NBBY) + keyType = AR_KEYTABLE_TYPE_40; + else if (k->kv_len <= 104 / NBBY) + keyType = AR_KEYTABLE_TYPE_104; + else + keyType = AR_KEYTABLE_TYPE_128; + break; + case HAL_CIPHER_CLR: + keyType = AR_KEYTABLE_TYPE_CLR; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cipher %u not supported\n", + __func__, k->kv_type); + return AH_FALSE; + } + + key0 = LE_READ_4(k->kv_val+0) ^ xorMask; + key1 = (LE_READ_2(k->kv_val+4) ^ xorMask) & 0xffff; + key2 = LE_READ_4(k->kv_val+6) ^ xorMask; + key3 = (LE_READ_2(k->kv_val+10) ^ xorMask) & 0xffff; + key4 = LE_READ_4(k->kv_val+12) ^ xorMask; + if (k->kv_len <= 104 / NBBY) + key4 &= 0xff; + + + /* + * Note: WEP key cache hardware requires that each double-word + * pair be written in even/odd order (since the destination is + * a 64-bit register). Don't reorder these writes w/o + * understanding this! + */ + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); + return ar5211SetKeyCacheEntryMac(ah, entry, mac); +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_misc.c b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_misc.c new file mode 100644 index 0000000000..519721236c --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_misc.c @@ -0,0 +1,685 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5211_misc.c,v 1.7 2008/11/27 22:29:52 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" +#include "ar5211/ar5211phy.h" + +#include "ah_eeprom_v3.h" + +#define AR_NUM_GPIO 6 /* 6 GPIO bits */ +#define AR_GPIOD_MASK 0x2f /* 6-bit mask */ + +void +ar5211GetMacAddress(struct ath_hal *ah, uint8_t *mac) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); +} + +HAL_BOOL +ar5211SetMacAddress(struct ath_hal *ah, const uint8_t *mac) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); + return AH_TRUE; +} + +void +ar5211GetBssIdMask(struct ath_hal *ah, uint8_t *mask) +{ + static const uint8_t ones[IEEE80211_ADDR_LEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + OS_MEMCPY(mask, ones, IEEE80211_ADDR_LEN); +} + +HAL_BOOL +ar5211SetBssIdMask(struct ath_hal *ah, const uint8_t *mask) +{ + return AH_FALSE; +} + +/* + * Read 16 bits of data from the specified EEPROM offset. + */ +HAL_BOOL +ar5211EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) +{ + OS_REG_WRITE(ah, AR_EEPROM_ADDR, off); + OS_REG_WRITE(ah, AR_EEPROM_CMD, AR_EEPROM_CMD_READ); + + if (!ath_hal_wait(ah, AR_EEPROM_STS, + AR_EEPROM_STS_READ_COMPLETE | AR_EEPROM_STS_READ_ERROR, + AR_EEPROM_STS_READ_COMPLETE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: read failed for entry 0x%x\n", __func__, off); + return AH_FALSE; + } + *data = OS_REG_READ(ah, AR_EEPROM_DATA) & 0xffff; + return AH_TRUE; +} + +#ifdef AH_SUPPORT_WRITE_EEPROM +/* + * Write 16 bits of data to the specified EEPROM offset. + */ +HAL_BOOL +ar5211EepromWrite(struct ath_hal *ah, u_int off, uint16_t data) +{ + return AH_FALSE; +} +#endif /* AH_SUPPORT_WRITE_EEPROM */ + +/* + * Attempt to change the cards operating regulatory domain to the given value + */ +HAL_BOOL +ar5211SetRegulatoryDomain(struct ath_hal *ah, + uint16_t regDomain, HAL_STATUS *status) +{ + HAL_STATUS ecode; + + if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { + ecode = HAL_EINVAL; + goto bad; + } + /* + * Check if EEPROM is configured to allow this; must + * be a proper version and the protection bits must + * permit re-writing that segment of the EEPROM. + */ + if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { + ecode = HAL_EEWRITE; + goto bad; + } +#ifdef AH_SUPPORT_WRITE_REGDOMAIN + if (ar5211EepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: set regulatory domain to %u (0x%x)\n", + __func__, regDomain, regDomain); + AH_PRIVATE(ah)->ah_currentRD = regDomain; + return AH_TRUE; + } +#endif + ecode = HAL_EIO; +bad: + if (status) + *status = ecode; + return AH_FALSE; +} + +/* + * Return the wireless modes (a,b,g,t) supported by hardware. + * + * This value is what is actually supported by the hardware + * and is unaffected by regulatory/country code settings. + * + */ +u_int +ar5211GetWirelessModes(struct ath_hal *ah) +{ + u_int mode = 0; + + if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { + mode = HAL_MODE_11A; + if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) + mode |= HAL_MODE_TURBO | HAL_MODE_108A; + } + if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) + mode |= HAL_MODE_11B; + return mode; +} + +#if 0 +HAL_BOOL +ar5211GetTurboDisable(struct ath_hal *ah) +{ + return (AH5211(ah)->ah_turboDisable != 0); +} +#endif + +/* + * Called if RfKill is supported (according to EEPROM). Set the interrupt and + * GPIO values so the ISR and can disable RF on a switch signal + */ +void +ar5211EnableRfKill(struct ath_hal *ah) +{ + uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent; + int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL); + int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY); + + /* + * Configure the desired GPIO port for input + * and enable baseband rf silence. + */ + ar5211GpioCfgInput(ah, select); + OS_REG_SET_BIT(ah, AR_PHY_BASE, 0x00002000); + /* + * If radio disable switch connection to GPIO bit x is enabled + * program GPIO interrupt. + * If rfkill bit on eeprom is 1, setupeeprommap routine has already + * verified that it is a later version of eeprom, it has a place for + * rfkill bit and it is set to 1, indicating that GPIO bit x hardware + * connection is present. + */ + ar5211GpioSetIntr(ah, select, (ar5211GpioGet(ah, select) != polarity)); +} + +/* + * Configure GPIO Output lines + */ +HAL_BOOL +ar5211GpioCfgOutput(struct ath_hal *ah, uint32_t gpio) +{ + uint32_t reg; + + HALASSERT(gpio < AR_NUM_GPIO); + + reg = OS_REG_READ(ah, AR_GPIOCR); + reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT)); + reg |= AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT); + + OS_REG_WRITE(ah, AR_GPIOCR, reg); + return AH_TRUE; +} + +/* + * Configure GPIO Input lines + */ +HAL_BOOL +ar5211GpioCfgInput(struct ath_hal *ah, uint32_t gpio) +{ + uint32_t reg; + + HALASSERT(gpio < AR_NUM_GPIO); + + reg = OS_REG_READ(ah, AR_GPIOCR); + reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT)); + reg |= AR_GPIOCR_0_CR_N << (gpio * AR_GPIOCR_CR_SHIFT); + + OS_REG_WRITE(ah, AR_GPIOCR, reg); + return AH_TRUE; +} + +/* + * Once configured for I/O - set output lines + */ +HAL_BOOL +ar5211GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) +{ + uint32_t reg; + + HALASSERT(gpio < AR_NUM_GPIO); + + reg = OS_REG_READ(ah, AR_GPIODO); + reg &= ~(1 << gpio); + reg |= (val&1) << gpio; + + OS_REG_WRITE(ah, AR_GPIODO, reg); + return AH_TRUE; +} + +/* + * Once configured for I/O - get input lines + */ +uint32_t +ar5211GpioGet(struct ath_hal *ah, uint32_t gpio) +{ + if (gpio < AR_NUM_GPIO) { + uint32_t val = OS_REG_READ(ah, AR_GPIODI); + val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1; + return val; + } else { + return 0xffffffff; + } +} + +/* + * Set the GPIO 0 Interrupt (gpio is ignored) + */ +void +ar5211GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) +{ + uint32_t val = OS_REG_READ(ah, AR_GPIOCR); + + /* Clear the bits that we will modify. */ + val &= ~(AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA | + AR_GPIOCR_0_CR_A); + + val |= AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_ENA; + if (ilevel) + val |= AR_GPIOCR_INT_SELH; + + /* Don't need to change anything for low level interrupt. */ + OS_REG_WRITE(ah, AR_GPIOCR, val); + + /* Change the interrupt mask. */ + ar5211SetInterrupts(ah, AH5211(ah)->ah_maskReg | HAL_INT_GPIO); +} + +/* + * Change the LED blinking pattern to correspond to the connectivity + */ +void +ar5211SetLedState(struct ath_hal *ah, HAL_LED_STATE state) +{ + static const uint32_t ledbits[8] = { + AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_INIT */ + AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_SCAN */ + AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_AUTH */ + AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_ASSOC*/ + AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_RUN */ + AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND, + AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND, + AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND, + }; + OS_REG_WRITE(ah, AR_PCICFG, + (OS_REG_READ(ah, AR_PCICFG) &~ + (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE)) + | ledbits[state & 0x7] + ); +} + +/* + * Change association related fields programmed into the hardware. + * Writing a valid BSSID to the hardware effectively enables the hardware + * to synchronize its TSF to the correct beacons and receive frames coming + * from that BSSID. It is called by the SME JOIN operation. + */ +void +ar5211WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + /* XXX save bssid for possible re-use on reset */ + OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); + OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); + OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | + ((assocId & 0x3fff)<> 19) & 0x1ff; + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + return (OS_REG_READ(ah, AR_TSF_U32) ^ + OS_REG_READ(ah, AR_TSF_L32) ^ nf); +} + +/* + * Detect if our card is present + */ +HAL_BOOL +ar5211DetectCardPresent(struct ath_hal *ah) +{ + uint16_t macVersion, macRev; + uint32_t v; + + /* + * Read the Silicon Revision register and compare that + * to what we read at attach time. If the same, we say + * a card/device is present. + */ + v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID_M; + macVersion = v >> AR_SREV_ID_S; + macRev = v & AR_SREV_REVISION_M; + return (AH_PRIVATE(ah)->ah_macVersion == macVersion && + AH_PRIVATE(ah)->ah_macRev == macRev); +} + +/* + * Update MIB Counters + */ +void +ar5211UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats) +{ + stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); + stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); + stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); + stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); + stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); +} + +HAL_BOOL +ar5211SetSifsTime(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + if (us > ath_hal_mac_usec(ah, 0xffff)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n", + __func__, us); + ahp->ah_sifstime = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us)); + ahp->ah_slottime = us; + return AH_TRUE; + } +} + +u_int +ar5211GetSifsTime(struct ath_hal *ah) +{ + u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff; + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +HAL_BOOL +ar5211SetSlotTime(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n", + __func__, us); + ahp->ah_slottime = us; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us)); + ahp->ah_slottime = us; + return AH_TRUE; + } +} + +u_int +ar5211GetSlotTime(struct ath_hal *ah) +{ + u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff; + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +HAL_BOOL +ar5211SetAckTimeout(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n", + __func__, us); + ahp->ah_acktimeout = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_RMW_FIELD(ah, AR_TIME_OUT, + AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us)); + ahp->ah_acktimeout = us; + return AH_TRUE; + } +} + +u_int +ar5211GetAckTimeout(struct ath_hal *ah) +{ + u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +u_int +ar5211GetAckCTSRate(struct ath_hal *ah) +{ + return ((AH5211(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0); +} + +HAL_BOOL +ar5211SetAckCTSRate(struct ath_hal *ah, u_int high) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + if (high) { + OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); + ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB; + } else { + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); + ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB; + } + return AH_TRUE; +} + +HAL_BOOL +ar5211SetCTSTimeout(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n", + __func__, us); + ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_RMW_FIELD(ah, AR_TIME_OUT, + AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); + ahp->ah_ctstimeout = us; + return AH_TRUE; + } +} + +u_int +ar5211GetCTSTimeout(struct ath_hal *ah) +{ + u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +HAL_BOOL +ar5211SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) +{ + /* nothing to do */ + return AH_TRUE; +} + +void +ar5211SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) +{ +} + +/* + * Control Adaptive Noise Immunity Parameters + */ +HAL_BOOL +ar5211AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) +{ + return AH_FALSE; +} + +void +ar5211AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats, HAL_CHANNEL *chan) +{ +} + +void +ar5211MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats) +{ +} + +/* + * Get the rssi of frame curently being received. + */ +uint32_t +ar5211GetCurRssi(struct ath_hal *ah) +{ + return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff); +} + +u_int +ar5211GetDefAntenna(struct ath_hal *ah) +{ + return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7); +} + +void +ar5211SetDefAntenna(struct ath_hal *ah, u_int antenna) +{ + OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); +} + +HAL_ANT_SETTING +ar5211GetAntennaSwitch(struct ath_hal *ah) +{ + return AH5211(ah)->ah_diversityControl; +} + +HAL_BOOL +ar5211SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) +{ + const HAL_CHANNEL *chan = + (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan; + + if (chan == AH_NULL) { + AH5211(ah)->ah_diversityControl = settings; + return AH_TRUE; + } + return ar5211SetAntennaSwitchInternal(ah, settings, chan); +} + +HAL_STATUS +ar5211GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t *result) +{ + + switch (type) { + case HAL_CAP_CIPHER: /* cipher handled in hardware */ + switch (capability) { + case HAL_CIPHER_AES_OCB: + case HAL_CIPHER_WEP: + case HAL_CIPHER_CLR: + return HAL_OK; + default: + return HAL_ENOTSUPP; + } + default: + return ath_hal_getcapability(ah, type, capability, result); + } +} + +HAL_BOOL +ar5211SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t setting, HAL_STATUS *status) +{ + switch (type) { + case HAL_CAP_DIAG: /* hardware diagnostic support */ + /* + * NB: could split this up into virtual capabilities, + * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly + * seems worth the additional complexity. + */ +#ifdef AH_DEBUG + AH_PRIVATE(ah)->ah_diagreg = setting; +#else + AH_PRIVATE(ah)->ah_diagreg = setting & 0x6; /* ACK+CTS */ +#endif + OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); + return AH_TRUE; + default: + return ath_hal_setcapability(ah, type, capability, + setting, status); + } +} + +HAL_BOOL +ar5211GetDiagState(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + (void) ahp; + if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) + return AH_TRUE; + switch (request) { + case HAL_DIAG_EEPROM: + return ath_hal_eepromDiag(ah, request, + args, argsize, result, resultsize); + case HAL_DIAG_RFGAIN: + *result = &ahp->ah_gainValues; + *resultsize = sizeof(GAIN_VALUES); + return AH_TRUE; + case HAL_DIAG_RFGAIN_CURSTEP: + *result = __DECONST(void *, ahp->ah_gainValues.currStep); + *resultsize = (*result == AH_NULL) ? + 0 : sizeof(GAIN_OPTIMIZATION_STEP); + return AH_TRUE; + } + return AH_FALSE; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_phy.c b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_phy.c new file mode 100644 index 0000000000..62a46b5a0a --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_phy.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5211_phy.c,v 1.3 2008/11/10 01:19:37 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5211/ar5211.h" + +/* shorthands to compact tables for readability */ +#define OFDM IEEE80211_T_OFDM +#define CCK IEEE80211_T_CCK +#define TURBO IEEE80211_T_TURBO + +HAL_RATE_TABLE ar5211_11a_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80|12), 0 }, +/* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 0 }, +/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, (0x80|48), 4 }, +/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 4 }, +/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 4 }, +/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 4 } + }, +}; + +HAL_RATE_TABLE ar5211_turbo_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, TURBO, 6000, 0x0b, 0x00, (0x80|12), 0 }, +/* 9 Mb */ { AH_TRUE, TURBO, 9000, 0x0f, 0x00, 18, 0 }, +/* 12 Mb */ { AH_TRUE, TURBO, 12000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, TURBO, 18000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, TURBO, 24000, 0x09, 0x00, (0x80|48), 4 }, +/* 36 Mb */ { AH_TRUE, TURBO, 36000, 0x0d, 0x00, 72, 4 }, +/* 48 Mb */ { AH_TRUE, TURBO, 48000, 0x08, 0x00, 96, 4 }, +/* 54 Mb */ { AH_TRUE, TURBO, 54000, 0x0c, 0x00, 108, 4 } + }, +}; + +HAL_RATE_TABLE ar5211_11b_table = { + 4, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 1 Mb */ { AH_TRUE, CCK, 1000, 0x0b, 0x00, (0x80| 2), 0 }, +/* 2 Mb */ { AH_TRUE, CCK, 2000, 0x0a, 0x04, (0x80| 4), 1 }, +/* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x09, 0x04, (0x80|11), 1 }, +/* 11 Mb */ { AH_TRUE, CCK, 11000, 0x08, 0x04, (0x80|22), 1 } + }, +}; + +#undef OFDM +#undef CCK +#undef TURBO + + +const HAL_RATE_TABLE * +ar5211GetRateTable(struct ath_hal *ah, u_int mode) +{ + HAL_RATE_TABLE *rt; + switch (mode) { + case HAL_MODE_11A: + rt = &ar5211_11a_table; + break; + case HAL_MODE_11B: + rt = &ar5211_11b_table; + break; + case HAL_MODE_TURBO: + rt = &ar5211_turbo_table; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", + __func__, mode); + return AH_NULL; + } + ath_hal_setupratetable(ah, rt); + return rt; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_power.c b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_power.c new file mode 100644 index 0000000000..bcfcf7cccf --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_power.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5211_power.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" +#include "ar5211/ar5211desc.h" + +/* + * Notify Power Mgt is enabled in self-generated frames. + * If requested, force chip awake. + * + * Returns A_OK if chip is awake or successfully forced awake. + * + * WARNING WARNING WARNING + * There is a problem with the chip where sometimes it will not wake up. + */ +static HAL_BOOL +ar5211SetPowerModeAwake(struct ath_hal *ah, int setChip) +{ +#define POWER_UP_TIME 2000 + uint32_t val; + int i; + + if (setChip) { + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_WAKE); + OS_DELAY(10); /* Give chip the chance to awake */ + + for (i = POWER_UP_TIME / 200; i != 0; i--) { + val = OS_REG_READ(ah, AR_PCICFG); + if ((val & AR_PCICFG_SPWR_DN) == 0) + break; + OS_DELAY(200); + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, + AR_SCR_SLE_WAKE); + } + if (i == 0) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n", + __func__, POWER_UP_TIME/20); +#endif + return AH_FALSE; + } + } + + OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + return AH_TRUE; +#undef POWER_UP_TIME +} + +/* + * Notify Power Mgt is disabled in self-generated frames. + * If requested, force chip to sleep. + */ +static void +ar5211SetPowerModeSleep(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + if (setChip) + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_SLP); +} + +/* + * Notify Power Management is enabled in self-generating + * fames. If request, set power mode of chip to + * auto/normal. Duration in units of 128us (1/8 TU). + */ +static void +ar5211SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + if (setChip) + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_NORM); +} + +HAL_BOOL +ar5211SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) +{ + struct ath_hal_5211 *ahp = AH5211(ah); +#ifdef AH_DEBUG + static const char* modes[] = { + "AWAKE", + "FULL-SLEEP", + "NETWORK SLEEP", + "UNDEFINED" + }; +#endif + int status = AH_TRUE; + + HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__, + modes[ahp->ah_powerMode], modes[mode], + setChip ? "set chip " : ""); + switch (mode) { + case HAL_PM_AWAKE: + status = ar5211SetPowerModeAwake(ah, setChip); + break; + case HAL_PM_FULL_SLEEP: + ar5211SetPowerModeSleep(ah, setChip); + break; + case HAL_PM_NETWORK_SLEEP: + ar5211SetPowerModeNetworkSleep(ah, setChip); + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n", + __func__, mode); + return AH_FALSE; + } + ahp->ah_powerMode = mode; + return status; +} + +HAL_POWER_MODE +ar5211GetPowerMode(struct ath_hal *ah) +{ + /* Just so happens the h/w maps directly to the abstracted value */ + return MS(OS_REG_READ(ah, AR_SCR), AR_SCR_SLE); +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_recv.c b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_recv.c new file mode 100644 index 0000000000..c5b0e183e3 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_recv.c @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5211_recv.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" +#include "ar5211/ar5211desc.h" + +/* + * Get the RXDP. + */ +uint32_t +ar5211GetRxDP(struct ath_hal *ah) +{ + return OS_REG_READ(ah, AR_RXDP); +} + +/* + * Set the RxDP. + */ +void +ar5211SetRxDP(struct ath_hal *ah, uint32_t rxdp) +{ + OS_REG_WRITE(ah, AR_RXDP, rxdp); + HALASSERT(OS_REG_READ(ah, AR_RXDP) == rxdp); +} + + +/* + * Set Receive Enable bits. + */ +void +ar5211EnableReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_CR, AR_CR_RXE); +} + +/* + * Stop Receive at the DMA engine + */ +HAL_BOOL +ar5211StopDmaReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */ + if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0)) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s failed to stop in 10ms\n" + "AR_CR=0x%08X\nAR_DIAG_SW=0x%08X\n" + , __func__ + , OS_REG_READ(ah, AR_CR) + , OS_REG_READ(ah, AR_DIAG_SW) + ); +#endif + return AH_FALSE; + } else { + return AH_TRUE; + } +} + +/* + * Start Transmit at the PCU engine (unpause receive) + */ +void +ar5211StartPcuReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_DIAG_SW, + OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_RX)); +} + +/* + * Stop Transmit at the PCU engine (pause receive) + */ +void +ar5211StopPcuReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_DIAG_SW, + OS_REG_READ(ah, AR_DIAG_SW) | AR_DIAG_SW_DIS_RX); +} + +/* + * Set multicast filter 0 (lower 32-bits) + * filter 1 (upper 32-bits) + */ +void +ar5211SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1) +{ + OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0); + OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1); +} + +/* + * Clear multicast filter by index + */ +HAL_BOOL +ar5211ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix) +{ + uint32_t val; + + if (ix >= 64) + return AH_FALSE; + if (ix >= 32) { + val = OS_REG_READ(ah, AR_MCAST_FIL1); + OS_REG_WRITE(ah, AR_MCAST_FIL1, (val &~ (1<<(ix-32)))); + } else { + val = OS_REG_READ(ah, AR_MCAST_FIL0); + OS_REG_WRITE(ah, AR_MCAST_FIL0, (val &~ (1<= 64) + return AH_FALSE; + if (ix >= 32) { + val = OS_REG_READ(ah, AR_MCAST_FIL1); + OS_REG_WRITE(ah, AR_MCAST_FIL1, (val | (1<<(ix-32)))); + } else { + val = OS_REG_READ(ah, AR_MCAST_FIL0); + OS_REG_WRITE(ah, AR_MCAST_FIL0, (val | (1<ds_ctl0 = 0; + ads->ds_ctl1 = size & AR_BufLen; + if (ads->ds_ctl1 != size) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: buffer size %u too large\n", + __func__, size); + return AH_FALSE; + } + if (flags & HAL_RXDESC_INTREQ) + ads->ds_ctl1 |= AR_RxInterReq; + ads->ds_status0 = ads->ds_status1 = 0; + + return AH_TRUE; +} + +/* + * Process an RX descriptor, and return the status to the caller. + * Copy some hardware specific items into the software portion + * of the descriptor. + * + * NB: the caller is responsible for validating the memory contents + * of the descriptor (e.g. flushing any cached copy). + */ +HAL_STATUS +ar5211ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, + uint32_t pa, struct ath_desc *nds, uint64_t tsf, + struct ath_rx_status *rs) +{ + struct ar5211_desc *ads = AR5211DESC(ds); + struct ar5211_desc *ands = AR5211DESC(nds); + + if ((ads->ds_status1 & AR_Done) == 0) + return HAL_EINPROGRESS; + /* + * Given the use of a self-linked tail be very sure that the hw is + * done with this descriptor; the hw may have done this descriptor + * once and picked it up again...make sure the hw has moved on. + */ + if ((ands->ds_status1 & AR_Done) == 0 && OS_REG_READ(ah, AR_RXDP) == pa) + return HAL_EINPROGRESS; + + rs->rs_datalen = ads->ds_status0 & AR_DataLen; + rs->rs_tstamp = MS(ads->ds_status1, AR_RcvTimestamp); + rs->rs_status = 0; + if ((ads->ds_status1 & AR_FrmRcvOK) == 0) { + if (ads->ds_status1 & AR_CRCErr) + rs->rs_status |= HAL_RXERR_CRC; + else if (ads->ds_status1 & AR_DecryptCRCErr) + rs->rs_status |= HAL_RXERR_DECRYPT; + else { + rs->rs_status |= HAL_RXERR_PHY; + rs->rs_phyerr = MS(ads->ds_status1, AR_PHYErr); + } + } + /* XXX what about KeyCacheMiss? */ + rs->rs_rssi = MS(ads->ds_status0, AR_RcvSigStrength); + if (ads->ds_status1 & AR_KeyIdxValid) + rs->rs_keyix = MS(ads->ds_status1, AR_KeyIdx); + else + rs->rs_keyix = HAL_RXKEYIX_INVALID; + /* NB: caller expected to do rate table mapping */ + rs->rs_rate = MS(ads->ds_status0, AR_RcvRate); + rs->rs_antenna = MS(ads->ds_status0, AR_RcvAntenna); + rs->rs_more = (ads->ds_status0 & AR_More) ? 1 : 0; + + return HAL_OK; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_reset.c b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_reset.c new file mode 100644 index 0000000000..6646a4ddfe --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_reset.c @@ -0,0 +1,2138 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5211_reset.c,v 1.9 2008/11/27 22:29:52 sam Exp $ + */ +#include "opt_ah.h" + +/* + * Chips specific device attachment and device info collection + * Connects Init Reg Vectors, EEPROM Data, and device Functions. + */ +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" +#include "ar5211/ar5211phy.h" + +#include "ah_eeprom_v3.h" + +/* Add static register initialization vectors */ +#include "ar5211/boss.ini" + +/* + * Structure to hold 11b tuning information for Beanie/Sombrero + * 16 MHz mode, divider ratio = 198 = NP+S. N=16, S=4 or 6, P=12 + */ +typedef struct { + uint32_t refClkSel; /* reference clock, 1 for 16 MHz */ + uint32_t channelSelect; /* P[7:4]S[3:0] bits */ + uint16_t channel5111; /* 11a channel for 5111 */ +} CHAN_INFO_2GHZ; + +#define CI_2GHZ_INDEX_CORRECTION 19 +const static CHAN_INFO_2GHZ chan2GHzData[] = { + { 1, 0x46, 96 }, /* 2312 -19 */ + { 1, 0x46, 97 }, /* 2317 -18 */ + { 1, 0x46, 98 }, /* 2322 -17 */ + { 1, 0x46, 99 }, /* 2327 -16 */ + { 1, 0x46, 100 }, /* 2332 -15 */ + { 1, 0x46, 101 }, /* 2337 -14 */ + { 1, 0x46, 102 }, /* 2342 -13 */ + { 1, 0x46, 103 }, /* 2347 -12 */ + { 1, 0x46, 104 }, /* 2352 -11 */ + { 1, 0x46, 105 }, /* 2357 -10 */ + { 1, 0x46, 106 }, /* 2362 -9 */ + { 1, 0x46, 107 }, /* 2367 -8 */ + { 1, 0x46, 108 }, /* 2372 -7 */ + /* index -6 to 0 are pad to make this a nolookup table */ + { 1, 0x46, 116 }, /* -6 */ + { 1, 0x46, 116 }, /* -5 */ + { 1, 0x46, 116 }, /* -4 */ + { 1, 0x46, 116 }, /* -3 */ + { 1, 0x46, 116 }, /* -2 */ + { 1, 0x46, 116 }, /* -1 */ + { 1, 0x46, 116 }, /* 0 */ + { 1, 0x46, 116 }, /* 2412 1 */ + { 1, 0x46, 117 }, /* 2417 2 */ + { 1, 0x46, 118 }, /* 2422 3 */ + { 1, 0x46, 119 }, /* 2427 4 */ + { 1, 0x46, 120 }, /* 2432 5 */ + { 1, 0x46, 121 }, /* 2437 6 */ + { 1, 0x46, 122 }, /* 2442 7 */ + { 1, 0x46, 123 }, /* 2447 8 */ + { 1, 0x46, 124 }, /* 2452 9 */ + { 1, 0x46, 125 }, /* 2457 10 */ + { 1, 0x46, 126 }, /* 2462 11 */ + { 1, 0x46, 127 }, /* 2467 12 */ + { 1, 0x46, 128 }, /* 2472 13 */ + { 1, 0x44, 124 }, /* 2484 14 */ + { 1, 0x46, 136 }, /* 2512 15 */ + { 1, 0x46, 140 }, /* 2532 16 */ + { 1, 0x46, 144 }, /* 2552 17 */ + { 1, 0x46, 148 }, /* 2572 18 */ + { 1, 0x46, 152 }, /* 2592 19 */ + { 1, 0x46, 156 }, /* 2612 20 */ + { 1, 0x46, 160 }, /* 2632 21 */ + { 1, 0x46, 164 }, /* 2652 22 */ + { 1, 0x46, 168 }, /* 2672 23 */ + { 1, 0x46, 172 }, /* 2692 24 */ + { 1, 0x46, 176 }, /* 2712 25 */ + { 1, 0x46, 180 } /* 2732 26 */ +}; + +/* Power timeouts in usec to wait for chip to wake-up. */ +#define POWER_UP_TIME 2000 + +#define DELAY_PLL_SETTLE 300 /* 300 us */ +#define DELAY_BASE_ACTIVATE 100 /* 100 us */ + +#define NUM_RATES 8 + +static HAL_BOOL ar5211SetResetReg(struct ath_hal *ah, uint32_t resetMask); +static HAL_BOOL ar5211SetChannel(struct ath_hal *, HAL_CHANNEL_INTERNAL *); +static int16_t ar5211RunNoiseFloor(struct ath_hal *, + uint8_t runTime, int16_t startingNF); +static HAL_BOOL ar5211IsNfGood(struct ath_hal *, HAL_CHANNEL_INTERNAL *chan); +static HAL_BOOL ar5211SetRf6and7(struct ath_hal *, HAL_CHANNEL *chan); +static HAL_BOOL ar5211SetBoardValues(struct ath_hal *, HAL_CHANNEL *chan); +static void ar5211SetPowerTable(struct ath_hal *, + PCDACS_EEPROM *pSrcStruct, uint16_t channel); +static void ar5211SetRateTable(struct ath_hal *, + RD_EDGES_POWER *pRdEdgesPower, TRGT_POWER_INFO *pPowerInfo, + uint16_t numChannels, HAL_CHANNEL *chan); +static uint16_t ar5211GetScaledPower(uint16_t channel, uint16_t pcdacValue, + const PCDACS_EEPROM *pSrcStruct); +static HAL_BOOL ar5211FindValueInList(uint16_t channel, uint16_t pcdacValue, + const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue); +static uint16_t ar5211GetInterpolatedValue(uint16_t target, + uint16_t srcLeft, uint16_t srcRight, + uint16_t targetLeft, uint16_t targetRight, HAL_BOOL scaleUp); +static void ar5211GetLowerUpperValues(uint16_t value, + const uint16_t *pList, uint16_t listSize, + uint16_t *pLowerValue, uint16_t *pUpperValue); +static void ar5211GetLowerUpperPcdacs(uint16_t pcdac, + uint16_t channel, const PCDACS_EEPROM *pSrcStruct, + uint16_t *pLowerPcdac, uint16_t *pUpperPcdac); + +static void ar5211SetRfgain(struct ath_hal *, const GAIN_VALUES *);; +static void ar5211RequestRfgain(struct ath_hal *); +static HAL_BOOL ar5211InvalidGainReadback(struct ath_hal *, GAIN_VALUES *); +static HAL_BOOL ar5211IsGainAdjustNeeded(struct ath_hal *, const GAIN_VALUES *); +static int32_t ar5211AdjustGain(struct ath_hal *, GAIN_VALUES *); +static void ar5211SetOperatingMode(struct ath_hal *, int opmode); + +/* + * Places the device in and out of reset and then places sane + * values in the registers based on EEPROM config, initialization + * vectors (as determined by the mode), and station configuration + * + * bChannelChange is used to preserve DMA/PCU registers across + * a HW Reset during channel change. + */ +HAL_BOOL +ar5211Reset(struct ath_hal *ah, HAL_OPMODE opmode, + HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status) +{ +uint32_t softLedCfg, softLedState; +#define N(a) (sizeof (a) /sizeof (a[0])) +#define FAIL(_code) do { ecode = _code; goto bad; } while (0) + struct ath_hal_5211 *ahp = AH5211(ah); + HAL_CHANNEL_INTERNAL *ichan; + uint32_t i, ledstate; + HAL_STATUS ecode; + int q; + + uint32_t data, synthDelay; + uint32_t macStaId1; + uint16_t modesIndex = 0, freqIndex = 0; + uint32_t saveFrameSeqCount[AR_NUM_DCU]; + uint32_t saveTsfLow = 0, saveTsfHigh = 0; + uint32_t saveDefAntenna; + + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s: opmode %u channel %u/0x%x %s channel\n", + __func__, opmode, chan->channel, chan->channelFlags, + bChannelChange ? "change" : "same"); + + OS_MARK(ah, AH_MARK_RESET, bChannelChange); +#define IS(_c,_f) (((_c)->channelFlags & _f) || 0) + if ((IS(chan, CHANNEL_2GHZ) ^ IS(chan,CHANNEL_5GHZ)) == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n", + __func__, chan->channel, chan->channelFlags); + FAIL(HAL_EINVAL); + } + if ((IS(chan, CHANNEL_OFDM) ^ IS(chan, CHANNEL_CCK)) == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; not marked as OFDM or CCK\n", + __func__, chan->channel, chan->channelFlags); + FAIL(HAL_EINVAL); + } +#undef IS + /* + * Map public channel to private. + */ + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->channel, chan->channelFlags); + FAIL(HAL_EINVAL); + } + switch (opmode) { + case HAL_M_STA: + case HAL_M_IBSS: + case HAL_M_HOSTAP: + case HAL_M_MONITOR: + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid operating mode %u\n", __func__, opmode); + FAIL(HAL_EINVAL); + break; + } + HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3); + + /* Preserve certain DMA hardware registers on a channel change */ + if (bChannelChange) { + /* + * Need to save/restore the TSF because of an issue + * that accelerates the TSF during a chip reset. + * + * We could use system timer routines to more + * accurately restore the TSF, but + * 1. Timer routines on certain platforms are + * not accurate enough (e.g. 1 ms resolution). + * 2. It would still not be accurate. + * + * The most important aspect of this workaround, + * is that, after reset, the TSF is behind + * other STAs TSFs. This will allow the STA to + * properly resynchronize its TSF in adhoc mode. + */ + saveTsfLow = OS_REG_READ(ah, AR_TSF_L32); + saveTsfHigh = OS_REG_READ(ah, AR_TSF_U32); + + /* Read frame sequence count */ + if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) { + saveFrameSeqCount[0] = OS_REG_READ(ah, AR_D0_SEQNUM); + } else { + for (i = 0; i < AR_NUM_DCU; i++) + saveFrameSeqCount[i] = OS_REG_READ(ah, AR_DSEQNUM(i)); + } + if (!(ichan->privFlags & CHANNEL_DFS)) + ichan->privFlags &= ~CHANNEL_INTERFERENCE; + chan->channelFlags = ichan->channelFlags; + chan->privFlags = ichan->privFlags; + } + + /* + * Preserve the antenna on a channel change + */ + saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA); + if (saveDefAntenna == 0) + saveDefAntenna = 1; + + /* Save hardware flag before chip reset clears the register */ + macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; + + /* Save led state from pci config register */ + ledstate = OS_REG_READ(ah, AR_PCICFG) & + (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK | + AR_PCICFG_LEDSLOW); + softLedCfg = OS_REG_READ(ah, AR_GPIOCR); + softLedState = OS_REG_READ(ah, AR_GPIODO); + + if (!ar5211ChipReset(ah, chan->channelFlags)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + FAIL(HAL_EIO); + } + + /* Setup the indices for the next set of register array writes */ + switch (chan->channelFlags & CHANNEL_ALL) { + case CHANNEL_A: + modesIndex = 1; + freqIndex = 1; + break; + case CHANNEL_T: + modesIndex = 2; + freqIndex = 1; + break; + case CHANNEL_B: + modesIndex = 3; + freqIndex = 2; + break; + case CHANNEL_PUREG: + modesIndex = 4; + freqIndex = 2; + break; + default: + /* Ah, a new wireless mode */ + HALASSERT(0); + break; + } + + /* Set correct Baseband to analog shift setting to access analog chips. */ + if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) { + OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007); + } else { + OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000047); + } + + /* Write parameters specific to AR5211 */ + if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) { + if (IS_CHAN_2GHZ(chan) && + AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1) { + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint32_t ob2GHz, db2GHz; + + if (IS_CHAN_CCK(chan)) { + ob2GHz = ee->ee_ob2GHz[0]; + db2GHz = ee->ee_db2GHz[0]; + } else { + ob2GHz = ee->ee_ob2GHz[1]; + db2GHz = ee->ee_db2GHz[1]; + } + ob2GHz = ath_hal_reverseBits(ob2GHz, 3); + db2GHz = ath_hal_reverseBits(db2GHz, 3); + ar5211Mode2_4[25][freqIndex] = + (ar5211Mode2_4[25][freqIndex] & ~0xC0) | + ((ob2GHz << 6) & 0xC0); + ar5211Mode2_4[26][freqIndex] = + (ar5211Mode2_4[26][freqIndex] & ~0x0F) | + (((ob2GHz >> 2) & 0x1) | + ((db2GHz << 1) & 0x0E)); + } + for (i = 0; i < N(ar5211Mode2_4); i++) + OS_REG_WRITE(ah, ar5211Mode2_4[i][0], + ar5211Mode2_4[i][freqIndex]); + } + + /* Write the analog registers 6 and 7 before other config */ + ar5211SetRf6and7(ah, chan); + + /* Write registers that vary across all modes */ + for (i = 0; i < N(ar5211Modes); i++) + OS_REG_WRITE(ah, ar5211Modes[i][0], ar5211Modes[i][modesIndex]); + + /* Write RFGain Parameters that differ between 2.4 and 5 GHz */ + for (i = 0; i < N(ar5211BB_RfGain); i++) + OS_REG_WRITE(ah, ar5211BB_RfGain[i][0], ar5211BB_RfGain[i][freqIndex]); + + /* Write Common Array Parameters */ + for (i = 0; i < N(ar5211Common); i++) { + uint32_t reg = ar5211Common[i][0]; + /* On channel change, don't reset the PCU registers */ + if (!(bChannelChange && (0x8000 <= reg && reg < 0x9000))) + OS_REG_WRITE(ah, reg, ar5211Common[i][1]); + } + + /* Fix pre-AR5211 register values, this includes AR5311s. */ + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) { + /* + * The TX and RX latency values have changed locations + * within the USEC register in AR5211. Since they're + * set via the .ini, for both AR5211 and AR5311, they + * are written properly here for AR5311. + */ + data = OS_REG_READ(ah, AR_USEC); + /* Must be 0 for proper write in AR5311 */ + HALASSERT((data & 0x00700000) == 0); + OS_REG_WRITE(ah, AR_USEC, + (data & (AR_USEC_M | AR_USEC_32_M | AR5311_USEC_TX_LAT_M)) | + ((29 << AR5311_USEC_RX_LAT_S) & AR5311_USEC_RX_LAT_M)); + /* The following registers exist only on AR5311. */ + OS_REG_WRITE(ah, AR5311_QDCLKGATE, 0); + + /* Set proper ADC & DAC delays for AR5311. */ + OS_REG_WRITE(ah, 0x00009878, 0x00000008); + + /* Enable the PCU FIFO corruption ECO on AR5311. */ + OS_REG_WRITE(ah, AR_DIAG_SW, + OS_REG_READ(ah, AR_DIAG_SW) | AR5311_DIAG_SW_USE_ECO); + } + + /* Restore certain DMA hardware registers on a channel change */ + if (bChannelChange) { + /* Restore TSF */ + OS_REG_WRITE(ah, AR_TSF_L32, saveTsfLow); + OS_REG_WRITE(ah, AR_TSF_U32, saveTsfHigh); + + if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) { + OS_REG_WRITE(ah, AR_D0_SEQNUM, saveFrameSeqCount[0]); + } else { + for (i = 0; i < AR_NUM_DCU; i++) + OS_REG_WRITE(ah, AR_DSEQNUM(i), saveFrameSeqCount[i]); + } + } + + OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr)); + OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4) + | macStaId1 + ); + ar5211SetOperatingMode(ah, opmode); + + /* Restore previous led state */ + OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | ledstate); + OS_REG_WRITE(ah, AR_GPIOCR, softLedCfg); + OS_REG_WRITE(ah, AR_GPIODO, softLedState); + + /* Restore previous antenna */ + OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); + + OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); + OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4)); + + /* Restore bmiss rssi & count thresholds */ + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); + + OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */ + + /* + * for pre-Production Oahu only. + * Disable clock gating in all DMA blocks. Helps when using + * 11B and AES but results in higher power consumption. + */ + if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_OAHU && + AH_PRIVATE(ah)->ah_macRev < AR_SREV_OAHU_PROD) { + OS_REG_WRITE(ah, AR_CFG, + OS_REG_READ(ah, AR_CFG) | AR_CFG_CLK_GATE_DIS); + } + + /* Setup the transmit power values. */ + if (!ar5211SetTransmitPower(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error init'ing transmit power\n", __func__); + FAIL(HAL_EIO); + } + + /* + * Configurable OFDM spoofing for 11n compatibility; used + * only when operating in station mode. + */ + if (opmode != HAL_M_HOSTAP && + (AH_PRIVATE(ah)->ah_11nCompat & HAL_DIAG_11N_SERVICES) != 0) { + /* NB: override the .ini setting */ + OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, + AR_PHY_FRAME_CTL_ERR_SERV, + MS(AH_PRIVATE(ah)->ah_11nCompat, HAL_DIAG_11N_SERVICES)&1); + } + + /* Setup board specific options for EEPROM version 3 */ + ar5211SetBoardValues(ah, chan); + + if (!ar5211SetChannel(ah, ichan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set channel\n", + __func__); + FAIL(HAL_EIO); + } + + /* Activate the PHY */ + if (AH_PRIVATE(ah)->ah_devid == AR5211_FPGA11B && IS_CHAN_2GHZ(chan)) + OS_REG_WRITE(ah, 0xd808, 0x502); /* required for FPGA */ + OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + + /* + * Wait for the frequency synth to settle (synth goes on + * via AR_PHY_ACTIVE_EN). Read the phy active delay register. + * Value is in 100ns increments. + */ + data = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_M; + if (IS_CHAN_CCK(chan)) { + synthDelay = (4 * data) / 22; + } else { + synthDelay = data / 10; + } + /* + * There is an issue if the AP starts the calibration before + * the baseband timeout completes. This could result in the + * rxclear false triggering. Add an extra delay to ensure this + * this does not happen. + */ + OS_DELAY(synthDelay + DELAY_BASE_ACTIVATE); + + /* Calibrate the AGC and wait for completion. */ + OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, + OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL); + (void) ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0); + + /* Perform noise floor and set status */ + if (!ar5211CalNoiseFloor(ah, ichan)) { + if (!IS_CHAN_CCK(chan)) + chan->channelFlags |= CHANNEL_CW_INT; + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: noise floor calibration failed\n", __func__); + FAIL(HAL_EIO); + } + + /* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */ + if (ahp->ah_calibrationTime != 0) { + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_DO_IQCAL | (INIT_IQCAL_LOG_COUNT_MAX << AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S)); + ahp->ah_bIQCalibration = AH_TRUE; + } + + /* set 1:1 QCU to DCU mapping for all queues */ + for (q = 0; q < AR_NUM_DCU; q++) + OS_REG_WRITE(ah, AR_DQCUMASK(q), 1<ah_maskReg = INIT_INTERRUPT_MASK; + + /* Enable bus error interrupts */ + OS_REG_WRITE(ah, AR_IMR_S2, OS_REG_READ(ah, AR_IMR_S2) | + AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR); + + /* Enable interrupts specific to AP */ + if (opmode == HAL_M_HOSTAP) { + OS_REG_WRITE(ah, AR_IMR, OS_REG_READ(ah, AR_IMR) | AR_IMR_MIB); + ahp->ah_maskReg |= AR_IMR_MIB; + } + + if (AH_PRIVATE(ah)->ah_rfkillEnabled) + ar5211EnableRfKill(ah); + + /* + * Writing to AR_BEACON will start timers. Hence it should + * be the last register to be written. Do not reset tsf, do + * not enable beacons at this point, but preserve other values + * like beaconInterval. + */ + OS_REG_WRITE(ah, AR_BEACON, + (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF))); + + /* Restore user-specified slot time and timeouts */ + if (ahp->ah_sifstime != (u_int) -1) + ar5211SetSifsTime(ah, ahp->ah_sifstime); + if (ahp->ah_slottime != (u_int) -1) + ar5211SetSlotTime(ah, ahp->ah_slottime); + if (ahp->ah_acktimeout != (u_int) -1) + ar5211SetAckTimeout(ah, ahp->ah_acktimeout); + if (ahp->ah_ctstimeout != (u_int) -1) + ar5211SetCTSTimeout(ah, ahp->ah_ctstimeout); + if (AH_PRIVATE(ah)->ah_diagreg != 0) + OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); + + AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */ + + HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__); + + return AH_TRUE; +bad: + if (*status) + *status = ecode; + return AH_FALSE; +#undef FAIL +#undef N +} + +/* + * Places the PHY and Radio chips into reset. A full reset + * must be called to leave this state. The PCI/MAC/PCU are + * not placed into reset as we must receive interrupt to + * re-enable the hardware. + */ +HAL_BOOL +ar5211PhyDisable(struct ath_hal *ah) +{ + return ar5211SetResetReg(ah, AR_RC_BB); +} + +/* + * Places all of hardware into reset + */ +HAL_BOOL +ar5211Disable(struct ath_hal *ah) +{ + if (!ar5211SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + /* + * Reset the HW - PCI must be reset after the rest of the + * device has been reset. + */ + if (!ar5211SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI)) + return AH_FALSE; + OS_DELAY(2100); /* 8245 @ 96Mhz hangs with 2000us. */ + + return AH_TRUE; +} + +/* + * Places the hardware into reset and then pulls it out of reset + * + * Only write the PLL if we're changing to or from CCK mode + * + * Attach calls with channelFlags = 0, as the coldreset should have + * us in the correct mode and we cannot check the hwchannel flags. + */ +HAL_BOOL +ar5211ChipReset(struct ath_hal *ah, uint16_t channelFlags) +{ + if (!ar5211SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + + /* Set CCK and Turbo modes correctly */ + switch (channelFlags & CHANNEL_ALL) { + case CHANNEL_2GHZ|CHANNEL_CCK: + case CHANNEL_2GHZ|CHANNEL_CCK|CHANNEL_TURBO: + OS_REG_WRITE(ah, AR_PHY_TURBO, 0); + OS_REG_WRITE(ah, AR5211_PHY_MODE, + AR5211_PHY_MODE_CCK | AR5211_PHY_MODE_RF2GHZ); + OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_44); + /* Wait for the PLL to settle */ + OS_DELAY(DELAY_PLL_SETTLE); + break; + case CHANNEL_2GHZ|CHANNEL_OFDM: + case CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO: + OS_REG_WRITE(ah, AR_PHY_TURBO, 0); + if (AH_PRIVATE(ah)->ah_devid == AR5211_DEVID) { + OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_40); + OS_DELAY(DELAY_PLL_SETTLE); + OS_REG_WRITE(ah, AR5211_PHY_MODE, + AR5211_PHY_MODE_OFDM | AR5211_PHY_MODE_RF2GHZ); + } + break; + case CHANNEL_A: + case CHANNEL_T: + if (channelFlags & CHANNEL_TURBO) { + OS_REG_WRITE(ah, AR_PHY_TURBO, + AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT); + } else { /* 5 GHZ OFDM Mode */ + OS_REG_WRITE(ah, AR_PHY_TURBO, 0); + } + if (AH_PRIVATE(ah)->ah_devid == AR5211_DEVID) { + OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_40); + OS_DELAY(DELAY_PLL_SETTLE); + OS_REG_WRITE(ah, AR5211_PHY_MODE, + AR5211_PHY_MODE_OFDM | AR5211_PHY_MODE_RF5GHZ); + } + break; + } + /* NB: else no flags set - must be attach calling - do nothing */ + + /* + * Reset the HW - PCI must be reset after the rest of the + * device has been reset + */ + if (!ar5211SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI)) + return AH_FALSE; + OS_DELAY(2100); /* 8245 @ 96Mhz hangs with 2000us. */ + + /* Bring out of sleep mode (AGAIN) */ + if (!ar5211SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + + /* Clear warm reset register */ + return ar5211SetResetReg(ah, 0); +} + +/* + * Recalibrate the lower PHY chips to account for temperature/environment + * changes. + */ +HAL_BOOL +ar5211PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan, u_int chainMask, + HAL_BOOL longCal, HAL_BOOL *isCalDone) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + HAL_CHANNEL_INTERNAL *ichan; + int32_t qCoff, qCoffDenom; + uint32_t data; + int32_t iqCorrMeas; + int32_t iCoff, iCoffDenom; + uint32_t powerMeasQ, powerMeasI; + + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->channel, chan->channelFlags); + return AH_FALSE; + } + /* IQ calibration in progress. Check to see if it has finished. */ + if (ahp->ah_bIQCalibration && + !(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_IQCAL)) { + /* IQ Calibration has finished. */ + ahp->ah_bIQCalibration = AH_FALSE; + + /* Read calibration results. */ + powerMeasI = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_I); + powerMeasQ = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_Q); + iqCorrMeas = OS_REG_READ(ah, AR_PHY_IQCAL_RES_IQ_CORR_MEAS); + + /* + * Prescale these values to remove 64-bit operation requirement at the loss + * of a little precision. + */ + iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; + qCoffDenom = powerMeasQ / 64; + + /* Protect against divide-by-0. */ + if (iCoffDenom != 0 && qCoffDenom != 0) { + iCoff = (-iqCorrMeas) / iCoffDenom; + /* IQCORR_Q_I_COFF is a signed 6 bit number */ + iCoff = iCoff & 0x3f; + + qCoff = ((int32_t)powerMeasI / qCoffDenom) - 64; + /* IQCORR_Q_Q_COFF is a signed 5 bit number */ + qCoff = qCoff & 0x1f; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, "powerMeasI = 0x%08x\n", + powerMeasI); + HALDEBUG(ah, HAL_DEBUG_PERCAL, "powerMeasQ = 0x%08x\n", + powerMeasQ); + HALDEBUG(ah, HAL_DEBUG_PERCAL, "iqCorrMeas = 0x%08x\n", + iqCorrMeas); + HALDEBUG(ah, HAL_DEBUG_PERCAL, "iCoff = %d\n", + iCoff); + HALDEBUG(ah, HAL_DEBUG_PERCAL, "qCoff = %d\n", + qCoff); + + /* Write IQ */ + data = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) | + AR_PHY_TIMING_CTRL4_IQCORR_ENABLE | + (((uint32_t)iCoff) << AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S) | + ((uint32_t)qCoff); + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4, data); + } + } + *isCalDone = !ahp->ah_bIQCalibration; + + if (longCal) { + /* Perform noise floor and set status */ + if (!ar5211IsNfGood(ah, ichan)) { + /* report up and clear internal state */ + chan->channelFlags |= CHANNEL_CW_INT; + ichan->channelFlags &= ~CHANNEL_CW_INT; + return AH_FALSE; + } + if (!ar5211CalNoiseFloor(ah, ichan)) { + /* + * Delay 5ms before retrying the noise floor + * just to make sure, as we are in an error + * condition here. + */ + OS_DELAY(5000); + if (!ar5211CalNoiseFloor(ah, ichan)) { + if (!IS_CHAN_CCK(chan)) + chan->channelFlags |= CHANNEL_CW_INT; + return AH_FALSE; + } + } + ar5211RequestRfgain(ah); + } + return AH_TRUE; +} + +HAL_BOOL +ar5211PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) +{ + return ar5211PerCalibrationN(ah, chan, 0x1, AH_TRUE, isIQdone); +} + +HAL_BOOL +ar5211ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + /* XXX */ + return AH_TRUE; +} + +/* + * Writes the given reset bit mask into the reset register + */ +static HAL_BOOL +ar5211SetResetReg(struct ath_hal *ah, uint32_t resetMask) +{ + uint32_t mask = resetMask ? resetMask : ~0; + HAL_BOOL rt; + + (void) OS_REG_READ(ah, AR_RXDP);/* flush any pending MMR writes */ + OS_REG_WRITE(ah, AR_RC, resetMask); + + /* need to wait at least 128 clocks when reseting PCI before read */ + OS_DELAY(15); + + resetMask &= AR_RC_MAC | AR_RC_BB; + mask &= AR_RC_MAC | AR_RC_BB; + rt = ath_hal_wait(ah, AR_RC, mask, resetMask); + if ((resetMask & AR_RC_MAC) == 0) { + if (isBigEndian()) { + /* + * Set CFG, little-endian for register + * and descriptor accesses. + */ + mask = INIT_CONFIG_STATUS | + AR_CFG_SWTD | AR_CFG_SWRD | AR_CFG_SWRG; + OS_REG_WRITE(ah, AR_CFG, LE_READ_4(&mask)); + } else + OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS); + } + return rt; +} + +/* + * Takes the MHz channel value and sets the Channel value + * + * ASSUMES: Writes enabled to analog bus before AGC is active + * or by disabling the AGC. + */ +static HAL_BOOL +ar5211SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + uint32_t refClk, reg32, data2111; + int16_t chan5111, chanIEEE; + + chanIEEE = ath_hal_mhz2ieee(ah, chan->channel, chan->channelFlags); + if (IS_CHAN_2GHZ(chan)) { + const CHAN_INFO_2GHZ* ci = + &chan2GHzData[chanIEEE + CI_2GHZ_INDEX_CORRECTION]; + + data2111 = ((ath_hal_reverseBits(ci->channelSelect, 8) & 0xff) + << 5) + | (ci->refClkSel << 4); + chan5111 = ci->channel5111; + } else { + data2111 = 0; + chan5111 = chanIEEE; + } + + /* Rest of the code is common for 5 GHz and 2.4 GHz. */ + if (chan5111 >= 145 || (chan5111 & 0x1)) { + reg32 = ath_hal_reverseBits(chan5111 - 24, 8) & 0xFF; + refClk = 1; + } else { + reg32 = ath_hal_reverseBits(((chan5111 - 24) / 2), 8) & 0xFF; + refClk = 0; + } + + reg32 = (reg32 << 2) | (refClk << 1) | (1 << 10) | 0x1; + OS_REG_WRITE(ah, AR_PHY(0x27), ((data2111 & 0xff) << 8) | (reg32 & 0xff)); + reg32 >>= 8; + OS_REG_WRITE(ah, AR_PHY(0x34), (data2111 & 0xff00) | (reg32 & 0xff)); + + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +} + +static int16_t +ar5211GetNoiseFloor(struct ath_hal *ah) +{ + int16_t nf; + + nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff; + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + return nf; +} + +/* + * Peform the noisefloor calibration for the length of time set + * in runTime (valid values 1 to 7) + * + * Returns: The NF value at the end of the given time (or 0 for failure) + */ +int16_t +ar5211RunNoiseFloor(struct ath_hal *ah, uint8_t runTime, int16_t startingNF) +{ + int i, searchTime; + + HALASSERT(runTime <= 7); + + /* Setup noise floor run time and starting value */ + OS_REG_WRITE(ah, AR_PHY(25), + (OS_REG_READ(ah, AR_PHY(25)) & ~0xFFF) | + ((runTime << 9) & 0xE00) | (startingNF & 0x1FF)); + /* Calibrate the noise floor */ + OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, + OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); + + /* Compute the required amount of searchTime needed to finish NF */ + if (runTime == 0) { + /* 8 search windows * 6.4us each */ + searchTime = 8 * 7; + } else { + /* 512 * runtime search windows * 6.4us each */ + searchTime = (runTime * 512) * 7; + } + + /* + * Do not read noise floor until it has been updated + * + * As a guesstimate - we may only get 1/60th the time on + * the air to see search windows in a heavily congested + * network (40 us every 2400 us of time) + */ + for (i = 0; i < 60; i++) { + if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0) + break; + OS_DELAY(searchTime); + } + if (i >= 60) { + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF with runTime %d failed to end on channel %d\n", + runTime, AH_PRIVATE(ah)->ah_curchan->channel); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + " PHY NF Reg state: 0x%x\n", + OS_REG_READ(ah, AR_PHY_AGC_CONTROL)); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + " PHY Active Reg state: 0x%x\n", + OS_REG_READ(ah, AR_PHY_ACTIVE)); + return 0; + } + + return ar5211GetNoiseFloor(ah); +} + +static HAL_BOOL +getNoiseFloorThresh(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, int16_t *nft) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) { + case CHANNEL_A: + *nft = ee->ee_noiseFloorThresh[0]; + break; + case CHANNEL_CCK|CHANNEL_2GHZ: + *nft = ee->ee_noiseFloorThresh[1]; + break; + case CHANNEL_OFDM|CHANNEL_2GHZ: + *nft = ee->ee_noiseFloorThresh[2]; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + return AH_TRUE; +} + +/* + * Read the NF and check it against the noise floor threshhold + * + * Returns: TRUE if the NF is good + */ +static HAL_BOOL +ar5211IsNfGood(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + int16_t nf, nfThresh; + + if (!getNoiseFloorThresh(ah, chan, &nfThresh)) + return AH_FALSE; + if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: NF did not complete in calibration window\n", __func__); + nf = ar5211GetNoiseFloor(ah); + if (nf > nfThresh) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: noise floor failed; detected %u, threshold %u\n", + __func__, nf, nfThresh); + /* + * NB: Don't discriminate 2.4 vs 5Ghz, if this + * happens it indicates a problem regardless + * of the band. + */ + chan->channelFlags |= CHANNEL_CW_INT; + } + chan->rawNoiseFloor = nf; + return (nf <= nfThresh); +} + +/* + * Peform the noisefloor calibration and check for any constant channel + * interference. + * + * NOTE: preAR5211 have a lengthy carrier wave detection process - hence + * it is if'ed for MKK regulatory domain only. + * + * Returns: TRUE for a successful noise floor calibration; else FALSE + */ +HAL_BOOL +ar5211CalNoiseFloor(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ +#define N(a) (sizeof (a) / sizeof (a[0])) + /* Check for Carrier Wave interference in MKK regulatory zone */ + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU && + ath_hal_getnfcheckrequired(ah, (HAL_CHANNEL *) chan)) { + static const uint8_t runtime[3] = { 0, 2, 7 }; + int16_t nf, nfThresh; + int i; + + if (!getNoiseFloorThresh(ah, chan, &nfThresh)) + return AH_FALSE; + /* + * Run a quick noise floor that will hopefully + * complete (decrease delay time). + */ + for (i = 0; i < N(runtime); i++) { + nf = ar5211RunNoiseFloor(ah, runtime[i], 0); + if (nf > nfThresh) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: run failed with %u > threshold %u " + "(runtime %u)\n", __func__, + nf, nfThresh, runtime[i]); + chan->rawNoiseFloor = 0; + } else + chan->rawNoiseFloor = nf; + } + return (i <= N(runtime)); + } else { + /* Calibrate the noise floor */ + OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, + OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | + AR_PHY_AGC_CONTROL_NF); + } + return AH_TRUE; +#undef N +} + +/* + * Adjust NF based on statistical values for 5GHz frequencies. + */ +int16_t +ar5211GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) +{ + static const struct { + uint16_t freqLow; + int16_t adjust; + } adjust5111[] = { + { 5790, 11 }, /* NB: ordered high -> low */ + { 5730, 10 }, + { 5690, 9 }, + { 5660, 8 }, + { 5610, 7 }, + { 5530, 5 }, + { 5450, 4 }, + { 5379, 2 }, + { 5209, 0 }, /* XXX? bogus but doesn't matter */ + { 0, 1 }, + }; + int i; + + for (i = 0; c->channel <= adjust5111[i].freqLow; i++) + ; + /* NB: placeholder for 5111's less severe requirement */ + return adjust5111[i].adjust / 3; +} + +/* + * Reads EEPROM header info from device structure and programs + * analog registers 6 and 7 + * + * REQUIRES: Access to the analog device + */ +static HAL_BOOL +ar5211SetRf6and7(struct ath_hal *ah, HAL_CHANNEL *chan) +{ +#define N(a) (sizeof (a) / sizeof (a[0])) + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ath_hal_5211 *ahp = AH5211(ah); + uint16_t rfXpdGain, rfPloSel, rfPwdXpd; + uint16_t tempOB, tempDB; + uint16_t freqIndex; + int i; + + freqIndex = (chan->channelFlags & CHANNEL_2GHZ) ? 2 : 1; + + /* + * TODO: This array mode correspondes with the index used + * during the read. + * For readability, this should be changed to an enum or #define + */ + switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) { + case CHANNEL_A: + if (chan->channel > 4000 && chan->channel < 5260) { + tempOB = ee->ee_ob1; + tempDB = ee->ee_db1; + } else if (chan->channel >= 5260 && chan->channel < 5500) { + tempOB = ee->ee_ob2; + tempDB = ee->ee_db2; + } else if (chan->channel >= 5500 && chan->channel < 5725) { + tempOB = ee->ee_ob3; + tempDB = ee->ee_db3; + } else if (chan->channel >= 5725) { + tempOB = ee->ee_ob4; + tempDB = ee->ee_db4; + } else { + /* XXX panic?? */ + tempOB = tempDB = 0; + } + + rfXpdGain = ee->ee_xgain[0]; + rfPloSel = ee->ee_xpd[0]; + rfPwdXpd = !ee->ee_xpd[0]; + + ar5211Rf6n7[5][freqIndex] = + (ar5211Rf6n7[5][freqIndex] & ~0x10000000) | + (ee->ee_cornerCal.pd84<< 28); + ar5211Rf6n7[6][freqIndex] = + (ar5211Rf6n7[6][freqIndex] & ~0x04000000) | + (ee->ee_cornerCal.pd90 << 26); + ar5211Rf6n7[21][freqIndex] = + (ar5211Rf6n7[21][freqIndex] & ~0x08) | + (ee->ee_cornerCal.gSel << 3); + break; + case CHANNEL_CCK|CHANNEL_2GHZ: + tempOB = ee->ee_obFor24; + tempDB = ee->ee_dbFor24; + rfXpdGain = ee->ee_xgain[1]; + rfPloSel = ee->ee_xpd[1]; + rfPwdXpd = !ee->ee_xpd[1]; + break; + case CHANNEL_OFDM|CHANNEL_2GHZ: + tempOB = ee->ee_obFor24g; + tempDB = ee->ee_dbFor24g; + rfXpdGain = ee->ee_xgain[2]; + rfPloSel = ee->ee_xpd[2]; + rfPwdXpd = !ee->ee_xpd[2]; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + + HALASSERT(1 <= tempOB && tempOB <= 5); + HALASSERT(1 <= tempDB && tempDB <= 5); + + /* Set rfXpdGain and rfPwdXpd */ + ar5211Rf6n7[11][freqIndex] = (ar5211Rf6n7[11][freqIndex] & ~0xC0) | + (((ath_hal_reverseBits(rfXpdGain, 4) << 7) | (rfPwdXpd << 6)) & 0xC0); + ar5211Rf6n7[12][freqIndex] = (ar5211Rf6n7[12][freqIndex] & ~0x07) | + ((ath_hal_reverseBits(rfXpdGain, 4) >> 1) & 0x07); + + /* Set OB */ + ar5211Rf6n7[12][freqIndex] = (ar5211Rf6n7[12][freqIndex] & ~0x80) | + ((ath_hal_reverseBits(tempOB, 3) << 7) & 0x80); + ar5211Rf6n7[13][freqIndex] = (ar5211Rf6n7[13][freqIndex] & ~0x03) | + ((ath_hal_reverseBits(tempOB, 3) >> 1) & 0x03); + + /* Set DB */ + ar5211Rf6n7[13][freqIndex] = (ar5211Rf6n7[13][freqIndex] & ~0x1C) | + ((ath_hal_reverseBits(tempDB, 3) << 2) & 0x1C); + + /* Set rfPloSel */ + ar5211Rf6n7[17][freqIndex] = (ar5211Rf6n7[17][freqIndex] & ~0x08) | + ((rfPloSel << 3) & 0x08); + + /* Write the Rf registers 6 & 7 */ + for (i = 0; i < N(ar5211Rf6n7); i++) + OS_REG_WRITE(ah, ar5211Rf6n7[i][0], ar5211Rf6n7[i][freqIndex]); + + /* Now that we have reprogrammed rfgain value, clear the flag. */ + ahp->ah_rfgainState = RFGAIN_INACTIVE; + + return AH_TRUE; +#undef N +} + +HAL_BOOL +ar5211SetAntennaSwitchInternal(struct ath_hal *ah, HAL_ANT_SETTING settings, + const HAL_CHANNEL *chan) +{ +#define ANT_SWITCH_TABLE1 0x9960 +#define ANT_SWITCH_TABLE2 0x9964 + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ath_hal_5211 *ahp = AH5211(ah); + uint32_t antSwitchA, antSwitchB; + int ix; + + switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) { + case CHANNEL_A: ix = 0; break; + case CHANNEL_B: ix = 1; break; + case CHANNEL_PUREG: ix = 2; break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + + antSwitchA = ee->ee_antennaControl[1][ix] + | (ee->ee_antennaControl[2][ix] << 6) + | (ee->ee_antennaControl[3][ix] << 12) + | (ee->ee_antennaControl[4][ix] << 18) + | (ee->ee_antennaControl[5][ix] << 24) + ; + antSwitchB = ee->ee_antennaControl[6][ix] + | (ee->ee_antennaControl[7][ix] << 6) + | (ee->ee_antennaControl[8][ix] << 12) + | (ee->ee_antennaControl[9][ix] << 18) + | (ee->ee_antennaControl[10][ix] << 24) + ; + /* + * For fixed antenna, give the same setting for both switch banks + */ + switch (settings) { + case HAL_ANT_FIXED_A: + antSwitchB = antSwitchA; + break; + case HAL_ANT_FIXED_B: + antSwitchA = antSwitchB; + break; + case HAL_ANT_VARIABLE: + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad antenna setting %u\n", + __func__, settings); + return AH_FALSE; + } + ahp->ah_diversityControl = settings; + + OS_REG_WRITE(ah, ANT_SWITCH_TABLE1, antSwitchA); + OS_REG_WRITE(ah, ANT_SWITCH_TABLE2, antSwitchB); + + return AH_TRUE; +#undef ANT_SWITCH_TABLE1 +#undef ANT_SWITCH_TABLE2 +} + +/* + * Reads EEPROM header info and programs the device for correct operation + * given the channel value + */ +static HAL_BOOL +ar5211SetBoardValues(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ath_hal_5211 *ahp = AH5211(ah); + int arrayMode, falseDectectBackoff; + + switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) { + case CHANNEL_A: + arrayMode = 0; + OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, + AR_PHY_FRAME_CTL_TX_CLIP, ee->ee_cornerCal.clip); + break; + case CHANNEL_CCK|CHANNEL_2GHZ: + arrayMode = 1; + break; + case CHANNEL_OFDM|CHANNEL_2GHZ: + arrayMode = 2; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + + /* Set the antenna register(s) correctly for the chip revision */ + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) { + OS_REG_WRITE(ah, AR_PHY(68), + (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFFFC) | 0x3); + } else { + OS_REG_WRITE(ah, AR_PHY(68), + (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFC06) | + (ee->ee_antennaControl[0][arrayMode] << 4) | 0x1); + + ar5211SetAntennaSwitchInternal(ah, + ahp->ah_diversityControl, chan); + + /* Set the Noise Floor Thresh on ar5211 devices */ + OS_REG_WRITE(ah, AR_PHY_BASE + (90 << 2), + (ee->ee_noiseFloorThresh[arrayMode] & 0x1FF) | (1<<9)); + } + OS_REG_WRITE(ah, AR_PHY_BASE + (17 << 2), + (OS_REG_READ(ah, AR_PHY_BASE + (17 << 2)) & 0xFFFFC07F) | + ((ee->ee_switchSettling[arrayMode] << 7) & 0x3F80)); + OS_REG_WRITE(ah, AR_PHY_BASE + (18 << 2), + (OS_REG_READ(ah, AR_PHY_BASE + (18 << 2)) & 0xFFFC0FFF) | + ((ee->ee_txrxAtten[arrayMode] << 12) & 0x3F000)); + OS_REG_WRITE(ah, AR_PHY_BASE + (20 << 2), + (OS_REG_READ(ah, AR_PHY_BASE + (20 << 2)) & 0xFFFF0000) | + ((ee->ee_pgaDesiredSize[arrayMode] << 8) & 0xFF00) | + (ee->ee_adcDesiredSize[arrayMode] & 0x00FF)); + OS_REG_WRITE(ah, AR_PHY_BASE + (13 << 2), + (ee->ee_txEndToXPAOff[arrayMode] << 24) | + (ee->ee_txEndToXPAOff[arrayMode] << 16) | + (ee->ee_txFrameToXPAOn[arrayMode] << 8) | + ee->ee_txFrameToXPAOn[arrayMode]); + OS_REG_WRITE(ah, AR_PHY_BASE + (10 << 2), + (OS_REG_READ(ah, AR_PHY_BASE + (10 << 2)) & 0xFFFF00FF) | + (ee->ee_txEndToXLNAOn[arrayMode] << 8)); + OS_REG_WRITE(ah, AR_PHY_BASE + (25 << 2), + (OS_REG_READ(ah, AR_PHY_BASE + (25 << 2)) & 0xFFF80FFF) | + ((ee->ee_thresh62[arrayMode] << 12) & 0x7F000)); + +#define NO_FALSE_DETECT_BACKOFF 2 +#define CB22_FALSE_DETECT_BACKOFF 6 + /* + * False detect backoff - suspected 32 MHz spur causes + * false detects in OFDM, causing Tx Hangs. Decrease + * weak signal sensitivity for this card. + */ + falseDectectBackoff = NO_FALSE_DETECT_BACKOFF; + if (AH_PRIVATE(ah)->ah_eeversion < AR_EEPROM_VER3_3) { + if (AH_PRIVATE(ah)->ah_subvendorid == 0x1022 && + IS_CHAN_OFDM(chan)) + falseDectectBackoff += CB22_FALSE_DETECT_BACKOFF; + } else { + uint32_t remainder = chan->channel % 32; + + if (remainder && (remainder < 10 || remainder > 22)) + falseDectectBackoff += ee->ee_falseDetectBackoff[arrayMode]; + } + OS_REG_WRITE(ah, 0x9924, + (OS_REG_READ(ah, 0x9924) & 0xFFFFFF01) + | ((falseDectectBackoff << 1) & 0xF7)); + + return AH_TRUE; +#undef NO_FALSE_DETECT_BACKOFF +#undef CB22_FALSE_DETECT_BACKOFF +} + +/* + * Set the limit on the overall output power. Used for dynamic + * transmit power control and the like. + * + * NOTE: The power is passed in is in units of 0.5 dBm. + */ +HAL_BOOL +ar5211SetTxPowerLimit(struct ath_hal *ah, uint32_t limit) +{ + + AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER); + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, limit); + return AH_TRUE; +} + +/* + * Sets the transmit power in the baseband for the given + * operating channel and mode. + */ +HAL_BOOL +ar5211SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + TRGT_POWER_INFO *pi; + RD_EDGES_POWER *rep; + PCDACS_EEPROM eepromPcdacs; + u_int nchan, cfgCtl; + int i; + + /* setup the pcdac struct to point to the correct info, based on mode */ + switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) { + case CHANNEL_A: + eepromPcdacs.numChannels = ee->ee_numChannels11a; + eepromPcdacs.pChannelList= ee->ee_channels11a; + eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11a; + nchan = ee->ee_numTargetPwr_11a; + pi = ee->ee_trgtPwr_11a; + break; + case CHANNEL_OFDM|CHANNEL_2GHZ: + eepromPcdacs.numChannels = ee->ee_numChannels2_4; + eepromPcdacs.pChannelList= ee->ee_channels11g; + eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11g; + nchan = ee->ee_numTargetPwr_11g; + pi = ee->ee_trgtPwr_11g; + break; + case CHANNEL_CCK|CHANNEL_2GHZ: + eepromPcdacs.numChannels = ee->ee_numChannels2_4; + eepromPcdacs.pChannelList= ee->ee_channels11b; + eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11b; + nchan = ee->ee_numTargetPwr_11b; + pi = ee->ee_trgtPwr_11b; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + + ar5211SetPowerTable(ah, &eepromPcdacs, chan->channel); + + rep = AH_NULL; + /* Match CTL to EEPROM value */ + cfgCtl = ath_hal_getctl(ah, chan); + for (i = 0; i < ee->ee_numCtls; i++) + if (ee->ee_ctl[i] != 0 && ee->ee_ctl[i] == cfgCtl) { + rep = &ee->ee_rdEdgesPower[i * NUM_EDGES]; + break; + } + ar5211SetRateTable(ah, rep, pi, nchan, chan); + + return AH_TRUE; +} + +/* + * Read the transmit power levels from the structures taken + * from EEPROM. Interpolate read transmit power values for + * this channel. Organize the transmit power values into a + * table for writing into the hardware. + */ +void +ar5211SetPowerTable(struct ath_hal *ah, PCDACS_EEPROM *pSrcStruct, uint16_t channel) +{ + static FULL_PCDAC_STRUCT pcdacStruct; + static uint16_t pcdacTable[PWR_TABLE_SIZE]; + + uint16_t i, j; + uint16_t *pPcdacValues; + int16_t *pScaledUpDbm; + int16_t minScaledPwr; + int16_t maxScaledPwr; + int16_t pwr; + uint16_t pcdacMin = 0; + uint16_t pcdacMax = 63; + uint16_t pcdacTableIndex; + uint16_t scaledPcdac; + uint32_t addr; + uint32_t temp32; + + OS_MEMZERO(&pcdacStruct, sizeof(FULL_PCDAC_STRUCT)); + OS_MEMZERO(pcdacTable, sizeof(uint16_t) * PWR_TABLE_SIZE); + pPcdacValues = pcdacStruct.PcdacValues; + pScaledUpDbm = pcdacStruct.PwrValues; + + /* Initialize the pcdacs to dBM structs pcdacs to be 1 to 63 */ + for (i = PCDAC_START, j = 0; i <= PCDAC_STOP; i+= PCDAC_STEP, j++) + pPcdacValues[j] = i; + + pcdacStruct.numPcdacValues = j; + pcdacStruct.pcdacMin = PCDAC_START; + pcdacStruct.pcdacMax = PCDAC_STOP; + + /* Fill out the power values for this channel */ + for (j = 0; j < pcdacStruct.numPcdacValues; j++ ) + pScaledUpDbm[j] = ar5211GetScaledPower(channel, pPcdacValues[j], pSrcStruct); + + /* Now scale the pcdac values to fit in the 64 entry power table */ + minScaledPwr = pScaledUpDbm[0]; + maxScaledPwr = pScaledUpDbm[pcdacStruct.numPcdacValues - 1]; + + /* find minimum and make monotonic */ + for (j = 0; j < pcdacStruct.numPcdacValues; j++) { + if (minScaledPwr >= pScaledUpDbm[j]) { + minScaledPwr = pScaledUpDbm[j]; + pcdacMin = j; + } + /* + * Make the full_hsh monotonically increasing otherwise + * interpolation algorithm will get fooled gotta start + * working from the top, hence i = 63 - j. + */ + i = (uint16_t)(pcdacStruct.numPcdacValues - 1 - j); + if (i == 0) + break; + if (pScaledUpDbm[i-1] > pScaledUpDbm[i]) { + /* + * It could be a glitch, so make the power for + * this pcdac the same as the power from the + * next highest pcdac. + */ + pScaledUpDbm[i - 1] = pScaledUpDbm[i]; + } + } + + for (j = 0; j < pcdacStruct.numPcdacValues; j++) + if (maxScaledPwr < pScaledUpDbm[j]) { + maxScaledPwr = pScaledUpDbm[j]; + pcdacMax = j; + } + + /* Find the first power level with a pcdac */ + pwr = (uint16_t)(PWR_STEP * ((minScaledPwr - PWR_MIN + PWR_STEP / 2) / PWR_STEP) + PWR_MIN); + + /* Write all the first pcdac entries based off the pcdacMin */ + pcdacTableIndex = 0; + for (i = 0; i < (2 * (pwr - PWR_MIN) / EEP_SCALE + 1); i++) + pcdacTable[pcdacTableIndex++] = pcdacMin; + + i = 0; + while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1]) { + pwr += PWR_STEP; + /* stop if dbM > max_power_possible */ + while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1] && + (pwr - pScaledUpDbm[i])*(pwr - pScaledUpDbm[i+1]) > 0) + i++; + /* scale by 2 and add 1 to enable round up or down as needed */ + scaledPcdac = (uint16_t)(ar5211GetInterpolatedValue(pwr, + pScaledUpDbm[i], pScaledUpDbm[i+1], + (uint16_t)(pPcdacValues[i] * 2), + (uint16_t)(pPcdacValues[i+1] * 2), 0) + 1); + + pcdacTable[pcdacTableIndex] = scaledPcdac / 2; + if (pcdacTable[pcdacTableIndex] > pcdacMax) + pcdacTable[pcdacTableIndex] = pcdacMax; + pcdacTableIndex++; + } + + /* Write all the last pcdac entries based off the last valid pcdac */ + while (pcdacTableIndex < PWR_TABLE_SIZE) { + pcdacTable[pcdacTableIndex] = pcdacTable[pcdacTableIndex - 1]; + pcdacTableIndex++; + } + + /* Finally, write the power values into the baseband power table */ + addr = AR_PHY_BASE + (608 << 2); + for (i = 0; i < 32; i++) { + temp32 = 0xffff & ((pcdacTable[2 * i + 1] << 8) | 0xff); + temp32 = (temp32 << 16) | (0xffff & ((pcdacTable[2 * i] << 8) | 0xff)); + OS_REG_WRITE(ah, addr, temp32); + addr += 4; + } + +} + +/* + * Set the transmit power in the baseband for the given + * operating channel and mode. + */ +void +ar5211SetRateTable(struct ath_hal *ah, RD_EDGES_POWER *pRdEdgesPower, + TRGT_POWER_INFO *pPowerInfo, uint16_t numChannels, + HAL_CHANNEL *chan) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ath_hal_5211 *ahp = AH5211(ah); + static uint16_t ratesArray[NUM_RATES]; + static const uint16_t tpcScaleReductionTable[5] = + { 0, 3, 6, 9, MAX_RATE_POWER }; + + uint16_t *pRatesPower; + uint16_t lowerChannel, lowerIndex=0, lowerPower=0; + uint16_t upperChannel, upperIndex=0, upperPower=0; + uint16_t twiceMaxEdgePower=63; + uint16_t twicePower = 0; + uint16_t i, numEdges; + uint16_t tempChannelList[NUM_EDGES]; /* temp array for holding edge channels */ + uint16_t twiceMaxRDPower; + int16_t scaledPower = 0; /* for gcc -O2 */ + uint16_t mask = 0x3f; + HAL_BOOL paPreDEnable = 0; + int8_t twiceAntennaGain, twiceAntennaReduction = 0; + + pRatesPower = ratesArray; + twiceMaxRDPower = chan->maxRegTxPower * 2; + + if (IS_CHAN_5GHZ(chan)) { + twiceAntennaGain = ee->ee_antennaGainMax[0]; + } else { + twiceAntennaGain = ee->ee_antennaGainMax[1]; + } + + twiceAntennaReduction = ath_hal_getantennareduction(ah, chan, twiceAntennaGain); + + if (pRdEdgesPower) { + /* Get the edge power */ + for (i = 0; i < NUM_EDGES; i++) { + if (pRdEdgesPower[i].rdEdge == 0) + break; + tempChannelList[i] = pRdEdgesPower[i].rdEdge; + } + numEdges = i; + + ar5211GetLowerUpperValues(chan->channel, tempChannelList, + numEdges, &lowerChannel, &upperChannel); + /* Get the index for this channel */ + for (i = 0; i < numEdges; i++) + if (lowerChannel == tempChannelList[i]) + break; + HALASSERT(i != numEdges); + + if ((lowerChannel == upperChannel && + lowerChannel == chan->channel) || + pRdEdgesPower[i].flag) { + twiceMaxEdgePower = pRdEdgesPower[i].twice_rdEdgePower; + HALASSERT(twiceMaxEdgePower > 0); + } + } + + /* extrapolate the power values for the test Groups */ + for (i = 0; i < numChannels; i++) + tempChannelList[i] = pPowerInfo[i].testChannel; + + ar5211GetLowerUpperValues(chan->channel, tempChannelList, + numChannels, &lowerChannel, &upperChannel); + + /* get the index for the channel */ + for (i = 0; i < numChannels; i++) { + if (lowerChannel == tempChannelList[i]) + lowerIndex = i; + if (upperChannel == tempChannelList[i]) { + upperIndex = i; + break; + } + } + + for (i = 0; i < NUM_RATES; i++) { + if (IS_CHAN_OFDM(chan)) { + /* power for rates 6,9,12,18,24 is all the same */ + if (i < 5) { + lowerPower = pPowerInfo[lowerIndex].twicePwr6_24; + upperPower = pPowerInfo[upperIndex].twicePwr6_24; + } else if (i == 5) { + lowerPower = pPowerInfo[lowerIndex].twicePwr36; + upperPower = pPowerInfo[upperIndex].twicePwr36; + } else if (i == 6) { + lowerPower = pPowerInfo[lowerIndex].twicePwr48; + upperPower = pPowerInfo[upperIndex].twicePwr48; + } else if (i == 7) { + lowerPower = pPowerInfo[lowerIndex].twicePwr54; + upperPower = pPowerInfo[upperIndex].twicePwr54; + } + } else { + switch (i) { + case 0: + case 1: + lowerPower = pPowerInfo[lowerIndex].twicePwr6_24; + upperPower = pPowerInfo[upperIndex].twicePwr6_24; + break; + case 2: + case 3: + lowerPower = pPowerInfo[lowerIndex].twicePwr36; + upperPower = pPowerInfo[upperIndex].twicePwr36; + break; + case 4: + case 5: + lowerPower = pPowerInfo[lowerIndex].twicePwr48; + upperPower = pPowerInfo[upperIndex].twicePwr48; + break; + case 6: + case 7: + lowerPower = pPowerInfo[lowerIndex].twicePwr54; + upperPower = pPowerInfo[upperIndex].twicePwr54; + break; + } + } + + twicePower = ar5211GetInterpolatedValue(chan->channel, + lowerChannel, upperChannel, lowerPower, upperPower, 0); + + /* Reduce power by band edge restrictions */ + twicePower = AH_MIN(twicePower, twiceMaxEdgePower); + + /* + * If turbo is set, reduce power to keep power + * consumption under 2 Watts. Note that we always do + * this unless specially configured. Then we limit + * power only for non-AP operation. + */ + if (IS_CHAN_TURBO(chan) && + AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1 +#ifdef AH_ENABLE_AP_SUPPORT + && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP +#endif + ) { + twicePower = AH_MIN(twicePower, ee->ee_turbo2WMaxPower5); + } + + /* Reduce power by max regulatory domain allowed restrictions */ + pRatesPower[i] = AH_MIN(twicePower, twiceMaxRDPower - twiceAntennaReduction); + + /* Use 6 Mb power level for transmit power scaling reduction */ + /* We don't want to reduce higher rates if its not needed */ + if (i == 0) { + scaledPower = pRatesPower[0] - + (tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale] * 2); + if (scaledPower < 1) + scaledPower = 1; + } + + pRatesPower[i] = AH_MIN(pRatesPower[i], scaledPower); + } + + /* Record txPower at Rate 6 for info gathering */ + ahp->ah_tx6PowerInHalfDbm = pRatesPower[0]; + +#ifdef AH_DEBUG + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s: final output power setting %d MHz:\n", + __func__, chan->channel); + HALDEBUG(ah, HAL_DEBUG_RESET, + "6 Mb %d dBm, MaxRD: %d dBm, MaxEdge %d dBm\n", + scaledPower / 2, twiceMaxRDPower / 2, twiceMaxEdgePower / 2); + HALDEBUG(ah, HAL_DEBUG_RESET, "TPC Scale %d dBm - Ant Red %d dBm\n", + tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale] * 2, + twiceAntennaReduction / 2); + if (IS_CHAN_TURBO(chan) && + AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1) + HALDEBUG(ah, HAL_DEBUG_RESET, "Max Turbo %d dBm\n", + ee->ee_turbo2WMaxPower5); + HALDEBUG(ah, HAL_DEBUG_RESET, + " %2d | %2d | %2d | %2d | %2d | %2d | %2d | %2d dBm\n", + pRatesPower[0] / 2, pRatesPower[1] / 2, pRatesPower[2] / 2, + pRatesPower[3] / 2, pRatesPower[4] / 2, pRatesPower[5] / 2, + pRatesPower[6] / 2, pRatesPower[7] / 2); +#endif /* AH_DEBUG */ + + /* Write the power table into the hardware */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, + ((paPreDEnable & 1)<< 30) | ((pRatesPower[3] & mask) << 24) | + ((paPreDEnable & 1)<< 22) | ((pRatesPower[2] & mask) << 16) | + ((paPreDEnable & 1)<< 14) | ((pRatesPower[1] & mask) << 8) | + ((paPreDEnable & 1)<< 6 ) | (pRatesPower[0] & mask)); + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, + ((paPreDEnable & 1)<< 30) | ((pRatesPower[7] & mask) << 24) | + ((paPreDEnable & 1)<< 22) | ((pRatesPower[6] & mask) << 16) | + ((paPreDEnable & 1)<< 14) | ((pRatesPower[5] & mask) << 8) | + ((paPreDEnable & 1)<< 6 ) | (pRatesPower[4] & mask)); + + /* set max power to the power value at rate 6 */ + ar5211SetTxPowerLimit(ah, pRatesPower[0]); + + AH_PRIVATE(ah)->ah_maxPowerLevel = pRatesPower[0]; +} + +/* + * Get or interpolate the pcdac value from the calibrated data + */ +uint16_t +ar5211GetScaledPower(uint16_t channel, uint16_t pcdacValue, const PCDACS_EEPROM *pSrcStruct) +{ + uint16_t powerValue; + uint16_t lFreq, rFreq; /* left and right frequency values */ + uint16_t llPcdac, ulPcdac; /* lower and upper left pcdac values */ + uint16_t lrPcdac, urPcdac; /* lower and upper right pcdac values */ + uint16_t lPwr, uPwr; /* lower and upper temp pwr values */ + uint16_t lScaledPwr, rScaledPwr; /* left and right scaled power */ + + if (ar5211FindValueInList(channel, pcdacValue, pSrcStruct, &powerValue)) + /* value was copied from srcStruct */ + return powerValue; + + ar5211GetLowerUpperValues(channel, pSrcStruct->pChannelList, + pSrcStruct->numChannels, &lFreq, &rFreq); + ar5211GetLowerUpperPcdacs(pcdacValue, lFreq, pSrcStruct, + &llPcdac, &ulPcdac); + ar5211GetLowerUpperPcdacs(pcdacValue, rFreq, pSrcStruct, + &lrPcdac, &urPcdac); + + /* get the power index for the pcdac value */ + ar5211FindValueInList(lFreq, llPcdac, pSrcStruct, &lPwr); + ar5211FindValueInList(lFreq, ulPcdac, pSrcStruct, &uPwr); + lScaledPwr = ar5211GetInterpolatedValue(pcdacValue, + llPcdac, ulPcdac, lPwr, uPwr, 0); + + ar5211FindValueInList(rFreq, lrPcdac, pSrcStruct, &lPwr); + ar5211FindValueInList(rFreq, urPcdac, pSrcStruct, &uPwr); + rScaledPwr = ar5211GetInterpolatedValue(pcdacValue, + lrPcdac, urPcdac, lPwr, uPwr, 0); + + return ar5211GetInterpolatedValue(channel, lFreq, rFreq, + lScaledPwr, rScaledPwr, 0); +} + +/* + * Find the value from the calibrated source data struct + */ +HAL_BOOL +ar5211FindValueInList(uint16_t channel, uint16_t pcdacValue, + const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue) +{ + const DATA_PER_CHANNEL *pChannelData; + const uint16_t *pPcdac; + uint16_t i, j; + + pChannelData = pSrcStruct->pDataPerChannel; + for (i = 0; i < pSrcStruct->numChannels; i++ ) { + if (pChannelData->channelValue == channel) { + pPcdac = pChannelData->PcdacValues; + for (j = 0; j < pChannelData->numPcdacValues; j++ ) { + if (*pPcdac == pcdacValue) { + *powerValue = pChannelData->PwrValues[j]; + return AH_TRUE; + } + pPcdac++; + } + } + pChannelData++; + } + return AH_FALSE; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +uint16_t +ar5211GetInterpolatedValue(uint16_t target, + uint16_t srcLeft, uint16_t srcRight, + uint16_t targetLeft, uint16_t targetRight, + HAL_BOOL scaleUp) +{ + uint16_t rv; + int16_t lRatio; + uint16_t scaleValue = EEP_SCALE; + + /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */ + if ((targetLeft * targetRight) == 0) + return 0; + if (scaleUp) + scaleValue = 1; + + if (srcRight != srcLeft) { + /* + * Note the ratio always need to be scaled, + * since it will be a fraction. + */ + lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft); + if (lRatio < 0) { + /* Return as Left target if value would be negative */ + rv = targetLeft * (scaleUp ? EEP_SCALE : 1); + } else if (lRatio > EEP_SCALE) { + /* Return as Right target if Ratio is greater than 100% (SCALE) */ + rv = targetRight * (scaleUp ? EEP_SCALE : 1); + } else { + rv = (lRatio * targetRight + (EEP_SCALE - lRatio) * + targetLeft) / scaleValue; + } + } else { + rv = targetLeft; + if (scaleUp) + rv *= EEP_SCALE; + } + return rv; +} + +/* + * Look for value being within 0.1 of the search values + * however, NDIS can't do float calculations, so multiply everything + * up by EEP_SCALE so can do integer arithmatic + * + * INPUT value -value to search for + * INPUT pList -ptr to the list to search + * INPUT listSize -number of entries in list + * OUTPUT pLowerValue -return the lower value + * OUTPUT pUpperValue -return the upper value + */ +void +ar5211GetLowerUpperValues(uint16_t value, + const uint16_t *pList, uint16_t listSize, + uint16_t *pLowerValue, uint16_t *pUpperValue) +{ + const uint16_t listEndValue = *(pList + listSize - 1); + uint32_t target = value * EEP_SCALE; + int i; + + /* + * See if value is lower than the first value in the list + * if so return first value + */ + if (target < (uint32_t)(*pList * EEP_SCALE - EEP_DELTA)) { + *pLowerValue = *pList; + *pUpperValue = *pList; + return; + } + + /* + * See if value is greater than last value in list + * if so return last value + */ + if (target > (uint32_t)(listEndValue * EEP_SCALE + EEP_DELTA)) { + *pLowerValue = listEndValue; + *pUpperValue = listEndValue; + return; + } + + /* look for value being near or between 2 values in list */ + for (i = 0; i < listSize; i++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (abs(pList[i] * EEP_SCALE - (int32_t) target) < EEP_DELTA) { + *pLowerValue = pList[i]; + *pUpperValue = pList[i]; + return; + } + + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < (uint32_t)(pList[i + 1] * EEP_SCALE - EEP_DELTA)) { + *pLowerValue = pList[i]; + *pUpperValue = pList[i + 1]; + return; + } + } +} + +/* + * Get the upper and lower pcdac given the channel and the pcdac + * used in the search + */ +void +ar5211GetLowerUpperPcdacs(uint16_t pcdac, uint16_t channel, + const PCDACS_EEPROM *pSrcStruct, + uint16_t *pLowerPcdac, uint16_t *pUpperPcdac) +{ + const DATA_PER_CHANNEL *pChannelData; + int i; + + /* Find the channel information */ + pChannelData = pSrcStruct->pDataPerChannel; + for (i = 0; i < pSrcStruct->numChannels; i++) { + if (pChannelData->channelValue == channel) + break; + pChannelData++; + } + ar5211GetLowerUpperValues(pcdac, pChannelData->PcdacValues, + pChannelData->numPcdacValues, pLowerPcdac, pUpperPcdac); +} + +#define DYN_ADJ_UP_MARGIN 15 +#define DYN_ADJ_LO_MARGIN 20 + +static const GAIN_OPTIMIZATION_LADDER gainLadder = { + 9, /* numStepsInLadder */ + 4, /* defaultStepNum */ + { { {4, 1, 1, 1}, 6, "FG8"}, + { {4, 0, 1, 1}, 4, "FG7"}, + { {3, 1, 1, 1}, 3, "FG6"}, + { {4, 0, 0, 1}, 1, "FG5"}, + { {4, 1, 1, 0}, 0, "FG4"}, /* noJack */ + { {4, 0, 1, 0}, -2, "FG3"}, /* halfJack */ + { {3, 1, 1, 0}, -3, "FG2"}, /* clip3 */ + { {4, 0, 0, 0}, -4, "FG1"}, /* noJack */ + { {2, 1, 1, 0}, -6, "FG0"} /* clip2 */ + } +}; + +/* + * Initialize the gain structure to good values + */ +void +ar5211InitializeGainValues(struct ath_hal *ah) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + GAIN_VALUES *gv = &ahp->ah_gainValues; + + /* initialize gain optimization values */ + gv->currStepNum = gainLadder.defaultStepNum; + gv->currStep = &gainLadder.optStep[gainLadder.defaultStepNum]; + gv->active = AH_TRUE; + gv->loTrig = 20; + gv->hiTrig = 35; +} + +static HAL_BOOL +ar5211InvalidGainReadback(struct ath_hal *ah, GAIN_VALUES *gv) +{ + HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan; + uint32_t gStep, g; + uint32_t L1, L2, L3, L4; + + if (IS_CHAN_CCK(chan)) { + gStep = 0x18; + L1 = 0; + L2 = gStep + 4; + L3 = 0x40; + L4 = L3 + 50; + + gv->loTrig = L1; + gv->hiTrig = L4+5; + } else { + gStep = 0x3f; + L1 = 0; + L2 = 50; + L3 = L1; + L4 = L3 + 50; + + gv->loTrig = L1 + DYN_ADJ_LO_MARGIN; + gv->hiTrig = L4 - DYN_ADJ_UP_MARGIN; + } + g = gv->currGain; + + return !((g >= L1 && g<= L2) || (g >= L3 && g <= L4)); +} + +/* + * Enable the probe gain check on the next packet + */ +static void +ar5211RequestRfgain(struct ath_hal *ah) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + /* Enable the gain readback probe */ + OS_REG_WRITE(ah, AR_PHY_PAPD_PROBE, + SM(ahp->ah_tx6PowerInHalfDbm, AR_PHY_PAPD_PROBE_POWERTX) + | AR_PHY_PAPD_PROBE_NEXT_TX); + + ahp->ah_rfgainState = HAL_RFGAIN_READ_REQUESTED; +} + +/* + * Exported call to check for a recent gain reading and return + * the current state of the thermal calibration gain engine. + */ +HAL_RFGAIN +ar5211GetRfgain(struct ath_hal *ah) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + GAIN_VALUES *gv = &ahp->ah_gainValues; + uint32_t rddata; + + if (!gv->active) + return HAL_RFGAIN_INACTIVE; + + if (ahp->ah_rfgainState == HAL_RFGAIN_READ_REQUESTED) { + /* Caller had asked to setup a new reading. Check it. */ + rddata = OS_REG_READ(ah, AR_PHY_PAPD_PROBE); + + if ((rddata & AR_PHY_PAPD_PROBE_NEXT_TX) == 0) { + /* bit got cleared, we have a new reading. */ + gv->currGain = rddata >> AR_PHY_PAPD_PROBE_GAINF_S; + /* inactive by default */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + if (!ar5211InvalidGainReadback(ah, gv) && + ar5211IsGainAdjustNeeded(ah, gv) && + ar5211AdjustGain(ah, gv) > 0) { + /* + * Change needed. Copy ladder info + * into eeprom info. + */ + ar5211SetRfgain(ah, gv); + ahp->ah_rfgainState = HAL_RFGAIN_NEED_CHANGE; + } + } + } + return ahp->ah_rfgainState; +} + +/* + * Check to see if our readback gain level sits within the linear + * region of our current variable attenuation window + */ +static HAL_BOOL +ar5211IsGainAdjustNeeded(struct ath_hal *ah, const GAIN_VALUES *gv) +{ + return (gv->currGain <= gv->loTrig || gv->currGain >= gv->hiTrig); +} + +/* + * Move the rabbit ears in the correct direction. + */ +static int32_t +ar5211AdjustGain(struct ath_hal *ah, GAIN_VALUES *gv) +{ + /* return > 0 for valid adjustments. */ + if (!gv->active) + return -1; + + gv->currStep = &gainLadder.optStep[gv->currStepNum]; + if (gv->currGain >= gv->hiTrig) { + if (gv->currStepNum == 0) { + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Max gain limit.\n", __func__); + return -1; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Adding gain: currG=%d [%s] --> ", + __func__, gv->currGain, gv->currStep->stepName); + gv->targetGain = gv->currGain; + while (gv->targetGain >= gv->hiTrig && gv->currStepNum > 0) { + gv->targetGain -= 2 * (gainLadder.optStep[--(gv->currStepNum)].stepGain - + gv->currStep->stepGain); + gv->currStep = &gainLadder.optStep[gv->currStepNum]; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n", + gv->targetGain, gv->currStep->stepName); + return 1; + } + if (gv->currGain <= gv->loTrig) { + if (gv->currStepNum == gainLadder.numStepsInLadder-1) { + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Min gain limit.\n", __func__); + return -2; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Deducting gain: currG=%d [%s] --> ", + __func__, gv->currGain, gv->currStep->stepName); + gv->targetGain = gv->currGain; + while (gv->targetGain <= gv->loTrig && + gv->currStepNum < (gainLadder.numStepsInLadder - 1)) { + gv->targetGain -= 2 * + (gainLadder.optStep[++(gv->currStepNum)].stepGain - gv->currStep->stepGain); + gv->currStep = &gainLadder.optStep[gv->currStepNum]; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n", + gv->targetGain, gv->currStep->stepName); + return 2; + } + return 0; /* caller didn't call needAdjGain first */ +} + +/* + * Adjust the 5GHz EEPROM information with the desired calibration values. + */ +static void +ar5211SetRfgain(struct ath_hal *ah, const GAIN_VALUES *gv) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + + if (!gv->active) + return; + ee->ee_cornerCal.clip = gv->currStep->paramVal[0]; /* bb_tx_clip */ + ee->ee_cornerCal.pd90 = gv->currStep->paramVal[1]; /* rf_pwd_90 */ + ee->ee_cornerCal.pd84 = gv->currStep->paramVal[2]; /* rf_pwd_84 */ + ee->ee_cornerCal.gSel = gv->currStep->paramVal[3]; /* rf_rfgainsel */ +} + +static void +ar5211SetOperatingMode(struct ath_hal *ah, int opmode) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + uint32_t val; + + val = OS_REG_READ(ah, AR_STA_ID1) & 0xffff; + switch (opmode) { + case HAL_M_HOSTAP: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_STA_AP + | AR_STA_ID1_RTS_USE_DEF + | ahp->ah_staId1Defaults); + break; + case HAL_M_IBSS: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_ADHOC + | AR_STA_ID1_DESC_ANTENNA + | ahp->ah_staId1Defaults); + break; + case HAL_M_STA: + case HAL_M_MONITOR: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_DEFAULT_ANTENNA + | ahp->ah_staId1Defaults); + break; + } +} + +void +ar5211SetPCUConfig(struct ath_hal *ah) +{ + ar5211SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode); +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_xmit.c b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_xmit.c new file mode 100644 index 0000000000..7f75bd06da --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211_xmit.c @@ -0,0 +1,662 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5211_xmit.c,v 1.6 2008/11/10 04:08:03 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" +#include "ar5211/ar5211desc.h" + +/* + * Update Tx FIFO trigger level. + * + * Set bIncTrigLevel to TRUE to increase the trigger level. + * Set bIncTrigLevel to FALSE to decrease the trigger level. + * + * Returns TRUE if the trigger level was updated + */ +HAL_BOOL +ar5211UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel) +{ + uint32_t curTrigLevel, txcfg; + HAL_INT ints = ar5211GetInterrupts(ah); + + /* + * Disable chip interrupts. This is because halUpdateTxTrigLevel + * is called from both ISR and non-ISR contexts. + */ + ar5211SetInterrupts(ah, ints &~ HAL_INT_GLOBAL); + txcfg = OS_REG_READ(ah, AR_TXCFG); + curTrigLevel = (txcfg & AR_TXCFG_FTRIG_M) >> AR_TXCFG_FTRIG_S; + if (bIncTrigLevel){ + /* increase the trigger level */ + curTrigLevel = curTrigLevel + + ((MAX_TX_FIFO_THRESHOLD - curTrigLevel) / 2); + } else { + /* decrease the trigger level if not already at the minimum */ + if (curTrigLevel > MIN_TX_FIFO_THRESHOLD) { + /* decrease the trigger level */ + curTrigLevel--; + } else { + /* no update to the trigger level */ + /* re-enable chip interrupts */ + ar5211SetInterrupts(ah, ints); + return AH_FALSE; + } + } + /* Update the trigger level */ + OS_REG_WRITE(ah, AR_TXCFG, (txcfg &~ AR_TXCFG_FTRIG_M) | + ((curTrigLevel << AR_TXCFG_FTRIG_S) & AR_TXCFG_FTRIG_M)); + /* re-enable chip interrupts */ + ar5211SetInterrupts(ah, ints); + return AH_TRUE; +} + +/* + * Set the properties of the tx queue with the parameters + * from qInfo. The queue must previously have been setup + * with a call to ar5211SetupTxQueue. + */ +HAL_BOOL +ar5211SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], qInfo); +} + +/* + * Return the properties for the specified tx queue. + */ +HAL_BOOL +ar5211GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + return ath_hal_getTxQProps(ah, qInfo, &ahp->ah_txq[q]); +} + +/* + * Allocate and initialize a tx DCU/QCU combination. + */ +int +ar5211SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + HAL_TX_QUEUE_INFO *qi; + int q; + + switch (type) { + case HAL_TX_QUEUE_BEACON: + q = 9; + break; + case HAL_TX_QUEUE_CAB: + q = 8; + break; + case HAL_TX_QUEUE_DATA: + q = 0; + if (ahp->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE) + return q; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad tx queue type %u\n", + __func__, type); + return -1; + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + + qi = &ahp->ah_txq[q]; + if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n", + __func__, q); + return -1; + } + OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO)); + qi->tqi_type = type; + if (qInfo == AH_NULL) { + /* by default enable OK+ERR+DESC+URN interrupts */ + qi->tqi_qflags = + HAL_TXQ_TXOKINT_ENABLE + | HAL_TXQ_TXERRINT_ENABLE + | HAL_TXQ_TXDESCINT_ENABLE + | HAL_TXQ_TXURNINT_ENABLE + ; + qi->tqi_aifs = INIT_AIFS; + qi->tqi_cwmin = HAL_TXQ_USEDEFAULT; /* NB: do at reset */ + qi->tqi_cwmax = INIT_CWMAX; + qi->tqi_shretry = INIT_SH_RETRY; + qi->tqi_lgretry = INIT_LG_RETRY; + } else + (void) ar5211SetTxQueueProps(ah, q, qInfo); + return q; +} + +/* + * Update the h/w interrupt registers to reflect a tx q's configuration. + */ +static void +setTxQInterrupts(struct ath_hal *ah, HAL_TX_QUEUE_INFO *qi) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", __func__ + , ahp->ah_txOkInterruptMask + , ahp->ah_txErrInterruptMask + , ahp->ah_txDescInterruptMask + , ahp->ah_txEolInterruptMask + , ahp->ah_txUrnInterruptMask + ); + + OS_REG_WRITE(ah, AR_IMR_S0, + SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK) + | SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC) + ); + OS_REG_WRITE(ah, AR_IMR_S1, + SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR) + | SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL) + ); + OS_REG_RMW_FIELD(ah, AR_IMR_S2, + AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask); +} + + +/* + * Free a tx DCU/QCU combination. + */ +HAL_BOOL +ar5211ReleaseTxQueue(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + HAL_TX_QUEUE_INFO *qi; + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + return AH_FALSE; + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: release queue %u\n", __func__, q); + + qi->tqi_type = HAL_TX_QUEUE_INACTIVE; + ahp->ah_txOkInterruptMask &= ~(1 << q); + ahp->ah_txErrInterruptMask &= ~(1 << q); + ahp->ah_txDescInterruptMask &= ~(1 << q); + ahp->ah_txEolInterruptMask &= ~(1 << q); + ahp->ah_txUrnInterruptMask &= ~(1 << q); + setTxQInterrupts(ah, qi); + + return AH_TRUE; +} + +/* + * Set the retry, aifs, cwmin/max, readyTime regs for specified queue + */ +HAL_BOOL +ar5211ResetTxQueue(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan; + HAL_TX_QUEUE_INFO *qi; + uint32_t cwMin, chanCwMin, value; + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + return AH_TRUE; /* XXX??? */ + } + + if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) { + /* + * Select cwmin according to channel type. + * NB: chan can be NULL during attach + */ + if (chan && IS_CHAN_B(chan)) + chanCwMin = INIT_CWMIN_11B; + else + chanCwMin = INIT_CWMIN; + /* make sure that the CWmin is of the form (2^n - 1) */ + for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1) + ; + } else + cwMin = qi->tqi_cwmin; + + /* set cwMin/Max and AIFS values */ + OS_REG_WRITE(ah, AR_DLCL_IFS(q), + SM(cwMin, AR_D_LCL_IFS_CWMIN) + | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) + | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); + + /* Set retry limit values */ + OS_REG_WRITE(ah, AR_DRETRY_LIMIT(q), + SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) + | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) + | SM(qi->tqi_lgretry, AR_D_RETRY_LIMIT_FR_LG) + | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH) + ); + + /* enable early termination on the QCU */ + OS_REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); + + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) { + /* Configure DCU to use the global sequence count */ + OS_REG_WRITE(ah, AR_DMISC(q), AR5311_D_MISC_SEQ_NUM_CONTROL); + } + /* multiqueue support */ + if (qi->tqi_cbrPeriod) { + OS_REG_WRITE(ah, AR_QCBRCFG(q), + SM(qi->tqi_cbrPeriod,AR_Q_CBRCFG_CBR_INTERVAL) + | SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_CBR_OVF_THRESH)); + OS_REG_WRITE(ah, AR_QMISC(q), + OS_REG_READ(ah, AR_QMISC(q)) | + AR_Q_MISC_FSP_CBR | + (qi->tqi_cbrOverflowLimit ? + AR_Q_MISC_CBR_EXP_CNTR_LIMIT : 0)); + } + if (qi->tqi_readyTime) { + OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), + SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_INT) | + AR_Q_RDYTIMECFG_EN); + } + if (qi->tqi_burstTime) { + OS_REG_WRITE(ah, AR_DCHNTIME(q), + SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | + AR_D_CHNTIME_EN); + if (qi->tqi_qflags & HAL_TXQ_RDYTIME_EXP_POLICY_ENABLE) { + OS_REG_WRITE(ah, AR_QMISC(q), + OS_REG_READ(ah, AR_QMISC(q)) | + AR_Q_MISC_RDYTIME_EXP_POLICY); + } + } + + if (qi->tqi_qflags & HAL_TXQ_BACKOFF_DISABLE) { + OS_REG_WRITE(ah, AR_DMISC(q), + OS_REG_READ(ah, AR_DMISC(q)) | + AR_D_MISC_POST_FR_BKOFF_DIS); + } + if (qi->tqi_qflags & HAL_TXQ_FRAG_BURST_BACKOFF_ENABLE) { + OS_REG_WRITE(ah, AR_DMISC(q), + OS_REG_READ(ah, AR_DMISC(q)) | + AR_D_MISC_FRAG_BKOFF_EN); + } + switch (qi->tqi_type) { + case HAL_TX_QUEUE_BEACON: + /* Configure QCU for beacons */ + OS_REG_WRITE(ah, AR_QMISC(q), + OS_REG_READ(ah, AR_QMISC(q)) + | AR_Q_MISC_FSP_DBA_GATED + | AR_Q_MISC_BEACON_USE + | AR_Q_MISC_CBR_INCR_DIS1); + /* Configure DCU for beacons */ + value = (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S) + | AR_D_MISC_BEACON_USE | AR_D_MISC_POST_FR_BKOFF_DIS; + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) + value |= AR5311_D_MISC_SEQ_NUM_CONTROL; + OS_REG_WRITE(ah, AR_DMISC(q), value); + break; + case HAL_TX_QUEUE_CAB: + /* Configure QCU for CAB (Crap After Beacon) frames */ + OS_REG_WRITE(ah, AR_QMISC(q), + OS_REG_READ(ah, AR_QMISC(q)) + | AR_Q_MISC_FSP_DBA_GATED | AR_Q_MISC_CBR_INCR_DIS1 + | AR_Q_MISC_CBR_INCR_DIS0 | AR_Q_MISC_RDYTIME_EXP_POLICY); + + value = (ahp->ah_beaconInterval + - (ath_hal_sw_beacon_response_time - ath_hal_dma_beacon_response_time) + - ath_hal_additional_swba_backoff) * 1024; + OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), value | AR_Q_RDYTIMECFG_EN); + + /* Configure DCU for CAB */ + value = (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S); + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) + value |= AR5311_D_MISC_SEQ_NUM_CONTROL; + OS_REG_WRITE(ah, AR_QMISC(q), value); + break; + default: + /* NB: silence compiler */ + break; + } + + /* + * Always update the secondary interrupt mask registers - this + * could be a new queue getting enabled in a running system or + * hw getting re-initialized during a reset! + * + * Since we don't differentiate between tx interrupts corresponding + * to individual queues - secondary tx mask regs are always unmasked; + * tx interrupts are enabled/disabled for all queues collectively + * using the primary mask reg + */ + if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE) + ahp->ah_txOkInterruptMask |= 1 << q; + else + ahp->ah_txOkInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE) + ahp->ah_txErrInterruptMask |= 1 << q; + else + ahp->ah_txErrInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE) + ahp->ah_txDescInterruptMask |= 1 << q; + else + ahp->ah_txDescInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE) + ahp->ah_txEolInterruptMask |= 1 << q; + else + ahp->ah_txEolInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE) + ahp->ah_txUrnInterruptMask |= 1 << q; + else + ahp->ah_txUrnInterruptMask &= ~(1 << q); + setTxQInterrupts(ah, qi); + + return AH_TRUE; +} + +/* + * Get the TXDP for the specified data queue. + */ +uint32_t +ar5211GetTxDP(struct ath_hal *ah, u_int q) +{ + HALASSERT(q < HAL_NUM_TX_QUEUES); + return OS_REG_READ(ah, AR_QTXDP(q)); +} + +/* + * Set the TxDP for the specified tx queue. + */ +HAL_BOOL +ar5211SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp) +{ + HALASSERT(q < HAL_NUM_TX_QUEUES); + HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + /* + * Make sure that TXE is deasserted before setting the TXDP. If TXE + * is still asserted, setting TXDP will have no effect. + */ + HALASSERT((OS_REG_READ(ah, AR_Q_TXE) & (1 << q)) == 0); + + OS_REG_WRITE(ah, AR_QTXDP(q), txdp); + + return AH_TRUE; +} + +/* + * Set Transmit Enable bits for the specified queues. + */ +HAL_BOOL +ar5211StartTxDma(struct ath_hal *ah, u_int q) +{ + HALASSERT(q < HAL_NUM_TX_QUEUES); + HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + /* Check that queue is not already active */ + HALASSERT((OS_REG_READ(ah, AR_Q_TXD) & (1<ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + n = OS_REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT_M; + /* + * Pending frame count (PFC) can momentarily go to zero + * while TXE remains asserted. In other words a PFC of + * zero is not sufficient to say that the queue has stopped. + */ + if (n == 0 && (OS_REG_READ(ah, AR_Q_TXE) & (1<ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + OS_REG_WRITE(ah, AR_Q_TXD, 1<ds_ctl0 = (pktLen & AR_FrameLen) + | (txRate0 << AR_XmitRate_S) + | (antMode << AR_AntModeXmit_S) + | (flags & HAL_TXDESC_CLRDMASK ? AR_ClearDestMask : 0) + | (flags & HAL_TXDESC_INTREQ ? AR_TxInterReq : 0) + | (flags & HAL_TXDESC_RTSENA ? AR_RTSCTSEnable : 0) + | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0) + ; + ads->ds_ctl1 = (type << 26) + | (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0) + ; + + if (keyIx != HAL_TXKEYIX_INVALID) { + ads->ds_ctl1 |= + (keyIx << AR_EncryptKeyIdx_S) & AR_EncryptKeyIdx; + ads->ds_ctl0 |= AR_EncryptKeyValid; + } + return AH_TRUE; +#undef RATE +} + +HAL_BOOL +ar5211SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int txRate1, u_int txTries1, + u_int txRate2, u_int txTries2, + u_int txRate3, u_int txTries3) +{ + (void) ah; (void) ds; + (void) txRate1; (void) txTries1; + (void) txRate2; (void) txTries2; + (void) txRate3; (void) txTries3; + return AH_FALSE; +} + +void +ar5211IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *ds) +{ + struct ar5211_desc *ads = AR5211DESC(ds); + + ads->ds_ctl0 |= AR_TxInterReq; +} + +HAL_BOOL +ar5211FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg, + const struct ath_desc *ds0) +{ + struct ar5211_desc *ads = AR5211DESC(ds); + + HALASSERT((segLen &~ AR_BufLen) == 0); + + if (firstSeg) { + /* + * First descriptor, don't clobber xmit control data + * setup by ar5211SetupTxDesc. + */ + ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_More); + } else if (lastSeg) { /* !firstSeg && lastSeg */ + /* + * Last descriptor in a multi-descriptor frame, + * copy the transmit parameters from the first + * frame for processing on completion. + */ + ads->ds_ctl0 = AR5211DESC_CONST(ds0)->ds_ctl0; + ads->ds_ctl1 = segLen; + } else { /* !firstSeg && !lastSeg */ + /* + * Intermediate descriptor in a multi-descriptor frame. + */ + ads->ds_ctl0 = 0; + ads->ds_ctl1 = segLen | AR_More; + } + ads->ds_status0 = ads->ds_status1 = 0; + return AH_TRUE; +} + +/* + * Processing of HW TX descriptor. + */ +HAL_STATUS +ar5211ProcTxDesc(struct ath_hal *ah, + struct ath_desc *ds, struct ath_tx_status *ts) +{ + struct ar5211_desc *ads = AR5211DESC(ds); + + if ((ads->ds_status1 & AR_Done) == 0) + return HAL_EINPROGRESS; + + /* Update software copies of the HW status */ + ts->ts_seqnum = MS(ads->ds_status1, AR_SeqNum); + ts->ts_tstamp = MS(ads->ds_status0, AR_SendTimestamp); + ts->ts_status = 0; + if ((ads->ds_status0 & AR_FrmXmitOK) == 0) { + if (ads->ds_status0 & AR_ExcessiveRetries) + ts->ts_status |= HAL_TXERR_XRETRY; + if (ads->ds_status0 & AR_Filtered) + ts->ts_status |= HAL_TXERR_FILT; + if (ads->ds_status0 & AR_FIFOUnderrun) + ts->ts_status |= HAL_TXERR_FIFO; + } + ts->ts_rate = MS(ads->ds_ctl0, AR_XmitRate); + ts->ts_rssi = MS(ads->ds_status1, AR_AckSigStrength); + ts->ts_shortretry = MS(ads->ds_status0, AR_ShortRetryCnt); + ts->ts_longretry = MS(ads->ds_status0, AR_LongRetryCnt); + ts->ts_virtcol = MS(ads->ds_status0, AR_VirtCollCnt); + ts->ts_antenna = 0; /* NB: don't know */ + ts->ts_finaltsi = 0; + /* + * NB: the number of retries is one less than it should be. + * Also, 0 retries and 1 retry are both reported as 0 retries. + */ + if (ts->ts_shortretry > 0) + ts->ts_shortretry++; + if (ts->ts_longretry > 0) + ts->ts_longretry++; + + return HAL_OK; +} + +/* + * Determine which tx queues need interrupt servicing. + * STUB. + */ +void +ar5211GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs) +{ + return; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211desc.h b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211desc.h new file mode 100644 index 0000000000..9fa6e29cf0 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211desc.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5211desc.h,v 1.5 2008/11/10 04:08:03 sam Exp $ + */ +#ifndef _DEV_ATH_AR5211DESC_H +#define _DEV_ATH_AR5211DESC_H + +#include "ah_desc.h" + +/* + * Defintions for the DMA descriptors used by the Atheros + * AR5211 and AR5110 Wireless Lan controller parts. + */ + +/* DMA descriptors */ +struct ar5211_desc { + uint32_t ds_link; /* link pointer */ + uint32_t ds_data; /* data buffer pointer */ + uint32_t ds_ctl0; /* DMA control 0 */ + uint32_t ds_ctl1; /* DMA control 1 */ + uint32_t ds_status0; /* DMA status 0 */ + uint32_t ds_status1; /* DMA status 1 */ +} __packed; +#define AR5211DESC(_ds) ((struct ar5211_desc *)(_ds)) +#define AR5211DESC_CONST(_ds) ((const struct ar5211_desc *)(_ds)) + +/* TX ds_ctl0 */ +#define AR_FrameLen 0x00000fff /* frame length */ +/* bits 12-17 are reserved */ +#define AR_XmitRate 0x003c0000 /* txrate */ +#define AR_XmitRate_S 18 +#define AR_RTSCTSEnable 0x00400000 /* RTS/CTS enable */ +#define AR_VEOL 0x00800000 /* virtual end-of-list */ +#define AR_ClearDestMask 0x01000000 /* Clear destination mask bit */ +#define AR_AntModeXmit 0x1e000000 /* TX antenna seslection */ +#define AR_AntModeXmit_S 25 +#define AR_TxInterReq 0x20000000 /* TX interrupt request */ +#define AR_EncryptKeyValid 0x40000000 /* EncryptKeyIdx is valid */ +/* bit 31 is reserved */ + +/* TX ds_ctl1 */ +#define AR_BufLen 0x00000fff /* data buffer length */ +#define AR_More 0x00001000 /* more desc in this frame */ +#define AR_EncryptKeyIdx 0x000fe000 /* ecnrypt key table index */ +#define AR_EncryptKeyIdx_S 13 +#define AR_FrmType 0x00700000 /* frame type indication */ +#define AR_FrmType_S 20 +#define AR_Frm_Normal 0x00000000 /* normal frame */ +#define AR_Frm_ATIM 0x00100000 /* ATIM frame */ +#define AR_Frm_PSPOLL 0x00200000 /* PS poll frame */ +#define AR_Frm_Beacon 0x00300000 /* Beacon frame */ +#define AR_Frm_ProbeResp 0x00400000 /* no delay data */ +#define AR_NoAck 0x00800000 /* No ACK flag */ +/* bits 24-31 are reserved */ + +/* RX ds_ctl1 */ +/* AR_BufLen 0x00000fff data buffer length */ +/* bit 12 is reserved */ +#define AR_RxInterReq 0x00002000 /* RX interrupt request */ +/* bits 14-31 are reserved */ + +/* TX ds_status0 */ +#define AR_FrmXmitOK 0x00000001 /* TX success */ +#define AR_ExcessiveRetries 0x00000002 /* excessive retries */ +#define AR_FIFOUnderrun 0x00000004 /* TX FIFO underrun */ +#define AR_Filtered 0x00000008 /* TX filter indication */ +/* NB: the spec has the Short+Long retry counts reversed */ +#define AR_LongRetryCnt 0x000000f0 /* long retry count */ +#define AR_LongRetryCnt_S 4 +#define AR_ShortRetryCnt 0x00000f00 /* short retry count */ +#define AR_ShortRetryCnt_S 8 +#define AR_VirtCollCnt 0x0000f000 /* virtual collision count */ +#define AR_VirtCollCnt_S 12 +#define AR_SendTimestamp 0xffff0000 /* TX timestamp */ +#define AR_SendTimestamp_S 16 + +/* RX ds_status0 */ +#define AR_DataLen 0x00000fff /* RX data length */ +/* AR_More 0x00001000 more desc in this frame */ +/* bits 13-14 are reserved */ +#define AR_RcvRate 0x00078000 /* reception rate */ +#define AR_RcvRate_S 15 +#define AR_RcvSigStrength 0x07f80000 /* receive signal strength */ +#define AR_RcvSigStrength_S 19 +#define AR_RcvAntenna 0x38000000 /* receive antenaa */ +#define AR_RcvAntenna_S 27 +/* bits 30-31 are reserved */ + +/* TX ds_status1 */ +#define AR_Done 0x00000001 /* descripter complete */ +#define AR_SeqNum 0x00001ffe /* TX sequence number */ +#define AR_SeqNum_S 1 +#define AR_AckSigStrength 0x001fe000 /* strength of ACK */ +#define AR_AckSigStrength_S 13 +/* bits 21-31 are reserved */ + +/* RX ds_status1 */ +/* AR_Done 0x00000001 descripter complete */ +#define AR_FrmRcvOK 0x00000002 /* frame reception success */ +#define AR_CRCErr 0x00000004 /* CRC error */ +/* bit 3 reserved */ +#define AR_DecryptCRCErr 0x00000010 /* Decryption CRC fiailure */ +#define AR_PHYErr 0x000000e0 /* PHY error */ +#define AR_PHYErr_S 5 +#define AR_PHYErr_Underrun 0x00000000 /* Transmit underrun */ +#define AR_PHYErr_Tim 0x00000020 /* Timing error */ +#define AR_PHYErr_Par 0x00000040 /* Parity error */ +#define AR_PHYErr_Rate 0x00000060 /* Illegal rate */ +#define AR_PHYErr_Len 0x00000080 /* Illegal length */ +#define AR_PHYErr_Radar 0x000000a0 /* Radar detect */ +#define AR_PHYErr_Srv 0x000000c0 /* Illegal service */ +#define AR_PHYErr_TOR 0x000000e0 /* Transmit override receive */ +#define AR_KeyIdxValid 0x00000100 /* decryption key index valid */ +#define AR_KeyIdx 0x00007e00 /* Decryption key index */ +#define AR_KeyIdx_S 9 +#define AR_RcvTimestamp 0x0fff8000 /* timestamp */ +#define AR_RcvTimestamp_S 15 +#define AR_KeyCacheMiss 0x10000000 /* key cache miss indication */ + +#endif /* _DEV_ATH_AR5211DESC_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211phy.h b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211phy.h new file mode 100644 index 0000000000..8bd7051188 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211phy.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5211phy.h,v 1.4 2008/11/10 01:19:38 sam Exp $ + */ +#ifndef _DEV_ATH_AR5211PHY_H +#define _DEV_ATH_AR5211PHY_H + +/* + * Definitions for the PHY on the Atheros AR5211/5311 chipset. + */ + +/* PHY registers */ +#define AR_PHY_BASE 0x9800 /* PHY registers base address */ +#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) + +#define AR_PHY_TURBO 0x9804 /* PHY frame control register */ +#define AR_PHY_FC_TURBO_MODE 0x00000001 /* Set turbo mode bits */ +#define AR_PHY_FC_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode setting */ + +#define AR_PHY_CHIP_ID 0x9818 /* PHY chip revision ID */ + +#define AR_PHY_ACTIVE 0x981C /* PHY activation register */ +#define AR_PHY_ACTIVE_EN 0x00000001 /* Activate PHY chips */ +#define AR_PHY_ACTIVE_DIS 0x00000000 /* Deactivate PHY chips */ + +#define AR_PHY_AGC_CONTROL 0x9860 /* PHY chip calibration and noise floor setting */ +#define AR_PHY_AGC_CONTROL_CAL 0x00000001 /* Perform PHY chip internal calibration */ +#define AR_PHY_AGC_CONTROL_NF 0x00000002 /* Perform PHY chip noise-floor calculation */ + +#define AR_PHY_PLL_CTL 0x987c /* PLL control register */ +#define AR_PHY_PLL_CTL_44 0x19 /* 44 MHz for 11b channels and FPGA */ +#define AR_PHY_PLL_CTL_40 0x18 /* 40 MHz */ +#define AR_PHY_PLL_CTL_20 0x13 /* 20 MHz half rate 11a for emulation */ + + +#define AR_PHY_RX_DELAY 0x9914 /* PHY analog_power_on_time, in 100ns increments */ +#define AR_PHY_RX_DELAY_M 0x00003FFF /* Mask for delay from active assertion (wake up) */ + /* to enable_receiver */ + +#define AR_PHY_TIMING_CTRL4 0x9920 /* PHY */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_M 0x0000001F /* Mask for kcos_theta-1 for q correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_M 0x000007E0 /* Mask for sin_theta for i correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5 /* Shift for sin_theta for i correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x00000800 /* enable IQ correction */ +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_M 0x0000F000 /* Mask for max number of samples (logarithmic) */ +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12 /* Shift for max number of samples */ +#define AR_PHY_TIMING_CTRL4_DO_IQCAL 0x00010000 /* perform IQ calibration */ + +#define AR_PHY_PAPD_PROBE 0x9930 +#define AR_PHY_PAPD_PROBE_POWERTX 0x00007E00 +#define AR_PHY_PAPD_PROBE_POWERTX_S 9 +#define AR_PHY_PAPD_PROBE_NEXT_TX 0x00008000 /* command to take next reading */ +#define AR_PHY_PAPD_PROBE_GAINF 0xFE000000 +#define AR_PHY_PAPD_PROBE_GAINF_S 25 + +#define AR_PHY_POWER_TX_RATE1 0x9934 +#define AR_PHY_POWER_TX_RATE2 0x9938 +#define AR_PHY_POWER_TX_RATE_MAX 0x993c + +#define AR_PHY_FRAME_CTL 0x9944 +#define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038 +#define AR_PHY_FRAME_CTL_TX_CLIP_S 3 +#define AR_PHY_FRAME_CTL_ERR_SERV 0x20000000 +#define AR_PHY_FRAME_CTL_ERR_SERV_S 29 + +#define AR_PHY_RADAR_0 0x9954 /* PHY radar detection settings */ +#define AR_PHY_RADAR_0_ENA 0x00000001 /* Enable radar detection */ + +#define AR_PHY_IQCAL_RES_PWR_MEAS_I 0x9c10 /*PHY IQ calibration results - power measurement for I */ +#define AR_PHY_IQCAL_RES_PWR_MEAS_Q 0x9c14 /*PHY IQ calibration results - power measurement for Q */ +#define AR_PHY_IQCAL_RES_IQ_CORR_MEAS 0x9c18 /*PHY IQ calibration results - IQ correlation measurement */ +#define AR_PHY_CURRENT_RSSI 0x9c1c /* rssi of current frame being received */ + +#define AR5211_PHY_MODE 0xA200 /* Mode register */ +#define AR5211_PHY_MODE_OFDM 0x0 /* bit 0 = 0 for OFDM */ +#define AR5211_PHY_MODE_CCK 0x1 /* bit 0 = 1 for CCK */ +#define AR5211_PHY_MODE_RF5GHZ 0x0 /* bit 1 = 0 for 5 GHz */ +#define AR5211_PHY_MODE_RF2GHZ 0x2 /* bit 1 = 1 for 2.4 GHz */ + +#endif /* _DEV_ATH_AR5211PHY_H */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211reg.h b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211reg.h new file mode 100644 index 0000000000..babd565aad --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5211/ar5211reg.h @@ -0,0 +1,853 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5211reg.h,v 1.4 2008/11/10 01:19:38 sam Exp $ + */ +#ifndef _DEV_ATH_AR5211REG_H +#define _DEV_ATH_AR5211REG_H + +/* + * Definitions for the Atheros AR5211/5311 chipset. + */ + +/* + * Maui2/Spirit specific registers/fields are indicated by AR5311. + * Oahu specific registers/fields are indicated by AR5211. + */ + +/* DMA Control and Interrupt Registers */ +#define AR_CR 0x0008 /* control register */ +#define AR_RXDP 0x000C /* receive queue descriptor pointer */ +#define AR_CFG 0x0014 /* configuration and status register */ +#define AR_IER 0x0024 /* Interrupt enable register */ +#define AR_RTSD0 0x0028 /* RTS Duration Parameters 0 */ +#define AR_RTSD1 0x002c /* RTS Duration Parameters 1 */ +#define AR_TXCFG 0x0030 /* tx DMA size config register */ +#define AR_RXCFG 0x0034 /* rx DMA size config register */ +#define AR5211_JUMBO_LAST 0x0038 /* Jumbo descriptor last address */ +#define AR_MIBC 0x0040 /* MIB control register */ +#define AR_TOPS 0x0044 /* timeout prescale count */ +#define AR_RXNPTO 0x0048 /* no frame received timeout */ +#define AR_TXNPTO 0x004C /* no frame trasmitted timeout */ +#define AR_RFGTO 0x0050 /* receive frame gap timeout */ +#define AR_RFCNT 0x0054 /* receive frame count limit */ +#define AR_MACMISC 0x0058 /* miscellaneous control/status */ +#define AR5311_QDCLKGATE 0x005c /* QCU/DCU clock gating control */ +#define AR_ISR 0x0080 /* Primary interrupt status register */ +#define AR_ISR_S0 0x0084 /* Secondary interrupt status reg 0 */ +#define AR_ISR_S1 0x0088 /* Secondary interrupt status reg 1 */ +#define AR_ISR_S2 0x008c /* Secondary interrupt status reg 2 */ +#define AR_ISR_S3 0x0090 /* Secondary interrupt status reg 3 */ +#define AR_ISR_S4 0x0094 /* Secondary interrupt status reg 4 */ +#define AR_IMR 0x00a0 /* Primary interrupt mask register */ +#define AR_IMR_S0 0x00a4 /* Secondary interrupt mask reg 0 */ +#define AR_IMR_S1 0x00a8 /* Secondary interrupt mask reg 1 */ +#define AR_IMR_S2 0x00ac /* Secondary interrupt mask reg 2 */ +#define AR_IMR_S3 0x00b0 /* Secondary interrupt mask reg 3 */ +#define AR_IMR_S4 0x00b4 /* Secondary interrupt mask reg 4 */ +#define AR_ISR_RAC 0x00c0 /* Primary interrupt status reg, */ +/* Shadow copies with read-and-clear access */ +#define AR_ISR_S0_S 0x00c4 /* Secondary interrupt status reg 0 */ +#define AR_ISR_S1_S 0x00c8 /* Secondary interrupt status reg 1 */ +#define AR_ISR_S2_S 0x00cc /* Secondary interrupt status reg 2 */ +#define AR_ISR_S3_S 0x00d0 /* Secondary interrupt status reg 3 */ +#define AR_ISR_S4_S 0x00d4 /* Secondary interrupt status reg 4 */ + +#define AR_Q0_TXDP 0x0800 /* Transmit Queue descriptor pointer */ +#define AR_Q1_TXDP 0x0804 /* Transmit Queue descriptor pointer */ +#define AR_Q2_TXDP 0x0808 /* Transmit Queue descriptor pointer */ +#define AR_Q3_TXDP 0x080c /* Transmit Queue descriptor pointer */ +#define AR_Q4_TXDP 0x0810 /* Transmit Queue descriptor pointer */ +#define AR_Q5_TXDP 0x0814 /* Transmit Queue descriptor pointer */ +#define AR_Q6_TXDP 0x0818 /* Transmit Queue descriptor pointer */ +#define AR_Q7_TXDP 0x081c /* Transmit Queue descriptor pointer */ +#define AR_Q8_TXDP 0x0820 /* Transmit Queue descriptor pointer */ +#define AR_Q9_TXDP 0x0824 /* Transmit Queue descriptor pointer */ +#define AR_QTXDP(i) (AR_Q0_TXDP + ((i)<<2)) + +#define AR_Q_TXE 0x0840 /* Transmit Queue enable */ +#define AR_Q_TXD 0x0880 /* Transmit Queue disable */ + +#define AR_Q0_CBRCFG 0x08c0 /* CBR configuration */ +#define AR_Q1_CBRCFG 0x08c4 /* CBR configuration */ +#define AR_Q2_CBRCFG 0x08c8 /* CBR configuration */ +#define AR_Q3_CBRCFG 0x08cc /* CBR configuration */ +#define AR_Q4_CBRCFG 0x08d0 /* CBR configuration */ +#define AR_Q5_CBRCFG 0x08d4 /* CBR configuration */ +#define AR_Q6_CBRCFG 0x08d8 /* CBR configuration */ +#define AR_Q7_CBRCFG 0x08dc /* CBR configuration */ +#define AR_Q8_CBRCFG 0x08e0 /* CBR configuration */ +#define AR_Q9_CBRCFG 0x08e4 /* CBR configuration */ +#define AR_QCBRCFG(i) (AR_Q0_CBRCFG + ((i)<<2)) + +#define AR_Q0_RDYTIMECFG 0x0900 /* ReadyTime configuration */ +#define AR_Q1_RDYTIMECFG 0x0904 /* ReadyTime configuration */ +#define AR_Q2_RDYTIMECFG 0x0908 /* ReadyTime configuration */ +#define AR_Q3_RDYTIMECFG 0x090c /* ReadyTime configuration */ +#define AR_Q4_RDYTIMECFG 0x0910 /* ReadyTime configuration */ +#define AR_Q5_RDYTIMECFG 0x0914 /* ReadyTime configuration */ +#define AR_Q6_RDYTIMECFG 0x0918 /* ReadyTime configuration */ +#define AR_Q7_RDYTIMECFG 0x091c /* ReadyTime configuration */ +#define AR_Q8_RDYTIMECFG 0x0920 /* ReadyTime configuration */ +#define AR_Q9_RDYTIMECFG 0x0924 /* ReadyTime configuration */ +#define AR_QRDYTIMECFG(i) (AR_Q0_RDYTIMECFG + ((i)<<2)) + +#define AR_Q_ONESHOTARM_SC 0x0940 /* OneShotArm set control */ +#define AR_Q_ONESHOTARM_CC 0x0980 /* OneShotArm clear control */ + +#define AR_Q0_MISC 0x09c0 /* Miscellaneous QCU settings */ +#define AR_Q1_MISC 0x09c4 /* Miscellaneous QCU settings */ +#define AR_Q2_MISC 0x09c8 /* Miscellaneous QCU settings */ +#define AR_Q3_MISC 0x09cc /* Miscellaneous QCU settings */ +#define AR_Q4_MISC 0x09d0 /* Miscellaneous QCU settings */ +#define AR_Q5_MISC 0x09d4 /* Miscellaneous QCU settings */ +#define AR_Q6_MISC 0x09d8 /* Miscellaneous QCU settings */ +#define AR_Q7_MISC 0x09dc /* Miscellaneous QCU settings */ +#define AR_Q8_MISC 0x09e0 /* Miscellaneous QCU settings */ +#define AR_Q9_MISC 0x09e4 /* Miscellaneous QCU settings */ +#define AR_QMISC(i) (AR_Q0_MISC + ((i)<<2)) + +#define AR_Q0_STS 0x0a00 /* Miscellaneous QCU status */ +#define AR_Q1_STS 0x0a04 /* Miscellaneous QCU status */ +#define AR_Q2_STS 0x0a08 /* Miscellaneous QCU status */ +#define AR_Q3_STS 0x0a0c /* Miscellaneous QCU status */ +#define AR_Q4_STS 0x0a10 /* Miscellaneous QCU status */ +#define AR_Q5_STS 0x0a14 /* Miscellaneous QCU status */ +#define AR_Q6_STS 0x0a18 /* Miscellaneous QCU status */ +#define AR_Q7_STS 0x0a1c /* Miscellaneous QCU status */ +#define AR_Q8_STS 0x0a20 /* Miscellaneous QCU status */ +#define AR_Q9_STS 0x0a24 /* Miscellaneous QCU status */ +#define AR_QSTS(i) (AR_Q0_STS + ((i)<<2)) + +#define AR_Q_RDYTIMESHDN 0x0a40 /* ReadyTimeShutdown status */ +#define AR_D0_QCUMASK 0x1000 /* QCU Mask */ +#define AR_D1_QCUMASK 0x1004 /* QCU Mask */ +#define AR_D2_QCUMASK 0x1008 /* QCU Mask */ +#define AR_D3_QCUMASK 0x100c /* QCU Mask */ +#define AR_D4_QCUMASK 0x1010 /* QCU Mask */ +#define AR_D5_QCUMASK 0x1014 /* QCU Mask */ +#define AR_D6_QCUMASK 0x1018 /* QCU Mask */ +#define AR_D7_QCUMASK 0x101c /* QCU Mask */ +#define AR_D8_QCUMASK 0x1020 /* QCU Mask */ +#define AR_D9_QCUMASK 0x1024 /* QCU Mask */ +#define AR_DQCUMASK(i) (AR_D0_QCUMASK + ((i)<<2)) + +#define AR_D0_LCL_IFS 0x1040 /* DCU-specific IFS settings */ +#define AR_D1_LCL_IFS 0x1044 /* DCU-specific IFS settings */ +#define AR_D2_LCL_IFS 0x1048 /* DCU-specific IFS settings */ +#define AR_D3_LCL_IFS 0x104c /* DCU-specific IFS settings */ +#define AR_D4_LCL_IFS 0x1050 /* DCU-specific IFS settings */ +#define AR_D5_LCL_IFS 0x1054 /* DCU-specific IFS settings */ +#define AR_D6_LCL_IFS 0x1058 /* DCU-specific IFS settings */ +#define AR_D7_LCL_IFS 0x105c /* DCU-specific IFS settings */ +#define AR_D8_LCL_IFS 0x1060 /* DCU-specific IFS settings */ +#define AR_D9_LCL_IFS 0x1064 /* DCU-specific IFS settings */ +#define AR_DLCL_IFS(i) (AR_D0_LCL_IFS + ((i)<<2)) + +#define AR_D0_RETRY_LIMIT 0x1080 /* Retry limits */ +#define AR_D1_RETRY_LIMIT 0x1084 /* Retry limits */ +#define AR_D2_RETRY_LIMIT 0x1088 /* Retry limits */ +#define AR_D3_RETRY_LIMIT 0x108c /* Retry limits */ +#define AR_D4_RETRY_LIMIT 0x1090 /* Retry limits */ +#define AR_D5_RETRY_LIMIT 0x1094 /* Retry limits */ +#define AR_D6_RETRY_LIMIT 0x1098 /* Retry limits */ +#define AR_D7_RETRY_LIMIT 0x109c /* Retry limits */ +#define AR_D8_RETRY_LIMIT 0x10a0 /* Retry limits */ +#define AR_D9_RETRY_LIMIT 0x10a4 /* Retry limits */ +#define AR_DRETRY_LIMIT(i) (AR_D0_RETRY_LIMIT + ((i)<<2)) + +#define AR_D0_CHNTIME 0x10c0 /* ChannelTime settings */ +#define AR_D1_CHNTIME 0x10c4 /* ChannelTime settings */ +#define AR_D2_CHNTIME 0x10c8 /* ChannelTime settings */ +#define AR_D3_CHNTIME 0x10cc /* ChannelTime settings */ +#define AR_D4_CHNTIME 0x10d0 /* ChannelTime settings */ +#define AR_D5_CHNTIME 0x10d4 /* ChannelTime settings */ +#define AR_D6_CHNTIME 0x10d8 /* ChannelTime settings */ +#define AR_D7_CHNTIME 0x10dc /* ChannelTime settings */ +#define AR_D8_CHNTIME 0x10e0 /* ChannelTime settings */ +#define AR_D9_CHNTIME 0x10e4 /* ChannelTime settings */ +#define AR_DCHNTIME(i) (AR_D0_CHNTIME + ((i)<<2)) + +#define AR_D0_MISC 0x1100 /* Misc DCU-specific settings */ +#define AR_D1_MISC 0x1104 /* Misc DCU-specific settings */ +#define AR_D2_MISC 0x1108 /* Misc DCU-specific settings */ +#define AR_D3_MISC 0x110c /* Misc DCU-specific settings */ +#define AR_D4_MISC 0x1110 /* Misc DCU-specific settings */ +#define AR_D5_MISC 0x1114 /* Misc DCU-specific settings */ +#define AR_D6_MISC 0x1118 /* Misc DCU-specific settings */ +#define AR_D7_MISC 0x111c /* Misc DCU-specific settings */ +#define AR_D8_MISC 0x1120 /* Misc DCU-specific settings */ +#define AR_D9_MISC 0x1124 /* Misc DCU-specific settings */ +#define AR_DMISC(i) (AR_D0_MISC + ((i)<<2)) + +#define AR_D0_SEQNUM 0x1140 /* Frame seqnum control/status */ +#define AR_D1_SEQNUM 0x1144 /* Frame seqnum control/status */ +#define AR_D2_SEQNUM 0x1148 /* Frame seqnum control/status */ +#define AR_D3_SEQNUM 0x114c /* Frame seqnum control/status */ +#define AR_D4_SEQNUM 0x1150 /* Frame seqnum control/status */ +#define AR_D5_SEQNUM 0x1154 /* Frame seqnum control/status */ +#define AR_D6_SEQNUM 0x1158 /* Frame seqnum control/status */ +#define AR_D7_SEQNUM 0x115c /* Frame seqnum control/status */ +#define AR_D8_SEQNUM 0x1160 /* Frame seqnum control/status */ +#define AR_D9_SEQNUM 0x1164 /* Frame seqnum control/status */ +#define AR_DSEQNUM(i) (AR_D0_SEQNUM + ((i<<2))) + +/* MAC DCU-global IFS settings */ +#define AR_D_GBL_IFS_SIFS 0x1030 /* DCU global SIFS settings */ +#define AR_D_GBL_IFS_SLOT 0x1070 /* DC global slot interval */ +#define AR_D_GBL_IFS_EIFS 0x10b0 /* DCU global EIFS setting */ +#define AR_D_GBL_IFS_MISC 0x10f0 /* DCU global misc. IFS settings */ +#define AR_D_FPCTL 0x1230 /* DCU frame prefetch settings */ +#define AR_D_TXPSE 0x1270 /* DCU transmit pause control/status */ +#define AR_D_TXBLK_CMD 0x1038 /* DCU transmit filter cmd (w/only) */ +#define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i)) /* DCU transmit filter data */ +#define AR_D_TXBLK_CLR 0x143c /* DCU clear tx filter (w/only) */ +#define AR_D_TXBLK_SET 0x147c /* DCU set tx filter (w/only) */ + +#define AR_D_TXPSE 0x1270 /* DCU transmit pause control/status */ + +#define AR_RC 0x4000 /* Warm reset control register */ +#define AR_SCR 0x4004 /* Sleep control register */ +#define AR_INTPEND 0x4008 /* Interrupt Pending register */ +#define AR_SFR 0x400C /* Sleep force register */ +#define AR_PCICFG 0x4010 /* PCI configuration register */ +#define AR_GPIOCR 0x4014 /* GPIO control register */ +#define AR_GPIODO 0x4018 /* GPIO data output access register */ +#define AR_GPIODI 0x401C /* GPIO data input access register */ +#define AR_SREV 0x4020 /* Silicon Revision register */ + +#define AR_EEPROM_ADDR 0x6000 /* EEPROM address register (10 bit) */ +#define AR_EEPROM_DATA 0x6004 /* EEPROM data register (16 bit) */ +#define AR_EEPROM_CMD 0x6008 /* EEPROM command register */ +#define AR_EEPROM_STS 0x600c /* EEPROM status register */ +#define AR_EEPROM_CFG 0x6010 /* EEPROM configuration register */ + +#define AR_STA_ID0 0x8000 /* station ID0 - low 32 bits */ +#define AR_STA_ID1 0x8004 /* station ID1 - upper 16 bits */ +#define AR_BSS_ID0 0x8008 /* BSSID low 32 bits */ +#define AR_BSS_ID1 0x800C /* BSSID upper 16 bits / AID */ +#define AR_SLOT_TIME 0x8010 /* Time-out after a collision */ +#define AR_TIME_OUT 0x8014 /* ACK & CTS time-out */ +#define AR_RSSI_THR 0x8018 /* RSSI warning & missed beacon threshold */ +#define AR_USEC 0x801c /* transmit latency register */ +#define AR_BEACON 0x8020 /* beacon control value/mode bits */ +#define AR_CFP_PERIOD 0x8024 /* CFP Interval (TU/msec) */ +#define AR_TIMER0 0x8028 /* Next beacon time (TU/msec) */ +#define AR_TIMER1 0x802c /* DMA beacon alert time (1/8 TU) */ +#define AR_TIMER2 0x8030 /* Software beacon alert (1/8 TU) */ +#define AR_TIMER3 0x8034 /* ATIM window time */ +#define AR_CFP_DUR 0x8038 /* maximum CFP duration in TU */ +#define AR_RX_FILTER 0x803C /* receive filter register */ +#define AR_MCAST_FIL0 0x8040 /* multicast filter lower 32 bits */ +#define AR_MCAST_FIL1 0x8044 /* multicast filter upper 32 bits */ +#define AR_DIAG_SW 0x8048 /* PCU control register */ +#define AR_TSF_L32 0x804c /* local clock lower 32 bits */ +#define AR_TSF_U32 0x8050 /* local clock upper 32 bits */ +#define AR_TST_ADDAC 0x8054 /* ADDAC test register */ +#define AR_DEF_ANTENNA 0x8058 /* default antenna register */ + +#define AR_LAST_TSTP 0x8080 /* Time stamp of the last beacon rcvd */ +#define AR_NAV 0x8084 /* current NAV value */ +#define AR_RTS_OK 0x8088 /* RTS exchange success counter */ +#define AR_RTS_FAIL 0x808c /* RTS exchange failure counter */ +#define AR_ACK_FAIL 0x8090 /* ACK failure counter */ +#define AR_FCS_FAIL 0x8094 /* FCS check failure counter */ +#define AR_BEACON_CNT 0x8098 /* Valid beacon counter */ + +#define AR_KEYTABLE_0 0x8800 /* Encryption key table */ +#define AR_KEYTABLE(n) (AR_KEYTABLE_0 + ((n)*32)) + +#define AR_CR_RXE 0x00000004 /* Receive enable */ +#define AR_CR_RXD 0x00000020 /* Receive disable */ +#define AR_CR_SWI 0x00000040 /* One-shot software interrupt */ +#define AR_CR_BITS "\20\3RXE\6RXD\7SWI" + +#define AR_CFG_SWTD 0x00000001 /* byteswap tx descriptor words */ +#define AR_CFG_SWTB 0x00000002 /* byteswap tx data buffer words */ +#define AR_CFG_SWRD 0x00000004 /* byteswap rx descriptor words */ +#define AR_CFG_SWRB 0x00000008 /* byteswap rx data buffer words */ +#define AR_CFG_SWRG 0x00000010 /* byteswap register access data words */ +#define AR_CFG_AP_ADHOC_INDICATION 0x00000020 /* AP/adhoc indication (0-AP, 1-Adhoc) */ +#define AR_CFG_PHOK 0x00000100 /* PHY OK status */ +#define AR_CFG_EEBS 0x00000200 /* EEPROM busy */ +#define AR_CFG_CLK_GATE_DIS 0x00000400 /* Clock gating disable (Oahu only) */ +#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_M 0x00060000 /* Mask of PCI core master request queue full threshold */ +#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17 /* Shift for PCI core master request queue full threshold */ +#define AR_CFG_BITS \ + "\20\1SWTD\2SWTB\3SWRD\4SWRB\5SWRG\10PHYOK11EEBS" + +#define AR_IER_ENABLE 0x00000001 /* Global interrupt enable */ +#define AR_IER_DISABLE 0x00000000 /* Global interrupt disable */ +#define AR_IER_BITS "\20\1ENABLE" + +#define AR_RTSD0_RTS_DURATION_6_M 0x000000FF +#define AR_RTSD0_RTS_DURATION_6_S 0 +#define AR_RTSD0_RTS_DURATION_9_M 0x0000FF00 +#define AR_RTSD0_RTS_DURATION_9_S 8 +#define AR_RTSD0_RTS_DURATION_12_M 0x00FF0000 +#define AR_RTSD0_RTS_DURATION_12_S 16 +#define AR_RTSD0_RTS_DURATION_18_M 0xFF000000 +#define AR_RTSD0_RTS_DURATION_18_S 24 + +#define AR_RTSD0_RTS_DURATION_24_M 0x000000FF +#define AR_RTSD0_RTS_DURATION_24_S 0 +#define AR_RTSD0_RTS_DURATION_36_M 0x0000FF00 +#define AR_RTSD0_RTS_DURATION_36_S 8 +#define AR_RTSD0_RTS_DURATION_48_M 0x00FF0000 +#define AR_RTSD0_RTS_DURATION_48_S 16 +#define AR_RTSD0_RTS_DURATION_54_M 0xFF000000 +#define AR_RTSD0_RTS_DURATION_54_S 24 + +#define AR_DMASIZE_4B 0x00000000 /* DMA size 4 bytes (TXCFG + RXCFG) */ +#define AR_DMASIZE_8B 0x00000001 /* DMA size 8 bytes */ +#define AR_DMASIZE_16B 0x00000002 /* DMA size 16 bytes */ +#define AR_DMASIZE_32B 0x00000003 /* DMA size 32 bytes */ +#define AR_DMASIZE_64B 0x00000004 /* DMA size 64 bytes */ +#define AR_DMASIZE_128B 0x00000005 /* DMA size 128 bytes */ +#define AR_DMASIZE_256B 0x00000006 /* DMA size 256 bytes */ +#define AR_DMASIZE_512B 0x00000007 /* DMA size 512 bytes */ + +#define AR_TXCFG_FTRIG_M 0x000003F0 /* Mask for Frame trigger level */ +#define AR_TXCFG_FTRIG_S 4 /* Shift for Frame trigger level */ +#define AR_TXCFG_FTRIG_IMMED 0x00000000 /* bytes in PCU TX FIFO before air */ +#define AR_TXCFG_FTRIG_64B 0x00000010 /* default */ +#define AR_TXCFG_FTRIG_128B 0x00000020 +#define AR_TXCFG_FTRIG_192B 0x00000030 +#define AR_TXCFG_FTRIG_256B 0x00000040 /* 5 bits total */ +#define AR_TXCFG_BITS "\20" + +#define AR5311_RXCFG_DEF_RX_ANTENNA 0x00000008 /* Default Receive Antenna */ + /* Maui2/Spirit only - reserved on Oahu */ +#define AR_RXCFG_ZLFDMA 0x00000010 /* Enable DMA of zero-length frame */ +#define AR_RXCFG_EN_JUM 0x00000020 /* Enable jumbo rx descriptors */ +#define AR_RXCFG_WR_JUM 0x00000040 /* Wrap jumbo rx descriptors */ + +#define AR_MIBC_COW 0x00000001 /* counter overflow warning */ +#define AR_MIBC_FMC 0x00000002 /* freeze MIB counters */ +#define AR_MIBC_CMC 0x00000004 /* clear MIB counters */ +#define AR_MIBC_MCS 0x00000008 /* MIB counter strobe, increment all */ + +#define AR_TOPS_MASK 0x0000FFFF /* Mask for timeout prescale */ + +#define AR_RXNPTO_MASK 0x000003FF /* Mask for no frame received timeout */ + +#define AR_TXNPTO_MASK 0x000003FF /* Mask for no frame transmitted timeout */ +#define AR_TXNPTO_QCU_MASK 0x03FFFC00 /* Mask indicating the set of QCUs */ + /* for which frame completions will cause */ + /* a reset of the no frame transmitted timeout */ + +#define AR_RPGTO_MASK 0x000003FF /* Mask for receive frame gap timeout */ + +#define AR_RPCNT_MASK 0x0000001F /* Mask for receive frame count limit */ + +#define AR_MACMISC_DMA_OBS_M 0x000001E0 /* Mask for DMA observation bus mux select */ +#define AR_MACMISC_DMA_OBS_S 5 /* Shift for DMA observation bus mux select */ +#define AR_MACMISC_MISC_OBS_M 0x00000E00 /* Mask for MISC observation bus mux select */ +#define AR_MACMISC_MISC_OBS_S 9 /* Shift for MISC observation bus mux select */ +#define AR_MACMISC_MAC_OBS_BUS_LSB_M 0x00007000 /* Mask for MAC observation bus mux select (lsb) */ +#define AR_MACMISC_MAC_OBS_BUS_LSB_S 12 /* Shift for MAC observation bus mux select (lsb) */ +#define AR_MACMISC_MAC_OBS_BUS_MSB_M 0x00038000 /* Mask for MAC observation bus mux select (msb) */ +#define AR_MACMISC_MAC_OBS_BUS_MSB_S 15 /* Shift for MAC observation bus mux select (msb) */ + + /* Maui2/Spirit only. */ +#define AR5311_QDCLKGATE_QCU_M 0x0000FFFF /* Mask for QCU clock disable */ +#define AR5311_QDCLKGATE_DCU_M 0x07FF0000 /* Mask for DCU clock disable */ + + /* Interrupt Status Registers */ +#define AR_ISR_RXOK 0x00000001 /* At least one frame received sans errors */ +#define AR_ISR_RXDESC 0x00000002 /* Receive interrupt request */ +#define AR_ISR_RXERR 0x00000004 /* Receive error interrupt */ +#define AR_ISR_RXNOPKT 0x00000008 /* No frame received within timeout clock */ +#define AR_ISR_RXEOL 0x00000010 /* Received descriptor empty interrupt */ +#define AR_ISR_RXORN 0x00000020 /* Receive FIFO overrun interrupt */ +#define AR_ISR_TXOK 0x00000040 /* Transmit okay interrupt */ +#define AR_ISR_TXDESC 0x00000080 /* Transmit interrupt request */ +#define AR_ISR_TXERR 0x00000100 /* Transmit error interrupt */ +#define AR_ISR_TXNOPKT 0x00000200 /* No frame transmitted interrupt */ +#define AR_ISR_TXEOL 0x00000400 /* Transmit descriptor empty interrupt */ +#define AR_ISR_TXURN 0x00000800 /* Transmit FIFO underrun interrupt */ +#define AR_ISR_MIB 0x00001000 /* MIB interrupt - see MIBC */ +#define AR_ISR_SWI 0x00002000 /* Software interrupt */ +#define AR_ISR_RXPHY 0x00004000 /* PHY receive error interrupt */ +#define AR_ISR_RXKCM 0x00008000 /* Key-cache miss interrupt */ +#define AR_ISR_SWBA 0x00010000 /* Software beacon alert interrupt */ +#define AR_ISR_BRSSI 0x00020000 /* Beacon threshold interrupt */ +#define AR_ISR_BMISS 0x00040000 /* Beacon missed interrupt */ +#define AR_ISR_HIUERR 0x00080000 /* An unexpected bus error has occurred */ +#define AR_ISR_BNR 0x00100000 /* Beacon not ready interrupt */ +#define AR_ISR_TIM 0x00800000 /* TIM interrupt */ +#define AR_ISR_GPIO 0x01000000 /* GPIO Interrupt */ +#define AR_ISR_QCBROVF 0x02000000 /* QCU CBR overflow interrupt */ +#define AR_ISR_QCBRURN 0x04000000 /* QCU CBR underrun interrupt */ +#define AR_ISR_QTRIG 0x08000000 /* QCU scheduling trigger interrupt */ +#define AR_ISR_RESV0 0xF0000000 /* Reserved */ + +#define AR_ISR_S0_QCU_TXOK_M 0x000003FF /* Mask for TXOK (QCU 0-9) */ +#define AR_ISR_S0_QCU_TXDESC_M 0x03FF0000 /* Mask for TXDESC (QCU 0-9) */ + +#define AR_ISR_S1_QCU_TXERR_M 0x000003FF /* Mask for TXERR (QCU 0-9) */ +#define AR_ISR_S1_QCU_TXEOL_M 0x03FF0000 /* Mask for TXEOL (QCU 0-9) */ + +#define AR_ISR_S2_QCU_TXURN_M 0x000003FF /* Mask for TXURN (QCU 0-9) */ +#define AR_ISR_S2_MCABT 0x00010000 /* Master cycle abort interrupt */ +#define AR_ISR_S2_SSERR 0x00020000 /* SERR interrupt */ +#define AR_ISR_S2_DPERR 0x00040000 /* PCI bus parity error */ +#define AR_ISR_S2_RESV0 0xFFF80000 /* Reserved */ + +#define AR_ISR_S3_QCU_QCBROVF_M 0x000003FF /* Mask for QCBROVF (QCU 0-9) */ +#define AR_ISR_S3_QCU_QCBRURN_M 0x03FF0000 /* Mask for QCBRURN (QCU 0-9) */ + +#define AR_ISR_S4_QCU_QTRIG_M 0x000003FF /* Mask for QTRIG (QCU 0-9) */ +#define AR_ISR_S4_RESV0 0xFFFFFC00 /* Reserved */ + + /* Interrupt Mask Registers */ +#define AR_IMR_RXOK 0x00000001 /* At least one frame received sans errors */ +#define AR_IMR_RXDESC 0x00000002 /* Receive interrupt request */ +#define AR_IMR_RXERR 0x00000004 /* Receive error interrupt */ +#define AR_IMR_RXNOPKT 0x00000008 /* No frame received within timeout clock */ +#define AR_IMR_RXEOL 0x00000010 /* Received descriptor empty interrupt */ +#define AR_IMR_RXORN 0x00000020 /* Receive FIFO overrun interrupt */ +#define AR_IMR_TXOK 0x00000040 /* Transmit okay interrupt */ +#define AR_IMR_TXDESC 0x00000080 /* Transmit interrupt request */ +#define AR_IMR_TXERR 0x00000100 /* Transmit error interrupt */ +#define AR_IMR_TXNOPKT 0x00000200 /* No frame transmitted interrupt */ +#define AR_IMR_TXEOL 0x00000400 /* Transmit descriptor empty interrupt */ +#define AR_IMR_TXURN 0x00000800 /* Transmit FIFO underrun interrupt */ +#define AR_IMR_MIB 0x00001000 /* MIB interrupt - see MIBC */ +#define AR_IMR_SWI 0x00002000 /* Software interrupt */ +#define AR_IMR_RXPHY 0x00004000 /* PHY receive error interrupt */ +#define AR_IMR_RXKCM 0x00008000 /* Key-cache miss interrupt */ +#define AR_IMR_SWBA 0x00010000 /* Software beacon alert interrupt */ +#define AR_IMR_BRSSI 0x00020000 /* Beacon threshold interrupt */ +#define AR_IMR_BMISS 0x00040000 /* Beacon missed interrupt */ +#define AR_IMR_HIUERR 0x00080000 /* An unexpected bus error has occurred */ +#define AR_IMR_BNR 0x00100000 /* BNR interrupt */ +#define AR_IMR_TIM 0x00800000 /* TIM interrupt */ +#define AR_IMR_GPIO 0x01000000 /* GPIO Interrupt */ +#define AR_IMR_QCBROVF 0x02000000 /* QCU CBR overflow interrupt */ +#define AR_IMR_QCBRURN 0x04000000 /* QCU CBR underrun interrupt */ +#define AR_IMR_QTRIG 0x08000000 /* QCU scheduling trigger interrupt */ +#define AR_IMR_RESV0 0xF0000000 /* Reserved */ + +#define AR_IMR_S0_QCU_TXOK 0x000003FF /* Mask for TXOK (QCU 0-9) */ +#define AR_IMR_S0_QCU_TXOK_S 0 +#define AR_IMR_S0_QCU_TXDESC 0x03FF0000 /* Mask for TXDESC (QCU 0-9) */ +#define AR_IMR_S0_QCU_TXDESC_S 16 /* Shift for TXDESC (QCU 0-9) */ + +#define AR_IMR_S1_QCU_TXERR 0x000003FF /* Mask for TXERR (QCU 0-9) */ +#define AR_IMR_S1_QCU_TXERR_S 0 +#define AR_IMR_S1_QCU_TXEOL 0x03FF0000 /* Mask for TXEOL (QCU 0-9) */ +#define AR_IMR_S1_QCU_TXEOL_S 16 /* Shift for TXEOL (QCU 0-9) */ + +#define AR_IMR_S2_QCU_TXURN 0x000003FF /* Mask for TXURN (QCU 0-9) */ +#define AR_IMR_S2_QCU_TXURN_S 0 +#define AR_IMR_S2_MCABT 0x00010000 /* Master cycle abort interrupt */ +#define AR_IMR_S2_SSERR 0x00020000 /* SERR interrupt */ +#define AR_IMR_S2_DPERR 0x00040000 /* PCI bus parity error */ +#define AR_IMR_S2_RESV0 0xFFF80000 /* Reserved */ + +#define AR_IMR_S3_QCU_QCBROVF_M 0x000003FF /* Mask for QCBROVF (QCU 0-9) */ +#define AR_IMR_S3_QCU_QCBRURN_M 0x03FF0000 /* Mask for QCBRURN (QCU 0-9) */ +#define AR_IMR_S3_QCU_QCBRURN_S 16 /* Shift for QCBRURN (QCU 0-9) */ + +#define AR_IMR_S4_QCU_QTRIG_M 0x000003FF /* Mask for QTRIG (QCU 0-9) */ +#define AR_IMR_S4_RESV0 0xFFFFFC00 /* Reserved */ + + /* Interrupt status registers (read-and-clear access, secondary shadow copies) */ + + /* QCU registers */ +#define AR_NUM_QCU 10 /* Only use QCU 0-9 for forward QCU compatibility */ +#define AR_QCU_0 0x0001 +#define AR_QCU_1 0x0002 +#define AR_QCU_2 0x0004 +#define AR_QCU_3 0x0008 +#define AR_QCU_4 0x0010 +#define AR_QCU_5 0x0020 +#define AR_QCU_6 0x0040 +#define AR_QCU_7 0x0080 +#define AR_QCU_8 0x0100 +#define AR_QCU_9 0x0200 + +#define AR_Q_TXE_M 0x000003FF /* Mask for TXE (QCU 0-9) */ + +#define AR_Q_TXD_M 0x000003FF /* Mask for TXD (QCU 0-9) */ + +#define AR_Q_CBRCFG_CBR_INTERVAL 0x00FFFFFF /* Mask for CBR interval (us) */ +#define AR_Q_CBRCFG_CBR_INTERVAL_S 0 /* Shift for CBR interval */ +#define AR_Q_CBRCFG_CBR_OVF_THRESH 0xFF000000 /* Mask for CBR overflow threshold */ +#define AR_Q_CBRCFG_CBR_OVF_THRESH_S 24 /* Shift for " " " */ + +#define AR_Q_RDYTIMECFG_INT 0x00FFFFFF /* CBR interval (us) */ +#define AR_Q_RDYTIMECFG_INT_S 0 /* Shift for ReadyTime Interval (us) */ +#define AR_Q_RDYTIMECFG_DURATION_M 0x00FFFFFF /* Mask for CBR interval (us) */ +#define AR_Q_RDYTIMECFG_EN 0x01000000 /* ReadyTime enable */ +#define AR_Q_RDYTIMECFG_RESV0 0xFE000000 /* Reserved */ + +#define AR_Q_ONESHOTARM_SC_M 0x0000FFFF /* Mask for MAC_Q_ONESHOTARM_SC (QCU 0-15) */ +#define AR_Q_ONESHOTARM_SC_RESV0 0xFFFF0000 /* Reserved */ + +#define AR_Q_ONESHOTARM_CC_M 0x0000FFFF /* Mask for MAC_Q_ONESHOTARM_CC (QCU 0-15) */ +#define AR_Q_ONESHOTARM_CC_RESV0 0xFFFF0000 /* Reserved */ + +#define AR_Q_MISC_FSP_M 0x0000000F /* Mask for Frame Scheduling Policy */ +#define AR_Q_MISC_FSP_ASAP 0 /* ASAP */ +#define AR_Q_MISC_FSP_CBR 1 /* CBR */ +#define AR_Q_MISC_FSP_DBA_GATED 2 /* DMA Beacon Alert gated */ +#define AR_Q_MISC_FSP_TIM_GATED 3 /* TIM gated */ +#define AR_Q_MISC_FSP_BEACON_SENT_GATED 4 /* Beacon-sent-gated */ +#define AR_Q_MISC_ONE_SHOT_EN 0x00000010 /* OneShot enable */ +#define AR_Q_MISC_CBR_INCR_DIS1 0x00000020 /* Disable CBR expired counter + incr (empty q) */ +#define AR_Q_MISC_CBR_INCR_DIS0 0x00000040 /* Disable CBR expired counter + incr (empty beacon q) */ +#define AR_Q_MISC_BEACON_USE 0x00000080 /* Beacon use indication */ +#define AR_Q_MISC_CBR_EXP_CNTR_LIMIT 0x00000100 /* CBR expired counter limit enable */ +#define AR_Q_MISC_RDYTIME_EXP_POLICY 0x00000200 /* Enable TXE cleared on ReadyTime expired or VEOL */ +#define AR_Q_MISC_RESET_CBR_EXP_CTR 0x00000400 /* Reset CBR expired counter */ +#define AR_Q_MISC_DCU_EARLY_TERM_REQ 0x00000800 /* DCU frame early termination request control */ +#define AR_Q_MISC_RESV0 0xFFFFF000 /* Reserved */ + +#define AR_Q_STS_PEND_FR_CNT_M 0x00000003 /* Mask for Pending Frame Count */ +#define AR_Q_STS_RESV0 0x000000FC /* Reserved */ +#define AR_Q_STS_CBR_EXP_CNT_M 0x0000FF00 /* Mask for CBR expired counter */ +#define AR_Q_STS_RESV1 0xFFFF0000 /* Reserved */ + +#define AR_Q_RDYTIMESHDN_M 0x000003FF /* Mask for ReadyTimeShutdown status (QCU 0-9) */ + + /* DCU registers */ +#define AR_NUM_DCU 10 /* Only use 10 DCU's for forward QCU/DCU compatibility */ +#define AR_DCU_0 0x0001 +#define AR_DCU_1 0x0002 +#define AR_DCU_2 0x0004 +#define AR_DCU_3 0x0008 +#define AR_DCU_4 0x0010 +#define AR_DCU_5 0x0020 +#define AR_DCU_6 0x0040 +#define AR_DCU_7 0x0080 +#define AR_DCU_8 0x0100 +#define AR_DCU_9 0x0200 + +#define AR_D_QCUMASK_M 0x000003FF /* Mask for QCU Mask (QCU 0-9) */ +#define AR_D_QCUMASK_RESV0 0xFFFFFC00 /* Reserved */ + +#define AR_D_LCL_IFS_CWMIN 0x000003FF /* Mask for CW_MIN */ +#define AR_D_LCL_IFS_CWMIN_S 0 /* Shift for CW_MIN */ +#define AR_D_LCL_IFS_CWMAX 0x000FFC00 /* Mask for CW_MAX */ +#define AR_D_LCL_IFS_CWMAX_S 10 /* Shift for CW_MAX */ +#define AR_D_LCL_IFS_AIFS 0x0FF00000 /* Mask for AIFS */ +#define AR_D_LCL_IFS_AIFS_S 20 /* Shift for AIFS */ +#define AR_D_LCL_IFS_RESV0 0xF0000000 /* Reserved */ + +#define AR_D_RETRY_LIMIT_FR_SH 0x0000000F /* Mask for frame short retry limit */ +#define AR_D_RETRY_LIMIT_FR_SH_S 0 /* Shift for frame short retry limit */ +#define AR_D_RETRY_LIMIT_FR_LG 0x000000F0 /* Mask for frame long retry limit */ +#define AR_D_RETRY_LIMIT_FR_LG_S 4 /* Shift for frame long retry limit */ +#define AR_D_RETRY_LIMIT_STA_SH 0x00003F00 /* Mask for station short retry limit */ +#define AR_D_RETRY_LIMIT_STA_SH_S 8 /* Shift for station short retry limit */ +#define AR_D_RETRY_LIMIT_STA_LG 0x000FC000 /* Mask for station short retry limit */ +#define AR_D_RETRY_LIMIT_STA_LG_S 14 /* Shift for station short retry limit */ +#define AR_D_RETRY_LIMIT_RESV0 0xFFF00000 /* Reserved */ + +#define AR_D_CHNTIME_EN 0x00100000 /* ChannelTime enable */ +#define AR_D_CHNTIME_RESV0 0xFFE00000 /* Reserved */ +#define AR_D_CHNTIME_DUR 0x000FFFFF /* Mask for ChannelTime duration (us) */ +#define AR_D_CHNTIME_DUR_S 0 /* Shift for ChannelTime duration */ + +#define AR_D_MISC_BKOFF_THRESH_M 0x000007FF /* Mask for Backoff threshold setting */ +#define AR_D_MISC_FRAG_BKOFF_EN 0x00000200 /* Backoff during a frag burst */ +#define AR_D_MISC_HCF_POLL_EN 0x00000800 /* HFC poll enable */ +#define AR_D_MISC_BKOFF_PERSISTENCE 0x00001000 /* Backoff persistence factor setting */ +#define AR_D_MISC_FR_PREFETCH_EN 0x00002000 /* Frame prefetch enable */ +#define AR_D_MISC_VIR_COL_HANDLING_M 0x0000C000 /* Mask for Virtual collision handling policy */ +#define AR_D_MISC_VIR_COL_HANDLING_NORMAL 0 /* Normal */ +#define AR_D_MISC_VIR_COL_HANDLING_MODIFIED 1 /* Modified */ +#define AR_D_MISC_VIR_COL_HANDLING_IGNORE 2 /* Ignore */ +#define AR_D_MISC_BEACON_USE 0x00010000 /* Beacon use indication */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL 0x00060000 /* Mask for DCU arbiter lockout control */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_S 17 /* Shift for DCU arbiter lockout control */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE 0 /* No lockout */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR 1 /* Intra-frame */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL 2 /* Global */ +#define AR_D_MISC_ARB_LOCKOUT_IGNORE 0x00080000 /* DCU arbiter lockout ignore control */ +#define AR_D_MISC_SEQ_NUM_INCR_DIS 0x00100000 /* Sequence number increment disable */ +#define AR_D_MISC_POST_FR_BKOFF_DIS 0x00200000 /* Post-frame backoff disable */ +#define AR_D_MISC_VIRT_COLL_POLICY 0x00400000 /* Virtual coll. handling policy */ +#define AR_D_MISC_BLOWN_IFS_POLICY 0x00800000 /* Blown IFS handling policy */ +#define AR5311_D_MISC_SEQ_NUM_CONTROL 0x01000000 /* Sequence Number local or global */ + /* Maui2/Spirit only, reserved on Oahu */ +#define AR_D_MISC_RESV0 0xFE000000 /* Reserved */ + +#define AR_D_SEQNUM_M 0x00000FFF /* Mask for value of sequence number */ +#define AR_D_SEQNUM_RESV0 0xFFFFF000 /* Reserved */ + +#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007 /* Mask forLFSR slice select */ +#define AR_D_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode indication */ +#define AR_D_GBL_IFS_MISC_SIFS_DURATION_USEC 0x000003F0 /* Mask for SIFS duration (us) */ +#define AR_D_GBL_IFS_MISC_USEC_DURATION 0x000FFC00 /* Mask for microsecond duration */ +#define AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY 0x00300000 /* Mask for DCU arbiter delay */ +#define AR_D_GBL_IFS_MISC_RESV0 0xFFC00000 /* Reserved */ + +/* Oahu only */ +#define AR_D_TXPSE_CTRL_M 0x000003FF /* Mask of DCUs to pause (DCUs 0-9) */ +#define AR_D_TXPSE_RESV0 0x0000FC00 /* Reserved */ +#define AR_D_TXPSE_STATUS 0x00010000 /* Transmit pause status */ +#define AR_D_TXPSE_RESV1 0xFFFE0000 /* Reserved */ + + /* DMA & PCI Registers in PCI space (usable during sleep) */ +#define AR_RC_MAC 0x00000001 /* MAC reset */ +#define AR_RC_BB 0x00000002 /* Baseband reset */ +#define AR_RC_RESV0 0x00000004 /* Reserved */ +#define AR_RC_RESV1 0x00000008 /* Reserved */ +#define AR_RC_PCI 0x00000010 /* PCI-core reset */ +#define AR_RC_BITS "\20\1MAC\2BB\3RESV0\4RESV1\5RPCI" + +#define AR_SCR_SLDUR 0x0000ffff /* sleep duration mask, units of 128us */ +#define AR_SCR_SLDUR_S 0 +#define AR_SCR_SLE 0x00030000 /* sleep enable mask */ +#define AR_SCR_SLE_S 16 /* sleep enable bits shift */ +#define AR_SCR_SLE_WAKE 0x00000000 /* force wake */ +#define AR_SCR_SLE_SLP 0x00010000 /* force sleep */ +#define AR_SCR_SLE_NORM 0x00020000 /* sleep logic normal operation */ +#define AR_SCR_SLE_UNITS 0x00000008 /* SCR units/TU */ +#define AR_SCR_BITS "\20\20SLE_SLP\21SLE" + +#define AR_INTPEND_TRUE 0x00000001 /* interrupt pending */ +#define AR_INTPEND_BITS "\20\1IP" + +#define AR_SFR_SLEEP 0x00000001 /* force sleep */ + +#define AR_PCICFG_CLKRUNEN 0x00000004 /* enable PCI CLKRUN function */ +#define AR_PCICFG_EEPROM_SIZE_M 0x00000018 /* Mask for EEPROM size */ +#define AR_PCICFG_EEPROM_SIZE_S 3 /* Mask for EEPROM size */ +#define AR_PCICFG_EEPROM_SIZE_4K 0 /* EEPROM size 4 Kbit */ +#define AR_PCICFG_EEPROM_SIZE_8K 1 /* EEPROM size 8 Kbit */ +#define AR_PCICFG_EEPROM_SIZE_16K 2 /* EEPROM size 16 Kbit */ +#define AR_PCICFG_EEPROM_SIZE_FAILED 3 /* Failure */ +#define AR_PCICFG_LEDCTL 0x00000060 /* LED control Status */ +#define AR_PCICFG_LEDCTL_NONE 0x00000000 /* STA is not associated or trying */ +#define AR_PCICFG_LEDCTL_PEND 0x00000020 /* STA is trying to associate */ +#define AR_PCICFG_LEDCTL_ASSOC 0x00000040 /* STA is associated */ +#define AR_PCICFG_PCI_BUS_SEL_M 0x00000380 /* Mask for PCI observation bus mux select */ +#define AR_PCICFG_DIS_CBE_FIX 0x00000400 /* Disable fix for bad PCI CBE# generation */ +#define AR_PCICFG_SL_INTEN 0x00000800 /* enable interrupt line assertion when asleep */ +#define AR_PCICFG_RESV0 0x00001000 /* Reserved */ +#define AR_PCICFG_SL_INPEN 0x00002000 /* Force asleep when an interrupt is pending */ +#define AR_PCICFG_RESV1 0x0000C000 /* Reserved */ +#define AR_PCICFG_SPWR_DN 0x00010000 /* mask for sleep/awake indication */ +#define AR_PCICFG_LEDMODE 0x000E0000 /* LED mode */ +#define AR_PCICFG_LEDMODE_PROP 0x00000000 /* Blink prop to filtered tx/rx */ +#define AR_PCICFG_LEDMODE_RPROP 0x00020000 /* Blink prop to unfiltered tx/rx */ +#define AR_PCICFG_LEDMODE_SPLIT 0x00040000 /* Blink power for tx/net for rx */ +#define AR_PCICFG_LEDMODE_RAND 0x00060000 /* Blink randomly */ +#define AR_PCICFG_LEDBLINK 0x00700000 /* LED blink threshold select */ +#define AR_PCICFG_LEDBLINK_S 20 +#define AR_PCICFG_LEDSLOW 0x00800000 /* LED slowest blink rate mode */ +#define AR_PCICFG_RESV2 0xFF000000 /* Reserved */ +#define AR_PCICFG_BITS "\20\3CLKRUNEN\13SL_INTEN" + +#define AR_GPIOCR_CR_SHIFT 2 /* Each CR is 2 bits */ +#define AR_GPIOCR_0_CR_N 0x00000000 /* Input only mode for GPIODO[0] */ +#define AR_GPIOCR_0_CR_0 0x00000001 /* Output only if GPIODO[0] = 0 */ +#define AR_GPIOCR_0_CR_1 0x00000002 /* Output only if GPIODO[0] = 1 */ +#define AR_GPIOCR_0_CR_A 0x00000003 /* Always output */ +#define AR_GPIOCR_1_CR_N 0x00000000 /* Input only mode for GPIODO[1] */ +#define AR_GPIOCR_1_CR_0 0x00000004 /* Output only if GPIODO[1] = 0 */ +#define AR_GPIOCR_1_CR_1 0x00000008 /* Output only if GPIODO[1] = 1 */ +#define AR_GPIOCR_1_CR_A 0x0000000C /* Always output */ +#define AR_GPIOCR_2_CR_N 0x00000000 /* Input only mode for GPIODO[2] */ +#define AR_GPIOCR_2_CR_0 0x00000010 /* Output only if GPIODO[2] = 0 */ +#define AR_GPIOCR_2_CR_1 0x00000020 /* Output only if GPIODO[2] = 1 */ +#define AR_GPIOCR_2_CR_A 0x00000030 /* Always output */ +#define AR_GPIOCR_3_CR_N 0x00000000 /* Input only mode for GPIODO[3] */ +#define AR_GPIOCR_3_CR_0 0x00000040 /* Output only if GPIODO[3] = 0 */ +#define AR_GPIOCR_3_CR_1 0x00000080 /* Output only if GPIODO[3] = 1 */ +#define AR_GPIOCR_3_CR_A 0x000000C0 /* Always output */ +#define AR_GPIOCR_4_CR_N 0x00000000 /* Input only mode for GPIODO[4] */ +#define AR_GPIOCR_4_CR_0 0x00000100 /* Output only if GPIODO[4] = 0 */ +#define AR_GPIOCR_4_CR_1 0x00000200 /* Output only if GPIODO[4] = 1 */ +#define AR_GPIOCR_4_CR_A 0x00000300 /* Always output */ +#define AR_GPIOCR_5_CR_N 0x00000000 /* Input only mode for GPIODO[5] */ +#define AR_GPIOCR_5_CR_0 0x00000400 /* Output only if GPIODO[5] = 0 */ +#define AR_GPIOCR_5_CR_1 0x00000800 /* Output only if GPIODO[5] = 1 */ +#define AR_GPIOCR_5_CR_A 0x00000C00 /* Always output */ +#define AR_GPIOCR_INT_SHIFT 12 /* Interrupt select field shifter */ +#define AR_GPIOCR_INT_MASK 0x00007000 /* Interrupt select field mask */ +#define AR_GPIOCR_INT_SEL0 0x00000000 /* Select Interrupt Pin GPIO_0 */ +#define AR_GPIOCR_INT_SEL1 0x00001000 /* Select Interrupt Pin GPIO_1 */ +#define AR_GPIOCR_INT_SEL2 0x00002000 /* Select Interrupt Pin GPIO_2 */ +#define AR_GPIOCR_INT_SEL3 0x00003000 /* Select Interrupt Pin GPIO_3 */ +#define AR_GPIOCR_INT_SEL4 0x00004000 /* Select Interrupt Pin GPIO_4 */ +#define AR_GPIOCR_INT_SEL5 0x00005000 /* Select Interrupt Pin GPIO_5 */ +#define AR_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO Interrupt */ +#define AR_GPIOCR_INT_SELL 0x00000000 /* Generate Interrupt if selected pin is low */ +#define AR_GPIOCR_INT_SELH 0x00010000 /* Generate Interrupt if selected pin is high */ + +#define AR_SREV_ID_M 0x000000FF /* Mask to read SREV info */ +#define AR_PCICFG_EEPROM_SIZE_16K 2 /* EEPROM size 16 Kbit */ +#define AR_SREV_ID_S 4 /* Major Rev Info */ +#define AR_SREV_REVISION_M 0x0000000F /* Chip revision level */ +#define AR_SREV_FPGA 1 +#define AR_SREV_D2PLUS 2 +#define AR_SREV_D2PLUS_MS 3 /* metal spin */ +#define AR_SREV_CRETE 4 +#define AR_SREV_CRETE_MS 5 /* FCS metal spin */ +#define AR_SREV_CRETE_MS23 7 /* 2.3 metal spin (6 skipped) */ +#define AR_SREV_CRETE_23 8 /* 2.3 full tape out */ +#define AR_SREV_VERSION_M 0x000000F0 /* Chip version indication */ +#define AR_SREV_VERSION_CRETE 0 +#define AR_SREV_VERSION_MAUI_1 1 +#define AR_SREV_VERSION_MAUI_2 2 +#define AR_SREV_VERSION_SPIRIT 3 +#define AR_SREV_VERSION_OAHU 4 +#define AR_SREV_OAHU_ES 0 /* Engineering Sample */ +#define AR_SREV_OAHU_PROD 2 /* Production */ + +#define RAD5_SREV_MAJOR 0x10 /* All current supported ar5211 5 GHz radios are rev 0x10 */ +#define RAD5_SREV_PROD 0x15 /* Current production level radios */ +#define RAD2_SREV_MAJOR 0x20 /* All current supported ar5211 2 GHz radios are rev 0x10 */ + + /* EEPROM Registers in the MAC */ +#define AR_EEPROM_CMD_READ 0x00000001 +#define AR_EEPROM_CMD_WRITE 0x00000002 +#define AR_EEPROM_CMD_RESET 0x00000004 + +#define AR_EEPROM_STS_READ_ERROR 0x00000001 +#define AR_EEPROM_STS_READ_COMPLETE 0x00000002 +#define AR_EEPROM_STS_WRITE_ERROR 0x00000004 +#define AR_EEPROM_STS_WRITE_COMPLETE 0x00000008 + +#define AR_EEPROM_CFG_SIZE_M 0x00000003 /* Mask for EEPROM size determination override */ +#define AR_EEPROM_CFG_SIZE_AUTO 0 +#define AR_EEPROM_CFG_SIZE_4KBIT 1 +#define AR_EEPROM_CFG_SIZE_8KBIT 2 +#define AR_EEPROM_CFG_SIZE_16KBIT 3 +#define AR_EEPROM_CFG_DIS_WAIT_WRITE_COMPL 0x00000004 /* Disable wait for write completion */ +#define AR_EEPROM_CFG_CLOCK_M 0x00000018 /* Mask for EEPROM clock rate control */ +#define AR_EEPROM_CFG_CLOCK_S 3 /* Shift for EEPROM clock rate control */ +#define AR_EEPROM_CFG_CLOCK_156KHZ 0 +#define AR_EEPROM_CFG_CLOCK_312KHZ 1 +#define AR_EEPROM_CFG_CLOCK_625KHZ 2 +#define AR_EEPROM_CFG_RESV0 0x000000E0 /* Reserved */ +#define AR_EEPROM_CFG_PROT_KEY_M 0x00FFFF00 /* Mask for EEPROM protection key */ +#define AR_EEPROM_CFG_PROT_KEY_S 8 /* Shift for EEPROM protection key */ +#define AR_EEPROM_CFG_EN_L 0x01000000 /* EPRM_EN_L setting */ + + /* MAC PCU Registers */ +#define AR_STA_ID1_SADH_MASK 0x0000FFFF /* Mask for upper 16 bits of MAC addr */ +#define AR_STA_ID1_STA_AP 0x00010000 /* Device is AP */ +#define AR_STA_ID1_ADHOC 0x00020000 /* Device is ad-hoc */ +#define AR_STA_ID1_PWR_SAV 0x00040000 /* Power save reporting in self-generated frames */ +#define AR_STA_ID1_KSRCHDIS 0x00080000 /* Key search disable */ +#define AR_STA_ID1_PCF 0x00100000 /* Observe PCF */ +#define AR_STA_ID1_DEFAULT_ANTENNA 0x00200000 /* Use default antenna */ +#define AR_STA_ID1_DESC_ANTENNA 0x00400000 /* Update default antenna w/ TX antenna */ +#define AR_STA_ID1_RTS_USE_DEF 0x00800000 /* Use default antenna to send RTS */ +#define AR_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mb/s rate for ACK & CTS */ +#define AR_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate for ACK & CTS */ +#define AR_STA_ID1_BITS \ + "\20\20AP\21ADHOC\22PWR_SAV\23KSRCHDIS\25PCF" + +#define AR_BSS_ID1_U16_M 0x0000FFFF /* Mask for upper 16 bits of BSSID */ +#define AR_BSS_ID1_AID_M 0xFFFF0000 /* Mask for association ID */ +#define AR_BSS_ID1_AID_S 16 /* Shift for association ID */ + +#define AR_SLOT_TIME_MASK 0x000007FF /* Slot time mask */ + +#define AR_TIME_OUT_ACK 0x00001FFF /* Mask for ACK time-out */ +#define AR_TIME_OUT_ACK_S 0 /* Shift for ACK time-out */ +#define AR_TIME_OUT_CTS 0x1FFF0000 /* Mask for CTS time-out */ +#define AR_TIME_OUT_CTS_S 16 /* Shift for CTS time-out */ + +#define AR_RSSI_THR_MASK 0x000000FF /* Mask for Beacon RSSI warning threshold */ +#define AR_RSSI_THR_BM_THR 0x0000FF00 /* Mask for Missed beacon threshold */ +#define AR_RSSI_THR_BM_THR_S 8 /* Shift for Missed beacon threshold */ + +#define AR_USEC_M 0x0000007F /* Mask for clock cycles in 1 usec */ +#define AR_USEC_32_M 0x00003F80 /* Mask for number of 32MHz clock cycles in 1 usec */ +#define AR_USEC_32_S 7 /* Shift for number of 32MHz clock cycles in 1 usec */ +/* + * Tx/Rx latencies are to signal start and are in usecs. + * + * NOTE: AR5211/AR5311 difference: on Oahu, the TX latency field + * has increased from 6 bits to 9 bits. The RX latency field + * is unchanged, but is shifted over 3 bits. + */ +#define AR5311_USEC_TX_LAT_M 0x000FC000 /* Tx latency */ +#define AR5311_USEC_TX_LAT_S 14 +#define AR5311_USEC_RX_LAT_M 0x03F00000 /* Rx latency */ +#define AR5311_USEC_RX_LAT_S 20 + +#define AR5211_USEC_TX_LAT_M 0x007FC000 /* Tx latency */ +#define AR5211_USEC_TX_LAT_S 14 +#define AR5211_USEC_RX_LAT_M 0x1F800000 /* Rx latency */ +#define AR5211_USEC_RX_LAT_S 23 + + +#define AR_BEACON_PERIOD 0x0000FFFF /* Beacon period in TU/msec */ +#define AR_BEACON_PERIOD_S 0 /* Byte offset of PERIOD start*/ +#define AR_BEACON_TIM 0x007F0000 /* Byte offset of TIM start */ +#define AR_BEACON_TIM_S 16 /* Byte offset of TIM start */ +#define AR_BEACON_EN 0x00800000 /* beacon enable */ +#define AR_BEACON_RESET_TSF 0x01000000 /* Clears TSF to 0 */ +#define AR_BEACON_BITS "\20\27ENABLE\30RESET_TSF" + +#define AR_RX_FILTER_ALL 0x00000000 /* Disallow all frames */ +#define AR_RX_UCAST 0x00000001 /* Allow unicast frames */ +#define AR_RX_MCAST 0x00000002 /* Allow multicast frames */ +#define AR_RX_BCAST 0x00000004 /* Allow broadcast frames */ +#define AR_RX_CONTROL 0x00000008 /* Allow control frames */ +#define AR_RX_BEACON 0x00000010 /* Allow beacon frames */ +#define AR_RX_PROM 0x00000020 /* Promiscuous mode */ +#define AR_RX_PHY_ERR 0x00000040 /* Allow all phy errors */ +#define AR_RX_PHY_RADAR 0x00000080 /* Allow radar phy errors */ +#define AR_RX_FILTER_BITS \ + "\20\1UCAST\2MCAST\3BCAST\4CONTROL\5BEACON\6PROMISC\7PHY_ERR\10PHY_RADAR" + +#define AR_DIAG_SW_CACHE_ACK 0x00000001 /* disable ACK if no valid key*/ +#define AR_DIAG_SW_DIS_ACK 0x00000002 /* disable ACK generation */ +#define AR_DIAG_SW_DIS_CTS 0x00000004 /* disable CTS generation */ +#define AR_DIAG_SW_DIS_ENCRYPT 0x00000008 /* disable encryption */ +#define AR_DIAG_SW_DIS_DECRYPT 0x00000010 /* disable decryption */ +#define AR_DIAG_SW_DIS_RX 0x00000020 /* disable receive */ +#define AR_DIAG_SW_CORR_FCS 0x00000080 /* corrupt FCS */ +#define AR_DIAG_SW_CHAN_INFO 0x00000100 /* dump channel info */ +#define AR_DIAG_SW_EN_SCRAMSD 0x00000200 /* enable fixed scrambler seed*/ +#define AR5311_DIAG_SW_USE_ECO 0x00000400 /* "super secret" use ECO enable bit */ +#define AR_DIAG_SW_SCRAM_SEED_M 0x0001FC00 /* Fixed scrambler seed mask */ +#define AR_DIAG_SW_SCRAM_SEED_S 10 /* Fixed scrambler seed shfit */ +#define AR_DIAG_SW_FRAME_NV0 0x00020000 /* accept frames of non-zero protocol version */ +#define AR_DIAG_SW_OBS_PT_SEL_M 0x000C0000 /* Observation point select */ +#define AR_DIAG_SW_OBS_PT_SEL_S 18 /* Observation point select */ +#define AR_DIAG_SW_BITS \ + "\20\1DIS_CACHE_ACK\2DIS_ACK\3DIS_CTS\4DIS_ENC\5DIS_DEC\6DIS_RX"\ + "\11CORR_FCS\12CHAN_INFO\13EN_SCRAM_SEED\14USE_ECO\24FRAME_NV0" + +#define AR_KEYTABLE_KEY0(n) (AR_KEYTABLE(n) + 0) /* key bit 0-31 */ +#define AR_KEYTABLE_KEY1(n) (AR_KEYTABLE(n) + 4) /* key bit 32-47 */ +#define AR_KEYTABLE_KEY2(n) (AR_KEYTABLE(n) + 8) /* key bit 48-79 */ +#define AR_KEYTABLE_KEY3(n) (AR_KEYTABLE(n) + 12) /* key bit 80-95 */ +#define AR_KEYTABLE_KEY4(n) (AR_KEYTABLE(n) + 16) /* key bit 96-127 */ +#define AR_KEYTABLE_TYPE(n) (AR_KEYTABLE(n) + 20) /* key type */ +#define AR_KEYTABLE_TYPE_40 0x00000000 /* WEP 40 bit key */ +#define AR_KEYTABLE_TYPE_104 0x00000001 /* WEP 104 bit key */ +#define AR_KEYTABLE_TYPE_128 0x00000003 /* WEP 128 bit key */ +#define AR_KEYTABLE_TYPE_AES 0x00000005 /* AES 128 bit key */ +#define AR_KEYTABLE_TYPE_CLR 0x00000007 /* no encryption */ +#define AR_KEYTABLE_MAC0(n) (AR_KEYTABLE(n) + 24) /* MAC address 1-32 */ +#define AR_KEYTABLE_MAC1(n) (AR_KEYTABLE(n) + 28) /* MAC address 33-47 */ +#define AR_KEYTABLE_VALID 0x00008000 /* key and MAC address valid */ + +#endif /* _DEV_ATH_AR5211REG_H */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5211/boss.ini b/sys/dev/netif/ath/hal/ath_hal/ar5211/boss.ini new file mode 100644 index 0000000000..a041c440ab --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5211/boss.ini @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: boss.ini,v 1.3 2008/11/10 04:08:03 sam Exp $ + */ +/* Auto Generated PCI Register Writes. Created: 09/12/02 */ + +static const uint32_t ar5211Modes[][5] = { + { 0x00000030, 0x00000015, 0x00000015, 0x0000001d, 0x00000015 }, + { 0x00001040, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x00001070, 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 }, + { 0x00001030, 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 }, + { 0x000010b0, 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 }, + { 0x000010f0, 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 }, + { 0x00008014, 0x04000400, 0x08000800, 0x20003000, 0x04000400 }, + { 0x0000801c, 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 }, + { 0x00009804, 0x00000000, 0x00000003, 0x00000000, 0x00000000 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02010200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b }, + { 0x00009844, 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c }, + { 0x00009848, 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 }, + { 0x00009850, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 }, + { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e }, + { 0x0000985c, 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e }, + { 0x00009860, 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 }, + { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009914, 0x00002710, 0x00002710, 0x0000157c, 0x00002710 }, + { 0x00009918, 0x00000190, 0x00000190, 0x00000084, 0x00000190 }, + { 0x00009944, 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 }, + { 0x0000a180, 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff }, + { 0x000098d4, 0x00000010, 0x00000014, 0x00000010, 0x00000010 }, +}; + +static const uint32_t ar5211Common[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000028, 0x84849c9c }, + { 0x0000002c, 0x7c7c7c7c }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001230, 0x00000000 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000000 }, + { 0x00008024, 0x00000000 }, + { 0x00008028, 0x00000030 }, + { 0x0000802c, 0x0007ffff }, + { 0x00008030, 0x01ffffff }, + { 0x00008034, 0x00000031 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008040, 0x00000000 }, + { 0x00008044, 0x00000002 }, + { 0x00008048, 0x00000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0x2d849093 }, + { 0x00009810, 0x7d32e000 }, + { 0x00009814, 0x00000f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x00026ffe }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00020100 }, + { 0x00009840, 0x206a017a }, + { 0x0000984c, 0x1284613c }, + { 0x00009854, 0x00000859 }, + { 0x00009868, 0x409a4190 }, + { 0x0000986c, 0x050cb081 }, + { 0x00009870, 0x0000000f }, + { 0x00009874, 0x00000080 }, + { 0x00009878, 0x0000000c }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00800000 }, + { 0x00009910, 0x00000001 }, + { 0x0000991c, 0x0000092a }, + { 0x00009920, 0x00000000 }, + { 0x00009924, 0x00058a05 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000000 }, + { 0x00009930, 0x00000000 }, + { 0x00009934, 0x00000000 }, + { 0x00009938, 0x00000000 }, + { 0x0000993c, 0x0000003f }, + { 0x00009940, 0x00000004 }, + { 0x00009948, 0x00000000 }, + { 0x0000994c, 0x00000000 }, + { 0x00009950, 0x00000000 }, + { 0x00009954, 0x5d50f14c }, + { 0x00009958, 0x00000018 }, + { 0x0000995c, 0x004b6a8e }, + { 0x0000a184, 0x06ff05ff }, + { 0x0000a188, 0x07ff07ff }, + { 0x0000a18c, 0x08ff08ff }, + { 0x0000a190, 0x09ff09ff }, + { 0x0000a194, 0x0aff0aff }, + { 0x0000a198, 0x0bff0bff }, + { 0x0000a19c, 0x0cff0cff }, + { 0x0000a1a0, 0x0dff0dff }, + { 0x0000a1a4, 0x0fff0eff }, + { 0x0000a1a8, 0x12ff12ff }, + { 0x0000a1ac, 0x14ff13ff }, + { 0x0000a1b0, 0x16ff15ff }, + { 0x0000a1b4, 0x19ff17ff }, + { 0x0000a1b8, 0x1bff1aff }, + { 0x0000a1bc, 0x1eff1dff }, + { 0x0000a1c0, 0x23ff20ff }, + { 0x0000a1c4, 0x27ff25ff }, + { 0x0000a1c8, 0x2cff29ff }, + { 0x0000a1cc, 0x31ff2fff }, + { 0x0000a1d0, 0x37ff34ff }, + { 0x0000a1d4, 0x3aff3aff }, + { 0x0000a1d8, 0x3aff3aff }, + { 0x0000a1dc, 0x3aff3aff }, + { 0x0000a1e0, 0x3aff3aff }, + { 0x0000a1e4, 0x3aff3aff }, + { 0x0000a1e8, 0x3aff3aff }, + { 0x0000a1ec, 0x3aff3aff }, + { 0x0000a1f0, 0x3aff3aff }, + { 0x0000a1f4, 0x3aff3aff }, + { 0x0000a1f8, 0x3aff3aff }, + { 0x0000a1fc, 0x3aff3aff }, + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000020 }, + { 0x00009b08, 0x00000010 }, + { 0x00009b0c, 0x00000030 }, + { 0x00009b10, 0x00000008 }, + { 0x00009b14, 0x00000028 }, + { 0x00009b18, 0x00000004 }, + { 0x00009b1c, 0x00000024 }, + { 0x00009b20, 0x00000014 }, + { 0x00009b24, 0x00000034 }, + { 0x00009b28, 0x0000000c }, + { 0x00009b2c, 0x0000002c }, + { 0x00009b30, 0x00000002 }, + { 0x00009b34, 0x00000022 }, + { 0x00009b38, 0x00000012 }, + { 0x00009b3c, 0x00000032 }, + { 0x00009b40, 0x0000000a }, + { 0x00009b44, 0x0000002a }, + { 0x00009b48, 0x00000006 }, + { 0x00009b4c, 0x00000026 }, + { 0x00009b50, 0x00000016 }, + { 0x00009b54, 0x00000036 }, + { 0x00009b58, 0x0000000e }, + { 0x00009b5c, 0x0000002e }, + { 0x00009b60, 0x00000001 }, + { 0x00009b64, 0x00000021 }, + { 0x00009b68, 0x00000011 }, + { 0x00009b6c, 0x00000031 }, + { 0x00009b70, 0x00000009 }, + { 0x00009b74, 0x00000029 }, + { 0x00009b78, 0x00000005 }, + { 0x00009b7c, 0x00000025 }, + { 0x00009b80, 0x00000015 }, + { 0x00009b84, 0x00000035 }, + { 0x00009b88, 0x0000000d }, + { 0x00009b8c, 0x0000002d }, + { 0x00009b90, 0x00000003 }, + { 0x00009b94, 0x00000023 }, + { 0x00009b98, 0x00000013 }, + { 0x00009b9c, 0x00000033 }, + { 0x00009ba0, 0x0000000b }, + { 0x00009ba4, 0x0000002b }, + { 0x00009ba8, 0x0000002b }, + { 0x00009bac, 0x0000002b }, + { 0x00009bb0, 0x0000002b }, + { 0x00009bb4, 0x0000002b }, + { 0x00009bb8, 0x0000002b }, + { 0x00009bbc, 0x0000002b }, + { 0x00009bc0, 0x0000002b }, + { 0x00009bc4, 0x0000002b }, + { 0x00009bc8, 0x0000002b }, + { 0x00009bcc, 0x0000002b }, + { 0x00009bd0, 0x0000002b }, + { 0x00009bd4, 0x0000002b }, + { 0x00009bd8, 0x0000002b }, + { 0x00009bdc, 0x0000002b }, + { 0x00009be0, 0x0000002b }, + { 0x00009be4, 0x0000002b }, + { 0x00009be8, 0x0000002b }, + { 0x00009bec, 0x0000002b }, + { 0x00009bf0, 0x0000002b }, + { 0x00009bf4, 0x0000002b }, + { 0x00009bf8, 0x00000002 }, + { 0x00009bfc, 0x00000016 }, + { 0x000098d4, 0x00000020 }, + { 0x000098d8, 0x00601068 }, +}; + +static uint32_t ar5211Mode2_4[][3] = { + { 0x0000a204, 0x00000000, 0x00000000 }, + { 0x0000a208, 0x503e4646, 0x503e4646 }, + { 0x0000a20c, 0x6480416c, 0x6480416c }, + { 0x0000a210, 0x0199a003, 0x0199a003 }, + { 0x0000a214, 0x044cd610, 0x044cd610 }, + { 0x0000a218, 0x13800040, 0x13800040 }, + { 0x0000a21c, 0x1be00060, 0x1be00060 }, + { 0x0000a220, 0x0c53800a, 0x0c53800a }, + { 0x0000a224, 0x0014df3b, 0x0014df3b }, + { 0x0000a228, 0x000001b5, 0x000001b5 }, + { 0x0000a22c, 0x00000020, 0x00000020 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00380000, 0x00380000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x000400f9, 0x000400f9 }, + { 0x000098d4, 0x00000000, 0x00000004 }, +}; + +static const uint32_t ar5211BB_RfGain[][3] = { + { 0x00009a00, 0x000001a9, 0x00000000 }, + { 0x00009a04, 0x000001e9, 0x00000040 }, + { 0x00009a08, 0x00000029, 0x00000080 }, + { 0x00009a0c, 0x00000069, 0x00000150 }, + { 0x00009a10, 0x00000199, 0x00000190 }, + { 0x00009a14, 0x000001d9, 0x000001d0 }, + { 0x00009a18, 0x00000019, 0x00000010 }, + { 0x00009a1c, 0x00000059, 0x00000044 }, + { 0x00009a20, 0x00000099, 0x00000084 }, + { 0x00009a24, 0x000001a5, 0x00000148 }, + { 0x00009a28, 0x000001e5, 0x00000188 }, + { 0x00009a2c, 0x00000025, 0x000001c8 }, + { 0x00009a30, 0x000001c8, 0x00000014 }, + { 0x00009a34, 0x00000008, 0x00000042 }, + { 0x00009a38, 0x00000048, 0x00000082 }, + { 0x00009a3c, 0x00000088, 0x00000178 }, + { 0x00009a40, 0x00000198, 0x000001b8 }, + { 0x00009a44, 0x000001d8, 0x000001f8 }, + { 0x00009a48, 0x00000018, 0x00000012 }, + { 0x00009a4c, 0x00000058, 0x00000052 }, + { 0x00009a50, 0x00000098, 0x00000092 }, + { 0x00009a54, 0x000001a4, 0x0000017c }, + { 0x00009a58, 0x000001e4, 0x000001bc }, + { 0x00009a5c, 0x00000024, 0x000001fc }, + { 0x00009a60, 0x00000064, 0x0000000a }, + { 0x00009a64, 0x000000a4, 0x0000004a }, + { 0x00009a68, 0x000000e4, 0x0000008a }, + { 0x00009a6c, 0x0000010a, 0x0000015a }, + { 0x00009a70, 0x0000014a, 0x0000019a }, + { 0x00009a74, 0x0000018a, 0x000001da }, + { 0x00009a78, 0x000001ca, 0x0000000e }, + { 0x00009a7c, 0x0000000a, 0x0000004e }, + { 0x00009a80, 0x0000004a, 0x0000008e }, + { 0x00009a84, 0x0000008a, 0x0000015e }, + { 0x00009a88, 0x000001ba, 0x0000019e }, + { 0x00009a8c, 0x000001fa, 0x000001de }, + { 0x00009a90, 0x0000003a, 0x00000009 }, + { 0x00009a94, 0x0000007a, 0x00000049 }, + { 0x00009a98, 0x00000186, 0x00000089 }, + { 0x00009a9c, 0x000001c6, 0x00000179 }, + { 0x00009aa0, 0x00000006, 0x000001b9 }, + { 0x00009aa4, 0x00000046, 0x000001f9 }, + { 0x00009aa8, 0x00000086, 0x00000039 }, + { 0x00009aac, 0x000000c6, 0x00000079 }, + { 0x00009ab0, 0x000000c6, 0x000000b9 }, + { 0x00009ab4, 0x000000c6, 0x000001bd }, + { 0x00009ab8, 0x000000c6, 0x000001fd }, + { 0x00009abc, 0x000000c6, 0x0000003d }, + { 0x00009ac0, 0x000000c6, 0x0000007d }, + { 0x00009ac4, 0x000000c6, 0x000000bd }, + { 0x00009ac8, 0x000000c6, 0x000000fd }, + { 0x00009acc, 0x000000c6, 0x000000fd }, + { 0x00009ad0, 0x000000c6, 0x000000fd }, + { 0x00009ad4, 0x000000c6, 0x000000fd }, + { 0x00009ad8, 0x000000c6, 0x000000fd }, + { 0x00009adc, 0x000000c6, 0x000000fd }, + { 0x00009ae0, 0x000000c6, 0x000000fd }, + { 0x00009ae4, 0x000000c6, 0x000000fd }, + { 0x00009ae8, 0x000000c6, 0x000000fd }, + { 0x00009aec, 0x000000c6, 0x000000fd }, + { 0x00009af0, 0x000000c6, 0x000000fd }, + { 0x00009af4, 0x000000c6, 0x000000fd }, + { 0x00009af8, 0x000000c6, 0x000000fd }, + { 0x00009afc, 0x000000c6, 0x000000fd }, +}; + +static uint32_t ar5211Rf6n7[][3] = { + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x10000000, 0x10000000 }, + { 0x0000989c, 0x04000000, 0x04000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x0a000000 }, + { 0x0000989c, 0x00380080, 0x02380080 }, + { 0x0000989c, 0x00020006, 0x00000006 }, + { 0x0000989c, 0x00000092, 0x00000092 }, + { 0x0000989c, 0x000000a0, 0x000000a0 }, + { 0x0000989c, 0x00040007, 0x00040007 }, + { 0x000098d4, 0x0000001a, 0x0000001a }, + { 0x0000989c, 0x00000048, 0x00000048 }, + { 0x0000989c, 0x00000010, 0x00000010 }, + { 0x0000989c, 0x00000008, 0x00000008 }, + { 0x0000989c, 0x0000000f, 0x0000000f }, + { 0x0000989c, 0x000000f2, 0x00000062 }, + { 0x0000989c, 0x0000904f, 0x0000904c }, + { 0x0000989c, 0x0000125a, 0x0000129a }, + { 0x000098cc, 0x0000000e, 0x0000000f }, +}; + diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar2316.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar2316.c new file mode 100644 index 0000000000..c724a958d7 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar2316.c @@ -0,0 +1,767 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar2316.c,v 1.9 2008/11/15 22:15:46 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#include "ah_eeprom_v3.h" + +#define AH_5212_2316 +#include "ar5212/ar5212.ini" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +typedef RAW_DATA_STRUCT_2413 RAW_DATA_STRUCT_2316; +typedef RAW_DATA_PER_CHANNEL_2413 RAW_DATA_PER_CHANNEL_2316; +#define PWR_TABLE_SIZE_2316 PWR_TABLE_SIZE_2413 + +struct ar2316State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[PWR_TABLE_SIZE_2316]; + + uint32_t Bank1Data[N(ar5212Bank1_2316)]; + uint32_t Bank2Data[N(ar5212Bank2_2316)]; + uint32_t Bank3Data[N(ar5212Bank3_2316)]; + uint32_t Bank6Data[N(ar5212Bank6_2316)]; + uint32_t Bank7Data[N(ar5212Bank7_2316)]; + + /* + * Private state for reduced stack usage. + */ + /* filled out Vpd table for all pdGains (chanL) */ + uint16_t vpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (chanR) */ + uint16_t vpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (interpolated) */ + uint16_t vpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; +}; +#define AR2316(ah) ((struct ar2316State *) AH5212(ah)->ah_rfHal) + +extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static void +ar2316WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int regWrites) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HAL_INI_WRITE_ARRAY(ah, ar5212Modes_2316, modesIndex, regWrites); + HAL_INI_WRITE_ARRAY(ah, ar5212Common_2316, 1, regWrites); + HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_2316, freqIndex, regWrites); + + /* For AP51 */ + if (!ahp->ah_cwCalRequire) { + OS_REG_WRITE(ah, 0xa358, (OS_REG_READ(ah, 0xa358) & ~0x2)); + } else { + ahp->ah_cwCalRequire = AH_FALSE; + } +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + */ +static HAL_BOOL +ar2316SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + uint32_t channelSel = 0; + uint32_t bModeSynth = 0; + uint32_t aModeRefSel = 0; + uint32_t reg32 = 0; + + OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel); + + if (chan->channel < 4800) { + uint32_t txctl; + + if (((chan->channel - 2192) % 5) == 0) { + channelSel = ((chan->channel - 672) * 2 - 3040)/10; + bModeSynth = 0; + } else if (((chan->channel - 2224) % 5) == 0) { + channelSel = ((chan->channel - 704) * 2 - 3040) / 10; + bModeSynth = 1; + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u MHz\n", + __func__, chan->channel); + return AH_FALSE; + } + + channelSel = (channelSel << 2) & 0xff; + channelSel = ath_hal_reverseBits(channelSel, 8); + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (chan->channel == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else if ((chan->channel % 20) == 0 && chan->channel >= 5120) { + channelSel = ath_hal_reverseBits( + ((chan->channel - 4800) / 20 << 2), 8); + aModeRefSel = ath_hal_reverseBits(3, 2); + } else if ((chan->channel % 10) == 0) { + channelSel = ath_hal_reverseBits( + ((chan->channel - 4800) / 10 << 1), 8); + aModeRefSel = ath_hal_reverseBits(2, 2); + } else if ((chan->channel % 5) == 0) { + channelSel = ath_hal_reverseBits( + (chan->channel - 4800) / 5, 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", + __func__, chan->channel); + return AH_FALSE; + } + + reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 12) | 0x1; + OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff); + + reg32 >>= 8; + OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f); + + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + * + * REQUIRES: Access to the analog rf device + */ +static HAL_BOOL +ar2316SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t modesIndex, uint16_t *rfXpdGain) +{ +#define RF_BANK_SETUP(_priv, _ix, _col) do { \ + int i; \ + for (i = 0; i < N(ar5212Bank##_ix##_2316); i++) \ + (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_2316[i][_col];\ +} while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t ob2GHz = 0, db2GHz = 0; + struct ar2316State *priv = AR2316(ah); + int regWrites = 0; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: chan 0x%x flag 0x%x modesIndex 0x%x\n", + __func__, chan->channel, chan->channelFlags, modesIndex); + + HALASSERT(priv != AH_NULL); + + /* Setup rf parameters */ + switch (chan->channelFlags & CHANNEL_ALL) { + case CHANNEL_B: + ob2GHz = ee->ee_obFor24; + db2GHz = ee->ee_dbFor24; + break; + case CHANNEL_G: + case CHANNEL_108G: + ob2GHz = ee->ee_obFor24g; + db2GHz = ee->ee_dbFor24g; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + + /* Bank 1 Write */ + RF_BANK_SETUP(priv, 1, 1); + + /* Bank 2 Write */ + RF_BANK_SETUP(priv, 2, modesIndex); + + /* Bank 3 Write */ + RF_BANK_SETUP(priv, 3, modesIndex); + + /* Bank 6 Write */ + RF_BANK_SETUP(priv, 6, modesIndex); + + ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 178, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 175, 0); + + /* Bank 7 Setup */ + RF_BANK_SETUP(priv, 7, modesIndex); + + /* Write Analog registers */ + HAL_INI_WRITE_BANK(ah, ar5212Bank1_2316, priv->Bank1Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank2_2316, priv->Bank2Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank3_2316, priv->Bank3Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank6_2316, priv->Bank6Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank7_2316, priv->Bank7Data, regWrites); + + /* Now that we have reprogrammed rfgain value, clear the flag. */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + return AH_TRUE; +#undef RF_BANK_SETUP +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar2316GetRfBank(struct ath_hal *ah, int bank) +{ + struct ar2316State *priv = AR2316(ah); + + HALASSERT(priv != AH_NULL); + switch (bank) { + case 1: return priv->Bank1Data; + case 2: return priv->Bank2Data; + case 3: return priv->Bank3Data; + case 6: return priv->Bank6Data; + case 7: return priv->Bank7Data; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Return indices surrounding the value in sorted integer lists. + * + * NB: the input list is assumed to be sorted in ascending order + */ +static void +GetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize, + uint32_t *vlo, uint32_t *vhi) +{ + int16_t target = v; + const int16_t *ep = lp+listSize; + const int16_t *tp; + + /* + * Check first and last elements for out-of-bounds conditions. + */ + if (target < lp[0]) { + *vlo = *vhi = 0; + return; + } + if (target >= ep[-1]) { + *vlo = *vhi = listSize - 1; + return; + } + + /* look for value being near or between 2 values in list */ + for (tp = lp; tp < ep; tp++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (*tp == target) { + *vlo = *vhi = tp - (const int16_t *) lp; + return; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < tp[1]) { + *vlo = tp - (const int16_t *) lp; + *vhi = *vlo + 1; + return; + } + } +} + +/* + * Fill the Vpdlist for indices Pmax-Pmin + */ +static HAL_BOOL +ar2316FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t Pmax, + const int16_t *pwrList, const int16_t *VpdList, + uint16_t numIntercepts, uint16_t retVpdList[][64]) +{ + uint16_t ii, jj, kk; + int16_t currPwr = (int16_t)(2*Pmin); + /* since Pmin is pwr*2 and pwrList is 4*pwr */ + uint32_t idxL, idxR; + + ii = 0; + jj = 0; + + if (numIntercepts < 2) + return AH_FALSE; + + while (ii <= (uint16_t)(Pmax - Pmin)) { + GetLowerUpperIndex(currPwr, pwrList, numIntercepts, + &(idxL), &(idxR)); + if (idxR < 1) + idxR = 1; /* extrapolate below */ + if (idxL == (uint32_t)(numIntercepts - 1)) + idxL = numIntercepts - 2; /* extrapolate above */ + if (pwrList[idxL] == pwrList[idxR]) + kk = VpdList[idxL]; + else + kk = (uint16_t) + (((currPwr - pwrList[idxL])*VpdList[idxR]+ + (pwrList[idxR] - currPwr)*VpdList[idxL])/ + (pwrList[idxR] - pwrList[idxL])); + retVpdList[pdGainIdx][ii] = kk; + ii++; + currPwr += 2; /* half dB steps */ + } + + return AH_TRUE; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static int16_t +interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight) +{ + int16_t rv; + + if (srcRight != srcLeft) { + rv = ((target - srcLeft)*targetRight + + (srcRight - target)*targetLeft) / (srcRight - srcLeft); + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Uses the data points read from EEPROM to reconstruct the pdadc power table + * Called by ar2316SetPowerTable() + */ +static int +ar2316getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel, + const RAW_DATA_STRUCT_2316 *pRawDataset, + uint16_t pdGainOverlap_t2, + int16_t *pMinCalPower, uint16_t pPdGainBoundaries[], + uint16_t pPdGainValues[], uint16_t pPDADCValues[]) +{ + struct ar2316State *priv = AR2316(ah); +#define VpdTable_L priv->vpdTable_L +#define VpdTable_R priv->vpdTable_R +#define VpdTable_I priv->vpdTable_I + uint32_t ii, jj, kk; + int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */ + uint32_t idxL, idxR; + uint32_t numPdGainsUsed = 0; + /* + * If desired to support -ve power levels in future, just + * change pwr_I_0 to signed 5-bits. + */ + int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on. */ + int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on */ + uint16_t numVpd = 0; + uint16_t Vpd_step; + int16_t tmpVal ; + uint32_t sizeCurrVpdTable, maxIndex, tgtIndex; + + /* Get upper lower index */ + GetLowerUpperIndex(channel, pRawDataset->pChannels, + pRawDataset->numChannels, &(idxL), &(idxR)); + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain; + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]; + if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) { + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]; + } + Pmin_t2[numPdGainsUsed] = (int16_t) + (Pmin_t2[numPdGainsUsed] / 2); + Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]) + Pmax_t2[numPdGainsUsed] = + pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2); + ar2316FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L + ); + ar2316FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R + ); + for (kk = 0; kk < (uint16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) { + VpdTable_I[numPdGainsUsed][kk] = + interpolate_signed( + channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR], + (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]); + } + /* fill VpdTable_I for this pdGain */ + numPdGainsUsed++; + } + /* if this pdGain is used */ + } + + *pMinCalPower = Pmin_t2[0]; + kk = 0; /* index for the final table */ + for (ii = 0; ii < numPdGainsUsed; ii++) { + if (ii == (numPdGainsUsed - 1)) + pPdGainBoundaries[ii] = Pmax_t2[ii] + + PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB; + else + pPdGainBoundaries[ii] = (uint16_t) + ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 ); + if (pPdGainBoundaries[ii] > 63) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: clamp pPdGainBoundaries[%d] %d\n", + __func__, ii, pPdGainBoundaries[ii]);/*XXX*/ + pPdGainBoundaries[ii] = 63; + } + + /* Find starting index for this pdGain */ + if (ii == 0) + ss = 0; /* for the first pdGain, start from index 0 */ + else + ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) - + pdGainOverlap_t2; + Vpd_step = (uint16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + *-ve ss indicates need to extrapolate data below for this pdGain + */ + while (ss < 0) { + tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step); + pPDADCValues[kk++] = (uint16_t)((tmpVal < 0) ? 0 : tmpVal); + ss++; + } + + sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii]; + tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii]; + maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; + + while (ss < (int16_t)maxIndex) + pPDADCValues[kk++] = VpdTable_I[ii][ss++]; + + Vpd_step = (uint16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] - + VpdTable_I[ii][sizeCurrVpdTable-2]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + * for last gain, pdGainBoundary == Pmax_t2, so will + * have to extrapolate + */ + if (tgtIndex > maxIndex) { /* need to extrapolate above */ + while(ss < (int16_t)tgtIndex) { + tmpVal = (uint16_t) + (VpdTable_I[ii][sizeCurrVpdTable-1] + + (ss-maxIndex)*Vpd_step); + pPDADCValues[kk++] = (tmpVal > 127) ? + 127 : tmpVal; + ss++; + } + } /* extrapolated above */ + } /* for all pdGainUsed */ + + while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) { + pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1]; + ii++; + } + while (kk < 128) { + pPDADCValues[kk] = pPDADCValues[kk-1]; + kk++; + } + + return numPdGainsUsed; +#undef VpdTable_L +#undef VpdTable_R +#undef VpdTable_I +} + +static HAL_BOOL +ar2316SetPowerTable(struct ath_hal *ah, + int16_t *minPower, int16_t *maxPower, HAL_CHANNEL_INTERNAL *chan, + uint16_t *rfXpdGain) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2316 *pRawDataset = AH_NULL; + uint16_t pdGainOverlap_t2; + int16_t minCalPower2316_t2; + uint16_t *pdadcValues = ahp->ah_pcdacTable; + uint16_t gainBoundaries[4]; + uint32_t reg32, regoffset; + int i, numPdGainsUsed; +#ifndef AH_USE_INIPDGAIN + uint32_t tpcrg1; +#endif + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n", + __func__, chan->channel,chan->channelFlags); + + if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: illegal mode\n", __func__); + return AH_FALSE; + } + + pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5), + AR_PHY_TPCRG5_PD_GAIN_OVERLAP); + + numPdGainsUsed = ar2316getGainBoundariesAndPdadcsForPowers(ah, + chan->channel, pRawDataset, pdGainOverlap_t2, + &minCalPower2316_t2,gainBoundaries, rfXpdGain, pdadcValues); + HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3); + +#ifdef AH_USE_INIPDGAIN + /* + * Use pd_gains curve from eeprom; Atheros always uses + * the default curve from the ini file but some vendors + * (e.g. Zcomax) want to override this curve and not + * honoring their settings results in tx power 5dBm low. + */ + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, + (pRawDataset->pDataPerChannel[0].numPdGains - 1)); +#else + tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1); + tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN) + | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN); + switch (numPdGainsUsed) { + case 3: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING3; + tpcrg1 |= SM(rfXpdGain[2], AR_PHY_TPCRG1_PDGAIN_SETTING3); + /* fall thru... */ + case 2: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING2; + tpcrg1 |= SM(rfXpdGain[1], AR_PHY_TPCRG1_PDGAIN_SETTING2); + /* fall thru... */ + case 1: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING1; + tpcrg1 |= SM(rfXpdGain[0], AR_PHY_TPCRG1_PDGAIN_SETTING1); + break; + } +#ifdef AH_DEBUG + if (tpcrg1 != OS_REG_READ(ah, AR_PHY_TPCRG1)) + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: using non-default " + "pd_gains (default 0x%x, calculated 0x%x)\n", + __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1); +#endif + OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1); +#endif + + /* + * Note the pdadc table may not start at 0 dBm power, could be + * negative or greater than 0. Need to offset the power + * values by the amount of minPower for griffin + */ + if (minCalPower2316_t2 != 0) + ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower2316_t2); + else + ahp->ah_txPowerIndexOffset = 0; + + /* Finally, write the power values into the baseband power table */ + regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */ + for (i = 0; i < 32; i++) { + reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0) | + ((pdadcValues[4*i + 1] & 0xFF) << 8) | + ((pdadcValues[4*i + 2] & 0xFF) << 16) | + ((pdadcValues[4*i + 3] & 0xFF) << 24) ; + OS_REG_WRITE(ah, regoffset, reg32); + regoffset += 4; + } + + OS_REG_WRITE(ah, AR_PHY_TPCRG5, + SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | + SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | + SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | + SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | + SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); + + return AH_TRUE; +} + +static int16_t +ar2316GetMinPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2316 *data) +{ + uint32_t ii,jj; + uint16_t Pmin=0,numVpd; + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = data->pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + Pmin = data->pDataPerPDGain[jj].pwr_t4[0]; + return(Pmin); + } + } + return(Pmin); +} + +static int16_t +ar2316GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2316 *data) +{ + uint32_t ii; + uint16_t Pmax=0,numVpd; + + for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + /* work forwards cuase lowest pdGain for highest power */ + numVpd = data->pDataPerPDGain[ii].numVpd; + if (numVpd > 0) { + Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1]; + return(Pmax); + } + } + return(Pmax); +} + +static HAL_BOOL +ar2316GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, + int16_t *maxPow, int16_t *minPow) +{ + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2316 *pRawDataset = AH_NULL; + const RAW_DATA_PER_CHANNEL_2316 *data=AH_NULL; + uint16_t numChannels; + int totalD,totalF, totalMin,last, i; + + *maxPow = 0; + + if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else + return(AH_FALSE); + + numChannels = pRawDataset->numChannels; + data = pRawDataset->pDataPerChannel; + + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if (numChannels < 1) + return(AH_FALSE); + + if ((chan->channel < data[0].channelValue) || + (chan->channel > data[numChannels-1].channelValue)) { + if (chan->channel < data[0].channelValue) { + *maxPow = ar2316GetMaxPower(ah, &data[0]); + *minPow = ar2316GetMinPower(ah, &data[0]); + return(AH_TRUE); + } else { + *maxPow = ar2316GetMaxPower(ah, &data[numChannels - 1]); + *minPow = ar2316GetMinPower(ah, &data[numChannels - 1]); + return(AH_TRUE); + } + } + + /* Linearly interpolate the power value now */ + for (last=0,i=0; (ichannel > data[i].channelValue); + last = i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = ar2316GetMaxPower(ah, &data[i]) - ar2316GetMaxPower(ah, &data[last]); + *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + + ar2316GetMaxPower(ah, &data[last])*totalD)/totalD); + totalMin = ar2316GetMinPower(ah, &data[i]) - ar2316GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + + ar2316GetMinPower(ah, &data[last])*totalD)/totalD); + return(AH_TRUE); + } else { + if (chan->channel == data[i].channelValue) { + *maxPow = ar2316GetMaxPower(ah, &data[i]); + *minPow = ar2316GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar2316RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +/* + * Allocate memory for private state. + * Scratch Buffer will be reinitialized every reset so no need to zero now + */ +static HAL_BOOL +ar2316RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar2316State *priv; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar2316State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar2316RfDetach; + priv->base.writeRegs = ar2316WriteRegs; + priv->base.getRfBank = ar2316GetRfBank; + priv->base.setChannel = ar2316SetChannel; + priv->base.setRfRegs = ar2316SetRfRegs; + priv->base.setPowerTable = ar2316SetPowerTable; + priv->base.getChannelMaxMinPower = ar2316GetChannelMaxMinPower; + priv->base.getNfAdjust = ar5212GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + + ahp->ah_cwCalRequire = AH_TRUE; /* force initial cal */ + + return AH_TRUE; +} + +static HAL_BOOL +ar2316Probe(struct ath_hal *ah) +{ + return IS_2316(ah); +} +AH_RF(RF2316, ar2316Probe, ar2316RfAttach); diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar2317.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar2317.c new file mode 100644 index 0000000000..c83cff09d2 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar2317.c @@ -0,0 +1,744 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar2317.c,v 1.8 2008/11/15 22:15:46 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#include "ah_eeprom_v3.h" + +#define AH_5212_2317 +#include "ar5212/ar5212.ini" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +typedef RAW_DATA_STRUCT_2413 RAW_DATA_STRUCT_2317; +typedef RAW_DATA_PER_CHANNEL_2413 RAW_DATA_PER_CHANNEL_2317; +#define PWR_TABLE_SIZE_2317 PWR_TABLE_SIZE_2413 + +struct ar2317State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[PWR_TABLE_SIZE_2317]; + + uint32_t Bank1Data[N(ar5212Bank1_2317)]; + uint32_t Bank2Data[N(ar5212Bank2_2317)]; + uint32_t Bank3Data[N(ar5212Bank3_2317)]; + uint32_t Bank6Data[N(ar5212Bank6_2317)]; + uint32_t Bank7Data[N(ar5212Bank7_2317)]; + + /* + * Private state for reduced stack usage. + */ + /* filled out Vpd table for all pdGains (chanL) */ + uint16_t vpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (chanR) */ + uint16_t vpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (interpolated) */ + uint16_t vpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; +}; +#define AR2317(ah) ((struct ar2317State *) AH5212(ah)->ah_rfHal) + +extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static void +ar2317WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + HAL_INI_WRITE_ARRAY(ah, ar5212Modes_2317, modesIndex, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212Common_2317, 1, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_2317, freqIndex, writes); +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + */ +static HAL_BOOL +ar2317SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + uint32_t channelSel = 0; + uint32_t bModeSynth = 0; + uint32_t aModeRefSel = 0; + uint32_t reg32 = 0; + + OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel); + + if (chan->channel < 4800) { + uint32_t txctl; + channelSel = chan->channel - 2272 ; + channelSel = ath_hal_reverseBits(channelSel, 8); + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (chan->channel == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else if ((chan->channel % 20) == 0 && chan->channel >= 5120) { + channelSel = ath_hal_reverseBits( + ((chan->channel - 4800) / 20 << 2), 8); + aModeRefSel = ath_hal_reverseBits(3, 2); + } else if ((chan->channel % 10) == 0) { + channelSel = ath_hal_reverseBits( + ((chan->channel - 4800) / 10 << 1), 8); + aModeRefSel = ath_hal_reverseBits(2, 2); + } else if ((chan->channel % 5) == 0) { + channelSel = ath_hal_reverseBits( + (chan->channel - 4800) / 5, 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", + __func__, chan->channel); + return AH_FALSE; + } + + reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 12) | 0x1; + OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff); + + reg32 >>= 8; + OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f); + + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + * + * REQUIRES: Access to the analog rf device + */ +static HAL_BOOL +ar2317SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t modesIndex, uint16_t *rfXpdGain) +{ +#define RF_BANK_SETUP(_priv, _ix, _col) do { \ + int i; \ + for (i = 0; i < N(ar5212Bank##_ix##_2317); i++) \ + (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_2317[i][_col];\ +} while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t ob2GHz = 0, db2GHz = 0; + struct ar2317State *priv = AR2317(ah); + int regWrites = 0; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: chan 0x%x flag 0x%x modesIndex 0x%x\n", + __func__, chan->channel, chan->channelFlags, modesIndex); + + HALASSERT(priv); + + /* Setup rf parameters */ + switch (chan->channelFlags & CHANNEL_ALL) { + case CHANNEL_B: + ob2GHz = ee->ee_obFor24; + db2GHz = ee->ee_dbFor24; + break; + case CHANNEL_G: + case CHANNEL_108G: + ob2GHz = ee->ee_obFor24g; + db2GHz = ee->ee_dbFor24g; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + + /* Bank 1 Write */ + RF_BANK_SETUP(priv, 1, 1); + + /* Bank 2 Write */ + RF_BANK_SETUP(priv, 2, modesIndex); + + /* Bank 3 Write */ + RF_BANK_SETUP(priv, 3, modesIndex); + + /* Bank 6 Write */ + RF_BANK_SETUP(priv, 6, modesIndex); + + ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 193, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 190, 0); + + /* Bank 7 Setup */ + RF_BANK_SETUP(priv, 7, modesIndex); + + /* Write Analog registers */ + HAL_INI_WRITE_BANK(ah, ar5212Bank1_2317, priv->Bank1Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank2_2317, priv->Bank2Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank3_2317, priv->Bank3Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank6_2317, priv->Bank6Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank7_2317, priv->Bank7Data, regWrites); + /* Now that we have reprogrammed rfgain value, clear the flag. */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + return AH_TRUE; +#undef RF_BANK_SETUP +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar2317GetRfBank(struct ath_hal *ah, int bank) +{ + struct ar2317State *priv = AR2317(ah); + + HALASSERT(priv != AH_NULL); + switch (bank) { + case 1: return priv->Bank1Data; + case 2: return priv->Bank2Data; + case 3: return priv->Bank3Data; + case 6: return priv->Bank6Data; + case 7: return priv->Bank7Data; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Return indices surrounding the value in sorted integer lists. + * + * NB: the input list is assumed to be sorted in ascending order + */ +static void +GetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize, + uint32_t *vlo, uint32_t *vhi) +{ + int16_t target = v; + const int16_t *ep = lp+listSize; + const int16_t *tp; + + /* + * Check first and last elements for out-of-bounds conditions. + */ + if (target < lp[0]) { + *vlo = *vhi = 0; + return; + } + if (target >= ep[-1]) { + *vlo = *vhi = listSize - 1; + return; + } + + /* look for value being near or between 2 values in list */ + for (tp = lp; tp < ep; tp++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (*tp == target) { + *vlo = *vhi = tp - (const int16_t *) lp; + return; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < tp[1]) { + *vlo = tp - (const int16_t *) lp; + *vhi = *vlo + 1; + return; + } + } +} + +/* + * Fill the Vpdlist for indices Pmax-Pmin + */ +static HAL_BOOL +ar2317FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t Pmax, + const int16_t *pwrList, const int16_t *VpdList, + uint16_t numIntercepts, uint16_t retVpdList[][64]) +{ + uint16_t ii, jj, kk; + int16_t currPwr = (int16_t)(2*Pmin); + /* since Pmin is pwr*2 and pwrList is 4*pwr */ + uint32_t idxL, idxR; + + ii = 0; + jj = 0; + + if (numIntercepts < 2) + return AH_FALSE; + + while (ii <= (uint16_t)(Pmax - Pmin)) { + GetLowerUpperIndex(currPwr, pwrList, numIntercepts, + &(idxL), &(idxR)); + if (idxR < 1) + idxR = 1; /* extrapolate below */ + if (idxL == (uint32_t)(numIntercepts - 1)) + idxL = numIntercepts - 2; /* extrapolate above */ + if (pwrList[idxL] == pwrList[idxR]) + kk = VpdList[idxL]; + else + kk = (uint16_t) + (((currPwr - pwrList[idxL])*VpdList[idxR]+ + (pwrList[idxR] - currPwr)*VpdList[idxL])/ + (pwrList[idxR] - pwrList[idxL])); + retVpdList[pdGainIdx][ii] = kk; + ii++; + currPwr += 2; /* half dB steps */ + } + + return AH_TRUE; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static int16_t +interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight) +{ + int16_t rv; + + if (srcRight != srcLeft) { + rv = ((target - srcLeft)*targetRight + + (srcRight - target)*targetLeft) / (srcRight - srcLeft); + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Uses the data points read from EEPROM to reconstruct the pdadc power table + * Called by ar2317SetPowerTable() + */ +static int +ar2317getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel, + const RAW_DATA_STRUCT_2317 *pRawDataset, + uint16_t pdGainOverlap_t2, + int16_t *pMinCalPower, uint16_t pPdGainBoundaries[], + uint16_t pPdGainValues[], uint16_t pPDADCValues[]) +{ + struct ar2317State *priv = AR2317(ah); +#define VpdTable_L priv->vpdTable_L +#define VpdTable_R priv->vpdTable_R +#define VpdTable_I priv->vpdTable_I + /* XXX excessive stack usage? */ + uint32_t ii, jj, kk; + int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */ + uint32_t idxL, idxR; + uint32_t numPdGainsUsed = 0; + /* + * If desired to support -ve power levels in future, just + * change pwr_I_0 to signed 5-bits. + */ + int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on. */ + int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on */ + uint16_t numVpd = 0; + uint16_t Vpd_step; + int16_t tmpVal ; + uint32_t sizeCurrVpdTable, maxIndex, tgtIndex; + + /* Get upper lower index */ + GetLowerUpperIndex(channel, pRawDataset->pChannels, + pRawDataset->numChannels, &(idxL), &(idxR)); + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain; + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]; + if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) { + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]; + } + Pmin_t2[numPdGainsUsed] = (int16_t) + (Pmin_t2[numPdGainsUsed] / 2); + Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]) + Pmax_t2[numPdGainsUsed] = + pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2); + ar2317FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L + ); + ar2317FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R + ); + for (kk = 0; kk < (uint16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) { + VpdTable_I[numPdGainsUsed][kk] = + interpolate_signed( + channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR], + (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]); + } + /* fill VpdTable_I for this pdGain */ + numPdGainsUsed++; + } + /* if this pdGain is used */ + } + + *pMinCalPower = Pmin_t2[0]; + kk = 0; /* index for the final table */ + for (ii = 0; ii < numPdGainsUsed; ii++) { + if (ii == (numPdGainsUsed - 1)) + pPdGainBoundaries[ii] = Pmax_t2[ii] + + PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB; + else + pPdGainBoundaries[ii] = (uint16_t) + ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 ); + if (pPdGainBoundaries[ii] > 63) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: clamp pPdGainBoundaries[%d] %d\n", + __func__, ii, pPdGainBoundaries[ii]);/*XXX*/ + pPdGainBoundaries[ii] = 63; + } + + /* Find starting index for this pdGain */ + if (ii == 0) + ss = 0; /* for the first pdGain, start from index 0 */ + else + ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) - + pdGainOverlap_t2; + Vpd_step = (uint16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + *-ve ss indicates need to extrapolate data below for this pdGain + */ + while (ss < 0) { + tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step); + pPDADCValues[kk++] = (uint16_t)((tmpVal < 0) ? 0 : tmpVal); + ss++; + } + + sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii]; + tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii]; + maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; + + while (ss < (int16_t)maxIndex) + pPDADCValues[kk++] = VpdTable_I[ii][ss++]; + + Vpd_step = (uint16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] - + VpdTable_I[ii][sizeCurrVpdTable-2]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + * for last gain, pdGainBoundary == Pmax_t2, so will + * have to extrapolate + */ + if (tgtIndex > maxIndex) { /* need to extrapolate above */ + while(ss < (int16_t)tgtIndex) { + tmpVal = (uint16_t) + (VpdTable_I[ii][sizeCurrVpdTable-1] + + (ss-maxIndex)*Vpd_step); + pPDADCValues[kk++] = (tmpVal > 127) ? + 127 : tmpVal; + ss++; + } + } /* extrapolated above */ + } /* for all pdGainUsed */ + + while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) { + pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1]; + ii++; + } + while (kk < 128) { + pPDADCValues[kk] = pPDADCValues[kk-1]; + kk++; + } + + return numPdGainsUsed; +#undef VpdTable_L +#undef VpdTable_R +#undef VpdTable_I +} + +static HAL_BOOL +ar2317SetPowerTable(struct ath_hal *ah, + int16_t *minPower, int16_t *maxPower, HAL_CHANNEL_INTERNAL *chan, + uint16_t *rfXpdGain) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2317 *pRawDataset = AH_NULL; + uint16_t pdGainOverlap_t2; + int16_t minCalPower2317_t2; + uint16_t *pdadcValues = ahp->ah_pcdacTable; + uint16_t gainBoundaries[4]; + uint32_t reg32, regoffset; + int i, numPdGainsUsed; +#ifndef AH_USE_INIPDGAIN + uint32_t tpcrg1; +#endif + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n", + __func__, chan->channel,chan->channelFlags); + + if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: illegal mode\n", __func__); + return AH_FALSE; + } + + pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5), + AR_PHY_TPCRG5_PD_GAIN_OVERLAP); + + numPdGainsUsed = ar2317getGainBoundariesAndPdadcsForPowers(ah, + chan->channel, pRawDataset, pdGainOverlap_t2, + &minCalPower2317_t2,gainBoundaries, rfXpdGain, pdadcValues); + HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3); + +#ifdef AH_USE_INIPDGAIN + /* + * Use pd_gains curve from eeprom; Atheros always uses + * the default curve from the ini file but some vendors + * (e.g. Zcomax) want to override this curve and not + * honoring their settings results in tx power 5dBm low. + */ + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, + (pRawDataset->pDataPerChannel[0].numPdGains - 1)); +#else + tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1); + tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN) + | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN); + switch (numPdGainsUsed) { + case 3: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING3; + tpcrg1 |= SM(rfXpdGain[2], AR_PHY_TPCRG1_PDGAIN_SETTING3); + /* fall thru... */ + case 2: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING2; + tpcrg1 |= SM(rfXpdGain[1], AR_PHY_TPCRG1_PDGAIN_SETTING2); + /* fall thru... */ + case 1: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING1; + tpcrg1 |= SM(rfXpdGain[0], AR_PHY_TPCRG1_PDGAIN_SETTING1); + break; + } +#ifdef AH_DEBUG + if (tpcrg1 != OS_REG_READ(ah, AR_PHY_TPCRG1)) + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: using non-default " + "pd_gains (default 0x%x, calculated 0x%x)\n", + __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1); +#endif + OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1); +#endif + + /* + * Note the pdadc table may not start at 0 dBm power, could be + * negative or greater than 0. Need to offset the power + * values by the amount of minPower for griffin + */ + if (minCalPower2317_t2 != 0) + ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower2317_t2); + else + ahp->ah_txPowerIndexOffset = 0; + + /* Finally, write the power values into the baseband power table */ + regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */ + for (i = 0; i < 32; i++) { + reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0) | + ((pdadcValues[4*i + 1] & 0xFF) << 8) | + ((pdadcValues[4*i + 2] & 0xFF) << 16) | + ((pdadcValues[4*i + 3] & 0xFF) << 24) ; + OS_REG_WRITE(ah, regoffset, reg32); + regoffset += 4; + } + + OS_REG_WRITE(ah, AR_PHY_TPCRG5, + SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | + SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | + SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | + SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | + SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); + + return AH_TRUE; +} + +static int16_t +ar2317GetMinPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2317 *data) +{ + uint32_t ii,jj; + uint16_t Pmin=0,numVpd; + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = data->pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + Pmin = data->pDataPerPDGain[jj].pwr_t4[0]; + return(Pmin); + } + } + return(Pmin); +} + +static int16_t +ar2317GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2317 *data) +{ + uint32_t ii; + uint16_t Pmax=0,numVpd; + uint16_t vpdmax; + + for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + /* work forwards cuase lowest pdGain for highest power */ + numVpd = data->pDataPerPDGain[ii].numVpd; + if (numVpd > 0) { + Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1]; + vpdmax = data->pDataPerPDGain[ii].Vpd[numVpd-1]; + return(Pmax); + } + } + return(Pmax); +} + +static HAL_BOOL +ar2317GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, + int16_t *maxPow, int16_t *minPow) +{ + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2317 *pRawDataset = AH_NULL; + const RAW_DATA_PER_CHANNEL_2317 *data=AH_NULL; + uint16_t numChannels; + int totalD,totalF, totalMin,last, i; + + *maxPow = 0; + + if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else + return(AH_FALSE); + + numChannels = pRawDataset->numChannels; + data = pRawDataset->pDataPerChannel; + + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if (numChannels < 1) + return(AH_FALSE); + + if ((chan->channel < data[0].channelValue) || + (chan->channel > data[numChannels-1].channelValue)) { + if (chan->channel < data[0].channelValue) { + *maxPow = ar2317GetMaxPower(ah, &data[0]); + *minPow = ar2317GetMinPower(ah, &data[0]); + return(AH_TRUE); + } else { + *maxPow = ar2317GetMaxPower(ah, &data[numChannels - 1]); + *minPow = ar2317GetMinPower(ah, &data[numChannels - 1]); + return(AH_TRUE); + } + } + + /* Linearly interpolate the power value now */ + for (last=0,i=0; (ichannel > data[i].channelValue); + last = i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = ar2317GetMaxPower(ah, &data[i]) - ar2317GetMaxPower(ah, &data[last]); + *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + + ar2317GetMaxPower(ah, &data[last])*totalD)/totalD); + totalMin = ar2317GetMinPower(ah, &data[i]) - ar2317GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + + ar2317GetMinPower(ah, &data[last])*totalD)/totalD); + return(AH_TRUE); + } else { + if (chan->channel == data[i].channelValue) { + *maxPow = ar2317GetMaxPower(ah, &data[i]); + *minPow = ar2317GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar2317RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +/* + * Allocate memory for analog bank scratch buffers + * Scratch Buffer will be reinitialized every reset so no need to zero now + */ +static HAL_BOOL +ar2317RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar2317State *priv; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar2317State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar2317RfDetach; + priv->base.writeRegs = ar2317WriteRegs; + priv->base.getRfBank = ar2317GetRfBank; + priv->base.setChannel = ar2317SetChannel; + priv->base.setRfRegs = ar2317SetRfRegs; + priv->base.setPowerTable = ar2317SetPowerTable; + priv->base.getChannelMaxMinPower = ar2317GetChannelMaxMinPower; + priv->base.getNfAdjust = ar5212GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + + return AH_TRUE; +} + +static HAL_BOOL +ar2317Probe(struct ath_hal *ah) +{ + return IS_2317(ah); +} +AH_RF(RF2317, ar2317Probe, ar2317RfAttach); diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar2413.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar2413.c new file mode 100644 index 0000000000..a9e4686372 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar2413.c @@ -0,0 +1,759 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar2413.c,v 1.8 2008/11/15 22:15:46 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#include "ah_eeprom_v3.h" + +#define AH_5212_2413 +#include "ar5212/ar5212.ini" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +struct ar2413State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[PWR_TABLE_SIZE_2413]; + + uint32_t Bank1Data[N(ar5212Bank1_2413)]; + uint32_t Bank2Data[N(ar5212Bank2_2413)]; + uint32_t Bank3Data[N(ar5212Bank3_2413)]; + uint32_t Bank6Data[N(ar5212Bank6_2413)]; + uint32_t Bank7Data[N(ar5212Bank7_2413)]; + + /* + * Private state for reduced stack usage. + */ + /* filled out Vpd table for all pdGains (chanL) */ + uint16_t vpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (chanR) */ + uint16_t vpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (interpolated) */ + uint16_t vpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; +}; +#define AR2413(ah) ((struct ar2413State *) AH5212(ah)->ah_rfHal) + +extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static void +ar2413WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + HAL_INI_WRITE_ARRAY(ah, ar5212Modes_2413, modesIndex, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212Common_2413, 1, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_2413, freqIndex, writes); +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + */ +static HAL_BOOL +ar2413SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + uint32_t channelSel = 0; + uint32_t bModeSynth = 0; + uint32_t aModeRefSel = 0; + uint32_t reg32 = 0; + uint16_t freq; + + OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel); + + if (chan->channel < 4800) { + uint32_t txctl; + + if (((chan->channel - 2192) % 5) == 0) { + channelSel = ((chan->channel - 672) * 2 - 3040)/10; + bModeSynth = 0; + } else if (((chan->channel - 2224) % 5) == 0) { + channelSel = ((chan->channel - 704) * 2 - 3040) / 10; + bModeSynth = 1; + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u MHz\n", + __func__, chan->channel); + return AH_FALSE; + } + + channelSel = (channelSel << 2) & 0xff; + channelSel = ath_hal_reverseBits(channelSel, 8); + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (chan->channel == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else if (((chan->channel % 5) == 2) && (chan->channel <= 5435)) { + freq = chan->channel - 2; /* Align to even 5MHz raster */ + channelSel = ath_hal_reverseBits( + (uint32_t)(((freq - 4800)*10)/25 + 1), 8); + aModeRefSel = ath_hal_reverseBits(0, 2); + } else if ((chan->channel % 20) == 0 && chan->channel >= 5120) { + channelSel = ath_hal_reverseBits( + ((chan->channel - 4800) / 20 << 2), 8); + aModeRefSel = ath_hal_reverseBits(3, 2); + } else if ((chan->channel % 10) == 0) { + channelSel = ath_hal_reverseBits( + ((chan->channel - 4800) / 10 << 1), 8); + aModeRefSel = ath_hal_reverseBits(2, 2); + } else if ((chan->channel % 5) == 0) { + channelSel = ath_hal_reverseBits( + (chan->channel - 4800) / 5, 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", + __func__, chan->channel); + return AH_FALSE; + } + + reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 12) | 0x1; + OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff); + + reg32 >>= 8; + OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f); + + AH_PRIVATE(ah)->ah_curchan = chan; + + return AH_TRUE; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + * + * REQUIRES: Access to the analog rf device + */ +static HAL_BOOL +ar2413SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t modesIndex, uint16_t *rfXpdGain) +{ +#define RF_BANK_SETUP(_priv, _ix, _col) do { \ + int i; \ + for (i = 0; i < N(ar5212Bank##_ix##_2413); i++) \ + (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_2413[i][_col];\ +} while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t ob2GHz = 0, db2GHz = 0; + struct ar2413State *priv = AR2413(ah); + int regWrites = 0; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: chan 0x%x flag 0x%x modesIndex 0x%x\n", + __func__, chan->channel, chan->channelFlags, modesIndex); + + HALASSERT(priv); + + /* Setup rf parameters */ + switch (chan->channelFlags & CHANNEL_ALL) { + case CHANNEL_B: + ob2GHz = ee->ee_obFor24; + db2GHz = ee->ee_dbFor24; + break; + case CHANNEL_G: + case CHANNEL_108G: + ob2GHz = ee->ee_obFor24g; + db2GHz = ee->ee_dbFor24g; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + + /* Bank 1 Write */ + RF_BANK_SETUP(priv, 1, 1); + + /* Bank 2 Write */ + RF_BANK_SETUP(priv, 2, modesIndex); + + /* Bank 3 Write */ + RF_BANK_SETUP(priv, 3, modesIndex); + + /* Bank 6 Write */ + RF_BANK_SETUP(priv, 6, modesIndex); + + ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 168, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 165, 0); + + /* Bank 7 Setup */ + RF_BANK_SETUP(priv, 7, modesIndex); + + /* Write Analog registers */ + HAL_INI_WRITE_BANK(ah, ar5212Bank1_2413, priv->Bank1Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank2_2413, priv->Bank2Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank3_2413, priv->Bank3Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank6_2413, priv->Bank6Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank7_2413, priv->Bank7Data, regWrites); + + /* Now that we have reprogrammed rfgain value, clear the flag. */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + return AH_TRUE; +#undef RF_BANK_SETUP +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar2413GetRfBank(struct ath_hal *ah, int bank) +{ + struct ar2413State *priv = AR2413(ah); + + HALASSERT(priv != AH_NULL); + switch (bank) { + case 1: return priv->Bank1Data; + case 2: return priv->Bank2Data; + case 3: return priv->Bank3Data; + case 6: return priv->Bank6Data; + case 7: return priv->Bank7Data; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Return indices surrounding the value in sorted integer lists. + * + * NB: the input list is assumed to be sorted in ascending order + */ +static void +GetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize, + uint32_t *vlo, uint32_t *vhi) +{ + int16_t target = v; + const uint16_t *ep = lp+listSize; + const uint16_t *tp; + + /* + * Check first and last elements for out-of-bounds conditions. + */ + if (target < lp[0]) { + *vlo = *vhi = 0; + return; + } + if (target >= ep[-1]) { + *vlo = *vhi = listSize - 1; + return; + } + + /* look for value being near or between 2 values in list */ + for (tp = lp; tp < ep; tp++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (*tp == target) { + *vlo = *vhi = tp - (const uint16_t *) lp; + return; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < tp[1]) { + *vlo = tp - (const uint16_t *) lp; + *vhi = *vlo + 1; + return; + } + } +} + +/* + * Fill the Vpdlist for indices Pmax-Pmin + */ +static HAL_BOOL +ar2413FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t Pmax, + const int16_t *pwrList, const uint16_t *VpdList, + uint16_t numIntercepts, uint16_t retVpdList[][64]) +{ + uint16_t ii, jj, kk; + int16_t currPwr = (int16_t)(2*Pmin); + /* since Pmin is pwr*2 and pwrList is 4*pwr */ + uint32_t idxL, idxR; + + ii = 0; + jj = 0; + + if (numIntercepts < 2) + return AH_FALSE; + + while (ii <= (uint16_t)(Pmax - Pmin)) { + GetLowerUpperIndex(currPwr, (const uint16_t *) pwrList, + numIntercepts, &(idxL), &(idxR)); + if (idxR < 1) + idxR = 1; /* extrapolate below */ + if (idxL == (uint32_t)(numIntercepts - 1)) + idxL = numIntercepts - 2; /* extrapolate above */ + if (pwrList[idxL] == pwrList[idxR]) + kk = VpdList[idxL]; + else + kk = (uint16_t) + (((currPwr - pwrList[idxL])*VpdList[idxR]+ + (pwrList[idxR] - currPwr)*VpdList[idxL])/ + (pwrList[idxR] - pwrList[idxL])); + retVpdList[pdGainIdx][ii] = kk; + ii++; + currPwr += 2; /* half dB steps */ + } + + return AH_TRUE; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static int16_t +interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight) +{ + int16_t rv; + + if (srcRight != srcLeft) { + rv = ((target - srcLeft)*targetRight + + (srcRight - target)*targetLeft) / (srcRight - srcLeft); + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Uses the data points read from EEPROM to reconstruct the pdadc power table + * Called by ar2413SetPowerTable() + */ +static int +ar2413getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel, + const RAW_DATA_STRUCT_2413 *pRawDataset, + uint16_t pdGainOverlap_t2, + int16_t *pMinCalPower, uint16_t pPdGainBoundaries[], + uint16_t pPdGainValues[], uint16_t pPDADCValues[]) +{ + struct ar2413State *priv = AR2413(ah); +#define VpdTable_L priv->vpdTable_L +#define VpdTable_R priv->vpdTable_R +#define VpdTable_I priv->vpdTable_I + uint32_t ii, jj, kk; + int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */ + uint32_t idxL, idxR; + uint32_t numPdGainsUsed = 0; + /* + * If desired to support -ve power levels in future, just + * change pwr_I_0 to signed 5-bits. + */ + int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on. */ + int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on */ + uint16_t numVpd = 0; + uint16_t Vpd_step; + int16_t tmpVal ; + uint32_t sizeCurrVpdTable, maxIndex, tgtIndex; + + /* Get upper lower index */ + GetLowerUpperIndex(channel, pRawDataset->pChannels, + pRawDataset->numChannels, &(idxL), &(idxR)); + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain; + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]; + if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) { + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]; + } + Pmin_t2[numPdGainsUsed] = (int16_t) + (Pmin_t2[numPdGainsUsed] / 2); + Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]) + Pmax_t2[numPdGainsUsed] = + pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2); + ar2413FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L + ); + ar2413FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R + ); + for (kk = 0; kk < (uint16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) { + VpdTable_I[numPdGainsUsed][kk] = + interpolate_signed( + channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR], + (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]); + } + /* fill VpdTable_I for this pdGain */ + numPdGainsUsed++; + } + /* if this pdGain is used */ + } + + *pMinCalPower = Pmin_t2[0]; + kk = 0; /* index for the final table */ + for (ii = 0; ii < numPdGainsUsed; ii++) { + if (ii == (numPdGainsUsed - 1)) + pPdGainBoundaries[ii] = Pmax_t2[ii] + + PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB; + else + pPdGainBoundaries[ii] = (uint16_t) + ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 ); + if (pPdGainBoundaries[ii] > 63) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: clamp pPdGainBoundaries[%d] %d\n", + __func__, ii, pPdGainBoundaries[ii]);/*XXX*/ + pPdGainBoundaries[ii] = 63; + } + + /* Find starting index for this pdGain */ + if (ii == 0) + ss = 0; /* for the first pdGain, start from index 0 */ + else + ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) - + pdGainOverlap_t2; + Vpd_step = (uint16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + *-ve ss indicates need to extrapolate data below for this pdGain + */ + while (ss < 0) { + tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step); + pPDADCValues[kk++] = (uint16_t)((tmpVal < 0) ? 0 : tmpVal); + ss++; + } + + sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii]; + tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii]; + maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; + + while (ss < (int16_t)maxIndex) + pPDADCValues[kk++] = VpdTable_I[ii][ss++]; + + Vpd_step = (uint16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] - + VpdTable_I[ii][sizeCurrVpdTable-2]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + * for last gain, pdGainBoundary == Pmax_t2, so will + * have to extrapolate + */ + if (tgtIndex > maxIndex) { /* need to extrapolate above */ + while(ss < (int16_t)tgtIndex) { + tmpVal = (uint16_t) + (VpdTable_I[ii][sizeCurrVpdTable-1] + + (ss-maxIndex)*Vpd_step); + pPDADCValues[kk++] = (tmpVal > 127) ? + 127 : tmpVal; + ss++; + } + } /* extrapolated above */ + } /* for all pdGainUsed */ + + while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) { + pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1]; + ii++; + } + while (kk < 128) { + pPDADCValues[kk] = pPDADCValues[kk-1]; + kk++; + } + + return numPdGainsUsed; +#undef VpdTable_L +#undef VpdTable_R +#undef VpdTable_I +} + +static HAL_BOOL +ar2413SetPowerTable(struct ath_hal *ah, + int16_t *minPower, int16_t *maxPower, HAL_CHANNEL_INTERNAL *chan, + uint16_t *rfXpdGain) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL; + uint16_t pdGainOverlap_t2; + int16_t minCalPower2413_t2; + uint16_t *pdadcValues = ahp->ah_pcdacTable; + uint16_t gainBoundaries[4]; + uint32_t reg32, regoffset; + int i, numPdGainsUsed; +#ifndef AH_USE_INIPDGAIN + uint32_t tpcrg1; +#endif + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n", + __func__, chan->channel,chan->channelFlags); + + if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: illegal mode\n", __func__); + return AH_FALSE; + } + + pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5), + AR_PHY_TPCRG5_PD_GAIN_OVERLAP); + + numPdGainsUsed = ar2413getGainBoundariesAndPdadcsForPowers(ah, + chan->channel, pRawDataset, pdGainOverlap_t2, + &minCalPower2413_t2,gainBoundaries, rfXpdGain, pdadcValues); + HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3); + +#ifdef AH_USE_INIPDGAIN + /* + * Use pd_gains curve from eeprom; Atheros always uses + * the default curve from the ini file but some vendors + * (e.g. Zcomax) want to override this curve and not + * honoring their settings results in tx power 5dBm low. + */ + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, + (pRawDataset->pDataPerChannel[0].numPdGains - 1)); +#else + tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1); + tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN) + | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN); + switch (numPdGainsUsed) { + case 3: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING3; + tpcrg1 |= SM(rfXpdGain[2], AR_PHY_TPCRG1_PDGAIN_SETTING3); + /* fall thru... */ + case 2: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING2; + tpcrg1 |= SM(rfXpdGain[1], AR_PHY_TPCRG1_PDGAIN_SETTING2); + /* fall thru... */ + case 1: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING1; + tpcrg1 |= SM(rfXpdGain[0], AR_PHY_TPCRG1_PDGAIN_SETTING1); + break; + } +#ifdef AH_DEBUG + if (tpcrg1 != OS_REG_READ(ah, AR_PHY_TPCRG1)) + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: using non-default " + "pd_gains (default 0x%x, calculated 0x%x)\n", + __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1); +#endif + OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1); +#endif + + /* + * Note the pdadc table may not start at 0 dBm power, could be + * negative or greater than 0. Need to offset the power + * values by the amount of minPower for griffin + */ + if (minCalPower2413_t2 != 0) + ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower2413_t2); + else + ahp->ah_txPowerIndexOffset = 0; + + /* Finally, write the power values into the baseband power table */ + regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */ + for (i = 0; i < 32; i++) { + reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0) | + ((pdadcValues[4*i + 1] & 0xFF) << 8) | + ((pdadcValues[4*i + 2] & 0xFF) << 16) | + ((pdadcValues[4*i + 3] & 0xFF) << 24) ; + OS_REG_WRITE(ah, regoffset, reg32); + regoffset += 4; + } + + OS_REG_WRITE(ah, AR_PHY_TPCRG5, + SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | + SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | + SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | + SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | + SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); + + return AH_TRUE; +} + +static int16_t +ar2413GetMinPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) +{ + uint32_t ii,jj; + uint16_t Pmin=0,numVpd; + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = data->pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + Pmin = data->pDataPerPDGain[jj].pwr_t4[0]; + return(Pmin); + } + } + return(Pmin); +} + +static int16_t +ar2413GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) +{ + uint32_t ii; + uint16_t Pmax=0,numVpd; + + for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + /* work forwards cuase lowest pdGain for highest power */ + numVpd = data->pDataPerPDGain[ii].numVpd; + if (numVpd > 0) { + Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1]; + return(Pmax); + } + } + return(Pmax); +} + +static HAL_BOOL +ar2413GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, + int16_t *maxPow, int16_t *minPow) +{ + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL; + const RAW_DATA_PER_CHANNEL_2413 *data = AH_NULL; + uint16_t numChannels; + int totalD,totalF, totalMin,last, i; + + *maxPow = 0; + + if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else + return(AH_FALSE); + + numChannels = pRawDataset->numChannels; + data = pRawDataset->pDataPerChannel; + + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if (numChannels < 1) + return(AH_FALSE); + + if ((chan->channel < data[0].channelValue) || + (chan->channel > data[numChannels-1].channelValue)) { + if (chan->channel < data[0].channelValue) { + *maxPow = ar2413GetMaxPower(ah, &data[0]); + *minPow = ar2413GetMinPower(ah, &data[0]); + return(AH_TRUE); + } else { + *maxPow = ar2413GetMaxPower(ah, &data[numChannels - 1]); + *minPow = ar2413GetMinPower(ah, &data[numChannels - 1]); + return(AH_TRUE); + } + } + + /* Linearly interpolate the power value now */ + for (last=0,i=0; (ichannel > data[i].channelValue); + last = i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = ar2413GetMaxPower(ah, &data[i]) - ar2413GetMaxPower(ah, &data[last]); + *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + + ar2413GetMaxPower(ah, &data[last])*totalD)/totalD); + totalMin = ar2413GetMinPower(ah, &data[i]) - ar2413GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + + ar2413GetMinPower(ah, &data[last])*totalD)/totalD); + return(AH_TRUE); + } else { + if (chan->channel == data[i].channelValue) { + *maxPow = ar2413GetMaxPower(ah, &data[i]); + *minPow = ar2413GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar2413RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +/* + * Allocate memory for analog bank scratch buffers + * Scratch Buffer will be reinitialized every reset so no need to zero now + */ +static HAL_BOOL +ar2413RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar2413State *priv; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar2413State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar2413RfDetach; + priv->base.writeRegs = ar2413WriteRegs; + priv->base.getRfBank = ar2413GetRfBank; + priv->base.setChannel = ar2413SetChannel; + priv->base.setRfRegs = ar2413SetRfRegs; + priv->base.setPowerTable = ar2413SetPowerTable; + priv->base.getChannelMaxMinPower = ar2413GetChannelMaxMinPower; + priv->base.getNfAdjust = ar5212GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + + return AH_TRUE; +} + +static HAL_BOOL +ar2413Probe(struct ath_hal *ah) +{ + return IS_2413(ah); +} +AH_RF(RF2413, ar2413Probe, ar2413RfAttach); diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar2425.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar2425.c new file mode 100644 index 0000000000..adb41b535c --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar2425.c @@ -0,0 +1,722 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar2425.c,v 1.8 2008/11/16 21:33:05 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#include "ah_eeprom_v3.h" + +#define AH_5212_2425 +#define AH_5212_2417 +#include "ar5212/ar5212.ini" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +struct ar2425State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[PWR_TABLE_SIZE_2413]; + + uint32_t Bank1Data[N(ar5212Bank1_2425)]; + uint32_t Bank2Data[N(ar5212Bank2_2425)]; + uint32_t Bank3Data[N(ar5212Bank3_2425)]; + uint32_t Bank6Data[N(ar5212Bank6_2425)]; /* 2417 is same size */ + uint32_t Bank7Data[N(ar5212Bank7_2425)]; +}; +#define AR2425(ah) ((struct ar2425State *) AH5212(ah)->ah_rfHal) + +extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static void +ar2425WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + HAL_INI_WRITE_ARRAY(ah, ar5212Modes_2425, modesIndex, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212Common_2425, 1, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_2425, freqIndex, writes); +#if 0 + /* + * for SWAN similar to Condor + * Bit 0 enables link to go to L1 when MAC goes to sleep. + * Bit 3 enables the loop back the link down to reset. + */ + if (IS_PCIE(ah) && ath_hal_pcieL1SKPEnable) { + OS_REG_WRITE(ah, AR_PCIE_PMC, + AR_PCIE_PMC_ENA_L1 | AR_PCIE_PMC_ENA_RESET); + } + /* + * for Standby issue in Swan/Condor. + * Bit 9 (MAC_WOW_PWR_STATE_MASK_D2)to be set to avoid skips + * before last Training Sequence 2 (TS2) + * Bit 8 (MAC_WOW_PWR_STATE_MASK_D1)to be unset to assert + * Power Reset along with PCI Reset + */ + OS_REG_SET_BIT(ah, AR_PCIE_PMC, MAC_WOW_PWR_STATE_MASK_D2); +#endif +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + */ +static HAL_BOOL +ar2425SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + uint32_t channelSel = 0; + uint32_t bModeSynth = 0; + uint32_t aModeRefSel = 0; + uint32_t reg32 = 0; + uint16_t freq; + + OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel); + + if (chan->channel < 4800) { + uint32_t txctl; + + channelSel = chan->channel - 2272; + channelSel = ath_hal_reverseBits(channelSel, 8); + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (chan->channel == 2484) { + // Enable channel spreading for channel 14 + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + + } else if (((chan->channel % 5) == 2) && (chan->channel <= 5435)) { + freq = chan->channel - 2; /* Align to even 5MHz raster */ + channelSel = ath_hal_reverseBits( + (uint32_t)(((freq - 4800)*10)/25 + 1), 8); + aModeRefSel = ath_hal_reverseBits(0, 2); + } else if ((chan->channel % 20) == 0 && chan->channel >= 5120) { + channelSel = ath_hal_reverseBits( + ((chan->channel - 4800) / 20 << 2), 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else if ((chan->channel % 10) == 0) { + channelSel = ath_hal_reverseBits( + ((chan->channel - 4800) / 10 << 1), 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else if ((chan->channel % 5) == 0) { + channelSel = ath_hal_reverseBits( + (chan->channel - 4800) / 5, 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", + __func__, chan->channel); + return AH_FALSE; + } + + reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 12) | 0x1; + OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff); + + reg32 >>= 8; + OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f); + + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + * + * REQUIRES: Access to the analog rf device + */ +static HAL_BOOL +ar2425SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t modesIndex, uint16_t *rfXpdGain) +{ +#define RF_BANK_SETUP(_priv, _ix, _col) do { \ + int i; \ + for (i = 0; i < N(ar5212Bank##_ix##_2425); i++) \ + (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_2425[i][_col];\ +} while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ar2425State *priv = AR2425(ah); + uint16_t ob2GHz = 0, db2GHz = 0; + int regWrites = 0; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "==>%s:chan 0x%x flag 0x%x modesIndex 0x%x\n", + __func__, chan->channel, chan->channelFlags, modesIndex); + + HALASSERT(priv); + + /* Setup rf parameters */ + switch (chan->channelFlags & CHANNEL_ALL) { + case CHANNEL_B: + ob2GHz = ee->ee_obFor24; + db2GHz = ee->ee_dbFor24; + break; + case CHANNEL_G: + case CHANNEL_108G: + ob2GHz = ee->ee_obFor24g; + db2GHz = ee->ee_dbFor24g; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + + /* Bank 1 Write */ + RF_BANK_SETUP(priv, 1, 1); + + /* Bank 2 Write */ + RF_BANK_SETUP(priv, 2, modesIndex); + + /* Bank 3 Write */ + RF_BANK_SETUP(priv, 3, modesIndex); + + /* Bank 6 Write */ + RF_BANK_SETUP(priv, 6, modesIndex); + + ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 193, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 190, 0); + + /* Bank 7 Setup */ + RF_BANK_SETUP(priv, 7, modesIndex); + + /* Write Analog registers */ + HAL_INI_WRITE_BANK(ah, ar5212Bank1_2425, priv->Bank1Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank2_2425, priv->Bank2Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank3_2425, priv->Bank3Data, regWrites); + if (IS_2417(ah)) { + HALASSERT(N(ar5212Bank6_2425) == N(ar5212Bank6_2417)); + HAL_INI_WRITE_BANK(ah, ar5212Bank6_2417, priv->Bank6Data, + regWrites); + } else + HAL_INI_WRITE_BANK(ah, ar5212Bank6_2425, priv->Bank6Data, + regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank7_2425, priv->Bank7Data, regWrites); + + /* Now that we have reprogrammed rfgain value, clear the flag. */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "<==%s\n", __func__); + return AH_TRUE; +#undef RF_BANK_SETUP +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar2425GetRfBank(struct ath_hal *ah, int bank) +{ + struct ar2425State *priv = AR2425(ah); + + HALASSERT(priv != AH_NULL); + switch (bank) { + case 1: return priv->Bank1Data; + case 2: return priv->Bank2Data; + case 3: return priv->Bank3Data; + case 6: return priv->Bank6Data; + case 7: return priv->Bank7Data; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Return indices surrounding the value in sorted integer lists. + * + * NB: the input list is assumed to be sorted in ascending order + */ +static void +GetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize, + uint32_t *vlo, uint32_t *vhi) +{ + int16_t target = v; + const uint16_t *ep = lp+listSize; + const uint16_t *tp; + + /* + * Check first and last elements for out-of-bounds conditions. + */ + if (target < lp[0]) { + *vlo = *vhi = 0; + return; + } + if (target >= ep[-1]) { + *vlo = *vhi = listSize - 1; + return; + } + + /* look for value being near or between 2 values in list */ + for (tp = lp; tp < ep; tp++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (*tp == target) { + *vlo = *vhi = tp - (const uint16_t *) lp; + return; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < tp[1]) { + *vlo = tp - (const uint16_t *) lp; + *vhi = *vlo + 1; + return; + } + } +} + +/* + * Fill the Vpdlist for indices Pmax-Pmin + */ +static HAL_BOOL +ar2425FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t Pmax, + const int16_t *pwrList, const uint16_t *VpdList, + uint16_t numIntercepts, + uint16_t retVpdList[][64]) +{ + uint16_t ii, jj, kk; + int16_t currPwr = (int16_t)(2*Pmin); + /* since Pmin is pwr*2 and pwrList is 4*pwr */ + uint32_t idxL, idxR; + + ii = 0; + jj = 0; + + if (numIntercepts < 2) + return AH_FALSE; + + while (ii <= (uint16_t)(Pmax - Pmin)) { + GetLowerUpperIndex(currPwr, (const uint16_t *) pwrList, + numIntercepts, &(idxL), &(idxR)); + if (idxR < 1) + idxR = 1; /* extrapolate below */ + if (idxL == (uint32_t)(numIntercepts - 1)) + idxL = numIntercepts - 2; /* extrapolate above */ + if (pwrList[idxL] == pwrList[idxR]) + kk = VpdList[idxL]; + else + kk = (uint16_t) + (((currPwr - pwrList[idxL])*VpdList[idxR]+ + (pwrList[idxR] - currPwr)*VpdList[idxL])/ + (pwrList[idxR] - pwrList[idxL])); + retVpdList[pdGainIdx][ii] = kk; + ii++; + currPwr += 2; /* half dB steps */ + } + + return AH_TRUE; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static int16_t +interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight) +{ + int16_t rv; + + if (srcRight != srcLeft) { + rv = ((target - srcLeft)*targetRight + + (srcRight - target)*targetLeft) / (srcRight - srcLeft); + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Uses the data points read from EEPROM to reconstruct the pdadc power table + * Called by ar2425SetPowerTable() + */ +static void +ar2425getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel, + const RAW_DATA_STRUCT_2413 *pRawDataset, + uint16_t pdGainOverlap_t2, + int16_t *pMinCalPower, uint16_t pPdGainBoundaries[], + uint16_t pPdGainValues[], uint16_t pPDADCValues[]) +{ + /* Note the items statically allocated below are to reduce stack usage */ + uint32_t ii, jj, kk; + int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */ + uint32_t idxL, idxR; + uint32_t numPdGainsUsed = 0; + static uint16_t VpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL][MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (chanL) */ + static uint16_t VpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL][MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (chanR) */ + static uint16_t VpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL][MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (interpolated) */ + /* + * If desired to support -ve power levels in future, just + * change pwr_I_0 to signed 5-bits. + */ + static int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on. */ + static int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on */ + uint16_t numVpd = 0; + uint16_t Vpd_step; + int16_t tmpVal ; + uint32_t sizeCurrVpdTable, maxIndex, tgtIndex; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "==>%s:\n", __func__); + + /* Get upper lower index */ + GetLowerUpperIndex(channel, pRawDataset->pChannels, + pRawDataset->numChannels, &(idxL), &(idxR)); + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain; + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]; + if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) { + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]; + } + Pmin_t2[numPdGainsUsed] = (int16_t) + (Pmin_t2[numPdGainsUsed] / 2); + Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]) + Pmax_t2[numPdGainsUsed] = + pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2); + ar2425FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L + ); + ar2425FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R + ); + for (kk = 0; kk < (uint16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) { + VpdTable_I[numPdGainsUsed][kk] = + interpolate_signed( + channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR], + (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]); + } + /* fill VpdTable_I for this pdGain */ + numPdGainsUsed++; + } + /* if this pdGain is used */ + } + + *pMinCalPower = Pmin_t2[0]; + kk = 0; /* index for the final table */ + for (ii = 0; ii < numPdGainsUsed; ii++) { + if (ii == (numPdGainsUsed - 1)) + pPdGainBoundaries[ii] = Pmax_t2[ii] + + PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB; + else + pPdGainBoundaries[ii] = (uint16_t) + ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 ); + + /* Find starting index for this pdGain */ + if (ii == 0) + ss = 0; /* for the first pdGain, start from index 0 */ + else + ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) - + pdGainOverlap_t2; + Vpd_step = (uint16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + *-ve ss indicates need to extrapolate data below for this pdGain + */ + while (ss < 0) { + tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step); + pPDADCValues[kk++] = (uint16_t)((tmpVal < 0) ? 0 : tmpVal); + ss++; + } + + sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii]; + tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii]; + maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; + + while (ss < (int16_t)maxIndex) + pPDADCValues[kk++] = VpdTable_I[ii][ss++]; + + Vpd_step = (uint16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] - + VpdTable_I[ii][sizeCurrVpdTable-2]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + * for last gain, pdGainBoundary == Pmax_t2, so will + * have to extrapolate + */ + if (tgtIndex > maxIndex) { /* need to extrapolate above */ + while(ss < (int16_t)tgtIndex) { + tmpVal = (uint16_t) + (VpdTable_I[ii][sizeCurrVpdTable-1] + + (ss-maxIndex)*Vpd_step); + pPDADCValues[kk++] = (tmpVal > 127) ? + 127 : tmpVal; + ss++; + } + } /* extrapolated above */ + } /* for all pdGainUsed */ + + while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) { + pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1]; + ii++; + } + while (kk < 128) { + pPDADCValues[kk] = pPDADCValues[kk-1]; + kk++; + } + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "<==%s\n", __func__); +} + + +/* Same as 2413 set power table */ +static HAL_BOOL +ar2425SetPowerTable(struct ath_hal *ah, + int16_t *minPower, int16_t *maxPower, HAL_CHANNEL_INTERNAL *chan, + uint16_t *rfXpdGain) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL; + uint16_t pdGainOverlap_t2; + int16_t minCalPower2413_t2; + uint16_t *pdadcValues = ahp->ah_pcdacTable; + uint16_t gainBoundaries[4]; + uint32_t i, reg32, regoffset; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s:chan 0x%x flag 0x%x\n", + __func__, chan->channel,chan->channelFlags); + + if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s:illegal mode\n", __func__); + return AH_FALSE; + } + + pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5), + AR_PHY_TPCRG5_PD_GAIN_OVERLAP); + + ar2425getGainBoundariesAndPdadcsForPowers(ah, chan->channel, + pRawDataset, pdGainOverlap_t2,&minCalPower2413_t2,gainBoundaries, + rfXpdGain, pdadcValues); + + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, + (pRawDataset->pDataPerChannel[0].numPdGains - 1)); + + /* + * Note the pdadc table may not start at 0 dBm power, could be + * negative or greater than 0. Need to offset the power + * values by the amount of minPower for griffin + */ + if (minCalPower2413_t2 != 0) + ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower2413_t2); + else + ahp->ah_txPowerIndexOffset = 0; + + /* Finally, write the power values into the baseband power table */ + regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */ + for (i = 0; i < 32; i++) { + reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0) | + ((pdadcValues[4*i + 1] & 0xFF) << 8) | + ((pdadcValues[4*i + 2] & 0xFF) << 16) | + ((pdadcValues[4*i + 3] & 0xFF) << 24) ; + OS_REG_WRITE(ah, regoffset, reg32); + regoffset += 4; + } + + OS_REG_WRITE(ah, AR_PHY_TPCRG5, + SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | + SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | + SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | + SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | + SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); + + return AH_TRUE; +} + +static int16_t +ar2425GetMinPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) +{ + uint32_t ii,jj; + uint16_t Pmin=0,numVpd; + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = data->pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + Pmin = data->pDataPerPDGain[jj].pwr_t4[0]; + return(Pmin); + } + } + return(Pmin); +} + +static int16_t +ar2425GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) +{ + uint32_t ii; + uint16_t Pmax=0,numVpd; + + for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + /* work forwards cuase lowest pdGain for highest power */ + numVpd = data->pDataPerPDGain[ii].numVpd; + if (numVpd > 0) { + Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1]; + return(Pmax); + } + } + return(Pmax); +} + +static +HAL_BOOL +ar2425GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, + int16_t *maxPow, int16_t *minPow) +{ + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL; + const RAW_DATA_PER_CHANNEL_2413 *data = AH_NULL; + uint16_t numChannels; + int totalD,totalF, totalMin,last, i; + + *maxPow = 0; + + if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else + return(AH_FALSE); + + numChannels = pRawDataset->numChannels; + data = pRawDataset->pDataPerChannel; + + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if (numChannels < 1) + return(AH_FALSE); + + if ((chan->channel < data[0].channelValue) || + (chan->channel > data[numChannels-1].channelValue)) { + if (chan->channel < data[0].channelValue) { + *maxPow = ar2425GetMaxPower(ah, &data[0]); + *minPow = ar2425GetMinPower(ah, &data[0]); + return(AH_TRUE); + } else { + *maxPow = ar2425GetMaxPower(ah, &data[numChannels - 1]); + *minPow = ar2425GetMinPower(ah, &data[numChannels - 1]); + return(AH_TRUE); + } + } + + /* Linearly interpolate the power value now */ + for (last=0,i=0; (ichannel > data[i].channelValue); + last = i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = ar2425GetMaxPower(ah, &data[i]) - ar2425GetMaxPower(ah, &data[last]); + *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + + ar2425GetMaxPower(ah, &data[last])*totalD)/totalD); + totalMin = ar2425GetMinPower(ah, &data[i]) - ar2425GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + + ar2425GetMinPower(ah, &data[last])*totalD)/totalD); + return(AH_TRUE); + } else { + if (chan->channel == data[i].channelValue) { + *maxPow = ar2425GetMaxPower(ah, &data[i]); + *minPow = ar2425GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar2425RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +/* + * Allocate memory for analog bank scratch buffers + * Scratch Buffer will be reinitialized every reset so no need to zero now + */ +static HAL_BOOL +ar2425RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar2425State *priv; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar2425State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar2425RfDetach; + priv->base.writeRegs = ar2425WriteRegs; + priv->base.getRfBank = ar2425GetRfBank; + priv->base.setChannel = ar2425SetChannel; + priv->base.setRfRegs = ar2425SetRfRegs; + priv->base.setPowerTable = ar2425SetPowerTable; + priv->base.getChannelMaxMinPower = ar2425GetChannelMaxMinPower; + priv->base.getNfAdjust = ar5212GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + + return AH_TRUE; +} + +static HAL_BOOL +ar2425Probe(struct ath_hal *ah) +{ + return IS_2425(ah) || IS_2417(ah); +} +AH_RF(RF2425, ar2425Probe, ar2425RfAttach); diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5111.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5111.c new file mode 100644 index 0000000000..79d11012b4 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5111.c @@ -0,0 +1,711 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: src/sys/dev/ath/ath_hal/ar5212/ar5111.c,v 1.2.2.1.2.1 2009/04/15 03:14:26 kensmith Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v3.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#define AH_5212_5111 +#include "ar5212/ar5212.ini" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +struct ar5111State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[PWR_TABLE_SIZE]; + + uint32_t Bank0Data[N(ar5212Bank0_5111)]; + uint32_t Bank1Data[N(ar5212Bank1_5111)]; + uint32_t Bank2Data[N(ar5212Bank2_5111)]; + uint32_t Bank3Data[N(ar5212Bank3_5111)]; + uint32_t Bank6Data[N(ar5212Bank6_5111)]; + uint32_t Bank7Data[N(ar5212Bank7_5111)]; +}; +#define AR5111(ah) ((struct ar5111State *) AH5212(ah)->ah_rfHal) + +static uint16_t ar5212GetScaledPower(uint16_t channel, uint16_t pcdacValue, + const PCDACS_EEPROM *pSrcStruct); +static HAL_BOOL ar5212FindValueInList(uint16_t channel, uint16_t pcdacValue, + const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue); +static void ar5212GetLowerUpperPcdacs(uint16_t pcdac, uint16_t channel, + const PCDACS_EEPROM *pSrcStruct, + uint16_t *pLowerPcdac, uint16_t *pUpperPcdac); + +extern void ar5212GetLowerUpperValues(uint16_t value, + const uint16_t *pList, uint16_t listSize, + uint16_t *pLowerValue, uint16_t *pUpperValue); +extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static void +ar5111WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + HAL_INI_WRITE_ARRAY(ah, ar5212Modes_5111, modesIndex, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212Common_5111, 1, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_5111, freqIndex, writes); +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + */ +static HAL_BOOL +ar5111SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ +#define CI_2GHZ_INDEX_CORRECTION 19 + uint32_t refClk, reg32, data2111; + int16_t chan5111, chanIEEE; + + /* + * Structure to hold 11b tuning information for 5111/2111 + * 16 MHz mode, divider ratio = 198 = NP+S. N=16, S=4 or 6, P=12 + */ + typedef struct { + uint32_t refClkSel; /* reference clock, 1 for 16 MHz */ + uint32_t channelSelect; /* P[7:4]S[3:0] bits */ + uint16_t channel5111; /* 11a channel for 5111 */ + } CHAN_INFO_2GHZ; + + static const CHAN_INFO_2GHZ chan2GHzData[] = { + { 1, 0x46, 96 }, /* 2312 -19 */ + { 1, 0x46, 97 }, /* 2317 -18 */ + { 1, 0x46, 98 }, /* 2322 -17 */ + { 1, 0x46, 99 }, /* 2327 -16 */ + { 1, 0x46, 100 }, /* 2332 -15 */ + { 1, 0x46, 101 }, /* 2337 -14 */ + { 1, 0x46, 102 }, /* 2342 -13 */ + { 1, 0x46, 103 }, /* 2347 -12 */ + { 1, 0x46, 104 }, /* 2352 -11 */ + { 1, 0x46, 105 }, /* 2357 -10 */ + { 1, 0x46, 106 }, /* 2362 -9 */ + { 1, 0x46, 107 }, /* 2367 -8 */ + { 1, 0x46, 108 }, /* 2372 -7 */ + /* index -6 to 0 are pad to make this a nolookup table */ + { 1, 0x46, 116 }, /* -6 */ + { 1, 0x46, 116 }, /* -5 */ + { 1, 0x46, 116 }, /* -4 */ + { 1, 0x46, 116 }, /* -3 */ + { 1, 0x46, 116 }, /* -2 */ + { 1, 0x46, 116 }, /* -1 */ + { 1, 0x46, 116 }, /* 0 */ + { 1, 0x46, 116 }, /* 2412 1 */ + { 1, 0x46, 117 }, /* 2417 2 */ + { 1, 0x46, 118 }, /* 2422 3 */ + { 1, 0x46, 119 }, /* 2427 4 */ + { 1, 0x46, 120 }, /* 2432 5 */ + { 1, 0x46, 121 }, /* 2437 6 */ + { 1, 0x46, 122 }, /* 2442 7 */ + { 1, 0x46, 123 }, /* 2447 8 */ + { 1, 0x46, 124 }, /* 2452 9 */ + { 1, 0x46, 125 }, /* 2457 10 */ + { 1, 0x46, 126 }, /* 2462 11 */ + { 1, 0x46, 127 }, /* 2467 12 */ + { 1, 0x46, 128 }, /* 2472 13 */ + { 1, 0x44, 124 }, /* 2484 14 */ + { 1, 0x46, 136 }, /* 2512 15 */ + { 1, 0x46, 140 }, /* 2532 16 */ + { 1, 0x46, 144 }, /* 2552 17 */ + { 1, 0x46, 148 }, /* 2572 18 */ + { 1, 0x46, 152 }, /* 2592 19 */ + { 1, 0x46, 156 }, /* 2612 20 */ + { 1, 0x46, 160 }, /* 2632 21 */ + { 1, 0x46, 164 }, /* 2652 22 */ + { 1, 0x46, 168 }, /* 2672 23 */ + { 1, 0x46, 172 }, /* 2692 24 */ + { 1, 0x46, 176 }, /* 2712 25 */ + { 1, 0x46, 180 } /* 2732 26 */ + }; + + OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel); + + chanIEEE = ath_hal_mhz2ieee(ah, chan->channel, chan->channelFlags); + if (IS_CHAN_2GHZ(chan)) { + const CHAN_INFO_2GHZ* ci = + &chan2GHzData[chanIEEE + CI_2GHZ_INDEX_CORRECTION]; + uint32_t txctl; + + data2111 = ((ath_hal_reverseBits(ci->channelSelect, 8) & 0xff) + << 5) + | (ci->refClkSel << 4); + chan5111 = ci->channel5111; + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (chan->channel == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else { + chan5111 = chanIEEE; /* no conversion needed */ + data2111 = 0; + } + + /* Rest of the code is common for 5 GHz and 2.4 GHz. */ + if (chan5111 >= 145 || (chan5111 & 0x1)) { + reg32 = ath_hal_reverseBits(chan5111 - 24, 8) & 0xff; + refClk = 1; + } else { + reg32 = ath_hal_reverseBits(((chan5111 - 24)/2), 8) & 0xff; + refClk = 0; + } + + reg32 = (reg32 << 2) | (refClk << 1) | (1 << 10) | 0x1; + OS_REG_WRITE(ah, AR_PHY(0x27), ((data2111 & 0xff) << 8) | (reg32 & 0xff)); + reg32 >>= 8; + OS_REG_WRITE(ah, AR_PHY(0x34), (data2111 & 0xff00) | (reg32 & 0xff)); + + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +#undef CI_2GHZ_INDEX_CORRECTION +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar5111GetRfBank(struct ath_hal *ah, int bank) +{ + struct ar5111State *priv = AR5111(ah); + + HALASSERT(priv != AH_NULL); + switch (bank) { + case 0: return priv->Bank0Data; + case 1: return priv->Bank1Data; + case 2: return priv->Bank2Data; + case 3: return priv->Bank3Data; + case 6: return priv->Bank6Data; + case 7: return priv->Bank7Data; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + * + * REQUIRES: Access to the analog rf device + */ +static HAL_BOOL +ar5111SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, + uint16_t modesIndex, uint16_t *rfXpdGain) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t rfXpdGainFixed, rfPloSel, rfPwdXpd, gainI; + uint16_t tempOB, tempDB; + uint32_t ob2GHz, db2GHz, rfReg[N(ar5212Bank6_5111)]; + int i, regWrites = 0; + + /* Setup rf parameters */ + switch (chan->channelFlags & CHANNEL_ALL) { + case CHANNEL_A: + case CHANNEL_T: + if (4000 < chan->channel && chan->channel < 5260) { + tempOB = ee->ee_ob1; + tempDB = ee->ee_db1; + } else if (5260 <= chan->channel && chan->channel < 5500) { + tempOB = ee->ee_ob2; + tempDB = ee->ee_db2; + } else if (5500 <= chan->channel && chan->channel < 5725) { + tempOB = ee->ee_ob3; + tempDB = ee->ee_db3; + } else if (chan->channel >= 5725) { + tempOB = ee->ee_ob4; + tempDB = ee->ee_db4; + } else { + /* XXX when does this happen??? */ + tempOB = tempDB = 0; + } + ob2GHz = db2GHz = 0; + + rfXpdGainFixed = ee->ee_xgain[headerInfo11A]; + rfPloSel = ee->ee_xpd[headerInfo11A]; + rfPwdXpd = !ee->ee_xpd[headerInfo11A]; + gainI = ee->ee_gainI[headerInfo11A]; + break; + case CHANNEL_B: + tempOB = ee->ee_obFor24; + tempDB = ee->ee_dbFor24; + ob2GHz = ee->ee_ob2GHz[0]; + db2GHz = ee->ee_db2GHz[0]; + + rfXpdGainFixed = ee->ee_xgain[headerInfo11B]; + rfPloSel = ee->ee_xpd[headerInfo11B]; + rfPwdXpd = !ee->ee_xpd[headerInfo11B]; + gainI = ee->ee_gainI[headerInfo11B]; + break; + case CHANNEL_G: + tempOB = ee->ee_obFor24g; + tempDB = ee->ee_dbFor24g; + ob2GHz = ee->ee_ob2GHz[1]; + db2GHz = ee->ee_db2GHz[1]; + + rfXpdGainFixed = ee->ee_xgain[headerInfo11G]; + rfPloSel = ee->ee_xpd[headerInfo11G]; + rfPwdXpd = !ee->ee_xpd[headerInfo11G]; + gainI = ee->ee_gainI[headerInfo11G]; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + + HALASSERT(1 <= tempOB && tempOB <= 5); + HALASSERT(1 <= tempDB && tempDB <= 5); + + /* Bank 0 Write */ + for (i = 0; i < N(ar5212Bank0_5111); i++) + rfReg[i] = ar5212Bank0_5111[i][modesIndex]; + if (IS_CHAN_2GHZ(chan)) { + ar5212ModifyRfBuffer(rfReg, ob2GHz, 3, 119, 0); + ar5212ModifyRfBuffer(rfReg, db2GHz, 3, 122, 0); + } + HAL_INI_WRITE_BANK(ah, ar5212Bank0_5111, rfReg, regWrites); + + /* Bank 1 Write */ + HAL_INI_WRITE_ARRAY(ah, ar5212Bank1_5111, 1, regWrites); + + /* Bank 2 Write */ + HAL_INI_WRITE_ARRAY(ah, ar5212Bank2_5111, modesIndex, regWrites); + + /* Bank 3 Write */ + HAL_INI_WRITE_ARRAY(ah, ar5212Bank3_5111, modesIndex, regWrites); + + /* Bank 6 Write */ + for (i = 0; i < N(ar5212Bank6_5111); i++) + rfReg[i] = ar5212Bank6_5111[i][modesIndex]; + if (IS_CHAN_A(chan)) { /* NB: CHANNEL_A | CHANNEL_T */ + ar5212ModifyRfBuffer(rfReg, ee->ee_cornerCal.pd84, 1, 51, 3); + ar5212ModifyRfBuffer(rfReg, ee->ee_cornerCal.pd90, 1, 45, 3); + } + ar5212ModifyRfBuffer(rfReg, rfPwdXpd, 1, 95, 0); + ar5212ModifyRfBuffer(rfReg, rfXpdGainFixed, 4, 96, 0); + /* Set 5212 OB & DB */ + ar5212ModifyRfBuffer(rfReg, tempOB, 3, 104, 0); + ar5212ModifyRfBuffer(rfReg, tempDB, 3, 107, 0); + HAL_INI_WRITE_BANK(ah, ar5212Bank6_5111, rfReg, regWrites); + + /* Bank 7 Write */ + for (i = 0; i < N(ar5212Bank7_5111); i++) + rfReg[i] = ar5212Bank7_5111[i][modesIndex]; + ar5212ModifyRfBuffer(rfReg, gainI, 6, 29, 0); + ar5212ModifyRfBuffer(rfReg, rfPloSel, 1, 4, 0); + + if (IS_CHAN_QUARTER_RATE(chan) || IS_CHAN_HALF_RATE(chan)) { + uint32_t rfWaitI, rfWaitS, rfMaxTime; + + rfWaitS = 0x1f; + rfWaitI = (IS_CHAN_HALF_RATE(chan)) ? 0x10 : 0x1f; + rfMaxTime = 3; + ar5212ModifyRfBuffer(rfReg, rfWaitS, 5, 19, 0); + ar5212ModifyRfBuffer(rfReg, rfWaitI, 5, 24, 0); + ar5212ModifyRfBuffer(rfReg, rfMaxTime, 2, 49, 0); + + } + + HAL_INI_WRITE_BANK(ah, ar5212Bank7_5111, rfReg, regWrites); + + /* Now that we have reprogrammed rfgain value, clear the flag. */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + return AH_TRUE; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static uint16_t +interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + uint16_t targetLeft, uint16_t targetRight) +{ + uint16_t rv; + int16_t lRatio; + + /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */ + if ((targetLeft * targetRight) == 0) + return 0; + + if (srcRight != srcLeft) { + /* + * Note the ratio always need to be scaled, + * since it will be a fraction. + */ + lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft); + if (lRatio < 0) { + /* Return as Left target if value would be negative */ + rv = targetLeft; + } else if (lRatio > EEP_SCALE) { + /* Return as Right target if Ratio is greater than 100% (SCALE) */ + rv = targetRight; + } else { + rv = (lRatio * targetRight + (EEP_SCALE - lRatio) * + targetLeft) / EEP_SCALE; + } + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Read the transmit power levels from the structures taken from EEPROM + * Interpolate read transmit power values for this channel + * Organize the transmit power values into a table for writing into the hardware + */ +static HAL_BOOL +ar5111SetPowerTable(struct ath_hal *ah, + int16_t *pMinPower, int16_t *pMaxPower, HAL_CHANNEL_INTERNAL *chan, + uint16_t *rfXpdGain) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + FULL_PCDAC_STRUCT pcdacStruct; + int i, j; + + uint16_t *pPcdacValues; + int16_t *pScaledUpDbm; + int16_t minScaledPwr; + int16_t maxScaledPwr; + int16_t pwr; + uint16_t pcdacMin = 0; + uint16_t pcdacMax = PCDAC_STOP; + uint16_t pcdacTableIndex; + uint16_t scaledPcdac; + PCDACS_EEPROM *pSrcStruct; + PCDACS_EEPROM eepromPcdacs; + + /* setup the pcdac struct to point to the correct info, based on mode */ + switch (chan->channelFlags & CHANNEL_ALL) { + case CHANNEL_A: + case CHANNEL_T: + eepromPcdacs.numChannels = ee->ee_numChannels11a; + eepromPcdacs.pChannelList = ee->ee_channels11a; + eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11a; + break; + case CHANNEL_B: + eepromPcdacs.numChannels = ee->ee_numChannels2_4; + eepromPcdacs.pChannelList = ee->ee_channels11b; + eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11b; + break; + case CHANNEL_G: + case CHANNEL_108G: + eepromPcdacs.numChannels = ee->ee_numChannels2_4; + eepromPcdacs.pChannelList = ee->ee_channels11g; + eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11g; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + + pSrcStruct = &eepromPcdacs; + + OS_MEMZERO(&pcdacStruct, sizeof(pcdacStruct)); + pPcdacValues = pcdacStruct.PcdacValues; + pScaledUpDbm = pcdacStruct.PwrValues; + + /* Initialize the pcdacs to dBM structs pcdacs to be 1 to 63 */ + for (i = PCDAC_START, j = 0; i <= PCDAC_STOP; i+= PCDAC_STEP, j++) + pPcdacValues[j] = i; + + pcdacStruct.numPcdacValues = j; + pcdacStruct.pcdacMin = PCDAC_START; + pcdacStruct.pcdacMax = PCDAC_STOP; + + /* Fill out the power values for this channel */ + for (j = 0; j < pcdacStruct.numPcdacValues; j++ ) + pScaledUpDbm[j] = ar5212GetScaledPower(chan->channel, + pPcdacValues[j], pSrcStruct); + + /* Now scale the pcdac values to fit in the 64 entry power table */ + minScaledPwr = pScaledUpDbm[0]; + maxScaledPwr = pScaledUpDbm[pcdacStruct.numPcdacValues - 1]; + + /* find minimum and make monotonic */ + for (j = 0; j < pcdacStruct.numPcdacValues; j++) { + if (minScaledPwr >= pScaledUpDbm[j]) { + minScaledPwr = pScaledUpDbm[j]; + pcdacMin = j; + } + /* + * Make the full_hsh monotonically increasing otherwise + * interpolation algorithm will get fooled gotta start + * working from the top, hence i = 63 - j. + */ + i = (uint16_t)(pcdacStruct.numPcdacValues - 1 - j); + if (i == 0) + break; + if (pScaledUpDbm[i-1] > pScaledUpDbm[i]) { + /* + * It could be a glitch, so make the power for + * this pcdac the same as the power from the + * next highest pcdac. + */ + pScaledUpDbm[i - 1] = pScaledUpDbm[i]; + } + } + + for (j = 0; j < pcdacStruct.numPcdacValues; j++) + if (maxScaledPwr < pScaledUpDbm[j]) { + maxScaledPwr = pScaledUpDbm[j]; + pcdacMax = j; + } + + /* Find the first power level with a pcdac */ + pwr = (uint16_t)(PWR_STEP * + ((minScaledPwr - PWR_MIN + PWR_STEP / 2) / PWR_STEP) + PWR_MIN); + + /* Write all the first pcdac entries based off the pcdacMin */ + pcdacTableIndex = 0; + for (i = 0; i < (2 * (pwr - PWR_MIN) / EEP_SCALE + 1); i++) { + HALASSERT(pcdacTableIndex < PWR_TABLE_SIZE); + ahp->ah_pcdacTable[pcdacTableIndex++] = pcdacMin; + } + + i = 0; + while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1] && + pcdacTableIndex < PWR_TABLE_SIZE) { + pwr += PWR_STEP; + /* stop if dbM > max_power_possible */ + while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1] && + (pwr - pScaledUpDbm[i])*(pwr - pScaledUpDbm[i+1]) > 0) + i++; + /* scale by 2 and add 1 to enable round up or down as needed */ + scaledPcdac = (uint16_t)(interpolate(pwr, + pScaledUpDbm[i], pScaledUpDbm[i + 1], + (uint16_t)(pPcdacValues[i] * 2), + (uint16_t)(pPcdacValues[i + 1] * 2)) + 1); + + HALASSERT(pcdacTableIndex < PWR_TABLE_SIZE); + ahp->ah_pcdacTable[pcdacTableIndex] = scaledPcdac / 2; + if (ahp->ah_pcdacTable[pcdacTableIndex] > pcdacMax) + ahp->ah_pcdacTable[pcdacTableIndex] = pcdacMax; + pcdacTableIndex++; + } + + /* Write all the last pcdac entries based off the last valid pcdac */ + while (pcdacTableIndex < PWR_TABLE_SIZE) { + ahp->ah_pcdacTable[pcdacTableIndex] = + ahp->ah_pcdacTable[pcdacTableIndex - 1]; + pcdacTableIndex++; + } + + /* No power table adjustment for 5111 */ + ahp->ah_txPowerIndexOffset = 0; + + return AH_TRUE; +} + +/* + * Get or interpolate the pcdac value from the calibrated data. + */ +static uint16_t +ar5212GetScaledPower(uint16_t channel, uint16_t pcdacValue, + const PCDACS_EEPROM *pSrcStruct) +{ + uint16_t powerValue; + uint16_t lFreq, rFreq; /* left and right frequency values */ + uint16_t llPcdac, ulPcdac; /* lower and upper left pcdac values */ + uint16_t lrPcdac, urPcdac; /* lower and upper right pcdac values */ + uint16_t lPwr, uPwr; /* lower and upper temp pwr values */ + uint16_t lScaledPwr, rScaledPwr; /* left and right scaled power */ + + if (ar5212FindValueInList(channel, pcdacValue, pSrcStruct, &powerValue)) { + /* value was copied from srcStruct */ + return powerValue; + } + + ar5212GetLowerUpperValues(channel, + pSrcStruct->pChannelList, pSrcStruct->numChannels, + &lFreq, &rFreq); + ar5212GetLowerUpperPcdacs(pcdacValue, + lFreq, pSrcStruct, &llPcdac, &ulPcdac); + ar5212GetLowerUpperPcdacs(pcdacValue, + rFreq, pSrcStruct, &lrPcdac, &urPcdac); + + /* get the power index for the pcdac value */ + ar5212FindValueInList(lFreq, llPcdac, pSrcStruct, &lPwr); + ar5212FindValueInList(lFreq, ulPcdac, pSrcStruct, &uPwr); + lScaledPwr = interpolate(pcdacValue, llPcdac, ulPcdac, lPwr, uPwr); + + ar5212FindValueInList(rFreq, lrPcdac, pSrcStruct, &lPwr); + ar5212FindValueInList(rFreq, urPcdac, pSrcStruct, &uPwr); + rScaledPwr = interpolate(pcdacValue, lrPcdac, urPcdac, lPwr, uPwr); + + return interpolate(channel, lFreq, rFreq, lScaledPwr, rScaledPwr); +} + +/* + * Find the value from the calibrated source data struct + */ +static HAL_BOOL +ar5212FindValueInList(uint16_t channel, uint16_t pcdacValue, + const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue) +{ + const DATA_PER_CHANNEL *pChannelData = pSrcStruct->pDataPerChannel; + int i; + + for (i = 0; i < pSrcStruct->numChannels; i++ ) { + if (pChannelData->channelValue == channel) { + const uint16_t* pPcdac = pChannelData->PcdacValues; + int j; + + for (j = 0; j < pChannelData->numPcdacValues; j++ ) { + if (*pPcdac == pcdacValue) { + *powerValue = pChannelData->PwrValues[j]; + return AH_TRUE; + } + pPcdac++; + } + } + pChannelData++; + } + return AH_FALSE; +} + +/* + * Get the upper and lower pcdac given the channel and the pcdac + * used in the search + */ +static void +ar5212GetLowerUpperPcdacs(uint16_t pcdac, uint16_t channel, + const PCDACS_EEPROM *pSrcStruct, + uint16_t *pLowerPcdac, uint16_t *pUpperPcdac) +{ + const DATA_PER_CHANNEL *pChannelData = pSrcStruct->pDataPerChannel; + int i; + + /* Find the channel information */ + for (i = 0; i < pSrcStruct->numChannels; i++) { + if (pChannelData->channelValue == channel) + break; + pChannelData++; + } + ar5212GetLowerUpperValues(pcdac, pChannelData->PcdacValues, + pChannelData->numPcdacValues, + pLowerPcdac, pUpperPcdac); +} + +static HAL_BOOL +ar5111GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, + int16_t *maxPow, int16_t *minPow) +{ + /* XXX - Get 5111 power limits! */ + /* NB: caller will cope */ + return AH_FALSE; +} + +/* + * Adjust NF based on statistical values for 5GHz frequencies. + */ +static int16_t +ar5111GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) +{ + static const struct { + uint16_t freqLow; + int16_t adjust; + } adjust5111[] = { + { 5790, 6 }, /* NB: ordered high -> low */ + { 5730, 4 }, + { 5690, 3 }, + { 5660, 2 }, + { 5610, 1 }, + { 5530, 0 }, + { 5450, 0 }, + { 5379, 1 }, + { 5209, 3 }, + { 3000, 5 }, + { 0, 0 }, + }; + int i; + + for (i = 0; c->channel <= adjust5111[i].freqLow; i++) + ; + return adjust5111[i].adjust; +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar5111RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +/* + * Allocate memory for analog bank scratch buffers + * Scratch Buffer will be reinitialized every reset so no need to zero now + */ +static HAL_BOOL +ar5111RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5111State *priv; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar5111State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar5111RfDetach; + priv->base.writeRegs = ar5111WriteRegs; + priv->base.getRfBank = ar5111GetRfBank; + priv->base.setChannel = ar5111SetChannel; + priv->base.setRfRegs = ar5111SetRfRegs; + priv->base.setPowerTable = ar5111SetPowerTable; + priv->base.getChannelMaxMinPower = ar5111GetChannelMaxMinPower; + priv->base.getNfAdjust = ar5111GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + + return AH_TRUE; +} + +static HAL_BOOL +ar5111Probe(struct ath_hal *ah) +{ + return IS_RAD5111(ah); +} +AH_RF(RF5111, ar5111Probe, ar5111RfAttach); diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5112.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5112.c new file mode 100644 index 0000000000..b124b1abae --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5112.c @@ -0,0 +1,881 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5112.c,v 1.7 2008/11/10 04:08:03 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v3.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#define AH_5212_5112 +#include "ar5212/ar5212.ini" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +struct ar5112State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[PWR_TABLE_SIZE]; + + uint32_t Bank1Data[N(ar5212Bank1_5112)]; + uint32_t Bank2Data[N(ar5212Bank2_5112)]; + uint32_t Bank3Data[N(ar5212Bank3_5112)]; + uint32_t Bank6Data[N(ar5212Bank6_5112)]; + uint32_t Bank7Data[N(ar5212Bank7_5112)]; +}; +#define AR5112(ah) ((struct ar5112State *) AH5212(ah)->ah_rfHal) + +static void ar5212GetLowerUpperIndex(uint16_t v, + uint16_t *lp, uint16_t listSize, + uint32_t *vlo, uint32_t *vhi); +static HAL_BOOL getFullPwrTable(uint16_t numPcdacs, uint16_t *pcdacs, + int16_t *power, int16_t maxPower, int16_t *retVals); +static int16_t getPminAndPcdacTableFromPowerTable(int16_t *pwrTableT4, + uint16_t retVals[]); +static int16_t getPminAndPcdacTableFromTwoPowerTables(int16_t *pwrTableLXpdT4, + int16_t *pwrTableHXpdT4, uint16_t retVals[], int16_t *pMid); +static int16_t interpolate_signed(uint16_t target, + uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight); + +extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static void +ar5112WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + HAL_INI_WRITE_ARRAY(ah, ar5212Modes_5112, modesIndex, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212Common_5112, 1, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_5112, freqIndex, writes); +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + */ +static HAL_BOOL +ar5112SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + uint32_t channelSel = 0; + uint32_t bModeSynth = 0; + uint32_t aModeRefSel = 0; + uint32_t reg32 = 0; + uint16_t freq; + + OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel); + + if (chan->channel < 4800) { + uint32_t txctl; + + if (((chan->channel - 2192) % 5) == 0) { + channelSel = ((chan->channel - 672) * 2 - 3040)/10; + bModeSynth = 0; + } else if (((chan->channel - 2224) % 5) == 0) { + channelSel = ((chan->channel - 704) * 2 - 3040) / 10; + bModeSynth = 1; + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u MHz\n", + __func__, chan->channel); + return AH_FALSE; + } + + channelSel = (channelSel << 2) & 0xff; + channelSel = ath_hal_reverseBits(channelSel, 8); + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (chan->channel == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else if (((chan->channel % 5) == 2) && (chan->channel <= 5435)) { + freq = chan->channel - 2; /* Align to even 5MHz raster */ + channelSel = ath_hal_reverseBits( + (uint32_t)(((freq - 4800)*10)/25 + 1), 8); + aModeRefSel = ath_hal_reverseBits(0, 2); + } else if ((chan->channel % 20) == 0 && chan->channel >= 5120) { + channelSel = ath_hal_reverseBits( + ((chan->channel - 4800) / 20 << 2), 8); + aModeRefSel = ath_hal_reverseBits(3, 2); + } else if ((chan->channel % 10) == 0) { + channelSel = ath_hal_reverseBits( + ((chan->channel - 4800) / 10 << 1), 8); + aModeRefSel = ath_hal_reverseBits(2, 2); + } else if ((chan->channel % 5) == 0) { + channelSel = ath_hal_reverseBits( + (chan->channel - 4800) / 5, 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", + __func__, chan->channel); + return AH_FALSE; + } + + reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 12) | 0x1; + OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff); + + reg32 >>= 8; + OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f); + + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar5112GetRfBank(struct ath_hal *ah, int bank) +{ + struct ar5112State *priv = AR5112(ah); + + HALASSERT(priv != AH_NULL); + switch (bank) { + case 1: return priv->Bank1Data; + case 2: return priv->Bank2Data; + case 3: return priv->Bank3Data; + case 6: return priv->Bank6Data; + case 7: return priv->Bank7Data; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + * + * REQUIRES: Access to the analog rf device + */ +static HAL_BOOL +ar5112SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, + uint16_t modesIndex, uint16_t *rfXpdGain) +{ +#define RF_BANK_SETUP(_priv, _ix, _col) do { \ + int i; \ + for (i = 0; i < N(ar5212Bank##_ix##_5112); i++) \ + (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_5112[i][_col];\ +} while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t rfXpdSel, gainI; + uint16_t ob5GHz = 0, db5GHz = 0; + uint16_t ob2GHz = 0, db2GHz = 0; + struct ar5112State *priv = AR5112(ah); + GAIN_VALUES *gv = &ahp->ah_gainValues; + int regWrites = 0; + + HALASSERT(priv); + + /* Setup rf parameters */ + switch (chan->channelFlags & CHANNEL_ALL) { + case CHANNEL_A: + case CHANNEL_T: + if (chan->channel > 4000 && chan->channel < 5260) { + ob5GHz = ee->ee_ob1; + db5GHz = ee->ee_db1; + } else if (chan->channel >= 5260 && chan->channel < 5500) { + ob5GHz = ee->ee_ob2; + db5GHz = ee->ee_db2; + } else if (chan->channel >= 5500 && chan->channel < 5725) { + ob5GHz = ee->ee_ob3; + db5GHz = ee->ee_db3; + } else if (chan->channel >= 5725) { + ob5GHz = ee->ee_ob4; + db5GHz = ee->ee_db4; + } else { + /* XXX else */ + } + rfXpdSel = ee->ee_xpd[headerInfo11A]; + gainI = ee->ee_gainI[headerInfo11A]; + break; + case CHANNEL_B: + ob2GHz = ee->ee_ob2GHz[0]; + db2GHz = ee->ee_db2GHz[0]; + rfXpdSel = ee->ee_xpd[headerInfo11B]; + gainI = ee->ee_gainI[headerInfo11B]; + break; + case CHANNEL_G: + case CHANNEL_108G: + ob2GHz = ee->ee_ob2GHz[1]; + db2GHz = ee->ee_ob2GHz[1]; + rfXpdSel = ee->ee_xpd[headerInfo11G]; + gainI = ee->ee_gainI[headerInfo11G]; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + + /* Setup Bank 1 Write */ + RF_BANK_SETUP(priv, 1, 1); + + /* Setup Bank 2 Write */ + RF_BANK_SETUP(priv, 2, modesIndex); + + /* Setup Bank 3 Write */ + RF_BANK_SETUP(priv, 3, modesIndex); + + /* Setup Bank 6 Write */ + RF_BANK_SETUP(priv, 6, modesIndex); + + ar5212ModifyRfBuffer(priv->Bank6Data, rfXpdSel, 1, 302, 0); + + ar5212ModifyRfBuffer(priv->Bank6Data, rfXpdGain[0], 2, 270, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, rfXpdGain[1], 2, 257, 0); + + if (IS_CHAN_OFDM(chan)) { + ar5212ModifyRfBuffer(priv->Bank6Data, + gv->currStep->paramVal[GP_PWD_138], 1, 168, 3); + ar5212ModifyRfBuffer(priv->Bank6Data, + gv->currStep->paramVal[GP_PWD_137], 1, 169, 3); + ar5212ModifyRfBuffer(priv->Bank6Data, + gv->currStep->paramVal[GP_PWD_136], 1, 170, 3); + ar5212ModifyRfBuffer(priv->Bank6Data, + gv->currStep->paramVal[GP_PWD_132], 1, 174, 3); + ar5212ModifyRfBuffer(priv->Bank6Data, + gv->currStep->paramVal[GP_PWD_131], 1, 175, 3); + ar5212ModifyRfBuffer(priv->Bank6Data, + gv->currStep->paramVal[GP_PWD_130], 1, 176, 3); + } + + /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ + if (IS_CHAN_2GHZ(chan)) { + ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 287, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 290, 0); + } else { + ar5212ModifyRfBuffer(priv->Bank6Data, ob5GHz, 3, 279, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, db5GHz, 3, 282, 0); + } + + /* Lower synth voltage for X112 Rev 2.0 only */ + if (IS_RADX112_REV2(ah)) { + /* Non-Reversed analyg registers - so values are pre-reversed */ + ar5212ModifyRfBuffer(priv->Bank6Data, 2, 2, 90, 2); + ar5212ModifyRfBuffer(priv->Bank6Data, 2, 2, 92, 2); + ar5212ModifyRfBuffer(priv->Bank6Data, 2, 2, 94, 2); + ar5212ModifyRfBuffer(priv->Bank6Data, 2, 1, 254, 2); + } + + /* Decrease Power Consumption for 5312/5213 and up */ + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) { + ar5212ModifyRfBuffer(priv->Bank6Data, 1, 1, 281, 1); + ar5212ModifyRfBuffer(priv->Bank6Data, 1, 2, 1, 3); + ar5212ModifyRfBuffer(priv->Bank6Data, 1, 2, 3, 3); + ar5212ModifyRfBuffer(priv->Bank6Data, 1, 1, 139, 3); + ar5212ModifyRfBuffer(priv->Bank6Data, 1, 1, 140, 3); + } + + /* Setup Bank 7 Setup */ + RF_BANK_SETUP(priv, 7, modesIndex); + if (IS_CHAN_OFDM(chan)) + ar5212ModifyRfBuffer(priv->Bank7Data, + gv->currStep->paramVal[GP_MIXGAIN_OVR], 2, 37, 0); + + ar5212ModifyRfBuffer(priv->Bank7Data, gainI, 6, 14, 0); + + /* Adjust params for Derby TX power control */ + if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) { + uint32_t rfDelay, rfPeriod; + + rfDelay = 0xf; + rfPeriod = (IS_CHAN_HALF_RATE(chan)) ? 0x8 : 0xf; + ar5212ModifyRfBuffer(priv->Bank7Data, rfDelay, 4, 58, 0); + ar5212ModifyRfBuffer(priv->Bank7Data, rfPeriod, 4, 70, 0); + } + +#ifdef notyet + /* Analog registers are setup - EAR can modify */ + if (ar5212IsEarEngaged(pDev, chan)) + uint32_t modifier; + ar5212EarModify(pDev, EAR_LC_RF_WRITE, chan, &modifier); +#endif + /* Write Analog registers */ + HAL_INI_WRITE_BANK(ah, ar5212Bank1_5112, priv->Bank1Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank2_5112, priv->Bank2Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank3_5112, priv->Bank3Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank6_5112, priv->Bank6Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank7_5112, priv->Bank7Data, regWrites); + + /* Now that we have reprogrammed rfgain value, clear the flag. */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + return AH_TRUE; +#undef RF_BANK_SETUP +} + +/* + * Read the transmit power levels from the structures taken from EEPROM + * Interpolate read transmit power values for this channel + * Organize the transmit power values into a table for writing into the hardware + */ +static HAL_BOOL +ar5112SetPowerTable(struct ath_hal *ah, + int16_t *pPowerMin, int16_t *pPowerMax, HAL_CHANNEL_INTERNAL *chan, + uint16_t *rfXpdGain) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint32_t numXpdGain = IS_RADX112_REV2(ah) ? 2 : 1; + uint32_t xpdGainMask = 0; + int16_t powerMid, *pPowerMid = &powerMid; + + const EXPN_DATA_PER_CHANNEL_5112 *pRawCh; + const EEPROM_POWER_EXPN_5112 *pPowerExpn = AH_NULL; + + uint32_t ii, jj, kk; + int16_t minPwr_t4, maxPwr_t4, Pmin, Pmid; + + uint32_t chan_idx_L = 0, chan_idx_R = 0; + uint16_t chan_L, chan_R; + + int16_t pwr_table0[64]; + int16_t pwr_table1[64]; + uint16_t pcdacs[10]; + int16_t powers[10]; + uint16_t numPcd; + int16_t powTableLXPD[2][64]; + int16_t powTableHXPD[2][64]; + int16_t tmpPowerTable[64]; + uint16_t xgainList[2]; + uint16_t xpdMask; + + switch (chan->channelFlags & CHANNEL_ALL) { + case CHANNEL_A: + case CHANNEL_T: + pPowerExpn = &ee->ee_modePowerArray5112[headerInfo11A]; + xpdGainMask = ee->ee_xgain[headerInfo11A]; + break; + case CHANNEL_B: + pPowerExpn = &ee->ee_modePowerArray5112[headerInfo11B]; + xpdGainMask = ee->ee_xgain[headerInfo11B]; + break; + case CHANNEL_G: + case CHANNEL_108G: + pPowerExpn = &ee->ee_modePowerArray5112[headerInfo11G]; + xpdGainMask = ee->ee_xgain[headerInfo11G]; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown channel flags 0x%x\n", + __func__, chan->channelFlags & CHANNEL_ALL); + return AH_FALSE; + } + + if ((xpdGainMask & pPowerExpn->xpdMask) < 1) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: desired xpdGainMask 0x%x not supported by " + "calibrated xpdMask 0x%x\n", __func__, + xpdGainMask, pPowerExpn->xpdMask); + return AH_FALSE; + } + + maxPwr_t4 = (int16_t)(2*(*pPowerMax)); /* pwr_t2 -> pwr_t4 */ + minPwr_t4 = (int16_t)(2*(*pPowerMin)); /* pwr_t2 -> pwr_t4 */ + + xgainList[0] = 0xDEAD; + xgainList[1] = 0xDEAD; + + kk = 0; + xpdMask = pPowerExpn->xpdMask; + for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) { + if (((xpdMask >> jj) & 1) > 0) { + if (kk > 1) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "A maximum of 2 xpdGains supported" + "in pExpnPower data\n"); + return AH_FALSE; + } + xgainList[kk++] = (uint16_t)jj; + } + } + + ar5212GetLowerUpperIndex(chan->channel, &pPowerExpn->pChannels[0], + pPowerExpn->numChannels, &chan_idx_L, &chan_idx_R); + + kk = 0; + for (ii = chan_idx_L; ii <= chan_idx_R; ii++) { + pRawCh = &(pPowerExpn->pDataPerChannel[ii]); + if (xgainList[1] == 0xDEAD) { + jj = xgainList[0]; + numPcd = pRawCh->pDataPerXPD[jj].numPcdacs; + OS_MEMCPY(&pcdacs[0], &pRawCh->pDataPerXPD[jj].pcdac[0], + numPcd * sizeof(uint16_t)); + OS_MEMCPY(&powers[0], &pRawCh->pDataPerXPD[jj].pwr_t4[0], + numPcd * sizeof(int16_t)); + if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0], + pRawCh->maxPower_t4, &tmpPowerTable[0])) { + return AH_FALSE; + } + OS_MEMCPY(&powTableLXPD[kk][0], &tmpPowerTable[0], + 64*sizeof(int16_t)); + } else { + jj = xgainList[0]; + numPcd = pRawCh->pDataPerXPD[jj].numPcdacs; + OS_MEMCPY(&pcdacs[0], &pRawCh->pDataPerXPD[jj].pcdac[0], + numPcd*sizeof(uint16_t)); + OS_MEMCPY(&powers[0], + &pRawCh->pDataPerXPD[jj].pwr_t4[0], + numPcd*sizeof(int16_t)); + if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0], + pRawCh->maxPower_t4, &tmpPowerTable[0])) { + return AH_FALSE; + } + OS_MEMCPY(&powTableLXPD[kk][0], &tmpPowerTable[0], + 64 * sizeof(int16_t)); + + jj = xgainList[1]; + numPcd = pRawCh->pDataPerXPD[jj].numPcdacs; + OS_MEMCPY(&pcdacs[0], &pRawCh->pDataPerXPD[jj].pcdac[0], + numPcd * sizeof(uint16_t)); + OS_MEMCPY(&powers[0], + &pRawCh->pDataPerXPD[jj].pwr_t4[0], + numPcd * sizeof(int16_t)); + if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0], + pRawCh->maxPower_t4, &tmpPowerTable[0])) { + return AH_FALSE; + } + OS_MEMCPY(&powTableHXPD[kk][0], &tmpPowerTable[0], + 64 * sizeof(int16_t)); + } + kk++; + } + + chan_L = pPowerExpn->pChannels[chan_idx_L]; + chan_R = pPowerExpn->pChannels[chan_idx_R]; + kk = chan_idx_R - chan_idx_L; + + if (xgainList[1] == 0xDEAD) { + for (jj = 0; jj < 64; jj++) { + pwr_table0[jj] = interpolate_signed( + chan->channel, chan_L, chan_R, + powTableLXPD[0][jj], powTableLXPD[kk][jj]); + } + Pmin = getPminAndPcdacTableFromPowerTable(&pwr_table0[0], + ahp->ah_pcdacTable); + *pPowerMin = (int16_t) (Pmin / 2); + *pPowerMid = (int16_t) (pwr_table0[63] / 2); + *pPowerMax = (int16_t) (pwr_table0[63] / 2); + rfXpdGain[0] = xgainList[0]; + rfXpdGain[1] = rfXpdGain[0]; + } else { + for (jj = 0; jj < 64; jj++) { + pwr_table0[jj] = interpolate_signed( + chan->channel, chan_L, chan_R, + powTableLXPD[0][jj], powTableLXPD[kk][jj]); + pwr_table1[jj] = interpolate_signed( + chan->channel, chan_L, chan_R, + powTableHXPD[0][jj], powTableHXPD[kk][jj]); + } + if (numXpdGain == 2) { + Pmin = getPminAndPcdacTableFromTwoPowerTables( + &pwr_table0[0], &pwr_table1[0], + ahp->ah_pcdacTable, &Pmid); + *pPowerMin = (int16_t) (Pmin / 2); + *pPowerMid = (int16_t) (Pmid / 2); + *pPowerMax = (int16_t) (pwr_table0[63] / 2); + rfXpdGain[0] = xgainList[0]; + rfXpdGain[1] = xgainList[1]; + } else if (minPwr_t4 <= pwr_table1[63] && + maxPwr_t4 <= pwr_table1[63]) { + Pmin = getPminAndPcdacTableFromPowerTable( + &pwr_table1[0], ahp->ah_pcdacTable); + rfXpdGain[0] = xgainList[1]; + rfXpdGain[1] = rfXpdGain[0]; + *pPowerMin = (int16_t) (Pmin / 2); + *pPowerMid = (int16_t) (pwr_table1[63] / 2); + *pPowerMax = (int16_t) (pwr_table1[63] / 2); + } else { + Pmin = getPminAndPcdacTableFromPowerTable( + &pwr_table0[0], ahp->ah_pcdacTable); + rfXpdGain[0] = xgainList[0]; + rfXpdGain[1] = rfXpdGain[0]; + *pPowerMin = (int16_t) (Pmin/2); + *pPowerMid = (int16_t) (pwr_table0[63] / 2); + *pPowerMax = (int16_t) (pwr_table0[63] / 2); + } + } + + /* + * Move 5112 rates to match power tables where the max + * power table entry corresponds with maxPower. + */ + HALASSERT(*pPowerMax <= PCDAC_STOP); + ahp->ah_txPowerIndexOffset = PCDAC_STOP - *pPowerMax; + + return AH_TRUE; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static int16_t +interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight) +{ + int16_t rv; + + if (srcRight != srcLeft) { + rv = ((target - srcLeft)*targetRight + + (srcRight - target)*targetLeft) / (srcRight - srcLeft); + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Return indices surrounding the value in sorted integer lists. + * + * NB: the input list is assumed to be sorted in ascending order + */ +static void +ar5212GetLowerUpperIndex(uint16_t v, uint16_t *lp, uint16_t listSize, + uint32_t *vlo, uint32_t *vhi) +{ + uint32_t target = v; + uint16_t *ep = lp+listSize; + uint16_t *tp; + + /* + * Check first and last elements for out-of-bounds conditions. + */ + if (target < lp[0]) { + *vlo = *vhi = 0; + return; + } + if (target >= ep[-1]) { + *vlo = *vhi = listSize - 1; + return; + } + + /* look for value being near or between 2 values in list */ + for (tp = lp; tp < ep; tp++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (*tp == target) { + *vlo = *vhi = tp - lp; + return; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < tp[1]) { + *vlo = tp - lp; + *vhi = *vlo + 1; + return; + } + } +} + +static HAL_BOOL +getFullPwrTable(uint16_t numPcdacs, uint16_t *pcdacs, int16_t *power, int16_t maxPower, int16_t *retVals) +{ + uint16_t ii; + uint16_t idxL = 0; + uint16_t idxR = 1; + + if (numPcdacs < 2) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: at least 2 pcdac values needed [%d]\n", + __func__, numPcdacs); + return AH_FALSE; + } + for (ii = 0; ii < 64; ii++) { + if (ii>pcdacs[idxR] && idxR < numPcdacs-1) { + idxL++; + idxR++; + } + retVals[ii] = interpolate_signed(ii, + pcdacs[idxL], pcdacs[idxR], power[idxL], power[idxR]); + if (retVals[ii] >= maxPower) { + while (ii < 64) + retVals[ii++] = maxPower; + } + } + return AH_TRUE; +} + +/* + * Takes a single calibration curve and creates a power table. + * Adjusts the new power table so the max power is relative + * to the maximum index in the power table. + * + * WARNING: rates must be adjusted for this relative power table + */ +static int16_t +getPminAndPcdacTableFromPowerTable(int16_t *pwrTableT4, uint16_t retVals[]) +{ + int16_t ii, jj, jjMax; + int16_t pMin, currPower, pMax; + + /* If the spread is > 31.5dB, keep the upper 31.5dB range */ + if ((pwrTableT4[63] - pwrTableT4[0]) > 126) { + pMin = pwrTableT4[63] - 126; + } else { + pMin = pwrTableT4[0]; + } + + pMax = pwrTableT4[63]; + jjMax = 63; + + /* Search for highest pcdac 0.25dB below maxPower */ + while ((pwrTableT4[jjMax] > (pMax - 1) ) && (jjMax >= 0)) { + jjMax--; + } + + jj = jjMax; + currPower = pMax; + for (ii = 63; ii >= 0; ii--) { + while ((jj < 64) && (jj > 0) && (pwrTableT4[jj] >= currPower)) { + jj--; + } + if (jj == 0) { + while (ii >= 0) { + retVals[ii] = retVals[ii + 1]; + ii--; + } + break; + } + retVals[ii] = jj; + currPower -= 2; // corresponds to a 0.5dB step + } + return pMin; +} + +/* + * Combines the XPD curves from two calibration sets into a single + * power table and adjusts the power table so the max power is relative + * to the maximum index in the power table + * + * WARNING: rates must be adjusted for this relative power table + */ +static int16_t +getPminAndPcdacTableFromTwoPowerTables(int16_t *pwrTableLXpdT4, + int16_t *pwrTableHXpdT4, uint16_t retVals[], int16_t *pMid) +{ + int16_t ii, jj, jjMax; + int16_t pMin, pMax, currPower; + int16_t *pwrTableT4; + uint16_t msbFlag = 0x40; // turns on the 7th bit of the pcdac + + /* If the spread is > 31.5dB, keep the upper 31.5dB range */ + if ((pwrTableLXpdT4[63] - pwrTableHXpdT4[0]) > 126) { + pMin = pwrTableLXpdT4[63] - 126; + } else { + pMin = pwrTableHXpdT4[0]; + } + + pMax = pwrTableLXpdT4[63]; + jjMax = 63; + /* Search for highest pcdac 0.25dB below maxPower */ + while ((pwrTableLXpdT4[jjMax] > (pMax - 1) ) && (jjMax >= 0)){ + jjMax--; + } + + *pMid = pwrTableHXpdT4[63]; + jj = jjMax; + ii = 63; + currPower = pMax; + pwrTableT4 = &(pwrTableLXpdT4[0]); + while (ii >= 0) { + if ((currPower <= *pMid) || ( (jj == 0) && (msbFlag == 0x40))){ + msbFlag = 0x00; + pwrTableT4 = &(pwrTableHXpdT4[0]); + jj = 63; + } + while ((jj > 0) && (pwrTableT4[jj] >= currPower)) { + jj--; + } + if ((jj == 0) && (msbFlag == 0x00)) { + while (ii >= 0) { + retVals[ii] = retVals[ii+1]; + ii--; + } + break; + } + retVals[ii] = jj | msbFlag; + currPower -= 2; // corresponds to a 0.5dB step + ii--; + } + return pMin; +} + +static int16_t +ar5112GetMinPower(struct ath_hal *ah, const EXPN_DATA_PER_CHANNEL_5112 *data) +{ + int i, minIndex; + int16_t minGain,minPwr,minPcdac,retVal; + + /* Assume NUM_POINTS_XPD0 > 0 */ + minGain = data->pDataPerXPD[0].xpd_gain; + for (minIndex=0,i=1; ipDataPerXPD[i].xpd_gain < minGain) { + minIndex = i; + minGain = data->pDataPerXPD[i].xpd_gain; + } + } + minPwr = data->pDataPerXPD[minIndex].pwr_t4[0]; + minPcdac = data->pDataPerXPD[minIndex].pcdac[0]; + for (i=1; ipDataPerXPD[minIndex].pwr_t4[i] < minPwr) { + minPwr = data->pDataPerXPD[minIndex].pwr_t4[i]; + minPcdac = data->pDataPerXPD[minIndex].pcdac[i]; + } + } + retVal = minPwr - (minPcdac*2); + return(retVal); +} + +static HAL_BOOL +ar5112GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, + int16_t *maxPow, int16_t *minPow) +{ + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + int numChannels=0,i,last; + int totalD, totalF,totalMin; + const EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL; + const EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL; + + *maxPow = 0; + if (IS_CHAN_A(chan)) { + powerArray = ee->ee_modePowerArray5112; + data = powerArray[headerInfo11A].pDataPerChannel; + numChannels = powerArray[headerInfo11A].numChannels; + } else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) { + /* XXX - is this correct? Should we also use the same power for turbo G? */ + powerArray = ee->ee_modePowerArray5112; + data = powerArray[headerInfo11G].pDataPerChannel; + numChannels = powerArray[headerInfo11G].numChannels; + } else if (IS_CHAN_B(chan)) { + powerArray = ee->ee_modePowerArray5112; + data = powerArray[headerInfo11B].pDataPerChannel; + numChannels = powerArray[headerInfo11B].numChannels; + } else { + return (AH_TRUE); + } + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if (numChannels < 1) + return(AH_FALSE); + + if ((chan->channel < data[0].channelValue) || + (chan->channel > data[numChannels-1].channelValue)) { + if (chan->channel < data[0].channelValue) { + *maxPow = data[0].maxPower_t4; + *minPow = ar5112GetMinPower(ah, &data[0]); + return(AH_TRUE); + } else { + *maxPow = data[numChannels - 1].maxPower_t4; + *minPow = ar5112GetMinPower(ah, &data[numChannels - 1]); + return(AH_TRUE); + } + } + + /* Linearly interpolate the power value now */ + for (last=0,i=0; + (ichannel > data[i].channelValue); + last=i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = data[i].maxPower_t4 - data[last].maxPower_t4; + *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD); + + totalMin = ar5112GetMinPower(ah,&data[i]) - ar5112GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar5112GetMinPower(ah, &data[last])*totalD)/totalD); + return (AH_TRUE); + } else { + if (chan->channel == data[i].channelValue) { + *maxPow = data[i].maxPower_t4; + *minPow = ar5112GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar5112RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +/* + * Allocate memory for analog bank scratch buffers + * Scratch Buffer will be reinitialized every reset so no need to zero now + */ +static HAL_BOOL +ar5112RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5112State *priv; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar5112State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar5112RfDetach; + priv->base.writeRegs = ar5112WriteRegs; + priv->base.getRfBank = ar5112GetRfBank; + priv->base.setChannel = ar5112SetChannel; + priv->base.setRfRegs = ar5112SetRfRegs; + priv->base.setPowerTable = ar5112SetPowerTable; + priv->base.getChannelMaxMinPower = ar5112GetChannelMaxMinPower; + priv->base.getNfAdjust = ar5212GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + + return AH_TRUE; +} + +static HAL_BOOL +ar5112Probe(struct ath_hal *ah) +{ + return IS_RAD5112(ah); +} +AH_RF(RF5112, ar5112Probe, ar5112RfAttach); diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212.h b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212.h new file mode 100644 index 0000000000..6645b76afc --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212.h @@ -0,0 +1,603 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212.h,v 1.16 2008/11/22 07:42:00 sam Exp $ + */ +#ifndef _ATH_AR5212_H_ +#define _ATH_AR5212_H_ + +#include "ah_eeprom.h" + +#define AR5212_MAGIC 0x19541014 + +/* DCU Transmit Filter macros */ +#define CALC_MMR(dcu, idx) \ + ( (4 * dcu) + (idx < 32 ? 0 : (idx < 64 ? 1 : (idx < 96 ? 2 : 3))) ) +#define TXBLK_FROM_MMR(mmr) \ + (AR_D_TXBLK_BASE + ((mmr & 0x1f) << 6) + ((mmr & 0x20) >> 3)) +#define CALC_TXBLK_ADDR(dcu, idx) (TXBLK_FROM_MMR(CALC_MMR(dcu, idx))) +#define CALC_TXBLK_VALUE(idx) (1 << (idx & 0x1f)) + +/* MAC register values */ + +#define INIT_INTERRUPT_MASK \ + ( AR_IMR_TXERR | AR_IMR_TXOK | AR_IMR_RXORN | \ + AR_IMR_RXERR | AR_IMR_RXOK | AR_IMR_TXURN | \ + AR_IMR_HIUERR ) +#define INIT_BEACON_CONTROL \ + ((INIT_RESET_TSF << 24) | (INIT_BEACON_EN << 23) | \ + (INIT_TIM_OFFSET << 16) | INIT_BEACON_PERIOD) + +#define INIT_CONFIG_STATUS 0x00000000 +#define INIT_RSSI_THR 0x00000781 /* Missed beacon counter initialized to 0x7 (max is 0xff) */ +#define INIT_IQCAL_LOG_COUNT_MAX 0xF +#define INIT_BCON_CNTRL_REG 0x00000000 + +#define INIT_USEC 40 +#define HALF_RATE_USEC 19 /* ((40 / 2) - 1 ) */ +#define QUARTER_RATE_USEC 9 /* ((40 / 4) - 1 ) */ + +#define RX_NON_FULL_RATE_LATENCY 63 +#define TX_HALF_RATE_LATENCY 108 +#define TX_QUARTER_RATE_LATENCY 216 + +#define IFS_SLOT_FULL_RATE 0x168 /* 9 us half, 40 MHz core clock (9*40) */ +#define IFS_SLOT_HALF_RATE 0x104 /* 13 us half, 20 MHz core clock (13*20) */ +#define IFS_SLOT_QUARTER_RATE 0xD2 /* 21 us quarter, 10 MHz core clock (21*10) */ +#define IFS_EIFS_FULL_RATE 0xE60 /* (74 + (2 * 9)) * 40MHz core clock */ +#define IFS_EIFS_HALF_RATE 0xDAC /* (149 + (2 * 13)) * 20MHz core clock */ +#define IFS_EIFS_QUARTER_RATE 0xD48 /* (298 + (2 * 21)) * 10MHz core clock */ + +#define ACK_CTS_TIMEOUT_11A 0x3E8 /* ACK timeout in 11a core clocks */ + +/* Tx frame start to tx data start delay */ +#define TX_FRAME_D_START_HALF_RATE 0xc +#define TX_FRAME_D_START_QUARTER_RATE 0xd + +/* + * Various fifo fill before Tx start, in 64-byte units + * i.e. put the frame in the air while still DMAing + */ +#define MIN_TX_FIFO_THRESHOLD 0x1 +#define MAX_TX_FIFO_THRESHOLD ((IEEE80211_MAX_LEN / 64) + 1) +#define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD + +#define HAL_DECOMP_MASK_SIZE 128 /* 1 byte per key */ + +/* + * Gain support. + */ +#define NUM_CORNER_FIX_BITS 4 +#define NUM_CORNER_FIX_BITS_5112 7 +#define DYN_ADJ_UP_MARGIN 15 +#define DYN_ADJ_LO_MARGIN 20 +#define PHY_PROBE_CCK_CORRECTION 5 +#define CCK_OFDM_GAIN_DELTA 15 + +enum GAIN_PARAMS { + GP_TXCLIP, + GP_PD90, + GP_PD84, + GP_GSEL, +}; + +enum GAIN_PARAMS_5112 { + GP_MIXGAIN_OVR, + GP_PWD_138, + GP_PWD_137, + GP_PWD_136, + GP_PWD_132, + GP_PWD_131, + GP_PWD_130, +}; + +typedef struct _gainOptStep { + int16_t paramVal[NUM_CORNER_FIX_BITS_5112]; + int32_t stepGain; + int8_t stepName[16]; +} GAIN_OPTIMIZATION_STEP; + +typedef struct { + uint32_t numStepsInLadder; + uint32_t defaultStepNum; + GAIN_OPTIMIZATION_STEP optStep[10]; +} GAIN_OPTIMIZATION_LADDER; + +typedef struct { + uint32_t currStepNum; + uint32_t currGain; + uint32_t targetGain; + uint32_t loTrig; + uint32_t hiTrig; + uint32_t gainFCorrection; + uint32_t active; + const GAIN_OPTIMIZATION_STEP *currStep; +} GAIN_VALUES; + +/* RF HAL structures */ +typedef struct RfHalFuncs { + void *priv; /* private state */ + + void (*rfDetach)(struct ath_hal *ah); + void (*writeRegs)(struct ath_hal *, + u_int modeIndex, u_int freqIndex, int regWrites); + uint32_t *(*getRfBank)(struct ath_hal *ah, int bank); + HAL_BOOL (*setChannel)(struct ath_hal *, HAL_CHANNEL_INTERNAL *); + HAL_BOOL (*setRfRegs)(struct ath_hal *, + HAL_CHANNEL_INTERNAL *, uint16_t modesIndex, + uint16_t *rfXpdGain); + HAL_BOOL (*setPowerTable)(struct ath_hal *ah, + int16_t *minPower, int16_t *maxPower, + HAL_CHANNEL_INTERNAL *, uint16_t *rfXpdGain); + HAL_BOOL (*getChannelMaxMinPower)(struct ath_hal *ah, HAL_CHANNEL *, + int16_t *maxPow, int16_t *minPow); + int16_t (*getNfAdjust)(struct ath_hal *, const HAL_CHANNEL_INTERNAL*); +} RF_HAL_FUNCS; + +struct ar5212AniParams { + int maxNoiseImmunityLevel; /* [0..4] */ + int totalSizeDesired[5]; + int coarseHigh[5]; + int coarseLow[5]; + int firpwr[5]; + + int maxSpurImmunityLevel; /* [0..7] */ + int cycPwrThr1[8]; + + int maxFirstepLevel; /* [0..2] */ + int firstep[3]; + + uint32_t ofdmTrigHigh; + uint32_t ofdmTrigLow; + uint32_t cckTrigHigh; + uint32_t cckTrigLow; + int32_t rssiThrLow; + uint32_t rssiThrHigh; + + int period; /* update listen period */ + + /* NB: intentionally ordered so data exported to user space is first */ + uint32_t ofdmPhyErrBase; /* Base value for ofdm err counter */ + uint32_t cckPhyErrBase; /* Base value for cck err counters */ +}; + +/* + * Per-channel ANI state private to the driver. + */ +struct ar5212AniState { + uint8_t noiseImmunityLevel; + uint8_t spurImmunityLevel; + uint8_t firstepLevel; + uint8_t ofdmWeakSigDetectOff; + uint8_t cckWeakSigThreshold; + uint32_t listenTime; + + /* NB: intentionally ordered so data exported to user space is first */ + HAL_CHANNEL c; + HAL_BOOL isSetup; /* has state to do a restore */ + uint32_t txFrameCount; /* Last txFrameCount */ + uint32_t rxFrameCount; /* Last rx Frame count */ + uint32_t cycleCount; /* Last cycleCount + (to detect wrap-around) */ + uint32_t ofdmPhyErrCount;/* OFDM err count since last reset */ + uint32_t cckPhyErrCount; /* CCK err count since last reset */ + + const struct ar5212AniParams *params; +}; + +#define HAL_ANI_ENA 0x00000001 /* ANI operation enabled */ +#define HAL_RSSI_ANI_ENA 0x00000002 /* rssi-based processing ena'd*/ + +struct ar5212Stats { + uint32_t ast_ani_niup; /* ANI increased noise immunity */ + uint32_t ast_ani_nidown; /* ANI decreased noise immunity */ + uint32_t ast_ani_spurup; /* ANI increased spur immunity */ + uint32_t ast_ani_spurdown;/* ANI descreased spur immunity */ + uint32_t ast_ani_ofdmon; /* ANI OFDM weak signal detect on */ + uint32_t ast_ani_ofdmoff;/* ANI OFDM weak signal detect off */ + uint32_t ast_ani_cckhigh;/* ANI CCK weak signal threshold high */ + uint32_t ast_ani_ccklow; /* ANI CCK weak signal threshold low */ + uint32_t ast_ani_stepup; /* ANI increased first step level */ + uint32_t ast_ani_stepdown;/* ANI decreased first step level */ + uint32_t ast_ani_ofdmerrs;/* ANI cumulative ofdm phy err count */ + uint32_t ast_ani_cckerrs;/* ANI cumulative cck phy err count */ + uint32_t ast_ani_reset; /* ANI parameters zero'd for non-STA */ + uint32_t ast_ani_lzero; /* ANI listen time forced to zero */ + uint32_t ast_ani_lneg; /* ANI listen time calculated < 0 */ + HAL_MIB_STATS ast_mibstats; /* MIB counter stats */ + HAL_NODE_STATS ast_nodestats; /* Latest rssi stats from driver */ +}; + +/* + * NF Cal history buffer + */ +#define AR5212_CCA_MAX_GOOD_VALUE -95 +#define AR5212_CCA_MAX_HIGH_VALUE -62 +#define AR5212_CCA_MIN_BAD_VALUE -125 + +#define AR512_NF_CAL_HIST_MAX 5 + +struct ar5212NfCalHist { + int16_t nfCalBuffer[AR512_NF_CAL_HIST_MAX]; + int16_t privNF; + uint8_t currIndex; + uint8_t first_run; + uint8_t invalidNFcount; +}; + +struct ath_hal_5212 { + struct ath_hal_private ah_priv; /* base class */ + + /* + * Per-chip common Initialization data. + * NB: RF backends have their own ini data. + */ + HAL_INI_ARRAY ah_ini_modes; + HAL_INI_ARRAY ah_ini_common; + + GAIN_VALUES ah_gainValues; + + uint8_t ah_macaddr[IEEE80211_ADDR_LEN]; + uint8_t ah_bssid[IEEE80211_ADDR_LEN]; + uint8_t ah_bssidmask[IEEE80211_ADDR_LEN]; + + /* + * Runtime state. + */ + uint32_t ah_maskReg; /* copy of AR_IMR */ + struct ar5212Stats ah_stats; /* various statistics */ + RF_HAL_FUNCS *ah_rfHal; + uint32_t ah_txDescMask; /* mask for TXDESC */ + uint32_t ah_txOkInterruptMask; + uint32_t ah_txErrInterruptMask; + uint32_t ah_txDescInterruptMask; + uint32_t ah_txEolInterruptMask; + uint32_t ah_txUrnInterruptMask; + HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES]; + uint32_t ah_intrTxqs; /* tx q interrupt state */ + /* decomp mask array */ + uint8_t ah_decompMask[HAL_DECOMP_MASK_SIZE]; + HAL_POWER_MODE ah_powerMode; + HAL_ANT_SETTING ah_antControl; /* antenna setting */ + HAL_BOOL ah_diversity; /* fast diversity setting */ + enum { + IQ_CAL_INACTIVE, + IQ_CAL_RUNNING, + IQ_CAL_DONE + } ah_bIQCalibration; /* IQ calibrate state */ + HAL_RFGAIN ah_rfgainState; /* RF gain calibrartion state */ + uint32_t ah_tx6PowerInHalfDbm; /* power output for 6Mb tx */ + uint32_t ah_staId1Defaults; /* STA_ID1 default settings */ + uint32_t ah_miscMode; /* MISC_MODE settings */ + uint32_t ah_rssiThr; /* RSSI_THR settings */ + HAL_BOOL ah_cwCalRequire; /* for ap51 */ + HAL_BOOL ah_tpcEnabled; /* per-packet tpc enabled */ + HAL_BOOL ah_phyPowerOn; /* PHY power state */ + HAL_BOOL ah_isHb63; /* cached HB63 check */ + uint32_t ah_macTPC; /* tpc register */ + uint32_t ah_beaconInterval; /* XXX */ + enum { + AUTO_32KHZ, /* use it if 32kHz crystal present */ + USE_32KHZ, /* do it regardless */ + DONT_USE_32KHZ, /* don't use it regardless */ + } ah_enable32kHzClock; /* whether to sleep at 32kHz */ + uint32_t ah_ofdmTxPower; + int16_t ah_txPowerIndexOffset; + /* + * Noise floor cal histogram support. + */ + struct ar5212NfCalHist ah_nfCalHist; + + u_int ah_slottime; /* user-specified slot time */ + u_int ah_acktimeout; /* user-specified ack timeout */ + u_int ah_ctstimeout; /* user-specified cts timeout */ + u_int ah_sifstime; /* user-specified sifs time */ + /* + * RF Silent handling; setup according to the EEPROM. + */ + uint32_t ah_gpioSelect; /* GPIO pin to use */ + uint32_t ah_polarity; /* polarity to disable RF */ + uint32_t ah_gpioBit; /* after init, prev value */ + /* + * ANI support. + */ + uint32_t ah_procPhyErr; /* Process Phy errs */ + HAL_BOOL ah_hasHwPhyCounters; /* Hardware has phy counters */ + struct ar5212AniParams ah_aniParams24; /* 2.4GHz parameters */ + struct ar5212AniParams ah_aniParams5; /* 5GHz parameters */ + struct ar5212AniState *ah_curani; /* cached last reference */ + struct ar5212AniState ah_ani[64]; /* per-channel state */ + + /* + * Transmit power state. Note these are maintained + * here so they can be retrieved by diagnostic tools. + */ + uint16_t *ah_pcdacTable; + u_int ah_pcdacTableSize; + uint16_t ah_ratesArray[16]; +}; +#define AH5212(_ah) ((struct ath_hal_5212 *)(_ah)) + +/* + * IS_XXXX macros test the MAC version + * IS_RADXXX macros test the radio/RF version (matching both 2G-only and 2/5G) + * + * Some single chip radios have equivalent radio/RF (e.g. 5112) + * for those use IS_RADXXX_ANY macros. + */ +#define IS_2317(ah) \ + ((AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV1) || \ + (AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV2)) +#define IS_2316(ah) \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2415) +#define IS_2413(ah) \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2413 || IS_2316(ah)) +#define IS_5424(ah) \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_5424 || \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_5413 && \ + AH_PRIVATE(ah)->ah_macRev <= AR_SREV_D2PLUS_MS)) +#define IS_5413(ah) \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_5413 || IS_5424(ah)) +#define IS_2425(ah) \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2425) +#define IS_2417(ah) \ + ((AH_PRIVATE(ah)->ah_macVersion) == AR_SREV_2417) +#define IS_HB63(ah) (AH5212(ah)->ah_isHb63 == AH_TRUE) + +#define IS_PCIE(ah) (IS_5424(ah) || IS_2425(ah)) + +#define AH_RADIO_MAJOR(ah) \ + (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) +#define AH_RADIO_MINOR(ah) \ + (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MINOR) +#define IS_RAD5111(ah) \ + (AH_RADIO_MAJOR(ah) == AR_RAD5111_SREV_MAJOR || \ + AH_RADIO_MAJOR(ah) == AR_RAD2111_SREV_MAJOR) +#define IS_RAD5112(ah) \ + (AH_RADIO_MAJOR(ah) == AR_RAD5112_SREV_MAJOR || \ + AH_RADIO_MAJOR(ah) == AR_RAD2112_SREV_MAJOR) +/* NB: does not include 5413 as Atheros' IS_5112 macro does */ +#define IS_RAD5112_ANY(ah) \ + (AR_RAD5112_SREV_MAJOR <= AH_RADIO_MAJOR(ah) && \ + AH_RADIO_MAJOR(ah) <= AR_RAD2413_SREV_MAJOR) +#define IS_RAD5112_REV1(ah) \ + (IS_RAD5112(ah) && \ + AH_RADIO_MINOR(ah) < (AR_RAD5112_SREV_2_0 & AR_RADIO_SREV_MINOR)) +#define IS_RADX112_REV2(ah) \ + (AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD5112_SREV_2_0 || \ + AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD2112_SREV_2_0 || \ + AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD2112_SREV_2_1 || \ + AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD5112_SREV_2_1) + +#define ar5212RfDetach(ah) do { \ + if (AH5212(ah)->ah_rfHal != AH_NULL) \ + AH5212(ah)->ah_rfHal->rfDetach(ah); \ +} while (0) +#define ar5212GetRfBank(ah, b) \ + AH5212(ah)->ah_rfHal->getRfBank(ah, b) + +/* + * Hack macros for Nala/San: 11b is handled + * using 11g; flip the channel flags to accomplish this. + */ +#define SAVE_CCK(_ah, _chan, _flag) do { \ + if ((IS_2425(_ah) || IS_2417(_ah)) && \ + (((_chan)->channelFlags) & CHANNEL_CCK)) { \ + (_chan)->channelFlags &= ~CHANNEL_CCK; \ + (_chan)->channelFlags |= CHANNEL_OFDM; \ + (_flag) = AH_TRUE; \ + } \ +} while (0) +#define RESTORE_CCK(_ah, _chan, _flag) do { \ + if ((IS_2425(_ah) || IS_2417(_ah)) && (_flag) == AH_TRUE) {\ + (_chan)->channelFlags &= ~CHANNEL_OFDM; \ + (_chan)->channelFlags |= CHANNEL_CCK; \ + } \ +} while (0) + +struct ath_hal; + +extern uint32_t ar5212GetRadioRev(struct ath_hal *ah); +extern void ar5212InitState(struct ath_hal_5212 *, uint16_t devid, HAL_SOFTC, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status); +extern void ar5212Detach(struct ath_hal *ah); +extern HAL_BOOL ar5212ChipTest(struct ath_hal *ah); +extern HAL_BOOL ar5212GetChannelEdges(struct ath_hal *ah, + uint16_t flags, uint16_t *low, uint16_t *high); +extern HAL_BOOL ar5212FillCapabilityInfo(struct ath_hal *ah); + +extern void ar5212SetBeaconTimers(struct ath_hal *ah, + const HAL_BEACON_TIMERS *); +extern void ar5212BeaconInit(struct ath_hal *ah, + uint32_t next_beacon, uint32_t beacon_period); +extern void ar5212ResetStaBeaconTimers(struct ath_hal *ah); +extern void ar5212SetStaBeaconTimers(struct ath_hal *ah, + const HAL_BEACON_STATE *); + +extern HAL_BOOL ar5212IsInterruptPending(struct ath_hal *ah); +extern HAL_BOOL ar5212GetPendingInterrupts(struct ath_hal *ah, HAL_INT *); +extern HAL_INT ar5212GetInterrupts(struct ath_hal *ah); +extern HAL_INT ar5212SetInterrupts(struct ath_hal *ah, HAL_INT ints); + +extern uint32_t ar5212GetKeyCacheSize(struct ath_hal *); +extern HAL_BOOL ar5212IsKeyCacheEntryValid(struct ath_hal *, uint16_t entry); +extern HAL_BOOL ar5212ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry); +extern HAL_BOOL ar5212SetKeyCacheEntryMac(struct ath_hal *, + uint16_t entry, const uint8_t *mac); +extern HAL_BOOL ar5212SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, + const HAL_KEYVAL *k, const uint8_t *mac, int xorKey); + +extern void ar5212GetMacAddress(struct ath_hal *ah, uint8_t *mac); +extern HAL_BOOL ar5212SetMacAddress(struct ath_hal *ah, const uint8_t *); +extern void ar5212GetBssIdMask(struct ath_hal *ah, uint8_t *mac); +extern HAL_BOOL ar5212SetBssIdMask(struct ath_hal *, const uint8_t *); +extern HAL_BOOL ar5212EepromRead(struct ath_hal *, u_int off, uint16_t *data); +extern HAL_BOOL ar5212EepromWrite(struct ath_hal *, u_int off, uint16_t data); +extern HAL_BOOL ar5212SetRegulatoryDomain(struct ath_hal *ah, + uint16_t regDomain, HAL_STATUS *stats); +extern u_int ar5212GetWirelessModes(struct ath_hal *ah); +extern void ar5212EnableRfKill(struct ath_hal *); +extern HAL_BOOL ar5212GpioCfgOutput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5212GpioCfgInput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5212GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val); +extern uint32_t ar5212GpioGet(struct ath_hal *ah, uint32_t gpio); +extern void ar5212GpioSetIntr(struct ath_hal *ah, u_int, uint32_t ilevel); +extern void ar5212SetLedState(struct ath_hal *ah, HAL_LED_STATE state); +extern void ar5212WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, + uint16_t assocId); +extern uint32_t ar5212GetTsf32(struct ath_hal *ah); +extern uint64_t ar5212GetTsf64(struct ath_hal *ah); +extern void ar5212ResetTsf(struct ath_hal *ah); +extern void ar5212SetBasicRate(struct ath_hal *ah, HAL_RATE_SET *pSet); +extern uint32_t ar5212GetRandomSeed(struct ath_hal *ah); +extern HAL_BOOL ar5212DetectCardPresent(struct ath_hal *ah); +extern void ar5212EnableMibCounters(struct ath_hal *); +extern void ar5212DisableMibCounters(struct ath_hal *); +extern void ar5212UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS* stats); +extern HAL_BOOL ar5212IsJapanChannelSpreadSupported(struct ath_hal *ah); +extern uint32_t ar5212GetCurRssi(struct ath_hal *ah); +extern u_int ar5212GetDefAntenna(struct ath_hal *ah); +extern void ar5212SetDefAntenna(struct ath_hal *ah, u_int antenna); +extern HAL_ANT_SETTING ar5212GetAntennaSwitch(struct ath_hal *); +extern HAL_BOOL ar5212SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); +extern HAL_BOOL ar5212IsSleepAfterBeaconBroken(struct ath_hal *ah); +extern HAL_BOOL ar5212SetSifsTime(struct ath_hal *, u_int); +extern u_int ar5212GetSifsTime(struct ath_hal *); +extern HAL_BOOL ar5212SetSlotTime(struct ath_hal *, u_int); +extern u_int ar5212GetSlotTime(struct ath_hal *); +extern HAL_BOOL ar5212SetAckTimeout(struct ath_hal *, u_int); +extern u_int ar5212GetAckTimeout(struct ath_hal *); +extern HAL_BOOL ar5212SetAckCTSRate(struct ath_hal *, u_int); +extern u_int ar5212GetAckCTSRate(struct ath_hal *); +extern HAL_BOOL ar5212SetCTSTimeout(struct ath_hal *, u_int); +extern u_int ar5212GetCTSTimeout(struct ath_hal *); +extern HAL_BOOL ar5212SetDecompMask(struct ath_hal *, uint16_t, int); +void ar5212SetCoverageClass(struct ath_hal *, uint8_t, int); +extern void ar5212SetPCUConfig(struct ath_hal *); +extern HAL_BOOL ar5212Use32KHzclock(struct ath_hal *ah, HAL_OPMODE opmode); +extern void ar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode); +extern void ar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode); +extern int16_t ar5212GetNfAdjust(struct ath_hal *, + const HAL_CHANNEL_INTERNAL *); +extern void ar5212SetCompRegs(struct ath_hal *ah); +extern HAL_STATUS ar5212GetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, + uint32_t, uint32_t *); +extern HAL_BOOL ar5212SetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, + uint32_t, uint32_t, HAL_STATUS *); +extern HAL_BOOL ar5212GetDiagState(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize); + +extern HAL_BOOL ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, + int setChip); +extern HAL_POWER_MODE ar5212GetPowerMode(struct ath_hal *ah); +extern HAL_BOOL ar5212GetPowerStatus(struct ath_hal *ah); + +extern uint32_t ar5212GetRxDP(struct ath_hal *ath); +extern void ar5212SetRxDP(struct ath_hal *ah, uint32_t rxdp); +extern void ar5212EnableReceive(struct ath_hal *ah); +extern HAL_BOOL ar5212StopDmaReceive(struct ath_hal *ah); +extern void ar5212StartPcuReceive(struct ath_hal *ah); +extern void ar5212StopPcuReceive(struct ath_hal *ah); +extern void ar5212SetMulticastFilter(struct ath_hal *ah, + uint32_t filter0, uint32_t filter1); +extern HAL_BOOL ar5212ClrMulticastFilterIndex(struct ath_hal *, uint32_t ix); +extern HAL_BOOL ar5212SetMulticastFilterIndex(struct ath_hal *, uint32_t ix); +extern uint32_t ar5212GetRxFilter(struct ath_hal *ah); +extern void ar5212SetRxFilter(struct ath_hal *ah, uint32_t bits); +extern HAL_BOOL ar5212SetupRxDesc(struct ath_hal *, + struct ath_desc *, uint32_t size, u_int flags); +extern HAL_STATUS ar5212ProcRxDesc(struct ath_hal *ah, struct ath_desc *, + uint32_t, struct ath_desc *, uint64_t, + struct ath_rx_status *); + +extern HAL_BOOL ar5212Reset(struct ath_hal *ah, HAL_OPMODE opmode, + HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status); +extern HAL_BOOL ar5212SetChannel(struct ath_hal *, HAL_CHANNEL_INTERNAL *); +extern void ar5212SetOperatingMode(struct ath_hal *ah, int opmode); +extern HAL_BOOL ar5212PhyDisable(struct ath_hal *ah); +extern HAL_BOOL ar5212Disable(struct ath_hal *ah); +extern HAL_BOOL ar5212ChipReset(struct ath_hal *ah, HAL_CHANNEL *); +extern HAL_BOOL ar5212PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, + HAL_BOOL *isIQdone); +extern HAL_BOOL ar5212PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan, + u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); +extern HAL_BOOL ar5212ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan); +extern int16_t ar5212GetNoiseFloor(struct ath_hal *ah); +extern void ar5212InitNfCalHistBuffer(struct ath_hal *); +extern int16_t ar5212GetNfHistMid(const int16_t calData[]); +extern void ar5212SetSpurMitigation(struct ath_hal *, HAL_CHANNEL_INTERNAL *); +extern HAL_BOOL ar5212SetAntennaSwitchInternal(struct ath_hal *ah, + HAL_ANT_SETTING settings, const HAL_CHANNEL_INTERNAL *ichan); +extern HAL_BOOL ar5212SetTxPowerLimit(struct ath_hal *ah, uint32_t limit); +extern HAL_BOOL ar5212GetChipPowerLimits(struct ath_hal *ah, + HAL_CHANNEL *chans, uint32_t nchans); +extern void ar5212InitializeGainValues(struct ath_hal *); +extern HAL_RFGAIN ar5212GetRfgain(struct ath_hal *ah); +extern void ar5212RequestRfgain(struct ath_hal *); + +extern HAL_BOOL ar5212UpdateTxTrigLevel(struct ath_hal *, + HAL_BOOL IncTrigLevel); +extern HAL_BOOL ar5212SetTxQueueProps(struct ath_hal *ah, int q, + const HAL_TXQ_INFO *qInfo); +extern HAL_BOOL ar5212GetTxQueueProps(struct ath_hal *ah, int q, + HAL_TXQ_INFO *qInfo); +extern int ar5212SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo); +extern HAL_BOOL ar5212ReleaseTxQueue(struct ath_hal *ah, u_int q); +extern HAL_BOOL ar5212ResetTxQueue(struct ath_hal *ah, u_int q); +extern uint32_t ar5212GetTxDP(struct ath_hal *ah, u_int q); +extern HAL_BOOL ar5212SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp); +extern HAL_BOOL ar5212StartTxDma(struct ath_hal *ah, u_int q); +extern uint32_t ar5212NumTxPending(struct ath_hal *ah, u_int q); +extern HAL_BOOL ar5212StopTxDma(struct ath_hal *ah, u_int q); +extern HAL_BOOL ar5212SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower, + u_int txRate0, u_int txTries0, + u_int keyIx, u_int antMode, u_int flags, + u_int rtsctsRate, u_int rtsctsDuration, + u_int compicvLen, u_int compivLen, u_int comp); +extern HAL_BOOL ar5212SetupXTxDesc(struct ath_hal *, struct ath_desc *, + u_int txRate1, u_int txRetries1, + u_int txRate2, u_int txRetries2, + u_int txRate3, u_int txRetries3); +extern HAL_BOOL ar5212FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg, + const struct ath_desc *ds0); +extern HAL_STATUS ar5212ProcTxDesc(struct ath_hal *ah, + struct ath_desc *, struct ath_tx_status *); +extern void ar5212GetTxIntrQueue(struct ath_hal *ah, uint32_t *); +extern void ar5212IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *); + +extern const HAL_RATE_TABLE *ar5212GetRateTable(struct ath_hal *, u_int mode); + +extern void ar5212AniAttach(struct ath_hal *, const struct ar5212AniParams *, + const struct ar5212AniParams *, HAL_BOOL ena); +extern void ar5212AniDetach(struct ath_hal *); +extern struct ar5212AniState *ar5212AniGetCurrentState(struct ath_hal *); +extern struct ar5212Stats *ar5212AniGetCurrentStats(struct ath_hal *); +extern HAL_BOOL ar5212AniControl(struct ath_hal *, HAL_ANI_CMD cmd, int param); +extern HAL_BOOL ar5212AniSetParams(struct ath_hal *, + const struct ar5212AniParams *, const struct ar5212AniParams *); +struct ath_rx_status; +extern void ar5212AniPhyErrReport(struct ath_hal *ah, + const struct ath_rx_status *rs); +extern void ar5212ProcessMibIntr(struct ath_hal *, const HAL_NODE_STATS *); +extern void ar5212AniPoll(struct ath_hal *, const HAL_NODE_STATS *, + HAL_CHANNEL *); +extern void ar5212AniReset(struct ath_hal *, HAL_CHANNEL_INTERNAL *, + HAL_OPMODE, int); +#endif /* _ATH_AR5212_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212.ini b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212.ini new file mode 100644 index 0000000000..d53dbe2e97 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212.ini @@ -0,0 +1,2171 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212.ini,v 1.3 2008/11/10 04:08:03 sam Exp $ + */ +/* Auto Generated PCI Register Writes. Created: 09/01/04 */ + +#ifdef AH_5212_COMMON +static const uint32_t ar5212Modes[][6] = { + { 0x00001040, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x00001030, 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 }, + { 0x00008014, 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 }, + { 0x00009804, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e }, + { 0x00009844, 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 }, + { 0x00009860, 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 }, + { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, + { 0x00009918, 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 }, + { 0x00009924, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 }, +}; +#endif /* AH_5212_COMMON */ + +#ifdef AH_5212_5111 +static const uint32_t ar5212Modes_5111[][6] = { + { 0x00000030, 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 }, + { 0x0000801c, 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b }, + { 0x00009848, 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 }, + { 0x00009850, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 }, + { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e }, + { 0x0000985c, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 }, + { 0x00009914, 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 }, + { 0x00009944, 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 }, + { 0x0000a20c, 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a }, +}; +#endif /* AH_5212_5111 */ + +#ifdef AH_5212_5112 +static const uint32_t ar5212Modes_5112[][6] = { + { 0x00000030, 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 }, + { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b }, + { 0x00009848, 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 }, + { 0x00009850, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 }, + { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e }, + { 0x0000985c, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 }, + { 0x00009944, 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 }, + { 0x0000a204, 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 }, + { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 }, + { 0x0000a20c, 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a }, +}; +#endif /* AH_5212_5112 */ + +#ifdef AH_5212_2413 +static const uint32_t ar5212Modes_2413[][6] = { + { 0x00000030, 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 }, + { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 }, + { 0x00009838, 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a }, + { 0x00009848, 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 }, + { 0x00009850, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da }, + { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e }, + { 0x0000985c, 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 }, + { 0x00009944, 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 }, + { 0x0000a204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 }, + { 0x0000a20c, 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a }, +}; +#endif /* AH_5212_2413 */ + +#ifdef AH_5212_2316 +static const uint32_t ar5212Modes_2316[][6] = { + { 0x00000030, 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 }, + { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 }, + { 0x00009838, 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a }, + { 0x00009848, 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 }, + { 0x00009850, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da }, + { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e }, + { 0x0000985c, 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 }, + { 0x00009944, 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 }, + { 0x0000a204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 }, + { 0x0000a20c, 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a }, +}; +#endif + +#ifdef AH_5212_5413 +static const uint32_t ar5212Modes_5413[][6] = { + { 0x00000030, 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 }, + { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b }, + { 0x00009848, 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 }, + { 0x00009850, 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da }, + { 0x00009858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 }, + { 0x00009944, 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 }, + { 0x0000a204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 }, + { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a }, + { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, + { 0x0000a304, 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 }, + { 0x0000a308, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 }, + { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a }, + { 0x0000a310, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f }, + { 0x0000a314, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b }, + { 0x0000a318, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a }, + { 0x0000a31c, 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b }, + { 0x0000a320, 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f }, + { 0x0000a324, 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f }, + { 0x0000a328, 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f }, + { 0x0000a32c, 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f }, + { 0x0000a330, 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f }, + { 0x0000a334, 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf }, +}; +#endif /* AH_5212_5413 */ + +#ifdef AH_5212_2425 +static const uint32_t ar5212Modes_2425[][6] = { + { 0x00000030, 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 }, + { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf }, + { 0x00009804, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001 }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000003, 0x00000003, 0x0000000b, 0x0000000b, 0x0000000b }, + { 0x00009844, 0x1372161c, 0x13721c25, 0x13721722, 0x13721422, 0x13721c25 }, + { 0x00009848, 0x0018fa61, 0x0018fa61, 0x00199a65, 0x00199a65, 0x00199a65 }, + { 0x00009850, 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da }, + { 0x00009858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 }, + { 0x00009944, 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 }, + { 0x0000a204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 }, + { 0x0000a20c, 0x00000140, 0x00000140, 0x0052c140, 0x0052c140, 0x0052c140 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a }, + { 0x0000a324, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf }, + { 0x0000a328, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf }, + { 0x0000a32c, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf }, + { 0x0000a330, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf }, + { 0x0000a334, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf }, +}; +#endif /* AH_5212_2425 */ + +#ifdef AH_5212_COMMON +static const uint32_t ar5212Common[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008020, 0x00000000 }, + { 0x00008024, 0x00000000 }, + { 0x00008028, 0x00000030 }, + { 0x0000802c, 0x0007ffff }, + { 0x00008030, 0x01ffffff }, + { 0x00008034, 0x00000031 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x00000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e1c }, + { 0x000080d4, 0x0002aaaa }, + { 0x000080d8, 0x02005555 }, + { 0x000080dc, 0x00000000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x00000000 }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00000088 }, + { 0x00008700, 0x00000000 }, + { 0x00008704, 0x0000008c }, + { 0x00008708, 0x000000e4 }, + { 0x0000870c, 0x000002d5 }, + { 0x00008710, 0x00000000 }, + { 0x00008714, 0x00000000 }, + { 0x00008718, 0x000000a0 }, + { 0x0000871c, 0x000001c9 }, + { 0x00008720, 0x0000002c }, + { 0x00008724, 0x0000002c }, + { 0x00008728, 0x00000030 }, + { 0x0000872c, 0x0000003c }, + { 0x00008730, 0x0000002c }, + { 0x00008734, 0x0000002c }, + { 0x00008738, 0x00000030 }, + { 0x0000873c, 0x0000003c }, + { 0x00008740, 0x00000000 }, + { 0x00008744, 0x00000000 }, + { 0x00008748, 0x00000000 }, + { 0x0000874c, 0x00000000 }, + { 0x00008750, 0x00000000 }, + { 0x00008754, 0x00000000 }, + { 0x00008758, 0x00000000 }, + { 0x0000875c, 0x00000000 }, + { 0x00008760, 0x000000d5 }, + { 0x00008764, 0x000000df }, + { 0x00008768, 0x00000102 }, + { 0x0000876c, 0x0000013a }, + { 0x00008770, 0x00000075 }, + { 0x00008774, 0x0000007f }, + { 0x00008778, 0x000000a2 }, + { 0x0000877c, 0x00000000 }, + { 0x00008100, 0x00010002 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x000000c0 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008114, 0x00000000 }, + { 0x000087c0, 0x03020100 }, + { 0x000087c4, 0x07060504 }, + { 0x000087c8, 0x0b0a0908 }, + { 0x000087cc, 0x0f0e0d0c }, + { 0x000087d0, 0x13121110 }, + { 0x000087d4, 0x17161514 }, + { 0x000087d8, 0x1b1a1918 }, + { 0x000087dc, 0x1f1e1d1c }, + { 0x000087e0, 0x03020100 }, + { 0x000087e4, 0x07060504 }, + { 0x000087e8, 0x0b0a0908 }, + { 0x000087ec, 0x0f0e0d0c }, + { 0x000087f0, 0x13121110 }, + { 0x000087f4, 0x17161514 }, + { 0x000087f8, 0x1b1a1918 }, + { 0x000087fc, 0x1f1e1d1c }, + { 0x0000980c, 0xad848e19 }, + { 0x00009810, 0x7d28e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x00009840, 0x206a017a }, + { 0x00009854, 0x00000859 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00800000 }, + { 0x00009910, 0x00000001 }, + { 0x0000991c, 0x00000c80 }, + { 0x00009920, 0x05100000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x0000003f }, + { 0x00009948, 0x9280b212 }, + { 0x00009954, 0x5d50e188 }, + { 0x0000995c, 0x004b6a8e }, + { 0x00009968, 0x000003ce }, + { 0x00009970, 0x192fb515 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x0000a210, 0x00806333 }, + { 0x0000a214, 0x00106c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x018830c6 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x00009b00, 0x00000000 }, + { 0x00009b28, 0x0000000c }, + { 0x00009b38, 0x00000012 }, + { 0x00009b64, 0x00000021 }, + { 0x00009b8c, 0x0000002d }, + { 0x00009b9c, 0x00000033 }, +}; +#endif /* AH_5212_COMMON */ + +#ifdef AH_5212_5111 +static const uint32_t ar5212Common_5111[][2] = { + { 0x00001230, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000982c, 0x00022ffe }, + { 0x0000983c, 0x00020100 }, + { 0x0000984c, 0x1284613c }, + { 0x00009930, 0x00004883 }, + { 0x00009940, 0x00000004 }, + { 0x00009958, 0x000000ff }, + { 0x00009974, 0x00000000 }, + { 0x000099f8, 0x00000018 }, + { 0x0000a204, 0x00000000 }, + { 0x0000a208, 0xd03e6788 }, + { 0x0000a228, 0x000001b5 }, + { 0x0000a23c, 0x13c889af }, + { 0x00009b04, 0x00000020 }, + { 0x00009b08, 0x00000010 }, + { 0x00009b0c, 0x00000030 }, + { 0x00009b10, 0x00000008 }, + { 0x00009b14, 0x00000028 }, + { 0x00009b18, 0x00000004 }, + { 0x00009b1c, 0x00000024 }, + { 0x00009b20, 0x00000014 }, + { 0x00009b24, 0x00000034 }, + { 0x00009b2c, 0x0000002c }, + { 0x00009b30, 0x00000002 }, + { 0x00009b34, 0x00000022 }, + { 0x00009b3c, 0x00000032 }, + { 0x00009b40, 0x0000000a }, + { 0x00009b44, 0x0000002a }, + { 0x00009b48, 0x00000006 }, + { 0x00009b4c, 0x00000026 }, + { 0x00009b50, 0x00000016 }, + { 0x00009b54, 0x00000036 }, + { 0x00009b58, 0x0000000e }, + { 0x00009b5c, 0x0000002e }, + { 0x00009b60, 0x00000001 }, + { 0x00009b68, 0x00000011 }, + { 0x00009b6c, 0x00000031 }, + { 0x00009b70, 0x00000009 }, + { 0x00009b74, 0x00000029 }, + { 0x00009b78, 0x00000005 }, + { 0x00009b7c, 0x00000025 }, + { 0x00009b80, 0x00000015 }, + { 0x00009b84, 0x00000035 }, + { 0x00009b88, 0x0000000d }, + { 0x00009b90, 0x00000003 }, + { 0x00009b94, 0x00000023 }, + { 0x00009b98, 0x00000013 }, + { 0x00009ba0, 0x0000000b }, + { 0x00009ba4, 0x0000002b }, + { 0x00009ba8, 0x0000002b }, + { 0x00009bac, 0x0000002b }, + { 0x00009bb0, 0x0000002b }, + { 0x00009bb4, 0x0000002b }, + { 0x00009bb8, 0x0000002b }, + { 0x00009bbc, 0x0000002b }, + { 0x00009bc0, 0x0000002b }, + { 0x00009bc4, 0x0000002b }, + { 0x00009bc8, 0x0000002b }, + { 0x00009bcc, 0x0000002b }, + { 0x00009bd0, 0x0000002b }, + { 0x00009bd4, 0x0000002b }, + { 0x00009bd8, 0x0000002b }, + { 0x00009bdc, 0x0000002b }, + { 0x00009be0, 0x0000002b }, + { 0x00009be4, 0x0000002b }, + { 0x00009be8, 0x0000002b }, + { 0x00009bec, 0x0000002b }, + { 0x00009bf0, 0x0000002b }, + { 0x00009bf4, 0x0000002b }, + { 0x00009bf8, 0x00000002 }, + { 0x00009bfc, 0x00000016 }, +}; +#endif /* AH_5212_5111 */ + +#ifdef AH_5212_5112 +static const uint32_t ar5212Common_5112[][2] = { + { 0x00001230, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000982c, 0x00022ffe }, + { 0x0000983c, 0x00020100 }, + { 0x0000984c, 0x1284613c }, + { 0x00009930, 0x00004882 }, + { 0x00009940, 0x00000004 }, + { 0x00009958, 0x000000ff }, + { 0x00009974, 0x00000000 }, + { 0x0000a228, 0x000001b5 }, + { 0x0000a23c, 0x13c889af }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, +}; +#endif /* AH_5212_5112 */ + +#ifdef AH_5212_2413 +static const uint32_t ar5212Common_2413[][2] = { + { 0x00001230, 0x000003e0 }, + { 0x00008060, 0x0000000f }, + { 0x00008118, 0x00000000 }, + { 0x0000811c, 0x00000000 }, + { 0x00008120, 0x00000000 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008140, 0x800000a8 }, + { 0x00008144, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x1284233c }, + { 0x00009870, 0x0000001f }, + { 0x00009874, 0x00000080 }, + { 0x00009878, 0x0000000e }, + { 0x00009958, 0x000000ff }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x02800000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x000000aa }, + { 0x000099f0, 0x0000000c }, + { 0x000099f4, 0x000000ff }, + { 0x000099f8, 0x00000014 }, + { 0x0000a228, 0x000009b5 }, + { 0x0000a23c, 0x93c889af }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0x5f690f01 }, + { 0x0000a264, 0x00418a11 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0c30c16a }, + { 0x0000a270, 0x00820820 }, + { 0x0000a274, 0x001b7caa }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x051701ce }, + { 0x0000a300, 0x18010000 }, + { 0x0000a304, 0x30032602 }, + { 0x0000a308, 0x48073e06 }, + { 0x0000a30c, 0x560b4c0a }, + { 0x0000a310, 0x641a600f }, + { 0x0000a314, 0x784f6e1b }, + { 0x0000a318, 0x868f7c5a }, + { 0x0000a31c, 0x8ecf865b }, + { 0x0000a320, 0x9d4f970f }, + { 0x0000a324, 0xa5cfa18f }, + { 0x0000a328, 0xb55faf1f }, + { 0x0000a32c, 0xbddfb99f }, + { 0x0000a330, 0xcd7fc73f }, + { 0x0000a334, 0xd5ffd1bf }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa1f }, + { 0x0000a35c, 0x066c420f }, + { 0x0000a360, 0x0f282207 }, + { 0x0000a364, 0x17601685 }, + { 0x0000a368, 0x1f801104 }, + { 0x0000a36c, 0x37a00c03 }, + { 0x0000a370, 0x3fc40883 }, + { 0x0000a374, 0x57c00803 }, + { 0x0000a378, 0x5fd80682 }, + { 0x0000a37c, 0x7fe00482 }, + { 0x0000a380, 0x7f3c7bba }, + { 0x0000a384, 0xf3307ff0 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, +}; +#endif /* AH_5212_2413 */ + +#ifdef AH_5212_2316 +static const uint32_t ar5212Common_2316[][2] = { + { 0x00001230, 0x000003e0 }, + { 0x00008060, 0x0000000f }, + { 0x00008118, 0x00000000 }, + { 0x0000811c, 0x00000000 }, + { 0x00008120, 0x00000000 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008140, 0x800000a8 }, + { 0x00008144, 0x00000000 }, + { 0x00009808, 0x00004000 }, + { 0x0000982c, 0x0000a000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x1284233c }, + { 0x00009870, 0x0000001f }, + { 0x00009874, 0x00000080 }, + { 0x00009878, 0x0000000e }, + { 0x00009958, 0x000000ff }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x02800000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x000000aa }, + { 0x000099f0, 0x0000000c }, + { 0x000099f4, 0x000000ff }, + { 0x000099f8, 0x00000014 }, + { 0x0000a228, 0x000009b5 }, + { 0x0000a23c, 0x93c889af }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0x5f690f01 }, + { 0x0000a264, 0x00418a11 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0c30c16a }, + { 0x0000a270, 0x00820820 }, + { 0x0000a274, 0x081b7caa }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x051701ce }, + { 0x0000a300, 0x18010000 }, + { 0x0000a304, 0x30032602 }, + { 0x0000a308, 0x48073e06 }, + { 0x0000a30c, 0x560b4c0a }, + { 0x0000a310, 0x641a600f }, + { 0x0000a314, 0x784f6e1b }, + { 0x0000a318, 0x868f7c5a }, + { 0x0000a31c, 0x8ecf865b }, + { 0x0000a320, 0x9d4f970f }, + { 0x0000a324, 0xa5cfa18f }, + { 0x0000a328, 0xb55faf1f }, + { 0x0000a32c, 0xbddfb99f }, + { 0x0000a330, 0xcd7fc73f }, + { 0x0000a334, 0xd5ffd1bf }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa1f }, + { 0x0000a35c, 0x066c420f }, + { 0x0000a360, 0x0f282207 }, + { 0x0000a364, 0x17601685 }, + { 0x0000a368, 0x1f801104 }, + { 0x0000a36c, 0x37a00c03 }, + { 0x0000a370, 0x3fc40883 }, + { 0x0000a374, 0x57c00803 }, + { 0x0000a378, 0x5fd80682 }, + { 0x0000a37c, 0x7fe00482 }, + { 0x0000a380, 0x7f3c7bba }, + { 0x0000a384, 0xf3307ff0 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, +}; +#endif + +#ifdef AH_5212_5413 +static const uint32_t ar5212Common_5413[][2] = { + { 0x00001230, 0x000003e0 }, + { 0x00004068, 0x00000010 }, + { 0x00008060, 0x0000000f }, + { 0x0000809c, 0x00000000 }, + { 0x000080a0, 0x00000000 }, + { 0x00008118, 0x00000000 }, + { 0x0000811c, 0x00000000 }, + { 0x00008120, 0x00000000 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008140, 0x800003f9 }, + { 0x00008144, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x1284233c }, + { 0x00009870, 0x0000001f }, + { 0x00009874, 0x00000080 }, + { 0x00009878, 0x0000000e }, + { 0x00009958, 0x00081fff }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x02800000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x000000aa }, + { 0x000099f0, 0x0000000c }, + { 0x000099f4, 0x000000ff }, + { 0x000099f8, 0x00000014 }, + { 0x0000a228, 0x000009b5 }, + { 0x0000a23c, 0x93c889af }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0x5f690f01 }, + { 0x0000a264, 0x00418a11 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0c30c16a }, + { 0x0000a270, 0x00820820 }, + { 0x0000a274, 0x081b7caa }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x051701ce }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa1f }, + { 0x0000a35c, 0x066c420f }, + { 0x0000a360, 0x0f282207 }, + { 0x0000a364, 0x17601685 }, + { 0x0000a368, 0x1f801104 }, + { 0x0000a36c, 0x37a00c03 }, + { 0x0000a370, 0x3fc40883 }, + { 0x0000a374, 0x57c00803 }, + { 0x0000a378, 0x5fd80682 }, + { 0x0000a37c, 0x7fe00482 }, + { 0x0000a380, 0x7f3c7bba }, + { 0x0000a384, 0xf3307ff0 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, +}; +#endif /* AH_5212_5413 */ + +#ifdef AH_5212_2425 +static const uint32_t ar5212Common_2425[][2] = { + { 0x00001230, 0x000003e0 }, + { 0x00008060, 0x0000000f }, + { 0x0000809c, 0x00000000 }, + { 0x000080a0, 0x00000000 }, + { 0x00008118, 0x00000000 }, + { 0x0000811c, 0x00000000 }, + { 0x00008120, 0x00000000 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008140, 0x800003f9 }, + { 0x00008144, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x1284233c }, + { 0x00009870, 0x0000001f }, + { 0x00009874, 0x00000080 }, + { 0x00009878, 0x0000000e }, + { 0x00009958, 0x00081fff }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x02800000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099dc, 0xfebadbe8 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x000000aa }, + { 0x000099f0, 0x0000000c }, + { 0x000099f4, 0x000000ff }, + { 0x000099f8, 0x00000014 }, + { 0x0000a228, 0x000009b5 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x93c889af }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0x5f690f01 }, + { 0x0000a264, 0x00418a11 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0c30c166 }, + { 0x0000a270, 0x00820820 }, + { 0x0000a274, 0x081a3caa }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x051701ce }, + { 0x0000a300, 0x16010000 }, + { 0x0000a304, 0x2c032402 }, + { 0x0000a308, 0x48433e42 }, + { 0x0000a30c, 0x5a0f500b }, + { 0x0000a310, 0x6c4b624a }, + { 0x0000a314, 0x7e8b748a }, + { 0x0000a318, 0x96cf8ccb }, + { 0x0000a31c, 0xa34f9d0f }, + { 0x0000a320, 0xa7cfa58f }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa1f }, + { 0x0000a35c, 0x066c420f }, + { 0x0000a360, 0x0f282207 }, + { 0x0000a364, 0x17601685 }, + { 0x0000a368, 0x1f801104 }, + { 0x0000a36c, 0x37a00c03 }, + { 0x0000a370, 0x3fc40883 }, + { 0x0000a374, 0x57c00803 }, + { 0x0000a378, 0x5fd80682 }, + { 0x0000a37c, 0x7fe00482 }, + { 0x0000a380, 0x7f3c7bba }, + { 0x0000a384, 0xf3307ff0 }, +}; +#endif /* AH_5212_2425 */ + +#ifdef AH_5212_5111 +static const uint32_t ar5212Bank0_5111[][6] = { + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 }, + { 0x0000989c, 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd }, + { 0x000098d4, 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 }, +}; + +static const uint32_t ar5212BB_RfGain_5111[][3] = { + { 0x00009a00, 0x000001a9, 0x00000000 }, + { 0x00009a04, 0x000001e9, 0x00000040 }, + { 0x00009a08, 0x00000029, 0x00000080 }, + { 0x00009a0c, 0x00000069, 0x00000150 }, + { 0x00009a10, 0x00000199, 0x00000190 }, + { 0x00009a14, 0x000001d9, 0x000001d0 }, + { 0x00009a18, 0x00000019, 0x00000010 }, + { 0x00009a1c, 0x00000059, 0x00000044 }, + { 0x00009a20, 0x00000099, 0x00000084 }, + { 0x00009a24, 0x000001a5, 0x00000148 }, + { 0x00009a28, 0x000001e5, 0x00000188 }, + { 0x00009a2c, 0x00000025, 0x000001c8 }, + { 0x00009a30, 0x000001c8, 0x00000014 }, + { 0x00009a34, 0x00000008, 0x00000042 }, + { 0x00009a38, 0x00000048, 0x00000082 }, + { 0x00009a3c, 0x00000088, 0x00000178 }, + { 0x00009a40, 0x00000198, 0x000001b8 }, + { 0x00009a44, 0x000001d8, 0x000001f8 }, + { 0x00009a48, 0x00000018, 0x00000012 }, + { 0x00009a4c, 0x00000058, 0x00000052 }, + { 0x00009a50, 0x00000098, 0x00000092 }, + { 0x00009a54, 0x000001a4, 0x0000017c }, + { 0x00009a58, 0x000001e4, 0x000001bc }, + { 0x00009a5c, 0x00000024, 0x000001fc }, + { 0x00009a60, 0x00000064, 0x0000000a }, + { 0x00009a64, 0x000000a4, 0x0000004a }, + { 0x00009a68, 0x000000e4, 0x0000008a }, + { 0x00009a6c, 0x0000010a, 0x0000015a }, + { 0x00009a70, 0x0000014a, 0x0000019a }, + { 0x00009a74, 0x0000018a, 0x000001da }, + { 0x00009a78, 0x000001ca, 0x0000000e }, + { 0x00009a7c, 0x0000000a, 0x0000004e }, + { 0x00009a80, 0x0000004a, 0x0000008e }, + { 0x00009a84, 0x0000008a, 0x0000015e }, + { 0x00009a88, 0x000001ba, 0x0000019e }, + { 0x00009a8c, 0x000001fa, 0x000001de }, + { 0x00009a90, 0x0000003a, 0x00000009 }, + { 0x00009a94, 0x0000007a, 0x00000049 }, + { 0x00009a98, 0x00000186, 0x00000089 }, + { 0x00009a9c, 0x000001c6, 0x00000179 }, + { 0x00009aa0, 0x00000006, 0x000001b9 }, + { 0x00009aa4, 0x00000046, 0x000001f9 }, + { 0x00009aa8, 0x00000086, 0x00000039 }, + { 0x00009aac, 0x000000c6, 0x00000079 }, + { 0x00009ab0, 0x000000c6, 0x000000b9 }, + { 0x00009ab4, 0x000000c6, 0x000001bd }, + { 0x00009ab8, 0x000000c6, 0x000001fd }, + { 0x00009abc, 0x000000c6, 0x0000003d }, + { 0x00009ac0, 0x000000c6, 0x0000007d }, + { 0x00009ac4, 0x000000c6, 0x000000bd }, + { 0x00009ac8, 0x000000c6, 0x000000fd }, + { 0x00009acc, 0x000000c6, 0x000000fd }, + { 0x00009ad0, 0x000000c6, 0x000000fd }, + { 0x00009ad4, 0x000000c6, 0x000000fd }, + { 0x00009ad8, 0x000000c6, 0x000000fd }, + { 0x00009adc, 0x000000c6, 0x000000fd }, + { 0x00009ae0, 0x000000c6, 0x000000fd }, + { 0x00009ae4, 0x000000c6, 0x000000fd }, + { 0x00009ae8, 0x000000c6, 0x000000fd }, + { 0x00009aec, 0x000000c6, 0x000000fd }, + { 0x00009af0, 0x000000c6, 0x000000fd }, + { 0x00009af4, 0x000000c6, 0x000000fd }, + { 0x00009af8, 0x000000c6, 0x000000fd }, + { 0x00009afc, 0x000000c6, 0x000000fd }, +}; +#endif /* AH_5212_5111 */ + +#ifdef AH_5212_5112 +static const uint32_t ar5212BB_RfGain_5112[][3] = { + { 0x00009a00, 0x00000007, 0x00000007 }, + { 0x00009a04, 0x00000047, 0x00000047 }, + { 0x00009a08, 0x00000087, 0x00000087 }, + { 0x00009a0c, 0x000001a0, 0x000001a0 }, + { 0x00009a10, 0x000001e0, 0x000001e0 }, + { 0x00009a14, 0x00000020, 0x00000020 }, + { 0x00009a18, 0x00000060, 0x00000060 }, + { 0x00009a1c, 0x000001a1, 0x000001a1 }, + { 0x00009a20, 0x000001e1, 0x000001e1 }, + { 0x00009a24, 0x00000021, 0x00000021 }, + { 0x00009a28, 0x00000061, 0x00000061 }, + { 0x00009a2c, 0x00000162, 0x00000162 }, + { 0x00009a30, 0x000001a2, 0x000001a2 }, + { 0x00009a34, 0x000001e2, 0x000001e2 }, + { 0x00009a38, 0x00000022, 0x00000022 }, + { 0x00009a3c, 0x00000062, 0x00000062 }, + { 0x00009a40, 0x00000163, 0x00000163 }, + { 0x00009a44, 0x000001a3, 0x000001a3 }, + { 0x00009a48, 0x000001e3, 0x000001e3 }, + { 0x00009a4c, 0x00000023, 0x00000023 }, + { 0x00009a50, 0x00000063, 0x00000063 }, + { 0x00009a54, 0x00000184, 0x00000184 }, + { 0x00009a58, 0x000001c4, 0x000001c4 }, + { 0x00009a5c, 0x00000004, 0x00000004 }, + { 0x00009a60, 0x000001ea, 0x0000000b }, + { 0x00009a64, 0x0000002a, 0x0000004b }, + { 0x00009a68, 0x0000006a, 0x0000008b }, + { 0x00009a6c, 0x000000aa, 0x000001ac }, + { 0x00009a70, 0x000001ab, 0x000001ec }, + { 0x00009a74, 0x000001eb, 0x0000002c }, + { 0x00009a78, 0x0000002b, 0x00000012 }, + { 0x00009a7c, 0x0000006b, 0x00000052 }, + { 0x00009a80, 0x000000ab, 0x00000092 }, + { 0x00009a84, 0x000001ac, 0x00000193 }, + { 0x00009a88, 0x000001ec, 0x000001d3 }, + { 0x00009a8c, 0x0000002c, 0x00000013 }, + { 0x00009a90, 0x0000003a, 0x00000053 }, + { 0x00009a94, 0x0000007a, 0x00000093 }, + { 0x00009a98, 0x000000ba, 0x00000194 }, + { 0x00009a9c, 0x000001bb, 0x000001d4 }, + { 0x00009aa0, 0x000001fb, 0x00000014 }, + { 0x00009aa4, 0x0000003b, 0x0000003a }, + { 0x00009aa8, 0x0000007b, 0x0000007a }, + { 0x00009aac, 0x000000bb, 0x000000ba }, + { 0x00009ab0, 0x000001bc, 0x000001bb }, + { 0x00009ab4, 0x000001fc, 0x000001fb }, + { 0x00009ab8, 0x0000003c, 0x0000003b }, + { 0x00009abc, 0x0000007c, 0x0000007b }, + { 0x00009ac0, 0x000000bc, 0x000000bb }, + { 0x00009ac4, 0x000000fc, 0x000001bc }, + { 0x00009ac8, 0x000000fc, 0x000001fc }, + { 0x00009acc, 0x000000fc, 0x0000003c }, + { 0x00009ad0, 0x000000fc, 0x0000007c }, + { 0x00009ad4, 0x000000fc, 0x000000bc }, + { 0x00009ad8, 0x000000fc, 0x000000fc }, + { 0x00009adc, 0x000000fc, 0x000000fc }, + { 0x00009ae0, 0x000000fc, 0x000000fc }, + { 0x00009ae4, 0x000000fc, 0x000000fc }, + { 0x00009ae8, 0x000000fc, 0x000000fc }, + { 0x00009aec, 0x000000fc, 0x000000fc }, + { 0x00009af0, 0x000000fc, 0x000000fc }, + { 0x00009af4, 0x000000fc, 0x000000fc }, + { 0x00009af8, 0x000000fc, 0x000000fc }, + { 0x00009afc, 0x000000fc, 0x000000fc }, +}; +#endif /* AH_5212_5112 */ + +#ifdef AH_5212_2413 +static const uint32_t ar5212BB_RfGain_2413[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000000, 0x00000040 }, + { 0x00009a08, 0x00000000, 0x00000080 }, + { 0x00009a0c, 0x00000000, 0x00000181 }, + { 0x00009a10, 0x00000000, 0x000001c1 }, + { 0x00009a14, 0x00000000, 0x00000001 }, + { 0x00009a18, 0x00000000, 0x00000041 }, + { 0x00009a1c, 0x00000000, 0x00000081 }, + { 0x00009a20, 0x00000000, 0x00000168 }, + { 0x00009a24, 0x00000000, 0x000001a8 }, + { 0x00009a28, 0x00000000, 0x000001e8 }, + { 0x00009a2c, 0x00000000, 0x00000028 }, + { 0x00009a30, 0x00000000, 0x00000068 }, + { 0x00009a34, 0x00000000, 0x00000189 }, + { 0x00009a38, 0x00000000, 0x000001c9 }, + { 0x00009a3c, 0x00000000, 0x00000009 }, + { 0x00009a40, 0x00000000, 0x00000049 }, + { 0x00009a44, 0x00000000, 0x00000089 }, + { 0x00009a48, 0x00000000, 0x00000190 }, + { 0x00009a4c, 0x00000000, 0x000001d0 }, + { 0x00009a50, 0x00000000, 0x00000010 }, + { 0x00009a54, 0x00000000, 0x00000050 }, + { 0x00009a58, 0x00000000, 0x00000090 }, + { 0x00009a5c, 0x00000000, 0x00000191 }, + { 0x00009a60, 0x00000000, 0x000001d1 }, + { 0x00009a64, 0x00000000, 0x00000011 }, + { 0x00009a68, 0x00000000, 0x00000051 }, + { 0x00009a6c, 0x00000000, 0x00000091 }, + { 0x00009a70, 0x00000000, 0x00000178 }, + { 0x00009a74, 0x00000000, 0x000001b8 }, + { 0x00009a78, 0x00000000, 0x000001f8 }, + { 0x00009a7c, 0x00000000, 0x00000038 }, + { 0x00009a80, 0x00000000, 0x00000078 }, + { 0x00009a84, 0x00000000, 0x00000199 }, + { 0x00009a88, 0x00000000, 0x000001d9 }, + { 0x00009a8c, 0x00000000, 0x00000019 }, + { 0x00009a90, 0x00000000, 0x00000059 }, + { 0x00009a94, 0x00000000, 0x00000099 }, + { 0x00009a98, 0x00000000, 0x000000d9 }, + { 0x00009a9c, 0x00000000, 0x000000f9 }, + { 0x00009aa0, 0x00000000, 0x000000f9 }, + { 0x00009aa4, 0x00000000, 0x000000f9 }, + { 0x00009aa8, 0x00000000, 0x000000f9 }, + { 0x00009aac, 0x00000000, 0x000000f9 }, + { 0x00009ab0, 0x00000000, 0x000000f9 }, + { 0x00009ab4, 0x00000000, 0x000000f9 }, + { 0x00009ab8, 0x00000000, 0x000000f9 }, + { 0x00009abc, 0x00000000, 0x000000f9 }, + { 0x00009ac0, 0x00000000, 0x000000f9 }, + { 0x00009ac4, 0x00000000, 0x000000f9 }, + { 0x00009ac8, 0x00000000, 0x000000f9 }, + { 0x00009acc, 0x00000000, 0x000000f9 }, + { 0x00009ad0, 0x00000000, 0x000000f9 }, + { 0x00009ad4, 0x00000000, 0x000000f9 }, + { 0x00009ad8, 0x00000000, 0x000000f9 }, + { 0x00009adc, 0x00000000, 0x000000f9 }, + { 0x00009ae0, 0x00000000, 0x000000f9 }, + { 0x00009ae4, 0x00000000, 0x000000f9 }, + { 0x00009ae8, 0x00000000, 0x000000f9 }, + { 0x00009aec, 0x00000000, 0x000000f9 }, + { 0x00009af0, 0x00000000, 0x000000f9 }, + { 0x00009af4, 0x00000000, 0x000000f9 }, + { 0x00009af8, 0x00000000, 0x000000f9 }, + { 0x00009afc, 0x00000000, 0x000000f9 }, +}; +#endif /* AH_5212_2413 */ + +#ifdef AH_5212_2316 +static const uint32_t ar5212BB_RfGain_2316[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000000, 0x00000040 }, + { 0x00009a08, 0x00000000, 0x00000080 }, + { 0x00009a0c, 0x00000000, 0x00000161 }, + { 0x00009a10, 0x00000000, 0x000001a1 }, + { 0x00009a14, 0x00000000, 0x000001e1 }, + { 0x00009a18, 0x00000000, 0x00000021 }, + { 0x00009a1c, 0x00000000, 0x00000061 }, + { 0x00009a20, 0x00000000, 0x000000a1 }, + { 0x00009a24, 0x00000000, 0x00000168 }, + { 0x00009a28, 0x00000000, 0x000001a8 }, + { 0x00009a2c, 0x00000000, 0x000001e8 }, + { 0x00009a30, 0x00000000, 0x00000028 }, + { 0x00009a34, 0x00000000, 0x00000068 }, + { 0x00009a38, 0x00000000, 0x000000a8 }, + { 0x00009a3c, 0x00000000, 0x00000189 }, + { 0x00009a40, 0x00000000, 0x000001c9 }, + { 0x00009a44, 0x00000000, 0x00000009 }, + { 0x00009a48, 0x00000000, 0x00000049 }, + { 0x00009a4c, 0x00000000, 0x00000089 }, + { 0x00009a50, 0x00000000, 0x000001b0 }, + { 0x00009a54, 0x00000000, 0x000001f0 }, + { 0x00009a58, 0x00000000, 0x00000030 }, + { 0x00009a5c, 0x00000000, 0x00000070 }, + { 0x00009a60, 0x00000000, 0x000000b0 }, + { 0x00009a64, 0x00000000, 0x000001b1 }, + { 0x00009a68, 0x00000000, 0x000001f1 }, + { 0x00009a6c, 0x00000000, 0x00000031 }, + { 0x00009a70, 0x00000000, 0x00000071 }, + { 0x00009a74, 0x00000000, 0x00000198 }, + { 0x00009a78, 0x00000000, 0x000001d8 }, + { 0x00009a7c, 0x00000000, 0x00000018 }, + { 0x00009a80, 0x00000000, 0x00000058 }, + { 0x00009a84, 0x00000000, 0x00000098 }, + { 0x00009a88, 0x00000000, 0x00000199 }, + { 0x00009a8c, 0x00000000, 0x000001d9 }, + { 0x00009a90, 0x00000000, 0x00000019 }, + { 0x00009a94, 0x00000000, 0x00000059 }, + { 0x00009a98, 0x00000000, 0x00000099 }, + { 0x00009a9c, 0x00000000, 0x000000d9 }, + { 0x00009aa0, 0x00000000, 0x000000f9 }, + { 0x00009aa4, 0x00000000, 0x000000f9 }, + { 0x00009aa8, 0x00000000, 0x000000f9 }, + { 0x00009aac, 0x00000000, 0x000000f9 }, + { 0x00009ab0, 0x00000000, 0x000000f9 }, + { 0x00009ab4, 0x00000000, 0x000000f9 }, + { 0x00009ab8, 0x00000000, 0x000000f9 }, + { 0x00009abc, 0x00000000, 0x000000f9 }, + { 0x00009ac0, 0x00000000, 0x000000f9 }, + { 0x00009ac4, 0x00000000, 0x000000f9 }, + { 0x00009ac8, 0x00000000, 0x000000f9 }, + { 0x00009acc, 0x00000000, 0x000000f9 }, + { 0x00009ad0, 0x00000000, 0x000000f9 }, + { 0x00009ad4, 0x00000000, 0x000000f9 }, + { 0x00009ad8, 0x00000000, 0x000000f9 }, + { 0x00009adc, 0x00000000, 0x000000f9 }, + { 0x00009ae0, 0x00000000, 0x000000f9 }, + { 0x00009ae4, 0x00000000, 0x000000f9 }, + { 0x00009ae8, 0x00000000, 0x000000f9 }, + { 0x00009aec, 0x00000000, 0x000000f9 }, + { 0x00009af0, 0x00000000, 0x000000f9 }, + { 0x00009af4, 0x00000000, 0x000000f9 }, + { 0x00009af8, 0x00000000, 0x000000f9 }, + { 0x00009afc, 0x00000000, 0x000000f9 }, +}; +#endif + +#ifdef AH_5212_5413 +static const uint32_t ar5212BB_RfGain_5413[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000040, 0x00000040 }, + { 0x00009a08, 0x00000080, 0x00000080 }, + { 0x00009a0c, 0x000001a1, 0x00000161 }, + { 0x00009a10, 0x000001e1, 0x000001a1 }, + { 0x00009a14, 0x00000021, 0x000001e1 }, + { 0x00009a18, 0x00000061, 0x00000021 }, + { 0x00009a1c, 0x00000188, 0x00000061 }, + { 0x00009a20, 0x000001c8, 0x00000188 }, + { 0x00009a24, 0x00000008, 0x000001c8 }, + { 0x00009a28, 0x00000048, 0x00000008 }, + { 0x00009a2c, 0x00000088, 0x00000048 }, + { 0x00009a30, 0x000001a9, 0x00000088 }, + { 0x00009a34, 0x000001e9, 0x00000169 }, + { 0x00009a38, 0x00000029, 0x000001a9 }, + { 0x00009a3c, 0x00000069, 0x000001e9 }, + { 0x00009a40, 0x000001d0, 0x00000029 }, + { 0x00009a44, 0x00000010, 0x00000069 }, + { 0x00009a48, 0x00000050, 0x00000190 }, + { 0x00009a4c, 0x00000090, 0x000001d0 }, + { 0x00009a50, 0x000001b1, 0x00000010 }, + { 0x00009a54, 0x000001f1, 0x00000050 }, + { 0x00009a58, 0x00000031, 0x00000090 }, + { 0x00009a5c, 0x00000071, 0x00000171 }, + { 0x00009a60, 0x000001b8, 0x000001b1 }, + { 0x00009a64, 0x000001f8, 0x000001f1 }, + { 0x00009a68, 0x00000038, 0x00000031 }, + { 0x00009a6c, 0x00000078, 0x00000071 }, + { 0x00009a70, 0x00000199, 0x00000198 }, + { 0x00009a74, 0x000001d9, 0x000001d8 }, + { 0x00009a78, 0x00000019, 0x00000018 }, + { 0x00009a7c, 0x00000059, 0x00000058 }, + { 0x00009a80, 0x00000099, 0x00000098 }, + { 0x00009a84, 0x000000d9, 0x00000179 }, + { 0x00009a88, 0x000000f9, 0x000001b9 }, + { 0x00009a8c, 0x000000f9, 0x000001f9 }, + { 0x00009a90, 0x000000f9, 0x00000039 }, + { 0x00009a94, 0x000000f9, 0x00000079 }, + { 0x00009a98, 0x000000f9, 0x000000b9 }, + { 0x00009a9c, 0x000000f9, 0x000000f9 }, + { 0x00009aa0, 0x000000f9, 0x000000f9 }, + { 0x00009aa4, 0x000000f9, 0x000000f9 }, + { 0x00009aa8, 0x000000f9, 0x000000f9 }, + { 0x00009aac, 0x000000f9, 0x000000f9 }, + { 0x00009ab0, 0x000000f9, 0x000000f9 }, + { 0x00009ab4, 0x000000f9, 0x000000f9 }, + { 0x00009ab8, 0x000000f9, 0x000000f9 }, + { 0x00009abc, 0x000000f9, 0x000000f9 }, + { 0x00009ac0, 0x000000f9, 0x000000f9 }, + { 0x00009ac4, 0x000000f9, 0x000000f9 }, + { 0x00009ac8, 0x000000f9, 0x000000f9 }, + { 0x00009acc, 0x000000f9, 0x000000f9 }, + { 0x00009ad0, 0x000000f9, 0x000000f9 }, + { 0x00009ad4, 0x000000f9, 0x000000f9 }, + { 0x00009ad8, 0x000000f9, 0x000000f9 }, + { 0x00009adc, 0x000000f9, 0x000000f9 }, + { 0x00009ae0, 0x000000f9, 0x000000f9 }, + { 0x00009ae4, 0x000000f9, 0x000000f9 }, + { 0x00009ae8, 0x000000f9, 0x000000f9 }, + { 0x00009aec, 0x000000f9, 0x000000f9 }, + { 0x00009af0, 0x000000f9, 0x000000f9 }, + { 0x00009af4, 0x000000f9, 0x000000f9 }, + { 0x00009af8, 0x000000f9, 0x000000f9 }, + { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; +#endif /* AH_5212_5413 */ + +#ifdef AH_5212_2425 +static const uint32_t ar5212BB_RfGain_2425[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000000, 0x00000040 }, + { 0x00009a08, 0x00000000, 0x00000080 }, + { 0x00009a0c, 0x00000000, 0x00000181 }, + { 0x00009a10, 0x00000000, 0x000001c1 }, + { 0x00009a14, 0x00000000, 0x00000001 }, + { 0x00009a18, 0x00000000, 0x00000041 }, + { 0x00009a1c, 0x00000000, 0x00000081 }, + { 0x00009a20, 0x00000000, 0x00000188 }, + { 0x00009a24, 0x00000000, 0x000001c8 }, + { 0x00009a28, 0x00000000, 0x00000008 }, + { 0x00009a2c, 0x00000000, 0x00000048 }, + { 0x00009a30, 0x00000000, 0x00000088 }, + { 0x00009a34, 0x00000000, 0x00000189 }, + { 0x00009a38, 0x00000000, 0x000001c9 }, + { 0x00009a3c, 0x00000000, 0x00000009 }, + { 0x00009a40, 0x00000000, 0x00000049 }, + { 0x00009a44, 0x00000000, 0x00000089 }, + { 0x00009a48, 0x00000000, 0x000001b0 }, + { 0x00009a4c, 0x00000000, 0x000001f0 }, + { 0x00009a50, 0x00000000, 0x00000030 }, + { 0x00009a54, 0x00000000, 0x00000070 }, + { 0x00009a58, 0x00000000, 0x00000171 }, + { 0x00009a5c, 0x00000000, 0x000001b1 }, + { 0x00009a60, 0x00000000, 0x000001f1 }, + { 0x00009a64, 0x00000000, 0x00000031 }, + { 0x00009a68, 0x00000000, 0x00000071 }, + { 0x00009a6c, 0x00000000, 0x000001b8 }, + { 0x00009a70, 0x00000000, 0x000001f8 }, + { 0x00009a74, 0x00000000, 0x00000038 }, + { 0x00009a78, 0x00000000, 0x00000078 }, + { 0x00009a7c, 0x00000000, 0x000000b8 }, + { 0x00009a80, 0x00000000, 0x000001b9 }, + { 0x00009a84, 0x00000000, 0x000001f9 }, + { 0x00009a88, 0x00000000, 0x00000039 }, + { 0x00009a8c, 0x00000000, 0x00000079 }, + { 0x00009a90, 0x00000000, 0x000000b9 }, + { 0x00009a94, 0x00000000, 0x000000f9 }, + { 0x00009a98, 0x00000000, 0x000000f9 }, + { 0x00009a9c, 0x00000000, 0x000000f9 }, + { 0x00009aa0, 0x00000000, 0x000000f9 }, + { 0x00009aa4, 0x00000000, 0x000000f9 }, + { 0x00009aa8, 0x00000000, 0x000000f9 }, + { 0x00009aac, 0x00000000, 0x000000f9 }, + { 0x00009ab0, 0x00000000, 0x000000f9 }, + { 0x00009ab4, 0x00000000, 0x000000f9 }, + { 0x00009ab8, 0x00000000, 0x000000f9 }, + { 0x00009abc, 0x00000000, 0x000000f9 }, + { 0x00009ac0, 0x00000000, 0x000000f9 }, + { 0x00009ac4, 0x00000000, 0x000000f9 }, + { 0x00009ac8, 0x00000000, 0x000000f9 }, + { 0x00009acc, 0x00000000, 0x000000f9 }, + { 0x00009ad0, 0x00000000, 0x000000f9 }, + { 0x00009ad4, 0x00000000, 0x000000f9 }, + { 0x00009ad8, 0x00000000, 0x000000f9 }, + { 0x00009adc, 0x00000000, 0x000000f9 }, + { 0x00009ae0, 0x00000000, 0x000000f9 }, + { 0x00009ae4, 0x00000000, 0x000000f9 }, + { 0x00009ae8, 0x00000000, 0x000000f9 }, + { 0x00009aec, 0x00000000, 0x000000f9 }, + { 0x00009af0, 0x00000000, 0x000000f9 }, + { 0x00009af4, 0x00000000, 0x000000f9 }, + { 0x00009af8, 0x00000000, 0x000000f9 }, + { 0x00009afc, 0x00000000, 0x000000f9 }, +}; +#endif /* AH_5212_2425 */ + +#ifdef AH_5212_5111 +static const uint32_t ar5212Bank1_5111[][2] = { + { 0x000098d4, 0x00000020 }, +}; +#endif /* AH_5212_5111 */ + +#ifdef AH_5212_5112 +static const uint32_t ar5212Bank1_5112[][2] = { + { 0x000098d4, 0x00000020 }, +}; +#endif /* AH_5212_5112 */ + +#ifdef AH_5212_2413 +static const uint32_t ar5212Bank1_2413[][2] = { + { 0x000098d4, 0x00000020 }, +}; +#endif /* AH_5212_2413 */ + +#ifdef AH_5212_2316 +static const uint32_t ar5212Bank1_2316[][2] = { + { 0x000098d4, 0x00000020 }, +}; +#endif + +#ifdef AH_5212_5413 +static const uint32_t ar5212Bank1_5413[][2] = { + { 0x000098d4, 0x00000020 }, +}; +#endif /* AH_5212_5413 */ + +#ifdef AH_5212_2425 +static const uint32_t ar5212Bank1_2425[][2] = { + { 0x000098d4, 0x00000020 }, +}; +#endif /* AH_5212_2425 */ + +#ifdef AH_5212_5111 +static const uint32_t ar5212Bank2_5111[][6] = { + { 0x000098d4, 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 }, +}; +#endif /* AH_5212_5111 */ + +#ifdef AH_5212_5112 +static const uint32_t ar5212Bank2_5112[][6] = { + { 0x000098d0, 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 }, +}; +#endif /* AH_5212_5112 */ + +#ifdef AH_5212_2413 +static const uint32_t ar5212Bank2_2413[][6] = { + { 0x000098d0, 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 }, +}; +#endif /* AH_5212_2413 */ + +#ifdef AH_5212_2316 +static const uint32_t ar5212Bank2_2316[][6] = { + { 0x000098d0, 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 }, +}; +#endif + +#ifdef AH_5212_5413 +static const uint32_t ar5212Bank2_5413[][6] = { + { 0x000098d0, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 }, +}; +#endif /* AH_5212_5413 */ + +#ifdef AH_5212_2425 +static const uint32_t ar5212Bank2_2425[][6] = { + { 0x000098d0, 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 }, +}; +#endif /* AH_5212_2425 */ + +#ifdef AH_5212_5111 +static const uint32_t ar5212Bank3_5111[][6] = { + { 0x000098d8, 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 }, +}; +#endif /* AH_5212_5111 */ + +#ifdef AH_5212_5112 +static const uint32_t ar5212Bank3_5112[][6] = { + { 0x000098dc, 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 }, +}; +#endif /* AH_5212_5112 */ + +#ifdef AH_5212_2413 +static const uint32_t ar5212Bank3_2413[][6] = { + { 0x000098dc, 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 }, +}; +#endif /* AH_5212_2413 */ + +#ifdef AH_5212_2316 +static const uint32_t ar5212Bank3_2316[][6] = { + { 0x000098dc, 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 }, +}; +#endif + +#ifdef AH_5212_5413 +static const uint32_t ar5212Bank3_5413[][6] = { + { 0x000098dc, 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 }, +}; +#endif /* AH_5212_5413 */ + +#ifdef AH_5212_2425 +static const uint32_t ar5212Bank3_2425[][6] = { + { 0x000098dc, 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 }, +}; +#endif /* AH_5212_2425 */ + +#ifdef AH_5212_5111 +static const uint32_t ar5212Bank6_5111[][6] = { + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 }, + { 0x0000989c, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 }, + { 0x0000989c, 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 }, + { 0x0000989c, 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 }, + { 0x0000989c, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 }, + { 0x0000989c, 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 }, + { 0x000098d4, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a }, +}; +#endif /* AH_5212_5111 */ + +#ifdef AH_5212_5112 +static const uint32_t ar5212Bank6_5112[][6] = { + { 0x0000989c, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 }, + { 0x0000989c, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 }, + { 0x0000989c, 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 }, + { 0x0000989c, 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 }, + { 0x0000989c, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 }, + { 0x0000989c, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 }, + { 0x0000989c, 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 }, + { 0x0000989c, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000 }, + { 0x0000989c, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 }, + { 0x0000989c, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 }, + { 0x0000989c, 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 }, + { 0x0000989c, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 }, + { 0x0000989c, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 }, + { 0x0000989c, 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 }, + { 0x0000989c, 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 }, + { 0x0000989c, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 }, + { 0x0000989c, 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 }, + { 0x0000989c, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 }, + { 0x0000989c, 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 }, + { 0x0000989c, 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 }, + { 0x0000989c, 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 }, + { 0x0000989c, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 }, + { 0x0000989c, 0x00270019, 0x00270019, 0x00270019, 0x00270019, 0x00270019 }, + { 0x0000989c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 }, + { 0x0000989c, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 }, + { 0x0000989c, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 }, + { 0x0000989c, 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 }, + { 0x0000989c, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 }, + { 0x000098d8, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 }, +}; +#endif /* AH_5212_5112 */ + +#ifdef AH_5212_2413 +static const uint32_t ar5212Bank6_2413[][6] = { + { 0x0000989c, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x40400000, 0x40400000, 0x40400000, 0x40400000, 0x40400000 }, + { 0x0000989c, 0x65050000, 0x65050000, 0x65050000, 0x65050000, 0x65050000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00420000, 0x00420000, 0x00420000, 0x00420000, 0x00420000 }, + { 0x0000989c, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000 }, + { 0x0000989c, 0x00030000, 0x00030000, 0x00030000, 0x00030000, 0x00030000 }, + { 0x0000989c, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000 }, + { 0x0000989c, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000 }, + { 0x0000989c, 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 }, + { 0x0000989c, 0x04220000, 0x04220000, 0x04220000, 0x04220000, 0x04220000 }, + { 0x0000989c, 0x00230018, 0x00230018, 0x00230018, 0x00230018, 0x00230018 }, + { 0x0000989c, 0x00280000, 0x00280000, 0x00280060, 0x00280060, 0x00280060 }, + { 0x0000989c, 0x005000c0, 0x005000c0, 0x005000c3, 0x005000c3, 0x005000c3 }, + { 0x0000989c, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f }, + { 0x0000989c, 0x00000458, 0x00000458, 0x00000458, 0x00000458, 0x00000458 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000 }, + { 0x000098d8, 0x00400230, 0x00400230, 0x00400230, 0x00400230, 0x00400230 }, +}; +#endif /* AH_5212_2413 */ + +#ifdef AH_5212_2316 +static const uint32_t ar5212Bank6_2316[][6] = { + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000 }, + { 0x0000989c, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 }, + { 0x0000989c, 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x95150000, 0x95150000, 0x95150000, 0x95150000, 0x95150000 }, + { 0x0000989c, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000 }, + { 0x0000989c, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000 }, + { 0x0000989c, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 }, + { 0x0000989c, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000 }, + { 0x0000989c, 0x10880000, 0x10880000, 0x10880000, 0x10880000, 0x10880000 }, + { 0x0000989c, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060 }, + { 0x0000989c, 0x00a00000, 0x00a00000, 0x00a00080, 0x00a00080, 0x00a00080 }, + { 0x0000989c, 0x00400000, 0x00400000, 0x0040000d, 0x0040000d, 0x0040000d }, + { 0x0000989c, 0x00110400, 0x00110400, 0x00110400, 0x00110400, 0x00110400 }, + { 0x0000989c, 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 }, + { 0x0000989c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 }, + { 0x0000989c, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00 }, + { 0x0000989c, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8 }, + { 0x000098c0, 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 }, +}; +#endif + +#ifdef AH_5212_5413 +static const uint32_t ar5212Bank6_5413[][6] = { + { 0x0000989c, 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 }, + { 0x0000989c, 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 }, + { 0x0000989c, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 }, + { 0x0000989c, 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 }, + { 0x0000989c, 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 }, + { 0x0000989c, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 }, + { 0x0000989c, 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 }, + { 0x0000989c, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 }, + { 0x0000989c, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 }, + { 0x0000989c, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 }, + { 0x0000989c, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 }, + { 0x0000989c, 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 }, + { 0x0000989c, 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 }, + { 0x0000989c, 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 }, + { 0x0000989c, 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 }, + { 0x0000989c, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 }, + { 0x0000989c, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 }, + { 0x0000989c, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f }, + { 0x0000989c, 0x00510040, 0x00510040, 0x00510040, 0x00510040, 0x00510040 }, + { 0x0000989c, 0x005000da, 0x005000da, 0x005000da, 0x005000da, 0x005000da }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 }, + { 0x0000989c, 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00002c00 }, + { 0x000098c8, 0x00000403, 0x00000403, 0x00000403, 0x00000403, 0x00000403 }, +}; +#endif /* AH_5212_5413 */ + +#ifdef AH_5212_2425 +static const uint32_t ar5212Bank6_2425[][6] = { + { 0x0000989c, 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 }, + { 0x0000989c, 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 }, + { 0x0000989c, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 }, + { 0x0000989c, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 }, + { 0x0000989c, 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 }, + { 0x0000989c, 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 }, + { 0x0000989c, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a }, + { 0x0000989c, 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 }, + { 0x0000989c, 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 }, + { 0x0000989c, 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 }, + { 0x0000989c, 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 }, + { 0x000098c4, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 }, +}; +#endif /* AH_5212_2425 */ + +#ifdef AH_5212_2417 +static const uint32_t ar5212Bank6_2417[][6] = { + { 0x0000989c, 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 }, + { 0x0000989c, 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 }, + { 0x0000989c, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 }, + { 0x0000989c, 0x00e70000, 0x00e70000, 0x80e70000, 0x80e70000, 0x00e70000 }, + { 0x0000989c, 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 }, + { 0x0000989c, 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 }, + { 0x0000989c, 0x0007001a, 0x0007001a, 0x0207001a, 0x0207001a, 0x0007001a }, + { 0x0000989c, 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 }, + { 0x0000989c, 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 }, + { 0x0000989c, 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 }, + { 0x0000989c, 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 }, + { 0x000098c4, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 }, +}; +#endif /* AH_5212_2417 */ + +#ifdef AH_5212_5111 +static const uint32_t ar5212Bank7_5111[][6] = { + { 0x0000989c, 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 }, + { 0x0000989c, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, + { 0x0000989c, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 }, + { 0x0000989c, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f }, + { 0x0000989c, 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 }, + { 0x0000989c, 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f }, + { 0x0000989c, 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a }, + { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e }, +}; +#endif /* AH_5212_5111 */ + +#ifdef AH_5212_5112 +static const uint32_t ar5212Bank7_5112[][6] = { + { 0x0000989c, 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 }, + { 0x0000989c, 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 }, + { 0x0000989c, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 }, + { 0x0000989c, 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 }, + { 0x0000989c, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 }, + { 0x0000989c, 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 }, + { 0x0000989c, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 }, + { 0x0000989c, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 }, + { 0x0000989c, 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 }, + { 0x0000989c, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 }, + { 0x0000989c, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc }, + { 0x0000989c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c }, + { 0x000098c4, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 }, +}; +#endif /* AH_5212_5112 */ + +#ifdef AH_5212_2413 +static const uint32_t ar5212Bank7_2413[][6] = { + { 0x0000989c, 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 }, + { 0x0000989c, 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 }, + { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e }, +}; +#endif /* AH_5212_2413 */ + +#ifdef AH_5212_2316 +static const uint32_t ar5212Bank7_2316[][6] = { + { 0x0000989c, 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 }, + { 0x0000989c, 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 }, + { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e }, +}; +#endif + +#ifdef AH_5212_5413 +static const uint32_t ar5212Bank7_5413[][6] = { + { 0x0000989c, 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 }, + { 0x0000989c, 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 }, + { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e }, +}; +#endif /* AH_5212_5413 */ + +#ifdef AH_5212_2317 +static const uint32_t ar5212Modes_2317[][6] = { + { 0x00000030, 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 }, + { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 }, + { 0x00009838, 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a }, + { 0x00009848, 0x0018da6d, 0x0018da6d, 0x001a6a67, 0x001a6a67, 0x001a6a67 }, + { 0x00009850, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da }, + { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e }, + { 0x0000985c, 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 }, + { 0x00009944, 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 }, + { 0x0000a204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 }, + { 0x0000a20c, 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a }, +}; + +static const uint32_t ar5212Common_2317[][2] = { + { 0x00001230, 0x000003e0 }, + { 0x00008060, 0x0000000f }, + { 0x00008118, 0x00000000 }, + { 0x0000811c, 0x00000000 }, + { 0x00008120, 0x00000000 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008140, 0x800000a8 }, + { 0x00008144, 0x00000000 }, + { 0x00009808, 0x00004000 }, + { 0x0000982c, 0x0000a000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x1284233c }, + { 0x00009870, 0x0000001f }, + { 0x00009874, 0x00000080 }, + { 0x00009878, 0x0000000e }, + { 0x00009958, 0x000000ff }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x02800000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099e0, 0x00000001 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x000000aa }, + { 0x000099f0, 0x0000000c }, + { 0x000099f4, 0x000000ff }, + { 0x000099f8, 0x00000014 }, + { 0x0000a228, 0x000009b5 }, + { 0x0000a23c, 0x93c889af }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0x5f690f01 }, + { 0x0000a264, 0x00418a11 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0c30c16a }, + { 0x0000a270, 0x00820820 }, + { 0x0000a274, 0x081a3caa }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x051701ce }, + { 0x0000a300, 0x16010000 }, + { 0x0000a304, 0x2c032402 }, + { 0x0000a308, 0x48433e42 }, + { 0x0000a30c, 0x5a0f500b }, + { 0x0000a310, 0x6c4b624a }, + { 0x0000a314, 0x7e8b748a }, + { 0x0000a318, 0x96cf8ccb }, + { 0x0000a31c, 0xa34f9d0f }, + { 0x0000a320, 0xa7cfa58f }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa1f }, + { 0x0000a35c, 0x066c420f }, + { 0x0000a360, 0x0f282207 }, + { 0x0000a364, 0x17601685 }, + { 0x0000a368, 0x1f801104 }, + { 0x0000a36c, 0x37a00c03 }, + { 0x0000a370, 0x3fc40883 }, + { 0x0000a374, 0x57c00803 }, + { 0x0000a378, 0x5fd80682 }, + { 0x0000a37c, 0x7fe00482 }, + { 0x0000a380, 0x7f3c7bba }, + { 0x0000a384, 0xf3307ff0 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, +}; + +static const uint32_t ar5212BB_RfGain_2317[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000000, 0x00000040 }, + { 0x00009a08, 0x00000000, 0x00000080 }, + { 0x00009a0c, 0x00000000, 0x00000181 }, + { 0x00009a10, 0x00000000, 0x000001c1 }, + { 0x00009a14, 0x00000000, 0x00000001 }, + { 0x00009a18, 0x00000000, 0x00000041 }, + { 0x00009a1c, 0x00000000, 0x00000081 }, + { 0x00009a20, 0x00000000, 0x00000188 }, + { 0x00009a24, 0x00000000, 0x000001c8 }, + { 0x00009a28, 0x00000000, 0x00000008 }, + { 0x00009a2c, 0x00000000, 0x00000048 }, + { 0x00009a30, 0x00000000, 0x00000088 }, + { 0x00009a34, 0x00000000, 0x00000189 }, + { 0x00009a38, 0x00000000, 0x000001c9 }, + { 0x00009a3c, 0x00000000, 0x00000009 }, + { 0x00009a40, 0x00000000, 0x00000049 }, + { 0x00009a44, 0x00000000, 0x00000089 }, + { 0x00009a48, 0x00000000, 0x00000190 }, + { 0x00009a4c, 0x00000000, 0x000001d0 }, + { 0x00009a50, 0x00000000, 0x00000010 }, + { 0x00009a54, 0x00000000, 0x00000050 }, + { 0x00009a58, 0x00000000, 0x00000090 }, + { 0x00009a5c, 0x00000000, 0x00000191 }, + { 0x00009a60, 0x00000000, 0x000001d1 }, + { 0x00009a64, 0x00000000, 0x00000011 }, + { 0x00009a68, 0x00000000, 0x00000051 }, + { 0x00009a6c, 0x00000000, 0x00000091 }, + { 0x00009a70, 0x00000000, 0x00000178 }, + { 0x00009a74, 0x00000000, 0x000001b8 }, + { 0x00009a78, 0x00000000, 0x000001f8 }, + { 0x00009a7c, 0x00000000, 0x00000038 }, + { 0x00009a80, 0x00000000, 0x00000078 }, + { 0x00009a84, 0x00000000, 0x00000179 }, + { 0x00009a88, 0x00000000, 0x000001b9 }, + { 0x00009a8c, 0x00000000, 0x000001f9 }, + { 0x00009a90, 0x00000000, 0x00000039 }, + { 0x00009a94, 0x00000000, 0x00000079 }, + { 0x00009a98, 0x00000000, 0x000000b9 }, + { 0x00009a9c, 0x00000000, 0x000000f9 }, + { 0x00009aa0, 0x00000000, 0x000000f9 }, + { 0x00009aa4, 0x00000000, 0x000000f9 }, + { 0x00009aa8, 0x00000000, 0x000000f9 }, + { 0x00009aac, 0x00000000, 0x000000f9 }, + { 0x00009ab0, 0x00000000, 0x000000f9 }, + { 0x00009ab4, 0x00000000, 0x000000f9 }, + { 0x00009ab8, 0x00000000, 0x000000f9 }, + { 0x00009abc, 0x00000000, 0x000000f9 }, + { 0x00009ac0, 0x00000000, 0x000000f9 }, + { 0x00009ac4, 0x00000000, 0x000000f9 }, + { 0x00009ac8, 0x00000000, 0x000000f9 }, + { 0x00009acc, 0x00000000, 0x000000f9 }, + { 0x00009ad0, 0x00000000, 0x000000f9 }, + { 0x00009ad4, 0x00000000, 0x000000f9 }, + { 0x00009ad8, 0x00000000, 0x000000f9 }, + { 0x00009adc, 0x00000000, 0x000000f9 }, + { 0x00009ae0, 0x00000000, 0x000000f9 }, + { 0x00009ae4, 0x00000000, 0x000000f9 }, + { 0x00009ae8, 0x00000000, 0x000000f9 }, + { 0x00009aec, 0x00000000, 0x000000f9 }, + { 0x00009af0, 0x00000000, 0x000000f9 }, + { 0x00009af4, 0x00000000, 0x000000f9 }, + { 0x00009af8, 0x00000000, 0x000000f9 }, + { 0x00009afc, 0x00000000, 0x000000f9 }, +}; + +static const uint32_t ar5212Bank1_2317[][2] = { + { 0x000098d4, 0x00000020 }, +}; + +static const uint32_t ar5212Bank2_2317[][6] = { + { 0x000098d0, 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 }, +}; + +static const uint32_t ar5212Bank3_2317[][6] = { + { 0x000098dc, 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 }, +}; + +static const uint32_t ar5212Bank6_2317[][6] = { + { 0x0000989c, 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 }, + { 0x0000989c, 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 }, + { 0x0000989c, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 }, + { 0x0000989c, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 }, + { 0x0000989c, 0x00140100, 0x00140100, 0x00140100, 0x00140100, 0x00140100 }, + { 0x0000989c, 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 }, + { 0x0000989c, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a }, + { 0x0000989c, 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 }, + { 0x0000989c, 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 }, + { 0x0000989c, 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 }, + { 0x0000989c, 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 }, + { 0x000098c4, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 }, +}; + +static const uint32_t ar5212Bank7_2317[][6] = { + { 0x0000989c, 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 }, + { 0x0000989c, 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 }, + { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e }, +}; +#endif /* AH_5212_2317 */ + +#ifdef AH_5212_2425 +static const uint32_t ar5212Bank7_2425[][6] = { + { 0x0000989c, 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 }, + { 0x0000989c, 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 }, + { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e }, +}; +#endif /* AH_5212_2425 */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_ani.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_ani.c new file mode 100644 index 0000000000..df4d7375bd --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_ani.c @@ -0,0 +1,1016 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: src/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c,v 1.2.2.1.2.1 2009/04/15 03:14:26 kensmith Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +/* + * Anti noise immunity support. We track phy errors and react + * to excessive errors by adjusting the noise immunity parameters. + */ + +#define HAL_EP_RND(x, mul) \ + ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) +#define BEACON_RSSI(ahp) \ + HAL_EP_RND(ahp->ah_stats.ast_nodestats.ns_avgbrssi, \ + HAL_RSSI_EP_MULTIPLIER) + +/* + * ANI processing tunes radio parameters according to PHY errors + * and related information. This is done for for noise and spur + * immunity in all operating modes if the device indicates it's + * capable at attach time. In addition, when there is a reference + * rssi value (e.g. beacon frames from an ap in station mode) + * further tuning is done. + * + * ANI_ENA indicates whether any ANI processing should be done; + * this is specified at attach time. + * + * ANI_ENA_RSSI indicates whether rssi-based processing should + * done, this is enabled based on operating mode and is meaningful + * only if ANI_ENA is true. + * + * ANI parameters are typically controlled only by the hal. The + * AniControl interface however permits manual tuning through the + * diagnostic api. + */ +#define ANI_ENA(ah) \ + (AH5212(ah)->ah_procPhyErr & HAL_ANI_ENA) +#define ANI_ENA_RSSI(ah) \ + (AH5212(ah)->ah_procPhyErr & HAL_RSSI_ANI_ENA) + +#define ah_mibStats ah_stats.ast_mibstats + +static void +enableAniMIBCounters(struct ath_hal *ah, const struct ar5212AniParams *params) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: Enable mib counters: " + "OfdmPhyErrBase 0x%x cckPhyErrBase 0x%x\n", + __func__, params->ofdmPhyErrBase, params->cckPhyErrBase); + + OS_REG_WRITE(ah, AR_FILTOFDM, 0); + OS_REG_WRITE(ah, AR_FILTCCK, 0); + + OS_REG_WRITE(ah, AR_PHYCNT1, params->ofdmPhyErrBase); + OS_REG_WRITE(ah, AR_PHYCNT2, params->cckPhyErrBase); + OS_REG_WRITE(ah, AR_PHYCNTMASK1, AR_PHY_ERR_OFDM_TIMING); + OS_REG_WRITE(ah, AR_PHYCNTMASK2, AR_PHY_ERR_CCK_TIMING); + + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save+clear counters*/ + ar5212EnableMibCounters(ah); /* enable everything */ +} + +static void +disableAniMIBCounters(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALDEBUG(ah, HAL_DEBUG_ANI, "Disable MIB counters\n"); + + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save stats */ + ar5212DisableMibCounters(ah); /* disable everything */ + + OS_REG_WRITE(ah, AR_PHYCNTMASK1, 0); + OS_REG_WRITE(ah, AR_PHYCNTMASK2, 0); +} + +/* + * This routine returns the index into the aniState array that + * corresponds to the channel in *chan. If no match is found and the + * array is still not fully utilized, a new entry is created for the + * channel. We assume the attach function has already initialized the + * ah_ani values and only the channel field needs to be set. + */ +static int +ar5212GetAniChannelIndex(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ +#define N(a) (sizeof(a) / sizeof(a[0])) + struct ath_hal_5212 *ahp = AH5212(ah); + int i; + + for (i = 0; i < N(ahp->ah_ani); i++) { + struct ar5212AniState *asp = &ahp->ah_ani[i]; + if (asp->c.channel == chan->channel) + return i; + if (asp->c.channel == 0) { + asp->c.channel = chan->channel; + asp->c.channelFlags = chan->channelFlags; + asp->c.privFlags = chan->privFlags; + asp->isSetup = AH_FALSE; + if (IS_CHAN_2GHZ(chan)) + asp->params = &ahp->ah_aniParams24; + else + asp->params = &ahp->ah_aniParams5; + return i; + } + } + /* XXX statistic */ + HALDEBUG(ah, HAL_DEBUG_ANY, + "No more channel states left. Using channel 0\n"); + return 0; /* XXX gotta return something valid */ +#undef N +} + +/* + * Return the current ANI state of the channel we're on + */ +struct ar5212AniState * +ar5212AniGetCurrentState(struct ath_hal *ah) +{ + return AH5212(ah)->ah_curani; +} + +/* + * Return the current statistics. + */ +struct ar5212Stats * +ar5212AniGetCurrentStats(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + /* update mib stats so we return current data */ + /* XXX? side-effects to doing this here? */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + return &ahp->ah_stats; +} + +static void +setPhyErrBase(struct ath_hal *ah, struct ar5212AniParams *params) +{ + if (params->ofdmTrigHigh >= AR_PHY_COUNTMAX) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "OFDM Trigger %d is too high for hw counters, using max\n", + params->ofdmTrigHigh); + params->ofdmPhyErrBase = 0; + } else + params->ofdmPhyErrBase = AR_PHY_COUNTMAX - params->ofdmTrigHigh; + if (params->cckTrigHigh >= AR_PHY_COUNTMAX) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "CCK Trigger %d is too high for hw counters, using max\n", + params->cckTrigHigh); + params->cckPhyErrBase = 0; + } else + params->cckPhyErrBase = AR_PHY_COUNTMAX - params->cckTrigHigh; +} + +/* + * Setup ANI handling. Sets all thresholds and reset the + * channel statistics. Note that ar5212AniReset should be + * called by ar5212Reset before anything else happens and + * that's where we force initial settings. + */ +void +ar5212AniAttach(struct ath_hal *ah, const struct ar5212AniParams *params24, + const struct ar5212AniParams *params5, HAL_BOOL enable) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + ahp->ah_hasHwPhyCounters = + AH_PRIVATE(ah)->ah_caps.halHwPhyCounterSupport; + + if (params24 != AH_NULL) { + OS_MEMCPY(&ahp->ah_aniParams24, params24, sizeof(*params24)); + setPhyErrBase(ah, &ahp->ah_aniParams24); + } + if (params5 != AH_NULL) { + OS_MEMCPY(&ahp->ah_aniParams5, params5, sizeof(*params5)); + setPhyErrBase(ah, &ahp->ah_aniParams5); + } + + OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani)); + if (ahp->ah_hasHwPhyCounters) { + /* Enable MIB Counters */ + enableAniMIBCounters(ah, &ahp->ah_aniParams24 /*XXX*/); + } + if (enable) { /* Enable ani now */ + HALASSERT(params24 != AH_NULL && params5 != AH_NULL); + ahp->ah_procPhyErr |= HAL_ANI_ENA; + } else { + ahp->ah_procPhyErr &= ~HAL_ANI_ENA; + } +} + +HAL_BOOL +ar5212AniSetParams(struct ath_hal *ah, const struct ar5212AniParams *params24, + const struct ar5212AniParams *params5) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_BOOL ena = (ahp->ah_procPhyErr & HAL_ANI_ENA) != 0; + + ar5212AniControl(ah, HAL_ANI_MODE, AH_FALSE); + + OS_MEMCPY(&ahp->ah_aniParams24, params24, sizeof(*params24)); + setPhyErrBase(ah, &ahp->ah_aniParams24); + OS_MEMCPY(&ahp->ah_aniParams5, params5, sizeof(*params5)); + setPhyErrBase(ah, &ahp->ah_aniParams5); + + OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani)); + ar5212AniReset(ah, AH_PRIVATE(ah)->ah_curchan, + AH_PRIVATE(ah)->ah_opmode, AH_FALSE); + + ar5212AniControl(ah, HAL_ANI_MODE, ena); + + return AH_TRUE; +} + +/* + * Cleanup any ANI state setup. + */ +void +ar5212AniDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALDEBUG(ah, HAL_DEBUG_ANI, "Detaching Ani\n"); + if (ahp->ah_hasHwPhyCounters) + disableAniMIBCounters(ah); +} + +/* + * Control Adaptive Noise Immunity Parameters + */ +HAL_BOOL +ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) +{ + typedef int TABLE[]; + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState = ahp->ah_curani; + const struct ar5212AniParams *params = aniState->params; + + OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd); + + switch (cmd) { + case HAL_ANI_NOISE_IMMUNITY_LEVEL: { + u_int level = param; + + if (level > params->maxNoiseImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: level out of range (%u > %u)\n", + __func__, level, params->maxNoiseImmunityLevel); + return AH_FALSE; + } + + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, + AR_PHY_DESIRED_SZ_TOT_DES, params->totalSizeDesired[level]); + OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, + AR_PHY_AGC_CTL1_COARSE_LOW, params->coarseLow[level]); + OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, + AR_PHY_AGC_CTL1_COARSE_HIGH, params->coarseHigh[level]); + OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRPWR, params->firpwr[level]); + + if (level > aniState->noiseImmunityLevel) + ahp->ah_stats.ast_ani_niup++; + else if (level < aniState->noiseImmunityLevel) + ahp->ah_stats.ast_ani_nidown++; + aniState->noiseImmunityLevel = level; + break; + } + case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: { + static const TABLE m1ThreshLow = { 127, 50 }; + static const TABLE m2ThreshLow = { 127, 40 }; + static const TABLE m1Thresh = { 127, 0x4d }; + static const TABLE m2Thresh = { 127, 0x40 }; + static const TABLE m2CountThr = { 31, 16 }; + static const TABLE m2CountThrLow = { 63, 48 }; + u_int on = param ? 1 : 0; + + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M1_THRESH_LOW, m1ThreshLow[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2_THRESH_LOW, m2ThreshLow[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, m2CountThrLow[on]); + + if (on) { + OS_REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + } else { + OS_REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + } + if (on) + ahp->ah_stats.ast_ani_ofdmon++; + else + ahp->ah_stats.ast_ani_ofdmoff++; + aniState->ofdmWeakSigDetectOff = !on; + break; + } + case HAL_ANI_CCK_WEAK_SIGNAL_THR: { + static const TABLE weakSigThrCck = { 8, 6 }; + u_int high = param ? 1 : 0; + + OS_REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, + AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, weakSigThrCck[high]); + if (high) + ahp->ah_stats.ast_ani_cckhigh++; + else + ahp->ah_stats.ast_ani_ccklow++; + aniState->cckWeakSigThreshold = high; + break; + } + case HAL_ANI_FIRSTEP_LEVEL: { + u_int level = param; + + if (level > params->maxFirstepLevel) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: level out of range (%u > %u)\n", + __func__, level, params->maxFirstepLevel); + return AH_FALSE; + } + OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRSTEP, params->firstep[level]); + if (level > aniState->firstepLevel) + ahp->ah_stats.ast_ani_stepup++; + else if (level < aniState->firstepLevel) + ahp->ah_stats.ast_ani_stepdown++; + aniState->firstepLevel = level; + break; + } + case HAL_ANI_SPUR_IMMUNITY_LEVEL: { + u_int level = param; + + if (level > params->maxSpurImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: level out of range (%u > %u)\n", + __func__, level, params->maxSpurImmunityLevel); + return AH_FALSE; + } + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5, + AR_PHY_TIMING5_CYCPWR_THR1, params->cycPwrThr1[level]); + if (level > aniState->spurImmunityLevel) + ahp->ah_stats.ast_ani_spurup++; + else if (level < aniState->spurImmunityLevel) + ahp->ah_stats.ast_ani_spurdown++; + aniState->spurImmunityLevel = level; + break; + } + case HAL_ANI_PRESENT: + break; + case HAL_ANI_MODE: + if (param == 0) { + ahp->ah_procPhyErr &= ~HAL_ANI_ENA; + /* Turn off HW counters if we have them */ + ar5212AniDetach(ah); + ar5212SetRxFilter(ah, + ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR); + } else { /* normal/auto mode */ + /* don't mess with state if already enabled */ + if (ahp->ah_procPhyErr & HAL_ANI_ENA) + break; + if (ahp->ah_hasHwPhyCounters) { + ar5212SetRxFilter(ah, + ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR); + /* Enable MIB Counters */ + enableAniMIBCounters(ah, + ahp->ah_curani != AH_NULL ? + ahp->ah_curani->params: + &ahp->ah_aniParams24 /*XXX*/); + } else { + ar5212SetRxFilter(ah, + ar5212GetRxFilter(ah) | HAL_RX_FILTER_PHYERR); + } + ahp->ah_procPhyErr |= HAL_ANI_ENA; + } + break; +#ifdef AH_PRIVATE_DIAG + case HAL_ANI_PHYERR_RESET: + ahp->ah_stats.ast_ani_ofdmerrs = 0; + ahp->ah_stats.ast_ani_cckerrs = 0; + break; +#endif /* AH_PRIVATE_DIAG */ + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid cmd %u\n", + __func__, cmd); + return AH_FALSE; + } + return AH_TRUE; +} + +static void +ar5212AniOfdmErrTrigger(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan; + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(chan != AH_NULL); + + if (!ANI_ENA(ah)) + return; + + aniState = ahp->ah_curani; + params = aniState->params; + /* First, raise noise immunity level, up to max */ + if (aniState->noiseImmunityLevel+1 <= params->maxNoiseImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise NI to %u\n", __func__, + aniState->noiseImmunityLevel + 1); + ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel + 1); + return; + } + /* then, raise spur immunity level, up to max */ + if (aniState->spurImmunityLevel+1 <= params->maxSpurImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise SI to %u\n", __func__, + aniState->spurImmunityLevel + 1); + ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel + 1); + return; + } + + if (ANI_ENA_RSSI(ah)) { + int32_t rssi = BEACON_RSSI(ahp); + if (rssi > params->rssiThrHigh) { + /* + * Beacon rssi is high, can turn off ofdm + * weak sig detect. + */ + if (!aniState->ofdmWeakSigDetectOff) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d OWSD off\n", __func__, rssi); + ar5212AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_FALSE); + ar5212AniControl(ah, + HAL_ANI_SPUR_IMMUNITY_LEVEL, 0); + return; + } + /* + * If weak sig detect is already off, as last resort, + * raise firstep level + */ + if (aniState->firstepLevel+1 <= params->maxFirstepLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d raise ST %u\n", __func__, rssi, + aniState->firstepLevel+1); + ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + return; + } + } else if (rssi > params->rssiThrLow) { + /* + * Beacon rssi in mid range, need ofdm weak signal + * detect, but we can raise firststepLevel. + */ + if (aniState->ofdmWeakSigDetectOff) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d OWSD on\n", __func__, rssi); + ar5212AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_TRUE); + } + if (aniState->firstepLevel+1 <= params->maxFirstepLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d raise ST %u\n", __func__, rssi, + aniState->firstepLevel+1); + ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + } + return; + } else { + /* + * Beacon rssi is low, if in 11b/g mode, turn off ofdm + * weak signal detection and zero firstepLevel to + * maximize CCK sensitivity + */ + /* XXX can optimize */ + if (IS_CHAN_B(chan) || IS_CHAN_G(chan)) { + if (!aniState->ofdmWeakSigDetectOff) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d OWSD off\n", + __func__, rssi); + ar5212AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_FALSE); + } + if (aniState->firstepLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d zero ST (was %u)\n", + __func__, rssi, + aniState->firstepLevel); + ar5212AniControl(ah, + HAL_ANI_FIRSTEP_LEVEL, 0); + } + return; + } + } + } +} + +static void +ar5212AniCckErrTrigger(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan; + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(chan != AH_NULL); + + if (!ANI_ENA(ah)) + return; + + /* first, raise noise immunity level, up to max */ + aniState = ahp->ah_curani; + params = aniState->params; + if (aniState->noiseImmunityLevel+1 <= params->maxNoiseImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise NI to %u\n", __func__, + aniState->noiseImmunityLevel + 1); + ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel + 1); + return; + } + + if (ANI_ENA_RSSI(ah)) { + int32_t rssi = BEACON_RSSI(ahp); + if (rssi > params->rssiThrLow) { + /* + * Beacon signal in mid and high range, + * raise firstep level. + */ + if (aniState->firstepLevel+1 <= params->maxFirstepLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d raise ST %u\n", __func__, rssi, + aniState->firstepLevel+1); + ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + } + } else { + /* + * Beacon rssi is low, zero firstep level to maximize + * CCK sensitivity in 11b/g mode. + */ + /* XXX can optimize */ + if (IS_CHAN_B(chan) || IS_CHAN_G(chan)) { + if (aniState->firstepLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d zero ST (was %u)\n", + __func__, rssi, + aniState->firstepLevel); + ar5212AniControl(ah, + HAL_ANI_FIRSTEP_LEVEL, 0); + } + } + } + } +} + +static void +ar5212AniRestart(struct ath_hal *ah, struct ar5212AniState *aniState) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + aniState->listenTime = 0; + if (ahp->ah_hasHwPhyCounters) { + const struct ar5212AniParams *params = aniState->params; + /* + * NB: these are written on reset based on the + * ini so we must re-write them! + */ + OS_REG_WRITE(ah, AR_PHYCNT1, params->ofdmPhyErrBase); + OS_REG_WRITE(ah, AR_PHYCNT2, params->cckPhyErrBase); + OS_REG_WRITE(ah, AR_PHYCNTMASK1, AR_PHY_ERR_OFDM_TIMING); + OS_REG_WRITE(ah, AR_PHYCNTMASK2, AR_PHY_ERR_CCK_TIMING); + + /* Clear the mib counters and save them in the stats */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + } + aniState->ofdmPhyErrCount = 0; + aniState->cckPhyErrCount = 0; +} + +/* + * Restore/reset the ANI parameters and reset the statistics. + * This routine must be called for every channel change. + * + * NOTE: This is where ah_curani is set; other ani code assumes + * it is setup to reflect the current channel. + */ +void +ar5212AniReset(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, + HAL_OPMODE opmode, int restore) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState; + uint32_t rxfilter; + int index; + + index = ar5212GetAniChannelIndex(ah, chan); + aniState = &ahp->ah_ani[index]; + ahp->ah_curani = aniState; +#if 0 + ath_hal_printf(ah,"%s: chan %u/0x%x restore %d setup %d opmode %u\n", + __func__, chan->channel, chan->channelFlags, restore, + aniState->isSetup, opmode); +#else + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: chan %u/0x%x restore %d setup %d opmode %u\n", + __func__, chan->channel, chan->channelFlags, restore, + aniState->isSetup, opmode); +#endif + OS_MARK(ah, AH_MARK_ANI_RESET, opmode); + + /* + * Turn off PHY error frame delivery while we futz with settings. + */ + rxfilter = ar5212GetRxFilter(ah); + ar5212SetRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR); + /* + * Automatic processing is done only in station mode right now. + */ + if (opmode == HAL_M_STA) + ahp->ah_procPhyErr |= HAL_RSSI_ANI_ENA; + else + ahp->ah_procPhyErr &= ~HAL_RSSI_ANI_ENA; + /* + * Set all ani parameters. We either set them to initial + * values or restore the previous ones for the channel. + * XXX if ANI follows hardware, we don't care what mode we're + * XXX in, we should keep the ani parameters + */ + if (restore && aniState->isSetup) { + ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel); + ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel); + ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + !aniState->ofdmWeakSigDetectOff); + ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, + aniState->cckWeakSigThreshold); + ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel); + } else { + ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0); + ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0); + ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_TRUE); + ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, AH_FALSE); + ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0); + aniState->isSetup = AH_TRUE; + } + ar5212AniRestart(ah, aniState); + + /* restore RX filter mask */ + ar5212SetRxFilter(ah, rxfilter); +} + +/* + * Process a MIB interrupt. We may potentially be invoked because + * any of the MIB counters overflow/trigger so don't assume we're + * here because a PHY error counter triggered. + */ +void +ar5212ProcessMibIntr(struct ath_hal *ah, const HAL_NODE_STATS *stats) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t phyCnt1, phyCnt2; + + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: mibc 0x%x phyCnt1 0x%x phyCnt2 0x%x " + "filtofdm 0x%x filtcck 0x%x\n", + __func__, OS_REG_READ(ah, AR_MIBC), + OS_REG_READ(ah, AR_PHYCNT1), OS_REG_READ(ah, AR_PHYCNT2), + OS_REG_READ(ah, AR_FILTOFDM), OS_REG_READ(ah, AR_FILTCCK)); + + /* + * First order of business is to clear whatever caused + * the interrupt so we don't keep getting interrupted. + * We have the usual mib counters that are reset-on-read + * and the additional counters that appeared starting in + * Hainan. We collect the mib counters and explicitly + * zero additional counters we are not using. Anything + * else is reset only if it caused the interrupt. + */ + /* NB: these are not reset-on-read */ + phyCnt1 = OS_REG_READ(ah, AR_PHYCNT1); + phyCnt2 = OS_REG_READ(ah, AR_PHYCNT2); + /* not used, always reset them in case they are the cause */ + OS_REG_WRITE(ah, AR_FILTOFDM, 0); + OS_REG_WRITE(ah, AR_FILTCCK, 0); + + /* Clear the mib counters and save them in the stats */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + ahp->ah_stats.ast_nodestats = *stats; + + /* + * Check for an ani stat hitting the trigger threshold. + * When this happens we get a MIB interrupt and the top + * 2 bits of the counter register will be 0b11, hence + * the mask check of phyCnt?. + */ + if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || + ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { + struct ar5212AniState *aniState = ahp->ah_curani; + const struct ar5212AniParams *params = aniState->params; + uint32_t ofdmPhyErrCnt, cckPhyErrCnt; + + ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase; + ahp->ah_stats.ast_ani_ofdmerrs += + ofdmPhyErrCnt - aniState->ofdmPhyErrCount; + aniState->ofdmPhyErrCount = ofdmPhyErrCnt; + + cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase; + ahp->ah_stats.ast_ani_cckerrs += + cckPhyErrCnt - aniState->cckPhyErrCount; + aniState->cckPhyErrCount = cckPhyErrCnt; + + /* + * NB: figure out which counter triggered. If both + * trigger we'll only deal with one as the processing + * clobbers the error counter so the trigger threshold + * check will never be true. + */ + if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh) + ar5212AniOfdmErrTrigger(ah); + if (aniState->cckPhyErrCount > params->cckTrigHigh) + ar5212AniCckErrTrigger(ah); + /* NB: always restart to insure the h/w counters are reset */ + ar5212AniRestart(ah, aniState); + } +} + +void +ar5212AniPhyErrReport(struct ath_hal *ah, const struct ath_rx_status *rs) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(!ahp->ah_hasHwPhyCounters && rs != AH_NULL); + + aniState = ahp->ah_curani; + params = aniState->params; + if (rs->rs_phyerr == HAL_PHYERR_OFDM_TIMING) { + aniState->ofdmPhyErrCount++; + ahp->ah_stats.ast_ani_ofdmerrs++; + if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh) { + ar5212AniOfdmErrTrigger(ah); + ar5212AniRestart(ah, aniState); + } + } else if (rs->rs_phyerr == HAL_PHYERR_CCK_TIMING) { + aniState->cckPhyErrCount++; + ahp->ah_stats.ast_ani_cckerrs++; + if (aniState->cckPhyErrCount > params->cckTrigHigh) { + ar5212AniCckErrTrigger(ah); + ar5212AniRestart(ah, aniState); + } + } +} + +static void +ar5212AniLowerImmunity(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(ANI_ENA(ah)); + + aniState = ahp->ah_curani; + params = aniState->params; + if (ANI_ENA_RSSI(ah)) { + int32_t rssi = BEACON_RSSI(ahp); + if (rssi > params->rssiThrHigh) { + /* + * Beacon signal is high, leave ofdm weak signal + * detection off or it may oscillate. Let it fall + * through. + */ + } else if (rssi > params->rssiThrLow) { + /* + * Beacon rssi in mid range, turn on ofdm weak signal + * detection or lower firstep level. + */ + if (aniState->ofdmWeakSigDetectOff) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d OWSD on\n", __func__, rssi); + ar5212AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_TRUE); + return; + } + if (aniState->firstepLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d lower ST %u\n", __func__, rssi, + aniState->firstepLevel-1); + ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel - 1); + return; + } + } else { + /* + * Beacon rssi is low, reduce firstep level. + */ + if (aniState->firstepLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d lower ST %u\n", __func__, rssi, + aniState->firstepLevel-1); + ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel - 1); + return; + } + } + } + /* then lower spur immunity level, down to zero */ + if (aniState->spurImmunityLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: lower SI %u\n", + __func__, aniState->spurImmunityLevel-1); + ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel - 1); + return; + } + /* + * if all else fails, lower noise immunity level down to a min value + * zero for now + */ + if (aniState->noiseImmunityLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: lower NI %u\n", + __func__, aniState->noiseImmunityLevel-1); + ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel - 1); + return; + } +} + +#define CLOCK_RATE 44000 /* XXX use mac_usec or similar */ +/* convert HW counter values to ms using 11g clock rate, goo9d enough + for 11a and Turbo */ + +/* + * Return an approximation of the time spent ``listening'' by + * deducting the cycles spent tx'ing and rx'ing from the total + * cycle count since our last call. A return value <0 indicates + * an invalid/inconsistent time. + */ +static int32_t +ar5212AniGetListenTime(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState; + uint32_t txFrameCount, rxFrameCount, cycleCount; + int32_t listenTime; + + txFrameCount = OS_REG_READ(ah, AR_TFCNT); + rxFrameCount = OS_REG_READ(ah, AR_RFCNT); + cycleCount = OS_REG_READ(ah, AR_CCCNT); + + aniState = ahp->ah_curani; + if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { + /* + * Cycle counter wrap (or initial call); it's not possible + * to accurately calculate a value because the registers + * right shift rather than wrap--so punt and return 0. + */ + listenTime = 0; + ahp->ah_stats.ast_ani_lzero++; + } else { + int32_t ccdelta = cycleCount - aniState->cycleCount; + int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; + int32_t tfdelta = txFrameCount - aniState->txFrameCount; + listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE; + } + aniState->cycleCount = cycleCount; + aniState->txFrameCount = txFrameCount; + aniState->rxFrameCount = rxFrameCount; + return listenTime; +} + +/* + * Update ani stats in preparation for listen time processing. + */ +static void +updateMIBStats(struct ath_hal *ah, struct ar5212AniState *aniState) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const struct ar5212AniParams *params = aniState->params; + uint32_t phyCnt1, phyCnt2; + int32_t ofdmPhyErrCnt, cckPhyErrCnt; + + HALASSERT(ahp->ah_hasHwPhyCounters); + + /* Clear the mib counters and save them in the stats */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + + /* NB: these are not reset-on-read */ + phyCnt1 = OS_REG_READ(ah, AR_PHYCNT1); + phyCnt2 = OS_REG_READ(ah, AR_PHYCNT2); + + /* NB: these are spec'd to never roll-over */ + ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase; + if (ofdmPhyErrCnt < 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "OFDM phyErrCnt %d phyCnt1 0x%x\n", + ofdmPhyErrCnt, phyCnt1); + ofdmPhyErrCnt = AR_PHY_COUNTMAX; + } + ahp->ah_stats.ast_ani_ofdmerrs += + ofdmPhyErrCnt - aniState->ofdmPhyErrCount; + aniState->ofdmPhyErrCount = ofdmPhyErrCnt; + + cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase; + if (cckPhyErrCnt < 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "CCK phyErrCnt %d phyCnt2 0x%x\n", + cckPhyErrCnt, phyCnt2); + cckPhyErrCnt = AR_PHY_COUNTMAX; + } + ahp->ah_stats.ast_ani_cckerrs += + cckPhyErrCnt - aniState->cckPhyErrCount; + aniState->cckPhyErrCount = cckPhyErrCnt; +} + +/* + * Do periodic processing. This routine is called from the + * driver's rx interrupt handler after processing frames. + */ +void +ar5212AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats, + HAL_CHANNEL *chan) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState = ahp->ah_curani; + const struct ar5212AniParams *params; + int32_t listenTime; + + ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi; + + /* XXX can aniState be null? */ + if (aniState == AH_NULL) + return; + if (!ANI_ENA(ah)) + return; + + listenTime = ar5212AniGetListenTime(ah); + if (listenTime < 0) { + ahp->ah_stats.ast_ani_lneg++; + /* restart ANI period if listenTime is invalid */ + ar5212AniRestart(ah, aniState); + } + /* XXX beware of overflow? */ + aniState->listenTime += listenTime; + + OS_MARK(ah, AH_MARK_ANI_POLL, aniState->listenTime); + + params = aniState->params; + if (aniState->listenTime > 5*params->period) { + /* + * Check to see if need to lower immunity if + * 5 aniPeriods have passed + */ + if (ahp->ah_hasHwPhyCounters) + updateMIBStats(ah, aniState); + if (aniState->ofdmPhyErrCount <= aniState->listenTime * + params->ofdmTrigLow/1000 && + aniState->cckPhyErrCount <= aniState->listenTime * + params->cckTrigLow/1000) + ar5212AniLowerImmunity(ah); + ar5212AniRestart(ah, aniState); + } else if (aniState->listenTime > params->period) { + if (ahp->ah_hasHwPhyCounters) + updateMIBStats(ah, aniState); + /* check to see if need to raise immunity */ + if (aniState->ofdmPhyErrCount > aniState->listenTime * + params->ofdmTrigHigh / 1000) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: OFDM err %u listenTime %u\n", __func__, + aniState->ofdmPhyErrCount, aniState->listenTime); + ar5212AniOfdmErrTrigger(ah); + ar5212AniRestart(ah, aniState); + } else if (aniState->cckPhyErrCount > aniState->listenTime * + params->cckTrigHigh / 1000) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: CCK err %u listenTime %u\n", __func__, + aniState->cckPhyErrCount, aniState->listenTime); + ar5212AniCckErrTrigger(ah); + ar5212AniRestart(ah, aniState); + } + } +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_attach.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_attach.c new file mode 100644 index 0000000000..5c51af829c --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_attach.c @@ -0,0 +1,870 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212_attach.c,v 1.18 2008/11/19 22:10:42 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#define AH_5212_COMMON +#include "ar5212/ar5212.ini" + +static const struct ath_hal_private ar5212hal = {{ + .ah_magic = AR5212_MAGIC, + .ah_abi = HAL_ABI_VERSION, + .ah_countryCode = CTRY_DEFAULT, + + .ah_getRateTable = ar5212GetRateTable, + .ah_detach = ar5212Detach, + + /* Reset Functions */ + .ah_reset = ar5212Reset, + .ah_phyDisable = ar5212PhyDisable, + .ah_disable = ar5212Disable, + .ah_setPCUConfig = ar5212SetPCUConfig, + .ah_perCalibration = ar5212PerCalibration, + .ah_perCalibrationN = ar5212PerCalibrationN, + .ah_resetCalValid = ar5212ResetCalValid, + .ah_setTxPowerLimit = ar5212SetTxPowerLimit, + .ah_getChanNoise = ath_hal_getChanNoise, + + /* Transmit functions */ + .ah_updateTxTrigLevel = ar5212UpdateTxTrigLevel, + .ah_setupTxQueue = ar5212SetupTxQueue, + .ah_setTxQueueProps = ar5212SetTxQueueProps, + .ah_getTxQueueProps = ar5212GetTxQueueProps, + .ah_releaseTxQueue = ar5212ReleaseTxQueue, + .ah_resetTxQueue = ar5212ResetTxQueue, + .ah_getTxDP = ar5212GetTxDP, + .ah_setTxDP = ar5212SetTxDP, + .ah_numTxPending = ar5212NumTxPending, + .ah_startTxDma = ar5212StartTxDma, + .ah_stopTxDma = ar5212StopTxDma, + .ah_setupTxDesc = ar5212SetupTxDesc, + .ah_setupXTxDesc = ar5212SetupXTxDesc, + .ah_fillTxDesc = ar5212FillTxDesc, + .ah_procTxDesc = ar5212ProcTxDesc, + .ah_getTxIntrQueue = ar5212GetTxIntrQueue, + .ah_reqTxIntrDesc = ar5212IntrReqTxDesc, + + /* RX Functions */ + .ah_getRxDP = ar5212GetRxDP, + .ah_setRxDP = ar5212SetRxDP, + .ah_enableReceive = ar5212EnableReceive, + .ah_stopDmaReceive = ar5212StopDmaReceive, + .ah_startPcuReceive = ar5212StartPcuReceive, + .ah_stopPcuReceive = ar5212StopPcuReceive, + .ah_setMulticastFilter = ar5212SetMulticastFilter, + .ah_setMulticastFilterIndex = ar5212SetMulticastFilterIndex, + .ah_clrMulticastFilterIndex = ar5212ClrMulticastFilterIndex, + .ah_getRxFilter = ar5212GetRxFilter, + .ah_setRxFilter = ar5212SetRxFilter, + .ah_setupRxDesc = ar5212SetupRxDesc, + .ah_procRxDesc = ar5212ProcRxDesc, + .ah_rxMonitor = ar5212AniPoll, + .ah_procMibEvent = ar5212ProcessMibIntr, + + /* Misc Functions */ + .ah_getCapability = ar5212GetCapability, + .ah_setCapability = ar5212SetCapability, + .ah_getDiagState = ar5212GetDiagState, + .ah_getMacAddress = ar5212GetMacAddress, + .ah_setMacAddress = ar5212SetMacAddress, + .ah_getBssIdMask = ar5212GetBssIdMask, + .ah_setBssIdMask = ar5212SetBssIdMask, + .ah_setRegulatoryDomain = ar5212SetRegulatoryDomain, + .ah_setLedState = ar5212SetLedState, + .ah_writeAssocid = ar5212WriteAssocid, + .ah_gpioCfgInput = ar5212GpioCfgInput, + .ah_gpioCfgOutput = ar5212GpioCfgOutput, + .ah_gpioGet = ar5212GpioGet, + .ah_gpioSet = ar5212GpioSet, + .ah_gpioSetIntr = ar5212GpioSetIntr, + .ah_getTsf32 = ar5212GetTsf32, + .ah_getTsf64 = ar5212GetTsf64, + .ah_resetTsf = ar5212ResetTsf, + .ah_detectCardPresent = ar5212DetectCardPresent, + .ah_updateMibCounters = ar5212UpdateMibCounters, + .ah_getRfGain = ar5212GetRfgain, + .ah_getDefAntenna = ar5212GetDefAntenna, + .ah_setDefAntenna = ar5212SetDefAntenna, + .ah_getAntennaSwitch = ar5212GetAntennaSwitch, + .ah_setAntennaSwitch = ar5212SetAntennaSwitch, + .ah_setSifsTime = ar5212SetSifsTime, + .ah_getSifsTime = ar5212GetSifsTime, + .ah_setSlotTime = ar5212SetSlotTime, + .ah_getSlotTime = ar5212GetSlotTime, + .ah_setAckTimeout = ar5212SetAckTimeout, + .ah_getAckTimeout = ar5212GetAckTimeout, + .ah_setAckCTSRate = ar5212SetAckCTSRate, + .ah_getAckCTSRate = ar5212GetAckCTSRate, + .ah_setCTSTimeout = ar5212SetCTSTimeout, + .ah_getCTSTimeout = ar5212GetCTSTimeout, + .ah_setDecompMask = ar5212SetDecompMask, + .ah_setCoverageClass = ar5212SetCoverageClass, + + /* Key Cache Functions */ + .ah_getKeyCacheSize = ar5212GetKeyCacheSize, + .ah_resetKeyCacheEntry = ar5212ResetKeyCacheEntry, + .ah_isKeyCacheEntryValid = ar5212IsKeyCacheEntryValid, + .ah_setKeyCacheEntry = ar5212SetKeyCacheEntry, + .ah_setKeyCacheEntryMac = ar5212SetKeyCacheEntryMac, + + /* Power Management Functions */ + .ah_setPowerMode = ar5212SetPowerMode, + .ah_getPowerMode = ar5212GetPowerMode, + + /* Beacon Functions */ + .ah_setBeaconTimers = ar5212SetBeaconTimers, + .ah_beaconInit = ar5212BeaconInit, + .ah_setStationBeaconTimers = ar5212SetStaBeaconTimers, + .ah_resetStationBeaconTimers = ar5212ResetStaBeaconTimers, + + /* Interrupt Functions */ + .ah_isInterruptPending = ar5212IsInterruptPending, + .ah_getPendingInterrupts = ar5212GetPendingInterrupts, + .ah_getInterrupts = ar5212GetInterrupts, + .ah_setInterrupts = ar5212SetInterrupts }, + + .ah_getChannelEdges = ar5212GetChannelEdges, + .ah_getWirelessModes = ar5212GetWirelessModes, + .ah_eepromRead = ar5212EepromRead, +#ifdef AH_SUPPORT_WRITE_EEPROM + .ah_eepromWrite = ar5212EepromWrite, +#endif + .ah_gpioCfgOutput = ar5212GpioCfgOutput, + .ah_gpioCfgInput = ar5212GpioCfgInput, + .ah_gpioGet = ar5212GpioGet, + .ah_gpioSet = ar5212GpioSet, + .ah_gpioSetIntr = ar5212GpioSetIntr, + .ah_getChipPowerLimits = ar5212GetChipPowerLimits, +}; + +/* + * Disable PLL when in L0s as well as receiver clock when in L1. + * This power saving option must be enabled through the Serdes. + * + * Programming the Serdes must go through the same 288 bit serial shift + * register as the other analog registers. Hence the 9 writes. + * + * XXX Clean up the magic numbers. + */ +static void +configurePciePowerSave(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); + + /* RX shut off when elecidle is asserted */ + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); + + /* Shut off PLL and CLKREQ active in L1 */ + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); + + /* Load the new settings */ + OS_REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); +} + +uint32_t +ar5212GetRadioRev(struct ath_hal *ah) +{ + uint32_t val; + int i; + + /* Read Radio Chip Rev Extract */ + OS_REG_WRITE(ah, AR_PHY(0x34), 0x00001c16); + for (i = 0; i < 8; i++) + OS_REG_WRITE(ah, AR_PHY(0x20), 0x00010000); + val = (OS_REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; + val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); + return ath_hal_reverseBits(val, 8); +} + +static void +ar5212AniSetup(struct ath_hal *ah) +{ + static const struct ar5212AniParams aniparams = { + .maxNoiseImmunityLevel = 4, /* levels 0..4 */ + .totalSizeDesired = { -55, -55, -55, -55, -62 }, + .coarseHigh = { -14, -14, -14, -14, -12 }, + .coarseLow = { -64, -64, -64, -64, -70 }, + .firpwr = { -78, -78, -78, -78, -80 }, + .maxSpurImmunityLevel = 2, /* NB: depends on chip rev */ + .cycPwrThr1 = { 2, 4, 6, 8, 10, 12, 14, 16 }, + .maxFirstepLevel = 2, /* levels 0..2 */ + .firstep = { 0, 4, 8 }, + .ofdmTrigHigh = 500, + .ofdmTrigLow = 200, + .cckTrigHigh = 200, + .cckTrigLow = 100, + .rssiThrHigh = 40, + .rssiThrLow = 7, + .period = 100, + }; + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_GRIFFIN) { + struct ar5212AniParams tmp; + OS_MEMCPY(&tmp, &aniparams, sizeof(struct ar5212AniParams)); + tmp.maxSpurImmunityLevel = 7; /* Venice and earlier */ + ar5212AniAttach(ah, &tmp, &tmp, AH_TRUE); + } else + ar5212AniAttach(ah, &aniparams, &aniparams, AH_TRUE); +} + +/* + * Attach for an AR5212 part. + */ +void +ar5212InitState(struct ath_hal_5212 *ahp, uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + static const uint8_t defbssidmask[IEEE80211_ADDR_LEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + struct ath_hal *ah; + + ah = &ahp->ah_priv.h; + /* set initial values */ + OS_MEMCPY(&ahp->ah_priv, &ar5212hal, sizeof(struct ath_hal_private)); + ah->ah_sc = sc; + ah->ah_st = st; + ah->ah_sh = sh; + + ah->ah_devid = devid; /* NB: for alq */ + AH_PRIVATE(ah)->ah_devid = devid; + AH_PRIVATE(ah)->ah_subvendorid = 0; /* XXX */ + + AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER; + AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */ + + ahp->ah_antControl = HAL_ANT_VARIABLE; + ahp->ah_diversity = AH_TRUE; + ahp->ah_bIQCalibration = AH_FALSE; + /* + * Enable MIC handling. + */ + ahp->ah_staId1Defaults = AR_STA_ID1_CRPT_MIC_ENABLE; + ahp->ah_rssiThr = INIT_RSSI_THR; + ahp->ah_tpcEnabled = AH_FALSE; /* disabled by default */ + ahp->ah_phyPowerOn = AH_FALSE; + ahp->ah_macTPC = SM(MAX_RATE_POWER, AR_TPC_ACK) + | SM(MAX_RATE_POWER, AR_TPC_CTS) + | SM(MAX_RATE_POWER, AR_TPC_CHIRP); + ahp->ah_beaconInterval = 100; /* XXX [20..1000] */ + ahp->ah_enable32kHzClock = DONT_USE_32KHZ;/* XXX */ + ahp->ah_slottime = (u_int) -1; + ahp->ah_acktimeout = (u_int) -1; + ahp->ah_ctstimeout = (u_int) -1; + ahp->ah_sifstime = (u_int) -1; + OS_MEMCPY(&ahp->ah_bssidmask, defbssidmask, IEEE80211_ADDR_LEN); +#undef N +} + +/* + * Validate MAC version and revision. + */ +static HAL_BOOL +ar5212IsMacSupported(uint8_t macVersion, uint8_t macRev) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + static const struct { + uint8_t version; + uint8_t revMin, revMax; + } macs[] = { + { AR_SREV_VERSION_VENICE, + AR_SREV_D2PLUS, AR_SREV_REVISION_MAX }, + { AR_SREV_VERSION_GRIFFIN, + AR_SREV_D2PLUS, AR_SREV_REVISION_MAX }, + { AR_SREV_5413, + AR_SREV_REVISION_MIN, AR_SREV_REVISION_MAX }, + { AR_SREV_5424, + AR_SREV_REVISION_MIN, AR_SREV_REVISION_MAX }, + { AR_SREV_2425, + AR_SREV_REVISION_MIN, AR_SREV_REVISION_MAX }, + { AR_SREV_2417, + AR_SREV_REVISION_MIN, AR_SREV_REVISION_MAX }, + }; + int i; + + for (i = 0; i < N(macs); i++) + if (macs[i].version == macVersion && + macs[i].revMin <= macRev && macRev <= macs[i].revMax) + return AH_TRUE; + return AH_FALSE; +#undef N +} + +/* + * Attach for an AR5212 part. + */ +static struct ath_hal * +ar5212Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) +{ +#define AH_EEPROM_PROTECT(ah) \ + (IS_PCIE(ah) ? AR_EEPROM_PROTECT_PCIE : AR_EEPROM_PROTECT) + struct ath_hal_5212 *ahp; + struct ath_hal *ah; + struct ath_hal_rf *rf; + uint32_t val; + uint16_t eeval; + HAL_STATUS ecode; + + HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + __func__, sc, (void*) st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp = ath_hal_malloc(sizeof (struct ath_hal_5212)); + if (ahp == AH_NULL) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot allocate memory for state block\n", __func__); + *status = HAL_ENOMEM; + return AH_NULL; + } + ar5212InitState(ahp, devid, sc, st, sh, status); + ah = &ahp->ah_priv.h; + + if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + /* Read Revisions from Chips before taking out of reset */ + val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID; + AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S; + AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION; + + if (!ar5212IsMacSupported(AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Mac Chip Rev 0x%02x.%x not supported\n" , + __func__, AH_PRIVATE(ah)->ah_macVersion, + AH_PRIVATE(ah)->ah_macRev); + ecode = HAL_ENOTSUPP; + goto bad; + } + + /* setup common ini data; rf backends handle remainder */ + HAL_INI_INIT(&ahp->ah_ini_modes, ar5212Modes, 6); + HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 2); + + if (!ar5212ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + ecode = HAL_EIO; + goto bad; + } + + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); + + if (IS_PCIE(ah)) { + /* XXX: build flag to disable this? */ + configurePciePowerSave(ah); + } + + if (!ar5212ChipTest(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", + __func__); + ecode = HAL_ESELFTEST; + goto bad; + } + + /* Enable PCI core retry fix in software for Hainan and up */ + if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_VENICE) + OS_REG_SET_BIT(ah, AR_PCICFG, AR_PCICFG_RETRYFIXEN); + + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* Read Radio Chip Rev Extract */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah); + + rf = ath_hal_rfprobe(ah, &ecode); + if (rf == AH_NULL) + goto bad; + + /* NB: silently accept anything in release code per Atheros */ + switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { + case AR_RAD5111_SREV_MAJOR: + case AR_RAD5112_SREV_MAJOR: + case AR_RAD2112_SREV_MAJOR: + case AR_RAD2111_SREV_MAJOR: + case AR_RAD2413_SREV_MAJOR: + case AR_RAD5413_SREV_MAJOR: + case AR_RAD5424_SREV_MAJOR: + break; + default: + if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { + /* + * When RF_Silent is used, the + * analog chip is reset. So when the system boots + * up with the radio switch off we cannot determine + * the RF chip rev. To workaround this check the + * mac+phy revs and if Hainan, set the radio rev + * to Derby. + */ + if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && + AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN && + AH_PRIVATE(ah)->ah_phyRev == AR_PHYREV_HAINAN) { + AH_PRIVATE(ah)->ah_analog5GhzRev = AR_ANALOG5REV_HAINAN; + break; + } + if (IS_2413(ah)) { /* Griffin */ + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD2413_SREV_MAJOR | 0x1; + break; + } + if (IS_5413(ah)) { /* Eagle */ + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD5413_SREV_MAJOR | 0x2; + break; + } + if (IS_2425(ah) || IS_2417(ah)) {/* Swan or Nala */ + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD5424_SREV_MAJOR | 0x2; + break; + } + } +#ifdef AH_DEBUG + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5G Radio Chip Rev 0x%02X is not supported by " + "this driver\n", + __func__, AH_PRIVATE(ah)->ah_analog5GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; +#endif + } + if (IS_RAD5112_REV1(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5112 Rev 1 is not supported by this " + "driver (analog5GhzRev 0x%x)\n", __func__, + AH_PRIVATE(ah)->ah_analog5GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; + } + + val = OS_REG_READ(ah, AR_PCICFG); + val = MS(val, AR_PCICFG_EEPROM_SIZE); + if (val == 0) { + if (!IS_PCIE(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unsupported EEPROM size %u (0x%x) found\n", + __func__, val, val); + ecode = HAL_EESIZE; + goto bad; + } + /* XXX AH_PRIVATE(ah)->ah_isPciExpress = AH_TRUE; */ + } else if (val != AR_PCICFG_EEPROM_SIZE_16K) { + if (AR_PCICFG_EEPROM_SIZE_FAILED == val) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unsupported EEPROM size %u (0x%x) found\n", + __func__, val, val); + ecode = HAL_EESIZE; + goto bad; + } + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: EEPROM size = %d. Must be %d (16k).\n", + __func__, val, AR_PCICFG_EEPROM_SIZE_16K); + ecode = HAL_EESIZE; + goto bad; + } + ecode = ath_hal_legacyEepromAttach(ah); + if (ecode != HAL_OK) { + goto bad; + } + ahp->ah_isHb63 = IS_2425(ah) && ath_hal_eepromGetFlag(ah, AR_EEP_ISTALON); + + /* + * If Bmode and AR5212, verify 2.4 analog exists + */ + if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) && + (AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD5111_SREV_MAJOR) { + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00004007); + OS_DELAY(2000); + AH_PRIVATE(ah)->ah_analog2GhzRev = ar5212GetRadioRev(ah); + + /* Set baseband for 5GHz chip */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + OS_DELAY(2000); + if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != AR_RAD2111_SREV_MAJOR) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 2G Radio Chip Rev 0x%02X is not " + "supported by this driver\n", __func__, + AH_PRIVATE(ah)->ah_analog2GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; + } + } + + ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read regulatory domain from EEPROM\n", + __func__); + goto bad; + } + AH_PRIVATE(ah)->ah_currentRD = eeval; + /* XXX record serial number */ + + /* + * Got everything we need now to setup the capabilities. + */ + if (!ar5212FillCapabilityInfo(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: failed ar5212FillCapabilityInfo\n", __func__); + ecode = HAL_EEREAD; + goto bad; + } + + if (!rf->attach(ah, &ecode)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", + __func__, ecode); + goto bad; + } + /* + * Set noise floor adjust method; we arrange a + * direct call instead of thunking. + */ + AH_PRIVATE(ah)->ah_getNfAdjust = ahp->ah_rfHal->getNfAdjust; + + /* Initialize gain ladder thermal calibration structure */ + ar5212InitializeGainValues(ah); + + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error getting mac address from EEPROM\n", __func__); + goto bad; + } + + ar5212AniSetup(ah); + /* Setup of Radar/AR structures happens in ath_hal_initchannels*/ + ar5212InitNfCalHistBuffer(ah); + + /* XXX EAR stuff goes here */ + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); + + return ah; + +bad: + if (ahp) + ar5212Detach((struct ath_hal *) ahp); + if (status) + *status = ecode; + return AH_NULL; +#undef AH_EEPROM_PROTECT +} + +void +ar5212Detach(struct ath_hal *ah) +{ + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__); + + HALASSERT(ah != AH_NULL); + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + ar5212AniDetach(ah); + ar5212RfDetach(ah); + ar5212Disable(ah); + ar5212SetPowerMode(ah, HAL_PM_FULL_SLEEP, AH_TRUE); + + ath_hal_eepromDetach(ah); + ath_hal_free(ah); +} + +HAL_BOOL +ar5212ChipTest(struct ath_hal *ah) +{ + uint32_t regAddr[2] = { AR_STA_ID0, AR_PHY_BASE+(8 << 2) }; + uint32_t regHold[2]; + uint32_t patternData[4] = + { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 }; + int i, j; + + /* Test PHY & MAC registers */ + for (i = 0; i < 2; i++) { + uint32_t addr = regAddr[i]; + uint32_t wrData, rdData; + + regHold[i] = OS_REG_READ(ah, addr); + for (j = 0; j < 0x100; j++) { + wrData = (j << 16) | j; + OS_REG_WRITE(ah, addr, wrData); + rdData = OS_REG_READ(ah, addr); + if (rdData != wrData) { + HALDEBUG(ah, HAL_DEBUG_ANY, +"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", + __func__, addr, wrData, rdData); + return AH_FALSE; + } + } + for (j = 0; j < 4; j++) { + wrData = patternData[j]; + OS_REG_WRITE(ah, addr, wrData); + rdData = OS_REG_READ(ah, addr); + if (wrData != rdData) { + HALDEBUG(ah, HAL_DEBUG_ANY, +"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", + __func__, addr, wrData, rdData); + return AH_FALSE; + } + } + OS_REG_WRITE(ah, regAddr[i], regHold[i]); + } + OS_DELAY(100); + return AH_TRUE; +} + +/* + * Store the channel edges for the requested operational mode + */ +HAL_BOOL +ar5212GetChannelEdges(struct ath_hal *ah, + uint16_t flags, uint16_t *low, uint16_t *high) +{ + if (flags & CHANNEL_5GHZ) { + *low = 4915; + *high = 6100; + return AH_TRUE; + } + if ((flags & CHANNEL_2GHZ) && + (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) || + ath_hal_eepromGetFlag(ah, AR_EEP_GMODE))) { + *low = 2312; + *high = 2732; + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Fill all software cached or static hardware state information. + * Return failure if capabilities are to come from EEPROM and + * cannot be read. + */ +HAL_BOOL +ar5212FillCapabilityInfo(struct ath_hal *ah) +{ +#define AR_KEYTABLE_SIZE 128 +#define IS_GRIFFIN_LITE(ah) \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_GRIFFIN && \ + AH_PRIVATE(ah)->ah_macRev == AR_SREV_GRIFFIN_LITE) +#define IS_COBRA(ah) \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_COBRA) +#define IS_2112(ah) \ + ((AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD2112_SREV_MAJOR) + + struct ath_hal_private *ahpriv = AH_PRIVATE(ah); + HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; + uint16_t capField, val; + + /* Read the capability EEPROM location */ + if (ath_hal_eepromGet(ah, AR_EEP_OPCAP, &capField) != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unable to read caps from eeprom\n", __func__); + return AH_FALSE; + } + if (IS_2112(ah)) + ath_hal_eepromSet(ah, AR_EEP_AMODE, AH_FALSE); + if (capField == 0 && IS_GRIFFIN_LITE(ah)) { + /* + * For griffin-lite cards with unprogrammed capabilities. + */ + ath_hal_eepromSet(ah, AR_EEP_COMPRESS, AH_FALSE); + ath_hal_eepromSet(ah, AR_EEP_FASTFRAME, AH_FALSE); + ath_hal_eepromSet(ah, AR_EEP_TURBO5DISABLE, AH_TRUE); + ath_hal_eepromSet(ah, AR_EEP_TURBO2DISABLE, AH_TRUE); + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: override caps for griffin-lite, now 0x%x (+!turbo)\n", + __func__, capField); + } + + /* Modify reg domain on newer cards that need to work with older sw */ + if (ahpriv->ah_opmode != HAL_M_HOSTAP && + ahpriv->ah_subvendorid == AR_SUBVENDOR_ID_NEW_A) { + if (ahpriv->ah_currentRD == 0x64 || + ahpriv->ah_currentRD == 0x65) + ahpriv->ah_currentRD += 5; + else if (ahpriv->ah_currentRD == 0x41) + ahpriv->ah_currentRD = 0x43; + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: regdomain mapped to 0x%x\n", + __func__, ahpriv->ah_currentRD); + } + + if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2417 || + AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2425) { + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: enable Bmode and disable turbo for Swan/Nala\n", + __func__); + ath_hal_eepromSet(ah, AR_EEP_BMODE, AH_TRUE); + ath_hal_eepromSet(ah, AR_EEP_COMPRESS, AH_FALSE); + ath_hal_eepromSet(ah, AR_EEP_FASTFRAME, AH_FALSE); + ath_hal_eepromSet(ah, AR_EEP_TURBO5DISABLE, AH_TRUE); + ath_hal_eepromSet(ah, AR_EEP_TURBO2DISABLE, AH_TRUE); + } + + /* Construct wireless mode from EEPROM */ + pCap->halWirelessModes = 0; + if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { + pCap->halWirelessModes |= HAL_MODE_11A; + if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) + pCap->halWirelessModes |= HAL_MODE_TURBO; + } + if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) + pCap->halWirelessModes |= HAL_MODE_11B; + if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) && + ahpriv->ah_subvendorid != AR_SUBVENDOR_ID_NOG) { + pCap->halWirelessModes |= HAL_MODE_11G; + if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE)) + pCap->halWirelessModes |= HAL_MODE_108G; + } + + pCap->halLow2GhzChan = 2312; + /* XXX 2417 too? */ + if (IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2425(ah) || IS_2417(ah)) + pCap->halHigh2GhzChan = 2500; + else + pCap->halHigh2GhzChan = 2732; + + pCap->halLow5GhzChan = 4915; + pCap->halHigh5GhzChan = 6100; + + pCap->halCipherCkipSupport = AH_FALSE; + pCap->halCipherTkipSupport = AH_TRUE; + pCap->halCipherAesCcmSupport = + (ath_hal_eepromGetFlag(ah, AR_EEP_AES) && + ((AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE) || + ((AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE) && + (AH_PRIVATE(ah)->ah_macRev >= AR_SREV_VERSION_OAHU)))); + + pCap->halMicCkipSupport = AH_FALSE; + pCap->halMicTkipSupport = AH_TRUE; + pCap->halMicAesCcmSupport = ath_hal_eepromGetFlag(ah, AR_EEP_AES); + /* + * Starting with Griffin TX+RX mic keys can be combined + * in one key cache slot. + */ + if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_GRIFFIN) + pCap->halTkipMicTxRxKeySupport = AH_TRUE; + else + pCap->halTkipMicTxRxKeySupport = AH_FALSE; + pCap->halChanSpreadSupport = AH_TRUE; + pCap->halSleepAfterBeaconBroken = AH_TRUE; + + if (ahpriv->ah_macRev > 1 || IS_COBRA(ah)) { + pCap->halCompressSupport = + ath_hal_eepromGetFlag(ah, AR_EEP_COMPRESS) && + (pCap->halWirelessModes & (HAL_MODE_11A|HAL_MODE_11G)) != 0; + pCap->halBurstSupport = ath_hal_eepromGetFlag(ah, AR_EEP_BURST); + pCap->halFastFramesSupport = + ath_hal_eepromGetFlag(ah, AR_EEP_FASTFRAME) && + (pCap->halWirelessModes & (HAL_MODE_11A|HAL_MODE_11G)) != 0; + pCap->halChapTuningSupport = AH_TRUE; + pCap->halTurboPrimeSupport = AH_TRUE; + } + pCap->halTurboGSupport = pCap->halWirelessModes & HAL_MODE_108G; + + pCap->halPSPollBroken = AH_TRUE; /* XXX fixed in later revs? */ + pCap->halVEOLSupport = AH_TRUE; + pCap->halBssIdMaskSupport = AH_TRUE; + pCap->halMcastKeySrchSupport = AH_TRUE; + if ((ahpriv->ah_macVersion == AR_SREV_VERSION_VENICE && + ahpriv->ah_macRev == 8) || + ahpriv->ah_macVersion > AR_SREV_VERSION_VENICE) + pCap->halTsfAddSupport = AH_TRUE; + + if (ath_hal_eepromGet(ah, AR_EEP_MAXQCU, &val) == HAL_OK) + pCap->halTotalQueues = val; + else + pCap->halTotalQueues = HAL_NUM_TX_QUEUES; + + if (ath_hal_eepromGet(ah, AR_EEP_KCENTRIES, &val) == HAL_OK) + pCap->halKeyCacheSize = val; + else + pCap->halKeyCacheSize = AR_KEYTABLE_SIZE; + + pCap->halChanHalfRate = AH_TRUE; + pCap->halChanQuarterRate = AH_TRUE; + + if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) && + ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) { + /* NB: enabled by default */ + ahpriv->ah_rfkillEnabled = AH_TRUE; + pCap->halRfSilentSupport = AH_TRUE; + } + + /* NB: this is a guess, noone seems to know the answer */ + ahpriv->ah_rxornIsFatal = + (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_VENICE); + + /* h/w phy counters first appeared in Hainan */ + pCap->halHwPhyCounterSupport = + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && + AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN) || + AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE; + + pCap->halTstampPrecision = 15; + + return AH_TRUE; +#undef IS_COBRA +#undef IS_GRIFFIN_LITE +#undef AR_KEYTABLE_SIZE +} + +static const char* +ar5212Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID || + vendorid == ATHEROS_3COM_VENDOR_ID || + vendorid == ATHEROS_3COM2_VENDOR_ID) { + switch (devid) { + case AR5212_FPGA: + return "Atheros 5212 (FPGA)"; + case AR5212_DEVID: + case AR5212_DEVID_IBM: + case AR5212_DEFAULT: + return "Atheros 5212"; + case AR5212_AR2413: + return "Atheros 2413"; + case AR5212_AR2417: + return "Atheros 2417"; + case AR5212_AR5413: + return "Atheros 5413"; + case AR5212_AR5424: + return "Atheros 5424/2424"; + } + } + return AH_NULL; +} +AH_CHIP(AR5212, ar5212Probe, ar5212Attach); diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_beacon.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_beacon.c new file mode 100644 index 0000000000..2dbc0cb2c6 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_beacon.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212_beacon.c,v 1.6 2008/11/10 04:08:03 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212desc.h" + +/* + * Initialize all of the hardware registers used to + * send beacons. Note that for station operation the + * driver calls ar5212SetStaBeaconTimers instead. + */ +void +ar5212SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt) +{ + + OS_REG_WRITE(ah, AR_TIMER0, bt->bt_nexttbtt); + OS_REG_WRITE(ah, AR_TIMER1, bt->bt_nextdba); + OS_REG_WRITE(ah, AR_TIMER2, bt->bt_nextswba); + OS_REG_WRITE(ah, AR_TIMER3, bt->bt_nextatim); + /* + * Set the Beacon register after setting all timers. + */ + if (bt->bt_intval & AR_BEACON_RESET_TSF) { + /* + * When resetting the TSF, + * write twice to the corresponding register; each + * write to the RESET_TSF bit toggles the internal + * signal to cause a reset of the TSF - but if the signal + * is left high, it will reset the TSF on the next + * chip reset also! writing the bit an even number + * of times fixes this issue + */ + OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_RESET_TSF); + } + OS_REG_WRITE(ah, AR_BEACON, bt->bt_intval); +} + +/* + * Old api for setting up beacon timer registers when + * operating in !station mode. Note the fixed constants + * adjusting the DBA and SWBA timers and the fixed ATIM + * window. + */ +void +ar5212BeaconInit(struct ath_hal *ah, + uint32_t next_beacon, uint32_t beacon_period) +{ + HAL_BEACON_TIMERS bt; + + bt.bt_nexttbtt = next_beacon; + /* + * TIMER1: in AP/adhoc mode this controls the DMA beacon + * alert timer; otherwise it controls the next wakeup time. + * TIMER2: in AP mode, it controls the SBA beacon alert + * interrupt; otherwise it sets the start of the next CFP. + */ + switch (AH_PRIVATE(ah)->ah_opmode) { + case HAL_M_STA: + case HAL_M_MONITOR: + bt.bt_nextdba = 0xffff; + bt.bt_nextswba = 0x7ffff; + break; + case HAL_M_HOSTAP: + case HAL_M_IBSS: + bt.bt_nextdba = (next_beacon - + ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */ + bt.bt_nextswba = (next_beacon - + ath_hal_sw_beacon_response_time) << 3; /* 1/8 TU */ + break; + } + /* + * Set the ATIM window + * Our hardware does not support an ATIM window of 0 + * (beacons will not work). If the ATIM windows is 0, + * force it to 1. + */ + bt.bt_nextatim = next_beacon + 1; + bt.bt_intval = beacon_period & + (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN); + ar5212SetBeaconTimers(ah, &bt); +} + +void +ar5212ResetStaBeaconTimers(struct ath_hal *ah) +{ + uint32_t val; + + OS_REG_WRITE(ah, AR_TIMER0, 0); /* no beacons */ + val = OS_REG_READ(ah, AR_STA_ID1); + val |= AR_STA_ID1_PWR_SAV; /* XXX */ + /* tell the h/w that the associated AP is not PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + val & ~(AR_STA_ID1_USE_DEFANT | AR_STA_ID1_PCF)); + OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_PERIOD); +} + +/* + * Set all the beacon related bits on the h/w for stations + * i.e. initializes the corresponding h/w timers; + * also tells the h/w whether to anticipate PCF beacons + */ +void +ar5212SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t nextTbtt, nextdtim,beaconintval, dtimperiod; + + HALASSERT(bs->bs_intval != 0); + /* if the AP will do PCF */ + if (bs->bs_cfpmaxduration != 0) { + /* tell the h/w that the associated AP is PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + OS_REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PCF); + + /* set CFP_PERIOD(1.024ms) register */ + OS_REG_WRITE(ah, AR_CFP_PERIOD, bs->bs_cfpperiod); + + /* set CFP_DUR(1.024ms) register to max cfp duration */ + OS_REG_WRITE(ah, AR_CFP_DUR, bs->bs_cfpmaxduration); + + /* set TIMER2(128us) to anticipated time of next CFP */ + OS_REG_WRITE(ah, AR_TIMER2, bs->bs_cfpnext << 3); + } else { + /* tell the h/w that the associated AP is not PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + OS_REG_READ(ah, AR_STA_ID1) &~ AR_STA_ID1_PCF); + } + + /* + * Set TIMER0(1.024ms) to the anticipated time of the next beacon. + */ + OS_REG_WRITE(ah, AR_TIMER0, bs->bs_nexttbtt); + + /* + * Start the beacon timers by setting the BEACON register + * to the beacon interval; also write the tim offset which + * we should know by now. The code, in ar5211WriteAssocid, + * also sets the tim offset once the AID is known which can + * be left as such for now. + */ + OS_REG_WRITE(ah, AR_BEACON, + (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_PERIOD|AR_BEACON_TIM)) + | SM(bs->bs_intval, AR_BEACON_PERIOD) + | SM(bs->bs_timoffset ? bs->bs_timoffset + 4 : 0, AR_BEACON_TIM) + ); + + /* + * Configure the BMISS interrupt. Note that we + * assume the caller blocks interrupts while enabling + * the threshold. + */ + HALASSERT(bs->bs_bmissthreshold <= MS(0xffffffff, AR_RSSI_THR_BM_THR)); + ahp->ah_rssiThr = (ahp->ah_rssiThr &~ AR_RSSI_THR_BM_THR) + | SM(bs->bs_bmissthreshold, AR_RSSI_THR_BM_THR); + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); + + /* + * Program the sleep registers to correlate with the beacon setup. + */ + + /* + * Oahu beacons timers on the station were used for power + * save operation (waking up in anticipation of a beacon) + * and any CFP function; Venice does sleep/power-save timers + * differently - so this is the right place to set them up; + * don't think the beacon timers are used by venice sta hw + * for any useful purpose anymore + * Setup venice's sleep related timers + * Current implementation assumes sw processing of beacons - + * assuming an interrupt is generated every beacon which + * causes the hardware to become awake until the sw tells + * it to go to sleep again; beacon timeout is to allow for + * beacon jitter; cab timeout is max time to wait for cab + * after seeing the last DTIM or MORE CAB bit + */ +#define CAB_TIMEOUT_VAL 10 /* in TU */ +#define BEACON_TIMEOUT_VAL 10 /* in TU */ +#define SLEEP_SLOP 3 /* in TU */ + + /* + * For max powersave mode we may want to sleep for longer than a + * beacon period and not want to receive all beacons; modify the + * timers accordingly; make sure to align the next TIM to the + * next DTIM if we decide to wake for DTIMs only + */ + beaconintval = bs->bs_intval & HAL_BEACON_PERIOD; + HALASSERT(beaconintval != 0); + if (bs->bs_sleepduration > beaconintval) { + HALASSERT(roundup(bs->bs_sleepduration, beaconintval) == + bs->bs_sleepduration); + beaconintval = bs->bs_sleepduration; + } + dtimperiod = bs->bs_dtimperiod; + if (bs->bs_sleepduration > dtimperiod) { + HALASSERT(dtimperiod == 0 || + roundup(bs->bs_sleepduration, dtimperiod) == + bs->bs_sleepduration); + dtimperiod = bs->bs_sleepduration; + } + HALASSERT(beaconintval <= dtimperiod); + if (beaconintval == dtimperiod) + nextTbtt = bs->bs_nextdtim; + else + nextTbtt = bs->bs_nexttbtt; + nextdtim = bs->bs_nextdtim; + + OS_REG_WRITE(ah, AR_SLEEP1, + SM((nextdtim - SLEEP_SLOP) << 3, AR_SLEEP1_NEXT_DTIM) + | SM(CAB_TIMEOUT_VAL, AR_SLEEP1_CAB_TIMEOUT) + | AR_SLEEP1_ASSUME_DTIM + | AR_SLEEP1_ENH_SLEEP_ENA + ); + OS_REG_WRITE(ah, AR_SLEEP2, + SM((nextTbtt - SLEEP_SLOP) << 3, AR_SLEEP2_NEXT_TIM) + | SM(BEACON_TIMEOUT_VAL, AR_SLEEP2_BEACON_TIMEOUT) + ); + OS_REG_WRITE(ah, AR_SLEEP3, + SM(beaconintval, AR_SLEEP3_TIM_PERIOD) + | SM(dtimperiod, AR_SLEEP3_DTIM_PERIOD) + ); + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next DTIM %d\n", + __func__, bs->bs_nextdtim); + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next beacon %d\n", + __func__, nextTbtt); + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: beacon period %d\n", + __func__, beaconintval); + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: DTIM period %d\n", + __func__, dtimperiod); +#undef CAB_TIMEOUT_VAL +#undef BEACON_TIMEOUT_VAL +#undef SLEEP_SLOP +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_eeprom.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_eeprom.c new file mode 100644 index 0000000000..d2999fda48 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_eeprom.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212_eeprom.c,v 1.6 2008/11/10 04:08:03 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +#ifdef AH_DEBUG +#include "ah_desc.h" /* NB: for HAL_PHYERR* */ +#endif + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +/* + * Read 16 bits of data from offset into *data + */ +HAL_BOOL +ar5212EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) +{ + OS_REG_WRITE(ah, AR_EEPROM_ADDR, off); + OS_REG_WRITE(ah, AR_EEPROM_CMD, AR_EEPROM_CMD_READ); + + if (!ath_hal_wait(ah, AR_EEPROM_STS, + AR_EEPROM_STS_READ_COMPLETE | AR_EEPROM_STS_READ_ERROR, + AR_EEPROM_STS_READ_COMPLETE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: read failed for entry 0x%x\n", + __func__, off); + return AH_FALSE; + } + *data = OS_REG_READ(ah, AR_EEPROM_DATA) & 0xffff; + return AH_TRUE; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_gpio.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_gpio.c new file mode 100644 index 0000000000..eb0022f16e --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_gpio.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212_gpio.c,v 1.3 2008/11/10 04:08:03 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +#ifdef AH_DEBUG +#include "ah_desc.h" /* NB: for HAL_PHYERR* */ +#endif + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#define AR_NUM_GPIO 6 /* 6 GPIO pins */ +#define AR_GPIOD_MASK 0x0000002F /* GPIO data reg r/w mask */ + +/* + * Configure GPIO Output lines + */ +HAL_BOOL +ar5212GpioCfgOutput(struct ath_hal *ah, uint32_t gpio) +{ + HALASSERT(gpio < AR_NUM_GPIO); + + /* + * NB: AR_GPIOCR_CR_A(pin) is all 1's so there's no need + * to clear the field before or'ing in the new value. + */ + OS_REG_WRITE(ah, AR_GPIOCR, + OS_REG_READ(ah, AR_GPIOCR) | AR_GPIOCR_CR_A(gpio)); + + return AH_TRUE; +} + +/* + * Configure GPIO Input lines + */ +HAL_BOOL +ar5212GpioCfgInput(struct ath_hal *ah, uint32_t gpio) +{ + HALASSERT(gpio < AR_NUM_GPIO); + + OS_REG_WRITE(ah, AR_GPIOCR, + (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_CR_A(gpio)) + | AR_GPIOCR_CR_N(gpio)); + + return AH_TRUE; +} + +/* + * Once configured for I/O - set output lines + */ +HAL_BOOL +ar5212GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) +{ + uint32_t reg; + + HALASSERT(gpio < AR_NUM_GPIO); + + reg = OS_REG_READ(ah, AR_GPIODO); + reg &= ~(1 << gpio); + reg |= (val&1) << gpio; + + OS_REG_WRITE(ah, AR_GPIODO, reg); + return AH_TRUE; +} + +/* + * Once configured for I/O - get input lines + */ +uint32_t +ar5212GpioGet(struct ath_hal *ah, uint32_t gpio) +{ + if (gpio < AR_NUM_GPIO) { + uint32_t val = OS_REG_READ(ah, AR_GPIODI); + val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1; + return val; + } else { + return 0xffffffff; + } +} + +/* + * Set the GPIO Interrupt + */ +void +ar5212GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) +{ + uint32_t val; + + /* XXX bounds check gpio */ + val = OS_REG_READ(ah, AR_GPIOCR); + val &= ~(AR_GPIOCR_CR_A(gpio) | + AR_GPIOCR_INT_MASK | AR_GPIOCR_INT_ENA | AR_GPIOCR_INT_SEL); + val |= AR_GPIOCR_CR_N(gpio) | AR_GPIOCR_INT(gpio) | AR_GPIOCR_INT_ENA; + if (ilevel) + val |= AR_GPIOCR_INT_SELH; /* interrupt on pin high */ + else + val |= AR_GPIOCR_INT_SELL; /* interrupt on pin low */ + + /* Don't need to change anything for low level interrupt. */ + OS_REG_WRITE(ah, AR_GPIOCR, val); + + /* Change the interrupt mask. */ + (void) ar5212SetInterrupts(ah, AH5212(ah)->ah_maskReg | HAL_INT_GPIO); +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_interrupts.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_interrupts.c new file mode 100644 index 0000000000..5d0b39cf9a --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_interrupts.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212_interrupts.c,v 1.6 2008/11/27 22:30:00 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + + +/* + * Checks to see if an interrupt is pending on our NIC + * + * Returns: TRUE if an interrupt is pending + * FALSE if not + */ +HAL_BOOL +ar5212IsInterruptPending(struct ath_hal *ah) +{ + /* + * Some platforms trigger our ISR before applying power to + * the card, so make sure the INTPEND is really 1, not 0xffffffff. + */ + return (OS_REG_READ(ah, AR_INTPEND) == AR_INTPEND_TRUE); +} + +/* + * Reads the Interrupt Status Register value from the NIC, thus deasserting + * the interrupt line, and returns both the masked and unmasked mapped ISR + * values. The value returned is mapped to abstract the hw-specific bit + * locations in the Interrupt Status Register. + * + * Returns: A hardware-abstracted bitmap of all non-masked-out + * interrupts pending, as well as an unmasked value + */ +HAL_BOOL +ar5212GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) +{ + uint32_t isr, isr0, isr1; + uint32_t mask2=0; + struct ath_hal_5212 *ahp = AH5212(ah); + + isr = OS_REG_READ(ah, AR_ISR); + if (isr & AR_ISR_BCNMISC) { + uint32_t isr2; + isr2 = OS_REG_READ(ah, AR_ISR_S2); + if (isr2 & AR_ISR_S2_TIM) + mask2 |= HAL_INT_TIM; + if (isr2 & AR_ISR_S2_DTIM) + mask2 |= HAL_INT_DTIM; + if (isr2 & AR_ISR_S2_DTIMSYNC) + mask2 |= HAL_INT_DTIMSYNC; + if (isr2 & (AR_ISR_S2_CABEND )) + mask2 |= HAL_INT_CABEND; + } + isr = OS_REG_READ(ah, AR_ISR_RAC); + if (isr == 0xffffffff) { + *masked = 0; + return AH_FALSE;; + } + + *masked = isr & HAL_INT_COMMON; + + if (isr & AR_ISR_HIUERR) + *masked |= HAL_INT_FATAL; + if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) + *masked |= HAL_INT_RX; + if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | AR_ISR_TXEOL)) { + *masked |= HAL_INT_TX; + isr0 = OS_REG_READ(ah, AR_ISR_S0_S); + ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXOK); + ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXDESC); + isr1 = OS_REG_READ(ah, AR_ISR_S1_S); + ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXERR); + ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXEOL); + } + + /* + * Receive overrun is usually non-fatal on Oahu/Spirit. + * BUT on some parts rx could fail and the chip must be reset. + * So we force a hardware reset in all cases. + */ + if ((isr & AR_ISR_RXORN) && AH_PRIVATE(ah)->ah_rxornIsFatal) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: receive FIFO overrun interrupt\n", __func__); + *masked |= HAL_INT_FATAL; + } + *masked |= mask2; + + /* + * On fatal errors collect ISR state for debugging. + */ + if (*masked & HAL_INT_FATAL) { + AH_PRIVATE(ah)->ah_fatalState[0] = isr; + AH_PRIVATE(ah)->ah_fatalState[1] = OS_REG_READ(ah, AR_ISR_S0_S); + AH_PRIVATE(ah)->ah_fatalState[2] = OS_REG_READ(ah, AR_ISR_S1_S); + AH_PRIVATE(ah)->ah_fatalState[3] = OS_REG_READ(ah, AR_ISR_S2_S); + AH_PRIVATE(ah)->ah_fatalState[4] = OS_REG_READ(ah, AR_ISR_S3_S); + AH_PRIVATE(ah)->ah_fatalState[5] = OS_REG_READ(ah, AR_ISR_S4_S); + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: fatal error, ISR_RAC=0x%x ISR_S2_S=0x%x\n", + __func__, isr, AH_PRIVATE(ah)->ah_fatalState[3]); + } + return AH_TRUE; +} + +HAL_INT +ar5212GetInterrupts(struct ath_hal *ah) +{ + return AH5212(ah)->ah_maskReg; +} + +/* + * Atomically enables NIC interrupts. Interrupts are passed in + * via the enumerated bitmask in ints. + */ +HAL_INT +ar5212SetInterrupts(struct ath_hal *ah, HAL_INT ints) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t omask = ahp->ah_maskReg; + uint32_t mask,mask2; + + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n", + __func__, omask, ints); + + if (omask & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + (void) OS_REG_READ(ah, AR_IER); /* flush write to HW */ + } + + mask = ints & HAL_INT_COMMON; + mask2 = 0; + if (ints & HAL_INT_TX) { + if (ahp->ah_txOkInterruptMask) + mask |= AR_IMR_TXOK; + if (ahp->ah_txErrInterruptMask) + mask |= AR_IMR_TXERR; + if (ahp->ah_txDescInterruptMask) + mask |= AR_IMR_TXDESC; + if (ahp->ah_txEolInterruptMask) + mask |= AR_IMR_TXEOL; + } + if (ints & HAL_INT_RX) + mask |= AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXDESC; + if (ints & (HAL_INT_BMISC)) { + mask |= AR_IMR_BCNMISC; + if (ints & HAL_INT_TIM) + mask2 |= AR_IMR_S2_TIM; + if (ints & HAL_INT_DTIM) + mask2 |= AR_IMR_S2_DTIM; + if (ints & HAL_INT_DTIMSYNC) + mask2 |= AR_IMR_S2_DTIMSYNC; + if (ints & HAL_INT_CABEND) + mask2 |= (AR_IMR_S2_CABEND ); + } + if (ints & HAL_INT_FATAL) { + /* + * NB: ar5212Reset sets MCABT+SSERR+DPERR in AR_IMR_S2 + * so enabling HIUERR enables delivery. + */ + mask |= AR_IMR_HIUERR; + } + + /* Write the new IMR and store off our SW copy. */ + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask); + OS_REG_WRITE(ah, AR_IMR, mask); + OS_REG_WRITE(ah, AR_IMR_S2, + (OS_REG_READ(ah, AR_IMR_S2) & + ~(AR_IMR_S2_TIM | + AR_IMR_S2_DTIM | + AR_IMR_S2_DTIMSYNC | + AR_IMR_S2_CABEND | + AR_IMR_S2_CABTO | + AR_IMR_S2_TSFOOR ) ) + | mask2); + ahp->ah_maskReg = ints; + + /* Re-enable interrupts if they were enabled before. */ + if (ints & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE); + } + + + return omask; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_keycache.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_keycache.c new file mode 100644 index 0000000000..a1f2dbbf97 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_keycache.c @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212_keycache.c,v 1.4 2008/11/10 04:08:03 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212desc.h" + +/* + * Note: The key cache hardware requires that each double-word + * pair be written in even/odd order (since the destination is + * a 64-bit register). Don't reorder the writes in this code + * w/o considering this! + */ +#define KEY_XOR 0xaa + +#define IS_MIC_ENABLED(ah) \ + (AH5212(ah)->ah_staId1Defaults & AR_STA_ID1_CRPT_MIC_ENABLE) + +/* + * Return the size of the hardware key cache. + */ +uint32_t +ar5212GetKeyCacheSize(struct ath_hal *ah) +{ + return AH_PRIVATE(ah)->ah_caps.halKeyCacheSize; +} + +/* + * Return true if the specific key cache entry is valid. + */ +HAL_BOOL +ar5212IsKeyCacheEntryValid(struct ath_hal *ah, uint16_t entry) +{ + if (entry < AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) { + uint32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry)); + if (val & AR_KEYTABLE_VALID) + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Clear the specified key cache entry and any associated MIC entry. + */ +HAL_BOOL +ar5212ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry) +{ + uint32_t keyType; + + if (entry >= AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n", + __func__, entry); + return AH_FALSE; + } + keyType = OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)); + + /* XXX why not clear key type/valid bit first? */ + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); + if (keyType == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) { + uint16_t micentry = entry+64; /* MIC goes at slot+64 */ + + HALASSERT(micentry < AH_PRIVATE(ah)->ah_caps.halKeyCacheSize); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); + /* NB: key type and MAC are known to be ok */ + } + return AH_TRUE; +} + +/* + * Sets the mac part of the specified key cache entry (and any + * associated MIC entry) and mark them valid. + */ +HAL_BOOL +ar5212SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac) +{ + uint32_t macHi, macLo; + + if (entry >= AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n", + __func__, entry); + return AH_FALSE; + } + /* + * Set MAC address -- shifted right by 1. MacLo is + * the 4 MSBs, and MacHi is the 2 LSBs. + */ + if (mac != AH_NULL) { + macHi = (mac[5] << 8) | mac[4]; + macLo = (mac[3] << 24)| (mac[2] << 16) + | (mac[1] << 8) | mac[0]; + macLo >>= 1; + macLo |= (macHi & 1) << 31; /* carry */ + macHi >>= 1; + } else { + macLo = macHi = 0; + } + OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID); + return AH_TRUE; +} + +/* + * Sets the contents of the specified key cache entry + * and any associated MIC entry. + */ +HAL_BOOL +ar5212SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, + const HAL_KEYVAL *k, const uint8_t *mac, + int xorKey) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + uint32_t key0, key1, key2, key3, key4; + uint32_t keyType; + uint32_t xorMask = xorKey ? + (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0; + + if (entry >= pCap->halKeyCacheSize) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n", + __func__, entry); + return AH_FALSE; + } + switch (k->kv_type) { + case HAL_CIPHER_AES_OCB: + keyType = AR_KEYTABLE_TYPE_AES; + break; + case HAL_CIPHER_AES_CCM: + if (!pCap->halCipherAesCcmSupport) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: AES-CCM not supported by mac rev 0x%x\n", + __func__, AH_PRIVATE(ah)->ah_macRev); + return AH_FALSE; + } + keyType = AR_KEYTABLE_TYPE_CCM; + break; + case HAL_CIPHER_TKIP: + keyType = AR_KEYTABLE_TYPE_TKIP; + if (IS_MIC_ENABLED(ah) && entry+64 >= pCap->halKeyCacheSize) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: entry %u inappropriate for TKIP\n", + __func__, entry); + return AH_FALSE; + } + break; + case HAL_CIPHER_WEP: + if (k->kv_len < 40 / NBBY) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: WEP key length %u too small\n", + __func__, k->kv_len); + return AH_FALSE; + } + if (k->kv_len <= 40 / NBBY) + keyType = AR_KEYTABLE_TYPE_40; + else if (k->kv_len <= 104 / NBBY) + keyType = AR_KEYTABLE_TYPE_104; + else + keyType = AR_KEYTABLE_TYPE_128; + break; + case HAL_CIPHER_CLR: + keyType = AR_KEYTABLE_TYPE_CLR; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cipher %u not supported\n", + __func__, k->kv_type); + return AH_FALSE; + } + + key0 = LE_READ_4(k->kv_val+0) ^ xorMask; + key1 = (LE_READ_2(k->kv_val+4) ^ xorMask) & 0xffff; + key2 = LE_READ_4(k->kv_val+6) ^ xorMask; + key3 = (LE_READ_2(k->kv_val+10) ^ xorMask) & 0xffff; + key4 = LE_READ_4(k->kv_val+12) ^ xorMask; + if (k->kv_len <= 104 / NBBY) + key4 &= 0xff; + + /* + * Note: key cache hardware requires that each double-word + * pair be written in even/odd order (since the destination is + * a 64-bit register). Don't reorder these writes w/o + * considering this! + */ + if (keyType == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) { + uint16_t micentry = entry+64; /* MIC goes at slot+64 */ + uint32_t mic0, mic1, mic2, mic3, mic4; + + /* + * Invalidate the encrypt/decrypt key until the MIC + * key is installed so pending rx frames will fail + * with decrypt errors rather than a MIC error. + */ + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); + (void) ar5212SetKeyCacheEntryMac(ah, entry, mac); + + + /* + * Write MIC entry according to new or old key layout. + * The MISC_MODE register is assumed already set so + * these writes will be handled properly (happens on + * attach and at every reset). + */ + /* RX mic */ + mic0 = LE_READ_4(k->kv_mic+0); + mic2 = LE_READ_4(k->kv_mic+4); + if (ahp->ah_miscMode & AR_MISC_MODE_MIC_NEW_LOC_ENABLE) { + /* + * Both RX and TX mic values can be combined into + * one cache slot entry: + * 8*N + 800 31:0 RX Michael key 0 + * 8*N + 804 15:0 TX Michael key 0 [31:16] + * 8*N + 808 31:0 RX Michael key 1 + * 8*N + 80C 15:0 TX Michael key 0 [15:0] + * 8*N + 810 31:0 TX Michael key 1 + * 8*N + 814 15:0 reserved + * 8*N + 818 31:0 reserved + * 8*N + 81C 14:0 reserved + * 15 key valid == 0 + */ + /* TX mic */ + mic1 = LE_READ_2(k->kv_txmic+2) & 0xffff; + mic3 = LE_READ_2(k->kv_txmic+0) & 0xffff; + mic4 = LE_READ_4(k->kv_txmic+4); + } else { + mic1 = mic3 = mic4 = 0; + } + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), + AR_KEYTABLE_TYPE_CLR); + /* NB: MIC key is not marked valid and has no MAC address */ + OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0); + + /* correct intentionally corrupted key */ + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); + } else { + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); + + (void) ar5212SetKeyCacheEntryMac(ah, entry, mac); + } + return AH_TRUE; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_misc.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_misc.c new file mode 100644 index 0000000000..5f23f92469 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_misc.c @@ -0,0 +1,1075 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: src/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c,v 1.2.2.1.2.1 2009/04/15 03:14:26 kensmith Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +#ifdef AH_DEBUG +#include "ah_desc.h" /* NB: for HAL_PHYERR* */ +#endif + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#include "ah_eeprom_v3.h" + +#define AR_NUM_GPIO 6 /* 6 GPIO pins */ +#define AR_GPIOD_MASK 0x0000002F /* GPIO data reg r/w mask */ + +extern void ar5212SetRateDurationTable(struct ath_hal *, HAL_CHANNEL *); + +void +ar5212GetMacAddress(struct ath_hal *ah, uint8_t *mac) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); +} + +HAL_BOOL +ar5212SetMacAddress(struct ath_hal *ah, const uint8_t *mac) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); + return AH_TRUE; +} + +void +ar5212GetBssIdMask(struct ath_hal *ah, uint8_t *mask) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + OS_MEMCPY(mask, ahp->ah_bssidmask, IEEE80211_ADDR_LEN); +} + +HAL_BOOL +ar5212SetBssIdMask(struct ath_hal *ah, const uint8_t *mask) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + /* save it since it must be rewritten on reset */ + OS_MEMCPY(ahp->ah_bssidmask, mask, IEEE80211_ADDR_LEN); + + OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask)); + OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4)); + return AH_TRUE; +} + +/* + * Attempt to change the cards operating regulatory domain to the given value + */ +HAL_BOOL +ar5212SetRegulatoryDomain(struct ath_hal *ah, + uint16_t regDomain, HAL_STATUS *status) +{ + HAL_STATUS ecode; + + if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { + ecode = HAL_EINVAL; + goto bad; + } + if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { + ecode = HAL_EEWRITE; + goto bad; + } +#ifdef AH_SUPPORT_WRITE_REGDOMAIN + if (ath_hal_eepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: set regulatory domain to %u (0x%x)\n", + __func__, regDomain, regDomain); + AH_PRIVATE(ah)->ah_currentRD = regDomain; + return AH_TRUE; + } +#endif + ecode = HAL_EIO; +bad: + if (status) + *status = ecode; + return AH_FALSE; +} + +/* + * Return the wireless modes (a,b,g,t) supported by hardware. + * + * This value is what is actually supported by the hardware + * and is unaffected by regulatory/country code settings. + */ +u_int +ar5212GetWirelessModes(struct ath_hal *ah) +{ + u_int mode = 0; + + if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { + mode = HAL_MODE_11A; + if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) + mode |= HAL_MODE_TURBO | HAL_MODE_108A; + if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate) + mode |= HAL_MODE_11A_HALF_RATE; + if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate) + mode |= HAL_MODE_11A_QUARTER_RATE; + } + if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) + mode |= HAL_MODE_11B; + if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) && + AH_PRIVATE(ah)->ah_subvendorid != AR_SUBVENDOR_ID_NOG) { + mode |= HAL_MODE_11G; + if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE)) + mode |= HAL_MODE_108G; + if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate) + mode |= HAL_MODE_11G_HALF_RATE; + if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate) + mode |= HAL_MODE_11G_QUARTER_RATE; + } + return mode; +} + +/* + * Set the interrupt and GPIO values so the ISR can disable RF + * on a switch signal. Assumes GPIO port and interrupt polarity + * are set prior to call. + */ +void +ar5212EnableRfKill(struct ath_hal *ah) +{ + uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent; + int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL); + int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY); + + /* + * Configure the desired GPIO port for input + * and enable baseband rf silence. + */ + ath_hal_gpioCfgInput(ah, select); + OS_REG_SET_BIT(ah, AR_PHY(0), 0x00002000); + /* + * If radio disable switch connection to GPIO bit x is enabled + * program GPIO interrupt. + * If rfkill bit on eeprom is 1, setupeeprommap routine has already + * verified that it is a later version of eeprom, it has a place for + * rfkill bit and it is set to 1, indicating that GPIO bit x hardware + * connection is present. + */ + ath_hal_gpioSetIntr(ah, select, + (ath_hal_gpioGet(ah, select) == polarity ? !polarity : polarity)); +} + +/* + * Change the LED blinking pattern to correspond to the connectivity + */ +void +ar5212SetLedState(struct ath_hal *ah, HAL_LED_STATE state) +{ + static const uint32_t ledbits[8] = { + AR_PCICFG_LEDCTL_NONE, /* HAL_LED_INIT */ + AR_PCICFG_LEDCTL_PEND, /* HAL_LED_SCAN */ + AR_PCICFG_LEDCTL_PEND, /* HAL_LED_AUTH */ + AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_ASSOC*/ + AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_RUN */ + AR_PCICFG_LEDCTL_NONE, + AR_PCICFG_LEDCTL_NONE, + AR_PCICFG_LEDCTL_NONE, + }; + uint32_t bits; + + bits = OS_REG_READ(ah, AR_PCICFG); + if (IS_2417(ah)) { + /* + * Enable LED for Nala. There is a bit marked reserved + * that must be set and we also turn on the power led. + * Because we mark s/w LED control setting the control + * status bits below is meangless (the driver must flash + * the LED(s) using the GPIO lines). + */ + bits = (bits &~ AR_PCICFG_LEDMODE) + | SM(AR_PCICFG_LEDMODE_POWON, AR_PCICFG_LEDMODE) +#if 0 + | SM(AR_PCICFG_LEDMODE_NETON, AR_PCICFG_LEDMODE) +#endif + | 0x08000000; + } + bits = (bits &~ AR_PCICFG_LEDCTL) + | SM(ledbits[state & 0x7], AR_PCICFG_LEDCTL); + OS_REG_WRITE(ah, AR_PCICFG, bits); +} + +/* + * Change association related fields programmed into the hardware. + * Writing a valid BSSID to the hardware effectively enables the hardware + * to synchronize its TSF to the correct beacons and receive frames coming + * from that BSSID. It is called by the SME JOIN operation. + */ +void +ar5212WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + /* XXX save bssid for possible re-use on reset */ + OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); + OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); + OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | + ((assocId & 0x3fff)<ah_curchan; + uint32_t reg; + uint8_t xset; + int i; + + if (chan == AH_NULL || !IS_CHAN_CCK(chan)) + return; + xset = 0; + for (i = 0; i < rs->rs_count; i++) { + uint8_t rset = rs->rs_rates[i]; + /* Basic rate defined? */ + if ((rset & 0x80) && (rset &= 0x7f) >= xset) + xset = rset; + } + /* + * Set the h/w bit to reflect whether or not the basic + * rate is found to be equal or less than 2Mbps. + */ + reg = OS_REG_READ(ah, AR_STA_ID1); + if (xset && xset/2 <= 2) + OS_REG_WRITE(ah, AR_STA_ID1, reg | AR_STA_ID1_BASE_RATE_11B); + else + OS_REG_WRITE(ah, AR_STA_ID1, reg &~ AR_STA_ID1_BASE_RATE_11B); +} + +/* + * Grab a semi-random value from hardware registers - may not + * change often + */ +uint32_t +ar5212GetRandomSeed(struct ath_hal *ah) +{ + uint32_t nf; + + nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff; + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + return (OS_REG_READ(ah, AR_TSF_U32) ^ + OS_REG_READ(ah, AR_TSF_L32) ^ nf); +} + +/* + * Detect if our card is present + */ +HAL_BOOL +ar5212DetectCardPresent(struct ath_hal *ah) +{ + uint16_t macVersion, macRev; + uint32_t v; + + /* + * Read the Silicon Revision register and compare that + * to what we read at attach time. If the same, we say + * a card/device is present. + */ + v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID; + macVersion = v >> AR_SREV_ID_S; + macRev = v & AR_SREV_REVISION; + return (AH_PRIVATE(ah)->ah_macVersion == macVersion && + AH_PRIVATE(ah)->ah_macRev == macRev); +} + +void +ar5212EnableMibCounters(struct ath_hal *ah) +{ + /* NB: this just resets the mib counter machinery */ + OS_REG_WRITE(ah, AR_MIBC, + ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) & 0x0f); +} + +void +ar5212DisableMibCounters(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_MIBC, AR_MIBC | AR_MIBC_CMC); +} + +/* + * Update MIB Counters + */ +void +ar5212UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS* stats) +{ + stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); + stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); + stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); + stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); + stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); +} + +/* + * Detect if the HW supports spreading a CCK signal on channel 14 + */ +HAL_BOOL +ar5212IsJapanChannelSpreadSupported(struct ath_hal *ah) +{ + return AH_TRUE; +} + +/* + * Get the rssi of frame curently being received. + */ +uint32_t +ar5212GetCurRssi(struct ath_hal *ah) +{ + return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff); +} + +u_int +ar5212GetDefAntenna(struct ath_hal *ah) +{ + return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7); +} + +void +ar5212SetDefAntenna(struct ath_hal *ah, u_int antenna) +{ + OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); +} + +HAL_ANT_SETTING +ar5212GetAntennaSwitch(struct ath_hal *ah) +{ + return AH5212(ah)->ah_antControl; +} + +HAL_BOOL +ar5212SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING setting) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_CHANNEL_INTERNAL *ichan = AH_PRIVATE(ah)->ah_curchan; + + if (!ahp->ah_phyPowerOn || ichan == AH_NULL) { + /* PHY powered off, just stash settings */ + ahp->ah_antControl = setting; + ahp->ah_diversity = (setting == HAL_ANT_VARIABLE); + return AH_TRUE; + } + return ar5212SetAntennaSwitchInternal(ah, setting, ichan); +} + +HAL_BOOL +ar5212IsSleepAfterBeaconBroken(struct ath_hal *ah) +{ + return AH_TRUE; +} + +HAL_BOOL +ar5212SetSifsTime(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + if (us > ath_hal_mac_usec(ah, 0xffff)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n", + __func__, us); + ahp->ah_sifstime = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us)); + ahp->ah_slottime = us; + return AH_TRUE; + } +} + +u_int +ar5212GetSifsTime(struct ath_hal *ah) +{ + u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff; + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +HAL_BOOL +ar5212SetSlotTime(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + if (us < HAL_SLOT_TIME_6 || us > ath_hal_mac_usec(ah, 0xffff)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n", + __func__, us); + ahp->ah_slottime = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us)); + ahp->ah_slottime = us; + return AH_TRUE; + } +} + +u_int +ar5212GetSlotTime(struct ath_hal *ah) +{ + u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff; + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +HAL_BOOL +ar5212SetAckTimeout(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n", + __func__, us); + ahp->ah_acktimeout = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_RMW_FIELD(ah, AR_TIME_OUT, + AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us)); + ahp->ah_acktimeout = us; + return AH_TRUE; + } +} + +u_int +ar5212GetAckTimeout(struct ath_hal *ah) +{ + u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +u_int +ar5212GetAckCTSRate(struct ath_hal *ah) +{ + return ((AH5212(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0); +} + +HAL_BOOL +ar5212SetAckCTSRate(struct ath_hal *ah, u_int high) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + if (high) { + OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); + ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB; + } else { + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); + ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB; + } + return AH_TRUE; +} + +HAL_BOOL +ar5212SetCTSTimeout(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n", + __func__, us); + ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_RMW_FIELD(ah, AR_TIME_OUT, + AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); + ahp->ah_ctstimeout = us; + return AH_TRUE; + } +} + +u_int +ar5212GetCTSTimeout(struct ath_hal *ah) +{ + u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +/* Setup decompression for given key index */ +HAL_BOOL +ar5212SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + if (keyidx >= HAL_DECOMP_MASK_SIZE) + return HAL_EINVAL; + OS_REG_WRITE(ah, AR_DCM_A, keyidx); + OS_REG_WRITE(ah, AR_DCM_D, en ? AR_DCM_D_EN : 0); + ahp->ah_decompMask[keyidx] = en; + + return AH_TRUE; +} + +/* Setup coverage class */ +void +ar5212SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) +{ + uint32_t slot, timeout, eifs; + u_int clkRate; + + AH_PRIVATE(ah)->ah_coverageClass = coverageclass; + + if (now) { + if (AH_PRIVATE(ah)->ah_coverageClass == 0) + return; + + /* Don't apply coverage class to non A channels */ + if (!IS_CHAN_A(AH_PRIVATE(ah)->ah_curchan)) + return; + + /* Get core clock rate */ + clkRate = ath_hal_mac_clks(ah, 1); + + /* Compute EIFS */ + slot = coverageclass * 3 * clkRate; + eifs = coverageclass * 6 * clkRate; + if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) { + slot += IFS_SLOT_HALF_RATE; + eifs += IFS_EIFS_HALF_RATE; + } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) { + slot += IFS_SLOT_QUARTER_RATE; + eifs += IFS_EIFS_QUARTER_RATE; + } else { /* full rate */ + slot += IFS_SLOT_FULL_RATE; + eifs += IFS_EIFS_FULL_RATE; + } + + /* + * Add additional time for air propagation for ACK and CTS + * timeouts. This value is in core clocks. + */ + timeout = ACK_CTS_TIMEOUT_11A + (coverageclass * 3 * clkRate); + + /* + * Write the values: slot, eifs, ack/cts timeouts. + */ + OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot); + OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs); + OS_REG_WRITE(ah, AR_TIME_OUT, + SM(timeout, AR_TIME_OUT_CTS) + | SM(timeout, AR_TIME_OUT_ACK)); + } +} + +void +ar5212SetPCUConfig(struct ath_hal *ah) +{ + ar5212SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode); +} + +/* + * Return whether an external 32KHz crystal should be used + * to reduce power consumption when sleeping. We do so if + * the crystal is present (obtained from EEPROM) and if we + * are not running as an AP and are configured to use it. + */ +HAL_BOOL +ar5212Use32KHzclock(struct ath_hal *ah, HAL_OPMODE opmode) +{ + if (opmode != HAL_M_HOSTAP) { + struct ath_hal_5212 *ahp = AH5212(ah); + return ath_hal_eepromGetFlag(ah, AR_EEP_32KHZCRYSTAL) && + (ahp->ah_enable32kHzClock == USE_32KHZ || + ahp->ah_enable32kHzClock == AUTO_32KHZ); + } else + return AH_FALSE; +} + +/* + * If 32KHz clock exists, use it to lower power consumption during sleep + * + * Note: If clock is set to 32 KHz, delays on accessing certain + * baseband registers (27-31, 124-127) are required. + */ +void +ar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode) +{ + if (ar5212Use32KHzclock(ah, opmode)) { + /* + * Enable clocks to be turned OFF in BB during sleep + * and also enable turning OFF 32MHz/40MHz Refclk + * from A2. + */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18); + OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1); + OS_REG_WRITE(ah, AR_TSF_PARM, 61); /* 32 KHz TSF incr */ + OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 1); + + if (IS_2413(ah) || IS_5413(ah) || IS_2417(ah)) { + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x26); + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0d); + OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x07); + OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x3f); + /* # Set sleep clock rate to 32 KHz. */ + OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x2); + } else { + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x0a); + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0c); + OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x03); + OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x20); + OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x3); + } + } else { + OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x0); + OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0); + + OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32MHz TSF inc */ + + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); + + if (IS_2417(ah)) + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0a); + else if (IS_HB63(ah)) + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x32); + else + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); + OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); + OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2417(ah) ? 0x14 : 0x18); + OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, + IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31); + } +} + +/* + * If 32KHz clock exists, turn it off and turn back on the 32Mhz + */ +void +ar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode) +{ + if (ar5212Use32KHzclock(ah, opmode)) { + /* # Set sleep clock rate back to 32 MHz. */ + OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0); + OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0); + + OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */ + OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, + IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31); + + /* + * Restore BB registers to power-on defaults + */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); + OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); + OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18); + } +} + +/* + * Adjust NF based on statistical values for 5GHz frequencies. + * Default method: this may be overridden by the rf backend. + */ +int16_t +ar5212GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) +{ + static const struct { + uint16_t freqLow; + int16_t adjust; + } adjustDef[] = { + { 5790, 11 }, /* NB: ordered high -> low */ + { 5730, 10 }, + { 5690, 9 }, + { 5660, 8 }, + { 5610, 7 }, + { 5530, 5 }, + { 5450, 4 }, + { 5379, 2 }, + { 5209, 0 }, + { 3000, 1 }, + { 0, 0 }, + }; + int i; + + for (i = 0; c->channel <= adjustDef[i].freqLow; i++) + ; + return adjustDef[i].adjust; +} + +HAL_STATUS +ar5212GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t *result) +{ +#define MACVERSION(ah) AH_PRIVATE(ah)->ah_macVersion + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + const struct ar5212AniState *ani; + + switch (type) { + case HAL_CAP_CIPHER: /* cipher handled in hardware */ + switch (capability) { + case HAL_CIPHER_AES_CCM: + return pCap->halCipherAesCcmSupport ? + HAL_OK : HAL_ENOTSUPP; + case HAL_CIPHER_AES_OCB: + case HAL_CIPHER_TKIP: + case HAL_CIPHER_WEP: + case HAL_CIPHER_MIC: + case HAL_CIPHER_CLR: + return HAL_OK; + default: + return HAL_ENOTSUPP; + } + case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ + switch (capability) { + case 0: /* hardware capability */ + return HAL_OK; + case 1: + return (ahp->ah_staId1Defaults & + AR_STA_ID1_CRPT_MIC_ENABLE) ? HAL_OK : HAL_ENXIO; + } + return HAL_EINVAL; + case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ + switch (capability) { + case 0: /* hardware capability */ + return pCap->halTkipMicTxRxKeySupport ? + HAL_ENXIO : HAL_OK; + case 1: /* current setting */ + return (ahp->ah_miscMode & + AR_MISC_MODE_MIC_NEW_LOC_ENABLE) ? HAL_ENXIO : HAL_OK; + } + return HAL_EINVAL; + case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC w/ WMM */ + /* XXX move to capability bit */ + return MACVERSION(ah) > AR_SREV_VERSION_VENICE || + (MACVERSION(ah) == AR_SREV_VERSION_VENICE && + AH_PRIVATE(ah)->ah_macRev >= 8) ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */ + switch (capability) { + case 0: /* hardware capability */ + return HAL_OK; + case 1: /* current setting */ + return ahp->ah_diversity ? HAL_OK : HAL_ENXIO; + } + return HAL_EINVAL; + case HAL_CAP_DIAG: + *result = AH_PRIVATE(ah)->ah_diagreg; + return HAL_OK; + case HAL_CAP_TPC: + switch (capability) { + case 0: /* hardware capability */ + return HAL_OK; + case 1: + return ahp->ah_tpcEnabled ? HAL_OK : HAL_ENXIO; + } + return HAL_OK; + case HAL_CAP_PHYDIAG: /* radar pulse detection capability */ + switch (capability) { + case HAL_CAP_RADAR: + return ath_hal_eepromGetFlag(ah, AR_EEP_AMODE) ? + HAL_OK: HAL_ENXIO; + case HAL_CAP_AR: + return (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) || + ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) ? + HAL_OK: HAL_ENXIO; + } + return HAL_ENXIO; + case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ + switch (capability) { + case 0: /* hardware capability */ + return HAL_OK; + case 1: + return (ahp->ah_staId1Defaults & + AR_STA_ID1_MCAST_KSRCH) ? HAL_OK : HAL_ENXIO; + } + return HAL_EINVAL; + case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ + switch (capability) { + case 0: /* hardware capability */ + return pCap->halTsfAddSupport ? HAL_OK : HAL_ENOTSUPP; + case 1: + return (ahp->ah_miscMode & AR_MISC_MODE_TX_ADD_TSF) ? + HAL_OK : HAL_ENXIO; + } + return HAL_EINVAL; + case HAL_CAP_TPC_ACK: + *result = MS(ahp->ah_macTPC, AR_TPC_ACK); + return HAL_OK; + case HAL_CAP_TPC_CTS: + *result = MS(ahp->ah_macTPC, AR_TPC_CTS); + return HAL_OK; + case HAL_CAP_INTMIT: /* interference mitigation */ + switch (capability) { + case 0: /* hardware capability */ + return HAL_OK; + case 1: + return (ahp->ah_procPhyErr & HAL_ANI_ENA) ? + HAL_OK : HAL_ENXIO; + case 2: /* HAL_ANI_NOISE_IMMUNITY_LEVEL */ + case 3: /* HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION */ + case 4: /* HAL_ANI_CCK_WEAK_SIGNAL_THR */ + case 5: /* HAL_ANI_FIRSTEP_LEVEL */ + case 6: /* HAL_ANI_SPUR_IMMUNITY_LEVEL */ + ani = ar5212AniGetCurrentState(ah); + if (ani == AH_NULL) + return HAL_ENXIO; + switch (capability) { + case 2: *result = ani->noiseImmunityLevel; break; + case 3: *result = !ani->ofdmWeakSigDetectOff; break; + case 4: *result = ani->cckWeakSigThreshold; break; + case 5: *result = ani->firstepLevel; break; + case 6: *result = ani->spurImmunityLevel; break; + } + return HAL_OK; + } + return HAL_EINVAL; + default: + return ath_hal_getcapability(ah, type, capability, result); + } +#undef MACVERSION +} + +HAL_BOOL +ar5212SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t setting, HAL_STATUS *status) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + uint32_t v; + + switch (type) { + case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ + if (setting) + ahp->ah_staId1Defaults |= AR_STA_ID1_CRPT_MIC_ENABLE; + else + ahp->ah_staId1Defaults &= ~AR_STA_ID1_CRPT_MIC_ENABLE; + return AH_TRUE; + case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ + if (!pCap->halTkipMicTxRxKeySupport) + return AH_FALSE; + /* NB: true =>'s use split key cache layout */ + if (setting) + ahp->ah_miscMode &= ~AR_MISC_MODE_MIC_NEW_LOC_ENABLE; + else + ahp->ah_miscMode |= AR_MISC_MODE_MIC_NEW_LOC_ENABLE; + /* NB: write here so keys can be setup w/o a reset */ + OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + return AH_TRUE; + case HAL_CAP_DIVERSITY: + if (ahp->ah_phyPowerOn) { + v = OS_REG_READ(ah, AR_PHY_CCK_DETECT); + if (setting) + v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; + else + v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; + OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, v); + } + ahp->ah_diversity = (setting != 0); + return AH_TRUE; + case HAL_CAP_DIAG: /* hardware diagnostic support */ + /* + * NB: could split this up into virtual capabilities, + * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly + * seems worth the additional complexity. + */ + AH_PRIVATE(ah)->ah_diagreg = setting; + OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); + return AH_TRUE; + case HAL_CAP_TPC: + ahp->ah_tpcEnabled = (setting != 0); + return AH_TRUE; + case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ + if (setting) + ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH; + else + ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH; + return AH_TRUE; + case HAL_CAP_TPC_ACK: + case HAL_CAP_TPC_CTS: + setting += ahp->ah_txPowerIndexOffset; + if (setting > 63) + setting = 63; + if (type == HAL_CAP_TPC_ACK) { + ahp->ah_macTPC &= AR_TPC_ACK; + ahp->ah_macTPC |= MS(setting, AR_TPC_ACK); + } else { + ahp->ah_macTPC &= AR_TPC_CTS; + ahp->ah_macTPC |= MS(setting, AR_TPC_CTS); + } + OS_REG_WRITE(ah, AR_TPC, ahp->ah_macTPC); + return AH_TRUE; + case HAL_CAP_INTMIT: { /* interference mitigation */ + static const HAL_ANI_CMD cmds[] = { + HAL_ANI_PRESENT, + HAL_ANI_MODE, + HAL_ANI_NOISE_IMMUNITY_LEVEL, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + HAL_ANI_CCK_WEAK_SIGNAL_THR, + HAL_ANI_FIRSTEP_LEVEL, + HAL_ANI_SPUR_IMMUNITY_LEVEL, + }; + return capability < N(cmds) ? + ar5212AniControl(ah, cmds[capability], setting) : + AH_FALSE; + } + case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ + if (pCap->halTsfAddSupport) { + if (setting) + ahp->ah_miscMode |= AR_MISC_MODE_TX_ADD_TSF; + else + ahp->ah_miscMode &= ~AR_MISC_MODE_TX_ADD_TSF; + return AH_TRUE; + } + /* fall thru... */ + default: + return ath_hal_setcapability(ah, type, capability, + setting, status); + } +#undef N +} + +HAL_BOOL +ar5212GetDiagState(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + (void) ahp; + if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) + return AH_TRUE; + switch (request) { + case HAL_DIAG_EEPROM: + case HAL_DIAG_EEPROM_EXP_11A: + case HAL_DIAG_EEPROM_EXP_11B: + case HAL_DIAG_EEPROM_EXP_11G: + case HAL_DIAG_RFGAIN: + return ath_hal_eepromDiag(ah, request, + args, argsize, result, resultsize); + case HAL_DIAG_RFGAIN_CURSTEP: + *result = __DECONST(void *, ahp->ah_gainValues.currStep); + *resultsize = (*result == AH_NULL) ? + 0 : sizeof(GAIN_OPTIMIZATION_STEP); + return AH_TRUE; + case HAL_DIAG_PCDAC: + *result = ahp->ah_pcdacTable; + *resultsize = ahp->ah_pcdacTableSize; + return AH_TRUE; + case HAL_DIAG_TXRATES: + *result = &ahp->ah_ratesArray[0]; + *resultsize = sizeof(ahp->ah_ratesArray); + return AH_TRUE; + case HAL_DIAG_ANI_CURRENT: + *result = ar5212AniGetCurrentState(ah); + *resultsize = (*result == AH_NULL) ? + 0 : sizeof(struct ar5212AniState); + return AH_TRUE; + case HAL_DIAG_ANI_STATS: + *result = ar5212AniGetCurrentStats(ah); + *resultsize = (*result == AH_NULL) ? + 0 : sizeof(struct ar5212Stats); + return AH_TRUE; + case HAL_DIAG_ANI_CMD: + if (argsize != 2*sizeof(uint32_t)) + return AH_FALSE; + ar5212AniControl(ah, ((const uint32_t *)args)[0], + ((const uint32_t *)args)[1]); + return AH_TRUE; + case HAL_DIAG_ANI_PARAMS: + /* + * NB: We assume struct ar5212AniParams is identical + * to HAL_ANI_PARAMS; if they diverge then we'll need + * to handle it here + */ + if (argsize == 0 && args == AH_NULL) { + struct ar5212AniState *aniState = + ar5212AniGetCurrentState(ah); + if (aniState == AH_NULL) + return AH_FALSE; + *result = __DECONST(void *, aniState->params); + *resultsize = sizeof(struct ar5212AniParams); + return AH_TRUE; + } else { + if (argsize != sizeof(struct ar5212AniParams)) + return AH_FALSE; + return ar5212AniSetParams(ah, args, args); + } + } + return AH_FALSE; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_phy.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_phy.c new file mode 100644 index 0000000000..96e67254cb --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_phy.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212_phy.c,v 1.5 2008/11/15 03:43:53 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" + +/* shorthands to compact tables for readability */ +#define OFDM IEEE80211_T_OFDM +#define CCK IEEE80211_T_CCK +#define TURBO IEEE80211_T_TURBO + +HAL_RATE_TABLE ar5212_11a_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80|12), 0 }, +/* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 0 }, +/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, (0x80|48), 4 }, +/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 4 }, +/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 4 }, +/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 4 } + }, +}; + +HAL_RATE_TABLE ar5212_half_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, OFDM, 3000, 0x0b, 0x00, (0x80|6), 0 }, +/* 9 Mb */ { AH_TRUE, OFDM, 4500, 0x0f, 0x00, 9, 0 }, +/* 12 Mb */ { AH_TRUE, OFDM, 6000, 0x0a, 0x00, (0x80|12), 2 }, +/* 18 Mb */ { AH_TRUE, OFDM, 9000, 0x0e, 0x00, 18, 2 }, +/* 24 Mb */ { AH_TRUE, OFDM, 12000, 0x09, 0x00, (0x80|24), 4 }, +/* 36 Mb */ { AH_TRUE, OFDM, 18000, 0x0d, 0x00, 36, 4 }, +/* 48 Mb */ { AH_TRUE, OFDM, 24000, 0x08, 0x00, 48, 4 }, +/* 54 Mb */ { AH_TRUE, OFDM, 27000, 0x0c, 0x00, 54, 4 } + }, +}; + +HAL_RATE_TABLE ar5212_quarter_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, OFDM, 1500, 0x0b, 0x00, (0x80|3), 0 }, +/* 9 Mb */ { AH_TRUE, OFDM, 2250, 0x0f, 0x00, 4, 0 }, +/* 12 Mb */ { AH_TRUE, OFDM, 3000, 0x0a, 0x00, (0x80|6), 2 }, +/* 18 Mb */ { AH_TRUE, OFDM, 4500, 0x0e, 0x00, 9, 2 }, +/* 24 Mb */ { AH_TRUE, OFDM, 6000, 0x09, 0x00, (0x80|12), 4 }, +/* 36 Mb */ { AH_TRUE, OFDM, 9000, 0x0d, 0x00, 18, 4 }, +/* 48 Mb */ { AH_TRUE, OFDM, 12000, 0x08, 0x00, 24, 4 }, +/* 54 Mb */ { AH_TRUE, OFDM, 13500, 0x0c, 0x00, 27, 4 } + }, +}; + +HAL_RATE_TABLE ar5212_turbog_table = { + 7, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, TURBO, 6000, 0x0b, 0x00, (0x80|12), 0 }, +/* 12 Mb */ { AH_TRUE, TURBO, 12000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, TURBO, 18000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, TURBO, 24000, 0x09, 0x00, (0x80|48), 3 }, +/* 36 Mb */ { AH_TRUE, TURBO, 36000, 0x0d, 0x00, 72, 3 }, +/* 48 Mb */ { AH_TRUE, TURBO, 48000, 0x08, 0x00, 96, 3 }, +/* 54 Mb */ { AH_TRUE, TURBO, 54000, 0x0c, 0x00, 108, 3 } + }, +}; + +HAL_RATE_TABLE ar5212_turboa_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, TURBO, 6000, 0x0b, 0x00, (0x80|12), 0 }, +/* 9 Mb */ { AH_TRUE, TURBO, 9000, 0x0f, 0x00, 18, 0 }, +/* 12 Mb */ { AH_TRUE, TURBO, 12000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, TURBO, 18000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, TURBO, 24000, 0x09, 0x00, (0x80|48), 4 }, +/* 36 Mb */ { AH_TRUE, TURBO, 36000, 0x0d, 0x00, 72, 4 }, +/* 48 Mb */ { AH_TRUE, TURBO, 48000, 0x08, 0x00, 96, 4 }, +/* 54 Mb */ { AH_TRUE, TURBO, 54000, 0x0c, 0x00, 108, 4 } + }, +}; + +HAL_RATE_TABLE ar5212_11b_table = { + 4, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80| 2), 0 }, +/* 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80| 4), 1 }, +/* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80|11), 1 }, +/* 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80|22), 1 } + }, +}; + + +/* Venice TODO: roundUpRate() is broken when the rate table does not represent rates + * in increasing order e.g. 5.5, 11, 6, 9. + * An average rate of 6 Mbps will currently map to 11 Mbps. + */ +HAL_RATE_TABLE ar5212_11g_table = { + 12, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80| 2), 0 }, +/* 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80| 4), 1 }, +/* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80|11), 2 }, +/* 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80|22), 3 }, +/* remove rates 6, 9 from rate ctrl */ +/* 6 Mb */ { AH_FALSE, OFDM, 6000, 0x0b, 0x00, 12, 4 }, +/* 9 Mb */ { AH_FALSE, OFDM, 9000, 0x0f, 0x00, 18, 4 }, +/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, 24, 6 }, +/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 6 }, +/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, 48, 8 }, +/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 8 }, +/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 8 }, +/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 8 } + }, +}; + +#undef OFDM +#undef CCK +#undef TURBO +#undef XR + +const HAL_RATE_TABLE * +ar5212GetRateTable(struct ath_hal *ah, u_int mode) +{ + HAL_RATE_TABLE *rt; + switch (mode) { + case HAL_MODE_11A: + rt = &ar5212_11a_table; + break; + case HAL_MODE_11B: + rt = &ar5212_11b_table; + break; + case HAL_MODE_11G: +#ifdef notdef + case HAL_MODE_PUREG: +#endif + rt = &ar5212_11g_table; + break; + case HAL_MODE_108A: + case HAL_MODE_TURBO: + rt = &ar5212_turboa_table; + break; + case HAL_MODE_108G: + rt = &ar5212_turbog_table; + break; + case HAL_MODE_11A_HALF_RATE: + case HAL_MODE_11G_HALF_RATE: + rt = &ar5212_half_table; + break; + case HAL_MODE_11A_QUARTER_RATE: + case HAL_MODE_11G_QUARTER_RATE: + rt = &ar5212_quarter_table; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", + __func__, mode); + return AH_NULL; + } + ath_hal_setupratetable(ah, rt); + return rt; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_power.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_power.c new file mode 100644 index 0000000000..aca52adf79 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_power.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212_power.c,v 1.4 2008/11/10 04:08:03 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212desc.h" + +/* + * Notify Power Mgt is enabled in self-generated frames. + * If requested, force chip awake. + * + * Returns A_OK if chip is awake or successfully forced awake. + * + * WARNING WARNING WARNING + * There is a problem with the chip where sometimes it will not wake up. + */ +static HAL_BOOL +ar5212SetPowerModeAwake(struct ath_hal *ah, int setChip) +{ +#define AR_SCR_MASK \ + (AR_SCR_SLDUR|AR_SCR_SLE|AR_SCR_SLE|AR_SCR_SLDTP|AR_SCR_SLDWP|\ + AR_SCR_SLEPOL|AR_SCR_MIBIE) +#define POWER_UP_TIME 2000 + uint32_t scr, val; + int i; + + if (setChip) { + /* + * Be careful setting the AWAKE mode. When we are called + * with the chip powered down the read returns 0xffffffff + * which when blindly written back with OS_REG_RMW_FIELD + * enables the MIB interrupt for the sleep performance + * counters. This can result in an interrupt storm when + * ANI is in operation as noone knows to turn off the MIB + * interrupt cause. + */ + scr = OS_REG_READ(ah, AR_SCR); + if (scr & ~AR_SCR_MASK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: bogus SCR 0x%x, PCICFG 0x%x\n", + __func__, scr, OS_REG_READ(ah, AR_PCICFG)); + scr = 0; + } + scr = (scr &~ AR_SCR_SLE) | AR_SCR_SLE_WAKE; + OS_REG_WRITE(ah, AR_SCR, scr); + OS_DELAY(10); /* Give chip the chance to awake */ + + for (i = POWER_UP_TIME / 50; i != 0; i--) { + val = OS_REG_READ(ah, AR_PCICFG); + if ((val & AR_PCICFG_SPWR_DN) == 0) + break; + OS_DELAY(50); + OS_REG_WRITE(ah, AR_SCR, scr); + } + if (i == 0) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n", + __func__, POWER_UP_TIME/50); +#endif + return AH_FALSE; + } + } + + OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + return AH_TRUE; +#undef POWER_UP_TIME +#undef AR_SCR_MASK +} + +/* + * Notify Power Mgt is disabled in self-generated frames. + * If requested, force chip to sleep. + */ +static void +ar5212SetPowerModeSleep(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + if (setChip) + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_SLP); +} + +/* + * Notify Power Management is enabled in self-generating + * fames. If request, set power mode of chip to + * auto/normal. Duration in units of 128us (1/8 TU). + */ +static void +ar5212SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + if (setChip) + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_NORM); +} + +/* + * Set power mgt to the requested mode, and conditionally set + * the chip as well + */ +HAL_BOOL +ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) +{ + struct ath_hal_5212 *ahp = AH5212(ah); +#ifdef AH_DEBUG + static const char* modes[] = { + "AWAKE", + "FULL-SLEEP", + "NETWORK SLEEP", + "UNDEFINED" + }; +#endif + int status = AH_TRUE; + + HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__, + modes[ahp->ah_powerMode], modes[mode], + setChip ? "set chip " : ""); + switch (mode) { + case HAL_PM_AWAKE: + status = ar5212SetPowerModeAwake(ah, setChip); + break; + case HAL_PM_FULL_SLEEP: + ar5212SetPowerModeSleep(ah, setChip); + break; + case HAL_PM_NETWORK_SLEEP: + ar5212SetPowerModeNetworkSleep(ah, setChip); + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n", + __func__, mode); + return AH_FALSE; + } + ahp->ah_powerMode = mode; + return status; +} + +/* + * Return the current sleep mode of the chip + */ +HAL_POWER_MODE +ar5212GetPowerMode(struct ath_hal *ah) +{ + /* Just so happens the h/w maps directly to the abstracted value */ + return MS(OS_REG_READ(ah, AR_SCR), AR_SCR_SLE); +} + +#if 0 +/* + * Return the current sleep state of the chip + * TRUE = sleeping + */ +HAL_BOOL +ar5212GetPowerStatus(struct ath_hal *ah) +{ + return (OS_REG_READ(ah, AR_PCICFG) & AR_PCICFG_SPWR_DN) != 0; +} +#endif diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_recv.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_recv.c new file mode 100644 index 0000000000..22bc1128e3 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_recv.c @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212_recv.c,v 1.4 2008/11/10 04:08:03 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212desc.h" + +/* + * Get the RXDP. + */ +uint32_t +ar5212GetRxDP(struct ath_hal *ath) +{ + return OS_REG_READ(ath, AR_RXDP); +} + +/* + * Set the RxDP. + */ +void +ar5212SetRxDP(struct ath_hal *ah, uint32_t rxdp) +{ + OS_REG_WRITE(ah, AR_RXDP, rxdp); + HALASSERT(OS_REG_READ(ah, AR_RXDP) == rxdp); +} + +/* + * Set Receive Enable bits. + */ +void +ar5212EnableReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_CR, AR_CR_RXE); +} + +/* + * Stop Receive at the DMA engine + */ +HAL_BOOL +ar5212StopDmaReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */ + if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0)) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: dma failed to stop in 10ms\n" + "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n", + __func__, + OS_REG_READ(ah, AR_CR), + OS_REG_READ(ah, AR_DIAG_SW)); +#endif + return AH_FALSE; + } else { + return AH_TRUE; + } +} + +/* + * Start Transmit at the PCU engine (unpause receive) + */ +void +ar5212StartPcuReceive(struct ath_hal *ah) +{ + struct ath_hal_private *ahp = AH_PRIVATE(ah); + + OS_REG_WRITE(ah, AR_DIAG_SW, + OS_REG_READ(ah, AR_DIAG_SW) &~ AR_DIAG_RX_DIS); + ar5212EnableMibCounters(ah); + /* NB: restore current settings */ + ar5212AniReset(ah, ahp->ah_curchan, ahp->ah_opmode, AH_TRUE); +} + +/* + * Stop Transmit at the PCU engine (pause receive) + */ +void +ar5212StopPcuReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_DIAG_SW, + OS_REG_READ(ah, AR_DIAG_SW) | AR_DIAG_RX_DIS); + ar5212DisableMibCounters(ah); +} + +/* + * Set multicast filter 0 (lower 32-bits) + * filter 1 (upper 32-bits) + */ +void +ar5212SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1) +{ + OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0); + OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1); +} + +/* + * Clear multicast filter by index + */ +HAL_BOOL +ar5212ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix) +{ + uint32_t val; + + if (ix >= 64) + return AH_FALSE; + if (ix >= 32) { + val = OS_REG_READ(ah, AR_MCAST_FIL1); + OS_REG_WRITE(ah, AR_MCAST_FIL1, (val &~ (1<<(ix-32)))); + } else { + val = OS_REG_READ(ah, AR_MCAST_FIL0); + OS_REG_WRITE(ah, AR_MCAST_FIL0, (val &~ (1<= 64) + return AH_FALSE; + if (ix >= 32) { + val = OS_REG_READ(ah, AR_MCAST_FIL1); + OS_REG_WRITE(ah, AR_MCAST_FIL1, (val | (1<<(ix-32)))); + } else { + val = OS_REG_READ(ah, AR_MCAST_FIL0); + OS_REG_WRITE(ah, AR_MCAST_FIL0, (val | (1<ds_ctl0 = 0; + ads->ds_ctl1 = size & AR_BufLen; + + if (flags & HAL_RXDESC_INTREQ) + ads->ds_ctl1 |= AR_RxInterReq; + ads->ds_rxstatus0 = ads->ds_rxstatus1 = 0; + + return AH_TRUE; +} + +/* + * Process an RX descriptor, and return the status to the caller. + * Copy some hardware specific items into the software portion + * of the descriptor. + * + * NB: the caller is responsible for validating the memory contents + * of the descriptor (e.g. flushing any cached copy). + */ +HAL_STATUS +ar5212ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, + uint32_t pa, struct ath_desc *nds, uint64_t tsf, + struct ath_rx_status *rs) +{ + struct ar5212_desc *ads = AR5212DESC(ds); + struct ar5212_desc *ands = AR5212DESC(nds); + + if ((ads->ds_rxstatus1 & AR_Done) == 0) + return HAL_EINPROGRESS; + /* + * Given the use of a self-linked tail be very sure that the hw is + * done with this descriptor; the hw may have done this descriptor + * once and picked it up again...make sure the hw has moved on. + */ + if ((ands->ds_rxstatus1&AR_Done) == 0 && OS_REG_READ(ah, AR_RXDP) == pa) + return HAL_EINPROGRESS; + + rs->rs_datalen = ads->ds_rxstatus0 & AR_DataLen; + rs->rs_tstamp = MS(ads->ds_rxstatus1, AR_RcvTimestamp); + rs->rs_status = 0; + /* XXX what about KeyCacheMiss? */ + rs->rs_rssi = MS(ads->ds_rxstatus0, AR_RcvSigStrength); + /* discard invalid h/w rssi data */ + if (rs->rs_rssi == -128) + rs->rs_rssi = 0; + if (ads->ds_rxstatus1 & AR_KeyIdxValid) + rs->rs_keyix = MS(ads->ds_rxstatus1, AR_KeyIdx); + else + rs->rs_keyix = HAL_RXKEYIX_INVALID; + /* NB: caller expected to do rate table mapping */ + rs->rs_rate = MS(ads->ds_rxstatus0, AR_RcvRate); + rs->rs_antenna = MS(ads->ds_rxstatus0, AR_RcvAntenna); + rs->rs_more = (ads->ds_rxstatus0 & AR_More) ? 1 : 0; + + if ((ads->ds_rxstatus1 & AR_FrmRcvOK) == 0) { + /* + * These four bits should not be set together. The + * 5212 spec states a Michael error can only occur if + * DecryptCRCErr not set (and TKIP is used). Experience + * indicates however that you can also get Michael errors + * when a CRC error is detected, but these are specious. + * Consequently we filter them out here so we don't + * confuse and/or complicate drivers. + */ + if (ads->ds_rxstatus1 & AR_CRCErr) + rs->rs_status |= HAL_RXERR_CRC; + else if (ads->ds_rxstatus1 & AR_PHYErr) { + u_int phyerr; + + rs->rs_status |= HAL_RXERR_PHY; + phyerr = MS(ads->ds_rxstatus1, AR_PHYErrCode); + rs->rs_phyerr = phyerr; + if (!AH5212(ah)->ah_hasHwPhyCounters && + phyerr != HAL_PHYERR_RADAR) + ar5212AniPhyErrReport(ah, rs); + } else if (ads->ds_rxstatus1 & AR_DecryptCRCErr) + rs->rs_status |= HAL_RXERR_DECRYPT; + else if (ads->ds_rxstatus1 & AR_MichaelErr) + rs->rs_status |= HAL_RXERR_MIC; + } + return HAL_OK; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_reset.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_reset.c new file mode 100644 index 0000000000..fcf5e7244b --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_reset.c @@ -0,0 +1,2659 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212_reset.c,v 1.20 2008/11/27 22:30:00 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#include "ah_eeprom_v3.h" + +/* Additional Time delay to wait after activiting the Base band */ +#define BASE_ACTIVATE_DELAY 100 /* 100 usec */ +#define PLL_SETTLE_DELAY 300 /* 300 usec */ + +static HAL_BOOL ar5212SetResetReg(struct ath_hal *, uint32_t resetMask); +/* NB: public for 5312 use */ +HAL_BOOL ar5212IsSpurChannel(struct ath_hal *, HAL_CHANNEL *); +HAL_BOOL ar5212ChannelChange(struct ath_hal *, HAL_CHANNEL *); +int16_t ar5212GetNf(struct ath_hal *, HAL_CHANNEL_INTERNAL *); +HAL_BOOL ar5212SetBoardValues(struct ath_hal *, HAL_CHANNEL_INTERNAL *); +void ar5212SetDeltaSlope(struct ath_hal *, HAL_CHANNEL *); +HAL_BOOL ar5212SetTransmitPower(struct ath_hal *ah, + HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain); +static HAL_BOOL ar5212SetRateTable(struct ath_hal *, + HAL_CHANNEL *, int16_t tpcScaleReduction, int16_t powerLimit, + HAL_BOOL commit, int16_t *minPower, int16_t *maxPower); +static void ar5212CorrectGainDelta(struct ath_hal *, int twiceOfdmCckDelta); +static void ar5212GetTargetPowers(struct ath_hal *, HAL_CHANNEL *, + const TRGT_POWER_INFO *pPowerInfo, uint16_t numChannels, + TRGT_POWER_INFO *pNewPower); +static uint16_t ar5212GetMaxEdgePower(uint16_t channel, + const RD_EDGES_POWER *pRdEdgesPower); +void ar5212SetRateDurationTable(struct ath_hal *, HAL_CHANNEL *); +void ar5212SetIFSTiming(struct ath_hal *, HAL_CHANNEL *); + +/* NB: public for RF backend use */ +void ar5212GetLowerUpperValues(uint16_t value, + uint16_t *pList, uint16_t listSize, + uint16_t *pLowerValue, uint16_t *pUpperValue); +void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static int +write_common(struct ath_hal *ah, const HAL_INI_ARRAY *ia, + HAL_BOOL bChannelChange, int writes) +{ +#define IS_NO_RESET_TIMER_ADDR(x) \ + ( (((x) >= AR_BEACON) && ((x) <= AR_CFP_DUR)) || \ + (((x) >= AR_SLEEP1) && ((x) <= AR_SLEEP3))) +#define V(r, c) (ia)->data[((r)*(ia)->cols) + (c)] + int r; + + /* Write Common Array Parameters */ + for (r = 0; r < ia->rows; r++) { + uint32_t reg = V(r, 0); + /* XXX timer/beacon setup registers? */ + /* On channel change, don't reset the PCU registers */ + if (!(bChannelChange && IS_NO_RESET_TIMER_ADDR(reg))) { + OS_REG_WRITE(ah, reg, V(r, 1)); + DMA_YIELD(writes); + } + } + return writes; +#undef IS_NO_RESET_TIMER_ADDR +#undef V +} + +#define IS_DISABLE_FAST_ADC_CHAN(x) (((x) == 2462) || ((x) == 2467)) + +/* + * Places the device in and out of reset and then places sane + * values in the registers based on EEPROM config, initialization + * vectors (as determined by the mode), and station configuration + * + * bChannelChange is used to preserve DMA/PCU registers across + * a HW Reset during channel change. + */ +HAL_BOOL +ar5212Reset(struct ath_hal *ah, HAL_OPMODE opmode, + HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status) +{ +#define N(a) (sizeof (a) / sizeof (a[0])) +#define FAIL(_code) do { ecode = _code; goto bad; } while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *ichan = AH_NULL; + const HAL_EEPROM *ee; + uint32_t softLedCfg, softLedState; + uint32_t saveFrameSeqCount, saveDefAntenna, saveLedState; + uint32_t macStaId1, synthDelay, txFrm2TxDStart; + uint16_t rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL]; + int16_t cckOfdmPwrDelta = 0; + u_int modesIndex, freqIndex; + HAL_STATUS ecode; + int i, regWrites; + uint32_t testReg, powerVal; + int8_t twiceAntennaGain, twiceAntennaReduction; + uint32_t ackTpcPow, ctsTpcPow, chirpTpcPow; + HAL_BOOL isBmode = AH_FALSE; + HAL_BOOL ichan_isBmode = AH_FALSE; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + ee = AH_PRIVATE(ah)->ah_eeprom; + + OS_MARK(ah, AH_MARK_RESET, bChannelChange); +#define IS(_c,_f) (((_c)->channelFlags & _f) || 0) + if ((IS(chan, CHANNEL_2GHZ) ^ IS(chan, CHANNEL_5GHZ)) == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n", + __func__, chan->channel, chan->channelFlags); + FAIL(HAL_EINVAL); + } + if ((IS(chan, CHANNEL_OFDM) ^ IS(chan, CHANNEL_CCK)) == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; not marked as OFDM or CCK\n", + __func__, chan->channel, chan->channelFlags); + FAIL(HAL_EINVAL); + } +#undef IS + + /* Bring out of sleep mode */ + if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip did not wakeup\n", + __func__); + FAIL(HAL_EIO); + } + + /* + * Map public channel to private. + */ + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->channel, chan->channelFlags); + FAIL(HAL_EINVAL); + } + switch (opmode) { + case HAL_M_STA: + case HAL_M_IBSS: + case HAL_M_HOSTAP: + case HAL_M_MONITOR: + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n", + __func__, opmode); + FAIL(HAL_EINVAL); + break; + } + HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3); + + SAVE_CCK(ah, ichan, ichan_isBmode); + SAVE_CCK(ah, chan, isBmode); + + /* Preserve certain DMA hardware registers on a channel change */ + if (bChannelChange) { + /* + * On Venice, the TSF is almost preserved across a reset; + * it requires doubling writes to the RESET_TSF + * bit in the AR_BEACON register; it also has the quirk + * of the TSF going back in time on the station (station + * latches onto the last beacon's tsf during a reset 50% + * of the times); the latter is not a problem for adhoc + * stations since as long as the TSF is behind, it will + * get resynchronized on receiving the next beacon; the + * TSF going backwards in time could be a problem for the + * sleep operation (supported on infrastructure stations + * only) - the best and most general fix for this situation + * is to resynchronize the various sleep/beacon timers on + * the receipt of the next beacon i.e. when the TSF itself + * gets resynchronized to the AP's TSF - power save is + * needed to be temporarily disabled until that time + * + * Need to save the sequence number to restore it after + * the reset! + */ + saveFrameSeqCount = OS_REG_READ(ah, AR_D_SEQNUM); + } else + saveFrameSeqCount = 0; /* NB: silence compiler */ +#if 0 + /* + * XXX disable for now; this appears to sometimes cause OFDM + * XXX timing error floods when ani is enabled and bg scanning + * XXX kicks in + */ + /* If the channel change is across the same mode - perform a fast channel change */ + if (IS_2413(ah) || IS_5413(ah)) { + /* + * Fast channel change can only be used when: + * -channel change requested - so it's not the initial reset. + * -it's not a change to the current channel - + * often called when switching modes on a channel + * -the modes of the previous and requested channel are the + * same + * XXX opmode shouldn't change either? + */ + if (bChannelChange && + (AH_PRIVATE(ah)->ah_curchan != AH_NULL) && + (chan->channel != AH_PRIVATE(ah)->ah_curchan->channel) && + ((chan->channelFlags & CHANNEL_ALL) == + (AH_PRIVATE(ah)->ah_curchan->channelFlags & CHANNEL_ALL))) { + if (ar5212ChannelChange(ah, chan)) { + /* If ChannelChange completed - skip the rest of reset */ + /* XXX ani? */ + return AH_TRUE; + } + } + } +#endif + /* + * Preserve the antenna on a channel change + */ + saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA); + if (saveDefAntenna == 0) /* XXX magic constants */ + saveDefAntenna = 1; + + /* Save hardware flag before chip reset clears the register */ + macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & + (AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT); + + /* Save led state from pci config register */ + saveLedState = OS_REG_READ(ah, AR_PCICFG) & + (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK | + AR_PCICFG_LEDSLOW); + softLedCfg = OS_REG_READ(ah, AR_GPIOCR); + softLedState = OS_REG_READ(ah, AR_GPIODO); + + ar5212RestoreClock(ah, opmode); /* move to refclk operation */ + + /* + * Adjust gain parameters before reset if + * there's an outstanding gain updated. + */ + (void) ar5212GetRfgain(ah); + + if (!ar5212ChipReset(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + FAIL(HAL_EIO); + } + + /* Setup the indices for the next set of register array writes */ + switch (chan->channelFlags & CHANNEL_ALL) { + case CHANNEL_A: + modesIndex = 1; + freqIndex = 1; + break; + case CHANNEL_T: + modesIndex = 2; + freqIndex = 1; + break; + case CHANNEL_B: + modesIndex = 3; + freqIndex = 2; + break; + case CHANNEL_PUREG: + modesIndex = 4; + freqIndex = 2; + break; + case CHANNEL_108G: + modesIndex = 5; + freqIndex = 2; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + FAIL(HAL_EINVAL); + } + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + /* Set correct Baseband to analog shift setting to access analog chips. */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0); + regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange, + regWrites); + ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites); + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) { + ar5212SetIFSTiming(ah, chan); + if (IS_5413(ah)) { + /* + * Force window_length for 1/2 and 1/4 rate channels, + * the ini file sets this to zero otherwise. + */ + OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, + AR_PHY_FRAME_CTL_WINLEN, 3); + } + } + + /* Overwrite INI values for revised chipsets */ + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) { + /* ADC_CTL */ + OS_REG_WRITE(ah, AR_PHY_ADC_CTL, + SM(2, AR_PHY_ADC_CTL_OFF_INBUFGAIN) | + SM(2, AR_PHY_ADC_CTL_ON_INBUFGAIN) | + AR_PHY_ADC_CTL_OFF_PWDDAC | + AR_PHY_ADC_CTL_OFF_PWDADC); + + /* TX_PWR_ADJ */ + if (chan->channel == 2484) { + cckOfdmPwrDelta = SCALE_OC_DELTA( + ee->ee_cckOfdmPwrDelta - + ee->ee_scaledCh14FilterCckDelta); + } else { + cckOfdmPwrDelta = SCALE_OC_DELTA( + ee->ee_cckOfdmPwrDelta); + } + + if (IS_CHAN_G(chan)) { + OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, + SM((ee->ee_cckOfdmPwrDelta*-1), + AR_PHY_TXPWRADJ_CCK_GAIN_DELTA) | + SM((cckOfdmPwrDelta*-1), + AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX)); + } else { + OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, 0); + } + + /* Add barker RSSI thresh enable as disabled */ + OS_REG_CLR_BIT(ah, AR_PHY_DAG_CTRLCCK, + AR_PHY_DAG_CTRLCCK_EN_RSSI_THR); + OS_REG_RMW_FIELD(ah, AR_PHY_DAG_CTRLCCK, + AR_PHY_DAG_CTRLCCK_RSSI_THR, 2); + + /* Set the mute mask to the correct default */ + OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F); + } + + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) { + /* Clear reg to alllow RX_CLEAR line debug */ + OS_REG_WRITE(ah, AR_PHY_BLUETOOTH, 0); + } + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) { +#ifdef notyet + /* Enable burst prefetch for the data queues */ + OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... ); + /* Enable double-buffering */ + OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS); +#endif + } + + /* Set ADC/DAC select values */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); + + if (IS_5413(ah) || IS_2417(ah)) { + uint32_t newReg=1; + if (IS_DISABLE_FAST_ADC_CHAN(chan->channel)) + newReg = 0; + /* As it's a clock changing register, only write when the value needs to be changed */ + if (OS_REG_READ(ah, AR_PHY_FAST_ADC) != newReg) + OS_REG_WRITE(ah, AR_PHY_FAST_ADC, newReg); + } + + /* Setup the transmit power values. */ + if (!ar5212SetTransmitPower(ah, ichan, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error init'ing transmit power\n", __func__); + FAIL(HAL_EIO); + } + + /* Write the analog registers */ + if (!ahp->ah_rfHal->setRfRegs(ah, ichan, modesIndex, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5212SetRfRegs failed\n", + __func__); + FAIL(HAL_EIO); + } + + /* Write delta slope for OFDM enabled modes (A, G, Turbo) */ + if (IS_CHAN_OFDM(chan)) { + if ((IS_5413(ah) || (AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3)) && + (!IS_CHAN_B(chan))) + ar5212SetSpurMitigation(ah, ichan); + ar5212SetDeltaSlope(ah, chan); + } + + /* Setup board specific options for EEPROM version 3 */ + if (!ar5212SetBoardValues(ah, ichan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error setting board options\n", __func__); + FAIL(HAL_EIO); + } + + /* Restore certain DMA hardware registers on a channel change */ + if (bChannelChange) + OS_REG_WRITE(ah, AR_D_SEQNUM, saveFrameSeqCount); + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr)); + OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4) + | macStaId1 + | AR_STA_ID1_RTS_USE_DEF + | ahp->ah_staId1Defaults + ); + ar5212SetOperatingMode(ah, opmode); + + /* Set Venice BSSID mask according to current state */ + OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask)); + OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4)); + + /* Restore previous led state */ + OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | saveLedState); + + /* Restore soft Led state to GPIO */ + OS_REG_WRITE(ah, AR_GPIOCR, softLedCfg); + OS_REG_WRITE(ah, AR_GPIODO, softLedState); + + /* Restore previous antenna */ + OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); + + /* then our BSSID */ + OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); + OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4)); + + /* Restore bmiss rssi & count thresholds */ + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); + + OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */ + + if (!ar5212SetChannel(ah, ichan)) + FAIL(HAL_EIO); + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1); + + ar5212SetRateDurationTable(ah, chan); + + /* Set Tx frame start to tx data start delay */ + if (IS_RAD5112_ANY(ah) && + (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan) || + IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan))) { + txFrm2TxDStart = + (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) ? + TX_FRAME_D_START_HALF_RATE: + TX_FRAME_D_START_QUARTER_RATE; + OS_REG_RMW_FIELD(ah, AR_PHY_TX_CTL, + AR_PHY_TX_FRAME_TO_TX_DATA_START, txFrm2TxDStart); + } + + /* + * Setup fast diversity. + * Fast diversity can be enabled or disabled via regadd.txt. + * Default is enabled. + * For reference, + * Disable: reg val + * 0x00009860 0x00009d18 (if 11a / 11g, else no change) + * 0x00009970 0x192bb514 + * 0x0000a208 0xd03e4648 + * + * Enable: 0x00009860 0x00009d10 (if 11a / 11g, else no change) + * 0x00009970 0x192fb514 + * 0x0000a208 0xd03e6788 + */ + + /* XXX Setup pre PHY ENABLE EAR additions */ + /* + * Wait for the frequency synth to settle (synth goes on + * via AR_PHY_ACTIVE_EN). Read the phy active delay register. + * Value is in 100ns increments. + */ + synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; + if (IS_CHAN_CCK(chan)) { + synthDelay = (4 * synthDelay) / 22; + } else { + synthDelay /= 10; + } + + /* Activate the PHY (includes baseband activate and synthesizer on) */ + OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + + /* + * There is an issue if the AP starts the calibration before + * the base band timeout completes. This could result in the + * rx_clear false triggering. As a workaround we add delay an + * extra BASE_ACTIVATE_DELAY usecs to ensure this condition + * does not happen. + */ + if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) { + OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY); + } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) { + OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY); + } else { + OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY); + } + + /* + * The udelay method is not reliable with notebooks. + * Need to check to see if the baseband is ready + */ + testReg = OS_REG_READ(ah, AR_PHY_TESTCTRL); + /* Selects the Tx hold */ + OS_REG_WRITE(ah, AR_PHY_TESTCTRL, AR_PHY_TESTCTRL_TXHOLD); + i = 0; + while ((i++ < 20) && + (OS_REG_READ(ah, 0x9c24) & 0x10)) /* test if baseband not ready */ OS_DELAY(200); + OS_REG_WRITE(ah, AR_PHY_TESTCTRL, testReg); + + /* Calibrate the AGC and start a NF calculation */ + OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, + OS_REG_READ(ah, AR_PHY_AGC_CONTROL) + | AR_PHY_AGC_CONTROL_CAL + | AR_PHY_AGC_CONTROL_NF); + + if (!IS_CHAN_B(chan) && ahp->ah_bIQCalibration != IQ_CAL_DONE) { + /* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */ + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, + INIT_IQCAL_LOG_COUNT_MAX); + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_DO_IQCAL); + ahp->ah_bIQCalibration = IQ_CAL_RUNNING; + } else + ahp->ah_bIQCalibration = IQ_CAL_INACTIVE; + + /* Setup compression registers */ + ar5212SetCompRegs(ah); + + /* Set 1:1 QCU to DCU mapping for all queues */ + for (i = 0; i < AR_NUM_DCU; i++) + OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); + + ahp->ah_intrTxqs = 0; + for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++) + ar5212ResetTxQueue(ah, i); + + /* + * Setup interrupt handling. Note that ar5212ResetTxQueue + * manipulates the secondary IMR's as queues are enabled + * and disabled. This is done with RMW ops to insure the + * settings we make here are preserved. + */ + ahp->ah_maskReg = AR_IMR_TXOK | AR_IMR_TXERR | AR_IMR_TXURN + | AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXORN + | AR_IMR_HIUERR + ; + if (opmode == HAL_M_HOSTAP) + ahp->ah_maskReg |= AR_IMR_MIB; + OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg); + /* Enable bus errors that are OR'd to set the HIUERR bit */ + OS_REG_WRITE(ah, AR_IMR_S2, + OS_REG_READ(ah, AR_IMR_S2) + | AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR); + + if (AH_PRIVATE(ah)->ah_rfkillEnabled) + ar5212EnableRfKill(ah); + + if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: offset calibration failed to complete in 1ms;" + " noisy environment?\n", __func__); + } + + /* + * Set clocks back to 32kHz if they had been using refClk, then + * use an external 32kHz crystal when sleeping, if one exists. + */ + ar5212SetupClock(ah, opmode); + + /* + * Writing to AR_BEACON will start timers. Hence it should + * be the last register to be written. Do not reset tsf, do + * not enable beacons at this point, but preserve other values + * like beaconInterval. + */ + OS_REG_WRITE(ah, AR_BEACON, + (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF))); + + /* XXX Setup post reset EAR additions */ + + /* QoS support */ + if (AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE || + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && + AH_PRIVATE(ah)->ah_macRev >= AR_SREV_GRIFFIN_LITE)) { + OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa); /* XXX magic */ + OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210); /* XXX magic */ + } + + /* Turn on NOACK Support for QoS packets */ + OS_REG_WRITE(ah, AR_NOACK, + SM(2, AR_NOACK_2BIT_VALUE) | + SM(5, AR_NOACK_BIT_OFFSET) | + SM(0, AR_NOACK_BYTE_OFFSET)); + + /* Get Antenna Gain reduction */ + if (IS_CHAN_5GHZ(chan)) { + ath_hal_eepromGet(ah, AR_EEP_ANTGAINMAX_5, &twiceAntennaGain); + } else { + ath_hal_eepromGet(ah, AR_EEP_ANTGAINMAX_2, &twiceAntennaGain); + } + twiceAntennaReduction = + ath_hal_getantennareduction(ah, chan, twiceAntennaGain); + + /* TPC for self-generated frames */ + + ackTpcPow = MS(ahp->ah_macTPC, AR_TPC_ACK); + if ((ackTpcPow-ahp->ah_txPowerIndexOffset) > ichan->maxTxPower) + ackTpcPow = ichan->maxTxPower+ahp->ah_txPowerIndexOffset; + + if (ackTpcPow > (2*ichan->maxRegTxPower - twiceAntennaReduction)) + ackTpcPow = (2*ichan->maxRegTxPower - twiceAntennaReduction) + + ahp->ah_txPowerIndexOffset; + + ctsTpcPow = MS(ahp->ah_macTPC, AR_TPC_CTS); + if ((ctsTpcPow-ahp->ah_txPowerIndexOffset) > ichan->maxTxPower) + ctsTpcPow = ichan->maxTxPower+ahp->ah_txPowerIndexOffset; + + if (ctsTpcPow > (2*ichan->maxRegTxPower - twiceAntennaReduction)) + ctsTpcPow = (2*ichan->maxRegTxPower - twiceAntennaReduction) + + ahp->ah_txPowerIndexOffset; + + chirpTpcPow = MS(ahp->ah_macTPC, AR_TPC_CHIRP); + if ((chirpTpcPow-ahp->ah_txPowerIndexOffset) > ichan->maxTxPower) + chirpTpcPow = ichan->maxTxPower+ahp->ah_txPowerIndexOffset; + + if (chirpTpcPow > (2*ichan->maxRegTxPower - twiceAntennaReduction)) + chirpTpcPow = (2*ichan->maxRegTxPower - twiceAntennaReduction) + + ahp->ah_txPowerIndexOffset; + + if (ackTpcPow > 63) + ackTpcPow = 63; + if (ctsTpcPow > 63) + ctsTpcPow = 63; + if (chirpTpcPow > 63) + chirpTpcPow = 63; + + powerVal = SM(ackTpcPow, AR_TPC_ACK) | + SM(ctsTpcPow, AR_TPC_CTS) | + SM(chirpTpcPow, AR_TPC_CHIRP); + + OS_REG_WRITE(ah, AR_TPC, powerVal); + + /* Restore user-specified settings */ + if (ahp->ah_miscMode != 0) + OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + if (ahp->ah_sifstime != (u_int) -1) + ar5212SetSifsTime(ah, ahp->ah_sifstime); + if (ahp->ah_slottime != (u_int) -1) + ar5212SetSlotTime(ah, ahp->ah_slottime); + if (ahp->ah_acktimeout != (u_int) -1) + ar5212SetAckTimeout(ah, ahp->ah_acktimeout); + if (ahp->ah_ctstimeout != (u_int) -1) + ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout); + if (AH_PRIVATE(ah)->ah_diagreg != 0) + OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); + + AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */ + + if (bChannelChange) { + if (!(ichan->privFlags & CHANNEL_DFS)) + ichan->privFlags &= ~CHANNEL_INTERFERENCE; + chan->channelFlags = ichan->channelFlags; + chan->privFlags = ichan->privFlags; + chan->maxRegTxPower = ichan->maxRegTxPower; + chan->maxTxPower = ichan->maxTxPower; + chan->minTxPower = ichan->minTxPower; + } + + HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__); + + RESTORE_CCK(ah, ichan, ichan_isBmode); + RESTORE_CCK(ah, chan, isBmode); + + OS_MARK(ah, AH_MARK_RESET_DONE, 0); + + return AH_TRUE; +bad: + if (ichan != AH_NULL) + RESTORE_CCK(ah, ichan, ichan_isBmode); + RESTORE_CCK(ah, chan, isBmode); + + OS_MARK(ah, AH_MARK_RESET_DONE, ecode); + if (*status) + *status = ecode; + return AH_FALSE; +#undef FAIL +#undef N +} + +/* + * Call the rf backend to change the channel. + */ +HAL_BOOL +ar5212SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + /* Change the synth */ + if (!ahp->ah_rfHal->setChannel(ah, chan)) + return AH_FALSE; + return AH_TRUE; +} + +/* + * This channel change evaluates whether the selected hardware can + * perform a synthesizer-only channel change (no reset). If the + * TX is not stopped, or the RFBus cannot be granted in the given + * time, the function returns false as a reset is necessary + */ +HAL_BOOL +ar5212ChannelChange(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + uint32_t ulCount; + uint32_t data, synthDelay, qnum; + uint16_t rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL]; + HAL_BOOL txStopped = AH_TRUE; + HAL_CHANNEL_INTERNAL *ichan; + + /* + * Map public channel to private. + */ + ichan = ath_hal_checkchannel(ah, chan); + + /* TX must be stopped or RF Bus grant will not work */ + for (qnum = 0; qnum < AH_PRIVATE(ah)->ah_caps.halTotalQueues; qnum++) { + if (ar5212NumTxPending(ah, qnum)) { + txStopped = AH_FALSE; + break; + } + } + if (!txStopped) + return AH_FALSE; + + /* Kill last Baseband Rx Frame */ + OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_REQUEST); /* Request analog bus grant */ + for (ulCount = 0; ulCount < 100; ulCount++) { + if (OS_REG_READ(ah, AR_PHY_RFBUS_GNT)) + break; + OS_DELAY(5); + } + if (ulCount >= 100) + return AH_FALSE; + + /* Change the synth */ + if (!ar5212SetChannel(ah, ichan)) + return AH_FALSE; + + /* + * Wait for the frequency synth to settle (synth goes on via PHY_ACTIVE_EN). + * Read the phy active delay register. Value is in 100ns increments. + */ + data = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; + if (IS_CHAN_CCK(ichan)) { + synthDelay = (4 * data) / 22; + } else { + synthDelay = data / 10; + } + OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY); + + /* Setup the transmit power values. */ + if (!ar5212SetTransmitPower(ah, ichan, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error init'ing transmit power\n", __func__); + return AH_FALSE; + } + + /* Write delta slope for OFDM enabled modes (A, G, Turbo) */ + if (IS_CHAN_OFDM(ichan)) { + if ((IS_5413(ah) || (AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3)) && + (!IS_CHAN_B(chan))) + ar5212SetSpurMitigation(ah, ichan); + ar5212SetDeltaSlope(ah, chan); + } + + /* Release the RFBus Grant */ + OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); + + /* Start Noise Floor Cal */ + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + + if (!(ichan->privFlags & CHANNEL_DFS)) + ichan->privFlags &= ~CHANNEL_INTERFERENCE; + chan->channelFlags = ichan->channelFlags; + chan->privFlags = ichan->privFlags; + chan->maxRegTxPower = ichan->maxRegTxPower; + chan->maxTxPower = ichan->maxTxPower; + chan->minTxPower = ichan->minTxPower; + return AH_TRUE; +} + +void +ar5212SetOperatingMode(struct ath_hal *ah, int opmode) +{ + uint32_t val; + + val = OS_REG_READ(ah, AR_STA_ID1); + val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC); + switch (opmode) { + case HAL_M_HOSTAP: + OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP + | AR_STA_ID1_KSRCH_MODE); + OS_REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); + break; + case HAL_M_IBSS: + OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC + | AR_STA_ID1_KSRCH_MODE); + OS_REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); + break; + case HAL_M_STA: + case HAL_M_MONITOR: + OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); + break; + } +} + +/* + * Places the PHY and Radio chips into reset. A full reset + * must be called to leave this state. The PCI/MAC/PCU are + * not placed into reset as we must receive interrupt to + * re-enable the hardware. + */ +HAL_BOOL +ar5212PhyDisable(struct ath_hal *ah) +{ + return ar5212SetResetReg(ah, AR_RC_BB); +} + +/* + * Places all of hardware into reset + */ +HAL_BOOL +ar5212Disable(struct ath_hal *ah) +{ + if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + /* + * Reset the HW - PCI must be reset after the rest of the + * device has been reset. + */ + return ar5212SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI); +} + +/* + * Places the hardware into reset and then pulls it out of reset + * + * TODO: Only write the PLL if we're changing to or from CCK mode + * + * WARNING: The order of the PLL and mode registers must be correct. + */ +HAL_BOOL +ar5212ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + + OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->channel : 0); + + /* + * Reset the HW - PCI must be reset after the rest of the + * device has been reset + */ + if (!ar5212SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI)) + return AH_FALSE; + + /* Bring out of sleep mode (AGAIN) */ + if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + + /* Clear warm reset register */ + if (!ar5212SetResetReg(ah, 0)) + return AH_FALSE; + + /* + * Perform warm reset before the mode/PLL/turbo registers + * are changed in order to deactivate the radio. Mode changes + * with an active radio can result in corrupted shifts to the + * radio device. + */ + + /* + * Set CCK and Turbo modes correctly. + */ + if (chan != AH_NULL) { /* NB: can be null during attach */ + uint32_t rfMode, phyPLL = 0, curPhyPLL, turbo; + + if (IS_5413(ah)) { /* NB: =>'s 5424 also */ + rfMode = AR_PHY_MODE_AR5112; + if (IS_CHAN_HALF_RATE(chan)) + rfMode |= AR_PHY_MODE_HALF; + else if (IS_CHAN_QUARTER_RATE(chan)) + rfMode |= AR_PHY_MODE_QUARTER; + + if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) + phyPLL = AR_PHY_PLL_CTL_44_5112; + else + phyPLL = AR_PHY_PLL_CTL_40_5413; + } else if (IS_RAD5111(ah)) { + rfMode = AR_PHY_MODE_AR5111; + if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) + phyPLL = AR_PHY_PLL_CTL_44; + else + phyPLL = AR_PHY_PLL_CTL_40; + if (IS_CHAN_HALF_RATE(chan)) + phyPLL = AR_PHY_PLL_CTL_HALF; + else if (IS_CHAN_QUARTER_RATE(chan)) + phyPLL = AR_PHY_PLL_CTL_QUARTER; + } else { /* 5112, 2413, 2316, 2317 */ + rfMode = AR_PHY_MODE_AR5112; + if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) + phyPLL = AR_PHY_PLL_CTL_44_5112; + else + phyPLL = AR_PHY_PLL_CTL_40_5112; + if (IS_CHAN_HALF_RATE(chan)) + phyPLL |= AR_PHY_PLL_CTL_HALF; + else if (IS_CHAN_QUARTER_RATE(chan)) + phyPLL |= AR_PHY_PLL_CTL_QUARTER; + } + if (IS_CHAN_OFDM(chan) && (IS_CHAN_CCK(chan) || + IS_CHAN_G(chan))) + rfMode |= AR_PHY_MODE_DYNAMIC; + else if (IS_CHAN_OFDM(chan)) + rfMode |= AR_PHY_MODE_OFDM; + else + rfMode |= AR_PHY_MODE_CCK; + if (IS_CHAN_5GHZ(chan)) + rfMode |= AR_PHY_MODE_RF5GHZ; + else + rfMode |= AR_PHY_MODE_RF2GHZ; + turbo = IS_CHAN_TURBO(chan) ? + (AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT) : 0; + curPhyPLL = OS_REG_READ(ah, AR_PHY_PLL_CTL); + /* + * PLL, Mode, and Turbo values must be written in the correct + * order to ensure: + * - The PLL cannot be set to 44 unless the CCK or DYNAMIC + * mode bit is set + * - Turbo cannot be set at the same time as CCK or DYNAMIC + */ + if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) { + OS_REG_WRITE(ah, AR_PHY_TURBO, turbo); + OS_REG_WRITE(ah, AR_PHY_MODE, rfMode); + if (curPhyPLL != phyPLL) { + OS_REG_WRITE(ah, AR_PHY_PLL_CTL, phyPLL); + /* Wait for the PLL to settle */ + OS_DELAY(PLL_SETTLE_DELAY); + } + } else { + if (curPhyPLL != phyPLL) { + OS_REG_WRITE(ah, AR_PHY_PLL_CTL, phyPLL); + /* Wait for the PLL to settle */ + OS_DELAY(PLL_SETTLE_DELAY); + } + OS_REG_WRITE(ah, AR_PHY_TURBO, turbo); + OS_REG_WRITE(ah, AR_PHY_MODE, rfMode); + } + } + return AH_TRUE; +} + +/* + * Recalibrate the lower PHY chips to account for temperature/environment + * changes. + */ +HAL_BOOL +ar5212PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan, u_int chainMask, + HAL_BOOL longCal, HAL_BOOL *isCalDone) +{ +#define IQ_CAL_TRIES 10 + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *ichan; + int32_t qCoff, qCoffDenom; + int32_t iqCorrMeas, iCoff, iCoffDenom; + uint32_t powerMeasQ, powerMeasI; + HAL_BOOL ichan_isBmode = AH_FALSE; + HAL_BOOL isBmode = AH_FALSE; + + OS_MARK(ah, AH_MARK_PERCAL, chan->channel); + *isCalDone = AH_FALSE; + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->channel, chan->channelFlags); + return AH_FALSE; + } + SAVE_CCK(ah, ichan, ichan_isBmode); + SAVE_CCK(ah, chan, isBmode); + + if (ahp->ah_bIQCalibration == IQ_CAL_DONE || + ahp->ah_bIQCalibration == IQ_CAL_INACTIVE) + *isCalDone = AH_TRUE; + + /* IQ calibration in progress. Check to see if it has finished. */ + if (ahp->ah_bIQCalibration == IQ_CAL_RUNNING && + !(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_IQCAL)) { + int i; + + /* IQ Calibration has finished. */ + ahp->ah_bIQCalibration = IQ_CAL_INACTIVE; + *isCalDone = AH_TRUE; + + /* workaround for misgated IQ Cal results */ + i = 0; + do { + /* Read calibration results. */ + powerMeasI = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_I); + powerMeasQ = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_Q); + iqCorrMeas = OS_REG_READ(ah, AR_PHY_IQCAL_RES_IQ_CORR_MEAS); + if (powerMeasI && powerMeasQ) + break; + /* Do we really need this??? */ + OS_REG_WRITE (ah, AR_PHY_TIMING_CTRL4, + OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) | + AR_PHY_TIMING_CTRL4_DO_IQCAL); + } while (++i < IQ_CAL_TRIES); + + /* + * Prescale these values to remove 64-bit operation + * requirement at the loss of a little precision. + */ + iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; + qCoffDenom = powerMeasQ / 128; + + /* Protect against divide-by-0 and loss of sign bits. */ + if (iCoffDenom != 0 && qCoffDenom >= 2) { + iCoff = (int8_t)(-iqCorrMeas) / iCoffDenom; + /* IQCORR_Q_I_COFF is a signed 6 bit number */ + if (iCoff < -32) { + iCoff = -32; + } else if (iCoff > 31) { + iCoff = 31; + } + + /* IQCORR_Q_Q_COFF is a signed 5 bit number */ + qCoff = (powerMeasI / qCoffDenom) - 128; + if (qCoff < -16) { + qCoff = -16; + } else if (qCoff > 15) { + qCoff = 15; + } + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "****************** MISGATED IQ CAL! *******************\n"); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "time = %d, i = %d, \n", OS_GETUPTIME(ah), i); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "powerMeasI = 0x%08x\n", powerMeasI); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "powerMeasQ = 0x%08x\n", powerMeasQ); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "iqCorrMeas = 0x%08x\n", iqCorrMeas); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "iCoff = %d\n", iCoff); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "qCoff = %d\n", qCoff); + + /* Write values and enable correction */ + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff); + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); + + ahp->ah_bIQCalibration = IQ_CAL_DONE; + ichan->iqCalValid = AH_TRUE; + ichan->iCoff = iCoff; + ichan->qCoff = qCoff; + } + } else if (!IS_CHAN_B(chan) && ahp->ah_bIQCalibration == IQ_CAL_DONE && + !ichan->iqCalValid) { + /* + * Start IQ calibration if configured channel has changed. + * Use a magic number of 15 based on default value. + */ + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, + INIT_IQCAL_LOG_COUNT_MAX); + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_DO_IQCAL); + ahp->ah_bIQCalibration = IQ_CAL_RUNNING; + } + /* XXX EAR */ + + if (longCal) { + /* Check noise floor results */ + ar5212GetNf(ah, ichan); + + if ((ichan->channelFlags & CHANNEL_CW_INT) == 0) { + /* Perform cal for 5Ghz channels and any OFDM on 5112 */ + if (IS_CHAN_5GHZ(chan) || + (IS_RAD5112(ah) && IS_CHAN_OFDM(chan))) + ar5212RequestRfgain(ah); + } else { + /* report up and clear internal state */ + chan->channelFlags |= CHANNEL_CW_INT; + ichan->channelFlags &= ~CHANNEL_CW_INT; + } + } + RESTORE_CCK(ah, ichan, ichan_isBmode); + RESTORE_CCK(ah, chan, isBmode); + + return AH_TRUE; +#undef IQ_CAL_TRIES +} + +HAL_BOOL +ar5212PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) +{ + return ar5212PerCalibrationN(ah, chan, 0x1, AH_TRUE, isIQdone); +} + +HAL_BOOL +ar5212ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + /* XXX */ + return AH_TRUE; +} + +/* + * Write the given reset bit mask into the reset register + */ +static HAL_BOOL +ar5212SetResetReg(struct ath_hal *ah, uint32_t resetMask) +{ + uint32_t mask = resetMask ? resetMask : ~0; + HAL_BOOL rt; + + /* XXX ar5212MacStop & co. */ + + if (IS_PCIE(ah)) { + resetMask &= ~AR_RC_PCI; + } + + (void) OS_REG_READ(ah, AR_RXDP);/* flush any pending MMR writes */ + OS_REG_WRITE(ah, AR_RC, resetMask); + OS_DELAY(15); /* need to wait at least 128 clocks + when reseting PCI before read */ + mask &= (AR_RC_MAC | AR_RC_BB); + resetMask &= (AR_RC_MAC | AR_RC_BB); + rt = ath_hal_wait(ah, AR_RC, mask, resetMask); + if ((resetMask & AR_RC_MAC) == 0) { + if (isBigEndian()) { + /* + * Set CFG, little-endian for register + * and descriptor accesses. + */ + mask = INIT_CONFIG_STATUS | AR_CFG_SWRD | AR_CFG_SWRG; +#ifndef AH_NEED_DESC_SWAP + mask |= AR_CFG_SWTD; +#endif + OS_REG_WRITE(ah, AR_CFG, LE_READ_4(&mask)); + } else + OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS); + if (ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + (void) OS_REG_READ(ah, AR_ISR_RAC); + } + + /* track PHY power state so we don't try to r/w BB registers */ + AH5212(ah)->ah_phyPowerOn = ((resetMask & AR_RC_BB) == 0); + return rt; +} + +int16_t +ar5212GetNoiseFloor(struct ath_hal *ah) +{ + int16_t nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff; + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + return nf; +} + +static HAL_BOOL +getNoiseFloorThresh(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *chan, + int16_t *nft) +{ + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) { + case CHANNEL_A: + *nft = ee->ee_noiseFloorThresh[headerInfo11A]; + break; + case CHANNEL_B: + *nft = ee->ee_noiseFloorThresh[headerInfo11B]; + break; + case CHANNEL_PUREG: + *nft = ee->ee_noiseFloorThresh[headerInfo11G]; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + return AH_TRUE; +} + +/* + * Setup the noise floor cal history buffer. + */ +void +ar5212InitNfCalHistBuffer(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + int i; + + ahp->ah_nfCalHist.first_run = 1; + ahp->ah_nfCalHist.currIndex = 0; + ahp->ah_nfCalHist.privNF = AR5212_CCA_MAX_GOOD_VALUE; + ahp->ah_nfCalHist.invalidNFcount = AR512_NF_CAL_HIST_MAX; + for (i = 0; i < AR512_NF_CAL_HIST_MAX; i ++) + ahp->ah_nfCalHist.nfCalBuffer[i] = AR5212_CCA_MAX_GOOD_VALUE; +} + +/* + * Add a noise floor value to the ring buffer. + */ +static __inline void +updateNFHistBuff(struct ar5212NfCalHist *h, int16_t nf) +{ + h->nfCalBuffer[h->currIndex] = nf; + if (++h->currIndex >= AR512_NF_CAL_HIST_MAX) + h->currIndex = 0; +} + +/* + * Return the median noise floor value in the ring buffer. + */ +int16_t +ar5212GetNfHistMid(const int16_t calData[AR512_NF_CAL_HIST_MAX]) +{ + int16_t sort[AR512_NF_CAL_HIST_MAX]; + int i, j; + + OS_MEMCPY(sort, calData, AR512_NF_CAL_HIST_MAX*sizeof(int16_t)); + for (i = 0; i < AR512_NF_CAL_HIST_MAX-1; i ++) { + for (j = 1; j < AR512_NF_CAL_HIST_MAX-i; j ++) { + if (sort[j] > sort[j-1]) { + int16_t nf = sort[j]; + sort[j] = sort[j-1]; + sort[j-1] = nf; + } + } + } + return sort[(AR512_NF_CAL_HIST_MAX-1)>>1]; +} + +/* + * Read the NF and check it against the noise floor threshhold + */ +int16_t +ar5212GetNf(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212NfCalHist *h = &ahp->ah_nfCalHist; + int16_t nf, nfThresh; + int32_t val; + + if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: NF did not complete in calibration window\n", __func__); + chan->rawNoiseFloor = h->privNF; /* most recent value */ + return chan->rawNoiseFloor; + } + + /* + * Finished NF cal, check against threshold. + */ + nf = ar5212GetNoiseFloor(ah); + if (getNoiseFloorThresh(ah, chan, &nfThresh)) { + if (nf > nfThresh) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: noise floor failed detected; detected %u, " + "threshold %u\n", __func__, nf, nfThresh); + /* + * NB: Don't discriminate 2.4 vs 5Ghz, if this + * happens it indicates a problem regardless + * of the band. + */ + chan->channelFlags |= CHANNEL_CW_INT; + nf = 0; + } + } else + nf = 0; + + /* + * Pass through histogram and write median value as + * calculated from the accrued window. We require a + * full window of in-range values to be seen before we + * start using the history. + */ + updateNFHistBuff(h, nf); + if (h->first_run) { + if (nf < AR5212_CCA_MIN_BAD_VALUE || + nf > AR5212_CCA_MAX_HIGH_VALUE) { + nf = AR5212_CCA_MAX_GOOD_VALUE; + h->invalidNFcount = AR512_NF_CAL_HIST_MAX; + } else if (--(h->invalidNFcount) == 0) { + h->first_run = 0; + h->privNF = nf = ar5212GetNfHistMid(h->nfCalBuffer); + } else { + nf = AR5212_CCA_MAX_GOOD_VALUE; + } + } else { + h->privNF = nf = ar5212GetNfHistMid(h->nfCalBuffer); + } + + val = OS_REG_READ(ah, AR_PHY(25)); + val &= 0xFFFFFE00; + val |= (((uint32_t)nf << 1) & 0x1FF); + OS_REG_WRITE(ah, AR_PHY(25), val); + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + + if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF, 0)) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: AGC not ready AGC_CONTROL 0x%x\n", + __func__, OS_REG_READ(ah, AR_PHY_AGC_CONTROL)); +#endif + } + + /* + * Now load a high maxCCAPower value again so that we're + * not capped by the median we just loaded + */ + val &= 0xFFFFFE00; + val |= (((uint32_t)(-50) << 1) & 0x1FF); + OS_REG_WRITE(ah, AR_PHY(25), val); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + + return (chan->rawNoiseFloor = nf); +} + +/* + * Set up compression configuration registers + */ +void +ar5212SetCompRegs(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + int i; + + /* Check if h/w supports compression */ + if (!AH_PRIVATE(ah)->ah_caps.halCompressSupport) + return; + + OS_REG_WRITE(ah, AR_DCCFG, 1); + + OS_REG_WRITE(ah, AR_CCFG, + (AR_COMPRESSION_WINDOW_SIZE >> 8) & AR_CCFG_WIN_M); + + OS_REG_WRITE(ah, AR_CCFG, + OS_REG_READ(ah, AR_CCFG) | AR_CCFG_MIB_INT_EN); + OS_REG_WRITE(ah, AR_CCUCFG, + AR_CCUCFG_RESET_VAL | AR_CCUCFG_CATCHUP_EN); + + OS_REG_WRITE(ah, AR_CPCOVF, 0); + + /* reset decompression mask */ + for (i = 0; i < HAL_DECOMP_MASK_SIZE; i++) { + OS_REG_WRITE(ah, AR_DCM_A, i); + OS_REG_WRITE(ah, AR_DCM_D, ahp->ah_decompMask[i]); + } +} + +HAL_BOOL +ar5212SetAntennaSwitchInternal(struct ath_hal *ah, HAL_ANT_SETTING settings, + const HAL_CHANNEL_INTERNAL *chan) +{ +#define ANT_SWITCH_TABLE1 AR_PHY(88) +#define ANT_SWITCH_TABLE2 AR_PHY(89) + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint32_t antSwitchA, antSwitchB; + int ix; + HAL_BOOL isBmode = AH_FALSE; + /* NB: need local copy for SAVE/RESTORE 'cuz chan is const */ + HAL_CHANNEL_INTERNAL ichan = *chan; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + HALASSERT(ahp->ah_phyPowerOn); + + SAVE_CCK(ah, &ichan, isBmode); + switch (ichan.channelFlags & CHANNEL_ALL_NOTURBO) { + case CHANNEL_A: ix = 0; break; + case CHANNEL_B: ix = 1; break; + case CHANNEL_PUREG: ix = 2; break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, ichan.channelFlags); + RESTORE_CCK(ah, &ichan, isBmode); + return AH_FALSE; + } + RESTORE_CCK(ah, &ichan, isBmode); + + antSwitchA = ee->ee_antennaControl[1][ix] + | (ee->ee_antennaControl[2][ix] << 6) + | (ee->ee_antennaControl[3][ix] << 12) + | (ee->ee_antennaControl[4][ix] << 18) + | (ee->ee_antennaControl[5][ix] << 24) + ; + antSwitchB = ee->ee_antennaControl[6][ix] + | (ee->ee_antennaControl[7][ix] << 6) + | (ee->ee_antennaControl[8][ix] << 12) + | (ee->ee_antennaControl[9][ix] << 18) + | (ee->ee_antennaControl[10][ix] << 24) + ; + /* + * For fixed antenna, give the same setting for both switch banks + */ + switch (settings) { + case HAL_ANT_FIXED_A: + antSwitchB = antSwitchA; + break; + case HAL_ANT_FIXED_B: + antSwitchA = antSwitchB; + break; + case HAL_ANT_VARIABLE: + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad antenna setting %u\n", + __func__, settings); + return AH_FALSE; + } + if (antSwitchB == antSwitchA) { + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Setting fast diversity off.\n", __func__); + OS_REG_CLR_BIT(ah,AR_PHY_CCK_DETECT, + AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); + ahp->ah_diversity = AH_FALSE; + } else { + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Setting fast diversity on.\n", __func__); + OS_REG_SET_BIT(ah,AR_PHY_CCK_DETECT, + AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); + ahp->ah_diversity = AH_TRUE; + } + ahp->ah_antControl = settings; + + OS_REG_WRITE(ah, ANT_SWITCH_TABLE1, antSwitchA); + OS_REG_WRITE(ah, ANT_SWITCH_TABLE2, antSwitchB); + + return AH_TRUE; +#undef ANT_SWITCH_TABLE2 +#undef ANT_SWITCH_TABLE1 +} + +HAL_BOOL +ar5212IsSpurChannel(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + uint32_t clockFreq = + ((IS_5413(ah) || IS_RAD5112_ANY(ah) || IS_2417(ah)) ? 40 : 32); + return ( ((chan->channel % clockFreq) != 0) + && (((chan->channel % clockFreq) < 10) + || (((chan->channel) % clockFreq) > 22)) ); +} + +/* + * Read EEPROM header info and program the device for correct operation + * given the channel value. + */ +HAL_BOOL +ar5212SetBoardValues(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ +#define NO_FALSE_DETECT_BACKOFF 2 +#define CB22_FALSE_DETECT_BACKOFF 6 +#define AR_PHY_BIS(_ah, _reg, _mask, _val) \ + OS_REG_WRITE(_ah, AR_PHY(_reg), \ + (OS_REG_READ(_ah, AR_PHY(_reg)) & _mask) | (_val)); + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + int arrayMode, falseDectectBackoff; + int is2GHz = IS_CHAN_2GHZ(chan); + int8_t adcDesiredSize, pgaDesiredSize; + uint16_t switchSettling, txrxAtten, rxtxMargin; + int iCoff, qCoff; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + switch (chan->channelFlags & CHANNEL_ALL) { + case CHANNEL_A: + case CHANNEL_T: + arrayMode = headerInfo11A; + if (!IS_RAD5112_ANY(ah) && !IS_2413(ah) && !IS_5413(ah)) + OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, + AR_PHY_FRAME_CTL_TX_CLIP, + ahp->ah_gainValues.currStep->paramVal[GP_TXCLIP]); + break; + case CHANNEL_B: + arrayMode = headerInfo11B; + break; + case CHANNEL_G: + case CHANNEL_108G: + arrayMode = headerInfo11G; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + + /* Set the antenna register(s) correctly for the chip revision */ + AR_PHY_BIS(ah, 68, 0xFFFFFC06, + (ee->ee_antennaControl[0][arrayMode] << 4) | 0x1); + + ar5212SetAntennaSwitchInternal(ah, ahp->ah_antControl, chan); + + /* Set the Noise Floor Thresh on ar5211 devices */ + OS_REG_WRITE(ah, AR_PHY(90), + (ee->ee_noiseFloorThresh[arrayMode] & 0x1FF) + | (1 << 9)); + + if (ee->ee_version >= AR_EEPROM_VER5_0 && IS_CHAN_TURBO(chan)) { + switchSettling = ee->ee_switchSettlingTurbo[is2GHz]; + adcDesiredSize = ee->ee_adcDesiredSizeTurbo[is2GHz]; + pgaDesiredSize = ee->ee_pgaDesiredSizeTurbo[is2GHz]; + txrxAtten = ee->ee_txrxAttenTurbo[is2GHz]; + rxtxMargin = ee->ee_rxtxMarginTurbo[is2GHz]; + } else { + switchSettling = ee->ee_switchSettling[arrayMode]; + adcDesiredSize = ee->ee_adcDesiredSize[arrayMode]; + pgaDesiredSize = ee->ee_pgaDesiredSize[is2GHz]; + txrxAtten = ee->ee_txrxAtten[is2GHz]; + rxtxMargin = ee->ee_rxtxMargin[is2GHz]; + } + + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, + AR_PHY_SETTLING_SWITCH, switchSettling); + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, + AR_PHY_DESIRED_SZ_ADC, adcDesiredSize); + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, + AR_PHY_DESIRED_SZ_PGA, pgaDesiredSize); + OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, + AR_PHY_RXGAIN_TXRX_ATTEN, txrxAtten); + OS_REG_WRITE(ah, AR_PHY(13), + (ee->ee_txEndToXPAOff[arrayMode] << 24) + | (ee->ee_txEndToXPAOff[arrayMode] << 16) + | (ee->ee_txFrameToXPAOn[arrayMode] << 8) + | ee->ee_txFrameToXPAOn[arrayMode]); + AR_PHY_BIS(ah, 10, 0xFFFF00FF, + ee->ee_txEndToXLNAOn[arrayMode] << 8); + AR_PHY_BIS(ah, 25, 0xFFF80FFF, + (ee->ee_thresh62[arrayMode] << 12) & 0x7F000); + + /* + * False detect backoff - suspected 32 MHz spur causes false + * detects in OFDM, causing Tx Hangs. Decrease weak signal + * sensitivity for this card. + */ + falseDectectBackoff = NO_FALSE_DETECT_BACKOFF; + if (ee->ee_version < AR_EEPROM_VER3_3) { + /* XXX magic number */ + if (AH_PRIVATE(ah)->ah_subvendorid == 0x1022 && + IS_CHAN_OFDM(chan)) + falseDectectBackoff += CB22_FALSE_DETECT_BACKOFF; + } else { + if (ar5212IsSpurChannel(ah, (HAL_CHANNEL *)chan)) { + falseDectectBackoff += ee->ee_falseDetectBackoff[arrayMode]; + } + } + AR_PHY_BIS(ah, 73, 0xFFFFFF01, (falseDectectBackoff << 1) & 0xFE); + + if (chan->iqCalValid) { + iCoff = chan->iCoff; + qCoff = chan->qCoff; + } else { + iCoff = ee->ee_iqCalI[is2GHz]; + qCoff = ee->ee_iqCalQ[is2GHz]; + } + + /* write previous IQ results */ + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff); + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); + + if (ee->ee_version >= AR_EEPROM_VER4_1) { + if (!IS_CHAN_108G(chan) || ee->ee_version >= AR_EEPROM_VER5_0) + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, + AR_PHY_GAIN_2GHZ_RXTX_MARGIN, rxtxMargin); + } + if (ee->ee_version >= AR_EEPROM_VER5_1) { + /* for now always disabled */ + OS_REG_WRITE(ah, AR_PHY_HEAVY_CLIP_ENABLE, 0); + } + + return AH_TRUE; +#undef AR_PHY_BIS +#undef NO_FALSE_DETECT_BACKOFF +#undef CB22_FALSE_DETECT_BACKOFF +} + +/* + * Apply Spur Immunity to Boards that require it. + * Applies only to OFDM RX operation. + */ + +void +ar5212SetSpurMitigation(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan) +{ + uint32_t pilotMask[2] = {0, 0}, binMagMask[4] = {0, 0, 0 , 0}; + uint16_t i, finalSpur, curChanAsSpur, binWidth = 0, spurDetectWidth, spurChan; + int32_t spurDeltaPhase = 0, spurFreqSd = 0, spurOffset, binOffsetNumT16, curBinOffset; + int16_t numBinOffsets; + static const uint16_t magMapFor4[4] = {1, 2, 2, 1}; + static const uint16_t magMapFor3[3] = {1, 2, 1}; + const uint16_t *pMagMap; + HAL_BOOL is2GHz = IS_CHAN_2GHZ(ichan); + uint32_t val; + +#define CHAN_TO_SPUR(_f, _freq) ( ((_freq) - ((_f) ? 2300 : 4900)) * 10 ) + if (IS_2417(ah)) { + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: no spur mitigation\n", + __func__); + return; + } + + curChanAsSpur = CHAN_TO_SPUR(is2GHz, ichan->channel); + + if (ichan->mainSpur) { + /* Pull out the saved spur value */ + finalSpur = ichan->mainSpur; + } else { + /* + * Check if spur immunity should be performed for this channel + * Should only be performed once per channel and then saved + */ + finalSpur = AR_NO_SPUR; + spurDetectWidth = HAL_SPUR_CHAN_WIDTH; + if (IS_CHAN_TURBO(ichan)) + spurDetectWidth *= 2; + + /* Decide if any spur affects the current channel */ + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { + spurChan = ath_hal_getSpurChan(ah, i, is2GHz); + if (spurChan == AR_NO_SPUR) { + break; + } + if ((curChanAsSpur - spurDetectWidth <= (spurChan & HAL_SPUR_VAL_MASK)) && + (curChanAsSpur + spurDetectWidth >= (spurChan & HAL_SPUR_VAL_MASK))) { + finalSpur = spurChan & HAL_SPUR_VAL_MASK; + break; + } + } + /* Save detected spur (or no spur) for this channel */ + ichan->mainSpur = finalSpur; + } + + /* Write spur immunity data */ + if (finalSpur == AR_NO_SPUR) { + /* Disable Spur Immunity Regs if they appear set */ + if (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER) { + /* Clear Spur Delta Phase, Spur Freq, and enable bits */ + OS_REG_RMW_FIELD(ah, AR_PHY_MASK_CTL, AR_PHY_MASK_CTL_RATE, 0); + val = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4); + val &= ~(AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | + AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | + AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + OS_REG_WRITE(ah, AR_PHY_MASK_CTL, val); + OS_REG_WRITE(ah, AR_PHY_TIMING11, 0); + + /* Clear pilot masks */ + OS_REG_WRITE(ah, AR_PHY_TIMING7, 0); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING8, AR_PHY_TIMING8_PILOT_MASK_2, 0); + OS_REG_WRITE(ah, AR_PHY_TIMING9, 0); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING10, AR_PHY_TIMING10_PILOT_MASK_2, 0); + + /* Clear magnitude masks */ + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, 0); + OS_REG_RMW_FIELD(ah, AR_PHY_MASK_CTL, AR_PHY_MASK_CTL_MASK_4, 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, 0); + OS_REG_RMW_FIELD(ah, AR_PHY_BIN_MASK2_4, AR_PHY_BIN_MASK2_4_MASK_4, 0); + } + } else { + spurOffset = finalSpur - curChanAsSpur; + /* + * Spur calculations: + * spurDeltaPhase is (spurOffsetIn100KHz / chipFrequencyIn100KHz) << 21 + * spurFreqSd is (spurOffsetIn100KHz / sampleFrequencyIn100KHz) << 11 + */ + switch (ichan->channelFlags & CHANNEL_ALL) { + case CHANNEL_A: /* Chip Frequency & sampleFrequency are 40 MHz */ + spurDeltaPhase = (spurOffset << 17) / 25; + spurFreqSd = spurDeltaPhase >> 10; + binWidth = HAL_BIN_WIDTH_BASE_100HZ; + break; + case CHANNEL_G: /* Chip Frequency is 44MHz, sampleFrequency is 40 MHz */ + spurFreqSd = (spurOffset << 8) / 55; + spurDeltaPhase = (spurOffset << 17) / 25; + binWidth = HAL_BIN_WIDTH_BASE_100HZ; + break; + case CHANNEL_T: /* Chip Frequency & sampleFrequency are 80 MHz */ + case CHANNEL_108G: + spurDeltaPhase = (spurOffset << 16) / 25; + spurFreqSd = spurDeltaPhase >> 10; + binWidth = HAL_BIN_WIDTH_TURBO_100HZ; + break; + } + + /* Compute Pilot Mask */ + binOffsetNumT16 = ((spurOffset * 1000) << 4) / binWidth; + /* The spur is on a bin if it's remainder at times 16 is 0 */ + if (binOffsetNumT16 & 0xF) { + numBinOffsets = 4; + pMagMap = magMapFor4; + } else { + numBinOffsets = 3; + pMagMap = magMapFor3; + } + for (i = 0; i < numBinOffsets; i++) { + if ((binOffsetNumT16 >> 4) > HAL_MAX_BINS_ALLOWED) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "Too man bins in spur mitigation\n"); + return; + } + + /* Get Pilot Mask values */ + curBinOffset = (binOffsetNumT16 >> 4) + i + 25; + if ((curBinOffset >= 0) && (curBinOffset <= 32)) { + if (curBinOffset <= 25) + pilotMask[0] |= 1 << curBinOffset; + else if (curBinOffset >= 27) + pilotMask[0] |= 1 << (curBinOffset - 1); + } else if ((curBinOffset >= 33) && (curBinOffset <= 52)) + pilotMask[1] |= 1 << (curBinOffset - 33); + + /* Get viterbi values */ + if ((curBinOffset >= -1) && (curBinOffset <= 14)) + binMagMask[0] |= pMagMap[i] << (curBinOffset + 1) * 2; + else if ((curBinOffset >= 15) && (curBinOffset <= 30)) + binMagMask[1] |= pMagMap[i] << (curBinOffset - 15) * 2; + else if ((curBinOffset >= 31) && (curBinOffset <= 46)) + binMagMask[2] |= pMagMap[i] << (curBinOffset -31) * 2; + else if((curBinOffset >= 47) && (curBinOffset <= 53)) + binMagMask[3] |= pMagMap[i] << (curBinOffset -47) * 2; + } + + /* Write Spur Delta Phase, Spur Freq, and enable bits */ + OS_REG_RMW_FIELD(ah, AR_PHY_MASK_CTL, AR_PHY_MASK_CTL_RATE, 0xFF); + val = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4); + val |= (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | + AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | + AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4, val); + OS_REG_WRITE(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_USE_SPUR_IN_AGC | + SM(spurFreqSd, AR_PHY_TIMING11_SPUR_FREQ_SD) | + SM(spurDeltaPhase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); + + /* Write pilot masks */ + OS_REG_WRITE(ah, AR_PHY_TIMING7, pilotMask[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING8, AR_PHY_TIMING8_PILOT_MASK_2, pilotMask[1]); + OS_REG_WRITE(ah, AR_PHY_TIMING9, pilotMask[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING10, AR_PHY_TIMING10_PILOT_MASK_2, pilotMask[1]); + + /* Write magnitude masks */ + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, binMagMask[0]); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, binMagMask[1]); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, binMagMask[2]); + OS_REG_RMW_FIELD(ah, AR_PHY_MASK_CTL, AR_PHY_MASK_CTL_MASK_4, binMagMask[3]); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, binMagMask[0]); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, binMagMask[1]); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, binMagMask[2]); + OS_REG_RMW_FIELD(ah, AR_PHY_BIN_MASK2_4, AR_PHY_BIN_MASK2_4_MASK_4, binMagMask[3]); + } +#undef CHAN_TO_SPUR +} + + +/* + * Delta slope coefficient computation. + * Required for OFDM operation. + */ +void +ar5212SetDeltaSlope(struct ath_hal *ah, HAL_CHANNEL *chan) +{ +#define COEF_SCALE_S 24 +#define INIT_CLOCKMHZSCALED 0x64000000 + unsigned long coef_scaled, coef_exp, coef_man, ds_coef_exp, ds_coef_man; + unsigned long clockMhzScaled = INIT_CLOCKMHZSCALED; + + if (IS_CHAN_TURBO(chan)) + clockMhzScaled *= 2; + /* half and quarter rate can divide the scaled clock by 2 or 4 respectively */ + /* scale for selected channel bandwidth */ + if (IS_CHAN_HALF_RATE(chan)) { + clockMhzScaled = clockMhzScaled >> 1; + } else if (IS_CHAN_QUARTER_RATE(chan)) { + clockMhzScaled = clockMhzScaled >> 2; + } + + /* + * ALGO -> coef = 1e8/fcarrier*fclock/40; + * scaled coef to provide precision for this floating calculation + */ + coef_scaled = clockMhzScaled / chan->channel; + + /* + * ALGO -> coef_exp = 14-floor(log2(coef)); + * floor(log2(x)) is the highest set bit position + */ + for (coef_exp = 31; coef_exp > 0; coef_exp--) + if ((coef_scaled >> coef_exp) & 0x1) + break; + /* A coef_exp of 0 is a legal bit position but an unexpected coef_exp */ + HALASSERT(coef_exp); + coef_exp = 14 - (coef_exp - COEF_SCALE_S); + + /* + * ALGO -> coef_man = floor(coef* 2^coef_exp+0.5); + * The coefficient is already shifted up for scaling + */ + coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1)); + ds_coef_man = coef_man >> (COEF_SCALE_S - coef_exp); + ds_coef_exp = coef_exp - 16; + + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3, + AR_PHY_TIMING3_DSC_MAN, ds_coef_man); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3, + AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); +#undef INIT_CLOCKMHZSCALED +#undef COEF_SCALE_S +} + +/* + * Set a limit on the overall output power. Used for dynamic + * transmit power control and the like. + * + * NB: limit is in units of 0.5 dbM. + */ +HAL_BOOL +ar5212SetTxPowerLimit(struct ath_hal *ah, uint32_t limit) +{ + uint16_t dummyXpdGains[2]; + HAL_BOOL ret, isBmode = AH_FALSE; + + SAVE_CCK(ah, AH_PRIVATE(ah)->ah_curchan, isBmode); + AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER); + ret = ar5212SetTransmitPower(ah, AH_PRIVATE(ah)->ah_curchan, + dummyXpdGains); + RESTORE_CCK(ah, AH_PRIVATE(ah)->ah_curchan, isBmode); + return ret; +} + +/* + * Set the transmit power in the baseband for the given + * operating channel and mode. + */ +HAL_BOOL +ar5212SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, + uint16_t *rfXpdGain) +{ +#define POW_OFDM(_r, _s) (((0 & 1)<< ((_s)+6)) | (((_r) & 0x3f) << (_s))) +#define POW_CCK(_r, _s) (((_r) & 0x3f) << (_s)) +#define N(a) (sizeof (a) / sizeof (a[0])) + static const uint16_t tpcScaleReductionTable[5] = + { 0, 3, 6, 9, MAX_RATE_POWER }; + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + int16_t minPower, maxPower, tpcInDb, powerLimit; + int i; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + OS_MEMZERO(ahp->ah_pcdacTable, ahp->ah_pcdacTableSize); + OS_MEMZERO(ahp->ah_ratesArray, sizeof(ahp->ah_ratesArray)); + + powerLimit = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit); + if (powerLimit >= MAX_RATE_POWER || powerLimit == 0) + tpcInDb = tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale]; + else + tpcInDb = 0; + if (!ar5212SetRateTable(ah, (HAL_CHANNEL *) chan, tpcInDb, powerLimit, + AH_TRUE, &minPower, &maxPower)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set rate table\n", + __func__); + return AH_FALSE; + } + if (!ahp->ah_rfHal->setPowerTable(ah, + &minPower, &maxPower, chan, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set power table\n", + __func__); + return AH_FALSE; + } + + /* + * Adjust XR power/rate up by 2 dB to account for greater peak + * to avg ratio - except in newer avg power designs + */ + if (!IS_2413(ah) && !IS_5413(ah)) + ahp->ah_ratesArray[15] += 4; + /* + * txPowerIndexOffset is set by the SetPowerTable() call - + * adjust the rate table + */ + for (i = 0; i < N(ahp->ah_ratesArray); i++) { + ahp->ah_ratesArray[i] += ahp->ah_txPowerIndexOffset; + if (ahp->ah_ratesArray[i] > 63) + ahp->ah_ratesArray[i] = 63; + } + + if (ee->ee_eepMap < 2) { + /* + * Correct gain deltas for 5212 G operation - + * Removed with revised chipset + */ + if (AH_PRIVATE(ah)->ah_phyRev < AR_PHY_CHIP_ID_REV_2 && + IS_CHAN_G(chan)) { + uint16_t cckOfdmPwrDelta; + + if (chan->channel == 2484) + cckOfdmPwrDelta = SCALE_OC_DELTA( + ee->ee_cckOfdmPwrDelta - + ee->ee_scaledCh14FilterCckDelta); + else + cckOfdmPwrDelta = SCALE_OC_DELTA( + ee->ee_cckOfdmPwrDelta); + ar5212CorrectGainDelta(ah, cckOfdmPwrDelta); + } + /* + * Finally, write the power values into the + * baseband power table + */ + for (i = 0; i < (PWR_TABLE_SIZE/2); i++) { + OS_REG_WRITE(ah, AR_PHY_PCDAC_TX_POWER(i), + ((((ahp->ah_pcdacTable[2*i + 1] << 8) | 0xff) & 0xffff) << 16) + | (((ahp->ah_pcdacTable[2*i] << 8) | 0xff) & 0xffff) + ); + } + } + + /* Write the OFDM power per rate set */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, + POW_OFDM(ahp->ah_ratesArray[3], 24) + | POW_OFDM(ahp->ah_ratesArray[2], 16) + | POW_OFDM(ahp->ah_ratesArray[1], 8) + | POW_OFDM(ahp->ah_ratesArray[0], 0) + ); + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, + POW_OFDM(ahp->ah_ratesArray[7], 24) + | POW_OFDM(ahp->ah_ratesArray[6], 16) + | POW_OFDM(ahp->ah_ratesArray[5], 8) + | POW_OFDM(ahp->ah_ratesArray[4], 0) + ); + + /* Write the CCK power per rate set */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, + POW_CCK(ahp->ah_ratesArray[10], 24) + | POW_CCK(ahp->ah_ratesArray[9], 16) + | POW_CCK(ahp->ah_ratesArray[15], 8) /* XR target power */ + | POW_CCK(ahp->ah_ratesArray[8], 0) + ); + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, + POW_CCK(ahp->ah_ratesArray[14], 24) + | POW_CCK(ahp->ah_ratesArray[13], 16) + | POW_CCK(ahp->ah_ratesArray[12], 8) + | POW_CCK(ahp->ah_ratesArray[11], 0) + ); + + /* + * Set max power to 30 dBm and, optionally, + * enable TPC in tx descriptors. + */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER | + (ahp->ah_tpcEnabled ? AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE : 0)); + + return AH_TRUE; +#undef N +#undef POW_CCK +#undef POW_OFDM +} + +/* + * Sets the transmit power in the baseband for the given + * operating channel and mode. + */ +static HAL_BOOL +ar5212SetRateTable(struct ath_hal *ah, HAL_CHANNEL *chan, + int16_t tpcScaleReduction, int16_t powerLimit, HAL_BOOL commit, + int16_t *pMinPower, int16_t *pMaxPower) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t *rpow = ahp->ah_ratesArray; + uint16_t twiceMaxEdgePower = MAX_RATE_POWER; + uint16_t twiceMaxEdgePowerCck = MAX_RATE_POWER; + uint16_t twiceMaxRDPower = MAX_RATE_POWER; + int i; + uint8_t cfgCtl; + int8_t twiceAntennaGain, twiceAntennaReduction; + const RD_EDGES_POWER *rep; + TRGT_POWER_INFO targetPowerOfdm, targetPowerCck; + int16_t scaledPower, maxAvailPower = 0; + int16_t r13, r9, r7, r0; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + twiceMaxRDPower = chan->maxRegTxPower * 2; + *pMaxPower = -MAX_RATE_POWER; + *pMinPower = MAX_RATE_POWER; + + /* Get conformance test limit maximum for this channel */ + cfgCtl = ath_hal_getctl(ah, chan); + for (i = 0; i < ee->ee_numCtls; i++) { + uint16_t twiceMinEdgePower; + + if (ee->ee_ctl[i] == 0) + continue; + if (ee->ee_ctl[i] == cfgCtl || + cfgCtl == ((ee->ee_ctl[i] & CTL_MODE_M) | SD_NO_CTL)) { + rep = &ee->ee_rdEdgesPower[i * NUM_EDGES]; + twiceMinEdgePower = ar5212GetMaxEdgePower(chan->channel, rep); + if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { + /* Find the minimum of all CTL edge powers that apply to this channel */ + twiceMaxEdgePower = AH_MIN(twiceMaxEdgePower, twiceMinEdgePower); + } else { + twiceMaxEdgePower = twiceMinEdgePower; + break; + } + } + } + + if (IS_CHAN_G(chan)) { + /* Check for a CCK CTL for 11G CCK powers */ + cfgCtl = (cfgCtl & ~CTL_MODE_M) | CTL_11B; + for (i = 0; i < ee->ee_numCtls; i++) { + uint16_t twiceMinEdgePowerCck; + + if (ee->ee_ctl[i] == 0) + continue; + if (ee->ee_ctl[i] == cfgCtl || + cfgCtl == ((ee->ee_ctl[i] & CTL_MODE_M) | SD_NO_CTL)) { + rep = &ee->ee_rdEdgesPower[i * NUM_EDGES]; + twiceMinEdgePowerCck = ar5212GetMaxEdgePower(chan->channel, rep); + if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { + /* Find the minimum of all CTL edge powers that apply to this channel */ + twiceMaxEdgePowerCck = AH_MIN(twiceMaxEdgePowerCck, twiceMinEdgePowerCck); + } else { + twiceMaxEdgePowerCck = twiceMinEdgePowerCck; + break; + } + } + } + } else { + /* Set the 11B cck edge power to the one found before */ + twiceMaxEdgePowerCck = twiceMaxEdgePower; + } + + /* Get Antenna Gain reduction */ + if (IS_CHAN_5GHZ(chan)) { + ath_hal_eepromGet(ah, AR_EEP_ANTGAINMAX_5, &twiceAntennaGain); + } else { + ath_hal_eepromGet(ah, AR_EEP_ANTGAINMAX_2, &twiceAntennaGain); + } + twiceAntennaReduction = + ath_hal_getantennareduction(ah, chan, twiceAntennaGain); + + if (IS_CHAN_OFDM(chan)) { + /* Get final OFDM target powers */ + if (IS_CHAN_2GHZ(chan)) { + ar5212GetTargetPowers(ah, chan, ee->ee_trgtPwr_11g, + ee->ee_numTargetPwr_11g, &targetPowerOfdm); + } else { + ar5212GetTargetPowers(ah, chan, ee->ee_trgtPwr_11a, + ee->ee_numTargetPwr_11a, &targetPowerOfdm); + } + + /* Get Maximum OFDM power */ + /* Minimum of target and edge powers */ + scaledPower = AH_MIN(twiceMaxEdgePower, + twiceMaxRDPower - twiceAntennaReduction); + + /* + * If turbo is set, reduce power to keep power + * consumption under 2 Watts. Note that we always do + * this unless specially configured. Then we limit + * power only for non-AP operation. + */ + if (IS_CHAN_TURBO(chan) +#ifdef AH_ENABLE_AP_SUPPORT + && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP +#endif + ) { + /* + * If turbo is set, reduce power to keep power + * consumption under 2 Watts + */ + if (ee->ee_version >= AR_EEPROM_VER3_1) + scaledPower = AH_MIN(scaledPower, + ee->ee_turbo2WMaxPower5); + /* + * EEPROM version 4.0 added an additional + * constraint on 2.4GHz channels. + */ + if (ee->ee_version >= AR_EEPROM_VER4_0 && + IS_CHAN_2GHZ(chan)) + scaledPower = AH_MIN(scaledPower, + ee->ee_turbo2WMaxPower2); + } + + maxAvailPower = AH_MIN(scaledPower, + targetPowerOfdm.twicePwr6_24); + + /* Reduce power by max regulatory domain allowed restrictions */ + scaledPower = maxAvailPower - (tpcScaleReduction * 2); + scaledPower = (scaledPower < 0) ? 0 : scaledPower; + scaledPower = AH_MIN(scaledPower, powerLimit); + + if (commit) { + /* Set OFDM rates 9, 12, 18, 24 */ + r0 = rpow[0] = rpow[1] = rpow[2] = rpow[3] = rpow[4] = scaledPower; + + /* Set OFDM rates 36, 48, 54, XR */ + rpow[5] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr36); + rpow[6] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr48); + r7 = rpow[7] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr54); + + if (ee->ee_version >= AR_EEPROM_VER4_0) { + /* Setup XR target power from EEPROM */ + rpow[15] = AH_MIN(scaledPower, IS_CHAN_2GHZ(chan) ? + ee->ee_xrTargetPower2 : ee->ee_xrTargetPower5); + } else { + /* XR uses 6mb power */ + rpow[15] = rpow[0]; + } + ahp->ah_ofdmTxPower = *pMaxPower; + + } else { + r0 = scaledPower; + r7 = AH_MIN(r0, targetPowerOfdm.twicePwr54); + } + *pMinPower = r7; + *pMaxPower = r0; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: MaxRD: %d TurboMax: %d MaxCTL: %d " + "TPC_Reduction %d chan=%d (0x%x) maxAvailPower=%d pwr6_24=%d, maxPower=%d\n", + __func__, twiceMaxRDPower, ee->ee_turbo2WMaxPower5, + twiceMaxEdgePower, tpcScaleReduction * 2, + chan->channel, chan->channelFlags, + maxAvailPower, targetPowerOfdm.twicePwr6_24, *pMaxPower); + } + + if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) { + /* Get final CCK target powers */ + ar5212GetTargetPowers(ah, chan, ee->ee_trgtPwr_11b, + ee->ee_numTargetPwr_11b, &targetPowerCck); + + /* Reduce power by max regulatory domain allowed restrictions */ + scaledPower = AH_MIN(twiceMaxEdgePowerCck, + twiceMaxRDPower - twiceAntennaReduction); + if (maxAvailPower < AH_MIN(scaledPower, targetPowerCck.twicePwr6_24)) + maxAvailPower = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24); + + /* Reduce power by user selection */ + scaledPower = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24) - (tpcScaleReduction * 2); + scaledPower = (scaledPower < 0) ? 0 : scaledPower; + scaledPower = AH_MIN(scaledPower, powerLimit); + + if (commit) { + /* Set CCK rates 2L, 2S, 5.5L, 5.5S, 11L, 11S */ + rpow[8] = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24); + r9 = rpow[9] = AH_MIN(scaledPower, targetPowerCck.twicePwr36); + rpow[10] = rpow[9]; + rpow[11] = AH_MIN(scaledPower, targetPowerCck.twicePwr48); + rpow[12] = rpow[11]; + r13 = rpow[13] = AH_MIN(scaledPower, targetPowerCck.twicePwr54); + rpow[14] = rpow[13]; + } else { + r9 = AH_MIN(scaledPower, targetPowerCck.twicePwr36); + r13 = AH_MIN(scaledPower, targetPowerCck.twicePwr54); + } + + /* Set min/max power based off OFDM values or initialization */ + if (r13 < *pMinPower) + *pMinPower = r13; + if (r9 > *pMaxPower) + *pMaxPower = r9; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: cck: MaxRD: %d MaxCTL: %d " + "TPC_Reduction %d chan=%d (0x%x) maxAvailPower=%d pwr6_24=%d, maxPower=%d\n", + __func__, twiceMaxRDPower, twiceMaxEdgePowerCck, + tpcScaleReduction * 2, chan->channel, chan->channelFlags, + maxAvailPower, targetPowerCck.twicePwr6_24, *pMaxPower); + } + if (commit) { + ahp->ah_tx6PowerInHalfDbm = *pMaxPower; + AH_PRIVATE(ah)->ah_maxPowerLevel = ahp->ah_tx6PowerInHalfDbm; + } + return AH_TRUE; +} + +HAL_BOOL +ar5212GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, uint32_t nchans) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + static const uint16_t tpcScaleReductionTable[5] = + { 0, 3, 6, 9, MAX_RATE_POWER }; + int16_t minPower, maxPower, tpcInDb, powerLimit; + HAL_CHANNEL *chan; + int i; + + /* + * Get Pier table max and min powers. + */ + for (i = 0; i < nchans; i++) { + chan = &chans[i]; + if (ahp->ah_rfHal->getChannelMaxMinPower(ah, chan, &maxPower, &minPower)) { + /* NB: rf code returns 1/4 dBm units, convert */ + chan->maxTxPower = maxPower / 2; + chan->minTxPower = minPower / 2; + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: no min/max power for %u/0x%x\n", + __func__, chan->channel, chan->channelFlags); + chan->maxTxPower = MAX_RATE_POWER; + chan->minTxPower = 0; + } + } + /* + * Now adjust to reflect any global scale and/or CTL's. + * (XXX is that correct?) + */ + powerLimit = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit); + if (powerLimit >= MAX_RATE_POWER || powerLimit == 0) + tpcInDb = tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale]; + else + tpcInDb = 0; + for (i=0; imaxTxPower) + chan->maxTxPower = maxPower; + if (minPower < chan->minTxPower) + chan->minTxPower = minPower; + } +#ifdef AH_DEBUG + for (i=0; i ofdm 6, 9, .. 48, 54 + * [8..14] --> cck 1L, 2L, 2S, .. 11L, 11S + * [15] --> XR (all rates get the same power) + * 2. powv[ii] is the pcdac corresponding to ii/2 dBm. + */ +static void +ar5212CorrectGainDelta(struct ath_hal *ah, int twiceOfdmCckDelta) +{ +#define N(_a) (sizeof(_a) / sizeof(_a[0])) + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + int16_t ratesIndex[N(ahp->ah_ratesArray)]; + uint16_t ii, jj, iter; + int32_t cckIndex; + int16_t gainDeltaAdjust; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + gainDeltaAdjust = ee->ee_cckOfdmGainDelta; + + /* make a local copy of desired powers as initial indices */ + OS_MEMCPY(ratesIndex, ahp->ah_ratesArray, sizeof(ratesIndex)); + + /* fix only the CCK indices */ + for (ii = 8; ii < 15; ii++) { + /* apply a gain_delta correction of -15 for CCK */ + ratesIndex[ii] -= gainDeltaAdjust; + + /* Now check for contention with all ofdm target powers */ + jj = 0; + iter = 0; + /* indicates not all ofdm rates checked forcontention yet */ + while (jj < 16) { + if (ratesIndex[ii] < 0) + ratesIndex[ii] = 0; + if (jj == 8) { /* skip CCK rates */ + jj = 15; + continue; + } + if (ratesIndex[ii] == ahp->ah_ratesArray[jj]) { + if (ahp->ah_ratesArray[jj] == 0) + ratesIndex[ii]++; + else if (iter > 50) { + /* + * To avoid pathological case of of + * dm target powers 0 and 0.5dBm + */ + ratesIndex[ii]++; + } else + ratesIndex[ii]--; + /* check with all rates again */ + jj = 0; + iter++; + } else + jj++; + } + if (ratesIndex[ii] >= PWR_TABLE_SIZE) + ratesIndex[ii] = PWR_TABLE_SIZE -1; + cckIndex = ahp->ah_ratesArray[ii] - twiceOfdmCckDelta; + if (cckIndex < 0) + cckIndex = 0; + + /* + * Validate that the indexes for the powv are not + * out of bounds. + */ + HALASSERT(cckIndex < PWR_TABLE_SIZE); + HALASSERT(ratesIndex[ii] < PWR_TABLE_SIZE); + ahp->ah_pcdacTable[ratesIndex[ii]] = + ahp->ah_pcdacTable[cckIndex]; + } + /* Override rate per power table with new values */ + for (ii = 8; ii < 15; ii++) + ahp->ah_ratesArray[ii] = ratesIndex[ii]; +#undef N +} + +/* + * Find the maximum conformance test limit for the given channel and CTL info + */ +static uint16_t +ar5212GetMaxEdgePower(uint16_t channel, const RD_EDGES_POWER *pRdEdgesPower) +{ + /* temp array for holding edge channels */ + uint16_t tempChannelList[NUM_EDGES]; + uint16_t clo, chi, twiceMaxEdgePower; + int i, numEdges; + + /* Get the edge power */ + for (i = 0; i < NUM_EDGES; i++) { + if (pRdEdgesPower[i].rdEdge == 0) + break; + tempChannelList[i] = pRdEdgesPower[i].rdEdge; + } + numEdges = i; + + ar5212GetLowerUpperValues(channel, tempChannelList, + numEdges, &clo, &chi); + /* Get the index for the lower channel */ + for (i = 0; i < numEdges && clo != tempChannelList[i]; i++) + ; + /* Is lower channel ever outside the rdEdge? */ + HALASSERT(i != numEdges); + + if ((clo == chi && clo == channel) || (pRdEdgesPower[i].flag)) { + /* + * If there's an exact channel match or an inband flag set + * on the lower channel use the given rdEdgePower + */ + twiceMaxEdgePower = pRdEdgesPower[i].twice_rdEdgePower; + HALASSERT(twiceMaxEdgePower > 0); + } else + twiceMaxEdgePower = MAX_RATE_POWER; + return twiceMaxEdgePower; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static uint16_t +interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + uint16_t targetLeft, uint16_t targetRight) +{ + uint16_t rv; + int16_t lRatio; + + /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */ + if ((targetLeft * targetRight) == 0) + return 0; + + if (srcRight != srcLeft) { + /* + * Note the ratio always need to be scaled, + * since it will be a fraction. + */ + lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft); + if (lRatio < 0) { + /* Return as Left target if value would be negative */ + rv = targetLeft; + } else if (lRatio > EEP_SCALE) { + /* Return as Right target if Ratio is greater than 100% (SCALE) */ + rv = targetRight; + } else { + rv = (lRatio * targetRight + (EEP_SCALE - lRatio) * + targetLeft) / EEP_SCALE; + } + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Return the four rates of target power for the given target power table + * channel, and number of channels + */ +static void +ar5212GetTargetPowers(struct ath_hal *ah, HAL_CHANNEL *chan, + const TRGT_POWER_INFO *powInfo, + uint16_t numChannels, TRGT_POWER_INFO *pNewPower) +{ + /* temp array for holding target power channels */ + uint16_t tempChannelList[NUM_TEST_FREQUENCIES]; + uint16_t clo, chi, ixlo, ixhi; + int i; + + /* Copy the target powers into the temp channel list */ + for (i = 0; i < numChannels; i++) + tempChannelList[i] = powInfo[i].testChannel; + + ar5212GetLowerUpperValues(chan->channel, tempChannelList, + numChannels, &clo, &chi); + + /* Get the indices for the channel */ + ixlo = ixhi = 0; + for (i = 0; i < numChannels; i++) { + if (clo == tempChannelList[i]) { + ixlo = i; + } + if (chi == tempChannelList[i]) { + ixhi = i; + break; + } + } + + /* + * Get the lower and upper channels, target powers, + * and interpolate between them. + */ + pNewPower->twicePwr6_24 = interpolate(chan->channel, clo, chi, + powInfo[ixlo].twicePwr6_24, powInfo[ixhi].twicePwr6_24); + pNewPower->twicePwr36 = interpolate(chan->channel, clo, chi, + powInfo[ixlo].twicePwr36, powInfo[ixhi].twicePwr36); + pNewPower->twicePwr48 = interpolate(chan->channel, clo, chi, + powInfo[ixlo].twicePwr48, powInfo[ixhi].twicePwr48); + pNewPower->twicePwr54 = interpolate(chan->channel, clo, chi, + powInfo[ixlo].twicePwr54, powInfo[ixhi].twicePwr54); +} + +/* + * Search a list for a specified value v that is within + * EEP_DELTA of the search values. Return the closest + * values in the list above and below the desired value. + * EEP_DELTA is a factional value; everything is scaled + * so only integer arithmetic is used. + * + * NB: the input list is assumed to be sorted in ascending order + */ +void +ar5212GetLowerUpperValues(uint16_t v, uint16_t *lp, uint16_t listSize, + uint16_t *vlo, uint16_t *vhi) +{ + uint32_t target = v * EEP_SCALE; + uint16_t *ep = lp+listSize; + + /* + * Check first and last elements for out-of-bounds conditions. + */ + if (target < (uint32_t)(lp[0] * EEP_SCALE - EEP_DELTA)) { + *vlo = *vhi = lp[0]; + return; + } + if (target > (uint32_t)(ep[-1] * EEP_SCALE + EEP_DELTA)) { + *vlo = *vhi = ep[-1]; + return; + } + + /* look for value being near or between 2 values in list */ + for (; lp < ep; lp++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (abs(lp[0] * EEP_SCALE - target) < EEP_DELTA) { + *vlo = *vhi = lp[0]; + return; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < (uint32_t)(lp[1] * EEP_SCALE - EEP_DELTA)) { + *vlo = lp[0]; + *vhi = lp[1]; + return; + } + } + HALASSERT(AH_FALSE); /* should not reach here */ +} + +/* + * Perform analog "swizzling" of parameters into their location + * + * NB: used by RF backends + */ +void +ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, uint32_t numBits, + uint32_t firstBit, uint32_t column) +{ +#define MAX_ANALOG_START 319 /* XXX */ + uint32_t tmp32, mask, arrayEntry, lastBit; + int32_t bitPosition, bitsLeft; + + HALASSERT(column <= 3); + HALASSERT(numBits <= 32); + HALASSERT(firstBit + numBits <= MAX_ANALOG_START); + + tmp32 = ath_hal_reverseBits(reg32, numBits); + arrayEntry = (firstBit - 1) / 8; + bitPosition = (firstBit - 1) % 8; + bitsLeft = numBits; + while (bitsLeft > 0) { + lastBit = (bitPosition + bitsLeft > 8) ? + 8 : bitPosition + bitsLeft; + mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) << + (column * 8); + rfBuf[arrayEntry] &= ~mask; + rfBuf[arrayEntry] |= ((tmp32 << bitPosition) << + (column * 8)) & mask; + bitsLeft -= 8 - bitPosition; + tmp32 = tmp32 >> (8 - bitPosition); + bitPosition = 0; + arrayEntry++; + } +#undef MAX_ANALOG_START +} + +/* + * Sets the rate to duration values in MAC - used for multi- + * rate retry. + * The rate duration table needs to cover all valid rate codes; + * the 11g table covers all ofdm rates, while the 11b table + * covers all cck rates => all valid rates get covered between + * these two mode's ratetables! + * But if we're turbo, the ofdm phy is replaced by the turbo phy + * and cck is not valid with turbo => all rates get covered + * by the turbo ratetable only + */ +void +ar5212SetRateDurationTable(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + const HAL_RATE_TABLE *rt; + int i; + + /* NB: band doesn't matter for 1/2 and 1/4 rate */ + if (IS_CHAN_HALF_RATE(chan)) { + rt = ar5212GetRateTable(ah, HAL_MODE_11A_HALF_RATE); + } else if (IS_CHAN_QUARTER_RATE(chan)) { + rt = ar5212GetRateTable(ah, HAL_MODE_11A_QUARTER_RATE); + } else { + rt = ar5212GetRateTable(ah, + IS_CHAN_TURBO(chan) ? HAL_MODE_TURBO : HAL_MODE_11G); + } + + for (i = 0; i < rt->rateCount; ++i) + OS_REG_WRITE(ah, + AR_RATE_DURATION(rt->info[i].rateCode), + ath_hal_computetxtime(ah, rt, + WLAN_CTRL_FRAME_SIZE, + rt->info[i].controlRate, AH_FALSE)); + if (!IS_CHAN_TURBO(chan)) { + /* 11g Table is used to cover the CCK rates. */ + rt = ar5212GetRateTable(ah, HAL_MODE_11G); + for (i = 0; i < rt->rateCount; ++i) { + uint32_t reg = AR_RATE_DURATION(rt->info[i].rateCode); + + if (rt->info[i].phy != IEEE80211_T_CCK) + continue; + + OS_REG_WRITE(ah, reg, + ath_hal_computetxtime(ah, rt, + WLAN_CTRL_FRAME_SIZE, + rt->info[i].controlRate, AH_FALSE)); + /* cck rates have short preamble option also */ + if (rt->info[i].shortPreamble) { + reg += rt->info[i].shortPreamble << 2; + OS_REG_WRITE(ah, reg, + ath_hal_computetxtime(ah, rt, + WLAN_CTRL_FRAME_SIZE, + rt->info[i].controlRate, + AH_TRUE)); + } + } + } +} + +/* Adjust various register settings based on half/quarter rate clock setting. + * This includes: +USEC, TX/RX latency, + * + IFS params: slot, eifs, misc etc. + */ +void +ar5212SetIFSTiming(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + uint32_t txLat, rxLat, usec, slot, refClock, eifs, init_usec; + + HALASSERT(IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)); + + refClock = OS_REG_READ(ah, AR_USEC) & AR_USEC_USEC32; + if (IS_CHAN_HALF_RATE(chan)) { + slot = IFS_SLOT_HALF_RATE; + rxLat = RX_NON_FULL_RATE_LATENCY << AR5212_USEC_RX_LAT_S; + txLat = TX_HALF_RATE_LATENCY << AR5212_USEC_TX_LAT_S; + usec = HALF_RATE_USEC; + eifs = IFS_EIFS_HALF_RATE; + init_usec = INIT_USEC >> 1; + } else { /* quarter rate */ + slot = IFS_SLOT_QUARTER_RATE; + rxLat = RX_NON_FULL_RATE_LATENCY << AR5212_USEC_RX_LAT_S; + txLat = TX_QUARTER_RATE_LATENCY << AR5212_USEC_TX_LAT_S; + usec = QUARTER_RATE_USEC; + eifs = IFS_EIFS_QUARTER_RATE; + init_usec = INIT_USEC >> 2; + } + + OS_REG_WRITE(ah, AR_USEC, (usec | refClock | txLat | rxLat)); + OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot); + OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs); + OS_REG_RMW_FIELD(ah, AR_D_GBL_IFS_MISC, + AR_D_GBL_IFS_MISC_USEC_DURATION, init_usec); +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_rfgain.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_rfgain.c new file mode 100644 index 0000000000..8448ed7b1b --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_rfgain.c @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212_rfgain.c,v 1.2 2008/11/19 21:23:01 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#include "ah_eeprom_v3.h" + +static const GAIN_OPTIMIZATION_LADDER gainLadder = { + 9, /* numStepsInLadder */ + 4, /* defaultStepNum */ + { { {4, 1, 1, 1}, 6, "FG8"}, + { {4, 0, 1, 1}, 4, "FG7"}, + { {3, 1, 1, 1}, 3, "FG6"}, + { {4, 0, 0, 1}, 1, "FG5"}, + { {4, 1, 1, 0}, 0, "FG4"}, /* noJack */ + { {4, 0, 1, 0}, -2, "FG3"}, /* halfJack */ + { {3, 1, 1, 0}, -3, "FG2"}, /* clip3 */ + { {4, 0, 0, 0}, -4, "FG1"}, /* noJack */ + { {2, 1, 1, 0}, -6, "FG0"} /* clip2 */ + } +}; + +static const GAIN_OPTIMIZATION_LADDER gainLadder5112 = { + 8, /* numStepsInLadder */ + 1, /* defaultStepNum */ + { { {3, 0,0,0, 0,0,0}, 6, "FG7"}, /* most fixed gain */ + { {2, 0,0,0, 0,0,0}, 0, "FG6"}, + { {1, 0,0,0, 0,0,0}, -3, "FG5"}, + { {0, 0,0,0, 0,0,0}, -6, "FG4"}, + { {0, 1,1,0, 0,0,0}, -8, "FG3"}, + { {0, 1,1,0, 1,1,0}, -10, "FG2"}, + { {0, 1,0,1, 1,1,0}, -13, "FG1"}, + { {0, 1,0,1, 1,0,1}, -16, "FG0"}, /* least fixed gain */ + } +}; + +/* + * Initialize the gain structure to good values + */ +void +ar5212InitializeGainValues(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + GAIN_VALUES *gv = &ahp->ah_gainValues; + + /* initialize gain optimization values */ + if (IS_RAD5112_ANY(ah)) { + gv->currStepNum = gainLadder5112.defaultStepNum; + gv->currStep = + &gainLadder5112.optStep[gainLadder5112.defaultStepNum]; + gv->active = AH_TRUE; + gv->loTrig = 20; + gv->hiTrig = 85; + } else { + gv->currStepNum = gainLadder.defaultStepNum; + gv->currStep = &gainLadder.optStep[gainLadder.defaultStepNum]; + gv->active = AH_TRUE; + gv->loTrig = 20; + gv->hiTrig = 35; + } +} + +#define MAX_ANALOG_START 319 /* XXX */ + +/* + * Find analog bits of given parameter data and return a reversed value + */ +static uint32_t +ar5212GetRfField(uint32_t *rfBuf, uint32_t numBits, uint32_t firstBit, uint32_t column) +{ + uint32_t reg32 = 0, mask, arrayEntry, lastBit; + uint32_t bitPosition, bitsShifted; + int32_t bitsLeft; + + HALASSERT(column <= 3); + HALASSERT(numBits <= 32); + HALASSERT(firstBit + numBits <= MAX_ANALOG_START); + + arrayEntry = (firstBit - 1) / 8; + bitPosition = (firstBit - 1) % 8; + bitsLeft = numBits; + bitsShifted = 0; + while (bitsLeft > 0) { + lastBit = (bitPosition + bitsLeft > 8) ? + (8) : (bitPosition + bitsLeft); + mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) << + (column * 8); + reg32 |= (((rfBuf[arrayEntry] & mask) >> (column * 8)) >> + bitPosition) << bitsShifted; + bitsShifted += lastBit - bitPosition; + bitsLeft -= (8 - bitPosition); + bitPosition = 0; + arrayEntry++; + } + reg32 = ath_hal_reverseBits(reg32, numBits); + return reg32; +} + +static HAL_BOOL +ar5212InvalidGainReadback(struct ath_hal *ah, GAIN_VALUES *gv) +{ + uint32_t gStep, g, mixOvr; + uint32_t L1, L2, L3, L4; + + if (IS_RAD5112_ANY(ah)) { + mixOvr = ar5212GetRfField(ar5212GetRfBank(ah, 7), 1, 36, 0); + L1 = 0; + L2 = 107; + L3 = 0; + L4 = 107; + if (mixOvr == 1) { + L2 = 83; + L4 = 83; + gv->hiTrig = 55; + } + } else { + gStep = ar5212GetRfField(ar5212GetRfBank(ah, 7), 6, 37, 0); + + L1 = 0; + L2 = (gStep == 0x3f) ? 50 : gStep + 4; + L3 = (gStep != 0x3f) ? 0x40 : L1; + L4 = L3 + 50; + + gv->loTrig = L1 + (gStep == 0x3f ? DYN_ADJ_LO_MARGIN : 0); + /* never adjust if != 0x3f */ + gv->hiTrig = L4 - (gStep == 0x3f ? DYN_ADJ_UP_MARGIN : -5); + } + g = gv->currGain; + + return !((g >= L1 && g<= L2) || (g >= L3 && g <= L4)); +} + +/* + * Enable the probe gain check on the next packet + */ +void +ar5212RequestRfgain(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t probePowerIndex; + + /* Enable the gain readback probe */ + probePowerIndex = ahp->ah_ofdmTxPower + ahp->ah_txPowerIndexOffset; + OS_REG_WRITE(ah, AR_PHY_PAPD_PROBE, + SM(probePowerIndex, AR_PHY_PAPD_PROBE_POWERTX) + | AR_PHY_PAPD_PROBE_NEXT_TX); + + ahp->ah_rfgainState = HAL_RFGAIN_READ_REQUESTED; +} + +/* + * Check to see if our readback gain level sits within the linear + * region of our current variable attenuation window + */ +static HAL_BOOL +ar5212IsGainAdjustNeeded(struct ath_hal *ah, const GAIN_VALUES *gv) +{ + return (gv->currGain <= gv->loTrig || gv->currGain >= gv->hiTrig); +} + +/* + * Move the rabbit ears in the correct direction. + */ +static int32_t +ar5212AdjustGain(struct ath_hal *ah, GAIN_VALUES *gv) +{ + const GAIN_OPTIMIZATION_LADDER *gl; + + if (IS_RAD5112_ANY(ah)) + gl = &gainLadder5112; + else + gl = &gainLadder; + gv->currStep = &gl->optStep[gv->currStepNum]; + if (gv->currGain >= gv->hiTrig) { + if (gv->currStepNum == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Max gain limit.\n", + __func__); + return -1; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Adding gain: currG=%d [%s] --> ", + __func__, gv->currGain, gv->currStep->stepName); + gv->targetGain = gv->currGain; + while (gv->targetGain >= gv->hiTrig && gv->currStepNum > 0) { + gv->targetGain -= 2 * (gl->optStep[--(gv->currStepNum)].stepGain - + gv->currStep->stepGain); + gv->currStep = &gl->optStep[gv->currStepNum]; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n", + gv->targetGain, gv->currStep->stepName); + return 1; + } + if (gv->currGain <= gv->loTrig) { + if (gv->currStepNum == gl->numStepsInLadder-1) { + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Min gain limit.\n", __func__); + return -2; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Deducting gain: currG=%d [%s] --> ", + __func__, gv->currGain, gv->currStep->stepName); + gv->targetGain = gv->currGain; + while (gv->targetGain <= gv->loTrig && + gv->currStepNum < (gl->numStepsInLadder - 1)) { + gv->targetGain -= 2 * + (gl->optStep[++(gv->currStepNum)].stepGain - gv->currStep->stepGain); + gv->currStep = &gl->optStep[gv->currStepNum]; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n", + gv->targetGain, gv->currStep->stepName); + return 2; + } + return 0; /* caller didn't call needAdjGain first */ +} + +/* + * Read rf register to determine if gainF needs correction + */ +static void +ar5212GetGainFCorrection(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + GAIN_VALUES *gv = &ahp->ah_gainValues; + + HALASSERT(IS_RADX112_REV2(ah)); + + gv->gainFCorrection = 0; + if (ar5212GetRfField(ar5212GetRfBank(ah, 7), 1, 36, 0) == 1) { + uint32_t mixGain = gv->currStep->paramVal[0]; + uint32_t gainStep = + ar5212GetRfField(ar5212GetRfBank(ah, 7), 4, 32, 0); + switch (mixGain) { + case 0 : + gv->gainFCorrection = 0; + break; + case 1 : + gv->gainFCorrection = gainStep; + break; + case 2 : + gv->gainFCorrection = 2 * gainStep - 5; + break; + case 3 : + gv->gainFCorrection = 2 * gainStep; + break; + } + } +} + +/* + * Exported call to check for a recent gain reading and return + * the current state of the thermal calibration gain engine. + */ +HAL_RFGAIN +ar5212GetRfgain(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + GAIN_VALUES *gv = &ahp->ah_gainValues; + uint32_t rddata, probeType; + + if (!gv->active) + return HAL_RFGAIN_INACTIVE; + + if (ahp->ah_rfgainState == HAL_RFGAIN_READ_REQUESTED) { + /* Caller had asked to setup a new reading. Check it. */ + rddata = OS_REG_READ(ah, AR_PHY_PAPD_PROBE); + + if ((rddata & AR_PHY_PAPD_PROBE_NEXT_TX) == 0) { + /* bit got cleared, we have a new reading. */ + gv->currGain = rddata >> AR_PHY_PAPD_PROBE_GAINF_S; + probeType = MS(rddata, AR_PHY_PAPD_PROBE_TYPE); + if (probeType == AR_PHY_PAPD_PROBE_TYPE_CCK) { + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + + HALASSERT(IS_RAD5112_ANY(ah)); + HALASSERT(ah->ah_magic == AR5212_MAGIC); + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) + gv->currGain += ee->ee_cckOfdmGainDelta; + else + gv->currGain += PHY_PROBE_CCK_CORRECTION; + } + if (IS_RADX112_REV2(ah)) { + ar5212GetGainFCorrection(ah); + if (gv->currGain >= gv->gainFCorrection) + gv->currGain -= gv->gainFCorrection; + else + gv->currGain = 0; + } + /* inactive by default */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + if (!ar5212InvalidGainReadback(ah, gv) && + ar5212IsGainAdjustNeeded(ah, gv) && + ar5212AdjustGain(ah, gv) > 0) { + /* + * Change needed. Copy ladder info + * into eeprom info. + */ + ahp->ah_rfgainState = HAL_RFGAIN_NEED_CHANGE; + /* for ap51 */ + ahp->ah_cwCalRequire = AH_TRUE; + /* Request IQ recalibration for temperature chang */ + ahp->ah_bIQCalibration = IQ_CAL_INACTIVE; + } + } + } + return ahp->ah_rfgainState; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_xmit.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_xmit.c new file mode 100644 index 0000000000..8b4f85cf83 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212_xmit.c @@ -0,0 +1,918 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212_xmit.c,v 1.7 2008/11/10 04:08:03 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212desc.h" +#include "ar5212/ar5212phy.h" +#ifdef AH_SUPPORT_5311 +#include "ar5212/ar5311reg.h" +#endif + +#ifdef AH_NEED_DESC_SWAP +static void ar5212SwapTxDesc(struct ath_desc *ds); +#endif + +/* + * Update Tx FIFO trigger level. + * + * Set bIncTrigLevel to TRUE to increase the trigger level. + * Set bIncTrigLevel to FALSE to decrease the trigger level. + * + * Returns TRUE if the trigger level was updated + */ +HAL_BOOL +ar5212UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t txcfg, curLevel, newLevel; + HAL_INT omask; + + /* + * Disable interrupts while futzing with the fifo level. + */ + omask = ar5212SetInterrupts(ah, ahp->ah_maskReg &~ HAL_INT_GLOBAL); + + txcfg = OS_REG_READ(ah, AR_TXCFG); + curLevel = MS(txcfg, AR_FTRIG); + newLevel = curLevel; + if (bIncTrigLevel) { /* increase the trigger level */ + if (curLevel < MAX_TX_FIFO_THRESHOLD) + newLevel++; + } else if (curLevel > MIN_TX_FIFO_THRESHOLD) + newLevel--; + if (newLevel != curLevel) + /* Update the trigger level */ + OS_REG_WRITE(ah, AR_TXCFG, + (txcfg &~ AR_FTRIG) | SM(newLevel, AR_FTRIG)); + + /* re-enable chip interrupts */ + ar5212SetInterrupts(ah, omask); + + return (newLevel != curLevel); +} + +/* + * Set the properties of the tx queue with the parameters + * from qInfo. + */ +HAL_BOOL +ar5212SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + if (q >= pCap->halTotalQueues) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], qInfo); +} + +/* + * Return the properties for the specified tx queue. + */ +HAL_BOOL +ar5212GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + + if (q >= pCap->halTotalQueues) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + return ath_hal_getTxQProps(ah, qInfo, &ahp->ah_txq[q]); +} + +/* + * Allocate and initialize a tx DCU/QCU combination. + */ +int +ar5212SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_TX_QUEUE_INFO *qi; + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + int q, defqflags; + + /* by default enable OK+ERR+DESC+URN interrupts */ + defqflags = HAL_TXQ_TXOKINT_ENABLE + | HAL_TXQ_TXERRINT_ENABLE + | HAL_TXQ_TXDESCINT_ENABLE + | HAL_TXQ_TXURNINT_ENABLE; + /* XXX move queue assignment to driver */ + switch (type) { + case HAL_TX_QUEUE_BEACON: + q = pCap->halTotalQueues-1; /* highest priority */ + defqflags |= HAL_TXQ_DBA_GATED + | HAL_TXQ_CBR_DIS_QEMPTY + | HAL_TXQ_ARB_LOCKOUT_GLOBAL + | HAL_TXQ_BACKOFF_DISABLE; + break; + case HAL_TX_QUEUE_CAB: + q = pCap->halTotalQueues-2; /* next highest priority */ + defqflags |= HAL_TXQ_DBA_GATED + | HAL_TXQ_CBR_DIS_QEMPTY + | HAL_TXQ_CBR_DIS_BEMPTY + | HAL_TXQ_ARB_LOCKOUT_GLOBAL + | HAL_TXQ_BACKOFF_DISABLE; + break; + case HAL_TX_QUEUE_UAPSD: + q = pCap->halTotalQueues-3; /* nextest highest priority */ + if (ahp->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: no available UAPSD tx queue\n", __func__); + return -1; + } + break; + case HAL_TX_QUEUE_DATA: + for (q = 0; q < pCap->halTotalQueues; q++) + if (ahp->ah_txq[q].tqi_type == HAL_TX_QUEUE_INACTIVE) + break; + if (q == pCap->halTotalQueues) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: no available tx queue\n", __func__); + return -1; + } + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: bad tx queue type %u\n", __func__, type); + return -1; + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + + qi = &ahp->ah_txq[q]; + if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n", + __func__, q); + return -1; + } + OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO)); + qi->tqi_type = type; + if (qInfo == AH_NULL) { + qi->tqi_qflags = defqflags; + qi->tqi_aifs = INIT_AIFS; + qi->tqi_cwmin = HAL_TXQ_USEDEFAULT; /* NB: do at reset */ + qi->tqi_cwmax = INIT_CWMAX; + qi->tqi_shretry = INIT_SH_RETRY; + qi->tqi_lgretry = INIT_LG_RETRY; + qi->tqi_physCompBuf = 0; + } else { + qi->tqi_physCompBuf = qInfo->tqi_compBuf; + (void) ar5212SetTxQueueProps(ah, q, qInfo); + } + /* NB: must be followed by ar5212ResetTxQueue */ + return q; +} + +/* + * Update the h/w interrupt registers to reflect a tx q's configuration. + */ +static void +setTxQInterrupts(struct ath_hal *ah, HAL_TX_QUEUE_INFO *qi) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", __func__, + ahp->ah_txOkInterruptMask, ahp->ah_txErrInterruptMask, + ahp->ah_txDescInterruptMask, ahp->ah_txEolInterruptMask, + ahp->ah_txUrnInterruptMask); + + OS_REG_WRITE(ah, AR_IMR_S0, + SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK) + | SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC) + ); + OS_REG_WRITE(ah, AR_IMR_S1, + SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR) + | SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL) + ); + OS_REG_RMW_FIELD(ah, AR_IMR_S2, + AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask); +} + +/* + * Free a tx DCU/QCU combination. + */ +HAL_BOOL +ar5212ReleaseTxQueue(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + HAL_TX_QUEUE_INFO *qi; + + if (q >= pCap->halTotalQueues) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + return AH_FALSE; + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: release queue %u\n", __func__, q); + + qi->tqi_type = HAL_TX_QUEUE_INACTIVE; + ahp->ah_txOkInterruptMask &= ~(1 << q); + ahp->ah_txErrInterruptMask &= ~(1 << q); + ahp->ah_txDescInterruptMask &= ~(1 << q); + ahp->ah_txEolInterruptMask &= ~(1 << q); + ahp->ah_txUrnInterruptMask &= ~(1 << q); + setTxQInterrupts(ah, qi); + + return AH_TRUE; +} + +/* + * Set the retry, aifs, cwmin/max, readyTime regs for specified queue + * Assumes: + * phwChannel has been set to point to the current channel + */ +HAL_BOOL +ar5212ResetTxQueue(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan; + HAL_TX_QUEUE_INFO *qi; + uint32_t cwMin, chanCwMin, value, qmisc, dmisc; + + if (q >= pCap->halTotalQueues) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + return AH_TRUE; /* XXX??? */ + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: reset queue %u\n", __func__, q); + + if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) { + /* + * Select cwmin according to channel type. + * NB: chan can be NULL during attach + */ + if (chan && IS_CHAN_B(chan)) + chanCwMin = INIT_CWMIN_11B; + else + chanCwMin = INIT_CWMIN; + /* make sure that the CWmin is of the form (2^n - 1) */ + for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1) + ; + } else + cwMin = qi->tqi_cwmin; + + /* set cwMin/Max and AIFS values */ + OS_REG_WRITE(ah, AR_DLCL_IFS(q), + SM(cwMin, AR_D_LCL_IFS_CWMIN) + | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) + | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); + + /* Set retry limit values */ + OS_REG_WRITE(ah, AR_DRETRY_LIMIT(q), + SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) + | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) + | SM(qi->tqi_lgretry, AR_D_RETRY_LIMIT_FR_LG) + | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH) + ); + + /* NB: always enable early termination on the QCU */ + qmisc = AR_Q_MISC_DCU_EARLY_TERM_REQ + | SM(AR_Q_MISC_FSP_ASAP, AR_Q_MISC_FSP); + + /* NB: always enable DCU to wait for next fragment from QCU */ + dmisc = AR_D_MISC_FRAG_WAIT_EN; + +#ifdef AH_SUPPORT_5311 + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) { + /* Configure DCU to use the global sequence count */ + dmisc |= AR5311_D_MISC_SEQ_NUM_CONTROL; + } +#endif + /* multiqueue support */ + if (qi->tqi_cbrPeriod) { + OS_REG_WRITE(ah, AR_QCBRCFG(q), + SM(qi->tqi_cbrPeriod,AR_Q_CBRCFG_CBR_INTERVAL) + | SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_CBR_OVF_THRESH)); + qmisc = (qmisc &~ AR_Q_MISC_FSP) | AR_Q_MISC_FSP_CBR; + if (qi->tqi_cbrOverflowLimit) + qmisc |= AR_Q_MISC_CBR_EXP_CNTR_LIMIT; + } + if (qi->tqi_readyTime) { + OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), + SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_INT) + | AR_Q_RDYTIMECFG_ENA); + } + + OS_REG_WRITE(ah, AR_DCHNTIME(q), + SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) + | (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); + + if (qi->tqi_readyTime && + (qi->tqi_qflags & HAL_TXQ_RDYTIME_EXP_POLICY_ENABLE)) + qmisc |= AR_Q_MISC_RDYTIME_EXP_POLICY; + if (qi->tqi_qflags & HAL_TXQ_DBA_GATED) + qmisc = (qmisc &~ AR_Q_MISC_FSP) | AR_Q_MISC_FSP_DBA_GATED; + if (MS(qmisc, AR_Q_MISC_FSP) != AR_Q_MISC_FSP_ASAP) { + /* + * These are meangingful only when not scheduled asap. + */ + if (qi->tqi_qflags & HAL_TXQ_CBR_DIS_BEMPTY) + qmisc |= AR_Q_MISC_CBR_INCR_DIS0; + else + qmisc &= ~AR_Q_MISC_CBR_INCR_DIS0; + if (qi->tqi_qflags & HAL_TXQ_CBR_DIS_QEMPTY) + qmisc |= AR_Q_MISC_CBR_INCR_DIS1; + else + qmisc &= ~AR_Q_MISC_CBR_INCR_DIS1; + } + + if (qi->tqi_qflags & HAL_TXQ_BACKOFF_DISABLE) + dmisc |= AR_D_MISC_POST_FR_BKOFF_DIS; + if (qi->tqi_qflags & HAL_TXQ_FRAG_BURST_BACKOFF_ENABLE) + dmisc |= AR_D_MISC_FRAG_BKOFF_EN; + if (qi->tqi_qflags & HAL_TXQ_ARB_LOCKOUT_GLOBAL) + dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, + AR_D_MISC_ARB_LOCKOUT_CNTRL); + else if (qi->tqi_qflags & HAL_TXQ_ARB_LOCKOUT_INTRA) + dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR, + AR_D_MISC_ARB_LOCKOUT_CNTRL); + if (qi->tqi_qflags & HAL_TXQ_IGNORE_VIRTCOL) + dmisc |= SM(AR_D_MISC_VIR_COL_HANDLING_IGNORE, + AR_D_MISC_VIR_COL_HANDLING); + if (qi->tqi_qflags & HAL_TXQ_SEQNUM_INC_DIS) + dmisc |= AR_D_MISC_SEQ_NUM_INCR_DIS; + + /* + * Fillin type-dependent bits. Most of this can be + * removed by specifying the queue parameters in the + * driver; it's here for backwards compatibility. + */ + switch (qi->tqi_type) { + case HAL_TX_QUEUE_BEACON: /* beacon frames */ + qmisc |= AR_Q_MISC_FSP_DBA_GATED + | AR_Q_MISC_BEACON_USE + | AR_Q_MISC_CBR_INCR_DIS1; + + dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, + AR_D_MISC_ARB_LOCKOUT_CNTRL) + | AR_D_MISC_BEACON_USE + | AR_D_MISC_POST_FR_BKOFF_DIS; + break; + case HAL_TX_QUEUE_CAB: /* CAB frames */ + /* + * No longer Enable AR_Q_MISC_RDYTIME_EXP_POLICY, + * There is an issue with the CAB Queue + * not properly refreshing the Tx descriptor if + * the TXE clear setting is used. + */ + qmisc |= AR_Q_MISC_FSP_DBA_GATED + | AR_Q_MISC_CBR_INCR_DIS1 + | AR_Q_MISC_CBR_INCR_DIS0; + + if (!qi->tqi_readyTime) { + /* + * NB: don't set default ready time if driver + * has explicitly specified something. This is + * here solely for backwards compatibility. + */ + value = (ahp->ah_beaconInterval + - (ath_hal_sw_beacon_response_time - + ath_hal_dma_beacon_response_time) + - ath_hal_additional_swba_backoff) * 1024; + OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), value | AR_Q_RDYTIMECFG_ENA); + } + dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, + AR_D_MISC_ARB_LOCKOUT_CNTRL); + break; + default: /* NB: silence compiler */ + break; + } + + OS_REG_WRITE(ah, AR_QMISC(q), qmisc); + OS_REG_WRITE(ah, AR_DMISC(q), dmisc); + + /* Setup compression scratchpad buffer */ + /* + * XXX: calling this asynchronously to queue operation can + * cause unexpected behavior!!! + */ + if (qi->tqi_physCompBuf) { + HALASSERT(qi->tqi_type == HAL_TX_QUEUE_DATA || + qi->tqi_type == HAL_TX_QUEUE_UAPSD); + OS_REG_WRITE(ah, AR_Q_CBBS, (80 + 2*q)); + OS_REG_WRITE(ah, AR_Q_CBBA, qi->tqi_physCompBuf); + OS_REG_WRITE(ah, AR_Q_CBC, HAL_COMP_BUF_MAX_SIZE/1024); + OS_REG_WRITE(ah, AR_Q0_MISC + 4*q, + OS_REG_READ(ah, AR_Q0_MISC + 4*q) + | AR_Q_MISC_QCU_COMP_EN); + } + + /* + * Always update the secondary interrupt mask registers - this + * could be a new queue getting enabled in a running system or + * hw getting re-initialized during a reset! + * + * Since we don't differentiate between tx interrupts corresponding + * to individual queues - secondary tx mask regs are always unmasked; + * tx interrupts are enabled/disabled for all queues collectively + * using the primary mask reg + */ + if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE) + ahp->ah_txOkInterruptMask |= 1 << q; + else + ahp->ah_txOkInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE) + ahp->ah_txErrInterruptMask |= 1 << q; + else + ahp->ah_txErrInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE) + ahp->ah_txDescInterruptMask |= 1 << q; + else + ahp->ah_txDescInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE) + ahp->ah_txEolInterruptMask |= 1 << q; + else + ahp->ah_txEolInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE) + ahp->ah_txUrnInterruptMask |= 1 << q; + else + ahp->ah_txUrnInterruptMask &= ~(1 << q); + setTxQInterrupts(ah, qi); + + return AH_TRUE; +} + +/* + * Get the TXDP for the specified queue + */ +uint32_t +ar5212GetTxDP(struct ath_hal *ah, u_int q) +{ + HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); + return OS_REG_READ(ah, AR_QTXDP(q)); +} + +/* + * Set the TxDP for the specified queue + */ +HAL_BOOL +ar5212SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp) +{ + HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); + HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + /* + * Make sure that TXE is deasserted before setting the TXDP. If TXE + * is still asserted, setting TXDP will have no effect. + */ + HALASSERT((OS_REG_READ(ah, AR_Q_TXE) & (1 << q)) == 0); + + OS_REG_WRITE(ah, AR_QTXDP(q), txdp); + + return AH_TRUE; +} + +/* + * Set Transmit Enable bits for the specified queue + */ +HAL_BOOL +ar5212StartTxDma(struct ath_hal *ah, u_int q) +{ + HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); + + HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + + /* Check to be sure we're not enabling a q that has its TXD bit set. */ + HALASSERT((OS_REG_READ(ah, AR_Q_TXD) & (1 << q)) == 0); + + OS_REG_WRITE(ah, AR_Q_TXE, 1 << q); + return AH_TRUE; +} + +/* + * Return the number of pending frames or 0 if the specified + * queue is stopped. + */ +uint32_t +ar5212NumTxPending(struct ath_hal *ah, u_int q) +{ + uint32_t npend; + + HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); + HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + npend = OS_REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT; + if (npend == 0) { + /* + * Pending frame count (PFC) can momentarily go to zero + * while TXE remains asserted. In other words a PFC of + * zero is not sufficient to say that the queue has stopped. + */ + if (OS_REG_READ(ah, AR_Q_TXE) & (1 << q)) + npend = 1; /* arbitrarily return 1 */ + } + return npend; +} + +/* + * Stop transmit on the specified queue + */ +HAL_BOOL +ar5212StopTxDma(struct ath_hal *ah, u_int q) +{ + u_int i; + u_int wait; + + HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); + + HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + OS_REG_WRITE(ah, AR_Q_TXD, 1 << q); + for (i = 1000; i != 0; i--) { + if (ar5212NumTxPending(ah, q) == 0) + break; + OS_DELAY(100); /* XXX get actual value */ + } +#ifdef AH_DEBUG + if (i == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: queue %u DMA did not stop in 100 msec\n", __func__, q); + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: QSTS 0x%x Q_TXE 0x%x Q_TXD 0x%x Q_CBR 0x%x\n", __func__, + OS_REG_READ(ah, AR_QSTS(q)), OS_REG_READ(ah, AR_Q_TXE), + OS_REG_READ(ah, AR_Q_TXD), OS_REG_READ(ah, AR_QCBRCFG(q))); + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Q_MISC 0x%x Q_RDYTIMECFG 0x%x Q_RDYTIMESHDN 0x%x\n", + __func__, OS_REG_READ(ah, AR_QMISC(q)), + OS_REG_READ(ah, AR_QRDYTIMECFG(q)), + OS_REG_READ(ah, AR_Q_RDYTIMESHDN)); + } +#endif /* AH_DEBUG */ + + /* 2413+ and up can kill packets at the PCU level */ + if (ar5212NumTxPending(ah, q) && + (IS_2413(ah) || IS_5413(ah) || IS_2425(ah) || IS_2417(ah))) { + uint32_t tsfLow, j; + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: Num of pending TX Frames %d on Q %d\n", + __func__, ar5212NumTxPending(ah, q), q); + + /* Kill last PCU Tx Frame */ + /* TODO - save off and restore current values of Q1/Q2? */ + for (j = 0; j < 2; j++) { + tsfLow = OS_REG_READ(ah, AR_TSF_L32); + OS_REG_WRITE(ah, AR_QUIET2, SM(100, AR_QUIET2_QUIET_PER) | + SM(10, AR_QUIET2_QUIET_DUR)); + OS_REG_WRITE(ah, AR_QUIET1, AR_QUIET1_QUIET_ENABLE | + SM(tsfLow >> 10, AR_QUIET1_NEXT_QUIET)); + if ((OS_REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) { + break; + } + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: TSF moved while trying to set quiet time " + "TSF: 0x%08x\n", __func__, tsfLow); + HALASSERT(j < 1); /* TSF shouldn't count twice or reg access is taking forever */ + } + + OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE); + + /* Allow the quiet mechanism to do its work */ + OS_DELAY(200); + OS_REG_CLR_BIT(ah, AR_QUIET1, AR_QUIET1_QUIET_ENABLE); + + /* Give at least 1 millisec more to wait */ + wait = 100; + + /* Verify all transmit is dead */ + while (ar5212NumTxPending(ah, q)) { + if ((--wait) == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Failed to stop Tx DMA in %d msec after killing last frame\n", + __func__, wait); + break; + } + OS_DELAY(10); + } + + OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE); + } + + OS_REG_WRITE(ah, AR_Q_TXD, 0); + return (i != 0); +} + +/* + * Descriptor Access Functions + */ + +#define VALID_PKT_TYPES \ + ((1<ah_txPowerIndexOffset ); + if(txPower > 63) txPower=63; + + ads->ds_ctl0 = (pktLen & AR_FrameLen) + | (txPower << AR_XmitPower_S) + | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0) + | (flags & HAL_TXDESC_CLRDMASK ? AR_ClearDestMask : 0) + | SM(antMode, AR_AntModeXmit) + | (flags & HAL_TXDESC_INTREQ ? AR_TxInterReq : 0) + ; + ads->ds_ctl1 = (type << AR_FrmType_S) + | (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0) + | (comp << AR_CompProc_S) + | (compicvLen << AR_CompICVLen_S) + | (compivLen << AR_CompIVLen_S) + ; + ads->ds_ctl2 = SM(txTries0, AR_XmitDataTries0) + | (flags & HAL_TXDESC_DURENA ? AR_DurUpdateEna : 0) + ; + ads->ds_ctl3 = (txRate0 << AR_XmitRate0_S) + ; + if (keyIx != HAL_TXKEYIX_INVALID) { + /* XXX validate key index */ + ads->ds_ctl1 |= SM(keyIx, AR_DestIdx); + ads->ds_ctl0 |= AR_DestIdxValid; + } + if (flags & RTSCTS) { + if (!isValidTxRate(rtsctsRate)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid rts/cts rate 0x%x\n", + __func__, rtsctsRate); + return AH_FALSE; + } + /* XXX validate rtsctsDuration */ + ads->ds_ctl0 |= (flags & HAL_TXDESC_CTSENA ? AR_CTSEnable : 0) + | (flags & HAL_TXDESC_RTSENA ? AR_RTSCTSEnable : 0) + ; + ads->ds_ctl2 |= SM(rtsctsDuration, AR_RTSCTSDuration); + ads->ds_ctl3 |= (rtsctsRate << AR_RTSCTSRate_S); + } + return AH_TRUE; +#undef RTSCTS +} + +HAL_BOOL +ar5212SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int txRate1, u_int txTries1, + u_int txRate2, u_int txTries2, + u_int txRate3, u_int txTries3) +{ + struct ar5212_desc *ads = AR5212DESC(ds); + + if (txTries1) { + HALASSERT(isValidTxRate(txRate1)); + ads->ds_ctl2 |= SM(txTries1, AR_XmitDataTries1) + | AR_DurUpdateEna + ; + ads->ds_ctl3 |= (txRate1 << AR_XmitRate1_S); + } + if (txTries2) { + HALASSERT(isValidTxRate(txRate2)); + ads->ds_ctl2 |= SM(txTries2, AR_XmitDataTries2) + | AR_DurUpdateEna + ; + ads->ds_ctl3 |= (txRate2 << AR_XmitRate2_S); + } + if (txTries3) { + HALASSERT(isValidTxRate(txRate3)); + ads->ds_ctl2 |= SM(txTries3, AR_XmitDataTries3) + | AR_DurUpdateEna + ; + ads->ds_ctl3 |= (txRate3 << AR_XmitRate3_S); + } + return AH_TRUE; +} + +void +ar5212IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *ds) +{ + struct ar5212_desc *ads = AR5212DESC(ds); + +#ifdef AH_NEED_DESC_SWAP + ads->ds_ctl0 |= __bswap32(AR_TxInterReq); +#else + ads->ds_ctl0 |= AR_TxInterReq; +#endif +} + +HAL_BOOL +ar5212FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg, + const struct ath_desc *ds0) +{ + struct ar5212_desc *ads = AR5212DESC(ds); + + HALASSERT((segLen &~ AR_BufLen) == 0); + + if (firstSeg) { + /* + * First descriptor, don't clobber xmit control data + * setup by ar5212SetupTxDesc. + */ + ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_More); + } else if (lastSeg) { /* !firstSeg && lastSeg */ + /* + * Last descriptor in a multi-descriptor frame, + * copy the multi-rate transmit parameters from + * the first frame for processing on completion. + */ + ads->ds_ctl0 = 0; + ads->ds_ctl1 = segLen; +#ifdef AH_NEED_DESC_SWAP + ads->ds_ctl2 = __bswap32(AR5212DESC_CONST(ds0)->ds_ctl2); + ads->ds_ctl3 = __bswap32(AR5212DESC_CONST(ds0)->ds_ctl3); +#else + ads->ds_ctl2 = AR5212DESC_CONST(ds0)->ds_ctl2; + ads->ds_ctl3 = AR5212DESC_CONST(ds0)->ds_ctl3; +#endif + } else { /* !firstSeg && !lastSeg */ + /* + * Intermediate descriptor in a multi-descriptor frame. + */ + ads->ds_ctl0 = 0; + ads->ds_ctl1 = segLen | AR_More; + ads->ds_ctl2 = 0; + ads->ds_ctl3 = 0; + } + ads->ds_txstatus0 = ads->ds_txstatus1 = 0; + return AH_TRUE; +} + +#ifdef AH_NEED_DESC_SWAP +/* Swap transmit descriptor */ +static __inline void +ar5212SwapTxDesc(struct ath_desc *ds) +{ + ds->ds_data = __bswap32(ds->ds_data); + ds->ds_ctl0 = __bswap32(ds->ds_ctl0); + ds->ds_ctl1 = __bswap32(ds->ds_ctl1); + ds->ds_hw[0] = __bswap32(ds->ds_hw[0]); + ds->ds_hw[1] = __bswap32(ds->ds_hw[1]); + ds->ds_hw[2] = __bswap32(ds->ds_hw[2]); + ds->ds_hw[3] = __bswap32(ds->ds_hw[3]); +} +#endif + +/* + * Processing of HW TX descriptor. + */ +HAL_STATUS +ar5212ProcTxDesc(struct ath_hal *ah, + struct ath_desc *ds, struct ath_tx_status *ts) +{ + struct ar5212_desc *ads = AR5212DESC(ds); + +#ifdef AH_NEED_DESC_SWAP + if ((ads->ds_txstatus1 & __bswap32(AR_Done)) == 0) + return HAL_EINPROGRESS; + + ar5212SwapTxDesc(ds); +#else + if ((ads->ds_txstatus1 & AR_Done) == 0) + return HAL_EINPROGRESS; +#endif + + /* Update software copies of the HW status */ + ts->ts_seqnum = MS(ads->ds_txstatus1, AR_SeqNum); + ts->ts_tstamp = MS(ads->ds_txstatus0, AR_SendTimestamp); + ts->ts_status = 0; + if ((ads->ds_txstatus0 & AR_FrmXmitOK) == 0) { + if (ads->ds_txstatus0 & AR_ExcessiveRetries) + ts->ts_status |= HAL_TXERR_XRETRY; + if (ads->ds_txstatus0 & AR_Filtered) + ts->ts_status |= HAL_TXERR_FILT; + if (ads->ds_txstatus0 & AR_FIFOUnderrun) + ts->ts_status |= HAL_TXERR_FIFO; + } + /* + * Extract the transmit rate used and mark the rate as + * ``alternate'' if it wasn't the series 0 rate. + */ + ts->ts_finaltsi = MS(ads->ds_txstatus1, AR_FinalTSIndex); + switch (ts->ts_finaltsi) { + case 0: + ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate0); + break; + case 1: + ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate1) | + HAL_TXSTAT_ALTRATE; + break; + case 2: + ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate2) | + HAL_TXSTAT_ALTRATE; + break; + case 3: + ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate3) | + HAL_TXSTAT_ALTRATE; + break; + } + ts->ts_rssi = MS(ads->ds_txstatus1, AR_AckSigStrength); + ts->ts_shortretry = MS(ads->ds_txstatus0, AR_RTSFailCnt); + ts->ts_longretry = MS(ads->ds_txstatus0, AR_DataFailCnt); + /* + * The retry count has the number of un-acked tries for the + * final series used. When doing multi-rate retry we must + * fixup the retry count by adding in the try counts for + * each series that was fully-processed. Beware that this + * takes values from the try counts in the final descriptor. + * These are not required by the hardware. We assume they + * are placed there by the driver as otherwise we have no + * access and the driver can't do the calculation because it + * doesn't know the descriptor format. + */ + switch (ts->ts_finaltsi) { + case 3: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries2); + case 2: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries1); + case 1: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries0); + } + ts->ts_virtcol = MS(ads->ds_txstatus0, AR_VirtCollCnt); + ts->ts_antenna = (ads->ds_txstatus1 & AR_XmitAtenna ? 2 : 1); + + return HAL_OK; +} + +/* + * Determine which tx queues need interrupt servicing. + */ +void +ar5212GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + *txqs &= ahp->ah_intrTxqs; + ahp->ah_intrTxqs &= ~(*txqs); +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212desc.h b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212desc.h new file mode 100644 index 0000000000..9885c9fbae --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212desc.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212desc.h,v 1.4 2008/11/10 04:08:03 sam Exp $ + */ +#ifndef _ATH_AR5212_DESC_H_ +#define _ATH_AR5212_DESC_H_ + +/* + * Hardware-specific descriptor structures. + */ +#include "ah_desc.h" + +/* + * AR5212-specific tx/rx descriptor definition. + */ +struct ar5212_desc { + uint32_t ds_link; /* link pointer */ + uint32_t ds_data; /* data buffer pointer */ + uint32_t ds_ctl0; /* DMA control 0 */ + uint32_t ds_ctl1; /* DMA control 1 */ + union { + struct { /* xmit format */ + uint32_t ctl2; /* DMA control 2 */ + uint32_t ctl3; /* DMA control 3 */ + uint32_t status0;/* DMA status 0 */ + uint32_t status1;/* DMA status 1 */ + } tx; + struct { /* recv format */ + uint32_t status0;/* DMA status 0 */ + uint32_t status1;/* DMA status 1 */ + } rx; + } u; +} __packed; +#define AR5212DESC(_ds) ((struct ar5212_desc *)(_ds)) +#define AR5212DESC_CONST(_ds) ((const struct ar5212_desc *)(_ds)) + +#define ds_ctl2 u.tx.ctl2 +#define ds_ctl3 u.tx.ctl3 +#define ds_txstatus0 u.tx.status0 +#define ds_txstatus1 u.tx.status1 +#define ds_rxstatus0 u.rx.status0 +#define ds_rxstatus1 u.rx.status1 + +/* TX ds_ctl0 */ +#define AR_FrameLen 0x00000fff /* frame length */ +/* bits 12-15 are reserved */ +#define AR_XmitPower 0x003f0000 /* transmit power control */ +#define AR_XmitPower_S 16 +#define AR_RTSCTSEnable 0x00400000 /* RTS/CTS protocol enable */ +#define AR_VEOL 0x00800000 /* virtual end-of-list */ +#define AR_ClearDestMask 0x01000000 /* Clear destination mask bit */ +#define AR_AntModeXmit 0x1e000000 /* TX antenna seslection */ +#define AR_AntModeXmit_S 25 +#define AR_TxInterReq 0x20000000 /* TX interrupt request */ +#define AR_DestIdxValid 0x40000000 /* destination index valid */ +#define AR_CTSEnable 0x80000000 /* precede frame with CTS */ + +/* TX ds_ctl1 */ +#define AR_BufLen 0x00000fff /* data buffer length */ +#define AR_More 0x00001000 /* more desc in this frame */ +#define AR_DestIdx 0x000fe000 /* destination table index */ +#define AR_DestIdx_S 13 +#define AR_FrmType 0x00f00000 /* frame type indication */ +#define AR_FrmType_S 20 +#define AR_NoAck 0x01000000 /* No ACK flag */ +#define AR_CompProc 0x06000000 /* compression processing */ +#define AR_CompProc_S 25 +#define AR_CompIVLen 0x18000000 /* length of frame IV */ +#define AR_CompIVLen_S 27 +#define AR_CompICVLen 0x60000000 /* length of frame ICV */ +#define AR_CompICVLen_S 29 +/* bit 31 is reserved */ + +/* TX ds_ctl2 */ +#define AR_RTSCTSDuration 0x00007fff /* RTS/CTS duration */ +#define AR_RTSCTSDuration_S 0 +#define AR_DurUpdateEna 0x00008000 /* frame duration update ctl */ +#define AR_XmitDataTries0 0x000f0000 /* series 0 max attempts */ +#define AR_XmitDataTries0_S 16 +#define AR_XmitDataTries1 0x00f00000 /* series 1 max attempts */ +#define AR_XmitDataTries1_S 20 +#define AR_XmitDataTries2 0x0f000000 /* series 2 max attempts */ +#define AR_XmitDataTries2_S 24 +#define AR_XmitDataTries3 0xf0000000 /* series 3 max attempts */ +#define AR_XmitDataTries3_S 28 + +/* TX ds_ctl3 */ +#define AR_XmitRate0 0x0000001f /* series 0 tx rate */ +#define AR_XmitRate0_S 0 +#define AR_XmitRate1 0x000003e0 /* series 1 tx rate */ +#define AR_XmitRate1_S 5 +#define AR_XmitRate2 0x00007c00 /* series 2 tx rate */ +#define AR_XmitRate2_S 10 +#define AR_XmitRate3 0x000f8000 /* series 3 tx rate */ +#define AR_XmitRate3_S 15 +#define AR_RTSCTSRate 0x01f00000 /* RTS or CTS rate */ +#define AR_RTSCTSRate_S 20 +/* bits 25-31 are reserved */ + +/* RX ds_ctl1 */ +/* AR_BufLen 0x00000fff data buffer length */ +/* bit 12 is reserved */ +#define AR_RxInterReq 0x00002000 /* RX interrupt request */ +/* bits 14-31 are reserved */ + +/* TX ds_txstatus0 */ +#define AR_FrmXmitOK 0x00000001 /* TX success */ +#define AR_ExcessiveRetries 0x00000002 /* excessive retries */ +#define AR_FIFOUnderrun 0x00000004 /* TX FIFO underrun */ +#define AR_Filtered 0x00000008 /* TX filter indication */ +#define AR_RTSFailCnt 0x000000f0 /* RTS failure count */ +#define AR_RTSFailCnt_S 4 +#define AR_DataFailCnt 0x00000f00 /* Data failure count */ +#define AR_DataFailCnt_S 8 +#define AR_VirtCollCnt 0x0000f000 /* virtual collision count */ +#define AR_VirtCollCnt_S 12 +#define AR_SendTimestamp 0xffff0000 /* TX timestamp */ +#define AR_SendTimestamp_S 16 + +/* RX ds_rxstatus0 */ +#define AR_DataLen 0x00000fff /* RX data length */ +/* AR_More 0x00001000 more desc in this frame */ +#define AR_DecompCRCErr 0x00002000 /* decompression CRC error */ +/* bit 14 is reserved */ +#define AR_RcvRate 0x000f8000 /* reception rate */ +#define AR_RcvRate_S 15 +#define AR_RcvSigStrength 0x0ff00000 /* receive signal strength */ +#define AR_RcvSigStrength_S 20 +#define AR_RcvAntenna 0xf0000000 /* receive antenaa */ +#define AR_RcvAntenna_S 28 + +/* TX ds_txstatus1 */ +#define AR_Done 0x00000001 /* descripter complete */ +#define AR_SeqNum 0x00001ffe /* TX sequence number */ +#define AR_SeqNum_S 1 +#define AR_AckSigStrength 0x001fe000 /* strength of ACK */ +#define AR_AckSigStrength_S 13 +#define AR_FinalTSIndex 0x00600000 /* final TX attempt series ix */ +#define AR_FinalTSIndex_S 21 +#define AR_CompSuccess 0x00800000 /* compression status */ +#define AR_XmitAtenna 0x01000000 /* transmit antenna */ +/* bits 25-31 are reserved */ + +/* RX ds_rxstatus1 */ +/* AR_Done 0x00000001 descripter complete */ +#define AR_FrmRcvOK 0x00000002 /* frame reception success */ +#define AR_CRCErr 0x00000004 /* CRC error */ +#define AR_DecryptCRCErr 0x00000008 /* Decryption CRC fiailure */ +#define AR_PHYErr 0x00000010 /* PHY error */ +#define AR_MichaelErr 0x00000020 /* Michae MIC decrypt error */ +/* bits 6-7 are reserved */ +#define AR_KeyIdxValid 0x00000100 /* decryption key index valid */ +#define AR_KeyIdx 0x0000fe00 /* Decryption key index */ +#define AR_KeyIdx_S 9 +#define AR_RcvTimestamp 0x7fff0000 /* timestamp */ +#define AR_RcvTimestamp_S 16 +#define AR_KeyCacheMiss 0x80000000 /* key cache miss indication */ + +/* NB: phy error code overlays key index and valid fields */ +#define AR_PHYErrCode 0x0000ff00 /* PHY error code */ +#define AR_PHYErrCode_S 8 + +#endif /* _ATH_AR5212_DESC_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212phy.h b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212phy.h new file mode 100644 index 0000000000..e040ec79b6 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212phy.h @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212phy.h,v 1.7 2008/11/19 21:23:01 sam Exp $ + */ +#ifndef _DEV_ATH_AR5212PHY_H_ +#define _DEV_ATH_AR5212PHY_H_ + +/* PHY registers */ +#define AR_PHY_BASE 0x9800 /* base address of phy regs */ +#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) + +#define AR_PHY_TEST 0x9800 /* PHY test control */ +#define PHY_AGC_CLR 0x10000000 /* disable AGC to A2 */ + +#define AR_PHY_TESTCTRL 0x9808 /* PHY Test Control/Status */ +#define AR_PHY_TESTCTRL_TXHOLD 0x3800 /* Select Tx hold */ +#define AR_PHY_TESTCTRL_TXSRC_ALT 0x00000080 /* Select input to tsdac along with bit 1 */ +#define AR_PHY_TESTCTRL_TXSRC_ALT_S 7 +#define AR_PHY_TESTCTRL_TXSRC_SRC 0x00000002 /* Used with bit 7 */ +#define AR_PHY_TESTCTRL_TXSRC_SRC_S 1 + +#define AR_PHY_TURBO 0x9804 /* frame control register */ +#define AR_PHY_FC_TURBO_MODE 0x00000001 /* Set turbo mode bits */ +#define AR_PHY_FC_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode setting */ +#define AR_PHY_FC_TURBO_MIMO 0x00000004 /* Set turbo for mimo mode */ + +#define AR_PHY_TIMING3 0x9814 /* Timing control 3 */ +#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000 +#define AR_PHY_TIMING3_DSC_MAN_S 17 +#define AR_PHY_TIMING3_DSC_EXP 0x0001E000 +#define AR_PHY_TIMING3_DSC_EXP_S 13 + +#define AR_PHY_CHIP_ID 0x9818 /* PHY chip revision ID */ +#define AR_PHY_CHIP_ID_REV_2 0x42 /* 5212 Rev 2 BB w. TPC fix */ +#define AR_PHY_CHIP_ID_REV_3 0x43 /* 5212 Rev 3 5213 */ +#define AR_PHY_CHIP_ID_REV_4 0x44 /* 5212 Rev 4 2313 and up */ + +#define AR_PHY_ACTIVE 0x981C /* activation register */ +#define AR_PHY_ACTIVE_EN 0x00000001 /* Activate PHY chips */ +#define AR_PHY_ACTIVE_DIS 0x00000000 /* Deactivate PHY chips */ + +#define AR_PHY_TX_CTL 0x9824 +#define AR_PHY_TX_FRAME_TO_TX_DATA_START 0x0000000f +#define AR_PHY_TX_FRAME_TO_TX_DATA_START_S 0 + +#define AR_PHY_ADC_CTL 0x982C +#define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003 +#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S 0 +#define AR_PHY_ADC_CTL_OFF_PWDDAC 0x00002000 +#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000 /* BB Rev 4.2+ only */ +#define AR_PHY_ADC_CTL_OFF_PWDADC 0x00008000 /* BB Rev 4.2+ only */ +#define AR_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000 +#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S 16 + +#define AR_PHY_BB_XP_PA_CTL 0x9838 +#define AR_PHY_BB_XPAA_ACTIVE_HIGH 0x00000001 +#define AR_PHY_BB_XPAB_ACTIVE_HIGH 0x00000002 +#define AR_PHY_BB_XPAB_ACTIVE_HIGH_S 1 + +#define AR_PHY_TSTDAC_CONST 0x983C +#define AR_PHY_TSTDAC_CONST_Q 0x0003FE00 +#define AR_PHY_TSTDAC_CONST_Q_S 9 +#define AR_PHY_TSTDAC_CONST_I 0x000001FF + + +#define AR_PHY_SETTLING 0x9844 +#define AR_PHY_SETTLING_AGC 0x0000007F +#define AR_PHY_SETTLING_AGC_S 0 +#define AR_PHY_SETTLING_SWITCH 0x00003F80 +#define AR_PHY_SETTLING_SWITCH_S 7 + +#define AR_PHY_RXGAIN 0x9848 +#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000 +#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12 +#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000 +#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18 + +#define AR_PHY_DESIRED_SZ 0x9850 +#define AR_PHY_DESIRED_SZ_ADC 0x000000FF +#define AR_PHY_DESIRED_SZ_ADC_S 0 +#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00 +#define AR_PHY_DESIRED_SZ_PGA_S 8 +#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000 +#define AR_PHY_DESIRED_SZ_TOT_DES_S 20 + +#define AR_PHY_FIND_SIG 0x9858 +#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000 +#define AR_PHY_FIND_SIG_FIRSTEP_S 12 +#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000 +#define AR_PHY_FIND_SIG_FIRPWR_S 18 + +#define AR_PHY_AGC_CTL1 0x985C +#define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80 +#define AR_PHY_AGC_CTL1_COARSE_LOW_S 7 +#define AR_PHY_AGC_CTL1_COARSE_HIGH 0x003F8000 +#define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15 + +#define AR_PHY_AGC_CONTROL 0x9860 /* chip calibration and noise floor setting */ +#define AR_PHY_AGC_CONTROL_CAL 0x00000001 /* do internal calibration */ +#define AR_PHY_AGC_CONTROL_NF 0x00000002 /* do noise-floor calculation */ +#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 /* Enable noise floor calibration to happen */ +#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 /* Allow Filter calibration */ +#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 /* Don't update noise floor automatically */ + +#define AR_PHY_SFCORR_LOW 0x986C +#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001 +#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00 +#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8 +#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000 +#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14 +#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000 +#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21 + +#define AR_PHY_SFCORR 0x9868 +#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F +#define AR_PHY_SFCORR_M2COUNT_THR_S 0 +#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000 +#define AR_PHY_SFCORR_M1_THRESH_S 17 +#define AR_PHY_SFCORR_M2_THRESH 0x7F000000 +#define AR_PHY_SFCORR_M2_THRESH_S 24 + +#define AR_PHY_SLEEP_CTR_CONTROL 0x9870 +#define AR_PHY_SLEEP_CTR_LIMIT 0x9874 +#define AR_PHY_SLEEP_SCAL 0x9878 + +#define AR_PHY_PLL_CTL 0x987c /* PLL control register */ +#define AR_PHY_PLL_CTL_40 0xaa /* 40 MHz */ +#define AR_PHY_PLL_CTL_44 0xab /* 44 MHz for 11b, 11g */ +#define AR_PHY_PLL_CTL_44_5112 0xeb /* 44 MHz for 11b, 11g */ +#define AR_PHY_PLL_CTL_40_5112 0xea /* 40 MHz for 11a, turbos */ +#define AR_PHY_PLL_CTL_40_5413 0x04 /* 40 MHz for 11a, turbos with 5413 */ +#define AR_PHY_PLL_CTL_HALF 0x100 /* Half clock for 1/2 chan width */ +#define AR_PHY_PLL_CTL_QUARTER 0x200 /* Quarter clock for 1/4 chan width */ + +#define AR_PHY_BIN_MASK_1 0x9900 +#define AR_PHY_BIN_MASK_2 0x9904 +#define AR_PHY_BIN_MASK_3 0x9908 + +#define AR_PHY_MASK_CTL 0x990c /* What are these for?? */ +#define AR_PHY_MASK_CTL_MASK_4 0x00003FFF +#define AR_PHY_MASK_CTL_MASK_4_S 0 +#define AR_PHY_MASK_CTL_RATE 0xFF000000 +#define AR_PHY_MASK_CTL_RATE_S 24 + +#define AR_PHY_RX_DELAY 0x9914 /* analog pow-on time (100ns) */ +#define AR_PHY_RX_DELAY_DELAY 0x00003FFF /* delay from wakeup to rx ena */ + +#define AR_PHY_TIMING_CTRL4 0x9920 /* timing control */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F /* Mask for kcos_theta-1 for q correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0 /* shift for Q_COFF */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0 /* Mask for sin_theta for i correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5 /* Shift for sin_theta for i correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800 /* enable IQ correction */ +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000 /* Mask for max number of samples (logarithmic) */ +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12 /* Shift for max number of samples */ +#define AR_PHY_TIMING_CTRL4_DO_IQCAL 0x10000 /* perform IQ calibration */ +#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000 /* Enable spur filter */ +#define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000 +#define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000 + +#define AR_PHY_TIMING5 0x9924 +#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE +#define AR_PHY_TIMING5_CYCPWR_THR1_S 1 + +#define AR_PHY_PAPD_PROBE 0x9930 +#define AR_PHY_PAPD_PROBE_POWERTX 0x00007E00 +#define AR_PHY_PAPD_PROBE_POWERTX_S 9 +#define AR_PHY_PAPD_PROBE_NEXT_TX 0x00008000 /* command to take next reading */ +#define AR_PHY_PAPD_PROBE_TYPE 0x01800000 +#define AR_PHY_PAPD_PROBE_TYPE_S 23 +#define AR_PHY_PAPD_PROBE_TYPE_OFDM 0 +#define AR_PHY_PAPD_PROBE_TYPE_CCK 2 +#define AR_PHY_PAPD_PROBE_GAINF 0xFE000000 +#define AR_PHY_PAPD_PROBE_GAINF_S 25 + +#define AR_PHY_POWER_TX_RATE1 0x9934 +#define AR_PHY_POWER_TX_RATE2 0x9938 +#define AR_PHY_POWER_TX_RATE_MAX 0x993c +#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040 + +#define AR_PHY_FRAME_CTL 0x9944 +#define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038 +#define AR_PHY_FRAME_CTL_TX_CLIP_S 3 +#define AR_PHY_FRAME_CTL_ERR_SERV 0x20000000 +#define AR_PHY_FRAME_CTL_ERR_SERV_S 29 +#define AR_PHY_FRAME_CTL_EMU_M 0x80000000 +#define AR_PHY_FRAME_CTL_EMU_S 31 +#define AR_PHY_FRAME_CTL_WINLEN 0x00000003 +#define AR_PHY_FRAME_CTL_WINLEN_S 0 + +#define AR_PHY_TXPWRADJ 0x994C /* BB Rev 4.2+ only */ +#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA 0x00000FC0 +#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S 6 +#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX 0x00FC0000 +#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18 + +#define AR_PHY_RADAR_0 0x9954 /* radar detection settings */ +#define AR_PHY_RADAR_0_ENA 0x00000001 /* Enable radar detection */ +#define AR_PHY_RADAR_0_INBAND 0x0000003e /* Inband pulse threshold */ +#define AR_PHY_RADAR_0_INBAND_S 1 +#define AR_PHY_RADAR_0_PRSSI 0x00000FC0 /* Pulse rssi threshold */ +#define AR_PHY_RADAR_0_PRSSI_S 6 +#define AR_PHY_RADAR_0_HEIGHT 0x0003F000 /* Pulse height threshold */ +#define AR_PHY_RADAR_0_HEIGHT_S 12 +#define AR_PHY_RADAR_0_RRSSI 0x00FC0000 /* Radar rssi threshold */ +#define AR_PHY_RADAR_0_RRSSI_S 18 +#define AR_PHY_RADAR_0_FIRPWR 0x7F000000 /* Radar firpwr threshold */ +#define AR_PHY_RADAR_0_FIRPWR_S 24 + + +#define AR_PHY_SIGMA_DELTA 0x996C /* AR5312 only */ +#define AR_PHY_SIGMA_DELTA_ADC_SEL 0x00000003 +#define AR_PHY_SIGMA_DELTA_ADC_SEL_S 0 +#define AR_PHY_SIGMA_DELTA_FILT2 0x000000F8 +#define AR_PHY_SIGMA_DELTA_FILT2_S 3 +#define AR_PHY_SIGMA_DELTA_FILT1 0x00001F00 +#define AR_PHY_SIGMA_DELTA_FILT1_S 8 +#define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000 +#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13 + +#define AR_PHY_RESTART 0x9970 /* restart */ +#define AR_PHY_RESTART_DIV_GC 0x001C0000 /* bb_ant_fast_div_gc_limit */ +#define AR_PHY_RESTART_DIV_GC_S 18 + +#define AR_PHY_RFBUS_REQ 0x997C +#define AR_PHY_RFBUS_REQ_REQUEST 0x00000001 + +#define AR_PHY_TIMING7 0x9980 /* Spur mitigation masks */ +#define AR_PHY_TIMING8 0x9984 +#define AR_PHY_TIMING8_PILOT_MASK_2 0x000FFFFF +#define AR_PHY_TIMING8_PILOT_MASK_2_S 0 + +#define AR_PHY_BIN_MASK2_1 0x9988 +#define AR_PHY_BIN_MASK2_2 0x998c +#define AR_PHY_BIN_MASK2_3 0x9990 +#define AR_PHY_BIN_MASK2_4 0x9994 +#define AR_PHY_BIN_MASK2_4_MASK_4 0x00003FFF +#define AR_PHY_BIN_MASK2_4_MASK_4_S 0 + +#define AR_PHY_TIMING9 0x9998 +#define AR_PHY_TIMING10 0x999c +#define AR_PHY_TIMING10_PILOT_MASK_2 0x000FFFFF +#define AR_PHY_TIMING10_PILOT_MASK_2_S 0 + +#define AR_PHY_TIMING11 0x99a0 /* Spur Mitigation control */ +#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF +#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0 +#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 +#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 +#define AR_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000 +#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000 + +#define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0 + +#define AR_PHY_M_SLEEP 0x99f0 /* sleep control registers */ +#define AR_PHY_REFCLKDLY 0x99f4 +#define AR_PHY_REFCLKPD 0x99f8 + +/* PHY IQ calibration results */ +#define AR_PHY_IQCAL_RES_PWR_MEAS_I 0x9c10 /* power measurement for I */ +#define AR_PHY_IQCAL_RES_PWR_MEAS_Q 0x9c14 /* power measurement for Q */ +#define AR_PHY_IQCAL_RES_IQ_CORR_MEAS 0x9c18 /* IQ correlation measurement */ + +#define AR_PHY_CURRENT_RSSI 0x9c1c /* rssi of current frame rx'd */ + +#define AR_PHY_RFBUS_GNT 0x9c20 +#define AR_PHY_RFBUS_GNT_GRANT 0x1 + +#define AR_PHY_PCDAC_TX_POWER_0 0xA180 +#define AR_PHY_PCDAC_TX_POWER(_n) (AR_PHY_PCDAC_TX_POWER_0 + ((_n)<<2)) + +#define AR_PHY_MODE 0xA200 /* Mode register */ +#define AR_PHY_MODE_QUARTER 0x40 /* Quarter Rate */ +#define AR_PHY_MODE_HALF 0x20 /* Half Rate */ +#define AR_PHY_MODE_AR5112 0x08 /* AR5112 */ +#define AR_PHY_MODE_AR5111 0x00 /* AR5111/AR2111 */ +#define AR_PHY_MODE_DYNAMIC 0x04 /* dynamic CCK/OFDM mode */ +#define AR_PHY_MODE_RF2GHZ 0x02 /* 2.4 GHz */ +#define AR_PHY_MODE_RF5GHZ 0x00 /* 5 GHz */ +#define AR_PHY_MODE_CCK 0x01 /* CCK */ +#define AR_PHY_MODE_OFDM 0x00 /* OFDM */ +#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100 /* Disable dynamic CCK detection */ + +#define AR_PHY_CCK_TX_CTRL 0xA204 +#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 + +#define AR_PHY_CCK_DETECT 0xA208 +#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F +#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0 +#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 + +#define AR_PHY_GAIN_2GHZ 0xA20C +#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000 +#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18 + +#define AR_PHY_CCK_RXCTRL4 0xA21C +#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01F80000 +#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19 + +#define AR_PHY_DAG_CTRLCCK 0xA228 +#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200 /* BB Rev 4.2+ only */ +#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00 /* BB Rev 4.2+ only */ +#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10 /* BB Rev 4.2+ only */ + +#define AR_PHY_POWER_TX_RATE3 0xA234 +#define AR_PHY_POWER_TX_RATE4 0xA238 + +#define AR_PHY_FAST_ADC 0xA24C +#define AR_PHY_BLUETOOTH 0xA254 + +#define AR_PHY_TPCRG1 0xA258 /* ar2413 power control */ +#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000 +#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14 +#define AR_PHY_TPCRG1_PDGAIN_SETTING1 0x00030000 +#define AR_PHY_TPCRG1_PDGAIN_SETTING1_S 16 +#define AR_PHY_TPCRG1_PDGAIN_SETTING2 0x000c0000 +#define AR_PHY_TPCRG1_PDGAIN_SETTING2_S 18 +#define AR_PHY_TPCRG1_PDGAIN_SETTING3 0x00300000 +#define AR_PHY_TPCRG1_PDGAIN_SETTING3_S 20 + +#define AR_PHY_TPCRG5 0xA26C /* ar2413 power control */ +#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F +#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22 + +#endif /* _DEV_ATH_AR5212PHY_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212reg.h b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212reg.h new file mode 100644 index 0000000000..681c6e33bb --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5212reg.h @@ -0,0 +1,995 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5212reg.h,v 1.5 2008/11/16 06:45:43 sam Exp $ + */ +#ifndef _DEV_ATH_AR5212REG_H_ +#define _DEV_ATH_AR5212REG_H_ + +/* + * Definitions for the Atheros 5212 chipset. + */ + +/* DMA Control and Interrupt Registers */ +#define AR_CR 0x0008 /* MAC control register */ +#define AR_RXDP 0x000C /* MAC receive queue descriptor pointer */ +#define AR_CFG 0x0014 /* MAC configuration and status register */ +#define AR_IER 0x0024 /* MAC Interrupt enable register */ +/* 0x28 is RTSD0 on the 5211 */ +/* 0x2c is RTSD1 on the 5211 */ +#define AR_TXCFG 0x0030 /* MAC tx DMA size config register */ +#define AR_RXCFG 0x0034 /* MAC rx DMA size config register */ +/* 0x38 is the jumbo descriptor address on the 5211 */ +#define AR_MIBC 0x0040 /* MAC MIB control register */ +#define AR_TOPS 0x0044 /* MAC timeout prescale count */ +#define AR_RXNPTO 0x0048 /* MAC no frame received timeout */ +#define AR_TXNPTO 0x004C /* MAC no frame trasmitted timeout */ +#define AR_RPGTO 0x0050 /* MAC receive frame gap timeout */ +#define AR_RPCNT 0x0054 /* MAC receive frame count limit */ +#define AR_MACMISC 0x0058 /* MAC miscellaneous control/status register */ +#define AR_SPC_0 0x005c /* MAC sleep performance (awake cycles) */ +#define AR_SPC_1 0x0060 /* MAC sleep performance (asleep cycles) */ +/* 0x5c is for QCU/DCU clock gating control on 5311 */ +#define AR_ISR 0x0080 /* MAC Primary interrupt status register */ +#define AR_ISR_S0 0x0084 /* MAC Secondary interrupt status register 0 */ +#define AR_ISR_S1 0x0088 /* MAC Secondary interrupt status register 1 */ +#define AR_ISR_S2 0x008c /* MAC Secondary interrupt status register 2 */ +#define AR_ISR_S3 0x0090 /* MAC Secondary interrupt status register 3 */ +#define AR_ISR_S4 0x0094 /* MAC Secondary interrupt status register 4 */ +#define AR_IMR 0x00a0 /* MAC Primary interrupt mask register */ +#define AR_IMR_S0 0x00a4 /* MAC Secondary interrupt mask register 0 */ +#define AR_IMR_S1 0x00a8 /* MAC Secondary interrupt mask register 1 */ +#define AR_IMR_S2 0x00ac /* MAC Secondary interrupt mask register 2 */ +#define AR_IMR_S3 0x00b0 /* MAC Secondary interrupt mask register 3 */ +#define AR_IMR_S4 0x00b4 /* MAC Secondary interrupt mask register 4 */ +#define AR_ISR_RAC 0x00c0 /* ISR read-and-clear access */ +/* Shadow copies with read-and-clear access */ +#define AR_ISR_S0_S 0x00c4 /* ISR_S0 shadow copy */ +#define AR_ISR_S1_S 0x00c8 /* ISR_S1 shadow copy */ +#define AR_ISR_S2_S 0x00cc /* ISR_S2 shadow copy */ +#define AR_ISR_S3_S 0x00d0 /* ISR_S3 shadow copy */ +#define AR_ISR_S4_S 0x00d4 /* ISR_S4 shadow copy */ +#define AR_DMADBG_0 0x00e0 /* DMA debug 0 */ +#define AR_DMADBG_1 0x00e4 /* DMA debug 1 */ +#define AR_DMADBG_2 0x00e8 /* DMA debug 2 */ +#define AR_DMADBG_3 0x00ec /* DMA debug 3 */ +#define AR_DMADBG_4 0x00f0 /* DMA debug 4 */ +#define AR_DMADBG_5 0x00f4 /* DMA debug 5 */ +#define AR_DMADBG_6 0x00f8 /* DMA debug 6 */ +#define AR_DMADBG_7 0x00fc /* DMA debug 7 */ +#define AR_DCM_A 0x0400 /* Decompression mask address */ +#define AR_DCM_D 0x0404 /* Decompression mask data */ +#define AR_DCCFG 0x0420 /* Decompression configuration */ +#define AR_CCFG 0x0600 /* Compression configuration */ +#define AR_CCUCFG 0x0604 /* Compression catchup configuration */ +#define AR_CPC_0 0x0610 /* Compression performance counter 0 */ +#define AR_CPC_1 0x0614 /* Compression performance counter 1 */ +#define AR_CPC_2 0x0618 /* Compression performance counter 2 */ +#define AR_CPC_3 0x061c /* Compression performance counter 3 */ +#define AR_CPCOVF 0x0620 /* Compression performance overflow status */ + +#define AR_Q0_TXDP 0x0800 /* MAC Transmit Queue descriptor pointer */ +#define AR_Q1_TXDP 0x0804 /* MAC Transmit Queue descriptor pointer */ +#define AR_Q2_TXDP 0x0808 /* MAC Transmit Queue descriptor pointer */ +#define AR_Q3_TXDP 0x080c /* MAC Transmit Queue descriptor pointer */ +#define AR_Q4_TXDP 0x0810 /* MAC Transmit Queue descriptor pointer */ +#define AR_Q5_TXDP 0x0814 /* MAC Transmit Queue descriptor pointer */ +#define AR_Q6_TXDP 0x0818 /* MAC Transmit Queue descriptor pointer */ +#define AR_Q7_TXDP 0x081c /* MAC Transmit Queue descriptor pointer */ +#define AR_Q8_TXDP 0x0820 /* MAC Transmit Queue descriptor pointer */ +#define AR_Q9_TXDP 0x0824 /* MAC Transmit Queue descriptor pointer */ +#define AR_QTXDP(_i) (AR_Q0_TXDP + ((_i)<<2)) + +#define AR_Q_TXE 0x0840 /* MAC Transmit Queue enable */ +#define AR_Q_TXD 0x0880 /* MAC Transmit Queue disable */ + +#define AR_Q0_CBRCFG 0x08c0 /* MAC CBR configuration */ +#define AR_Q1_CBRCFG 0x08c4 /* MAC CBR configuration */ +#define AR_Q2_CBRCFG 0x08c8 /* MAC CBR configuration */ +#define AR_Q3_CBRCFG 0x08cc /* MAC CBR configuration */ +#define AR_Q4_CBRCFG 0x08d0 /* MAC CBR configuration */ +#define AR_Q5_CBRCFG 0x08d4 /* MAC CBR configuration */ +#define AR_Q6_CBRCFG 0x08d8 /* MAC CBR configuration */ +#define AR_Q7_CBRCFG 0x08dc /* MAC CBR configuration */ +#define AR_Q8_CBRCFG 0x08e0 /* MAC CBR configuration */ +#define AR_Q9_CBRCFG 0x08e4 /* MAC CBR configuration */ +#define AR_QCBRCFG(_i) (AR_Q0_CBRCFG + ((_i)<<2)) + +#define AR_Q0_RDYTIMECFG 0x0900 /* MAC ReadyTime configuration */ +#define AR_Q1_RDYTIMECFG 0x0904 /* MAC ReadyTime configuration */ +#define AR_Q2_RDYTIMECFG 0x0908 /* MAC ReadyTime configuration */ +#define AR_Q3_RDYTIMECFG 0x090c /* MAC ReadyTime configuration */ +#define AR_Q4_RDYTIMECFG 0x0910 /* MAC ReadyTime configuration */ +#define AR_Q5_RDYTIMECFG 0x0914 /* MAC ReadyTime configuration */ +#define AR_Q6_RDYTIMECFG 0x0918 /* MAC ReadyTime configuration */ +#define AR_Q7_RDYTIMECFG 0x091c /* MAC ReadyTime configuration */ +#define AR_Q8_RDYTIMECFG 0x0920 /* MAC ReadyTime configuration */ +#define AR_Q9_RDYTIMECFG 0x0924 /* MAC ReadyTime configuration */ +#define AR_QRDYTIMECFG(_i) (AR_Q0_RDYTIMECFG + ((_i)<<2)) + +#define AR_Q_ONESHOTARM_SC 0x0940 /* MAC OneShotArm set control */ +#define AR_Q_ONESHOTARM_CC 0x0980 /* MAC OneShotArm clear control */ + +#define AR_Q0_MISC 0x09c0 /* MAC Miscellaneous QCU settings */ +#define AR_Q1_MISC 0x09c4 /* MAC Miscellaneous QCU settings */ +#define AR_Q2_MISC 0x09c8 /* MAC Miscellaneous QCU settings */ +#define AR_Q3_MISC 0x09cc /* MAC Miscellaneous QCU settings */ +#define AR_Q4_MISC 0x09d0 /* MAC Miscellaneous QCU settings */ +#define AR_Q5_MISC 0x09d4 /* MAC Miscellaneous QCU settings */ +#define AR_Q6_MISC 0x09d8 /* MAC Miscellaneous QCU settings */ +#define AR_Q7_MISC 0x09dc /* MAC Miscellaneous QCU settings */ +#define AR_Q8_MISC 0x09e0 /* MAC Miscellaneous QCU settings */ +#define AR_Q9_MISC 0x09e4 /* MAC Miscellaneous QCU settings */ +#define AR_QMISC(_i) (AR_Q0_MISC + ((_i)<<2)) + +#define AR_Q0_STS 0x0a00 /* MAC Miscellaneous QCU status */ +#define AR_Q1_STS 0x0a04 /* MAC Miscellaneous QCU status */ +#define AR_Q2_STS 0x0a08 /* MAC Miscellaneous QCU status */ +#define AR_Q3_STS 0x0a0c /* MAC Miscellaneous QCU status */ +#define AR_Q4_STS 0x0a10 /* MAC Miscellaneous QCU status */ +#define AR_Q5_STS 0x0a14 /* MAC Miscellaneous QCU status */ +#define AR_Q6_STS 0x0a18 /* MAC Miscellaneous QCU status */ +#define AR_Q7_STS 0x0a1c /* MAC Miscellaneous QCU status */ +#define AR_Q8_STS 0x0a20 /* MAC Miscellaneous QCU status */ +#define AR_Q9_STS 0x0a24 /* MAC Miscellaneous QCU status */ +#define AR_QSTS(_i) (AR_Q0_STS + ((_i)<<2)) + +#define AR_Q_RDYTIMESHDN 0x0a40 /* MAC ReadyTimeShutdown status */ +#define AR_Q_CBBS 0xb00 /* Compression buffer base select */ +#define AR_Q_CBBA 0xb04 /* Compression buffer base access */ +#define AR_Q_CBC 0xb08 /* Compression buffer configuration */ + +#define AR_D0_QCUMASK 0x1000 /* MAC QCU Mask */ +#define AR_D1_QCUMASK 0x1004 /* MAC QCU Mask */ +#define AR_D2_QCUMASK 0x1008 /* MAC QCU Mask */ +#define AR_D3_QCUMASK 0x100c /* MAC QCU Mask */ +#define AR_D4_QCUMASK 0x1010 /* MAC QCU Mask */ +#define AR_D5_QCUMASK 0x1014 /* MAC QCU Mask */ +#define AR_D6_QCUMASK 0x1018 /* MAC QCU Mask */ +#define AR_D7_QCUMASK 0x101c /* MAC QCU Mask */ +#define AR_D8_QCUMASK 0x1020 /* MAC QCU Mask */ +#define AR_D9_QCUMASK 0x1024 /* MAC QCU Mask */ +#define AR_DQCUMASK(_i) (AR_D0_QCUMASK + ((_i)<<2)) + +#define AR_D0_LCL_IFS 0x1040 /* MAC DCU-specific IFS settings */ +#define AR_D1_LCL_IFS 0x1044 /* MAC DCU-specific IFS settings */ +#define AR_D2_LCL_IFS 0x1048 /* MAC DCU-specific IFS settings */ +#define AR_D3_LCL_IFS 0x104c /* MAC DCU-specific IFS settings */ +#define AR_D4_LCL_IFS 0x1050 /* MAC DCU-specific IFS settings */ +#define AR_D5_LCL_IFS 0x1054 /* MAC DCU-specific IFS settings */ +#define AR_D6_LCL_IFS 0x1058 /* MAC DCU-specific IFS settings */ +#define AR_D7_LCL_IFS 0x105c /* MAC DCU-specific IFS settings */ +#define AR_D8_LCL_IFS 0x1060 /* MAC DCU-specific IFS settings */ +#define AR_D9_LCL_IFS 0x1064 /* MAC DCU-specific IFS settings */ +#define AR_DLCL_IFS(_i) (AR_D0_LCL_IFS + ((_i)<<2)) + +#define AR_D0_RETRY_LIMIT 0x1080 /* MAC Retry limits */ +#define AR_D1_RETRY_LIMIT 0x1084 /* MAC Retry limits */ +#define AR_D2_RETRY_LIMIT 0x1088 /* MAC Retry limits */ +#define AR_D3_RETRY_LIMIT 0x108c /* MAC Retry limits */ +#define AR_D4_RETRY_LIMIT 0x1090 /* MAC Retry limits */ +#define AR_D5_RETRY_LIMIT 0x1094 /* MAC Retry limits */ +#define AR_D6_RETRY_LIMIT 0x1098 /* MAC Retry limits */ +#define AR_D7_RETRY_LIMIT 0x109c /* MAC Retry limits */ +#define AR_D8_RETRY_LIMIT 0x10a0 /* MAC Retry limits */ +#define AR_D9_RETRY_LIMIT 0x10a4 /* MAC Retry limits */ +#define AR_DRETRY_LIMIT(_i) (AR_D0_RETRY_LIMIT + ((_i)<<2)) + +#define AR_D0_CHNTIME 0x10c0 /* MAC ChannelTime settings */ +#define AR_D1_CHNTIME 0x10c4 /* MAC ChannelTime settings */ +#define AR_D2_CHNTIME 0x10c8 /* MAC ChannelTime settings */ +#define AR_D3_CHNTIME 0x10cc /* MAC ChannelTime settings */ +#define AR_D4_CHNTIME 0x10d0 /* MAC ChannelTime settings */ +#define AR_D5_CHNTIME 0x10d4 /* MAC ChannelTime settings */ +#define AR_D6_CHNTIME 0x10d8 /* MAC ChannelTime settings */ +#define AR_D7_CHNTIME 0x10dc /* MAC ChannelTime settings */ +#define AR_D8_CHNTIME 0x10e0 /* MAC ChannelTime settings */ +#define AR_D9_CHNTIME 0x10e4 /* MAC ChannelTime settings */ +#define AR_DCHNTIME(_i) (AR_D0_CHNTIME + ((_i)<<2)) + +#define AR_D0_MISC 0x1100 /* MAC Miscellaneous DCU-specific settings */ +#define AR_D1_MISC 0x1104 /* MAC Miscellaneous DCU-specific settings */ +#define AR_D2_MISC 0x1108 /* MAC Miscellaneous DCU-specific settings */ +#define AR_D3_MISC 0x110c /* MAC Miscellaneous DCU-specific settings */ +#define AR_D4_MISC 0x1110 /* MAC Miscellaneous DCU-specific settings */ +#define AR_D5_MISC 0x1114 /* MAC Miscellaneous DCU-specific settings */ +#define AR_D6_MISC 0x1118 /* MAC Miscellaneous DCU-specific settings */ +#define AR_D7_MISC 0x111c /* MAC Miscellaneous DCU-specific settings */ +#define AR_D8_MISC 0x1120 /* MAC Miscellaneous DCU-specific settings */ +#define AR_D9_MISC 0x1124 /* MAC Miscellaneous DCU-specific settings */ +#define AR_DMISC(_i) (AR_D0_MISC + ((_i)<<2)) + +#define AR_D_SEQNUM 0x1140 /* MAC Frame sequence number */ + +/* MAC DCU-global IFS settings */ +#define AR_D_GBL_IFS_SIFS 0x1030 /* DCU global SIFS settings */ +#define AR_D_GBL_IFS_SLOT 0x1070 /* DC global slot interval */ +#define AR_D_GBL_IFS_EIFS 0x10b0 /* DCU global EIFS setting */ +#define AR_D_GBL_IFS_MISC 0x10f0 /* DCU global misc. IFS settings */ +#define AR_D_FPCTL 0x1230 /* DCU frame prefetch settings */ +#define AR_D_TXPSE 0x1270 /* DCU transmit pause control/status */ +#define AR_D_TXBLK_CMD 0x1038 /* DCU transmit filter cmd (w/only) */ +#define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i)) /* DCU transmit filter data */ +#define AR_D_TXBLK_CLR 0x143c /* DCU clear tx filter (w/only) */ +#define AR_D_TXBLK_SET 0x147c /* DCU set tx filter (w/only) */ + +#define AR_RC 0x4000 /* Warm reset control register */ +#define AR_SCR 0x4004 /* Sleep control register */ +#define AR_INTPEND 0x4008 /* Interrupt Pending register */ +#define AR_SFR 0x400C /* Sleep force register */ +#define AR_PCICFG 0x4010 /* PCI configuration register */ +#define AR_GPIOCR 0x4014 /* GPIO control register */ +#define AR_GPIODO 0x4018 /* GPIO data output access register */ +#define AR_GPIODI 0x401C /* GPIO data input access register */ +#define AR_SREV 0x4020 /* Silicon Revision register */ +#define AR_TXEPOST 0x4028 /* TXE write posting resgister */ +#define AR_QSM 0x402C /* QCU sleep mask */ + +#define AR_PCIE_PMC 0x4068 /* PCIe power mgt config and status register */ +#define AR_PCIE_SERDES 0x4080 /* PCIe Serdes register */ +#define AR_PCIE_SERDES2 0x4084 /* PCIe Serdes register */ + +#define AR_EEPROM_ADDR 0x6000 /* EEPROM address register (10 bit) */ +#define AR_EEPROM_DATA 0x6004 /* EEPROM data register (16 bit) */ +#define AR_EEPROM_CMD 0x6008 /* EEPROM command register */ +#define AR_EEPROM_STS 0x600c /* EEPROM status register */ +#define AR_EEPROM_CFG 0x6010 /* EEPROM configuration register */ + +#define AR_STA_ID0 0x8000 /* MAC station ID0 register - low 32 bits */ +#define AR_STA_ID1 0x8004 /* MAC station ID1 register - upper 16 bits */ +#define AR_BSS_ID0 0x8008 /* MAC BSSID low 32 bits */ +#define AR_BSS_ID1 0x800C /* MAC BSSID upper 16 bits / AID */ +#define AR_SLOT_TIME 0x8010 /* MAC Time-out after a collision */ +#define AR_TIME_OUT 0x8014 /* MAC ACK & CTS time-out */ +#define AR_RSSI_THR 0x8018 /* MAC RSSI warning & missed beacon threshold */ +#define AR_USEC 0x801c /* MAC transmit latency register */ +#define AR_BEACON 0x8020 /* MAC beacon control value/mode bits */ +#define AR_CFP_PERIOD 0x8024 /* MAC CFP Interval (TU/msec) */ +#define AR_TIMER0 0x8028 /* MAC Next beacon time (TU/msec) */ +#define AR_TIMER1 0x802c /* MAC DMA beacon alert time (1/8 TU) */ +#define AR_TIMER2 0x8030 /* MAC Software beacon alert (1/8 TU) */ +#define AR_TIMER3 0x8034 /* MAC ATIM window time */ +#define AR_CFP_DUR 0x8038 /* MAC maximum CFP duration in TU */ +#define AR_RX_FILTER 0x803C /* MAC receive filter register */ +#define AR_MCAST_FIL0 0x8040 /* MAC multicast filter lower 32 bits */ +#define AR_MCAST_FIL1 0x8044 /* MAC multicast filter upper 32 bits */ +#define AR_DIAG_SW 0x8048 /* MAC PCU control register */ +#define AR_TSF_L32 0x804c /* MAC local clock lower 32 bits */ +#define AR_TSF_U32 0x8050 /* MAC local clock upper 32 bits */ +#define AR_TST_ADDAC 0x8054 /* ADDAC test register */ +#define AR_DEF_ANTENNA 0x8058 /* default antenna register */ +#define AR_QOS_MASK 0x805c /* MAC AES mute mask: QoS field */ +#define AR_SEQ_MASK 0x8060 /* MAC AES mute mask: seqnum field */ +#define AR_OBSERV_2 0x8068 /* Observation bus 2 */ +#define AR_OBSERV_1 0x806c /* Observation bus 1 */ + +#define AR_LAST_TSTP 0x8080 /* MAC Time stamp of the last beacon received */ +#define AR_NAV 0x8084 /* MAC current NAV value */ +#define AR_RTS_OK 0x8088 /* MAC RTS exchange success counter */ +#define AR_RTS_FAIL 0x808c /* MAC RTS exchange failure counter */ +#define AR_ACK_FAIL 0x8090 /* MAC ACK failure counter */ +#define AR_FCS_FAIL 0x8094 /* FCS check failure counter */ +#define AR_BEACON_CNT 0x8098 /* Valid beacon counter */ + +#define AR_SLEEP1 0x80d4 /* Enhanced sleep control 1 */ +#define AR_SLEEP2 0x80d8 /* Enhanced sleep control 2 */ +#define AR_SLEEP3 0x80dc /* Enhanced sleep control 3 */ +#define AR_BSSMSKL 0x80e0 /* BSSID mask lower 32 bits */ +#define AR_BSSMSKU 0x80e4 /* BSSID mask upper 16 bits */ +#define AR_TPC 0x80e8 /* Transmit power control for self gen frames */ +#define AR_TFCNT 0x80ec /* Profile count, transmit frames */ +#define AR_RFCNT 0x80f0 /* Profile count, receive frames */ +#define AR_RCCNT 0x80f4 /* Profile count, receive clear */ +#define AR_CCCNT 0x80f8 /* Profile count, cycle counter */ + +#define AR_QUIET1 0x80fc /* Quiet time programming for TGh */ +#define AR_QUIET1_NEXT_QUIET_S 0 /* TSF of next quiet period (TU) */ +#define AR_QUIET1_NEXT_QUIET 0xffff +#define AR_QUIET1_QUIET_ENABLE 0x10000 /* Enable Quiet time operation */ +#define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x20000 /* Do we ack/cts during quiet period */ + +#define AR_QUIET2 0x8100 /* More Quiet time programming */ +#define AR_QUIET2_QUIET_PER_S 0 /* Periodicity of quiet period (TU) */ +#define AR_QUIET2_QUIET_PER 0xffff +#define AR_QUIET2_QUIET_DUR_S 16 /* Duration of quiet period (TU) */ +#define AR_QUIET2_QUIET_DUR 0xffff0000 + +#define AR_TSF_PARM 0x8104 /* TSF parameters */ +#define AR_NOACK 0x8108 /* No ack policy in QoS Control Field */ +#define AR_PHY_ERR 0x810c /* Phy error filter */ + +#define AR_QOS_CONTROL 0x8118 /* Control TKIP MIC for QoS */ +#define AR_QOS_SELECT 0x811c /* MIC QoS select */ +#define AR_MISC_MODE 0x8120 /* PCU Misc. mode control */ + +/* Hainan MIB counter registers */ +#define AR_FILTOFDM 0x8124 /* Count of filtered OFDM frames */ +#define AR_FILTCCK 0x8128 /* Count of filtered CCK frames */ +#define AR_PHYCNT1 0x812c /* Phy Error 1 counter */ +#define AR_PHYCNTMASK1 0x8130 /* Phy Error 1 counter mask */ +#define AR_PHYCNT2 0x8134 /* Phy Error 2 counter */ +#define AR_PHYCNTMASK2 0x8138 /* Phy Error 2 counter mask */ +#define AR_PHY_COUNTMAX (3 << 22) /* Max value in counter before intr */ +#define AR_MIBCNT_INTRMASK (3<<22) /* Mask for top two bits of counters */ + +#define AR_RATE_DURATION_0 0x8700 /* base of multi-rate retry */ +#define AR_RATE_DURATION(_n) (AR_RATE_DURATION_0 + ((_n)<<2)) + +#define AR_KEYTABLE_0 0x8800 /* MAC Key Cache */ +#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32)) + +#define AR_CFP_MASK 0x0000ffff /* Mask for next beacon time */ + +#define AR_CR_RXE 0x00000004 /* Receive enable */ +#define AR_CR_RXD 0x00000020 /* Receive disable */ +#define AR_CR_SWI 0x00000040 /* One-shot software interrupt */ + +#define AR_CFG_SWTD 0x00000001 /* byteswap tx descriptor words */ +#define AR_CFG_SWTB 0x00000002 /* byteswap tx data buffer words */ +#define AR_CFG_SWRD 0x00000004 /* byteswap rx descriptor words */ +#define AR_CFG_SWRB 0x00000008 /* byteswap rx data buffer words */ +#define AR_CFG_SWRG 0x00000010 /* byteswap register access data words */ +#define AR_CFG_AP_ADHOC_INDICATION 0x00000020 /* AP/adhoc indication (0-AP, 1-Adhoc) */ +#define AR_CFG_PHOK 0x00000100 /* PHY OK status */ +#define AR_CFG_EEBS 0x00000200 /* EEPROM busy */ +#define AR_5211_CFG_CLK_GATE_DIS 0x00000400 /* Clock gating disable (Oahu only) */ +#define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000 /* Mask of PCI core master request queue full threshold */ +#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17 /* Shift for PCI core master request queue full threshold */ + +#define AR_IER_ENABLE 0x00000001 /* Global interrupt enable */ +#define AR_IER_DISABLE 0x00000000 /* Global interrupt disable */ + +#define AR_DMASIZE_4B 0x00000000 /* DMA size 4 bytes (TXCFG + RXCFG) */ +#define AR_DMASIZE_8B 0x00000001 /* DMA size 8 bytes */ +#define AR_DMASIZE_16B 0x00000002 /* DMA size 16 bytes */ +#define AR_DMASIZE_32B 0x00000003 /* DMA size 32 bytes */ +#define AR_DMASIZE_64B 0x00000004 /* DMA size 64 bytes */ +#define AR_DMASIZE_128B 0x00000005 /* DMA size 128 bytes */ +#define AR_DMASIZE_256B 0x00000006 /* DMA size 256 bytes */ +#define AR_DMASIZE_512B 0x00000007 /* DMA size 512 bytes */ + +#define AR_FTRIG 0x000003F0 /* Mask for Frame trigger level */ +#define AR_FTRIG_S 4 /* Shift for Frame trigger level */ +#define AR_FTRIG_IMMED 0x00000000 /* bytes in PCU TX FIFO before air */ +#define AR_FTRIG_64B 0x00000010 /* default */ +#define AR_FTRIG_128B 0x00000020 +#define AR_FTRIG_192B 0x00000030 +#define AR_FTRIG_256B 0x00000040 /* 5 bits total */ + +#define AR_RXCFG_ZLFDMA 0x00000010 /* Enable DMA of zero-length frame */ + +#define AR_MIBC_COW 0x00000001 /* counter overflow warning */ +#define AR_MIBC_FMC 0x00000002 /* freeze MIB counters */ +#define AR_MIBC_CMC 0x00000004 /* clear MIB counters */ +#define AR_MIBC_MCS 0x00000008 /* MIB counter strobe, increment all */ + +#define AR_TOPS_MASK 0x0000FFFF /* Mask for timeout prescale */ + +#define AR_RXNPTO_MASK 0x000003FF /* Mask for no frame received timeout */ + +#define AR_TXNPTO_MASK 0x000003FF /* Mask for no frame transmitted timeout */ +#define AR_TXNPTO_QCU_MASK 0x000FFC00 /* Mask indicating the set of QCUs */ + /* for which frame completions will cause */ + /* a reset of the no frame xmit'd timeout */ + +#define AR_RPGTO_MASK 0x000003FF /* Mask for receive frame gap timeout */ + +#define AR_RPCNT_MASK 0x0000001F /* Mask for receive frame count limit */ + +#define AR_MACMISC_DMA_OBS 0x000001E0 /* Mask for DMA observation bus mux select */ +#define AR_MACMISC_DMA_OBS_S 5 /* Shift for DMA observation bus mux select */ +#define AR_MACMISC_MISC_OBS 0x00000E00 /* Mask for MISC observation bus mux select */ +#define AR_MACMISC_MISC_OBS_S 9 /* Shift for MISC observation bus mux select */ +#define AR_MACMISC_MAC_OBS_BUS_LSB 0x00007000 /* Mask for MAC observation bus mux select (lsb) */ +#define AR_MACMISC_MAC_OBS_BUS_LSB_S 12 /* Shift for MAC observation bus mux select (lsb) */ +#define AR_MACMISC_MAC_OBS_BUS_MSB 0x00038000 /* Mask for MAC observation bus mux select (msb) */ +#define AR_MACMISC_MAC_OBS_BUS_MSB_S 15 /* Shift for MAC observation bus mux select (msb) */ + +/* + * Interrupt Status Registers + * + * Only the bits in the ISR_P register and the IMR_P registers + * control whether the MAC's INTA# output is asserted. The bits in + * the secondary interrupt status/mask registers control what bits + * are set in the primary interrupt status register; however the + * IMR_S* registers DO NOT determine whether INTA# is asserted. + * That is INTA# is asserted only when the logical AND of ISR_P + * and IMR_P is non-zero. The secondary interrupt mask/status + * registers affect what bits are set in ISR_P but they do not + * directly affect whether INTA# is asserted. + */ +#define AR_ISR_RXOK 0x00000001 /* At least one frame received sans errors */ +#define AR_ISR_RXDESC 0x00000002 /* Receive interrupt request */ +#define AR_ISR_RXERR 0x00000004 /* Receive error interrupt */ +#define AR_ISR_RXNOPKT 0x00000008 /* No frame received within timeout clock */ +#define AR_ISR_RXEOL 0x00000010 /* Received descriptor empty interrupt */ +#define AR_ISR_RXORN 0x00000020 /* Receive FIFO overrun interrupt */ +#define AR_ISR_TXOK 0x00000040 /* Transmit okay interrupt */ +#define AR_ISR_TXDESC 0x00000080 /* Transmit interrupt request */ +#define AR_ISR_TXERR 0x00000100 /* Transmit error interrupt */ +#define AR_ISR_TXNOPKT 0x00000200 /* No frame transmitted interrupt */ +#define AR_ISR_TXEOL 0x00000400 /* Transmit descriptor empty interrupt */ +#define AR_ISR_TXURN 0x00000800 /* Transmit FIFO underrun interrupt */ +#define AR_ISR_MIB 0x00001000 /* MIB interrupt - see MIBC */ +#define AR_ISR_SWI 0x00002000 /* Software interrupt */ +#define AR_ISR_RXPHY 0x00004000 /* PHY receive error interrupt */ +#define AR_ISR_RXKCM 0x00008000 /* Key-cache miss interrupt */ +#define AR_ISR_SWBA 0x00010000 /* Software beacon alert interrupt */ +#define AR_ISR_BRSSI 0x00020000 /* Beacon threshold interrupt */ +#define AR_ISR_BMISS 0x00040000 /* Beacon missed interrupt */ +#define AR_ISR_HIUERR 0x00080000 /* An unexpected bus error has occurred */ +#define AR_ISR_BNR 0x00100000 /* Beacon not ready interrupt */ +#define AR_ISR_RXCHIRP 0x00200000 /* Phy received a 'chirp' */ +#define AR_ISR_RXDOPPL 0x00400000 /* Phy received a 'doppler chirp' */ +#define AR_ISR_BCNMISC 0x00800000 /* 'or' of TIM, CABEND, DTIMSYNC, BCNTO, + CABTO, DTIM bits from ISR_S2 */ +#define AR_ISR_TIM 0x00800000 /* TIM interrupt */ +#define AR_ISR_GPIO 0x01000000 /* GPIO Interrupt */ +#define AR_ISR_QCBROVF 0x02000000 /* QCU CBR overflow interrupt */ +#define AR_ISR_QCBRURN 0x04000000 /* QCU CBR underrun interrupt */ +#define AR_ISR_QTRIG 0x08000000 /* QCU scheduling trigger interrupt */ +#define AR_ISR_RESV0 0xF0000000 /* Reserved */ + +#define AR_ISR_S0_QCU_TXOK 0x000003FF /* Mask for TXOK (QCU 0-9) */ +#define AR_ISR_S0_QCU_TXOK_S 0 +#define AR_ISR_S0_QCU_TXDESC 0x03FF0000 /* Mask for TXDESC (QCU 0-9) */ +#define AR_ISR_S0_QCU_TXDESC_S 16 + +#define AR_ISR_S1_QCU_TXERR 0x000003FF /* Mask for TXERR (QCU 0-9) */ +#define AR_ISR_S1_QCU_TXERR_S 0 +#define AR_ISR_S1_QCU_TXEOL 0x03FF0000 /* Mask for TXEOL (QCU 0-9) */ +#define AR_ISR_S1_QCU_TXEOL_S 16 + +#define AR_ISR_S2_QCU_TXURN 0x000003FF /* Mask for TXURN (QCU 0-9) */ +#define AR_ISR_S2_MCABT 0x00010000 /* Master cycle abort interrupt */ +#define AR_ISR_S2_SSERR 0x00020000 /* SERR interrupt */ +#define AR_ISR_S2_DPERR 0x00040000 /* PCI bus parity error */ +#define AR_ISR_S2_TIM 0x01000000 /* TIM */ +#define AR_ISR_S2_CABEND 0x02000000 /* CABEND */ +#define AR_ISR_S2_DTIMSYNC 0x04000000 /* DTIMSYNC */ +#define AR_ISR_S2_BCNTO 0x08000000 /* BCNTO */ +#define AR_ISR_S2_CABTO 0x10000000 /* CABTO */ +#define AR_ISR_S2_DTIM 0x20000000 /* DTIM */ +#define AR_ISR_S2_RESV0 0xE0F8FC00 /* Reserved */ + +#define AR_ISR_S3_QCU_QCBROVF 0x000003FF /* Mask for QCBROVF (QCU 0-9) */ +#define AR_ISR_S3_QCU_QCBRURN 0x03FF0000 /* Mask for QCBRURN (QCU 0-9) */ + +#define AR_ISR_S4_QCU_QTRIG 0x000003FF /* Mask for QTRIG (QCU 0-9) */ +#define AR_ISR_S4_RESV0 0xFFFFFC00 /* Reserved */ + +/* + * Interrupt Mask Registers + * + * Only the bits in the IMR control whether the MAC's INTA# + * output will be asserted. The bits in the secondary interrupt + * mask registers control what bits get set in the primary + * interrupt status register; however the IMR_S* registers + * DO NOT determine whether INTA# is asserted. + */ +#define AR_IMR_RXOK 0x00000001 /* At least one frame received sans errors */ +#define AR_IMR_RXDESC 0x00000002 /* Receive interrupt request */ +#define AR_IMR_RXERR 0x00000004 /* Receive error interrupt */ +#define AR_IMR_RXNOPKT 0x00000008 /* No frame received within timeout clock */ +#define AR_IMR_RXEOL 0x00000010 /* Received descriptor empty interrupt */ +#define AR_IMR_RXORN 0x00000020 /* Receive FIFO overrun interrupt */ +#define AR_IMR_TXOK 0x00000040 /* Transmit okay interrupt */ +#define AR_IMR_TXDESC 0x00000080 /* Transmit interrupt request */ +#define AR_IMR_TXERR 0x00000100 /* Transmit error interrupt */ +#define AR_IMR_TXNOPKT 0x00000200 /* No frame transmitted interrupt */ +#define AR_IMR_TXEOL 0x00000400 /* Transmit descriptor empty interrupt */ +#define AR_IMR_TXURN 0x00000800 /* Transmit FIFO underrun interrupt */ +#define AR_IMR_MIB 0x00001000 /* MIB interrupt - see MIBC */ +#define AR_IMR_SWI 0x00002000 /* Software interrupt */ +#define AR_IMR_RXPHY 0x00004000 /* PHY receive error interrupt */ +#define AR_IMR_RXKCM 0x00008000 /* Key-cache miss interrupt */ +#define AR_IMR_SWBA 0x00010000 /* Software beacon alert interrupt */ +#define AR_IMR_BRSSI 0x00020000 /* Beacon threshold interrupt */ +#define AR_IMR_BMISS 0x00040000 /* Beacon missed interrupt */ +#define AR_IMR_HIUERR 0x00080000 /* An unexpected bus error has occurred */ +#define AR_IMR_BNR 0x00100000 /* BNR interrupt */ +#define AR_IMR_RXCHIRP 0x00200000 /* RXCHIRP interrupt */ +#define AR_IMR_BCNMISC 0x00800000 /* Venice: BCNMISC */ +#define AR_IMR_TIM 0x00800000 /* TIM interrupt */ +#define AR_IMR_GPIO 0x01000000 /* GPIO Interrupt */ +#define AR_IMR_QCBROVF 0x02000000 /* QCU CBR overflow interrupt */ +#define AR_IMR_QCBRURN 0x04000000 /* QCU CBR underrun interrupt */ +#define AR_IMR_QTRIG 0x08000000 /* QCU scheduling trigger interrupt */ +#define AR_IMR_RESV0 0xF0000000 /* Reserved */ + +#define AR_IMR_S0_QCU_TXOK 0x000003FF /* TXOK (QCU 0-9) */ +#define AR_IMR_S0_QCU_TXOK_S 0 +#define AR_IMR_S0_QCU_TXDESC 0x03FF0000 /* TXDESC (QCU 0-9) */ +#define AR_IMR_S0_QCU_TXDESC_S 16 + +#define AR_IMR_S1_QCU_TXERR 0x000003FF /* TXERR (QCU 0-9) */ +#define AR_IMR_S1_QCU_TXERR_S 0 +#define AR_IMR_S1_QCU_TXEOL 0x03FF0000 /* TXEOL (QCU 0-9) */ +#define AR_IMR_S1_QCU_TXEOL_S 16 + +#define AR_IMR_S2_QCU_TXURN 0x000003FF /* Mask for TXURN (QCU 0-9) */ +#define AR_IMR_S2_QCU_TXURN_S 0 +#define AR_IMR_S2_MCABT 0x00010000 /* Master cycle abort interrupt */ +#define AR_IMR_S2_SSERR 0x00020000 /* SERR interrupt */ +#define AR_IMR_S2_DPERR 0x00040000 /* PCI bus parity error */ +#define AR_IMR_S2_TIM 0x01000000 /* TIM */ +#define AR_IMR_S2_CABEND 0x02000000 /* CABEND */ +#define AR_IMR_S2_DTIMSYNC 0x04000000 /* DTIMSYNC */ +#define AR_IMR_S2_BCNTO 0x08000000 /* BCNTO */ +#define AR_IMR_S2_CABTO 0x10000000 /* CABTO */ +#define AR_IMR_S2_DTIM 0x20000000 /* DTIM */ +#define AR_IMR_S2_TSFOOR 0x80000000 /* TSF OOR */ +#define AR_IMR_S2_RESV0 0xE0F8FC00 /* Reserved */ + +#define AR_IMR_S3_QCU_QCBROVF 0x000003FF /* Mask for QCBROVF (QCU 0-9) */ +#define AR_IMR_S3_QCU_QCBRURN 0x03FF0000 /* Mask for QCBRURN (QCU 0-9) */ +#define AR_IMR_S3_QCU_QCBRURN_S 16 /* Shift for QCBRURN (QCU 0-9) */ + +#define AR_IMR_S4_QCU_QTRIG 0x000003FF /* Mask for QTRIG (QCU 0-9) */ +#define AR_IMR_S4_RESV0 0xFFFFFC00 /* Reserved */ + +/* QCU registers */ +#define AR_NUM_QCU 10 /* Only use QCU 0-9 for forward QCU compatibility */ +#define AR_QCU_0 0x0001 +#define AR_QCU_1 0x0002 +#define AR_QCU_2 0x0004 +#define AR_QCU_3 0x0008 +#define AR_QCU_4 0x0010 +#define AR_QCU_5 0x0020 +#define AR_QCU_6 0x0040 +#define AR_QCU_7 0x0080 +#define AR_QCU_8 0x0100 +#define AR_QCU_9 0x0200 + +#define AR_Q_CBRCFG_CBR_INTERVAL 0x00FFFFFF /* Mask for CBR interval (us) */ +#define AR_Q_CBRCFG_CBR_INTERVAL_S 0 /* Shift for CBR interval */ +#define AR_Q_CBRCFG_CBR_OVF_THRESH 0xFF000000 /* Mask for CBR overflow threshold */ +#define AR_Q_CBRCFG_CBR_OVF_THRESH_S 24 /* Shift for CBR overflow thresh */ + +#define AR_Q_RDYTIMECFG_INT 0x00FFFFFF /* CBR interval (us) */ +#define AR_Q_RDYTIMECFG_INT_S 0 // Shift for ReadyTime Interval (us) */ +#define AR_Q_RDYTIMECFG_ENA 0x01000000 /* CBR enable */ +/* bits 25-31 are reserved */ + +#define AR_Q_MISC_FSP 0x0000000F /* Frame Scheduling Policy mask */ +#define AR_Q_MISC_FSP_ASAP 0 /* ASAP */ +#define AR_Q_MISC_FSP_CBR 1 /* CBR */ +#define AR_Q_MISC_FSP_DBA_GATED 2 /* DMA Beacon Alert gated */ +#define AR_Q_MISC_FSP_TIM_GATED 3 /* TIM gated */ +#define AR_Q_MISC_FSP_BEACON_SENT_GATED 4 /* Beacon-sent-gated */ +#define AR_Q_MISC_FSP_S 0 +#define AR_Q_MISC_ONE_SHOT_EN 0x00000010 /* OneShot enable */ +#define AR_Q_MISC_CBR_INCR_DIS1 0x00000020 /* Disable CBR expired counter incr + (empty q) */ +#define AR_Q_MISC_CBR_INCR_DIS0 0x00000040 /* Disable CBR expired counter incr + (empty beacon q) */ +#define AR_Q_MISC_BEACON_USE 0x00000080 /* Beacon use indication */ +#define AR_Q_MISC_CBR_EXP_CNTR_LIMIT 0x00000100 /* CBR expired counter limit enable */ +#define AR_Q_MISC_RDYTIME_EXP_POLICY 0x00000200 /* Enable TXE cleared on ReadyTime expired or VEOL */ +#define AR_Q_MISC_RESET_CBR_EXP_CTR 0x00000400 /* Reset CBR expired counter */ +#define AR_Q_MISC_DCU_EARLY_TERM_REQ 0x00000800 /* DCU frame early termination request control */ +#define AR_Q_MISC_QCU_COMP_EN 0x00001000 /* QCU frame compression enable */ +#define AR_Q_MISC_RESV0 0xFFFFF000 /* Reserved */ + +#define AR_Q_STS_PEND_FR_CNT 0x00000003 /* Mask for Pending Frame Count */ +#define AR_Q_STS_RESV0 0x000000FC /* Reserved */ +#define AR_Q_STS_CBR_EXP_CNT 0x0000FF00 /* Mask for CBR expired counter */ +#define AR_Q_STS_RESV1 0xFFFF0000 /* Reserved */ + +/* DCU registers */ +#define AR_NUM_DCU 10 /* Only use 10 DCU's for forward QCU/DCU compatibility */ +#define AR_DCU_0 0x0001 +#define AR_DCU_1 0x0002 +#define AR_DCU_2 0x0004 +#define AR_DCU_3 0x0008 +#define AR_DCU_4 0x0010 +#define AR_DCU_5 0x0020 +#define AR_DCU_6 0x0040 +#define AR_DCU_7 0x0080 +#define AR_DCU_8 0x0100 +#define AR_DCU_9 0x0200 + +#define AR_D_QCUMASK 0x000003FF /* Mask for QCU Mask (QCU 0-9) */ +#define AR_D_QCUMASK_RESV0 0xFFFFFC00 /* Reserved */ + +#define AR_D_LCL_IFS_CWMIN 0x000003FF /* Mask for CW_MIN */ +#define AR_D_LCL_IFS_CWMIN_S 0 +#define AR_D_LCL_IFS_CWMAX 0x000FFC00 /* Mask for CW_MAX */ +#define AR_D_LCL_IFS_CWMAX_S 10 +#define AR_D_LCL_IFS_AIFS 0x0FF00000 /* Mask for AIFS */ +#define AR_D_LCL_IFS_AIFS_S 20 +/* + * Note: even though this field is 8 bits wide the + * maximum supported AIFS value is 0xfc. Setting the AIFS value + * to 0xfd 0xfe, or 0xff will not work correctly and will cause + * the DCU to hang. + */ +#define AR_D_LCL_IFS_RESV0 0xF0000000 /* Reserved */ + +#define AR_D_RETRY_LIMIT_FR_SH 0x0000000F /* frame short retry limit */ +#define AR_D_RETRY_LIMIT_FR_SH_S 0 +#define AR_D_RETRY_LIMIT_FR_LG 0x000000F0 /* frame long retry limit */ +#define AR_D_RETRY_LIMIT_FR_LG_S 4 +#define AR_D_RETRY_LIMIT_STA_SH 0x00003F00 /* station short retry limit */ +#define AR_D_RETRY_LIMIT_STA_SH_S 8 +#define AR_D_RETRY_LIMIT_STA_LG 0x000FC000 /* station short retry limit */ +#define AR_D_RETRY_LIMIT_STA_LG_S 14 +#define AR_D_RETRY_LIMIT_RESV0 0xFFF00000 /* Reserved */ + +#define AR_D_CHNTIME_DUR 0x000FFFFF /* ChannelTime duration (us) */ +#define AR_D_CHNTIME_DUR_S 0 /* Shift for ChannelTime duration */ +#define AR_D_CHNTIME_EN 0x00100000 /* ChannelTime enable */ +#define AR_D_CHNTIME_RESV0 0xFFE00000 /* Reserved */ + +#define AR_D_MISC_BKOFF_THRESH 0x0000003F /* Backoff threshold */ +#define AR_D_MISC_ETS_RTS 0x00000040 /* End of transmission series + station RTS/data failure + count reset policy */ +#define AR_D_MISC_ETS_CW 0x00000080 /* End of transmission series + CW reset policy */ +#define AR_D_MISC_FRAG_WAIT_EN 0x00000100 /* Wait for next fragment */ +#define AR_D_MISC_FRAG_BKOFF_EN 0x00000200 /* Backoff during a frag burst */ +#define AR_D_MISC_HCF_POLL_EN 0x00000800 /* HFC poll enable */ +#define AR_D_MISC_BKOFF_PERSISTENCE 0x00001000 /* Backoff persistence factor + setting */ +#define AR_D_MISC_FR_PREFETCH_EN 0x00002000 /* Frame prefetch enable */ +#define AR_D_MISC_VIR_COL_HANDLING 0x0000C000 /* Mask for Virtual collision + handling policy */ +#define AR_D_MISC_VIR_COL_HANDLING_S 14 +/* FOO redefined for venice CW increment policy */ +#define AR_D_MISC_VIR_COL_HANDLING_DEFAULT 0 /* Normal */ +#define AR_D_MISC_VIR_COL_HANDLING_IGNORE 1 /* Ignore */ +#define AR_D_MISC_BEACON_USE 0x00010000 /* Beacon use indication */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL 0x00060000 /* DCU arbiter lockout ctl */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_S 17 /* DCU arbiter lockout ctl */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE 0 /* No lockout */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR 1 /* Intra-frame */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL 2 /* Global */ +#define AR_D_MISC_ARB_LOCKOUT_IGNORE 0x00080000 /* DCU arbiter lockout ignore control */ +#define AR_D_MISC_SEQ_NUM_INCR_DIS 0x00100000 /* Sequence number increment disable */ +#define AR_D_MISC_POST_FR_BKOFF_DIS 0x00200000 /* Post-frame backoff disable */ +#define AR_D_MISC_VIRT_COLL_POLICY 0x00400000 /* Virtual coll. handling policy */ +#define AR_D_MISC_BLOWN_IFS_POLICY 0x00800000 /* Blown IFS handling policy */ +#define AR_D_MISC_RESV0 0xFE000000 /* Reserved */ + +#define AR_D_SEQNUM_RESV0 0xFFFFF000 /* Reserved */ + +#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007 /* LFSR slice select */ +#define AR_D_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode indication */ +#define AR_D_GBL_IFS_MISC_SIFS_DURATION_USEC 0x000003F0 /* SIFS duration (us) */ +#define AR_D_GBL_IFS_MISC_USEC_DURATION 0x000FFC00 /* microsecond duration */ +#define AR_D_GBL_IFS_MISC_USEC_DURATION_S 10 +#define AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY 0x00300000 /* DCU arbiter delay */ +#define AR_D_GBL_IFS_MISC_RESV0 0xFFC00000 /* Reserved */ + +/* DMA & PCI Registers in PCI space (usable during sleep) */ +#define AR_RC_MAC 0x00000001 /* MAC reset */ +#define AR_RC_BB 0x00000002 /* Baseband reset */ +#define AR_RC_RESV0 0x00000004 /* Reserved */ +#define AR_RC_RESV1 0x00000008 /* Reserved */ +#define AR_RC_PCI 0x00000010 /* PCI-core reset */ + +#define AR_SCR_SLDUR 0x0000ffff /* sleep duration, units of 128us */ +#define AR_SCR_SLDUR_S 0 +#define AR_SCR_SLE 0x00030000 /* sleep enable */ +#define AR_SCR_SLE_S 16 +#define AR_SCR_SLE_WAKE 0 /* force wake */ +#define AR_SCR_SLE_SLP 1 /* force sleep */ +#define AR_SCR_SLE_NORM 2 /* sleep logic normal operation */ +#define AR_SCR_SLDTP 0x00040000 /* sleep duration timing policy */ +#define AR_SCR_SLDWP 0x00080000 /* sleep duration write policy */ +#define AR_SCR_SLEPOL 0x00100000 /* sleep policy mode */ +#define AR_SCR_MIBIE 0x00200000 /* sleep perf cntrs MIB intr ena */ + +#define AR_INTPEND_TRUE 0x00000001 /* interrupt pending */ + +#define AR_SFR_SLEEP 0x00000001 /* force sleep */ + +#define AR_PCICFG_SCLK_SEL 0x00000002 /* sleep clock select */ +#define AR_PCICFG_SCLK_SEL_S 1 +#define AR_PCICFG_CLKRUNEN 0x00000004 /* enable PCI CLKRUN function */ +#define AR_PCICFG_EEPROM_SIZE 0x00000018 /* Mask for EEPROM size */ +#define AR_PCICFG_EEPROM_SIZE_4 0 /* EEPROM size 4 Kbit */ +#define AR_PCICFG_EEPROM_SIZE_8K 1 /* EEPROM size 8 Kbit */ +#define AR_PCICFG_EEPROM_SIZE_16K 2 /* EEPROM size 16 Kbit */ +#define AR_PCICFG_EEPROM_SIZE_FAILED 3 /* Failure */ +#define AR_PCICFG_EEPROM_SIZE_S 3 +#define AR_PCICFG_LEDCTL 0x00000060 /* LED control Status */ +#define AR_PCICFG_LEDCTL_NONE 0 /* STA is not associated or trying */ +#define AR_PCICFG_LEDCTL_PEND 1 /* STA is trying to associate */ +#define AR_PCICFG_LEDCTL_ASSOC 2 /* STA is associated */ +#define AR_PCICFG_LEDCTL_S 5 +#define AR_PCICFG_PCI_BUS_SEL 0x00000380 /* PCI observation bus mux select */ +#define AR_PCICFG_DIS_CBE_FIX 0x00000400 /* Disable fix for bad PCI CBE# generation */ +#define AR_PCICFG_SL_INTEN 0x00000800 /* enable interrupt line assertion when asleep */ +#define AR_PCICFG_RETRYFIXEN 0x00001000 /* Enable PCI core retry fix */ +#define AR_PCICFG_SL_INPEN 0x00002000 /* Force asleep when an interrupt is pending */ +#define AR_PCICFG_RESV1 0x0000C000 /* Reserved */ +#define AR_PCICFG_SPWR_DN 0x00010000 /* mask for sleep/awake indication */ +#define AR_PCICFG_LEDMODE 0x000E0000 /* LED mode */ +#define AR_PCICFG_LEDMODE_PROP 0 /* Blink prop to filtered tx/rx */ +#define AR_PCICFG_LEDMODE_RPROP 1 /* Blink prop to unfiltered tx/rx */ +#define AR_PCICFG_LEDMODE_SPLIT 2 /* Blink power for tx/net for rx */ +#define AR_PCICFG_LEDMODE_RAND 3 /* Blink randomly */ +/* NB: s/w led control present in Hainan 1.1 and above */ +#define AR_PCICFG_LEDMODE_OFF 4 /* s/w control + both led's off */ +#define AR_PCICFG_LEDMODE_POWON 5 /* s/w control + power led on */ +#define AR_PCICFG_LEDMODE_NETON 6 /* s/w control + network led on */ +#define AR_PCICFG_LEDMODE_S 17 +#define AR_PCICFG_LEDBLINK 0x00700000 /* LED blink threshold select */ +#define AR_PCICFG_LEDBLINK_S 20 +#define AR_PCICFG_LEDSLOW 0x00800000 /* LED slowest blink rate mode */ +#define AR_PCICFG_LEDSLOW_S 23 +#define AR_PCICFG_SCLK_RATE_IND 0x03000000 /* Sleep clock rate */ +#define AR_PCICFG_SCLK_RATE_IND_S 24 +#define AR_PCICFG_RESV2 0xFC000000 /* Reserved */ + +#define AR_GPIOCR_CR_SHIFT 2 /* Each CR is 2 bits */ +#define AR_GPIOCR_CR_N(_g) (0 << (AR_GPIOCR_CR_SHIFT * (_g))) +#define AR_GPIOCR_CR_0(_g) (1 << (AR_GPIOCR_CR_SHIFT * (_g))) +#define AR_GPIOCR_CR_1(_g) (2 << (AR_GPIOCR_CR_SHIFT * (_g))) +#define AR_GPIOCR_CR_A(_g) (3 << (AR_GPIOCR_CR_SHIFT * (_g))) +#define AR_GPIOCR_INT_SHIFT 12 /* Interrupt select field shifter */ +#define AR_GPIOCR_INT(_g) ((_g) << AR_GPIOCR_INT_SHIFT) +#define AR_GPIOCR_INT_MASK 0x00007000 /* Interrupt select field mask */ +#define AR_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO Interrupt */ +#define AR_GPIOCR_INT_SELL 0x00000000 /* Generate int if pin is low */ +#define AR_GPIOCR_INT_SELH 0x00010000 /* Generate int if pin is high */ +#define AR_GPIOCR_INT_SEL AR_GPIOCR_INT_SELH + +#define AR_SREV_ID 0x000000FF /* Mask to read SREV info */ +#define AR_SREV_ID_S 4 /* Mask to shift Major Rev Info */ +#define AR_SREV_REVISION 0x0000000F /* Mask for Chip revision level */ +#define AR_SREV_REVISION_MIN 0 /* lowest revision level */ +#define AR_SREV_REVISION_MAX 0xF /* highest revision level */ +#define AR_SREV_FPGA 1 +#define AR_SREV_D2PLUS 2 +#define AR_SREV_D2PLUS_MS 3 /* metal spin */ +#define AR_SREV_CRETE 4 +#define AR_SREV_CRETE_MS 5 /* FCS metal spin */ +#define AR_SREV_CRETE_MS23 7 /* 2.3 metal spin (6 skipped) */ +#define AR_SREV_CRETE_23 8 /* 2.3 full tape out */ +#define AR_SREV_GRIFFIN_LITE 8 +#define AR_SREV_HAINAN 9 +#define AR_SREV_CONDOR 11 +#define AR_SREV_VERSION 0x000000F0 /* Mask for Chip version */ +#define AR_SREV_VERSION_CRETE 0 +#define AR_SREV_VERSION_MAUI_1 1 +#define AR_SREV_VERSION_MAUI_2 2 +#define AR_SREV_VERSION_SPIRIT 3 +#define AR_SREV_VERSION_OAHU 4 +#define AR_SREV_VERSION_VENICE 5 +#define AR_SREV_VERSION_GRIFFIN 7 +#define AR_SREV_VERSION_CONDOR 9 +#define AR_SREV_VERSION_EAGLE 10 +#define AR_SREV_VERSION_COBRA 11 +#define AR_SREV_2413 AR_SREV_VERSION_GRIFFIN +#define AR_SREV_5413 AR_SREV_VERSION_EAGLE +#define AR_SREV_2415 AR_SREV_VERSION_COBRA +#define AR_SREV_5424 AR_SREV_VERSION_CONDOR +#define AR_SREV_2425 14 /* SWAN */ +#define AR_SREV_2417 15 /* Nala */ +#define AR_SREV_OAHU_ES 0 /* Engineering Sample */ +#define AR_SREV_OAHU_PROD 2 /* Production */ + +#define AR_PHYREV_HAINAN 0x43 +#define AR_ANALOG5REV_HAINAN 0x46 + +#define AR_RADIO_SREV_MAJOR 0xF0 +#define AR_RADIO_SREV_MINOR 0x0F +#define AR_RAD5111_SREV_MAJOR 0x10 /* All current supported ar5211 5 GHz + radios are rev 0x10 */ +#define AR_RAD5111_SREV_PROD 0x15 /* Current production level radios */ +#define AR_RAD2111_SREV_MAJOR 0x20 /* All current supported ar5211 2 GHz + radios are rev 0x10 */ +#define AR_RAD5112_SREV_MAJOR 0x30 /* 5112 Major Rev */ +#define AR_RAD5112_SREV_2_0 0x35 /* AR5112 Revision 2.0 */ +#define AR_RAD5112_SREV_2_1 0x36 /* AR5112 Revision 2.1 */ +#define AR_RAD2112_SREV_MAJOR 0x40 /* 2112 Major Rev */ +#define AR_RAD2112_SREV_2_0 0x45 /* AR2112 Revision 2.0 */ +#define AR_RAD2112_SREV_2_1 0x46 /* AR2112 Revision 2.1 */ +#define AR_RAD2413_SREV_MAJOR 0x50 /* 2413 Major Rev */ +#define AR_RAD5413_SREV_MAJOR 0x60 /* 5413 Major Rev */ +#define AR_RAD2316_SREV_MAJOR 0x70 /* 2316 Major Rev */ +#define AR_RAD2317_SREV_MAJOR 0x80 /* 2317 Major Rev */ +#define AR_RAD5424_SREV_MAJOR 0xa0 /* Mostly same as 5413 Major Rev */ + +#define AR_PCIE_PMC_ENA_L1 0x01 /* enable PCIe core enter L1 when + d2_sleep_en is asserted */ +#define AR_PCIE_PMC_ENA_RESET 0x08 /* enable reset on link going down */ + +/* EEPROM Registers in the MAC */ +#define AR_EEPROM_CMD_READ 0x00000001 +#define AR_EEPROM_CMD_WRITE 0x00000002 +#define AR_EEPROM_CMD_RESET 0x00000004 + +#define AR_EEPROM_STS_READ_ERROR 0x00000001 +#define AR_EEPROM_STS_READ_COMPLETE 0x00000002 +#define AR_EEPROM_STS_WRITE_ERROR 0x00000004 +#define AR_EEPROM_STS_WRITE_COMPLETE 0x00000008 + +#define AR_EEPROM_CFG_SIZE 0x00000003 /* size determination override */ +#define AR_EEPROM_CFG_SIZE_AUTO 0 +#define AR_EEPROM_CFG_SIZE_4KBIT 1 +#define AR_EEPROM_CFG_SIZE_8KBIT 2 +#define AR_EEPROM_CFG_SIZE_16KBIT 3 +#define AR_EEPROM_CFG_DIS_WWRCL 0x00000004 /* Disable wait for write completion */ +#define AR_EEPROM_CFG_CLOCK 0x00000018 /* clock rate control */ +#define AR_EEPROM_CFG_CLOCK_S 3 /* clock rate control */ +#define AR_EEPROM_CFG_CLOCK_156KHZ 0 +#define AR_EEPROM_CFG_CLOCK_312KHZ 1 +#define AR_EEPROM_CFG_CLOCK_625KHZ 2 +#define AR_EEPROM_CFG_RESV0 0x000000E0 /* Reserved */ +#define AR_EEPROM_CFG_PKEY 0x00FFFF00 /* protection key */ +#define AR_EEPROM_CFG_PKEY_S 8 +#define AR_EEPROM_CFG_EN_L 0x01000000 /* EPRM_EN_L setting */ + +/* MAC PCU Registers */ + +#define AR_STA_ID1_SADH_MASK 0x0000FFFF /* upper 16 bits of MAC addr */ +#define AR_STA_ID1_STA_AP 0x00010000 /* Device is AP */ +#define AR_STA_ID1_ADHOC 0x00020000 /* Device is ad-hoc */ +#define AR_STA_ID1_PWR_SAV 0x00040000 /* Power save reporting in + self-generated frames */ +#define AR_STA_ID1_KSRCHDIS 0x00080000 /* Key search disable */ +#define AR_STA_ID1_PCF 0x00100000 /* Observe PCF */ +#define AR_STA_ID1_USE_DEFANT 0x00200000 /* Use default antenna */ +#define AR_STA_ID1_UPD_DEFANT 0x00400000 /* Update default antenna w/ + TX antenna */ +#define AR_STA_ID1_RTS_USE_DEF 0x00800000 /* Use default antenna to send RTS */ +#define AR_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mb/s rate for ACK & CTS */ +#define AR_STA_ID1_BASE_RATE_11B 0x02000000/* Use 11b base rate for ACK & CTS */ +#define AR_STA_ID1_USE_DA_SG 0x04000000 /* Use default antenna for + self-generated frames */ +#define AR_STA_ID1_CRPT_MIC_ENABLE 0x08000000 /* Enable Michael */ +#define AR_STA_ID1_KSRCH_MODE 0x10000000 /* Look-up key when keyID != 0 */ +#define AR_STA_ID1_PRE_SEQNUM 0x20000000 /* Preserve s/w sequence number */ +#define AR_STA_ID1_CBCIV_ENDIAN 0x40000000 +#define AR_STA_ID1_MCAST_KSRCH 0x80000000 /* Do keycache search for mcast */ + +#define AR_BSS_ID1_U16 0x0000FFFF /* Upper 16 bits of BSSID */ +#define AR_BSS_ID1_AID 0xFFFF0000 /* Association ID */ +#define AR_BSS_ID1_AID_S 16 + +#define AR_SLOT_TIME_MASK 0x000007FF /* Slot time mask */ + +#define AR_TIME_OUT_ACK 0x00003FFF /* ACK time-out */ +#define AR_TIME_OUT_ACK_S 0 +#define AR_TIME_OUT_CTS 0x3FFF0000 /* CTS time-out */ +#define AR_TIME_OUT_CTS_S 16 + +#define AR_RSSI_THR_MASK 0x000000FF /* Beacon RSSI warning threshold */ +#define AR_RSSI_THR_BM_THR 0x0000FF00 /* Missed beacon threshold */ +#define AR_RSSI_THR_BM_THR_S 8 + +#define AR_USEC_USEC 0x0000007F /* clock cycles in 1 usec */ +#define AR_USEC_USEC_S 0 +#define AR_USEC_USEC32 0x00003F80 /* 32MHz clock cycles in 1 usec */ +#define AR_USEC_USEC32_S 7 + +#define AR5212_USEC_TX_LAT_M 0x007FC000 /* Tx latency */ +#define AR5212_USEC_TX_LAT_S 14 +#define AR5212_USEC_RX_LAT_M 0x1F800000 /* Rx latency */ +#define AR5212_USEC_RX_LAT_S 23 + +#define AR_BEACON_PERIOD 0x0000FFFF /* Beacon period mask in TU/msec */ +#define AR_BEACON_PERIOD_S 0 +#define AR_BEACON_TIM 0x007F0000 /* byte offset of TIM start */ +#define AR_BEACON_TIM_S 16 +#define AR_BEACON_EN 0x00800000 /* Beacon enable */ +#define AR_BEACON_RESET_TSF 0x01000000 /* Clear TSF to 0 */ + +#define AR_RX_NONE 0x00000000 /* Disallow all frames */ +#define AR_RX_UCAST 0x00000001 /* Allow unicast frames */ +#define AR_RX_MCAST 0x00000002 /* Allow multicast frames */ +#define AR_RX_BCAST 0x00000004 /* Allow broadcast frames */ +#define AR_RX_CONTROL 0x00000008 /* Allow control frames */ +#define AR_RX_BEACON 0x00000010 /* Allow beacon frames */ +#define AR_RX_PROM 0x00000020 /* Promiscuous mode, all packets */ +#define AR_RX_PROBE_REQ 0x00000080 /* Allow probe request frames */ + +#define AR_DIAG_CACHE_ACK 0x00000001 /* No ACK if no valid key found */ +#define AR_DIAG_ACK_DIS 0x00000002 /* Disable ACK generation */ +#define AR_DIAG_CTS_DIS 0x00000004 /* Disable CTS generation */ +#define AR_DIAG_ENCRYPT_DIS 0x00000008 /* Disable encryption */ +#define AR_DIAG_DECRYPT_DIS 0x00000010 /* Disable decryption */ +#define AR_DIAG_RX_DIS 0x00000020 /* Disable receive */ +#define AR_DIAG_CORR_FCS 0x00000080 /* Corrupt FCS */ +#define AR_DIAG_CHAN_INFO 0x00000100 /* Dump channel info */ +#define AR_DIAG_EN_SCRAMSD 0x00000200 /* Enable fixed scrambler seed */ +#define AR_DIAG_SCRAM_SEED 0x0001FC00 /* Fixed scrambler seed */ +#define AR_DIAG_SCRAM_SEED_S 10 +#define AR_DIAG_FRAME_NV0 0x00020000 /* Accept frames of non-zero + protocol version */ +#define AR_DIAG_OBS_PT_SEL 0x000C0000 /* Observation point select */ +#define AR_DIAG_OBS_PT_SEL_S 18 +#define AR_DIAG_RX_CLR_HI 0x00100000 /* Force rx_clear high */ +#define AR_DIAG_IGNORE_CS 0x00200000 /* Force virtual carrier sense */ +#define AR_DIAG_CHAN_IDLE 0x00400000 /* Force channel idle high */ +#define AR_DIAG_PHEAR_ME 0x00800000 /* Uses framed and wait_wep in the pherr_enable_eifs if set to 0 */ + +#define AR_SLEEP1_NEXT_DTIM 0x0007ffff /* Abs. time(1/8TU) for next DTIM */ +#define AR_SLEEP1_NEXT_DTIM_S 0 +#define AR_SLEEP1_ASSUME_DTIM 0x00080000 /* Assume DTIM present on missent beacon */ +#define AR_SLEEP1_ENH_SLEEP_ENA 0x00100000 /* Enable enhanced sleep logic */ +#define AR_SLEEP1_CAB_TIMEOUT 0xff000000 /* CAB timeout(TU) */ +#define AR_SLEEP1_CAB_TIMEOUT_S 24 + +#define AR_SLEEP2_NEXT_TIM 0x0007ffff /* Abs. time(1/8TU) for next DTIM */ +#define AR_SLEEP2_NEXT_TIM_S 0 +#define AR_SLEEP2_BEACON_TIMEOUT 0xff000000 /* Beacon timeout(TU) */ +#define AR_SLEEP2_BEACON_TIMEOUT_S 24 + +#define AR_SLEEP3_TIM_PERIOD 0x0000ffff /* Tim/Beacon period (TU) */ +#define AR_SLEEP3_TIM_PERIOD_S 0 +#define AR_SLEEP3_DTIM_PERIOD 0xffff0000 /* DTIM period (TU) */ +#define AR_SLEEP3_DTIM_PERIOD_S 16 + +#define AR_TPC_ACK 0x0000003f /* ack frames */ +#define AR_TPC_ACK_S 0 +#define AR_TPC_CTS 0x00003f00 /* cts frames */ +#define AR_TPC_CTS_S 8 +#define AR_TPC_CHIRP 0x003f0000 /* chirp frames */ +#define AR_TPC_CHIRP_S 16 +#define AR_TPC_DOPPLER 0x0f000000 /* doppler chirp span */ +#define AR_TPC_DOPPLER_S 24 + +#define AR_PHY_ERR_RADAR 0x00000020 /* Radar signal */ +#define AR_PHY_ERR_OFDM_TIMING 0x00020000 /* False detect for OFDM */ +#define AR_PHY_ERR_CCK_TIMING 0x02000000 /* False detect for CCK */ + +#define AR_TSF_PARM_INCREMENT 0x000000ff +#define AR_TSF_PARM_INCREMENT_S 0 + +#define AR_NOACK_2BIT_VALUE 0x0000000f +#define AR_NOACK_2BIT_VALUE_S 0 +#define AR_NOACK_BIT_OFFSET 0x00000070 +#define AR_NOACK_BIT_OFFSET_S 4 +#define AR_NOACK_BYTE_OFFSET 0x00000180 +#define AR_NOACK_BYTE_OFFSET_S 7 + +#define AR_MISC_MODE_BSSID_MATCH_FORCE 0x1 /* Force BSSID match */ +#define AR_MISC_MODE_ACKSIFS_MEMORY 0x2 /* ACKSIFS use contents of Rate */ +#define AR_MISC_MODE_MIC_NEW_LOC_ENABLE 0x4 /* Xmit Michael Key same as Rcv */ +#define AR_MISC_MODE_TX_ADD_TSF 0x8 /* Beacon/Probe-Rsp timestamp add (not replace) */ + +#define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0) /* key bit 0-31 */ +#define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4) /* key bit 32-47 */ +#define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8) /* key bit 48-79 */ +#define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12) /* key bit 80-95 */ +#define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16) /* key bit 96-127 */ +#define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20) /* key type */ +#define AR_KEYTABLE_TYPE_40 0x00000000 /* WEP 40 bit key */ +#define AR_KEYTABLE_TYPE_104 0x00000001 /* WEP 104 bit key */ +#define AR_KEYTABLE_TYPE_128 0x00000003 /* WEP 128 bit key */ +#define AR_KEYTABLE_TYPE_TKIP 0x00000004 /* TKIP and Michael */ +#define AR_KEYTABLE_TYPE_AES 0x00000005 /* AES/OCB 128 bit key */ +#define AR_KEYTABLE_TYPE_CCM 0x00000006 /* AES/CCM 128 bit key */ +#define AR_KEYTABLE_TYPE_CLR 0x00000007 /* no encryption */ +#define AR_KEYTABLE_ANT 0x00000008 /* previous transmit antenna */ +#define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24) /* MAC address 1-32 */ +#define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28) /* MAC address 33-47 */ +#define AR_KEYTABLE_VALID 0x00008000 /* key and MAC address valid */ + +/* Compress settings */ +#define AR_CCFG_WIN_M 0x00000007 /* mask for AR_CCFG_WIN size */ +#define AR_CCFG_MIB_INT_EN 0x00000008 /* compression performance MIB counter int enable */ +#define AR_CCUCFG_RESET_VAL 0x00100200 /* the should be reset value */ +#define AR_CCUCFG_CATCHUP_EN 0x00000001 /* Compression catchup enable */ +#define AR_DCM_D_EN 0x00000001 /* all direct frames to be decompressed */ +#define AR_COMPRESSION_WINDOW_SIZE 4096 /* default comp. window size */ + +#endif /* _DEV_AR5212REG_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5311reg.h b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5311reg.h new file mode 100644 index 0000000000..efb8568636 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5311reg.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5311reg.h,v 1.3 2008/10/06 18:32:50 sam Exp $ + */ +#ifndef _DEV_ATH_AR5311REG_H_ +#define _DEV_ATH_AR5311REG_H_ + +/* + * Definitions for the Atheros 5311 chipset. + */ +#define AR5311_QDCLKGATE 0x005c /* MAC QCU/DCU clock gating control */ +#define AR5311_QDCLKGATE_QCU_M 0x0000FFFF /* QCU clock disable */ +#define AR5311_QDCLKGATE_DCU_M 0x07FF0000 /* DCU clock disable */ + +#define AR5311_RXCFG_DEF_RX_ANTENNA 0x00000008 /* Default Receive Antenna */ + +/* + * NOTE: MAC_5211/MAC_5311 difference + * On Oahu the TX latency field has increased from 6 bits to 9 bits. + * The RX latency field is unchanged but is shifted over 3 bits. + */ +#define AR5311_USEC_TX_LAT_M 0x000FC000 /* tx latency (usec) */ +#define AR5311_USEC_TX_LAT_S 14 +#define AR5311_USEC_RX_LAT_M 0x03F00000 /* rx latency (usec) */ +#define AR5311_USEC_RX_LAT_S 20 + +/* + * NOTE: MAC_5211/MAC_5311 difference + * On Maui2/Spirit the frame sequence number is controlled per DCU. + * On Oahu the frame sequence number is global across all DCUs and + * is controlled + */ +#define AR5311_D_MISC_SEQ_NUM_CONTROL 0x01000000 /* seq num local or global */ +#define AR5311_DIAG_USE_ECO 0x00000400 /* "super secret" enable ECO */ + +#endif /* _DEV_ATH_AR5311REG_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5413.c b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5413.c new file mode 100644 index 0000000000..ecf8538bfc --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5212/ar5413.c @@ -0,0 +1,797 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5413.c,v 1.8 2008/11/15 22:15:46 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v3.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#define AH_5212_5413 +#include "ar5212/ar5212.ini" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +struct ar5413State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[PWR_TABLE_SIZE_2413]; + + uint32_t Bank1Data[N(ar5212Bank1_5413)]; + uint32_t Bank2Data[N(ar5212Bank2_5413)]; + uint32_t Bank3Data[N(ar5212Bank3_5413)]; + uint32_t Bank6Data[N(ar5212Bank6_5413)]; + uint32_t Bank7Data[N(ar5212Bank7_5413)]; + + /* + * Private state for reduced stack usage. + */ + /* filled out Vpd table for all pdGains (chanL) */ + uint16_t vpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (chanR) */ + uint16_t vpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (interpolated) */ + uint16_t vpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; +}; +#define AR5413(ah) ((struct ar5413State *) AH5212(ah)->ah_rfHal) + +extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static void +ar5413WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + HAL_INI_WRITE_ARRAY(ah, ar5212Modes_5413, modesIndex, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212Common_5413, 1, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_5413, freqIndex, writes); +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + */ +static HAL_BOOL +ar5413SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + uint32_t channelSel = 0; + uint32_t bModeSynth = 0; + uint32_t aModeRefSel = 0; + uint32_t reg32 = 0; + uint16_t freq; + + OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel); + + if (chan->channel < 4800) { + uint32_t txctl; + + if (((chan->channel - 2192) % 5) == 0) { + channelSel = ((chan->channel - 672) * 2 - 3040)/10; + bModeSynth = 0; + } else if (((chan->channel - 2224) % 5) == 0) { + channelSel = ((chan->channel - 704) * 2 - 3040) / 10; + bModeSynth = 1; + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u MHz\n", + __func__, chan->channel); + return AH_FALSE; + } + + channelSel = (channelSel << 2) & 0xff; + channelSel = ath_hal_reverseBits(channelSel, 8); + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (chan->channel == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else if (((chan->channel % 5) == 2) && (chan->channel <= 5435)) { + freq = chan->channel - 2; /* Align to even 5MHz raster */ + channelSel = ath_hal_reverseBits( + (uint32_t)(((freq - 4800)*10)/25 + 1), 8); + aModeRefSel = ath_hal_reverseBits(0, 2); + } else if ((chan->channel % 20) == 0 && chan->channel >= 5120) { + channelSel = ath_hal_reverseBits( + ((chan->channel - 4800) / 20 << 2), 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else if ((chan->channel % 10) == 0) { + channelSel = ath_hal_reverseBits( + ((chan->channel - 4800) / 10 << 1), 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else if ((chan->channel % 5) == 0) { + channelSel = ath_hal_reverseBits( + (chan->channel - 4800) / 5, 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", + __func__, chan->channel); + return AH_FALSE; + } + + reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 12) | 0x1; + OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff); + + reg32 >>= 8; + OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f); + + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + * + * REQUIRES: Access to the analog rf device + */ +static HAL_BOOL +ar5413SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t modesIndex, uint16_t *rfXpdGain) +{ +#define RF_BANK_SETUP(_priv, _ix, _col) do { \ + int i; \ + for (i = 0; i < N(ar5212Bank##_ix##_5413); i++) \ + (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_5413[i][_col];\ +} while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t ob5GHz = 0, db5GHz = 0; + uint16_t ob2GHz = 0, db2GHz = 0; + struct ar5413State *priv = AR5413(ah); + int regWrites = 0; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: chan 0x%x flag 0x%x modesIndex 0x%x\n", + __func__, chan->channel, chan->channelFlags, modesIndex); + + HALASSERT(priv != AH_NULL); + + /* Setup rf parameters */ + switch (chan->channelFlags & CHANNEL_ALL) { + case CHANNEL_A: + case CHANNEL_T: + if (chan->channel > 4000 && chan->channel < 5260) { + ob5GHz = ee->ee_ob1; + db5GHz = ee->ee_db1; + } else if (chan->channel >= 5260 && chan->channel < 5500) { + ob5GHz = ee->ee_ob2; + db5GHz = ee->ee_db2; + } else if (chan->channel >= 5500 && chan->channel < 5725) { + ob5GHz = ee->ee_ob3; + db5GHz = ee->ee_db3; + } else if (chan->channel >= 5725) { + ob5GHz = ee->ee_ob4; + db5GHz = ee->ee_db4; + } else { + /* XXX else */ + } + break; + case CHANNEL_B: + ob2GHz = ee->ee_obFor24; + db2GHz = ee->ee_dbFor24; + break; + case CHANNEL_G: + case CHANNEL_108G: + ob2GHz = ee->ee_obFor24g; + db2GHz = ee->ee_dbFor24g; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + + /* Bank 1 Write */ + RF_BANK_SETUP(priv, 1, 1); + + /* Bank 2 Write */ + RF_BANK_SETUP(priv, 2, modesIndex); + + /* Bank 3 Write */ + RF_BANK_SETUP(priv, 3, modesIndex); + + /* Bank 6 Write */ + RF_BANK_SETUP(priv, 6, modesIndex); + + /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ + if (IS_CHAN_2GHZ(chan)) { + ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 241, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 238, 0); + + /* TODO - only for Eagle 1.0 2GHz - remove for production */ + /* XXX: but without this bit G doesn't work. */ + ar5212ModifyRfBuffer(priv->Bank6Data, 1 , 1, 291, 2); + + /* Optimum value for rf_pwd_iclobuf2G for PCIe chips only */ + if (IS_PCIE(ah)) { + ar5212ModifyRfBuffer(priv->Bank6Data, ath_hal_reverseBits(6, 3), + 3, 131, 3); + } + } else { + ar5212ModifyRfBuffer(priv->Bank6Data, ob5GHz, 3, 247, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, db5GHz, 3, 244, 0); + + } + + /* Bank 7 Setup */ + RF_BANK_SETUP(priv, 7, modesIndex); + + /* Write Analog registers */ + HAL_INI_WRITE_BANK(ah, ar5212Bank1_5413, priv->Bank1Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank2_5413, priv->Bank2Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank3_5413, priv->Bank3Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank6_5413, priv->Bank6Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank7_5413, priv->Bank7Data, regWrites); + + /* Now that we have reprogrammed rfgain value, clear the flag. */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + return AH_TRUE; +#undef RF_BANK_SETUP +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar5413GetRfBank(struct ath_hal *ah, int bank) +{ + struct ar5413State *priv = AR5413(ah); + + HALASSERT(priv != AH_NULL); + switch (bank) { + case 1: return priv->Bank1Data; + case 2: return priv->Bank2Data; + case 3: return priv->Bank3Data; + case 6: return priv->Bank6Data; + case 7: return priv->Bank7Data; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Return indices surrounding the value in sorted integer lists. + * + * NB: the input list is assumed to be sorted in ascending order + */ +static void +GetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize, + uint32_t *vlo, uint32_t *vhi) +{ + int16_t target = v; + const uint16_t *ep = lp+listSize; + const uint16_t *tp; + + /* + * Check first and last elements for out-of-bounds conditions. + */ + if (target < lp[0]) { + *vlo = *vhi = 0; + return; + } + if (target >= ep[-1]) { + *vlo = *vhi = listSize - 1; + return; + } + + /* look for value being near or between 2 values in list */ + for (tp = lp; tp < ep; tp++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (*tp == target) { + *vlo = *vhi = tp - (const uint16_t *) lp; + return; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < tp[1]) { + *vlo = tp - (const uint16_t *) lp; + *vhi = *vlo + 1; + return; + } + } +} + +/* + * Fill the Vpdlist for indices Pmax-Pmin + */ +static HAL_BOOL +ar5413FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t Pmax, + const int16_t *pwrList, const uint16_t *VpdList, + uint16_t numIntercepts, + uint16_t retVpdList[][64]) +{ + uint16_t ii, jj, kk; + int16_t currPwr = (int16_t)(2*Pmin); + /* since Pmin is pwr*2 and pwrList is 4*pwr */ + uint32_t idxL, idxR; + + ii = 0; + jj = 0; + + if (numIntercepts < 2) + return AH_FALSE; + + while (ii <= (uint16_t)(Pmax - Pmin)) { + GetLowerUpperIndex(currPwr, (const uint16_t *) pwrList, + numIntercepts, &(idxL), &(idxR)); + if (idxR < 1) + idxR = 1; /* extrapolate below */ + if (idxL == (uint32_t)(numIntercepts - 1)) + idxL = numIntercepts - 2; /* extrapolate above */ + if (pwrList[idxL] == pwrList[idxR]) + kk = VpdList[idxL]; + else + kk = (uint16_t) + (((currPwr - pwrList[idxL])*VpdList[idxR]+ + (pwrList[idxR] - currPwr)*VpdList[idxL])/ + (pwrList[idxR] - pwrList[idxL])); + retVpdList[pdGainIdx][ii] = kk; + ii++; + currPwr += 2; /* half dB steps */ + } + + return AH_TRUE; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static int16_t +interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight) +{ + int16_t rv; + + if (srcRight != srcLeft) { + rv = ((target - srcLeft)*targetRight + + (srcRight - target)*targetLeft) / (srcRight - srcLeft); + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Uses the data points read from EEPROM to reconstruct the pdadc power table + * Called by ar5413SetPowerTable() + */ +static int +ar5413getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel, + const RAW_DATA_STRUCT_2413 *pRawDataset, + uint16_t pdGainOverlap_t2, + int16_t *pMinCalPower, uint16_t pPdGainBoundaries[], + uint16_t pPdGainValues[], uint16_t pPDADCValues[]) +{ + struct ar5413State *priv = AR5413(ah); +#define VpdTable_L priv->vpdTable_L +#define VpdTable_R priv->vpdTable_R +#define VpdTable_I priv->vpdTable_I + uint32_t ii, jj, kk; + int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */ + uint32_t idxL, idxR; + uint32_t numPdGainsUsed = 0; + /* + * If desired to support -ve power levels in future, just + * change pwr_I_0 to signed 5-bits. + */ + int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on. */ + int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on */ + uint16_t numVpd = 0; + uint16_t Vpd_step; + int16_t tmpVal ; + uint32_t sizeCurrVpdTable, maxIndex, tgtIndex; + + /* Get upper lower index */ + GetLowerUpperIndex(channel, pRawDataset->pChannels, + pRawDataset->numChannels, &(idxL), &(idxR)); + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain; + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]; + if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) { + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]; + } + Pmin_t2[numPdGainsUsed] = (int16_t) + (Pmin_t2[numPdGainsUsed] / 2); + Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]) + Pmax_t2[numPdGainsUsed] = + pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2); + ar5413FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L + ); + ar5413FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R + ); + for (kk = 0; kk < (uint16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) { + VpdTable_I[numPdGainsUsed][kk] = + interpolate_signed( + channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR], + (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]); + } + /* fill VpdTable_I for this pdGain */ + numPdGainsUsed++; + } + /* if this pdGain is used */ + } + + *pMinCalPower = Pmin_t2[0]; + kk = 0; /* index for the final table */ + for (ii = 0; ii < numPdGainsUsed; ii++) { + if (ii == (numPdGainsUsed - 1)) + pPdGainBoundaries[ii] = Pmax_t2[ii] + + PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB; + else + pPdGainBoundaries[ii] = (uint16_t) + ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 ); + if (pPdGainBoundaries[ii] > 63) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: clamp pPdGainBoundaries[%d] %d\n", + __func__, ii, pPdGainBoundaries[ii]);/*XXX*/ + pPdGainBoundaries[ii] = 63; + } + + /* Find starting index for this pdGain */ + if (ii == 0) + ss = 0; /* for the first pdGain, start from index 0 */ + else + ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) - + pdGainOverlap_t2; + Vpd_step = (uint16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + *-ve ss indicates need to extrapolate data below for this pdGain + */ + while (ss < 0) { + tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step); + pPDADCValues[kk++] = (uint16_t)((tmpVal < 0) ? 0 : tmpVal); + ss++; + } + + sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii]; + tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii]; + maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; + + while (ss < (int16_t)maxIndex) + pPDADCValues[kk++] = VpdTable_I[ii][ss++]; + + Vpd_step = (uint16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] - + VpdTable_I[ii][sizeCurrVpdTable-2]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + * for last gain, pdGainBoundary == Pmax_t2, so will + * have to extrapolate + */ + if (tgtIndex > maxIndex) { /* need to extrapolate above */ + while(ss < (int16_t)tgtIndex) { + tmpVal = (uint16_t) + (VpdTable_I[ii][sizeCurrVpdTable-1] + + (ss-maxIndex)*Vpd_step); + pPDADCValues[kk++] = (tmpVal > 127) ? + 127 : tmpVal; + ss++; + } + } /* extrapolated above */ + } /* for all pdGainUsed */ + + while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) { + pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1]; + ii++; + } + while (kk < 128) { + pPDADCValues[kk] = pPDADCValues[kk-1]; + kk++; + } + + return numPdGainsUsed; +#undef VpdTable_L +#undef VpdTable_R +#undef VpdTable_I +} + +static HAL_BOOL +ar5413SetPowerTable(struct ath_hal *ah, + int16_t *minPower, int16_t *maxPower, HAL_CHANNEL_INTERNAL *chan, + uint16_t *rfXpdGain) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL; + uint16_t pdGainOverlap_t2; + int16_t minCalPower5413_t2; + uint16_t *pdadcValues = ahp->ah_pcdacTable; + uint16_t gainBoundaries[4]; + uint32_t reg32, regoffset; + int i, numPdGainsUsed; +#ifndef AH_USE_INIPDGAIN + uint32_t tpcrg1; +#endif + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n", + __func__, chan->channel,chan->channelFlags); + + if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else { + HALASSERT(IS_CHAN_5GHZ(chan)); + pRawDataset = &ee->ee_rawDataset2413[headerInfo11A]; + } + + pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5), + AR_PHY_TPCRG5_PD_GAIN_OVERLAP); + + numPdGainsUsed = ar5413getGainBoundariesAndPdadcsForPowers(ah, + chan->channel, pRawDataset, pdGainOverlap_t2, + &minCalPower5413_t2,gainBoundaries, rfXpdGain, pdadcValues); + HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3); + +#ifdef AH_USE_INIPDGAIN + /* + * Use pd_gains curve from eeprom; Atheros always uses + * the default curve from the ini file but some vendors + * (e.g. Zcomax) want to override this curve and not + * honoring their settings results in tx power 5dBm low. + */ + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, + (pRawDataset->pDataPerChannel[0].numPdGains - 1)); +#else + tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1); + tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN) + | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN); + switch (numPdGainsUsed) { + case 3: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING3; + tpcrg1 |= SM(rfXpdGain[2], AR_PHY_TPCRG1_PDGAIN_SETTING3); + /* fall thru... */ + case 2: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING2; + tpcrg1 |= SM(rfXpdGain[1], AR_PHY_TPCRG1_PDGAIN_SETTING2); + /* fall thru... */ + case 1: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING1; + tpcrg1 |= SM(rfXpdGain[0], AR_PHY_TPCRG1_PDGAIN_SETTING1); + break; + } +#ifdef AH_DEBUG + if (tpcrg1 != OS_REG_READ(ah, AR_PHY_TPCRG1)) + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: using non-default " + "pd_gains (default 0x%x, calculated 0x%x)\n", + __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1); +#endif + OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1); +#endif + + /* + * Note the pdadc table may not start at 0 dBm power, could be + * negative or greater than 0. Need to offset the power + * values by the amount of minPower for griffin + */ + if (minCalPower5413_t2 != 0) + ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower5413_t2); + else + ahp->ah_txPowerIndexOffset = 0; + + /* Finally, write the power values into the baseband power table */ + regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */ + for (i = 0; i < 32; i++) { + reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0) | + ((pdadcValues[4*i + 1] & 0xFF) << 8) | + ((pdadcValues[4*i + 2] & 0xFF) << 16) | + ((pdadcValues[4*i + 3] & 0xFF) << 24) ; + OS_REG_WRITE(ah, regoffset, reg32); + regoffset += 4; + } + + OS_REG_WRITE(ah, AR_PHY_TPCRG5, + SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | + SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | + SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | + SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | + SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); + + return AH_TRUE; +} + +static int16_t +ar5413GetMinPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) +{ + uint32_t ii,jj; + uint16_t Pmin=0,numVpd; + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = data->pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + Pmin = data->pDataPerPDGain[jj].pwr_t4[0]; + return(Pmin); + } + } + return(Pmin); +} + +static int16_t +ar5413GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) +{ + uint32_t ii; + uint16_t Pmax=0,numVpd; + + for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + /* work forwards cuase lowest pdGain for highest power */ + numVpd = data->pDataPerPDGain[ii].numVpd; + if (numVpd > 0) { + Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1]; + return(Pmax); + } + } + return(Pmax); +} + +static HAL_BOOL +ar5413GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, + int16_t *maxPow, int16_t *minPow) +{ + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL; + const RAW_DATA_PER_CHANNEL_2413 *data=AH_NULL; + uint16_t numChannels; + int totalD,totalF, totalMin,last, i; + + *maxPow = 0; + + if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else { + HALASSERT(IS_CHAN_5GHZ(chan)); + pRawDataset = &ee->ee_rawDataset2413[headerInfo11A]; + } + + numChannels = pRawDataset->numChannels; + data = pRawDataset->pDataPerChannel; + + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if (numChannels < 1) + return(AH_FALSE); + + if ((chan->channel < data[0].channelValue) || + (chan->channel > data[numChannels-1].channelValue)) { + if (chan->channel < data[0].channelValue) { + *maxPow = ar5413GetMaxPower(ah, &data[0]); + *minPow = ar5413GetMinPower(ah, &data[0]); + return(AH_TRUE); + } else { + *maxPow = ar5413GetMaxPower(ah, &data[numChannels - 1]); + *minPow = ar5413GetMinPower(ah, &data[numChannels - 1]); + return(AH_TRUE); + } + } + + /* Linearly interpolate the power value now */ + for (last=0,i=0; (ichannel > data[i].channelValue); + last = i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = ar5413GetMaxPower(ah, &data[i]) - ar5413GetMaxPower(ah, &data[last]); + *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + + ar5413GetMaxPower(ah, &data[last])*totalD)/totalD); + totalMin = ar5413GetMinPower(ah, &data[i]) - ar5413GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + + ar5413GetMinPower(ah, &data[last])*totalD)/totalD); + return(AH_TRUE); + } else { + if (chan->channel == data[i].channelValue) { + *maxPow = ar5413GetMaxPower(ah, &data[i]); + *minPow = ar5413GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar5413RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +/* + * Allocate memory for analog bank scratch buffers + * Scratch Buffer will be reinitialized every reset so no need to zero now + */ +static HAL_BOOL +ar5413RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5413State *priv; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar5413State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar5413RfDetach; + priv->base.writeRegs = ar5413WriteRegs; + priv->base.getRfBank = ar5413GetRfBank; + priv->base.setChannel = ar5413SetChannel; + priv->base.setRfRegs = ar5413SetRfRegs; + priv->base.setPowerTable = ar5413SetPowerTable; + priv->base.getChannelMaxMinPower = ar5413GetChannelMaxMinPower; + priv->base.getNfAdjust = ar5212GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + + return AH_TRUE; +} + +static HAL_BOOL +ar5413Probe(struct ath_hal *ah) +{ + return IS_5413(ah); +} +AH_RF(RF5413, ar5413Probe, ar5413RfAttach); diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312.h b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312.h new file mode 100644 index 0000000000..3eb1a162aa --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: src/sys/dev/ath/ath_hal/ar5312/ar5312.h,v 1.2.2.1.2.1 2009/04/15 03:14:26 kensmith Exp $ + */ +#ifndef _ATH_AR5312_H_ +#define _ATH_AR5312_H_ + +#include "ah_soc.h" +#include "ar5212/ar5212.h" + +#define AR5312_UNIT(_ah) \ + (((const struct ar531x_config *)((_ah)->ah_st))->unit) +#define AR5312_BOARDCONFIG(_ah) \ + (((const struct ar531x_config *)((_ah)->ah_st))->board) +#define AR5312_RADIOCONFIG(_ah) \ + (((const struct ar531x_config *)((_ah)->ah_st))->radio) + +#define IS_5312_2_X(ah) \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && \ + (AH_PRIVATE(ah)->ah_macRev == 2 || AH_PRIVATE(ah)->ah_macRev == 7)) +#define IS_5315(ah) \ + (AH_PRIVATE(ah)->ah_devid == AR5212_AR2315_REV6 || \ + AH_PRIVATE(ah)->ah_devid == AR5212_AR2315_REV7 || \ + AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV1 || \ + AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV2) + +extern HAL_BOOL ar5312IsInterruptPending(struct ath_hal *ah); + +/* AR5312 */ +extern HAL_BOOL ar5312GpioCfgOutput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5312GpioCfgInput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5312GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val); +extern uint32_t ar5312GpioGet(struct ath_hal *ah, uint32_t gpio); +extern void ar5312GpioSetIntr(struct ath_hal *ah, u_int, uint32_t ilevel); + +/* AR2315+ */ +extern HAL_BOOL ar5315GpioCfgOutput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5315GpioCfgInput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5315GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val); +extern uint32_t ar5315GpioGet(struct ath_hal *ah, uint32_t gpio); +extern void ar5315GpioSetIntr(struct ath_hal *ah, u_int, uint32_t ilevel); + +extern void ar5312SetLedState(struct ath_hal *ah, HAL_LED_STATE state); +extern HAL_BOOL ar5312DetectCardPresent(struct ath_hal *ah); +extern void ar5312SetupClock(struct ath_hal *ah, HAL_OPMODE opmode); +extern void ar5312RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode); +extern void ar5312DumpState(struct ath_hal *ah); +extern HAL_BOOL ar5312Reset(struct ath_hal *ah, HAL_OPMODE opmode, + HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status); +extern HAL_BOOL ar5312ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan); +extern HAL_BOOL ar5312SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, + int setChip); +extern HAL_BOOL ar5312PhyDisable(struct ath_hal *ah); +extern HAL_BOOL ar5312Disable(struct ath_hal *ah); +extern HAL_BOOL ar5312MacReset(struct ath_hal *ah, unsigned int RCMask); +extern uint32_t ar5312GetPowerMode(struct ath_hal *ah); +extern HAL_BOOL ar5312GetPowerStatus(struct ath_hal *ah); + +/* BSP functions */ +extern HAL_BOOL ar5312EepromRead(struct ath_hal *, u_int off, uint16_t *data); +extern HAL_BOOL ar5312EepromWrite(struct ath_hal *, u_int off, uint16_t data); + +#endif /* _ATH_AR3212_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_attach.c b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_attach.c new file mode 100644 index 0000000000..60d3a0ff5c --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_attach.c @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: src/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c,v 1.3.2.1.2.1 2009/04/15 03:14:26 kensmith Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5312/ar5312.h" +#include "ar5312/ar5312reg.h" +#include "ar5312/ar5312phy.h" + +/* Add static register initialization vectors */ +#define AH_5212_COMMON +#include "ar5212/ar5212.ini" + +static HAL_BOOL ar5312GetMacAddr(struct ath_hal *ah); + +static void +ar5312AniSetup(struct ath_hal *ah) +{ + static const struct ar5212AniParams aniparams = { + .maxNoiseImmunityLevel = 4, /* levels 0..4 */ + .totalSizeDesired = { -41, -41, -48, -48, -48 }, + .coarseHigh = { -18, -18, -16, -14, -12 }, + .coarseLow = { -56, -56, -60, -60, -60 }, + .firpwr = { -72, -72, -75, -78, -80 }, + .maxSpurImmunityLevel = 2, + .cycPwrThr1 = { 2, 4, 6 }, + .maxFirstepLevel = 2, /* levels 0..2 */ + .firstep = { 0, 4, 8 }, + .ofdmTrigHigh = 500, + .ofdmTrigLow = 200, + .cckTrigHigh = 200, + .cckTrigLow = 100, + .rssiThrHigh = 40, + .rssiThrLow = 7, + .period = 100, + }; + ar5212AniAttach(ah, &aniparams, &aniparams, AH_TRUE); +} + +/* + * Attach for an AR5312 part. + */ +static struct ath_hal * +ar5312Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH_NULL; + struct ath_hal *ah; + struct ath_hal_rf *rf; + uint32_t val; + uint16_t eeval; + HAL_STATUS ecode; + + HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + __func__, sc, st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp = ath_hal_malloc(sizeof (struct ath_hal_5212)); + if (ahp == AH_NULL) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot allocate memory for state block\n", __func__); + *status = HAL_ENOMEM; + return AH_NULL; + } + ar5212InitState(ahp, devid, sc, st, sh, status); + ah = &ahp->ah_priv.h; + + /* override 5212 methods for our needs */ + ah->ah_reset = ar5312Reset; + ah->ah_phyDisable = ar5312PhyDisable; + ah->ah_setLedState = ar5312SetLedState; + ah->ah_detectCardPresent = ar5312DetectCardPresent; + ah->ah_setPowerMode = ar5312SetPowerMode; + ah->ah_getPowerMode = ar5312GetPowerMode; + ah->ah_isInterruptPending = ar5312IsInterruptPending; + + ahp->ah_priv.ah_eepromRead = ar5312EepromRead; +#ifdef AH_SUPPORT_WRITE_EEPROM + ahp->ah_priv.ah_eepromWrite = ar5312EepromWrite; +#endif +#if ( AH_SUPPORT_2316 || AH_SUPPORT_2317) + if (IS_5315(ah)) { + ahp->ah_priv.ah_gpioCfgOutput = ar5315GpioCfgOutput; + ahp->ah_priv.ah_gpioCfgInput = ar5315GpioCfgInput; + ahp->ah_priv.ah_gpioGet = ar5315GpioGet; + ahp->ah_priv.ah_gpioSet = ar5315GpioSet; + ahp->ah_priv.ah_gpioSetIntr = ar5315GpioSetIntr; + } else +#endif + { + ahp->ah_priv.ah_gpioCfgOutput = ar5312GpioCfgOutput; + ahp->ah_priv.ah_gpioCfgInput = ar5312GpioCfgInput; + ahp->ah_priv.ah_gpioGet = ar5312GpioGet; + ahp->ah_priv.ah_gpioSet = ar5312GpioSet; + ahp->ah_priv.ah_gpioSetIntr = ar5312GpioSetIntr; + } + + ah->ah_gpioCfgInput = ahp->ah_priv.ah_gpioCfgInput; + ah->ah_gpioCfgOutput = ahp->ah_priv.ah_gpioCfgOutput; + ah->ah_gpioGet = ahp->ah_priv.ah_gpioGet; + ah->ah_gpioSet = ahp->ah_priv.ah_gpioSet; + ah->ah_gpioSetIntr = ahp->ah_priv.ah_gpioSetIntr; + + /* setup common ini data; rf backends handle remainder */ + HAL_INI_INIT(&ahp->ah_ini_modes, ar5212Modes, 6); + HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 2); + + if (!ar5312ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + ecode = HAL_EIO; + goto bad; + } + +#if ( AH_SUPPORT_2316 || AH_SUPPORT_2317) + if ((devid == AR5212_AR2315_REV6) || + (devid == AR5212_AR2315_REV7) || + (devid == AR5212_AR2317_REV1) || + (devid == AR5212_AR2317_REV2) ) { + val = ((OS_REG_READ(ah, (AR5315_RSTIMER_BASE -((uint32_t) sh)) + AR5315_WREV)) >> AR5315_WREV_S) + & AR5315_WREV_ID; + AH_PRIVATE(ah)->ah_macVersion = val >> AR5315_WREV_ID_S; + AH_PRIVATE(ah)->ah_macRev = val & AR5315_WREV_REVISION; + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: Mac Chip Rev 0x%02x.%x\n" , __func__, + AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev); + } else +#endif + { + val = OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) sh)) + 0x0020); + val = OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) sh)) + 0x0080); + /* Read Revisions from Chips */ + val = ((OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) sh)) + AR5312_WREV)) >> AR5312_WREV_S) & AR5312_WREV_ID; + AH_PRIVATE(ah)->ah_macVersion = val >> AR5312_WREV_ID_S; + AH_PRIVATE(ah)->ah_macRev = val & AR5312_WREV_REVISION; + } + /* XXX - THIS IS WRONG. NEEDS TO BE FIXED */ + if (((AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_VENICE && + AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_VENICE) || + AH_PRIVATE(ah)->ah_macRev < AR_SREV_D2PLUS) && + AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_COBRA) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: Mac Chip Rev 0x%02x.%x is not supported by " + "this driver\n", __func__, + AH_PRIVATE(ah)->ah_macVersion, + AH_PRIVATE(ah)->ah_macRev); +#endif + ecode = HAL_ENOTSUPP; + goto bad; + } + + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); + + if (!ar5212ChipTest(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", + __func__); + ecode = HAL_ESELFTEST; + goto bad; + } + + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* Read Radio Chip Rev Extract */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah); + + rf = ath_hal_rfprobe(ah, &ecode); + if (rf == AH_NULL) + goto bad; + if (IS_RAD5112(ah) && !IS_RADX112_REV2(ah)) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: 5112 Rev 1 is not supported by this " + "driver (analog5GhzRev 0x%x)\n", __func__, + AH_PRIVATE(ah)->ah_analog5GhzRev); +#endif + ecode = HAL_ENOTSUPP; + goto bad; + } + + ecode = ath_hal_legacyEepromAttach(ah); + if (ecode != HAL_OK) { + goto bad; + } + + /* + * If Bmode and AR5212, verify 2.4 analog exists + */ + if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) && + (AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD5111_SREV_MAJOR) { + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00004007); + OS_DELAY(2000); + AH_PRIVATE(ah)->ah_analog2GhzRev = ar5212GetRadioRev(ah); + + /* Set baseband for 5GHz chip */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + OS_DELAY(2000); + if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != AR_RAD2111_SREV_MAJOR) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: 2G Radio Chip Rev 0x%02X is not " + "supported by this driver\n", __func__, + AH_PRIVATE(ah)->ah_analog2GhzRev); +#endif + ecode = HAL_ENOTSUPP; + goto bad; + } + } + + ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read regulatory domain from EEPROM\n", + __func__); + goto bad; + } + AH_PRIVATE(ah)->ah_currentRD = eeval; + /* XXX record serial number */ + + /* XXX other capabilities */ + /* + * Got everything we need now to setup the capabilities. + */ + if (!ar5212FillCapabilityInfo(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: failed ar5212FillCapabilityInfo\n", __func__); + ecode = HAL_EEREAD; + goto bad; + } + + if (!rf->attach(ah, &ecode)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", + __func__, ecode); + goto bad; + } + /* arrange a direct call instead of thunking */ + AH_PRIVATE(ah)->ah_getNfAdjust = ahp->ah_rfHal->getNfAdjust; + + /* Initialize gain ladder thermal calibration structure */ + ar5212InitializeGainValues(ah); + + /* BSP specific call for MAC address of this WMAC device */ + if (!ar5312GetMacAddr(ah)) { + ecode = HAL_EEBADMAC; + goto bad; + } + + ar5312AniSetup(ah); + ar5212InitNfCalHistBuffer(ah); + + /* XXX EAR stuff goes here */ + return ah; + +bad: + if (ahp) + ar5212Detach((struct ath_hal *) ahp); + if (status) + *status = ecode; + return AH_NULL; +} + +static HAL_BOOL +ar5312GetMacAddr(struct ath_hal *ah) +{ + const struct ar531x_boarddata *board = AR5312_BOARDCONFIG(ah); + int wlanNum = AR5312_UNIT(ah); + const uint8_t *macAddr; + + switch (wlanNum) { + case 0: + macAddr = board->wlan0Mac; + break; + case 1: + macAddr = board->wlan1Mac; + break; + default: +#ifdef AH_DEBUG + ath_hal_printf(ah, "Invalid WLAN wmac index (%d)\n", + wlanNum); +#endif + return AH_FALSE; + } + OS_MEMCPY(AH5212(ah)->ah_macaddr, macAddr, 6); + return AH_TRUE; +} + +static const char* +ar5312Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID) { + switch (devid) { + case AR5212_AR5312_REV2: + case AR5212_AR5312_REV7: + return "Atheros 5312 WiSoC"; + case AR5212_AR2313_REV8: + return "Atheros 2313 WiSoC"; + case AR5212_AR2315_REV6: + case AR5212_AR2315_REV7: + return "Atheros 2315 WiSoC"; + case AR5212_AR2317_REV1: + return "Atheros 2317 WiSoC"; + case AR5212_AR2413: + return "Atheros 2413"; + case AR5212_AR2417: + return "Atheros 2417"; + } + } + return AH_NULL; +} +AH_CHIP(AR5312, ar5312Probe, ar5312Attach); diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_eeprom.c b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_eeprom.c new file mode 100644 index 0000000000..c14b8b2cdb --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_eeprom.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5312_eeprom.c,v 1.4 2008/11/10 04:08:04 sam Exp $ + */ +#include "opt_ah.h" + + +#ifdef AH_SUPPORT_AR5312 + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5312/ar5312.h" +#include "ar5312/ar5312reg.h" +#include "ar5212/ar5212desc.h" + +/* + * Read 16 bits of data from offset into *data + */ +HAL_BOOL +ar5312EepromRead(struct ath_hal *ah, u_int off, uint16_t *dataIn) +{ + int i,offset; + const char *eepromAddr = AR5312_RADIOCONFIG(ah); + uint8_t *data; + + data = (uint8_t *) dataIn; + for (i=0,offset=2*off; i<2; i++,offset++) { + data[i] = eepromAddr[offset]; + } + return AH_TRUE; +} +#endif /* AH_SUPPORT_AR5312 */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_gpio.c b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_gpio.c new file mode 100644 index 0000000000..02ed5651dd --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_gpio.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5312_gpio.c,v 1.3 2008/11/10 04:08:04 sam Exp $ + */ +#include "opt_ah.h" + +#ifdef AH_SUPPORT_AR5312 + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5312/ar5312.h" +#include "ar5312/ar5312reg.h" +#include "ar5312/ar5312phy.h" + +#define AR_NUM_GPIO 6 /* 6 GPIO pins */ +#define AR5312_GPIOD_MASK 0x0000002F /* GPIO data reg r/w mask */ + +/* + * Configure GPIO Output lines + */ +HAL_BOOL +ar5312GpioCfgOutput(struct ath_hal *ah, uint32_t gpio) +{ + uint32_t gpioOffset = (AR5312_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + HALASSERT(gpio < AR_NUM_GPIO); + + OS_REG_WRITE(ah, gpioOffset+AR5312_GPIOCR, + (OS_REG_READ(ah, gpioOffset+AR5312_GPIOCR) &~ AR_GPIOCR_CR_A(gpio)) + | AR_GPIOCR_CR_A(gpio)); + + return AH_TRUE; +} + +/* + * Configure GPIO Input lines + */ +HAL_BOOL +ar5312GpioCfgInput(struct ath_hal *ah, uint32_t gpio) +{ + uint32_t gpioOffset = (AR5312_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + HALASSERT(gpio < AR_NUM_GPIO); + + OS_REG_WRITE(ah, gpioOffset+AR5312_GPIOCR, + (OS_REG_READ(ah, gpioOffset+AR5312_GPIOCR) &~ AR_GPIOCR_CR_A(gpio)) + | AR_GPIOCR_CR_N(gpio)); + + return AH_TRUE; +} + +/* + * Once configured for I/O - set output lines + */ +HAL_BOOL +ar5312GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) +{ + uint32_t reg; + uint32_t gpioOffset = (AR5312_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + HALASSERT(gpio < AR_NUM_GPIO); + + reg = OS_REG_READ(ah, gpioOffset+AR5312_GPIODO); + reg &= ~(1 << gpio); + reg |= (val&1) << gpio; + + OS_REG_WRITE(ah, gpioOffset+AR5312_GPIODO, reg); + return AH_TRUE; +} + +/* + * Once configured for I/O - get input lines + */ +uint32_t +ar5312GpioGet(struct ath_hal *ah, uint32_t gpio) +{ + uint32_t gpioOffset = (AR5312_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + if (gpio < AR_NUM_GPIO) { + uint32_t val = OS_REG_READ(ah, gpioOffset+AR5312_GPIODI); + val = ((val & AR5312_GPIOD_MASK) >> gpio) & 0x1; + return val; + } else { + return 0xffffffff; + } +} + +/* + * Set the GPIO Interrupt + */ +void +ar5312GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) +{ + uint32_t val; + uint32_t gpioOffset = (AR5312_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + /* XXX bounds check gpio */ + val = OS_REG_READ(ah, gpioOffset+AR5312_GPIOCR); + val &= ~(AR_GPIOCR_CR_A(gpio) | + AR_GPIOCR_INT_MASK | AR_GPIOCR_INT_ENA | AR_GPIOCR_INT_SEL); + val |= AR_GPIOCR_CR_N(gpio) | AR_GPIOCR_INT(gpio) | AR_GPIOCR_INT_ENA; + if (ilevel) + val |= AR_GPIOCR_INT_SELH; /* interrupt on pin high */ + else + val |= AR_GPIOCR_INT_SELL; /* interrupt on pin low */ + + /* Don't need to change anything for low level interrupt. */ + OS_REG_WRITE(ah, gpioOffset+AR5312_GPIOCR, val); + + /* Change the interrupt mask. */ + (void) ar5212SetInterrupts(ah, AH5212(ah)->ah_maskReg | HAL_INT_GPIO); +} + + +#endif /* AH_SUPPORT_AR5312 */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_interrupts.c b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_interrupts.c new file mode 100644 index 0000000000..c40191ed55 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_interrupts.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5312_interrupts.c,v 1.2 2008/11/10 01:19:39 sam Exp $ + */ +#include "opt_ah.h" + +#ifdef AH_SUPPORT_AR5312 + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5312/ar5312.h" +#include "ar5312/ar5312reg.h" +#include "ar5312/ar5312phy.h" + + +/* + * Checks to see if an interrupt is pending on our NIC + * + * Returns: TRUE if an interrupt is pending + * FALSE if not + */ +HAL_BOOL +ar5312IsInterruptPending(struct ath_hal *ah) +{ + /* + * Some platforms trigger our ISR before applying power to + * the card. For the 5312, this is always true. + */ + + return(AH_TRUE); +} +#endif /* AH_SUPPORT_AR5312 */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_misc.c b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_misc.c new file mode 100644 index 0000000000..79283186c5 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_misc.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5312_misc.c,v 1.4 2008/11/22 07:40:15 sam Exp $ + */ +#include "opt_ah.h" + +#ifdef AH_SUPPORT_AR5312 + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5312/ar5312.h" +#include "ar5312/ar5312reg.h" +#include "ar5312/ar5312phy.h" + +#define AR_NUM_GPIO 6 /* 6 GPIO pins */ +#define AR_GPIOD_MASK 0x0000002F /* GPIO data reg r/w mask */ + +/* + * Change the LED blinking pattern to correspond to the connectivity + */ +void +ar5312SetLedState(struct ath_hal *ah, HAL_LED_STATE state) +{ + uint32_t val; + uint32_t resOffset = (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)); + if(IS_2316(ah)) return; /* not yet */ + val = SM(AR5312_PCICFG_LEDSEL0, AR5312_PCICFG_LEDSEL) | + SM(AR5312_PCICFG_LEDMOD0, AR5312_PCICFG_LEDMODE) | + 2; + OS_REG_WRITE(ah, resOffset+AR5312_PCICFG, + (OS_REG_READ(ah, AR5312_PCICFG) &~ + (AR5312_PCICFG_LEDSEL | AR5312_PCICFG_LEDMODE | + AR5312_PCICFG_LEDSBR)) + | val); +} + +/* + * Detect if our wireless mac is present. + */ +HAL_BOOL +ar5312DetectCardPresent(struct ath_hal *ah) +{ + uint16_t macVersion, macRev; + uint32_t v; + + /* + * Read the Silicon Revision register and compare that + * to what we read at attach time. If the same, we say + * a card/device is present. + */ +#if (AH_SUPPORT_2316 || AH_SUPPORT_2317) + if(IS_5315(ah)) + { + v = (OS_REG_READ(ah, + (AR5315_RSTIMER_BASE-((uint32_t) ah->ah_sh)) + AR5315_WREV)) + & AR_SREV_ID; + macVersion = v >> AR_SREV_ID_S; + macRev = v & AR_SREV_REVISION; + return (AH_PRIVATE(ah)->ah_macVersion == macVersion && + AH_PRIVATE(ah)->ah_macRev == macRev); + } + else +#endif + { + v = (OS_REG_READ(ah, + (AR5312_RSTIMER_BASE-((uint32_t) ah->ah_sh)) + AR5312_WREV)) + & AR_SREV_ID; + macVersion = v >> AR_SREV_ID_S; + macRev = v & AR_SREV_REVISION; + return (AH_PRIVATE(ah)->ah_macVersion == macVersion && + AH_PRIVATE(ah)->ah_macRev == macRev); + } +} + +/* + * If 32KHz clock exists, use it to lower power consumption during sleep + * + * Note: If clock is set to 32 KHz, delays on accessing certain + * baseband registers (27-31, 124-127) are required. + */ +void +ar5312SetupClock(struct ath_hal *ah, HAL_OPMODE opmode) +{ + if (ar5212Use32KHzclock(ah, opmode)) { + /* + * Enable clocks to be turned OFF in BB during sleep + * and also enable turning OFF 32MHz/40MHz Refclk + * from A2. + */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x0d); + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0c); + OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x03); + OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x05); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) ? 0x14 : 0x18); + + OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1); + OS_REG_WRITE(ah, AR_TSF_PARM, 61); /* 32 KHz TSF incr */ + + } else { + OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */ + OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, + IS_RAD5112_ANY(ah) ? 39 : 31); + + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); + + if (IS_5312_2_X(ah)) { + /* Set ADC/DAC select values */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x04); + } else { + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); + OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); + OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) ? 0x14 : 0x18); + } + } +} + +/* + * If 32KHz clock exists, turn it off and turn back on the 32Mhz + */ +void +ar5312RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode) +{ + if (ar5212Use32KHzclock(ah, opmode)) { + /* # Set sleep clock rate back to 32 MHz. */ + OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */ + OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, + IS_RAD5112_ANY(ah) ? 39 : 31); + + /* + * Restore BB registers to power-on defaults + */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); + if (IS_5312_2_X(ah)) { + /* Set ADC/DAC select values */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x04); + } else { + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); + OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); + OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) ? 0x14 : 0x18); + } + } +} + +#endif /* AH_SUPPORT_AR5312 */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_power.c b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_power.c new file mode 100644 index 0000000000..1cc4ed64a0 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_power.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5312_power.c,v 1.4 2008/11/10 04:08:04 sam Exp $ + */ +#include "opt_ah.h" + +#ifdef AH_SUPPORT_AR5312 + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5312/ar5312.h" +#include "ar5312/ar5312reg.h" +#include "ar5212/ar5212desc.h" + +/* + * Notify Power Mgt is enabled in self-generated frames. + * If requested, force chip awake. + * + * Returns A_OK if chip is awake or successfully forced awake. + * + * WARNING WARNING WARNING + * There is a problem with the chip where sometimes it will not wake up. + */ +static HAL_BOOL +ar5312SetPowerModeAwake(struct ath_hal *ah, int setChip) +{ + /* No need for this at the moment for APs */ + return AH_TRUE; +} + +/* + * Notify Power Mgt is disabled in self-generated frames. + * If requested, force chip to sleep. + */ +static void +ar5312SetPowerModeSleep(struct ath_hal *ah, int setChip) +{ + /* No need for this at the moment for APs */ +} + +/* + * Notify Power Management is enabled in self-generating + * fames. If request, set power mode of chip to + * auto/normal. Duration in units of 128us (1/8 TU). + */ +static void +ar5312SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip) +{ + /* No need for this at the moment for APs */ +} + +/* + * Set power mgt to the requested mode, and conditionally set + * the chip as well + */ +HAL_BOOL +ar5312SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) +{ + struct ath_hal_5212 *ahp = AH5212(ah); +#ifdef AH_DEBUG + static const char* modes[] = { + "AWAKE", + "FULL-SLEEP", + "NETWORK SLEEP", + "UNDEFINED" + }; +#endif + int status = AH_TRUE; + + HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__, + modes[ahp->ah_powerMode], modes[mode], + setChip ? "set chip " : ""); + switch (mode) { + case HAL_PM_AWAKE: + status = ar5312SetPowerModeAwake(ah, setChip); + break; + case HAL_PM_FULL_SLEEP: + ar5312SetPowerModeSleep(ah, setChip); + break; + case HAL_PM_NETWORK_SLEEP: + ar5312SetPowerModeNetworkSleep(ah, setChip); + break; + default: + HALDEBUG(ah, HAL_DEBUG_POWER, "%s: unknown power mode %u\n", + __func__, mode); + return AH_FALSE; + } + ahp->ah_powerMode = mode; + return status; +} + +/* + * Return the current sleep mode of the chip + */ +uint32_t +ar5312GetPowerMode(struct ath_hal *ah) +{ + return HAL_PM_AWAKE; +} + +/* + * Return the current sleep state of the chip + * TRUE = sleeping + */ +HAL_BOOL +ar5312GetPowerStatus(struct ath_hal *ah) +{ + return 0; /* Currently, 5312 is never in sleep mode. */ +} +#endif /* AH_SUPPORT_AR5312 */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_reset.c b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_reset.c new file mode 100644 index 0000000000..6c0bb0a8a1 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312_reset.c @@ -0,0 +1,919 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5312_reset.c,v 1.10 2008/11/22 07:41:37 sam Exp $ + */ +#include "opt_ah.h" + +#ifdef AH_SUPPORT_AR5312 + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5312/ar5312.h" +#include "ar5312/ar5312reg.h" +#include "ar5312/ar5312phy.h" + +#include "ah_eeprom_v3.h" + +/* Additional Time delay to wait after activiting the Base band */ +#define BASE_ACTIVATE_DELAY 100 /* 100 usec */ +#define PLL_SETTLE_DELAY 300 /* 300 usec */ + +extern int16_t ar5212GetNf(struct ath_hal *, HAL_CHANNEL_INTERNAL *); +extern void ar5212SetRateDurationTable(struct ath_hal *, HAL_CHANNEL *); +extern HAL_BOOL ar5212SetTransmitPower(struct ath_hal *ah, + HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain); +extern void ar5212SetDeltaSlope(struct ath_hal *, HAL_CHANNEL *); +extern HAL_BOOL ar5212SetBoardValues(struct ath_hal *, HAL_CHANNEL_INTERNAL *); +extern void ar5212SetIFSTiming(struct ath_hal *, HAL_CHANNEL *); +extern HAL_BOOL ar5212IsSpurChannel(struct ath_hal *, HAL_CHANNEL *); +extern HAL_BOOL ar5212ChannelChange(struct ath_hal *, HAL_CHANNEL *); + +static HAL_BOOL ar5312SetResetReg(struct ath_hal *, uint32_t resetMask); + +static int +write_common(struct ath_hal *ah, const HAL_INI_ARRAY *ia, + HAL_BOOL bChannelChange, int writes) +{ +#define IS_NO_RESET_TIMER_ADDR(x) \ + ( (((x) >= AR_BEACON) && ((x) <= AR_CFP_DUR)) || \ + (((x) >= AR_SLEEP1) && ((x) <= AR_SLEEP3))) +#define V(r, c) (ia)->data[((r)*(ia)->cols) + (c)] + int i; + + /* Write Common Array Parameters */ + for (i = 0; i < ia->rows; i++) { + uint32_t reg = V(i, 0); + /* XXX timer/beacon setup registers? */ + /* On channel change, don't reset the PCU registers */ + if (!(bChannelChange && IS_NO_RESET_TIMER_ADDR(reg))) { + OS_REG_WRITE(ah, reg, V(i, 1)); + DMA_YIELD(writes); + } + } + return writes; +#undef IS_NO_RESET_TIMER_ADDR +#undef V +} + +/* + * Places the device in and out of reset and then places sane + * values in the registers based on EEPROM config, initialization + * vectors (as determined by the mode), and station configuration + * + * bChannelChange is used to preserve DMA/PCU registers across + * a HW Reset during channel change. + */ +HAL_BOOL +ar5312Reset(struct ath_hal *ah, HAL_OPMODE opmode, + HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status) +{ +#define N(a) (sizeof (a) / sizeof (a[0])) +#define FAIL(_code) do { ecode = _code; goto bad; } while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *ichan; + const HAL_EEPROM *ee; + uint32_t saveFrameSeqCount, saveDefAntenna; + uint32_t macStaId1, synthDelay, txFrm2TxDStart; + uint16_t rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL]; + int16_t cckOfdmPwrDelta = 0; + u_int modesIndex, freqIndex; + HAL_STATUS ecode; + int i, regWrites = 0; + uint32_t testReg; + uint32_t saveLedState = 0; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + ee = AH_PRIVATE(ah)->ah_eeprom; + + OS_MARK(ah, AH_MARK_RESET, bChannelChange); +#define IS(_c,_f) (((_c)->channelFlags & _f) || 0) + if ((IS(chan, CHANNEL_2GHZ) ^ IS(chan, CHANNEL_5GHZ)) == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n", + __func__, chan->channel, chan->channelFlags); + FAIL(HAL_EINVAL); + } + if ((IS(chan, CHANNEL_OFDM) ^ IS(chan, CHANNEL_CCK)) == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; not marked as OFDM or CCK\n", + __func__, chan->channel, chan->channelFlags); + FAIL(HAL_EINVAL); + } +#undef IS + /* + * Map public channel to private. + */ + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->channel, chan->channelFlags); + FAIL(HAL_EINVAL); + } + switch (opmode) { + case HAL_M_STA: + case HAL_M_IBSS: + case HAL_M_HOSTAP: + case HAL_M_MONITOR: + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n", + __func__, opmode); + FAIL(HAL_EINVAL); + break; + } + HALASSERT(ahp->ah_eeversion >= AR_EEPROM_VER3); + + /* Preserve certain DMA hardware registers on a channel change */ + if (bChannelChange) { + /* + * On Venice, the TSF is almost preserved across a reset; + * it requires the doubling writes to the RESET_TSF + * bit in the AR_BEACON register; it also has the quirk + * of the TSF going back in time on the station (station + * latches onto the last beacon's tsf during a reset 50% + * of the times); the latter is not a problem for adhoc + * stations since as long as the TSF is behind, it will + * get resynchronized on receiving the next beacon; the + * TSF going backwards in time could be a problem for the + * sleep operation (supported on infrastructure stations + * only) - the best and most general fix for this situation + * is to resynchronize the various sleep/beacon timers on + * the receipt of the next beacon i.e. when the TSF itself + * gets resynchronized to the AP's TSF - power save is + * needed to be temporarily disabled until that time + * + * Need to save the sequence number to restore it after + * the reset! + */ + saveFrameSeqCount = OS_REG_READ(ah, AR_D_SEQNUM); + } else + saveFrameSeqCount = 0; /* NB: silence compiler */ + + /* If the channel change is across the same mode - perform a fast channel change */ + if ((IS_2413(ah) || IS_5413(ah))) { + /* + * Channel change can only be used when: + * -channel change requested - so it's not the initial reset. + * -it's not a change to the current channel - often called when switching modes + * on a channel + * -the modes of the previous and requested channel are the same - some ugly code for XR + */ + if (bChannelChange && + (AH_PRIVATE(ah)->ah_curchan != AH_NULL) && + (chan->channel != AH_PRIVATE(ah)->ah_curchan->channel) && + ((chan->channelFlags & CHANNEL_ALL) == + (AH_PRIVATE(ah)->ah_curchan->channelFlags & CHANNEL_ALL))) { + if (ar5212ChannelChange(ah, chan)) + /* If ChannelChange completed - skip the rest of reset */ + return AH_TRUE; + } + } + + /* + * Preserve the antenna on a channel change + */ + saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA); + if (saveDefAntenna == 0) /* XXX magic constants */ + saveDefAntenna = 1; + + /* Save hardware flag before chip reset clears the register */ + macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & + (AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT); + + /* Save led state from pci config register */ + if (!IS_5315(ah)) + saveLedState = OS_REG_READ(ah, AR5312_PCICFG) & + (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK | + AR_PCICFG_LEDSLOW); + + ar5312RestoreClock(ah, opmode); /* move to refclk operation */ + + /* + * Adjust gain parameters before reset if + * there's an outstanding gain updated. + */ + (void) ar5212GetRfgain(ah); + + if (!ar5312ChipReset(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + FAIL(HAL_EIO); + } + + /* Setup the indices for the next set of register array writes */ + switch (chan->channelFlags & CHANNEL_ALL) { + case CHANNEL_A: + modesIndex = 1; + freqIndex = 1; + break; + case CHANNEL_T: + modesIndex = 2; + freqIndex = 1; + break; + case CHANNEL_B: + modesIndex = 3; + freqIndex = 2; + break; + case CHANNEL_PUREG: + modesIndex = 4; + freqIndex = 2; + break; + case CHANNEL_108G: + modesIndex = 5; + freqIndex = 2; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + FAIL(HAL_EINVAL); + } + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + /* Set correct Baseband to analog shift setting to access analog chips. */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0); + regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange, + regWrites); + ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites); + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) { + ar5212SetIFSTiming(ah, chan); + } + + /* Overwrite INI values for revised chipsets */ + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) { + /* ADC_CTL */ + OS_REG_WRITE(ah, AR_PHY_ADC_CTL, + SM(2, AR_PHY_ADC_CTL_OFF_INBUFGAIN) | + SM(2, AR_PHY_ADC_CTL_ON_INBUFGAIN) | + AR_PHY_ADC_CTL_OFF_PWDDAC | + AR_PHY_ADC_CTL_OFF_PWDADC); + + /* TX_PWR_ADJ */ + if (chan->channel == 2484) { + cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta - ee->ee_scaledCh14FilterCckDelta); + } else { + cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta); + } + + if (IS_CHAN_G(chan)) { + OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, + SM((ee->ee_cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_GAIN_DELTA) | + SM((cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX)); + } else { + OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, 0); + } + + /* Add barker RSSI thresh enable as disabled */ + OS_REG_CLR_BIT(ah, AR_PHY_DAG_CTRLCCK, + AR_PHY_DAG_CTRLCCK_EN_RSSI_THR); + OS_REG_RMW_FIELD(ah, AR_PHY_DAG_CTRLCCK, + AR_PHY_DAG_CTRLCCK_RSSI_THR, 2); + + /* Set the mute mask to the correct default */ + OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F); + } + + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) { + /* Clear reg to alllow RX_CLEAR line debug */ + OS_REG_WRITE(ah, AR_PHY_BLUETOOTH, 0); + } + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) { +#ifdef notyet + /* Enable burst prefetch for the data queues */ + OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... ); + /* Enable double-buffering */ + OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS); +#endif + } + + if (IS_5312_2_X(ah)) { + /* ADC_CTRL */ + OS_REG_WRITE(ah, AR_PHY_SIGMA_DELTA, + SM(2, AR_PHY_SIGMA_DELTA_ADC_SEL) | + SM(4, AR_PHY_SIGMA_DELTA_FILT2) | + SM(0x16, AR_PHY_SIGMA_DELTA_FILT1) | + SM(0, AR_PHY_SIGMA_DELTA_ADC_CLIP)); + + if (IS_CHAN_2GHZ(chan)) + OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, AR_PHY_RXGAIN_TXRX_RF_MAX, 0x0F); + + /* CCK Short parameter adjustment in 11B mode */ + if (IS_CHAN_B(chan)) + OS_REG_RMW_FIELD(ah, AR_PHY_CCK_RXCTRL4, AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT, 12); + + /* Set ADC/DAC select values */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x04); + + /* Increase 11A AGC Settling */ + if ((chan->channelFlags & CHANNEL_ALL) == CHANNEL_A) + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_AGC, 32); + } else { + /* Set ADC/DAC select values */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); + } + + /* Setup the transmit power values. */ + if (!ar5212SetTransmitPower(ah, ichan, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error init'ing transmit power\n", __func__); + FAIL(HAL_EIO); + } + + /* Write the analog registers */ + if (!ahp->ah_rfHal->setRfRegs(ah, ichan, modesIndex, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5212SetRfRegs failed\n", + __func__); + FAIL(HAL_EIO); + } + + /* Write delta slope for OFDM enabled modes (A, G, Turbo) */ + if (IS_CHAN_OFDM(chan)) { + if ((IS_5413(ah) || (AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3)) && + (!IS_CHAN_B(chan))) + ar5212SetSpurMitigation(ah, ichan); + ar5212SetDeltaSlope(ah, chan); + } + + /* Setup board specific options for EEPROM version 3 */ + if (!ar5212SetBoardValues(ah, ichan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error setting board options\n", __func__); + FAIL(HAL_EIO); + } + + /* Restore certain DMA hardware registers on a channel change */ + if (bChannelChange) + OS_REG_WRITE(ah, AR_D_SEQNUM, saveFrameSeqCount); + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr)); + OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4) + | macStaId1 + | AR_STA_ID1_RTS_USE_DEF + | ahp->ah_staId1Defaults + ); + ar5212SetOperatingMode(ah, opmode); + + /* Set Venice BSSID mask according to current state */ + OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask)); + OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4)); + + /* Restore previous led state */ + if (!IS_5315(ah)) + OS_REG_WRITE(ah, AR5312_PCICFG, OS_REG_READ(ah, AR_PCICFG) | saveLedState); + + /* Restore previous antenna */ + OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); + + /* then our BSSID */ + OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); + OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4)); + + /* Restore bmiss rssi & count thresholds */ + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); + + OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */ + + if (!ar5212SetChannel(ah, ichan)) + FAIL(HAL_EIO); + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1); + + ar5212SetRateDurationTable(ah, chan); + + /* Set Tx frame start to tx data start delay */ + if (IS_RAD5112_ANY(ah) && + (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan) || + IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan))) { + txFrm2TxDStart = + (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) ? + TX_FRAME_D_START_HALF_RATE: + TX_FRAME_D_START_QUARTER_RATE; + OS_REG_RMW_FIELD(ah, AR_PHY_TX_CTL, + AR_PHY_TX_FRAME_TO_TX_DATA_START, txFrm2TxDStart); + } + + /* + * Setup fast diversity. + * Fast diversity can be enabled or disabled via regadd.txt. + * Default is enabled. + * For reference, + * Disable: reg val + * 0x00009860 0x00009d18 (if 11a / 11g, else no change) + * 0x00009970 0x192bb514 + * 0x0000a208 0xd03e4648 + * + * Enable: 0x00009860 0x00009d10 (if 11a / 11g, else no change) + * 0x00009970 0x192fb514 + * 0x0000a208 0xd03e6788 + */ + + /* XXX Setup pre PHY ENABLE EAR additions */ + + /* flush SCAL reg */ + if (IS_5312_2_X(ah)) { + (void) OS_REG_READ(ah, AR_PHY_SLEEP_SCAL); + } + + /* + * Wait for the frequency synth to settle (synth goes on + * via AR_PHY_ACTIVE_EN). Read the phy active delay register. + * Value is in 100ns increments. + */ + synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; + if (IS_CHAN_CCK(chan)) { + synthDelay = (4 * synthDelay) / 22; + } else { + synthDelay /= 10; + } + + /* Activate the PHY (includes baseband activate and synthesizer on) */ + OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + + /* + * There is an issue if the AP starts the calibration before + * the base band timeout completes. This could result in the + * rx_clear false triggering. As a workaround we add delay an + * extra BASE_ACTIVATE_DELAY usecs to ensure this condition + * does not happen. + */ + if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) { + OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY); + } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) { + OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY); + } else { + OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY); + } + + /* + * The udelay method is not reliable with notebooks. + * Need to check to see if the baseband is ready + */ + testReg = OS_REG_READ(ah, AR_PHY_TESTCTRL); + /* Selects the Tx hold */ + OS_REG_WRITE(ah, AR_PHY_TESTCTRL, AR_PHY_TESTCTRL_TXHOLD); + i = 0; + while ((i++ < 20) && + (OS_REG_READ(ah, 0x9c24) & 0x10)) /* test if baseband not ready */ OS_DELAY(200); + OS_REG_WRITE(ah, AR_PHY_TESTCTRL, testReg); + + /* Calibrate the AGC and start a NF calculation */ + OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, + OS_REG_READ(ah, AR_PHY_AGC_CONTROL) + | AR_PHY_AGC_CONTROL_CAL + | AR_PHY_AGC_CONTROL_NF); + + if (!IS_CHAN_B(chan) && ahp->ah_bIQCalibration != IQ_CAL_DONE) { + /* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */ + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, + INIT_IQCAL_LOG_COUNT_MAX); + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_DO_IQCAL); + ahp->ah_bIQCalibration = IQ_CAL_RUNNING; + } else + ahp->ah_bIQCalibration = IQ_CAL_INACTIVE; + + /* Setup compression registers */ + ar5212SetCompRegs(ah); + + /* Set 1:1 QCU to DCU mapping for all queues */ + for (i = 0; i < AR_NUM_DCU; i++) + OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); + + ahp->ah_intrTxqs = 0; + for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++) + ar5212ResetTxQueue(ah, i); + + /* + * Setup interrupt handling. Note that ar5212ResetTxQueue + * manipulates the secondary IMR's as queues are enabled + * and disabled. This is done with RMW ops to insure the + * settings we make here are preserved. + */ + ahp->ah_maskReg = AR_IMR_TXOK | AR_IMR_TXERR | AR_IMR_TXURN + | AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXORN + | AR_IMR_HIUERR + ; + if (opmode == HAL_M_HOSTAP) + ahp->ah_maskReg |= AR_IMR_MIB; + OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg); + /* Enable bus errors that are OR'd to set the HIUERR bit */ + OS_REG_WRITE(ah, AR_IMR_S2, + OS_REG_READ(ah, AR_IMR_S2) + | AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR); + + if (AH_PRIVATE(ah)->ah_rfkillEnabled) + ar5212EnableRfKill(ah); + + if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: offset calibration failed to complete in 1ms;" + " noisy environment?\n", __func__); + } + + /* + * Set clocks back to 32kHz if they had been using refClk, then + * use an external 32kHz crystal when sleeping, if one exists. + */ + ar5312SetupClock(ah, opmode); + + /* + * Writing to AR_BEACON will start timers. Hence it should + * be the last register to be written. Do not reset tsf, do + * not enable beacons at this point, but preserve other values + * like beaconInterval. + */ + OS_REG_WRITE(ah, AR_BEACON, + (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF))); + + /* XXX Setup post reset EAR additions */ + + /* QoS support */ + if (AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE || + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && + AH_PRIVATE(ah)->ah_macRev >= AR_SREV_GRIFFIN_LITE)) { + OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa); /* XXX magic */ + OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210); /* XXX magic */ + } + + /* Turn on NOACK Support for QoS packets */ + OS_REG_WRITE(ah, AR_NOACK, + SM(2, AR_NOACK_2BIT_VALUE) | + SM(5, AR_NOACK_BIT_OFFSET) | + SM(0, AR_NOACK_BYTE_OFFSET)); + + /* Restore user-specified settings */ + if (ahp->ah_miscMode != 0) + OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + if (ahp->ah_slottime != (u_int) -1) + ar5212SetSlotTime(ah, ahp->ah_slottime); + if (ahp->ah_acktimeout != (u_int) -1) + ar5212SetAckTimeout(ah, ahp->ah_acktimeout); + if (ahp->ah_ctstimeout != (u_int) -1) + ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout); + if (ahp->ah_sifstime != (u_int) -1) + ar5212SetSifsTime(ah, ahp->ah_sifstime); + if (AH_PRIVATE(ah)->ah_diagreg != 0) + OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); + + AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */ + + if (bChannelChange) { + if (!(ichan->privFlags & CHANNEL_DFS)) + ichan->privFlags &= ~CHANNEL_INTERFERENCE; + chan->channelFlags = ichan->channelFlags; + chan->privFlags = ichan->privFlags; + } + + HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__); + + OS_MARK(ah, AH_MARK_RESET_DONE, 0); + + return AH_TRUE; +bad: + OS_MARK(ah, AH_MARK_RESET_DONE, ecode); + if (*status) + *status = ecode; + return AH_FALSE; +#undef FAIL +#undef N +} + +/* + * Places the PHY and Radio chips into reset. A full reset + * must be called to leave this state. The PCI/MAC/PCU are + * not placed into reset as we must receive interrupt to + * re-enable the hardware. + */ +HAL_BOOL +ar5312PhyDisable(struct ath_hal *ah) +{ + return ar5312SetResetReg(ah, AR_RC_BB); +} + +/* + * Places all of hardware into reset + */ +HAL_BOOL +ar5312Disable(struct ath_hal *ah) +{ + if (!ar5312SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + /* + * Reset the HW - PCI must be reset after the rest of the + * device has been reset. + */ + return ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB); +} + +/* + * Places the hardware into reset and then pulls it out of reset + * + * TODO: Only write the PLL if we're changing to or from CCK mode + * + * WARNING: The order of the PLL and mode registers must be correct. + */ +HAL_BOOL +ar5312ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + + OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->channel : 0); + + /* + * Reset the HW + */ + if (!ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n", + __func__); + return AH_FALSE; + } + + /* Bring out of sleep mode (AGAIN) */ + if (!ar5312SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetPowerMode failed\n", + __func__); + return AH_FALSE; + } + + /* Clear warm reset register */ + if (!ar5312SetResetReg(ah, 0)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n", + __func__); + return AH_FALSE; + } + + /* + * Perform warm reset before the mode/PLL/turbo registers + * are changed in order to deactivate the radio. Mode changes + * with an active radio can result in corrupted shifts to the + * radio device. + */ + + /* + * Set CCK and Turbo modes correctly. + */ + if (chan != AH_NULL) { /* NB: can be null during attach */ + uint32_t rfMode, phyPLL = 0, curPhyPLL, turbo; + + if (IS_RAD5112_ANY(ah)) { + rfMode = AR_PHY_MODE_AR5112; + if (!IS_5315(ah)) { + if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) { + phyPLL = AR_PHY_PLL_CTL_44_5312; + } else { + if (IS_CHAN_HALF_RATE(chan)) { + phyPLL = AR_PHY_PLL_CTL_40_5312_HALF; + } else if (IS_CHAN_QUARTER_RATE(chan)) { + phyPLL = AR_PHY_PLL_CTL_40_5312_QUARTER; + } else { + phyPLL = AR_PHY_PLL_CTL_40_5312; + } + } + } else { + if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) + phyPLL = AR_PHY_PLL_CTL_44_5112; + else + phyPLL = AR_PHY_PLL_CTL_40_5112; + if (IS_CHAN_HALF_RATE(chan)) + phyPLL |= AR_PHY_PLL_CTL_HALF; + else if (IS_CHAN_QUARTER_RATE(chan)) + phyPLL |= AR_PHY_PLL_CTL_QUARTER; + } + } else { + rfMode = AR_PHY_MODE_AR5111; + if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) + phyPLL = AR_PHY_PLL_CTL_44; + else + phyPLL = AR_PHY_PLL_CTL_40; + if (IS_CHAN_HALF_RATE(chan)) + phyPLL = AR_PHY_PLL_CTL_HALF; + else if (IS_CHAN_QUARTER_RATE(chan)) + phyPLL = AR_PHY_PLL_CTL_QUARTER; + } + if (IS_CHAN_OFDM(chan) && (IS_CHAN_CCK(chan) || + IS_CHAN_G(chan))) + rfMode |= AR_PHY_MODE_DYNAMIC; + else if (IS_CHAN_OFDM(chan)) + rfMode |= AR_PHY_MODE_OFDM; + else + rfMode |= AR_PHY_MODE_CCK; + if (IS_CHAN_5GHZ(chan)) + rfMode |= AR_PHY_MODE_RF5GHZ; + else + rfMode |= AR_PHY_MODE_RF2GHZ; + turbo = IS_CHAN_TURBO(chan) ? + (AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT) : 0; + curPhyPLL = OS_REG_READ(ah, AR_PHY_PLL_CTL); + /* + * PLL, Mode, and Turbo values must be written in the correct + * order to ensure: + * - The PLL cannot be set to 44 unless the CCK or DYNAMIC + * mode bit is set + * - Turbo cannot be set at the same time as CCK or DYNAMIC + */ + if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) { + OS_REG_WRITE(ah, AR_PHY_TURBO, turbo); + OS_REG_WRITE(ah, AR_PHY_MODE, rfMode); + if (curPhyPLL != phyPLL) { + OS_REG_WRITE(ah, AR_PHY_PLL_CTL, phyPLL); + /* Wait for the PLL to settle */ + OS_DELAY(PLL_SETTLE_DELAY); + } + } else { + if (curPhyPLL != phyPLL) { + OS_REG_WRITE(ah, AR_PHY_PLL_CTL, phyPLL); + /* Wait for the PLL to settle */ + OS_DELAY(PLL_SETTLE_DELAY); + } + OS_REG_WRITE(ah, AR_PHY_TURBO, turbo); + OS_REG_WRITE(ah, AR_PHY_MODE, rfMode); + } + } + return AH_TRUE; +} + +/* + * Write the given reset bit mask into the reset register + */ +static HAL_BOOL +ar5312SetResetReg(struct ath_hal *ah, uint32_t resetMask) +{ + uint32_t mask = resetMask ? resetMask : ~0; + HAL_BOOL rt; + + if ((rt = ar5312MacReset(ah, mask)) == AH_FALSE) { + return rt; + } + if ((resetMask & AR_RC_MAC) == 0) { + if (isBigEndian()) { + /* + * Set CFG, little-endian for register + * and descriptor accesses. + */ +#ifdef AH_NEED_DESC_SWAP + mask = INIT_CONFIG_STATUS | AR_CFG_SWRD; +#else + mask = INIT_CONFIG_STATUS | + AR_CFG_SWTD | AR_CFG_SWRD; +#endif + OS_REG_WRITE(ah, AR_CFG, mask); + } else + OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS); + } + return rt; +} + +/* + * ar5312MacReset resets (and then un-resets) the specified + * wireless components. + * Note: The RCMask cannot be zero on entering from ar5312SetResetReg. + */ + +HAL_BOOL +ar5312MacReset(struct ath_hal *ah, unsigned int RCMask) +{ + int wlanNum = AR5312_UNIT(ah); + uint32_t resetBB, resetBits, regMask; + uint32_t reg; + + if (RCMask == 0) + return(AH_FALSE); +#if ( AH_SUPPORT_2316 || AH_SUPPORT_2317 ) + if (IS_5315(ah)) { + switch(wlanNum) { + case 0: + resetBB = AR5315_RC_BB0_CRES | AR5315_RC_WBB0_RES; + /* Warm and cold reset bits for wbb */ + resetBits = AR5315_RC_WMAC0_RES; + break; + case 1: + resetBB = AR5315_RC_BB1_CRES | AR5315_RC_WBB1_RES; + /* Warm and cold reset bits for wbb */ + resetBits = AR5315_RC_WMAC1_RES; + break; + default: + return(AH_FALSE); + } + regMask = ~(resetBB | resetBits); + + /* read before */ + reg = OS_REG_READ(ah, + (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh) + AR5315_RESET)); + + if (RCMask == AR_RC_BB) { + /* Put baseband in reset */ + reg |= resetBB; /* Cold and warm reset the baseband bits */ + } else { + /* + * Reset the MAC and baseband. This is a bit different than + * the PCI version, but holding in reset causes problems. + */ + reg &= regMask; + reg |= (resetBits | resetBB) ; + } + OS_REG_WRITE(ah, + (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5315_RESET), + reg); + /* read after */ + OS_REG_READ(ah, + (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh) +AR5315_RESET)); + OS_DELAY(100); + + /* Bring MAC and baseband out of reset */ + reg &= regMask; + /* read before */ + OS_REG_READ(ah, + (AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET)); + OS_REG_WRITE(ah, + (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5315_RESET), + reg); + /* read after */ + OS_REG_READ(ah, + (AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET)); + + + } + else +#endif + { + + switch(wlanNum) { + case 0: + resetBB = AR5312_RC_BB0_CRES | AR5312_RC_WBB0_RES; + /* Warm and cold reset bits for wbb */ + resetBits = AR5312_RC_WMAC0_RES; + break; + case 1: + resetBB = AR5312_RC_BB1_CRES | AR5312_RC_WBB1_RES; + /* Warm and cold reset bits for wbb */ + resetBits = AR5312_RC_WMAC1_RES; + break; + default: + return(AH_FALSE); + } + regMask = ~(resetBB | resetBits); + + /* read before */ + reg = OS_REG_READ(ah, + (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh) + AR5312_RESET)); + + if (RCMask == AR_RC_BB) { + /* Put baseband in reset */ + reg |= resetBB; /* Cold and warm reset the baseband bits */ + } else { + /* + * Reset the MAC and baseband. This is a bit different than + * the PCI version, but holding in reset causes problems. + */ + reg &= regMask; + reg |= (resetBits | resetBB) ; + } + OS_REG_WRITE(ah, + (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5312_RESET), + reg); + /* read after */ + OS_REG_READ(ah, + (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh) +AR5312_RESET)); + OS_DELAY(100); + + /* Bring MAC and baseband out of reset */ + reg &= regMask; + /* read before */ + OS_REG_READ(ah, + (AR5312_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5312_RESET)); + OS_REG_WRITE(ah, + (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5312_RESET), + reg); + /* read after */ + OS_REG_READ(ah, + (AR5312_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5312_RESET)); + } + return(AH_TRUE); +} + +#endif /* AH_SUPPORT_AR5312 */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312phy.h b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312phy.h new file mode 100644 index 0000000000..9f867c7526 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312phy.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5312phy.h,v 1.3 2008/10/06 18:32:50 sam Exp $ + */ +#ifndef _DEV_ATH_AR5312PHY_H_ +#define _DEV_ATH_AR5312PHY_H_ + +#include "ar5212/ar5212phy.h" + +/* PHY registers */ + +#define AR_PHY_PLL_CTL_44_5312 0x14d6 /* 44 MHz for 11b, 11g */ +#define AR_PHY_PLL_CTL_40_5312 0x14d4 /* 40 MHz for 11a, turbos */ +#define AR_PHY_PLL_CTL_40_5312_HALF 0x15d4 /* 40 MHz for 11a, turbos (Half)*/ +#define AR_PHY_PLL_CTL_40_5312_QUARTER 0x16d4 /* 40 MHz for 11a, turbos (Quarter)*/ + +#endif /* _DEV_ATH_AR5312PHY_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312reg.h b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312reg.h new file mode 100644 index 0000000000..ff79cd3f08 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5312reg.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5312reg.h,v 1.4 2008/11/10 04:08:04 sam Exp $ + */ +#ifndef _DEV_ATH_AR5312REG_H_ +#define _DEV_ATH_AR5312REG_H_ + +#include "ar5212/ar5212reg.h" +/* + * Definitions for the Atheros 5312 chipset. + */ + +/* Register base addresses for modules which are not wmac modules */ +/* 531X has a fixed memory map */ + + +#define REG_WRITE(_reg,_val) *((volatile uint32_t *)(_reg)) = (_val); +#define REG_READ(_reg) *((volatile uint32_t *)(_reg)) +/* + * PCI-MAC Configuration registers (AR2315+) + */ +#define AR5315_RSTIMER_BASE 0xb1000000 /* Address for reset/timer registers */ +#define AR5315_GPIO_BASE 0xb1000000 /* Address for GPIO registers */ +#define AR5315_WLAN0 0xb0000000 + +#define AR5315_RESET 0x0004 /* Offset of reset control register */ +#define AR5315_SREV 0x0014 /* Offset of reset control register */ +#define AR5315_ENDIAN_CTL 0x000c /* offset of the endian control register */ +#define AR5315_CONFIG_WLAN 0x00000002 /* WLAN byteswap */ + +#define AR5315_REV_MAJ 0x00f0 +#define AR5315_REV_MIN 0x000f + +#define AR5315_GPIODIR 0x0098 /* GPIO direction register */ +#define AR5315_GPIODO 0x0090 /* GPIO data output access reg */ +#define AR5315_GPIODI 0x0088 /* GPIO data input access reg*/ +#define AR5315_GPIOINT 0x00a0 /* GPIO interrupt control */ + +#define AR5315_GPIODIR_M(x) (1 << (x)) /* mask for i/o */ +#define AR5315_GPIODIR_O(x) (1 << (x)) /* output */ +#define AR5315_GPIODIR_I(x) 0 /* input */ + +#define AR5315_GPIOINT_S 0 +#define AR5315_GPIOINT_M 0x3F +#define AR5315_GPIOINTLVL_S 6 +#define AR5315_GPIOINTLVL_M (3 << AR5315_GPIOINTLVL_S) + +#define AR5315_WREV (-0xefbfe0) /* Revision ID register offset */ +#define AR5315_WREV_S 0 /* Shift for WMAC revision info */ +#define AR5315_WREV_ID 0x000000FF /* Mask for WMAC revision info */ +#define AR5315_WREV_ID_S 4 /* Shift for WMAC Rev ID */ +#define AR5315_WREV_REVISION 0x0000000F /* Mask for WMAN Revsion version */ + +#define AR5315_RC_BB0_CRES 0x00000002 /* Cold reset to WMAC0 & WBB0 */ +#define AR5315_RC_BB1_CRES 0x00000200 /* Cold reset to WMAC1 & WBB1n */ +#define AR5315_RC_WMAC0_RES 0x00000001 /* Warm reset to WMAC 0 */ +#define AR5315_RC_WBB0_RES 0x00000002 /* Warm reset to WBB0 */ +#define AR5315_RC_WMAC1_RES 0x00020000 /* Warm reset to WMAC1 */ +#define AR5315_RC_WBB1_RES 0x00040000 /* Warm reset to WBB */ + +/* + * PCI-MAC Configuration registers (AR5312) + */ +#define AR5312_RSTIMER_BASE 0xbc003000 /* Address for reset/timer registers */ +#define AR5312_GPIO_BASE 0xbc002000 /* Address for GPIO registers */ +#define AR5312_WLAN0 0xb8000000 +#define AR5312_WLAN1 0xb8500000 + +#define AR5312_RESET 0x0020 /* Offset of reset control register */ +#define AR5312_PCICFG 0x00B0 /* MAC/PCI configuration reg (LEDs) */ + +#define AR5312_PCICFG_LEDMODE 0x0000001c /* LED Mode mask */ +#define AR5312_PCICFG_LEDMODE_S 2 /* LED Mode shift */ +#define AR5312_PCICFG_LEDMOD0 0 /* Blnk prop to Tx and filtered Rx */ +#define AR5312_PCICFG_LEDMOD1 1 /* Blnk prop to all Tx and Rx */ +#define AR5312_PCICFG_LEDMOD2 2 /* DEBG flash */ +#define AR5312_PCICFG_LEDMOD3 3 /* BLNK Randomly */ + +#define AR5312_PCICFG_LEDSEL 0x000000e0 /* LED Throughput select */ +#define AR5312_PCICFG_LEDSEL_S 5 +#define AR5312_PCICFG_LEDSEL0 0 /* See blink rate table on p. 143 */ +#define AR5312_PCICFG_LEDSEL1 1 /* of AR5212 data sheet */ +#define AR5312_PCICFG_LEDSEL2 2 +#define AR5312_PCICFG_LEDSEL3 3 +#define AR5312_PCICFG_LEDSEL4 4 +#define AR5312_PCICFG_LEDSEL5 5 +#define AR5312_PCICFG_LEDSEL6 6 +#define AR5312_PCICFG_LEDSEL7 7 + +#define AR5312_PCICFG_LEDSBR 0x00000100 /* Slow blink rate if no + activity. 0 = blink @ lowest + rate */ + +#undef AR_GPIOCR +#undef AR_GPIODO /* Undefine the 5212 defs */ +#undef AR_GPIODI + +#define AR5312_GPIOCR 0x0008 /* GPIO Control register */ +#define AR5312_GPIODO 0x0000 /* GPIO data output access reg */ +#define AR5312_GPIODI 0x0004 /* GPIO data input access reg*/ +/* NB: AR5312 uses AR5212 defines for GPIOCR definitions */ + +#define AR5312_WREV 0x0090 /* Revision ID register offset */ +#define AR5312_WREV_S 8 /* Shift for WMAC revision info */ +#define AR5312_WREV_ID 0x000000FF /* Mask for WMAC revision info */ +#define AR5312_WREV_ID_S 4 /* Shift for WMAC Rev ID */ +#define AR5312_WREV_REVISION 0x0000000F /* Mask for WMAN Revsion version */ + +#define AR5312_RC_BB0_CRES 0x00000004 /* Cold reset to WMAC0 & WBB0 */ +#define AR5312_RC_BB1_CRES 0x00000200 /* Cold reset to WMAC1 & WBB1n */ +#define AR5312_RC_WMAC0_RES 0x00002000 /* Warm reset to WMAC 0 */ +#define AR5312_RC_WBB0_RES 0x00004000 /* Warm reset to WBB0 */ +#define AR5312_RC_WMAC1_RES 0x00020000 /* Warm reset to WMAC1 */ +#define AR5312_RC_WBB1_RES 0x00040000 /* Warm reset to WBB */ + + +#define AR_RAD2112_SREV_MAJOR 0x40 /* 2112 Major Rev */ + +enum AR5312PowerMode { + AR5312_POWER_MODE_FORCE_SLEEP = 0, + AR5312_POWER_MODE_FORCE_WAKE = 1, + AR5312_POWER_MODE_NORMAL = 2, +}; + +#endif /* _DEV_AR5312REG_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5315_gpio.c b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5315_gpio.c new file mode 100644 index 0000000000..2aca97a2e2 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5312/ar5315_gpio.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5315_gpio.c,v 1.3 2008/11/10 04:08:04 sam Exp $ + */ +#include "opt_ah.h" + +#if (AH_SUPPORT_2316 || AH_SUPPORT_2317) + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5312/ar5312.h" +#include "ar5312/ar5312reg.h" +#include "ar5312/ar5312phy.h" + +#define AR_NUM_GPIO 7 /* 6 GPIO pins */ +#define AR5315_GPIOD_MASK 0x0000007F /* GPIO data reg r/w mask */ + +/* + * Configure GPIO Output lines + */ +HAL_BOOL +ar5315GpioCfgOutput(struct ath_hal *ah, uint32_t gpio) +{ + uint32_t gpioOffset = (AR5315_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + HALASSERT(gpio < AR_NUM_GPIO); + + OS_REG_WRITE(ah, gpioOffset+AR5315_GPIODIR, + (OS_REG_READ(ah, gpioOffset+AR5315_GPIODIR) &~ AR5315_GPIODIR_M(gpio)) + | AR5315_GPIODIR_O(gpio)); + + return AH_TRUE; +} + +/* + * Configure GPIO Input lines + */ +HAL_BOOL +ar5315GpioCfgInput(struct ath_hal *ah, uint32_t gpio) +{ + uint32_t gpioOffset = (AR5315_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + HALASSERT(gpio < AR_NUM_GPIO); + + OS_REG_WRITE(ah, gpioOffset+AR5315_GPIODIR, + (OS_REG_READ(ah, gpioOffset+AR5315_GPIODIR) &~ AR5315_GPIODIR_M(gpio)) + | AR5315_GPIODIR_I(gpio)); + + return AH_TRUE; +} + +/* + * Once configured for I/O - set output lines + */ +HAL_BOOL +ar5315GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) +{ + uint32_t reg; + uint32_t gpioOffset = (AR5315_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + HALASSERT(gpio < AR_NUM_GPIO); + + reg = OS_REG_READ(ah, gpioOffset+AR5315_GPIODO); + reg &= ~(1 << gpio); + reg |= (val&1) << gpio; + + OS_REG_WRITE(ah, gpioOffset+AR5315_GPIODO, reg); + return AH_TRUE; +} + +/* + * Once configured for I/O - get input lines + */ +uint32_t +ar5315GpioGet(struct ath_hal *ah, uint32_t gpio) +{ + uint32_t gpioOffset = (AR5315_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + if (gpio < AR_NUM_GPIO) { + uint32_t val = OS_REG_READ(ah, gpioOffset+AR5315_GPIODI); + val = ((val & AR5315_GPIOD_MASK) >> gpio) & 0x1; + return val; + } else { + return 0xffffffff; + } +} + +/* + * Set the GPIO Interrupt + */ +void +ar5315GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) +{ + uint32_t val; + uint32_t gpioOffset = (AR5315_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + /* XXX bounds check gpio */ + val = OS_REG_READ(ah, gpioOffset+AR5315_GPIOINT); + val &= ~(AR5315_GPIOINT_M | AR5315_GPIOINTLVL_M); + val |= gpio << AR5315_GPIOINT_S; + if (ilevel) + val |= 2 << AR5315_GPIOINTLVL_S; /* interrupt on pin high */ + else + val |= 1 << AR5315_GPIOINTLVL_S; /* interrupt on pin low */ + + /* Don't need to change anything for low level interrupt. */ + OS_REG_WRITE(ah, gpioOffset+AR5315_GPIOINT, val); + + /* Change the interrupt mask. */ + (void) ar5212SetInterrupts(ah, AH5212(ah)->ah_maskReg | HAL_INT_GPIO); +} + + +#endif /* AH_SUPPORT_2316 || AH_SUPPORT_2317 */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar2133.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar2133.c new file mode 100644 index 0000000000..5d90b6ea0b --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar2133.c @@ -0,0 +1,466 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar2133.c,v 1.13 2008/11/11 00:11:30 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v14.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +struct ar2133State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[1]; + + uint32_t *Bank0Data; + uint32_t *Bank1Data; + uint32_t *Bank2Data; + uint32_t *Bank3Data; + uint32_t *Bank6Data; + uint32_t *Bank7Data; + + /* NB: Bank*Data storage follows */ +}; +#define AR2133(ah) ((struct ar2133State *) AH5212(ah)->ah_rfHal) + +#define ar5416ModifyRfBuffer ar5212ModifyRfBuffer /*XXX*/ + +extern void ar5416ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); +HAL_BOOL ar2133GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL + *chans, uint32_t nchans); + +static HAL_BOOL ar2133GetChannelMaxMinPower(struct ath_hal *, HAL_CHANNEL *, + int16_t *maxPow,int16_t *minPow); +int16_t ar2133GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c); + +static void +ar2133WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + (void) ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_bb_rfgain, + freqIndex, writes); +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + */ +static HAL_BOOL +ar2133SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + uint32_t channelSel = 0; + uint32_t bModeSynth = 0; + uint32_t aModeRefSel = 0; + uint32_t reg32 = 0; + uint16_t freq; + CHAN_CENTERS centers; + + OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel); + + ar5416GetChannelCenters(ah, chan, ¢ers); + freq = centers.synth_center; + + if (freq < 4800) { + uint32_t txctl; + + if (((freq - 2192) % 5) == 0) { + channelSel = ((freq - 672) * 2 - 3040)/10; + bModeSynth = 0; + } else if (((freq - 2224) % 5) == 0) { + channelSel = ((freq - 704) * 2 - 3040) / 10; + bModeSynth = 1; + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u MHz\n", __func__, freq); + return AH_FALSE; + } + + channelSel = (channelSel << 2) & 0xff; + channelSel = ath_hal_reverseBits(channelSel, 8); + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else if ((freq % 20) == 0 && freq >= 5120) { + channelSel = ath_hal_reverseBits(((freq - 4800) / 20 << 2), 8); + if (AR_SREV_SOWL_10_OR_LATER(ah)) + aModeRefSel = ath_hal_reverseBits(3, 2); + else + aModeRefSel = ath_hal_reverseBits(1, 2); + } else if ((freq % 10) == 0) { + channelSel = ath_hal_reverseBits(((freq - 4800) / 10 << 1), 8); + if (AR_SREV_SOWL_10_OR_LATER(ah)) + aModeRefSel = ath_hal_reverseBits(2, 2); + else + aModeRefSel = ath_hal_reverseBits(1, 2); + } else if ((freq % 5) == 0) { + channelSel = ath_hal_reverseBits((freq - 4800) / 5, 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", + __func__, freq); + return AH_FALSE; + } + + reg32 = (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 5) | 0x1; + + OS_REG_WRITE(ah, AR_PHY(0x37), reg32); + + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; + +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar2133GetRfBank(struct ath_hal *ah, int bank) +{ + struct ar2133State *priv = AR2133(ah); + + HALASSERT(priv != AH_NULL); + switch (bank) { + case 1: return priv->Bank1Data; + case 2: return priv->Bank2Data; + case 3: return priv->Bank3Data; + case 6: return priv->Bank6Data; + case 7: return priv->Bank7Data; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + * + * REQUIRES: Access to the analog rf device + */ +static HAL_BOOL +ar2133SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, + uint16_t modesIndex, uint16_t *rfXpdGain) +{ + struct ar2133State *priv = AR2133(ah); + int writes; + + HALASSERT(priv); + + /* Setup Bank 0 Write */ + ath_hal_ini_bank_setup(priv->Bank0Data, &AH5416(ah)->ah_ini_bank0, 1); + + /* Setup Bank 1 Write */ + ath_hal_ini_bank_setup(priv->Bank1Data, &AH5416(ah)->ah_ini_bank1, 1); + + /* Setup Bank 2 Write */ + ath_hal_ini_bank_setup(priv->Bank2Data, &AH5416(ah)->ah_ini_bank2, 1); + + /* Setup Bank 3 Write */ + ath_hal_ini_bank_setup(priv->Bank3Data, &AH5416(ah)->ah_ini_bank3, modesIndex); + + /* Setup Bank 6 Write */ + ath_hal_ini_bank_setup(priv->Bank6Data, &AH5416(ah)->ah_ini_bank6, modesIndex); + + /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ + if (IS_CHAN_2GHZ(chan)) { + ar5416ModifyRfBuffer(priv->Bank6Data, + ath_hal_eepromGet(ah, AR_EEP_OB_2, AH_NULL), 3, 197, 0); + ar5416ModifyRfBuffer(priv->Bank6Data, + ath_hal_eepromGet(ah, AR_EEP_DB_2, AH_NULL), 3, 194, 0); + } else { + ar5416ModifyRfBuffer(priv->Bank6Data, + ath_hal_eepromGet(ah, AR_EEP_OB_5, AH_NULL), 3, 203, 0); + ar5416ModifyRfBuffer(priv->Bank6Data, + ath_hal_eepromGet(ah, AR_EEP_DB_5, AH_NULL), 3, 200, 0); + } + /* Setup Bank 7 Setup */ + ath_hal_ini_bank_setup(priv->Bank7Data, &AH5416(ah)->ah_ini_bank7, 1); + + /* Write Analog registers */ + writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank0, + priv->Bank0Data, 0); + writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank1, + priv->Bank1Data, writes); + writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank2, + priv->Bank2Data, writes); + writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank3, + priv->Bank3Data, writes); + writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank6, + priv->Bank6Data, writes); + (void) ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank7, + priv->Bank7Data, writes); + + return AH_TRUE; +#undef RF_BANK_SETUP +} + +/* + * Read the transmit power levels from the structures taken from EEPROM + * Interpolate read transmit power values for this channel + * Organize the transmit power values into a table for writing into the hardware + */ + +static HAL_BOOL +ar2133SetPowerTable(struct ath_hal *ah, int16_t *pPowerMin, int16_t *pPowerMax, + HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain) +{ + return AH_TRUE; +} + +#if 0 +static int16_t +ar2133GetMinPower(struct ath_hal *ah, EXPN_DATA_PER_CHANNEL_5112 *data) +{ + int i, minIndex; + int16_t minGain,minPwr,minPcdac,retVal; + + /* Assume NUM_POINTS_XPD0 > 0 */ + minGain = data->pDataPerXPD[0].xpd_gain; + for (minIndex=0,i=1; ipDataPerXPD[i].xpd_gain < minGain) { + minIndex = i; + minGain = data->pDataPerXPD[i].xpd_gain; + } + } + minPwr = data->pDataPerXPD[minIndex].pwr_t4[0]; + minPcdac = data->pDataPerXPD[minIndex].pcdac[0]; + for (i=1; ipDataPerXPD[minIndex].pwr_t4[i] < minPwr) { + minPwr = data->pDataPerXPD[minIndex].pwr_t4[i]; + minPcdac = data->pDataPerXPD[minIndex].pcdac[i]; + } + } + retVal = minPwr - (minPcdac*2); + return(retVal); +} +#endif + +static HAL_BOOL +ar2133GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, int16_t *maxPow, + int16_t *minPow) +{ +#if 0 + struct ath_hal_5212 *ahp = AH5212(ah); + int numChannels=0,i,last; + int totalD, totalF,totalMin; + EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL; + EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL; + + *maxPow = 0; + if (IS_CHAN_A(chan)) { + powerArray = ahp->ah_modePowerArray5112; + data = powerArray[headerInfo11A].pDataPerChannel; + numChannels = powerArray[headerInfo11A].numChannels; + } else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) { + /* XXX - is this correct? Should we also use the same power for turbo G? */ + powerArray = ahp->ah_modePowerArray5112; + data = powerArray[headerInfo11G].pDataPerChannel; + numChannels = powerArray[headerInfo11G].numChannels; + } else if (IS_CHAN_B(chan)) { + powerArray = ahp->ah_modePowerArray5112; + data = powerArray[headerInfo11B].pDataPerChannel; + numChannels = powerArray[headerInfo11B].numChannels; + } else { + return (AH_TRUE); + } + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if ((numChannels < 1) || + (chan->channel < data[0].channelValue) || + (chan->channel > data[numChannels-1].channelValue)) + return(AH_FALSE); + + /* Linearly interpolate the power value now */ + for (last=0,i=0; + (ichannel > data[i].channelValue); + last=i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = data[i].maxPower_t4 - data[last].maxPower_t4; + *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD); + + totalMin = ar2133GetMinPower(ah,&data[i]) - ar2133GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar2133GetMinPower(ah, &data[last])*totalD)/totalD); + return (AH_TRUE); + } else { + if (chan->channel == data[i].channelValue) { + *maxPow = data[i].maxPower_t4; + *minPow = ar2133GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +#else + *maxPow = *minPow = 0; + return AH_FALSE; +#endif +} + +static void +ar2133GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + int16_t nf; + + switch (ahp->ah_rx_chainmask) { + case 0x7: + nf = MS(OS_REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ctl] [chain 2] is %d\n", nf); + nfarray[4] = nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ext] [chain 2] is %d\n", nf); + nfarray[5] = nf; + /* fall thru... */ + case 0x3: + case 0x5: + nf = MS(OS_REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ctl] [chain 1] is %d\n", nf); + nfarray[2] = nf; + + + nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ext] [chain 1] is %d\n", nf); + nfarray[3] = nf; + /* fall thru... */ + case 0x1: + nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ctl] [chain 0] is %d\n", nf); + nfarray[0] = nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ext] [chain 0] is %d\n", nf); + nfarray[1] = nf; + + break; + } +} + +/* + * Adjust NF based on statistical values for 5GHz frequencies. + * Stubbed:Not used by Fowl + */ +int16_t +ar2133GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) +{ + return 0; +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar2133RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +/* + * Allocate memory for analog bank scratch buffers + * Scratch Buffer will be reinitialized every reset so no need to zero now + */ +HAL_BOOL +ar2133RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar2133State *priv; + uint32_t *bankData; + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar2133State) + + AH5416(ah)->ah_ini_bank0.rows * sizeof(uint32_t) + + AH5416(ah)->ah_ini_bank1.rows * sizeof(uint32_t) + + AH5416(ah)->ah_ini_bank2.rows * sizeof(uint32_t) + + AH5416(ah)->ah_ini_bank3.rows * sizeof(uint32_t) + + AH5416(ah)->ah_ini_bank6.rows * sizeof(uint32_t) + + AH5416(ah)->ah_ini_bank7.rows * sizeof(uint32_t) + ); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar2133RfDetach; + priv->base.writeRegs = ar2133WriteRegs; + priv->base.getRfBank = ar2133GetRfBank; + priv->base.setChannel = ar2133SetChannel; + priv->base.setRfRegs = ar2133SetRfRegs; + priv->base.setPowerTable = ar2133SetPowerTable; + priv->base.getChannelMaxMinPower = ar2133GetChannelMaxMinPower; + priv->base.getNfAdjust = ar2133GetNfAdjust; + + bankData = (uint32_t *) &priv[1]; + priv->Bank0Data = bankData, bankData += AH5416(ah)->ah_ini_bank0.rows; + priv->Bank1Data = bankData, bankData += AH5416(ah)->ah_ini_bank1.rows; + priv->Bank2Data = bankData, bankData += AH5416(ah)->ah_ini_bank2.rows; + priv->Bank3Data = bankData, bankData += AH5416(ah)->ah_ini_bank3.rows; + priv->Bank6Data = bankData, bankData += AH5416(ah)->ah_ini_bank6.rows; + priv->Bank7Data = bankData, bankData += AH5416(ah)->ah_ini_bank7.rows; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + /* + * Set noise floor adjust method; we arrange a + * direct call instead of thunking. + */ + AH_PRIVATE(ah)->ah_getNfAdjust = priv->base.getNfAdjust; + AH_PRIVATE(ah)->ah_getNoiseFloor = ar2133GetNoiseFloor; + + return AH_TRUE; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416.h b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416.h new file mode 100644 index 0000000000..34e76b958c --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416.h,v 1.19 2008/11/11 21:38:13 sam Exp $ + */ +#ifndef _ATH_AR5416_H_ +#define _ATH_AR5416_H_ + +#include "ar5212/ar5212.h" +#include "ar5416_cal.h" + +#define AR5416_MAGIC 0x20065416 + +enum { + HAL_RESET_POWER_ON, + HAL_RESET_WARM, + HAL_RESET_COLD, +}; + +typedef struct { + uint16_t synth_center; + uint16_t ctl_center; + uint16_t ext_center; +} CHAN_CENTERS; + +#define AR5416_DEFAULT_RXCHAINMASK 7 +#define AR5416_DEFAULT_TXCHAINMASK 1 +#define AR5416_MAX_RATE_POWER 63 +#define AR5416_KEYTABLE_SIZE 128 + +#define AR5416_CCA_MAX_GOOD_VALUE -85 +#define AR5416_CCA_MAX_HIGH_VALUE -62 +#define AR5416_CCA_MIN_BAD_VALUE -140 + +struct ath_hal_5416 { + struct ath_hal_5212 ah_5212; + + /* NB: RF data setup at attach */ + HAL_INI_ARRAY ah_ini_bb_rfgain; + HAL_INI_ARRAY ah_ini_bank0; + HAL_INI_ARRAY ah_ini_bank1; + HAL_INI_ARRAY ah_ini_bank2; + HAL_INI_ARRAY ah_ini_bank3; + HAL_INI_ARRAY ah_ini_bank6; + HAL_INI_ARRAY ah_ini_bank7; + HAL_INI_ARRAY ah_ini_addac; + + u_int ah_globaltxtimeout; /* global tx timeout */ + int ah_hangs; /* h/w hangs state */ + uint8_t ah_keytype[AR5416_KEYTABLE_SIZE]; + /* + * Extension Channel Rx Clear State + */ + uint32_t ah_cycleCount; + uint32_t ah_ctlBusy; + uint32_t ah_extBusy; + uint32_t ah_rx_chainmask; + uint32_t ah_tx_chainmask; + + struct ar5416PerCal ah_cal; /* periodic calibration state */ +}; +#define AH5416(_ah) ((struct ath_hal_5416 *)(_ah)) + +#define IS_5416_PCI(ah) ((AH_PRIVATE(ah)->ah_macVersion) == AR_SREV_VERSION_OWL_PCI) +#define IS_5416_PCIE(ah) ((AH_PRIVATE(ah)->ah_macVersion) == AR_SREV_VERSION_OWL_PCIE) +#undef IS_PCIE +#define IS_PCIE(ah) (IS_5416_PCIE(ah)) + +extern HAL_BOOL ar2133RfAttach(struct ath_hal *, HAL_STATUS *); + +struct ath_hal; + +extern struct ath_hal * ar5416Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status); +extern void ar5416InitState(struct ath_hal_5416 *, uint16_t devid, + HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, + HAL_STATUS *status); +extern void ar5416Detach(struct ath_hal *ah); +extern HAL_BOOL ar5416FillCapabilityInfo(struct ath_hal *ah); + +#define IS_5GHZ_FAST_CLOCK_EN(_ah, _c) \ + (IS_CHAN_5GHZ(_c) && ath_hal_eepromGetFlag(ah, AR_EEP_FSTCLK_5G)) + +extern void ar5416AniAttach(struct ath_hal *, const struct ar5212AniParams *, + const struct ar5212AniParams *, HAL_BOOL ena); +extern void ar5416AniDetach(struct ath_hal *); +extern HAL_BOOL ar5416AniControl(struct ath_hal *, HAL_ANI_CMD cmd, int param); +extern HAL_BOOL ar5416AniSetParams(struct ath_hal *, + const struct ar5212AniParams *, const struct ar5212AniParams *); +extern void ar5416ProcessMibIntr(struct ath_hal *, const HAL_NODE_STATS *); +extern void ar5416AniPoll(struct ath_hal *, const HAL_NODE_STATS *, + HAL_CHANNEL *); +extern void ar5416AniReset(struct ath_hal *, HAL_CHANNEL_INTERNAL *, + HAL_OPMODE, int); + +extern void ar5416SetBeaconTimers(struct ath_hal *, const HAL_BEACON_TIMERS *); +extern void ar5416BeaconInit(struct ath_hal *ah, + uint32_t next_beacon, uint32_t beacon_period); +extern void ar5416ResetStaBeaconTimers(struct ath_hal *ah); +extern void ar5416SetStaBeaconTimers(struct ath_hal *ah, + const HAL_BEACON_STATE *); + +extern HAL_BOOL ar5416EepromRead(struct ath_hal *, u_int off, uint16_t *data); +extern HAL_BOOL ar5416EepromWrite(struct ath_hal *, u_int off, uint16_t data); + +extern HAL_BOOL ar5416IsInterruptPending(struct ath_hal *ah); +extern HAL_BOOL ar5416GetPendingInterrupts(struct ath_hal *, HAL_INT *masked); +extern HAL_INT ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints); + +extern HAL_BOOL ar5416GpioCfgOutput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5416GpioCfgInput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5416GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val); +extern uint32_t ar5416GpioGet(struct ath_hal *ah, uint32_t gpio); +extern void ar5416GpioSetIntr(struct ath_hal *ah, u_int, uint32_t ilevel); + +extern u_int ar5416GetWirelessModes(struct ath_hal *ah); +extern void ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state); +extern void ar5416ResetTsf(struct ath_hal *ah); +extern HAL_BOOL ar5416SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); +extern HAL_BOOL ar5416SetDecompMask(struct ath_hal *, uint16_t, int); +extern void ar5416SetCoverageClass(struct ath_hal *, uint8_t, int); +extern uint32_t ar5416Get11nExtBusy(struct ath_hal *ah); +extern void ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode); +extern HAL_HT_RXCLEAR ar5416Get11nRxClear(struct ath_hal *ah); +extern void ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear); +extern HAL_STATUS ar5416GetCapability(struct ath_hal *ah, + HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t *result); +extern HAL_BOOL ar5416GetDiagState(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize); + +extern HAL_BOOL ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, + int setChip); +extern HAL_POWER_MODE ar5416GetPowerMode(struct ath_hal *ah); +extern HAL_BOOL ar5416GetPowerStatus(struct ath_hal *ah); + +extern HAL_BOOL ar5416ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry); +extern HAL_BOOL ar5416SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, + const HAL_KEYVAL *k, const uint8_t *mac, int xorKey); + +extern void ar5416StartPcuReceive(struct ath_hal *ah); +extern void ar5416StopPcuReceive(struct ath_hal *ah); +extern HAL_BOOL ar5416SetupRxDesc(struct ath_hal *, + struct ath_desc *, uint32_t size, u_int flags); +extern HAL_STATUS ar5416ProcRxDesc(struct ath_hal *ah, struct ath_desc *, + uint32_t, struct ath_desc *, uint64_t, + struct ath_rx_status *); + +extern HAL_BOOL ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, + HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status); +extern HAL_BOOL ar5416PhyDisable(struct ath_hal *ah); +extern HAL_RFGAIN ar5416GetRfgain(struct ath_hal *ah); +extern HAL_BOOL ar5416Disable(struct ath_hal *ah); +extern HAL_BOOL ar5416ChipReset(struct ath_hal *ah, HAL_CHANNEL *); +extern HAL_BOOL ar5416SetResetReg(struct ath_hal *, uint32_t type); +extern HAL_BOOL ar5416SetTxPowerLimit(struct ath_hal *ah, uint32_t limit); +extern HAL_BOOL ar5416GetChipPowerLimits(struct ath_hal *ah, + HAL_CHANNEL *chans, uint32_t nchans); +extern void ar5416GetChannelCenters(struct ath_hal *, + HAL_CHANNEL_INTERNAL *chan, CHAN_CENTERS *centers); + +extern HAL_BOOL ar5416StopTxDma(struct ath_hal *ah, u_int q); +extern HAL_BOOL ar5416SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower, + u_int txRate0, u_int txTries0, + u_int keyIx, u_int antMode, u_int flags, + u_int rtsctsRate, u_int rtsctsDuration, + u_int compicvLen, u_int compivLen, u_int comp); +extern HAL_BOOL ar5416SetupXTxDesc(struct ath_hal *, struct ath_desc *, + u_int txRate1, u_int txRetries1, + u_int txRate2, u_int txRetries2, + u_int txRate3, u_int txRetries3); +extern HAL_BOOL ar5416FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg, + const struct ath_desc *ds0); +extern HAL_STATUS ar5416ProcTxDesc(struct ath_hal *ah, + struct ath_desc *, struct ath_tx_status *); + +extern const HAL_RATE_TABLE *ar5416GetRateTable(struct ath_hal *, u_int mode); +#endif /* _ATH_AR5416_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416.ini b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416.ini new file mode 100644 index 0000000000..6e96f680d9 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416.ini @@ -0,0 +1,688 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416.ini,v 1.3 2008/11/10 04:08:04 sam Exp $ + */ +/* Auto Generated PCI Register Writes. Created: 09/20/06 */ + +static const uint32_t ar5416Modes[][6] = { + /* Register A A-20/40 G-20/40 G G-Turbo */ + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840, 0x06e006e0 }, + { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009844, 0x1372161e, 0x13721c1e, 0x13721c30, 0x137216a4, 0x13721c25 }, + { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x00009850, 0x6c28b4e0, 0x6c28b4e0, 0x6d68b0de, 0x6d68b0de, 0x6c28b0de }, + { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, + { 0x0000985c, 0x313a5d5e, 0x313a5d5e, 0x313a605e, 0x313a605e, 0x313a5d5e }, + { 0x00009860, 0x00049d10, 0x00049d10, 0x00049d20, 0x00049d20, 0x00049d10 }, + { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000370 }, + { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a19, 0xd0058a13, 0xd0058a0b }, + { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, +#ifdef TB243 + { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, + { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, + { 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210, 0x00001120 }, +#else + { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, + { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, + { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, +#ifdef __LINUX_ARM_ARCH__ + { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 }, +#else + { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 }, +#endif +#endif + { 0x0000c9bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 }, + { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, 0x00000440 }, + { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, + { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, + { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, + { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, + { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, + { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, + { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, + { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, + { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, + { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, + { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, + { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, + { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +static const uint32_t ar5416Common[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, +#ifdef AR9100 + { 0x00020010, 0x00000000 }, +#else + { 0x00007010, 0x00000000 }, +#endif + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04800 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0x00000000 }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081d0, 0x00003210 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x00008300, 0x00000000 }, + { 0x00008304, 0x00000000 }, + { 0x00008308, 0x00000000 }, + { 0x0000830c, 0x00000000 }, + { 0x00008310, 0x00000000 }, + { 0x00008314, 0x00000000 }, + { 0x00008318, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00000000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xad848e19 }, + { 0x00009810, 0x7d14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x00009840, 0x206a016e }, + { 0x0000984c, 0x1284233c }, + { 0x00009854, 0x00000859 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x05100000 }, + { 0x0000a920, 0x05100000 }, + { 0x0000b920, 0x05100000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280b212 }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5d50e188 }, + { 0x00009958, 0x00081fff }, + { 0x0000c95c, 0x004b6a8e }, + { 0x0000c968, 0x000003ce }, + { 0x00009970, 0x190c0514 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x001fff00 }, + { 0x000099ac, 0x000000c4 }, + { 0x000099b0, 0x03051000 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000200 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x000000aa }, + { 0x000099fc, 0x00001042 }, + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b28, 0x0000000c }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b38, 0x00000012 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b64, 0x00000021 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b8c, 0x0000002d }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009b9c, 0x00000033 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, + { 0x0000a210, 0x40806333 }, + { 0x0000a214, 0x00106c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x018830c6 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x00000bb5 }, + { 0x0000a22c, 0x00000011 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889af }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0ebae9c6 }, + { 0x0000b26c, 0x0ebae9c6 }, + { 0x0000c26c, 0x0ebae9c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x051701ce }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa1f }, + { 0x0000d35c, 0x066c420f }, + { 0x0000d360, 0x0f282207 }, + { 0x0000d364, 0x17601685 }, + { 0x0000d368, 0x1f801104 }, + { 0x0000d36c, 0x37a00c03 }, + { 0x0000d370, 0x3fc40883 }, + { 0x0000d374, 0x57c00803 }, + { 0x0000d378, 0x5fd80682 }, + { 0x0000d37c, 0x7fe00482 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x08000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, +}; + +static const uint32_t ar5416Bank0[][2] = { + { 0x000098b0, 0x1e5795e5 }, + { 0x000098e0, 0x02008020 }, +}; + +static const uint32_t ar5416BB_RfGain[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000040, 0x00000040 }, + { 0x00009a08, 0x00000080, 0x00000080 }, + { 0x00009a0c, 0x000001a1, 0x00000141 }, + { 0x00009a10, 0x000001e1, 0x00000181 }, + { 0x00009a14, 0x00000021, 0x000001c1 }, + { 0x00009a18, 0x00000061, 0x00000001 }, + { 0x00009a1c, 0x00000168, 0x00000041 }, + { 0x00009a20, 0x000001a8, 0x000001a8 }, + { 0x00009a24, 0x000001e8, 0x000001e8 }, + { 0x00009a28, 0x00000028, 0x00000028 }, + { 0x00009a2c, 0x00000068, 0x00000068 }, + { 0x00009a30, 0x00000189, 0x000000a8 }, + { 0x00009a34, 0x000001c9, 0x00000169 }, + { 0x00009a38, 0x00000009, 0x000001a9 }, + { 0x00009a3c, 0x00000049, 0x000001e9 }, + { 0x00009a40, 0x00000089, 0x00000029 }, + { 0x00009a44, 0x00000170, 0x00000069 }, + { 0x00009a48, 0x000001b0, 0x00000190 }, + { 0x00009a4c, 0x000001f0, 0x000001d0 }, + { 0x00009a50, 0x00000030, 0x00000010 }, + { 0x00009a54, 0x00000070, 0x00000050 }, + { 0x00009a58, 0x00000191, 0x00000090 }, + { 0x00009a5c, 0x000001d1, 0x00000151 }, + { 0x00009a60, 0x00000011, 0x00000191 }, + { 0x00009a64, 0x00000051, 0x000001d1 }, + { 0x00009a68, 0x00000091, 0x00000011 }, + { 0x00009a6c, 0x000001b8, 0x00000051 }, + { 0x00009a70, 0x000001f8, 0x00000198 }, + { 0x00009a74, 0x00000038, 0x000001d8 }, + { 0x00009a78, 0x00000078, 0x00000018 }, + { 0x00009a7c, 0x00000199, 0x00000058 }, + { 0x00009a80, 0x000001d9, 0x00000098 }, + { 0x00009a84, 0x00000019, 0x00000159 }, + { 0x00009a88, 0x00000059, 0x00000199 }, + { 0x00009a8c, 0x00000099, 0x000001d9 }, + { 0x00009a90, 0x000000d9, 0x00000019 }, + { 0x00009a94, 0x000000f9, 0x00000059 }, + { 0x00009a98, 0x000000f9, 0x00000099 }, + { 0x00009a9c, 0x000000f9, 0x000000d9 }, + { 0x00009aa0, 0x000000f9, 0x000000f9 }, + { 0x00009aa4, 0x000000f9, 0x000000f9 }, + { 0x00009aa8, 0x000000f9, 0x000000f9 }, + { 0x00009aac, 0x000000f9, 0x000000f9 }, + { 0x00009ab0, 0x000000f9, 0x000000f9 }, + { 0x00009ab4, 0x000000f9, 0x000000f9 }, + { 0x00009ab8, 0x000000f9, 0x000000f9 }, + { 0x00009abc, 0x000000f9, 0x000000f9 }, + { 0x00009ac0, 0x000000f9, 0x000000f9 }, + { 0x00009ac4, 0x000000f9, 0x000000f9 }, + { 0x00009ac8, 0x000000f9, 0x000000f9 }, + { 0x00009acc, 0x000000f9, 0x000000f9 }, + { 0x00009ad0, 0x000000f9, 0x000000f9 }, + { 0x00009ad4, 0x000000f9, 0x000000f9 }, + { 0x00009ad8, 0x000000f9, 0x000000f9 }, + { 0x00009adc, 0x000000f9, 0x000000f9 }, + { 0x00009ae0, 0x000000f9, 0x000000f9 }, + { 0x00009ae4, 0x000000f9, 0x000000f9 }, + { 0x00009ae8, 0x000000f9, 0x000000f9 }, + { 0x00009aec, 0x000000f9, 0x000000f9 }, + { 0x00009af0, 0x000000f9, 0x000000f9 }, + { 0x00009af4, 0x000000f9, 0x000000f9 }, + { 0x00009af8, 0x000000f9, 0x000000f9 }, + { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; + +static const uint32_t ar5416Bank1[][2] = { + { 0x000098b0, 0x02108421 }, + { 0x000098ec, 0x00000008 }, +}; + +static const uint32_t ar5416Bank2[][2] = { + { 0x000098b0, 0x0e73ff17 }, + { 0x000098e0, 0x00000420 }, +}; + +static const uint32_t ar5416Bank3[][3] = { + { 0x000098f0, 0x01400018, 0x01c00018 }, +}; + +#ifdef USE_NONTPC_BANK +static const uint32_t ar5416Bank6[][3] = { +/* Reg A G */ + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x004210a2, 0x004210a2 }, + { 0x0000989c, 0x0014008f, 0x0014008f }, + { 0x0000989c, 0x00c40003, 0x00c40003 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000f1, 0x000000f1 }, + { 0x0000989c, 0x00002081, 0x00002081 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +#else +/* TPC bank */ +static const uint32_t ar5416Bank6[][3] = { +/* Reg A G */ + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x00421022, 0x00421022 }, + { 0x0000989c, 0x001400df, 0x001400df }, + { 0x0000989c, 0x00c40002, 0x00c40002 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000e1, 0x000000e1 }, + { 0x0000989c, 0x00002081, 0x00002081 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +#endif + +static const uint32_t ar5416Bank7[][2] = { + { 0x0000989c, 0x00000500 }, + { 0x0000989c, 0x00000800 }, + { 0x000098cc, 0x0000000e }, +}; + +static const uint32_t ar5416Addac[][2] = { + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000003 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x0000000c }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000030 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000060 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000058 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x0989c, 0x00000000 }, + {0x098c4, 0x00000000 }, +}; diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_ani.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_ani.c new file mode 100644 index 0000000000..59bfb2034c --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_ani.c @@ -0,0 +1,886 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_ani.c,v 1.1 2008/11/11 20:46:06 sam Exp $ + */ +#include "opt_ah.h" + +/* + * XXX this is virtually the same code as for 5212; we reuse + * storage in the 5212 state block; need to refactor. + */ +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* + * Anti noise immunity support. We track phy errors and react + * to excessive errors by adjusting the noise immunity parameters. + */ + +#define HAL_EP_RND(x, mul) \ + ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) +#define BEACON_RSSI(ahp) \ + HAL_EP_RND(ahp->ah_stats.ast_nodestats.ns_avgbrssi, \ + HAL_RSSI_EP_MULTIPLIER) + +/* + * ANI processing tunes radio parameters according to PHY errors + * and related information. This is done for for noise and spur + * immunity in all operating modes if the device indicates it's + * capable at attach time. In addition, when there is a reference + * rssi value (e.g. beacon frames from an ap in station mode) + * further tuning is done. + * + * ANI_ENA indicates whether any ANI processing should be done; + * this is specified at attach time. + * + * ANI_ENA_RSSI indicates whether rssi-based processing should + * done, this is enabled based on operating mode and is meaningful + * only if ANI_ENA is true. + * + * ANI parameters are typically controlled only by the hal. The + * AniControl interface however permits manual tuning through the + * diagnostic api. + */ +#define ANI_ENA(ah) \ + (AH5212(ah)->ah_procPhyErr & HAL_ANI_ENA) +#define ANI_ENA_RSSI(ah) \ + (AH5212(ah)->ah_procPhyErr & HAL_RSSI_ANI_ENA) + +#define ah_mibStats ah_stats.ast_mibstats + +static void +enableAniMIBCounters(struct ath_hal *ah, const struct ar5212AniParams *params) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: Enable mib counters: " + "OfdmPhyErrBase 0x%x cckPhyErrBase 0x%x\n", + __func__, params->ofdmPhyErrBase, params->cckPhyErrBase); + + OS_REG_WRITE(ah, AR_FILTOFDM, 0); + OS_REG_WRITE(ah, AR_FILTCCK, 0); + + OS_REG_WRITE(ah, AR_PHYCNT1, params->ofdmPhyErrBase); + OS_REG_WRITE(ah, AR_PHYCNT2, params->cckPhyErrBase); + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); + + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save+clear counters*/ + ar5212EnableMibCounters(ah); /* enable everything */ +} + +static void +disableAniMIBCounters(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALDEBUG(ah, HAL_DEBUG_ANI, "Disable MIB counters\n"); + + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save stats */ + ar5212DisableMibCounters(ah); /* disable everything */ + + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, 0); + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, 0); +} + +/* + * This routine returns the index into the aniState array that + * corresponds to the channel in *chan. If no match is found and the + * array is still not fully utilized, a new entry is created for the + * channel. We assume the attach function has already initialized the + * ah_ani values and only the channel field needs to be set. + */ +static int +ar5416GetAniChannelIndex(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ +#define N(a) (sizeof(a) / sizeof(a[0])) + struct ath_hal_5212 *ahp = AH5212(ah); + int i; + + for (i = 0; i < N(ahp->ah_ani); i++) { + struct ar5212AniState *asp = &ahp->ah_ani[i]; + if (asp->c.channel == chan->channel) + return i; + if (asp->c.channel == 0) { + asp->c.channel = chan->channel; + asp->c.channelFlags = chan->channelFlags; + asp->c.privFlags = chan->privFlags; + asp->isSetup = AH_FALSE; + if (IS_CHAN_2GHZ(chan)) + asp->params = &ahp->ah_aniParams24; + else + asp->params = &ahp->ah_aniParams5; + return i; + } + } + /* XXX statistic */ + HALDEBUG(ah, HAL_DEBUG_ANY, + "No more channel states left. Using channel 0\n"); + return 0; /* XXX gotta return something valid */ +#undef N +} + +static void +setPhyErrBase(struct ath_hal *ah, struct ar5212AniParams *params) +{ + if (params->ofdmTrigHigh >= AR_PHY_COUNTMAX) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "OFDM Trigger %d is too high for hw counters, using max\n", + params->ofdmTrigHigh); + params->ofdmPhyErrBase = 0; + } else + params->ofdmPhyErrBase = AR_PHY_COUNTMAX - params->ofdmTrigHigh; + if (params->cckTrigHigh >= AR_PHY_COUNTMAX) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "CCK Trigger %d is too high for hw counters, using max\n", + params->cckTrigHigh); + params->cckPhyErrBase = 0; + } else + params->cckPhyErrBase = AR_PHY_COUNTMAX - params->cckTrigHigh; +} + +/* + * Setup ANI handling. Sets all thresholds and reset the + * channel statistics. Note that ar5416AniReset should be + * called by ar5416Reset before anything else happens and + * that's where we force initial settings. + */ +void +ar5416AniAttach(struct ath_hal *ah, const struct ar5212AniParams *params24, + const struct ar5212AniParams *params5, HAL_BOOL enable) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + if (params24 != AH_NULL) { + OS_MEMCPY(&ahp->ah_aniParams24, params24, sizeof(*params24)); + setPhyErrBase(ah, &ahp->ah_aniParams24); + } + if (params5 != AH_NULL) { + OS_MEMCPY(&ahp->ah_aniParams5, params5, sizeof(*params5)); + setPhyErrBase(ah, &ahp->ah_aniParams5); + } + + OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani)); + /* Enable MIB Counters */ + enableAniMIBCounters(ah, &ahp->ah_aniParams24 /*XXX*/); + + if (enable) { /* Enable ani now */ + HALASSERT(params24 != AH_NULL && params5 != AH_NULL); + ahp->ah_procPhyErr |= HAL_ANI_ENA; + } else { + ahp->ah_procPhyErr &= ~HAL_ANI_ENA; + } +} + +/* + * Cleanup any ANI state setup. + */ +void +ar5416AniDetach(struct ath_hal *ah) +{ + HALDEBUG(ah, HAL_DEBUG_ANI, "Detaching Ani\n"); + disableAniMIBCounters(ah); +} + +/* + * Control Adaptive Noise Immunity Parameters + */ +HAL_BOOL +ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) +{ + typedef int TABLE[]; + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState = ahp->ah_curani; + const struct ar5212AniParams *params = aniState->params; + + OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd); + + switch (cmd) { + case HAL_ANI_NOISE_IMMUNITY_LEVEL: { + u_int level = param; + + if (level >= params->maxNoiseImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: level out of range (%u > %u)\n", + __func__, level, params->maxNoiseImmunityLevel); + return AH_FALSE; + } + + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, + AR_PHY_DESIRED_SZ_TOT_DES, params->totalSizeDesired[level]); + OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, + AR_PHY_AGC_CTL1_COARSE_LOW, params->coarseLow[level]); + OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, + AR_PHY_AGC_CTL1_COARSE_HIGH, params->coarseHigh[level]); + OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRPWR, params->firpwr[level]); + + if (level > aniState->noiseImmunityLevel) + ahp->ah_stats.ast_ani_niup++; + else if (level < aniState->noiseImmunityLevel) + ahp->ah_stats.ast_ani_nidown++; + aniState->noiseImmunityLevel = level; + break; + } + case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: { + static const TABLE m1ThreshLow = { 127, 50 }; + static const TABLE m2ThreshLow = { 127, 40 }; + static const TABLE m1Thresh = { 127, 0x4d }; + static const TABLE m2Thresh = { 127, 0x40 }; + static const TABLE m2CountThr = { 31, 16 }; + static const TABLE m2CountThrLow = { 63, 48 }; + u_int on = param ? 1 : 0; + + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M1_THRESH_LOW, m1ThreshLow[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2_THRESH_LOW, m2ThreshLow[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, m2CountThrLow[on]); + + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLow[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLow[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M1_THRESH, m1Thresh[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M2_THRESH, m2Thresh[on]); + + if (on) { + OS_REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + } else { + OS_REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + } + if (on) + ahp->ah_stats.ast_ani_ofdmon++; + else + ahp->ah_stats.ast_ani_ofdmoff++; + aniState->ofdmWeakSigDetectOff = !on; + break; + } + case HAL_ANI_CCK_WEAK_SIGNAL_THR: { + static const TABLE weakSigThrCck = { 8, 6 }; + u_int high = param ? 1 : 0; + + OS_REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, + AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, weakSigThrCck[high]); + if (high) + ahp->ah_stats.ast_ani_cckhigh++; + else + ahp->ah_stats.ast_ani_ccklow++; + aniState->cckWeakSigThreshold = high; + break; + } + case HAL_ANI_FIRSTEP_LEVEL: { + u_int level = param; + + if (level >= params->maxFirstepLevel) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: level out of range (%u > %u)\n", + __func__, level, params->maxFirstepLevel); + return AH_FALSE; + } + OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRSTEP, params->firstep[level]); + if (level > aniState->firstepLevel) + ahp->ah_stats.ast_ani_stepup++; + else if (level < aniState->firstepLevel) + ahp->ah_stats.ast_ani_stepdown++; + aniState->firstepLevel = level; + break; + } + case HAL_ANI_SPUR_IMMUNITY_LEVEL: { + u_int level = param; + + if (level >= params->maxSpurImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: level out of range (%u > %u)\n", + __func__, level, params->maxSpurImmunityLevel); + return AH_FALSE; + } + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5, + AR_PHY_TIMING5_CYCPWR_THR1, params->cycPwrThr1[level]); + if (level > aniState->spurImmunityLevel) + ahp->ah_stats.ast_ani_spurup++; + else if (level < aniState->spurImmunityLevel) + ahp->ah_stats.ast_ani_spurdown++; + aniState->spurImmunityLevel = level; + break; + } + case HAL_ANI_PRESENT: + break; + case HAL_ANI_MODE: + if (param == 0) { + ahp->ah_procPhyErr &= ~HAL_ANI_ENA; + /* Turn off HW counters if we have them */ + ar5416AniDetach(ah); + ar5212SetRxFilter(ah, + ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR); + } else { /* normal/auto mode */ + /* don't mess with state if already enabled */ + if (ahp->ah_procPhyErr & HAL_ANI_ENA) + break; + ar5212SetRxFilter(ah, + ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR); + /* Enable MIB Counters */ + enableAniMIBCounters(ah, ahp->ah_curani != AH_NULL ? + ahp->ah_curani->params: &ahp->ah_aniParams24 /*XXX*/); + ahp->ah_procPhyErr |= HAL_ANI_ENA; + } + break; +#ifdef AH_PRIVATE_DIAG + case HAL_ANI_PHYERR_RESET: + ahp->ah_stats.ast_ani_ofdmerrs = 0; + ahp->ah_stats.ast_ani_cckerrs = 0; + break; +#endif /* AH_PRIVATE_DIAG */ + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid cmd %u\n", + __func__, cmd); + return AH_FALSE; + } + return AH_TRUE; +} + +static void +ar5416AniOfdmErrTrigger(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan; + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(chan != AH_NULL); + + if (!ANI_ENA(ah)) + return; + + aniState = ahp->ah_curani; + params = aniState->params; + /* First, raise noise immunity level, up to max */ + if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) { + ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel + 1); + return; + } + /* then, raise spur immunity level, up to max */ + if (aniState->spurImmunityLevel+1 < params->maxSpurImmunityLevel) { + ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel + 1); + return; + } + + if (ANI_ENA_RSSI(ah)) { + int32_t rssi = BEACON_RSSI(ahp); + if (rssi > params->rssiThrHigh) { + /* + * Beacon rssi is high, can turn off ofdm + * weak sig detect. + */ + if (!aniState->ofdmWeakSigDetectOff) { + ar5416AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_FALSE); + ar5416AniControl(ah, + HAL_ANI_SPUR_IMMUNITY_LEVEL, 0); + return; + } + /* + * If weak sig detect is already off, as last resort, + * raise firstep level + */ + if (aniState->firstepLevel+1 < params->maxFirstepLevel) { + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + return; + } + } else if (rssi > params->rssiThrLow) { + /* + * Beacon rssi in mid range, need ofdm weak signal + * detect, but we can raise firststepLevel. + */ + if (aniState->ofdmWeakSigDetectOff) + ar5416AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_TRUE); + if (aniState->firstepLevel+1 < params->maxFirstepLevel) + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + return; + } else { + /* + * Beacon rssi is low, if in 11b/g mode, turn off ofdm + * weak signal detection and zero firstepLevel to + * maximize CCK sensitivity + */ + /* XXX can optimize */ + if (IS_CHAN_B(chan) || IS_CHAN_G(chan)) { + if (!aniState->ofdmWeakSigDetectOff) + ar5416AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_FALSE); + if (aniState->firstepLevel > 0) + ar5416AniControl(ah, + HAL_ANI_FIRSTEP_LEVEL, 0); + return; + } + } + } +} + +static void +ar5416AniCckErrTrigger(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan; + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(chan != AH_NULL); + + if (!ANI_ENA(ah)) + return; + + /* first, raise noise immunity level, up to max */ + aniState = ahp->ah_curani; + params = aniState->params; + if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) { + ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel + 1); + return; + } + + if (ANI_ENA_RSSI(ah)) { + int32_t rssi = BEACON_RSSI(ahp); + if (rssi > params->rssiThrLow) { + /* + * Beacon signal in mid and high range, + * raise firstep level. + */ + if (aniState->firstepLevel+1 < params->maxFirstepLevel) + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + } else { + /* + * Beacon rssi is low, zero firstep level to maximize + * CCK sensitivity in 11b/g mode. + */ + /* XXX can optimize */ + if (IS_CHAN_B(chan) || IS_CHAN_G(chan)) { + if (aniState->firstepLevel > 0) + ar5416AniControl(ah, + HAL_ANI_FIRSTEP_LEVEL, 0); + } + } + } +} + +static void +ar5416AniRestart(struct ath_hal *ah, struct ar5212AniState *aniState) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const struct ar5212AniParams *params = aniState->params; + + aniState->listenTime = 0; + /* + * NB: these are written on reset based on the + * ini so we must re-write them! + */ + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: Writing ofdmbase=%u cckbase=%u\n", __func__, + params->ofdmPhyErrBase, params->cckPhyErrBase); + OS_REG_WRITE(ah, AR_PHY_ERR_1, params->ofdmPhyErrBase); + OS_REG_WRITE(ah, AR_PHY_ERR_2, params->cckPhyErrBase); + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_CCK_TIMING); + + /* Clear the mib counters and save them in the stats */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + aniState->ofdmPhyErrCount = 0; + aniState->cckPhyErrCount = 0; +} + +/* + * Restore/reset the ANI parameters and reset the statistics. + * This routine must be called for every channel change. + * + * NOTE: This is where ah_curani is set; other ani code assumes + * it is setup to reflect the current channel. + */ +void +ar5416AniReset(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, + HAL_OPMODE opmode, int restore) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState; + uint32_t rxfilter; + int index; + + index = ar5416GetAniChannelIndex(ah, chan); + aniState = &ahp->ah_ani[index]; + ahp->ah_curani = aniState; +#if 0 + ath_hal_printf(ah,"%s: chan %u/0x%x restore %d setup %d opmode %u\n", + __func__, chan->channel, chan->channelFlags, restore, + aniState->isSetup, opmode); +#else + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: chan %u/0x%x restore %d setup %d opmode %u\n", + __func__, chan->channel, chan->channelFlags, restore, + aniState->isSetup, opmode); +#endif + OS_MARK(ah, AH_MARK_ANI_RESET, opmode); + + /* + * Turn off PHY error frame delivery while we futz with settings. + */ + rxfilter = ar5212GetRxFilter(ah); + ar5212SetRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR); + /* + * Automatic processing is done only in station mode right now. + */ + if (opmode == HAL_M_STA) + ahp->ah_procPhyErr |= HAL_RSSI_ANI_ENA; + else + ahp->ah_procPhyErr &= ~HAL_RSSI_ANI_ENA; + /* + * Set all ani parameters. We either set them to initial + * values or restore the previous ones for the channel. + * XXX if ANI follows hardware, we don't care what mode we're + * XXX in, we should keep the ani parameters + */ + if (restore && aniState->isSetup) { + ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel); + ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel); + ar5416AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + !aniState->ofdmWeakSigDetectOff); + ar5416AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, + aniState->cckWeakSigThreshold); + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel); + } else { + ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0); + ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0); + ar5416AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_TRUE); + ar5416AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, AH_FALSE); + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0); + aniState->isSetup = AH_TRUE; + } + ar5416AniRestart(ah, aniState); + + /* restore RX filter mask */ + ar5212SetRxFilter(ah, rxfilter); +} + +/* + * Process a MIB interrupt. We may potentially be invoked because + * any of the MIB counters overflow/trigger so don't assume we're + * here because a PHY error counter triggered. + */ +void +ar5416ProcessMibIntr(struct ath_hal *ah, const HAL_NODE_STATS *stats) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t phyCnt1, phyCnt2; + + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: mibc 0x%x phyCnt1 0x%x phyCnt2 0x%x " + "filtofdm 0x%x filtcck 0x%x\n", + __func__, OS_REG_READ(ah, AR_MIBC), + OS_REG_READ(ah, AR_PHYCNT1), OS_REG_READ(ah, AR_PHYCNT2), + OS_REG_READ(ah, AR_FILTOFDM), OS_REG_READ(ah, AR_FILTCCK)); + + /* + * First order of business is to clear whatever caused + * the interrupt so we don't keep getting interrupted. + * We have the usual mib counters that are reset-on-read + * and the additional counters that appeared starting in + * Hainan. We collect the mib counters and explicitly + * zero additional counters we are not using. Anything + * else is reset only if it caused the interrupt. + */ + /* NB: these are not reset-on-read */ + phyCnt1 = OS_REG_READ(ah, AR_PHY_ERR_1); + phyCnt2 = OS_REG_READ(ah, AR_PHY_ERR_2); + /* not used, always reset them in case they are the cause */ + OS_REG_WRITE(ah, AR_FILTOFDM, 0); + OS_REG_WRITE(ah, AR_FILTCCK, 0); + if ((OS_REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING) == 0) + OS_REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); + + /* Clear the mib counters and save them in the stats */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + ahp->ah_stats.ast_nodestats = *stats; + + /* + * Check for an ani stat hitting the trigger threshold. + * When this happens we get a MIB interrupt and the top + * 2 bits of the counter register will be 0b11, hence + * the mask check of phyCnt?. + */ + if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || + ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { + struct ar5212AniState *aniState = ahp->ah_curani; + const struct ar5212AniParams *params = aniState->params; + uint32_t ofdmPhyErrCnt, cckPhyErrCnt; + + ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase; + ahp->ah_stats.ast_ani_ofdmerrs += + ofdmPhyErrCnt - aniState->ofdmPhyErrCount; + aniState->ofdmPhyErrCount = ofdmPhyErrCnt; + + cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase; + ahp->ah_stats.ast_ani_cckerrs += + cckPhyErrCnt - aniState->cckPhyErrCount; + aniState->cckPhyErrCount = cckPhyErrCnt; + + /* + * NB: figure out which counter triggered. If both + * trigger we'll only deal with one as the processing + * clobbers the error counter so the trigger threshold + * check will never be true. + */ + if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh) + ar5416AniOfdmErrTrigger(ah); + if (aniState->cckPhyErrCount > params->cckTrigHigh) + ar5416AniCckErrTrigger(ah); + /* NB: always restart to insure the h/w counters are reset */ + ar5416AniRestart(ah, aniState); + } +} + +static void +ar5416AniLowerImmunity(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(ANI_ENA(ah)); + + aniState = ahp->ah_curani; + params = aniState->params; + if (ANI_ENA_RSSI(ah)) { + int32_t rssi = BEACON_RSSI(ahp); + if (rssi > params->rssiThrHigh) { + /* + * Beacon signal is high, leave ofdm weak signal + * detection off or it may oscillate. Let it fall + * through. + */ + } else if (rssi > params->rssiThrLow) { + /* + * Beacon rssi in mid range, turn on ofdm weak signal + * detection or lower firstep level. + */ + if (aniState->ofdmWeakSigDetectOff) { + ar5416AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_TRUE); + return; + } + if (aniState->firstepLevel > 0) { + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel - 1); + return; + } + } else { + /* + * Beacon rssi is low, reduce firstep level. + */ + if (aniState->firstepLevel > 0) { + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel - 1); + return; + } + } + } + /* then lower spur immunity level, down to zero */ + if (aniState->spurImmunityLevel > 0) { + ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel - 1); + return; + } + /* + * if all else fails, lower noise immunity level down to a min value + * zero for now + */ + if (aniState->noiseImmunityLevel > 0) { + ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel - 1); + return; + } +} + +#define CLOCK_RATE 44000 /* XXX use mac_usec or similar */ +/* convert HW counter values to ms using 11g clock rate, goo9d enough + for 11a and Turbo */ + +/* + * Return an approximation of the time spent ``listening'' by + * deducting the cycles spent tx'ing and rx'ing from the total + * cycle count since our last call. A return value <0 indicates + * an invalid/inconsistent time. + */ +static int32_t +ar5416AniGetListenTime(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState; + uint32_t txFrameCount, rxFrameCount, cycleCount; + int32_t listenTime; + + txFrameCount = OS_REG_READ(ah, AR_TFCNT); + rxFrameCount = OS_REG_READ(ah, AR_RFCNT); + cycleCount = OS_REG_READ(ah, AR_CCCNT); + + aniState = ahp->ah_curani; + if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { + /* + * Cycle counter wrap (or initial call); it's not possible + * to accurately calculate a value because the registers + * right shift rather than wrap--so punt and return 0. + */ + listenTime = 0; + ahp->ah_stats.ast_ani_lzero++; + } else { + int32_t ccdelta = cycleCount - aniState->cycleCount; + int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; + int32_t tfdelta = txFrameCount - aniState->txFrameCount; + listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE; + } + aniState->cycleCount = cycleCount; + aniState->txFrameCount = txFrameCount; + aniState->rxFrameCount = rxFrameCount; + return listenTime; +} + +/* + * Update ani stats in preparation for listen time processing. + */ +static void +updateMIBStats(struct ath_hal *ah, struct ar5212AniState *aniState) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const struct ar5212AniParams *params = aniState->params; + uint32_t phyCnt1, phyCnt2; + int32_t ofdmPhyErrCnt, cckPhyErrCnt; + + /* Clear the mib counters and save them in the stats */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + + /* NB: these are not reset-on-read */ + phyCnt1 = OS_REG_READ(ah, AR_PHY_ERR_1); + phyCnt2 = OS_REG_READ(ah, AR_PHY_ERR_2); + + /* NB: these are spec'd to never roll-over */ + ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase; + if (ofdmPhyErrCnt < 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "OFDM phyErrCnt %d phyCnt1 0x%x\n", + ofdmPhyErrCnt, phyCnt1); + ofdmPhyErrCnt = AR_PHY_COUNTMAX; + } + ahp->ah_stats.ast_ani_ofdmerrs += + ofdmPhyErrCnt - aniState->ofdmPhyErrCount; + aniState->ofdmPhyErrCount = ofdmPhyErrCnt; + + cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase; + if (cckPhyErrCnt < 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "CCK phyErrCnt %d phyCnt2 0x%x\n", + cckPhyErrCnt, phyCnt2); + cckPhyErrCnt = AR_PHY_COUNTMAX; + } + ahp->ah_stats.ast_ani_cckerrs += + cckPhyErrCnt - aniState->cckPhyErrCount; + aniState->cckPhyErrCount = cckPhyErrCnt; +} + +/* + * Do periodic processing. This routine is called from the + * driver's rx interrupt handler after processing frames. + */ +void +ar5416AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats, + HAL_CHANNEL *chan) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState = ahp->ah_curani; + const struct ar5212AniParams *params; + int32_t listenTime; + + ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi; + + /* XXX can aniState be null? */ + if (aniState == AH_NULL) + return; + if (!ANI_ENA(ah)) + return; + + listenTime = ar5416AniGetListenTime(ah); + if (listenTime < 0) { + ahp->ah_stats.ast_ani_lneg++; + /* restart ANI period if listenTime is invalid */ + ar5416AniRestart(ah, aniState); + } + /* XXX beware of overflow? */ + aniState->listenTime += listenTime; + + OS_MARK(ah, AH_MARK_ANI_POLL, aniState->listenTime); + + params = aniState->params; + if (aniState->listenTime > 5*params->period) { + /* + * Check to see if need to lower immunity if + * 5 aniPeriods have passed + */ + updateMIBStats(ah, aniState); + if (aniState->ofdmPhyErrCount <= aniState->listenTime * + params->ofdmTrigLow/1000 && + aniState->cckPhyErrCount <= aniState->listenTime * + params->cckTrigLow/1000) + ar5416AniLowerImmunity(ah); + ar5416AniRestart(ah, aniState); + } else if (aniState->listenTime > params->period) { + updateMIBStats(ah, aniState); + /* check to see if need to raise immunity */ + if (aniState->ofdmPhyErrCount > aniState->listenTime * + params->ofdmTrigHigh / 1000) { + ar5416AniOfdmErrTrigger(ah); + ar5416AniRestart(ah, aniState); + } else if (aniState->cckPhyErrCount > aniState->listenTime * + params->cckTrigHigh / 1000) { + ar5416AniCckErrTrigger(ah); + ar5416AniRestart(ah, aniState); + } + } +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_attach.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_attach.c new file mode 100644 index 0000000000..d5ffdae6c0 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_attach.c @@ -0,0 +1,486 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_attach.c,v 1.27 2008/11/27 22:30:07 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#include "ar5416/ar5416.ini" + +static void +ar5416AniSetup(struct ath_hal *ah) +{ + static const struct ar5212AniParams aniparams = { + .maxNoiseImmunityLevel = 4, /* levels 0..4 */ + .totalSizeDesired = { -55, -55, -55, -55, -62 }, + .coarseHigh = { -14, -14, -14, -14, -12 }, + .coarseLow = { -64, -64, -64, -64, -70 }, + .firpwr = { -78, -78, -78, -78, -80 }, + .maxSpurImmunityLevel = 2, + .cycPwrThr1 = { 2, 4, 6 }, + .maxFirstepLevel = 2, /* levels 0..2 */ + .firstep = { 0, 4, 8 }, + .ofdmTrigHigh = 500, + .ofdmTrigLow = 200, + .cckTrigHigh = 200, + .cckTrigLow = 100, + .rssiThrHigh = 40, + .rssiThrLow = 7, + .period = 100, + }; + /* NB: ANI is not enabled yet */ + ar5212AniAttach(ah, &aniparams, &aniparams, AH_FALSE); +} + +/* + * Attach for an AR5416 part. + */ +void +ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp; + struct ath_hal *ah; + + ahp = &ahp5416->ah_5212; + ar5212InitState(ahp, devid, sc, st, sh, status); + ah = &ahp->ah_priv.h; + + /* override 5212 methods for our needs */ + ah->ah_magic = AR5416_MAGIC; + ah->ah_getRateTable = ar5416GetRateTable; + ah->ah_detach = ar5416Detach; + + /* Reset functions */ + ah->ah_reset = ar5416Reset; + ah->ah_phyDisable = ar5416PhyDisable; + ah->ah_disable = ar5416Disable; + ah->ah_perCalibration = ar5416PerCalibration; + ah->ah_perCalibrationN = ar5416PerCalibrationN, + ah->ah_resetCalValid = ar5416ResetCalValid, + ah->ah_setTxPowerLimit = ar5416SetTxPowerLimit; + + /* Transmit functions */ + ah->ah_stopTxDma = ar5416StopTxDma; + ah->ah_setupTxDesc = ar5416SetupTxDesc; + ah->ah_setupXTxDesc = ar5416SetupXTxDesc; + ah->ah_fillTxDesc = ar5416FillTxDesc; + ah->ah_procTxDesc = ar5416ProcTxDesc; + + /* Receive Functions */ + ah->ah_startPcuReceive = ar5416StartPcuReceive; + ah->ah_stopPcuReceive = ar5416StopPcuReceive; + ah->ah_setupRxDesc = ar5416SetupRxDesc; + ah->ah_procRxDesc = ar5416ProcRxDesc; + ah->ah_rxMonitor = ar5416AniPoll, + ah->ah_procMibEvent = ar5416ProcessMibIntr, + + /* Misc Functions */ + ah->ah_getDiagState = ar5416GetDiagState; + ah->ah_setLedState = ar5416SetLedState; + ah->ah_gpioCfgOutput = ar5416GpioCfgOutput; + ah->ah_gpioCfgInput = ar5416GpioCfgInput; + ah->ah_gpioGet = ar5416GpioGet; + ah->ah_gpioSet = ar5416GpioSet; + ah->ah_gpioSetIntr = ar5416GpioSetIntr; + ah->ah_resetTsf = ar5416ResetTsf; + ah->ah_getRfGain = ar5416GetRfgain; + ah->ah_setAntennaSwitch = ar5416SetAntennaSwitch; + ah->ah_setDecompMask = ar5416SetDecompMask; + ah->ah_setCoverageClass = ar5416SetCoverageClass; + + ah->ah_resetKeyCacheEntry = ar5416ResetKeyCacheEntry; + ah->ah_setKeyCacheEntry = ar5416SetKeyCacheEntry; + + /* Power Management Functions */ + ah->ah_setPowerMode = ar5416SetPowerMode; + + /* Beacon Management Functions */ + ah->ah_setBeaconTimers = ar5416SetBeaconTimers; + ah->ah_beaconInit = ar5416BeaconInit; + ah->ah_setStationBeaconTimers = ar5416SetStaBeaconTimers; + ah->ah_resetStationBeaconTimers = ar5416ResetStaBeaconTimers; + + /* XXX 802.11n Functions */ +#if 0 + ah->ah_chainTxDesc = ar5416ChainTxDesc; + ah->ah_setupFirstTxDesc = ar5416SetupFirstTxDesc; + ah->ah_setupLastTxDesc = ar5416SetupLastTxDesc; + ah->ah_set11nRateScenario = ar5416Set11nRateScenario; + ah->ah_set11nAggrMiddle = ar5416Set11nAggrMiddle; + ah->ah_clr11nAggr = ar5416Clr11nAggr; + ah->ah_set11nBurstDuration = ar5416Set11nBurstDuration; + ah->ah_get11nExtBusy = ar5416Get11nExtBusy; + ah->ah_set11nMac2040 = ar5416Set11nMac2040; + ah->ah_get11nRxClear = ar5416Get11nRxClear; + ah->ah_set11nRxClear = ar5416Set11nRxClear; +#endif + + /* Interrupt functions */ + ah->ah_isInterruptPending = ar5416IsInterruptPending; + ah->ah_getPendingInterrupts = ar5416GetPendingInterrupts; + ah->ah_setInterrupts = ar5416SetInterrupts; + + ahp->ah_priv.ah_getWirelessModes= ar5416GetWirelessModes; + ahp->ah_priv.ah_eepromRead = ar5416EepromRead; +#ifdef AH_SUPPORT_WRITE_EEPROM + ahp->ah_priv.ah_eepromWrite = ar5416EepromWrite; +#endif + ahp->ah_priv.ah_gpioCfgOutput = ar5416GpioCfgOutput; + ahp->ah_priv.ah_gpioCfgInput = ar5416GpioCfgInput; + ahp->ah_priv.ah_gpioGet = ar5416GpioGet; + ahp->ah_priv.ah_gpioSet = ar5416GpioSet; + ahp->ah_priv.ah_gpioSetIntr = ar5416GpioSetIntr; + ahp->ah_priv.ah_getChipPowerLimits = ar5416GetChipPowerLimits; + + /* + * Start by setting all Owl devices to 2x2 + */ + AH5416(ah)->ah_rx_chainmask = AR5416_DEFAULT_RXCHAINMASK; + AH5416(ah)->ah_tx_chainmask = AR5416_DEFAULT_TXCHAINMASK; +} + +/* + * Attach for an AR5416 part. + */ +struct ath_hal * +ar5416Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) +{ + struct ath_hal_5416 *ahp5416; + struct ath_hal_5212 *ahp; + struct ath_hal *ah; + uint32_t val; + HAL_STATUS ecode; + HAL_BOOL rfStatus; + + HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + __func__, sc, (void*) st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416) + + /* extra space for Owl 2.1/2.2 WAR */ + sizeof(ar5416Addac) + ); + if (ahp5416 == AH_NULL) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot allocate memory for state block\n", __func__); + *status = HAL_ENOMEM; + return AH_NULL; + } + ar5416InitState(ahp5416, devid, sc, st, sh, status); + ahp = &ahp5416->ah_5212; + ah = &ahp->ah_priv.h; + + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { + /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", __func__); + ecode = HAL_EIO; + goto bad; + } + + if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", __func__); + ecode = HAL_EIO; + goto bad; + } + /* Read Revisions from Chips before taking out of reset */ + val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID; + AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S; + AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION; + + /* setup common ini data; rf backends handle remainder */ + HAL_INI_INIT(&ahp->ah_ini_modes, ar5416Modes, 6); + HAL_INI_INIT(&ahp->ah_ini_common, ar5416Common, 2); + + HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar5416BB_RfGain, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar5416Bank0, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar5416Bank1, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar5416Bank2, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar5416Bank3, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar5416Bank6, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar5416Bank7, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar5416Addac, 2); + + if (!IS_5416V2_2(ah)) { /* Owl 2.1/2.0 */ + struct ini { + uint32_t *data; /* NB: !const */ + int rows, cols; + }; + /* override CLKDRV value */ + OS_MEMCPY(&AH5416(ah)[1], ar5416Addac, sizeof(ar5416Addac)); + AH5416(ah)->ah_ini_addac.data = (uint32_t *) &AH5416(ah)[1]; + HAL_INI_VAL((struct ini *)&AH5416(ah)->ah_ini_addac, 31, 1) = 0; + } + + if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); + + if (!ar5212ChipTest(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", + __func__); + ecode = HAL_ESELFTEST; + goto bad; + } + + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* Read Radio Chip Rev Extract */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah); + switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { + case AR_RAD5122_SREV_MAJOR: /* Fowl: 5G/2x2 */ + case AR_RAD2122_SREV_MAJOR: /* Fowl: 2+5G/2x2 */ + case AR_RAD2133_SREV_MAJOR: /* Fowl: 2G/3x3 */ + case AR_RAD5133_SREV_MAJOR: /* Fowl: 2+5G/3x3 */ + break; + default: + if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { + /* + * When RF_Silen is used the analog chip is reset. + * So when the system boots with radio switch off + * the RF chip rev reads back as zero and we need + * to use the mac+phy revs to set the radio rev. + */ + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD5133_SREV_MAJOR; + break; + } + /* NB: silently accept anything in release code per Atheros */ +#ifdef AH_DEBUG + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5G Radio Chip Rev 0x%02X is not supported by " + "this driver\n", __func__, + AH_PRIVATE(ah)->ah_analog5GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; +#endif + } + + ecode = ath_hal_v14EepromAttach(ah); + if (ecode != HAL_OK) + goto bad; + + /* + * Got everything we need now to setup the capabilities. + */ + if (!ar5416FillCapabilityInfo(ah)) { + ecode = HAL_EEREAD; + goto bad; + } + + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error getting mac address from EEPROM\n", __func__); + goto bad; + } + /* XXX How about the serial number ? */ + /* Read Reg Domain */ + AH_PRIVATE(ah)->ah_currentRD = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); + + /* + * ah_miscMode is populated by ar5416FillCapabilityInfo() + * starting from griffin. Set here to make sure that + * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is + * placed into hardware. + */ + if (ahp->ah_miscMode != 0) + OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: Attaching AR2133 radio\n", + __func__); + rfStatus = ar2133RfAttach(ah, &ecode); + if (!rfStatus) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", + __func__, ecode); + goto bad; + } + + ar5416AniSetup(ah); /* Anti Noise Immunity */ + ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); + + return ah; +bad: + if (ahp) + ar5416Detach((struct ath_hal *) ahp); + if (status) + *status = ecode; + return AH_NULL; +} + +void +ar5416Detach(struct ath_hal *ah) +{ + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__); + + HALASSERT(ah != AH_NULL); + HALASSERT(ah->ah_magic == AR5416_MAGIC); + + ar5416AniDetach(ah); + ar5212RfDetach(ah); + ah->ah_disable(ah); + ar5416SetPowerMode(ah, HAL_PM_FULL_SLEEP, AH_TRUE); + ath_hal_eepromDetach(ah); + ath_hal_free(ah); +} + +/* + * Fill all software cached or static hardware state information. + * Return failure if capabilities are to come from EEPROM and + * cannot be read. + */ +HAL_BOOL +ar5416FillCapabilityInfo(struct ath_hal *ah) +{ + struct ath_hal_private *ahpriv = AH_PRIVATE(ah); + HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; + uint16_t val; + + /* Construct wireless mode from EEPROM */ + pCap->halWirelessModes = 0; + if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { + pCap->halWirelessModes |= HAL_MODE_11A + | HAL_MODE_11NA_HT20 + | HAL_MODE_11NA_HT40PLUS + | HAL_MODE_11NA_HT40MINUS + ; + } + if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE)) { + pCap->halWirelessModes |= HAL_MODE_11G + | HAL_MODE_11NG_HT20 + | HAL_MODE_11NG_HT40PLUS + | HAL_MODE_11NG_HT40MINUS + ; + pCap->halWirelessModes |= HAL_MODE_11A + | HAL_MODE_11NA_HT20 + | HAL_MODE_11NA_HT40PLUS + | HAL_MODE_11NA_HT40MINUS + ; + } + + pCap->halLow2GhzChan = 2312; + pCap->halHigh2GhzChan = 2732; + + pCap->halLow5GhzChan = 4915; + pCap->halHigh5GhzChan = 6100; + + pCap->halCipherCkipSupport = AH_FALSE; + pCap->halCipherTkipSupport = AH_TRUE; + pCap->halCipherAesCcmSupport = ath_hal_eepromGetFlag(ah, AR_EEP_AES); + + pCap->halMicCkipSupport = AH_FALSE; + pCap->halMicTkipSupport = AH_TRUE; + pCap->halMicAesCcmSupport = ath_hal_eepromGetFlag(ah, AR_EEP_AES); + /* + * Starting with Griffin TX+RX mic keys can be combined + * in one key cache slot. + */ + pCap->halTkipMicTxRxKeySupport = AH_TRUE; + pCap->halChanSpreadSupport = AH_TRUE; + pCap->halSleepAfterBeaconBroken = AH_TRUE; + + pCap->halCompressSupport = AH_FALSE; + pCap->halBurstSupport = AH_TRUE; + pCap->halFastFramesSupport = AH_FALSE; /* XXX? */ + pCap->halChapTuningSupport = AH_TRUE; + pCap->halTurboPrimeSupport = AH_TRUE; + + pCap->halTurboGSupport = pCap->halWirelessModes & HAL_MODE_108G; + + pCap->halPSPollBroken = AH_TRUE; /* XXX fixed in later revs? */ + pCap->halVEOLSupport = AH_TRUE; + pCap->halBssIdMaskSupport = AH_TRUE; + pCap->halMcastKeySrchSupport = AH_FALSE; + pCap->halTsfAddSupport = AH_TRUE; + + if (ath_hal_eepromGet(ah, AR_EEP_MAXQCU, &val) == HAL_OK) + pCap->halTotalQueues = val; + else + pCap->halTotalQueues = HAL_NUM_TX_QUEUES; + + if (ath_hal_eepromGet(ah, AR_EEP_KCENTRIES, &val) == HAL_OK) + pCap->halKeyCacheSize = val; + else + pCap->halKeyCacheSize = AR5416_KEYTABLE_SIZE; + + /* XXX not needed */ + pCap->halChanHalfRate = AH_FALSE; /* XXX ? */ + pCap->halChanQuarterRate = AH_FALSE; /* XXX ? */ + + pCap->halTstampPrecision = 32; + pCap->halHwPhyCounterSupport = AH_TRUE; + + pCap->halFastCCSupport = AH_TRUE; + pCap->halNumGpioPins = 6; + pCap->halWowSupport = AH_FALSE; + pCap->halWowMatchPatternExact = AH_FALSE; + pCap->halBtCoexSupport = AH_FALSE; /* XXX need support */ + pCap->halAutoSleepSupport = AH_FALSE; +#if 0 /* XXX not yet */ + pCap->halNumAntCfg2GHz = ar5416GetNumAntConfig(ahp, HAL_FREQ_BAND_2GHZ); + pCap->halNumAntCfg5GHz = ar5416GetNumAntConfig(ahp, HAL_FREQ_BAND_5GHZ); +#endif + pCap->halHTSupport = AH_TRUE; + pCap->halTxChainMask = ath_hal_eepromGet(ah, AR_EEP_TXMASK, AH_NULL); + /* XXX CB71 uses GPIO 0 to indicate 3 rx chains */ + pCap->halRxChainMask = ath_hal_eepromGet(ah, AR_EEP_RXMASK, AH_NULL); + pCap->halRtsAggrLimit = 8*1024; /* Owl 2.0 limit */ + pCap->halMbssidAggrSupport = AH_TRUE; + pCap->halForcePpmSupport = AH_TRUE; + pCap->halEnhancedPmSupport = AH_TRUE; + + if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) && + ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) { + /* NB: enabled by default */ + ahpriv->ah_rfkillEnabled = AH_TRUE; + pCap->halRfSilentSupport = AH_TRUE; + } + + ahpriv->ah_rxornIsFatal = AH_FALSE; + + return AH_TRUE; +} + +static const char* +ar5416Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID && + (devid == AR5416_DEVID_PCI || devid == AR5416_DEVID_PCIE)) + return "Atheros 5416"; + return AH_NULL; +} +AH_CHIP(AR5416, ar5416Probe, ar5416Attach); diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_beacon.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_beacon.c new file mode 100644 index 0000000000..1d68c68424 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_beacon.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_beacon.c,v 1.8 2008/11/11 01:03:12 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#define TU_TO_USEC(_tu) ((_tu) << 10) + +/* + * Initialize all of the hardware registers used to + * send beacons. Note that for station operation the + * driver calls ar5416SetStaBeaconTimers instead. + */ +void +ar5416SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt) +{ + uint32_t bperiod; + + OS_REG_WRITE(ah, AR_NEXT_TBTT, TU_TO_USEC(bt->bt_nexttbtt)); + OS_REG_WRITE(ah, AR_NEXT_DBA, TU_TO_USEC(bt->bt_nextdba) >> 3); + OS_REG_WRITE(ah, AR_NEXT_SWBA, TU_TO_USEC(bt->bt_nextswba) >> 3); + OS_REG_WRITE(ah, AR_NEXT_NDP, TU_TO_USEC(bt->bt_nextatim)); + + bperiod = TU_TO_USEC(bt->bt_intval & HAL_BEACON_PERIOD); + OS_REG_WRITE(ah, AR5416_BEACON_PERIOD, bperiod); + OS_REG_WRITE(ah, AR_DBA_PERIOD, bperiod); + OS_REG_WRITE(ah, AR_SWBA_PERIOD, bperiod); + OS_REG_WRITE(ah, AR_NDP_PERIOD, bperiod); + + /* + * Reset TSF if required. + */ + if (bt->bt_intval & AR_BEACON_RESET_TSF) + ar5416ResetTsf(ah); + + /* enable timers */ + /* NB: flags == 0 handled specially for backwards compatibility */ + OS_REG_SET_BIT(ah, AR_TIMER_MODE, + bt->bt_flags != 0 ? bt->bt_flags : + AR_TIMER_MODE_TBTT | AR_TIMER_MODE_DBA | AR_TIMER_MODE_SWBA); +} + +/* + * Initializes all of the hardware registers used to + * send beacons. Note that for station operation the + * driver calls ar5212SetStaBeaconTimers instead. + */ +void +ar5416BeaconInit(struct ath_hal *ah, + uint32_t next_beacon, uint32_t beacon_period) +{ + HAL_BEACON_TIMERS bt; + + bt.bt_nexttbtt = next_beacon; + /* + * TIMER1: in AP/adhoc mode this controls the DMA beacon + * alert timer; otherwise it controls the next wakeup time. + * TIMER2: in AP mode, it controls the SBA beacon alert + * interrupt; otherwise it sets the start of the next CFP. + */ + bt.bt_flags = 0; + switch (AH_PRIVATE(ah)->ah_opmode) { + case HAL_M_STA: + case HAL_M_MONITOR: + bt.bt_nextdba = 0xffff; + bt.bt_nextswba = 0x7ffff; + bt.bt_flags |= AR_TIMER_MODE_TBTT; + break; + case HAL_M_IBSS: + OS_REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ATIM_TXPOLICY); + bt.bt_flags |= AR_TIMER_MODE_NDP; + /* fall thru... */ + case HAL_M_HOSTAP: + bt.bt_nextdba = (next_beacon - + ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */ + bt.bt_nextswba = (next_beacon - + ath_hal_sw_beacon_response_time) << 3; /* 1/8 TU */ + bt.bt_flags |= AR_TIMER_MODE_TBTT + | AR_TIMER_MODE_DBA + | AR_TIMER_MODE_SWBA; + break; + } + /* + * Set the ATIM window + * Our hardware does not support an ATIM window of 0 + * (beacons will not work). If the ATIM windows is 0, + * force it to 1. + */ + bt.bt_nextatim = next_beacon + 1; + bt.bt_intval = beacon_period & + (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN); + ar5416SetBeaconTimers(ah, &bt); +} + +#define AR_BEACON_PERIOD_MAX 0xffff + +void +ar5416ResetStaBeaconTimers(struct ath_hal *ah) +{ + uint32_t val; + + OS_REG_WRITE(ah, AR_NEXT_TBTT, 0); /* no beacons */ + val = OS_REG_READ(ah, AR_STA_ID1); + val |= AR_STA_ID1_PWR_SAV; /* XXX */ + /* tell the h/w that the associated AP is not PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + val & ~(AR_STA_ID1_USE_DEFANT | AR_STA_ID1_PCF)); + OS_REG_WRITE(ah, AR5416_BEACON_PERIOD, AR_BEACON_PERIOD_MAX); + OS_REG_WRITE(ah, AR_DBA_PERIOD, AR_BEACON_PERIOD_MAX); +} + +/* + * Set all the beacon related bits on the h/w for stations + * i.e. initializes the corresponding h/w timers; + * also tells the h/w whether to anticipate PCF beacons + */ +void +ar5416SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs) +{ + uint32_t nextTbtt, nextdtim,beaconintval, dtimperiod; + + HALASSERT(bs->bs_intval != 0); + + /* NB: no cfp setting since h/w automatically takes care */ + + OS_REG_WRITE(ah, AR_NEXT_TBTT, bs->bs_nexttbtt); + + /* + * Start the beacon timers by setting the BEACON register + * to the beacon interval; no need to write tim offset since + * h/w parses IEs. + */ + OS_REG_WRITE(ah, AR5416_BEACON_PERIOD, + TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD)); + OS_REG_WRITE(ah, AR_DBA_PERIOD, + TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD)); + + /* + * Configure the BMISS interrupt. Note that we + * assume the caller blocks interrupts while enabling + * the threshold. + */ + HALASSERT(bs->bs_bmissthreshold <= + (AR_RSSI_THR_BM_THR >> AR_RSSI_THR_BM_THR_S)); + OS_REG_RMW_FIELD(ah, AR_RSSI_THR, + AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); + + /* + * Program the sleep registers to correlate with the beacon setup. + */ + + /* + * Oahu beacons timers on the station were used for power + * save operation (waking up in anticipation of a beacon) + * and any CFP function; Venice does sleep/power-save timers + * differently - so this is the right place to set them up; + * don't think the beacon timers are used by venice sta hw + * for any useful purpose anymore + * Setup venice's sleep related timers + * Current implementation assumes sw processing of beacons - + * assuming an interrupt is generated every beacon which + * causes the hardware to become awake until the sw tells + * it to go to sleep again; beacon timeout is to allow for + * beacon jitter; cab timeout is max time to wait for cab + * after seeing the last DTIM or MORE CAB bit + */ +#define CAB_TIMEOUT_VAL 10 /* in TU */ +#define BEACON_TIMEOUT_VAL 10 /* in TU */ +#define SLEEP_SLOP 3 /* in TU */ + + /* + * For max powersave mode we may want to sleep for longer than a + * beacon period and not want to receive all beacons; modify the + * timers accordingly; make sure to align the next TIM to the + * next DTIM if we decide to wake for DTIMs only + */ + beaconintval = bs->bs_intval & HAL_BEACON_PERIOD; + HALASSERT(beaconintval != 0); + if (bs->bs_sleepduration > beaconintval) { + HALASSERT(roundup(bs->bs_sleepduration, beaconintval) == + bs->bs_sleepduration); + beaconintval = bs->bs_sleepduration; + } + dtimperiod = bs->bs_dtimperiod; + if (bs->bs_sleepduration > dtimperiod) { + HALASSERT(dtimperiod == 0 || + roundup(bs->bs_sleepduration, dtimperiod) == + bs->bs_sleepduration); + dtimperiod = bs->bs_sleepduration; + } + HALASSERT(beaconintval <= dtimperiod); + if (beaconintval == dtimperiod) + nextTbtt = bs->bs_nextdtim; + else + nextTbtt = bs->bs_nexttbtt; + nextdtim = bs->bs_nextdtim; + + OS_REG_WRITE(ah, AR_NEXT_DTIM, + TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP)); + OS_REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP)); + + /* cab timeout is now in 1/8 TU */ + OS_REG_WRITE(ah, AR_SLEEP1, + SM((CAB_TIMEOUT_VAL << 3), AR5416_SLEEP1_CAB_TIMEOUT) + | AR_SLEEP1_ASSUME_DTIM); + /* beacon timeout is now in 1/8 TU */ + OS_REG_WRITE(ah, AR_SLEEP2, + SM((BEACON_TIMEOUT_VAL << 3), AR5416_SLEEP2_BEACON_TIMEOUT)); + + OS_REG_WRITE(ah, AR_TIM_PERIOD, beaconintval); + OS_REG_WRITE(ah, AR_DTIM_PERIOD, dtimperiod); + OS_REG_SET_BIT(ah, AR_TIMER_MODE, + AR_TIMER_MODE_TBTT | AR_TIMER_MODE_TIM | AR_TIMER_MODE_DTIM); + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next DTIM %d\n", + __func__, bs->bs_nextdtim); + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next beacon %d\n", + __func__, nextTbtt); + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: beacon period %d\n", + __func__, beaconintval); + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: DTIM period %d\n", + __func__, dtimperiod); +#undef CAB_TIMEOUT_VAL +#undef BEACON_TIMEOUT_VAL +#undef SLEEP_SLOP +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal.c new file mode 100644 index 0000000000..49db049663 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal.c @@ -0,0 +1,663 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_cal.c,v 1.7 2008/11/11 17:43:23 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ah_eeprom_v14.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* Owl specific stuff */ +#define NUM_NOISEFLOOR_READINGS 6 /* 3 chains * (ctl + ext) */ + +static void ar5416StartNFCal(struct ath_hal *ah); +static void ar5416LoadNF(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *); +static int16_t ar5416GetNf(struct ath_hal *, HAL_CHANNEL_INTERNAL *); + +/* + * Determine if calibration is supported by device and channel flags + */ +static OS_INLINE HAL_BOOL +ar5416IsCalSupp(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_CAL_TYPE calType) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + + switch (calType & cal->suppCals) { + case IQ_MISMATCH_CAL: + /* Run IQ Mismatch for non-CCK only */ + return !IS_CHAN_B(chan); + case ADC_GAIN_CAL: + case ADC_DC_CAL: + /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */ + return !IS_CHAN_B(chan) && + !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)); + } + return AH_FALSE; +} + +/* + * Setup HW to collect samples used for current cal + */ +static void +ar5416SetupMeasurement(struct ath_hal *ah, HAL_CAL_LIST *currCal) +{ + /* Start calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */ + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, + currCal->calData->calCountMax); + + /* Select calibration to run */ + switch (currCal->calData->calType) { + case IQ_MISMATCH_CAL: + OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: start IQ Mismatch calibration\n", __func__); + break; + case ADC_GAIN_CAL: + OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: start ADC Gain calibration\n", __func__); + break; + case ADC_DC_CAL: + OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: start ADC DC calibration\n", __func__); + break; + case ADC_DC_INIT_CAL: + OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: start Init ADC DC calibration\n", __func__); + break; + } + /* Kick-off cal */ + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL); +} + +/* + * Initialize shared data structures and prepare a cal to be run. + */ +static void +ar5416ResetMeasurement(struct ath_hal *ah, HAL_CAL_LIST *currCal) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + + /* Reset data structures shared between different calibrations */ + OS_MEMZERO(cal->caldata, sizeof(cal->caldata)); + cal->calSamples = 0; + + /* Setup HW for new calibration */ + ar5416SetupMeasurement(ah, currCal); + + /* Change SW state to RUNNING for this calibration */ + currCal->calState = CAL_RUNNING; +} + +#if 0 +/* + * Run non-periodic calibrations. + */ +static HAL_BOOL +ar5416RunInitCals(struct ath_hal *ah, int init_cal_count) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + HAL_CHANNEL_INTERNAL ichan; /* XXX bogus */ + HAL_CAL_LIST *curCal = ahp->ah_cal_curr; + HAL_BOOL isCalDone; + int i; + + if (curCal == AH_NULL) + return AH_FALSE; + + ichan.calValid = 0; + for (i = 0; i < init_cal_count; i++) { + /* Reset this Cal */ + ar5416ResetMeasurement(ah, curCal); + /* Poll for offset calibration complete */ + if (!ath_hal_wait(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL, 0)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Cal %d failed to finish in 100ms.\n", + __func__, curCal->calData->calType); + /* Re-initialize list pointers for periodic cals */ + cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL; + return AH_FALSE; + } + /* Run this cal */ + ar5416DoCalibration(ah, &ichan, ahp->ah_rxchainmask, + curCal, &isCalDone); + if (!isCalDone) + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: init cal %d did not complete.\n", + __func__, curCal->calData->calType); + if (curCal->calNext != AH_NULL) + curCal = curCal->calNext; + } + + /* Re-initialize list pointers for periodic cals */ + cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL; + return AH_TRUE; +} +#endif + +/* + * Initialize Calibration infrastructure. + */ +HAL_BOOL +ar5416InitCal(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + HAL_CHANNEL_INTERNAL *ichan; + + ichan = ath_hal_checkchannel(ah, chan); + HALASSERT(ichan != AH_NULL); + + if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + /* Enable Rx Filter Cal */ + OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_FLTR_CAL); + + /* Clear the carrier leak cal bit */ + OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + + /* kick off the cal */ + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); + + /* Poll for offset calibration complete */ + if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: offset calibration failed to complete in 1ms; " + "noisy environment?\n", __func__); + return AH_FALSE; + } + + /* Set the cl cal bit and rerun the cal a 2nd time */ + /* Enable Rx Filter Cal */ + OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_FLTR_CAL); + + OS_REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + } + + /* Calibrate the AGC */ + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); + + /* Poll for offset calibration complete */ + if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: offset calibration did not complete in 1ms; " + "noisy environment?\n", __func__); + return AH_FALSE; + } + + /* + * Do NF calibration after DC offset and other CALs. + * Per system engineers, noise floor value can sometimes be 20 dB + * higher than normal value if DC offset and noise floor cal are + * triggered at the same time. + */ + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + + /* Initialize list pointers */ + cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL; + + /* + * Enable IQ, ADC Gain, ADC DC Offset Cals + */ + if (AR_SREV_SOWL_10_OR_LATER(ah)) { + /* Setup all non-periodic, init time only calibrations */ + /* XXX: Init DC Offset not working yet */ +#if 0 + if (ar5416IsCalSupp(ah, chan, ADC_DC_INIT_CAL)) { + INIT_CAL(&cal->adcDcCalInitData); + INSERT_CAL(cal, &cal->adcDcCalInitData); + } + /* Initialize current pointer to first element in list */ + cal->cal_curr = cal->cal_list; + + if (cal->ah_cal_curr != AH_NULL && !ar5416RunInitCals(ah, 0)) + return AH_FALSE; +#endif + } + + /* If Cals are supported, add them to list via INIT/INSERT_CAL */ + if (ar5416IsCalSupp(ah, chan, ADC_GAIN_CAL)) { + INIT_CAL(&cal->adcGainCalData); + INSERT_CAL(cal, &cal->adcGainCalData); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: enable ADC Gain Calibration.\n", __func__); + } + if (ar5416IsCalSupp(ah, chan, ADC_DC_CAL)) { + INIT_CAL(&cal->adcDcCalData); + INSERT_CAL(cal, &cal->adcDcCalData); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: enable ADC DC Calibration.\n", __func__); + } + if (ar5416IsCalSupp(ah, chan, IQ_MISMATCH_CAL)) { + INIT_CAL(&cal->iqCalData); + INSERT_CAL(cal, &cal->iqCalData); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: enable IQ Calibration.\n", __func__); + } + /* Initialize current pointer to first element in list */ + cal->cal_curr = cal->cal_list; + + /* Kick off measurements for the first cal */ + if (cal->cal_curr != AH_NULL) + ar5416ResetMeasurement(ah, cal->cal_curr); + + /* Mark all calibrations on this channel as being invalid */ + ichan->calValid = 0; + + return AH_TRUE; +} + +/* + * Entry point for upper layers to restart current cal. + * Reset the calibration valid bit in channel. + */ +HAL_BOOL +ar5416ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); + HAL_CAL_LIST *currCal = cal->cal_curr; + + if (!AR_SREV_SOWL_10_OR_LATER(ah)) + return AH_FALSE; + if (currCal == AH_NULL) + return AH_FALSE; + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->channel, chan->channelFlags); + return AH_FALSE; + } + /* + * Expected that this calibration has run before, post-reset. + * Current state should be done + */ + if (currCal->calState != CAL_DONE) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Calibration state incorrect, %d\n", + __func__, currCal->calState); + return AH_FALSE; + } + + /* Verify Cal is supported on this channel */ + if (!ar5416IsCalSupp(ah, chan, currCal->calData->calType)) + return AH_FALSE; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: Resetting Cal %d state for channel %u/0x%x\n", + __func__, currCal->calData->calType, chan->channel, + chan->channelFlags); + + /* Disable cal validity in channel */ + ichan->calValid &= ~currCal->calData->calType; + currCal->calState = CAL_WAITING; + + return AH_TRUE; +} + +/* + * Recalibrate the lower PHY chips to account for temperature/environment + * changes. + */ +static void +ar5416DoCalibration(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan, + uint8_t rxchainmask, HAL_CAL_LIST *currCal, HAL_BOOL *isCalDone) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + + /* Cal is assumed not done until explicitly set below */ + *isCalDone = AH_FALSE; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: %s Calibration, state %d, calValid 0x%x\n", + __func__, currCal->calData->calName, currCal->calState, + ichan->calValid); + + /* Calibration in progress. */ + if (currCal->calState == CAL_RUNNING) { + /* Check to see if it has finished. */ + if (!(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_CAL)) { + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: sample %d of %d finished\n", + __func__, cal->calSamples, + currCal->calData->calNumSamples); + /* + * Collect measurements for active chains. + */ + currCal->calData->calCollect(ah); + if (++cal->calSamples >= currCal->calData->calNumSamples) { + int i, numChains = 0; + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + if (rxchainmask & (1 << i)) + numChains++; + } + /* + * Process accumulated data + */ + currCal->calData->calPostProc(ah, numChains); + + /* Calibration has finished. */ + ichan->calValid |= currCal->calData->calType; + currCal->calState = CAL_DONE; + *isCalDone = AH_TRUE; + } else { + /* + * Set-up to collect of another sub-sample. + */ + ar5416SetupMeasurement(ah, currCal); + } + } + } else if (!(ichan->calValid & currCal->calData->calType)) { + /* If current cal is marked invalid in channel, kick it off */ + ar5416ResetMeasurement(ah, currCal); + } +} + +/* + * Internal interface to schedule periodic calibration work. + */ +HAL_BOOL +ar5416PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan, + u_int rxchainmask, HAL_BOOL longcal, HAL_BOOL *isCalDone) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + HAL_CAL_LIST *currCal = cal->cal_curr; + HAL_CHANNEL_INTERNAL *ichan; + + OS_MARK(ah, AH_MARK_PERCAL, chan->channel); + + *isCalDone = AH_TRUE; + + /* Invalid channel check */ + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->channel, chan->channelFlags); + return AH_FALSE; + } + + /* + * For given calibration: + * 1. Call generic cal routine + * 2. When this cal is done (isCalDone) if we have more cals waiting + * (eg after reset), mask this to upper layers by not propagating + * isCalDone if it is set to TRUE. + * Instead, change isCalDone to FALSE and setup the waiting cal(s) + * to be run. + */ + if (currCal != AH_NULL && + (currCal->calState == CAL_RUNNING || + currCal->calState == CAL_WAITING)) { + ar5416DoCalibration(ah, ichan, rxchainmask, currCal, isCalDone); + if (*isCalDone == AH_TRUE) { + cal->cal_curr = currCal = currCal->calNext; + if (currCal->calState == CAL_WAITING) { + *isCalDone = AH_FALSE; + ar5416ResetMeasurement(ah, currCal); + } + } + } + + /* Do NF cal only at longer intervals */ + if (longcal) { + /* + * Get the value from the previous NF cal + * and update the history buffer. + */ + ar5416GetNf(ah, ichan); + + /* + * Load the NF from history buffer of the current channel. + * NF is slow time-variant, so it is OK to use a + * historical value. + */ + ar5416LoadNF(ah, AH_PRIVATE(ah)->ah_curchan); + + /* start NF calibration, without updating BB NF register*/ + ar5416StartNFCal(ah); + + if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) { + /* report up and clear internal state */ + chan->channelFlags |= CHANNEL_CW_INT; + ichan->channelFlags &= ~CHANNEL_CW_INT; + } + } + return AH_TRUE; +} + +/* + * Recalibrate the lower PHY chips to account for temperature/environment + * changes. + */ +HAL_BOOL +ar5416PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + HAL_CAL_LIST *curCal = cal->cal_curr; + + if (curCal != AH_NULL && curCal->calData->calType == IQ_MISMATCH_CAL) { + return ar5416PerCalibrationN(ah, chan, ahp->ah_rx_chainmask, + AH_TRUE, isIQdone); + } else { + HAL_BOOL isCalDone; + + *isIQdone = AH_FALSE; + return ar5416PerCalibrationN(ah, chan, ahp->ah_rx_chainmask, + AH_TRUE, &isCalDone); + } +} + +static HAL_BOOL +ar5416GetEepromNoiseFloorThresh(struct ath_hal *ah, + const HAL_CHANNEL_INTERNAL *chan, int16_t *nft) +{ + switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) { + case CHANNEL_A: + case CHANNEL_A_HT20: + case CHANNEL_A_HT40PLUS: + case CHANNEL_A_HT40MINUS: + ath_hal_eepromGet(ah, AR_EEP_NFTHRESH_5, nft); + break; + case CHANNEL_B: + case CHANNEL_G: + case CHANNEL_G_HT20: + case CHANNEL_G_HT40PLUS: + case CHANNEL_G_HT40MINUS: + ath_hal_eepromGet(ah, AR_EEP_NFTHRESH_2, nft); + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + return AH_TRUE; +} + +static void +ar5416StartNFCal(struct ath_hal *ah) +{ + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); +} + +static void +ar5416LoadNF(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + static const uint32_t ar5416_cca_regs[] = { + AR_PHY_CCA, + AR_PHY_CH1_CCA, + AR_PHY_CH2_CCA, + AR_PHY_EXT_CCA, + AR_PHY_CH1_EXT_CCA, + AR_PHY_CH2_EXT_CCA + }; + struct ar5212NfCalHist *h; + int i, j; + int32_t val; + uint8_t chainmask; + + /* + * Force NF calibration for all chains. + */ + if (AR_SREV_KITE(ah)) { + /* Kite has only one chain */ + chainmask = 0x9; + } else if (AR_SREV_MERLIN(ah)) { + /* Merlin has only two chains */ + chainmask = 0x1B; + } else { + chainmask = 0x3F; + } + + /* + * Write filtered NF values into maxCCApwr register parameter + * so we can load below. + */ + h = AH5416(ah)->ah_cal.nfCalHist; + for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) + if (chainmask & (1 << i)) { + val = OS_REG_READ(ah, ar5416_cca_regs[i]); + val &= 0xFFFFFE00; + val |= (((uint32_t)(h[i].privNF) << 1) & 0x1ff); + OS_REG_WRITE(ah, ar5416_cca_regs[i], val); + } + + /* Load software filtered NF value into baseband internal minCCApwr variable. */ + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + + /* Wait for load to complete, should be fast, a few 10s of us. */ + for (j = 0; j < 1000; j++) { + if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0) + break; + OS_DELAY(10); + } + + /* + * Restore maxCCAPower register parameter again so that we're not capped + * by the median we just loaded. This will be initial (and max) value + * of next noise floor calibration the baseband does. + */ + for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) + if (chainmask & (1 << i)) { + val = OS_REG_READ(ah, ar5416_cca_regs[i]); + val &= 0xFFFFFE00; + val |= (((uint32_t)(-50) << 1) & 0x1ff); + OS_REG_WRITE(ah, ar5416_cca_regs[i], val); + } +} + +void +ar5416InitNfHistBuff(struct ar5212NfCalHist *h) +{ + int i, j; + + for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { + h[i].currIndex = 0; + h[i].privNF = AR5416_CCA_MAX_GOOD_VALUE; + h[i].invalidNFcount = AR512_NF_CAL_HIST_MAX; + for (j = 0; j < AR512_NF_CAL_HIST_MAX; j ++) + h[i].nfCalBuffer[j] = AR5416_CCA_MAX_GOOD_VALUE; + } +} + +/* + * Update the noise floor buffer as a ring buffer + */ +static void +ar5416UpdateNFHistBuff(struct ar5212NfCalHist *h, int16_t *nfarray) +{ + int i; + + for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { + h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; + + if (++h[i].currIndex >= AR512_NF_CAL_HIST_MAX) + h[i].currIndex = 0; + if (h[i].invalidNFcount > 0) { + if (nfarray[i] < AR5416_CCA_MIN_BAD_VALUE || + nfarray[i] > AR5416_CCA_MAX_HIGH_VALUE) { + h[i].invalidNFcount = AR512_NF_CAL_HIST_MAX; + } else { + h[i].invalidNFcount--; + h[i].privNF = nfarray[i]; + } + } else { + h[i].privNF = ar5212GetNfHistMid(h[i].nfCalBuffer); + } + } +} + +/* + * Read the NF and check it against the noise floor threshhold + */ +static int16_t +ar5416GetNf(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + int16_t nf, nfThresh; + + if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: NF didn't complete in calibration window\n", __func__); + nf = 0; + } else { + /* Finished NF cal, check against threshold */ + int16_t nfarray[NUM_NOISEFLOOR_READINGS] = { 0 }; + + /* TODO - enhance for multiple chains and ext ch */ + ath_hal_getNoiseFloor(ah, nfarray); + nf = nfarray[0]; + if (ar5416GetEepromNoiseFloorThresh(ah, chan, &nfThresh)) { + if (nf > nfThresh) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: noise floor failed detected; " + "detected %d, threshold %d\n", __func__, + nf, nfThresh); + /* + * NB: Don't discriminate 2.4 vs 5Ghz, if this + * happens it indicates a problem regardless + * of the band. + */ + chan->channelFlags |= CHANNEL_CW_INT; + nf = 0; + } + } else { + nf = 0; + } + ar5416UpdateNFHistBuff(AH5416(ah)->ah_cal.nfCalHist, nfarray); + chan->rawNoiseFloor = nf; + } + return nf; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal.h b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal.h new file mode 100644 index 0000000000..124002985b --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_cal.h,v 1.3 2008/11/11 17:43:23 sam Exp $ + */ +#ifndef _ATH_AR5416_CAL_H_ +#define _ATH_AR5416_CAL_H_ + +typedef enum { + ADC_DC_INIT_CAL = 0x1, + ADC_GAIN_CAL = 0x2, + ADC_DC_CAL = 0x4, + IQ_MISMATCH_CAL = 0x8 +} HAL_CAL_TYPE; + +/* Calibrate state */ +typedef enum { + CAL_INACTIVE, + CAL_WAITING, + CAL_RUNNING, + CAL_DONE +} HAL_CAL_STATE; + +typedef union { + uint32_t u; + int32_t s; +} HAL_CAL_SAMPLE; + +#define MIN_CAL_SAMPLES 1 +#define MAX_CAL_SAMPLES 64 +#define INIT_LOG_COUNT 5 +#define PER_MIN_LOG_COUNT 2 +#define PER_MAX_LOG_COUNT 10 + +/* Per Calibration data structure */ +typedef struct per_cal_data { + const char *calName; /* for diagnostics */ + HAL_CAL_TYPE calType; /* Type of calibration */ + uint32_t calNumSamples; /* # SW samples to collect */ + uint32_t calCountMax; /* # HW samples to collect */ + void (*calCollect)(struct ath_hal *); /* Accumulator function */ + /* Post-processing function */ + void (*calPostProc)(struct ath_hal *, uint8_t); +} HAL_PERCAL_DATA; + +/* List structure for calibration data */ +typedef struct cal_list { + struct cal_list *calNext; + HAL_CAL_STATE calState; + const HAL_PERCAL_DATA *calData; +} HAL_CAL_LIST; + +struct ar5416PerCal { + /* + * Periodic calibration state. + */ + HAL_CAL_TYPE suppCals; + HAL_CAL_LIST iqCalData; + HAL_CAL_LIST adcGainCalData; + HAL_CAL_LIST adcDcCalInitData; + HAL_CAL_LIST adcDcCalData; + HAL_CAL_LIST *cal_list; + HAL_CAL_LIST *cal_last; + HAL_CAL_LIST *cal_curr; +#define AR5416_MAX_CHAINS 3 /* XXX dup's eeprom def */ + HAL_CAL_SAMPLE caldata[4][AR5416_MAX_CHAINS]; + int calSamples; + /* + * Noise floor cal histogram support. + * XXX be nice to re-use space in ar5212 + */ +#define AR5416_NUM_NF_READINGS 6 /* (3 chains * (ctl + ext) */ + struct ar5212NfCalHist nfCalHist[AR5416_NUM_NF_READINGS]; +}; + +#define INIT_CAL(_perCal) do { \ + (_perCal)->calState = CAL_WAITING; \ + (_perCal)->calNext = AH_NULL; \ +} while (0) + +#define INSERT_CAL(_cal, _perCal) do { \ + if ((_cal)->cal_last == AH_NULL) { \ + (_cal)->cal_list = (_cal)->cal_last = (_perCal); \ + ((_cal)->cal_last)->calNext = (_perCal); \ + } else { \ + ((_cal)->cal_last)->calNext = (_perCal); \ + (_cal)->cal_last = (_perCal); \ + (_perCal)->calNext = (_cal)->cal_list; \ + } \ +} while (0) + +HAL_BOOL ar5416InitCal(struct ath_hal *ah, HAL_CHANNEL *chan); +HAL_BOOL ar5416PerCalibration(struct ath_hal *, HAL_CHANNEL *, + HAL_BOOL *isIQdone); +HAL_BOOL ar5416PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan, + u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); +HAL_BOOL ar5416ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan); + +void ar5416IQCalCollect(struct ath_hal *ah); +void ar5416IQCalibration(struct ath_hal *ah, uint8_t numChains); +void ar5416AdcGainCalCollect(struct ath_hal *ah); +void ar5416AdcGainCalibration(struct ath_hal *ah, uint8_t numChains); +void ar5416AdcDcCalCollect(struct ath_hal *ah); +void ar5416AdcDcCalibration(struct ath_hal *ah, uint8_t numChains); +void ar5416InitNfHistBuff(struct ar5212NfCalHist *h); +#endif /* _ATH_AR5416_CAL_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal_adcdc.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal_adcdc.c new file mode 100644 index 0000000000..2e580bdd37 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal_adcdc.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_cal_adcdc.c,v 1.2 2008/11/11 17:43:23 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* Adc DC Offset Cal aliases */ +#define totalAdcDcOffsetIOddPhase(i) caldata[0][i].s +#define totalAdcDcOffsetIEvenPhase(i) caldata[1][i].s +#define totalAdcDcOffsetQOddPhase(i) caldata[2][i].s +#define totalAdcDcOffsetQEvenPhase(i) caldata[3][i].s + +void +ar5416AdcDcCalCollect(struct ath_hal *ah) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + int i; + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + cal->totalAdcDcOffsetIOddPhase(i) += (int32_t) + OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + cal->totalAdcDcOffsetIEvenPhase(i) += (int32_t) + OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + cal->totalAdcDcOffsetQOddPhase(i) += (int32_t) + OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + cal->totalAdcDcOffsetQEvenPhase(i) += (int32_t) + OS_REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n", + cal->calSamples, i, + cal->totalAdcDcOffsetIOddPhase(i), + cal->totalAdcDcOffsetIEvenPhase(i), + cal->totalAdcDcOffsetQOddPhase(i), + cal->totalAdcDcOffsetQEvenPhase(i)); + } +} + +void +ar5416AdcDcCalibration(struct ath_hal *ah, uint8_t numChains) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + const HAL_PERCAL_DATA *calData = cal->cal_curr->calData; + uint32_t numSamples; + int i; + + numSamples = (1 << (calData->calCountMax + 5)) * calData->calNumSamples; + for (i = 0; i < numChains; i++) { + uint32_t iOddMeasOffset = cal->totalAdcDcOffsetIOddPhase(i); + uint32_t iEvenMeasOffset = cal->totalAdcDcOffsetIEvenPhase(i); + int32_t qOddMeasOffset = cal->totalAdcDcOffsetQOddPhase(i); + int32_t qEvenMeasOffset = cal->totalAdcDcOffsetQEvenPhase(i); + int32_t qDcMismatch, iDcMismatch; + uint32_t val; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "Starting ADC DC Offset Cal for Chain %d\n", i); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_odd_i = %d\n", + iOddMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_even_i = %d\n", + iEvenMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_odd_q = %d\n", + qOddMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_even_q = %d\n", + qEvenMeasOffset); + + HALASSERT(numSamples); + + iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / + numSamples) & 0x1ff; + qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / + numSamples) & 0x1ff; + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " dc_offset_mismatch_i = 0x%08x\n", iDcMismatch); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " dc_offset_mismatch_q = 0x%08x\n", qDcMismatch); + + val = OS_REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); + val &= 0xc0000fff; + val |= (qDcMismatch << 12) | (iDcMismatch << 21); + OS_REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "ADC DC Offset Cal done for Chain %d\n", i); + } + OS_REG_SET_BIT(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), + AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal_adcgain.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal_adcgain.c new file mode 100644 index 0000000000..ce38b03fd2 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal_adcgain.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_cal_adcgain.c,v 1.2 2008/11/11 17:43:23 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* Adc Gain Cal aliases */ +#define totalAdcIOddPhase(i) caldata[0][i].u +#define totalAdcIEvenPhase(i) caldata[1][i].u +#define totalAdcQOddPhase(i) caldata[2][i].u +#define totalAdcQEvenPhase(i) caldata[3][i].u + +/* + * Collect data from HW to later perform ADC Gain Calibration + */ +void +ar5416AdcGainCalCollect(struct ath_hal *ah) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + int i; + + /* + * Accumulate ADC Gain cal measures for active chains + */ + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + cal->totalAdcIOddPhase(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + cal->totalAdcIEvenPhase(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + cal->totalAdcQOddPhase(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + cal->totalAdcQEvenPhase(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n", + cal->calSamples, i, cal->totalAdcIOddPhase(i), + cal->totalAdcIEvenPhase(i), cal->totalAdcQOddPhase(i), + cal->totalAdcQEvenPhase(i)); + } +} + +/* + * Use HW data to do ADC Gain Calibration + */ +void +ar5416AdcGainCalibration(struct ath_hal *ah, uint8_t numChains) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + uint32_t i; + + for (i = 0; i < numChains; i++) { + uint32_t iOddMeasOffset = cal->totalAdcIOddPhase(i); + uint32_t iEvenMeasOffset = cal->totalAdcIEvenPhase(i); + uint32_t qOddMeasOffset = cal->totalAdcQOddPhase(i); + uint32_t qEvenMeasOffset = cal->totalAdcQEvenPhase(i); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "Start ADC Gain Cal for Chain %d\n", i); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " pwr_meas_odd_i = 0x%08x\n", iOddMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " pwr_meas_even_i = 0x%08x\n", iEvenMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " pwr_meas_odd_q = 0x%08x\n", qOddMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " pwr_meas_even_q = 0x%08x\n", qEvenMeasOffset); + + if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { + uint32_t iGainMismatch = + ((iEvenMeasOffset*32)/iOddMeasOffset) & 0x3f; + uint32_t qGainMismatch = + ((qOddMeasOffset*32)/qEvenMeasOffset) & 0x3f; + uint32_t val; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " gain_mismatch_i = 0x%08x\n", + iGainMismatch); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " gain_mismatch_q = 0x%08x\n", + qGainMismatch); + + val = OS_REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); + val &= 0xfffff000; + val |= (qGainMismatch) | (iGainMismatch << 6); + OS_REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "ADC Gain Cal done for Chain %d\n", i); + } + } + OS_REG_SET_BIT(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), + AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal_iq.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal_iq.c new file mode 100644 index 0000000000..931249e307 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_cal_iq.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_cal_iq.c,v 1.2 2008/11/11 17:43:23 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* IQ Cal aliases */ +#define totalPowerMeasI(i) caldata[0][i].u +#define totalPowerMeasQ(i) caldata[1][i].u +#define totalIqCorrMeas(i) caldata[2][i].s + +/* + * Collect data from HW to later perform IQ Mismatch Calibration + */ +void +ar5416IQCalCollect(struct ath_hal *ah) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + int i; + + /* + * Accumulate IQ cal measures for active chains + */ + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + cal->totalPowerMeasI(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + cal->totalPowerMeasQ(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + cal->totalIqCorrMeas(i) += (int32_t) + OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", + cal->calSamples, i, cal->totalPowerMeasI(i), + cal->totalPowerMeasQ(i), cal->totalIqCorrMeas(i)); + } +} + +/* + * Use HW data to do IQ Mismatch Calibration + */ +void +ar5416IQCalibration(struct ath_hal *ah, uint8_t numChains) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + int i; + + for (i = 0; i < numChains; i++) { + uint32_t powerMeasI = cal->totalPowerMeasI(i); + uint32_t powerMeasQ = cal->totalPowerMeasQ(i); + uint32_t iqCorrMeas = cal->totalIqCorrMeas(i); + uint32_t qCoffDenom, iCoffDenom; + int iqCorrNeg; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "Start IQ Cal and Correction for Chain %d\n", i); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "Orignal: iq_corr_meas = 0x%08x\n", iqCorrMeas); + + iqCorrNeg = 0; + /* iqCorrMeas is always negative. */ + if (iqCorrMeas > 0x80000000) { + iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; + iqCorrNeg = 1; + } + + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_i = 0x%08x\n", + powerMeasI); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_q = 0x%08x\n", + powerMeasQ); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " iqCorrNeg is 0x%08x\n", + iqCorrNeg); + + iCoffDenom = (powerMeasI/2 + powerMeasQ/2)/ 128; + qCoffDenom = powerMeasQ / 64; + /* Protect against divide-by-0 */ + if (powerMeasQ != 0) { + /* IQ corr_meas is already negated if iqcorr_neg == 1 */ + int32_t iCoff = iqCorrMeas/iCoffDenom; + int32_t qCoff = powerMeasI/qCoffDenom - 64; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, " iCoff = 0x%08x\n", + iCoff); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " qCoff = 0x%08x\n", + qCoff); + + /* Negate iCoff if iqCorrNeg == 0 */ + iCoff = iCoff & 0x3f; + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "New: iCoff = 0x%08x\n", iCoff); + + if (iqCorrNeg == 0x0) + iCoff = 0x40 - iCoff; + if (qCoff > 15) + qCoff = 15; + else if (qCoff <= -16) + qCoff = 16; + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " : iCoff = 0x%x qCoff = 0x%x\n", iCoff, qCoff); + + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4_CHAIN(i), + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4_CHAIN(i), + AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "IQ Cal and Correction done for Chain %d\n", i); + } + } + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_eeprom.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_eeprom.c new file mode 100644 index 0000000000..812159f0e4 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_eeprom.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_eeprom.c,v 1.6 2008/11/10 04:08:04 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ah_eeprom_v14.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* + * Read 16 bits of data from offset into *data + */ +HAL_BOOL +ar5416EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) +{ + OS_REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); + if (!ath_hal_wait(ah, AR_EEPROM_STATUS_DATA, + AR_EEPROM_STATUS_DATA_BUSY | AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) + return AH_FALSE; + *data = MS(OS_REG_READ(ah, AR_EEPROM_STATUS_DATA), + AR_EEPROM_STATUS_DATA_VAL); + return AH_TRUE; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_gpio.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_gpio.c new file mode 100644 index 0000000000..0aa284378d --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_gpio.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_gpio.c,v 1.3 2008/11/10 04:08:04 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +#ifdef AH_DEBUG +#include "ah_desc.h" /* NB: for HAL_PHYERR* */ +#endif + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#define AR_NUM_GPIO 6 /* 6 GPIO pins */ +#define AR_GPIO_BIT(_gpio) (1 << _gpio) + +/* + * Configure GPIO Output lines + */ +HAL_BOOL +ar5416GpioCfgOutput(struct ath_hal *ah, uint32_t gpio) +{ + HALASSERT(gpio < AR_NUM_GPIO); + OS_REG_CLR_BIT(ah, AR_GPIO_INTR_OUT, AR_GPIO_BIT(gpio)); + return AH_TRUE; +} + +/* + * Configure GPIO Input lines + */ +HAL_BOOL +ar5416GpioCfgInput(struct ath_hal *ah, uint32_t gpio) +{ + HALASSERT(gpio < AR_NUM_GPIO); + OS_REG_SET_BIT(ah, AR_GPIO_INTR_OUT, AR_GPIO_BIT(gpio)); + return AH_TRUE; +} + +/* + * Once configured for I/O - set output lines + */ +HAL_BOOL +ar5416GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) +{ + uint32_t reg; + + HALASSERT(gpio < AR_NUM_GPIO); + reg = MS(OS_REG_READ(ah, AR_GPIO_INTR_OUT), AR_GPIO_OUT_VAL); + if (val & 1) + reg |= AR_GPIO_BIT(gpio); + else + reg &= ~AR_GPIO_BIT(gpio); + + OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_OUT, AR_GPIO_OUT_VAL, reg); + return AH_TRUE; +} + +/* + * Once configured for I/O - get input lines + */ +uint32_t +ar5416GpioGet(struct ath_hal *ah, uint32_t gpio) +{ + if (gpio >= AR_NUM_GPIO) + return 0xffffffff; + return ((OS_REG_READ(ah, AR_GPIO_IN) & AR_GPIO_BIT(gpio)) >> gpio); +} + +/* + * Set the GPIO Interrupt + */ +void +ar5416GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) +{ + uint32_t val; + + HALASSERT(gpio < AR_NUM_GPIO); + /* XXX bounds check gpio */ + val = MS(OS_REG_READ(ah, AR_GPIO_INTR_OUT), AR_GPIO_INTR_CTRL); + if (ilevel) /* 0 == interrupt on pin high */ + val &= ~AR_GPIO_BIT(gpio); + else /* 1 == interrupt on pin low */ + val |= AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_OUT, AR_GPIO_INTR_CTRL, val); + + /* Change the interrupt mask. */ + val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE), AR_INTR_GPIO); + val |= AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE, AR_INTR_GPIO, val); + + val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK), AR_INTR_GPIO); + val |= AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK, AR_INTR_GPIO, val); +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_interrupts.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_interrupts.c new file mode 100644 index 0000000000..bef7522ce9 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_interrupts.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_interrupts.c,v 1.6 2008/11/10 04:08:04 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" + +/* + * Checks to see if an interrupt is pending on our NIC + * + * Returns: TRUE if an interrupt is pending + * FALSE if not + */ +HAL_BOOL +ar5416IsInterruptPending(struct ath_hal *ah) +{ + uint32_t isr; + /* + * Some platforms trigger our ISR before applying power to + * the card, so make sure the INTPEND is really 1, not 0xffffffff. + */ + isr = OS_REG_READ(ah, AR_INTR_ASYNC_CAUSE); + if (isr != AR_INTR_SPURIOUS && (isr & AR_INTR_MAC_IRQ) != 0) + return AH_TRUE; + + isr = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE); + if (isr != AR_INTR_SPURIOUS && (isr & AR_INTR_SYNC_DEFAULT)) + return AH_TRUE; + + return AH_FALSE; +} + +/* + * Reads the Interrupt Status Register value from the NIC, thus deasserting + * the interrupt line, and returns both the masked and unmasked mapped ISR + * values. The value returned is mapped to abstract the hw-specific bit + * locations in the Interrupt Status Register. + * + * Returns: A hardware-abstracted bitmap of all non-masked-out + * interrupts pending, as well as an unmasked value + */ +HAL_BOOL +ar5416GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) +{ + uint32_t isr, isr0, isr1, sync_cause; + + /* + * Verify there's a mac interrupt and the RTC is on. + */ + if ((OS_REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) && + (OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) == AR_RTC_STATUS_ON) + isr = OS_REG_READ(ah, AR_ISR); + else + isr = 0; + sync_cause = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE); + sync_cause &= AR_INTR_SYNC_DEFAULT; + if (isr == 0 && sync_cause == 0) { + *masked = 0; + return AH_FALSE; + } + + if (isr != 0) { + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t mask2; + + mask2 = 0; + if (isr & AR_ISR_BCNMISC) { + uint32_t isr2 = OS_REG_READ(ah, AR_ISR_S2); + if (isr2 & AR_ISR_S2_TIM) + mask2 |= HAL_INT_TIM; + if (isr2 & AR_ISR_S2_DTIM) + mask2 |= HAL_INT_DTIM; + if (isr2 & AR_ISR_S2_DTIMSYNC) + mask2 |= HAL_INT_DTIMSYNC; + if (isr2 & (AR_ISR_S2_CABEND )) + mask2 |= HAL_INT_CABEND; + if (isr2 & AR_ISR_S2_GTT) + mask2 |= HAL_INT_GTT; + if (isr2 & AR_ISR_S2_CST) + mask2 |= HAL_INT_CST; + if (isr2 & AR_ISR_S2_TSFOOR) + mask2 |= HAL_INT_TSFOOR; + } + + isr = OS_REG_READ(ah, AR_ISR_RAC); + if (isr == 0xffffffff) { + *masked = 0; + return AH_FALSE;; + } + + *masked = isr & HAL_INT_COMMON; + if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) + *masked |= HAL_INT_RX; + if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | AR_ISR_TXEOL)) { + *masked |= HAL_INT_TX; + isr0 = OS_REG_READ(ah, AR_ISR_S0_S); + ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXOK); + ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXDESC); + isr1 = OS_REG_READ(ah, AR_ISR_S1_S); + ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXERR); + ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXEOL); + } + + /* Interrupt Mitigation on AR5416 */ +#ifdef AR5416_INT_MITIGATION + if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) + *masked |= HAL_INT_RX; + if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM)) + *masked |= HAL_INT_TX; +#endif + *masked |= mask2; + } + if (sync_cause != 0) { + if (sync_cause & (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) { + *masked |= HAL_INT_FATAL; + } + if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RADM CPL timeout\n", + __func__); + OS_REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); + OS_REG_WRITE(ah, AR_RC, 0); + *masked |= HAL_INT_FATAL; + } + /* + * On fatal errors collect ISR state for debugging. + */ + if (*masked & HAL_INT_FATAL) { + AH_PRIVATE(ah)->ah_fatalState[0] = isr; + AH_PRIVATE(ah)->ah_fatalState[1] = sync_cause; + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: fatal error, ISR_RAC 0x%x SYNC_CAUSE 0x%x\n", + __func__, isr, sync_cause); + } + + OS_REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); + /* NB: flush write */ + (void) OS_REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); + } + return AH_TRUE; +} + +/* + * Atomically enables NIC interrupts. Interrupts are passed in + * via the enumerated bitmask in ints. + */ +HAL_INT +ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t omask = ahp->ah_maskReg; + uint32_t mask,mask2; + + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n", + __func__, omask, ints); + + if (omask & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + (void) OS_REG_READ(ah, AR_IER); + + OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); + (void) OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE); + + OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); + (void) OS_REG_READ(ah, AR_INTR_SYNC_ENABLE); + } + + mask = ints & HAL_INT_COMMON; + mask2 = 0; + + if (ints & HAL_INT_TX) { + if (ahp->ah_txOkInterruptMask) + mask |= AR_IMR_TXOK; + if (ahp->ah_txErrInterruptMask) + mask |= AR_IMR_TXERR; + if (ahp->ah_txDescInterruptMask) + mask |= AR_IMR_TXDESC; + if (ahp->ah_txEolInterruptMask) + mask |= AR_IMR_TXEOL; + } + if (ints & HAL_INT_RX) + mask |= AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXDESC; +#ifdef AR5416_INT_MITIGATION + /* + * Overwrite default mask if Interrupt mitigation + * is specified for AR5416 + */ + mask = ints & HAL_INT_COMMON; + if (ints & HAL_INT_TX) + mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM; + if (ints & HAL_INT_RX) + mask |= AR_IMR_RXERR | AR_IMR_RXMINTR | AR_IMR_RXINTM; +#endif + if (ints & (HAL_INT_BMISC)) { + mask |= AR_IMR_BCNMISC; + if (ints & HAL_INT_TIM) + mask2 |= AR_IMR_S2_TIM; + if (ints & HAL_INT_DTIM) + mask2 |= AR_IMR_S2_DTIM; + if (ints & HAL_INT_DTIMSYNC) + mask2 |= AR_IMR_S2_DTIMSYNC; + if (ints & HAL_INT_CABEND) + mask2 |= (AR_IMR_S2_CABEND ); + if (ints & HAL_INT_GTT) + mask2 |= AR_IMR_S2_GTT; + if (ints & HAL_INT_CST) + mask2 |= AR_IMR_S2_CST; + if (ints & HAL_INT_TSFOOR) + mask2 |= AR_IMR_S2_TSFOOR; + } + + /* Write the new IMR and store off our SW copy. */ + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask); + OS_REG_WRITE(ah, AR_IMR, mask); + mask = OS_REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM | + AR_IMR_S2_DTIM | + AR_IMR_S2_DTIMSYNC | + AR_IMR_S2_CABEND | + AR_IMR_S2_CABTO | + AR_IMR_S2_TSFOOR | + AR_IMR_S2_GTT | + AR_IMR_S2_CST); + OS_REG_WRITE(ah, AR_IMR_S2, mask | mask2); + + ahp->ah_maskReg = ints; + + /* Re-enable interrupts if they were enabled before. */ + if (ints & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE); + + OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, AR_INTR_MAC_IRQ); + OS_REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); + + OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT); + OS_REG_WRITE(ah, AR_INTR_SYNC_MASK, AR_INTR_SYNC_DEFAULT); + } + + return omask; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_keycache.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_keycache.c new file mode 100644 index 0000000000..cb8ad71db4 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_keycache.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_keycache.c,v 1.3 2008/11/10 04:08:04 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5416/ar5416.h" + +static const int keyType[] = { + 1, /* HAL_CIPHER_WEP */ + 0, /* HAL_CIPHER_AES_OCB */ + 2, /* HAL_CIPHER_AES_CCM */ + 0, /* HAL_CIPHER_CKIP */ + 3, /* HAL_CIPHER_TKIP */ + 0, /* HAL_CIPHER_CLR */ +}; + +/* + * Clear the specified key cache entry and any associated MIC entry. + */ +HAL_BOOL +ar5416ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + + if (ar5212ResetKeyCacheEntry(ah, entry)) { + ahp->ah_keytype[entry] = keyType[HAL_CIPHER_CLR]; + return AH_TRUE; + } else + return AH_FALSE; +} + +/* + * Sets the contents of the specified key cache entry + * and any associated MIC entry. + */ +HAL_BOOL +ar5416SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, + const HAL_KEYVAL *k, const uint8_t *mac, + int xorKey) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + + if (ar5212SetKeyCacheEntry(ah, entry, k, mac, xorKey)) { + ahp->ah_keytype[entry] = keyType[k->kv_type]; + return AH_TRUE; + } else + return AH_FALSE; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_misc.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_misc.c new file mode 100644 index 0000000000..0ed704fd4a --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_misc.c @@ -0,0 +1,499 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_misc.c,v 1.12 2008/11/27 22:30:07 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +#ifdef AH_DEBUG +#include "ah_desc.h" /* NB: for HAL_PHYERR* */ +#endif + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* + * Return the wireless modes (a,b,g,t) supported by hardware. + * + * This value is what is actually supported by the hardware + * and is unaffected by regulatory/country code settings. + * + */ +u_int +ar5416GetWirelessModes(struct ath_hal *ah) +{ + u_int mode; + + mode = ar5212GetWirelessModes(ah); + if (mode & HAL_MODE_11A) + mode |= HAL_MODE_11NA_HT20 + | HAL_MODE_11NA_HT40PLUS + | HAL_MODE_11NA_HT40MINUS + ; + if (mode & HAL_MODE_11G) + mode |= HAL_MODE_11NG_HT20 + | HAL_MODE_11NG_HT40PLUS + | HAL_MODE_11NG_HT40MINUS + ; + return mode; +} + +/* + * Change the LED blinking pattern to correspond to the connectivity + */ +void +ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state) +{ + static const uint32_t ledbits[8] = { + AR_MAC_LED_ASSOC_NONE, /* HAL_LED_INIT */ + AR_MAC_LED_ASSOC_PEND, /* HAL_LED_SCAN */ + AR_MAC_LED_ASSOC_PEND, /* HAL_LED_AUTH */ + AR_MAC_LED_ASSOC_ACTIVE, /* HAL_LED_ASSOC*/ + AR_MAC_LED_ASSOC_ACTIVE, /* HAL_LED_RUN */ + AR_MAC_LED_ASSOC_NONE, + AR_MAC_LED_ASSOC_NONE, + AR_MAC_LED_ASSOC_NONE, + }; + uint32_t bits; + + bits = OS_REG_READ(ah, AR_MAC_LED); + bits = (bits &~ AR_MAC_LED_MODE) + | SM(AR_MAC_LED_MODE_POWON, AR_MAC_LED_MODE) +#if 1 + | SM(AR_MAC_LED_MODE_NETON, AR_MAC_LED_MODE) +#endif + ; + bits = (bits &~ AR_MAC_LED_ASSOC) + | SM(ledbits[state & 0x7], AR_MAC_LED_ASSOC); + OS_REG_WRITE(ah, AR_MAC_LED, bits); +} + +/* + * Reset the current hardware tsf for stamlme. + */ +void +ar5416ResetTsf(struct ath_hal *ah) +{ + uint32_t v; + int i; + + for (i = 0; i < 10; i++) { + v = OS_REG_READ(ah, AR_SLP32_MODE); + if ((v & AR_SLP32_TSF_WRITE_STATUS) == 0) + break; + OS_DELAY(10); + } + OS_REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); +} + +HAL_BOOL +ar5416SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) +{ + return AH_TRUE; +} + +/* Setup decompression for given key index */ +HAL_BOOL +ar5416SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) +{ + return HAL_OK; +} + +/* Setup coverage class */ +void +ar5416SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) +{ +} + +/* + * Return approximation of extension channel busy over an time interval + * 0% (clear) -> 100% (busy) + * + */ +uint32_t +ar5416Get11nExtBusy(struct ath_hal *ah) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + uint32_t busy; /* percentage */ + uint32_t cycleCount, ctlBusy, extBusy; + + ctlBusy = OS_REG_READ(ah, AR_RCCNT); + extBusy = OS_REG_READ(ah, AR_EXTRCCNT); + cycleCount = OS_REG_READ(ah, AR_CCCNT); + + if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cycleCount) { + /* + * Cycle counter wrap (or initial call); it's not possible + * to accurately calculate a value because the registers + * right shift rather than wrap--so punt and return 0. + */ + busy = 0; + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycle counter wrap. ExtBusy = 0\n", + __func__); + + } else { + uint32_t cycleDelta = cycleCount - ahp->ah_cycleCount; + uint32_t ctlBusyDelta = ctlBusy - ahp->ah_ctlBusy; + uint32_t extBusyDelta = extBusy - ahp->ah_extBusy; + uint32_t ctlClearDelta = 0; + + /* Compute control channel rxclear. + * The cycle delta may be less than the control channel delta. + * This could be solved by freezing the timers (or an atomic read, + * if one was available). Checking for the condition should be + * sufficient. + */ + if (cycleDelta > ctlBusyDelta) { + ctlClearDelta = cycleDelta - ctlBusyDelta; + } + + /* Compute ratio of extension channel busy to control channel clear + * as an approximation to extension channel cleanliness. + * + * According to the hardware folks, ext rxclear is undefined + * if the ctrl rxclear is de-asserted (i.e. busy) + */ + if (ctlClearDelta) { + busy = (extBusyDelta * 100) / ctlClearDelta; + } else { + busy = 100; + } + if (busy > 100) { + busy = 100; + } +#if 0 + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycleDelta 0x%x, ctlBusyDelta 0x%x, " + "extBusyDelta 0x%x, ctlClearDelta 0x%x, " + "busy %d\n", + __func__, cycleDelta, ctlBusyDelta, extBusyDelta, ctlClearDelta, busy); +#endif + } + + ahp->ah_cycleCount = cycleCount; + ahp->ah_ctlBusy = ctlBusy; + ahp->ah_extBusy = extBusy; + + return busy; +} + +/* + * Configure 20/40 operation + * + * 20/40 = joint rx clear (control and extension) + * 20 = rx clear (control) + * + * - NOTE: must stop MAC (tx) and requeue 40 MHz packets as 20 MHz when changing + * from 20/40 => 20 only + */ +void +ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode) +{ + uint32_t macmode; + + /* Configure MAC for 20/40 operation */ + if (mode == HAL_HT_MACMODE_2040) { + macmode = AR_2040_JOINED_RX_CLEAR; + } else { + macmode = 0; + } + OS_REG_WRITE(ah, AR_2040_MODE, macmode); +} + +/* + * Get Rx clear (control/extension channel) + * + * Returns active low (busy) for ctrl/ext channel + * Owl 2.0 + */ +HAL_HT_RXCLEAR +ar5416Get11nRxClear(struct ath_hal *ah) +{ + HAL_HT_RXCLEAR rxclear = 0; + uint32_t val; + + val = OS_REG_READ(ah, AR_DIAG_SW); + + /* control channel */ + if (val & AR_DIAG_RXCLEAR_CTL_LOW) { + rxclear |= HAL_RX_CLEAR_CTL_LOW; + } + /* extension channel */ + if (val & AR_DIAG_RXCLEAR_CTL_LOW) { + rxclear |= HAL_RX_CLEAR_EXT_LOW; + } + return rxclear; +} + +/* + * Set Rx clear (control/extension channel) + * + * Useful for forcing the channel to appear busy for + * debugging/diagnostics + * Owl 2.0 + */ +void +ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear) +{ + /* control channel */ + if (rxclear & HAL_RX_CLEAR_CTL_LOW) { + OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW); + } else { + OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW); + } + /* extension channel */ + if (rxclear & HAL_RX_CLEAR_EXT_LOW) { + OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW); + } else { + OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW); + } +} + +HAL_STATUS +ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t *result) +{ + switch (type) { + case HAL_CAP_BB_HANG: + switch (capability) { + case HAL_BB_HANG_RIFS: + return AR_SREV_SOWL(ah) ? HAL_OK : HAL_ENOTSUPP; + case HAL_BB_HANG_DFS: + return AR_SREV_SOWL(ah) ? HAL_OK : HAL_ENOTSUPP; + case HAL_BB_HANG_RX_CLEAR: + return AR_SREV_MERLIN(ah) ? HAL_OK : HAL_ENOTSUPP; + } + break; + case HAL_CAP_MAC_HANG: + return ((ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCI) || + (ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCIE) || + AR_SREV_SOWL(ah)) ? + HAL_OK : HAL_ENOTSUPP; + default: + break; + } + return ar5212GetCapability(ah, type, capability, result); +} + +static int ar5416DetectMacHang(struct ath_hal *ah); +static int ar5416DetectBBHang(struct ath_hal *ah); + +HAL_BOOL +ar5416GetDiagState(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + int hangs; + + if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) + return AH_TRUE; + switch (request) { + case HAL_DIAG_EEPROM: + return ath_hal_eepromDiag(ah, request, + args, argsize, result, resultsize); + case HAL_DIAG_CHECK_HANGS: + if (argsize != sizeof(int)) + return AH_FALSE; + hangs = *(const int *) args; + ahp->ah_hangs = 0; + if (hangs & HAL_BB_HANGS) + ahp->ah_hangs |= ar5416DetectBBHang(ah); + /* NB: if BB is hung MAC will be hung too so skip check */ + if (ahp->ah_hangs == 0 && (hangs & HAL_MAC_HANGS)) + ahp->ah_hangs |= ar5416DetectMacHang(ah); + *result = &ahp->ah_hangs; + *resultsize = sizeof(ahp->ah_hangs); + return AH_TRUE; + } + return ar5212GetDiagState(ah, request, + args, argsize, result, resultsize); +} + +typedef struct { + uint32_t dma_dbg_3; + uint32_t dma_dbg_4; + uint32_t dma_dbg_5; + uint32_t dma_dbg_6; +} mac_dbg_regs_t; + +typedef enum { + dcu_chain_state = 0x1, + dcu_complete_state = 0x2, + qcu_state = 0x4, + qcu_fsp_ok = 0x8, + qcu_fsp_state = 0x10, + qcu_stitch_state = 0x20, + qcu_fetch_state = 0x40, + qcu_complete_state = 0x80 +} hal_mac_hangs_t; + +typedef struct { + int states; + uint8_t dcu_chain_state; + uint8_t dcu_complete_state; + uint8_t qcu_state; + uint8_t qcu_fsp_ok; + uint8_t qcu_fsp_state; + uint8_t qcu_stitch_state; + uint8_t qcu_fetch_state; + uint8_t qcu_complete_state; +} hal_mac_hang_check_t; + +static HAL_BOOL +ar5416CompareDbgHang(struct ath_hal *ah, const mac_dbg_regs_t *regs, + const hal_mac_hang_check_t *check) +{ + int found_states; + + found_states = 0; + if (check->states & dcu_chain_state) { + int i; + + for (i = 0; i < 6; i++) { + if (((regs->dma_dbg_4 >> (5*i)) & 0x1f) == + check->dcu_chain_state) + found_states |= dcu_chain_state; + } + for (i = 0; i < 4; i++) { + if (((regs->dma_dbg_5 >> (5*i)) & 0x1f) == + check->dcu_chain_state) + found_states |= dcu_chain_state; + } + } + if (check->states & dcu_complete_state) { + if ((regs->dma_dbg_6 & 0x3) == check->dcu_complete_state) + found_states |= dcu_complete_state; + } + if (check->states & qcu_stitch_state) { + if (((regs->dma_dbg_3 >> 18) & 0xf) == check->qcu_stitch_state) + found_states |= qcu_stitch_state; + } + if (check->states & qcu_fetch_state) { + if (((regs->dma_dbg_3 >> 22) & 0xf) == check->qcu_fetch_state) + found_states |= qcu_fetch_state; + } + if (check->states & qcu_complete_state) { + if (((regs->dma_dbg_3 >> 26) & 0x7) == check->qcu_complete_state) + found_states |= qcu_complete_state; + } + return (found_states == check->states); +} + +#define NUM_STATUS_READS 50 + +static int +ar5416DetectMacHang(struct ath_hal *ah) +{ + static const hal_mac_hang_check_t hang_sig1 = { + .dcu_chain_state = 0x6, + .dcu_complete_state = 0x1, + .states = dcu_chain_state + | dcu_complete_state, + }; + static const hal_mac_hang_check_t hang_sig2 = { + .qcu_stitch_state = 0x9, + .qcu_fetch_state = 0x8, + .qcu_complete_state = 0x4, + .states = qcu_stitch_state + | qcu_fetch_state + | qcu_complete_state, + }; + mac_dbg_regs_t mac_dbg; + int i; + + mac_dbg.dma_dbg_3 = OS_REG_READ(ah, AR_DMADBG_3); + mac_dbg.dma_dbg_4 = OS_REG_READ(ah, AR_DMADBG_4); + mac_dbg.dma_dbg_5 = OS_REG_READ(ah, AR_DMADBG_5); + mac_dbg.dma_dbg_6 = OS_REG_READ(ah, AR_DMADBG_6); + for (i = 1; i <= NUM_STATUS_READS; i++) { + if (mac_dbg.dma_dbg_3 != OS_REG_READ(ah, AR_DMADBG_3) || + mac_dbg.dma_dbg_4 != OS_REG_READ(ah, AR_DMADBG_4) || + mac_dbg.dma_dbg_5 != OS_REG_READ(ah, AR_DMADBG_5) || + mac_dbg.dma_dbg_6 != OS_REG_READ(ah, AR_DMADBG_6)) + return 0; + } + + if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig1)) + return HAL_MAC_HANG_SIG1; + if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig2)) + return HAL_MAC_HANG_SIG2; + + HALDEBUG(ah, HAL_DEBUG_ANY, "%s Found an unknown MAC hang signature " + "DMADBG_3=0x%x DMADBG_4=0x%x DMADBG_5=0x%x DMADBG_6=0x%x\n", + __func__, mac_dbg.dma_dbg_3, mac_dbg.dma_dbg_4, mac_dbg.dma_dbg_5, + mac_dbg.dma_dbg_6); + + return HAL_MAC_HANG_UNKNOWN; +} + +/* + * Determine if the baseband using the Observation Bus Register + */ +static int +ar5416DetectBBHang(struct ath_hal *ah) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + /* + * Check the PCU Observation Bus 1 register (0x806c) + * NUM_STATUS_READS times + * + * 4 known BB hang signatures - + * [1] bits 8,9,11 are 0. State machine state (bits 25-31) is 0x1E + * [2] bits 8,9 are 1, bit 11 is 0. State machine state + * (bits 25-31) is 0x52 + * [3] bits 8,9 are 1, bit 11 is 0. State machine state + * (bits 25-31) is 0x18 + * [4] bit 10 is 1, bit 11 is 0. WEP state (bits 12-17) is 0x2, + * Rx State (bits 20-24) is 0x7. + */ + static const struct { + uint32_t val; + uint32_t mask; + int code; + } hang_list[] = { + /* Reg Value Reg Mask Hang Code XXX */ + { 0x1E000000, 0x7E000B00, HAL_BB_HANG_DFS }, + { 0x52000B00, 0x7E000B00, HAL_BB_HANG_RIFS }, + { 0x18000B00, 0x7E000B00, HAL_BB_HANG_RX_CLEAR }, + { 0x00702400, 0x7E7FFFEF, HAL_BB_HANG_RX_CLEAR } + }; + uint32_t hang_sig; + int i; + + hang_sig = OS_REG_READ(ah, AR_OBSERV_1); + for (i = 1; i <= NUM_STATUS_READS; i++) { + if (hang_sig != OS_REG_READ(ah, AR_OBSERV_1)) + return 0; + } + for (i = 0; i < N(hang_list); i++) + if ((hang_sig & hang_list[i].mask) == hang_list[i].val) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s BB hang, signature 0x%x, code 0x%x\n", + __func__, hang_sig, hang_list[i].code); + return hang_list[i].code; + } + + HALDEBUG(ah, HAL_DEBUG_ANY, "%s Found an unknown BB hang signature! " + "<0x806c>=0x%x\n", __func__, hang_sig); + + return HAL_BB_HANG_UNKNOWN; +#undef N +} +#undef NUM_STATUS_READS diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_phy.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_phy.c new file mode 100644 index 0000000000..f8f5b2a80c --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_phy.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_phy.c,v 1.4 2008/11/27 22:30:08 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5416/ar5416.h" + +/* shorthands to compact tables for readability */ +#define OFDM IEEE80211_T_OFDM +#define CCK IEEE80211_T_CCK +#define HT IEEE80211_T_HT + +HAL_RATE_TABLE ar5416_11ng_table = { + 28, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80| 2), 0 }, +/* 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80| 4), 1 }, +/* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80|11), 2 }, +/* 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80|22), 3 }, +/* Remove rates 6, 9 from rate ctrl */ +/* 6 Mb */ { AH_FALSE, OFDM, 6000, 0x0b, 0x00, 12, 4 }, +/* 9 Mb */ { AH_FALSE, OFDM, 9000, 0x0f, 0x00, 18, 4 }, +/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, 24, 6 }, +/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 6 }, +/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, 48, 8 }, +/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 8 }, +/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 8 }, +/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 8 }, +/* 6.5 Mb */ { AH_TRUE, HT, 6500, 0x80, 0x00, 0, 8 }, +/* 13 Mb */ { AH_TRUE, HT, 13000, 0x81, 0x00, 1, 8 }, +/*19.5 Mb */ { AH_TRUE, HT, 19500, 0x82, 0x00, 2, 8 }, +/* 26 Mb */ { AH_TRUE, HT, 26000, 0x83, 0x00, 3, 8 }, +/* 39 Mb */ { AH_TRUE, HT, 39000, 0x84, 0x00, 4, 8 }, +/* 52 Mb */ { AH_TRUE, HT, 52000, 0x85, 0x00, 5, 8 }, +/*58.5 Mb */ { AH_TRUE, HT, 58500, 0x86, 0x00, 6, 8 }, +/* 65 Mb */ { AH_TRUE, HT, 65000, 0x87, 0x00, 7, 8 }, +/* 13 Mb */ { AH_TRUE, HT, 13000, 0x88, 0x00, 8, 8 }, +/* 26 Mb */ { AH_TRUE, HT, 26000, 0x89, 0x00, 9, 8 }, +/* 39 Mb */ { AH_TRUE, HT, 39000, 0x8a, 0x00, 10, 8 }, +/* 52 Mb */ { AH_TRUE, HT, 52000, 0x8b, 0x00, 11, 8 }, +/* 78 Mb */ { AH_TRUE, HT, 78000, 0x8c, 0x00, 12, 8 }, +/* 104 Mb */ { AH_TRUE, HT, 104000, 0x8d, 0x00, 13, 8 }, +/* 117 Mb */ { AH_TRUE, HT, 117000, 0x8e, 0x00, 14, 8 }, +/* 130 Mb */ { AH_TRUE, HT, 130000, 0x8f, 0x00, 15, 8 }, + }, +}; + +static HAL_RATE_TABLE ar5416_11na_table = { + 24, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80|12), 0 }, +/* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 0 }, +/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, (0x80|48), 4 }, +/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 8 }, +/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 8 }, +/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 8 }, +/* 6.5 Mb */ { AH_TRUE, HT, 6500, 0x80, 0x00, 0, 8 }, +/* 13 Mb */ { AH_TRUE, HT, 13000, 0x81, 0x00, 1, 8 }, +/*19.5 Mb */ { AH_TRUE, HT, 19500, 0x82, 0x00, 2, 8 }, +/* 26 Mb */ { AH_TRUE, HT, 26000, 0x83, 0x00, 3, 8 }, +/* 39 Mb */ { AH_TRUE, HT, 39000, 0x84, 0x00, 4, 8 }, +/* 52 Mb */ { AH_TRUE, HT, 52000, 0x85, 0x00, 5, 8 }, +/*58.5 Mb */ { AH_TRUE, HT, 58500, 0x86, 0x00, 6, 8 }, +/* 65 Mb */ { AH_TRUE, HT, 65000, 0x87, 0x00, 7, 8 }, +/* 13 Mb */ { AH_TRUE, HT, 13000, 0x88, 0x00, 8, 8 }, +/* 26 Mb */ { AH_TRUE, HT, 26000, 0x89, 0x00, 9, 8 }, +/* 39 Mb */ { AH_TRUE, HT, 39000, 0x8a, 0x00, 10, 8 }, +/* 52 Mb */ { AH_TRUE, HT, 52000, 0x8b, 0x00, 11, 8 }, +/* 78 Mb */ { AH_TRUE, HT, 78000, 0x8c, 0x00, 12, 8 }, +/* 104 Mb */ { AH_TRUE, HT, 104000, 0x8d, 0x00, 13, 8 }, +/* 117 Mb */ { AH_TRUE, HT, 117000, 0x8e, 0x00, 14, 8 }, +/* 130 Mb */ { AH_TRUE, HT, 130000, 0x8f, 0x00, 15, 8 }, + }, +}; + +#undef OFDM +#undef CCK +#undef HT + +const HAL_RATE_TABLE * +ar5416GetRateTable(struct ath_hal *ah, u_int mode) +{ + HAL_RATE_TABLE *rt; + switch (mode) { + case HAL_MODE_11NG_HT20: + case HAL_MODE_11NG_HT40PLUS: + case HAL_MODE_11NG_HT40MINUS: + rt = &ar5416_11ng_table; + break; + case HAL_MODE_11NA_HT20: + case HAL_MODE_11NA_HT40PLUS: + case HAL_MODE_11NA_HT40MINUS: + rt = &ar5416_11na_table; + break; + default: + return ar5212GetRateTable(ah, mode); + } + ath_hal_setupratetable(ah, rt); + return rt; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_power.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_power.c new file mode 100644 index 0000000000..b83b0f8951 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_power.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_power.c,v 1.6 2008/11/11 00:11:30 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" + +/* + * Notify Power Mgt is enabled in self-generated frames. + * If requested, force chip awake. + * + * Returns A_OK if chip is awake or successfully forced awake. + * + * WARNING WARNING WARNING + * There is a problem with the chip where sometimes it will not wake up. + */ +static HAL_BOOL +ar5416SetPowerModeAwake(struct ath_hal *ah, int setChip) +{ +#define POWER_UP_TIME 200000 + uint32_t val; + int i = 0; + + if (setChip) { + /* + * Do a Power-On-Reset if OWL is shutdown + * the NetBSD driver power-cycles the Cardbus slot + * as part of the reset procedure. + */ + if ((OS_REG_READ(ah, AR_RTC_STATUS) + & AR_RTC_PM_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) { + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) + goto bad; + } + + OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); + OS_DELAY(50); /* Give chip the chance to awake */ + + for (i = POWER_UP_TIME / 50; i != 0; i--) { + val = OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; + if (val == AR_RTC_STATUS_ON) + break; + OS_DELAY(50); + OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); + } + bad: + if (i == 0) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n", + __func__, POWER_UP_TIME/1000); +#endif + return AH_FALSE; + } + } + + OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + return AH_TRUE; +#undef POWER_UP_TIME +} + +/* + * Notify Power Mgt is disabled in self-generated frames. + * If requested, force chip to sleep. + */ +static void +ar5416SetPowerModeSleep(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + if (setChip) { + /* Clear the RTC force wake bit to allow the mac to sleep */ + OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); + OS_REG_WRITE(ah, AR_RC, AR_RC_AHB|AR_RC_HOSTIF); + /* Shutdown chip. Active low */ + OS_REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN); + } +} + +/* + * Notify Power Management is enabled in self-generating + * fames. If request, set power mode of chip to + * auto/normal. Duration in units of 128us (1/8 TU). + */ +static void +ar5416SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + + if (setChip) + OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); +} + +/* + * Set power mgt to the requested mode, and conditionally set + * the chip as well + */ +HAL_BOOL +ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) +{ + struct ath_hal_5212 *ahp = AH5212(ah); +#ifdef AH_DEBUG + static const char* modes[] = { + "AWAKE", + "FULL-SLEEP", + "NETWORK SLEEP", + "UNDEFINED" + }; +#endif + int status = AH_TRUE; + if (!setChip) + return AH_TRUE; + + HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__, + modes[ahp->ah_powerMode], modes[mode], setChip ? "set chip " : ""); + switch (mode) { + case HAL_PM_AWAKE: + status = ar5416SetPowerModeAwake(ah, setChip); + break; + case HAL_PM_FULL_SLEEP: + ar5416SetPowerModeSleep(ah, setChip); + break; + case HAL_PM_NETWORK_SLEEP: + ar5416SetPowerModeNetworkSleep(ah, setChip); + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode 0x%x\n", + __func__, mode); + return AH_FALSE; + } + ahp->ah_powerMode = mode; + return status; +} + +/* + * Return the current sleep mode of the chip + */ +HAL_POWER_MODE +ar5416GetPowerMode(struct ath_hal *ah) +{ + int mode = OS_REG_READ(ah, AR_RTC_STATUS); + switch (mode & AR_RTC_PM_STATUS_M) { + case AR_RTC_STATUS_ON: + case AR_RTC_STATUS_WAKEUP: + return HAL_PM_AWAKE; + case AR_RTC_STATUS_SLEEP: + return HAL_PM_NETWORK_SLEEP; + case AR_RTC_STATUS_SHUTDOWN: + return HAL_PM_FULL_SLEEP; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unknown power mode, RTC_STATUS 0x%x\n", + __func__, mode); + return HAL_PM_UNDEFINED; + } +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_recv.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_recv.c new file mode 100644 index 0000000000..e8883737ea --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_recv.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_recv.c,v 1.7 2008/11/11 20:46:06 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_desc.h" +#include "ah_internal.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416desc.h" + +/* + * Start receive at the PCU engine + */ +void +ar5416StartPcuReceive(struct ath_hal *ah) +{ + struct ath_hal_private *ahp = AH_PRIVATE(ah); + + HALDEBUG(ah, HAL_DEBUG_RX, "%s: Start PCU Receive \n", __func__); + ar5212EnableMibCounters(ah); + /* NB: restore current settings */ + ar5416AniReset(ah, ahp->ah_curchan, ahp->ah_opmode, AH_TRUE); + /* + * NB: must do after enabling phy errors to avoid rx + * frames w/ corrupted descriptor status. + */ + OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT); +} + +/* + * Stop receive at the PCU engine + * and abort current frame in PCU + */ +void +ar5416StopPcuReceive(struct ath_hal *ah) +{ + OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT); + + HALDEBUG(ah, HAL_DEBUG_RX, "%s: Stop PCU Receive \n", __func__); + ar5212DisableMibCounters(ah); +} + +/* + * Initialize RX descriptor, by clearing the status and setting + * the size (and any other flags). + */ +HAL_BOOL +ar5416SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds, + uint32_t size, u_int flags) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + HALASSERT((size &~ AR_BufLen) == 0); + + ads->ds_ctl1 = size & AR_BufLen; + if (flags & HAL_RXDESC_INTREQ) + ads->ds_ctl1 |= AR_RxIntrReq; + + /* this should be enough */ + ads->ds_rxstatus8 &= ~AR_RxDone; + + return AH_TRUE; +} + +/* + * Process an RX descriptor, and return the status to the caller. + * Copy some hardware specific items into the software portion + * of the descriptor. + * + * NB: the caller is responsible for validating the memory contents + * of the descriptor (e.g. flushing any cached copy). + */ +HAL_STATUS +ar5416ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, + uint32_t pa, struct ath_desc *nds, uint64_t tsf, + struct ath_rx_status *rs) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + struct ar5416_desc *ands = AR5416DESC(nds); + + if ((ads->ds_rxstatus8 & AR_RxDone) == 0) + return HAL_EINPROGRESS; + /* + * Given the use of a self-linked tail be very sure that the hw is + * done with this descriptor; the hw may have done this descriptor + * once and picked it up again...make sure the hw has moved on. + */ + if ((ands->ds_rxstatus8 & AR_RxDone) == 0 + && OS_REG_READ(ah, AR_RXDP) == pa) + return HAL_EINPROGRESS; + + rs->rs_status = 0; + rs->rs_flags = 0; + + rs->rs_datalen = ads->ds_rxstatus1 & AR_DataLen; + rs->rs_tstamp = ads->AR_RcvTimestamp; + + /* XXX what about KeyCacheMiss? */ + + rs->rs_rssi = MS(ads->ds_rxstatus4, AR_RxRSSICombined); + rs->rs_rssi_ctl[0] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt00); + rs->rs_rssi_ctl[1] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt01); + rs->rs_rssi_ctl[2] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt02); + rs->rs_rssi_ext[0] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt10); + rs->rs_rssi_ext[1] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt11); + rs->rs_rssi_ext[2] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt12); + + if (ads->ds_rxstatus8 & AR_RxKeyIdxValid) + rs->rs_keyix = MS(ads->ds_rxstatus8, AR_KeyIdx); + else + rs->rs_keyix = HAL_RXKEYIX_INVALID; + + /* NB: caller expected to do rate table mapping */ + rs->rs_rate = RXSTATUS_RATE(ah, ads); + rs->rs_more = (ads->ds_rxstatus1 & AR_RxMore) ? 1 : 0; + + rs->rs_isaggr = (ads->ds_rxstatus8 & AR_RxAggr) ? 1 : 0; + rs->rs_moreaggr = (ads->ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0; + rs->rs_antenna = MS(ads->ds_rxstatus3, AR_RxAntenna); + + if (ads->ds_rxstatus3 & AR_GI) + rs->rs_flags |= HAL_RX_GI; + if (ads->ds_rxstatus3 & AR_2040) + rs->rs_flags |= HAL_RX_2040; + + if (ads->ds_rxstatus8 & AR_PreDelimCRCErr) + rs->rs_flags |= HAL_RX_DELIM_CRC_PRE; + if (ads->ds_rxstatus8 & AR_PostDelimCRCErr) + rs->rs_flags |= HAL_RX_DELIM_CRC_POST; + if (ads->ds_rxstatus8 & AR_DecryptBusyErr) + rs->rs_flags |= HAL_RX_DECRYPT_BUSY; + if (ads->ds_rxstatus8 & AR_HiRxChain) + rs->rs_flags |= HAL_RX_HI_RX_CHAIN; + + if ((ads->ds_rxstatus8 & AR_RxFrameOK) == 0) { + /* + * These four bits should not be set together. The + * 5416 spec states a Michael error can only occur if + * DecryptCRCErr not set (and TKIP is used). Experience + * indicates however that you can also get Michael errors + * when a CRC error is detected, but these are specious. + * Consequently we filter them out here so we don't + * confuse and/or complicate drivers. + */ + if (ads->ds_rxstatus8 & AR_CRCErr) + rs->rs_status |= HAL_RXERR_CRC; + else if (ads->ds_rxstatus8 & AR_PHYErr) { + u_int phyerr; + + rs->rs_status |= HAL_RXERR_PHY; + phyerr = MS(ads->ds_rxstatus8, AR_PHYErrCode); + rs->rs_phyerr = phyerr; + } else if (ads->ds_rxstatus8 & AR_DecryptCRCErr) + rs->rs_status |= HAL_RXERR_DECRYPT; + else if (ads->ds_rxstatus8 & AR_MichaelErr) + rs->rs_status |= HAL_RXERR_MIC; + } + + return HAL_OK; +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_reset.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_reset.c new file mode 100644 index 0000000000..74ba497e46 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_reset.c @@ -0,0 +1,2895 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_reset.c,v 1.27 2008/11/27 22:30:08 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ah_eeprom_v14.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#ifdef AH_SUPPORT_AR9280 +#include "ar5416/ar9280.h" +#endif + +/* Eeprom versioning macros. Returns true if the version is equal or newer than the ver specified */ +#define EEP_MINOR(_ah) \ + (AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK) +#define IS_EEP_MINOR_V2(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_2) +#define IS_EEP_MINOR_V3(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_3) + +/* Additional Time delay to wait after activiting the Base band */ +#define BASE_ACTIVATE_DELAY 100 /* 100 usec */ +#define PLL_SETTLE_DELAY 300 /* 300 usec */ +#define RTC_PLL_SETTLE_DELAY 1000 /* 1 ms */ + +static void ar5416InitDMA(struct ath_hal *ah); +static void ar5416InitBB(struct ath_hal *ah, HAL_CHANNEL *chan); +static void ar5416InitIMR(struct ath_hal *ah, HAL_OPMODE opmode); +static void ar5416InitQoS(struct ath_hal *ah); +static void ar5416InitUserSettings(struct ath_hal *ah); + +static HAL_BOOL ar5416SetTransmitPower(struct ath_hal *ah, + HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain); + +#if 0 +static HAL_BOOL ar5416ChannelChange(struct ath_hal *, HAL_CHANNEL *); +#endif +static void ar5416SetDeltaSlope(struct ath_hal *, HAL_CHANNEL_INTERNAL *); +static void ar5416SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan); +#ifdef AH_SUPPORT_AR9280 +static void ar9280SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan); +#endif + +static HAL_BOOL ar5416SetResetPowerOn(struct ath_hal *ah); +static HAL_BOOL ar5416SetReset(struct ath_hal *ah, int type); +static void ar5416InitPLL(struct ath_hal *ah, HAL_CHANNEL *chan); +static HAL_BOOL ar5416SetBoardValues(struct ath_hal *, HAL_CHANNEL_INTERNAL *); +static HAL_BOOL ar5416SetPowerPerRateTable(struct ath_hal *ah, + struct ar5416eeprom *pEepData, + HAL_CHANNEL_INTERNAL *chan, int16_t *ratesArray, + uint16_t cfgCtl, uint16_t AntennaReduction, + uint16_t twiceMaxRegulatoryPower, + uint16_t powerLimit); +static HAL_BOOL ar5416SetPowerCalTable(struct ath_hal *ah, + struct ar5416eeprom *pEepData, + HAL_CHANNEL_INTERNAL *chan, + int16_t *pTxPowerIndexOffset); +static uint16_t ar5416GetMaxEdgePower(uint16_t freq, + CAL_CTL_EDGES *pRdEdgesPower, HAL_BOOL is2GHz); +static void ar5416GetTargetPowers(struct ath_hal *ah, + HAL_CHANNEL_INTERNAL *chan, CAL_TARGET_POWER_HT *powInfo, + uint16_t numChannels, CAL_TARGET_POWER_HT *pNewPower, + uint16_t numRates, HAL_BOOL isHt40Target); +static void ar5416GetTargetPowersLeg(struct ath_hal *ah, + HAL_CHANNEL_INTERNAL *chan, CAL_TARGET_POWER_LEG *powInfo, + uint16_t numChannels, CAL_TARGET_POWER_LEG *pNewPower, + uint16_t numRates, HAL_BOOL isExtTarget); + +static int16_t interpolate(uint16_t target, uint16_t srcLeft, + uint16_t srcRight, int16_t targetLeft, int16_t targetRight); +static void ar5416Set11nRegs(struct ath_hal *ah, HAL_CHANNEL *chan); +static void ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah, + HAL_CHANNEL_INTERNAL *chan, CAL_DATA_PER_FREQ *pRawDataSet, + uint8_t * bChans, uint16_t availPiers, + uint16_t tPdGainOverlap, int16_t *pMinCalPower, + uint16_t * pPdGainBoundaries, uint8_t * pPDADCValues, + uint16_t numXpdGains); +static HAL_BOOL getLowerUpperIndex(uint8_t target, uint8_t *pList, + uint16_t listSize, uint16_t *indexL, uint16_t *indexR); +static HAL_BOOL ar5416FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, + uint8_t *pPwrList, uint8_t *pVpdList, + uint16_t numIntercepts, uint8_t *pRetVpdList); + +/* + * Places the device in and out of reset and then places sane + * values in the registers based on EEPROM config, initialization + * vectors (as determined by the mode), and station configuration + * + * bChannelChange is used to preserve DMA/PCU registers across + * a HW Reset during channel change. + */ +HAL_BOOL +ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, + HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status) +{ +#define N(a) (sizeof (a) / sizeof (a[0])) +#define FAIL(_code) do { ecode = _code; goto bad; } while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *ichan; + uint32_t softLedCfg; + uint32_t saveDefAntenna, saveLedState; + uint32_t macStaId1; + uint16_t rfXpdGain[2]; + u_int modesIndex, freqIndex; + HAL_STATUS ecode; + int i, regWrites = 0; + uint32_t powerVal, rssiThrReg; + uint32_t ackTpcPow, ctsTpcPow, chirpTpcPow; + + OS_MARK(ah, AH_MARK_RESET, bChannelChange); +#define IS(_c,_f) (((_c)->channelFlags & _f) || 0) + if ((IS(chan, CHANNEL_2GHZ) ^ IS(chan, CHANNEL_5GHZ)) == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n", + __func__, chan->channel, chan->channelFlags); + FAIL(HAL_EINVAL); + } + if ((IS(chan, CHANNEL_OFDM) ^ IS(chan, CHANNEL_CCK)) == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; not marked as OFDM or CCK\n", + __func__, chan->channel, chan->channelFlags); + FAIL(HAL_EINVAL); + } +#undef IS + + /* Bring out of sleep mode */ + if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip did not wakeup\n", + __func__); + FAIL(HAL_EIO); + } + + /* + * Map public channel to private. + */ + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->channel, chan->channelFlags); + FAIL(HAL_EINVAL); + } else { + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s: Ch=%u Max=%d Min=%d\n",__func__, + ichan->channel, ichan->maxTxPower, ichan->minTxPower); + } + switch (opmode) { + case HAL_M_STA: + case HAL_M_IBSS: + case HAL_M_HOSTAP: + case HAL_M_MONITOR: + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n", + __func__, opmode); + FAIL(HAL_EINVAL); + break; + } + HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1); + + /* XXX Turn on fast channel change for 5416 */ + /* + * Preserve the bmiss rssi threshold and count threshold + * across resets + */ + rssiThrReg = OS_REG_READ(ah, AR_RSSI_THR); + /* If reg is zero, first time thru set to default val */ + if (rssiThrReg == 0) + rssiThrReg = INIT_RSSI_THR; + + /* + * Preserve the antenna on a channel change + */ + saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA); + if (saveDefAntenna == 0) /* XXX magic constants */ + saveDefAntenna = 1; + + /* Save hardware flag before chip reset clears the register */ + macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & + (AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT); + + /* Save led state from pci config register */ + saveLedState = OS_REG_READ(ah, AR_MAC_LED) & + (AR_MAC_LED_ASSOC | AR_MAC_LED_MODE | + AR_MAC_LED_BLINK_THRESH_SEL | AR_MAC_LED_BLINK_SLOW); + softLedCfg = OS_REG_READ(ah, AR_GPIO_INTR_OUT); + + /* + * Adjust gain parameters before reset if + * there's an outstanding gain updated. + */ + (void) ar5416GetRfgain(ah); + + if (!ar5416ChipReset(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + FAIL(HAL_EIO); + } + + /* Restore bmiss rssi & count thresholds */ + OS_REG_WRITE(ah, AR_RSSI_THR, rssiThrReg); + + /* Setup the indices for the next set of register array writes */ + /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */ + switch (chan->channelFlags & CHANNEL_ALL) { + case CHANNEL_A: + case CHANNEL_A_HT20: + modesIndex = 1; + freqIndex = 1; + break; + case CHANNEL_T: + case CHANNEL_A_HT40PLUS: + case CHANNEL_A_HT40MINUS: + modesIndex = 2; + freqIndex = 1; + break; + case CHANNEL_PUREG: + case CHANNEL_G_HT20: + case CHANNEL_B: /* treat as channel G , no B mode suport in owl */ + modesIndex = 4; + freqIndex = 2; + break; + case CHANNEL_G_HT40PLUS: + case CHANNEL_G_HT40MINUS: + modesIndex = 3; + freqIndex = 2; + break; + case CHANNEL_108G: + modesIndex = 5; + freqIndex = 2; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + FAIL(HAL_EINVAL); + } + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + /* Set correct Baseband to analog shift setting to access analog chips. */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* + * Write addac shifts + */ + OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); +#if 0 + /* NB: only required for Sowl */ + ar5416EepromSetAddac(ah, ichan); +#endif + regWrites = ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_addac, 1, + regWrites); + OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); + + /* XXX Merlin ini fixups */ + /* XXX Merlin 100us delay for shift registers */ + regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, + regWrites); +#ifdef AH_SUPPORT_AR9280 + if (AR_SREV_MERLIN_20_OR_LATER(ah)) { + regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_rxgain, + modesIndex, regWrites); + regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_txgain, + modesIndex, regWrites); + } +#endif + /* XXX Merlin 100us delay for shift registers */ + regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_common, 1, regWrites); + /* Setup 11n MAC/Phy mode registers */ + ar5416Set11nRegs(ah,chan); + /* XXX updated regWrites? */ + ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites); +#ifdef AH_SUPPORT_AR9280 + if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { + /* 5GHz channels w/ Fast Clock use different modal values */ + regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_xmodes, + modesIndex, regWrites); + } +#endif + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_DAG_CTRLCCK=0x%x\n", + __func__, OS_REG_READ(ah,AR_PHY_DAG_CTRLCCK)); + HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_ADC_CTL=0x%x\n", + __func__, OS_REG_READ(ah,AR_PHY_ADC_CTL)); + + /* Set the mute mask to the correct default */ + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) + OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F); + + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) { + /* Clear reg to alllow RX_CLEAR line debug */ + OS_REG_WRITE(ah, AR_PHY_BLUETOOTH, 0); + } + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) { +#ifdef notyet + /* Enable burst prefetch for the data queues */ + OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... ); + /* Enable double-buffering */ + OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS); +#endif + } + + /* Set ADC/DAC select values */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); + + if (AH5416(ah)->ah_rx_chainmask == 0x5 || + AH5416(ah)->ah_tx_chainmask == 0x5) + OS_REG_WRITE(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN); + /* Setup Chain Masks */ + OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, AH5416(ah)->ah_rx_chainmask); + OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, AH5416(ah)->ah_rx_chainmask); + OS_REG_WRITE(ah, AR_SELFGEN_MASK, AH5416(ah)->ah_tx_chainmask); + + /* Setup the transmit power values. */ + if (!ar5416SetTransmitPower(ah, ichan, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error init'ing transmit power\n", __func__); + FAIL(HAL_EIO); + } + + /* Write the analog registers */ + if (!ahp->ah_rfHal->setRfRegs(ah, ichan, freqIndex, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: ar5212SetRfRegs failed\n", __func__); + FAIL(HAL_EIO); + } + + /* Write delta slope for OFDM enabled modes (A, G, Turbo) */ + if (IS_CHAN_OFDM(chan)|| IS_CHAN_HT(chan)) + ar5416SetDeltaSlope(ah, ichan); + +#ifdef AH_SUPPORT_AR9280 + if (AR_SREV_MERLIN_10_OR_LATER(ah)) + ar9280SpurMitigate(ah, ichan); + else +#endif + ar5416SpurMitigate(ah, ichan); + + /* Setup board specific options for EEPROM version 3 */ + if (!ar5416SetBoardValues(ah, ichan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error setting board options\n", __func__); + FAIL(HAL_EIO); + } + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr)); + OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4) + | macStaId1 + | AR_STA_ID1_RTS_USE_DEF + | ahp->ah_staId1Defaults + ); + ar5212SetOperatingMode(ah, opmode); + + /* Set Venice BSSID mask according to current state */ + OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask)); + OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4)); + + /* Restore previous led state */ + OS_REG_WRITE(ah, AR_MAC_LED, OS_REG_READ(ah, AR_MAC_LED) | saveLedState); + /* Restore soft Led state to GPIO */ + OS_REG_WRITE(ah, AR_GPIO_INTR_OUT, softLedCfg); + + /* Restore previous antenna */ + OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); + + /* then our BSSID */ + OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); + OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4)); + + /* Restore bmiss rssi & count thresholds */ + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); + + OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */ + + if (!ar5212SetChannel(ah, ichan)) + FAIL(HAL_EIO); + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + /* Set 1:1 QCU to DCU mapping for all queues */ + for (i = 0; i < AR_NUM_DCU; i++) + OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); + + ahp->ah_intrTxqs = 0; + for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++) + ar5212ResetTxQueue(ah, i); + + ar5416InitIMR(ah, opmode); + ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1); + ar5416InitQoS(ah); + ar5416InitUserSettings(ah); + + /* + * disable seq number generation in hw + */ + OS_REG_WRITE(ah, AR_STA_ID1, + OS_REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); + + ar5416InitDMA(ah); + + /* + * program OBS bus to see MAC interrupts + */ + OS_REG_WRITE(ah, AR_OBS, 8); + +#ifdef AR5416_INT_MITIGATION + OS_REG_WRITE(ah, AR_MIRT, 0); + OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); + OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); +#endif + + ar5416InitBB(ah, chan); + + /* Setup compression registers */ + ar5212SetCompRegs(ah); /* XXX not needed? */ + + /* + * 5416 baseband will check the per rate power table + * and select the lower of the two + */ + ackTpcPow = 63; + ctsTpcPow = 63; + chirpTpcPow = 63; + powerVal = SM(ackTpcPow, AR_TPC_ACK) | + SM(ctsTpcPow, AR_TPC_CTS) | + SM(chirpTpcPow, AR_TPC_CHIRP); + OS_REG_WRITE(ah, AR_TPC, powerVal); + + if (!ar5416InitCal(ah, chan)) + FAIL(HAL_ESELFTEST); + + AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */ + + if (bChannelChange) { + if (!(ichan->privFlags & CHANNEL_DFS)) + ichan->privFlags &= ~CHANNEL_INTERFERENCE; + chan->channelFlags = ichan->channelFlags; + chan->privFlags = ichan->privFlags; + chan->maxRegTxPower = ichan->maxRegTxPower; + chan->maxTxPower = ichan->maxTxPower; + chan->minTxPower = ichan->minTxPower; + } + + HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__); + + OS_MARK(ah, AH_MARK_RESET_DONE, 0); + + return AH_TRUE; +bad: + OS_MARK(ah, AH_MARK_RESET_DONE, ecode); + if (*status) + *status = ecode; + return AH_FALSE; +#undef FAIL +#undef N +} + +#if 0 +/* + * This channel change evaluates whether the selected hardware can + * perform a synthesizer-only channel change (no reset). If the + * TX is not stopped, or the RFBus cannot be granted in the given + * time, the function returns false as a reset is necessary + */ +HAL_BOOL +ar5416ChannelChange(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + uint32_t ulCount; + uint32_t data, synthDelay, qnum; + uint16_t rfXpdGain[4]; + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *ichan; + + /* + * Map public channel to private. + */ + ichan = ath_hal_checkchannel(ah, chan); + + /* TX must be stopped or RF Bus grant will not work */ + for (qnum = 0; qnum < AH_PRIVATE(ah)->ah_caps.halTotalQueues; qnum++) { + if (ar5212NumTxPending(ah, qnum)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: frames pending on queue %d\n", __func__, qnum); + return AH_FALSE; + } + } + + /* + * Kill last Baseband Rx Frame - Request analog bus grant + */ + OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_REQUEST); + if (!ath_hal_wait(ah, AR_PHY_RFBUS_GNT, AR_PHY_RFBUS_GRANT_EN, AR_PHY_RFBUS_GRANT_EN)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: could not kill baseband rx\n", + __func__); + return AH_FALSE; + } + + ar5416Set11nRegs(ah, chan); /* NB: setup 5416-specific regs */ + + /* Change the synth */ + if (!ar5212SetChannel(ah, ichan)) + return AH_FALSE; + + /* Setup the transmit power values. */ + if (!ar5416SetTransmitPower(ah, ichan, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error init'ing transmit power\n", __func__); + return AH_FALSE; + } + + /* + * Wait for the frequency synth to settle (synth goes on + * via PHY_ACTIVE_EN). Read the phy active delay register. + * Value is in 100ns increments. + */ + data = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; + if (IS_CHAN_CCK(ichan)) { + synthDelay = (4 * data) / 22; + } else { + synthDelay = data / 10; + } + + OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY); + + /* Release the RFBus Grant */ + OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); + + /* Write delta slope for OFDM enabled modes (A, G, Turbo) */ + if (IS_CHAN_OFDM(ichan)|| IS_CHAN_HT(chan)) { + if (ahp->ah_eeprom.ee_version >= AR_EEPROM_VER5_3 && + !IS_CHAN_B(chan)) + ar5212SetSpurMitigation(ah, ichan); + ar5416SetDeltaSlope(ah, ichan); + } + + /* XXX spur mitigation for Melin */ + + /* Copy over internal channel flags to public hal channel */ + + if (!(ichan->privFlags & CHANNEL_DFS)) + ichan->privFlags &= ~CHANNEL_INTERFERENCE; + chan->channelFlags = ichan->channelFlags; + chan->privFlags = ichan->privFlags; + chan->maxRegTxPower = ichan->maxRegTxPower; + chan->maxTxPower = ichan->maxTxPower; + chan->minTxPower = ichan->minTxPower; + AH_PRIVATE(ah)->ah_curchan->ah_channel_time=0; + AH_PRIVATE(ah)->ah_curchan->ah_tsf_last = ar5212GetTsf64(ah); + ar5212TxEnable(ah,AH_TRUE); + return AH_TRUE; +} +#endif + +static void +ar5416InitDMA(struct ath_hal *ah) +{ + + /* + * set AHB_MODE not to do cacheline prefetches + */ + OS_REG_SET_BIT(ah, AR_AHB_MODE, AR_AHB_PREFETCH_RD_EN); + + /* + * let mac dma reads be in 128 byte chunks + */ + OS_REG_WRITE(ah, AR_TXCFG, + (OS_REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK) | AR_TXCFG_DMASZ_128B); + + /* + * let mac dma writes be in 128 byte chunks + */ + OS_REG_WRITE(ah, AR_RXCFG, + (OS_REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK) | AR_RXCFG_DMASZ_128B); + + /* XXX restore TX trigger level */ + + /* + * Setup receive FIFO threshold to hold off TX activities + */ + OS_REG_WRITE(ah, AR_RXFIFO_CFG, 0x200); + + /* + * reduce the number of usable entries in PCU TXBUF to avoid + * wrap around. + */ + OS_REG_WRITE(ah, AR_PCU_TXBUF_CTRL, AR_PCU_TXBUF_CTRL_USABLE_SIZE); +} + +static void +ar5416InitBB(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + uint32_t synthDelay; + + /* + * Wait for the frequency synth to settle (synth goes on + * via AR_PHY_ACTIVE_EN). Read the phy active delay register. + * Value is in 100ns increments. + */ + synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; + if (IS_CHAN_CCK(chan)) { + synthDelay = (4 * synthDelay) / 22; + } else { + synthDelay /= 10; + } + + /* Turn on PLL on 5416 */ + HALDEBUG(ah, HAL_DEBUG_RESET, "%s %s channel\n", + __func__, IS_CHAN_5GHZ(chan) ? "5GHz" : "2GHz"); + ar5416InitPLL(ah, chan); + + /* Activate the PHY (includes baseband activate and synthesizer on) */ + OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + + /* + * If the AP starts the calibration before the base band timeout + * completes we could get rx_clear false triggering. Add an + * extra BASE_ACTIVATE_DELAY usecs to ensure this condition + * does not happen. + */ + if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) { + OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY); + } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) { + OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY); + } else { + OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY); + } +} + +static void +ar5416InitIMR(struct ath_hal *ah, HAL_OPMODE opmode) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + /* + * Setup interrupt handling. Note that ar5212ResetTxQueue + * manipulates the secondary IMR's as queues are enabled + * and disabled. This is done with RMW ops to insure the + * settings we make here are preserved. + */ + ahp->ah_maskReg = AR_IMR_TXERR | AR_IMR_TXURN + | AR_IMR_RXERR | AR_IMR_RXORN + | AR_IMR_BCNMISC; + +#ifdef AR5416_INT_MITIGATION + ahp->ah_maskReg |= AR_IMR_TXINTM | AR_IMR_RXINTM + | AR_IMR_TXMINTR | AR_IMR_RXMINTR; +#else + ahp->ah_maskReg |= AR_IMR_TXOK | AR_IMR_RXOK; +#endif + if (opmode == HAL_M_HOSTAP) + ahp->ah_maskReg |= AR_IMR_MIB; + OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg); + /* Enable bus errors that are OR'd to set the HIUERR bit */ + +#if 0 + OS_REG_WRITE(ah, AR_IMR_S2, + OS_REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT | AR_IMR_S2_CST); +#endif +} + +static void +ar5416InitQoS(struct ath_hal *ah) +{ + /* QoS support */ + OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa); /* XXX magic */ + OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210); /* XXX magic */ + + /* Turn on NOACK Support for QoS packets */ + OS_REG_WRITE(ah, AR_NOACK, + SM(2, AR_NOACK_2BIT_VALUE) | + SM(5, AR_NOACK_BIT_OFFSET) | + SM(0, AR_NOACK_BYTE_OFFSET)); + + /* + * initialize TXOP for all TIDs + */ + OS_REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL); + OS_REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF); + OS_REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF); + OS_REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF); + OS_REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); +} + +static void +ar5416InitUserSettings(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + /* Restore user-specified settings */ + if (ahp->ah_miscMode != 0) + OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + if (ahp->ah_sifstime != (u_int) -1) + ar5212SetSifsTime(ah, ahp->ah_sifstime); + if (ahp->ah_slottime != (u_int) -1) + ar5212SetSlotTime(ah, ahp->ah_slottime); + if (ahp->ah_acktimeout != (u_int) -1) + ar5212SetAckTimeout(ah, ahp->ah_acktimeout); + if (ahp->ah_ctstimeout != (u_int) -1) + ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout); + if (AH_PRIVATE(ah)->ah_diagreg != 0) + OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); +#if 0 /* XXX Todo */ + if (ahp->ah_globaltxtimeout != (u_int) -1) + ar5416SetGlobalTxTimeout(ah, ahp->ah_globaltxtimeout); +#endif +} + +/* + * Places the hardware into reset and then pulls it out of reset + */ +HAL_BOOL +ar5416ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + uint32_t rfMode = 0; + + OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->channel : 0); + /* + * Warm reset is optimistic. + */ + if (AR_SREV_MERLIN_20_OR_LATER(ah) && + ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) + return AH_FALSE; + } else { + if (!ar5416SetResetReg(ah, HAL_RESET_WARM)) + return AH_FALSE; + } + + /* Bring out of sleep mode (AGAIN) */ + if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + + ar5416InitPLL(ah, chan); + + /* + * Perform warm reset before the mode/PLL/turbo registers + * are changed in order to deactivate the radio. Mode changes + * with an active radio can result in corrupted shifts to the + * radio device. + */ + if (chan != AH_NULL) { + /* treat channel B as channel G , no B mode suport in owl */ + rfMode |= (IS_CHAN_G(chan) || IS_CHAN_B(chan)) ? + AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; + if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { + /* phy mode bits for 5GHz channels require Fast Clock */ + rfMode |= AR_PHY_MODE_DYNAMIC + | AR_PHY_MODE_DYN_CCK_DISABLE; + } else if (!AR_SREV_MERLIN_10_OR_LATER(ah)) { + rfMode |= (IS_CHAN_5GHZ(chan)) ? + AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ; + } + OS_REG_WRITE(ah, AR_PHY_MODE, rfMode); + } + return AH_TRUE; +} + +/* + * Delta slope coefficient computation. + * Required for OFDM operation. + */ +static void +ar5416GetDeltaSlopeValues(struct ath_hal *ah, uint32_t coef_scaled, + uint32_t *coef_mantissa, uint32_t *coef_exponent) +{ +#define COEF_SCALE_S 24 + uint32_t coef_exp, coef_man; + /* + * ALGO -> coef_exp = 14-floor(log2(coef)); + * floor(log2(x)) is the highest set bit position + */ + for (coef_exp = 31; coef_exp > 0; coef_exp--) + if ((coef_scaled >> coef_exp) & 0x1) + break; + /* A coef_exp of 0 is a legal bit position but an unexpected coef_exp */ + HALASSERT(coef_exp); + coef_exp = 14 - (coef_exp - COEF_SCALE_S); + + /* + * ALGO -> coef_man = floor(coef* 2^coef_exp+0.5); + * The coefficient is already shifted up for scaling + */ + coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1)); + + *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp); + *coef_exponent = coef_exp - 16; + +#undef COEF_SCALE_S +} + +void +ar5416SetDeltaSlope(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ +#define INIT_CLOCKMHZSCALED 0x64000000 + uint32_t coef_scaled, ds_coef_exp, ds_coef_man; + uint32_t clockMhzScaled = INIT_CLOCKMHZSCALED; + + CHAN_CENTERS centers; + + if (IS_CHAN_TURBO(chan)) + clockMhzScaled *= 2; + /* half and quarter rate can divide the scaled clock by 2 or 4 respectively */ + /* scale for selected channel bandwidth */ + if (IS_CHAN_HALF_RATE(chan)) { + clockMhzScaled = clockMhzScaled >> 1; + } else if (IS_CHAN_QUARTER_RATE(chan)) { + clockMhzScaled = clockMhzScaled >> 2; + } + + /* + * ALGO -> coef = 1e8/fcarrier*fclock/40; + * scaled coef to provide precision for this floating calculation + */ + ar5416GetChannelCenters(ah, chan, ¢ers); + coef_scaled = clockMhzScaled / centers.synth_center; + + ar5416GetDeltaSlopeValues(ah, coef_scaled, &ds_coef_man, &ds_coef_exp); + + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3, + AR_PHY_TIMING3_DSC_MAN, ds_coef_man); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3, + AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); + + /* + * For Short GI, + * scaled coeff is 9/10 that of normal coeff + */ + coef_scaled = (9 * coef_scaled)/10; + + ar5416GetDeltaSlopeValues(ah, coef_scaled, &ds_coef_man, &ds_coef_exp); + + /* for short gi */ + OS_REG_RMW_FIELD(ah, AR_PHY_HALFGI, + AR_PHY_HALFGI_DSC_MAN, ds_coef_man); + OS_REG_RMW_FIELD(ah, AR_PHY_HALFGI, + AR_PHY_HALFGI_DSC_EXP, ds_coef_exp); +#undef INIT_CLOCKMHZSCALED +} + +/* + * Convert to baseband spur frequency given input channel frequency + * and compute register settings below. + */ +#define SPUR_RSSI_THRESH 40 + +static void +ar5416SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, + AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 }; + static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, + AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 }; + static const int inc[4] = { 0, 100, 0, 0 }; + + int bb_spur = AR_NO_SPUR; + int bin, cur_bin; + int spur_freq_sd; + int spur_delta_phase; + int denominator; + int upper, lower, cur_vit_mask; + int tmp, new; + int i; + + int8_t mask_m[123]; + int8_t mask_p[123]; + int8_t mask_amt; + int tmp_mask; + int cur_bb_spur; + HAL_BOOL is2GHz = IS_CHAN_2GHZ(chan); + + OS_MEMZERO(mask_m, sizeof(mask_m)); + OS_MEMZERO(mask_p, sizeof(mask_p)); + + /* + * Need to verify range +/- 9.5 for static ht20, otherwise spur + * is out-of-band and can be ignored. + */ + for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { + cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz); + if (AR_NO_SPUR == cur_bb_spur) + break; + cur_bb_spur = cur_bb_spur - (chan->channel * 10); + if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) { + bb_spur = cur_bb_spur; + break; + } + } + if (AR_NO_SPUR == bb_spur) + return; + + bin = bb_spur * 32; + + tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0)); + new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | + AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | + AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | + AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), new); + + new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | + AR_PHY_SPUR_REG_ENABLE_MASK_PPM | + AR_PHY_SPUR_REG_MASK_RATE_SELECT | + AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | + SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); + OS_REG_WRITE(ah, AR_PHY_SPUR_REG, new); + /* + * Should offset bb_spur by +/- 10 MHz for dynamic 2040 MHz + * config, no offset for HT20. + * spur_delta_phase = bb_spur/40 * 2**21 for static ht20, + * /80 for dyn2040. + */ + spur_delta_phase = ((bb_spur * 524288) / 100) & + AR_PHY_TIMING11_SPUR_DELTA_PHASE; + /* + * in 11A mode the denominator of spur_freq_sd should be 40 and + * it should be 44 in 11G + */ + denominator = IS_CHAN_2GHZ(chan) ? 440 : 400; + spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff; + + new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | + SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | + SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); + OS_REG_WRITE(ah, AR_PHY_TIMING11, new); + + + /* + * ============================================ + * pilot mask 1 [31:0] = +6..-26, no 0 bin + * pilot mask 2 [19:0] = +26..+7 + * + * channel mask 1 [31:0] = +6..-26, no 0 bin + * channel mask 2 [19:0] = +26..+7 + */ + //cur_bin = -26; + cur_bin = -6000; + upper = bin + 100; + lower = bin - 100; + + for (i = 0; i < 4; i++) { + int pilot_mask = 0; + int chan_mask = 0; + int bp = 0; + for (bp = 0; bp < 30; bp++) { + if ((cur_bin > lower) && (cur_bin < upper)) { + pilot_mask = pilot_mask | 0x1 << bp; + chan_mask = chan_mask | 0x1 << bp; + } + cur_bin += 100; + } + cur_bin += inc[i]; + OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); + OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask); + } + + /* ================================================= + * viterbi mask 1 based on channel magnitude + * four levels 0-3 + * - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c) + * [1 2 2 1] for -9.6 or [1 2 1] for +16 + * - enable_mask_ppm, all bins move with freq + * + * - mask_select, 8 bits for rates (reg 67,0x990c) + * - mask_rate_cntl, 8 bits for rates (reg 67,0x990c) + * choose which mask to use mask or mask2 + */ + + /* + * viterbi mask 2 2nd set for per data rate puncturing + * four levels 0-3 + * - mask_select, 8 bits for rates (reg 67) + * - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994) + * [1 2 2 1] for -9.6 or [1 2 1] for +16 + */ + cur_vit_mask = 6100; + upper = bin + 120; + lower = bin - 120; + + for (i = 0; i < 123; i++) { + if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { + if ((abs(cur_vit_mask - bin)) < 75) { + mask_amt = 1; + } else { + mask_amt = 0; + } + if (cur_vit_mask < 0) { + mask_m[abs(cur_vit_mask / 100)] = mask_amt; + } else { + mask_p[cur_vit_mask / 100] = mask_amt; + } + } + cur_vit_mask -= 100; + } + + tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) + | (mask_m[48] << 26) | (mask_m[49] << 24) + | (mask_m[50] << 22) | (mask_m[51] << 20) + | (mask_m[52] << 18) | (mask_m[53] << 16) + | (mask_m[54] << 14) | (mask_m[55] << 12) + | (mask_m[56] << 10) | (mask_m[57] << 8) + | (mask_m[58] << 6) | (mask_m[59] << 4) + | (mask_m[60] << 2) | (mask_m[61] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); + + tmp_mask = (mask_m[31] << 28) + | (mask_m[32] << 26) | (mask_m[33] << 24) + | (mask_m[34] << 22) | (mask_m[35] << 20) + | (mask_m[36] << 18) | (mask_m[37] << 16) + | (mask_m[48] << 14) | (mask_m[39] << 12) + | (mask_m[40] << 10) | (mask_m[41] << 8) + | (mask_m[42] << 6) | (mask_m[43] << 4) + | (mask_m[44] << 2) | (mask_m[45] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); + + tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) + | (mask_m[18] << 26) | (mask_m[18] << 24) + | (mask_m[20] << 22) | (mask_m[20] << 20) + | (mask_m[22] << 18) | (mask_m[22] << 16) + | (mask_m[24] << 14) | (mask_m[24] << 12) + | (mask_m[25] << 10) | (mask_m[26] << 8) + | (mask_m[27] << 6) | (mask_m[28] << 4) + | (mask_m[29] << 2) | (mask_m[30] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); + + tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28) + | (mask_m[ 2] << 26) | (mask_m[ 3] << 24) + | (mask_m[ 4] << 22) | (mask_m[ 5] << 20) + | (mask_m[ 6] << 18) | (mask_m[ 7] << 16) + | (mask_m[ 8] << 14) | (mask_m[ 9] << 12) + | (mask_m[10] << 10) | (mask_m[11] << 8) + | (mask_m[12] << 6) | (mask_m[13] << 4) + | (mask_m[14] << 2) | (mask_m[15] << 0); + OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); + + tmp_mask = (mask_p[15] << 28) + | (mask_p[14] << 26) | (mask_p[13] << 24) + | (mask_p[12] << 22) | (mask_p[11] << 20) + | (mask_p[10] << 18) | (mask_p[ 9] << 16) + | (mask_p[ 8] << 14) | (mask_p[ 7] << 12) + | (mask_p[ 6] << 10) | (mask_p[ 5] << 8) + | (mask_p[ 4] << 6) | (mask_p[ 3] << 4) + | (mask_p[ 2] << 2) | (mask_p[ 1] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); + + tmp_mask = (mask_p[30] << 28) + | (mask_p[29] << 26) | (mask_p[28] << 24) + | (mask_p[27] << 22) | (mask_p[26] << 20) + | (mask_p[25] << 18) | (mask_p[24] << 16) + | (mask_p[23] << 14) | (mask_p[22] << 12) + | (mask_p[21] << 10) | (mask_p[20] << 8) + | (mask_p[19] << 6) | (mask_p[18] << 4) + | (mask_p[17] << 2) | (mask_p[16] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); + + tmp_mask = (mask_p[45] << 28) + | (mask_p[44] << 26) | (mask_p[43] << 24) + | (mask_p[42] << 22) | (mask_p[41] << 20) + | (mask_p[40] << 18) | (mask_p[39] << 16) + | (mask_p[38] << 14) | (mask_p[37] << 12) + | (mask_p[36] << 10) | (mask_p[35] << 8) + | (mask_p[34] << 6) | (mask_p[33] << 4) + | (mask_p[32] << 2) | (mask_p[31] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); + + tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) + | (mask_p[59] << 26) | (mask_p[58] << 24) + | (mask_p[57] << 22) | (mask_p[56] << 20) + | (mask_p[55] << 18) | (mask_p[54] << 16) + | (mask_p[53] << 14) | (mask_p[52] << 12) + | (mask_p[51] << 10) | (mask_p[50] << 8) + | (mask_p[49] << 6) | (mask_p[48] << 4) + | (mask_p[47] << 2) | (mask_p[46] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); +} + +#ifdef AH_SUPPORT_AR9280 +#define AR_BASE_FREQ_2GHZ 2300 +#define AR_BASE_FREQ_5GHZ 4900 +#define AR_SPUR_FEEQ_BOUND_HT40 19 +#define AR_SPUR_FEEQ_BOUND_HT20 10 + +static void +ar9280SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan) +{ + static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, + AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 }; + static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, + AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 }; + static int inc[4] = { 0, 100, 0, 0 }; + + int bb_spur = AR_NO_SPUR; + int freq; + int bin, cur_bin; + int bb_spur_off, spur_subchannel_sd; + int spur_freq_sd; + int spur_delta_phase; + int denominator; + int upper, lower, cur_vit_mask; + int tmp, newVal; + int i; + CHAN_CENTERS centers; + + int8_t mask_m[123]; + int8_t mask_p[123]; + int8_t mask_amt; + int tmp_mask; + int cur_bb_spur; + HAL_BOOL is2GHz = IS_CHAN_2GHZ(ichan); + + OS_MEMZERO(&mask_m, sizeof(int8_t) * 123); + OS_MEMZERO(&mask_p, sizeof(int8_t) * 123); + + ar5416GetChannelCenters(ah, ichan, ¢ers); + freq = centers.synth_center; + + /* + * Need to verify range +/- 9.38 for static ht20 and +/- 18.75 for ht40, + * otherwise spur is out-of-band and can be ignored. + */ + for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { + cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz); + /* Get actual spur freq in MHz from EEPROM read value */ + if (is2GHz) { + cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; + } else { + cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; + } + + if (AR_NO_SPUR == cur_bb_spur) + break; + cur_bb_spur = cur_bb_spur - freq; + + if (IS_CHAN_HT40(ichan)) { + if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && + (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { + bb_spur = cur_bb_spur; + break; + } + } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && + (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { + bb_spur = cur_bb_spur; + break; + } + } + + if (AR_NO_SPUR == bb_spur) { +#if 1 + /* + * MRC CCK can interfere with beacon detection and cause deaf/mute. + * Disable MRC CCK for now. + */ + OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); +#else + /* Enable MRC CCK if no spur is found in this channel. */ + OS_REG_SET_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); +#endif + return; + } else { + /* + * For Merlin, spur can break CCK MRC algorithm. Disable CCK MRC if spur + * is found in this channel. + */ + OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); + } + + bin = bb_spur * 320; + + tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0)); + + newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | + AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | + AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | + AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), newVal); + + newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | + AR_PHY_SPUR_REG_ENABLE_MASK_PPM | + AR_PHY_SPUR_REG_MASK_RATE_SELECT | + AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | + SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); + OS_REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); + + /* Pick control or extn channel to cancel the spur */ + if (IS_CHAN_HT40(ichan)) { + if (bb_spur < 0) { + spur_subchannel_sd = 1; + bb_spur_off = bb_spur + 10; + } else { + spur_subchannel_sd = 0; + bb_spur_off = bb_spur - 10; + } + } else { + spur_subchannel_sd = 0; + bb_spur_off = bb_spur; + } + + /* + * spur_delta_phase = bb_spur/40 * 2**21 for static ht20, + * /80 for dyn2040. + */ + if (IS_CHAN_HT40(ichan)) + spur_delta_phase = ((bb_spur * 262144) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; + else + spur_delta_phase = ((bb_spur * 524288) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; + + /* + * in 11A mode the denominator of spur_freq_sd should be 40 and + * it should be 44 in 11G + */ + denominator = IS_CHAN_2GHZ(ichan) ? 44 : 40; + spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; + + newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | + SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | + SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); + OS_REG_WRITE(ah, AR_PHY_TIMING11, newVal); + + /* Choose to cancel between control and extension channels */ + newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; + OS_REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); + + /* + * ============================================ + * Set Pilot and Channel Masks + * + * pilot mask 1 [31:0] = +6..-26, no 0 bin + * pilot mask 2 [19:0] = +26..+7 + * + * channel mask 1 [31:0] = +6..-26, no 0 bin + * channel mask 2 [19:0] = +26..+7 + */ + cur_bin = -6000; + upper = bin + 100; + lower = bin - 100; + + for (i = 0; i < 4; i++) { + int pilot_mask = 0; + int chan_mask = 0; + int bp = 0; + for (bp = 0; bp < 30; bp++) { + if ((cur_bin > lower) && (cur_bin < upper)) { + pilot_mask = pilot_mask | 0x1 << bp; + chan_mask = chan_mask | 0x1 << bp; + } + cur_bin += 100; + } + cur_bin += inc[i]; + OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); + OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask); + } + + /* ================================================= + * viterbi mask 1 based on channel magnitude + * four levels 0-3 + * - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c) + * [1 2 2 1] for -9.6 or [1 2 1] for +16 + * - enable_mask_ppm, all bins move with freq + * + * - mask_select, 8 bits for rates (reg 67,0x990c) + * - mask_rate_cntl, 8 bits for rates (reg 67,0x990c) + * choose which mask to use mask or mask2 + */ + + /* + * viterbi mask 2 2nd set for per data rate puncturing + * four levels 0-3 + * - mask_select, 8 bits for rates (reg 67) + * - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994) + * [1 2 2 1] for -9.6 or [1 2 1] for +16 + */ + cur_vit_mask = 6100; + upper = bin + 120; + lower = bin - 120; + + for (i = 0; i < 123; i++) { + if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { + if ((abs(cur_vit_mask - bin)) < 75) { + mask_amt = 1; + } else { + mask_amt = 0; + } + if (cur_vit_mask < 0) { + mask_m[abs(cur_vit_mask / 100)] = mask_amt; + } else { + mask_p[cur_vit_mask / 100] = mask_amt; + } + } + cur_vit_mask -= 100; + } + + tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) + | (mask_m[48] << 26) | (mask_m[49] << 24) + | (mask_m[50] << 22) | (mask_m[51] << 20) + | (mask_m[52] << 18) | (mask_m[53] << 16) + | (mask_m[54] << 14) | (mask_m[55] << 12) + | (mask_m[56] << 10) | (mask_m[57] << 8) + | (mask_m[58] << 6) | (mask_m[59] << 4) + | (mask_m[60] << 2) | (mask_m[61] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); + + tmp_mask = (mask_m[31] << 28) + | (mask_m[32] << 26) | (mask_m[33] << 24) + | (mask_m[34] << 22) | (mask_m[35] << 20) + | (mask_m[36] << 18) | (mask_m[37] << 16) + | (mask_m[48] << 14) | (mask_m[39] << 12) + | (mask_m[40] << 10) | (mask_m[41] << 8) + | (mask_m[42] << 6) | (mask_m[43] << 4) + | (mask_m[44] << 2) | (mask_m[45] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); + + tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) + | (mask_m[18] << 26) | (mask_m[18] << 24) + | (mask_m[20] << 22) | (mask_m[20] << 20) + | (mask_m[22] << 18) | (mask_m[22] << 16) + | (mask_m[24] << 14) | (mask_m[24] << 12) + | (mask_m[25] << 10) | (mask_m[26] << 8) + | (mask_m[27] << 6) | (mask_m[28] << 4) + | (mask_m[29] << 2) | (mask_m[30] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); + + tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28) + | (mask_m[ 2] << 26) | (mask_m[ 3] << 24) + | (mask_m[ 4] << 22) | (mask_m[ 5] << 20) + | (mask_m[ 6] << 18) | (mask_m[ 7] << 16) + | (mask_m[ 8] << 14) | (mask_m[ 9] << 12) + | (mask_m[10] << 10) | (mask_m[11] << 8) + | (mask_m[12] << 6) | (mask_m[13] << 4) + | (mask_m[14] << 2) | (mask_m[15] << 0); + OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); + + tmp_mask = (mask_p[15] << 28) + | (mask_p[14] << 26) | (mask_p[13] << 24) + | (mask_p[12] << 22) | (mask_p[11] << 20) + | (mask_p[10] << 18) | (mask_p[ 9] << 16) + | (mask_p[ 8] << 14) | (mask_p[ 7] << 12) + | (mask_p[ 6] << 10) | (mask_p[ 5] << 8) + | (mask_p[ 4] << 6) | (mask_p[ 3] << 4) + | (mask_p[ 2] << 2) | (mask_p[ 1] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); + + tmp_mask = (mask_p[30] << 28) + | (mask_p[29] << 26) | (mask_p[28] << 24) + | (mask_p[27] << 22) | (mask_p[26] << 20) + | (mask_p[25] << 18) | (mask_p[24] << 16) + | (mask_p[23] << 14) | (mask_p[22] << 12) + | (mask_p[21] << 10) | (mask_p[20] << 8) + | (mask_p[19] << 6) | (mask_p[18] << 4) + | (mask_p[17] << 2) | (mask_p[16] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); + + tmp_mask = (mask_p[45] << 28) + | (mask_p[44] << 26) | (mask_p[43] << 24) + | (mask_p[42] << 22) | (mask_p[41] << 20) + | (mask_p[40] << 18) | (mask_p[39] << 16) + | (mask_p[38] << 14) | (mask_p[37] << 12) + | (mask_p[36] << 10) | (mask_p[35] << 8) + | (mask_p[34] << 6) | (mask_p[33] << 4) + | (mask_p[32] << 2) | (mask_p[31] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); + + tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) + | (mask_p[59] << 26) | (mask_p[58] << 24) + | (mask_p[57] << 22) | (mask_p[56] << 20) + | (mask_p[55] << 18) | (mask_p[54] << 16) + | (mask_p[53] << 14) | (mask_p[52] << 12) + | (mask_p[51] << 10) | (mask_p[50] << 8) + | (mask_p[49] << 6) | (mask_p[48] << 4) + | (mask_p[47] << 2) | (mask_p[46] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); +} +#endif /* AH_SUPPORT_AR9280 */ + +/* + * Set a limit on the overall output power. Used for dynamic + * transmit power control and the like. + * + * NB: limit is in units of 0.5 dbM. + */ +HAL_BOOL +ar5416SetTxPowerLimit(struct ath_hal *ah, uint32_t limit) +{ + uint16_t dummyXpdGains[2]; + + AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER); + return ar5416SetTransmitPower(ah, AH_PRIVATE(ah)->ah_curchan, + dummyXpdGains); +} + +HAL_BOOL +ar5416GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, uint32_t nchans) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + int16_t minPower, maxPower; + HAL_CHANNEL *chan; + int i; + + /* + * Get Pier table max and min powers. + */ + for (i = 0; i < nchans; i++) { + chan = &chans[i]; + if (ahp->ah_rfHal->getChannelMaxMinPower(ah, chan, &maxPower, &minPower)) { + /* NB: rf code returns 1/4 dBm units, convert */ + chan->maxTxPower = maxPower / 2; + chan->minTxPower = minPower / 2; + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: no min/max power for %u/0x%x\n", + __func__, chan->channel, chan->channelFlags); + chan->maxTxPower = AR5416_MAX_RATE_POWER; + chan->minTxPower = 0; + } + } +#ifdef AH_DEBUG + for (i=0; iah_eeprom; + struct ar5416eeprom *pEepData = &ee->ee_base; + + HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1); + + /* Setup info for the actual eeprom */ + ath_hal_memzero(ratesArray, sizeof(ratesArray)); + cfgCtl = ath_hal_getctl(ah, (HAL_CHANNEL *)chan); + powerLimit = chan->maxRegTxPower * 2; + twiceAntennaReduction = chan->antennaMax; + twiceMaxRegulatoryPower = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit); + pModal = &pEepData->modalHeader[IS_CHAN_2GHZ(chan)]; + HALDEBUG(ah, HAL_DEBUG_RESET, "%s Channel=%u CfgCtl=%u\n", + __func__,chan->channel, cfgCtl ); + + if (IS_EEP_MINOR_V2(ah)) { + ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; + } + + if (!ar5416SetPowerPerRateTable(ah, pEepData, chan, + &ratesArray[0],cfgCtl, + twiceAntennaReduction, + twiceMaxRegulatoryPower, powerLimit)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unable to set tx power per rate table\n", __func__); + return AH_FALSE; + } + + if (!ar5416SetPowerCalTable(ah, pEepData, chan, &txPowerIndexOffset)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set power table\n", + __func__); + return AH_FALSE; + } + + maxPower = AH_MAX(ratesArray[rate6mb], ratesArray[rateHt20_0]); + + if (IS_CHAN_2GHZ(chan)) { + maxPower = AH_MAX(maxPower, ratesArray[rate1l]); + } + + if (IS_CHAN_HT40(chan)) { + maxPower = AH_MAX(maxPower, ratesArray[rateHt40_0]); + } + + ahp->ah_tx6PowerInHalfDbm = maxPower; + AH_PRIVATE(ah)->ah_maxPowerLevel = maxPower; + ahp->ah_txPowerIndexOffset = txPowerIndexOffset; + + /* + * txPowerIndexOffset is set by the SetPowerTable() call - + * adjust the rate table (0 offset if rates EEPROM not loaded) + */ + for (i = 0; i < N(ratesArray); i++) { + ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); + if (ratesArray[i] > AR5416_MAX_RATE_POWER) + ratesArray[i] = AR5416_MAX_RATE_POWER; + } + +#ifdef AH_EEPROM_DUMP + ar5416PrintPowerPerRate(ah, ratesArray); +#endif + + /* Write the OFDM power per rate set */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, + POW_SM(ratesArray[rate18mb], 24) + | POW_SM(ratesArray[rate12mb], 16) + | POW_SM(ratesArray[rate9mb], 8) + | POW_SM(ratesArray[rate6mb], 0) + ); + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, + POW_SM(ratesArray[rate54mb], 24) + | POW_SM(ratesArray[rate48mb], 16) + | POW_SM(ratesArray[rate36mb], 8) + | POW_SM(ratesArray[rate24mb], 0) + ); + + if (IS_CHAN_2GHZ(chan)) { + /* Write the CCK power per rate set */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, + POW_SM(ratesArray[rate2s], 24) + | POW_SM(ratesArray[rate2l], 16) + | POW_SM(ratesArray[rateXr], 8) /* XR target power */ + | POW_SM(ratesArray[rate1l], 0) + ); + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, + POW_SM(ratesArray[rate11s], 24) + | POW_SM(ratesArray[rate11l], 16) + | POW_SM(ratesArray[rate5_5s], 8) + | POW_SM(ratesArray[rate5_5l], 0) + ); + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s AR_PHY_POWER_TX_RATE3=0x%x AR_PHY_POWER_TX_RATE4=0x%x\n", + __func__, OS_REG_READ(ah,AR_PHY_POWER_TX_RATE3), + OS_REG_READ(ah,AR_PHY_POWER_TX_RATE4)); + } + + /* Write the HT20 power per rate set */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, + POW_SM(ratesArray[rateHt20_3], 24) + | POW_SM(ratesArray[rateHt20_2], 16) + | POW_SM(ratesArray[rateHt20_1], 8) + | POW_SM(ratesArray[rateHt20_0], 0) + ); + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, + POW_SM(ratesArray[rateHt20_7], 24) + | POW_SM(ratesArray[rateHt20_6], 16) + | POW_SM(ratesArray[rateHt20_5], 8) + | POW_SM(ratesArray[rateHt20_4], 0) + ); + + if (IS_CHAN_HT40(chan)) { + /* Write the HT40 power per rate set */ + /* Correct PAR difference between HT40 and HT20/LEGACY */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, + POW_SM(ratesArray[rateHt40_3] + ht40PowerIncForPdadc, 24) + | POW_SM(ratesArray[rateHt40_2] + ht40PowerIncForPdadc, 16) + | POW_SM(ratesArray[rateHt40_1] + ht40PowerIncForPdadc, 8) + | POW_SM(ratesArray[rateHt40_0] + ht40PowerIncForPdadc, 0) + ); + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, + POW_SM(ratesArray[rateHt40_7] + ht40PowerIncForPdadc, 24) + | POW_SM(ratesArray[rateHt40_6] + ht40PowerIncForPdadc, 16) + | POW_SM(ratesArray[rateHt40_5] + ht40PowerIncForPdadc, 8) + | POW_SM(ratesArray[rateHt40_4] + ht40PowerIncForPdadc, 0) + ); + /* Write the Dup/Ext 40 power per rate set */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, + POW_SM(ratesArray[rateExtOfdm], 24) + | POW_SM(ratesArray[rateExtCck], 16) + | POW_SM(ratesArray[rateDupOfdm], 8) + | POW_SM(ratesArray[rateDupCck], 0) + ); + } + + /* Write the Power subtraction for dynamic chain changing, for per-packet powertx */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_SUB, + POW_SM(pModal->pwrDecreaseFor3Chain, 6) + | POW_SM(pModal->pwrDecreaseFor2Chain, 0) + ); + return AH_TRUE; +#undef POW_SM +#undef N +} + +/* + * Exported call to check for a recent gain reading and return + * the current state of the thermal calibration gain engine. + */ +HAL_RFGAIN +ar5416GetRfgain(struct ath_hal *ah) +{ + return HAL_RFGAIN_INACTIVE; +} + +/* + * Places all of hardware into reset + */ +HAL_BOOL +ar5416Disable(struct ath_hal *ah) +{ + if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + return ar5416SetResetReg(ah, HAL_RESET_COLD); +} + +/* + * Places the PHY and Radio chips into reset. A full reset + * must be called to leave this state. The PCI/MAC/PCU are + * not placed into reset as we must receive interrupt to + * re-enable the hardware. + */ +HAL_BOOL +ar5416PhyDisable(struct ath_hal *ah) +{ + return ar5416SetResetReg(ah, HAL_RESET_WARM); +} + +/* + * Write the given reset bit mask into the reset register + */ +HAL_BOOL +ar5416SetResetReg(struct ath_hal *ah, uint32_t type) +{ + /* + * Set force wake + */ + OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); + + switch (type) { + case HAL_RESET_POWER_ON: + return ar5416SetResetPowerOn(ah); + break; + case HAL_RESET_WARM: + case HAL_RESET_COLD: + return ar5416SetReset(ah, type); + break; + default: + return AH_FALSE; + } +} + +static HAL_BOOL +ar5416SetResetPowerOn(struct ath_hal *ah) +{ + /* Power On Reset (Hard Reset) */ + + /* + * Set force wake + * + * If the MAC was running, previously calling + * reset will wake up the MAC but it may go back to sleep + * before we can start polling. + * Set force wake stops that + * This must be called before initiating a hard reset. + */ + OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); + + /* + * RTC reset and clear + */ + OS_REG_WRITE(ah, AR_RTC_RESET, 0); + OS_DELAY(20); + OS_REG_WRITE(ah, AR_RTC_RESET, 1); + + /* + * Poll till RTC is ON + */ + if (!ath_hal_wait(ah, AR_RTC_STATUS, AR_RTC_PM_STATUS_M, AR_RTC_STATUS_ON)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RTC not waking up\n", __func__); + return AH_FALSE; + } + + return ar5416SetReset(ah, HAL_RESET_COLD); +} + +static HAL_BOOL +ar5416SetReset(struct ath_hal *ah, int type) +{ + uint32_t tmpReg; + + /* + * Force wake + */ + OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); + + /* + * Reset AHB + */ + tmpReg = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE); + if (tmpReg & (AR_INTR_SYNC_LOCAL_TIMEOUT|AR_INTR_SYNC_RADM_CPL_TIMEOUT)) { + OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); + OS_REG_WRITE(ah, AR_RC, AR_RC_AHB|AR_RC_HOSTIF); + } else { + OS_REG_WRITE(ah, AR_RC, AR_RC_AHB); + } + + /* + * Set Mac(BB,Phy) Warm Reset + */ + switch (type) { + case HAL_RESET_WARM: + OS_REG_WRITE(ah, AR_RTC_RC, AR_RTC_RC_MAC_WARM); + break; + case HAL_RESET_COLD: + OS_REG_WRITE(ah, AR_RTC_RC, AR_RTC_RC_MAC_WARM|AR_RTC_RC_MAC_COLD); + break; + default: + HALASSERT(0); + break; + } + + /* + * Clear resets and force wakeup + */ + OS_REG_WRITE(ah, AR_RTC_RC, 0); + if (!ath_hal_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RTC stuck in MAC reset\n", __func__); + return AH_FALSE; + } + + /* Clear AHB reset */ + OS_REG_WRITE(ah, AR_RC, 0); + + /* Set register and descriptor swapping on + * Bigendian platforms on cold reset + */ +#ifdef __BIG_ENDIAN__ + if (type == HAL_RESET_COLD) { + uint32_t mask; + + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s Applying descriptor swap\n", __func__); + + mask = INIT_CONFIG_STATUS | AR_CFG_SWRD | AR_CFG_SWRG; +#ifndef AH_NEED_DESC_SWAP + mask |= AR_CFG_SWTD; +#endif + OS_REG_WRITE(ah, AR_CFG, LE_READ_4(&mask)); + } +#endif + + ar5416InitPLL(ah, AH_NULL); + + return AH_TRUE; +} + +#ifndef IS_5GHZ_FAST_CLOCK_EN +#define IS_5GHZ_FAST_CLOCK_EN(ah, chan) AH_FALSE +#endif + +static void +ar5416InitPLL(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + uint32_t pll; + + if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV); + + if (chan != AH_NULL && IS_CHAN_HALF_RATE(chan)) { + pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL); + } else if (chan && IS_CHAN_QUARTER_RATE(chan)) { + pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL); + } + if (chan != AH_NULL && IS_CHAN_5GHZ(chan)) { + pll |= SM(0x28, AR_RTC_SOWL_PLL_DIV); + + /* + * PLL WAR for Merlin 2.0/2.1 + * When doing fast clock, set PLL to 0x142c + * Else, set PLL to 0x2850 to prevent reset-to-reset variation + */ + if (AR_SREV_MERLIN_20(ah)) { + if (IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { + pll = 0x142c; + } else { + pll = 0x2850; + } + } + } else { + pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV); + } + } else if (AR_SREV_SOWL_10_OR_LATER(ah)) { + pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV); + + if (chan != AH_NULL && IS_CHAN_HALF_RATE(chan)) { + pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL); + } else if (chan && IS_CHAN_QUARTER_RATE(chan)) { + pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL); + } + if (chan != AH_NULL && IS_CHAN_5GHZ(chan)) { + pll |= SM(0x50, AR_RTC_SOWL_PLL_DIV); + } else { + pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV); + } + } else { + pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2; + + if (chan != AH_NULL && IS_CHAN_HALF_RATE(chan)) { + pll |= SM(0x1, AR_RTC_PLL_CLKSEL); + } else if (chan != AH_NULL && IS_CHAN_QUARTER_RATE(chan)) { + pll |= SM(0x2, AR_RTC_PLL_CLKSEL); + } + if (chan != AH_NULL && IS_CHAN_5GHZ(chan)) { + pll |= SM(0xa, AR_RTC_PLL_DIV); + } else { + pll |= SM(0xb, AR_RTC_PLL_DIV); + } + } + OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); + + /* TODO: + * For multi-band owl, switch between bands by reiniting the PLL. + */ + + OS_DELAY(RTC_PLL_SETTLE_DELAY); + + OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK); +} + +/* + * Read EEPROM header info and program the device for correct operation + * given the channel value. + */ +static HAL_BOOL +ar5416SetBoardValues(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + const HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + const struct ar5416eeprom *eep = &ee->ee_base; + const MODAL_EEP_HEADER *pModal; + int i, regChainOffset; + uint8_t txRxAttenLocal; /* workaround for eeprom versions <= 14.2 */ + + HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1); + pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); + + txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; /* workaround for eeprom versions <= 14.2 */ + + OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + if (AR_SREV_MERLIN(ah)) { + if (i >= 2) break; + } + if (AR_SREV_OWL_20_OR_LATER(ah) && + (AH5416(ah)->ah_rx_chainmask == 0x5 || + AH5416(ah)->ah_tx_chainmask == 0x5) && i != 0) { + /* Regs are swapped from chain 2 to 1 for 5416 2_0 with + * only chains 0 and 2 populated + */ + regChainOffset = (i == 1) ? 0x2000 : 0x1000; + } else { + regChainOffset = i * 0x1000; + } + + OS_REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, pModal->antCtrlChain[i]); + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4 + regChainOffset, + (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4 + regChainOffset) & + ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | + SM(pModal->iqCalICh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | + SM(pModal->iqCalQCh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); + + /* + * Large signal upgrade. + * XXX update + */ + + if ((i == 0) || AR_SREV_OWL_20_OR_LATER(ah)) { + OS_REG_WRITE(ah, AR_PHY_RXGAIN + regChainOffset, + (OS_REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) & ~AR_PHY_RXGAIN_TXRX_ATTEN) | + SM(IS_EEP_MINOR_V3(ah) ? pModal->txRxAttenCh[i] : txRxAttenLocal, + AR_PHY_RXGAIN_TXRX_ATTEN)); + + OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) | + SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN)); + } + } + + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, pModal->switchSettling); + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize); + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_PGA, pModal->pgaDesiredSize); + OS_REG_WRITE(ah, AR_PHY_RF_CTL4, + SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) + | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) + | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) + | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); + + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn); + + if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, + pModal->thresh62); + OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, + pModal->thresh62); + } else { + OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62, + pModal->thresh62); + OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA_THRESH62, + pModal->thresh62); + } + + /* Minor Version Specific application */ + if (IS_EEP_MINOR_V2(ah)) { + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_DATA_START, pModal->txFrameToDataStart); + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_PA_ON, pModal->txFrameToPaOn); + } + + if (IS_EEP_MINOR_V3(ah)) { + if (IS_CHAN_HT40(chan)) { + /* Overwrite switch settling with HT40 value */ + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); + } + + if ((AR_SREV_OWL_20_OR_LATER(ah)) && + ( AH5416(ah)->ah_rx_chainmask == 0x5 || AH5416(ah)->ah_tx_chainmask == 0x5)){ + /* Reg Offsets are swapped for logical mapping */ + OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | + SM(pModal->bswMargin[2], AR_PHY_GAIN_2GHZ_BSW_MARGIN)); + OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | + SM(pModal->bswAtten[2], AR_PHY_GAIN_2GHZ_BSW_ATTEN)); + OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | + SM(pModal->bswMargin[1], AR_PHY_GAIN_2GHZ_BSW_MARGIN)); + OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | + SM(pModal->bswAtten[1], AR_PHY_GAIN_2GHZ_BSW_ATTEN)); + } else { + OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | + SM(pModal->bswMargin[1], AR_PHY_GAIN_2GHZ_BSW_MARGIN)); + OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | + SM(pModal->bswAtten[1], AR_PHY_GAIN_2GHZ_BSW_ATTEN)); + OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | + SM(pModal->bswMargin[2],AR_PHY_GAIN_2GHZ_BSW_MARGIN)); + OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | + SM(pModal->bswAtten[2], AR_PHY_GAIN_2GHZ_BSW_ATTEN)); + } + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, AR_PHY_GAIN_2GHZ_BSW_MARGIN, pModal->bswMargin[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, AR_PHY_GAIN_2GHZ_BSW_ATTEN, pModal->bswAtten[0]); + } + return AH_TRUE; +} + +/* + * Helper functions common for AP/CB/XB + */ + +/* + * ar5416SetPowerPerRateTable + * + * Sets the transmit power in the baseband for the given + * operating channel and mode. + */ +static HAL_BOOL +ar5416SetPowerPerRateTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, + HAL_CHANNEL_INTERNAL *chan, + int16_t *ratesArray, uint16_t cfgCtl, + uint16_t AntennaReduction, + uint16_t twiceMaxRegulatoryPower, + uint16_t powerLimit) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) +/* Local defines to distinguish between extension and control CTL's */ +#define EXT_ADDITIVE (0x8000) +#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE) +#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE) +#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE) + + uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + int i; + int16_t twiceLargestAntenna; + CAL_CTL_DATA *rep; + CAL_TARGET_POWER_LEG targetPowerOfdm, targetPowerCck = {0, {0, 0, 0, 0}}; + CAL_TARGET_POWER_LEG targetPowerOfdmExt = {0, {0, 0, 0, 0}}, targetPowerCckExt = {0, {0, 0, 0, 0}}; + CAL_TARGET_POWER_HT targetPowerHt20, targetPowerHt40 = {0, {0, 0, 0, 0}}; + int16_t scaledPower, minCtlPower; + +#define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */ +#define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */ + static const uint16_t ctlModesFor11a[] = { + CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 + }; + static const uint16_t ctlModesFor11g[] = { + CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 + }; + const uint16_t *pCtlMode; + uint16_t numCtlModes, ctlMode, freq; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + + /* Compute TxPower reduction due to Antenna Gain */ + + twiceLargestAntenna = AH_MAX(AH_MAX(pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[0], + pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[1]), + pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[2]); +#if 0 + /* Turn it back on if we need to calculate per chain antenna gain reduction */ + /* Use only if the expected gain > 6dbi */ + /* Chain 0 is always used */ + twiceLargestAntenna = pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[0]; + + /* Look at antenna gains of Chains 1 and 2 if the TX mask is set */ + if (ahp->ah_tx_chainmask & 0x2) + twiceLargestAntenna = AH_MAX(twiceLargestAntenna, + pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[1]); + + if (ahp->ah_tx_chainmask & 0x4) + twiceLargestAntenna = AH_MAX(twiceLargestAntenna, + pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[2]); +#endif + twiceLargestAntenna = (int16_t)AH_MIN((AntennaReduction) - twiceLargestAntenna, 0); + + /* XXX setup for 5212 use (really used?) */ + ath_hal_eepromSet(ah, + IS_CHAN_2GHZ(chan) ? AR_EEP_ANTGAINMAX_2 : AR_EEP_ANTGAINMAX_5, + twiceLargestAntenna); + + /* + * scaledPower is the minimum of the user input power level and + * the regulatory allowed power level + */ + scaledPower = AH_MIN(powerLimit, twiceMaxRegulatoryPower + twiceLargestAntenna); + + /* Reduce scaled Power by number of chains active to get to per chain tx power level */ + /* TODO: better value than these? */ + switch (owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask)) { + case 1: + break; + case 2: + scaledPower -= pEepData->modalHeader[IS_CHAN_2GHZ(chan)].pwrDecreaseFor2Chain; + break; + case 3: + scaledPower -= pEepData->modalHeader[IS_CHAN_2GHZ(chan)].pwrDecreaseFor3Chain; + break; + default: + return AH_FALSE; /* Unsupported number of chains */ + } + + scaledPower = AH_MAX(0, scaledPower); + + /* Get target powers from EEPROM - our baseline for TX Power */ + if (IS_CHAN_2GHZ(chan)) { + /* Setup for CTL modes */ + numCtlModes = N(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; /* CTL_11B, CTL_11G, CTL_2GHT20 */ + pCtlMode = ctlModesFor11g; + + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPowerCck, + AR5416_NUM_2G_CCK_TARGET_POWERS, &targetPowerCck, 4, AH_FALSE); + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower2G, + AR5416_NUM_2G_20_TARGET_POWERS, &targetPowerOfdm, 4, AH_FALSE); + ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower2GHT20, + AR5416_NUM_2G_20_TARGET_POWERS, &targetPowerHt20, 8, AH_FALSE); + + if (IS_CHAN_HT40(chan)) { + numCtlModes = N(ctlModesFor11g); /* All 2G CTL's */ + + ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower2GHT40, + AR5416_NUM_2G_40_TARGET_POWERS, &targetPowerHt40, 8, AH_TRUE); + /* Get target powers for extension channels */ + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPowerCck, + AR5416_NUM_2G_CCK_TARGET_POWERS, &targetPowerCckExt, 4, AH_TRUE); + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower2G, + AR5416_NUM_2G_20_TARGET_POWERS, &targetPowerOfdmExt, 4, AH_TRUE); + } + } else { + /* Setup for CTL modes */ + numCtlModes = N(ctlModesFor11a) - SUB_NUM_CTL_MODES_AT_5G_40; /* CTL_11A, CTL_5GHT20 */ + pCtlMode = ctlModesFor11a; + + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower5G, + AR5416_NUM_5G_20_TARGET_POWERS, &targetPowerOfdm, 4, AH_FALSE); + ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower5GHT20, + AR5416_NUM_5G_20_TARGET_POWERS, &targetPowerHt20, 8, AH_FALSE); + + if (IS_CHAN_HT40(chan)) { + numCtlModes = N(ctlModesFor11a); /* All 5G CTL's */ + + ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower5GHT40, + AR5416_NUM_5G_40_TARGET_POWERS, &targetPowerHt40, 8, AH_TRUE); + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower5G, + AR5416_NUM_5G_20_TARGET_POWERS, &targetPowerOfdmExt, 4, AH_TRUE); + } + } + + /* + * For MIMO, need to apply regulatory caps individually across dynamically + * running modes: CCK, OFDM, HT20, HT40 + * + * The outer loop walks through each possible applicable runtime mode. + * The inner loop walks through each ctlIndex entry in EEPROM. + * The ctl value is encoded as [7:4] == test group, [3:0] == test mode. + * + */ + for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { + + HAL_BOOL isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || + (pCtlMode[ctlMode] == CTL_2GHT40); + if (isHt40CtlMode) { + freq = centers.ctl_center; + } else if (pCtlMode[ctlMode] & EXT_ADDITIVE) { + freq = centers.ext_center; + } else { + freq = centers.ctl_center; + } + + /* walk through each CTL index stored in EEPROM */ + for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { + uint16_t twiceMinEdgePower; + + /* compare test group from regulatory channel list with test mode from pCtlMode list */ + if ((((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == pEepData->ctlIndex[i]) || + (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == + ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) { + rep = &(pEepData->ctlData[i]); + twiceMinEdgePower = ar5416GetMaxEdgePower(freq, + rep->ctlEdges[owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask) - 1], + IS_CHAN_2GHZ(chan)); + if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { + /* Find the minimum of all CTL edge powers that apply to this channel */ + twiceMaxEdgePower = AH_MIN(twiceMaxEdgePower, twiceMinEdgePower); + } else { + /* specific */ + twiceMaxEdgePower = twiceMinEdgePower; + break; + } + } + } + minCtlPower = (uint8_t)AH_MIN(twiceMaxEdgePower, scaledPower); + /* Apply ctl mode to correct target power set */ + switch(pCtlMode[ctlMode]) { + case CTL_11B: + for (i = 0; i < N(targetPowerCck.tPow2x); i++) { + targetPowerCck.tPow2x[i] = (uint8_t)AH_MIN(targetPowerCck.tPow2x[i], minCtlPower); + } + break; + case CTL_11A: + case CTL_11G: + for (i = 0; i < N(targetPowerOfdm.tPow2x); i++) { + targetPowerOfdm.tPow2x[i] = (uint8_t)AH_MIN(targetPowerOfdm.tPow2x[i], minCtlPower); + } + break; + case CTL_5GHT20: + case CTL_2GHT20: + for (i = 0; i < N(targetPowerHt20.tPow2x); i++) { + targetPowerHt20.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt20.tPow2x[i], minCtlPower); + } + break; + case CTL_11B_EXT: + targetPowerCckExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerCckExt.tPow2x[0], minCtlPower); + break; + case CTL_11A_EXT: + case CTL_11G_EXT: + targetPowerOfdmExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerOfdmExt.tPow2x[0], minCtlPower); + break; + case CTL_5GHT40: + case CTL_2GHT40: + for (i = 0; i < N(targetPowerHt40.tPow2x); i++) { + targetPowerHt40.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt40.tPow2x[i], minCtlPower); + } + break; + default: + return AH_FALSE; + break; + } + } /* end ctl mode checking */ + + /* Set rates Array from collected data */ + ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = ratesArray[rate18mb] = ratesArray[rate24mb] = targetPowerOfdm.tPow2x[0]; + ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; + ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; + ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; + ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; + + for (i = 0; i < N(targetPowerHt20.tPow2x); i++) { + ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; + } + + if (IS_CHAN_2GHZ(chan)) { + ratesArray[rate1l] = targetPowerCck.tPow2x[0]; + ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1]; + ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2]; + ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3]; + } + if (IS_CHAN_HT40(chan)) { + for (i = 0; i < N(targetPowerHt40.tPow2x); i++) { + ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i]; + } + ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; + ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; + ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; + if (IS_CHAN_2GHZ(chan)) { + ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; + } + } + return AH_TRUE; +#undef EXT_ADDITIVE +#undef CTL_11A_EXT +#undef CTL_11G_EXT +#undef CTL_11B_EXT +#undef SUB_NUM_CTL_MODES_AT_5G_40 +#undef SUB_NUM_CTL_MODES_AT_2G_40 +#undef N +} + +/************************************************************************** + * fbin2freq + * + * Get channel value from binary representation held in eeprom + * RETURNS: the frequency in MHz + */ +static uint16_t +fbin2freq(uint8_t fbin, HAL_BOOL is2GHz) +{ + /* + * Reserved value 0xFF provides an empty definition both as + * an fbin and as a frequency - do not convert + */ + if (fbin == AR5416_BCHAN_UNUSED) { + return fbin; + } + + return (uint16_t)((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); +} + +/* + * ar5416GetMaxEdgePower + * + * Find the maximum conformance test limit for the given channel and CTL info + */ +static uint16_t +ar5416GetMaxEdgePower(uint16_t freq, CAL_CTL_EDGES *pRdEdgesPower, HAL_BOOL is2GHz) +{ + uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + int i; + + /* Get the edge power */ + for (i = 0; (i < AR5416_NUM_BAND_EDGES) && (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED) ; i++) { + /* + * If there's an exact channel match or an inband flag set + * on the lower channel use the given rdEdgePower + */ + if (freq == fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) { + twiceMaxEdgePower = MS(pRdEdgesPower[i].tPowerFlag, CAL_CTL_EDGES_POWER); + break; + } else if ((i > 0) && (freq < fbin2freq(pRdEdgesPower[i].bChannel, is2GHz))) { + if (fbin2freq(pRdEdgesPower[i - 1].bChannel, is2GHz) < freq && (pRdEdgesPower[i - 1].tPowerFlag & CAL_CTL_EDGES_FLAG) != 0) { + twiceMaxEdgePower = MS(pRdEdgesPower[i - 1].tPowerFlag, CAL_CTL_EDGES_POWER); + } + /* Leave loop - no more affecting edges possible in this monotonic increasing list */ + break; + } + } + HALASSERT(twiceMaxEdgePower > 0); + return twiceMaxEdgePower; +} + +/************************************************************** + * ar5416GetTargetPowers + * + * Return the rates of target power for the given target power table + * channel, and number of channels + */ +static void +ar5416GetTargetPowers(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, + CAL_TARGET_POWER_HT *powInfo, uint16_t numChannels, + CAL_TARGET_POWER_HT *pNewPower, uint16_t numRates, + HAL_BOOL isHt40Target) +{ + uint16_t clo, chi; + int i; + int matchIndex = -1, lowIndex = -1; + uint16_t freq; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + freq = isHt40Target ? centers.synth_center : centers.ctl_center; + + /* Copy the target powers into the temp channel list */ + if (freq <= fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) { + matchIndex = 0; + } else { + for (i = 0; (i < numChannels) && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) { + if (freq == fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) { + matchIndex = i; + break; + } else if ((freq < fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) && + (freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan)))) + { + lowIndex = i - 1; + break; + } + } + if ((matchIndex == -1) && (lowIndex == -1)) { + HALASSERT(freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan))); + matchIndex = i - 1; + } + } + + if (matchIndex != -1) { + OS_MEMCPY(pNewPower, &powInfo[matchIndex], sizeof(*pNewPower)); + } else { + HALASSERT(lowIndex != -1); + /* + * Get the lower and upper channels, target powers, + * and interpolate between them. + */ + clo = fbin2freq(powInfo[lowIndex].bChannel, IS_CHAN_2GHZ(chan)); + chi = fbin2freq(powInfo[lowIndex + 1].bChannel, IS_CHAN_2GHZ(chan)); + + for (i = 0; i < numRates; i++) { + pNewPower->tPow2x[i] = (uint8_t)interpolate(freq, clo, chi, + powInfo[lowIndex].tPow2x[i], powInfo[lowIndex + 1].tPow2x[i]); + } + } +} +/************************************************************** + * ar5416GetTargetPowersLeg + * + * Return the four rates of target power for the given target power table + * channel, and number of channels + */ +static void +ar5416GetTargetPowersLeg(struct ath_hal *ah, + HAL_CHANNEL_INTERNAL *chan, + CAL_TARGET_POWER_LEG *powInfo, uint16_t numChannels, + CAL_TARGET_POWER_LEG *pNewPower, uint16_t numRates, + HAL_BOOL isExtTarget) +{ + uint16_t clo, chi; + int i; + int matchIndex = -1, lowIndex = -1; + uint16_t freq; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + freq = (isExtTarget) ? centers.ext_center :centers.ctl_center; + + /* Copy the target powers into the temp channel list */ + if (freq <= fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) { + matchIndex = 0; + } else { + for (i = 0; (i < numChannels) && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) { + if (freq == fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) { + matchIndex = i; + break; + } else if ((freq < fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) && + (freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan)))) + { + lowIndex = i - 1; + break; + } + } + if ((matchIndex == -1) && (lowIndex == -1)) { + HALASSERT(freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan))); + matchIndex = i - 1; + } + } + + if (matchIndex != -1) { + OS_MEMCPY(pNewPower, &powInfo[matchIndex], sizeof(*pNewPower)); + } else { + HALASSERT(lowIndex != -1); + /* + * Get the lower and upper channels, target powers, + * and interpolate between them. + */ + clo = fbin2freq(powInfo[lowIndex].bChannel, IS_CHAN_2GHZ(chan)); + chi = fbin2freq(powInfo[lowIndex + 1].bChannel, IS_CHAN_2GHZ(chan)); + + for (i = 0; i < numRates; i++) { + pNewPower->tPow2x[i] = (uint8_t)interpolate(freq, clo, chi, + powInfo[lowIndex].tPow2x[i], powInfo[lowIndex + 1].tPow2x[i]); + } + } +} + +/************************************************************** + * ar5416SetPowerCalTable + * + * Pull the PDADC piers from cal data and interpolate them across the given + * points as well as from the nearest pier(s) to get a power detector + * linear voltage to power level table. + */ +static HAL_BOOL +ar5416SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, HAL_CHANNEL_INTERNAL *chan, int16_t *pTxPowerIndexOffset) +{ + CAL_DATA_PER_FREQ *pRawDataset; + uint8_t *pCalBChans = AH_NULL; + uint16_t pdGainOverlap_t2; + static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES]; + uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK]; + uint16_t numPiers, i, j; + int16_t tMinCalPower; + uint16_t numXpdGain, xpdMask; + uint16_t xpdGainValues[AR5416_NUM_PD_GAINS]; + uint32_t reg32, regOffset, regChainOffset; + + ath_hal_memzero(xpdGainValues, sizeof(xpdGainValues)); + + xpdMask = pEepData->modalHeader[IS_CHAN_2GHZ(chan)].xpdGain; + + if (IS_EEP_MINOR_V2(ah)) { + pdGainOverlap_t2 = pEepData->modalHeader[IS_CHAN_2GHZ(chan)].pdGainOverlap; + } else { + pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); + } + + if (IS_CHAN_2GHZ(chan)) { + pCalBChans = pEepData->calFreqPier2G; + numPiers = AR5416_NUM_2G_CAL_PIERS; + } else { + pCalBChans = pEepData->calFreqPier5G; + numPiers = AR5416_NUM_5G_CAL_PIERS; + } + + numXpdGain = 0; + /* Calculate the value of xpdgains from the xpdGain Mask */ + for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { + if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { + if (numXpdGain >= AR5416_NUM_PD_GAINS) { + HALASSERT(0); + break; + } + xpdGainValues[numXpdGain] = (uint16_t)(AR5416_PD_GAINS_IN_MASK - i); + numXpdGain++; + } + } + + /* Write the detector gain biases and their number */ + OS_REG_WRITE(ah, AR_PHY_TPCRG1, (OS_REG_READ(ah, AR_PHY_TPCRG1) & + ~(AR_PHY_TPCRG1_NUM_PD_GAIN | AR_PHY_TPCRG1_PD_GAIN_1 | AR_PHY_TPCRG1_PD_GAIN_2 | AR_PHY_TPCRG1_PD_GAIN_3)) | + SM(numXpdGain - 1, AR_PHY_TPCRG1_NUM_PD_GAIN) | SM(xpdGainValues[0], AR_PHY_TPCRG1_PD_GAIN_1 ) | + SM(xpdGainValues[1], AR_PHY_TPCRG1_PD_GAIN_2) | SM(xpdGainValues[2], AR_PHY_TPCRG1_PD_GAIN_3)); + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + + if (AR_SREV_OWL_20_OR_LATER(ah) && + ( AH5416(ah)->ah_rx_chainmask == 0x5 || AH5416(ah)->ah_tx_chainmask == 0x5) && (i != 0)) { + /* Regs are swapped from chain 2 to 1 for 5416 2_0 with + * only chains 0 and 2 populated + */ + regChainOffset = (i == 1) ? 0x2000 : 0x1000; + } else { + regChainOffset = i * 0x1000; + } + + if (pEepData->baseEepHeader.txMask & (1 << i)) { + if (IS_CHAN_2GHZ(chan)) { + pRawDataset = pEepData->calPierData2G[i]; + } else { + pRawDataset = pEepData->calPierData5G[i]; + } + + ar5416GetGainBoundariesAndPdadcs(ah, chan, pRawDataset, + pCalBChans, numPiers, + pdGainOverlap_t2, + &tMinCalPower, gainBoundaries, + pdadcValues, numXpdGain); + + if ((i == 0) || AR_SREV_OWL_20_OR_LATER(ah)) { + /* + * Note the pdadc table may not start at 0 dBm power, could be + * negative or greater than 0. Need to offset the power + * values by the amount of minPower for griffin + */ + + OS_REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, + SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | + SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | + SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | + SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | + SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); + } + + /* Write the power values into the baseband power table */ + regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; + + for (j = 0; j < 32; j++) { + reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0) | + ((pdadcValues[4*j + 1] & 0xFF) << 8) | + ((pdadcValues[4*j + 2] & 0xFF) << 16) | + ((pdadcValues[4*j + 3] & 0xFF) << 24) ; + OS_REG_WRITE(ah, regOffset, reg32); + +#ifdef PDADC_DUMP + ath_hal_printf(ah, "PDADC: Chain %d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d |\n", + i, + 4*j, pdadcValues[4*j], + 4*j+1, pdadcValues[4*j + 1], + 4*j+2, pdadcValues[4*j + 2], + 4*j+3, pdadcValues[4*j + 3]); +#endif + regOffset += 4; + } + } + } + *pTxPowerIndexOffset = 0; + + return AH_TRUE; +} + +/************************************************************** + * ar5416GetGainBoundariesAndPdadcs + * + * Uses the data points read from EEPROM to reconstruct the pdadc power table + * Called by ar5416SetPowerCalTable only. + */ +static void +ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah, + HAL_CHANNEL_INTERNAL *chan, CAL_DATA_PER_FREQ *pRawDataSet, + uint8_t * bChans, uint16_t availPiers, + uint16_t tPdGainOverlap, int16_t *pMinCalPower, uint16_t * pPdGainBoundaries, + uint8_t * pPDADCValues, uint16_t numXpdGains) +{ + + int i, j, k; + int16_t ss; /* potentially -ve index for taking care of pdGainOverlap */ + uint16_t idxL, idxR, numPiers; /* Pier indexes */ + + /* filled out Vpd table for all pdGains (chanL) */ + static uint8_t vpdTableL[AR5416_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + + /* filled out Vpd table for all pdGains (chanR) */ + static uint8_t vpdTableR[AR5416_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + + /* filled out Vpd table for all pdGains (interpolated) */ + static uint8_t vpdTableI[AR5416_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + + uint8_t *pVpdL, *pVpdR, *pPwrL, *pPwrR; + uint8_t minPwrT4[AR5416_NUM_PD_GAINS]; + uint8_t maxPwrT4[AR5416_NUM_PD_GAINS]; + int16_t vpdStep; + int16_t tmpVal; + uint16_t sizeCurrVpdTable, maxIndex, tgtIndex; + HAL_BOOL match; + int16_t minDelta = 0; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + + /* Trim numPiers for the number of populated channel Piers */ + for (numPiers = 0; numPiers < availPiers; numPiers++) { + if (bChans[numPiers] == AR5416_BCHAN_UNUSED) { + break; + } + } + + /* Find pier indexes around the current channel */ + match = getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), + bChans, numPiers, &idxL, &idxR); + + if (match) { + /* Directly fill both vpd tables from the matching index */ + for (i = 0; i < numXpdGains; i++) { + minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; + maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; + ar5416FillVpdTable(minPwrT4[i], maxPwrT4[i], pRawDataSet[idxL].pwrPdg[i], + pRawDataSet[idxL].vpdPdg[i], AR5416_PD_GAIN_ICEPTS, vpdTableI[i]); + } + } else { + for (i = 0; i < numXpdGains; i++) { + pVpdL = pRawDataSet[idxL].vpdPdg[i]; + pPwrL = pRawDataSet[idxL].pwrPdg[i]; + pVpdR = pRawDataSet[idxR].vpdPdg[i]; + pPwrR = pRawDataSet[idxR].pwrPdg[i]; + + /* Start Vpd interpolation from the max of the minimum powers */ + minPwrT4[i] = AH_MAX(pPwrL[0], pPwrR[0]); + + /* End Vpd interpolation from the min of the max powers */ + maxPwrT4[i] = AH_MIN(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], pPwrR[AR5416_PD_GAIN_ICEPTS - 1]); + HALASSERT(maxPwrT4[i] > minPwrT4[i]); + + /* Fill pier Vpds */ + ar5416FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrL, pVpdL, AR5416_PD_GAIN_ICEPTS, vpdTableL[i]); + ar5416FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrR, pVpdR, AR5416_PD_GAIN_ICEPTS, vpdTableR[i]); + + /* Interpolate the final vpd */ + for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { + vpdTableI[i][j] = (uint8_t)(interpolate((uint16_t)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), + bChans[idxL], bChans[idxR], vpdTableL[i][j], vpdTableR[i][j])); + } + } + } + *pMinCalPower = (int16_t)(minPwrT4[0] / 2); + + k = 0; /* index for the final table */ + for (i = 0; i < numXpdGains; i++) { + if (i == (numXpdGains - 1)) { + pPdGainBoundaries[i] = (uint16_t)(maxPwrT4[i] / 2); + } else { + pPdGainBoundaries[i] = (uint16_t)((maxPwrT4[i] + minPwrT4[i+1]) / 4); + } + + pPdGainBoundaries[i] = (uint16_t)AH_MIN(AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); + + /* NB: only applies to owl 1.0 */ + if ((i == 0) && !AR_SREV_OWL_20_OR_LATER(ah) ) { + /* + * fix the gain delta, but get a delta that can be applied to min to + * keep the upper power values accurate, don't think max needs to + * be adjusted because should not be at that area of the table? + */ + minDelta = pPdGainBoundaries[0] - 23; + pPdGainBoundaries[0] = 23; + } + else { + minDelta = 0; + } + + /* Find starting index for this pdGain */ + if (i == 0) { + ss = 0; /* for the first pdGain, start from index 0 */ + } else { + /* need overlap entries extrapolated below. */ + ss = (int16_t)((pPdGainBoundaries[i-1] - (minPwrT4[i] / 2)) - tPdGainOverlap + 1 + minDelta); + } + vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); + vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); + /* + *-ve ss indicates need to extrapolate data below for this pdGain + */ + while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { + tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); + pPDADCValues[k++] = (uint8_t)((tmpVal < 0) ? 0 : tmpVal); + ss++; + } + + sizeCurrVpdTable = (uint8_t)((maxPwrT4[i] - minPwrT4[i]) / 2 +1); + tgtIndex = (uint8_t)(pPdGainBoundaries[i] + tPdGainOverlap - (minPwrT4[i] / 2)); + maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; + + while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { + pPDADCValues[k++] = vpdTableI[i][ss++]; + } + + vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - vpdTableI[i][sizeCurrVpdTable - 2]); + vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); + /* + * for last gain, pdGainBoundary == Pmax_t2, so will + * have to extrapolate + */ + if (tgtIndex > maxIndex) { /* need to extrapolate above */ + while ((ss <= tgtIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { + tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + + (ss - maxIndex +1) * vpdStep)); + pPDADCValues[k++] = (uint8_t)((tmpVal > 255) ? 255 : tmpVal); + ss++; + } + } /* extrapolated above */ + } /* for all pdGainUsed */ + + /* Fill out pdGainBoundaries - only up to 2 allowed here, but hardware allows up to 4 */ + while (i < AR5416_PD_GAINS_IN_MASK) { + pPdGainBoundaries[i] = pPdGainBoundaries[i-1]; + i++; + } + + while (k < AR5416_NUM_PDADC_VALUES) { + pPDADCValues[k] = pPDADCValues[k-1]; + k++; + } + return; +} + +/************************************************************** + * getLowerUppderIndex + * + * Return indices surrounding the value in sorted integer lists. + * Requirement: the input list must be monotonically increasing + * and populated up to the list size + * Returns: match is set if an index in the array matches exactly + * or a the target is before or after the range of the array. + */ +HAL_BOOL +getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize, + uint16_t *indexL, uint16_t *indexR) +{ + uint16_t i; + + /* + * Check first and last elements for beyond ordered array cases. + */ + if (target <= pList[0]) { + *indexL = *indexR = 0; + return AH_TRUE; + } + if (target >= pList[listSize-1]) { + *indexL = *indexR = (uint16_t)(listSize - 1); + return AH_TRUE; + } + + /* look for value being near or between 2 values in list */ + for (i = 0; i < listSize - 1; i++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (pList[i] == target) { + *indexL = *indexR = i; + return AH_TRUE; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < pList[i + 1]) { + *indexL = i; + *indexR = (uint16_t)(i + 1); + return AH_FALSE; + } + } + HALASSERT(0); + return AH_FALSE; +} + +/************************************************************** + * ar5416FillVpdTable + * + * Fill the Vpdlist for indices Pmax-Pmin + * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4 + */ +static HAL_BOOL +ar5416FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList, + uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList) +{ + uint16_t i, k; + uint8_t currPwr = pwrMin; + uint16_t idxL, idxR; + + HALASSERT(pwrMax > pwrMin); + for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) { + getLowerUpperIndex(currPwr, pPwrList, numIntercepts, + &(idxL), &(idxR)); + if (idxR < 1) + idxR = 1; /* extrapolate below */ + if (idxL == numIntercepts - 1) + idxL = (uint16_t)(numIntercepts - 2); /* extrapolate above */ + if (pPwrList[idxL] == pPwrList[idxR]) + k = pVpdList[idxL]; + else + k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) / + (pPwrList[idxR] - pPwrList[idxL]) ); + HALASSERT(k < 256); + pRetVpdList[i] = (uint8_t)k; + currPwr += 2; /* half dB steps */ + } + + return AH_TRUE; +} + +/************************************************************************** + * interpolate + * + * Returns signed interpolated or the scaled up interpolated value + */ +static int16_t +interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight) +{ + int16_t rv; + + if (srcRight == srcLeft) { + rv = targetLeft; + } else { + rv = (int16_t)( ((target - srcLeft) * targetRight + + (srcRight - target) * targetLeft) / (srcRight - srcLeft) ); + } + return rv; +} + +static void +ar5416Set11nRegs(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + uint32_t phymode; + HAL_HT_MACMODE macmode; /* MAC - 20/40 mode */ + + if (!IS_CHAN_HT(chan)) + return; + + /* Enable 11n HT, 20 MHz */ + phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40 + | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH; + + /* Configure baseband for dynamic 20/40 operation */ + if (IS_CHAN_HT40(chan)) { + phymode |= AR_PHY_FC_DYN2040_EN | AR_PHY_FC_SHORT_GI_40; + + /* Configure control (primary) channel at +-10MHz */ + if ((chan->channelFlags & CHANNEL_HT40PLUS)) + phymode |= AR_PHY_FC_DYN2040_PRI_CH; +#if 0 + /* Configure 20/25 spacing */ + if (ht->ht_extprotspacing == HAL_HT_EXTPROTSPACING_25) + phymode |= AR_PHY_FC_DYN2040_EXT_CH; +#endif + macmode = HAL_HT_MACMODE_2040; + } else + macmode = HAL_HT_MACMODE_20; + OS_REG_WRITE(ah, AR_PHY_TURBO, phymode); + + /* Configure MAC for 20/40 operation */ + ar5416Set11nMac2040(ah, macmode); + + /* global transmit timeout (25 TUs default)*/ + /* XXX - put this elsewhere??? */ + OS_REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S) ; + + /* carrier sense timeout */ + OS_REG_SET_BIT(ah, AR_GTTM, AR_GTTM_CST_USEC); + OS_REG_WRITE(ah, AR_CST, 1 << AR_CST_TIMEOUT_LIMIT_S); +} + +void +ar5416GetChannelCenters(struct ath_hal *ah, + HAL_CHANNEL_INTERNAL *chan, CHAN_CENTERS *centers) +{ + centers->ctl_center = chan->channel; + centers->synth_center = chan->channel; + /* + * In 20/40 phy mode, the center frequency is + * "between" the control and extension channels. + */ + if (chan->channelFlags & CHANNEL_HT40PLUS) { + centers->synth_center += HT40_CHANNEL_CENTER_SHIFT; + centers->ext_center = + centers->synth_center + HT40_CHANNEL_CENTER_SHIFT; + } else if (chan->channelFlags & CHANNEL_HT40MINUS) { + centers->synth_center -= HT40_CHANNEL_CENTER_SHIFT; + centers->ext_center = + centers->synth_center - HT40_CHANNEL_CENTER_SHIFT; + } else { + centers->ext_center = chan->channel; + } +} diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_xmit.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_xmit.c new file mode 100644 index 0000000000..a0e2f14c93 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416_xmit.c @@ -0,0 +1,698 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416_xmit.c,v 1.9 2008/11/27 22:30:08 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_desc.h" +#include "ah_internal.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar5416/ar5416desc.h" + +/* + * Stop transmit on the specified queue + */ +HAL_BOOL +ar5416StopTxDma(struct ath_hal *ah, u_int q) +{ +#define STOP_DMA_TIMEOUT 4000 /* us */ +#define STOP_DMA_ITER 100 /* us */ + u_int i; + + HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); + + HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + OS_REG_WRITE(ah, AR_Q_TXD, 1 << q); + for (i = STOP_DMA_TIMEOUT/STOP_DMA_ITER; i != 0; i--) { + if (ar5212NumTxPending(ah, q) == 0) + break; + OS_DELAY(STOP_DMA_ITER); + } +#ifdef AH_DEBUG + if (i == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: queue %u DMA did not stop in 400 msec\n", __func__, q); + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: QSTS 0x%x Q_TXE 0x%x Q_TXD 0x%x Q_CBR 0x%x\n", __func__, + OS_REG_READ(ah, AR_QSTS(q)), OS_REG_READ(ah, AR_Q_TXE), + OS_REG_READ(ah, AR_Q_TXD), OS_REG_READ(ah, AR_QCBRCFG(q))); + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Q_MISC 0x%x Q_RDYTIMECFG 0x%x Q_RDYTIMESHDN 0x%x\n", + __func__, OS_REG_READ(ah, AR_QMISC(q)), + OS_REG_READ(ah, AR_QRDYTIMECFG(q)), + OS_REG_READ(ah, AR_Q_RDYTIMESHDN)); + } +#endif /* AH_DEBUG */ + + /* ar5416 and up can kill packets at the PCU level */ + if (ar5212NumTxPending(ah, q)) { + uint32_t j; + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: Num of pending TX Frames %d on Q %d\n", + __func__, ar5212NumTxPending(ah, q), q); + + /* Kill last PCU Tx Frame */ + /* TODO - save off and restore current values of Q1/Q2? */ + for (j = 0; j < 2; j++) { + uint32_t tsfLow = OS_REG_READ(ah, AR_TSF_L32); + OS_REG_WRITE(ah, AR_QUIET2, + SM(10, AR_QUIET2_QUIET_DUR)); + OS_REG_WRITE(ah, AR_QUIET_PERIOD, 100); + OS_REG_WRITE(ah, AR_NEXT_QUIET, tsfLow >> 10); + OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET); + + if ((OS_REG_READ(ah, AR_TSF_L32)>>10) == (tsfLow>>10)) + break; + + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: TSF moved while trying to set quiet time " + "TSF: 0x%08x\n", __func__, tsfLow); + HALASSERT(j < 1); /* TSF shouldn't count twice or reg access is taking forever */ + } + + OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE); + + /* Allow the quiet mechanism to do its work */ + OS_DELAY(200); + OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET); + + /* Verify the transmit q is empty */ + for (i = STOP_DMA_TIMEOUT/STOP_DMA_ITER; i != 0; i--) { + if (ar5212NumTxPending(ah, q) == 0) + break; + OS_DELAY(STOP_DMA_ITER); + } + if (i == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Failed to stop Tx DMA in %d msec after killing" + " last frame\n", __func__, STOP_DMA_TIMEOUT / 1000); + } + OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE); + } + + OS_REG_WRITE(ah, AR_Q_TXD, 0); + return (i != 0); +#undef STOP_DMA_ITER +#undef STOP_DMA_TIMEOUT +} + +#define VALID_KEY_TYPES \ + ((1 << HAL_KEY_TYPE_CLEAR) | (1 << HAL_KEY_TYPE_WEP)|\ + (1 << HAL_KEY_TYPE_AES) | (1 << HAL_KEY_TYPE_TKIP)) +#define isValidKeyType(_t) ((1 << (_t)) & VALID_KEY_TYPES) + +#define set11nTries(_series, _index) \ + (SM((_series)[_index].Tries, AR_XmitDataTries##_index)) + +#define set11nRate(_series, _index) \ + (SM((_series)[_index].Rate, AR_XmitRate##_index)) + +#define set11nPktDurRTSCTS(_series, _index) \ + (SM((_series)[_index].PktDuration, AR_PacketDur##_index) |\ + ((_series)[_index].RateFlags & HAL_RATESERIES_RTS_CTS ?\ + AR_RTSCTSQual##_index : 0)) + +#define set11nRateFlags(_series, _index) \ + ((_series)[_index].RateFlags & HAL_RATESERIES_2040 ? AR_2040_##_index : 0) \ + |((_series)[_index].RateFlags & HAL_RATESERIES_HALFGI ? AR_GI##_index : 0) \ + |SM((_series)[_index].ChSel, AR_ChainSel##_index) + +/* + * Descriptor Access Functions + */ + +#define VALID_PKT_TYPES \ + ((1<ah_txPowerIndexOffset); + if (txPower > 63) + txPower = 63; + + ads->ds_ctl0 = (pktLen & AR_FrameLen) + | (txPower << AR_XmitPower_S) + | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0) + | (flags & HAL_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) + | (flags & HAL_TXDESC_INTREQ ? AR_TxIntrReq : 0) + ; + ads->ds_ctl1 = (type << AR_FrameType_S) + | (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0) + ; + ads->ds_ctl2 = SM(txTries0, AR_XmitDataTries0) + | (flags & HAL_TXDESC_DURENA ? AR_DurUpdateEn : 0) + ; + ads->ds_ctl3 = (txRate0 << AR_XmitRate0_S) + ; + ads->ds_ctl4 = 0; + ads->ds_ctl5 = 0; + ads->ds_ctl6 = 0; + ads->ds_ctl7 = SM(ahp->ah_tx_chainmask, AR_ChainSel0) + | SM(ahp->ah_tx_chainmask, AR_ChainSel1) + | SM(ahp->ah_tx_chainmask, AR_ChainSel2) + | SM(ahp->ah_tx_chainmask, AR_ChainSel3) + ; + ads->ds_ctl8 = 0; + ads->ds_ctl9 = (txPower << 24); /* XXX? */ + ads->ds_ctl10 = (txPower << 24); /* XXX? */ + ads->ds_ctl11 = (txPower << 24); /* XXX? */ + if (keyIx != HAL_TXKEYIX_INVALID) { + /* XXX validate key index */ + ads->ds_ctl1 |= SM(keyIx, AR_DestIdx); + ads->ds_ctl0 |= AR_DestIdxValid; + ads->ds_ctl6 |= SM(ahp->ah_keytype[keyIx], AR_EncrType); + } + if (flags & RTSCTS) { + if (!isValidTxRate(rtsctsRate)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid rts/cts rate 0x%x\n", + __func__, rtsctsRate); + return AH_FALSE; + } + /* XXX validate rtsctsDuration */ + ads->ds_ctl0 |= (flags & HAL_TXDESC_CTSENA ? AR_CTSEnable : 0) + | (flags & HAL_TXDESC_RTSENA ? AR_RTSEnable : 0) + ; + ads->ds_ctl2 |= SM(rtsctsDuration, AR_BurstDur); + ads->ds_ctl7 |= (rtsctsRate << AR_RTSCTSRate_S); + } + return AH_TRUE; +#undef RTSCTS +} + +HAL_BOOL +ar5416SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int txRate1, u_int txTries1, + u_int txRate2, u_int txTries2, + u_int txRate3, u_int txTries3) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + if (txTries1) { + HALASSERT(isValidTxRate(txRate1)); + ads->ds_ctl2 |= SM(txTries1, AR_XmitDataTries1); + ads->ds_ctl3 |= (txRate1 << AR_XmitRate1_S); + } + if (txTries2) { + HALASSERT(isValidTxRate(txRate2)); + ads->ds_ctl2 |= SM(txTries2, AR_XmitDataTries2); + ads->ds_ctl3 |= (txRate2 << AR_XmitRate2_S); + } + if (txTries3) { + HALASSERT(isValidTxRate(txRate3)); + ads->ds_ctl2 |= SM(txTries3, AR_XmitDataTries3); + ads->ds_ctl3 |= (txRate3 << AR_XmitRate3_S); + } + return AH_TRUE; +} + +HAL_BOOL +ar5416FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg, + const struct ath_desc *ds0) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + HALASSERT((segLen &~ AR_BufLen) == 0); + + if (firstSeg) { + /* + * First descriptor, don't clobber xmit control data + * setup by ar5212SetupTxDesc. + */ + ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore); + } else if (lastSeg) { /* !firstSeg && lastSeg */ + /* + * Last descriptor in a multi-descriptor frame, + * copy the multi-rate transmit parameters from + * the first frame for processing on completion. + */ + ads->ds_ctl0 = 0; + ads->ds_ctl1 = segLen; +#ifdef AH_NEED_DESC_SWAP + ads->ds_ctl2 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl2); + ads->ds_ctl3 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl3); +#else + ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; + ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; +#endif + } else { /* !firstSeg && !lastSeg */ + /* + * Intermediate descriptor in a multi-descriptor frame. + */ + ads->ds_ctl0 = 0; + ads->ds_ctl1 = segLen | AR_TxMore; + ads->ds_ctl2 = 0; + ads->ds_ctl3 = 0; + } + /* XXX only on last descriptor? */ + OS_MEMZERO(ads->u.tx.status, sizeof(ads->u.tx.status)); + return AH_TRUE; +} + +#if 0 + +HAL_BOOL +ar5416ChainTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int pktLen, + u_int hdrLen, + HAL_PKT_TYPE type, + u_int keyIx, + HAL_CIPHER cipher, + uint8_t delims, + u_int segLen, + HAL_BOOL firstSeg, + HAL_BOOL lastSeg) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads); + + int isaggr = 0; + + (void) hdrLen; + (void) ah; + + HALASSERT((segLen &~ AR_BufLen) == 0); + + HALASSERT(isValidPktType(type)); + if (type == HAL_PKT_TYPE_AMPDU) { + type = HAL_PKT_TYPE_NORMAL; + isaggr = 1; + } + + if (!firstSeg) { + ath_hal_memzero(ds->ds_hw, AR5416_DESC_TX_CTL_SZ); + } + + ads->ds_ctl0 = (pktLen & AR_FrameLen); + ads->ds_ctl1 = (type << AR_FrameType_S) + | (isaggr ? (AR_IsAggr | AR_MoreAggr) : 0); + ads->ds_ctl2 = 0; + ads->ds_ctl3 = 0; + if (keyIx != HAL_TXKEYIX_INVALID) { + /* XXX validate key index */ + ads->ds_ctl1 |= SM(keyIx, AR_DestIdx); + ads->ds_ctl0 |= AR_DestIdxValid; + } + + ads->ds_ctl6 = SM(keyType[cipher], AR_EncrType); + if (isaggr) { + ads->ds_ctl6 |= SM(delims, AR_PadDelim); + } + + if (firstSeg) { + ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore); + } else if (lastSeg) { /* !firstSeg && lastSeg */ + ads->ds_ctl0 = 0; + ads->ds_ctl1 |= segLen; + } else { /* !firstSeg && !lastSeg */ + /* + * Intermediate descriptor in a multi-descriptor frame. + */ + ads->ds_ctl0 = 0; + ads->ds_ctl1 |= segLen | AR_TxMore; + } + ds_txstatus[0] = ds_txstatus[1] = 0; + ds_txstatus[9] &= ~AR_TxDone; + + return AH_TRUE; +} + +HAL_BOOL +ar5416SetupFirstTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int aggrLen, u_int flags, u_int txPower, + u_int txRate0, u_int txTries0, u_int antMode, + u_int rtsctsRate, u_int rtsctsDuration) +{ +#define RTSCTS (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA) + struct ar5416_desc *ads = AR5416DESC(ds); + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(txTries0 != 0); + HALASSERT(isValidTxRate(txRate0)); + HALASSERT((flags & RTSCTS) != RTSCTS); + /* XXX validate antMode */ + + txPower = (txPower + ahp->ah_txPowerIndexOffset ); + if(txPower > 63) txPower=63; + + ads->ds_ctl0 |= (txPower << AR_XmitPower_S) + | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0) + | (flags & HAL_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) + | (flags & HAL_TXDESC_INTREQ ? AR_TxIntrReq : 0); + ads->ds_ctl1 |= (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0); + ads->ds_ctl2 |= SM(txTries0, AR_XmitDataTries0); + ads->ds_ctl3 |= (txRate0 << AR_XmitRate0_S); + ads->ds_ctl7 = SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel0) + | SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel1) + | SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel2) + | SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel3); + + /* NB: no V1 WAR */ + ads->ds_ctl8 = 0; + ads->ds_ctl9 = (txPower << 24); + ads->ds_ctl10 = (txPower << 24); + ads->ds_ctl11 = (txPower << 24); + + ads->ds_ctl6 &= ~(0xffff); + ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); + + if (flags & RTSCTS) { + /* XXX validate rtsctsDuration */ + ads->ds_ctl0 |= (flags & HAL_TXDESC_CTSENA ? AR_CTSEnable : 0) + | (flags & HAL_TXDESC_RTSENA ? AR_RTSEnable : 0); + ads->ds_ctl2 |= SM(rtsctsDuration, AR_BurstDur); + } + + return AH_TRUE; +#undef RTSCTS +} + +HAL_BOOL +ar5416SetupLastTxDesc(struct ath_hal *ah, struct ath_desc *ds, + const struct ath_desc *ds0) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_ctl1 &= ~AR_MoreAggr; + ads->ds_ctl6 &= ~AR_PadDelim; + + /* hack to copy rate info to last desc for later processing */ +#ifdef AH_NEED_DESC_SWAP + ads->ds_ctl2 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl2); + ads->ds_ctl3 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl3); +#else + ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; + ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; +#endif + + return AH_TRUE; +} +#endif /* 0 */ + +#ifdef AH_NEED_DESC_SWAP +/* Swap transmit descriptor */ +static __inline void +ar5416SwapTxDesc(struct ath_desc *ds) +{ + ds->ds_data = __bswap32(ds->ds_data); + ds->ds_ctl0 = __bswap32(ds->ds_ctl0); + ds->ds_ctl1 = __bswap32(ds->ds_ctl1); + ds->ds_hw[0] = __bswap32(ds->ds_hw[0]); + ds->ds_hw[1] = __bswap32(ds->ds_hw[1]); + ds->ds_hw[2] = __bswap32(ds->ds_hw[2]); + ds->ds_hw[3] = __bswap32(ds->ds_hw[3]); +} +#endif + +/* + * Processing of HW TX descriptor. + */ +HAL_STATUS +ar5416ProcTxDesc(struct ath_hal *ah, + struct ath_desc *ds, struct ath_tx_status *ts) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads); + +#ifdef AH_NEED_DESC_SWAP + if ((ds_txstatus[9] & __bswap32(AR_TxDone)) == 0) + return HAL_EINPROGRESS; + ar5416SwapTxDesc(ds); +#else + if ((ds_txstatus[9] & AR_TxDone) == 0) + return HAL_EINPROGRESS; +#endif + + /* Update software copies of the HW status */ + ts->ts_seqnum = MS(ds_txstatus[9], AR_SeqNum); + ts->ts_tstamp = AR_SendTimestamp(ds_txstatus); + + ts->ts_status = 0; + if (ds_txstatus[1] & AR_ExcessiveRetries) + ts->ts_status |= HAL_TXERR_XRETRY; + if (ds_txstatus[1] & AR_Filtered) + ts->ts_status |= HAL_TXERR_FILT; + if (ds_txstatus[1] & AR_FIFOUnderrun) + ts->ts_status |= HAL_TXERR_FIFO; + if (ds_txstatus[9] & AR_TxOpExceeded) + ts->ts_status |= HAL_TXERR_XTXOP; + if (ds_txstatus[1] & AR_TxTimerExpired) + ts->ts_status |= HAL_TXERR_TIMER_EXPIRED; + + ts->ts_flags = 0; + if (ds_txstatus[0] & AR_TxBaStatus) { + ts->ts_flags |= HAL_TX_BA; + ts->ts_ba_low = AR_BaBitmapLow(ds_txstatus); + ts->ts_ba_high = AR_BaBitmapHigh(ds_txstatus); + } + if (ds->ds_ctl1 & AR_IsAggr) + ts->ts_flags |= HAL_TX_AGGR; + if (ds_txstatus[1] & AR_DescCfgErr) + ts->ts_flags |= HAL_TX_DESC_CFG_ERR; + if (ds_txstatus[1] & AR_TxDataUnderrun) + ts->ts_flags |= HAL_TX_DATA_UNDERRUN; + if (ds_txstatus[1] & AR_TxDelimUnderrun) + ts->ts_flags |= HAL_TX_DELIM_UNDERRUN; + + /* + * Extract the transmit rate used and mark the rate as + * ``alternate'' if it wasn't the series 0 rate. + */ + ts->ts_finaltsi = MS(ds_txstatus[9], AR_FinalTxIdx); + switch (ts->ts_finaltsi) { + case 0: + ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate0); + break; + case 1: + ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate1) | + HAL_TXSTAT_ALTRATE; + break; + case 2: + ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate2) | + HAL_TXSTAT_ALTRATE; + break; + case 3: + ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate3) | + HAL_TXSTAT_ALTRATE; + break; + } + + ts->ts_rssi = MS(ds_txstatus[5], AR_TxRSSICombined); + ts->ts_rssi_ctl[0] = MS(ds_txstatus[0], AR_TxRSSIAnt00); + ts->ts_rssi_ctl[1] = MS(ds_txstatus[0], AR_TxRSSIAnt01); + ts->ts_rssi_ctl[2] = MS(ds_txstatus[0], AR_TxRSSIAnt02); + ts->ts_rssi_ext[0] = MS(ds_txstatus[5], AR_TxRSSIAnt10); + ts->ts_rssi_ext[1] = MS(ds_txstatus[5], AR_TxRSSIAnt11); + ts->ts_rssi_ext[2] = MS(ds_txstatus[5], AR_TxRSSIAnt12); + ts->ts_evm0 = AR_TxEVM0(ds_txstatus); + ts->ts_evm1 = AR_TxEVM1(ds_txstatus); + ts->ts_evm2 = AR_TxEVM2(ds_txstatus); + + ts->ts_shortretry = MS(ds_txstatus[1], AR_RTSFailCnt); + ts->ts_longretry = MS(ds_txstatus[1], AR_DataFailCnt); + /* + * The retry count has the number of un-acked tries for the + * final series used. When doing multi-rate retry we must + * fixup the retry count by adding in the try counts for + * each series that was fully-processed. Beware that this + * takes values from the try counts in the final descriptor. + * These are not required by the hardware. We assume they + * are placed there by the driver as otherwise we have no + * access and the driver can't do the calculation because it + * doesn't know the descriptor format. + */ + switch (ts->ts_finaltsi) { + case 3: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries2); + case 2: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries1); + case 1: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries0); + } + + /* + * These fields are not used. Zero these to preserve compatability + * with existing drivers. + */ + ts->ts_virtcol = MS(ads->ds_ctl1, AR_VirtRetryCnt); + ts->ts_antenna = 0; /* We don't switch antennas on Owl*/ + + /* handle tx trigger level changes internally */ + if ((ts->ts_status & HAL_TXERR_FIFO) || + (ts->ts_flags & (HAL_TX_DATA_UNDERRUN | HAL_TX_DELIM_UNDERRUN))) + ar5212UpdateTxTrigLevel(ah, AH_TRUE); + + return HAL_OK; +} + +#if 0 +HAL_BOOL +ar5416SetGlobalTxTimeout(struct ath_hal *ah, u_int tu) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + + if (tu > 0xFFFF) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad global tx timeout %u\n", + __func__, tu); + /* restore default handling */ + ahp->ah_globaltxtimeout = (u_int) -1; + return AH_FALSE; + } + OS_REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu); + ahp->ah_globaltxtimeout = tu; + return AH_TRUE; +} + +u_int +ar5416GetGlobalTxTimeout(struct ath_hal *ah) +{ + return MS(OS_REG_READ(ah, AR_GTXTO), AR_GTXTO_TIMEOUT_LIMIT); +} + +void +ar5416Set11nRateScenario(struct ath_hal *ah, struct ath_desc *ds, + u_int durUpdateEn, u_int rtsctsRate, + HAL_11N_RATE_SERIES series[], u_int nseries) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + HALASSERT(nseries == 4); + (void)nseries; + + + ads->ds_ctl2 = set11nTries(series, 0) + | set11nTries(series, 1) + | set11nTries(series, 2) + | set11nTries(series, 3) + | (durUpdateEn ? AR_DurUpdateEn : 0); + + ads->ds_ctl3 = set11nRate(series, 0) + | set11nRate(series, 1) + | set11nRate(series, 2) + | set11nRate(series, 3); + + ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0) + | set11nPktDurRTSCTS(series, 1); + + ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2) + | set11nPktDurRTSCTS(series, 3); + + ads->ds_ctl7 = set11nRateFlags(series, 0) + | set11nRateFlags(series, 1) + | set11nRateFlags(series, 2) + | set11nRateFlags(series, 3) + | SM(rtsctsRate, AR_RTSCTSRate); + + /* + * Enable RTSCTS if any of the series is flagged for RTSCTS, + * but only if CTS is not enabled. + */ + /* + * FIXME : the entire RTS/CTS handling should be moved to this + * function (by passing the global RTS/CTS flags to this function). + * currently it is split between this function and the + * setupFiirstDescriptor. with this current implementation there + * is an implicit assumption that setupFirstDescriptor is called + * before this function. + */ + if (((series[0].RateFlags & HAL_RATESERIES_RTS_CTS) || + (series[1].RateFlags & HAL_RATESERIES_RTS_CTS) || + (series[2].RateFlags & HAL_RATESERIES_RTS_CTS) || + (series[3].RateFlags & HAL_RATESERIES_RTS_CTS) ) && + (ads->ds_ctl0 & AR_CTSEnable) == 0) { + ads->ds_ctl0 |= AR_RTSEnable; + ads->ds_ctl0 &= ~AR_CTSEnable; + } +} + +void +ar5416Set11nAggrMiddle(struct ath_hal *ah, struct ath_desc *ds, u_int numDelims) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads); + + ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); + + ads->ds_ctl6 &= ~AR_PadDelim; + ads->ds_ctl6 |= SM(numDelims, AR_PadDelim); + ads->ds_ctl6 &= ~AR_AggrLen; + + /* + * Clear the TxDone status here, may need to change + * func name to reflect this + */ + ds_txstatus[9] &= ~AR_TxDone; +} + +void +ar5416Clr11nAggr(struct ath_hal *ah, struct ath_desc *ds) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); + ads->ds_ctl6 &= ~AR_PadDelim; + ads->ds_ctl6 &= ~AR_AggrLen; +} + +void +ar5416Set11nBurstDuration(struct ath_hal *ah, struct ath_desc *ds, + u_int burstDuration) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_ctl2 &= ~AR_BurstDur; + ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); +} +#endif diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416desc.h b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416desc.h new file mode 100644 index 0000000000..7c60b24c89 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416desc.h @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416desc.h,v 1.7 2008/11/11 00:11:30 sam Exp $ + */ +#ifndef _ATH_AR5416_DESC_H_ +#define _ATH_AR5416_DESC_H + +/* + * Hardware-specific descriptor structures. + */ +#include "ah_desc.h" + +/* XXX Need to replace this with a dynamic + * method of determining Owl2 if possible + */ +#define _get_index(_ah) ( IS_5416V1(_ah) ? -4 : 0 ) +#define AR5416_DS_TXSTATUS(_ah, _ads) \ + ((uint32_t*)(&(_ads)->u.tx.status[_get_index(_ah)])) +#define AR5416_DS_TXSTATUS_CONST(_ah, _ads) \ + ((const uint32_t*)(&(_ads)->u.tx.status[_get_index(_ah)])) + +#define AR5416_NUM_TX_STATUS 10 /* Number of TX status words */ +/* Clear the whole descriptor */ +#define AR5416_DESC_TX_CTL_SZ sizeof(struct ar5416_tx_desc) + +struct ar5416_tx_desc { /* tx desc has 12 control words + 10 status words */ + uint32_t ctl2; + uint32_t ctl3; + uint32_t ctl4; + uint32_t ctl5; + uint32_t ctl6; + uint32_t ctl7; + uint32_t ctl8; + uint32_t ctl9; + uint32_t ctl10; + uint32_t ctl11; + uint32_t status[AR5416_NUM_TX_STATUS]; +}; + +struct ar5416_rx_desc { /* rx desc has 2 control words + 9 status words */ + uint32_t status0; + uint32_t status1; + uint32_t status2; + uint32_t status3; + uint32_t status4; + uint32_t status5; + uint32_t status6; + uint32_t status7; + uint32_t status8; +}; + + +struct ar5416_desc { + uint32_t ds_link; /* link pointer */ + uint32_t ds_data; /* data buffer pointer */ + uint32_t ds_ctl0; /* DMA control 0 */ + uint32_t ds_ctl1; /* DMA control 1 */ + union { + struct ar5416_tx_desc tx; + struct ar5416_rx_desc rx; + } u; +} __packed; +#define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds)) +#define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds)) + +#define ds_ctl2 u.tx.ctl2 +#define ds_ctl3 u.tx.ctl3 +#define ds_ctl4 u.tx.ctl4 +#define ds_ctl5 u.tx.ctl5 +#define ds_ctl6 u.tx.ctl6 +#define ds_ctl7 u.tx.ctl7 +#define ds_ctl8 u.tx.ctl8 +#define ds_ctl9 u.tx.ctl9 +#define ds_ctl10 u.tx.ctl10 +#define ds_ctl11 u.tx.ctl11 + +#define ds_rxstatus0 u.rx.status0 +#define ds_rxstatus1 u.rx.status1 +#define ds_rxstatus2 u.rx.status2 +#define ds_rxstatus3 u.rx.status3 +#define ds_rxstatus4 u.rx.status4 +#define ds_rxstatus5 u.rx.status5 +#define ds_rxstatus6 u.rx.status6 +#define ds_rxstatus7 u.rx.status7 +#define ds_rxstatus8 u.rx.status8 + +/*********** + * TX Desc * + ***********/ + +/* ds_ctl0 */ +#define AR_FrameLen 0x00000fff +#define AR_VirtMoreFrag 0x00001000 +#define AR_TxCtlRsvd00 0x0000e000 +#define AR_XmitPower 0x003f0000 +#define AR_XmitPower_S 16 +#define AR_RTSEnable 0x00400000 +#define AR_VEOL 0x00800000 +#define AR_ClrDestMask 0x01000000 +#define AR_TxCtlRsvd01 0x1e000000 +#define AR_TxIntrReq 0x20000000 +#define AR_DestIdxValid 0x40000000 +#define AR_CTSEnable 0x80000000 + +/* ds_ctl1 */ +#define AR_BufLen 0x00000fff +#define AR_TxMore 0x00001000 +#define AR_DestIdx 0x000fe000 +#define AR_DestIdx_S 13 +#define AR_FrameType 0x00f00000 +#define AR_FrameType_S 20 +#define AR_NoAck 0x01000000 +#define AR_InsertTS 0x02000000 +#define AR_CorruptFCS 0x04000000 +#define AR_ExtOnly 0x08000000 +#define AR_ExtAndCtl 0x10000000 +#define AR_MoreAggr 0x20000000 +#define AR_IsAggr 0x40000000 +#define AR_MoreRifs 0x80000000 + +/* ds_ctl2 */ +#define AR_BurstDur 0x00007fff +#define AR_BurstDur_S 0 +#define AR_DurUpdateEn 0x00008000 +#define AR_XmitDataTries0 0x000f0000 +#define AR_XmitDataTries0_S 16 +#define AR_XmitDataTries1 0x00f00000 +#define AR_XmitDataTries1_S 20 +#define AR_XmitDataTries2 0x0f000000 +#define AR_XmitDataTries2_S 24 +#define AR_XmitDataTries3 0xf0000000 +#define AR_XmitDataTries3_S 28 + +/* ds_ctl3 */ +#define AR_XmitRate0 0x000000ff +#define AR_XmitRate0_S 0 +#define AR_XmitRate1 0x0000ff00 +#define AR_XmitRate1_S 8 +#define AR_XmitRate2 0x00ff0000 +#define AR_XmitRate2_S 16 +#define AR_XmitRate3 0xff000000 +#define AR_XmitRate3_S 24 + +/* ds_ctl4 */ +#define AR_PacketDur0 0x00007fff +#define AR_PacketDur0_S 0 +#define AR_RTSCTSQual0 0x00008000 +#define AR_PacketDur1 0x7fff0000 +#define AR_PacketDur1_S 16 +#define AR_RTSCTSQual1 0x80000000 + +/* ds_ctl5 */ +#define AR_PacketDur2 0x00007fff +#define AR_PacketDur2_S 0 +#define AR_RTSCTSQual2 0x00008000 +#define AR_PacketDur3 0x7fff0000 +#define AR_PacketDur3_S 16 +#define AR_RTSCTSQual3 0x80000000 + +/* ds_ctl6 */ +#define AR_AggrLen 0x0000ffff +#define AR_AggrLen_S 0 +#define AR_TxCtlRsvd60 0x00030000 +#define AR_PadDelim 0x03fc0000 +#define AR_PadDelim_S 18 +#define AR_EncrType 0x0c000000 +#define AR_EncrType_S 26 +#define AR_TxCtlRsvd61 0xf0000000 + +/* ds_ctl7 */ +#define AR_2040_0 0x00000001 +#define AR_GI0 0x00000002 +#define AR_ChainSel0 0x0000001c +#define AR_ChainSel0_S 2 +#define AR_2040_1 0x00000020 +#define AR_GI1 0x00000040 +#define AR_ChainSel1 0x00000380 +#define AR_ChainSel1_S 7 +#define AR_2040_2 0x00000400 +#define AR_GI2 0x00000800 +#define AR_ChainSel2 0x00007000 +#define AR_ChainSel2_S 12 +#define AR_2040_3 0x00008000 +#define AR_GI3 0x00010000 +#define AR_ChainSel3 0x000e0000 +#define AR_ChainSel3_S 17 +#define AR_RTSCTSRate 0x0ff00000 +#define AR_RTSCTSRate_S 20 +#define AR_STBC0 0x10000000 +#define AR_STBC1 0x20000000 +#define AR_STBC2 0x40000000 +#define AR_STBC3 0x80000000 + +/************* + * TX Status * + *************/ + +/* ds_status0 */ +#define AR_TxRSSIAnt00 0x000000ff +#define AR_TxRSSIAnt00_S 0 +#define AR_TxRSSIAnt01 0x0000ff00 +#define AR_TxRSSIAnt01_S 8 +#define AR_TxRSSIAnt02 0x00ff0000 +#define AR_TxRSSIAnt02_S 16 +#define AR_TxStatusRsvd00 0x3f000000 +#define AR_TxBaStatus 0x40000000 +#define AR_TxStatusRsvd01 0x80000000 + +/* ds_status1 */ +#define AR_FrmXmitOK 0x00000001 +#define AR_ExcessiveRetries 0x00000002 +#define AR_FIFOUnderrun 0x00000004 +#define AR_Filtered 0x00000008 +#define AR_RTSFailCnt 0x000000f0 +#define AR_RTSFailCnt_S 4 +#define AR_DataFailCnt 0x00000f00 +#define AR_DataFailCnt_S 8 +#define AR_VirtRetryCnt 0x0000f000 +#define AR_VirtRetryCnt_S 12 +#define AR_TxDelimUnderrun 0x00010000 +#define AR_TxDelimUnderrun_S 13 +#define AR_TxDataUnderrun 0x00020000 +#define AR_TxDataUnderrun_S 14 +#define AR_DescCfgErr 0x00040000 +#define AR_DescCfgErr_S 15 +#define AR_TxTimerExpired 0x00080000 +#define AR_TxStatusRsvd10 0xfff00000 + +/* ds_status2 */ +#define AR_SendTimestamp(_ptr) (_ptr)[2] + +/* ds_status3 */ +#define AR_BaBitmapLow(_ptr) (_ptr)[3] + +/* ds_status4 */ +#define AR_BaBitmapHigh(_ptr) (_ptr)[4] + +/* ds_status5 */ +#define AR_TxRSSIAnt10 0x000000ff +#define AR_TxRSSIAnt10_S 0 +#define AR_TxRSSIAnt11 0x0000ff00 +#define AR_TxRSSIAnt11_S 8 +#define AR_TxRSSIAnt12 0x00ff0000 +#define AR_TxRSSIAnt12_S 16 +#define AR_TxRSSICombined 0xff000000 +#define AR_TxRSSICombined_S 24 + +/* ds_status6 */ +#define AR_TxEVM0(_ptr) (_ptr)[6] + +/* ds_status7 */ +#define AR_TxEVM1(_ptr) (_ptr)[7] + +/* ds_status8 */ +#define AR_TxEVM2(_ptr) (_ptr)[8] + +/* ds_status9 */ +#define AR_TxDone 0x00000001 +#define AR_SeqNum 0x00001ffe +#define AR_SeqNum_S 1 +#define AR_TxStatusRsvd80 0x0001e000 +#define AR_TxOpExceeded 0x00020000 +#define AR_TxStatusRsvd81 0x001c0000 +#define AR_FinalTxIdx 0x00600000 +#define AR_FinalTxIdx_S 21 +#define AR_TxStatusRsvd82 0x01800000 +#define AR_PowerMgmt 0x02000000 +#define AR_TxStatusRsvd83 0xfc000000 + +/*********** + * RX Desc * + ***********/ + +/* ds_ctl0 */ +#define AR_RxCTLRsvd00 0xffffffff + +/* ds_ctl1 */ +#define AR_BufLen 0x00000fff +#define AR_RxCtlRsvd00 0x00001000 +#define AR_RxIntrReq 0x00002000 +#define AR_RxCtlRsvd01 0xffffc000 + +/************* + * Rx Status * + *************/ + +/* ds_status0 */ +#define AR_RxRSSIAnt00 0x000000ff +#define AR_RxRSSIAnt00_S 0 +#define AR_RxRSSIAnt01 0x0000ff00 +#define AR_RxRSSIAnt01_S 8 +#define AR_RxRSSIAnt02 0x00ff0000 +#define AR_RxRSSIAnt02_S 16 +/* Rev specific */ +/* Owl 1.x only */ +#define AR_RxStatusRsvd00 0xff000000 +/* Owl 2.x only */ +#define AR_RxRate 0xff000000 +#define AR_RxRate_S 24 + +/* ds_status1 */ +#define AR_DataLen 0x00000fff +#define AR_RxMore 0x00001000 +#define AR_NumDelim 0x003fc000 +#define AR_NumDelim_S 14 +#define AR_RxStatusRsvd10 0xff800000 + +/* ds_status2 */ +#define AR_RcvTimestamp ds_rxstatus2 + +/* ds_status3 */ +#define AR_GI 0x00000001 +#define AR_2040 0x00000002 +/* Rev specific */ +/* Owl 1.x only */ +#define AR_RxRateV1 0x000003fc +#define AR_RxRateV1_S 2 +#define AR_Parallel40 0x00000400 +#define AR_RxStatusRsvd30 0xfffff800 +/* Owl 2.x only */ +#define AR_DupFrame 0x00000004 +#define AR_RxAntenna 0xffffff00 +#define AR_RxAntenna_S 8 + +/* ds_status4 */ +#define AR_RxRSSIAnt10 0x000000ff +#define AR_RxRSSIAnt10_S 0 +#define AR_RxRSSIAnt11 0x0000ff00 +#define AR_RxRSSIAnt11_S 8 +#define AR_RxRSSIAnt12 0x00ff0000 +#define AR_RxRSSIAnt12_S 16 +#define AR_RxRSSICombined 0xff000000 +#define AR_RxRSSICombined_S 24 + +/* ds_status5 */ +#define AR_RxEVM0 ds_rxstatus5 + +/* ds_status6 */ +#define AR_RxEVM1 ds_rxstatus6 + +/* ds_status7 */ +#define AR_RxEVM2 ds_rxstatus7 + +/* ds_status8 */ +#define AR_RxDone 0x00000001 +#define AR_RxFrameOK 0x00000002 +#define AR_CRCErr 0x00000004 +#define AR_DecryptCRCErr 0x00000008 +#define AR_PHYErr 0x00000010 +#define AR_MichaelErr 0x00000020 +#define AR_PreDelimCRCErr 0x00000040 +#define AR_RxStatusRsvd70 0x00000080 +#define AR_RxKeyIdxValid 0x00000100 +#define AR_KeyIdx 0x0000fe00 +#define AR_KeyIdx_S 9 +#define AR_PHYErrCode 0x0000ff00 +#define AR_PHYErrCode_S 8 +#define AR_RxMoreAggr 0x00010000 +#define AR_RxAggr 0x00020000 +#define AR_PostDelimCRCErr 0x00040000 +#define AR_RxStatusRsvd71 0x2ff80000 +#define AR_HiRxChain 0x10000000 +#define AR_DecryptBusyErr 0x40000000 +#define AR_KeyMiss 0x80000000 + +#define TXCTL_OFFSET(ah) 2 +#define TXCTL_NUMWORDS(ah) (AR_SREV_5416_V20_OR_LATER(ah) ? 12 : 8) +#define TXSTATUS_OFFSET(ah) (AR_SREV_5416_V20_OR_LATER(ah) ? 14 : 10) +#define TXSTATUS_NUMWORDS(ah) 10 + +#define RXCTL_OFFSET(ah) 3 +#define RXCTL_NUMWORDS(ah) 1 +#define RXSTATUS_OFFSET(ah) 4 +#define RXSTATUS_NUMWORDS(ah) 9 +#define RXSTATUS_RATE(ah, ads) \ + (AR_SREV_OWL_20_OR_LATER(ah) ? \ + MS((ads)->ds_rxstatus0, AR_RxRate) : \ + ((ads)->ds_rxstatus3 >> 2) & 0xFF) +#define RXSTATUS_DUPLICATE(ah, ads) \ + (AR_SREV_OWL_20_OR_LATER(ah) ? \ + MS((ads)->ds_rxstatus3, AR_Parallel40) : \ + ((ads)->ds_rxstatus3 >> 10) & 0x1) +#endif /* _ATH_AR5416_DESC_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416phy.h b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416phy.h new file mode 100644 index 0000000000..416aae68d2 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416phy.h @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416phy.h,v 1.10 2008/11/11 20:46:06 sam Exp $ + */ +#ifndef _DEV_ATH_AR5416PHY_H_ +#define _DEV_ATH_AR5416PHY_H_ + +#include "ar5212/ar5212phy.h" + +#define AR_PHY_CHIP_ID_REV_0 0x80 /* 5416 Rev 0 (owl 1.0) BB */ +#define AR_PHY_CHIP_ID_REV_1 0x81 /* 5416 Rev 1 (owl 2.0) BB */ + +#define RFSILENT_BB 0x00002000 /* shush bb */ +#define AR_PHY_RESTART 0x9970 /* restart */ +#define AR_PHY_RESTART_DIV_GC 0x001C0000 /* bb_ant_fast_div_gc_limit */ +#define AR_PHY_RESTART_DIV_GC_S 18 + +/* PLL settling times */ +#define RTC_PLL_SETTLE_DELAY 1000 /* 1 ms */ +#define HT40_CHANNEL_CENTER_SHIFT 10 /* MHz */ + +#define AR_PHY_RFBUS_REQ 0x997C +#define AR_PHY_RFBUS_REQ_EN 0x00000001 + +#define AR_2040_MODE 0x8318 +#define AR_2040_JOINED_RX_CLEAR 0x00000001 // use ctl + ext rx_clear for cca + +#define AR_PHY_FC_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode setting */ +#define AR_PHY_FC_DYN2040_EN 0x00000004 /* Enable dyn 20/40 mode */ +#define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008 /* dyn 20/40 - primary only */ +#define AR_PHY_FC_DYN2040_PRI_CH 0x00000010 /* dyn 20/40 - primary ch offset (0=+10MHz, 1=-10MHz)*/ +#define AR_PHY_FC_DYN2040_EXT_CH 0x00000020 /* dyn 20/40 - ext ch spacing (0=20MHz/ 1=25MHz) */ +#define AR_PHY_FC_HT_EN 0x00000040 /* ht enable */ +#define AR_PHY_FC_SHORT_GI_40 0x00000080 /* allow short GI for HT 40 */ +#define AR_PHY_FC_WALSH 0x00000100 /* walsh spatial spreading for 2 chains,2 streams TX */ +#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200 /* single length (4us) 1st HT long training symbol */ + +#define AR_PHY_TIMING2 0x9810 /* Timing Control 2 */ +#define AR_PHY_TIMING2_USE_FORCE 0x00001000 +#define AR_PHY_TIMING2_FORCE_VAL 0x00000fff + +#define AR_PHY_TIMING_CTRL4_CHAIN(_i) \ + (AR_PHY_TIMING_CTRL4 + ((_i) << 12)) +#define AR_PHY_TIMING_CTRL4_DO_CAL 0x10000 /* perform calibration */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F /* Mask for kcos_theta-1 for q correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0 /* shift for Q_COFF */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0 /* Mask for sin_theta for i correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5 /* Shift for sin_theta for i correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800 /* enable IQ correction */ +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000 /* Mask for max number of samples (logarithmic) */ +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12 /* Shift for max number of samples */ + +#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000 +#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000 /* Enable spur filter */ +#define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000 +#define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000 + +#define AR_PHY_ADC_SERIAL_CTL 0x9830 +#define AR_PHY_SEL_INTERNAL_ADDAC 0x00000000 +#define AR_PHY_SEL_EXTERNAL_RADIO 0x00000001 + +#define AR_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003C00 +#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S 10 +#define AR_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001F +#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S 0 + +#define AR_PHY_EXT_CCA 0x99bc +#define AR_PHY_EXT_CCA_CYCPWR_THR1 0x0000FE00 +#define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9 +#define AR_PHY_EXT_MINCCA_PWR 0xFF800000 +#define AR_PHY_EXT_MINCCA_PWR_S 23 +#define AR_PHY_EXT_CCA_THRESH62 0x007F0000 +#define AR_PHY_EXT_CCA_THRESH62_S 16 +#define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000 +#define AR9280_PHY_EXT_MINCCA_PWR_S 16 + +#define AR_PHY_HALFGI 0x99D0 /* Timing control 3 */ +#define AR_PHY_HALFGI_DSC_MAN 0x0007FFF0 +#define AR_PHY_HALFGI_DSC_MAN_S 4 +#define AR_PHY_HALFGI_DSC_EXP 0x0000000F +#define AR_PHY_HALFGI_DSC_EXP_S 0 + +#define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0 + +#define AR_PHY_M_SLEEP 0x99f0 /* sleep control registers */ +#define AR_PHY_REFCLKDLY 0x99f4 +#define AR_PHY_REFCLKPD 0x99f8 + +#define AR_PHY_CALMODE 0x99f0 +/* Calibration Types */ +#define AR_PHY_CALMODE_IQ 0x00000000 +#define AR_PHY_CALMODE_ADC_GAIN 0x00000001 +#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002 +#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003 +/* Calibration results */ +#define AR_PHY_CAL_MEAS_0(_i) (0x9c10 + ((_i) << 12)) +#define AR_PHY_CAL_MEAS_1(_i) (0x9c14 + ((_i) << 12)) +#define AR_PHY_CAL_MEAS_2(_i) (0x9c18 + ((_i) << 12)) +#define AR_PHY_CAL_MEAS_3(_i) (0x9c1c + ((_i) << 12)) + + +#define AR_PHY_CCA 0x9864 +#define AR_PHY_MINCCA_PWR 0x0FF80000 +#define AR_PHY_MINCCA_PWR_S 19 +#define AR9280_PHY_MINCCA_PWR 0x1FF00000 +#define AR9280_PHY_MINCCA_PWR_S 20 +#define AR9280_PHY_CCA_THRESH62 0x000FF000 +#define AR9280_PHY_CCA_THRESH62_S 12 + +#define AR_PHY_CH1_CCA 0xa864 +#define AR_PHY_CH1_MINCCA_PWR 0x0FF80000 +#define AR_PHY_CH1_MINCCA_PWR_S 19 +#define AR_PHY_CCA_THRESH62 0x0007F000 +#define AR_PHY_CCA_THRESH62_S 12 +#define AR9280_PHY_CH1_MINCCA_PWR 0x1FF00000 +#define AR9280_PHY_CH1_MINCCA_PWR_S 20 + +#define AR_PHY_CH2_CCA 0xb864 +#define AR_PHY_CH2_MINCCA_PWR 0x0FF80000 +#define AR_PHY_CH2_MINCCA_PWR_S 19 + +#define AR_PHY_CH1_EXT_CCA 0xa9bc +#define AR_PHY_CH1_EXT_MINCCA_PWR 0xFF800000 +#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23 +#define AR9280_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000 +#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16 + +#define AR_PHY_CH2_EXT_CCA 0xb9bc +#define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000 +#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23 + +#define AR_PHY_RX_CHAINMASK 0x99a4 + +#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12)) +#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 +#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 +#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac + +#define AR_PHY_EXT_CCA0 0x99b8 +#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF +#define AR_PHY_EXT_CCA0_THRESH62_S 0 + +#define AR_PHY_CH1_EXT_CCA 0xa9bc +#define AR_PHY_CH1_EXT_MINCCA_PWR 0xFF800000 +#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23 + +#define AR_PHY_CH2_EXT_CCA 0xb9bc +#define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000 +#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23 +#define AR_PHY_ANALOG_SWAP 0xa268 +#define AR_PHY_SWAP_ALT_CHAIN 0x00000040 +#define AR_PHY_CAL_CHAINMASK 0xa39c + +#define AR_PHY_SWITCH_CHAIN_0 0x9960 +#define AR_PHY_SWITCH_COM 0x9964 + +#define AR_PHY_RF_CTL2 0x9824 +#define AR_PHY_TX_FRAME_TO_DATA_START 0x000000FF +#define AR_PHY_TX_FRAME_TO_DATA_START_S 0 +#define AR_PHY_TX_FRAME_TO_PA_ON 0x0000FF00 +#define AR_PHY_TX_FRAME_TO_PA_ON_S 8 + +#define AR_PHY_RF_CTL3 0x9828 +#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000 +#define AR_PHY_TX_END_TO_A2_RX_ON_S 16 + +#define AR_PHY_RF_CTL4 0x9834 +#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF 0xFF000000 +#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24 +#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00FF0000 +#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16 +#define AR_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000FF00 +#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S 8 +#define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF +#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0 + +#define AR_PHY_SYNTH_CONTROL 0x9874 + +#define AR_PHY_FORCE_CLKEN_CCK 0xA22C +#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX 0x00000040 + +#define AR_PHY_POWER_TX_SUB 0xA3C8 +#define AR_PHY_POWER_TX_RATE5 0xA38C +#define AR_PHY_POWER_TX_RATE6 0xA390 +#define AR_PHY_POWER_TX_RATE7 0xA3CC +#define AR_PHY_POWER_TX_RATE8 0xA3D0 +#define AR_PHY_POWER_TX_RATE9 0xA3D4 + +#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000 +#define AR_PHY_TPCRG1_PD_GAIN_1_S 16 +#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000 +#define AR_PHY_TPCRG1_PD_GAIN_2_S 18 +#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000 +#define AR_PHY_TPCRG1_PD_GAIN_3_S 20 + +#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0 +#define AR_PHY_MASK2_M_31_45 0xa3a4 +#define AR_PHY_MASK2_M_16_30 0xa3a8 +#define AR_PHY_MASK2_M_00_15 0xa3ac +#define AR_PHY_MASK2_P_15_01 0xa3b8 +#define AR_PHY_MASK2_P_30_16 0xa3bc +#define AR_PHY_MASK2_P_45_31 0xa3c0 +#define AR_PHY_MASK2_P_61_45 0xa3c4 + +#define AR_PHY_SPUR_REG 0x994c +#define AR_PHY_SFCORR_EXT 0x99c0 +#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F +#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0 +#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80 +#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7 +#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000 +#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14 +#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000 +#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21 +#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28 + +/* enable vit puncture per rate, 8 bits, lsb is low rate */ +#define AR_PHY_SPUR_REG_MASK_RATE_CNTL (0xFF << 18) +#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18 + +#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000 /* bins move with freq offset */ +#define AR_PHY_SPUR_REG_MASK_RATE_SELECT (0xFF << 9) /* use mask1 or mask2, one per rate */ +#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S 9 +#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100 +#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7F +#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0 + +#define AR_PHY_PILOT_MASK_01_30 0xa3b0 +#define AR_PHY_PILOT_MASK_31_60 0xa3b4 + +#define AR_PHY_CHANNEL_MASK_01_30 0x99d4 +#define AR_PHY_CHANNEL_MASK_31_60 0x99d8 + +#define AR_PHY_CL_CAL_CTL 0xA358 /* carrier leak cal control */ +#define AR_PHY_CL_CAL_ENABLE 0x00000002 +#endif /* _DEV_ATH_AR5416PHY_H_ */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416reg.h b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416reg.h new file mode 100644 index 0000000000..770ec22bab --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar5416reg.h @@ -0,0 +1,506 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar5416reg.h,v 1.10 2008/11/11 00:11:30 sam Exp $ + */ +#ifndef _DEV_ATH_AR5416REG_H +#define _DEV_ATH_AR5416REG_H + +#include "ar5212/ar5212reg.h" + +/* + * Register added starting with the AR5416 + */ +#define AR_MIRT 0x0020 /* interrupt rate threshold */ +#define AR_TIMT 0x0028 /* Tx Interrupt mitigation threshold */ +#define AR_RIMT 0x002C /* Rx Interrupt mitigation threshold */ +#define AR_GTXTO 0x0064 /* global transmit timeout */ +#define AR_GTTM 0x0068 /* global transmit timeout mode */ +#define AR_CST 0x006C /* carrier sense timeout */ +#define AR_MAC_LED 0x1f04 /* LED control */ +#define AR5416_PCIE_PM_CTRL 0x4014 +#define AR_AHB_MODE 0x4024 /* AHB mode for dma */ +#define AR_INTR_SYNC_CAUSE_CLR 0x4028 /* clear interrupt */ +#define AR_INTR_SYNC_CAUSE 0x4028 /* check pending interrupts */ +#define AR_INTR_SYNC_ENABLE 0x402c /* enable interrupts */ +#define AR_INTR_ASYNC_MASK 0x4030 /* asynchronous interrupt mask */ +#define AR_INTR_SYNC_MASK 0x4034 /* synchronous interrupt mask */ +#define AR_INTR_ASYNC_CAUSE 0x4038 /* check pending interrupts */ +#define AR_INTR_ASYNC_ENABLE 0x403c /* enable interrupts */ +#define AR5416_PCIE_SERDES 0x4040 +#define AR5416_PCIE_SERDES2 0x4044 +#define AR_GPIO_IN 0x4048 /* GPIO input register */ +#define AR_GPIO_INTR_OUT 0x404c /* GPIO output register */ +#define AR_EEPROM_STATUS_DATA 0x407c +#define AR_OBS 0x4080 +#define AR_RTC_RC 0x7000 /* reset control */ +#define AR_RTC_PLL_CONTROL 0x7014 +#define AR_RTC_RESET 0x7040 /* RTC reset register */ +#define AR_RTC_STATUS 0x7044 /* system sleep status */ +#define AR_RTC_SLEEP_CLK 0x7048 +#define AR_RTC_FORCE_WAKE 0x704c /* control MAC force wake */ +#define AR_RTC_INTR_CAUSE 0x7050 /* RTC interrupt cause/clear */ +#define AR_RTC_INTR_ENABLE 0x7054 /* RTC interrupt enable */ +#define AR_RTC_INTR_MASK 0x7058 /* RTC interrupt mask */ +/* AR9280: rf long shift registers */ +#define AR_AN_RF2G1_CH0 0x7810 +#define AR_AN_RF5G1_CH0 0x7818 +#define AR_AN_RF2G1_CH1 0x7834 +#define AR_AN_RF5G1_CH1 0x783C +#define AR_AN_TOP2 0x7894 +#define AR_AN_SYNTH9 0x7868 +#define AR9285_AN_RF2G3 0x7828 +#define AR9285_AN_TOP3 0x786c +#define AR_RESET_TSF 0x8020 +#define AR_RXFIFO_CFG 0x8114 +#define AR_PHY_ERR_1 0x812c +#define AR_PHY_ERR_MASK_1 0x8130 /* mask for AR_PHY_ERR_1 */ +#define AR_PHY_ERR_2 0x8134 +#define AR_PHY_ERR_MASK_2 0x8138 /* mask for AR_PHY_ERR_2 */ +#define AR_TSFOOR_THRESHOLD 0x813c +#define AR_PHY_ERR_3 0x8168 +#define AR_PHY_ERR_MASK_3 0x816c /* mask for AR_PHY_ERR_3 */ +#define AR_TXOP_X 0x81ec /* txop for legacy non-qos */ +#define AR_TXOP_0_3 0x81f0 /* txop for various tid's */ +#define AR_TXOP_4_7 0x81f4 +#define AR_TXOP_8_11 0x81f8 +#define AR_TXOP_12_15 0x81fc +/* generic timers based on tsf - all uS */ +#define AR_NEXT_TBTT 0x8200 +#define AR_NEXT_DBA 0x8204 +#define AR_NEXT_SWBA 0x8208 +#define AR_NEXT_CFP 0x8208 +#define AR_NEXT_HCF 0x820C +#define AR_NEXT_TIM 0x8210 +#define AR_NEXT_DTIM 0x8214 +#define AR_NEXT_QUIET 0x8218 +#define AR_NEXT_NDP 0x821C +#define AR5416_BEACON_PERIOD 0x8220 +#define AR_DBA_PERIOD 0x8224 +#define AR_SWBA_PERIOD 0x8228 +#define AR_HCF_PERIOD 0x822C +#define AR_TIM_PERIOD 0x8230 +#define AR_DTIM_PERIOD 0x8234 +#define AR_QUIET_PERIOD 0x8238 +#define AR_NDP_PERIOD 0x823C +#define AR_TIMER_MODE 0x8240 +#define AR_SLP32_MODE 0x8244 +#define AR_SLP32_WAKE 0x8248 +#define AR_SLP32_INC 0x824c +#define AR_SLP_CNT 0x8250 /* 32kHz cycles with mac asleep */ +#define AR_SLP_CYCLE_CNT 0x8254 /* absolute number of 32kHz cycles */ +#define AR_SLP_MIB_CTRL 0x8258 +#define AR_2040_MODE 0x8318 +#define AR_EXTRCCNT 0x8328 /* extension channel rx clear count */ +#define AR_SELFGEN_MASK 0x832c /* rx and cal chain masks */ +#define AR_PCU_TXBUF_CTRL 0x8340 + +/* DMA & PCI Registers in PCI space (usable during sleep)*/ +#define AR_RC_AHB 0x00000001 /* AHB reset */ +#define AR_RC_APB 0x00000002 /* APB reset */ +#define AR_RC_HOSTIF 0x00000100 /* host interface reset */ + +#define AR_MIRT_VAL 0x0000ffff /* in uS */ +#define AR_MIRT_VAL_S 16 + +#define AR_TIMT_LAST 0x0000ffff /* Last packet threshold */ +#define AR_TIMT_LAST_S 0 +#define AR_TIMT_FIRST 0xffff0000 /* First packet threshold */ +#define AR_TIMT_FIRST_S 16 + +#define AR_RIMT_LAST 0x0000ffff /* Last packet threshold */ +#define AR_RIMT_LAST_S 0 +#define AR_RIMT_FIRST 0xffff0000 /* First packet threshold */ +#define AR_RIMT_FIRST_S 16 + +#define AR_GTXTO_TIMEOUT_COUNTER 0x0000FFFF // Mask for timeout counter (in TUs) +#define AR_GTXTO_TIMEOUT_LIMIT 0xFFFF0000 // Mask for timeout limit (in TUs) +#define AR_GTXTO_TIMEOUT_LIMIT_S 16 // Shift for timeout limit + +#define AR_GTTM_USEC 0x00000001 // usec strobe +#define AR_GTTM_IGNORE_IDLE 0x00000002 // ignore channel idle +#define AR_GTTM_RESET_IDLE 0x00000004 // reset counter on channel idle low +#define AR_GTTM_CST_USEC 0x00000008 // CST usec strobe + +#define AR_CST_TIMEOUT_COUNTER 0x0000FFFF // Mask for timeout counter (in TUs) +#define AR_CST_TIMEOUT_LIMIT 0xFFFF0000 // Mask for timeout limit (in TUs) +#define AR_CST_TIMEOUT_LIMIT_S 16 // Shift for timeout limit + +/* MAC tx DMA size config */ +#define AR_TXCFG_DMASZ_MASK 0x00000003 +#define AR_TXCFG_DMASZ_4B 0 +#define AR_TXCFG_DMASZ_8B 1 +#define AR_TXCFG_DMASZ_16B 2 +#define AR_TXCFG_DMASZ_32B 3 +#define AR_TXCFG_DMASZ_64B 4 +#define AR_TXCFG_DMASZ_128B 5 +#define AR_TXCFG_DMASZ_256B 6 +#define AR_TXCFG_DMASZ_512B 7 +#define AR_TXCFG_ATIM_TXPOLICY 0x00000800 + +/* MAC rx DMA size config */ +#define AR_RXCFG_DMASZ_MASK 0x00000007 +#define AR_RXCFG_DMASZ_4B 0 +#define AR_RXCFG_DMASZ_8B 1 +#define AR_RXCFG_DMASZ_16B 2 +#define AR_RXCFG_DMASZ_32B 3 +#define AR_RXCFG_DMASZ_64B 4 +#define AR_RXCFG_DMASZ_128B 5 +#define AR_RXCFG_DMASZ_256B 6 +#define AR_RXCFG_DMASZ_512B 7 + +/* MAC Led registers */ +#define AR_MAC_LED_BLINK_SLOW 0x00000008 /* LED slowest blink rate mode */ +#define AR_MAC_LED_BLINK_THRESH_SEL 0x00000070 /* LED blink threshold select */ +#define AR_MAC_LED_MODE 0x00000380 /* LED mode select */ +#define AR_MAC_LED_MODE_S 7 +#define AR_MAC_LED_MODE_PROP 0 /* Blink prop to filtered tx/rx */ +#define AR_MAC_LED_MODE_RPROP 1 /* Blink prop to unfiltered tx/rx */ +#define AR_MAC_LED_MODE_SPLIT 2 /* Blink power for tx/net for rx */ +#define AR_MAC_LED_MODE_RAND 3 /* Blink randomly */ +#define AR_MAC_LED_MODE_POWON 5 /* Power LED on (s/w control) */ +#define AR_MAC_LED_MODE_NETON 6 /* Network LED on (s/w control) */ +#define AR_MAC_LED_ASSOC 0x00000c00 +#define AR_MAC_LED_ASSOC_NONE 0x00000000 /* STA is not associated or trying */ +#define AR_MAC_LED_ASSOC_ACTIVE 0x00000400 /* STA is associated */ +#define AR_MAC_LED_ASSOC_PEND 0x00000800 /* STA is trying to associate */ +#define AR_MAC_LED_ASSOC_S 10 + +#define AR_AHB_EXACT_WR_EN 0x00000000 /* write exact bytes */ +#define AR_AHB_BUF_WR_EN 0x00000001 /* buffer write upto cacheline*/ +#define AR_AHB_EXACT_RD_EN 0x00000000 /* read exact bytes */ +#define AR_AHB_CACHELINE_RD_EN 0x00000002 /* read upto end of cacheline */ +#define AR_AHB_PREFETCH_RD_EN 0x00000004 /* prefetch upto page boundary*/ +#define AR_AHB_PAGE_SIZE_1K 0x00000000 /* set page-size as 1k */ +#define AR_AHB_PAGE_SIZE_2K 0x00000008 /* set page-size as 2k */ +#define AR_AHB_PAGE_SIZE_4K 0x00000010 /* set page-size as 4k */ + +/* MAC PCU Registers */ +#define AR_STA_ID1_PRESERVE_SEQNUM 0x20000000 /* Don't replace seq num */ + +/* Extended PCU DIAG_SW control fields */ +#define AR_DIAG_DUAL_CHAIN_INFO 0x01000000 /* dual chain channel info */ +#define AR_DIAG_RX_ABORT 0x02000000 /* abort rx */ +#define AR_DIAG_SATURATE_CCNT 0x04000000 /* sat. cycle cnts (no shift) */ +#define AR_DIAG_OBS_PT_SEL2 0x08000000 /* observation point sel */ +#define AR_DIAG_RXCLEAR_CTL_LOW 0x10000000 /* force rx_clear(ctl) low/busy */ +#define AR_DIAG_RXCLEAR_EXT_LOW 0x20000000 /* force rx_clear(ext) low/busy */ + +#define AR_TXOP_X_VAL 0x000000FF + +#define AR_RESET_TSF_ONCE 0x01000000 /* reset tsf once; self-clears*/ + +/* Interrupts */ +#define AR_ISR_TXMINTR 0x00080000 /* Maximum interrupt tx rate */ +#define AR_ISR_RXMINTR 0x01000000 /* Maximum interrupt rx rate */ +#define AR_ISR_TXINTM 0x40000000 /* Tx int after mitigation */ +#define AR_ISR_RXINTM 0x80000000 /* Rx int after mitigation */ + +#define AR_ISR_S2_CST 0x00400000 /* Carrier sense timeout */ +#define AR_ISR_S2_GTT 0x00800000 /* Global transmit timeout */ +#define AR_ISR_S2_TSFOOR 0x40000000 /* RX TSF out of range */ + +#define AR_INTR_SPURIOUS 0xffffffff +#define AR_INTR_RTC_IRQ 0x00000001 /* rtc in shutdown state */ +#define AR_INTR_MAC_IRQ 0x00000002 /* pending mac interrupt */ +#define AR_INTR_EEP_PROT_ACCESS 0x00000004 /* eeprom protected access */ +#define AR_INTR_MAC_AWAKE 0x00020000 /* mac is awake */ +#define AR_INTR_MAC_ASLEEP 0x00040000 /* mac is asleep */ + +/* Interrupt Mask Registers */ +#define AR_IMR_TXMINTR 0x00080000 /* Maximum interrupt tx rate */ +#define AR_IMR_RXMINTR 0x01000000 /* Maximum interrupt rx rate */ +#define AR_IMR_TXINTM 0x40000000 /* Tx int after mitigation */ +#define AR_IMR_RXINTM 0x80000000 /* Rx int after mitigation */ + +#define AR_IMR_S2_CST 0x00400000 /* Carrier sense timeout */ +#define AR_IMR_S2_GTT 0x00800000 /* Global transmit timeout */ + +/* synchronous interrupt signals */ +#define AR_INTR_SYNC_RTC_IRQ 0x00000001 +#define AR_INTR_SYNC_MAC_IRQ 0x00000002 +#define AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS 0x00000004 +#define AR_INTR_SYNC_APB_TIMEOUT 0x00000008 +#define AR_INTR_SYNC_PCI_MODE_CONFLICT 0x00000010 +#define AR_INTR_SYNC_HOST1_FATAL 0x00000020 +#define AR_INTR_SYNC_HOST1_PERR 0x00000040 +#define AR_INTR_SYNC_TRCV_FIFO_PERR 0x00000080 +#define AR_INTR_SYNC_RADM_CPL_EP 0x00000100 +#define AR_INTR_SYNC_RADM_CPL_DLLP_ABORT 0x00000200 +#define AR_INTR_SYNC_RADM_CPL_TLP_ABORT 0x00000400 +#define AR_INTR_SYNC_RADM_CPL_ECRC_ERR 0x00000800 +#define AR_INTR_SYNC_RADM_CPL_TIMEOUT 0x00001000 +#define AR_INTR_SYNC_LOCAL_TIMEOUT 0x00002000 +#define AR_INTR_SYNC_PM_ACCESS 0x00004000 +#define AR_INTR_SYNC_MAC_AWAKE 0x00008000 +#define AR_INTR_SYNC_MAC_ASLEEP 0x00010000 +#define AR_INTR_SYNC_MAC_SLEEP_ACCESS 0x00020000 +#define AR_INTR_SYNC_ALL 0x0003FFFF + +/* default synchronous interrupt signals enabled */ +#define AR_INTR_SYNC_DEFAULT \ + (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR | \ + AR_INTR_SYNC_RADM_CPL_EP | AR_INTR_SYNC_RADM_CPL_DLLP_ABORT | \ + AR_INTR_SYNC_RADM_CPL_TLP_ABORT | AR_INTR_SYNC_RADM_CPL_ECRC_ERR | \ + AR_INTR_SYNC_RADM_CPL_TIMEOUT | AR_INTR_SYNC_LOCAL_TIMEOUT | \ + AR_INTR_SYNC_MAC_SLEEP_ACCESS) + +/* RTC registers */ +#define AR_RTC_RC_M 0x00000003 +#define AR_RTC_RC_MAC_WARM 0x00000001 +#define AR_RTC_RC_MAC_COLD 0x00000002 +#define AR_RTC_PLL_DIV 0x0000001f +#define AR_RTC_PLL_DIV_S 0 +#define AR_RTC_PLL_DIV2 0x00000020 +#define AR_RTC_PLL_REFDIV_5 0x000000c0 + +#define AR_RTC_SOWL_PLL_DIV 0x000003ff +#define AR_RTC_SOWL_PLL_DIV_S 0 +#define AR_RTC_SOWL_PLL_REFDIV 0x00003C00 +#define AR_RTC_SOWL_PLL_REFDIV_S 10 +#define AR_RTC_SOWL_PLL_CLKSEL 0x0000C000 +#define AR_RTC_SOWL_PLL_CLKSEL_S 14 + +#define AR_RTC_RESET_EN 0x00000001 /* Reset RTC bit */ + +#define AR_RTC_PM_STATUS_M 0x0000000f /* Pwr Mgmt Status */ +#define AR_RTC_STATUS_M 0x0000003f /* RTC Status */ +#define AR_RTC_STATUS_SHUTDOWN 0x00000001 +#define AR_RTC_STATUS_ON 0x00000002 +#define AR_RTC_STATUS_SLEEP 0x00000004 +#define AR_RTC_STATUS_WAKEUP 0x00000008 +#define AR_RTC_STATUS_COLDRESET 0x00000010 /* Not currently used */ +#define AR_RTC_STATUS_PLLCHANGE 0x00000020 /* Not currently used */ + +#define AR_RTC_SLEEP_DERIVED_CLK 0x2 + +#define AR_RTC_FORCE_WAKE_EN 0x00000001 /* enable force wake */ +#define AR_RTC_FORCE_WAKE_ON_INT 0x00000002 /* auto-wake on MAC interrupt */ + +#define AR_RTC_PLL_CLKSEL 0x00000300 +#define AR_RTC_PLL_CLKSEL_S 8 + +/* AR9280: rf long shift registers */ +#define AR_AN_RF2G1_CH0_OB 0x03800000 +#define AR_AN_RF2G1_CH0_OB_S 23 +#define AR_AN_RF2G1_CH0_DB 0x1C000000 +#define AR_AN_RF2G1_CH0_DB_S 26 + +#define AR_AN_RF5G1_CH0_OB5 0x00070000 +#define AR_AN_RF5G1_CH0_OB5_S 16 +#define AR_AN_RF5G1_CH0_DB5 0x00380000 +#define AR_AN_RF5G1_CH0_DB5_S 19 + +#define AR_AN_RF2G1_CH1_OB 0x03800000 +#define AR_AN_RF2G1_CH1_OB_S 23 +#define AR_AN_RF2G1_CH1_DB 0x1C000000 +#define AR_AN_RF2G1_CH1_DB_S 26 + +#define AR_AN_RF5G1_CH1_OB5 0x00070000 +#define AR_AN_RF5G1_CH1_OB5_S 16 +#define AR_AN_RF5G1_CH1_DB5 0x00380000 +#define AR_AN_RF5G1_CH1_DB5_S 19 + +#define AR_AN_TOP2_XPABIAS_LVL 0xC0000000 +#define AR_AN_TOP2_XPABIAS_LVL_S 30 +#define AR_AN_TOP2_LOCALBIAS 0x00200000 +#define AR_AN_TOP2_LOCALBIAS_S 21 +#define AR_AN_TOP2_PWDCLKIND 0x00400000 +#define AR_AN_TOP2_PWDCLKIND_S 22 + +#define AR_AN_SYNTH9_REFDIVA 0xf8000000 +#define AR_AN_SYNTH9_REFDIVA_S 27 + +/* AR9285 Analog registers */ +#define AR9285_AN_RF2G3_OB_0 0x00E00000 +#define AR9285_AN_RF2G3_OB_0_S 21 +#define AR9285_AN_RF2G3_OB_1 0x001C0000 +#define AR9285_AN_RF2G3_OB_1_S 18 +#define AR9285_AN_RF2G3_OB_2 0x00038000 +#define AR9285_AN_RF2G3_OB_2_S 15 +#define AR9285_AN_RF2G3_OB_3 0x00007000 +#define AR9285_AN_RF2G3_OB_3_S 12 +#define AR9285_AN_RF2G3_OB_4 0x00000E00 +#define AR9285_AN_RF2G3_OB_4_S 9 + +#define AR9285_AN_RF2G3_DB1_0 0x000001C0 +#define AR9285_AN_RF2G3_DB1_0_S 6 +#define AR9285_AN_RF2G3_DB1_1 0x00000038 +#define AR9285_AN_RF2G3_DB1_1_S 3 +#define AR9285_AN_RF2G3_DB1_2 0x00000007 +#define AR9285_AN_RF2G3_DB1_2_S 0 +#define AR9285_AN_RF2G4 0x782C +#define AR9285_AN_RF2G4_DB1_3 0xE0000000 +#define AR9285_AN_RF2G4_DB1_3_S 29 +#define AR9285_AN_RF2G4_DB1_4 0x1C000000 +#define AR9285_AN_RF2G4_DB1_4_S 26 + +#define AR9285_AN_RF2G4_DB2_0 0x03800000 +#define AR9285_AN_RF2G4_DB2_0_S 23 +#define AR9285_AN_RF2G4_DB2_1 0x00700000 +#define AR9285_AN_RF2G4_DB2_1_S 20 +#define AR9285_AN_RF2G4_DB2_2 0x000E0000 +#define AR9285_AN_RF2G4_DB2_2_S 17 +#define AR9285_AN_RF2G4_DB2_3 0x0001C000 +#define AR9285_AN_RF2G4_DB2_3_S 14 +#define AR9285_AN_RF2G4_DB2_4 0x00003800 +#define AR9285_AN_RF2G4_DB2_4_S 11 + +#define AR9285_AN_TOP3_XPABIAS_LVL 0x0000000C +#define AR9285_AN_TOP3_XPABIAS_LVL_S 2 + +/* Sleep control */ +#define AR5416_SLEEP1_CAB_TIMEOUT 0xFFE00000 /* Cab timeout (TU) */ +#define AR5416_SLEEP1_CAB_TIMEOUT_S 22 + +#define AR5416_SLEEP2_BEACON_TIMEOUT 0xFFE00000 /* Beacon timeout (TU)*/ +#define AR5416_SLEEP2_BEACON_TIMEOUT_S 22 + +/* Sleep Registers */ +#define AR_SLP32_HALFCLK_LATENCY 0x000FFFFF /* rising <-> falling edge */ +#define AR_SLP32_ENA 0x00100000 +#define AR_SLP32_TSF_WRITE_STATUS 0x00200000 /* tsf update in progress */ + +#define AR_SLP32_WAKE_XTL_TIME 0x0000FFFF /* time to wake crystal */ + +#define AR_SLP32_TST_INC 0x000FFFFF + +#define AR_SLP_MIB_CLEAR 0x00000001 /* clear pending */ +#define AR_SLP_MIB_PENDING 0x00000002 /* clear counters */ + +#define AR_TIMER_MODE_TBTT 0x00000001 +#define AR_TIMER_MODE_DBA 0x00000002 +#define AR_TIMER_MODE_SWBA 0x00000004 +#define AR_TIMER_MODE_HCF 0x00000008 +#define AR_TIMER_MODE_TIM 0x00000010 +#define AR_TIMER_MODE_DTIM 0x00000020 +#define AR_TIMER_MODE_QUIET 0x00000040 +#define AR_TIMER_MODE_NDP 0x00000080 +#define AR_TIMER_MODE_OVERFLOW_INDEX 0x00000700 +#define AR_TIMER_MODE_OVERFLOW_INDEX_S 8 +#define AR_TIMER_MODE_THRESH 0xFFFFF000 +#define AR_TIMER_MODE_THRESH_S 12 + +/* PCU Misc modes */ +#define AR_PCU_FORCE_BSSID_MATCH 0x00000001 /* force bssid to match */ +#define AR_PCU_MIC_NEW_LOC_ENA 0x00000004 /* tx/rx mic keys together */ +#define AR_PCU_TX_ADD_TSF 0x00000008 /* add tx_tsf + int_tsf */ +#define AR_PCU_CCK_SIFS_MODE 0x00000010 /* assume 11b sifs */ +#define AR_PCU_RX_ANT_UPDT 0x00000800 /* KC_RX_ANT_UPDATE */ +#define AR_PCU_TXOP_TBTT_LIMIT_ENA 0x00001000 /* enforce txop / tbtt */ +#define AR_PCU_MISS_BCN_IN_SLEEP 0x00004000 /* count bmiss's when sleeping */ +#define AR_PCU_BUG_12306_FIX_ENA 0x00020000 /* use rx_clear to count sifs */ +#define AR_PCU_FORCE_QUIET_COLL 0x00040000 /* kill xmit for channel change */ +#define AR_PCU_TBTT_PROTECT 0x00200000 /* no xmit upto tbtt+20 uS */ +#define AR_PCU_CLEAR_VMF 0x01000000 /* clear vmf mode (fast cc)*/ +#define AR_PCU_CLEAR_BA_VALID 0x04000000 /* clear ba state */ + +/* GPIO Interrupt */ +#define AR_INTR_GPIO 0x3FF00000 /* gpio interrupted */ +#define AR_INTR_GPIO_S 20 + +#define AR_GPIO_OUT_CTRL 0x000003FF /* 0 = out, 1 = in */ +#define AR_GPIO_OUT_VAL 0x000FFC00 +#define AR_GPIO_OUT_VAL_S 10 +#define AR_GPIO_INTR_CTRL 0x3FF00000 +#define AR_GPIO_INTR_CTRL_S 20 + +#define AR_2040_JOINED_RX_CLEAR 0x00000001 /* use ctl + ext rx_clear for cca */ + +#define AR_PCU_TXBUF_CTRL_SIZE_MASK 0x7FF +#define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700 + +/* Eeprom defines */ +#define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff +#define AR_EEPROM_STATUS_DATA_VAL_S 0 +#define AR_EEPROM_STATUS_DATA_BUSY 0x00010000 +#define AR_EEPROM_STATUS_DATA_BUSY_ACCESS 0x00020000 +#define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000 +#define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000 + +#define AR_SREV_REVISION_OWL_10 0x08 +#define AR_SREV_REVISION_OWL_20 0x09 +#define AR_SREV_REVISION_OWL_22 0x0a + +#define AR_RAD5133_SREV_MAJOR 0xc0 /* Fowl: 2+5G/3x3 */ +#define AR_RAD2133_SREV_MAJOR 0xd0 /* Fowl: 2G/3x3 */ +#define AR_RAD5122_SREV_MAJOR 0xe0 /* Fowl: 5G/2x2 */ +#define AR_RAD2122_SREV_MAJOR 0xf0 /* Fowl: 2+5G/2x2 */ + +/* Test macro for owl 1.0 */ +#define IS_5416V1(_ah) ((_ah)->ah_macRev == AR_SREV_REVISION_OWL_10) +#define IS_5416V2(_ah) ((_ah)->ah_macRev >= AR_SREV_REVISION_OWL_20) +#define IS_5416V2_2(_ah) ((_ah)->ah_macRev == AR_SREV_REVISION_OWL_22) + +/* Expanded Mac Silicon Rev (16 bits starting with Sowl) */ +#define AR_XSREV_ID 0xFFFFFFFF /* Chip ID */ +#define AR_XSREV_ID_S 0 +#define AR_XSREV_VERSION 0xFFFC0000 /* Chip version */ +#define AR_XSREV_VERSION_S 18 +#define AR_XSREV_TYPE 0x0003F000 /* Chip type */ +#define AR_XSREV_TYPE_S 12 +#define AR_XSREV_TYPE_CHAIN 0x00001000 /* Chain Mode (1:3 chains, + * 0:2 chains) */ +#define AR_XSREV_TYPE_HOST_MODE 0x00002000 /* Host Mode (1:PCI, 0:PCIe) */ +#define AR_XSREV_REVISION 0x00000F00 +#define AR_XSREV_REVISION_S 8 + +#define AR_XSREV_VERSION_OWL_PCI 0x0D +#define AR_XSREV_VERSION_OWL_PCIE 0x0C +#define AR_XSREV_REVISION_OWL_10 0 /* Owl 1.0 */ +#define AR_XSREV_REVISION_OWL_20 1 /* Owl 2.0/2.1 */ +#define AR_XSREV_REVISION_OWL_22 2 /* Owl 2.2 */ +#define AR_XSREV_VERSION_SOWL 0x40 +#define AR_XSREV_REVISION_SOWL_10 0 /* Sowl 1.0 */ +#define AR_XSREV_REVISION_SOWL_11 1 /* Sowl 1.1 */ +#define AR_XSREV_VERSION_MERLIN 0x80 /* Merlin Version */ +#define AR_XSREV_REVISION_MERLIN_10 0 /* Merlin 1.0 */ +#define AR_XSREV_REVISION_MERLIN_20 1 /* Merlin 2.0 */ +#define AR_XSREV_REVISION_MERLIN_21 2 /* Merlin 2.1 */ +#define AR_XSREV_VERSION_KITE 0xC0 /* Kite Version */ +#define AR_XSREV_REVISION_KITE_10 0 /* Kite 1.0 */ + +#define AR_SREV_OWL_20_OR_LATER(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_SOWL || \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_OWL_20) +#define AR_SREV_OWL_22_OR_LATER(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_SOWL || \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_OWL_22) + +#define AR_SREV_SOWL(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_SOWL) +#define AR_SREV_SOWL_10_OR_LATER(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_SOWL) +#define AR_SREV_SOWL_11(_ah) \ + (AR_SREV_SOWL(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_SOWL_11) + +#define AR_SREV_MERLIN(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_MERLIN) +#define AR_SREV_MERLIN_10_OR_LATER(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_MERLIN) +#define AR_SREV_MERLIN_20(_ah) \ + (AR_SREV_MERLIN(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_MERLIN_20) +#define AR_SREV_MERLIN_20_OR_LATER(_ah) \ + (AR_SREV_MERLIN_20(_ah) || \ + AH_PRIVATE((_ah))->ah_macVersion > AR_XSREV_VERSION_MERLIN) + +#define AR_SREV_KITE(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_KITE) +#define AR_SREV_KITE_10_OR_LATER(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_KITE) +#endif /* _DEV_ATH_AR5416REG_H */ diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar9160.ini b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar9160.ini new file mode 100644 index 0000000000..85f09a32cc --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar9160.ini @@ -0,0 +1,699 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar9160.ini,v 1.5 2008/11/10 04:08:05 sam Exp $ + */ +/* Auto Generated PCI Register Writes. Created: 05/22/08 */ + +static const uint32_t ar9160Modes[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, + { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 }, + { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, + { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, + { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, + { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, + { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, + { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, + { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, + { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, + { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce }, + { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 }, + { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, + { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, + { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, + { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, + { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, + { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, + { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, + { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, + { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, + { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, + { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, + { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, + { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, + { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +static const uint32_t ar9160Common[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00007010, 0x00000020 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04800 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0x00000000 }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081d0, 0x00003210 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x00008300, 0x00000000 }, + { 0x00008304, 0x00000000 }, + { 0x00008308, 0x00000000 }, + { 0x0000830c, 0x00000000 }, + { 0x00008310, 0x00000000 }, + { 0x00008314, 0x00000000 }, + { 0x00008318, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00000000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xad848e19 }, + { 0x00009810, 0x7d14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x00009840, 0x206a01ae }, + { 0x0000984c, 0x1284233c }, + { 0x00009854, 0x00000859 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x05100000 }, + { 0x0000a920, 0x05100000 }, + { 0x0000b920, 0x05100000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280b212 }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5f3ca3de }, + { 0x00009958, 0x2108ecff }, + { 0x00009940, 0x00750604 }, + { 0x0000c95c, 0x004b6a8e }, + { 0x00009970, 0x190fb515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x006f0000 }, + { 0x000099b0, 0x03051000 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000200 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099fc, 0x00001042 }, + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b28, 0x0000000c }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b38, 0x00000012 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b64, 0x00000021 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b8c, 0x0000002d }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009b9c, 0x00000033 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, + { 0x0000a210, 0x40806333 }, + { 0x0000a214, 0x00106c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x018830c6 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x001a0bb5 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889af }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000001 }, + { 0x0000a26c, 0x0ebae9c6 }, + { 0x0000b26c, 0x0ebae9c6 }, + { 0x0000c26c, 0x0ebae9c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x050701ce }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa33 }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, +}; + +static const uint32_t ar9160Bank0[][2] = { + { 0x000098b0, 0x1e5795e5 }, + { 0x000098e0, 0x02008020 }, +}; + +static const uint32_t ar9160BB_RfGain[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000040, 0x00000040 }, + { 0x00009a08, 0x00000080, 0x00000080 }, + { 0x00009a0c, 0x000001a1, 0x00000141 }, + { 0x00009a10, 0x000001e1, 0x00000181 }, + { 0x00009a14, 0x00000021, 0x000001c1 }, + { 0x00009a18, 0x00000061, 0x00000001 }, + { 0x00009a1c, 0x00000168, 0x00000041 }, + { 0x00009a20, 0x000001a8, 0x000001a8 }, + { 0x00009a24, 0x000001e8, 0x000001e8 }, + { 0x00009a28, 0x00000028, 0x00000028 }, + { 0x00009a2c, 0x00000068, 0x00000068 }, + { 0x00009a30, 0x00000189, 0x000000a8 }, + { 0x00009a34, 0x000001c9, 0x00000169 }, + { 0x00009a38, 0x00000009, 0x000001a9 }, + { 0x00009a3c, 0x00000049, 0x000001e9 }, + { 0x00009a40, 0x00000089, 0x00000029 }, + { 0x00009a44, 0x00000170, 0x00000069 }, + { 0x00009a48, 0x000001b0, 0x00000190 }, + { 0x00009a4c, 0x000001f0, 0x000001d0 }, + { 0x00009a50, 0x00000030, 0x00000010 }, + { 0x00009a54, 0x00000070, 0x00000050 }, + { 0x00009a58, 0x00000191, 0x00000090 }, + { 0x00009a5c, 0x000001d1, 0x00000151 }, + { 0x00009a60, 0x00000011, 0x00000191 }, + { 0x00009a64, 0x00000051, 0x000001d1 }, + { 0x00009a68, 0x00000091, 0x00000011 }, + { 0x00009a6c, 0x000001b8, 0x00000051 }, + { 0x00009a70, 0x000001f8, 0x00000198 }, + { 0x00009a74, 0x00000038, 0x000001d8 }, + { 0x00009a78, 0x00000078, 0x00000018 }, + { 0x00009a7c, 0x00000199, 0x00000058 }, + { 0x00009a80, 0x000001d9, 0x00000098 }, + { 0x00009a84, 0x00000019, 0x00000159 }, + { 0x00009a88, 0x00000059, 0x00000199 }, + { 0x00009a8c, 0x00000099, 0x000001d9 }, + { 0x00009a90, 0x000000d9, 0x00000019 }, + { 0x00009a94, 0x000000f9, 0x00000059 }, + { 0x00009a98, 0x000000f9, 0x00000099 }, + { 0x00009a9c, 0x000000f9, 0x000000d9 }, + { 0x00009aa0, 0x000000f9, 0x000000f9 }, + { 0x00009aa4, 0x000000f9, 0x000000f9 }, + { 0x00009aa8, 0x000000f9, 0x000000f9 }, + { 0x00009aac, 0x000000f9, 0x000000f9 }, + { 0x00009ab0, 0x000000f9, 0x000000f9 }, + { 0x00009ab4, 0x000000f9, 0x000000f9 }, + { 0x00009ab8, 0x000000f9, 0x000000f9 }, + { 0x00009abc, 0x000000f9, 0x000000f9 }, + { 0x00009ac0, 0x000000f9, 0x000000f9 }, + { 0x00009ac4, 0x000000f9, 0x000000f9 }, + { 0x00009ac8, 0x000000f9, 0x000000f9 }, + { 0x00009acc, 0x000000f9, 0x000000f9 }, + { 0x00009ad0, 0x000000f9, 0x000000f9 }, + { 0x00009ad4, 0x000000f9, 0x000000f9 }, + { 0x00009ad8, 0x000000f9, 0x000000f9 }, + { 0x00009adc, 0x000000f9, 0x000000f9 }, + { 0x00009ae0, 0x000000f9, 0x000000f9 }, + { 0x00009ae4, 0x000000f9, 0x000000f9 }, + { 0x00009ae8, 0x000000f9, 0x000000f9 }, + { 0x00009aec, 0x000000f9, 0x000000f9 }, + { 0x00009af0, 0x000000f9, 0x000000f9 }, + { 0x00009af4, 0x000000f9, 0x000000f9 }, + { 0x00009af8, 0x000000f9, 0x000000f9 }, + { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; + +static const uint32_t ar9160Bank1[][2] = { + { 0x000098b0, 0x02108421 }, + { 0x000098ec, 0x00000008 }, +}; + +static const uint32_t ar9160Bank2[][2] = { + { 0x000098b0, 0x0e73ff17 }, + { 0x000098e0, 0x00000420 }, +}; + +static const uint32_t ar9160Bank3[][3] = { + { 0x000098f0, 0x01400018, 0x01c00018 }, +}; + +static const uint32_t ar9160Bank6[][3] = { +/* Reg A G */ + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x004210a2, 0x004210a2 }, + { 0x0000989c, 0x0014008f, 0x0014008f }, + { 0x0000989c, 0x00c40003, 0x00c40003 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000f1, 0x000000f1 }, + { 0x0000989c, 0x00002081, 0x00002081 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const uint32_t ar9160Bank6TPC[][3] = { + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x00423022, 0x00423022 }, + { 0x0000989c, 0x2014008f, 0x2014008f }, + { 0x0000989c, 0x00c40002, 0x00c40002 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000e1, 0x000000e1 }, + { 0x0000989c, 0x00007080, 0x00007080 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const uint32_t ar9160Bank7[][2] = { + { 0x0000989c, 0x00000500 }, + { 0x0000989c, 0x00000800 }, + { 0x000098cc, 0x0000000e }, +}; + +/* Auto generated PCI Register Writes for SOWL1.0 ADDAC Shift Chain */ +static const uint32_t ar9160Addac[][2] = { + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000018 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000019 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000003 }, + {0x0000989c, 0x00000008 }, + {0x0000989c, 0x00000000 }, + {0x000098cc, 0x00000000 }, +}; + +/* Auto generated PCI Register Writes for SOWL1.1 ADDAC Shift Chain */ +static const uint32_t ar9160Addac_1_1[][2] = { + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000018 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000019 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x000098cc, 0x00000000 }, +}; diff --git a/sys/dev/netif/ath/hal/ath_hal/ar5416/ar9160_attach.c b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar9160_attach.c new file mode 100644 index 0000000000..f92c3a60f0 --- /dev/null +++ b/sys/dev/netif/ath/hal/ath_hal/ar5416/ar9160_attach.c @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ar9160_attach.c,v 1.14 2008/11/27 22:30:08 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#include "ar5416/ar9160.ini" + +static const HAL_PERCAL_DATA ar9160_iq_cal = { /* multi sample */ + .calName = "IQ", .calType = IQ_MISMATCH_CAL, + .calNumSamples = MAX_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416IQCalCollect, + .calPostProc = ar5416IQCalibration +}; +static const HAL_PERCAL_DATA ar9160_adc_gain_cal = { /* multi sample */ + .calName = "ADC Gain", .calType = ADC_GAIN_CAL, + .calNumSamples = MAX_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416AdcGainCalCollect, + .calPostProc = ar5416AdcGainCalibration +}; +static const HAL_PERCAL_DATA ar9160_adc_dc_cal = { /* multi sample */ + .calName = "ADC DC", .calType = ADC_DC_CAL, + .calNumSamples = MAX_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416AdcDcCalCollect, + .calPostProc = ar5416AdcDcCalibration +}; +static const HAL_PERCAL_DATA ar9160_adc_init_dc_cal = { + .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = INIT_LOG_COUNT, + .calCollect = ar5416AdcDcCalCollect, + .calPostProc = ar5416AdcDcCalibration +}; + +struct ath_hal *ar9160Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status); +static void ar9160Detach(struct ath_hal *); +static HAL_BOOL ar9160FillCapabilityInfo(struct ath_hal *ah); + +static void +ar9160AniSetup(struct ath_hal *ah) +{ + static const struct ar5212AniParams aniparams = { + .maxNoiseImmunityLevel = 4, /* levels 0..4 */ + .totalSizeDesired = { -55, -55, -55, -55, -62 }, + .coarseHigh = { -14, -14, -14, -14, -12 }, + .coarseLow = { -64, -64, -64, -64, -70 }, + .firpwr = { -78, -78, -78, -78, -80 }, + .maxSpurImmunityLevel = 2, + .cycPwrThr1 = { 2, 4, 6 }, + .maxFirstepLevel = 2, /* levels 0..2 */ + .firstep = { 0, 4, 8 }, + .ofdmTrigHigh = 500, + .ofdmTrigLow = 200, + .cckTrigHigh = 200, + .cckTrigLow = 100, + .rssiThrHigh = 40, + .rssiThrLow = 7, + .period = 100, + }; + /* NB: ANI is not enabled yet */ + ar5212AniAttach(ah, &aniparams, &aniparams, AH_FALSE); +} + +/* + * Attach for an AR9160 part. + */ +struct ath_hal * +ar9160Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) +{ + struct ath_hal_5416 *ahp5416; + struct ath_hal_5212 *ahp; + struct ath_hal *ah; + uint32_t val; + HAL_STATUS ecode; + HAL_BOOL rfStatus; + + HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + __func__, sc, (void*) st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416)); + if (ahp5416 == AH_NULL) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot allocate memory for state block\n", __func__); + *status = HAL_ENOMEM; + return AH_NULL; + } + ar5416InitState(ahp5416, devid, sc, st, sh, status); + ahp = &ahp5416->ah_5212; + ah = &ahp->ah_priv.h; + + /* XXX override with 9160 specific state */ + /* override 5416 methods for our needs */ + ah->ah_detach = ar9160Detach; + + AH5416(ah)->ah_cal.iqCalData.calData = &ar9160_iq_cal; + AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9160_adc_gain_cal; + AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9160_adc_dc_cal; + AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9160_adc_init_dc_cal; + AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; + + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { + /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + + if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + /* Read Revisions from Chips before taking out of reset */ + val = OS_REG_READ(ah, AR_SREV); + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n", + __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION), + MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION)); + /* NB: include chip type to differentiate from pre-Sowl versions */ + AH_PRIVATE(ah)->ah_macVersion = + (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S; + AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION); + /* XXX extract pcie info */ + + /* setup common ini data; rf backends handle remainder */ + HAL_INI_INIT(&ahp->ah_ini_modes, ar9160Modes, 6); + HAL_INI_INIT(&ahp->ah_ini_common, ar9160Common, 2); + + HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar9160BB_RfGain, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar9160Bank0, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar9160Bank1, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar9160Bank2, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar9160Bank3, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar9160Bank6, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar9160Bank7, 2); + if (AR_SREV_SOWL_11(ah)) + HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar9160Addac_1_1, 2); + else + HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar9160Addac, 2); + + if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + ecode = HAL_EIO; + goto bad; + } + + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); + + if (!ar5212ChipTest(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", + __func__); + ecode = HAL_ESELFTEST; + goto bad; + } + + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* Read Radio Chip Rev Extract */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah); + switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { + case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */ + case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */ + break; + default: + if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD5133_SREV_MAJOR; + break; + } +#ifdef AH_DEBUG + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5G Radio Chip Rev 0x%02X is not supported by " + "this driver\n", __func__, + AH_PRIVATE(ah)->ah_analog5GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; +#endif + } + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: Attaching AR2133 radio\n", + __func__); + rfStatus = ar2133RfAttach(ah, &ecode); + if (!rfStatus) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", + __func__, ecode); + goto bad; + } + + ecode = ath_hal_v14EepromAttach(ah); + if (ecode != HAL_OK) + goto bad; + + /* + * Got everything we need now to setup the capabilities. + */ + if (!ar9160FillCapabilityInfo(ah)) { + ecode = HAL_EEREAD; + goto bad; + } + + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error getting mac address from EEPROM\n", __func__); + goto bad; + } + /* XXX How about the serial number ? */ + /* Read Reg Domain */ + AH_PRIVATE(ah)->ah_currentRD = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); + + /* + * ah_miscMode is populated by ar5416FillCapabilityInfo() + * starting from griffin. Set here to make sure that + * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is + * placed into hardware. + */ + if (ahp->ah_miscMode != 0) + OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + + ar9160AniSetup(ah); /* Anti Noise Immunity */ + ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); + + return ah; +bad: + if (ahp) + ar9160Detach((struct ath_hal *) ahp); + if (status) + *status = ecode; + return AH_NULL; +} + +void +ar9160Detach(struct ath_hal *ah) +{ + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__); + + HALASSERT(ah != AH_NULL); + HALASSERT(ah->ah_magic == AR5416_MAGIC); + + ar5416Detach(ah); +} + +/* + * Fill all software cached or static hardware state information. + * Return failure if capabilities are to come from EEPROM and + * cannot be read. + */ +static HAL_BOOL +ar9160FillCapabilityInfo(struct ath_hal *ah) +{ + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + if (!ar5416FillCapabilityInfo(ah)) + return AH_FALSE; + pCap->halCSTSupport = AH_TRUE; + pCap->halRifsRxSupport = AH_TRUE; + pCap->halRifsTxSupport = AH_TRUE; + pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ + pCap->halExtChanDfsSupport = AH_TRUE; + pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ + return AH_TRUE; +} + +static const char* +ar9160Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID && devid == AR9160_DEVID_PCI) + return "Atheros 9160"; + return AH_NULL; +} +AH_CHIP(AR9160, ar9160Probe, ar9160Attach); diff --git a/sys/dev/netif/ath/rate_amrr/amrr.c b/sys/dev/netif/ath/rate_amrr/amrr.c index 73f1748764..3dff3ec052 100644 --- a/sys/dev/netif/ath/rate_amrr/amrr.c +++ b/sys/dev/netif/ath/rate_amrr/amrr.c @@ -67,7 +67,7 @@ #include #include -#include +#include #define AMRR_DEBUG #ifdef AMRR_DEBUG diff --git a/sys/dev/netif/ath/rate_onoe/onoe.c b/sys/dev/netif/ath/rate_onoe/onoe.c index d011e46c64..9e1dedc3a4 100644 --- a/sys/dev/netif/ath/rate_onoe/onoe.c +++ b/sys/dev/netif/ath/rate_onoe/onoe.c @@ -64,7 +64,7 @@ #include #include -#include +#include #define ONOE_DEBUG #ifdef ONOE_DEBUG diff --git a/sys/dev/netif/ath/rate_sample/Makefile b/sys/dev/netif/ath/rate_sample/Makefile index db2ee638ae..fb7e7903bf 100644 --- a/sys/dev/netif/ath/rate_sample/Makefile +++ b/sys/dev/netif/ath/rate_sample/Makefile @@ -39,7 +39,7 @@ KMOD = ath_rate SRCS = sample.c -SRCS += device_if.h bus_if.h pci_if.h +SRCS += device_if.h bus_if.h pci_if.h opt_ah.h KMODDEPS = wlan ath_hal diff --git a/sys/dev/netif/ath/rate_sample/sample.c b/sys/dev/netif/ath/rate_sample/sample.c index 16ad29f2f9..920a0048f2 100644 --- a/sys/dev/netif/ath/rate_sample/sample.c +++ b/sys/dev/netif/ath/rate_sample/sample.c @@ -62,7 +62,7 @@ #include #include -#include +#include #define SAMPLE_DEBUG #ifdef SAMPLE_DEBUG diff --git a/sys/dev/raid/aac/aac.c b/sys/dev/raid/aac/aac.c index 1948710425..4a57bbd5ad 100644 --- a/sys/dev/raid/aac/aac.c +++ b/sys/dev/raid/aac/aac.c @@ -309,7 +309,7 @@ aac_attach(struct aac_softc *sc) } if (sc->flags & AAC_FLAGS_NEW_COMM) { if (bus_setup_intr(sc->aac_dev, sc->aac_irq, - INTR_MPSAFE, aac_new_intr, + 0, aac_new_intr, sc, &sc->aac_intr, NULL)) { device_printf(sc->aac_dev, "can't set up interrupt\n"); return (EINVAL); @@ -321,7 +321,7 @@ aac_attach(struct aac_softc *sc) device_printf(sc->aac_dev, "can't set up FAST interrupt\n"); if (bus_setup_intr(sc->aac_dev, sc->aac_irq, - INTR_MPSAFE, aac_fast_intr, + 0, aac_fast_intr, sc, &sc->aac_intr, NULL)) { device_printf(sc->aac_dev, "can't set up MPSAFE interrupt\n"); @@ -1632,6 +1632,7 @@ aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) aac_unmap_command(cm); sc->flags |= AAC_QUEUE_FRZN; aac_requeue_ready(cm); + break; } DELAY(5); /* wait 5 usec. */ } diff --git a/sys/dev/raid/aac/aacvar.h b/sys/dev/raid/aac/aacvar.h index 2f7068268f..8fffe8ed87 100644 --- a/sys/dev/raid/aac/aacvar.h +++ b/sys/dev/raid/aac/aacvar.h @@ -174,7 +174,7 @@ struct aac_command #define AAC_ON_AACQ_COMPLETE (1<<8) #define AAC_ON_AACQ_NORM (1<<10) #define AAC_ON_AACQ_AIF (1<<11) -#define AAC_ON_AACQ_MASK ((1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<10)|(1<11)) +#define AAC_ON_AACQ_MASK ((1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<10)|(1<<11)) #define AAC_QUEUE_FRZN (1<<9) /* Freeze the processing of * commands on the queue. */ diff --git a/sys/dev/usbmisc/ugensa/ugensa.c b/sys/dev/usbmisc/ugensa/ugensa.c index 23cb373047..d06c931636 100644 --- a/sys/dev/usbmisc/ugensa/ugensa.c +++ b/sys/dev/usbmisc/ugensa/ugensa.c @@ -86,7 +86,7 @@ static device_method_t ugensa_methods[] = { { 0, 0 } }; -static driver_t ugensa_driver = { +static driver_t ugensa_driver = { "ucom", ugensa_methods, sizeof (struct ugensa_softc) @@ -169,31 +169,32 @@ static int ugensa_match(device_t self) { struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; if (uaa->iface == NULL) return UMATCH_NONE; /* - * Some devices have massstorage interfaces - don't claim ownership - * of these ... in general. - * - * Some devices (most notably Huawei E220) need special handling - * though. These come up with single umass interface, waiting for - * magic sent to it, detach and attach again with three interfaces. - * We have to claim such mass storage interface to send a magic to - * it. + * Some devices have mass storage interfaces. What we do with these + * is telling them that we don't need the mass storage and then + * just treat them the way we should. + * + * These devices, most notably Huawei (vendor id 0x12d1) have only + * one interface in mass storage, and after sending them magic, + * they have more than one and are in the correct operating mode. */ - id = usbd_get_interface_descriptor(uaa->iface); - if (id == NULL || id->bInterfaceClass == UICLASS_MASS) { - if ((uaa->vendor == 0x12d1 && uaa->product == 0x1003) || - (uaa->vendor == 0x12d1 && uaa->product == 0x1004)) { - if (uaa->nifaces == 1) - return UMATCH_VENDOR_IFACESUBCLASS; - else - return UMATCH_NONE; - } else - return UMATCH_NONE; + + if (uaa->vendor == 0x12d1) { + if (uaa->nifaces > 1) { + /* + * XXX: we might want to let the normal lookup handle + * these cases. Right now we just claim we know the + * device if it isn't in mass storage mode anymore. + */ + return UMATCH_VENDOR_IFACESUBCLASS; + } else { + ugensa_e220_changemode(uaa->device); + return -1; // avoid umass to reattach (UMATCH_HIGHEST) + } } return (usb_lookup(ugensa_devs, uaa->vendor, uaa->product) != NULL) ? @@ -218,13 +219,6 @@ ugensa_attach(device_t self) ucom->sc_iface = uaa->iface; id = usbd_get_interface_descriptor(ucom->sc_iface); - if (id == NULL || id->bInterfaceClass == UICLASS_MASS) { - if ((uaa->vendor == 0x12d1 && uaa->product == 0x1003) || - (uaa->vendor == 0x12d1 && uaa->product == 0x1004)) { - ugensa_e220_changemode(uaa->device); - } - return ENXIO; - } sc->sc_iface_no = id->bInterfaceNumber; ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; diff --git a/sys/dev/usbmisc/umass/umass.c b/sys/dev/usbmisc/umass/umass.c index e4edf4f591..14de9cabcf 100644 --- a/sys/dev/usbmisc/umass/umass.c +++ b/sys/dev/usbmisc/umass/umass.c @@ -2737,6 +2737,10 @@ umass_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb) kfree(ccb, M_USBDEV); } +/* + * Rescan the SCSI bus to detect newly added devices. We use + * an async rescan to avoid reentrancy issues. + */ static void umass_cam_rescan(void *addr) { @@ -2759,7 +2763,7 @@ umass_cam_rescan(void *addr) } xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/); - ccb->ccb_h.func_code = XPT_SCAN_BUS; + ccb->ccb_h.func_code = XPT_SCAN_BUS | XPT_FC_QUEUED; ccb->ccb_h.cbfcnp = umass_cam_rescan_callback; ccb->crcn.flags = CAM_FLAG_NONE; xpt_action(ccb); diff --git a/sys/dev/video/fb/vga.c b/sys/dev/video/fb/vga.c index fe5bc18485..11cb82c434 100644 --- a/sys/dev/video/fb/vga.c +++ b/sys/dev/video/fb/vga.c @@ -1338,7 +1338,7 @@ vga_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data, { #ifndef VGA_NO_FONT_LOADING u_char buf[PARAM_BUFSIZE]; - u_int32_t segment; + vm_offset_t segment; int c; #ifdef VGA_ALT_SEQACCESS u_char val = 0; @@ -1411,7 +1411,7 @@ vga_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data, { #ifndef VGA_NO_FONT_LOADING u_char buf[PARAM_BUFSIZE]; - u_int32_t segment; + vm_offset_t segment; int c; #ifdef VGA_ALT_SEQACCESS u_char val = 0; diff --git a/sys/dev/virtual/cdrom/vcd.c b/sys/dev/virtual/cdrom/vcd.c index 3ca23436a4..849233eb6f 100644 --- a/sys/dev/virtual/cdrom/vcd.c +++ b/sys/dev/virtual/cdrom/vcd.c @@ -157,13 +157,13 @@ vcdstrategy(struct dev_strategy_args *ap) switch(bp->b_cmd) { case BUF_CMD_READ: - lseek(sc->fd, bio->bio_offset, 0); - n = read(sc->fd, bp->b_data, bp->b_bcount); + n = pread(sc->fd, bp->b_data, + bp->b_bcount, bio->bio_offset); break; case BUF_CMD_WRITE: /* XXX HANDLE SHORT WRITE XXX */ - lseek(sc->fd, bio->bio_offset, 0); - n = write(sc->fd, bp->b_data, bp->b_bcount); + n = pwrite(sc->fd, bp->b_data, + bp->b_bcount, bio->bio_offset); break; default: panic("vcd: bad b_cmd %d", bp->b_cmd); diff --git a/sys/dev/virtual/disk/vdisk.c b/sys/dev/virtual/disk/vdisk.c index 7dc245f6e3..9a2b9e292c 100644 --- a/sys/dev/virtual/disk/vdisk.c +++ b/sys/dev/virtual/disk/vdisk.c @@ -160,10 +160,10 @@ vkdstrategy(struct dev_strategy_args *ap) sc = dev->si_drv1; devstat_start_transaction(&sc->stats); - cothread_lock(sc->cotd); + cothread_lock(sc->cotd, 0); TAILQ_INSERT_TAIL(&sc->cotd_queue, bio, bio_act); cothread_signal(sc->cotd); - cothread_unlock(sc->cotd); + cothread_unlock(sc->cotd, 0); return(0); } @@ -177,14 +177,14 @@ vkd_io_intr(cothread_t cotd) sc = cotd->arg; - cothread_lock(cotd); + cothread_lock(cotd, 0); while (!TAILQ_EMPTY(&sc->cotd_done)) { bio = TAILQ_FIRST(&sc->cotd_done); TAILQ_REMOVE(&sc->cotd_done, bio, bio_act); devstat_end_transaction_buf(&sc->stats, bio->bio_buf); biodone(bio); } - cothread_unlock(sc->cotd); + cothread_unlock(sc->cotd, 0); } /* @@ -202,14 +202,14 @@ vkd_io_thread(cothread_t cotd) struct vkd_softc *sc = cotd->arg; int count; - cothread_lock(cotd); + cothread_lock(cotd, 1); for (;;) { count = 0; while ((bio = TAILQ_FIRST(&sc->cotd_queue)) != NULL) { TAILQ_REMOVE(&sc->cotd_queue, bio, bio_act); - cothread_unlock(cotd); + cothread_unlock(cotd, 1); vkd_doio(sc, bio); - cothread_lock(cotd); + cothread_lock(cotd, 1); TAILQ_INSERT_TAIL(&sc->cotd_done, bio, bio_act); if (++count == 8) { cothread_intr(cotd); @@ -221,7 +221,7 @@ vkd_io_thread(cothread_t cotd) cothread_wait(cotd); /* interlocks cothread lock */ } /* NOT REACHED */ - cothread_unlock(cotd); + cothread_unlock(cotd, 1); } static diff --git a/sys/dev/virtual/net/if_vke.c b/sys/dev/virtual/net/if_vke.c index 360f56b6b4..92c2174543 100644 --- a/sys/dev/virtual/net/if_vke.c +++ b/sys/dev/virtual/net/if_vke.c @@ -1,13 +1,13 @@ /* * Copyright (c) 2007 The DragonFly Project. All rights reserved. - * + * * This code is derived from software contributed to The DragonFly Project * by Sepherosa Ziehau - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -17,7 +17,7 @@ * 3. Neither the name of The DragonFly Project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific, prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -30,7 +30,7 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * * $DragonFly: src/sys/dev/virtual/net/if_vke.c,v 1.10 2008/05/27 23:44:46 dillon Exp $ */ @@ -45,6 +45,7 @@ #include #include +#include #include #include @@ -56,6 +57,7 @@ #include #include +#include #include #include #include @@ -64,15 +66,40 @@ #define VKE_DEVNAME "vke" +#define VKE_CHUNK 8 /* number of mbufs to queue before interrupting */ + +#define NETFIFOSIZE 256 +#define NETFIFOMASK (NETFIFOSIZE -1) +#define NETFIFOINDEX(u) ((u) & NETFIFOMASK) + +#define VKE_COTD_RUN 0 +#define VKE_COTD_EXIT 1 +#define VKE_COTD_DEAD 2 + +struct vke_fifo { + struct mbuf *array[NETFIFOSIZE]; + int rindex; + int windex; +}; +typedef struct vke_fifo *fifo_t; + struct vke_softc { struct arpcom arpcom; int sc_fd; int sc_unit; - struct kqueue_info *sc_kqueue; + cothread_t cotd_tx; + cothread_t cotd_rx; + + int cotd_tx_exit; + int cotd_rx_exit; void *sc_txbuf; - struct mbuf *sc_rx_mbuf; + int sc_txbuf_len; + + fifo_t sc_txfifo; + fifo_t sc_txfifo_done; + fifo_t sc_rxfifo; struct sysctl_ctx_list sc_sysctl_ctx; struct sysctl_oid *sc_sysctl_tree; @@ -87,10 +114,21 @@ static void vke_init(void *); static int vke_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); static int vke_attach(const struct vknetif_info *, int); -static void vke_intr(void *, struct intrframe *); static int vke_stop(struct vke_softc *); -static void vke_rxeof(struct vke_softc *); static int vke_init_addr(struct ifnet *, in_addr_t, in_addr_t); +static void vke_tx_intr(cothread_t cotd); +static void vke_tx_thread(cothread_t cotd); +static void vke_rx_intr(cothread_t cotd); +static void vke_rx_thread(cothread_t cotd); + +static int vke_txfifo_enqueue(struct vke_softc *sc, struct mbuf *m); +static struct mbuf *vke_txfifo_dequeue(struct vke_softc *sc); + +static int vke_txfifo_done_enqueue(struct vke_softc *sc, struct mbuf *m); +static struct mbuf * vke_txfifo_done_dequeue(struct vke_softc *sc, struct mbuf *nm); + +static struct mbuf *vke_rxfifo_dequeue(struct vke_softc *sc, struct mbuf *nm); +static struct mbuf *vke_rxfifo_sniff(struct vke_softc *sc); static void vke_sysinit(void *arg __unused) @@ -107,19 +145,135 @@ vke_sysinit(void *arg __unused) } SYSINIT(vke, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, vke_sysinit, NULL); +/* + * vke_txfifo_done_enqueue() - Add an mbuf to the transmit done fifo. Since + * the cothread cannot free transmit mbufs after processing we put them on + * the done fifo so the kernel can free them. + */ +static int +vke_txfifo_done_enqueue(struct vke_softc *sc, struct mbuf *m) +{ + fifo_t fifo = sc->sc_txfifo_done; + + if (NETFIFOINDEX(fifo->windex + 1) == NETFIFOINDEX(fifo->rindex)) + return (-1); + + fifo->array[NETFIFOINDEX(fifo->windex)] = m; + cpu_sfence(); + ++fifo->windex; + return (0); +} + +/* + * vke_txfifo_done_dequeue() - Remove an mbuf from the transmit done fifo. + */ +static struct mbuf * +vke_txfifo_done_dequeue(struct vke_softc *sc, struct mbuf *nm) +{ + fifo_t fifo = sc->sc_txfifo_done; + struct mbuf *m; + + if (NETFIFOINDEX(fifo->rindex) == NETFIFOINDEX(fifo->windex)) + return (NULL); + + m = fifo->array[NETFIFOINDEX(fifo->rindex)]; + fifo->array[NETFIFOINDEX(fifo->rindex)] = nm; + cpu_lfence(); + ++fifo->rindex; + return (m); +} + +/* + * vke_txfifo_enqueue() - Add an mbuf to the transmit fifo. Wake up the + * cothread via cothread_signal(). + */ +static int +vke_txfifo_enqueue(struct vke_softc *sc, struct mbuf *m) +{ + fifo_t fifo = sc->sc_txfifo; + cothread_t cotd = sc->cotd_tx; + + if (NETFIFOINDEX(fifo->windex + 1) == NETFIFOINDEX(fifo->rindex)) + return (-1); + + fifo->array[NETFIFOINDEX(fifo->windex)] = m; + cpu_sfence(); + cothread_signal(cotd); + ++fifo->windex; + + return (0); +} + +/* + * vke_txfifo_dequeue() - Return next mbuf on the transmit fifo if one + * exists. + */ +static struct mbuf * +vke_txfifo_dequeue(struct vke_softc *sc) +{ + fifo_t fifo = sc->sc_txfifo; + struct mbuf *m; + + if (NETFIFOINDEX(fifo->rindex) == NETFIFOINDEX(fifo->windex)) + return (NULL); + + m = fifo->array[NETFIFOINDEX(fifo->rindex)]; + fifo->array[NETFIFOINDEX(fifo->rindex)] = NULL; + + cpu_lfence(); + ++fifo->rindex; + return (m); +} + +/* + * vke_rxfifo_dequeue() - Return next mbuf on the receice fifo if one + * exists replacing it with newm which should point to a newly allocated + * mbuf. + */ +static struct mbuf * +vke_rxfifo_dequeue(struct vke_softc *sc, struct mbuf *newm) +{ + fifo_t fifo = sc->sc_rxfifo; + struct mbuf *m; + + if (NETFIFOINDEX(fifo->rindex) == NETFIFOINDEX(fifo->windex)) + return (NULL); + + m = fifo->array[NETFIFOINDEX(fifo->rindex)]; + fifo->array[NETFIFOINDEX(fifo->rindex)] = newm; + cpu_lfence(); + ++fifo->rindex; + return (m); +} + +/* + * Return the next mbuf if available but do NOT remove it from the FIFO. + */ +static struct mbuf * +vke_rxfifo_sniff(struct vke_softc *sc) +{ + fifo_t fifo = sc->sc_rxfifo; + struct mbuf *m; + + if (NETFIFOINDEX(fifo->rindex) == NETFIFOINDEX(fifo->windex)) + return (NULL); + + m = fifo->array[NETFIFOINDEX(fifo->rindex)]; + cpu_lfence(); + return (m); +} + static void vke_init(void *xsc) { struct vke_softc *sc = xsc; struct ifnet *ifp = &sc->arpcom.ac_if; + int i; ASSERT_SERIALIZED(ifp->if_serializer); - vke_stop(sc); - KKASSERT(sc->sc_kqueue == NULL); - sc->sc_kqueue = kqueue_add(sc->sc_fd, vke_intr, sc); - KKASSERT(sc->sc_kqueue != NULL); + vke_stop(sc); ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; @@ -141,7 +295,19 @@ vke_init(void *xsc) vke_init_addr(ifp, addr, mask); } - ifp->if_start(ifp); + sc->sc_txfifo = kmalloc(sizeof(*sc->sc_txfifo), M_DEVBUF, M_WAITOK); + sc->sc_txfifo_done = kmalloc(sizeof(*sc->sc_txfifo_done), M_DEVBUF, M_WAITOK); + + sc->sc_rxfifo = kmalloc(sizeof(*sc->sc_rxfifo), M_DEVBUF, M_WAITOK); + for (i = 0; i < NETFIFOSIZE; i++) { + sc->sc_rxfifo->array[i] = m_getcl(MB_WAIT, MT_DATA, M_PKTHDR); + sc->sc_txfifo->array[i] = NULL; + sc->sc_txfifo_done->array[i] = NULL; + } + + sc->cotd_tx_exit = sc->cotd_rx_exit = VKE_COTD_RUN; + sc->cotd_tx = cothread_create(vke_tx_thread, vke_tx_intr, sc, "vke_tx"); + sc->cotd_rx = cothread_create(vke_rx_thread, vke_rx_intr, sc, "vke_rx"); } static void @@ -149,29 +315,33 @@ vke_start(struct ifnet *ifp) { struct vke_softc *sc = ifp->if_softc; struct mbuf *m; + cothread_t cotd = sc->cotd_tx; + int count; ASSERT_SERIALIZED(ifp->if_serializer); if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) return; + cothread_lock(cotd, 0); + count = 0; + while ((m = ifq_dequeue(&ifp->if_snd, NULL)) != NULL) { - /* - * Copy the data into a single mbuf and write it out - * non-blocking. - */ - if (m->m_pkthdr.len <= MCLBYTES) { - m_copydata(m, 0, m->m_pkthdr.len, sc->sc_txbuf); - BPF_MTAP(ifp, m); - if (write(sc->sc_fd, sc->sc_txbuf, m->m_pkthdr.len) < 0) - ifp->if_oerrors++; - else - ifp->if_opackets++; + if (vke_txfifo_enqueue(sc, m) != -1) { + if (count++ == VKE_CHUNK) { + cothread_signal(cotd); + count = 0; + } } else { - ifp->if_oerrors++; + m_freem(m); } - m_freem(m); } + + if (count) { + cothread_signal(cotd); + } + + cothread_unlock(cotd, 0); } static int @@ -230,82 +400,260 @@ static int vke_stop(struct vke_softc *sc) { struct ifnet *ifp = &sc->arpcom.ac_if; + int i; ASSERT_SERIALIZED(ifp->if_serializer); ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); - if (sc->sc_kqueue) { - kqueue_del(sc->sc_kqueue); - sc->sc_kqueue = NULL; - } - if (sc->sc_rx_mbuf != NULL) { - m_freem(sc->sc_rx_mbuf); - sc->sc_rx_mbuf = NULL; + if (sc) { + if (sc->cotd_tx) { + cothread_lock(sc->cotd_tx, 0); + if (sc->cotd_tx_exit == VKE_COTD_RUN) + sc->cotd_tx_exit = VKE_COTD_EXIT; + cothread_signal(sc->cotd_tx); + cothread_unlock(sc->cotd_tx, 0); + cothread_delete(&sc->cotd_tx); + } + if (sc->cotd_rx) { + cothread_lock(sc->cotd_rx, 0); + if (sc->cotd_rx_exit == VKE_COTD_RUN) + sc->cotd_rx_exit = VKE_COTD_EXIT; + cothread_signal(sc->cotd_rx); + cothread_unlock(sc->cotd_rx, 0); + cothread_delete(&sc->cotd_rx); + } + + for (i = 0; i < NETFIFOSIZE; i++) { + if (sc->sc_rxfifo && sc->sc_rxfifo->array[i]) { + m_freem(sc->sc_rxfifo->array[i]); + sc->sc_rxfifo->array[i] = NULL; + } + if (sc->sc_txfifo && sc->sc_txfifo->array[i]) { + m_freem(sc->sc_txfifo->array[i]); + sc->sc_txfifo->array[i] = NULL; + } + if (sc->sc_txfifo_done && sc->sc_txfifo_done->array[i]) { + m_freem(sc->sc_txfifo_done->array[i]); + sc->sc_txfifo_done->array[i] = NULL; + } + } + + if (sc->sc_txfifo) { + kfree(sc->sc_txfifo, M_DEVBUF); + sc->sc_txfifo = NULL; + } + + if (sc->sc_txfifo_done) { + kfree(sc->sc_txfifo_done, M_DEVBUF); + sc->sc_txfifo_done = NULL; + } + + if (sc->sc_rxfifo) { + kfree(sc->sc_rxfifo, M_DEVBUF); + sc->sc_rxfifo = NULL; + } } + + return 0; } +/* + * vke_rx_intr() is the interrupt function for the receive cothread. + */ static void -vke_intr(void *xsc, struct intrframe *frame __unused) +vke_rx_intr(cothread_t cotd) { - struct vke_softc *sc = xsc; + struct mbuf *m; + struct mbuf *nm; + struct vke_softc *sc = cotd->arg; struct ifnet *ifp = &sc->arpcom.ac_if; + static int count = 0; ifnet_serialize_all(ifp); + cothread_lock(cotd, 0); - if ((ifp->if_flags & IFF_RUNNING) == 0) - goto back; + if (sc->cotd_rx_exit != VKE_COTD_RUN) { + cothread_unlock(cotd, 0); + ifnet_deserialize_all(ifp); + return; + } - vke_rxeof(sc); + while ((m = vke_rxfifo_sniff(sc)) != NULL) { + nm = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR); + if (nm) { + vke_rxfifo_dequeue(sc, nm); + ifp->if_input(ifp, m); + if (count++ == VKE_CHUNK) { + cothread_signal(cotd); + count = 0; + } + } else { + vke_rxfifo_dequeue(sc, m); + } + } - ifp->if_start(ifp); + if (count) + cothread_signal(cotd); -back: + cothread_unlock(cotd, 0); ifnet_deserialize_all(ifp); } +/* + * vke_tx_intr() is the interrupt function for the transmit cothread. + * Calls vke_start() to handle processing transmit mbufs. + */ static void -vke_rxeof(struct vke_softc *sc) +vke_tx_intr(cothread_t cotd) { + struct vke_softc *sc = cotd->arg; struct ifnet *ifp = &sc->arpcom.ac_if; struct mbuf *m; - ASSERT_SERIALIZED(ifp->if_serializer); + ifnet_serialize_all(ifp); + cothread_lock(cotd, 0); + + if (sc->cotd_tx_exit != VKE_COTD_RUN) { + cothread_unlock(cotd, 0); + ifnet_deserialize_all(ifp); + return; + } + + if ((ifp->if_flags & IFF_RUNNING) == 0) + ifp->if_start(ifp); + + /* Free TX mbufs that have been processed */ + while ((m = vke_txfifo_done_dequeue(sc, NULL)) != NULL) { + m_freem(m); + } + + cothread_unlock(cotd, 0); + + ifnet_deserialize_all(ifp); +} + +/* + * vke_rx_thread() is the body of the receive cothread. + */ +static void +vke_rx_thread(cothread_t cotd) +{ + struct mbuf *m; + struct vke_softc *sc = cotd->arg; + struct ifnet *ifp = &sc->arpcom.ac_if; + int count; + fifo_t fifo = sc->sc_rxfifo; + fd_set fdset; + struct timeval tv; + + /* Select timeout cannot be infinite since we need to check for + * the exit flag sc->cotd_rx_exit. + */ + tv.tv_sec = 0; + tv.tv_usec = 500000; + + FD_ZERO(&fdset); + + cothread_lock(cotd, 1); for (;;) { int n; + count = 0; + while (sc->cotd_rx_exit == VKE_COTD_RUN) { + /* Wait for the RX FIFO to drain */ + while (NETFIFOINDEX(fifo->windex + 1) == + NETFIFOINDEX(fifo->rindex)) { + usleep(20000); + } + + if ((m = fifo->array[NETFIFOINDEX(fifo->windex)]) != + NULL) { + cothread_unlock(cotd, 1); + n = read(sc->sc_fd, mtod(m, void *), MCLBYTES); + cothread_lock(cotd, 1); + if (n <= 0) + break; + ifp->if_ipackets++; + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = m->m_len = n; + ++fifo->windex; + cpu_sfence(); + if (count++ == VKE_CHUNK) { + cothread_intr(cotd); + count = 0; + } + } + } - /* - * Try to get an mbuf - */ - if ((m = sc->sc_rx_mbuf) == NULL) - m = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR); - else - sc->sc_rx_mbuf = NULL; - - /* - * Drain the interface whether we get an mbuf or not or - * we might stop receiving interrupts. - */ - if (m) { - n = read(sc->sc_fd, mtod(m, void *), MCLBYTES); - } else { - n = read(sc->sc_fd, sc->sc_txbuf, MCLBYTES); + if (count) { + cothread_intr(cotd); } - if (n < 0) { - sc->sc_rx_mbuf = m; /* We can use it next time */ + + if (sc->cotd_rx_exit != VKE_COTD_RUN) break; + + cothread_unlock(cotd, 1); + + /* Set up data for select() call */ + FD_SET(sc->sc_fd, &fdset); + + if (select(sc->sc_fd + 1, &fdset, NULL, NULL, &tv) == -1) + kprintf(VKE_DEVNAME "%d: select failed for TAP device\n", sc->sc_unit); + + cothread_lock(cotd, 1); + } + + sc->cotd_rx_exit = VKE_COTD_DEAD; + cothread_unlock(cotd, 1); +} + +/* + * vke_tx_thread() is the body of the transmit cothread. + */ +static void +vke_tx_thread(cothread_t cotd) +{ + struct mbuf *m; + struct vke_softc *sc = cotd->arg; + struct ifnet *ifp = &sc->arpcom.ac_if; + int count = 0; + + cothread_lock(cotd, 1); + + while (sc->cotd_tx_exit == VKE_COTD_RUN) { + /* Write outgoing packets to the TAP interface */ + while ((m = vke_txfifo_dequeue(sc)) != NULL) { + if (m->m_pkthdr.len <= MCLBYTES) { + m_copydata(m, 0, m->m_pkthdr.len, sc->sc_txbuf); + sc->sc_txbuf_len = m->m_pkthdr.len; + cothread_unlock(cotd, 1); + + if (write(sc->sc_fd, sc->sc_txbuf, sc->sc_txbuf_len) < 0) { + cothread_lock(cotd, 1); + ifp->if_oerrors++; + } else { + cothread_lock(cotd, 1); + vke_txfifo_done_enqueue(sc, m); + ifp->if_opackets++; + if (count++ == VKE_CHUNK) { + cothread_intr(cotd); + count = 0; + } + } + } } - if (m) { - ifp->if_ipackets++; - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = n; - ifp->if_input(ifp, m); - } else { - ifp->if_ierrors++; + + if (count) { + cothread_intr(cotd); } + + cothread_wait(cotd); /* interlocks cothread lock */ } + /* NOT REACHED */ + sc->cotd_tx_exit = VKE_COTD_DEAD; + cothread_unlock(cotd, 1); } static int @@ -344,7 +692,7 @@ vke_attach(const struct vknetif_info *info, int unit) } enaddr[4] = (int)getpid() >> 8; enaddr[5] = (int)getpid() & 255; - + } enaddr[1] += 1; diff --git a/sys/emulation/linux/linux_misc.c b/sys/emulation/linux/linux_misc.c index a9c7960cec..8d6927bf03 100644 --- a/sys/emulation/linux/linux_misc.c +++ b/sys/emulation/linux/linux_misc.c @@ -264,6 +264,7 @@ sys_linux_uselib(struct linux_uselib_args *args) vp = NULL; error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW); + nd.nl_flags |= NLC_EXEC; if (error == 0) error = nlookup(&nd); if (error == 0) @@ -298,11 +299,6 @@ sys_linux_uselib(struct linux_uselib_args *args) goto cleanup; } - /* Can we access it? */ - error = VOP_ACCESS(vp, VEXEC, p->p_ucred); - if (error) - goto cleanup; - error = VOP_OPEN(vp, FREAD, p->p_ucred, NULL); if (error) goto cleanup; diff --git a/sys/kern/kern_cputimer.c b/sys/kern/kern_cputimer.c index 7ef1184682..7c2a84f96b 100644 --- a/sys/kern/kern_cputimer.c +++ b/sys/kern/kern_cputimer.c @@ -274,4 +274,237 @@ SYSCTL_PROC(_kern_cputimer, OID_AUTO, clock, CTLTYPE_UINT|CTLFLAG_RD, SYSCTL_PROC(_kern_cputimer, OID_AUTO, freq, CTLTYPE_INT|CTLFLAG_RD, NULL, 0, sysctl_cputimer_freq, "I", ""); +static struct cputimer_intr *sys_cputimer_intr; +static uint32_t cputimer_intr_caps; +SLIST_HEAD(, cputimer_intr) cputimer_intr_head = + SLIST_HEAD_INITIALIZER(&cputimer_intr_head); +void +cputimer_intr_register(struct cputimer_intr *cti) +{ + struct cputimer_intr *scan; + + SLIST_FOREACH(scan, &cputimer_intr_head, next) { + if (scan == cti) + return; + } + cti->config(cti, sys_cputimer); + SLIST_INSERT_HEAD(&cputimer_intr_head, cti, next); +} + +void +cputimer_intr_deregister(struct cputimer_intr *cti) +{ + KKASSERT(cti != sys_cputimer_intr); + SLIST_REMOVE(&cputimer_intr_head, cti, cputimer_intr, next); +} + +int +cputimer_intr_select(struct cputimer_intr *cti, int prio) +{ + KKASSERT(cti != NULL); + + if (prio == 0) + prio = cti->prio; + + if (sys_cputimer_intr == NULL) { + KKASSERT(cputimer_intr_caps == 0); + sys_cputimer_intr = cti; + return 0; + } + + if ((cti->caps & cputimer_intr_caps) == cputimer_intr_caps) { + if (prio > sys_cputimer_intr->prio) { + sys_cputimer_intr = cti; + return 0; + } else { + return EBUSY; + } + } else { + return EOPNOTSUPP; + } +} + +void +cputimer_intr_default_enable(struct cputimer_intr *cti __unused) +{ +} + +void +cputimer_intr_default_restart(struct cputimer_intr *cti) +{ + cti->reload(cti, 0); +} + +void +cputimer_intr_default_config(struct cputimer_intr *cti __unused, + const struct cputimer *timer __unused) +{ +} + +void +cputimer_intr_default_pmfixup(struct cputimer_intr *cti __unused) +{ +} + +void +cputimer_intr_default_initclock(struct cputimer_intr *cti __unused, + boolean_t selected __unused) +{ +} + +void +cputimer_intr_enable(void) +{ + struct cputimer_intr *cti; + + SLIST_FOREACH(cti, &cputimer_intr_head, next) + cti->enable(cti); +} + +void +cputimer_intr_config(const struct cputimer *timer) +{ + struct cputimer_intr *cti; + + SLIST_FOREACH(cti, &cputimer_intr_head, next) + cti->config(cti, timer); +} + +void +cputimer_intr_pmfixup(void) +{ + struct cputimer_intr *cti; + + SLIST_FOREACH(cti, &cputimer_intr_head, next) + cti->pmfixup(cti); +} + +void +cputimer_intr_reload(sysclock_t reload) +{ + struct cputimer_intr *cti = sys_cputimer_intr; + + cti->reload(cti, reload); +} + +void +cputimer_intr_restart(void) +{ + struct cputimer_intr *cti = sys_cputimer_intr; + + cti->restart(cti); +} + +int +cputimer_intr_select_caps(uint32_t caps) +{ + struct cputimer_intr *cti, *maybe; + int error; + + maybe = NULL; + SLIST_FOREACH(cti, &cputimer_intr_head, next) { + if ((cti->caps & caps) == caps) { + if (maybe == NULL) + maybe = cti; + else if (cti->prio > maybe->prio) + maybe = cti; + } + } + if (maybe == NULL) + return ENOENT; + + cputimer_intr_caps = caps; + error = cputimer_intr_select(maybe, CPUTIMER_INTR_PRIO_MAX); + KKASSERT(!error); + + return 0; +} + +static void +cputimer_intr_initclocks(void) +{ + struct cputimer_intr *cti, *ncti; + + /* + * An interrupt cputimer may deregister itself, + * so use SLIST_FOREACH_MUTABLE here. + */ + SLIST_FOREACH_MUTABLE(cti, &cputimer_intr_head, next, ncti) { + boolean_t selected = FALSE; + + if (cti == sys_cputimer_intr) + selected = TRUE; + cti->initclock(cti, selected); + } +} +/* NOTE: Must be SECOND to allow platform initialization to go first */ +SYSINIT(cputimer_intr, SI_BOOT2_CLOCKREG, SI_ORDER_SECOND, + cputimer_intr_initclocks, NULL) + +static int +sysctl_cputimer_intr_reglist(SYSCTL_HANDLER_ARGS) +{ + struct cputimer_intr *scan; + int error = 0; + int loop = 0; + + /* + * Build a list of available interrupt cputimers + */ + SLIST_FOREACH(scan, &cputimer_intr_head, next) { + if (error == 0 && loop) + error = SYSCTL_OUT(req, " ", 1); + if (error == 0) + error = SYSCTL_OUT(req, scan->name, strlen(scan->name)); + ++loop; + } + return (error); +} + +static int +sysctl_cputimer_intr_freq(SYSCTL_HANDLER_ARGS) +{ + int error; + + error = SYSCTL_OUT(req, &sys_cputimer_intr->freq, + sizeof(sys_cputimer_intr->freq)); + return (error); +} + +static int +sysctl_cputimer_intr_select(SYSCTL_HANDLER_ARGS) +{ + struct cputimer_intr *cti; + char name[32]; + int error; + + ksnprintf(name, sizeof(name), "%s", sys_cputimer_intr->name); + error = sysctl_handle_string(oidp, name, sizeof(name), req); + if (error != 0 || req->newptr == NULL) + return error; + + SLIST_FOREACH(cti, &cputimer_intr_head, next) { + if (strcmp(cti->name, name) == 0) + break; + } + if (cti == NULL) + return ENOENT; + if (cti == sys_cputimer_intr) + return 0; + + error = cputimer_intr_select(cti, CPUTIMER_INTR_PRIO_MAX); + if (!error) + cputimer_intr_restart(); + return error; +} + +SYSCTL_NODE(_kern_cputimer, OID_AUTO, intr, CTLFLAG_RW, NULL, + "interrupt cputimer"); + +SYSCTL_PROC(_kern_cputimer_intr, OID_AUTO, reglist, CTLTYPE_STRING|CTLFLAG_RD, + NULL, 0, sysctl_cputimer_intr_reglist, "A", ""); +SYSCTL_PROC(_kern_cputimer_intr, OID_AUTO, freq, CTLTYPE_INT|CTLFLAG_RD, + NULL, 0, sysctl_cputimer_intr_freq, "I", ""); +SYSCTL_PROC(_kern_cputimer_intr, OID_AUTO, select, CTLTYPE_STRING|CTLFLAG_RW, + NULL, 0, sysctl_cputimer_intr_select, "A", ""); diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index a71e93459e..766799c232 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -227,6 +227,7 @@ kern_fcntl(int fd, int cmd, union fcntl_dat *dat, struct ucred *cred) struct vnode *vp; u_int newmin; u_int oflags; + u_int nflags; int tmp, error, flg = F_POSIX; KKASSERT(p); @@ -269,16 +270,19 @@ kern_fcntl(int fd, int cmd, union fcntl_dat *dat, struct ucred *cred) break; case F_SETFL: - oflags = fp->f_flag & FCNTLFLAGS; - fp->f_flag &= ~FCNTLFLAGS; - fp->f_flag |= FFLAGS(dat->fc_flags & ~O_ACCMODE) & FCNTLFLAGS; + oflags = fp->f_flag; + nflags = FFLAGS(dat->fc_flags & ~O_ACCMODE) & FCNTLFLAGS; + nflags |= oflags & ~FCNTLFLAGS; + error = 0; - if ((fp->f_flag ^ oflags) & FASYNC) { - tmp = fp->f_flag & FASYNC; + if (((nflags ^ oflags) & O_APPEND) && (oflags & FAPPENDONLY)) + error = EINVAL; + if (error == 0 && ((nflags ^ oflags) & FASYNC)) { + tmp = nflags & FASYNC; error = fo_ioctl(fp, FIOASYNC, (caddr_t)&tmp, cred); } - if (error) - fp->f_flag = (fp->f_flag & ~FCNTLFLAGS) | oflags; + if (error == 0) + fp->f_flag = nflags; break; case F_GETOWN: diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index ae3c1476c6..0975726d76 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -669,7 +669,7 @@ sys_wait4(struct wait_args *uap) int error, status; error = kern_wait(uap->pid, uap->status ? &status : NULL, - uap->options, uap->rusage ? &rusage : NULL, &uap->sysmsg_fds[0]); + uap->options, uap->rusage ? &rusage : NULL, &uap->sysmsg_result); if (error == 0 && uap->status) error = copyout(&status, uap->status, sizeof(*uap->status)); diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c index 07f03e7f7e..a5ad65c027 100644 --- a/sys/kern/kern_intr.c +++ b/sys/kern/kern_intr.c @@ -185,6 +185,8 @@ register_int(int intr, inthand2_t *handler, void *arg, const char *name, struct intr_info *info; struct intrec **list; intrec_t rec; + int orig_cpuid = mycpuid, cpuid; + char envpath[32]; if (intr < 0 || intr >= MAX_INTS) panic("register_int: bad intr %d", intr); @@ -220,6 +222,15 @@ register_int(int intr, inthand2_t *handler, void *arg, const char *name, (emergency_intr_enable ? emergency_intr_freq : 1)); } + cpuid = orig_cpuid; + ksnprintf(envpath, sizeof(envpath), "hw.irq.%d.dest", intr); + kgetenv_int(envpath, &cpuid); + if (cpuid >= ncpus) + cpuid = orig_cpuid; + + if (cpuid != orig_cpuid) + lwkt_migratecpu(cpuid); + /* * Create an interrupt thread if necessary, leave it in an unscheduled * state. @@ -295,6 +306,9 @@ register_int(int intr, inthand2_t *handler, void *arg, const char *name, kprintf("machintr_vector_setup: failed on irq %d\n", intr); } + if (cpuid != orig_cpuid) + lwkt_migratecpu(orig_cpuid); + return(rec); } @@ -861,8 +875,8 @@ ithread_handler(void *arg) use_limit = 100; else if (use_limit > 500000) use_limit = 500000; - systimer_init_periodic(&ill_timer, ithread_livelock_wakeup, - (void *)intr, use_limit); + systimer_init_periodic_nq(&ill_timer, ithread_livelock_wakeup, + (void *)intr, use_limit); /* fall through */ case ISTATE_LIVELOCKED: /* diff --git a/sys/kern/kern_kinfo.c b/sys/kern/kern_kinfo.c index 5e5e4ddbcc..c8d0578415 100644 --- a/sys/kern/kern_kinfo.c +++ b/sys/kern/kern_kinfo.c @@ -54,6 +54,8 @@ #include #else #include + +dev_t dev2udev(cdev_t dev); /* kvm_proc.c */ #endif diff --git a/sys/kern/kern_usched.c b/sys/kern/kern_usched.c index 10960260ca..da48f96147 100644 --- a/sys/kern/kern_usched.c +++ b/sys/kern/kern_usched.c @@ -163,7 +163,8 @@ sys_usched_set(struct usched_set_args *uap) struct lwp *lp; int cpuid; /* USCHED_GET_CPU doesn't require root privileges. */ - if (uap->cmd != USCHED_GET_CPU && (error = priv_check(curthread, PRIV_ROOT)) != 0) + if ((uap->cmd != USCHED_GET_CPU) && (uap->cmd != USCHED_DEL_CPU) && + (error = priv_check(curthread, PRIV_ROOT)) != 0) return (error); if (uap->pid != 0 && uap->pid != curthread->td_proc->p_pid) diff --git a/sys/kern/vfs_helper.c b/sys/kern/vfs_helper.c index 0ea69e52ca..1b2f6a53a2 100644 --- a/sys/kern/vfs_helper.c +++ b/sys/kern/vfs_helper.c @@ -110,8 +110,6 @@ vop_helper_access(struct vop_access_args *ap, uid_t ino_uid, gid_t ino_gid, /* Otherwise, check the owner. */ if (cred->cr_uid == ino_uid) { - if (mode & VOWN) - return (0); if (mode & VEXEC) mask |= S_IXUSR; if (mode & VREAD) @@ -249,6 +247,12 @@ vop_helper_chown(struct vnode *vp, uid_t new_uid, gid_t new_gid, *cur_uidp = new_uid; *cur_gidp = new_gid; /* XXX QUOTA CODE */ + + /* + * DragonFly clears both SUID and SGID if either the owner or + * group is changed and root isn't doing it. If root is doing + * it we do not clear SUID/SGID. + */ if (cred->cr_uid != 0 && (ouid != new_uid || ogid != new_gid)) *cur_modep &= ~(S_ISUID | S_ISGID); return(0); diff --git a/sys/kern/vfs_nlookup.c b/sys/kern/vfs_nlookup.c index 3efa97f257..09758a6c19 100644 --- a/sys/kern/vfs_nlookup.c +++ b/sys/kern/vfs_nlookup.c @@ -70,8 +70,6 @@ #include #endif -static int naccess_va(struct vattr *va, int vmode, struct ucred *cred); - /* * Initialize a nlookup() structure, early error return for copyin faults * or a degenerate empty string (which is not allowed). @@ -283,10 +281,9 @@ nlookup_simple(const char *str, enum uio_seg seg, * and an error code of 0 will be returned for a non-existant * target (not ENOENT). * - * If NLC_RENAME is set the last directory mut allow node deletion, + * If NLC_RENAME_DST is set the last directory mut allow node deletion, * plus the sticky check is made, and an error code of 0 will be returned - * for a non-existant target (not ENOENT). NLC_RENAME is set used for - * the rename target. + * for a non-existant target (not ENOENT). * * If NLC_DELETE is set the last directory mut allow node deletion, * plus the sticky check is made. @@ -300,12 +297,14 @@ nlookup(struct nlookupdata *nd) { struct nlcomponent nlc; struct nchandle nch; + struct nchandle par; struct mount *mp; int wasdotordotdot; char *ptr; char *xptr; int error; int len; + int dflags; #ifdef KTRACE if (KTRPOINT(nd->nl_td, KTR_NAMEI)) @@ -371,16 +370,22 @@ nlookup(struct nlookupdata *nd) /* * Check directory search permissions. */ - if ((error = naccess(&nd->nl_nch, VEXEC, nd->nl_cred, NULL)) != 0) + dflags = 0; + if ((error = naccess(&nd->nl_nch, NLC_EXEC, nd->nl_cred, &dflags)) != 0) break; /* - * Extract the path component + * Extract the path component. Path components are limited to + * 255 characters. */ nlc.nlc_nameptr = ptr; while (*ptr && *ptr != '/') ++ptr; nlc.nlc_namelen = ptr - nlc.nlc_nameptr; + if (nlc.nlc_namelen >= 256) { + error = ENAMETOOLONG; + break; + } /* * Lookup the path component in the cache, creating an unresolved @@ -390,6 +395,10 @@ nlookup(struct nlookupdata *nd) * When handling ".." we have to detect a traversal back through a * mount point. If we are at the root, ".." just returns the root. * + * When handling "." or ".." we also have to recalculate dflags + * since our dflags will be for some sub-directory instead of the + * parent dir. + * * This subsection returns a locked, refd 'nch' unless it errors out. * The namecache topology is not allowed to be disconnected, so * encountering a NULL parent will generate EINVAL. This typically @@ -420,7 +429,7 @@ nlookup(struct nlookupdata *nd) KKASSERT(nch.ncp != NULL); cache_get(&nch, &nch); } - wasdotordotdot = 1; + wasdotordotdot = 2; } else { nch = cache_nlookup(&nd->nl_nch, &nlc); while ((error = cache_resolve(&nch, nd->nl_cred)) == EAGAIN) { @@ -431,6 +440,23 @@ nlookup(struct nlookupdata *nd) } wasdotordotdot = 0; } + + /* + * If the last component was "." or ".." our dflags no longer + * represents the parent directory and we have to explicitly + * look it up. + */ + if (wasdotordotdot && error == 0) { + dflags = 0; + if ((par.ncp = nch.ncp->nc_parent) != NULL) { + par.mount = nch.mount; + cache_hold(&par); + dflags = 0; + error = naccess(&par, 0, nd->nl_cred, &dflags); + cache_drop(&par); + } + } + /* * [end of subsection] ncp is locked and ref'd. nd->nl_nch is ref'd */ @@ -455,9 +481,6 @@ nlookup(struct nlookupdata *nd) * requested. Note that ncp->nc_error is left as ENOENT in that * case, which we check later on. * - * NOTE: For NLC_RENAME in the ENOENT case we do a VCREATE test, - * same as for NLC_CREATE. - * * Also handle invalid '.' or '..' components terminating a path * for a create/rename/delete. The standard requires this and pax * pretty stupidly depends on it. @@ -465,15 +488,28 @@ nlookup(struct nlookupdata *nd) for (xptr = ptr; *xptr == '/'; ++xptr) ; if (*xptr == 0) { - if (error == ENOENT && (nd->nl_flags & (NLC_CREATE | NLC_RENAME))) { - if (nd->nl_flags & NLC_NFS_RDONLY) + if (error == ENOENT && + (nd->nl_flags & (NLC_CREATE | NLC_RENAME_DST)) + ) { + if (nd->nl_flags & NLC_NFS_RDONLY) { error = EROFS; - else - error = naccess(&nch, VCREATE, nd->nl_cred, NULL); + } else { + error = naccess(&nch, nd->nl_flags | dflags, + nd->nl_cred, NULL); + } } if (error == 0 && wasdotordotdot && - (nd->nl_flags & (NLC_CREATE | NLC_RENAME | NLC_DELETE))) { - error = EINVAL; + (nd->nl_flags & (NLC_CREATE | NLC_DELETE | + NLC_RENAME_SRC | NLC_RENAME_DST))) { + /* + * POSIX junk + */ + if (nd->nl_flags & NLC_CREATE) + error = EEXIST; + else if (nd->nl_flags & NLC_DELETE) + error = (wasdotordotdot == 1) ? EINVAL : ENOTEMPTY; + else + error = EINVAL; } } @@ -599,17 +635,17 @@ nlookup(struct nlookupdata *nd) /* * Successful lookup of last element. * - * Check directory permissions if a deletion or rename (target) - * is specified. This also handles the sticky test. + * Check permissions if the target exists. If the target does not + * exist directory permissions were already tested in the early + * completion code above. * - * We already checked permissions for creates in the early - * termination code above. + * nd->nl_flags will be adjusted on return with NLC_APPENDONLY + * if the file is marked append-only, and NLC_STICKY if the directory + * containing the file is sticky. */ - if (*ptr == 0 && (nd->nl_flags & (NLC_DELETE | NLC_RENAME))) { - if (nd->nl_flags & NLC_DELETE) - error = naccess(&nch, VDELETE, nd->nl_cred, NULL); - else - error = naccess(&nch, VRENAME, nd->nl_cred, NULL); + if (nch.ncp->nc_vp && (nd->nl_flags & NLC_ALLCHKS)) { + error = naccess(&nch, nd->nl_flags | dflags, + nd->nl_cred, NULL); if (error) { cache_put(&nch); break; @@ -617,9 +653,7 @@ nlookup(struct nlookupdata *nd) } /* - * Termination: no more elements. If NLC_CREATE was set the - * ncp may represent a negative hit (ncp->nc_error will be ENOENT), - * but we still return an error code of 0. + * Termination: no more elements. * * If NLC_REFDVP is set acquire a referenced parent dvp. */ @@ -637,6 +671,12 @@ nlookup(struct nlookupdata *nd) error = 0; break; } + + /* + * NOTE: If NLC_CREATE was set the ncp may represent a negative hit + * (ncp->nc_error will be ENOENT), but we will still return an error + * code of 0. + */ return(error); } @@ -728,26 +768,27 @@ fail: /* * Check access [XXX cache vattr!] [XXX quota] * - * Generally check the V* access bits from sys/vnode.h. All specified bits - * must pass for this function to return 0. + * Generally check the NLC_* access bits. All specified bits must pass + * for this function to return 0. * - * The file does not have to exist when checking VCREATE or VRENAME access. + * The file does not have to exist when checking NLC_CREATE or NLC_RENAME_DST + * access, otherwise it must exist. No error is returned in this case. * - * The file must not exist if VEXCL is specified. + * The file must not exist if NLC_EXCL is specified. * - * Directory permissions in general are tested for VCREATE if the file - * does not exist, VDELETE if the file does exist, and VRENAME whether - * the file exists or not. + * Directory permissions in general are tested for NLC_CREATE if the file + * does not exist, NLC_DELETE if the file does exist, and NLC_RENAME_DST + * whether the file exists or not. * - * The directory sticky bit is tested for VDELETE and VRENAME. NOTE: For - * VRENAME we only care if the target exists. + * The directory sticky bit is tested for NLC_DELETE and NLC_RENAME_DST, + * the latter is only tested if the target exists. * * The passed ncp may or may not be locked. The caller should use a - * locked ncp on leaf lookups, especially for VCREATE, VRENAME, VDELETE, - * and VEXCL checks. + * locked ncp on leaf lookups, especially for NLC_CREATE, NLC_RENAME_DST, + * NLC_DELETE, and NLC_EXCL checks. */ int -naccess(struct nchandle *nch, int vmode, struct ucred *cred, int *stickyp) +naccess(struct nchandle *nch, int nflags, struct ucred *cred, int *nflagsp) { struct nchandle par; struct vnode *vp; @@ -761,62 +802,117 @@ naccess(struct nchandle *nch, int vmode, struct ucred *cred, int *stickyp) cache_unlock(nch); } error = nch->ncp->nc_error; - sticky = 0; /* - * Directory permissions and VEXCL checks. Do a precursor conditional - * to reduce overhead since most access checks are for read-only. + * Directory permissions checks. Silently ignore ENOENT if these + * tests pass. It isn't an error. */ - if (vmode & (VDELETE|VRENAME|VCREATE|VEXCL)) { - if (((vmode & VCREATE) && nch->ncp->nc_vp == NULL) || - ((vmode & VDELETE) && nch->ncp->nc_vp != NULL) || - (vmode & VRENAME) + if (nflags & (NLC_CREATE | NLC_DELETE | NLC_RENAME_SRC | NLC_RENAME_DST)) { + if (((nflags & NLC_CREATE) && nch->ncp->nc_vp == NULL) || + ((nflags & NLC_DELETE) && nch->ncp->nc_vp != NULL) || + ((nflags & NLC_RENAME_SRC) && nch->ncp->nc_vp != NULL) || + (nflags & NLC_RENAME_DST) ) { if ((par.ncp = nch->ncp->nc_parent) == NULL) { if (error != EAGAIN) error = EINVAL; - } else { + } else if (error == 0 || error == ENOENT) { par.mount = nch->mount; cache_hold(&par); - error = naccess(&par, VWRITE, cred, &sticky); - if ((vmode & (VDELETE | VRENAME)) && sticky) - vmode |= VSVTX; + sticky = 0; + error = naccess(&par, NLC_WRITE, cred, NULL); cache_drop(&par); } } - if ((vmode & VEXCL) && nch->ncp->nc_vp != NULL) - error = EEXIST; } + + /* + * NLC_EXCL check. Target file must not exist. + */ + if (error == 0 && (nflags & NLC_EXCL) && nch->ncp->nc_vp != NULL) + error = EEXIST; + + /* + * Get the vnode attributes so we can do the rest of our checks. + * + * NOTE: We only call naccess_va() if the target exists. + */ if (error == 0) { error = cache_vget(nch, cred, LK_SHARED, &vp); if (error == ENOENT) { - if (vmode & (VCREATE | VRENAME)) + /* + * Silently zero-out ENOENT if creating or renaming + * (rename target). It isn't an error. + */ + if (nflags & (NLC_CREATE | NLC_RENAME_DST)) error = 0; } else if (error == 0) { - /* XXX cache the va in the namecache or in the vnode */ - if ((error = VOP_GETATTR(vp, &va)) == 0) { - if ((vmode & VWRITE) && vp->v_mount) { - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; + /* + * Get the vnode attributes and check for illegal O_TRUNC + * requests and read-only mounts. + * + * NOTE: You can still open devices on read-only mounts for + * writing. + * + * NOTE: creates/deletes/renames are handled by the NLC_WRITE + * check on the parent directory above. + * + * XXX cache the va in the namecache or in the vnode + */ + error = VOP_GETATTR(vp, &va); + if (error == 0 && (nflags & NLC_TRUNCATE)) { + switch(va.va_type) { + case VREG: + case VDATABASE: + case VCHR: + case VBLK: + break; + case VDIR: + error = EISDIR; + break; + default: + error = EINVAL; + break; + } + } + if (error == 0 && (nflags & NLC_WRITE) && vp->v_mount && + (vp->v_mount->mnt_flag & MNT_RDONLY) + ) { + switch(va.va_type) { + case VDIR: + case VLNK: + case VREG: + case VDATABASE: + error = EROFS; + break; + default: + break; } } vput(vp); + /* + * Check permissions based on file attributes. The passed + * flags (*nflagsp) are modified with feedback based on + * special attributes and requirements. + */ if (error == 0) { /* - * Set the returned (*stickyp) if VSVTX is set and the uid - * is not the owner of the directory. The caller uses this - * disallow deletions of files not owned by the user if the - * user also does not own the directory and the sticky bit - * is set on the directory. Weird, I know. + * Adjust the returned (*nflagsp) if non-NULL. */ - if (stickyp && va.va_uid != cred->cr_uid) - *stickyp = (va.va_mode & VSVTX); + if (nflagsp) { + if ((va.va_mode & VSVTX) && va.va_uid != cred->cr_uid) + *nflagsp |= NLC_STICKY; + if (va.va_flags & APPEND) + *nflagsp |= NLC_APPENDONLY; + if (va.va_flags & IMMUTABLE) + *nflagsp |= NLC_IMMUTABLE; + } /* * Process general access. */ - error = naccess_va(&va, vmode, cred); + error = naccess_va(&va, nflags, cred); } } } @@ -826,20 +922,89 @@ naccess(struct nchandle *nch, int vmode, struct ucred *cred, int *stickyp) /* * Check the requested access against the given vattr using cred. */ -static int -naccess_va(struct vattr *va, int vmode, struct ucred *cred) +naccess_va(struct vattr *va, int nflags, struct ucred *cred) { int i; + int vmode; + + /* + * Test the immutable bit. Creations, deletions, renames (source + * or destination) are not allowed. chown/chmod/other is also not + * allowed but is handled by SETATTR. Hardlinks to the immutable + * file are allowed. + * + * If the directory is set to immutable then creations, deletions, + * renames (source or dest) and hardlinks to files within the directory + * are not allowed, and regular files opened through the directory may + * not be written to or truncated (unless a special device). + * + * NOTE! New hardlinks to immutable files work but new hardlinks to + * files, immutable or not, sitting inside an immutable directory are + * not allowed. As always if the file is hardlinked via some other + * path additional hardlinks may be possible even if the file is marked + * immutable. The sysop needs to create a closure by checking the hard + * link count. Once closure is achieved you are good, and security + * scripts should check link counts anyway. + * + * Writes and truncations are only allowed on special devices. + */ + if ((va->va_flags & IMMUTABLE) || (nflags & NLC_IMMUTABLE)) { + if ((nflags & NLC_IMMUTABLE) && (nflags & NLC_HLINK)) + return (EPERM); + if (nflags & (NLC_CREATE | NLC_DELETE | + NLC_RENAME_SRC | NLC_RENAME_DST)) { + return (EPERM); + } + if (nflags & (NLC_WRITE | NLC_TRUNCATE)) { + switch(va->va_type) { + case VDIR: + return (EISDIR); + case VLNK: + case VREG: + case VDATABASE: + return (EPERM); + default: + break; + } + } + } /* - * Test the immutable bit for files, directories, and softlinks. + * Test the no-unlink and append-only bits for opens, rename targets, + * and deletions. These bits are not tested for creations or + * rename sources. * - * NOTE: Only called for VRENAME if the target exists. + * Unlike FreeBSD we allow a file with APPEND set to be renamed. + * If you do not wish this you must also set NOUNLINK. + * + * If the governing directory is marked APPEND-only it implies + * NOUNLINK for all entries in the directory. */ - if (vmode & (VWRITE|VDELETE|VRENAME)) { - if (va->va_type == VDIR || va->va_type == VLNK || va->va_type == VREG) { - if (va->va_flags & IMMUTABLE) + if (((va->va_flags & NOUNLINK) || (nflags & NLC_APPENDONLY)) && + (nflags & (NLC_DELETE | NLC_RENAME_SRC | NLC_RENAME_DST)) + ) { + return (EPERM); + } + + /* + * A file marked append-only may not be deleted but can be renamed. + */ + if ((va->va_flags & APPEND) && + (nflags & (NLC_DELETE | NLC_RENAME_DST)) + ) { + return (EPERM); + } + + /* + * A file marked append-only which is opened for writing must also + * be opened O_APPEND. + */ + if ((va->va_flags & APPEND) && (nflags & (NLC_OPEN | NLC_TRUNCATE))) { + if (nflags & NLC_TRUNCATE) + return (EPERM); + if ((nflags & (NLC_OPEN | NLC_WRITE)) == (NLC_OPEN | NLC_WRITE)) { + if ((nflags & NLC_APPEND) == 0) return (EPERM); } } @@ -853,12 +1018,19 @@ naccess_va(struct vattr *va, int vmode, struct ucred *cred) /* * Check owner perms. * - * If VOWN is set the owner of the file is allowed no matter when + * If NLC_OWN is set the owner of the file is allowed no matter when * the owner-mode bits say (utimes). */ + vmode = 0; + if (nflags & NLC_READ) + vmode |= S_IRUSR; + if (nflags & NLC_WRITE) + vmode |= S_IWUSR; + if (nflags & NLC_EXEC) + vmode |= S_IXUSR; + if (cred->cr_uid == va->va_uid) { - if ((vmode & VOWN) == 0) { - vmode &= S_IRWXU; + if ((nflags & NLC_OWN) == 0) { if ((vmode & va->va_mode) != vmode) return(EACCES); } @@ -866,23 +1038,21 @@ naccess_va(struct vattr *va, int vmode, struct ucred *cred) } /* - * If VSVTX is set only the owner may create or delete the file. - * This bit is typically set for VDELETE checks from unlink or - * the source file in a rename, and for VCREATE checks from the - * target file in a rename. + * If NLC_STICKY is set only the owner may delete or rename a file. + * This bit is typically set on /tmp. * - * Note that other V bits are not typically set in the VSVTX case. - * For creations and deletions we usually just care about directory - * permissions, not file permissions. So if this test passes the - * return value winds up being 0. + * Note that the NLC_READ/WRITE/EXEC bits are not typically set in + * the specific delete or rename case. For deletions and renames we + * usually just care about directory permissions, not file permissions. */ - if (vmode & VSVTX) + if ((nflags & NLC_STICKY) && + (nflags & (NLC_RENAME_SRC | NLC_RENAME_DST | NLC_DELETE))) { return(EACCES); + } /* * Check group perms */ - vmode &= S_IRWXU; vmode >>= 3; for (i = 0; i < cred->cr_ngroups; ++i) { if (va->va_gid == cred->cr_groups[i]) { diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 09c36aae46..73faa7fe88 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -92,7 +92,8 @@ static int getutimes (const struct timeval *, struct timespec *); static int setfown (struct vnode *, uid_t, gid_t); static int setfmode (struct vnode *, int); static int setfflags (struct vnode *, int); -static int setutimes (struct vnode *, const struct timespec *, int); +static int setutimes (struct vnode *, struct vattr *, + const struct timespec *, int); static int usermount = 0; /* if 1, non-root can mount fs. */ int (*union_dircheckp) (struct thread *, struct vnode **, struct file *); @@ -1656,6 +1657,7 @@ sys_chroot(struct chroot_args *uap) nlookup_done(&nd); return(error); } + nd.nl_flags |= NLC_EXEC; error = nlookup(&nd); if (error == 0) error = kern_chroot(&nd.nl_nch); @@ -1701,7 +1703,7 @@ kern_open(struct nlookupdata *nd, int oflags, int mode, int *res) if (error) return (error); fp = nfp; - cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; + cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT; /* * XXX p_dupfd is a real mess. It allows a device to return a @@ -1825,7 +1827,7 @@ sys_open(struct open_args *uap) struct nlookupdata nd; int error; - error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); + error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); if (error == 0) { error = kern_open(&nd, uap->flags, uap->mode, &uap->sysmsg_result); @@ -2037,9 +2039,13 @@ kern_link(struct nlookupdata *nd, struct nlookupdata *linknd) /* * Lookup the source and obtained a locked vnode. * + * You may only hardlink a file which you have write permission + * on or which you own. + * * XXX relookup on vget failure / race ? */ bwillinode(1); + nd->nl_flags |= NLC_WRITE | NLC_OWN | NLC_HLINK; if ((error = nlookup(nd)) != 0) return (error); vp = nd->nl_nch.ncp->nc_vp; @@ -2258,12 +2264,16 @@ kern_lseek(int fd, off_t offset, int whence, off_t *res) /* * Validate the seek position. Negative offsets are not allowed - * for regular files, block specials, or directories. + * for regular files or directories. + * + * Normally we would also not want to allow negative offsets for + * character and block-special devices. However kvm addresses + * on 64 bit architectures might appear to be negative and must + * be allowed. */ if (error == 0) { if (new_offset < 0 && - (vp->v_type == VREG || vp->v_type == VDIR || - vp->v_type == VCHR || vp->v_type == VBLK)) { + (vp->v_type == VREG || vp->v_type == VDIR)) { error = EINVAL; } else { fp->f_offset = new_offset; @@ -2564,7 +2574,6 @@ sys_chflags(struct chflags_args *uap) vp = NULL; error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); - /* XXX Add NLC flag indicating modifying operation? */ if (error == 0) error = nlookup(&nd); if (error == 0) @@ -2594,7 +2603,6 @@ sys_lchflags(struct lchflags_args *uap) vp = NULL; error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); - /* XXX Add NLC flag indicating modifying operation? */ if (error == 0) error = nlookup(&nd); if (error == 0) @@ -2660,7 +2668,6 @@ kern_chmod(struct nlookupdata *nd, int mode) struct vnode *vp; int error; - /* XXX Add NLC flag indicating modifying operation? */ if ((error = nlookup(nd)) != 0) return (error); if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0) @@ -2761,7 +2768,6 @@ kern_chown(struct nlookupdata *nd, int uid, int gid) struct vnode *vp; int error; - /* XXX Add NLC flag indicating modifying operation? */ if ((error = nlookup(nd)) != 0) return (error); if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0) @@ -2849,26 +2855,20 @@ getutimes(const struct timeval *tvp, struct timespec *tsp) } static int -setutimes(struct vnode *vp, const struct timespec *ts, int nullflag) +setutimes(struct vnode *vp, struct vattr *vattr, + const struct timespec *ts, int nullflag) { struct thread *td = curthread; struct proc *p = td->td_proc; int error; - struct vattr vattr; - /* - * note: vget is required for any operation that might mod the vnode - * so VINACTIVE is properly cleared. - */ - if ((error = vget(vp, LK_EXCLUSIVE)) == 0) { - VATTR_NULL(&vattr); - vattr.va_atime = ts[0]; - vattr.va_mtime = ts[1]; - if (nullflag) - vattr.va_vaflags |= VA_UTIMES_NULL; - error = VOP_SETATTR(vp, &vattr, p->p_ucred); - vput(vp); - } + VATTR_NULL(vattr); + vattr->va_atime = ts[0]; + vattr->va_mtime = ts[1]; + if (nullflag) + vattr->va_vaflags |= VA_UTIMES_NULL; + error = VOP_SETATTR(vp, vattr, p->p_ucred); + return error; } @@ -2877,11 +2877,18 @@ kern_utimes(struct nlookupdata *nd, struct timeval *tptr) { struct timespec ts[2]; struct vnode *vp; + struct vattr vattr; int error; if ((error = getutimes(tptr, ts)) != 0) return (error); - /* XXX Add NLC flag indicating modifying operation? */ + + /* + * NOTE: utimes() succeeds for the owner even if the file + * is not user-writable. + */ + nd->nl_flags |= NLC_OWN | NLC_WRITE; + if ((error = nlookup(nd)) != 0) return (error); if ((error = ncp_writechk(&nd->nl_nch)) != 0) @@ -2890,12 +2897,15 @@ kern_utimes(struct nlookupdata *nd, struct timeval *tptr) return (error); /* - * NOTE: utimes() succeeds for the owner even if the file - * is not user-writable. + * note: vget is required for any operation that might mod the vnode + * so VINACTIVE is properly cleared. */ - if ((error = vn_writechk(vp, &nd->nl_nch)) == 0 && - (error = VOP_ACCESS(vp, VWRITE | VOWN, nd->nl_cred)) == 0) { - error = setutimes(vp, ts, tptr == NULL); + if ((error = vn_writechk(vp, &nd->nl_nch)) == 0) { + error = vget(vp, LK_EXCLUSIVE); + if (error == 0) { + error = setutimes(vp, &vattr, ts, (tptr == NULL)); + vput(vp); + } } vrele(vp); return (error); @@ -2949,6 +2959,11 @@ sys_lutimes(struct lutimes_args *uap) return (error); } +/* + * Set utimes on a file descriptor. The creds used to open the + * file are used to determine whether the operation is allowed + * or not. + */ int kern_futimes(int fd, struct timeval *tptr) { @@ -2956,6 +2971,8 @@ kern_futimes(int fd, struct timeval *tptr) struct proc *p = td->td_proc; struct timespec ts[2]; struct file *fp; + struct vnode *vp; + struct vattr vattr; int error; error = getutimes(tptr, ts); @@ -2965,8 +2982,22 @@ kern_futimes(int fd, struct timeval *tptr) return (error); if (fp->f_nchandle.ncp) error = ncp_writechk(&fp->f_nchandle); - if (error == 0) - error = setutimes((struct vnode *)fp->f_data, ts, tptr == NULL); + if (error == 0) { + vp = fp->f_data; + error = vget(vp, LK_EXCLUSIVE); + if (error == 0) { + error = VOP_GETATTR(vp, &vattr); + if (error == 0) { + error = naccess_va(&vattr, NLC_OWN | NLC_WRITE, + fp->f_cred); + } + if (error == 0) { + error = setutimes(vp, &vattr, ts, + (tptr == NULL)); + } + vput(vp); + } + } fdrop(fp); return (error); } @@ -3002,7 +3033,7 @@ kern_truncate(struct nlookupdata *nd, off_t length) if (length < 0) return(EINVAL); - /* XXX Add NLC flag indicating modifying operation? */ + nd->nl_flags |= NLC_WRITE | NLC_TRUNCATE; if ((error = nlookup(nd)) != 0) return (error); if ((error = ncp_writechk(&nd->nl_nch)) != 0) @@ -3015,8 +3046,7 @@ kern_truncate(struct nlookupdata *nd, off_t length) } if (vp->v_type == VDIR) { error = EISDIR; - } else if ((error = vn_writechk(vp, &nd->nl_nch)) == 0 && - (error = VOP_ACCESS(vp, VWRITE, nd->nl_cred)) == 0) { + } else if ((error = vn_writechk(vp, &nd->nl_nch)) == 0) { VATTR_NULL(&vattr); vattr.va_size = length; error = VOP_SETATTR(vp, &vattr, nd->nl_cred); @@ -3066,6 +3096,10 @@ kern_ftruncate(int fd, off_t length) error = EINVAL; goto done; } + if (fp->f_flag & FAPPENDONLY) { /* inode was set s/uapnd */ + error = EINVAL; + goto done; + } vp = (struct vnode *)fp->f_data; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (vp->v_type == VDIR) { @@ -3137,7 +3171,7 @@ kern_rename(struct nlookupdata *fromnd, struct nlookupdata *tond) int error; bwillinode(1); - fromnd->nl_flags |= NLC_REFDVP | NLC_DELETE; + fromnd->nl_flags |= NLC_REFDVP | NLC_RENAME_SRC; if ((error = nlookup(fromnd)) != 0) return (error); if ((fnchd.ncp = fromnd->nl_nch.ncp->nc_parent) == NULL) @@ -3158,7 +3192,7 @@ kern_rename(struct nlookupdata *fromnd, struct nlookupdata *tond) fromnd->nl_flags &= ~NLC_NCPISLOCKED; cache_unlock(&fromnd->nl_nch); - tond->nl_flags |= NLC_RENAME | NLC_REFDVP; + tond->nl_flags |= NLC_RENAME_DST | NLC_REFDVP; if ((error = nlookup(tond)) != 0) { cache_drop(&fnchd); return (error); diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index d0ab7c8654..89c30f8962 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -131,7 +131,13 @@ vn_open(struct nlookupdata *nd, struct file *fp, int fmode, int cmode) struct ucred *cred = nd->nl_cred; struct vattr vat; struct vattr *vap = &vat; - int mode, error; + int error; + + /* + * Certain combinations are illegal + */ + if ((fmode & (FWRITE | O_TRUNC)) == O_TRUNC) + return(EACCES); /* * Lookup the path and create or obtain the vnode. After a @@ -142,6 +148,18 @@ vn_open(struct nlookupdata *nd, struct file *fp, int fmode, int cmode) * XXX with only a little work we should be able to avoid locking * the vnode if FWRITE, O_CREAT, and O_TRUNC are *not* set. */ + nd->nl_flags |= NLC_OPEN; + if (fmode & O_APPEND) + nd->nl_flags |= NLC_APPEND; + if (fmode & O_TRUNC) + nd->nl_flags |= NLC_TRUNCATE; + if (fmode & FREAD) + nd->nl_flags |= NLC_READ; + if (fmode & FWRITE) + nd->nl_flags |= NLC_WRITE; + if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0) + nd->nl_flags |= NLC_FOLLOW; + if (fmode & O_CREAT) { /* * CONDITIONAL CREATE FILE CASE @@ -153,8 +171,6 @@ vn_open(struct nlookupdata *nd, struct file *fp, int fmode, int cmode) * write permission on the governing directory or EPERM * is returned. */ - if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0) - nd->nl_flags |= NLC_FOLLOW; nd->nl_flags |= NLC_CREATE; nd->nl_flags |= NLC_REFDVP; bwillinode(1); @@ -219,7 +235,6 @@ again: goto bad; } if ((fmode & O_CREAT) == 0) { - mode = 0; if (fmode & (FWRITE | O_TRUNC)) { if (vp->v_type == VDIR) { error = EISDIR; @@ -241,27 +256,6 @@ again: } goto bad; } - mode |= VWRITE; - } - if (fmode & FREAD) - mode |= VREAD; - if (mode) { - error = VOP_ACCESS(vp, mode, cred); - if (error) { - /* - * Special stale handling, re-resolve the - * vnode. - */ - if (error == ESTALE) { - vput(vp); - vp = NULL; - cache_setunresolved(&nd->nl_nch); - error = cache_resolve(&nd->nl_nch, cred); - if (error == 0) - goto again; - } - goto bad; - } } } if (fmode & O_TRUNC) { @@ -284,6 +278,8 @@ again: * used to open the file. */ if (fp) { + if (nd->nl_flags & NLC_APPENDONLY) + fmode |= FAPPENDONLY; fp->f_nchandle = nd->nl_nch; cache_zero(&nd->nl_nch); cache_unlock(&fp->f_nchandle); diff --git a/sys/net/if_poll.c b/sys/net/if_poll.c index 602573702d..e56689daab 100644 --- a/sys/net/if_poll.c +++ b/sys/net/if_poll.c @@ -64,6 +64,12 @@ * ifpoll_info.ifpi_tx[n].poll_func == NULL * No TX polling handler will be installed on CPU(n) * + * RX is polled at the specified polling frequency (net.ifpoll.X.pollhz). + * TX and status polling could be done at lower frequency than RX frequency + * (net.ifpoll.0.status_frac and net.ifpoll.X.tx_frac). To avoid systimer + * staggering at high frequency, RX systimer gives TX and status polling a + * piggyback (XXX). + * * All of the registered polling handlers are called only if the interface * is marked as 'IFF_RUNNING and IFF_NPOLLING'. However, the interface's * register and deregister function (ifnet.if_qpoll) will be called even @@ -106,11 +112,9 @@ #define IOPOLL_EACH_BURST 5 #define IFPOLL_FREQ_DEFAULT 2000 -#define IOPOLL_FREQ_DEFAULT IFPOLL_FREQ_DEFAULT -#define STPOLL_FREQ_DEFAULT 100 -#define IFPOLL_TXFRAC_DEFAULT 1 -#define IFPOLL_STFRAC_DEFAULT 20 +#define IFPOLL_TXFRAC_DEFAULT 1 /* 1/2 of the pollhz */ +#define IFPOLL_STFRAC_DEFAULT 19 /* 1/20 of the pollhz */ #define IFPOLL_RX 0x1 #define IFPOLL_TX 0x2 @@ -128,10 +132,6 @@ struct iopoll_rec { }; struct iopoll_ctx { -#ifdef IFPOLL_MULTI_SYSTIMER - struct systimer pollclock; -#endif - union ifpoll_time prev_t; uint32_t short_ticks; /* statistics */ uint32_t lost_polls; /* statistics */ @@ -142,11 +142,7 @@ struct iopoll_ctx { struct netmsg poll_netmsg; int poll_cpuid; -#ifdef IFPOLL_MULTI_SYSTIMER - int pollhz; /* tunable */ -#else - int poll_type; /* IFPOLL_{RX,TX} */ -#endif + int pollhz; uint32_t phase; /* state */ int residual_burst; /* state */ uint32_t poll_each_burst; /* tunable */ @@ -166,7 +162,18 @@ struct iopoll_ctx { struct sysctl_oid *poll_sysctl_tree; } __cachealign; -struct iopoll_comm { +struct poll_comm { + struct systimer pollclock; + int poll_cpuid; + + int stfrac_count; /* state */ + int poll_stfrac; /* tunable */ + + int txfrac_count; /* state */ + int poll_txfrac; /* tunable */ + + int pollhz; /* tunable */ + struct sysctl_ctx_list sysctl_ctx; struct sysctl_oid *sysctl_tree; } __cachealign; @@ -178,15 +185,10 @@ struct stpoll_rec { }; struct stpoll_ctx { -#ifdef IFPOLL_MULTI_SYSTIMER - struct systimer pollclock; -#endif - struct netmsg poll_netmsg; -#ifdef IFPOLL_MULTI_SYSTIMER - int pollhz; /* tunable */ -#endif + int pollhz; + uint32_t poll_handlers; /* next free entry in pr[]. */ struct stpoll_rec pr[IFPOLL_LIST_LEN]; @@ -199,77 +201,7 @@ struct iopoll_sysctl_netmsg { struct iopoll_ctx *ctx; }; -#ifndef IFPOLL_MULTI_SYSTIMER - -struct ifpoll_data { - struct systimer clock; - int txfrac_count; - int stfrac_count; - u_int tx_cpumask; - u_int rx_cpumask; -} __cachealign; - -#endif - -static struct stpoll_ctx stpoll_context; -static struct iopoll_comm *iopoll_common[IFPOLL_CTX_MAX]; -static struct iopoll_ctx *rxpoll_context[IFPOLL_CTX_MAX]; -static struct iopoll_ctx *txpoll_context[IFPOLL_CTX_MAX]; - -SYSCTL_NODE(_net, OID_AUTO, ifpoll, CTLFLAG_RW, 0, - "Network device polling parameters"); - -static int ifpoll_ncpus = IFPOLL_CTX_MAX; - -static int iopoll_burst_max = IOPOLL_BURST_MAX; -static int iopoll_each_burst = IOPOLL_EACH_BURST; - -TUNABLE_INT("net.ifpoll.burst_max", &iopoll_burst_max); -TUNABLE_INT("net.ifpoll.each_burst", &iopoll_each_burst); - -#ifdef IFPOLL_MULTI_SYSTIMER - -static int stpoll_hz = STPOLL_FREQ_DEFAULT; -static int iopoll_hz = IOPOLL_FREQ_DEFAULT; - -TUNABLE_INT("net.ifpoll.stpoll_hz", &stpoll_hz); -TUNABLE_INT("net.ifpoll.iopoll_hz", &iopoll_hz); - -#else /* !IFPOLL_MULTI_SYSTIMER */ - -static struct ifpoll_data ifpoll0; -static int ifpoll_pollhz = IFPOLL_FREQ_DEFAULT; -static int ifpoll_stfrac = IFPOLL_STFRAC_DEFAULT; -static int ifpoll_txfrac = IFPOLL_TXFRAC_DEFAULT; -static int ifpoll_handlers; - -TUNABLE_INT("net.ifpoll.pollhz", &ifpoll_pollhz); -TUNABLE_INT("net.ifpoll.status_frac", &ifpoll_stfrac); -TUNABLE_INT("net.ifpoll.tx_frac", &ifpoll_txfrac); - -static void sysctl_ifpollhz_handler(struct netmsg *); -static int sysctl_ifpollhz(SYSCTL_HANDLER_ARGS); - -SYSCTL_PROC(_net_ifpoll, OID_AUTO, pollhz, CTLTYPE_INT | CTLFLAG_RW, - 0, 0, sysctl_ifpollhz, "I", "Polling frequency"); -SYSCTL_INT(_net_ifpoll, OID_AUTO, tx_frac, CTLFLAG_RW, - &ifpoll_txfrac, 0, "Every this many cycles poll transmit"); -SYSCTL_INT(_net_ifpoll, OID_AUTO, st_frac, CTLFLAG_RW, - &ifpoll_stfrac, 0, "Every this many cycles poll status"); - -#endif /* IFPOLL_MULTI_SYSTIMER */ - void ifpoll_init_pcpu(int); - -#ifndef IFPOLL_MULTI_SYSTIMER -static void ifpoll_start_handler(struct netmsg *); -static void ifpoll_stop_handler(struct netmsg *); -static void ifpoll_handler_addevent(void); -static void ifpoll_handler_delevent(void); -static void ifpoll_ipi_handler(void *, int); -static void ifpoll_systimer(systimer_t, struct intrframe *); -#endif - static void ifpoll_register_handler(struct netmsg *); static void ifpoll_deregister_handler(struct netmsg *); @@ -279,44 +211,66 @@ static void ifpoll_deregister_handler(struct netmsg *); static void stpoll_init(void); static void stpoll_handler(struct netmsg *); static void stpoll_clock(struct stpoll_ctx *); -#ifdef IFPOLL_MULTI_SYSTIMER -static void stpoll_systimer(systimer_t, struct intrframe *); -#endif static int stpoll_register(struct ifnet *, const struct ifpoll_status *); static int stpoll_deregister(struct ifnet *); -#ifdef IFPOLL_MULTI_SYSTIMER -static void sysctl_stpollhz_handler(struct netmsg *); -static int sysctl_stpollhz(SYSCTL_HANDLER_ARGS); -#endif - /* * RX/TX polling */ static struct iopoll_ctx *iopoll_ctx_create(int, int); -static struct iopoll_comm *iopoll_comm_create(int); static void iopoll_init(int); static void iopoll_handler(struct netmsg *); static void iopollmore_handler(struct netmsg *); static void iopoll_clock(struct iopoll_ctx *); -#ifdef IFPOLL_MULTI_SYSTIMER -static void iopoll_systimer(systimer_t, struct intrframe *); -#endif static int iopoll_register(struct ifnet *, struct iopoll_ctx *, const struct ifpoll_io *); static int iopoll_deregister(struct ifnet *, struct iopoll_ctx *); static void iopoll_add_sysctl(struct sysctl_ctx_list *, struct sysctl_oid_list *, struct iopoll_ctx *); -#ifdef IFPOLL_MULTI_SYSTIMER -static void sysctl_iopollhz_handler(struct netmsg *); -static int sysctl_iopollhz(SYSCTL_HANDLER_ARGS); -#endif static void sysctl_burstmax_handler(struct netmsg *); static int sysctl_burstmax(SYSCTL_HANDLER_ARGS); static void sysctl_eachburst_handler(struct netmsg *); static int sysctl_eachburst(SYSCTL_HANDLER_ARGS); +/* + * Common functions + */ +static void poll_comm_init(int); +static void poll_comm_start(int); +static void poll_comm_adjust_pollhz(struct poll_comm *); +static void poll_comm_systimer0(systimer_t, struct intrframe *); +static void poll_comm_systimer(systimer_t, struct intrframe *); +static void sysctl_pollhz_handler(struct netmsg *); +static void sysctl_stfrac_handler(struct netmsg *); +static void sysctl_txfrac_handler(struct netmsg *); +static int sysctl_pollhz(SYSCTL_HANDLER_ARGS); +static int sysctl_stfrac(SYSCTL_HANDLER_ARGS); +static int sysctl_txfrac(SYSCTL_HANDLER_ARGS); + +static struct stpoll_ctx stpoll_context; +static struct poll_comm *poll_common[IFPOLL_CTX_MAX]; +static struct iopoll_ctx *rxpoll_context[IFPOLL_CTX_MAX]; +static struct iopoll_ctx *txpoll_context[IFPOLL_CTX_MAX]; + +SYSCTL_NODE(_net, OID_AUTO, ifpoll, CTLFLAG_RW, 0, + "Network device polling parameters"); + +static int ifpoll_ncpus = IFPOLL_CTX_MAX; + +static int iopoll_burst_max = IOPOLL_BURST_MAX; +static int iopoll_each_burst = IOPOLL_EACH_BURST; + +static int ifpoll_pollhz = IFPOLL_FREQ_DEFAULT; +static int ifpoll_stfrac = IFPOLL_STFRAC_DEFAULT; +static int ifpoll_txfrac = IFPOLL_TXFRAC_DEFAULT; + +TUNABLE_INT("net.ifpoll.burst_max", &iopoll_burst_max); +TUNABLE_INT("net.ifpoll.each_burst", &iopoll_each_burst); +TUNABLE_INT("net.ifpoll.pollhz", &ifpoll_pollhz); +TUNABLE_INT("net.ifpoll.status_frac", &ifpoll_stfrac); +TUNABLE_INT("net.ifpoll.tx_frac", &ifpoll_txfrac); + static __inline void ifpoll_sendmsg_oncpu(struct netmsg *msg) { @@ -369,166 +323,25 @@ ifpoll_time_diff(const union ifpoll_time *s, const union ifpoll_time *e) void ifpoll_init_pcpu(int cpuid) { - if (cpuid >= IFPOLL_CTX_MAX) { + if (cpuid >= IFPOLL_CTX_MAX) return; - } else if (cpuid == 0) { + + if (cpuid == 0) { if (ifpoll_ncpus > ncpus) ifpoll_ncpus = ncpus; - kprintf("ifpoll_ncpus %d\n", ifpoll_ncpus); + if (bootverbose) + kprintf("ifpoll_ncpus %d\n", ifpoll_ncpus); + } -#ifndef IFPOLL_MULTI_SYSTIMER - systimer_init_periodic_nq(&ifpoll0.clock, - ifpoll_systimer, NULL, 1); -#endif + poll_comm_init(cpuid); + if (cpuid == 0) stpoll_init(); - } iopoll_init(cpuid); -} - -#ifndef IFPOLL_MULTI_SYSTIMER - -#ifdef SMP -static void -ifpoll_ipi_handler(void *arg __unused, int poll) -{ - KKASSERT(mycpuid < ifpoll_ncpus); - - if (poll & IFPOLL_TX) - iopoll_clock(txpoll_context[mycpuid]); - if (poll & IFPOLL_RX) - iopoll_clock(rxpoll_context[mycpuid]); -} -#endif /* SMP */ - -static void -ifpoll_systimer(systimer_t info __unused, struct intrframe *frame __unused) -{ -#ifdef SMP - uint32_t cpumask = 0; -#endif - - KKASSERT(mycpuid == 0); - - if (ifpoll0.stfrac_count-- == 0) { - ifpoll0.stfrac_count = ifpoll_stfrac; - stpoll_clock(&stpoll_context); - } - - if (ifpoll0.txfrac_count-- == 0) { - ifpoll0.txfrac_count = ifpoll_txfrac; - -#ifdef SMP - /* TODO: We may try to piggyback TX on RX */ - cpumask = smp_active_mask & ifpoll0.tx_cpumask; - if (cpumask != 0) { - lwkt_send_ipiq2_mask(cpumask, ifpoll_ipi_handler, - NULL, IFPOLL_TX); - } -#else - iopoll_clock(txpoll_context[0]); -#endif - } - -#ifdef SMP - cpumask = smp_active_mask & ifpoll0.rx_cpumask; - if (cpumask != 0) { - lwkt_send_ipiq2_mask(cpumask, ifpoll_ipi_handler, - NULL, IFPOLL_RX); - } -#else - iopoll_clock(rxpoll_context[0]); -#endif -} - -static void -ifpoll_start_handler(struct netmsg *nmsg) -{ - KKASSERT(&curthread->td_msgport == ifnet_portfn(0)); - - kprintf("ifpoll: start\n"); - systimer_adjust_periodic(&ifpoll0.clock, ifpoll_pollhz); - lwkt_replymsg(&nmsg->nm_lmsg, 0); -} - -static void -ifpoll_stop_handler(struct netmsg *nmsg) -{ - KKASSERT(&curthread->td_msgport == ifnet_portfn(0)); - - kprintf("ifpoll: stop\n"); - systimer_adjust_periodic(&ifpoll0.clock, 1); - lwkt_replymsg(&nmsg->nm_lmsg, 0); -} - -static void -ifpoll_handler_addevent(void) -{ - if (atomic_fetchadd_int(&ifpoll_handlers, 1) == 0) { - struct netmsg *nmsg; - - /* Start systimer */ - nmsg = kmalloc(sizeof(*nmsg), M_LWKTMSG, M_WAITOK); - netmsg_init(nmsg, &netisr_afree_rport, 0, ifpoll_start_handler); - ifnet_sendmsg(&nmsg->nm_lmsg, 0); - } -} - -static void -ifpoll_handler_delevent(void) -{ - KKASSERT(ifpoll_handlers > 0); - if (atomic_fetchadd_int(&ifpoll_handlers, -1) == 1) { - struct netmsg *nmsg; - - /* Stop systimer */ - nmsg = kmalloc(sizeof(*nmsg), M_LWKTMSG, M_WAITOK); - netmsg_init(nmsg, &netisr_afree_rport, 0, ifpoll_stop_handler); - ifnet_sendmsg(&nmsg->nm_lmsg, 0); - } -} - -static void -sysctl_ifpollhz_handler(struct netmsg *nmsg) -{ - KKASSERT(&curthread->td_msgport == ifnet_portfn(0)); - - /* - * If there is no handler registered, don't adjust polling - * systimer frequency; polling systimer frequency will be - * adjusted once there is registered handler. - */ - ifpoll_pollhz = nmsg->nm_lmsg.u.ms_result; - if (ifpoll_handlers) - systimer_adjust_periodic(&ifpoll0.clock, ifpoll_pollhz); - lwkt_replymsg(&nmsg->nm_lmsg, 0); + poll_comm_start(cpuid); } -static int -sysctl_ifpollhz(SYSCTL_HANDLER_ARGS) -{ - struct netmsg nmsg; - int error, phz; - - phz = ifpoll_pollhz; - error = sysctl_handle_int(oidp, &phz, 0, req); - if (error || req->newptr == NULL) - return error; - if (phz <= 0) - return EINVAL; - else if (phz > IFPOLL_FREQ_MAX) - phz = IFPOLL_FREQ_MAX; - - netmsg_init(&nmsg, &curthread->td_msgport, MSGF_MPSAFE, - sysctl_ifpollhz_handler); - nmsg.nm_lmsg.u.ms_result = phz; - - return ifnet_domsg(&nmsg.nm_lmsg, 0); -} - -#endif /* !IFPOLL_MULTI_SYSTIMER */ - int ifpoll_register(struct ifnet *ifp) { @@ -633,6 +446,9 @@ ifpoll_register_handler(struct netmsg *nmsg) if (error) goto failed; + /* Adjust polling frequency, after all registration is done */ + poll_comm_adjust_pollhz(poll_common[cpuid]); + nextcpu = cpuid + 1; if (nextcpu < ifpoll_ncpus) ifnet_forwardmsg(&nmsg->nm_lmsg, nextcpu); @@ -658,6 +474,9 @@ ifpoll_deregister_handler(struct netmsg *nmsg) iopoll_deregister(ifp, rxpoll_context[cpuid]); iopoll_deregister(ifp, txpoll_context[cpuid]); + /* Adjust polling frequency, after all deregistration is done */ + poll_comm_adjust_pollhz(poll_common[cpuid]); + nextcpu = cpuid + 1; if (nextcpu < ifpoll_ncpus) ifnet_forwardmsg(&nmsg->nm_lmsg, nextcpu); @@ -669,24 +488,15 @@ static void stpoll_init(void) { struct stpoll_ctx *st_ctx = &stpoll_context; + const struct poll_comm *comm = poll_common[0]; -#ifdef IFPOLL_MULTI_SYSTIMER - st_ctx->pollhz = stpoll_hz; -#endif + st_ctx->pollhz = comm->pollhz / (comm->poll_stfrac + 1); sysctl_ctx_init(&st_ctx->poll_sysctl_ctx); st_ctx->poll_sysctl_tree = SYSCTL_ADD_NODE(&st_ctx->poll_sysctl_ctx, - SYSCTL_STATIC_CHILDREN(_net_ifpoll), + SYSCTL_CHILDREN(comm->sysctl_tree), OID_AUTO, "status", CTLFLAG_RD, 0, ""); -#ifdef IFPOLL_MULTI_SYSTIMER - SYSCTL_ADD_PROC(&st_ctx->poll_sysctl_ctx, - SYSCTL_CHILDREN(st_ctx->poll_sysctl_tree), - OID_AUTO, "pollhz", CTLTYPE_INT | CTLFLAG_RW, - st_ctx, 0, sysctl_stpollhz, "I", - "Status polling frequency"); -#endif - SYSCTL_ADD_UINT(&st_ctx->poll_sysctl_ctx, SYSCTL_CHILDREN(st_ctx->poll_sysctl_tree), OID_AUTO, "handlers", CTLFLAG_RD, @@ -695,59 +505,8 @@ stpoll_init(void) netmsg_init(&st_ctx->poll_netmsg, &netisr_adone_rport, MSGF_MPSAFE, stpoll_handler); - -#ifdef IFPOLL_MULTI_SYSTIMER - systimer_init_periodic_nq(&st_ctx->pollclock, - stpoll_systimer, st_ctx, 1); -#endif } -#ifdef IFPOLL_MULTI_SYSTIMER - -static void -sysctl_stpollhz_handler(struct netmsg *msg) -{ - struct stpoll_ctx *st_ctx = &stpoll_context; - - KKASSERT(&curthread->td_msgport == ifnet_portfn(0)); - - /* - * If there is no handler registered, don't adjust polling - * systimer frequency; polling systimer frequency will be - * adjusted once there is registered handler. - */ - st_ctx->pollhz = msg->nm_lmsg.u.ms_result; - if (st_ctx->poll_handlers) - systimer_adjust_periodic(&st_ctx->pollclock, st_ctx->pollhz); - - lwkt_replymsg(&msg->nm_lmsg, 0); -} - -static int -sysctl_stpollhz(SYSCTL_HANDLER_ARGS) -{ - struct stpoll_ctx *st_ctx = arg1; - struct netmsg msg; - int error, phz; - - phz = st_ctx->pollhz; - error = sysctl_handle_int(oidp, &phz, 0, req); - if (error || req->newptr == NULL) - return error; - if (phz <= 0) - return EINVAL; - else if (phz > IFPOLL_FREQ_MAX) - phz = IFPOLL_FREQ_MAX; - - netmsg_init(&msg, &curthread->td_msgport, MSGF_MPSAFE, - sysctl_stpollhz_handler); - msg.nm_lmsg.u.ms_result = phz; - - return ifnet_domsg(&msg.nm_lmsg, 0); -} - -#endif /* IFPOLL_MULTI_SYSTIMER */ - /* * stpoll_handler is scheduled by sched_stpoll when appropriate, typically * once per polling systimer tick. @@ -757,7 +516,7 @@ stpoll_handler(struct netmsg *msg) { struct stpoll_ctx *st_ctx = &stpoll_context; struct thread *td = curthread; - int i, poll_hz; + int i; KKASSERT(&td->td_msgport == ifnet_portfn(0)); @@ -771,12 +530,6 @@ stpoll_handler(struct netmsg *msg) return; } -#ifdef IFPOLL_MULTI_SYSTIMER - poll_hz = st_ctx->pollhz; -#else - poll_hz = ifpoll_pollhz / (ifpoll_stfrac + 1); -#endif - for (i = 0; i < st_ctx->poll_handlers; ++i) { const struct stpoll_rec *rec = &st_ctx->pr[i]; struct ifnet *ifp = rec->ifp; @@ -786,7 +539,7 @@ stpoll_handler(struct netmsg *msg) if ((ifp->if_flags & (IFF_RUNNING | IFF_NPOLLING)) == (IFF_RUNNING | IFF_NPOLLING)) - rec->status_func(ifp, poll_hz); + rec->status_func(ifp, st_ctx->pollhz); lwkt_serialize_exit(rec->serializer); } @@ -796,29 +549,17 @@ stpoll_handler(struct netmsg *msg) /* * Hook from status poll systimer. Tries to schedule an status poll. + * NOTE: Caller should hold critical section. */ static void stpoll_clock(struct stpoll_ctx *st_ctx) { - globaldata_t gd = mycpu; - - KKASSERT(gd->gd_cpuid == 0); + KKASSERT(mycpuid == 0); if (st_ctx->poll_handlers == 0) return; - - crit_enter_gd(gd); sched_stpoll(st_ctx); - crit_exit_gd(gd); -} - -#ifdef IFPOLL_MULTI_SYSTIMER -static void -stpoll_systimer(systimer_t info, struct intrframe *frame __unused) -{ - stpoll_clock(info->data); } -#endif static int stpoll_register(struct ifnet *ifp, const struct ifpoll_status *st_rec) @@ -858,15 +599,6 @@ stpoll_register(struct ifnet *ifp, const struct ifpoll_status *st_rec) rec->status_func = st_rec->status_func; st_ctx->poll_handlers++; - -#ifdef IFPOLL_MULTI_SYSTIMER - if (st_ctx->poll_handlers == 1) { - systimer_adjust_periodic(&st_ctx->pollclock, - st_ctx->pollhz); - } -#else - ifpoll_handler_addevent(); -#endif error = 0; } return error; @@ -893,31 +625,11 @@ stpoll_deregister(struct ifnet *ifp) /* Last entry replaces this one. */ st_ctx->pr[i] = st_ctx->pr[st_ctx->poll_handlers]; } - -#ifdef IFPOLL_MULTI_SYSTIMER - if (st_ctx->poll_handlers == 0) - systimer_adjust_periodic(&st_ctx->pollclock, 1); -#else - ifpoll_handler_delevent(); -#endif error = 0; } return error; } -#ifndef IFPOLL_MULTI_SYSTIMER -static __inline int -iopoll_hz(struct iopoll_ctx *io_ctx) -{ - int poll_hz; - - poll_hz = ifpoll_pollhz; - if (io_ctx->poll_type == IFPOLL_TX) - poll_hz /= ifpoll_txfrac + 1; - return poll_hz; -} -#endif - static __inline void iopoll_reset_state(struct iopoll_ctx *io_ctx) { @@ -937,35 +649,14 @@ iopoll_init(int cpuid) { KKASSERT(cpuid < IFPOLL_CTX_MAX); - /* Create iopoll_comm context before TX/RX poll context */ - iopoll_common[cpuid] = iopoll_comm_create(cpuid); - rxpoll_context[cpuid] = iopoll_ctx_create(cpuid, IFPOLL_RX); txpoll_context[cpuid] = iopoll_ctx_create(cpuid, IFPOLL_TX); } -static struct iopoll_comm * -iopoll_comm_create(int cpuid) -{ - struct iopoll_comm *comm; - char cpuid_str[16]; - - comm = kmalloc(sizeof(*comm), M_DEVBUF, M_WAITOK | M_ZERO); - - ksnprintf(cpuid_str, sizeof(cpuid_str), "%d", cpuid); - - sysctl_ctx_init(&comm->sysctl_ctx); - comm->sysctl_tree = SYSCTL_ADD_NODE(&comm->sysctl_ctx, - SYSCTL_STATIC_CHILDREN(_net_ifpoll), - OID_AUTO, cpuid_str, CTLFLAG_RD, 0, ""); - - return comm; -} - static struct iopoll_ctx * iopoll_ctx_create(int cpuid, int poll_type) { - struct iopoll_comm *comm; + struct poll_comm *comm; struct iopoll_ctx *io_ctx; const char *poll_type_str; @@ -982,6 +673,8 @@ iopoll_ctx_create(int cpuid, int poll_type) if (iopoll_each_burst > iopoll_burst_max) iopoll_each_burst = iopoll_burst_max; + comm = poll_common[cpuid]; + /* * Create the per-cpu polling context */ @@ -990,11 +683,10 @@ iopoll_ctx_create(int cpuid, int poll_type) io_ctx->poll_each_burst = iopoll_each_burst; io_ctx->poll_burst_max = iopoll_burst_max; io_ctx->user_frac = 50; -#ifdef IFPOLL_MULTI_SYSTIMER - io_ctx->pollhz = iopoll_hz; -#else - io_ctx->poll_type = poll_type; -#endif + if (poll_type == IFPOLL_RX) + io_ctx->pollhz = comm->pollhz; + else + io_ctx->pollhz = comm->pollhz / (comm->poll_txfrac + 1); io_ctx->poll_cpuid = cpuid; iopoll_reset_state(io_ctx); @@ -1014,7 +706,6 @@ iopoll_ctx_create(int cpuid, int poll_type) else poll_type_str = "tx"; - comm = iopoll_common[cpuid]; sysctl_ctx_init(&io_ctx->poll_sysctl_ctx); io_ctx->poll_sysctl_tree = SYSCTL_ADD_NODE(&io_ctx->poll_sysctl_ctx, SYSCTL_CHILDREN(comm->sysctl_tree), @@ -1022,14 +713,6 @@ iopoll_ctx_create(int cpuid, int poll_type) iopoll_add_sysctl(&io_ctx->poll_sysctl_ctx, SYSCTL_CHILDREN(io_ctx->poll_sysctl_tree), io_ctx); -#ifdef IFPOLL_MULTI_SYSTIMER - /* - * Initialize systimer - */ - systimer_init_periodic_nq(&io_ctx->pollclock, - iopoll_systimer, io_ctx, 1); -#endif - return io_ctx; } @@ -1047,28 +730,22 @@ iopoll_ctx_create(int cpuid, int poll_type) * meaning either stray interrupts or delayed events. * * WARNING! called from fastint or IPI, the MP lock might not be held. + * NOTE: Caller should hold critical section. */ static void iopoll_clock(struct iopoll_ctx *io_ctx) { - globaldata_t gd = mycpu; union ifpoll_time t; - int delta, poll_hz; + int delta; - KKASSERT(gd->gd_cpuid == io_ctx->poll_cpuid); + KKASSERT(mycpuid == io_ctx->poll_cpuid); if (io_ctx->poll_handlers == 0) return; -#ifdef IFPOLL_MULTI_SYSTIMER - poll_hz = io_ctx->pollhz; -#else - poll_hz = iopoll_hz(io_ctx); -#endif - ifpoll_time_get(&t); delta = ifpoll_time_diff(&io_ctx->prev_t, &t); - if (delta * poll_hz < 500000) + if (delta * io_ctx->pollhz < 500000) io_ctx->short_ticks++; else io_ctx->prev_t = t; @@ -1087,23 +764,13 @@ iopoll_clock(struct iopoll_ctx *io_ctx) if (io_ctx->phase != 0) io_ctx->suspect++; io_ctx->phase = 1; - crit_enter_gd(gd); sched_iopoll(io_ctx); - crit_exit_gd(gd); io_ctx->phase = 2; } if (io_ctx->pending_polls++ > 0) io_ctx->lost_polls++; } -#ifdef IFPOLL_MULTI_SYSTIMER -static void -iopoll_systimer(systimer_t info, struct intrframe *frame __unused) -{ - iopoll_clock(info->data); -} -#endif - /* * iopoll_handler is scheduled by sched_iopoll when appropriate, typically * once per polling systimer tick. @@ -1186,7 +853,7 @@ iopollmore_handler(struct netmsg *msg) struct thread *td = curthread; struct iopoll_ctx *io_ctx; union ifpoll_time t; - int kern_load, poll_hz; + int kern_load; uint32_t pending_polls; io_ctx = msg->nm_lmsg.u.ms_resultp; @@ -1202,12 +869,6 @@ iopollmore_handler(struct netmsg *msg) return; } -#ifdef IFPOLL_MULTI_SYSTIMER - poll_hz = io_ctx->pollhz; -#else - poll_hz = iopoll_hz(io_ctx); -#endif - io_ctx->phase = 5; if (io_ctx->residual_burst > 0) { sched_iopoll(io_ctx); @@ -1219,7 +880,7 @@ iopollmore_handler(struct netmsg *msg) /* Here we can account time spent in iopoll's in this tick */ ifpoll_time_get(&t); kern_load = ifpoll_time_diff(&io_ctx->poll_start_t, &t); - kern_load = (kern_load * poll_hz) / 10000; /* 0..100 */ + kern_load = (kern_load * io_ctx->pollhz) / 10000; /* 0..100 */ io_ctx->kern_frac = kern_load; if (kern_load > (100 - io_ctx->user_frac)) { @@ -1257,12 +918,6 @@ static void iopoll_add_sysctl(struct sysctl_ctx_list *ctx, struct sysctl_oid_list *parent, struct iopoll_ctx *io_ctx) { -#ifdef IFPOLL_MULTI_SYSTIMER - SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "pollhz", - CTLTYPE_INT | CTLFLAG_RW, io_ctx, 0, sysctl_iopollhz, - "I", "Device polling frequency"); -#endif - SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "burst_max", CTLTYPE_UINT | CTLFLAG_RW, io_ctx, 0, sysctl_burstmax, "IU", "Max Polling burst size"); @@ -1311,58 +966,6 @@ iopoll_add_sysctl(struct sysctl_ctx_list *ctx, struct sysctl_oid_list *parent, "Number of registered poll handlers"); } -#ifdef IFPOLL_MULTI_SYSTIMER - -static int -sysctl_iopollhz(SYSCTL_HANDLER_ARGS) -{ - struct iopoll_ctx *io_ctx = arg1; - struct iopoll_sysctl_netmsg msg; - struct netmsg *nmsg; - int error, phz; - - phz = io_ctx->pollhz; - error = sysctl_handle_int(oidp, &phz, 0, req); - if (error || req->newptr == NULL) - return error; - if (phz <= 0) - return EINVAL; - else if (phz > IFPOLL_FREQ_MAX) - phz = IFPOLL_FREQ_MAX; - - nmsg = &msg.nmsg; - netmsg_init(nmsg, &curthread->td_msgport, MSGF_MPSAFE, - sysctl_iopollhz_handler); - nmsg->nm_lmsg.u.ms_result = phz; - msg.ctx = io_ctx; - - return ifnet_domsg(&nmsg->nm_lmsg, io_ctx->poll_cpuid); -} - -static void -sysctl_iopollhz_handler(struct netmsg *nmsg) -{ - struct iopoll_sysctl_netmsg *msg = (struct iopoll_sysctl_netmsg *)nmsg; - struct iopoll_ctx *io_ctx; - - io_ctx = msg->ctx; - KKASSERT(&curthread->td_msgport == ifnet_portfn(io_ctx->poll_cpuid)); - - /* - * If polling is disabled or there is no polling handler - * registered, don't adjust polling systimer frequency. - * Polling systimer frequency will be adjusted once there - * are registered handlers. - */ - io_ctx->pollhz = nmsg->nm_lmsg.u.ms_result; - if (io_ctx->poll_handlers) - systimer_adjust_periodic(&io_ctx->pollclock, io_ctx->pollhz); - - lwkt_replymsg(&nmsg->nm_lmsg, 0); -} - -#endif /* IFPOLL_MULTI_SYSTIMER */ - static void sysctl_burstmax_handler(struct netmsg *nmsg) { @@ -1491,24 +1094,6 @@ iopoll_register(struct ifnet *ifp, struct iopoll_ctx *io_ctx, rec->poll_func = io_rec->poll_func; io_ctx->poll_handlers++; - if (io_ctx->poll_handlers == 1) { -#ifdef IFPOLL_MULTI_SYSTIMER - systimer_adjust_periodic(&io_ctx->pollclock, - io_ctx->pollhz); -#else - u_int *mask; - - if (io_ctx->poll_type == IFPOLL_RX) - mask = &ifpoll0.rx_cpumask; - else - mask = &ifpoll0.tx_cpumask; - KKASSERT((*mask & mycpu->gd_cpumask) == 0); - atomic_set_int(mask, mycpu->gd_cpumask); -#endif - } -#ifndef IFPOLL_MULTI_SYSTIMER - ifpoll_handler_addevent(); -#endif error = 0; } return error; @@ -1534,25 +1119,264 @@ iopoll_deregister(struct ifnet *ifp, struct iopoll_ctx *io_ctx) io_ctx->pr[i] = io_ctx->pr[io_ctx->poll_handlers]; } - if (io_ctx->poll_handlers == 0) { -#ifdef IFPOLL_MULTI_SYSTIMER - systimer_adjust_periodic(&io_ctx->pollclock, 1); -#else - u_int *mask; - - if (io_ctx->poll_type == IFPOLL_RX) - mask = &ifpoll0.rx_cpumask; - else - mask = &ifpoll0.tx_cpumask; - KKASSERT(*mask & mycpu->gd_cpumask); - atomic_clear_int(mask, mycpu->gd_cpumask); -#endif + if (io_ctx->poll_handlers == 0) iopoll_reset_state(io_ctx); - } -#ifndef IFPOLL_MULTI_SYSTIMER - ifpoll_handler_delevent(); -#endif error = 0; } return error; } + +static void +poll_comm_init(int cpuid) +{ + struct poll_comm *comm; + char cpuid_str[16]; + + comm = kmalloc(sizeof(*comm), M_DEVBUF, M_WAITOK | M_ZERO); + + if (ifpoll_stfrac < 0) + ifpoll_stfrac = IFPOLL_STFRAC_DEFAULT; + if (ifpoll_txfrac < 0) + ifpoll_txfrac = IFPOLL_TXFRAC_DEFAULT; + + comm->pollhz = ifpoll_pollhz; + comm->poll_cpuid = cpuid; + comm->poll_stfrac = ifpoll_stfrac; + comm->poll_txfrac = ifpoll_txfrac; + + ksnprintf(cpuid_str, sizeof(cpuid_str), "%d", cpuid); + + sysctl_ctx_init(&comm->sysctl_ctx); + comm->sysctl_tree = SYSCTL_ADD_NODE(&comm->sysctl_ctx, + SYSCTL_STATIC_CHILDREN(_net_ifpoll), + OID_AUTO, cpuid_str, CTLFLAG_RD, 0, ""); + + SYSCTL_ADD_PROC(&comm->sysctl_ctx, SYSCTL_CHILDREN(comm->sysctl_tree), + OID_AUTO, "pollhz", CTLTYPE_INT | CTLFLAG_RW, + comm, 0, sysctl_pollhz, + "I", "Device polling frequency"); + + if (cpuid == 0) { + SYSCTL_ADD_PROC(&comm->sysctl_ctx, + SYSCTL_CHILDREN(comm->sysctl_tree), + OID_AUTO, "status_frac", + CTLTYPE_INT | CTLFLAG_RW, + comm, 0, sysctl_stfrac, + "I", "# of cycles before status is polled"); + } + SYSCTL_ADD_PROC(&comm->sysctl_ctx, SYSCTL_CHILDREN(comm->sysctl_tree), + OID_AUTO, "tx_frac", CTLTYPE_INT | CTLFLAG_RW, + comm, 0, sysctl_txfrac, + "I", "# of cycles before TX is polled"); + + poll_common[cpuid] = comm; +} + +static void +poll_comm_start(int cpuid) +{ + struct poll_comm *comm = poll_common[cpuid]; + void (*func)(systimer_t, struct intrframe *); + + /* + * Initialize systimer + */ + if (cpuid == 0) + func = poll_comm_systimer0; + else + func = poll_comm_systimer; + systimer_init_periodic_nq(&comm->pollclock, func, comm, 1); +} + +static void +_poll_comm_systimer(struct poll_comm *comm) +{ + if (comm->txfrac_count-- == 0) { + comm->txfrac_count = comm->poll_txfrac; + iopoll_clock(txpoll_context[comm->poll_cpuid]); + } + iopoll_clock(rxpoll_context[comm->poll_cpuid]); +} + +static void +poll_comm_systimer0(systimer_t info, struct intrframe *frame __unused) +{ + struct poll_comm *comm = info->data; + globaldata_t gd = mycpu; + + KKASSERT(comm->poll_cpuid == gd->gd_cpuid && gd->gd_cpuid == 0); + + crit_enter_gd(gd); + + if (comm->stfrac_count-- == 0) { + comm->stfrac_count = comm->poll_stfrac; + stpoll_clock(&stpoll_context); + } + _poll_comm_systimer(comm); + + crit_exit_gd(gd); +} + +static void +poll_comm_systimer(systimer_t info, struct intrframe *frame __unused) +{ + struct poll_comm *comm = info->data; + globaldata_t gd = mycpu; + + KKASSERT(comm->poll_cpuid == gd->gd_cpuid && gd->gd_cpuid != 0); + + crit_enter_gd(gd); + _poll_comm_systimer(comm); + crit_exit_gd(gd); +} + +static void +poll_comm_adjust_pollhz(struct poll_comm *comm) +{ + uint32_t handlers; + int pollhz = 1; + + KKASSERT(&curthread->td_msgport == ifnet_portfn(comm->poll_cpuid)); + + /* + * If there is no polling handler registered, set systimer + * frequency to the lowest value. Polling systimer frequency + * will be adjusted to the requested value, once there are + * registered handlers. + */ + handlers = rxpoll_context[mycpuid]->poll_handlers + + txpoll_context[mycpuid]->poll_handlers; + if (comm->poll_cpuid == 0) + handlers += stpoll_context.poll_handlers; + if (handlers) + pollhz = comm->pollhz; + systimer_adjust_periodic(&comm->pollclock, pollhz); +} + +static int +sysctl_pollhz(SYSCTL_HANDLER_ARGS) +{ + struct poll_comm *comm = arg1; + struct netmsg nmsg; + int error, phz; + + phz = comm->pollhz; + error = sysctl_handle_int(oidp, &phz, 0, req); + if (error || req->newptr == NULL) + return error; + if (phz <= 0) + return EINVAL; + else if (phz > IFPOLL_FREQ_MAX) + phz = IFPOLL_FREQ_MAX; + + netmsg_init(&nmsg, &curthread->td_msgport, MSGF_MPSAFE, + sysctl_pollhz_handler); + nmsg.nm_lmsg.u.ms_result = phz; + + return ifnet_domsg(&nmsg.nm_lmsg, comm->poll_cpuid); +} + +static void +sysctl_pollhz_handler(struct netmsg *nmsg) +{ + struct poll_comm *comm = poll_common[mycpuid]; + + KKASSERT(&curthread->td_msgport == ifnet_portfn(comm->poll_cpuid)); + + /* Save polling frequency */ + comm->pollhz = nmsg->nm_lmsg.u.ms_result; + + /* + * Adjust cached pollhz + */ + rxpoll_context[mycpuid]->pollhz = comm->pollhz; + txpoll_context[mycpuid]->pollhz = + comm->pollhz / (comm->poll_txfrac + 1); + if (mycpuid == 0) + stpoll_context.pollhz = comm->pollhz / (comm->poll_stfrac + 1); + + /* + * Adjust polling frequency + */ + poll_comm_adjust_pollhz(comm); + + lwkt_replymsg(&nmsg->nm_lmsg, 0); +} + +static int +sysctl_stfrac(SYSCTL_HANDLER_ARGS) +{ + struct poll_comm *comm = arg1; + struct netmsg nmsg; + int error, stfrac; + + KKASSERT(comm->poll_cpuid == 0); + + stfrac = comm->poll_stfrac; + error = sysctl_handle_int(oidp, &stfrac, 0, req); + if (error || req->newptr == NULL) + return error; + if (stfrac < 0) + return EINVAL; + + netmsg_init(&nmsg, &curthread->td_msgport, MSGF_MPSAFE, + sysctl_stfrac_handler); + nmsg.nm_lmsg.u.ms_result = stfrac; + + return ifnet_domsg(&nmsg.nm_lmsg, comm->poll_cpuid); +} + +static void +sysctl_stfrac_handler(struct netmsg *nmsg) +{ + struct poll_comm *comm = poll_common[mycpuid]; + int stfrac = nmsg->nm_lmsg.u.ms_result; + + KKASSERT(&curthread->td_msgport == ifnet_portfn(comm->poll_cpuid)); + + crit_enter(); + comm->poll_stfrac = stfrac; + if (comm->stfrac_count > comm->poll_stfrac) + comm->stfrac_count = comm->poll_stfrac; + crit_exit(); + + lwkt_replymsg(&nmsg->nm_lmsg, 0); +} + +static int +sysctl_txfrac(SYSCTL_HANDLER_ARGS) +{ + struct poll_comm *comm = arg1; + struct netmsg nmsg; + int error, txfrac; + + txfrac = comm->poll_txfrac; + error = sysctl_handle_int(oidp, &txfrac, 0, req); + if (error || req->newptr == NULL) + return error; + if (txfrac < 0) + return EINVAL; + + netmsg_init(&nmsg, &curthread->td_msgport, MSGF_MPSAFE, + sysctl_txfrac_handler); + nmsg.nm_lmsg.u.ms_result = txfrac; + + return ifnet_domsg(&nmsg.nm_lmsg, comm->poll_cpuid); +} + +static void +sysctl_txfrac_handler(struct netmsg *nmsg) +{ + struct poll_comm *comm = poll_common[mycpuid]; + int txfrac = nmsg->nm_lmsg.u.ms_result; + + KKASSERT(&curthread->td_msgport == ifnet_portfn(comm->poll_cpuid)); + + crit_enter(); + comm->poll_txfrac = txfrac; + if (comm->txfrac_count > comm->poll_txfrac) + comm->txfrac_count = comm->poll_txfrac; + crit_exit(); + + lwkt_replymsg(&nmsg->nm_lmsg, 0); +} diff --git a/sys/net/route.c b/sys/net/route.c index e1bd3e0207..b014dfbeff 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -775,15 +775,24 @@ static void rtrequest1_msghandler(struct netmsg *netmsg) { struct netmsg_rtq *msg = (void *)netmsg; + struct rt_addrinfo rtinfo; struct rtentry *rt = NULL; int nextcpu; int error; - error = rtrequest1(msg->req, msg->rtinfo, &rt); + /* + * Copy the rtinfo. We need to make sure that the original + * rtinfo, which is setup by the caller, in the netmsg will + * _not_ be changed; else the next CPU on the netmsg forwarding + * path will see a different rtinfo than what this CPU has seen. + */ + rtinfo = *msg->rtinfo; + + error = rtrequest1(msg->req, &rtinfo, &rt); if (rt) --rt->rt_refcnt; if (msg->callback) - msg->callback(msg->req, error, msg->rtinfo, rt, msg->arg); + msg->callback(msg->req, error, &rtinfo, rt, msg->arg); /* * RTM_DELETE's are propogated even if an error occurs, since a @@ -798,7 +807,7 @@ rtrequest1_msghandler(struct netmsg *netmsg) if (error && msg->req != RTM_DELETE) { if (mycpuid != 0) { panic("rtrequest1_msghandler: rtrequest table " - "error was not on cpu #0: %p", msg->rtinfo); + "error was not on cpu #0"); } lwkt_replymsg(&msg->netmsg.nm_lmsg, error); } else if (nextcpu < ncpus) { @@ -1666,15 +1675,23 @@ static void rtsearch_msghandler(struct netmsg *netmsg) { struct netmsg_rts *msg = (void *)netmsg; - struct rt_addrinfo *rtinfo = msg->rtinfo; + struct rt_addrinfo rtinfo; struct radix_node_head *rnh; struct rtentry *rt; int nextcpu, error; + /* + * Copy the rtinfo. We need to make sure that the original + * rtinfo, which is setup by the caller, in the netmsg will + * _not_ be changed; else the next CPU on the netmsg forwarding + * path will see a different rtinfo than what this CPU has seen. + */ + rtinfo = *msg->rtinfo; + /* * Find the correct routing tree to use for this Address Family */ - if ((rnh = rt_tables[mycpuid][rtinfo->rti_dst->sa_family]) == NULL) { + if ((rnh = rt_tables[mycpuid][rtinfo.rti_dst->sa_family]) == NULL) { if (mycpuid != 0) panic("partially initialized routing tables\n"); lwkt_replymsg(&msg->netmsg.nm_lmsg, EAFNOSUPPORT); @@ -1684,14 +1701,14 @@ rtsearch_msghandler(struct netmsg *netmsg) /* * Correct rtinfo for the host route searching. */ - if (rtinfo->rti_flags & RTF_HOST) { - rtinfo->rti_netmask = NULL; - rtinfo->rti_flags &= ~(RTF_CLONING | RTF_PRCLONING); + if (rtinfo.rti_flags & RTF_HOST) { + rtinfo.rti_netmask = NULL; + rtinfo.rti_flags &= ~(RTF_CLONING | RTF_PRCLONING); } rt = (struct rtentry *) - rnh->rnh_lookup((char *)rtinfo->rti_dst, - (char *)rtinfo->rti_netmask, rnh); + rnh->rnh_lookup((char *)rtinfo.rti_dst, + (char *)rtinfo.rti_netmask, rnh); /* * If we are asked to do the "exact match", we need to make sure @@ -1699,7 +1716,7 @@ rtsearch_msghandler(struct netmsg *netmsg) * route searching got a network route. */ if (rt != NULL && msg->exact_match && - ((rt->rt_flags ^ rtinfo->rti_flags) & RTF_HOST)) + ((rt->rt_flags ^ rtinfo.rti_flags) & RTF_HOST)) rt = NULL; if (rt == NULL) { @@ -1714,7 +1731,7 @@ rtsearch_msghandler(struct netmsg *netmsg) msg->found_cnt++; rt->rt_refcnt++; - error = msg->callback(msg->req, msg->rtinfo, rt, msg->arg, + error = msg->callback(msg->req, &rtinfo, rt, msg->arg, msg->found_cnt); rt->rt_refcnt--; @@ -1737,7 +1754,7 @@ rtsearch_msghandler(struct netmsg *netmsg) */ if (msg->req != RTM_GET && msg->found_cnt > 1) { panic("rtsearch_msghandler: unrecoverable error " - "cpu %d, rtinfo %p", mycpuid, msg->rtinfo); + "cpu %d", mycpuid); } lwkt_replymsg(&msg->netmsg.nm_lmsg, error); } else if (nextcpu < ncpus) { diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index ae2750d0c3..e437e092eb 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -391,7 +391,7 @@ rts_input(struct mbuf *m, sa_family_t family) } static void * -reallocbuf(void *ptr, size_t len, size_t olen) +reallocbuf_nofree(void *ptr, size_t len, size_t olen) { void *newptr; @@ -399,7 +399,6 @@ reallocbuf(void *ptr, size_t len, size_t olen) if (newptr == NULL) return NULL; bcopy(ptr, newptr, olen); - kfree(ptr, M_RTABLE); return (newptr); } @@ -407,8 +406,8 @@ reallocbuf(void *ptr, size_t len, size_t olen) * Internal helper routine for route_output(). */ static int -fillrtmsg(struct rt_msghdr **prtm, struct rtentry *rt, - struct rt_addrinfo *rtinfo) +_fillrtmsg(struct rt_msghdr **prtm, struct rtentry *rt, + struct rt_addrinfo *rtinfo) { int msglen; struct rt_msghdr *rtm = *prtm; @@ -437,7 +436,8 @@ fillrtmsg(struct rt_msghdr **prtm, struct rtentry *rt, msglen = rt_msgsize(rtm->rtm_type, rtinfo); if (rtm->rtm_msglen < msglen) { - rtm = reallocbuf(rtm, msglen, rtm->rtm_msglen); + /* NOTE: Caller will free the old rtm accordingly */ + rtm = reallocbuf_nofree(rtm, msglen, rtm->rtm_msglen); if (rtm == NULL) return (ENOBUFS); *prtm = rtm; @@ -451,6 +451,34 @@ fillrtmsg(struct rt_msghdr **prtm, struct rtentry *rt, return (0); } +struct rtm_arg { + struct rt_msghdr *bak_rtm; + struct rt_msghdr *new_rtm; +}; + +static int +fillrtmsg(struct rtm_arg *arg, struct rtentry *rt, + struct rt_addrinfo *rtinfo) +{ + struct rt_msghdr *rtm = arg->new_rtm; + int error; + + error = _fillrtmsg(&rtm, rt, rtinfo); + if (!error) { + if (arg->new_rtm != rtm) { + /* + * _fillrtmsg() just allocated a new rtm; + * if the previously allocated rtm is not + * the backing rtm, it should be freed. + */ + if (arg->new_rtm != arg->bak_rtm) + kfree(arg->new_rtm, M_RTABLE); + arg->new_rtm = rtm; + } + } + return error; +} + static void route_output_add_callback(int, int, struct rt_addrinfo *, struct rtentry *, void *); static void route_output_delete_callback(int, int, struct rt_addrinfo *, @@ -466,10 +494,12 @@ static int route_output_lock_callback(int, struct rt_addrinfo *, static int route_output(struct mbuf *m, struct socket *so, ...) { + struct rtm_arg arg; struct rt_msghdr *rtm = NULL; struct rawcb *rp = NULL; struct pr_output_info *oi; struct rt_addrinfo rtinfo; + sa_family_t family; int len, error = 0; __va_list ap; @@ -479,6 +509,8 @@ route_output(struct mbuf *m, struct socket *so, ...) oi = __va_arg(ap, struct pr_output_info *); __va_end(ap); + family = familyof(NULL); + #define gotoerr(e) { error = e; goto flush;} if (m == NULL || @@ -487,32 +519,30 @@ route_output(struct mbuf *m, struct socket *so, ...) return (ENOBUFS); len = m->m_pkthdr.len; if (len < sizeof(struct rt_msghdr) || - len != mtod(m, struct rt_msghdr *)->rtm_msglen) { - rtinfo.rti_dst = NULL; + len != mtod(m, struct rt_msghdr *)->rtm_msglen) gotoerr(EINVAL); - } + rtm = kmalloc(len, M_RTABLE, M_INTWAIT | M_NULLOK); - if (rtm == NULL) { - rtinfo.rti_dst = NULL; + if (rtm == NULL) gotoerr(ENOBUFS); - } + m_copydata(m, 0, len, (caddr_t)rtm); - if (rtm->rtm_version != RTM_VERSION) { - rtinfo.rti_dst = NULL; + if (rtm->rtm_version != RTM_VERSION) gotoerr(EPROTONOSUPPORT); - } + rtm->rtm_pid = oi->p_pid; bzero(&rtinfo, sizeof(struct rt_addrinfo)); rtinfo.rti_addrs = rtm->rtm_addrs; - if (rt_xaddrs((char *)(rtm + 1), (char *)rtm + len, &rtinfo) != 0) { - rtinfo.rti_dst = NULL; + if (rt_xaddrs((char *)(rtm + 1), (char *)rtm + len, &rtinfo) != 0) gotoerr(EINVAL); - } + rtinfo.rti_flags = rtm->rtm_flags; if (rtinfo.rti_dst == NULL || rtinfo.rti_dst->sa_family >= AF_MAX || (rtinfo.rti_gateway && rtinfo.rti_gateway->sa_family >= AF_MAX)) gotoerr(EINVAL); + family = familyof(rtinfo.rti_dst); + if (rtinfo.rti_genmask != NULL) { error = rtmask_add_global(rtinfo.rti_genmask); if (error) @@ -538,18 +568,35 @@ route_output(struct mbuf *m, struct socket *so, ...) break; case RTM_DELETE: /* - * note: &rtm passed as argument so 'rtm' can be replaced. + * Backing rtm (bak_rtm) could _not_ be freed during + * rtrequest1_global or rtsearch_global, even if the + * callback reallocates the rtm due to its size changes, + * since rtinfo points to the backing rtm's memory area. + * After rtrequest1_global or rtsearch_global returns, + * it is safe to free the backing rtm, since rtinfo will + * not be used anymore. + * + * new_rtm will be used to save the new rtm allocated + * by rtrequest1_global or rtsearch_global. */ + arg.bak_rtm = rtm; + arg.new_rtm = rtm; error = rtrequest1_global(RTM_DELETE, &rtinfo, - route_output_delete_callback, &rtm); + route_output_delete_callback, &arg); + rtm = arg.new_rtm; + if (rtm != arg.bak_rtm) + kfree(arg.bak_rtm, M_RTABLE); break; case RTM_GET: - /* - * note: &rtm passed as argument so 'rtm' can be replaced. - */ + /* See the comment in RTM_DELETE */ + arg.bak_rtm = rtm; + arg.new_rtm = rtm; error = rtsearch_global(RTM_GET, &rtinfo, - route_output_get_callback, &rtm, + route_output_get_callback, &arg, RTS_NOEXACTMATCH); + rtm = arg.new_rtm; + if (rtm != arg.bak_rtm) + kfree(arg.bak_rtm, M_RTABLE); break; case RTM_CHANGE: error = rtsearch_global(RTM_CHANGE, &rtinfo, @@ -565,7 +612,6 @@ route_output(struct mbuf *m, struct socket *so, ...) error = EOPNOTSUPP; break; } - flush: if (rtm != NULL) { if (error != 0) @@ -597,7 +643,7 @@ flush: kfree(rtm, M_RTABLE); } if (m != NULL) - rts_input_skip(m, familyof(rtinfo.rti_dst), rp); + rts_input_skip(m, family, rp); return (error); } @@ -634,29 +680,30 @@ static void route_output_delete_callback(int cmd, int error, struct rt_addrinfo *rtinfo, struct rtentry *rt, void *arg) { - struct rt_msghdr **rtm = arg; - if (error == 0 && rt) { ++rt->rt_refcnt; - if (fillrtmsg(rtm, rt, rtinfo) != 0) { + if (fillrtmsg(arg, rt, rtinfo) != 0) { error = ENOBUFS; /* XXX no way to return the error */ } --rt->rt_refcnt; } + if (rt && rt->rt_refcnt == 0) { + ++rt->rt_refcnt; + rtfree(rt); + } } static int route_output_get_callback(int cmd, struct rt_addrinfo *rtinfo, struct rtentry *rt, void *arg, int found_cnt) { - struct rt_msghdr **rtm = arg; int error, found = 0; if (((rtinfo->rti_flags ^ rt->rt_flags) & RTF_HOST) == 0) found = 1; - error = fillrtmsg(rtm, rt, rtinfo); + error = fillrtmsg(arg, rt, rtinfo); if (!error && found) { /* Got the exact match, we could return now! */ error = EJUSTRETURN; diff --git a/sys/net/tap/if_tap.c b/sys/net/tap/if_tap.c index f4bd6cae31..4cb6fb2ec1 100644 --- a/sys/net/tap/if_tap.c +++ b/sys/net/tap/if_tap.c @@ -65,6 +65,7 @@ #include #include #include +#include #include #include @@ -72,6 +73,7 @@ #include "if_tapvar.h" #include "if_tap.h" +#define TAP_IFFLAGS (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST) #define CDEV_NAME "tap" #define CDEV_MAJOR 149 @@ -86,6 +88,12 @@ static int tapmodevent (module_t, int, void *); /* device */ static void tapcreate (cdev_t); +static void tapdestroy(struct tap_softc *); + +/* clone */ +static int tap_clone_create(struct if_clone *, int); +static void tap_clone_destroy(struct ifnet *); + /* network interface */ static void tapifstart (struct ifnet *); @@ -93,6 +101,7 @@ static int tapifioctl (struct ifnet *, u_long, caddr_t, struct ucred *); static void tapifinit (void *); static void tapifstop(struct tap_softc *, int); +static void tapifflags(struct tap_softc *); /* character device */ static d_open_t tapopen; @@ -117,10 +126,27 @@ static struct dev_ops tap_ops = { static int taprefcnt = 0; /* module ref. counter */ static int taplastunit = -1; /* max. open unit number */ static int tapdebug = 0; /* debug flag */ +static int tapuopen = 0; /* all user open() */ +static int tapuponopen = 0; /* IFF_UP */ MALLOC_DECLARE(M_TAP); MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface"); +struct if_clone tap_cloner = IF_CLONE_INITIALIZER("tap", + tap_clone_create, tap_clone_destroy, + 0, IF_MAXUNIT); +static SLIST_HEAD(,tap_softc) tap_listhead = + SLIST_HEAD_INITIALIZER(&tap_listhead); + SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, ""); +SYSCTL_DECL(_net_link); +SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0, + "Ethernet tunnel software network interface"); +SYSCTL_INT(_net_link_tap, OID_AUTO, user_open, CTLFLAG_RW, &tapuopen, 0, + "Allow user to open /dev/tap (based on node permissions)"); +SYSCTL_INT(_net_link_tap, OID_AUTO, up_on_open, CTLFLAG_RW, &tapuponopen, 0, + "Bring interface up when /dev/tap is opened"); +SYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, ""); + DEV_MODULE(if_tap, tapmodevent, NULL); /* @@ -131,9 +157,8 @@ DEV_MODULE(if_tap, tapmodevent, NULL); static int tapmodevent(module_t mod, int type, void *data) { - static int attached = 0; - struct ifnet *ifp = NULL; - int unit; + static int attached = 0; + struct tap_softc *tp, *ntp; switch (type) { case MOD_LOAD: @@ -141,6 +166,9 @@ tapmodevent(module_t mod, int type, void *data) return (EEXIST); dev_ops_add(&tap_ops, 0, 0); + SLIST_INIT(&tap_listhead); + if_clone_attach(&tap_cloner); + attached = 1; break; @@ -148,37 +176,13 @@ tapmodevent(module_t mod, int type, void *data) if (taprefcnt > 0) return (EBUSY); + if_clone_detach(&tap_cloner); dev_ops_remove(&tap_ops, 0, 0); - /* XXX: maintain tap ifs in a local list */ - unit = 0; - while (unit <= taplastunit) { - TAILQ_FOREACH(ifp, &ifnet, if_link) { - if ((strcmp(ifp->if_dname, TAP) == 0) || - (strcmp(ifp->if_dname, VMNET) == 0)) { - if (ifp->if_dunit == unit) - break; - } - } - - if (ifp != NULL) { - struct tap_softc *tp = ifp->if_softc; - - TAPDEBUG(ifp, "detached. minor = %#x, " \ - "taplastunit = %d\n", - minor(tp->tap_dev), taplastunit); - - ifnet_serialize_all(ifp); - tapifstop(tp, 1); - ifnet_deserialize_all(ifp); + /* Maintain tap ifs in a local list */ + SLIST_FOREACH_MUTABLE(tp, &tap_listhead, tap_link, ntp) + tapdestroy(tp); - ether_ifdetach(ifp); - destroy_dev(tp->tap_dev); - kfree(tp, M_TAP); - } else { - unit++; - } - } attached = 0; break; @@ -241,7 +245,7 @@ tapcreate(cdev_t dev) ifp->if_start = tapifstart; ifp->if_ioctl = tapifioctl; ifp->if_mtu = ETHERMTU; - ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST); + ifp->if_flags = TAP_IFFLAGS; ifq_set_maxlen(&ifp->if_snd, ifqmaxlen); ifq_set_ready(&ifp->if_snd); @@ -250,9 +254,32 @@ tapcreate(cdev_t dev) tp->tap_flags |= TAP_INITED; tp->tap_devq.ifq_maxlen = ifqmaxlen; + SLIST_INSERT_HEAD(&tap_listhead, tp, tap_link); + TAPDEBUG(ifp, "created. minor = %#x\n", minor(tp->tap_dev)); } /* tapcreate */ +/* + * tap_clone_create: + * + * Create a new tap instance. + */ +static int +tap_clone_create(struct if_clone *ifc __unused, int unit) +{ + struct tap_softc *tp = NULL; + cdev_t dev; + + dev = get_dev(CDEV_MAJOR, unit); + tapcreate(dev); + + tp = dev->si_drv1; + tp->tap_flags |= TAP_CLONE; + TAPDEBUG(&tp->tap_if, "clone created. minor = %#x tap_flags = 0x%x\n", + minor(tp->tap_dev), tp->tap_flags); + + return (0); +} /* * tapopen @@ -262,15 +289,17 @@ tapcreate(cdev_t dev) static int tapopen(struct dev_open_args *ap) { - cdev_t dev = ap->a_head.a_dev; + cdev_t dev = NULL; struct tap_softc *tp = NULL; struct ifnet *ifp = NULL; int error; - if ((error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) != 0) + if (tapuopen == 0 && + (error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) != 0) return (error); get_mplock(); + dev = ap->a_head.a_dev; tp = dev->si_drv1; if (tp == NULL) { tapcreate(dev); @@ -281,13 +310,14 @@ tapopen(struct dev_open_args *ap) rel_mplock(); return (EBUSY); } - ifp = &tp->arpcom.ac_if; - EVENTHANDLER_INVOKE(ifnet_attach_event, ifp); + if ((tp->tap_flags & TAP_CLONE) == 0) { + EVENTHANDLER_INVOKE(ifnet_attach_event, ifp); - /* Announce the return of the interface. */ - rt_ifannouncemsg(ifp, IFAN_ARRIVAL); + /* Announce the return of the interface. */ + rt_ifannouncemsg(ifp, IFAN_ARRIVAL); + } } bcopy(tp->arpcom.ac_enaddr, tp->ether_addr, sizeof(tp->ether_addr)); @@ -297,6 +327,18 @@ tapopen(struct dev_open_args *ap) tp->tap_flags |= TAP_OPEN; taprefcnt ++; + if (tapuponopen && (ifp->if_flags & IFF_UP) == 0) { + crit_enter(); + if_up(ifp); + crit_exit(); + + ifnet_serialize_all(ifp); + tapifflags(tp); + ifnet_deserialize_all(ifp); + + tp->tap_flags |= TAP_CLOSEDOWN; + } + TAPDEBUG(ifp, "opened. minor = %#x, refcnt = %d, taplastunit = %d\n", minor(tp->tap_dev), taprefcnt, taplastunit); @@ -314,35 +356,43 @@ static int tapclose(struct dev_close_args *ap) { cdev_t dev = ap->a_head.a_dev; - struct tap_softc *tp = dev->si_drv1; - struct ifnet *ifp = &tp->tap_if; - int clear_flags = 1; - - /* junk all pending output */ + struct tap_softc *tp = dev->si_drv1; + struct ifnet *ifp = &tp->tap_if; + int clear_flags = 0; get_mplock(); + + /* Junk all pending output */ ifq_purge(&ifp->if_snd); /* - * do not bring the interface down, and do not anything with + * Do not bring the interface down, and do not anything with * interface, if we are in VMnet mode. just close the device. + * + * If the interface is not cloned, we always bring it down. + * + * If the interface is cloned, then we bring it down during + * closing only if it was brought up during opening. */ - - if ((tp->tap_flags & TAP_VMNET) == 0) { + if ((tp->tap_flags & TAP_VMNET) == 0 && + ((tp->tap_flags & TAP_CLONE) == 0 || + (tp->tap_flags & TAP_CLOSEDOWN))) { if (ifp->if_flags & IFF_UP) if_down(ifp); - clear_flags = 0; + clear_flags = 1; } ifnet_serialize_all(ifp); tapifstop(tp, clear_flags); ifnet_deserialize_all(ifp); - if_purgeaddrs_nolink(ifp); + if ((tp->tap_flags & TAP_CLONE) == 0) { + if_purgeaddrs_nolink(ifp); - EVENTHANDLER_INVOKE(ifnet_detach_event, ifp); + EVENTHANDLER_INVOKE(ifnet_detach_event, ifp); - /* Announce the departure of the interface. */ - rt_ifannouncemsg(ifp, IFAN_DEPARTURE); + /* Announce the departure of the interface. */ + rt_ifannouncemsg(ifp, IFAN_DEPARTURE); + } funsetown(tp->tap_sigio); tp->tap_sigio = NULL; @@ -362,10 +412,56 @@ tapclose(struct dev_close_args *ap) TAPDEBUG(ifp, "closed. minor = %#x, refcnt = %d, taplastunit = %d\n", minor(tp->tap_dev), taprefcnt, taplastunit); +#ifdef foo + if ((tp->tap_flags & TAP_CLONE) == 0) + tapdestroy(tp); +#endif + rel_mplock(); return (0); } +/* + * tapdestroy: + * + * Destroy a tap instance. + */ +static void +tapdestroy(struct tap_softc *tp) +{ + struct ifnet *ifp = &tp->arpcom.ac_if; + + TAPDEBUG(ifp, "destroyed. minor = %#x, refcnt = %d, taplastunit = %d\n", + minor(tp->tap_dev), taprefcnt, taplastunit); + + ifnet_serialize_all(ifp); + tapifstop(tp, 1); + ifnet_deserialize_all(ifp); + + ether_ifdetach(ifp); + SLIST_REMOVE(&tap_listhead, tp, tap_softc, tap_link); + + destroy_dev(tp->tap_dev); + kfree(tp, M_TAP); + + taplastunit--; +} + +/* + * tap_clone_destroy: + * + * Destroy a tap instance. + */ +static void +tap_clone_destroy(struct ifnet *ifp) +{ + struct tap_softc *tp = ifp->if_softc; + + TAPDEBUG(&tp->tap_if, "clone destroyed. minor = %#x tap_flags = 0x%x\n", + minor(tp->tap_dev), tp->tap_flags); + if (tp->tap_flags & TAP_CLONE) + tapdestroy(tp); +} /* * tapifinit @@ -380,7 +476,8 @@ tapifinit(void *xtp) struct tap_softc *tp = xtp; struct ifnet *ifp = &tp->tap_if; - TAPDEBUG(ifp, "initializing, minor = %#x\n", minor(tp->tap_dev)); + TAPDEBUG(ifp, "initializing, minor = %#x tap_flags = 0x%x\n", + minor(tp->tap_dev), tp->tap_flags); ASSERT_IFNET_SERIALIZED_ALL(ifp); @@ -417,20 +514,9 @@ tapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) return (dummy); case SIOCSIFFLAGS: - if ((tp->tap_flags & TAP_VMNET) == 0) { - /* - * Only for non-vmnet tap(4) - */ - if (ifp->if_flags & IFF_UP) { - if ((ifp->if_flags & IFF_RUNNING) == 0) - tapifinit(tp); - } else { - tapifstop(tp, 1); - } - } else { - /* XXX */ - } + tapifflags(tp); break; + case SIOCADDMULTI: /* XXX -- just like vmnet does */ case SIOCDELMULTI: break; @@ -747,6 +833,12 @@ tapwrite(struct dev_write_args *ap) TAPDEBUG(ifp, "writing, minor = %#x\n", minor(tp->tap_dev)); + if ((tp->tap_flags & TAP_READY) != TAP_READY) { + TAPDEBUG(ifp, "not ready. minor = %#x, tap_flags = 0x%x\n", + minor(tp->tap_dev), tp->tap_flags); + return (EHOSTDOWN); + } + if (uio->uio_resid == 0) return (0); @@ -844,7 +936,7 @@ tappoll(struct dev_poll_args *ap) if (ap->a_events & (POLLOUT | POLLWRNORM)) revents |= (ap->a_events & (POLLOUT | POLLWRNORM)); ap->a_events = revents; - return(0); + return (0); } /* @@ -917,6 +1009,28 @@ tapifstop(struct tap_softc *tp, int clear_flags) ASSERT_IFNET_SERIALIZED_ALL(ifp); IF_DRAIN(&tp->tap_devq); + tp->tap_flags &= ~TAP_CLOSEDOWN; if (clear_flags) ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); } + +static void +tapifflags(struct tap_softc *tp) +{ + struct ifnet *ifp = &tp->arpcom.ac_if; + + ASSERT_IFNET_SERIALIZED_ALL(ifp); + if ((tp->tap_flags & TAP_VMNET) == 0) { + /* + * Only for non-vmnet tap(4) + */ + if (ifp->if_flags & IFF_UP) { + if ((ifp->if_flags & IFF_RUNNING) == 0) + tapifinit(tp); + } else { + tapifstop(tp, 1); + } + } else { + /* XXX */ + } +} diff --git a/sys/net/tap/if_tapvar.h b/sys/net/tap/if_tapvar.h index 2cd173e44e..75f3f9b874 100644 --- a/sys/net/tap/if_tapvar.h +++ b/sys/net/tap/if_tapvar.h @@ -54,6 +54,8 @@ struct tap_softc { #define TAP_ASYNC (1 << 3) #define TAP_READY (TAP_OPEN|TAP_INITED) #define TAP_VMNET (1 << 4) +#define TAP_CLONE (1 << 5) +#define TAP_CLOSEDOWN (1 << 6) u_int8_t ether_addr[ETHER_ADDR_LEN]; /* ether addr of the remote side */ @@ -61,6 +63,8 @@ struct tap_softc { struct sigio *tap_sigio; /* information for async I/O */ struct selinfo tap_rsel; /* read select */ struct ifqueue tap_devq; + + SLIST_ENTRY(tap_softc) tap_link; /* Local tap list */ }; #endif /* !_NET_IF_TAPVAR_H_ */ diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index c571c74e68..521c463491 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -126,6 +126,14 @@ static int icmpbmcastecho = 0; SYSCTL_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_RW, &icmpbmcastecho, 0, ""); +static char icmp_reply_src[IFNAMSIZ]; +SYSCTL_STRING(_net_inet_icmp, OID_AUTO, reply_src, CTLFLAG_RW, + icmp_reply_src, IFNAMSIZ, "icmp reply source for non-local packets."); + +static int icmp_rfi; +SYSCTL_INT(_net_inet_icmp, OID_AUTO, reply_from_interface, CTLFLAG_RW, + &icmp_rfi, 0, "ICMP reply from incoming interface for " + "non-local packets"); #ifdef ICMPPRINTFS int icmpprintfs = 0; @@ -612,6 +620,8 @@ icmp_reflect(struct mbuf *m) struct ip *ip = mtod(m, struct ip *); struct in_ifaddr *ia; struct in_ifaddr_container *iac; + struct ifaddr_container *ifac; + struct ifnet *ifp; struct in_addr t; struct mbuf *opts = 0; int optlen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof(struct ip); @@ -626,8 +636,10 @@ icmp_reflect(struct mbuf *m) } t = ip->ip_dst; ip->ip_dst = ip->ip_src; + ro = &rt; bzero(ro, sizeof *ro); + /* * If the incoming packet was addressed directly to us, * use dst as the src for the reply. Otherwise (broadcast @@ -641,12 +653,9 @@ icmp_reflect(struct mbuf *m) goto match; } } - if (m->m_pkthdr.rcvif != NULL && - m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) { - struct ifaddr_container *ifac; - - TAILQ_FOREACH(ifac, &m->m_pkthdr.rcvif->if_addrheads[mycpuid], - ifa_link) { + ifp = m->m_pkthdr.rcvif; + if (ifp != NULL && (ifp->if_flags & IFF_BROADCAST)) { + TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) { struct ifaddr *ifa = ifac->ifa; if (ifa->ifa_addr->sa_family != AF_INET) @@ -657,8 +666,45 @@ icmp_reflect(struct mbuf *m) goto match; } } + /* + * If the packet was transiting through us, use the address of + * the interface the packet came through in. If that interface + * doesn't have a suitable IP address, the normal selection + * criteria apply. + */ + if (icmp_rfi && ifp != NULL) { + TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) { + struct ifaddr *ifa = ifac->ifa; + + if (ifa->ifa_addr->sa_family != AF_INET) + continue; + ia = ifatoia(ifa); + goto match; + } + } + /* + * If the incoming packet was not addressed directly to us, use + * designated interface for icmp replies specified by sysctl + * net.inet.icmp.reply_src (default not set). Otherwise continue + * with normal source selection. + */ + if (icmp_reply_src[0] != '\0' && (ifp = ifunit(icmp_reply_src))) { + TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) { + struct ifaddr *ifa = ifac->ifa; + + if (ifa->ifa_addr->sa_family != AF_INET) + continue; + ia = ifatoia(ifa); + goto match; + } + } + /* + * If the packet was transiting through us, use the address of + * the interface that is the closest to the packet source. + * When we don't have a route back to the packet source, stop here + * and drop the packet. + */ ia = ip_rtaddr(ip->ip_dst, ro); - /* We need a route to do anything useful. */ if (ia == NULL) { m_freem(m); icmpstat.icps_noroute++; diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index c0f736dab7..817c25802f 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -713,18 +713,13 @@ tcp_newtcpcb(struct inpcb *inp) tp->tt_delack = &it->inp_tp_delack; tcp_inittimers(tp); + /* + * Zero out timer message. We don't create it here, + * since the current CPU may not be the owner of this + * inpcb. + */ tp->tt_msg = &it->inp_tp_timermsg; - if (isipv6) { - /* Don't mess with IPv6; always create timer message */ - tcp_create_timermsg(tp); - } else { - /* - * Zero out timer message. We don't create it here, - * since the current CPU may not be the owner of this - * inpcb. - */ - bzero(tp->tt_msg, sizeof(*tp->tt_msg)); - } + bzero(tp->tt_msg, sizeof(*tp->tt_msg)); if (tcp_do_rfc1323) tp->t_flags = (TF_REQ_SCALE | TF_REQ_TSTMP); @@ -864,9 +859,10 @@ tcp_close(struct tcpcb *tp) /* * Make sure that all of our timers are stopped before we * delete the PCB. For listen TCP socket (tp->tt_msg == NULL), - * timers are never used. + * timers are never used. If timer message is never created + * (tp->tt_msg->tt_tcb == NULL), timers are never used too. */ - if (tp->tt_msg != NULL) { + if (tp->tt_msg != NULL && tp->tt_msg->tt_tcb != NULL) { tcp_callout_stop(tp, tp->tt_rexmt); tcp_callout_stop(tp, tp->tt_persist); tcp_callout_stop(tp, tp->tt_keep); diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 727e35456a..8cd7ebd1eb 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -792,7 +792,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) */ if (sc->sc_rxtslot != 0) tp->snd_cwnd = tp->t_maxseg; - tcp_create_timermsg(tp); + tcp_create_timermsg(tp, &curthread->td_msgport); tcp_callout_reset(tp, tp->tt_keep, tcp_keepinit, tcp_timer_keep); tcpstat.tcps_accepts++; diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 1aeb860373..1a74e2883e 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -230,7 +230,7 @@ tcp_send_timermsg(struct tcpcb *tp, uint32_t task) tmsg->tt_tasks |= task; if (tmsg->tt_nmsg.nm_lmsg.ms_flags & MSGF_DONE) - lwkt_sendmsg(tcp_cport(mycpuid), &tmsg->tt_nmsg.nm_lmsg); + lwkt_sendmsg(tmsg->tt_msgport, &tmsg->tt_nmsg.nm_lmsg); } int tcp_syn_backoff[TCP_MAXRXTSHIFT + 1] = @@ -696,13 +696,14 @@ tcp_timer_handler(struct netmsg *nmsg) } void -tcp_create_timermsg(struct tcpcb *tp) +tcp_create_timermsg(struct tcpcb *tp, struct lwkt_port *msgport) { struct netmsg_tcp_timer *tmsg = tp->tt_msg; netmsg_init(&tmsg->tt_nmsg, &netisr_adone_rport, MSGF_DROPABLE | MSGF_PRIORITY, tcp_timer_handler); tmsg->tt_cpuid = mycpuid; + tmsg->tt_msgport = msgport; tmsg->tt_tcb = tp; tmsg->tt_tasks = 0; } diff --git a/sys/netinet/tcp_timer.h b/sys/netinet/tcp_timer.h index f3cfc96458..30ad18fbef 100644 --- a/sys/netinet/tcp_timer.h +++ b/sys/netinet/tcp_timer.h @@ -135,6 +135,7 @@ struct netmsg_tcp_timer { struct netmsg tt_nmsg; struct tcpcb *tt_tcb; int tt_cpuid; /* owner cpuid */ + lwkt_port_t tt_msgport; /* owner msgport */ uint32_t tt_tasks; /* pending tasks */ uint32_t tt_running_tasks; /* running tasks */ uint32_t tt_prev_tasks; /* prev pending tasks (debug) */ @@ -164,7 +165,8 @@ void tcp_timer_rexmt(void *xtp); void tcp_timer_delack(void *xtp); void tcp_inittimers(struct tcpcb *); -void tcp_create_timermsg(struct tcpcb *); +struct lwkt_port; +void tcp_create_timermsg(struct tcpcb *, struct lwkt_port *); void tcp_destroy_timermsg(struct tcpcb *); #endif /* _KERNEL */ diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index a6159dfdb3..d0b27a28a1 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -955,7 +955,11 @@ tcp_connect_oncpu(struct tcpcb *tp, struct sockaddr_in *sin, rtalloc(ro); } - tcp_create_timermsg(tp); + /* + * Create TCP timer message now; we are on the tcpcb's owner + * CPU/thread. + */ + tcp_create_timermsg(tp, &curthread->td_msgport); /* Compute window scaling to request. */ while (tp->request_r_scale < TCP_MAX_WINSHIFT && @@ -1128,6 +1132,9 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td) inp->in6p_flowinfo = sin6->sin6_flowinfo; in_pcbinsconnhash(inp); + /* NOTE: must be done in tcpcb's owner thread */ + tcp_create_timermsg(tp, &curthread->td_msgport); + /* Compute window scaling to request. */ while (tp->request_r_scale < TCP_MAX_WINSHIFT && (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.ssb_hiwat) diff --git a/sys/netproto/ipx/spx_debug.h b/sys/netproto/ipx/spx_debug.h index 0b68cac3be..c57b2a497c 100644 --- a/sys/netproto/ipx/spx_debug.h +++ b/sys/netproto/ipx/spx_debug.h @@ -57,7 +57,7 @@ struct spx_debug { #define SA_DROP 4 #ifdef SANAMES -char *spxnames[] = +const char *spxnames[] = { "input", "output", "user", "respond", "drop" }; #endif diff --git a/sys/platform/pc32/acpica5/acpi_pstate_machdep.c b/sys/platform/pc32/acpica5/acpi_pstate_machdep.c new file mode 100644 index 0000000000..017349f7f9 --- /dev/null +++ b/sys/platform/pc32/acpica5/acpi_pstate_machdep.c @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2009 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Sepherosa Ziehau + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include +#include + +#include "acpi.h" +#include "acpi_cpu_pstate.h" + +#define AMD_APMI_HWPSTATE 0x80 + +#define AMD_MSR_PSTATE_CSR_MASK 0x7ULL +#define AMD1XH_MSR_PSTATE_CTL 0xc0010062 +#define AMD1XH_MSR_PSTATE_ST 0xc0010063 + +#define AMD_MSR_PSTATE_EN 0x8000000000000000ULL + +#define AMD10H_MSR_PSTATE_START 0xc0010064 +#define AMD10H_MSR_PSTATE_COUNT 5 + +#define AMD0F_PST_CTL_FID(cval) (((cval) >> 0) & 0x3f) +#define AMD0F_PST_CTL_VID(cval) (((cval) >> 6) & 0x1f) +#define AMD0F_PST_CTL_VST(cval) (((cval) >> 11) & 0x7f) +#define AMD0F_PST_CTL_MVS(cval) (((cval) >> 18) & 0x3) +#define AMD0F_PST_CTL_PLLTIME(cval) (((cval) >> 20) & 0x7f) +#define AMD0F_PST_CTL_RVO(cval) (((cval) >> 28) & 0x3) +#define AMD0F_PST_CTL_IRT(cval) (((cval) >> 30) & 0x3) + +#define AMD0F_PST_ST_FID(sval) (((sval) >> 0) & 0x3f) +#define AMD0F_PST_ST_VID(sval) (((sval) >> 6) & 0x3f) + +static const struct acpi_pst_md * + acpi_pst_amd_probe(void); +static int acpi_pst_amd_check_csr(const ACPI_RESOURCE_GENERIC_REGISTER *, + const ACPI_RESOURCE_GENERIC_REGISTER *); +static int acpi_pst_amd1x_check_pstates(const struct acpi_pstate *, int, + uint32_t, uint32_t); +static int acpi_pst_amd10_check_pstates(const struct acpi_pstate *, int); +static int acpi_pst_amd0f_check_pstates(const struct acpi_pstate *, int); +static int acpi_pst_amd1x_set_pstate( + const ACPI_RESOURCE_GENERIC_REGISTER *, + const ACPI_RESOURCE_GENERIC_REGISTER *, + const struct acpi_pstate *); +static int acpi_pst_amd0f_set_pstate( + const ACPI_RESOURCE_GENERIC_REGISTER *, + const ACPI_RESOURCE_GENERIC_REGISTER *, + const struct acpi_pstate *); +static const struct acpi_pstate * + acpi_pst_amd1x_get_pstate( + const ACPI_RESOURCE_GENERIC_REGISTER *, + const struct acpi_pstate *, int); +static const struct acpi_pstate * + acpi_pst_amd0f_get_pstate( + const ACPI_RESOURCE_GENERIC_REGISTER *, + const struct acpi_pstate *, int); + +static const struct acpi_pst_md acpi_pst_amd10h = { + .pmd_check_csr = acpi_pst_amd_check_csr, + .pmd_check_pstates = acpi_pst_amd10_check_pstates, + .pmd_set_pstate = acpi_pst_amd1x_set_pstate, + .pmd_get_pstate = acpi_pst_amd1x_get_pstate +}; + +static const struct acpi_pst_md acpi_pst_amd0fh = { + .pmd_check_csr = acpi_pst_amd_check_csr, + .pmd_check_pstates = acpi_pst_amd0f_check_pstates, + .pmd_set_pstate = acpi_pst_amd0f_set_pstate, + .pmd_get_pstate = acpi_pst_amd0f_get_pstate +}; + +const struct acpi_pst_md * +acpi_pst_md_probe(void) +{ + if (strcmp(cpu_vendor, "AuthenticAMD") == 0) + return acpi_pst_amd_probe(); + return NULL; +} + +static const struct acpi_pst_md * +acpi_pst_amd_probe(void) +{ + uint32_t regs[4], ext_family; + + if ((cpu_id & 0x00000f00) != 0x00000f00) + return NULL; + + /* Check whether APMI exists */ + do_cpuid(0x80000000, regs); + if (regs[0] < 0x80000007) + return NULL; + + /* Fetch APMI */ + do_cpuid(0x80000007, regs); + + ext_family = cpu_id & 0x0ff00000; + switch (ext_family) { + case 0x00000000: /* Family 0fh */ + if ((regs[3] & 0x06) == 0x06) + return &acpi_pst_amd0fh; + break; + + case 0x00100000: /* Family 10h */ + if (regs[3] & 0x80) + return &acpi_pst_amd10h; + break; + + default: + break; + } + return NULL; +} + +static int +acpi_pst_amd_check_csr(const ACPI_RESOURCE_GENERIC_REGISTER *ctrl, + const ACPI_RESOURCE_GENERIC_REGISTER *status) +{ + if (ctrl->SpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE) { + kprintf("cpu%d: Invalid P-State control register\n", mycpuid); + return EINVAL; + } + if (status->SpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE) { + kprintf("cpu%d: Invalid P-State status register\n", mycpuid); + return EINVAL; + } + return 0; +} + +static int +acpi_pst_amd1x_check_pstates(const struct acpi_pstate *pstates, int npstates, + uint32_t msr_start, uint32_t msr_end) +{ + int i; + + /* + * Make sure that related MSR P-State registers are enabled. + * + * NOTE: + * We don't check status register value here; + * it will not be used. + */ + for (i = 0; i < npstates; ++i) { + uint64_t pstate; + uint32_t msr; + + msr = msr_start + + (pstates[i].st_cval & AMD_MSR_PSTATE_CSR_MASK); + if (msr >= msr_end) { + kprintf("cpu%d: MSR P-State register %#08x " + "does not exist\n", mycpuid, msr); + return EINVAL; + } + + pstate = rdmsr(msr); + if ((pstate & AMD_MSR_PSTATE_EN) == 0) { + kprintf("cpu%d: MSR P-State register %#08x " + "is not enabled\n", mycpuid, msr); + return EINVAL; + } + } + return 0; +} + +static int +acpi_pst_amd10_check_pstates(const struct acpi_pstate *pstates, int npstates) +{ + /* Only P0-P4 are supported */ + if (npstates > AMD10H_MSR_PSTATE_COUNT) { + kprintf("cpu%d: only P0-P4 is allowed\n", mycpuid); + return EINVAL; + } + + return acpi_pst_amd1x_check_pstates(pstates, npstates, + AMD10H_MSR_PSTATE_START, + AMD10H_MSR_PSTATE_START + AMD10H_MSR_PSTATE_COUNT); +} + +static int +acpi_pst_amd1x_set_pstate(const ACPI_RESOURCE_GENERIC_REGISTER *ctrl __unused, + const ACPI_RESOURCE_GENERIC_REGISTER *status __unused, + const struct acpi_pstate *pstate) +{ + uint64_t cval; + + cval = pstate->st_cval & AMD_MSR_PSTATE_CSR_MASK; + wrmsr(AMD1XH_MSR_PSTATE_CTL, cval); + + /* + * Don't check AMD1XH_MSR_PSTATE_ST here, since it is + * affected by various P-State limits. + * + * For details: + * AMD Family 10h Processor BKDG Rev 3.20 (#31116) + * 2.4.2.4 P-state Transition Behavior + */ + + return 0; +} + +static const struct acpi_pstate * +acpi_pst_amd1x_get_pstate(const ACPI_RESOURCE_GENERIC_REGISTER *status __unused, + const struct acpi_pstate *pstates, int npstates) +{ + uint64_t sval; + int i; + + sval = rdmsr(AMD1XH_MSR_PSTATE_ST) & AMD_MSR_PSTATE_CSR_MASK; + for (i = 0; i < npstates; ++i) { + if ((pstates[i].st_sval & AMD_MSR_PSTATE_CSR_MASK) == sval) + return &pstates[i]; + } + return NULL; +} + +static int +acpi_pst_amd0f_check_pstates(const struct acpi_pstate *pstates, int npstates) +{ + struct amd0f_fidvid fv_max, fv_min; + int i; + + amd0f_fidvid_limit(&fv_min, &fv_max); + + for (i = 0; i < npstates; ++i) { + const struct acpi_pstate *p = &pstates[i]; + uint32_t fid, vid, mvs, rvo; + int mvs_mv, rvo_mv; + + fid = AMD0F_PST_CTL_FID(p->st_cval); + vid = AMD0F_PST_CTL_VID(p->st_cval); + + if (fid > fv_max.fid || fid < fv_min.fid) { + kprintf("cpu%d: Invalid FID %#x [%#x, %#x]\n", + mycpuid, fid, fv_min.fid, fv_max.fid); + return EINVAL; + } + if (vid < fv_max.vid || vid > fv_min.vid) { + kprintf("cpu%d: Invalid VID %#x [%#x, %#x]\n", + mycpuid, vid, fv_max.vid, fv_min.fid); + return EINVAL; + } + + mvs = AMD0F_PST_CTL_MVS(p->st_cval); + rvo = AMD0F_PST_CTL_RVO(p->st_cval); + + /* Only 0 is allowed, i.e. 25mV stepping */ + if (mvs != 0) { + kprintf("cpu%d: Invalid MVS %#x\n", mycpuid, mvs); + return EINVAL; + } + + /* -> mV */ + mvs_mv = 25 * (1 << mvs); + rvo_mv = 25 * rvo; + if (rvo_mv % mvs_mv != 0) { + kprintf("cpu%d: Invalid MVS/RVO (%#x/%#x)\n", + mycpuid, mvs, rvo); + return EINVAL; + } + } + return 0; +} + +static int +acpi_pst_amd0f_set_pstate(const ACPI_RESOURCE_GENERIC_REGISTER *ctrl __unused, + const ACPI_RESOURCE_GENERIC_REGISTER *status __unused, + const struct acpi_pstate *pstate) +{ + struct amd0f_fidvid fv; + struct amd0f_xsit xsit; + + fv.fid = AMD0F_PST_CTL_FID(pstate->st_cval); + fv.vid = AMD0F_PST_CTL_VID(pstate->st_cval); + + xsit.rvo = AMD0F_PST_CTL_RVO(pstate->st_cval); + xsit.mvs = AMD0F_PST_CTL_MVS(pstate->st_cval); + xsit.vst = AMD0F_PST_CTL_VST(pstate->st_cval); + xsit.pll_time = AMD0F_PST_CTL_PLLTIME(pstate->st_cval); + xsit.irt = AMD0F_PST_CTL_IRT(pstate->st_cval); + + return amd0f_set_fidvid(&fv, &xsit); +} + +static const struct acpi_pstate * +acpi_pst_amd0f_get_pstate(const ACPI_RESOURCE_GENERIC_REGISTER * ctrl __unused, + const struct acpi_pstate *pstates, int npstates) +{ + struct amd0f_fidvid fv; + int error, i; + + error = amd0f_get_fidvid(&fv); + if (error) + return NULL; + + for (i = 0; i < npstates; ++i) { + const struct acpi_pstate *p = &pstates[i]; + + if (fv.fid == AMD0F_PST_ST_FID(p->st_sval) && + fv.vid == AMD0F_PST_ST_VID(p->st_sval)) + return p; + } + return NULL; +} diff --git a/sys/platform/pc32/apic/apic_vector.s b/sys/platform/pc32/apic/apic_vector.s index 26b1d773f1..981ab0ed57 100644 --- a/sys/platform/pc32/apic/apic_vector.s +++ b/sys/platform/pc32/apic/apic_vector.s @@ -383,6 +383,7 @@ Xipiq: movl $0, lapic_eoi /* End Of Interrupt to APIC */ FAKE_MCOUNT(15*4(%esp)) + incl PCPU(cnt) + V_IPI movl PCPU(curthread),%ebx cmpl $TDPRI_CRIT,TD_PRI(%ebx) jge 1f @@ -411,7 +412,7 @@ Xtimer: movl $0, lapic_eoi /* End Of Interrupt to APIC */ FAKE_MCOUNT(15*4(%esp)) - incl PCPU(cnt) + V_INTR + incl PCPU(cnt) + V_TIMER movl PCPU(curthread),%ebx cmpl $TDPRI_CRIT,TD_PRI(%ebx) jge 1f diff --git a/sys/platform/pc32/apic/apicreg.h b/sys/platform/pc32/apic/apicreg.h index b2c56f2693..df5e57cab0 100644 --- a/sys/platform/pc32/apic/apicreg.h +++ b/sys/platform/pc32/apic/apicreg.h @@ -808,6 +808,7 @@ typedef struct IOAPIC ioapic_t; #define IOART_HI_DEST_MASK APIC_ID_MASK #define IOART_HI_DEST_RESV ~APIC_ID_MASK #define IOART_HI_DEST_BROADCAST IOART_HI_DEST_MASK +#define IOART_HI_DEST_SHIFT 24 /* * Low 32 bit word diff --git a/sys/platform/pc32/apic/mpapic.c b/sys/platform/pc32/apic/mpapic.c index c5273a1861..bb85a9d29b 100644 --- a/sys/platform/pc32/apic/mpapic.c +++ b/sys/platform/pc32/apic/mpapic.c @@ -44,30 +44,41 @@ static void lapic_timer_calibrate(void); static void lapic_timer_set_divisor(int); -static void lapic_timer_intr_reload(sysclock_t); static void lapic_timer_fixup_handler(void *); static void lapic_timer_restart_handler(void *); -void lapic_timer_fixup(void); void lapic_timer_process(void); void lapic_timer_process_frame(struct intrframe *); -void lapic_timer_intr_test(void); -void lapic_timer_oneshot_intr_enable(void); -void lapic_timer_restart(void); -int lapic_timer_test; -int lapic_timer_enable; - -TUNABLE_INT("hw.lapic_timer_test", &lapic_timer_test); +static int lapic_timer_enable = 1; TUNABLE_INT("hw.lapic_timer_enable", &lapic_timer_enable); +static void lapic_timer_intr_reload(struct cputimer_intr *, sysclock_t); +static void lapic_timer_intr_enable(struct cputimer_intr *); +static void lapic_timer_intr_restart(struct cputimer_intr *); +static void lapic_timer_intr_pmfixup(struct cputimer_intr *); + +static struct cputimer_intr lapic_cputimer_intr = { + .freq = 0, + .reload = lapic_timer_intr_reload, + .enable = lapic_timer_intr_enable, + .config = cputimer_intr_default_config, + .restart = lapic_timer_intr_restart, + .pmfixup = lapic_timer_intr_pmfixup, + .initclock = cputimer_intr_default_initclock, + .next = SLIST_ENTRY_INITIALIZER, + .name = "lapic", + .type = CPUTIMER_INTR_LAPIC, + .prio = CPUTIMER_INTR_PRIO_LAPIC, + .caps = CPUTIMER_INTR_CAP_NONE +}; + /* * pointers to pmapped apic hardware. */ volatile ioapic_t **ioapic; -static sysclock_t lapic_timer_freq; static int lapic_timer_divisor_idx = -1; static const uint32_t lapic_timer_divisors[] = { APIC_TDCR_2, APIC_TDCR_4, APIC_TDCR_8, APIC_TDCR_16, @@ -175,8 +186,10 @@ apic_initialize(boolean_t bsp) if (bsp) { lapic_timer_calibrate(); - if (lapic_timer_enable) - cputimer_intr_reload = lapic_timer_intr_reload; + if (lapic_timer_enable) { + cputimer_intr_register(&lapic_cputimer_intr); + cputimer_intr_select(&lapic_cputimer_intr, 0); + } } else { lapic_timer_set_divisor(lapic_timer_divisor_idx); } @@ -228,10 +241,10 @@ lapic_timer_calibrate(void) } if (lapic_timer_divisor_idx >= APIC_TIMER_NDIVISORS) panic("lapic: no proper timer divisor?!\n"); - lapic_timer_freq = value / 2; + lapic_cputimer_intr.freq = value / 2; kprintf("lapic: divisor index %d, frequency %u Hz\n", - lapic_timer_divisor_idx, lapic_timer_freq); + lapic_timer_divisor_idx, lapic_cputimer_intr.freq); } static void @@ -249,47 +262,21 @@ lapic_timer_process_oncpu(struct globaldata *gd, struct intrframe *frame) void lapic_timer_process(void) { - struct globaldata *gd = mycpu; - - if (__predict_false(lapic_timer_test)) { - gd->gd_timer_running = 0; - kprintf("%d proc\n", gd->gd_cpuid); - } else { - lapic_timer_process_oncpu(gd, NULL); - } + lapic_timer_process_oncpu(mycpu, NULL); } void lapic_timer_process_frame(struct intrframe *frame) { - struct globaldata *gd = mycpu; - - if (__predict_false(lapic_timer_test)) { - gd->gd_timer_running = 0; - kprintf("%d proc frame\n", gd->gd_cpuid); - } else { - lapic_timer_process_oncpu(gd, frame); - } -} - -void -lapic_timer_intr_test(void) -{ - struct globaldata *gd = mycpu; - - if (!gd->gd_timer_running) { - gd->gd_timer_running = 1; - KKASSERT(lapic_timer_freq != 0); - lapic_timer_oneshot_quick(lapic_timer_freq); - } + lapic_timer_process_oncpu(mycpu, frame); } static void -lapic_timer_intr_reload(sysclock_t reload) +lapic_timer_intr_reload(struct cputimer_intr *cti, sysclock_t reload) { struct globaldata *gd = mycpu; - reload = (int64_t)reload * lapic_timer_freq / sys_cputimer->freq; + reload = (int64_t)reload * cti->freq / sys_cputimer->freq; if (reload < 2) reload = 2; @@ -302,8 +289,8 @@ lapic_timer_intr_reload(sysclock_t reload) } } -void -lapic_timer_oneshot_intr_enable(void) +static void +lapic_timer_intr_enable(struct cputimer_intr *cti __unused) { uint32_t timer; @@ -381,20 +368,16 @@ lapic_timer_restart_handler(void *dummy __unused) * module controls PM. So once ACPI-CA is attached, we try * to apply the fixup to prevent LAPIC timer from hanging. */ -void -lapic_timer_fixup(void) +static void +lapic_timer_intr_pmfixup(struct cputimer_intr *cti __unused) { - if (lapic_timer_test || lapic_timer_enable) { - lwkt_send_ipiq_mask(smp_active_mask, - lapic_timer_fixup_handler, NULL); - } + lwkt_send_ipiq_mask(smp_active_mask, + lapic_timer_fixup_handler, NULL); } -void -lapic_timer_restart(void) +static void +lapic_timer_intr_restart(struct cputimer_intr *cti __unused) { - KKASSERT(lapic_timer_enable); - cputimer_intr_reload = lapic_timer_intr_reload; lwkt_send_ipiq_mask(smp_active_mask, lapic_timer_restart_handler, NULL); } @@ -482,6 +465,8 @@ io_apic_setup_intpin(int apic, int pin) u_int32_t target; /* the window register is 32 bits */ u_int32_t vector; /* the window register is 32 bits */ int level; + int cpuid; + char envpath[32]; select = pin * 2 + IOAPIC_REDTBL0; /* register */ @@ -559,10 +544,18 @@ io_apic_setup_intpin(int apic, int pin) apic_pin_trigger |= (1 << irq); polarity(apic, pin, &flags, level); } - + + cpuid = 0; + ksnprintf(envpath, sizeof(envpath), "hw.irq.%d.dest", irq); + kgetenv_int(envpath, &cpuid); + + /* ncpus may not be available yet */ + if (cpuid > mp_naps) + cpuid = 0; + if (bootverbose) { - kprintf("IOAPIC #%d intpin %d -> irq %d\n", - apic, pin, irq); + kprintf("IOAPIC #%d intpin %d -> irq %d (CPU%d)\n", + apic, pin, irq, cpuid); } /* @@ -578,7 +571,9 @@ io_apic_setup_intpin(int apic, int pin) vector = IDT_OFFSET + irq; /* IDT vec */ target = io_apic_read(apic, select + 1) & IOART_HI_DEST_RESV; - target |= IOART_HI_DEST_BROADCAST; + /* Deliver all interrupts to CPU0 (BSP) */ + target |= (CPU_TO_ID(cpuid) << IOART_HI_DEST_SHIFT) & + IOART_HI_DEST_MASK; flags |= io_apic_read(apic, select) & IOART_RESV; io_apic_write(apic, select, flags | vector); io_apic_write(apic, select + 1, target); @@ -625,6 +620,7 @@ io_apic_setup(int apic) IOART_DELLOPRI)) /* + * XXX this function is only used by 8254 setup * Setup the source of External INTerrupts. */ int @@ -634,11 +630,23 @@ ext_int_setup(int apic, int intr) u_int32_t flags; /* the window register is 32 bits */ u_int32_t target; /* the window register is 32 bits */ u_int32_t vector; /* the window register is 32 bits */ + int cpuid; + char envpath[32]; if (apic_int_type(apic, intr) != 3) return -1; - target = IOART_HI_DEST_BROADCAST; + cpuid = 0; + ksnprintf(envpath, sizeof(envpath), "hw.irq.%d.dest", intr); + kgetenv_int(envpath, &cpuid); + + /* ncpus may not be available yet */ + if (cpuid > mp_naps) + cpuid = 0; + + /* Deliver interrupts to CPU0 (BSP) */ + target = (CPU_TO_ID(cpuid) << IOART_HI_DEST_SHIFT) & + IOART_HI_DEST_MASK; select = IOAPIC_REDTBL0 + (2 * intr); vector = IDT_OFFSET + intr; flags = DEFAULT_EXTINT_FLAGS; @@ -945,10 +953,10 @@ set_apic_timer(int us) * divisor (lapic.dcr_timer is setup during the * divisor calculation). */ - KKASSERT(lapic_timer_freq != 0 && + KKASSERT(lapic_cputimer_intr.freq != 0 && lapic_timer_divisor_idx >= 0); - count = ((us * (int64_t)lapic_timer_freq) + 999999) / 1000000; + count = ((us * (int64_t)lapic_cputimer_intr.freq) + 999999) / 1000000; lapic_timer_oneshot(count); } diff --git a/sys/platform/pc32/conf/files b/sys/platform/pc32/conf/files index 4feef69586..823ac29202 100644 --- a/sys/platform/pc32/conf/files +++ b/sys/platform/pc32/conf/files @@ -38,16 +38,6 @@ ukbdmap.h optional ukbd_dflt_keymap \ emulation/dragonfly12/dfbsd12_getdirentries.c nonoptional compat_df12 emulation/dragonfly12/dfbsd12_stat.c nonoptional compat_df12 # -hal.o optional ath_hal \ - dependency "$S/contrib/dev/ath/public/i386-elf.hal.o.uu" \ - compile-with "uudecode < $S/contrib/dev/ath/public/i386-elf.hal.o.uu" \ - no-implicit-rule -opt_ah.h optional ath_hal \ - dependency "$S/contrib/dev/ath/public/i386-elf.opt_ah.h" \ - compile-with "rm -f opt_ah.h; cp $S/contrib/dev/ath/public/i386-elf.opt_ah.h opt_ah.h" \ - no-obj no-implicit-rule before-depend \ - clean "opt_ah.h" -# emulation/linux/linux_file.c optional compat_linux emulation/linux/linux_getcwd.c optional compat_linux emulation/linux/linux_ioctl.c optional compat_linux @@ -202,6 +192,7 @@ platform/pc32/i386/trap.c standard platform/pc32/i386/userconfig.c optional userconfig platform/pc32/i386/vm86.c standard platform/pc32/i386/vm_machdep.c standard +platform/pc32/i386/cpufreq_machdep.c standard platform/pc32/isa/asc.c optional asc platform/pc32/isa/clock.c standard dev/video/ctx/ctx.c optional ctx diff --git a/sys/platform/pc32/i386/busdma_machdep.c b/sys/platform/pc32/i386/busdma_machdep.c index 93b345cf5c..e129f8ff7d 100644 --- a/sys/platform/pc32/i386/busdma_machdep.c +++ b/sys/platform/pc32/i386/busdma_machdep.c @@ -51,6 +51,11 @@ #define MAX_BPAGES 1024 +/* + * 16 x N declared on stack. + */ +#define BUS_DMA_CACHE_SEGMENTS 8 + struct bounce_zone; struct bus_dmamap; @@ -70,6 +75,11 @@ struct bus_dma_tag { int map_count; bus_dma_segment_t *segments; struct bounce_zone *bounce_zone; +#ifdef SMP + struct spinlock spin; +#else + int unused0; +#endif }; /* @@ -194,6 +204,28 @@ run_filter(bus_dma_tag_t dmat, bus_addr_t paddr) return (retval); } +static __inline +bus_dma_segment_t * +bus_dma_tag_lock(bus_dma_tag_t tag, bus_dma_segment_t *cache) +{ + if (tag->nsegments <= BUS_DMA_CACHE_SEGMENTS) + return(cache); +#ifdef SMP + spin_lock_wr(&tag->spin); +#endif + return(tag->segments); +} + +static __inline +void +bus_dma_tag_unlock(bus_dma_tag_t tag) +{ +#ifdef SMP + if (tag->nsegments > BUS_DMA_CACHE_SEGMENTS) + spin_unlock_wr(&tag->spin); +#endif +} + /* * Allocate a device specific dma_tag. */ @@ -229,8 +261,11 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, /* Return a NULL tag on failure */ *dmat = NULL; - newtag = kmalloc(sizeof(*newtag), M_DEVBUF, M_INTWAIT); + newtag = kmalloc(sizeof(*newtag), M_DEVBUF, M_INTWAIT | M_ZERO); +#ifdef SMP + spin_init(&newtag->spin); +#endif newtag->parent = parent; newtag->alignment = alignment; newtag->boundary = boundary; @@ -349,6 +384,12 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat) return (0); } +bus_size_t +bus_dma_tag_getmaxsize(bus_dma_tag_t tag) +{ + return(tag->maxsize); +} + /* * Allocate a handle for mapping from kva/uva/physical * address space into bus device space. @@ -754,6 +795,8 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg, int flags) { + bus_dma_segment_t cache_segments[BUS_DMA_CACHE_SEGMENTS]; + bus_dma_segment_t *segments; vm_paddr_t lastaddr = 0; int error, nsegs = 1; @@ -770,13 +813,16 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, map->callback_arg = callback_arg; } + segments = bus_dma_tag_lock(dmat, cache_segments); error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, - dmat->segments, dmat->nsegments, + segments, dmat->nsegments, NULL, flags, &lastaddr, &nsegs, 1); - if (error == EINPROGRESS) + if (error == EINPROGRESS) { + bus_dma_tag_unlock(dmat); return error; - - callback(callback_arg, dmat->segments, nsegs, error); + } + callback(callback_arg, segments, nsegs, error); + bus_dma_tag_unlock(dmat); return 0; } @@ -789,6 +835,8 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmamap_callback2_t *callback, void *callback_arg, int flags) { + bus_dma_segment_t cache_segments[BUS_DMA_CACHE_SEGMENTS]; + bus_dma_segment_t *segments; int nsegs, error; /* @@ -799,15 +847,18 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, flags &= ~BUS_DMA_WAITOK; flags |= BUS_DMA_NOWAIT; + segments = bus_dma_tag_lock(dmat, cache_segments); error = bus_dmamap_load_mbuf_segment(dmat, map, m0, - dmat->segments, dmat->nsegments, &nsegs, flags); + segments, dmat->nsegments, &nsegs, flags); if (error) { /* force "no valid mappings" in callback */ - callback(callback_arg, dmat->segments, 0, 0, error); + callback(callback_arg, segments, 0, + 0, error); } else { - callback(callback_arg, dmat->segments, nsegs, + callback(callback_arg, segments, nsegs, m0->m_pkthdr.len, error); } + bus_dma_tag_unlock(dmat); return error; } @@ -880,6 +931,16 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, bus_size_t resid; struct iovec *iov; pmap_t pmap; + bus_dma_segment_t cache_segments[BUS_DMA_CACHE_SEGMENTS]; + bus_dma_segment_t *segments; + bus_dma_segment_t *segs; + int nsegs_left; + + if (dmat->nsegments <= BUS_DMA_CACHE_SEGMENTS) + segments = cache_segments; + else + segments = kmalloc(sizeof(bus_dma_segment_t) * dmat->nsegments, + M_DEVBUF, M_WAITOK | M_ZERO); /* * XXX @@ -892,6 +953,9 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, resid = uio->uio_resid; iov = uio->uio_iov; + segs = segments; + nsegs_left = dmat->nsegments; + if (uio->uio_segflg == UIO_USERSPACE) { struct thread *td; @@ -917,20 +981,33 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, caddr_t addr = (caddr_t) iov[i].iov_base; error = _bus_dmamap_load_buffer(dmat, map, addr, minlen, - dmat->segments, dmat->nsegments, + segs, nsegs_left, pmap, flags, &lastaddr, &nsegs, first); first = 0; resid -= minlen; + if (error == 0) { + nsegs_left -= nsegs; + segs += nsegs; + } } + /* + * Minimum one DMA segment, even if 0-length buffer. + */ + if (nsegs_left == dmat->nsegments) + --nsegs_left; + if (error) { /* force "no valid mappings" in callback */ - callback(callback_arg, dmat->segments, 0, 0, error); + callback(callback_arg, segments, 0, + 0, error); } else { - callback(callback_arg, dmat->segments, nsegs, + callback(callback_arg, segments, dmat->nsegments - nsegs_left, uio->uio_resid, error); } + if (dmat->nsegments > BUS_DMA_CACHE_SEGMENTS) + kfree(segments, M_DEVBUF); return error; } diff --git a/sys/platform/pc32/i386/cpufreq_machdep.c b/sys/platform/pc32/i386/cpufreq_machdep.c new file mode 100644 index 0000000000..21a48eca35 --- /dev/null +++ b/sys/platform/pc32/i386/cpufreq_machdep.c @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2004 Martin V\xe9giard. + * Copyright (c) 2004-2005 Bruno Ducrot + * Copyright (c) 2004 FUKUDA Nobuhiko + * Copyright (c) 2004, 2006 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Juan Romero Pardines and Martin Vegiard. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include + +#define AMD0F_MSR_FIDVID_CTL 0xc0010041 +#define AMD0F_MSR_FIDVID_STATUS 0xc0010042 + +/* AMD0F_MSR_FIDVID_STATUS */ +#define AMD0F_STA_CFID(x) ((x) & 0x3f) +#define AMD0F_STA_SFID(x) (((x) >> 8) & 0x3f) +#define AMD0F_STA_MFID(x) (((x) >> 16) & 0x3f) +#define AMD0F_STA_PENDING(x) (((x) >> 31) & 0x01) +#define AMD0F_STA_CVID(x) (((x) >> 32) & 0x1f) +#define AMD0F_STA_SVID(x) (((x) >> 40) & 0x1f) +#define AMD0F_STA_MVID(x) (((x) >> 48) & 0x1f) + +#define AMD0F_WRITE_FIDVID(fid, vid, ctrl) \ + wrmsr(AMD0F_MSR_FIDVID_CTL, \ + (((ctrl) << 32) | (1ULL << 16) | ((vid) << 8) | (fid))) + +#define AMD0F_WAIT_FIDVID_CHG(status) \ +do { \ + (status) = rdmsr(AMD0F_MSR_FIDVID_STATUS); \ +} while (AMD0F_STA_PENDING(status)) + +#define AMD0F_FID2VCO(fid) \ + (((fid) < 8) ? (8 + ((fid) << 1)) : (fid)) + +#define AMD0F_DELAY_VST(vst) DELAY(20 * (vst)) +#define AMD0F_DELAY_IRT(irt) DELAY(10 * (1 << (irt))) + +/* XXX */ +#define abs(x) ((x) < 0 ? -(x) : (x)) + +int +amd0f_set_fidvid(const struct amd0f_fidvid *fv, const struct amd0f_xsit *xsit) +{ + uint32_t val, cfid, cvid, tvid; + uint64_t status; + + /* + * We don't wait change pending bit here, need to ensure + * that it isn't stuck. + */ + status = rdmsr(AMD0F_MSR_FIDVID_STATUS); + if (AMD0F_STA_PENDING(status)) + return EBUSY; + + cfid = AMD0F_STA_CFID(status); + cvid = AMD0F_STA_CVID(status); + if (fv->fid == cfid && fv->vid == cvid) + return 0; + + /* + * Phase 1: Raise core voltage to the TargetVID + */ + if ((fv->fid & ~0x1) > (cfid & ~0x1) || cvid > fv->vid) { + KKASSERT(fv->vid >= xsit->rvo); + tvid = fv->vid - xsit->rvo; + } else { + KKASSERT(cvid >= xsit->rvo); + tvid = cvid - xsit->rvo; + } + while (cvid > tvid) { + if (cvid > (1 << xsit->mvs)) + val = cvid - (1 << xsit->mvs); + else + val = 0; + AMD0F_WRITE_FIDVID(cfid, val, 0ULL); + AMD0F_WAIT_FIDVID_CHG(status); + cvid = AMD0F_STA_CVID(status); + AMD0F_DELAY_VST(xsit->vst); + } + + /* + * Phase 2: Change to requested core frequency + */ + if (cfid != fv->fid) { + /* NOTE: Keep type as int, else following 'abs' will break */ + int vco_fid, vco_cfid; + + vco_fid = AMD0F_FID2VCO(fv->fid); + vco_cfid = AMD0F_FID2VCO(cfid); + while (abs(vco_fid - vco_cfid) > 2) { + if (fv->fid > cfid) { + if (cfid > 6) + val = cfid + 2; + else + val = AMD0F_FID2VCO(cfid) + 2; + } else { + KKASSERT(cfid >= 2); + val = cfid - 2; + } + AMD0F_WRITE_FIDVID(val, cvid, + (uint64_t)xsit->pll_time * 1000 / 5); + AMD0F_WAIT_FIDVID_CHG(status); + cfid = AMD0F_STA_CFID(status); + AMD0F_DELAY_IRT(xsit->irt); + vco_cfid = AMD0F_FID2VCO(cfid); + } + if (cfid != fv->fid) { + AMD0F_WRITE_FIDVID(fv->fid, cvid, + (uint64_t)xsit->pll_time * 1000 / 5); + AMD0F_WAIT_FIDVID_CHG(status); + cfid = AMD0F_STA_CFID(status); + AMD0F_DELAY_IRT(xsit->irt); + } + } + + /* + * Phase 3: Change to requested voltage + */ + if (cvid != fv->vid) { + AMD0F_WRITE_FIDVID(cfid, fv->vid, 0ULL); + AMD0F_WAIT_FIDVID_CHG(status); + cvid = AMD0F_STA_CVID(status); + AMD0F_DELAY_VST(xsit->vst); + } + return 0; +} + +int +amd0f_get_fidvid(struct amd0f_fidvid *fv) +{ + uint64_t status; + + status = rdmsr(AMD0F_MSR_FIDVID_STATUS); + if (AMD0F_STA_PENDING(status)) + return EBUSY; + + fv->fid = AMD0F_STA_CFID(status); + fv->vid = AMD0F_STA_CVID(status); + return 0; +} + +void +amd0f_fidvid_limit(struct amd0f_fidvid *fv_min, struct amd0f_fidvid *fv_max) +{ + uint32_t max_fid, max_vid, start_fid, start_vid; + uint64_t status; + + status = rdmsr(AMD0F_MSR_FIDVID_STATUS); + + start_fid = AMD0F_STA_SFID(status); + max_fid = AMD0F_STA_MFID(status); + start_vid = AMD0F_STA_SVID(status); + max_vid = AMD0F_STA_MVID(status); + + if (max_fid == 0x2a && max_vid != 0) { + fv_max->fid = start_fid + 0xa; + fv_max->vid = max_vid + 0x2; + fv_min->fid = 0x2; + fv_min->vid = start_vid; + } else { + fv_max->fid = max_fid; + fv_max->vid = max_vid + 0x2; + fv_min->fid = start_fid; + fv_min->vid = start_vid; + } +} diff --git a/sys/platform/pc32/i386/genassym.c b/sys/platform/pc32/i386/genassym.c index f6ec7df5ca..5e73826a4a 100644 --- a/sys/platform/pc32/i386/genassym.c +++ b/sys/platform/pc32/i386/genassym.c @@ -109,6 +109,8 @@ ASSYM(V_SYSCALL, offsetof(struct vmmeter, v_syscall)); ASSYM(V_SENDSYS, offsetof(struct vmmeter, v_sendsys)); ASSYM(V_WAITSYS, offsetof(struct vmmeter, v_waitsys)); ASSYM(V_INTR, offsetof(struct vmmeter, v_intr)); +ASSYM(V_IPI, offsetof(struct vmmeter, v_ipi)); +ASSYM(V_TIMER, offsetof(struct vmmeter, v_timer)); ASSYM(V_FORWARDED_INTS, offsetof(struct vmmeter, v_forwarded_ints)); ASSYM(V_FORWARDED_HITS, offsetof(struct vmmeter, v_forwarded_hits)); ASSYM(V_FORWARDED_MISSES, offsetof(struct vmmeter, v_forwarded_misses)); diff --git a/sys/platform/pc32/include/cpufreq.h b/sys/platform/pc32/include/cpufreq.h new file mode 100644 index 0000000000..1bb09448bb --- /dev/null +++ b/sys/platform/pc32/include/cpufreq.h @@ -0,0 +1,22 @@ +#ifndef _MACHINE_CPUFREQ_H_ +#define _MACHINE_CPUFREQ_H_ + +struct amd0f_fidvid { + uint32_t fid; + uint32_t vid; +}; + +struct amd0f_xsit { + uint32_t rvo; + uint32_t mvs; + uint32_t vst; + uint32_t pll_time; + uint32_t irt; +}; + +void amd0f_fidvid_limit(struct amd0f_fidvid *, struct amd0f_fidvid *); +int amd0f_set_fidvid(const struct amd0f_fidvid *, + const struct amd0f_xsit *); +int amd0f_get_fidvid(struct amd0f_fidvid *); + +#endif /* !_MACHINE_CPUFREQ_H_ */ diff --git a/sys/platform/pc32/isa/clock.c b/sys/platform/pc32/isa/clock.c index 243961bf7d..c608039c43 100644 --- a/sys/platform/pc32/isa/clock.c +++ b/sys/platform/pc32/isa/clock.c @@ -124,9 +124,6 @@ enum tstate timer0_state; enum tstate timer1_state; enum tstate timer2_state; -static void i8254_intr_reload(sysclock_t); -void (*cputimer_intr_reload)(sysclock_t) = i8254_intr_reload; - static int beeping = 0; static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; @@ -135,6 +132,7 @@ static int rtc_loaded; static int i8254_cputimer_div; +static int i8254_nointr; static int i8254_intr_disable = 0; TUNABLE_INT("hw.i8254.intr_disable", &i8254_intr_disable); @@ -158,6 +156,25 @@ static struct cputimer i8254_cputimer = { 0, 0, 0 }; +static void i8254_intr_reload(struct cputimer_intr *, sysclock_t); +static void i8254_intr_config(struct cputimer_intr *, const struct cputimer *); +static void i8254_intr_initclock(struct cputimer_intr *, boolean_t); + +static struct cputimer_intr i8254_cputimer_intr = { + .freq = TIMER_FREQ, + .reload = i8254_intr_reload, + .enable = cputimer_intr_default_enable, + .config = i8254_intr_config, + .restart = cputimer_intr_default_restart, + .pmfixup = cputimer_intr_default_pmfixup, + .initclock = i8254_intr_initclock, + .next = SLIST_ENTRY_INITIALIZER, + .name = "i8254", + .type = CPUTIMER_INTR_8254, + .prio = CPUTIMER_INTR_PRIO_8254, + .caps = CPUTIMER_INTR_CAP_PS +}; + /* * timer0 clock interrupt. Timer0 is in one-shot mode and has stopped * counting as of this interrupt. We use timer1 in free-running mode (not @@ -308,8 +325,8 @@ i8254_cputimer_count(void) * simple shift, multiplication, or division, we do so. Otherwise 64 * bit arithmatic is required every time the interrupt timer is reloaded. */ -void -cputimer_intr_config(struct cputimer *timer) +static void +i8254_intr_config(struct cputimer_intr *cti, const struct cputimer *timer) { int freq; int div; @@ -317,8 +334,8 @@ cputimer_intr_config(struct cputimer *timer) /* * Will a simple divide do the trick? */ - div = (timer->freq + (i8254_cputimer.freq / 2)) / i8254_cputimer.freq; - freq = i8254_cputimer.freq * div; + div = (timer->freq + (cti->freq / 2)) / cti->freq; + freq = cti->freq * div; if (freq >= timer->freq - 1 && freq <= timer->freq + 1) i8254_cputimer_div = div; @@ -334,14 +351,14 @@ cputimer_intr_config(struct cputimer *timer) * We may have to convert from the system timebase to the 8254 timebase. */ static void -i8254_intr_reload(sysclock_t reload) +i8254_intr_reload(struct cputimer_intr *cti, sysclock_t reload) { __uint16_t count; if (i8254_cputimer_div) reload /= i8254_cputimer_div; else - reload = (int64_t)reload * i8254_cputimer.freq / sys_cputimer->freq; + reload = (int64_t)reload * cti->freq / sys_cputimer->freq; if ((int)reload < 2) reload = 2; @@ -367,84 +384,6 @@ i8254_intr_reload(sysclock_t reload) clock_unlock(); } -#ifdef SMP - -extern int lapic_timer_test; -extern int lapic_timer_enable; -extern void lapic_timer_oneshot_intr_enable(void); -extern void lapic_timer_intr_test(void); -extern void lapic_timer_restart(void); - -/* Piggyback lapic_timer test */ -static void -i8254_intr_reload_test(sysclock_t reload) -{ - i8254_intr_reload(reload); - if (__predict_false(lapic_timer_test)) - lapic_timer_intr_test(); -} - -#endif /* SMP */ - -void -cputimer_intr_enable(void) -{ -#ifdef SMP - if (lapic_timer_test || lapic_timer_enable) { - lapic_timer_oneshot_intr_enable(); - if (lapic_timer_test) /* XXX */ - cputimer_intr_reload = i8254_intr_reload_test; - } -#endif -} - -void -cputimer_intr_switch(enum cputimer_intr_type type) -{ -#ifdef SMP - if (!i8254_intr_disable && - (lapic_timer_enable || lapic_timer_test)) { - switch (type) { - case CPUTIMER_INTRT_C3: - cputimer_intr_reload = i8254_intr_reload; - /* Force a quick reload */ - i8254_intr_reload(0); - break; - - case CPUTIMER_INTRT_FAST: - if (lapic_timer_test) /* XXX */ - cputimer_intr_reload = i8254_intr_reload_test; - else if (lapic_timer_enable) - lapic_timer_restart(); - break; - } - } -#endif -} - -static int -sysctl_cputimer_intr_switch(SYSCTL_HANDLER_ARGS) -{ - enum cputimer_intr_type type = CPUTIMER_INTRT_FAST; - int error; - - error = sysctl_handle_int(oidp, &type, 0, req); - if (error || req->newptr == NULL) - return error; - switch (type) { - case CPUTIMER_INTRT_C3: - case CPUTIMER_INTRT_FAST: - break; - default: - return EINVAL; - } - cputimer_intr_switch(type); - return 0; -} -SYSCTL_PROC(_hw, OID_AUTO, cputimer_intr_type, CTLTYPE_INT | CTLFLAG_RW, - 0, 0, sysctl_cputimer_intr_switch, "I", - "cputimer_intr switch [0|1]"); - /* * DELAY(usec) - Spin for the specified number of microseconds. * DRIVERSLEEP(usec) - Spin for the specified number of microseconds, @@ -696,6 +635,11 @@ i8254_restore(void) outb(TIMER_CNTR0, 0); /* msb */ clock_unlock(); + if (!i8254_nointr) { + cputimer_intr_register(&i8254_cputimer_intr); + cputimer_intr_select(&i8254_cputimer_intr, 0); + } + /* * Timer1 or timer2 is our free-running clock, but only if another * has not been selected. @@ -843,6 +787,12 @@ startrtclock(void) "CLK_USE_I8254_CALIBRATION not specified - using default frequency\n"); freq = i8254_cputimer.freq; #endif + /* + * NOTE: + * Interrupt timer's freq must be adjusted + * before we change the cuptimer's frequency. + */ + i8254_cputimer_intr.freq = freq; cputimer_set_frequency(&i8254_cputimer, freq); } else { if (bootverbose) @@ -1060,8 +1010,8 @@ resettodr(void) * used. Instead, 8254 based systimers are used for all major clock * interrupts. statclock_disable is set by default. */ -void -cpu_initclocks(void *arg __unused) +static void +i8254_intr_initclock(struct cputimer_intr *cti, boolean_t selected) { int diag; #ifdef APIC_IO @@ -1071,10 +1021,11 @@ cpu_initclocks(void *arg __unused) callout_init(&sysbeepstop_ch); -#ifdef SMP - if (lapic_timer_enable && i8254_intr_disable) + if (!selected && i8254_intr_disable) { + i8254_nointr = 1; /* don't try to register again */ + cputimer_intr_deregister(cti); return; -#endif + } if (statclock_disable) { /* @@ -1156,6 +1107,7 @@ cpu_initclocks(void *arg __unused) * so make sure it is. */ KKASSERT(sys_cputimer == &i8254_cputimer); + KKASSERT(cti == &i8254_cputimer_intr); lastcnt = get_interrupt_counter(apic_8254_intr); @@ -1164,7 +1116,7 @@ cpu_initclocks(void *arg __unused) * it to happen, then see if we got it. */ kprintf("APIC_IO: Testing 8254 interrupt delivery\n"); - i8254_intr_reload(2); + i8254_intr_reload(cti, 2); base = sys_cputimer->count(); while (sys_cputimer->count() - base < sys_cputimer->freq / 100) ; /* nothing */ @@ -1202,7 +1154,6 @@ cpu_initclocks(void *arg __unused) INTR_NOENTROPY); machintr_intren(apic_8254_intr); } - } if (apic_int_type(0, 0) != 3 || int_to_apicintpin[apic_8254_intr].ioapic != 0 || @@ -1216,7 +1167,6 @@ cpu_initclocks(void *arg __unused) } #endif } -SYSINIT(clocks8254, SI_BOOT2_CLOCKREG, SI_ORDER_FIRST, cpu_initclocks, NULL) #ifdef APIC_IO diff --git a/sys/platform/pc64/amd64/busdma_machdep.c b/sys/platform/pc64/amd64/busdma_machdep.c index 93b345cf5c..e129f8ff7d 100644 --- a/sys/platform/pc64/amd64/busdma_machdep.c +++ b/sys/platform/pc64/amd64/busdma_machdep.c @@ -51,6 +51,11 @@ #define MAX_BPAGES 1024 +/* + * 16 x N declared on stack. + */ +#define BUS_DMA_CACHE_SEGMENTS 8 + struct bounce_zone; struct bus_dmamap; @@ -70,6 +75,11 @@ struct bus_dma_tag { int map_count; bus_dma_segment_t *segments; struct bounce_zone *bounce_zone; +#ifdef SMP + struct spinlock spin; +#else + int unused0; +#endif }; /* @@ -194,6 +204,28 @@ run_filter(bus_dma_tag_t dmat, bus_addr_t paddr) return (retval); } +static __inline +bus_dma_segment_t * +bus_dma_tag_lock(bus_dma_tag_t tag, bus_dma_segment_t *cache) +{ + if (tag->nsegments <= BUS_DMA_CACHE_SEGMENTS) + return(cache); +#ifdef SMP + spin_lock_wr(&tag->spin); +#endif + return(tag->segments); +} + +static __inline +void +bus_dma_tag_unlock(bus_dma_tag_t tag) +{ +#ifdef SMP + if (tag->nsegments > BUS_DMA_CACHE_SEGMENTS) + spin_unlock_wr(&tag->spin); +#endif +} + /* * Allocate a device specific dma_tag. */ @@ -229,8 +261,11 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, /* Return a NULL tag on failure */ *dmat = NULL; - newtag = kmalloc(sizeof(*newtag), M_DEVBUF, M_INTWAIT); + newtag = kmalloc(sizeof(*newtag), M_DEVBUF, M_INTWAIT | M_ZERO); +#ifdef SMP + spin_init(&newtag->spin); +#endif newtag->parent = parent; newtag->alignment = alignment; newtag->boundary = boundary; @@ -349,6 +384,12 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat) return (0); } +bus_size_t +bus_dma_tag_getmaxsize(bus_dma_tag_t tag) +{ + return(tag->maxsize); +} + /* * Allocate a handle for mapping from kva/uva/physical * address space into bus device space. @@ -754,6 +795,8 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg, int flags) { + bus_dma_segment_t cache_segments[BUS_DMA_CACHE_SEGMENTS]; + bus_dma_segment_t *segments; vm_paddr_t lastaddr = 0; int error, nsegs = 1; @@ -770,13 +813,16 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, map->callback_arg = callback_arg; } + segments = bus_dma_tag_lock(dmat, cache_segments); error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, - dmat->segments, dmat->nsegments, + segments, dmat->nsegments, NULL, flags, &lastaddr, &nsegs, 1); - if (error == EINPROGRESS) + if (error == EINPROGRESS) { + bus_dma_tag_unlock(dmat); return error; - - callback(callback_arg, dmat->segments, nsegs, error); + } + callback(callback_arg, segments, nsegs, error); + bus_dma_tag_unlock(dmat); return 0; } @@ -789,6 +835,8 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmamap_callback2_t *callback, void *callback_arg, int flags) { + bus_dma_segment_t cache_segments[BUS_DMA_CACHE_SEGMENTS]; + bus_dma_segment_t *segments; int nsegs, error; /* @@ -799,15 +847,18 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, flags &= ~BUS_DMA_WAITOK; flags |= BUS_DMA_NOWAIT; + segments = bus_dma_tag_lock(dmat, cache_segments); error = bus_dmamap_load_mbuf_segment(dmat, map, m0, - dmat->segments, dmat->nsegments, &nsegs, flags); + segments, dmat->nsegments, &nsegs, flags); if (error) { /* force "no valid mappings" in callback */ - callback(callback_arg, dmat->segments, 0, 0, error); + callback(callback_arg, segments, 0, + 0, error); } else { - callback(callback_arg, dmat->segments, nsegs, + callback(callback_arg, segments, nsegs, m0->m_pkthdr.len, error); } + bus_dma_tag_unlock(dmat); return error; } @@ -880,6 +931,16 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, bus_size_t resid; struct iovec *iov; pmap_t pmap; + bus_dma_segment_t cache_segments[BUS_DMA_CACHE_SEGMENTS]; + bus_dma_segment_t *segments; + bus_dma_segment_t *segs; + int nsegs_left; + + if (dmat->nsegments <= BUS_DMA_CACHE_SEGMENTS) + segments = cache_segments; + else + segments = kmalloc(sizeof(bus_dma_segment_t) * dmat->nsegments, + M_DEVBUF, M_WAITOK | M_ZERO); /* * XXX @@ -892,6 +953,9 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, resid = uio->uio_resid; iov = uio->uio_iov; + segs = segments; + nsegs_left = dmat->nsegments; + if (uio->uio_segflg == UIO_USERSPACE) { struct thread *td; @@ -917,20 +981,33 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, caddr_t addr = (caddr_t) iov[i].iov_base; error = _bus_dmamap_load_buffer(dmat, map, addr, minlen, - dmat->segments, dmat->nsegments, + segs, nsegs_left, pmap, flags, &lastaddr, &nsegs, first); first = 0; resid -= minlen; + if (error == 0) { + nsegs_left -= nsegs; + segs += nsegs; + } } + /* + * Minimum one DMA segment, even if 0-length buffer. + */ + if (nsegs_left == dmat->nsegments) + --nsegs_left; + if (error) { /* force "no valid mappings" in callback */ - callback(callback_arg, dmat->segments, 0, 0, error); + callback(callback_arg, segments, 0, + 0, error); } else { - callback(callback_arg, dmat->segments, nsegs, + callback(callback_arg, segments, dmat->nsegments - nsegs_left, uio->uio_resid, error); } + if (dmat->nsegments > BUS_DMA_CACHE_SEGMENTS) + kfree(segments, M_DEVBUF); return error; } diff --git a/sys/platform/pc64/amd64/exception.S b/sys/platform/pc64/amd64/exception.S index e469fec2c8..f1a262bbe7 100644 --- a/sys/platform/pc64/amd64/exception.S +++ b/sys/platform/pc64/amd64/exception.S @@ -376,7 +376,7 @@ IDTVEC(nmi) jnz nmi_needswapgs /* we came from userland */ movl $MSR_GSBASE,%ecx rdmsr - cmpl $VM_MAXUSER_ADDRESS >> 32,%edx + cmpl $VM_MAX_USER_ADDRESS >> 32,%edx jae nmi_calltrap /* GS.base holds a kernel VA */ nmi_needswapgs: incl %ebx diff --git a/sys/platform/pc64/amd64/genassym.c b/sys/platform/pc64/amd64/genassym.c index 64cb85e0b6..d4c073c48f 100644 --- a/sys/platform/pc64/amd64/genassym.c +++ b/sys/platform/pc64/amd64/genassym.c @@ -101,7 +101,7 @@ ASSYM(V_FORWARDED_MISSES, offsetof(struct vmmeter, v_forwarded_misses)); ASSYM(MAXCOMLEN, MAXCOMLEN); ASSYM(EFAULT, EFAULT); ASSYM(ENAMETOOLONG, ENAMETOOLONG); -ASSYM(VM_MAXUSER_ADDRESS, VM_MAXUSER_ADDRESS); +ASSYM(VM_MAX_USER_ADDRESS, VM_MAX_USER_ADDRESS); ASSYM(GD_CURTHREAD, offsetof(struct mdglobaldata, mi.gd_curthread)); ASSYM(GD_CNT, offsetof(struct mdglobaldata, mi.gd_cnt)); diff --git a/sys/platform/pc64/amd64/global.s b/sys/platform/pc64/amd64/global.s index a6d594e390..27327b7c08 100644 --- a/sys/platform/pc64/amd64/global.s +++ b/sys/platform/pc64/amd64/global.s @@ -42,9 +42,12 @@ * segment. */ .data +#if JG .globl CPU_prvspace, lapic .set CPU_prvspace,(MPPTDI << PDRSHIFT) + /* JG TODO check for correctness */ .set lapic,CPU_prvspace + (NPTEPG-1) * PAGE_SIZE +#endif .globl globaldata .set globaldata,0 diff --git a/sys/platform/pc64/amd64/locore.s b/sys/platform/pc64/amd64/locore.s index d38027cddf..81237ab161 100644 --- a/sys/platform/pc64/amd64/locore.s +++ b/sys/platform/pc64/amd64/locore.s @@ -1,6 +1,5 @@ /*- * Copyright (c) 2003 Peter Wemm - * Copyright (c) 2008 The DragonFly Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,24 +34,6 @@ #include "assym.s" -/* - * PTmap is recursive pagemap at top of virtual address space. - * Within PTmap, the page directory can be found (third indirection). - */ - .globl PTmap,PTD,PTDpde - .set PTmap,(PTDPTDI << PDRSHIFT) - .set PTD,PTmap + (PTDPTDI * PAGE_SIZE) - .set PTDpde,PTD + (PTDPTDI * PDESIZE) - -/* - * APTmap, APTD is the alternate recursive pagemap. - * It's used when modifying another process's page tables. - */ - .globl APTmap,APTD,APTDpde - .set APTmap,APTDPTDI << PDRSHIFT - .set APTD,APTmap + (APTDPTDI * PAGE_SIZE) - .set APTDpde,PTD + (APTDPTDI * PDESIZE) - /* * Compiled KERNBASE location */ @@ -67,7 +48,6 @@ .set dmapend,DMAP_MAX_ADDRESS .text - /********************************************************************** * * This is where the loader trampoline start us, set the ball rolling... diff --git a/sys/platform/pc64/amd64/machdep.c b/sys/platform/pc64/amd64/machdep.c index b3fa41ac74..d8eb2fca53 100644 --- a/sys/platform/pc64/amd64/machdep.c +++ b/sys/platform/pc64/amd64/machdep.c @@ -152,15 +152,14 @@ SYSINIT(cpu, SI_BOOT2_SMP, SI_ORDER_FIRST, cpu_startup, NULL) extern vm_offset_t ksym_start, ksym_end; #endif -uint64_t common_lvl4_phys; -uint64_t common_lvl3_phys; -uint64_t IdlePTD; uint64_t KPTphys; uint64_t SMPptpa; pt_entry_t *SMPpt; -pdp_entry_t *link_pdpe; +/* JG SMP */ +struct privatespace CPU_prvspace[1]; + int _udatasel, _ucodesel, _ucode32sel; u_long atdevbase; #ifdef SMP @@ -299,8 +298,7 @@ cpu_startup(void *dummy) #ifdef PERFMON perfmon_init(); #endif - kprintf("real memory = %llu (%lluK bytes)\n", - (long long)ptoa(Maxmem), (long long)ptoa(Maxmem) / 1024); + kprintf("real memory = %llu (%lluK bytes)\n", ptoa(Maxmem), ptoa(Maxmem) / 1024); /* * Display any holes after the first chunk of extended memory. */ @@ -312,10 +310,8 @@ cpu_startup(void *dummy) vm_paddr_t size1 = phys_avail[indx + 1] - phys_avail[indx]; kprintf("0x%08llx - 0x%08llx, %llu bytes (%llu pages)\n", - (long long)phys_avail[indx], - (long long)phys_avail[indx + 1] - 1, - (long long)size1, - (long long)(size1 / PAGE_SIZE)); + phys_avail[indx], phys_avail[indx + 1] - 1, size1, + size1 / PAGE_SIZE); } } @@ -1482,7 +1478,7 @@ getmemsize(caddr_t kmdp, u_int64_t first) kprintf("Physical memory use set to %ldK\n", Maxmem * 4); /* call pmap initialization to make new kernel address space */ - pmap_bootstrap(&first, 0); + pmap_bootstrap(&first); /* * Size up each available chunk of physical memory. @@ -1681,11 +1677,13 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) u_int64_t msr; char *env; +#if JG /* * This must be done before the first references * to CPU_prvspace[0] are made. */ init_paging(&physfree); +#endif /* * Prevent lowering of the ipl if we call tsleep() early. @@ -1752,6 +1750,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) } ssdtosyssd(&gdt_segs[GPROC0_SEL], (struct system_segment_descriptor *)&gdt[GPROC0_SEL]); + r_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1; r_gdt.rd_base = (long) gdt; lgdt(&r_gdt); @@ -1880,11 +1879,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) /* setup proc 0's pcb */ thread0.td_pcb->pcb_flags = 0; -#if JG thread0.td_pcb->pcb_cr3 = KPML4phys; -#else - thread0.td_pcb->pcb_cr3 = IdlePTD; -#endif thread0.td_pcb->pcb_ext = 0; lwp0.lwp_md.md_regs = &proc0_tf; env = kgetenv("kernelname"); diff --git a/sys/platform/pc64/amd64/pmap.c b/sys/platform/pc64/amd64/pmap.c index f5691bdf0b..0ac749c99a 100644 --- a/sys/platform/pc64/amd64/pmap.c +++ b/sys/platform/pc64/amd64/pmap.c @@ -2,8 +2,10 @@ * Copyright (c) 1991 Regents of the University of California. * Copyright (c) 1994 John S. Dyson * Copyright (c) 1994 David Greenman - * Copyright (c) 2008 The DragonFly Project. - * Copyright (c) 2008 Jordan Gordeev. + * Copyright (c) 2003 Peter Wemm + * Copyright (c) 2005-2008 Alan L. Cox + * Copyright (c) 2008, 2009 The DragonFly Project. + * Copyright (c) 2008, 2009 Jordan Gordeev. * All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -109,6 +111,8 @@ #include #include +#include + #define PMAP_KEEP_PDIRS #ifndef PMAP_SHPGPERPROC #define PMAP_SHPGPERPROC 200 @@ -126,10 +130,23 @@ #define PMAP_INLINE #endif +/* JGPMAP32 */ +#define PTDPTDI 0 + +#define READY0 +#define READY1 +#define READY2 +#define READY3 +#define READY4 +#define READY5 + /* * Get PDEs and PTEs for user/kernel address space */ +#if JGPMAP32 #define pmap_pde(m, v) (&((m)->pm_pdir[(vm_offset_t)(v) >> PDRSHIFT])) +#endif +static pd_entry_t *pmap_pde(pmap_t pmap, vm_offset_t va); #define pdir_pde(m, v) (m[(vm_offset_t)(v) >> PDRSHIFT]) #define pmap_pde_v(pte) ((*(pd_entry_t *)pte & PG_V) != 0) @@ -163,9 +180,18 @@ static int pseflag; /* PG_PS or-in */ static vm_object_t kptobj; +static int ndmpdp; +static vm_paddr_t dmaplimit; static int nkpt; vm_offset_t kernel_vm_end; +static uint64_t KPDphys; /* phys addr of kernel level 2 */ +uint64_t KPDPphys; /* phys addr of kernel level 3 */ +uint64_t KPML4phys; /* phys addr of kernel level 4 */ + +static uint64_t DMPDphys; /* phys addr of direct mapped level 2 */ +static uint64_t DMPDPphys; /* phys addr of direct mapped level 3 */ + /* * Data for the pv entry allocation mechanism */ @@ -197,7 +223,6 @@ extern uint64_t SMPptpa; #define DISABLE_PSE static PMAP_INLINE void free_pv_entry (pv_entry_t pv); -static pt_entry_t * get_ptbase (pmap_t pmap); static pv_entry_t get_pv_entry (void); static void i386_protection_init (void); static __inline void pmap_clearbit (vm_page_t m, int bit); @@ -220,6 +245,8 @@ static int pmap_release_free_page (pmap_t pmap, vm_page_t p); static vm_page_t _pmap_allocpte (pmap_t pmap, vm_pindex_t ptepindex); static pt_entry_t * pmap_pte_quick (pmap_t pmap, vm_offset_t va); static vm_page_t pmap_page_lookup (vm_object_t object, vm_pindex_t pindex); +static int pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m, + pmap_inval_info_t info); static int pmap_unuse_pt (pmap_t, vm_offset_t, vm_page_t, pmap_inval_info_t); static vm_offset_t pmap_kmem_choose(vm_offset_t addr); @@ -227,44 +254,18 @@ static unsigned pdir4mb; /* * Move the kernel virtual free pointer to the next - * 4MB. This is used to help improve performance - * by using a large (4MB) page for much of the kernel + * 2MB. This is used to help improve performance + * by using a large (2MB) page for much of the kernel * (.text, .data, .bss) */ static vm_offset_t pmap_kmem_choose(vm_offset_t addr) +READY2 { vm_offset_t newaddr = addr; -#ifndef DISABLE_PSE - if (cpu_feature & CPUID_PSE) { - newaddr = (addr + (NBPDR - 1)) & ~(NBPDR - 1); - } -#endif - return newaddr; -} - -/* - * pmap_pte: - * - * Extract the page table entry associated with the given map/virtual - * pair. - * - * This function may NOT be called from an interrupt. - */ -PMAP_INLINE pt_entry_t * -pmap_pte(pmap_t pmap, vm_offset_t va) -{ - pd_entry_t *pdeaddr; - if (pmap) { - pdeaddr = pmap_pde(pmap, va); - if (*pdeaddr & PG_PS) - return pdeaddr; - if (*pdeaddr) { - return get_ptbase(pmap) + amd64_btop(va); - } - } - return (0); + newaddr = (addr + (NBPDR - 1)) & ~(NBPDR - 1); + return newaddr; } /* @@ -277,35 +278,163 @@ pmap_pte(pmap_t pmap, vm_offset_t va) * * Should only be called while in a critical section. */ +static __inline pt_entry_t *pmap_pte(pmap_t pmap, vm_offset_t va); + static pt_entry_t * pmap_pte_quick(pmap_t pmap, vm_offset_t va) +READY0 { - struct mdglobaldata *gd = mdcpu; - pd_entry_t pde, newpf; - - if ((pde = pmap->pm_pdir[va >> PDRSHIFT]) != 0) { - pd_entry_t frame = pmap->pm_pdir[PTDPTDI] & PG_FRAME; - vm_pindex_t index = amd64_btop(va); - /* are we current address space or kernel? */ - if ((pmap == &kernel_pmap) || - (frame == (PTDpde & PG_FRAME))) { - return (pt_entry_t *) PTmap + index; - } - newpf = pde & PG_FRAME; - if ( ((* (pt_entry_t *) gd->gd_PMAP1) & PG_FRAME) != newpf) { - * (pt_entry_t *) gd->gd_PMAP1 = newpf | PG_RW | PG_V; - cpu_invlpg(gd->gd_PADDR1); - } - return gd->gd_PADDR1 + (index & (NPTEPG - 1)); - } - return (0); + return pmap_pte(pmap, va); +} + +/* Return a non-clipped PD index for a given VA */ +static __inline vm_pindex_t +pmap_pde_pindex(vm_offset_t va) +READY1 +{ + return va >> PDRSHIFT; +} + +/* Return various clipped indexes for a given VA */ +static __inline vm_pindex_t +pmap_pte_index(vm_offset_t va) +READY1 +{ + + return ((va >> PAGE_SHIFT) & ((1ul << NPTEPGSHIFT) - 1)); +} + +static __inline vm_pindex_t +pmap_pde_index(vm_offset_t va) +READY1 +{ + + return ((va >> PDRSHIFT) & ((1ul << NPDEPGSHIFT) - 1)); +} + +static __inline vm_pindex_t +pmap_pdpe_index(vm_offset_t va) +READY1 +{ + + return ((va >> PDPSHIFT) & ((1ul << NPDPEPGSHIFT) - 1)); +} + +static __inline vm_pindex_t +pmap_pml4e_index(vm_offset_t va) +READY1 +{ + + return ((va >> PML4SHIFT) & ((1ul << NPML4EPGSHIFT) - 1)); +} + +/* Return a pointer to the PML4 slot that corresponds to a VA */ +static __inline pml4_entry_t * +pmap_pml4e(pmap_t pmap, vm_offset_t va) +READY1 +{ + + return (&pmap->pm_pml4[pmap_pml4e_index(va)]); +} + +/* Return a pointer to the PDP slot that corresponds to a VA */ +static __inline pdp_entry_t * +pmap_pml4e_to_pdpe(pml4_entry_t *pml4e, vm_offset_t va) +READY1 +{ + pdp_entry_t *pdpe; + + pdpe = (pdp_entry_t *)PHYS_TO_DMAP(*pml4e & PG_FRAME); + return (&pdpe[pmap_pdpe_index(va)]); +} + +/* Return a pointer to the PDP slot that corresponds to a VA */ +static __inline pdp_entry_t * +pmap_pdpe(pmap_t pmap, vm_offset_t va) +READY1 +{ + pml4_entry_t *pml4e; + + pml4e = pmap_pml4e(pmap, va); + if ((*pml4e & PG_V) == 0) + return NULL; + return (pmap_pml4e_to_pdpe(pml4e, va)); +} + +/* Return a pointer to the PD slot that corresponds to a VA */ +static __inline pd_entry_t * +pmap_pdpe_to_pde(pdp_entry_t *pdpe, vm_offset_t va) +READY1 +{ + pd_entry_t *pde; + + pde = (pd_entry_t *)PHYS_TO_DMAP(*pdpe & PG_FRAME); + return (&pde[pmap_pde_index(va)]); +} + +/* Return a pointer to the PD slot that corresponds to a VA */ +static __inline pd_entry_t * +pmap_pde(pmap_t pmap, vm_offset_t va) +READY1 +{ + pdp_entry_t *pdpe; + + pdpe = pmap_pdpe(pmap, va); + if (pdpe == NULL || (*pdpe & PG_V) == 0) + return NULL; + return (pmap_pdpe_to_pde(pdpe, va)); +} + +/* Return a pointer to the PT slot that corresponds to a VA */ +static __inline pt_entry_t * +pmap_pde_to_pte(pd_entry_t *pde, vm_offset_t va) +READY1 +{ + pt_entry_t *pte; + + pte = (pt_entry_t *)PHYS_TO_DMAP(*pde & PG_FRAME); + return (&pte[pmap_pte_index(va)]); +} + +/* Return a pointer to the PT slot that corresponds to a VA */ +static __inline pt_entry_t * +pmap_pte(pmap_t pmap, vm_offset_t va) +READY1 +{ + pd_entry_t *pde; + + pde = pmap_pde(pmap, va); + if (pde == NULL || (*pde & PG_V) == 0) + return NULL; + if ((*pde & PG_PS) != 0) /* compat with i386 pmap_pte() */ + return ((pt_entry_t *)pde); + return (pmap_pde_to_pte(pde, va)); } -static u_int64_t +PMAP_INLINE pt_entry_t * +vtopte(vm_offset_t va) +READY1 +{ + uint64_t mask = ((1ul << (NPTEPGSHIFT + NPDEPGSHIFT + NPDPEPGSHIFT + NPML4EPGSHIFT)) - 1); + + return (PTmap + ((va >> PAGE_SHIFT) & mask)); +} + +static __inline pd_entry_t * +vtopde(vm_offset_t va) +READY1 +{ + uint64_t mask = ((1ul << (NPDEPGSHIFT + NPDPEPGSHIFT + NPML4EPGSHIFT)) - 1); + + return (PDmap + ((va >> PDRSHIFT) & mask)); +} + +static uint64_t allocpages(vm_paddr_t *firstaddr, int n) +READY1 { - u_int64_t ret; + uint64_t ret; ret = *firstaddr; bzero((void *)ret, n * PAGE_SIZE); @@ -315,6 +444,7 @@ allocpages(vm_paddr_t *firstaddr, int n) void create_pagetables(vm_paddr_t *firstaddr) +READY0 { int i; int count; @@ -323,6 +453,83 @@ create_pagetables(vm_paddr_t *firstaddr) /* we are running (mostly) V=P at this point */ + /* Allocate pages */ + KPTphys = allocpages(firstaddr, NKPT); + KPML4phys = allocpages(firstaddr, 1); + KPDPphys = allocpages(firstaddr, NKPML4E); + KPDphys = allocpages(firstaddr, NKPDPE); + + ndmpdp = (ptoa(Maxmem) + NBPDP - 1) >> PDPSHIFT; + if (ndmpdp < 4) /* Minimum 4GB of dirmap */ + ndmpdp = 4; + DMPDPphys = allocpages(firstaddr, NDMPML4E); + if ((amd_feature & AMDID_PAGE1GB) == 0) + DMPDphys = allocpages(firstaddr, ndmpdp); + dmaplimit = (vm_paddr_t)ndmpdp << PDPSHIFT; + + /* Fill in the underlying page table pages */ + /* Read-only from zero to physfree */ + /* XXX not fully used, underneath 2M pages */ + for (i = 0; (i << PAGE_SHIFT) < *firstaddr; i++) { + ((pt_entry_t *)KPTphys)[i] = i << PAGE_SHIFT; + ((pt_entry_t *)KPTphys)[i] |= PG_RW | PG_V | PG_G; + } + + /* Now map the page tables at their location within PTmap */ + for (i = 0; i < NKPT; i++) { + ((pd_entry_t *)KPDphys)[i] = KPTphys + (i << PAGE_SHIFT); + ((pd_entry_t *)KPDphys)[i] |= PG_RW | PG_V; + } + + /* Map from zero to end of allocations under 2M pages */ + /* This replaces some of the KPTphys entries above */ + for (i = 0; (i << PDRSHIFT) < *firstaddr; i++) { + ((pd_entry_t *)KPDphys)[i] = i << PDRSHIFT; + ((pd_entry_t *)KPDphys)[i] |= PG_RW | PG_V | PG_PS | PG_G; + } + + /* And connect up the PD to the PDP */ + for (i = 0; i < NKPDPE; i++) { + ((pdp_entry_t *)KPDPphys)[i + KPDPI] = KPDphys + + (i << PAGE_SHIFT); + ((pdp_entry_t *)KPDPphys)[i + KPDPI] |= PG_RW | PG_V | PG_U; + } + + /* Now set up the direct map space using either 2MB or 1GB pages */ + /* Preset PG_M and PG_A because demotion expects it */ + if ((amd_feature & AMDID_PAGE1GB) == 0) { + for (i = 0; i < NPDEPG * ndmpdp; i++) { + ((pd_entry_t *)DMPDphys)[i] = (vm_paddr_t)i << PDRSHIFT; + ((pd_entry_t *)DMPDphys)[i] |= PG_RW | PG_V | PG_PS | + PG_G | PG_M | PG_A; + } + /* And the direct map space's PDP */ + for (i = 0; i < ndmpdp; i++) { + ((pdp_entry_t *)DMPDPphys)[i] = DMPDphys + + (i << PAGE_SHIFT); + ((pdp_entry_t *)DMPDPphys)[i] |= PG_RW | PG_V | PG_U; + } + } else { + for (i = 0; i < ndmpdp; i++) { + ((pdp_entry_t *)DMPDPphys)[i] = + (vm_paddr_t)i << PDPSHIFT; + ((pdp_entry_t *)DMPDPphys)[i] |= PG_RW | PG_V | PG_PS | + PG_G | PG_M | PG_A; + } + } + + /* And recursively map PML4 to itself in order to get PTmap */ + ((pdp_entry_t *)KPML4phys)[PML4PML4I] = KPML4phys; + ((pdp_entry_t *)KPML4phys)[PML4PML4I] |= PG_RW | PG_V | PG_U; + + /* Connect the Direct Map slot up to the PML4 */ + ((pdp_entry_t *)KPML4phys)[DMPML4I] = DMPDPphys; + ((pdp_entry_t *)KPML4phys)[DMPML4I] |= PG_RW | PG_V | PG_U; + + /* Connect the KVA slot up to the PML4 */ + ((pdp_entry_t *)KPML4phys)[KPML4I] = KPDPphys; + ((pdp_entry_t *)KPML4phys)[KPML4I] |= PG_RW | PG_V | PG_U; +#if JGPMAP32 common_lvl4_phys = allocpages(firstaddr, 1); /* 512 512G mappings */ common_lvl3_phys = allocpages(firstaddr, 1); /* 512 1G mappings */ KPTphys = allocpages(firstaddr, NKPT); /* kernel page table */ @@ -401,12 +608,15 @@ create_pagetables(vm_paddr_t *firstaddr) * Matt: location of user page directory entry (representing 1G) */ link_pdpe = &((pdp_entry_t *)common_lvl3_phys)[LINKPDPI]; +#endif /* JGPMAP32 */ } +READY0 void init_paging(vm_paddr_t *firstaddr) { create_pagetables(firstaddr); +#if JGPMAP32 /* switch to the newly created page table */ *link_pdpe = IdlePTD | PG_RW | PG_V | PG_U; load_cr3(common_lvl4_phys); @@ -415,6 +625,7 @@ init_paging(vm_paddr_t *firstaddr) { KvaStart = (vm_offset_t)VADDR(PTDPTDI, 0); KvaEnd = (vm_offset_t)VADDR(APTDPTDI, 0); KvaSize = KvaEnd - KvaStart; +#endif } /* @@ -428,7 +639,8 @@ init_paging(vm_paddr_t *firstaddr) { * (physical) address starting relative to 0] */ void -pmap_bootstrap(vm_paddr_t *firstaddr, vm_paddr_t loadaddr) +pmap_bootstrap(vm_paddr_t *firstaddr) +READY0 { vm_offset_t va; pt_entry_t *pte; @@ -436,19 +648,25 @@ pmap_bootstrap(vm_paddr_t *firstaddr, vm_paddr_t loadaddr) int i; int pg; + KvaStart = VM_MIN_KERNEL_ADDRESS; + KvaEnd = VM_MAX_KERNEL_ADDRESS; + KvaSize = KvaEnd - KvaStart; + avail_start = *firstaddr; /* - * XXX The calculation of virtual_start is wrong. It's NKPT*PAGE_SIZE - * too large. It should instead be correctly calculated in locore.s and - * not based on 'first' (which is a physical address, not a virtual - * address, for the start of unused physical memory). The kernel - * page tables are NOT double mapped and thus should not be included - * in this calculation. + * Create an initial set of page tables to run the kernel in. */ + create_pagetables(firstaddr); + virtual_start = (vm_offset_t) PTOV_OFFSET + *firstaddr; virtual_start = pmap_kmem_choose(virtual_start); - virtual_end = VADDR(KPTDI+NKPDE-1, NPTEPG-1); + + virtual_end = VM_MAX_KERNEL_ADDRESS; + + /* XXX do %cr0 as well */ + load_cr4(rcr4() | CR4_PGE | CR4_PSE); + load_cr3(KPML4phys); /* * Initialize protection array. @@ -460,7 +678,10 @@ pmap_bootstrap(vm_paddr_t *firstaddr, vm_paddr_t loadaddr) * pmap_create, which is unlikely to work correctly at this part of * the boot sequence (XXX and which no longer exists). */ +#if JGPMAP32 kernel_pmap.pm_pdir = (pd_entry_t *)(PTOV_OFFSET + (uint64_t)IdlePTD); +#endif + kernel_pmap.pm_pml4 = (pdp_entry_t *) (PTOV_OFFSET + KPML4phys); kernel_pmap.pm_count = 1; kernel_pmap.pm_active = (cpumask_t)-1; /* don't allow deactivation */ TAILQ_INIT(&kernel_pmap.pm_pvlist); @@ -474,7 +695,11 @@ pmap_bootstrap(vm_paddr_t *firstaddr, vm_paddr_t loadaddr) v = (c)va; va += ((n)*PAGE_SIZE); p = pte; pte += (n); va = virtual_start; +#ifdef JG pte = (pt_entry_t *) pmap_pte(&kernel_pmap, va); +#else + pte = vtopte(va); +#endif /* * CMAP1/CMAP2 are used for zeroing and copying pages. @@ -502,8 +727,10 @@ pmap_bootstrap(vm_paddr_t *firstaddr, vm_paddr_t loadaddr) virtual_start = va; *CMAP1 = 0; +#if JGPMAP32 for (i = 0; i < NKPT; i++) PTD[i] = 0; +#endif /* * PG_G is terribly broken on SMP because we IPI invltlb's in some @@ -557,7 +784,9 @@ pmap_bootstrap(vm_paddr_t *firstaddr, vm_paddr_t loadaddr) * PSE will be enabled as soon as all APs are up. */ PTD[KPTDI] = (pd_entry_t)ptditmp; +#if JGPMAP32 kernel_pmap.pm_pdir[KPTDI] = (pd_entry_t)ptditmp; +#endif cpu_invltlb(); #endif } @@ -596,12 +825,15 @@ pmap_bootstrap(vm_paddr_t *firstaddr, vm_paddr_t loadaddr) */ void pmap_set_opt(void) +READY0 { if (pseflag && (cpu_feature & CPUID_PSE)) { load_cr4(rcr4() | CR4_PSE); if (pdir4mb && mycpu->gd_cpuid == 0) { /* only on BSP */ +#if JGPMAP32 kernel_pmap.pm_pdir[KPTDI] = PTD[KPTDI] = (pd_entry_t)pdir4mb; +#endif cpu_invltlb(); } } @@ -617,6 +849,7 @@ pmap_set_opt(void) */ void pmap_init(void) +READY0 { int i; int initial_pvs; @@ -624,7 +857,8 @@ pmap_init(void) /* * object for kernel page table pages */ - kptobj = vm_object_allocate(OBJT_DEFAULT, NKPDE); + /* JG I think the number can be arbitrary */ + kptobj = vm_object_allocate(OBJT_DEFAULT, 5); /* * Allocate memory for random pmap data structures. Includes the @@ -664,6 +898,7 @@ pmap_init(void) */ void pmap_init2(void) +READY0 { int shpgperproc = PMAP_SHPGPERPROC; @@ -686,12 +921,9 @@ pmap_init2(void) * This should be an invalid condition. */ static int -pmap_nw_modified(pt_entry_t ptea) +pmap_nw_modified(pt_entry_t pte) +READY1 { - int pte; - - pte = (int) ptea; - if ((pte & (PG_M|PG_RW)) == PG_M) return 1; else @@ -706,6 +938,7 @@ pmap_nw_modified(pt_entry_t ptea) */ static PMAP_INLINE int pmap_track_modified(vm_offset_t va) +READY0 { if ((va < clean_sva) || (va >= clean_eva)) return 1; @@ -713,29 +946,6 @@ pmap_track_modified(vm_offset_t va) return 0; } -static pt_entry_t * -get_ptbase(pmap_t pmap) -{ - pd_entry_t frame = pmap->pm_pdir[PTDPTDI] & PG_FRAME; - struct globaldata *gd = mycpu; - - /* are we current address space or kernel? */ - if (pmap == &kernel_pmap || frame == (PTDpde & PG_FRAME)) { - return (pt_entry_t *) PTmap; - } - - /* otherwise, we are alternate address space */ - KKASSERT(gd->gd_intr_nesting_level == 0 && - (gd->gd_curthread->td_flags & TDF_INTTHREAD) == 0); - - if (frame != (((pd_entry_t) APTDpde) & PG_FRAME)) { - APTDpde = (pd_entry_t)(frame | PG_RW | PG_V); - /* The page directory is not shared between CPUs */ - cpu_invltlb(); - } - return (pt_entry_t *) APTmap; -} - /* * pmap_extract: * @@ -746,23 +956,61 @@ get_ptbase(pmap_t pmap) */ vm_paddr_t pmap_extract(pmap_t pmap, vm_offset_t va) +READY1 { - vm_offset_t rtval; - vm_offset_t pdirindex; + vm_paddr_t rtval; + pt_entry_t *pte; + pd_entry_t pde, *pdep; - pdirindex = va >> PDRSHIFT; - if (pmap && (rtval = pmap->pm_pdir[pdirindex])) { - pt_entry_t *pte; - if ((rtval & PG_PS) != 0) { - rtval &= ~(NBPDR - 1); - rtval |= va & (NBPDR - 1); - return rtval; + rtval = 0; + pdep = pmap_pde(pmap, va); + if (pdep != NULL) { + pde = *pdep; + if (pde) { + if ((pde & PG_PS) != 0) { + rtval = (pde & PG_PS_FRAME) | (va & PDRMASK); + } else { + pte = pmap_pde_to_pte(pdep, va); + rtval = (*pte & PG_FRAME) | (va & PAGE_MASK); + } } - pte = get_ptbase(pmap) + amd64_btop(va); - rtval = ((*pte & PG_FRAME) | (va & PAGE_MASK)); - return rtval; } - return 0; + return rtval; +} + +/* + * Routine: pmap_kextract + * Function: + * Extract the physical page address associated + * kernel virtual address. + */ +vm_paddr_t +pmap_kextract(vm_offset_t va) +READY1 +{ + pd_entry_t pde; + vm_paddr_t pa; + + if (va >= DMAP_MIN_ADDRESS && va < DMAP_MAX_ADDRESS) { + pa = DMAP_TO_PHYS(va); + } else { + pde = *vtopde(va); + if (pde & PG_PS) { + pa = (pde & PG_PS_FRAME) | (va & PDRMASK); + } else { + /* + * Beware of a concurrent promotion that changes the + * PDE at this point! For example, vtopte() must not + * be used to access the PTE because it would use the + * new PDE. It is, however, safe to use the old PDE + * because the page table page is preserved by the + * promotion. + */ + pa = *pmap_pde_to_pte(&pde, va); + pa = (pa & PG_FRAME) | (va & PAGE_MASK); + } + } + return pa; } /*************************************************** @@ -778,6 +1026,7 @@ pmap_extract(pmap_t pmap, vm_offset_t va) */ void pmap_kenter(vm_offset_t va, vm_paddr_t pa) +READY1 { pt_entry_t *pte; pt_entry_t npte; @@ -799,6 +1048,7 @@ pmap_kenter(vm_offset_t va, vm_paddr_t pa) */ void pmap_kenter_quick(vm_offset_t va, vm_paddr_t pa) +READY1 { pt_entry_t *pte; pt_entry_t npte; @@ -811,6 +1061,7 @@ pmap_kenter_quick(vm_offset_t va, vm_paddr_t pa) void pmap_kenter_sync(vm_offset_t va) +READY1 { pmap_inval_info info; @@ -821,6 +1072,7 @@ pmap_kenter_sync(vm_offset_t va) void pmap_kenter_sync_quick(vm_offset_t va) +READY1 { cpu_invlpg((void *)va); } @@ -830,6 +1082,7 @@ pmap_kenter_sync_quick(vm_offset_t va) */ void pmap_kremove(vm_offset_t va) +READY1 { pt_entry_t *pte; pmap_inval_info info; @@ -843,6 +1096,7 @@ pmap_kremove(vm_offset_t va) void pmap_kremove_quick(vm_offset_t va) +READY1 { pt_entry_t *pte; pte = vtopte(va); @@ -855,6 +1109,7 @@ pmap_kremove_quick(vm_offset_t va) */ void pmap_kmodify_rw(vm_offset_t va) +READY1 { *vtopte(va) |= PG_RW; cpu_invlpg((void *)va); @@ -862,6 +1117,7 @@ pmap_kmodify_rw(vm_offset_t va) void pmap_kmodify_nc(vm_offset_t va) +READY1 { *vtopte(va) |= PG_N; cpu_invlpg((void *)va); @@ -876,7 +1132,12 @@ pmap_kmodify_nc(vm_offset_t va) */ vm_offset_t pmap_map(vm_offset_t virt, vm_paddr_t start, vm_paddr_t end, int prot) +READY1 { + /* + * JG Are callers prepared to get an address in the DMAP, + * instead of the passed-in virt? + */ while (start < end) { pmap_kenter(virt, start); virt += PAGE_SIZE; @@ -896,6 +1157,7 @@ pmap_map(vm_offset_t virt, vm_paddr_t start, vm_paddr_t end, int prot) */ void pmap_qenter(vm_offset_t va, vm_page_t *m, int count) +READY1 { vm_offset_t end_va; @@ -917,6 +1179,7 @@ pmap_qenter(vm_offset_t va, vm_page_t *m, int count) void pmap_qenter2(vm_offset_t va, vm_page_t *m, int count, cpumask_t *mask) +READY1 { vm_offset_t end_va; cpumask_t cmask = mycpu->gd_cpumask; @@ -955,10 +1218,11 @@ pmap_qenter2(vm_offset_t va, vm_page_t *m, int count, cpumask_t *mask) */ void pmap_qremove(vm_offset_t va, int count) +READY1 { vm_offset_t end_va; - end_va = va + count*PAGE_SIZE; + end_va = va + count * PAGE_SIZE; while (va < end_va) { pt_entry_t *pte; @@ -983,6 +1247,7 @@ pmap_qremove(vm_offset_t va, int count) */ static vm_page_t pmap_page_lookup(vm_object_t object, vm_pindex_t pindex) +READY1 { vm_page_t m; @@ -999,11 +1264,12 @@ pmap_page_lookup(vm_object_t object, vm_pindex_t pindex) */ void pmap_init_thread(thread_t td) +READY1 { /* enforce pcb placement */ td->td_pcb = (struct pcb *)(td->td_kstack + td->td_kstack_size) - 1; td->td_savefpu = &td->td_pcb->pcb_save; - td->td_sp = (char *)td->td_pcb - 16; + td->td_sp = (char *)td->td_pcb - 16; /* JG is -16 needed on amd64? */ } /* @@ -1011,6 +1277,7 @@ pmap_init_thread(thread_t td) */ void pmap_init_proc(struct proc *p) +READY1 { } @@ -1020,6 +1287,7 @@ pmap_init_proc(struct proc *p) */ void pmap_dispose_proc(struct proc *p) +READY1 { KASSERT(p->p_lock == 0, ("attempt to dispose referenced proc! %p", p)); } @@ -1033,7 +1301,8 @@ pmap_dispose_proc(struct proc *p) * drops to zero, then it decrements the wire count. */ static int -_pmap_unwire_pte_hold(pmap_t pmap, vm_page_t m, pmap_inval_info_t info) +_pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m, pmap_inval_info_t info) +READY1 { /* * Wait until we can busy the page ourselves. We cannot have @@ -1053,7 +1322,23 @@ _pmap_unwire_pte_hold(pmap_t pmap, vm_page_t m, pmap_inval_info_t info) */ vm_page_busy(m); pmap_inval_add(info, pmap, -1); - pmap->pm_pdir[m->pindex] = 0; + + if (m->pindex >= (NUPDE + NUPDPE)) { + /* PDP page */ + pml4_entry_t *pml4; + pml4 = pmap_pml4e(pmap, va); + *pml4 = 0; + } else if (m->pindex >= NUPDE) { + /* PD page */ + pdp_entry_t *pdp; + pdp = pmap_pdpe(pmap, va); + *pdp = 0; + } else { + /* PTE page */ + pd_entry_t *pd; + pd = pmap_pde(pmap, va); + *pd = 0; + } KKASSERT(pmap->pm_stats.resident_count > 0); --pmap->pm_stats.resident_count; @@ -1061,6 +1346,23 @@ _pmap_unwire_pte_hold(pmap_t pmap, vm_page_t m, pmap_inval_info_t info) if (pmap->pm_ptphint == m) pmap->pm_ptphint = NULL; +#if JG + if (m->pindex < NUPDE) { + /* We just released a PT, unhold the matching PD */ + vm_page_t pdpg; + + pdpg = PHYS_TO_VM_PAGE(*pmap_pdpe(pmap, va) & PG_FRAME); + pmap_unwire_pte_hold(pmap, va, pdpg, info); + } + if (m->pindex >= NUPDE && m->pindex < (NUPDE + NUPDPE)) { + /* We just released a PD, unhold the matching PDP */ + vm_page_t pdppg; + + pdppg = PHYS_TO_VM_PAGE(*pmap_pml4e(pmap, va) & PG_FRAME); + pmap_unwire_pte_hold(pmap, va, pdppg, info); + } +#endif + /* * This was our last hold, the page had better be unwired * after we decrement wire_count. @@ -1084,14 +1386,15 @@ _pmap_unwire_pte_hold(pmap_t pmap, vm_page_t m, pmap_inval_info_t info) } static PMAP_INLINE int -pmap_unwire_pte_hold(pmap_t pmap, vm_page_t m, pmap_inval_info_t info) +pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m, pmap_inval_info_t info) +READY1 { KKASSERT(m->hold_count > 0); if (m->hold_count > 1) { vm_page_unhold(m); return 0; } else { - return _pmap_unwire_pte_hold(pmap, m, info); + return _pmap_unwire_pte_hold(pmap, va, m, info); } } @@ -1102,24 +1405,30 @@ pmap_unwire_pte_hold(pmap_t pmap, vm_page_t m, pmap_inval_info_t info) static int pmap_unuse_pt(pmap_t pmap, vm_offset_t va, vm_page_t mpte, pmap_inval_info_t info) +READY1 { + /* JG Use FreeBSD/amd64 or FreeBSD/i386 ptepde approaches? */ vm_pindex_t ptepindex; - if (va >= UPT_MIN_ADDRESS) + if (va >= VM_MAX_USER_ADDRESS) return 0; if (mpte == NULL) { - ptepindex = (va >> PDRSHIFT); + ptepindex = pmap_pde_pindex(va); +#if JGHINT if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == ptepindex)) { mpte = pmap->pm_ptphint; } else { +#endif pmap_inval_flush(info); - mpte = pmap_page_lookup( pmap->pm_pteobj, ptepindex); + mpte = pmap_page_lookup(pmap->pm_pteobj, ptepindex); pmap->pm_ptphint = mpte; +#if JGHINT } +#endif } - return pmap_unwire_pte_hold(pmap, mpte, info); + return pmap_unwire_pte_hold(pmap, va, mpte, info); } /* @@ -1132,10 +1441,14 @@ pmap_unuse_pt(pmap_t pmap, vm_offset_t va, vm_page_t mpte, */ void pmap_pinit0(struct pmap *pmap) +READY1 { +#if JGPMAP32 pmap->pm_pdir = (pd_entry_t *)kmem_alloc_pageable(&kernel_map, PAGE_SIZE); pmap_kenter((vm_offset_t)pmap->pm_pdir, (vm_offset_t) IdlePTD); +#endif + pmap->pm_pml4 = (pml4_entry_t *)(PTOV_OFFSET + KPML4phys); pmap->pm_count = 1; pmap->pm_active = 0; pmap->pm_ptphint = NULL; @@ -1149,6 +1462,7 @@ pmap_pinit0(struct pmap *pmap) */ void pmap_pinit(struct pmap *pmap) +READY1 { vm_page_t ptdpg; @@ -1156,16 +1470,16 @@ pmap_pinit(struct pmap *pmap) * No need to allocate page table space yet but we do need a valid * page directory table. */ - if (pmap->pm_pdir == NULL) { - pmap->pm_pdir = - (pd_entry_t *)kmem_alloc_pageable(&kernel_map, PAGE_SIZE); + if (pmap->pm_pml4 == NULL) { + pmap->pm_pml4 = + (pml4_entry_t *)kmem_alloc_pageable(&kernel_map, PAGE_SIZE); } /* * Allocate an object for the ptes */ if (pmap->pm_pteobj == NULL) - pmap->pm_pteobj = vm_object_allocate(OBJT_DEFAULT, PTDPTDI + 1); + pmap->pm_pteobj = vm_object_allocate(OBJT_DEFAULT, PML4PML4I + 1); /* * Allocate the page directory page, unless we already have @@ -1173,23 +1487,23 @@ pmap_pinit(struct pmap *pmap) * already be set appropriately. */ if ((ptdpg = pmap->pm_pdirm) == NULL) { - ptdpg = vm_page_grab(pmap->pm_pteobj, PTDPTDI, + ptdpg = vm_page_grab(pmap->pm_pteobj, PML4PML4I, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); pmap->pm_pdirm = ptdpg; vm_page_flag_clear(ptdpg, PG_MAPPED | PG_BUSY); ptdpg->valid = VM_PAGE_BITS_ALL; ptdpg->wire_count = 1; ++vmstats.v_wire_count; - pmap_kenter((vm_offset_t)pmap->pm_pdir, VM_PAGE_TO_PHYS(ptdpg)); + pmap_kenter((vm_offset_t)pmap->pm_pml4, VM_PAGE_TO_PHYS(ptdpg)); } if ((ptdpg->flags & PG_ZERO) == 0) - bzero(pmap->pm_pdir, PAGE_SIZE); + bzero(pmap->pm_pml4, PAGE_SIZE); - pmap->pm_pdir[MPPTDI] = PTD[MPPTDI]; + pmap->pm_pml4[KPML4I] = KPDPphys | PG_RW | PG_V | PG_U; + pmap->pm_pml4[DMPML4I] = DMPDPphys | PG_RW | PG_V | PG_U; /* install self-referential address mapping entry */ - *(pd_entry_t *) (pmap->pm_pdir + PTDPTDI) = - VM_PAGE_TO_PHYS(ptdpg) | PG_V | PG_RW | PG_A | PG_M; + pmap->pm_pml4[PML4PML4I] = VM_PAGE_TO_PHYS(ptdpg) | PG_V | PG_RW | PG_A | PG_M; pmap->pm_count = 1; pmap->pm_active = 0; @@ -1207,13 +1521,15 @@ pmap_pinit(struct pmap *pmap) */ void pmap_puninit(pmap_t pmap) +READY1 { vm_page_t p; KKASSERT(pmap->pm_active == 0); if ((p = pmap->pm_pdirm) != NULL) { - KKASSERT(pmap->pm_pdir != NULL); - pmap_kremove((vm_offset_t)pmap->pm_pdir); + KKASSERT(pmap->pm_pml4 != NULL); + KKASSERT(pmap->pm_pml4 != (PTOV_OFFSET + KPML4phys)); + pmap_kremove((vm_offset_t)pmap->pm_pml4); p->wire_count--; vmstats.v_wire_count--; KKASSERT((p->flags & PG_BUSY) == 0); @@ -1221,9 +1537,10 @@ pmap_puninit(pmap_t pmap) vm_page_free_zero(p); pmap->pm_pdirm = NULL; } - if (pmap->pm_pdir) { - kmem_free(&kernel_map, (vm_offset_t)pmap->pm_pdir, PAGE_SIZE); - pmap->pm_pdir = NULL; + if (pmap->pm_pml4) { + KKASSERT(pmap->pm_pml4 != (PTOV_OFFSET + KPML4phys)); + kmem_free(&kernel_map, (vm_offset_t)pmap->pm_pml4, PAGE_SIZE); + pmap->pm_pml4 = NULL; } if (pmap->pm_pteobj) { vm_object_deallocate(pmap->pm_pteobj); @@ -1239,11 +1556,14 @@ pmap_puninit(pmap_t pmap) */ void pmap_pinit2(struct pmap *pmap) +READY0 { crit_enter(); TAILQ_INSERT_TAIL(&pmap_list, pmap, pm_pmnode); /* XXX copies current process, does not fill in MPPTDI */ +#if JGPMAP32 bcopy(PTD + KPTDI, pmap->pm_pdir + KPTDI, nkpt * PTESIZE); +#endif crit_exit(); } @@ -1257,8 +1577,9 @@ pmap_pinit2(struct pmap *pmap) */ static int pmap_release_free_page(struct pmap *pmap, vm_page_t p) +READY1 { - pd_entry_t *pde = (pd_entry_t *) pmap->pm_pdir; + pml4_entry_t *pml4 = pmap->pm_pml4; /* * This code optimizes the case of freeing non-busy * page-table pages. Those pages are zero now, and @@ -1272,7 +1593,12 @@ pmap_release_free_page(struct pmap *pmap, vm_page_t p) /* * Remove the page table page from the processes address space. */ + /* JG XXX we need to turn 'pindex' into a page table level + * (PML4, PDP, PD, PT) and index within the page table page + */ +#if JGPMAP32 pde[p->pindex] = 0; +#endif KKASSERT(pmap->pm_stats.resident_count > 0); --pmap->pm_stats.resident_count; @@ -1282,22 +1608,9 @@ pmap_release_free_page(struct pmap *pmap, vm_page_t p) if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == p->pindex)) pmap->pm_ptphint = NULL; - /* - * We leave the page directory page cached, wired, and mapped in - * the pmap until the dtor function (pmap_puninit()) gets called. - * However, still clean it up so we can set PG_ZERO. - */ - if (p->pindex == PTDPTDI) { - bzero(pde + KPTDI, nkpt * PTESIZE); - pde[MPPTDI] = 0; - pde[APTDPTDI] = 0; - vm_page_flag_set(p, PG_ZERO); - vm_page_wakeup(p); - } else { - p->wire_count--; - vmstats.v_wire_count--; - vm_page_free_zero(p); - } + p->wire_count--; + vmstats.v_wire_count--; + vm_page_free_zero(p); return 1; } @@ -1307,9 +1620,9 @@ pmap_release_free_page(struct pmap *pmap, vm_page_t p) */ static vm_page_t _pmap_allocpte(pmap_t pmap, vm_pindex_t ptepindex) +READY1 { - vm_offset_t pteva, ptepa; - vm_page_t m; + vm_page_t m, pdppg, pdpg; /* * Find or fabricate a new pagetable page @@ -1317,6 +1630,11 @@ _pmap_allocpte(pmap_t pmap, vm_pindex_t ptepindex) m = vm_page_grab(pmap->pm_pteobj, ptepindex, VM_ALLOC_NORMAL | VM_ALLOC_ZERO | VM_ALLOC_RETRY); + + if ((m->flags & PG_ZERO) == 0) { + pmap_zero_page(VM_PAGE_TO_PHYS(m)); + } + KASSERT(m->queue == PQ_NONE, ("_pmap_allocpte: %p->queue != PQ_NONE", m)); @@ -1331,11 +1649,13 @@ _pmap_allocpte(pmap_t pmap, vm_pindex_t ptepindex) * directory page while we were blocked, if so just unbusy and * return the held page. */ +#if JGPMAP32 if ((ptepa = pmap->pm_pdir[ptepindex]) != 0) { KKASSERT((ptepa & PG_FRAME) == VM_PAGE_TO_PHYS(m)); vm_page_wakeup(m); return(m); } +#endif if (m->wire_count == 0) vmstats.v_wire_count++; @@ -1349,29 +1669,103 @@ _pmap_allocpte(pmap_t pmap, vm_pindex_t ptepindex) ++pmap->pm_stats.resident_count; +#if JGPMAP32 ptepa = VM_PAGE_TO_PHYS(m); pmap->pm_pdir[ptepindex] = (pd_entry_t) (ptepa | PG_U | PG_RW | PG_V | PG_A | PG_M); +#endif + if (ptepindex >= (NUPDE + NUPDPE)) { + pml4_entry_t *pml4; + vm_pindex_t pml4index; + + /* Wire up a new PDPE page */ + pml4index = ptepindex - (NUPDE + NUPDPE); + pml4 = &pmap->pm_pml4[pml4index]; + *pml4 = VM_PAGE_TO_PHYS(m) | PG_U | PG_RW | PG_V | PG_A | PG_M; + + } else if (ptepindex >= NUPDE) { + vm_pindex_t pml4index; + vm_pindex_t pdpindex; + pml4_entry_t *pml4; + pdp_entry_t *pdp; + + /* Wire up a new PDE page */ + pdpindex = ptepindex - NUPDE; + pml4index = pdpindex >> NPML4EPGSHIFT; + + pml4 = &pmap->pm_pml4[pml4index]; + if ((*pml4 & PG_V) == 0) { + /* Have to allocate a new pdp, recurse */ + if (_pmap_allocpte(pmap, NUPDE + NUPDPE + pml4index) + == NULL) { + --m->wire_count; + vm_page_free(m); + return (NULL); + } + } else { + /* Add reference to pdp page */ + pdppg = PHYS_TO_VM_PAGE(*pml4 & PG_FRAME); + pdppg->wire_count++; + } + pdp = (pdp_entry_t *)PHYS_TO_DMAP(*pml4 & PG_FRAME); - /* - * Set the page table hint - */ - pmap->pm_ptphint = m; + /* Now find the pdp page */ + pdp = &pdp[pdpindex & ((1ul << NPDPEPGSHIFT) - 1)]; + *pdp = VM_PAGE_TO_PHYS(m) | PG_U | PG_RW | PG_V | PG_A | PG_M; - /* - * Try to use the new mapping, but if we cannot, then - * do it with the routine that maps the page explicitly. - */ - if ((m->flags & PG_ZERO) == 0) { - if ((pmap->pm_pdir[PTDPTDI] & PG_FRAME) == - (((pd_entry_t) PTDpde) & PG_FRAME)) { - pteva = UPT_MIN_ADDRESS + amd64_ptob(ptepindex); - bzero((caddr_t) pteva, PAGE_SIZE); + } else { + vm_pindex_t pml4index; + vm_pindex_t pdpindex; + pml4_entry_t *pml4; + pdp_entry_t *pdp; + pd_entry_t *pd; + + /* Wire up a new PTE page */ + pdpindex = ptepindex >> NPDPEPGSHIFT; + pml4index = pdpindex >> NPML4EPGSHIFT; + + /* First, find the pdp and check that its valid. */ + pml4 = &pmap->pm_pml4[pml4index]; + if ((*pml4 & PG_V) == 0) { + /* Have to allocate a new pd, recurse */ + if (_pmap_allocpte(pmap, NUPDE + pdpindex) + == NULL) { + --m->wire_count; + vm_page_free(m); + return (NULL); + } + pdp = (pdp_entry_t *)PHYS_TO_DMAP(*pml4 & PG_FRAME); + pdp = &pdp[pdpindex & ((1ul << NPDPEPGSHIFT) - 1)]; } else { - pmap_zero_page(ptepa); + pdp = (pdp_entry_t *)PHYS_TO_DMAP(*pml4 & PG_FRAME); + pdp = &pdp[pdpindex & ((1ul << NPDPEPGSHIFT) - 1)]; + if ((*pdp & PG_V) == 0) { + /* Have to allocate a new pd, recurse */ + if (_pmap_allocpte(pmap, NUPDE + pdpindex) + == NULL) { + --m->wire_count; + vm_page_free(m); + return (NULL); + } + } else { + /* Add reference to the pd page */ + pdpg = PHYS_TO_VM_PAGE(*pdp & PG_FRAME); + pdpg->wire_count++; + } } + pd = (pd_entry_t *)PHYS_TO_DMAP(*pdp & PG_FRAME); + + /* Now we know where the page directory page is */ + pd = &pd[ptepindex & ((1ul << NPDEPGSHIFT) - 1)]; + *pd = VM_PAGE_TO_PHYS(m) | PG_U | PG_RW | PG_V | PG_A | PG_M; } + + /* + * Set the page table hint + */ + pmap->pm_ptphint = m; + m->valid = VM_PAGE_BITS_ALL; vm_page_flag_clear(m, PG_ZERO); vm_page_flag_set(m, PG_MAPPED); @@ -1382,28 +1776,29 @@ _pmap_allocpte(pmap_t pmap, vm_pindex_t ptepindex) static vm_page_t pmap_allocpte(pmap_t pmap, vm_offset_t va) +READY1 { vm_pindex_t ptepindex; - vm_offset_t ptepa; + pd_entry_t *pd; vm_page_t m; /* * Calculate pagetable page index */ - ptepindex = va >> PDRSHIFT; + ptepindex = pmap_pde_pindex(va); /* * Get the page directory entry */ - ptepa = (vm_offset_t) pmap->pm_pdir[ptepindex]; + pd = pmap_pde(pmap, va); /* - * This supports switching from a 4MB page to a + * This supports switching from a 2MB page to a * normal 4K page. */ - if (ptepa & PG_PS) { - pmap->pm_pdir[ptepindex] = 0; - ptepa = 0; + if (pd != NULL && (*pd & (PG_PS | PG_V)) == (PG_PS | PG_V)) { + *pd = 0; + pd = NULL; cpu_invltlb(); smp_invltlb(); } @@ -1412,18 +1807,10 @@ pmap_allocpte(pmap_t pmap, vm_offset_t va) * If the page table page is mapped, we just increment the * hold count, and activate it. */ - if (ptepa) { - /* - * In order to get the page table page, try the - * hint first. - */ - if (pmap->pm_ptphint && - (pmap->pm_ptphint->pindex == ptepindex)) { - m = pmap->pm_ptphint; - } else { - m = pmap_page_lookup( pmap->pm_pteobj, ptepindex); - pmap->pm_ptphint = m; - } + if (pd != NULL && (*pd & PG_V) != 0) { + /* YYY hint is used here on i386 */ + m = pmap_page_lookup( pmap->pm_pteobj, ptepindex); + pmap->pm_ptphint = m; m->hold_count++; return m; } @@ -1447,6 +1834,7 @@ static int pmap_release_callback(struct vm_page *p, void *data); void pmap_release(struct pmap *pmap) +READY1 { vm_object_t object = pmap->pm_pteobj; struct rb_vm_page_scan_info info; @@ -1481,10 +1869,11 @@ pmap_release(struct pmap *pmap) static int pmap_release_callback(struct vm_page *p, void *data) +READY1 { struct rb_vm_page_scan_info *info = data; - if (p->pindex == PTDPTDI) { + if (p->pindex == PML4PML4I) { info->mpte = p; return(0); } @@ -1505,32 +1894,61 @@ pmap_release_callback(struct vm_page *p, void *data) void pmap_growkernel(vm_offset_t addr) +READY1 { + vm_paddr_t paddr; struct pmap *pmap; vm_offset_t ptppaddr; vm_page_t nkpg; - pd_entry_t newpdir; + pd_entry_t *pde, newpdir; + pdp_entry_t newpdp; crit_enter(); if (kernel_vm_end == 0) { kernel_vm_end = KERNBASE; nkpt = 0; - while (pdir_pde(PTD, kernel_vm_end)) { + while ((*pmap_pde(&kernel_pmap, kernel_vm_end) & PG_V) != 0) { kernel_vm_end = (kernel_vm_end + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1); nkpt++; + if (kernel_vm_end - 1 >= kernel_map.max_offset) { + kernel_vm_end = kernel_map.max_offset; + break; + } } } - addr = (addr + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1); + addr = roundup2(addr, PAGE_SIZE * NPTEPG); + if (addr - 1 >= kernel_map.max_offset) + addr = kernel_map.max_offset; while (kernel_vm_end < addr) { - if (pdir_pde(PTD, kernel_vm_end)) { + pde = pmap_pde(&kernel_pmap, kernel_vm_end); + if (pde == NULL) { + /* We need a new PDP entry */ + nkpg = vm_page_alloc(kptobj, nkpt, + VM_ALLOC_NORMAL | VM_ALLOC_SYSTEM + | VM_ALLOC_INTERRUPT); + if (nkpg == NULL) + panic("pmap_growkernel: no memory to grow kernel"); + if ((nkpg->flags & PG_ZERO) == 0) + pmap_zero_page(nkpg); + paddr = VM_PAGE_TO_PHYS(nkpg); + newpdp = (pdp_entry_t) + (paddr | PG_V | PG_RW | PG_A | PG_M); + *pmap_pdpe(&kernel_pmap, kernel_vm_end) = newpdp; + continue; /* try again */ + } + if ((*pde & PG_V) != 0) { kernel_vm_end = (kernel_vm_end + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1); + if (kernel_vm_end - 1 >= kernel_map.max_offset) { + kernel_vm_end = kernel_map.max_offset; + break; + } continue; } /* * This index is bogus, but out of the way */ - nkpg = vm_page_alloc(kptobj, nkpt, + nkpg = vm_page_alloc(kptobj, nkpt, VM_ALLOC_NORMAL | VM_ALLOC_SYSTEM | VM_ALLOC_INTERRUPT); if (nkpg == NULL) panic("pmap_growkernel: no memory to grow kernel"); @@ -1539,18 +1957,14 @@ pmap_growkernel(vm_offset_t addr) ptppaddr = VM_PAGE_TO_PHYS(nkpg); pmap_zero_page(ptppaddr); newpdir = (pd_entry_t) (ptppaddr | PG_V | PG_RW | PG_A | PG_M); - pdir_pde(PTD, kernel_vm_end) = newpdir; *pmap_pde(&kernel_pmap, kernel_vm_end) = newpdir; nkpt++; - /* - * This update must be interlocked with pmap_pinit2. - */ - TAILQ_FOREACH(pmap, &pmap_list, pm_pmnode) { - *pmap_pde(pmap, kernel_vm_end) = newpdir; + kernel_vm_end = (kernel_vm_end + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1); + if (kernel_vm_end - 1 >= kernel_map.max_offset) { + kernel_vm_end = kernel_map.max_offset; + break; } - kernel_vm_end = (kernel_vm_end + PAGE_SIZE * NPTEPG) & - ~(PAGE_SIZE * NPTEPG - 1); } crit_exit(); } @@ -1562,6 +1976,7 @@ pmap_growkernel(vm_offset_t addr) */ void pmap_destroy(pmap_t pmap) +READY0 { int count; @@ -1580,6 +1995,7 @@ pmap_destroy(pmap_t pmap) */ void pmap_reference(pmap_t pmap) +READY2 { if (pmap != NULL) { pmap->pm_count++; @@ -1596,8 +2012,10 @@ pmap_reference(pmap_t pmap) */ static PMAP_INLINE void free_pv_entry(pv_entry_t pv) +READY2 { pv_entry_count--; + KKASSERT(pv_entry_count >= 0); zfree(pvzone, pv); } @@ -1607,13 +2025,14 @@ free_pv_entry(pv_entry_t pv) */ static pv_entry_t get_pv_entry(void) +READY2 { pv_entry_count++; if (pv_entry_high_water && - (pv_entry_count > pv_entry_high_water) && - (pmap_pagedaemon_waken == 0)) { + (pv_entry_count > pv_entry_high_water) && + (pmap_pagedaemon_waken == 0)) { pmap_pagedaemon_waken = 1; - wakeup (&vm_pages_needed); + wakeup(&vm_pages_needed); } return zalloc(pvzone); } @@ -1624,6 +2043,7 @@ get_pv_entry(void) */ void pmap_collect(void) +READY0 { int i; vm_page_t m; @@ -1631,7 +2051,6 @@ pmap_collect(void) if (pmap_pagedaemon_waken == 0) return; - pmap_pagedaemon_waken = 0; if (warningdone < 5) { kprintf("pmap_collect: collecting pv entries -- suggest increasing PMAP_SHPGPERPROC\n"); @@ -1645,6 +2064,7 @@ pmap_collect(void) continue; pmap_remove_all(m); } + pmap_pagedaemon_waken = 0; } @@ -1657,6 +2077,7 @@ pmap_collect(void) static int pmap_remove_entry(struct pmap *pmap, vm_page_t m, vm_offset_t va, pmap_inval_info_t info) +READY1 { pv_entry_t pv; int rtval; @@ -1675,9 +2096,11 @@ pmap_remove_entry(struct pmap *pmap, vm_page_t m, } rtval = 0; + /* JGXXX When can 'pv' be NULL? */ if (pv) { TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); m->md.pv_list_count--; + KKASSERT(m->md.pv_list_count >= 0); if (TAILQ_EMPTY(&m->md.pv_list)) vm_page_flag_clear(m, PG_MAPPED | PG_WRITEABLE); TAILQ_REMOVE(&pmap->pm_pvlist, pv, pv_plist); @@ -1695,6 +2118,7 @@ pmap_remove_entry(struct pmap *pmap, vm_page_t m, */ static void pmap_insert_entry(pmap_t pmap, vm_offset_t va, vm_page_t mpte, vm_page_t m) +READY1 { pv_entry_t pv; @@ -1717,6 +2141,7 @@ pmap_insert_entry(pmap_t pmap, vm_offset_t va, vm_page_t mpte, vm_page_t m) static int pmap_remove_pte(struct pmap *pmap, pt_entry_t *ptq, vm_offset_t va, pmap_inval_info_t info) +READY1 { pt_entry_t oldpte; vm_page_t m; @@ -1740,7 +2165,7 @@ pmap_remove_pte(struct pmap *pmap, pt_entry_t *ptq, vm_offset_t va, #if defined(PMAP_DIAGNOSTIC) if (pmap_nw_modified((pt_entry_t) oldpte)) { kprintf( - "pmap_remove: modified page not writable: va: 0x%x, pte: 0x%x\n", + "pmap_remove: modified page not writable: va: 0x%lx, pte: 0x%lx\n", va, oldpte); } #endif @@ -1767,19 +2192,16 @@ pmap_remove_pte(struct pmap *pmap, pt_entry_t *ptq, vm_offset_t va, */ static void pmap_remove_page(struct pmap *pmap, vm_offset_t va, pmap_inval_info_t info) +READY1 { - pt_entry_t *ptq; + pt_entry_t *pte; - /* - * if there is no pte for this address, just skip it!!! Otherwise - * get a local va for mappings for this pmap and remove the entry. - */ - if (*pmap_pde(pmap, va) != 0) { - ptq = get_ptbase(pmap) + amd64_btop(va); - if (*ptq) { - pmap_remove_pte(pmap, ptq, va, info); - } - } + pte = pmap_pte(pmap, va); + if (pte == NULL) + return; + if ((*pte & PG_V) == 0) + return; + pmap_remove_pte(pmap, pte, va, info); } /* @@ -1795,11 +2217,13 @@ pmap_remove_page(struct pmap *pmap, vm_offset_t va, pmap_inval_info_t info) */ void pmap_remove(struct pmap *pmap, vm_offset_t sva, vm_offset_t eva) +READY1 { - pt_entry_t *ptbase; - vm_offset_t pdnxt; - vm_offset_t ptpaddr; - vm_offset_t sindex, eindex; + vm_offset_t va_next; + pml4_entry_t *pml4e; + pdp_entry_t *pdpe; + pd_entry_t ptpaddr, *pde; + pt_entry_t *pte; struct pmap_inval_info info; if (pmap == NULL) @@ -1815,65 +2239,75 @@ pmap_remove(struct pmap *pmap, vm_offset_t sva, vm_offset_t eva) * common operation and easy to short circuit some * code. */ - if (((sva + PAGE_SIZE) == eva) && - ((pmap->pm_pdir[(sva >> PDRSHIFT)] & PG_PS) == 0)) { - pmap_remove_page(pmap, sva, &info); - pmap_inval_flush(&info); - return; + if (sva + PAGE_SIZE == eva) { + pde = pmap_pde(pmap, sva); + if (pde && (*pde & PG_PS) == 0) { + pmap_remove_page(pmap, sva, &info); + pmap_inval_flush(&info); + return; + } } - /* - * Get a local virtual address for the mappings that are being - * worked with. - */ - sindex = amd64_btop(sva); - eindex = amd64_btop(eva); + for (; sva < eva; sva = va_next) { + pml4e = pmap_pml4e(pmap, sva); + if ((*pml4e & PG_V) == 0) { + va_next = (sva + NBPML4) & ~PML4MASK; + if (va_next < sva) + va_next = eva; + continue; + } - for (; sindex < eindex; sindex = pdnxt) { - vm_pindex_t pdirindex; + pdpe = pmap_pml4e_to_pdpe(pml4e, sva); + if ((*pdpe & PG_V) == 0) { + va_next = (sva + NBPDP) & ~PDPMASK; + if (va_next < sva) + va_next = eva; + continue; + } /* * Calculate index for next page table. */ - pdnxt = ((sindex + NPTEPG) & ~(NPTEPG - 1)); - if (pmap->pm_stats.resident_count == 0) - break; + va_next = (sva + NBPDR) & ~PDRMASK; + if (va_next < sva) + va_next = eva; - pdirindex = sindex / NPDEPG; - if (((ptpaddr = pmap->pm_pdir[pdirindex]) & PG_PS) != 0) { - pmap_inval_add(&info, pmap, -1); - pmap->pm_pdir[pdirindex] = 0; - pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE; - continue; - } + pde = pmap_pdpe_to_pde(pdpe, sva); + ptpaddr = *pde; /* - * Weed out invalid mappings. Note: we assume that the page - * directory table is always allocated, and in kernel virtual. + * Weed out invalid mappings. */ if (ptpaddr == 0) continue; + /* + * Check for large page. + */ + if ((ptpaddr & PG_PS) != 0) { + /* JG FreeBSD has more complex treatment here */ + pmap_inval_add(&info, pmap, -1); + *pde = 0; + pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE; + continue; + } + /* * Limit our scan to either the end of the va represented * by the current page table page, or to the end of the * range being removed. */ - if (pdnxt > eindex) { - pdnxt = eindex; - } + if (va_next > eva) + va_next = eva; /* * NOTE: pmap_remove_pte() can block. */ - for (; sindex != pdnxt; sindex++) { - vm_offset_t va; - - ptbase = get_ptbase(pmap); - if (ptbase[sindex] == 0) + for (pte = pmap_pde_to_pte(pde, sva); sva != va_next; pte++, + sva += PAGE_SIZE) { + if (*pte == 0) continue; - va = amd64_ptob(sindex); - if (pmap_remove_pte(pmap, ptbase + sindex, va, &info)) + if (pmap_remove_pte(pmap, pte, sva, &info)) break; } } @@ -1891,6 +2325,7 @@ pmap_remove(struct pmap *pmap, vm_offset_t sva, vm_offset_t eva) static void pmap_remove_all(vm_page_t m) +READY1 { struct pmap_inval_info info; pt_entry_t *pte, tpte; @@ -1920,9 +2355,9 @@ pmap_remove_all(vm_page_t m) */ if (tpte & PG_M) { #if defined(PMAP_DIAGNOSTIC) - if (pmap_nw_modified((pt_entry_t) tpte)) { + if (pmap_nw_modified(tpte)) { kprintf( - "pmap_remove_all: modified page not writable: va: 0x%x, pte: 0x%x\n", + "pmap_remove_all: modified page not writable: va: 0x%lx, pte: 0x%lx\n", pv->pv_va, tpte); } #endif @@ -1933,6 +2368,7 @@ pmap_remove_all(vm_page_t m) TAILQ_REMOVE(&pv->pv_pmap->pm_pvlist, pv, pv_plist); ++pv->pv_pmap->pm_generation; m->md.pv_list_count--; + KKASSERT(m->md.pv_list_count >= 0); if (TAILQ_EMPTY(&m->md.pv_list)) vm_page_flag_clear(m, PG_MAPPED | PG_WRITEABLE); pmap_unuse_pt(pv->pv_pmap, pv->pv_va, pv->pv_ptem, &info); @@ -1954,12 +2390,17 @@ pmap_remove_all(vm_page_t m) */ void pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) +READY1 { - pt_entry_t *ptbase; - vm_offset_t pdnxt, ptpaddr; - vm_pindex_t sindex, eindex; + vm_offset_t va_next; + pml4_entry_t *pml4e; + pdp_entry_t *pdpe; + pd_entry_t ptpaddr, *pde; + pt_entry_t *pte; pmap_inval_info info; + /* JG review for NX */ + if (pmap == NULL) return; @@ -1973,21 +2414,37 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) pmap_inval_init(&info); - ptbase = get_ptbase(pmap); + for (; sva < eva; sva = va_next) { - sindex = amd64_btop(sva); - eindex = amd64_btop(eva); + pml4e = pmap_pml4e(pmap, sva); + if ((*pml4e & PG_V) == 0) { + va_next = (sva + NBPML4) & ~PML4MASK; + if (va_next < sva) + va_next = eva; + continue; + } - for (; sindex < eindex; sindex = pdnxt) { + pdpe = pmap_pml4e_to_pdpe(pml4e, sva); + if ((*pdpe & PG_V) == 0) { + va_next = (sva + NBPDP) & ~PDPMASK; + if (va_next < sva) + va_next = eva; + continue; + } - vm_pindex_t pdirindex; + va_next = (sva + NBPDR) & ~PDRMASK; + if (va_next < sva) + va_next = eva; - pdnxt = ((sindex + NPTEPG) & ~(NPTEPG - 1)); + pde = pmap_pdpe_to_pde(pdpe, sva); + ptpaddr = *pde; - pdirindex = sindex / NPDEPG; - if (((ptpaddr = pmap->pm_pdir[pdirindex]) & PG_PS) != 0) { + /* + * Check for large page. + */ + if ((ptpaddr & PG_PS) != 0) { pmap_inval_add(&info, pmap, -1); - pmap->pm_pdir[pdirindex] &= ~(PG_M|PG_RW); + *pde &= ~(PG_M|PG_RW); pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE; continue; } @@ -1999,13 +2456,12 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) if (ptpaddr == 0) continue; - if (pdnxt > eindex) { - pdnxt = eindex; - } + if (va_next > eva) + va_next = eva; - for (; sindex != pdnxt; sindex++) { - - pt_entry_t pbits; + for (pte = pmap_pde_to_pte(pde, sva); sva != va_next; pte++, + sva += PAGE_SIZE) { + pt_entry_t obits, pbits; vm_page_t m; /* @@ -2014,19 +2470,21 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) * ptbase[sindex] (or otherwise we have to do another * pmap_inval_add() call). */ - pmap_inval_add(&info, pmap, amd64_ptob(sindex)); - pbits = ptbase[sindex]; - + pmap_inval_add(&info, pmap, sva); + obits = pbits = *pte; + if ((pbits & PG_V) == 0) + continue; if (pbits & PG_MANAGED) { m = NULL; if (pbits & PG_A) { - m = PHYS_TO_VM_PAGE(pbits); + m = PHYS_TO_VM_PAGE(pbits & PG_FRAME); vm_page_flag_set(m, PG_REFERENCED); pbits &= ~PG_A; } if (pbits & PG_M) { - if (pmap_track_modified(amd64_ptob(sindex))) { + if (pmap_track_modified(sva)) { if (m == NULL) + KKASSERT(pbits == (pbits & PG_FRAME)); m = PHYS_TO_VM_PAGE(pbits); vm_page_dirty(m); pbits &= ~PG_M; @@ -2036,8 +2494,8 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) pbits &= ~PG_RW; - if (pbits != ptbase[sindex]) { - ptbase[sindex] = pbits; + if (pbits != obits) { + *pte = pbits; } } } @@ -2059,60 +2517,63 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) void pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, boolean_t wired) +READY1 { vm_paddr_t pa; + pd_entry_t *pde; pt_entry_t *pte; vm_paddr_t opa; - vm_offset_t origpte, newpte; + pt_entry_t origpte, newpte; vm_page_t mpte; pmap_inval_info info; if (pmap == NULL) return; - va &= PG_FRAME; + va = trunc_page(va); #ifdef PMAP_DIAGNOSTIC if (va >= KvaEnd) panic("pmap_enter: toobig"); if ((va >= UPT_MIN_ADDRESS) && (va < UPT_MAX_ADDRESS)) - panic("pmap_enter: invalid to pmap_enter page table pages (va: 0x%x)", va); + panic("pmap_enter: invalid to pmap_enter page table pages (va: 0x%lx)", va); #endif if (va < UPT_MAX_ADDRESS && pmap == &kernel_pmap) { kprintf("Warning: pmap_enter called on UVA with kernel_pmap\n"); - print_backtrace(); +#ifdef DDB + db_print_backtrace(); +#endif } if (va >= UPT_MAX_ADDRESS && pmap != &kernel_pmap) { kprintf("Warning: pmap_enter called on KVA without kernel_pmap\n"); - print_backtrace(); +#ifdef DDB + db_print_backtrace(); +#endif } /* * In the case that a page table page is not * resident, we are creating it here. */ - if (va < UPT_MIN_ADDRESS) + if (va < VM_MAX_USER_ADDRESS) mpte = pmap_allocpte(pmap, va); else mpte = NULL; pmap_inval_init(&info); - pte = pmap_pte(pmap, va); - - /* - * Page Directory table entry not valid, we need a new PT page - */ - if (pte == NULL) { - panic("pmap_enter: invalid page directory pdir=%x, va=0x%x\n", - pmap->pm_pdir[PTDPTDI], va); - } - - pa = VM_PAGE_TO_PHYS(m) & PG_FRAME; - origpte = *(vm_offset_t *)pte; + pde = pmap_pde(pmap, va); + if (pde != NULL && (*pde & PG_V) != 0) { + if ((*pde & PG_PS) != 0) + panic("pmap_enter: attempted pmap_enter on 2MB page"); + pte = pmap_pde_to_pte(pde, va); + } else + panic("pmap_enter: invalid page directory va=%#lx", va); + + KKASSERT(pte != NULL); + pa = VM_PAGE_TO_PHYS(m); + KKASSERT(pa == (pa & PG_FRAME)); + origpte = *pte; opa = origpte & PG_FRAME; - if (origpte & PG_PS) - panic("pmap_enter: attempted pmap_enter on 4MB page"); - /* * Mapping has not changed, must be protection or wiring change. */ @@ -2129,9 +2590,9 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, pmap->pm_stats.wired_count--; #if defined(PMAP_DIAGNOSTIC) - if (pmap_nw_modified((pt_entry_t) origpte)) { + if (pmap_nw_modified(origpte)) { kprintf( - "pmap_enter: modified page not writable: va: 0x%x, pte: 0x%x\n", + "pmap_enter: modified page not writable: va: 0x%lx, pte: 0x%lx\n", va, origpte); } #endif @@ -2168,7 +2629,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, int err; err = pmap_remove_pte(pmap, pte, va, &info); if (err) - panic("pmap_enter: pte vanished, va: 0x%x", va); + panic("pmap_enter: pte vanished, va: 0x%lx", va); } /* @@ -2194,11 +2655,11 @@ validate: /* * Now validate mapping with desired protection/wiring. */ - newpte = (vm_offset_t) (pa | pte_prot(pmap, prot) | PG_V); + newpte = (pt_entry_t) (pa | pte_prot(pmap, prot) | PG_V); if (wired) newpte |= PG_W; - if (va < UPT_MIN_ADDRESS) + if (va < VM_MAX_USER_ADDRESS) newpte |= PG_U; if (pmap == &kernel_pmap) newpte |= pgeflag; @@ -2226,23 +2687,28 @@ validate: */ static void pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m) +READY1 { pt_entry_t *pte; vm_paddr_t pa; vm_page_t mpte; vm_pindex_t ptepindex; - vm_offset_t ptepa; + pd_entry_t *ptepa; pmap_inval_info info; pmap_inval_init(&info); if (va < UPT_MAX_ADDRESS && pmap == &kernel_pmap) { kprintf("Warning: pmap_enter_quick called on UVA with kernel_pmap\n"); - print_backtrace(); +#ifdef DDB + db_print_backtrace(); +#endif } if (va >= UPT_MAX_ADDRESS && pmap != &kernel_pmap) { kprintf("Warning: pmap_enter_quick called on KVA without kernel_pmap\n"); - print_backtrace(); +#ifdef DDB + db_print_backtrace(); +#endif } KKASSERT(va < UPT_MIN_ADDRESS); /* assert used on user pmaps only */ @@ -2253,32 +2719,32 @@ pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m) * A held page table page (mpte), or NULL, is passed onto the * section following. */ - if (va < UPT_MIN_ADDRESS) { + if (va < VM_MAX_USER_ADDRESS) { /* * Calculate pagetable page index */ - ptepindex = va >> PDRSHIFT; + ptepindex = pmap_pde_pindex(va); do { /* * Get the page directory entry */ - ptepa = (vm_offset_t) pmap->pm_pdir[ptepindex]; + ptepa = pmap_pde(pmap, va); /* * If the page table page is mapped, we just increment * the hold count, and activate it. */ - if (ptepa) { - if (ptepa & PG_PS) - panic("pmap_enter_quick: unexpected mapping into 4MB page"); - if (pmap->pm_ptphint && - (pmap->pm_ptphint->pindex == ptepindex)) { - mpte = pmap->pm_ptphint; - } else { + if (ptepa && (*ptepa & PG_V) != 0) { + if (*ptepa & PG_PS) + panic("pmap_enter_quick: unexpected mapping into 2MB page"); +// if (pmap->pm_ptphint && +// (pmap->pm_ptphint->pindex == ptepindex)) { +// mpte = pmap->pm_ptphint; +// } else { mpte = pmap_page_lookup( pmap->pm_pteobj, ptepindex); pmap->pm_ptphint = mpte; - } +// } if (mpte) mpte->hold_count++; } else { @@ -2298,7 +2764,7 @@ pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m) pte = vtopte(va); if (*pte & PG_V) { if (mpte) - pmap_unwire_pte_hold(pmap, mpte, &info); + pmap_unwire_pte_hold(pmap, va, mpte, &info); pa = VM_PAGE_TO_PHYS(m); KKASSERT(((*pte ^ pa) & PG_FRAME) == 0); return; @@ -2334,8 +2800,10 @@ pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m) * Make a temporary mapping for a physical address. This is only intended * to be used for panic dumps. */ +/* JG Needed on amd64? */ void * pmap_kenter_temporary(vm_paddr_t pa, int i) +READY2 { pmap_kenter((vm_offset_t)crashdumpmap + (i * PAGE_SIZE), pa); return ((void *)crashdumpmap); @@ -2354,10 +2822,11 @@ void pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_prot_t prot, vm_object_t object, vm_pindex_t pindex, vm_size_t size, int limit) +READY1 { struct rb_vm_page_scan_info info; struct lwp *lp; - int psize; + vm_size_t psize; /* * We can't preinit if read access isn't set or there is no pmap @@ -2413,6 +2882,7 @@ pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_prot_t prot, static int pmap_object_init_pt_callback(vm_page_t p, void *data) +READY1 { struct rb_vm_page_scan_info *info = data; vm_pindex_t rel_index; @@ -2455,6 +2925,7 @@ static int pmap_prefault_pageorder[] = { void pmap_prefault(pmap_t pmap, vm_offset_t addra, vm_map_entry_t entry) +READY0 { int i; vm_offset_t starta; @@ -2550,6 +3021,7 @@ pmap_prefault(pmap_t pmap, vm_offset_t addra, vm_map_entry_t entry) */ void pmap_change_wiring(pmap_t pmap, vm_offset_t va, boolean_t wired) +READY0 { pt_entry_t *pte; @@ -2595,6 +3067,7 @@ pmap_change_wiring(pmap_t pmap, vm_offset_t va, boolean_t wired) void pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len, vm_offset_t src_addr) +READY0 { pmap_inval_info info; vm_offset_t addr; @@ -2614,6 +3087,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, */ return; +#if JGPMAP32 src_frame = src_pmap->pm_pdir[PTDPTDI] & PG_FRAME; if (src_frame != (PTDpde & PG_FRAME)) { return; @@ -2625,6 +3099,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, /* The page directory is not shared between CPUs */ cpu_invltlb(); } +#endif pmap_inval_init(&info); pmap_inval_add(&info, dst_pmap, -1); pmap_inval_add(&info, src_pmap, -1); @@ -2656,15 +3131,19 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, pdnxt = ((addr + PAGE_SIZE*NPTEPG) & ~(PAGE_SIZE*NPTEPG - 1)); ptepindex = addr >> PDRSHIFT; +#if JGPMAP32 srcptepaddr = (vm_offset_t) src_pmap->pm_pdir[ptepindex]; +#endif if (srcptepaddr == 0) continue; if (srcptepaddr & PG_PS) { +#if JGPMAP32 if (dst_pmap->pm_pdir[ptepindex] == 0) { dst_pmap->pm_pdir[ptepindex] = (pd_entry_t) srcptepaddr; dst_pmap->pm_stats.resident_count += NBPDR / PAGE_SIZE; } +#endif continue; } @@ -2678,7 +3157,9 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, pdnxt = end_addr; src_pte = vtopte(addr); +#if JGPMAP32 dst_pte = avtopte(addr); +#endif while (addr < pdnxt) { pt_entry_t ptetemp; @@ -2697,6 +3178,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, */ dstmpte = pmap_allocpte(dst_pmap, addr); +#if JGPMAP32 if (src_frame != (PTDpde & PG_FRAME) || dst_frame != (APTDpde & PG_FRAME) ) { @@ -2722,6 +3204,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, pmap_unwire_pte_hold(dst_pmap, dstmpte, &info); goto failed; } +#endif if (dstmpte->hold_count >= srcmpte->hold_count) break; } @@ -2738,32 +3221,18 @@ failed: /* * pmap_zero_page: * - * Zero the specified PA by mapping the page into KVM and clearing its - * contents. + * Zero the specified physical page. * * This function may be called from an interrupt and no locking is * required. */ void pmap_zero_page(vm_paddr_t phys) +READY1 { - struct mdglobaldata *gd = mdcpu; + vm_offset_t va = PHYS_TO_DMAP(phys); - crit_enter(); - if (*gd->gd_CMAP3) - panic("pmap_zero_page: CMAP3 busy"); - *gd->gd_CMAP3 = - PG_V | PG_RW | (phys & PG_FRAME) | PG_A | PG_M; - cpu_invlpg(gd->gd_CADDR3); - -#if defined(I686_CPU) - if (cpu_class == CPUCLASS_686) - i686_pagezero(gd->gd_CADDR3); - else -#endif - bzero(gd->gd_CADDR3, PAGE_SIZE); - *gd->gd_CMAP3 = 0; - crit_exit(); + pagezero((void *)va); } /* @@ -2773,23 +3242,20 @@ pmap_zero_page(vm_paddr_t phys) */ void pmap_page_assertzero(vm_paddr_t phys) +READY1 { struct mdglobaldata *gd = mdcpu; int i; crit_enter(); - if (*gd->gd_CMAP3) - panic("pmap_zero_page: CMAP3 busy"); - *gd->gd_CMAP3 = - PG_V | PG_RW | (phys & PG_FRAME) | PG_A | PG_M; - cpu_invlpg(gd->gd_CADDR3); + vm_offset_t virt = PHYS_TO_DMAP(phys); + for (i = 0; i < PAGE_SIZE; i += sizeof(int)) { - if (*(int *)((char *)gd->gd_CADDR3 + i) != 0) { + if (*(int *)((char *)virt + i) != 0) { panic("pmap_page_assertzero() @ %p not zero!\n", - (void *)gd->gd_CADDR3); + (void *)virt); } } - *gd->gd_CMAP3 = 0; crit_exit(); } @@ -2803,22 +3269,13 @@ pmap_page_assertzero(vm_paddr_t phys) */ void pmap_zero_page_area(vm_paddr_t phys, int off, int size) +READY1 { struct mdglobaldata *gd = mdcpu; crit_enter(); - if (*gd->gd_CMAP3) - panic("pmap_zero_page: CMAP3 busy"); - *gd->gd_CMAP3 = PG_V | PG_RW | (phys & PG_FRAME) | PG_A | PG_M; - cpu_invlpg(gd->gd_CADDR3); - -#if defined(I686_CPU) - if (cpu_class == CPUCLASS_686 && off == 0 && size == PAGE_SIZE) - i686_pagezero(gd->gd_CADDR3); - else -#endif - bzero((char *)gd->gd_CADDR3 + off, size); - *gd->gd_CMAP3 = 0; + vm_offset_t virt = PHYS_TO_DMAP(phys); + bzero((char *)virt + off, size); crit_exit(); } @@ -2831,25 +3288,14 @@ pmap_zero_page_area(vm_paddr_t phys, int off, int size) */ void pmap_copy_page(vm_paddr_t src, vm_paddr_t dst) +READY1 { - struct mdglobaldata *gd = mdcpu; + vm_offset_t src_virt, dst_virt; crit_enter(); - if (*gd->gd_CMAP1) - panic("pmap_copy_page: CMAP1 busy"); - if (*gd->gd_CMAP2) - panic("pmap_copy_page: CMAP2 busy"); - - *gd->gd_CMAP1 = PG_V | (src & PG_FRAME) | PG_A; - *gd->gd_CMAP2 = PG_V | PG_RW | (dst & PG_FRAME) | PG_A | PG_M; - - cpu_invlpg(gd->gd_CADDR1); - cpu_invlpg(gd->gd_CADDR2); - - bcopy(gd->gd_CADDR1, gd->gd_CADDR2, PAGE_SIZE); - - *gd->gd_CMAP1 = 0; - *gd->gd_CMAP2 = 0; + src_virt = PHYS_TO_DMAP(src); + dst_virt = PHYS_TO_DMAP(dst); + bcopy(src_virt, dst_virt, PAGE_SIZE); crit_exit(); } @@ -2862,27 +3308,16 @@ pmap_copy_page(vm_paddr_t src, vm_paddr_t dst) */ void pmap_copy_page_frag(vm_paddr_t src, vm_paddr_t dst, size_t bytes) +READY1 { - struct mdglobaldata *gd = mdcpu; + vm_offset_t src_virt, dst_virt; crit_enter(); - if (*gd->gd_CMAP1) - panic("pmap_copy_page: CMAP1 busy"); - if (*gd->gd_CMAP2) - panic("pmap_copy_page: CMAP2 busy"); - - *gd->gd_CMAP1 = PG_V | (src & PG_FRAME) | PG_A; - *gd->gd_CMAP2 = PG_V | PG_RW | (dst & PG_FRAME) | PG_A | PG_M; - - cpu_invlpg(gd->gd_CADDR1); - cpu_invlpg(gd->gd_CADDR2); - - bcopy((char *)gd->gd_CADDR1 + (src & PAGE_MASK), - (char *)gd->gd_CADDR2 + (dst & PAGE_MASK), + src_virt = PHYS_TO_DMAP(src); + dst_virt = PHYS_TO_DMAP(dst); + bcopy((char *)src_virt + (src & PAGE_MASK), + (char *)dst_virt + (dst & PAGE_MASK), bytes); - - *gd->gd_CMAP1 = 0; - *gd->gd_CMAP2 = 0; crit_exit(); } @@ -2895,6 +3330,7 @@ pmap_copy_page_frag(vm_paddr_t src, vm_paddr_t dst, size_t bytes) */ boolean_t pmap_page_exists_quick(pmap_t pmap, vm_page_t m) +READY2 { pv_entry_t pv; int loops = 0; @@ -2927,6 +3363,7 @@ pmap_page_exists_quick(pmap_t pmap, vm_page_t m) */ void pmap_remove_pages(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) +READY1 { struct lwp *lp; pt_entry_t *pte, tpte; @@ -2934,7 +3371,7 @@ pmap_remove_pages(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) vm_page_t m; pmap_inval_info info; int iscurrentpmap; - int32_t save_generation; + int save_generation; lp = curthread->td_lwp; if (lp && pmap == vmspace_pmap(lp->lwp_vmspace)) @@ -2969,10 +3406,10 @@ pmap_remove_pages(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) } tpte = pte_load_clear(pte); - m = PHYS_TO_VM_PAGE(tpte); + m = PHYS_TO_VM_PAGE(tpte & PG_FRAME); KASSERT(m < &vm_page_array[vm_page_array_size], - ("pmap_remove_pages: bad tpte %x", tpte)); + ("pmap_remove_pages: bad tpte %lx", tpte)); KKASSERT(pmap->pm_stats.resident_count > 0); --pmap->pm_stats.resident_count; @@ -3016,6 +3453,7 @@ pmap_remove_pages(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) */ static boolean_t pmap_testbit(vm_page_t m, int bit) +READY1 { pv_entry_t pv; pt_entry_t *pte; @@ -3040,8 +3478,8 @@ pmap_testbit(vm_page_t m, int bit) } #if defined(PMAP_DIAGNOSTIC) - if (!pv->pv_pmap) { - kprintf("Null pmap (tb) at va: 0x%x\n", pv->pv_va); + if (pv->pv_pmap == NULL) { + kprintf("Null pmap (tb) at va: 0x%lx\n", pv->pv_va); continue; } #endif @@ -3060,6 +3498,7 @@ pmap_testbit(vm_page_t m, int bit) */ static __inline void pmap_clearbit(vm_page_t m, int bit) +READY1 { struct pmap_inval_info info; pv_entry_t pv; @@ -3086,8 +3525,8 @@ pmap_clearbit(vm_page_t m, int bit) } #if defined(PMAP_DIAGNOSTIC) - if (!pv->pv_pmap) { - kprintf("Null pmap (cb) at va: 0x%x\n", pv->pv_va); + if (pv->pv_pmap == NULL) { + kprintf("Null pmap (cb) at va: 0x%lx\n", pv->pv_va); continue; } #endif @@ -3111,14 +3550,14 @@ again: if (bit == PG_RW) { if (pbits & PG_M) { vm_page_dirty(m); - atomic_clear_int(pte, PG_M|PG_RW); + atomic_clear_long(pte, PG_M|PG_RW); } else { /* * The cpu may be trying to set PG_M * simultaniously with our clearing * of PG_RW. */ - if (!atomic_cmpset_int(pte, pbits, + if (!atomic_cmpset_long(pte, pbits, pbits & ~PG_RW)) goto again; } @@ -3131,9 +3570,9 @@ again: * when they clear the VPTE_M bit in their * virtual page tables. */ - atomic_clear_int(pte, PG_M); + atomic_clear_long(pte, PG_M); } else { - atomic_clear_int(pte, bit); + atomic_clear_long(pte, bit); } } } @@ -3148,7 +3587,9 @@ again: */ void pmap_page_protect(vm_page_t m, vm_prot_t prot) +READY1 { + /* JG NX support? */ if ((prot & VM_PROT_WRITE) == 0) { if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { pmap_clearbit(m, PG_RW); @@ -3161,6 +3602,7 @@ pmap_page_protect(vm_page_t m, vm_prot_t prot) vm_paddr_t pmap_phys_address(vm_pindex_t ppn) +READY2 { return (amd64_ptob(ppn)); } @@ -3179,6 +3621,7 @@ pmap_phys_address(vm_pindex_t ppn) */ int pmap_ts_referenced(vm_page_t m) +READY1 { pv_entry_t pv, pvf, pvn; pt_entry_t *pte; @@ -3207,9 +3650,9 @@ pmap_ts_referenced(vm_page_t m) if (pte && (*pte & PG_A)) { #ifdef SMP - atomic_clear_int(pte, PG_A); + atomic_clear_long(pte, PG_A); #else - atomic_clear_int_nonlocked(pte, PG_A); + atomic_clear_long_nonlocked(pte, PG_A); #endif rtval++; if (rtval > 4) { @@ -3231,6 +3674,7 @@ pmap_ts_referenced(vm_page_t m) */ boolean_t pmap_is_modified(vm_page_t m) +READY2 { return pmap_testbit(m, PG_M); } @@ -3240,6 +3684,7 @@ pmap_is_modified(vm_page_t m) */ void pmap_clear_modify(vm_page_t m) +READY2 { pmap_clearbit(m, PG_M); } @@ -3251,6 +3696,7 @@ pmap_clear_modify(vm_page_t m) */ void pmap_clear_reference(vm_page_t m) +READY2 { pmap_clearbit(m, PG_A); } @@ -3261,9 +3707,11 @@ pmap_clear_reference(vm_page_t m) static void i386_protection_init(void) +READY0 { int *kp, prot; + /* JG NX support may go here; No VM_PROT_EXECUTE ==> set NX bit */ kp = protection_codes; for (prot = 0; prot < 8; prot++) { switch (prot) { @@ -3298,6 +3746,7 @@ i386_protection_init(void) */ void * pmap_mapdev(vm_paddr_t pa, vm_size_t size) +READY1 { vm_offset_t va, tmpva, offset; pt_entry_t *pte; @@ -3306,10 +3755,10 @@ pmap_mapdev(vm_paddr_t pa, vm_size_t size) size = roundup(offset + size, PAGE_SIZE); va = kmem_alloc_nofault(&kernel_map, size); - if (!va) + if (va == 0) panic("pmap_mapdev: Couldn't alloc kernel virtual memory"); - pa = pa & PG_FRAME; + pa = pa & ~PAGE_MASK; for (tmpva = va; size > 0;) { pte = vtopte(tmpva); *pte = pa | PG_RW | PG_V; /* | pgeflag; */ @@ -3325,10 +3774,11 @@ pmap_mapdev(vm_paddr_t pa, vm_size_t size) void pmap_unmapdev(vm_offset_t va, vm_size_t size) +READY1 { vm_offset_t base, offset; - base = va & PG_FRAME; + base = va & ~PAGE_MASK; offset = va & PAGE_MASK; size = roundup(offset + size, PAGE_SIZE); pmap_qremove(va, size >> PAGE_SHIFT); @@ -3340,6 +3790,7 @@ pmap_unmapdev(vm_offset_t va, vm_size_t size) */ int pmap_mincore(pmap_t pmap, vm_offset_t addr) +READY0 { pt_entry_t *ptep, pte; vm_page_t m; @@ -3397,6 +3848,7 @@ pmap_mincore(pmap_t pmap, vm_offset_t addr) */ void pmap_replacevm(struct proc *p, struct vmspace *newvm, int adjrefs) +READY2 { struct vmspace *oldvm; struct lwp *lp; @@ -3423,6 +3875,7 @@ pmap_replacevm(struct proc *p, struct vmspace *newvm, int adjrefs) */ void pmap_setlwpvm(struct lwp *lp, struct vmspace *newvm) +READY1 { struct vmspace *oldvm; struct pmap *pmap; @@ -3442,10 +3895,8 @@ pmap_setlwpvm(struct lwp *lp, struct vmspace *newvm) #if defined(SWTCH_OPTIM_STATS) tlb_flush_count++; #endif - curthread->td_pcb->pcb_cr3 = vtophys(pmap->pm_pdir); - curthread->td_pcb->pcb_cr3 |= PG_RW | PG_U | PG_V; - *link_pdpe = curthread->td_pcb->pcb_cr3 | PG_RW | PG_U | PG_V; - load_cr3(common_lvl4_phys); + curthread->td_pcb->pcb_cr3 = vtophys(pmap->pm_pml4); + load_cr3(curthread->td_pcb->pcb_cr3); pmap = vmspace_pmap(oldvm); #if defined(SMP) atomic_clear_int(&pmap->pm_active, @@ -3460,6 +3911,7 @@ pmap_setlwpvm(struct lwp *lp, struct vmspace *newvm) vm_offset_t pmap_addr_hint(vm_object_t obj, vm_offset_t addr, vm_size_t size) +READY0 { if ((obj == NULL) || (size < NBPDR) || (obj->type != OBJT_DEVICE)) { @@ -3479,6 +3931,7 @@ void pmap_pvdump (vm_paddr_t pa); /* print address space of pmap*/ static void pads(pmap_t pm) +READY0 { vm_offset_t va; unsigned i, j; @@ -3488,6 +3941,7 @@ pads(pmap_t pm) return; crit_enter(); for (i = 0; i < NPDEPG; i++) { +#if JGPMAP32 if (pm->pm_pdir[i]) { for (j = 0; j < NPTEPG; j++) { va = (i << PDRSHIFT) + (j << PAGE_SHIFT); @@ -3500,6 +3954,7 @@ pads(pmap_t pm) kprintf("%lx:%lx ", va, *ptep); }; } +#endif } crit_exit(); @@ -3507,6 +3962,7 @@ pads(pmap_t pm) void pmap_pvdump(vm_paddr_t pa) +READY0 { pv_entry_t pv; vm_page_t m; diff --git a/sys/platform/pc64/amd64/support.s b/sys/platform/pc64/amd64/support.s index 6995903682..8c61fb0463 100644 --- a/sys/platform/pc64/amd64/support.s +++ b/sys/platform/pc64/amd64/support.s @@ -248,12 +248,12 @@ ENTRY(copyout) addq %rdx,%rax jc copyout_fault /* - * XXX STOP USING VM_MAXUSER_ADDRESS. + * XXX STOP USING VM_MAX_USER_ADDRESS. * It is an end address, not a max, so every time it is used correctly it * looks like there is an off by one error, and of course it caused an off * by one error in several places. */ - movq $VM_MAXUSER_ADDRESS,%rcx + movq $VM_MAX_USER_ADDRESS,%rcx cmpq %rcx,%rax ja copyout_fault @@ -302,7 +302,7 @@ ENTRY(copyin) movq %rdi,%rax addq %rdx,%rax jc copyin_fault - movq $VM_MAXUSER_ADDRESS,%rcx + movq $VM_MAX_USER_ADDRESS,%rcx cmpq %rcx,%rax ja copyin_fault @@ -342,7 +342,7 @@ ENTRY(casuword32) movq TD_PCB(%rcx), %rcx movq $fusufault,PCB_ONFAULT(%rcx) - movq $VM_MAXUSER_ADDRESS-4,%rax + movq $VM_MAX_USER_ADDRESS-4,%rax cmpq %rax,%rdi /* verify address is valid */ ja fusufault @@ -372,7 +372,7 @@ ENTRY(casuword) movq TD_PCB(%rcx), %rcx movq $fusufault,PCB_ONFAULT(%rcx) - movq $VM_MAXUSER_ADDRESS-4,%rax + movq $VM_MAX_USER_ADDRESS-4,%rax cmpq %rax,%rdi /* verify address is valid */ ja fusufault @@ -406,7 +406,7 @@ ENTRY(fuword) movq TD_PCB(%rcx), %rcx movq $fusufault,PCB_ONFAULT(%rcx) - movq $VM_MAXUSER_ADDRESS-8,%rax + movq $VM_MAX_USER_ADDRESS-8,%rax cmpq %rax,%rdi /* verify address is valid */ ja fusufault @@ -419,7 +419,7 @@ ENTRY(fuword32) movq TD_PCB(%rcx), %rcx movq $fusufault,PCB_ONFAULT(%rcx) - movq $VM_MAXUSER_ADDRESS-4,%rax + movq $VM_MAX_USER_ADDRESS-4,%rax cmpq %rax,%rdi /* verify address is valid */ ja fusufault @@ -444,7 +444,7 @@ ENTRY(fuword16) movq TD_PCB(%rcx), %rcx movq $fusufault,PCB_ONFAULT(%rcx) - movq $VM_MAXUSER_ADDRESS-2,%rax + movq $VM_MAX_USER_ADDRESS-2,%rax cmpq %rax,%rdi ja fusufault @@ -457,7 +457,7 @@ ENTRY(fubyte) movq TD_PCB(%rcx), %rcx movq $fusufault,PCB_ONFAULT(%rcx) - movq $VM_MAXUSER_ADDRESS-1,%rax + movq $VM_MAX_USER_ADDRESS-1,%rax cmpq %rax,%rdi ja fusufault @@ -485,7 +485,7 @@ ENTRY(suword) movq TD_PCB(%rcx), %rcx movq $fusufault,PCB_ONFAULT(%rcx) - movq $VM_MAXUSER_ADDRESS-8,%rax + movq $VM_MAX_USER_ADDRESS-8,%rax cmpq %rax,%rdi /* verify address validity */ ja fusufault @@ -501,7 +501,7 @@ ENTRY(suword32) movq TD_PCB(%rcx), %rcx movq $fusufault,PCB_ONFAULT(%rcx) - movq $VM_MAXUSER_ADDRESS-4,%rax + movq $VM_MAX_USER_ADDRESS-4,%rax cmpq %rax,%rdi /* verify address validity */ ja fusufault @@ -517,7 +517,7 @@ ENTRY(suword16) movq TD_PCB(%rcx), %rcx movq $fusufault,PCB_ONFAULT(%rcx) - movq $VM_MAXUSER_ADDRESS-2,%rax + movq $VM_MAX_USER_ADDRESS-2,%rax cmpq %rax,%rdi /* verify address validity */ ja fusufault @@ -533,7 +533,7 @@ ENTRY(subyte) movq TD_PCB(%rcx), %rcx movq $fusufault,PCB_ONFAULT(%rcx) - movq $VM_MAXUSER_ADDRESS-1,%rax + movq $VM_MAX_USER_ADDRESS-1,%rax cmpq %rax,%rdi /* verify address validity */ ja fusufault @@ -562,13 +562,13 @@ ENTRY(copyinstr) movq TD_PCB(%rcx), %rcx movq $cpystrflt,PCB_ONFAULT(%rcx) - movq $VM_MAXUSER_ADDRESS,%rax + movq $VM_MAX_USER_ADDRESS,%rax /* make sure 'from' is within bounds */ subq %rsi,%rax jbe cpystrflt - /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */ + /* restrict maxlen to <= VM_MAX_USER_ADDRESS-from */ cmpq %rdx,%rax jae 1f movq %rax,%rdx @@ -592,7 +592,7 @@ ENTRY(copyinstr) jmp cpystrflt_x 3: /* rdx is zero - return ENAMETOOLONG or EFAULT */ - movq $VM_MAXUSER_ADDRESS,%rax + movq $VM_MAX_USER_ADDRESS,%rax cmpq %rax,%rsi jae cpystrflt 4: diff --git a/sys/platform/pc64/amd64/swtch.s b/sys/platform/pc64/amd64/swtch.s index 2b10dd68c3..f25bdd9cc3 100644 --- a/sys/platform/pc64/amd64/swtch.s +++ b/sys/platform/pc64/amd64/swtch.s @@ -225,21 +225,13 @@ ENTRY(cpu_exit_switch) /* * Get us out of the vmspace */ -#if JG + movq KPML4phys,%rcx movq %cr3,%rax cmpq %rcx,%rax je 1f /* JG no increment of statistics counters? see cpu_heavy_restore */ movq %rcx,%cr3 1: -#else - movq IdlePTD, %rcx - orq $(PG_RW|PG_V), %rcx - movq link_pdpe,%r12 - movq %rcx, (%r12) - movq %cr3, %rcx - movq %rcx, %cr3 -#endif movq PCPU(curthread),%rbx /* @@ -317,8 +309,6 @@ ENTRY(cpu_heavy_restore) * YYY which naturally also means that the PM_ACTIVE bit had better * already have been set before we set it above, check? YYY */ -#if JG -#error x movq %cr3,%rsi movq PCB_CR3(%rdx),%rcx cmpq %rsi,%rcx @@ -329,15 +319,6 @@ ENTRY(cpu_heavy_restore) #endif movq %rcx,%cr3 4: -#else - movq PCB_CR3(%rdx),%rcx - orq $(PG_RW|PG_U|PG_V), %rcx - /*XXX*/ - movq link_pdpe,%r12 - movq %rcx, (%r12) - movq %cr3, %rcx - movq %rcx, %cr3 -#endif /* * Clear TDF_RUNNING flag in old thread only after cleaning up * %cr3. The target thread is already protected by being TDF_RUNQ @@ -513,13 +494,6 @@ ENTRY(savectx) movq %rax,PCB_RIP(%rcx) movq %cr3,%rax -#ifndef JG - movq (%rax), %rax - movq $0x000ffffffffff000, %rcx - andq %rcx, %rax - movq (%rax), %rax - andq %rcx, %rax -#endif movq %rax,PCB_CR3(%rcx) movq %rbx,PCB_RBX(%rcx) @@ -590,15 +564,11 @@ ENTRY(savectx) */ ENTRY(cpu_idle_restore) /* cli */ - movq IdlePTD,%rcx + movq KPML4phys,%rcx /* JG xor? */ movl $0,%ebp /* JG push RBP? */ pushq $0 - orq $(PG_RW|PG_V), %rcx - movq link_pdpe,%r12 - movq %rcx, (%r12) - movq %cr3, %rcx movq %rcx,%cr3 andl $~TDF_RUNNING,TD_FLAGS(%rbx) orl $TDF_RUNNING,TD_FLAGS(%rax) @@ -628,14 +598,10 @@ ENTRY(cpu_idle_restore) */ ENTRY(cpu_kthread_restore) sti - movq IdlePTD,%rcx + movq KPML4phys,%rcx movq TD_PCB(%rax),%rdx /* JG "movq $0, %rbp"? "xorq %rbp, %rbp"? */ movl $0,%ebp - orq $(PG_RW|PG_V), %rcx - movq link_pdpe,%r12 - movq %rcx, (%r12) - movq %cr3, %rcx movq %rcx,%cr3 /* rax and rbx come from the switchout code */ andl $~TDF_RUNNING,TD_FLAGS(%rbx) @@ -718,22 +684,12 @@ ENTRY(cpu_lwkt_switch) * deleted due to a process exiting. */ ENTRY(cpu_lwkt_restore) -#if JG - movq common_lvl4_phys,%rcx /* YYY borrow but beware desched/cpuchg/exit */ -#endif - movq IdlePTD, %rcx - orq $(PG_RW|PG_V), %rcx - movq link_pdpe,%r12 - movq %rcx, (%r12) - movq %cr3, %rcx - movq %rcx, %cr3 -#if JG + movq KPML4phys,%rcx /* YYY borrow but beware desched/cpuchg/exit */ movq %cr3,%rdx cmpq %rcx,%rdx je 1f movq %rcx,%cr3 1: -#endif andl $~TDF_RUNNING,TD_FLAGS(%rbx) orl $TDF_RUNNING,TD_FLAGS(%rax) popfq diff --git a/sys/platform/pc64/amd64/vm_machdep.c b/sys/platform/pc64/amd64/vm_machdep.c index a1a907d8f8..c9b4d16e8d 100644 --- a/sys/platform/pc64/amd64/vm_machdep.c +++ b/sys/platform/pc64/amd64/vm_machdep.c @@ -141,7 +141,7 @@ cpu_fork(struct lwp *lp1, struct lwp *lp2, int flags) * Set registers for trampoline to user mode. Leave space for the * return address on stack. These are the kernel mode register values. */ - pcb2->pcb_cr3 = vtophys(vmspace_pmap(lp2->lwp_proc->p_vmspace)->pm_pdir); + pcb2->pcb_cr3 = vtophys(vmspace_pmap(lp2->lwp_proc->p_vmspace)->pm_pml4); pcb2->pcb_cr3 |= PG_RW | PG_U | PG_V; pcb2->pcb_rbx = (unsigned long)fork_return; /* fork_trampoline argument */ pcb2->pcb_rbp = 0; @@ -234,10 +234,11 @@ void cpu_lwp_exit(void) { struct thread *td = curthread; - struct pcb *pcb = td->td_pcb; + struct pcb *pcb; #if NNPX > 0 npxexit(); #endif /* NNPX */ + pcb = td->td_pcb; KKASSERT(pcb->pcb_ext == NULL); /* Some i386 functionality was dropped */ if (pcb->pcb_flags & PCB_DBREGS) { /* diff --git a/sys/platform/pc64/conf/files b/sys/platform/pc64/conf/files index 671ad07ef6..dce96ad991 100644 --- a/sys/platform/pc64/conf/files +++ b/sys/platform/pc64/conf/files @@ -31,16 +31,6 @@ ukbdmap.h optional ukbd_dflt_keymap \ no-obj no-implicit-rule before-depend \ clean "ukbdmap.h" # -hal.o optional ath_hal \ - dependency "$S/contrib/dev/ath/public/amd64-elf.hal.o.uu" \ - compile-with "uudecode < $S/contrib/dev/ath/public/amd64-elf.hal.o.uu" \ - no-implicit-rule -opt_ah.h optional ath_hal \ - dependency "$S/contrib/dev/ath/public/amd64-elf.opt_ah.h" \ - compile-with "rm -f opt_ah.h; cp $S/contrib/dev/ath/public/amd64-elf.opt_ah.h opt_ah.h" \ - no-obj no-implicit-rule before-depend \ - clean "opt_ah.h" -# emulation/linux/linux_file.c optional compat_linux32 emulation/linux/linux_getcwd.c optional compat_linux32 emulation/linux/linux_ioctl.c optional compat_linux32 diff --git a/sys/platform/pc64/conf/kern.mk b/sys/platform/pc64/conf/kern.mk index 6cae74924c..175a7f9f7d 100644 --- a/sys/platform/pc64/conf/kern.mk +++ b/sys/platform/pc64/conf/kern.mk @@ -9,7 +9,7 @@ # reserved for user applications. # CFLAGS+= -mpreferred-stack-boundary=4 -CFLAGS+= -mcmodel=small -mno-red-zone \ +CFLAGS+= -mcmodel=kernel -mno-red-zone \ -mfpmath=387 -mno-sse -mno-sse2 -mno-sse3 -mno-mmx -mno-3dnow \ -msoft-float -fno-asynchronous-unwind-tables \ -fno-omit-frame-pointer diff --git a/sys/platform/pc64/include/pmap.h b/sys/platform/pc64/include/pmap.h index 36e8971009..6a6d8ad22f 100644 --- a/sys/platform/pc64/include/pmap.h +++ b/sys/platform/pc64/include/pmap.h @@ -1,5 +1,6 @@ /* * Copyright (c) 1991 Regents of the University of California. + * Copyright (c) 2003 Peter Wemm. * Copyright (c) 2008 The DragonFly Project. * All rights reserved. * @@ -62,37 +63,51 @@ #endif /* - * Pte related macros + * Pte related macros. This is complicated by having to deal with + * the sign extension of the 48th bit. */ -#define VADDR(pdi, pti) ((vm_offset_t)(((pdi)< KVA_PAGES - 2 -#error "Maximum NKPDE is KVA_PAGES - 2" +#define NKPT 32 #endif +#define NKPML4E 1 /* number of kernel PML4 slots */ +#define NKPDPE howmany(NKPT, NPDEPG)/* number of kernel PDP slots */ + +#define NUPML4E (NPML4EPG/2) /* number of userland PML4 pages */ +#define NUPDPE (NUPML4E*NPDPEPG)/* number of userland PDP pages */ +#define NUPDE (NUPDPE*NPDEPG) /* number of userland PD entries */ + +#define NDMPML4E 1 /* number of dmap PML4 slots */ + /* - * The *PTDI values control the layout of virtual memory - * - * XXX This works for now, but I am not real happy with it, I'll fix it - * right after I fix locore.s and the magic 28K hole - * - * SMP_PRIVPAGES: The per-cpu address space is 0xff80000 -> 0xffbfffff + * The *PML4I values control the layout of virtual memory */ -#define APTDPTDI (NPDEPG-1) /* alt ptd entry that points to APTD */ -#define MPPTDI (APTDPTDI-1) /* per cpu ptd entry */ -#define KPTDI (MPPTDI-NKPDE) /* start of kernel virtual pde's */ -#define PTDPTDI (KPTDI-1) /* ptd entry that points to ptd! */ -#define UMAXPTDI (PTDPTDI-1) /* ptd entry for user space end */ -#define UMAXPTEOFF (NPTEPG) /* pte entry for user space end */ +#define PML4PML4I (NPML4EPG/2) /* Index of recursive pml4 mapping */ + +#define KPML4I (NPML4EPG-1) /* Top 512GB for KVM */ +#define DMPML4I (KPML4I-1) /* Next 512GB down for direct map */ -#define LINKPML4I 0 -#define LINKPDPI 0 +#define KPDPI (NPDPEPG-2) /* kernbase at -2GB */ + +/* per-CPU data is at -2MB */ +/* XXX can the kernel decide to use this memory for something else? */ +#define MPPML4I KPML4I +#define MPPDPI KPDPI +#define MPPTDI (NPDEPG-1) /* * XXX doesn't really belong here I guess... @@ -120,14 +135,18 @@ * and directories. */ #ifdef _KERNEL -extern pt_entry_t PTmap[], APTmap[], Upte; -extern pd_entry_t PTD[], APTD[], PTDpde, APTDpde, Upde; - -extern uint64_t IdlePTD; /* physical address of "Idle" state directory */ - -extern uint64_t common_lvl4_phys; -extern uint64_t common_lvl3_phys; -extern pdp_entry_t *link_pdpe; +#define addr_PTmap (KVADDR(PML4PML4I, 0, 0, 0)) +#define addr_PDmap (KVADDR(PML4PML4I, PML4PML4I, 0, 0)) +#define addr_PDPmap (KVADDR(PML4PML4I, PML4PML4I, PML4PML4I, 0)) +#define addr_PML4map (KVADDR(PML4PML4I, PML4PML4I, PML4PML4I, PML4PML4I)) +#define addr_PML4pml4e (addr_PML4map + (PML4PML4I * sizeof(pml4_entry_t))) +#define PTmap ((pt_entry_t *)(addr_PTmap)) +#define PDmap ((pd_entry_t *)(addr_PDmap)) +#define PDPmap ((pd_entry_t *)(addr_PDPmap)) +#define PML4map ((pd_entry_t *)(addr_PML4map)) +#define PML4pml4e ((pd_entry_t *)(addr_PML4pml4e)) + +extern u_int64_t KPML4phys; /* physical address of kernel level 4 */ #endif #ifdef _KERNEL @@ -137,29 +156,10 @@ extern pdp_entry_t *link_pdpe; * Note: these work recursively, thus vtopte of a pte will give * the corresponding pde that in turn maps it. */ -#define vtopte(va) (PTmap + amd64_btop(va)) +pt_entry_t *vtopte(vm_offset_t); #define avtopte(va) (APTmap + amd64_btop(va)) -/* - * Routine: pmap_kextract - * Function: - * Extract the physical page address associated - * kernel virtual address. - */ -static __inline vm_paddr_t -pmap_kextract(vm_offset_t va) -{ - vm_paddr_t pa; - - if ((pa = (vm_offset_t) PTD[va >> PDRSHIFT]) & PG_PS) { - pa = (pa & ~(NBPDR - 1)) | (va & (NBPDR - 1)); - } else { - pa = *(vm_offset_t *)vtopte(va); - pa = (pa & PG_FRAME) | (va & PAGE_MASK); - } - return pa; -} /* * XXX @@ -171,6 +171,15 @@ pmap_kextract(vm_offset_t va) #define pte_load_clear(pte) atomic_readandclear_long(pte) +static __inline void +pte_store(pt_entry_t *ptep, pt_entry_t pte) +{ + + *ptep = pte; +} + +#define pde_store(pdep, pde) pte_store((pdep), (pde)) + /* * Pmap stuff */ @@ -199,7 +208,7 @@ struct pmap_statistics { typedef struct pmap_statistics *pmap_statistics_t; struct pmap { - pd_entry_t *pm_pdir; /* KVA of page directory */ + pml4_entry_t *pm_pml4; /* KVA of level 4 page table */ struct vm_page *pm_pdirm; /* VM page for pg directory */ struct vm_object *pm_pteobj; /* Container for pte's */ TAILQ_ENTRY(pmap) pm_pmnode; /* list of pmaps */ @@ -250,14 +259,17 @@ extern vm_offset_t clean_eva; extern vm_offset_t clean_sva; extern char *ptvmmap; /* poor name! */ -void pmap_bootstrap ( vm_paddr_t *, vm_paddr_t); +void pmap_bootstrap ( vm_paddr_t *); void *pmap_mapdev (vm_paddr_t, vm_size_t); void pmap_unmapdev (vm_offset_t, vm_size_t); +#if JG pt_entry_t *pmap_pte (pmap_t, vm_offset_t) __pure2; +#endif struct vm_page *pmap_use_pt (pmap_t, vm_offset_t); #ifdef SMP void pmap_set_opt (void); #endif +vm_paddr_t pmap_kextract(vm_offset_t); #endif /* _KERNEL */ diff --git a/sys/platform/pc64/include/vmparam.h b/sys/platform/pc64/include/vmparam.h index 98c11740b1..b660e21d21 100644 --- a/sys/platform/pc64/include/vmparam.h +++ b/sys/platform/pc64/include/vmparam.h @@ -102,35 +102,31 @@ * messy at times, but hey, we'll do anything to save a page :-) */ -#define VM_MAX_KERNEL_ADDRESS (1024UL * 1024 * 1024) -#define VM_MIN_KERNEL_ADDRESS (512UL * 1024 * 1024) +#define VM_MAX_KERNEL_ADDRESS KVADDR(KPML4I, NPDPEPG-1, NPDEPG-1, NPTEPG-1) +#define VM_MIN_KERNEL_ADDRESS KVADDR(KPML4I, NPDPEPG-7, 0, 0) #define DMAP_MIN_ADDRESS KVADDR(DMPML4I, 0, 0, 0) #define DMAP_MAX_ADDRESS KVADDR(DMPML4I+1, 0, 0, 0) -#define KERNBASE (512 * 1024 * 1024) -#define PTOV_OFFSET KERNBASE +#define KERNBASE KVADDR(KPML4I, KPDPI, 0, 0) +#define PTOV_OFFSET KERNBASE +#if JG #define KPT_MAX_ADDRESS VADDR(PTDPTDI, KPTDI+NKPT) #define KPT_MIN_ADDRESS VADDR(PTDPTDI, KPTDI) +#endif -#define UPT_MAX_ADDRESS VADDR(PTDPTDI, PTDPTDI) -#define UPT_MIN_ADDRESS VADDR(PTDPTDI, 0) - -#define VM_MAXUSER_ADDRESS UPT_MIN_ADDRESS - -#define USRSTACK VM_MAXUSER_ADDRESS - -#define VM_MAX_ADDRESS UPT_MAX_ADDRESS -#define VM_MIN_ADDRESS (0) +#define UPT_MAX_ADDRESS KVADDR(PML4PML4I, PML4PML4I, PML4PML4I, PML4PML4I) +#define UPT_MIN_ADDRESS KVADDR(PML4PML4I, 0, 0, 0) #define VM_MIN_USER_ADDRESS ((vm_offset_t)0) -#define VM_MAX_USER_ADDRESS VM_MAXUSER_ADDRESS +#define VM_MAX_USER_ADDRESS UVADDR(NUPML4E, 0, 0, 0) + +#define USRSTACK VM_MAX_USER_ADDRESS #define PHYS_TO_DMAP(x) ((x) | DMAP_MIN_ADDRESS) #define DMAP_TO_PHYS(x) ((x) & ~DMAP_MIN_ADDRESS) - /* initial pagein size of beginning of executable file */ #ifndef VM_INITIAL_PAGEIN #define VM_INITIAL_PAGEIN 16 diff --git a/sys/platform/pc64/isa/clock.c b/sys/platform/pc64/isa/clock.c index ba5a449a5b..7bdc3860a6 100644 --- a/sys/platform/pc64/isa/clock.c +++ b/sys/platform/pc64/isa/clock.c @@ -36,7 +36,6 @@ * * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 * $FreeBSD: src/sys/i386/isa/clock.c,v 1.149.2.6 2002/11/02 04:41:50 iwasaki Exp $ - * $DragonFly: src/sys/platform/pc64/isa/clock.c,v 1.1 2008/08/29 17:07:19 dillon Exp $ */ /* @@ -50,8 +49,10 @@ * reintroduced and updated by Chris Stenton 8/10/94 */ -//#include "use_apm.h" -//#include "opt_clock.h" +#if 0 +#include "use_apm.h" +#include "opt_clock.h" +#endif #include #include @@ -125,10 +126,6 @@ enum tstate timer0_state; enum tstate timer1_state; enum tstate timer2_state; - -static void i8254_intr_reload(sysclock_t); -void (*cputimer_intr_reload)(sysclock_t) = i8254_intr_reload; - static int beeping = 0; static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; @@ -137,6 +134,10 @@ static int rtc_loaded; static int i8254_cputimer_div; +static int i8254_nointr; +static int i8254_intr_disable = 0; +TUNABLE_INT("hw.i8254.intr_disable", &i8254_intr_disable); + static struct callout sysbeepstop_ch; static sysclock_t i8254_cputimer_count(void); @@ -157,6 +158,25 @@ static struct cputimer i8254_cputimer = { 0, 0, 0 }; +static void i8254_intr_reload(struct cputimer_intr *, sysclock_t); +static void i8254_intr_config(struct cputimer_intr *, const struct cputimer *); +static void i8254_intr_initclock(struct cputimer_intr *, boolean_t); + +static struct cputimer_intr i8254_cputimer_intr = { + .freq = TIMER_FREQ, + .reload = i8254_intr_reload, + .enable = cputimer_intr_default_enable, + .config = i8254_intr_config, + .restart = cputimer_intr_default_restart, + .pmfixup = cputimer_intr_default_pmfixup, + .initclock = i8254_intr_initclock, + .next = SLIST_ENTRY_INITIALIZER, + .name = "i8254", + .type = CPUTIMER_INTR_8254, + .prio = CPUTIMER_INTR_PRIO_8254, + .caps = CPUTIMER_INTR_CAP_PS +}; + /* * timer0 clock interrupt. Timer0 is in one-shot mode and has stopped * counting as of this interrupt. We use timer1 in free-running mode (not @@ -307,8 +327,8 @@ i8254_cputimer_count(void) * simple shift, multiplication, or division, we do so. Otherwise 64 * bit arithmatic is required every time the interrupt timer is reloaded. */ -void -cputimer_intr_config(struct cputimer *timer) +static void +i8254_intr_config(struct cputimer_intr *cti, const struct cputimer *timer) { int freq; int div; @@ -316,8 +336,8 @@ cputimer_intr_config(struct cputimer *timer) /* * Will a simple divide do the trick? */ - div = (timer->freq + (i8254_cputimer.freq / 2)) / i8254_cputimer.freq; - freq = i8254_cputimer.freq * div; + div = (timer->freq + (cti->freq / 2)) / cti->freq; + freq = cti->freq * div; if (freq >= timer->freq - 1 && freq <= timer->freq + 1) i8254_cputimer_div = div; @@ -333,14 +353,14 @@ cputimer_intr_config(struct cputimer *timer) * We may have to convert from the system timebase to the 8254 timebase. */ static void -i8254_intr_reload(sysclock_t reload) +i8254_intr_reload(struct cputimer_intr *cti, sysclock_t reload) { __uint16_t count; if (i8254_cputimer_div) reload /= i8254_cputimer_div; else - reload = (int64_t)reload * i8254_cputimer.freq / sys_cputimer->freq; + reload = (int64_t)reload * cti->freq / sys_cputimer->freq; if ((int)reload < 2) reload = 2; @@ -366,16 +386,6 @@ i8254_intr_reload(sysclock_t reload) clock_unlock(); } -void -cputimer_intr_enable(void) -{ -} - -void -cputimer_intr_switch(enum cputimer_intr_type type) -{ -} - /* * DELAY(usec) - Spin for the specified number of microseconds. * DRIVERSLEEP(usec) - Spin for the specified number of microseconds, @@ -627,6 +637,11 @@ i8254_restore(void) outb(TIMER_CNTR0, 0); /* msb */ clock_unlock(); + if (!i8254_nointr) { + cputimer_intr_register(&i8254_cputimer_intr); + cputimer_intr_select(&i8254_cputimer_intr, 0); + } + /* * Timer1 or timer2 is our free-running clock, but only if another * has not been selected. @@ -774,6 +789,12 @@ startrtclock(void) "CLK_USE_I8254_CALIBRATION not specified - using default frequency\n"); freq = i8254_cputimer.freq; #endif + /* + * NOTE: + * Interrupt timer's freq must be adjusted + * before we change the cuptimer's frequency. + */ + i8254_cputimer_intr.freq = freq; cputimer_set_frequency(&i8254_cputimer, freq); } else { if (bootverbose) @@ -991,8 +1012,8 @@ resettodr(void) * used. Instead, 8254 based systimers are used for all major clock * interrupts. statclock_disable is set by default. */ -void -cpu_initclocks(void *arg __unused) +static void +i8254_intr_initclock(struct cputimer_intr *cti, boolean_t selected) { int diag; #ifdef APIC_IO @@ -1000,6 +1021,14 @@ cpu_initclocks(void *arg __unused) void *clkdesc; #endif /* APIC_IO */ + callout_init(&sysbeepstop_ch); + + if (!selected && i8254_intr_disable) { + i8254_nointr = 1; /* don't try to register again */ + cputimer_intr_deregister(cti); + return; + } + if (statclock_disable) { /* * The stat interrupt mask is different without the @@ -1075,15 +1104,21 @@ cpu_initclocks(void *arg __unused) sysclock_t base; long lastcnt; + /* + * Following code assumes the 8254 is the cpu timer, + * so make sure it is. + */ + KKASSERT(sys_cputimer == &i8254_cputimer); + KKASSERT(cti == &i8254_cputimer_intr); + lastcnt = get_interrupt_counter(apic_8254_intr); /* - * XXX this assumes the 8254 is the cpu timer. Force an - * 8254 Timer0 interrupt and wait 1/100s for it to happen, - * then see if we got it. + * Force an 8254 Timer0 interrupt and wait 1/100s for + * it to happen, then see if we got it. */ kprintf("APIC_IO: Testing 8254 interrupt delivery\n"); - cputimer_intr_reload(2); /* XXX assumes 8254 */ + i8254_intr_reload(cti, 2); base = sys_cputimer->count(); while (sys_cputimer->count() - base < sys_cputimer->freq / 100) ; /* nothing */ @@ -1121,7 +1156,6 @@ cpu_initclocks(void *arg __unused) INTR_NOENTROPY); machintr_intren(apic_8254_intr); } - } if (apic_int_type(0, 0) != 3 || int_to_apicintpin[apic_8254_intr].ioapic != 0 || @@ -1134,9 +1168,7 @@ cpu_initclocks(void *arg __unused) "routing 8254 via 8259 and IOAPIC #0 intpin 0\n"); } #endif - callout_init(&sysbeepstop_ch); } -SYSINIT(clocks8254, SI_BOOT2_CLOCKREG, SI_ORDER_FIRST, cpu_initclocks, NULL) #ifdef APIC_IO diff --git a/sys/platform/vkernel/i386/cpu_regs.c b/sys/platform/vkernel/i386/cpu_regs.c index e6958c0624..1219e5ae8d 100644 --- a/sys/platform/vkernel/i386/cpu_regs.c +++ b/sys/platform/vkernel/i386/cpu_regs.c @@ -769,11 +769,16 @@ cpu_mplock_contested(void) /* * Called by the spinlock code with or without a critical section held * when a spinlock is found to be seriously constested. + * + * We need to enter a critical section to prevent signals from recursing + * into pthreads. */ void cpu_spinlock_contested(void) { + crit_enter(); usleep(1000); + crit_exit(); } #endif diff --git a/sys/platform/vkernel/i386/exception.c b/sys/platform/vkernel/i386/exception.c index 3d14d3166d..7513a5f962 100644 --- a/sys/platform/vkernel/i386/exception.c +++ b/sys/platform/vkernel/i386/exception.c @@ -69,20 +69,24 @@ static void exc_debugger(int signo, siginfo_t *info, void *ctx); /* * IPIs are 'fast' interrupts, so we deal with them directly from our * signal handler. + * + * WARNING: Signals are not physically disabled here so we have to enter + * our critical section before bumping gd_intr_nesting_level or another + * interrupt can come along and get really confused. */ static void ipisig(int nada, siginfo_t *info, void *ctxp) { - ++mycpu->gd_intr_nesting_level; if (curthread->td_pri < TDPRI_CRIT) { curthread->td_pri += TDPRI_CRIT; + ++mycpu->gd_intr_nesting_level; lwkt_process_ipiq(); + --mycpu->gd_intr_nesting_level; curthread->td_pri -= TDPRI_CRIT; } else { need_ipiq(); } - --mycpu->gd_intr_nesting_level; } /* @@ -91,6 +95,10 @@ ipisig(int nada, siginfo_t *info, void *ctxp) * Note: cpu_mask_all_signals() masks all signals except SIGXCPU itself. * SIGXCPU itself is blocked on entry to stopsig() by the signal handler * itself. + * + * WARNING: Signals are not physically disabled here so we have to enter + * our critical section before bumping gd_intr_nesting_level or another + * interrupt can come along and get really confused. */ static void @@ -107,11 +115,13 @@ stopsig(int nada, siginfo_t *info, void *ctxp) sigaddset(&ss, SIGTERM); sigaddset(&ss, SIGWINCH); + curthread->td_pri += TDPRI_CRIT; ++mycpu->gd_intr_nesting_level; while (stopped_cpus & mycpu->gd_cpumask) { sigsuspend(&ss); } --mycpu->gd_intr_nesting_level; + curthread->td_pri -= TDPRI_CRIT; } #endif diff --git a/sys/platform/vkernel/include/cothread.h b/sys/platform/vkernel/include/cothread.h index 850fddafdd..7fd72a2dc7 100644 --- a/sys/platform/vkernel/include/cothread.h +++ b/sys/platform/vkernel/include/cothread.h @@ -45,6 +45,7 @@ struct cothread { void *arg; void (*thr_func)(struct cothread *); void (*thr_intr)(struct cothread *); + void *intr_id; pthread_mutex_t mutex; pthread_cond_t cond; }; @@ -54,10 +55,11 @@ typedef struct cothread *cothread_t; cothread_t cothread_create(void (*thr_func)(cothread_t cotd), void (*thr_intr)(cothread_t cotd), void *arg, const char *name); +void cothread_delete(cothread_t *cotdp); void cothread_intr(cothread_t cotd); void cothread_signal(cothread_t cotd); void cothread_wait(cothread_t cotd); -void cothread_lock(cothread_t cotd); -void cothread_unlock(cothread_t cotd); +void cothread_lock(cothread_t cotd, int is_cotd); +void cothread_unlock(cothread_t cotd, int is_cotd); #endif diff --git a/sys/platform/vkernel/platform/console.c b/sys/platform/vkernel/platform/console.c index b4088abb33..c7874701de 100644 --- a/sys/platform/vkernel/platform/console.c +++ b/sys/platform/vkernel/platform/console.c @@ -182,8 +182,9 @@ vcons_tty_start(struct tty *tp) /* * Dummy up ttyv1, etc. */ - if (minor(tp->t_dev) == 0) - write(1, buf, n); + if (minor(tp->t_dev) == 0) { + pwrite(1, buf, n, -1); + } } tp->t_state &= ~TS_BUSY; ttwwakeup(tp); @@ -370,7 +371,8 @@ vconsgetc(void *private) console_stolen_by_kernel = 1; for (;;) { - if ((n = read(0, &c, 1)) == 1) + n = pread(0, &c, 1, -1); + if (n == 1) break; if (n < 0 && errno == EINTR) continue; @@ -395,7 +397,7 @@ vconsputc(void *private, int c) { char cc = c; - write(1, &cc, 1); + pwrite(1, &cc, 1, -1); } void diff --git a/sys/platform/vkernel/platform/cothread.c b/sys/platform/vkernel/platform/cothread.c index d5821e585e..c432de5a11 100644 --- a/sys/platform/vkernel/platform/cothread.c +++ b/sys/platform/vkernel/platform/cothread.c @@ -84,23 +84,46 @@ cothread_create(void (*thr_func)(cothread_t cotd), cotd->thr_intr = thr_intr; cotd->thr_func = thr_func; cotd->arg = arg; + crit_enter(); pthread_mutex_init(&cotd->mutex, NULL); pthread_cond_init(&cotd->cond, NULL); + crit_exit(); cotd->pintr = pthread_self(); - register_int(1, (void *)thr_intr, cotd, name, NULL, 0); + cotd->intr_id = register_int(1, (void *)thr_intr, cotd, name, NULL, 0); /* * The vkernel's cpu_disable_intr() masks signals. We don't want * our coprocessor thread taking any unix signals :-) */ + crit_enter(); cpu_mask_all_signals(); pthread_create(&cotd->pthr, NULL, (void *)cothread_thread, cotd); cpu_unmask_all_signals(); + crit_exit(); return(cotd); } +/* + * Wait for the target thread to terminate and then destroy the cothread + * structure. + */ +void +cothread_delete(cothread_t *cotdp) +{ + cothread_t cotd; + + if ((cotd = *cotdp) != NULL) { + unregister_int(cotd->intr_id); + crit_enter(); + pthread_join(cotd->pthr, NULL); + crit_exit(); + kfree(cotd, M_DEVBUF); + *cotdp = NULL; + } +} + static void cothread_thread(void *arg) { @@ -131,7 +154,9 @@ cothread_intr(cothread_t cotd) void cothread_signal(cothread_t cotd) { + crit_enter(); pthread_cond_signal(&cotd->cond); + crit_exit(); } /* @@ -143,15 +168,30 @@ cothread_wait(cothread_t cotd) pthread_cond_wait(&cotd->cond, &cotd->mutex); } +/* + * Typically called by kernel thread or cothread + */ void -cothread_lock(cothread_t cotd) +cothread_lock(cothread_t cotd, int is_cotd) { - pthread_mutex_lock(&cotd->mutex); + if (is_cotd) { + pthread_mutex_lock(&cotd->mutex); + } else { + crit_enter(); + pthread_mutex_lock(&cotd->mutex); + crit_exit(); + } } void -cothread_unlock(cothread_t cotd) +cothread_unlock(cothread_t cotd, int is_cotd) { - pthread_mutex_unlock(&cotd->mutex); + if (is_cotd) { + pthread_mutex_unlock(&cotd->mutex); + } else { + crit_enter(); + pthread_mutex_unlock(&cotd->mutex); + crit_exit(); + } } diff --git a/sys/platform/vkernel/platform/init.c b/sys/platform/vkernel/platform/init.c index 7d37aa85ea..2d3fd72148 100644 --- a/sys/platform/vkernel/platform/init.c +++ b/sys/platform/vkernel/platform/init.c @@ -756,10 +756,12 @@ init_disk(char *diskExp[], int diskFileNum, enum vkdisk_type type) memcpy(info->fname, fname, l); if (DiskNum == 0) { - if (type == VKD_CD) + if (type == VKD_CD) { rootdevnames[0] = "cd9660:vcd0a"; - else if (type == VKD_DISK) + } else if (type == VKD_DISK) { rootdevnames[0] = "ufs:vkd0s0a"; + rootdevnames[1] = "ufs:vkd0s1a"; + } } DiskNum++; diff --git a/sys/platform/vkernel/platform/pmap.c b/sys/platform/vkernel/platform/pmap.c index 8f65346f46..1a2ca6cd8b 100644 --- a/sys/platform/vkernel/platform/pmap.c +++ b/sys/platform/vkernel/platform/pmap.c @@ -1149,7 +1149,6 @@ _pmap_allocpte(pmap_t pmap, unsigned ptepindex) * return the held page. */ if ((ptepa = pmap->pm_pdir[ptepindex]) != 0) { - Debugger("PTEPA RACE"); KKASSERT((ptepa & VPTE_FRAME) == VM_PAGE_TO_PHYS(m)); vm_page_wakeup(m); return(m); diff --git a/sys/platform/vkernel/platform/systimer.c b/sys/platform/vkernel/platform/systimer.c index 9a89f00aef..c378a585e6 100644 --- a/sys/platform/vkernel/platform/systimer.c +++ b/sys/platform/vkernel/platform/systimer.c @@ -53,7 +53,9 @@ #include #include -static void cputimer_intr(void *dummy, struct intrframe *frame); +#define VKTIMER_FREQ 1000000 /* 1us granularity */ + +static void vktimer_intr(void *dummy, struct intrframe *frame); int disable_rtc_set; SYSCTL_INT(_machdep, CPU_DISRTCSET, disable_rtc_set, @@ -70,10 +72,6 @@ static struct kqueue_info *kqueue_timer_info; static int cputimer_mib[16]; static int cputimer_miblen; -static void vkernel_intr_reload(sysclock_t); -void (*cputimer_intr_reload)(sysclock_t) = vkernel_intr_reload; - - /* * SYSTIMER IMPLEMENTATION */ @@ -90,17 +88,36 @@ static struct cputimer vkernel_cputimer = { cputimer_default_fromus, vkernel_timer_construct, cputimer_default_destruct, - 1000000, /* 1us granularity */ + VKTIMER_FREQ, 0, 0, 0 }; +static void vktimer_intr_reload(struct cputimer_intr *, sysclock_t); +static void vktimer_intr_initclock(struct cputimer_intr *, boolean_t); + +static struct cputimer_intr vkernel_cputimer_intr = { + .freq = VKTIMER_FREQ, + .reload = vktimer_intr_reload, + .enable = cputimer_intr_default_enable, + .config = cputimer_intr_default_config, + .restart = cputimer_intr_default_restart, + .pmfixup = cputimer_intr_default_pmfixup, + .initclock = vktimer_intr_initclock, + .next = SLIST_ENTRY_INITIALIZER, + .name = "vkernel", + .type = CPUTIMER_INTR_VKERNEL, + .prio = CPUTIMER_INTR_PRIO_VKERNEL, + .caps = CPUTIMER_INTR_CAP_NONE +}; + /* * Initialize the systimer subsystem, called from MI code in early boot. */ -void +static void cpu_initclocks(void *arg __unused) { int len; + kprintf("initclocks\n"); len = sizeof(vkernel_cputimer.freq); if (sysctlbyname("kern.cputimer.freq", &vkernel_cputimer.freq, &len, @@ -111,6 +128,10 @@ cpu_initclocks(void *arg __unused) if (sysctlnametomib("kern.cputimer.clock", cputimer_mib, &len) < 0) panic("cpu_initclocks: can't get kern.cputimer.clock!"); cputimer_miblen = len; + + cputimer_intr_register(&vkernel_cputimer_intr); + cputimer_intr_select(&vkernel_cputimer_intr, 0); + cputimer_register(&vkernel_cputimer); cputimer_select(&vkernel_cputimer, 0); } @@ -126,16 +147,6 @@ vkernel_timer_construct(struct cputimer *timer, sysclock_t oclock) timer->base = oclock - vkernel_timer_get_timecount(); } -void -cputimer_intr_enable(void) -{ -} - -void -cputimer_intr_switch(enum cputimer_intr_type type) -{ -} - /* * Get the current counter, with 2's complement rollover. * @@ -156,13 +167,15 @@ vkernel_timer_get_timecount(void) } /* - * Configure the interrupt for our core systimer. Use the kqueue timer + * Initialize the interrupt for our core systimer. Use the kqueue timer * support functions. */ -void -cputimer_intr_config(struct cputimer *timer) +static void +vktimer_intr_initclock(struct cputimer_intr *cti __unused, + boolean_t selected __unused) { - kqueue_timer_info = kqueue_add_timer(cputimer_intr, NULL); + KKASSERT(kqueue_timer_info == NULL); + kqueue_timer_info = kqueue_add_timer(vktimer_intr, NULL); } /* @@ -171,7 +184,7 @@ cputimer_intr_config(struct cputimer *timer) * check to ensure that a reasonable reload value is selected. */ static void -vkernel_intr_reload(sysclock_t reload) +vktimer_intr_reload(struct cputimer_intr *cti __unused, sysclock_t reload) { if (kqueue_timer_info) { if ((int)reload < 1) @@ -186,7 +199,7 @@ vkernel_intr_reload(sysclock_t reload) * NOTE: frame is a struct intrframe pointer. */ static void -cputimer_intr(void *dummy, struct intrframe *frame) +vktimer_intr(void *dummy, struct intrframe *frame) { static sysclock_t sysclock_count; struct globaldata *gd = mycpu; @@ -238,10 +251,16 @@ resettodr(void) { } +/* + * We need to enter a critical section to prevent signals from recursing + * into pthreads. + */ void DELAY(int usec) { + crit_enter(); usleep(usec); + crit_exit(); } void @@ -252,6 +271,6 @@ DRIVERSLEEP(int usec) else if (1000000 / usec >= hz) tsleep(DRIVERSLEEP, 0, "DELAY", 1000000 / usec / hz + 1); else - usleep(usec); + DELAY(usec); } diff --git a/sys/sys/_pthreadtypes.h b/sys/sys/_pthreadtypes.h new file mode 100644 index 0000000000..7c326378d0 --- /dev/null +++ b/sys/sys/_pthreadtypes.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu + * Copyright (c) 1995-1998 by John Birrell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL CHRIS PROVENZANO BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SYS__PTHREADTYPES_H_ +#define _SYS__PTHREADTYPES_H_ + +/* + * Forward structure definitions. + * + * These are mostly opaque to the user. + */ +struct pthread; +struct pthread_attr; +struct pthread_cond; +struct pthread_cond_attr; +struct pthread_mutex; +struct pthread_mutex_attr; +struct pthread_once; +struct pthread_rwlock; +struct pthread_rwlockattr; +struct pthread_barrier; +struct pthread_barrier_attr; + +/* + * Primitive system data type definitions required by P1003.1c. + * + * Note that P1003.1c specifies that there are no defined comparison + * or assignment operators for the types pthread_attr_t, pthread_cond_t, + * pthread_condattr_t, pthread_mutex_t, pthread_mutexattr_t. + */ +typedef struct pthread *pthread_t; +typedef struct pthread_attr *pthread_attr_t; +typedef struct pthread_mutex *pthread_mutex_t; +typedef struct pthread_mutex_attr *pthread_mutexattr_t; +typedef struct pthread_cond *pthread_cond_t; +typedef struct pthread_cond_attr *pthread_condattr_t; +typedef int pthread_key_t; +typedef struct pthread_once pthread_once_t; +typedef struct pthread_rwlock *pthread_rwlock_t; +typedef struct pthread_rwlockattr *pthread_rwlockattr_t; +typedef struct pthread_barrier *pthread_barrier_t; +typedef struct pthread_barrierattr *pthread_barrierattr_t; + +/* + * Additional type definitions: + * + * Note that P1003.1c reserves the prefixes pthread_ and PTHREAD_ for + * use in header symbols. + */ +typedef void *pthread_addr_t; +typedef void *(*pthread_startroutine_t) (void *); + +/* + * Once definitions. + */ +struct pthread_once { + int state; + pthread_mutex_t mutex; +}; + +#endif /* ! _SYS__PTHREADTYPES_H_ */ diff --git a/sys/sys/bus_dma.h b/sys/sys/bus_dma.h index b91f6ff3be..2c3a0fe92a 100644 --- a/sys/sys/bus_dma.h +++ b/sys/sys/bus_dma.h @@ -182,6 +182,7 @@ int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat); int bus_dma_tag_destroy(bus_dma_tag_t dmat); +bus_size_t bus_dma_tag_getmaxsize(bus_dma_tag_t tag); /* * Allocate a handle for mapping from kva/uva/physical diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h index 7df1b0ec1a..df00fe223a 100644 --- a/sys/sys/fcntl.h +++ b/sys/sys/fcntl.h @@ -113,6 +113,7 @@ #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES) #define FREVOKED 0x10000000 /* revoked by fdrevoke() */ +#define FAPPENDONLY 0x20000000 /* O_APPEND cannot be changed */ #endif #define O_FMASK (O_FBLOCKING|O_FNONBLOCKING|O_FAPPEND|O_FOFFSET|\ @@ -126,7 +127,7 @@ /* bits to save after open */ #define FMASK (FREAD|FWRITE|FAPPEND|FASYNC|FFSYNC|FNONBLOCK|\ - O_DIRECT|O_MAPONREAD) + FAPPENDONLY|FREVOKED|O_DIRECT|O_MAPONREAD) /* bits settable by fcntl(F_SETFL, ...) */ #define FCNTLFLAGS (FAPPEND|FASYNC|FFSYNC|FNONBLOCK|FPOSIXSHM|\ O_DIRECT|O_MAPONREAD) diff --git a/sys/sys/nata.h b/sys/sys/nata.h index 9dde0701e9..d806605ed9 100644 --- a/sys/sys/nata.h +++ b/sys/sys/nata.h @@ -335,6 +335,7 @@ struct ata_params { #define ATAPI_READ_BUFFER_CAPACITY 0x5c /* get buffer capicity */ #define ATAPI_SEND_CUE_SHEET 0x5d /* send CUE sheet */ #define ATAPI_SERVICE_ACTION_IN 0x96 /* get service data */ +#define ATAPI_READ_CAPACITY_16 0x96 /* get service data */ #define ATAPI_BLANK 0xa1 /* blank the media */ #define ATAPI_SEND_KEY 0xa3 /* send DVD key structure */ #define ATAPI_REPORT_KEY 0xa4 /* get DVD key structure */ diff --git a/sys/sys/nlookup.h b/sys/sys/nlookup.h index 3859bc9890..cec3b965b6 100644 --- a/sys/sys/nlookup.h +++ b/sys/sys/nlookup.h @@ -94,6 +94,11 @@ struct nlookupdata { int nl_vp_fmode; }; +/* + * NOTE: nlookup() flags related to open checks do not actually perform + * any modifying operation. e.g. the file isn't created, truncated, + * etc. vn_open() handles that. + */ #define NLC_FOLLOW 0x00000001 /* follow leaf symlink */ #define NLC_NOCROSSMOUNT 0x00000002 /* do not cross mount points */ #define NLC_HASBUF 0x00000004 /* nl_path is allocated */ @@ -101,13 +106,41 @@ struct nlookupdata { #define NLC_WILLBEDIR 0x00000010 #define NLC_NCPISLOCKED 0x00000020 #define NLC_LOCKVP 0x00000040 /* nl_open_vp from vn_open */ -#define NLC_CREATE 0x00000080 -#define NLC_DELETE 0x00000100 -#define NLC_RENAME 0x00000200 /* rename (target) */ +#define NLC_CREATE 0x00000080 /* do create checks */ +#define NLC_DELETE 0x00000100 /* do delete checks */ +#define NLC_RENAME_DST 0x00000200 /* do rename checks (target) */ +#define NLC_OPEN 0x00000400 /* do open checks */ +#define NLC_TRUNCATE 0x00000800 /* do truncation checks */ +#define NLC_HLINK 0x00001000 /* do hardlink checks */ +#define NLC_RENAME_SRC 0x00002000 /* do rename checks (source) */ +#define NLC_UNUSED00004000 0x00004000 +#define NLC_UNUSED00008000 0x00008000 #define NLC_NFS_RDONLY 0x00010000 /* set by nfs_namei() only */ #define NLC_NFS_NOSOFTLINKTRAV 0x00020000 /* do not traverse softlnks */ #define NLC_REFDVP 0x00040000 /* set ref'd/unlocked nl_dvp */ +#define NLC_APPEND 0x00100000 /* open check: append */ +#define NLC_UNUSED00200000 0x00200000 + +#define NLC_READ 0x00400000 /* require read access */ +#define NLC_WRITE 0x00800000 /* require write access */ +#define NLC_EXEC 0x01000000 /* require execute access */ +#define NLC_EXCL 0x02000000 /* open check: exclusive */ +#define NLC_OWN 0x04000000 /* open check: owner override */ +#define NLC_UNUSED08000000 0x08000000 +#define NLC_STICKY 0x10000000 /* indicate sticky case */ +#define NLC_APPENDONLY 0x20000000 /* indicate append-only */ +#define NLC_IMMUTABLE 0x40000000 /* indicate immutable set */ +#define NLC_WRITABLE 0x80000000 /* indicate writeable */ + +/* + * All checks. If any of these bits are set general user/group/world + * permission checks will be done by nlookup(). + */ +#define NLC_ALLCHKS (NLC_CREATE | NLC_DELETE | NLC_RENAME_DST | \ + NLC_OPEN | NLC_TRUNCATE | NLC_RENAME_SRC | \ + NLC_READ | NLC_WRITE | NLC_EXEC | NLC_OWN) + #ifdef _KERNEL int nlookup_init(struct nlookupdata *, const char *, enum uio_seg, int); @@ -122,6 +155,7 @@ int nlookup(struct nlookupdata *); int nreadsymlink(struct nlookupdata *nd, struct nchandle *nch, struct nlcomponent *nlc); int naccess(struct nchandle *nch, int vmode, struct ucred *cred, int *stickyp); +int naccess_va(struct vattr *va, int nflags, struct ucred *cred); #endif diff --git a/sys/sys/spinlock2.h b/sys/sys/spinlock2.h index b0fe767255..0eb9249b95 100644 --- a/sys/sys/spinlock2.h +++ b/sys/sys/spinlock2.h @@ -203,6 +203,7 @@ spin_unlock_wr_quick(globaldata_t gd, struct spinlock *mtx) #ifdef SMP mtx->lock = 0; #endif + KKASSERT(gd->gd_spinlocks_wr > 0); --gd->gd_spinlocks_wr; } diff --git a/sys/sys/systimer.h b/sys/sys/systimer.h index dd0d3ae1b3..484dafeb42 100644 --- a/sys/sys/systimer.h +++ b/sys/sys/systimer.h @@ -39,6 +39,8 @@ #ifndef _SYS_SYSTIMER_H_ #define _SYS_SYSTIMER_H_ +#if defined(_KERNEL) || defined(_KERNEL_STRUCTURES) + #ifndef _SYS_TYPES_H_ #include #endif @@ -46,12 +48,18 @@ #include #endif +/* XXX fix sys/kinfo.h */ +#ifndef __BOOLEAN_T_DEFINED__ +#define __BOOLEAN_T_DEFINED__ +typedef __boolean_t boolean_t; +#endif + struct intrframe; typedef __uint32_t sysclock_t; typedef TAILQ_HEAD(systimerq, systimer) *systimerq_t; -typedef void (*systimer_func_t)(struct systimer *info); -typedef void (*systimer_func2_t)(struct systimer *info, struct intrframe *frame); +typedef void (*systimer_func_t)(struct systimer *); +typedef void (*systimer_func2_t)(struct systimer *, struct intrframe *); typedef struct systimer { TAILQ_ENTRY(systimer) node; @@ -78,14 +86,15 @@ void systimer_init_periodic(systimer_t, void *, void *, int); void systimer_init_periodic_nq(systimer_t, void *, void *, int); void systimer_adjust_periodic(systimer_t, int); void systimer_init_oneshot(systimer_t, void *, void *, int); -void systimer_changed(void); /* * cputimer interface. This provides a free-running (non-interrupt) * timebase for the system. The cputimer * * These variables hold the fixed cputimer frequency, determining the - * granularity of cputimer_count(). + * granularity of cputimer_count(). + * + * Note that cputimer_count() always returns a full-width wrapping counter. * * The 64 bit versions are used for converting count values into uS or nS * as follows: @@ -101,8 +110,8 @@ struct cputimer { sysclock_t (*count)(void); sysclock_t (*fromhz)(int freq); sysclock_t (*fromus)(int us); - void (*construct)(struct cputimer *cputimer, sysclock_t oldclock); - void (*destruct)(struct cputimer *cputimer); + void (*construct)(struct cputimer *, sysclock_t); + void (*destruct)(struct cputimer *); sysclock_t freq; /* in Hz */ int64_t freq64_usec; /* in (1e6 << 32) / timer_freq */ int64_t freq64_nsec; /* in (1e9 << 32) / timer_freq */ @@ -124,14 +133,6 @@ extern struct cputimer *sys_cputimer; #define CPUTIMER_PRI_HPET 15 #define CPUTIMER_PRI_VKERNEL 20 -enum cputimer_intr_type { - CPUTIMER_INTRT_C3 = 0, - CPUTIMER_INTRT_FAST -}; - -/* - * note that cputimer_count() always returns a full-width wrapping counter. - */ void cputimer_select(struct cputimer *, int); void cputimer_register(struct cputimer *); void cputimer_deregister(struct cputimer *); @@ -141,10 +142,103 @@ sysclock_t cputimer_default_fromus(int); void cputimer_default_construct(struct cputimer *, sysclock_t); void cputimer_default_destruct(struct cputimer *); +/* + * Interrupt cputimer interface. + * + * Interrupt cputimers are normally one shot timers which will + * generate interrupt upon expiration. + * + * initclock -- Called at SI_BOOT2_CLOCKREG, SI_ORDER_SECOND. The + * interrupt timer could deregister itself here, if it + * is not the selected system interrupt cputimer. Before + * this function is called, 'enable' and 'reload' will + * not be called. + * enable -- Enable interrupt. It is called by each CPU. It is + * only called once during boot. Before this function + * is called, 'reload' will not be called. + * reload -- Called by each CPU when it wants to to reprogram the + * one shot timer expiration time. The reload value is + * measured in sys_cputimer->freq. + * config -- Setup the interrupt cputimer according to the passed + * in non-interrupt cputimer. It will be called when + * sys_cputimer's frequency is changed or when sys_cputimer + * itself is changed. It is also called when this interrupt + * cputimer gets registered. + * restart -- Start the possibly stalled interrupt cputimer immediately. + * Do fixup if necessary. + * pmfixup -- Called after ACPI power management is enabled. + */ +struct cputimer_intr { + sysclock_t freq; + void (*reload) + (struct cputimer_intr *, sysclock_t); + void (*enable) + (struct cputimer_intr *); + void (*config) + (struct cputimer_intr *, const struct cputimer *); + void (*restart) + (struct cputimer_intr *); + void (*pmfixup) + (struct cputimer_intr *); + void (*initclock) + (struct cputimer_intr *, boolean_t); + SLIST_ENTRY(cputimer_intr) next; + const char *name; + int type; /* CPUTIMER_INTR_ */ + int prio; /* CPUTIMER_INTR_PRIO_ */ + uint32_t caps; /* CPUTIMER_INTR_CAP_ */ +}; + +#define CPUTIMER_INTR_8254 0 +#define CPUTIMER_INTR_LAPIC 1 +#define CPUTIMER_INTR_VKERNEL 2 + +/* NOTE: Keep the new values less than CPUTIMER_INTR_PRIO_MAX */ +#define CPUTIMER_INTR_PRIO_8254 0 +#define CPUTIMER_INTR_PRIO_LAPIC 10 +#define CPUTIMER_INTR_PRIO_VKERNEL 20 +#define CPUTIMER_INTR_PRIO_MAX 1000 + +#define CPUTIMER_INTR_CAP_NONE 0 +#define CPUTIMER_INTR_CAP_PS 0x1 /* works during powersaving */ + +/* + * Interrupt cputimer implementation interfaces + * + * NOTE: + * cputimer_intr_deregister() is _not_ allowed to be called + * with the currently selected interrupt cputimer. + */ +void cputimer_intr_register(struct cputimer_intr *); +void cputimer_intr_deregister(struct cputimer_intr *); +int cputimer_intr_select(struct cputimer_intr *, int); + +/* + * Interrupt cputimer implementation helper functions + * + * default_enable -- NOP + * default_restart -- reload(0) + * default_config -- NOP + * default_pmfixup -- NOP + * default_initclock -- NOP + */ +void cputimer_intr_default_enable(struct cputimer_intr *); +void cputimer_intr_default_restart(struct cputimer_intr *); +void cputimer_intr_default_config(struct cputimer_intr *, + const struct cputimer *); +void cputimer_intr_default_pmfixup(struct cputimer_intr *); +void cputimer_intr_default_initclock(struct cputimer_intr *, boolean_t); + +/* + * Interrupt cputimer external interfaces + */ void cputimer_intr_enable(void); -void cputimer_intr_config(struct cputimer *); -extern void (*cputimer_intr_reload)(sysclock_t); -void cputimer_intr_switch(enum cputimer_intr_type); +void cputimer_intr_pmfixup(void); +void cputimer_intr_config(const struct cputimer *); +void cputimer_intr_reload(sysclock_t); +void cputimer_intr_restart(void); +int cputimer_intr_select_caps(uint32_t); -#endif +#endif /* _KERNEL || _KERNEL_STRUCTURES */ +#endif /* !_SYS_SYSTIMER_H_ */ diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 508b0b234e..43c72b5783 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -262,7 +262,6 @@ void adjust_timeout_calltodo (struct timeval *time_change); /* Initialize the world */ void mi_startup (void); -void cpu_initclocks (void *arg __unused); void nchinit (void); /* Finalize the world. */ diff --git a/sys/sys/types.h b/sys/sys/types.h index b65800a960..bdaa8a5f38 100644 --- a/sys/sys/types.h +++ b/sys/sys/types.h @@ -58,6 +58,9 @@ #ifndef _MACHINE_TYPES_H_ #include #endif +#ifndef _SYS__PTHREADTYPES_H_ +#include +#endif #ifndef _POSIX_SOURCE typedef unsigned char u_char; diff --git a/sys/sys/varsym.h b/sys/sys/varsym.h index ee5ef61000..f482fdbec7 100644 --- a/sys/sys/varsym.h +++ b/sys/sys/varsym.h @@ -52,7 +52,7 @@ struct varsymset { #define MAXVARSYM_NAME 64 #define MAXVARSYM_DATA 256 -#define MAXVARSYM_SET 8192 +#define MAXVARSYM_SET 16384 #ifdef _KERNEL diff --git a/sys/sys/vmmeter.h b/sys/sys/vmmeter.h index 264e5ffe0d..48baf2e4cb 100644 --- a/sys/sys/vmmeter.h +++ b/sys/sys/vmmeter.h @@ -54,6 +54,8 @@ struct vmmeter { u_int v_trap; /* calls to trap */ u_int v_syscall; /* calls to syscall() */ u_int v_intr; /* device interrupts */ + u_int v_ipi; /* inter processor interrupts */ + u_int v_timer; /* LAPIC timer interrupts */ u_int v_soft; /* software interrupts */ /* * Virtual memory activity. diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 0031e6c630..ce3f111426 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -314,16 +314,7 @@ struct vnode { /* * Modes. Note that these V-modes must match file S_I*USR, SUID, SGID, * and SVTX flag bits. - * - * VOWN, VCREATE, VDELETE, VRENAME, and VEXCL may only be used in - * naccess() calls. */ -#define VRENAME 0200000 /* set with VCREATE or VDELETE if rename */ -#define VOWN 0100000 /* succeed if file owner or (other flags) */ -#define VDELETE 040000 /* delete if the file/dir exists */ -#define VCREATE 020000 /* create if the file/dir does not exist */ -#define VEXCL 010000 /* error if the file/dir already exists */ - #define VSUID 04000 /* set user id on execution */ #define VSGID 02000 /* set group id on execution */ #define VSVTX 01000 /* save swapped text even after use */ diff --git a/sys/vfs/gnu/ext2fs/ext2_vnops.c b/sys/vfs/gnu/ext2fs/ext2_vnops.c index 7bf177ef14..5198a72299 100644 --- a/sys/vfs/gnu/ext2fs/ext2_vnops.c +++ b/sys/vfs/gnu/ext2fs/ext2_vnops.c @@ -1380,8 +1380,6 @@ ext2_access(struct vop_access_args *ap) /* Otherwise, check the owner. */ if (cred->cr_uid == ip->i_uid) { - if (mode & VOWN) - return (0); if (mode & VEXEC) mask |= S_IXUSR; if (mode & VREAD) diff --git a/sys/vfs/hammer/hammer.h b/sys/vfs/hammer/hammer.h index 04d4e94a95..40df11f131 100644 --- a/sys/vfs/hammer/hammer.h +++ b/sys/vfs/hammer/hammer.h @@ -296,6 +296,7 @@ struct hammer_inode { struct hammer_btree_leaf_elm ino_leaf; /* in-memory cache */ struct hammer_inode_data ino_data; /* in-memory cache */ struct hammer_rec_rb_tree rec_tree; /* in-memory cache */ + int rec_generation; struct hammer_node_cache cache[2]; /* search initiate cache */ /* @@ -1069,8 +1070,6 @@ hammer_off_t hammer_blockmap_alloc(hammer_transaction_t trans, int zone, int bytes, int *errorp); hammer_reserve_t hammer_blockmap_reserve(hammer_mount_t hmp, int zone, int bytes, hammer_off_t *zone_offp, int *errorp); -void hammer_blockmap_reserve_undo(hammer_mount_t hmp, hammer_reserve_t resv, - hammer_off_t zone_offset, int bytes); void hammer_blockmap_reserve_complete(hammer_mount_t hmp, hammer_reserve_t resv); void hammer_reserve_clrdelay(hammer_mount_t hmp, hammer_reserve_t resv); diff --git a/sys/vfs/hammer/hammer_blockmap.c b/sys/vfs/hammer/hammer_blockmap.c index d88d11faf7..069fff6673 100644 --- a/sys/vfs/hammer/hammer_blockmap.c +++ b/sys/vfs/hammer/hammer_blockmap.c @@ -565,19 +565,6 @@ failed: return(resv); } -#if 0 -/* - * Backend function - undo a portion of a reservation. - */ -void -hammer_blockmap_reserve_undo(hammer_mount_t hmp, hammer_reserve_t resv, - hammer_off_t zone_offset, int bytes) -{ - resv->bytes_freed += bytes; -} - -#endif - /* * Dereference a reservation structure. Upon the final release the * underlying big-block is checked and if it is entirely free we delete diff --git a/sys/vfs/hammer/hammer_btree.c b/sys/vfs/hammer/hammer_btree.c index 56a4b34459..d208df74b6 100644 --- a/sys/vfs/hammer/hammer_btree.c +++ b/sys/vfs/hammer/hammer_btree.c @@ -614,6 +614,10 @@ hammer_btree_lookup(hammer_cursor_t cursor) * Execute the logic required to start an iteration. The first record * located within the specified range is returned and iteration control * flags are adjusted for successive hammer_btree_iterate() calls. + * + * Set ATEDISK so a low-level caller can call btree_first/btree_iterate + * in a loop without worrying about it. Higher-level merged searches will + * adjust the flag appropriately. */ int hammer_btree_first(hammer_cursor_t cursor) @@ -634,6 +638,10 @@ hammer_btree_first(hammer_cursor_t cursor) * * Set ATEDISK when iterating backwards to skip the current entry, * which after an ENOENT lookup will be pointing beyond our end point. + * + * Set ATEDISK so a low-level caller can call btree_last/btree_iterate_reverse + * in a loop without worrying about it. Higher-level merged searches will + * adjust the flag appropriately. */ int hammer_btree_last(hammer_cursor_t cursor) @@ -2159,16 +2167,22 @@ btree_remove(hammer_cursor_t cursor) hammer_flush_node(node); hammer_delete_node(cursor->trans, node); } else { - kprintf("Warning: BTREE_REMOVE: Defering " - "parent removal1 @ %016llx, skipping\n", - node->node_offset); + /* + * Defer parent removal because we could not + * get the lock, just let the leaf remain + * empty. + */ + /**/ } hammer_unlock(&node->lock); hammer_rel_node(node); } else { - kprintf("Warning: BTREE_REMOVE: Defering parent " - "removal2 @ %016llx, skipping\n", - node->node_offset); + /* + * Defer parent removal because we could not + * get the lock, just let the leaf remain + * empty. + */ + /**/ } } else { KKASSERT(parent->ondisk->count > 1); diff --git a/sys/vfs/hammer/hammer_cursor.h b/sys/vfs/hammer/hammer_cursor.h index 332fa4a963..20e97219a0 100644 --- a/sys/vfs/hammer/hammer_cursor.h +++ b/sys/vfs/hammer/hammer_cursor.h @@ -107,6 +107,7 @@ struct hammer_cursor { * Iteration and extraction control variables */ int flags; + int rec_generation; /* * Merged in-memory/on-disk iterations also use these fields. @@ -138,6 +139,7 @@ typedef struct hammer_cursor *hammer_cursor_t; #define HAMMER_CURSOR_REBLOCKING 0x00020000 #define HAMMER_CURSOR_TRACKED 0x00040000 #define HAMMER_CURSOR_TRACKED_RIPOUT 0x00080000 +#define HAMMER_CURSOR_LASTWASMEM 0x00100000 /* hammer_ip_next logic */ /* * Flags we can clear when reusing a cursor (we can clear all of them) diff --git a/sys/vfs/hammer/hammer_inode.c b/sys/vfs/hammer/hammer_inode.c index 56aec8c862..a123dffdf1 100644 --- a/sys/vfs/hammer/hammer_inode.c +++ b/sys/vfs/hammer/hammer_inode.c @@ -47,10 +47,10 @@ static int hammer_setup_child_callback(hammer_record_t rec, void *data); #if 0 static int hammer_syncgrp_child_callback(hammer_record_t rec, void *data); #endif -static int hammer_setup_parent_inodes(hammer_inode_t ip, +static int hammer_setup_parent_inodes(hammer_inode_t ip, int depth, hammer_flush_group_t flg); static int hammer_setup_parent_inodes_helper(hammer_record_t record, - hammer_flush_group_t flg); + int depth, hammer_flush_group_t flg); static void hammer_inode_wakereclaims(hammer_inode_t ip, int dowake); #ifdef DEBUG_TRUNCATE @@ -251,6 +251,7 @@ hammer_get_vnode(struct hammer_inode *ip, struct vnode **vpp) hammer_lock_ex(&ip->lock); if (ip->vp != NULL) { hammer_unlock(&ip->lock); + vp = *vpp; vp->v_type = VBAD; vx_put(vp); continue; @@ -924,6 +925,9 @@ retry: cursor.asof = HAMMER_MAX_TID; cursor.flags |= HAMMER_CURSOR_ASOF; + /* + * Replace any in-memory version of the record. + */ error = hammer_ip_lookup(&cursor); if (error == 0 && hammer_cursor_inmem(&cursor)) { record = cursor.iprec; @@ -937,6 +941,11 @@ retry: error = 0; } } + + /* + * Allocate replacement general record. The backend flush will + * delete any on-disk version of the record. + */ if (error == 0 || error == ENOENT) { record = hammer_alloc_mem_record(ip, sizeof(pfsm->pfsd)); record->type = HAMMER_MEM_RECORD_GENERAL; @@ -1159,12 +1168,13 @@ retry: } /* - * The record isn't managed by the inode's record tree, - * destroy it whether we succeed or fail. + * Note: The record was never on the inode's record tree + * so just wave our hands importantly and destroy it. */ + record->flags |= HAMMER_RECF_COMMITTED; record->flags &= ~HAMMER_RECF_INTERLOCK_BE; - record->flags |= HAMMER_RECF_DELETED_FE | HAMMER_RECF_COMMITTED; record->flush_state = HAMMER_FST_IDLE; + ++ip->rec_generation; hammer_rel_mem_record(record); /* @@ -1391,8 +1401,9 @@ hammer_destroy_inode_callback(struct hammer_inode *ip, void *data __unused) KKASSERT(rec->lock.refs == 1); rec->flush_state = HAMMER_FST_IDLE; rec->flush_group = NULL; - rec->flags |= HAMMER_RECF_DELETED_FE; - rec->flags |= HAMMER_RECF_DELETED_BE; + rec->flags |= HAMMER_RECF_DELETED_FE; /* wave hands */ + rec->flags |= HAMMER_RECF_DELETED_BE; /* wave hands */ + ++ip->rec_generation; hammer_rel_mem_record(rec); } ip->flags &= ~HAMMER_INODE_MODMASK; @@ -1559,7 +1570,7 @@ hammer_flush_inode(hammer_inode_t ip, int flags) * can't flush, 0 means there weren't any dependancies, and * 1 means we have good connectivity. */ - good = hammer_setup_parent_inodes(ip, flg); + good = hammer_setup_parent_inodes(ip, 0, flg); if (good >= 0) { /* @@ -1611,20 +1622,47 @@ hammer_flush_inode(hammer_inode_t ip, int flags) * ref/rel code later, the rel CAN block. */ static int -hammer_setup_parent_inodes(hammer_inode_t ip, hammer_flush_group_t flg) +hammer_setup_parent_inodes(hammer_inode_t ip, int depth, + hammer_flush_group_t flg) { hammer_record_t depend; int good; int r; + /* + * If we hit our recursion limit and we have parent dependencies + * We cannot continue. Returning < 0 will cause us to be flagged + * for reflush. Returning -2 cuts off additional dependency checks + * because they are likely to also hit the depth limit. + * + * We cannot return < 0 if there are no dependencies or there might + * not be anything to wakeup (ip). + */ + if (depth == 20 && TAILQ_FIRST(&ip->target_list)) { + kprintf("HAMMER Warning: depth limit reached on " + "setup recursion, inode %p %016llx\n", + ip, (long long)ip->obj_id); + return(-2); + } + + /* + * Scan dependencies + */ good = 0; TAILQ_FOREACH(depend, &ip->target_list, target_entry) { - r = hammer_setup_parent_inodes_helper(depend, flg); + r = hammer_setup_parent_inodes_helper(depend, depth, flg); KKASSERT(depend->target_ip == ip); if (r < 0 && good == 0) good = -1; if (r > 0) good = 1; + + /* + * If we failed due to the recursion depth limit then stop + * now. + */ + if (r == -2) + break; } return(good); } @@ -1646,7 +1684,7 @@ hammer_setup_parent_inodes(hammer_inode_t ip, hammer_flush_group_t flg) * Return -1 if we can't resolve the dependancy and there is no connectivity. */ static int -hammer_setup_parent_inodes_helper(hammer_record_t record, +hammer_setup_parent_inodes_helper(hammer_record_t record, int depth, hammer_flush_group_t flg) { hammer_mount_t hmp; @@ -1689,19 +1727,25 @@ hammer_setup_parent_inodes_helper(hammer_record_t record, /* * It must be a setup record. Try to resolve the setup dependancies * by recursing upwards so we can place ip on the flush list. + * + * Limit ourselves to 20 levels of recursion to avoid blowing out + * the kernel stack. If we hit the recursion limit we can't flush + * until the parent flushes. The parent will flush independantly + * on its own and ultimately a deep recursion will be resolved. */ KKASSERT(record->flush_state == HAMMER_FST_SETUP); - good = hammer_setup_parent_inodes(pip, flg); + good = hammer_setup_parent_inodes(pip, depth + 1, flg); /* * If good < 0 the parent has no connectivity and we cannot safely * flush the directory entry, which also means we can't flush our - * ip. Flag the parent and us for downward recursion once the - * parent's connectivity is resolved. + * ip. Flag us for downward recursion once the parent's + * connectivity is resolved. Flag the parent for [re]flush or it + * may not check for downward recursions. */ if (good < 0) { - /* pip->flags |= HAMMER_INODE_CONN_DOWN; set by recursion */ + pip->flags |= HAMMER_INODE_REFLUSH; record->target_ip->flags |= HAMMER_INODE_CONN_DOWN; return(good); } @@ -1949,16 +1993,20 @@ hammer_setup_child_callback(hammer_record_t rec, void *data) int r; /* - * Deleted records are ignored. Note that the flush detects deleted - * front-end records at multiple points to deal with races. This is - * just the first line of defense. The only time DELETED_FE cannot - * be set is when HAMMER_RECF_INTERLOCK_BE is set. + * Records deleted or committed by the backend are ignored. + * Note that the flush detects deleted frontend records at + * multiple points to deal with races. This is just the first + * line of defense. The only time HAMMER_RECF_DELETED_FE cannot + * be set is when HAMMER_RECF_INTERLOCK_BE is set, because it + * messes up link-count calculations. * - * Don't get confused between record deletion and, say, directory - * entry deletion. The deletion of a directory entry that is on - * the media has nothing to do with the record deletion flags. + * NOTE: Don't get confused between record deletion and, say, + * directory entry deletion. The deletion of a directory entry + * which is on-media has nothing to do with the record deletion + * flags. */ - if (rec->flags & (HAMMER_RECF_DELETED_FE|HAMMER_RECF_DELETED_BE)) { + if (rec->flags & (HAMMER_RECF_DELETED_FE | HAMMER_RECF_DELETED_BE | + HAMMER_RECF_COMMITTED)) { if (rec->flush_state == HAMMER_FST_FLUSH) { KKASSERT(rec->flush_group == rec->ip->flush_group); r = 1; @@ -2343,9 +2391,9 @@ hammer_sync_record_callback(hammer_record_t record, void *data) record->flags |= HAMMER_RECF_INTERLOCK_BE; /* - * The backend may have already disposed of the record. + * The backend has already disposed of the record. */ - if (record->flags & HAMMER_RECF_DELETED_BE) { + if (record->flags & (HAMMER_RECF_DELETED_BE | HAMMER_RECF_COMMITTED)) { error = 0; goto done; } @@ -2369,8 +2417,13 @@ hammer_sync_record_callback(hammer_record_t record, void *data) */ /* fall through */ case HAMMER_MEM_RECORD_GENERAL: - record->flags |= HAMMER_RECF_DELETED_FE; + /* + * Set deleted-by-backend flag. Do not set the + * backend committed flag, because we are throwing + * the record away. + */ record->flags |= HAMMER_RECF_DELETED_BE; + ++record->ip->rec_generation; error = 0; goto done; case HAMMER_MEM_RECORD_ADD: @@ -2408,10 +2461,19 @@ hammer_sync_record_callback(hammer_record_t record, void *data) */ if (record->flags & HAMMER_RECF_DELETED_FE) { if (record->type == HAMMER_MEM_RECORD_ADD) { + /* + * Convert a front-end deleted directory-add to + * a directory-delete entry later. + */ record->flags |= HAMMER_RECF_CONVERT_DELETE; } else { + /* + * Dispose of the record (race case). Mark as + * deleted by backend (and not committed). + */ KKASSERT(record->type != HAMMER_MEM_RECORD_DEL); record->flags |= HAMMER_RECF_DELETED_BE; + ++record->ip->rec_generation; error = 0; goto done; } @@ -2421,9 +2483,10 @@ hammer_sync_record_callback(hammer_record_t record, void *data) * Assign the create_tid for new records. Deletions already * have the record's entire key properly set up. */ - if (record->type != HAMMER_MEM_RECORD_DEL) + if (record->type != HAMMER_MEM_RECORD_DEL) { record->leaf.base.create_tid = trans->tid; record->leaf.create_ts = trans->time32; + } for (;;) { error = hammer_ip_sync_record_cursor(cursor, record); if (error != EDEADLK) @@ -2515,7 +2578,10 @@ hammer_sync_inode(hammer_transaction_t trans, hammer_inode_t ip) } } else if ((depend->flags & HAMMER_RECF_DELETED_FE) == 0) { /* - * Not part of our flush group + * Not part of our flush group and not deleted by + * the front-end, adjust the link count synced to + * the media (undo what the frontend did when it + * queued the record). */ KKASSERT((depend->flags & HAMMER_RECF_DELETED_BE) == 0); switch(depend->type) { @@ -2719,8 +2785,8 @@ defer_buffer_flush: hammer_record_t record = RB_ROOT(&ip->rec_tree); hammer_ref(&record->lock); KKASSERT(record->lock.refs == 1); - record->flags |= HAMMER_RECF_DELETED_FE; record->flags |= HAMMER_RECF_DELETED_BE; + ++record->ip->rec_generation; hammer_rel_mem_record(record); } break; diff --git a/sys/vfs/hammer/hammer_io.c b/sys/vfs/hammer/hammer_io.c index 3fe2fea5b3..bcd6223b78 100644 --- a/sys/vfs/hammer/hammer_io.c +++ b/sys/vfs/hammer/hammer_io.c @@ -1252,7 +1252,8 @@ hammer_io_direct_write(hammer_mount_t hmp, hammer_record_t record, KKASSERT(error == 0); } else { /* - * Major suckage occured. + * Major suckage occured. Also note: The record was never added + * to the tree so we do not have to worry about the backend. */ kprintf("hammer_direct_write: failed @ %016llx\n", leaf->data_offset); diff --git a/sys/vfs/hammer/hammer_object.c b/sys/vfs/hammer/hammer_object.c index ee30f33011..1ec890a33d 100644 --- a/sys/vfs/hammer/hammer_object.c +++ b/sys/vfs/hammer/hammer_object.c @@ -37,7 +37,7 @@ #include "hammer.h" static int hammer_mem_lookup(hammer_cursor_t cursor); -static int hammer_mem_first(hammer_cursor_t cursor); +static void hammer_mem_first(hammer_cursor_t cursor); static int hammer_frontend_trunc_callback(hammer_record_t record, void *data __unused); static int hammer_bulk_scan_callback(hammer_record_t record, void *data); @@ -72,7 +72,10 @@ hammer_rec_rb_compare(hammer_record_t rec1, hammer_record_t rec2) return(1); /* - * Never match against an item deleted by the front-end. + * For search & insertion purposes records deleted by the + * frontend or deleted/committed by the backend are silently + * ignored. Otherwise pipelined insertions will get messed + * up. * * rec1 is greater then rec2 if rec1 is marked deleted. * rec1 is less then rec2 if rec2 is marked deleted. @@ -80,10 +83,14 @@ hammer_rec_rb_compare(hammer_record_t rec1, hammer_record_t rec2) * Multiple deleted records may be present, do not return 0 * if both are marked deleted. */ - if (rec1->flags & HAMMER_RECF_DELETED_FE) + if (rec1->flags & (HAMMER_RECF_DELETED_FE | HAMMER_RECF_DELETED_BE | + HAMMER_RECF_COMMITTED)) { return(1); - if (rec2->flags & HAMMER_RECF_DELETED_FE) + } + if (rec2->flags & (HAMMER_RECF_DELETED_FE | HAMMER_RECF_DELETED_BE | + HAMMER_RECF_COMMITTED)) { return(-1); + } return(0); } @@ -105,11 +112,15 @@ hammer_rec_cmp(hammer_base_elm_t elm, hammer_record_t rec) return(2); /* - * Never match against an item deleted by the front-end. + * Never match against an item deleted by the frontend + * or backend, or committed by the backend. + * * elm is less then rec if rec is marked deleted. */ - if (rec->flags & HAMMER_RECF_DELETED_FE) + if (rec->flags & (HAMMER_RECF_DELETED_FE | HAMMER_RECF_DELETED_BE | + HAMMER_RECF_COMMITTED)) { return(-1); + } return(0); } @@ -295,11 +306,11 @@ hammer_flush_record_done(hammer_record_t record, int error) KKASSERT(record->flush_state == HAMMER_FST_FLUSH); KKASSERT(record->flags & HAMMER_RECF_INTERLOCK_BE); + /* + * If an error occured, the backend was unable to sync the + * record to its media. Leave the record intact. + */ if (error) { - /* - * An error occured, the backend was unable to sync the - * record to its media. Leave the record intact. - */ hammer_critical_error(record->ip->hmp, record->ip, error, "while flushing record"); } @@ -307,7 +318,11 @@ hammer_flush_record_done(hammer_record_t record, int error) --record->flush_group->refs; record->flush_group = NULL; - if (record->flags & HAMMER_RECF_DELETED_BE) { + /* + * Adjust the flush state and dependancy based on success or + * failure. + */ + if (record->flags & (HAMMER_RECF_DELETED_BE | HAMMER_RECF_COMMITTED)) { if ((target_ip = record->target_ip) != NULL) { TAILQ_REMOVE(&target_ip->target_list, record, target_entry); @@ -325,6 +340,10 @@ hammer_flush_record_done(hammer_record_t record, int error) } } record->flags &= ~HAMMER_RECF_INTERLOCK_BE; + + /* + * Cleanup + */ if (record->flags & HAMMER_RECF_WANTED) { record->flags &= ~HAMMER_RECF_WANTED; wakeup(record); @@ -361,9 +380,12 @@ hammer_rel_mem_record(struct hammer_record *record) /* * Upon release of the last reference a record marked deleted + * by the front or backend, or committed by the backend, * is destroyed. */ - if (record->flags & HAMMER_RECF_DELETED_FE) { + if (record->flags & (HAMMER_RECF_DELETED_FE | + HAMMER_RECF_DELETED_BE | + HAMMER_RECF_COMMITTED)) { KKASSERT(ip->lock.refs > 0); KKASSERT(record->flush_state != HAMMER_FST_FLUSH); @@ -422,19 +444,16 @@ hammer_rel_mem_record(struct hammer_record *record) } /* - * Release the reservation. If the record was not - * committed return the reservation before - * releasing it. + * Release the reservation. + * + * If the record was not committed we can theoretically + * undo the reservation. However, doing so might + * create weird edge cases with the ordering of + * direct writes because the related buffer cache + * elements are per-vnode. So we don't try. */ if ((resv = record->resv) != NULL) { -#if 0 - if ((record->flags & HAMMER_RECF_COMMITTED) == 0) { - hammer_blockmap_reserve_undo( - hmp, resv, - record->leaf.data_offset, - record->leaf.data_len); - } -#endif + /* XXX undo leaf.data_offset,leaf.data_len */ hammer_blockmap_reserve_complete(hmp, resv); record->resv = NULL; } @@ -447,10 +466,14 @@ hammer_rel_mem_record(struct hammer_record *record) /* * Record visibility depends on whether the record is being accessed by - * the backend or the frontend. + * the backend or the frontend. Backend tests ignore the frontend delete + * flag. Frontend tests do NOT ignore the backend delete/commit flags and + * must also check for commit races. * * Return non-zero if the record is visible, zero if it isn't or if it is - * deleted. + * deleted. Returns 0 if the record has been comitted (unless the special + * delete-visibility flag is set). A committed record must be located + * via the media B-Tree. Returns non-zero if the record is good. * * If HAMMER_CURSOR_DELETE_VISIBILITY is set we allow deleted memory * records to be returned. This is so pending deletions are detected @@ -464,11 +487,16 @@ hammer_ip_iterate_mem_good(hammer_cursor_t cursor, hammer_record_t record) if (cursor->flags & HAMMER_CURSOR_DELETE_VISIBILITY) return(1); if (cursor->flags & HAMMER_CURSOR_BACKEND) { - if (record->flags & HAMMER_RECF_DELETED_BE) + if (record->flags & (HAMMER_RECF_DELETED_BE | + HAMMER_RECF_COMMITTED)) { return(0); + } } else { - if (record->flags & HAMMER_RECF_DELETED_FE) + if (record->flags & (HAMMER_RECF_DELETED_FE | + HAMMER_RECF_DELETED_BE | + HAMMER_RECF_COMMITTED)) { return(0); + } } return(1); } @@ -494,7 +522,7 @@ hammer_rec_scan_callback(hammer_record_t rec, void *data) KKASSERT(cursor->iprec == NULL); /* - * Skip if the record was marked deleted. + * Skip if the record was marked deleted or committed. */ if (hammer_ip_iterate_mem_good(cursor, rec) == 0) return(0); @@ -518,7 +546,8 @@ hammer_rec_scan_callback(hammer_record_t rec, void *data) hammer_ref(&rec->lock); /* - * The record may have been deleted while we were blocked. + * The record may have been deleted or committed while we + * were blocked. XXX remove? */ if (hammer_ip_iterate_mem_good(cursor, rec) == 0) { hammer_rel_mem_record(rec); @@ -539,13 +568,13 @@ hammer_rec_scan_callback(hammer_record_t rec, void *data) * record list. * * The lookup must fail if the record is marked for deferred deletion. + * + * The API for mem/btree_lookup() does not mess with the ATE/EOF bits. */ static int hammer_mem_lookup(hammer_cursor_t cursor) { - int error; - KKASSERT(cursor->ip); if (cursor->iprec) { hammer_rel_mem_record(cursor->iprec); @@ -554,19 +583,18 @@ hammer_mem_lookup(hammer_cursor_t cursor) hammer_rec_rb_tree_RB_SCAN(&cursor->ip->rec_tree, hammer_rec_find_cmp, hammer_rec_scan_callback, cursor); - if (cursor->iprec == NULL) - error = ENOENT; - else - error = 0; - return(error); + return (cursor->iprec ? 0 : ENOENT); } /* * hammer_mem_first() - locate the first in-memory record matching the * cursor within the bounds of the key range. + * + * WARNING! API is slightly different from btree_first(). hammer_mem_first() + * will set ATEMEM the same as MEMEOF, and does not return any error. */ static -int +void hammer_mem_first(hammer_cursor_t cursor) { hammer_inode_t ip; @@ -578,17 +606,13 @@ hammer_mem_first(hammer_cursor_t cursor) hammer_rel_mem_record(cursor->iprec); cursor->iprec = NULL; } - hammer_rec_rb_tree_RB_SCAN(&ip->rec_tree, hammer_rec_scan_cmp, hammer_rec_scan_callback, cursor); - /* - * Adjust scan.node and keep it linked into the RB-tree so we can - * hold the cursor through third party modifications of the RB-tree. - */ if (cursor->iprec) - return(0); - return(ENOENT); + cursor->flags &= ~(HAMMER_CURSOR_MEMEOF | HAMMER_CURSOR_ATEMEM); + else + cursor->flags |= HAMMER_CURSOR_MEMEOF | HAMMER_CURSOR_ATEMEM; } /************************************************************************ @@ -635,6 +659,7 @@ hammer_ip_add_directory(struct hammer_transaction *trans, bcopy(name, record->data->entry.name, bytes); ++ip->ino_data.nlinks; + ip->ino_data.ctime = trans->time; hammer_modify_inode(ip, HAMMER_INODE_DDIRTY); /* @@ -720,15 +745,18 @@ hammer_ip_del_directory(struct hammer_transaction *trans, if (hammer_cursor_inmem(cursor)) { /* * In-memory (unsynchronized) records can simply be freed. + * * Even though the HAMMER_RECF_DELETED_FE flag is ignored * by the backend, we must still avoid races against the - * backend potentially syncing the record to the media. + * backend potentially syncing the record to the media. * * We cannot call hammer_ip_delete_record(), that routine may * only be called from the backend. */ record = cursor->iprec; - if (record->flags & HAMMER_RECF_INTERLOCK_BE) { + if (record->flags & (HAMMER_RECF_INTERLOCK_BE | + HAMMER_RECF_DELETED_BE | + HAMMER_RECF_COMMITTED)) { KKASSERT(cursor->deadlk_rec == NULL); hammer_ref(&record->lock); cursor->deadlk_rec = record; @@ -796,8 +824,10 @@ hammer_ip_del_directory(struct hammer_transaction *trans, * on-media until we unmount. */ if (error == 0) { - if (ip) + if (ip) { --ip->ino_data.nlinks; /* do before we might block */ + ip->ino_data.ctime = trans->time; + } dip->ino_data.mtime = trans->time; hammer_modify_inode(dip, HAMMER_INODE_MTIME); if (ip) { @@ -880,8 +910,10 @@ hammer_bulk_scan_callback(hammer_record_t record, void *data) { struct hammer_bulk_info *info = data; - if (record->flags & HAMMER_RECF_DELETED_FE) + if (record->flags & (HAMMER_RECF_DELETED_FE | HAMMER_RECF_DELETED_BE | + HAMMER_RECF_COMMITTED)) { return(0); + } hammer_ref(&record->lock); info->record = record; return(-1); /* stop scan */ @@ -1125,9 +1157,9 @@ hammer_ip_sync_record_cursor(hammer_cursor_t cursor, hammer_record_t record) error = hammer_ip_delete_record(cursor, record->ip, trans->tid); if (error == 0) { - record->flags |= HAMMER_RECF_DELETED_FE; - record->flags |= HAMMER_RECF_DELETED_BE; - record->flags |= HAMMER_RECF_COMMITTED; + record->flags |= HAMMER_RECF_DELETED_BE | + HAMMER_RECF_COMMITTED; + ++record->ip->rec_generation; } } goto done; @@ -1207,11 +1239,13 @@ hammer_ip_sync_record_cursor(hammer_cursor_t cursor, hammer_record_t record) kprintf("BTREE INSERT error %d @ %016llx:%d key %016llx\n", error, cursor->node->node_offset, cursor->index, record->leaf.base.key); /* - * Our record is on-disk, normally mark the in-memory version as - * deleted. If the record represented a directory deletion but - * we had to sync a valid directory entry to disk we must convert - * the record to a covering delete so the frontend does not have - * visibility on the synced entry. + * Our record is on-disk and we normally mark the in-memory version + * as having been committed (and not BE-deleted). + * + * If the record represented a directory deletion but we had to + * sync a valid directory entry to disk due to dependancies, + * we must convert the record to a covering delete so the + * frontend does not have visibility on the synced entry. */ if (error == 0) { if (doprop) { @@ -1220,17 +1254,27 @@ hammer_ip_sync_record_cursor(hammer_cursor_t cursor, hammer_record_t record) &record->leaf); } if (record->flags & HAMMER_RECF_CONVERT_DELETE) { + /* + * Must convert deleted directory entry add + * to a directory entry delete. + */ KKASSERT(record->type == HAMMER_MEM_RECORD_ADD); record->flags &= ~HAMMER_RECF_DELETED_FE; record->type = HAMMER_MEM_RECORD_DEL; KKASSERT(record->flush_state == HAMMER_FST_FLUSH); record->flags &= ~HAMMER_RECF_CONVERT_DELETE; + KKASSERT((record->flags & (HAMMER_RECF_COMMITTED | + HAMMER_RECF_DELETED_BE)) == 0); + /* converted record is not yet committed */ /* hammer_flush_record_done takes care of the rest */ } else { - record->flags |= HAMMER_RECF_DELETED_FE; - record->flags |= HAMMER_RECF_DELETED_BE; + /* + * Everything went fine and we are now done with + * this record. + */ + record->flags |= HAMMER_RECF_COMMITTED; + ++record->ip->rec_generation; } - record->flags |= HAMMER_RECF_COMMITTED; } else { if (record->leaf.data_offset) { hammer_blockmap_free(trans, record->leaf.data_offset, @@ -1328,6 +1372,101 @@ hammer_ip_lookup(hammer_cursor_t cursor) return(error); } +/* + * Helper for hammer_ip_first()/hammer_ip_next() + * + * NOTE: Both ATEDISK and DISKEOF will be set the same. This sets up + * hammer_ip_first() for calling hammer_ip_next(), and sets up the re-seek + * state if hammer_ip_next() needs to re-seek. + */ +static __inline +int +_hammer_ip_seek_btree(hammer_cursor_t cursor) +{ + hammer_inode_t ip = cursor->ip; + int error; + + if (ip->flags & (HAMMER_INODE_ONDISK|HAMMER_INODE_DONDISK)) { + error = hammer_btree_lookup(cursor); + if (error == ENOENT || error == EDEADLK) { + if (hammer_debug_general & 0x2000) + kprintf("error %d node %p %016llx index %d\n", error, cursor->node, cursor->node->node_offset, cursor->index); + cursor->flags &= ~HAMMER_CURSOR_ATEDISK; + error = hammer_btree_iterate(cursor); + } + if (error == 0) { + cursor->flags &= ~(HAMMER_CURSOR_DISKEOF | + HAMMER_CURSOR_ATEDISK); + } else { + cursor->flags |= HAMMER_CURSOR_DISKEOF | + HAMMER_CURSOR_ATEDISK; + if (error == ENOENT) + error = 0; + } + } else { + cursor->flags |= HAMMER_CURSOR_DISKEOF | HAMMER_CURSOR_ATEDISK; + error = 0; + } + return(error); +} + +/* + * Helper for hammer_ip_next() + * + * The caller has determined that the media cursor is further along than the + * memory cursor and must be reseeked after a generation number change. + */ +static +int +_hammer_ip_reseek(hammer_cursor_t cursor) +{ + struct hammer_base_elm save; + hammer_btree_elm_t elm; + int error; + int r; + int again = 0; + + /* + * Do the re-seek. + */ + kprintf("HAMMER: Debug: re-seeked during scan @ino=%016llx\n", + (long long)cursor->ip->obj_id); + save = cursor->key_beg; + cursor->key_beg = cursor->iprec->leaf.base; + error = _hammer_ip_seek_btree(cursor); + KKASSERT(error == 0); + cursor->key_beg = save; + + /* + * If the memory record was previous returned to + * the caller and the media record matches + * (-1/+1: only create_tid differs), then iterate + * the media record to avoid a double result. + */ + if ((cursor->flags & HAMMER_CURSOR_ATEDISK) == 0 && + (cursor->flags & HAMMER_CURSOR_LASTWASMEM)) { + elm = &cursor->node->ondisk->elms[cursor->index]; + r = hammer_btree_cmp(&elm->base, + &cursor->iprec->leaf.base); + if (cursor->flags & HAMMER_CURSOR_ASOF) { + if (r >= -1 && r <= 1) { + kprintf("HAMMER: Debug: iterated after " + "re-seek (asof r=%d)\n", r); + cursor->flags |= HAMMER_CURSOR_ATEDISK; + again = 1; + } + } else { + if (r == 0) { + kprintf("HAMMER: Debug: iterated after " + "re-seek\n"); + cursor->flags |= HAMMER_CURSOR_ATEDISK; + again = 1; + } + } + } + return(again); +} + /* * Locate the first record within the cursor's key_beg/key_end range, * restricted to a particular inode. 0 is returned on success, ENOENT @@ -1339,6 +1478,7 @@ hammer_ip_lookup(hammer_cursor_t cursor) * This function can return EDEADLK, requiring the caller to terminate * the cursor and try again. */ + int hammer_ip_first(hammer_cursor_t cursor) { @@ -1351,62 +1491,30 @@ hammer_ip_first(hammer_cursor_t cursor) * Clean up fields and setup for merged scan */ cursor->flags &= ~HAMMER_CURSOR_RETEST; - cursor->flags |= HAMMER_CURSOR_ATEDISK | HAMMER_CURSOR_ATEMEM; - cursor->flags |= HAMMER_CURSOR_DISKEOF | HAMMER_CURSOR_MEMEOF; - if (cursor->iprec) { - hammer_rel_mem_record(cursor->iprec); - cursor->iprec = NULL; - } /* - * Search the on-disk B-Tree. hammer_btree_lookup() only does an - * exact lookup so if we get ENOENT we have to call the iterate - * function to validate the first record after the begin key. - * - * The ATEDISK flag is used by hammer_btree_iterate to determine - * whether it must index forwards or not. It is also used here - * to select the next record from in-memory or on-disk. + * Search the in-memory record list (Red-Black tree). Unlike the + * B-Tree search, mem_first checks for records in the range. * - * EDEADLK can only occur if the lookup hit an empty internal - * element and couldn't delete it. Since this could only occur - * in-range, we can just iterate from the failure point. + * This function will setup both ATEMEM and MEMEOF properly for + * the ip iteration. ATEMEM will be set if MEMEOF is set. */ - if (ip->flags & (HAMMER_INODE_ONDISK|HAMMER_INODE_DONDISK)) { - error = hammer_btree_lookup(cursor); - if (error == ENOENT || error == EDEADLK) { - cursor->flags &= ~HAMMER_CURSOR_ATEDISK; - if (hammer_debug_general & 0x2000) - kprintf("error %d node %p %016llx index %d\n", error, cursor->node, cursor->node->node_offset, cursor->index); - error = hammer_btree_iterate(cursor); - } - if (error && error != ENOENT) - return(error); - if (error == 0) { - cursor->flags &= ~HAMMER_CURSOR_DISKEOF; - cursor->flags &= ~HAMMER_CURSOR_ATEDISK; - } else { - cursor->flags |= HAMMER_CURSOR_ATEDISK; - } - } + hammer_mem_first(cursor); /* - * Search the in-memory record list (Red-Black tree). Unlike the - * B-Tree search, mem_first checks for records in the range. + * Detect generation changes during blockages, including + * blockages which occur on the initial btree search. */ - error = hammer_mem_first(cursor); - if (error && error != ENOENT) - return(error); - if (error == 0) { - cursor->flags &= ~HAMMER_CURSOR_MEMEOF; - cursor->flags &= ~HAMMER_CURSOR_ATEMEM; - if (hammer_ip_iterate_mem_good(cursor, cursor->iprec) == 0) - cursor->flags |= HAMMER_CURSOR_ATEMEM; - } + cursor->rec_generation = cursor->ip->rec_generation; /* - * This will return the first matching record. + * Initial search and result */ - return(hammer_ip_next(cursor)); + error = _hammer_ip_seek_btree(cursor); + if (error == 0) + error = hammer_ip_next(cursor); + + return (error); } /* @@ -1414,6 +1522,9 @@ hammer_ip_first(hammer_cursor_t cursor) * cursor. This call may be made multiple times after the cursor has been * initially searched with hammer_ip_first(). * + * There are numerous special cases in this code to deal with races between + * in-memory records and on-media records. + * * 0 is returned on success, ENOENT if no further records match the * requested range, or some other error code is returned. */ @@ -1421,51 +1532,97 @@ int hammer_ip_next(hammer_cursor_t cursor) { hammer_btree_elm_t elm; - hammer_record_t rec, save; + hammer_record_t rec; + hammer_record_t tmprec; int error; int r; -next_btree: +again: /* - * Load the current on-disk and in-memory record. If we ate any - * records we have to get the next one. - * - * If we deleted the last on-disk record we had scanned ATEDISK will - * be clear and RETEST will be set, forcing a call to iterate. The - * fact that ATEDISK is clear causes iterate to re-test the 'current' - * element. If ATEDISK is set, iterate will skip the 'current' - * element. - * * Get the next on-disk record + * + * NOTE: If we deleted the last on-disk record we had scanned + * ATEDISK will be clear and RETEST will be set, forcing + * a call to iterate. The fact that ATEDISK is clear causes + * iterate to re-test the 'current' element. If ATEDISK is + * set, iterate will skip the 'current' element. */ - if (cursor->flags & (HAMMER_CURSOR_ATEDISK|HAMMER_CURSOR_RETEST)) { - if ((cursor->flags & HAMMER_CURSOR_DISKEOF) == 0) { + error = 0; + if ((cursor->flags & HAMMER_CURSOR_DISKEOF) == 0) { + if (cursor->flags & (HAMMER_CURSOR_ATEDISK | + HAMMER_CURSOR_RETEST)) { error = hammer_btree_iterate(cursor); cursor->flags &= ~HAMMER_CURSOR_RETEST; if (error == 0) { cursor->flags &= ~HAMMER_CURSOR_ATEDISK; hammer_cache_node(&cursor->ip->cache[1], cursor->node); - } else { + } else if (error == ENOENT) { cursor->flags |= HAMMER_CURSOR_DISKEOF | HAMMER_CURSOR_ATEDISK; + error = 0; } } } -next_memory: /* - * Get the next in-memory record. + * If the generation changed the backend has deleted or committed + * one or more memory records since our last check. + * + * When this case occurs if the disk cursor is > current memory record + * or the disk cursor is at EOF, we must re-seek the disk-cursor. + * Since the cursor is ahead it must have not yet been eaten (if + * not at eof anyway). (XXX data offset case?) + * + * NOTE: we are not doing a full check here. That will be handled + * later on. + * + * If we have exhausted all memory records we do not have to do any + * further seeks. + */ + while (cursor->rec_generation != cursor->ip->rec_generation && + error == 0 + ) { + kprintf("HAMMER: Debug: generation changed during scan @ino=%016llx\n", (long long)cursor->ip->obj_id); + cursor->rec_generation = cursor->ip->rec_generation; + if (cursor->flags & HAMMER_CURSOR_MEMEOF) + break; + if (cursor->flags & HAMMER_CURSOR_DISKEOF) { + r = 1; + } else { + KKASSERT((cursor->flags & HAMMER_CURSOR_ATEDISK) == 0); + elm = &cursor->node->ondisk->elms[cursor->index]; + r = hammer_btree_cmp(&elm->base, + &cursor->iprec->leaf.base); + } + + /* + * Do we re-seek the media cursor? + */ + if (r > 0) { + if (_hammer_ip_reseek(cursor)) + goto again; + } + } + + /* + * We can now safely get the next in-memory record. We cannot + * block here. * * hammer_rec_scan_cmp: Is the record still in our general range, * (non-inclusive of snapshot exclusions)? * hammer_rec_scan_callback: Is the record in our snapshot? */ - if (cursor->flags & HAMMER_CURSOR_ATEMEM) { - if ((cursor->flags & HAMMER_CURSOR_MEMEOF) == 0) { - save = cursor->iprec; + tmprec = NULL; + if ((cursor->flags & HAMMER_CURSOR_MEMEOF) == 0) { + /* + * If the current memory record was eaten then get the next + * one. Stale records are skipped. + */ + if (cursor->flags & HAMMER_CURSOR_ATEMEM) { + tmprec = cursor->iprec; cursor->iprec = NULL; - rec = save ? hammer_rec_rb_tree_RB_NEXT(save) : NULL; + rec = hammer_rec_rb_tree_RB_NEXT(tmprec); while (rec) { if (hammer_rec_scan_cmp(rec, cursor) != 0) break; @@ -1473,28 +1630,39 @@ next_memory: break; rec = hammer_rec_rb_tree_RB_NEXT(rec); } - if (save) - hammer_rel_mem_record(save); if (cursor->iprec) { KKASSERT(cursor->iprec == rec); cursor->flags &= ~HAMMER_CURSOR_ATEMEM; } else { cursor->flags |= HAMMER_CURSOR_MEMEOF; } + cursor->flags &= ~HAMMER_CURSOR_LASTWASMEM; } } /* - * The memory record may have become stale while being held in - * cursor->iprec. We are interlocked against the backend on - * with regards to B-Tree entries. + * MEMORY RECORD VALIDITY TEST + * + * (We still can't block, which is why tmprec is being held so + * long). + * + * If the memory record is no longer valid we skip it. It may + * have been deleted by the frontend. If it was deleted or + * committed by the backend the generation change re-seeked the + * disk cursor and the record will be present there. */ - if ((cursor->flags & HAMMER_CURSOR_ATEMEM) == 0) { - if (hammer_ip_iterate_mem_good(cursor, cursor->iprec) == 0) { + if (error == 0 && (cursor->flags & HAMMER_CURSOR_MEMEOF) == 0) { + KKASSERT(cursor->iprec); + KKASSERT((cursor->flags & HAMMER_CURSOR_ATEMEM) == 0); + if (!hammer_ip_iterate_mem_good(cursor, cursor->iprec)) { cursor->flags |= HAMMER_CURSOR_ATEMEM; - goto next_memory; + if (tmprec) + hammer_rel_mem_record(tmprec); + goto again; } } + if (tmprec) + hammer_rel_mem_record(tmprec); /* * Extract either the disk or memory record depending on their @@ -1531,6 +1699,7 @@ next_memory: error = hammer_btree_extract(cursor, HAMMER_CURSOR_GET_LEAF); cursor->flags |= HAMMER_CURSOR_ATEDISK; + cursor->flags &= ~HAMMER_CURSOR_LASTWASMEM; break; } @@ -1557,7 +1726,7 @@ next_memory: if ((cursor->flags & HAMMER_CURSOR_DELETE_VISIBILITY) == 0) { cursor->flags |= HAMMER_CURSOR_ATEDISK; cursor->flags |= HAMMER_CURSOR_ATEMEM; - goto next_btree; + goto again; } } else if (cursor->iprec->type == HAMMER_MEM_RECORD_DATA) { if ((cursor->flags & HAMMER_CURSOR_DELETE_VISIBILITY) == 0) { @@ -1567,7 +1736,7 @@ next_memory: } else { panic("hammer_ip_next: duplicate mem/b-tree entry %p %d %08x", cursor->iprec, cursor->iprec->type, cursor->iprec->flags); cursor->flags |= HAMMER_CURSOR_ATEMEM; - goto next_memory; + goto again; } } /* fall through to the memory entry */ @@ -1577,6 +1746,7 @@ next_memory: */ cursor->leaf = &cursor->iprec->leaf; cursor->flags |= HAMMER_CURSOR_ATEMEM; + cursor->flags |= HAMMER_CURSOR_LASTWASMEM; /* * If the memory entry is an on-disk deletion we should have @@ -1595,6 +1765,7 @@ next_memory: */ error = hammer_btree_extract(cursor, HAMMER_CURSOR_GET_LEAF); cursor->flags |= HAMMER_CURSOR_ATEDISK; + cursor->flags &= ~HAMMER_CURSOR_LASTWASMEM; break; default: /* @@ -1602,6 +1773,7 @@ next_memory: * * XXX error not set properly */ + cursor->flags &= ~HAMMER_CURSOR_LASTWASMEM; cursor->leaf = NULL; error = ENOENT; break; @@ -1977,6 +2149,8 @@ hammer_ip_delete_record(hammer_cursor_t cursor, hammer_inode_t ip, KKASSERT((iprec->flags & HAMMER_RECF_INTERLOCK_BE) ==0); iprec->flags |= HAMMER_RECF_DELETED_FE; iprec->flags |= HAMMER_RECF_DELETED_BE; + KKASSERT(iprec->ip == ip); + ++ip->rec_generation; return(0); } diff --git a/sys/vfs/hammer/hammer_vnops.c b/sys/vfs/hammer/hammer_vnops.c index 220a7d5968..bcb481f06d 100644 --- a/sys/vfs/hammer/hammer_vnops.c +++ b/sys/vfs/hammer/hammer_vnops.c @@ -1626,6 +1626,7 @@ hammer_vop_nrename(struct vop_nrename_args *ap) ip); if (error == 0) { ip->ino_data.parent_obj_id = tdip->obj_id; + ip->ino_data.ctime = trans.time; hammer_modify_inode(ip, HAMMER_INODE_DDIRTY); } } @@ -1813,6 +1814,7 @@ hammer_vop_setattr(struct vop_setattr_args *ap) if (error == 0) { if (ip->ino_data.uflags != flags) { ip->ino_data.uflags = flags; + ip->ino_data.ctime = trans.time; modflags |= HAMMER_INODE_DDIRTY; kflags |= NOTE_ATTRIB; } @@ -1849,8 +1851,9 @@ hammer_vop_setattr(struct vop_setattr_args *ap) ip->ino_data.uid = uuid_uid; ip->ino_data.gid = uuid_gid; ip->ino_data.mode = cur_mode; + ip->ino_data.ctime = trans.time; + modflags |= HAMMER_INODE_DDIRTY; } - modflags |= HAMMER_INODE_DDIRTY; kflags |= NOTE_ATTRIB; } } @@ -1875,7 +1878,8 @@ hammer_vop_setattr(struct vop_setattr_args *ap) kflags |= NOTE_WRITE | NOTE_EXTEND; } ip->ino_data.size = vap->va_size; - modflags |= HAMMER_INODE_DDIRTY; + ip->ino_data.mtime = trans.time; + modflags |= HAMMER_INODE_MTIME | HAMMER_INODE_DDIRTY; /* * on-media truncation is cached in the inode until @@ -1946,7 +1950,8 @@ hammer_vop_setattr(struct vop_setattr_args *ap) } hammer_ip_frontend_trunc(ip, vap->va_size); ip->ino_data.size = vap->va_size; - modflags |= HAMMER_INODE_DDIRTY; + ip->ino_data.mtime = trans.time; + modflags |= HAMMER_INODE_MTIME | HAMMER_INODE_DDIRTY; kflags |= NOTE_ATTRIB; break; default: @@ -1956,14 +1961,12 @@ hammer_vop_setattr(struct vop_setattr_args *ap) break; } if (vap->va_atime.tv_sec != VNOVAL) { - ip->ino_data.atime = - hammer_timespec_to_time(&vap->va_atime); + ip->ino_data.atime = hammer_timespec_to_time(&vap->va_atime); modflags |= HAMMER_INODE_ATIME; kflags |= NOTE_ATTRIB; } if (vap->va_mtime.tv_sec != VNOVAL) { - ip->ino_data.mtime = - hammer_timespec_to_time(&vap->va_mtime); + ip->ino_data.mtime = hammer_timespec_to_time(&vap->va_mtime); modflags |= HAMMER_INODE_MTIME; kflags |= NOTE_ATTRIB; } @@ -1976,6 +1979,7 @@ hammer_vop_setattr(struct vop_setattr_args *ap) cur_uid, cur_gid, &cur_mode); if (error == 0 && ip->ino_data.mode != cur_mode) { ip->ino_data.mode = cur_mode; + ip->ino_data.ctime = trans.time; modflags |= HAMMER_INODE_DDIRTY; kflags |= NOTE_ATTRIB; } diff --git a/sys/vfs/hpfs/hpfs_vnops.c b/sys/vfs/hpfs/hpfs_vnops.c index 181c9e5c74..08469b64f8 100644 --- a/sys/vfs/hpfs/hpfs_vnops.c +++ b/sys/vfs/hpfs/hpfs_vnops.c @@ -750,8 +750,6 @@ hpfs_access(struct vop_access_args *ap) /* Otherwise, check the owner. */ if (cred->cr_uid == hp->h_uid) { - if (mode & VOWN) - return (0); if (mode & VEXEC) mask |= S_IXUSR; if (mode & VREAD) diff --git a/sys/vfs/msdosfs/msdosfs_vnops.c b/sys/vfs/msdosfs/msdosfs_vnops.c index 045d7429f3..0a2052b6ab 100644 --- a/sys/vfs/msdosfs/msdosfs_vnops.c +++ b/sys/vfs/msdosfs/msdosfs_vnops.c @@ -280,8 +280,6 @@ msdosfs_access(struct vop_access_args *ap) /* Otherwise, check the owner. */ if (cred->cr_uid == pmp->pm_uid) { - if (mode & VOWN) - return (0); if (mode & VEXEC) mask |= S_IXUSR; if (mode & VREAD) diff --git a/sys/vfs/nfs/nfs_serv.c b/sys/vfs/nfs/nfs_serv.c index 4b2f1df018..06121293d7 100644 --- a/sys/vfs/nfs/nfs_serv.c +++ b/sys/vfs/nfs/nfs_serv.c @@ -452,7 +452,7 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, pubflag = nfs_ispublicfh(fhp); - error = nfs_namei(&nd, cred, NAMEI_LOOKUP, NULL, &vp, + error = nfs_namei(&nd, cred, 0, NULL, &vp, fhp, len, slp, nam, &md, &dpos, &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), pubflag); @@ -1579,7 +1579,7 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, * be valid at all if an error occurs so we have to invalidate it * prior to calling nfsm_reply ( which might goto nfsmout ). */ - error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp, + error = nfs_namei(&nd, cred, NLC_CREATE, &dvp, &vp, fhp, len, slp, nam, &md, &dpos, &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); mp = vfs_getvfs(&fhp->fh_fsid); @@ -1851,7 +1851,7 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, * nfsmout. */ - error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp, + error = nfs_namei(&nd, cred, NLC_CREATE, &dvp, &vp, fhp, len, slp, nam, &md, &dpos, &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); if (dirp) @@ -1988,7 +1988,7 @@ nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, nfsm_srvmtofh(fhp); nfsm_srvnamesiz(len); - error = nfs_namei(&nd, cred, NAMEI_DELETE, &dvp, &vp, + error = nfs_namei(&nd, cred, NLC_DELETE, &dvp, &vp, fhp, len, slp, nam, &md, &dpos, &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); if (dirp) { @@ -2093,7 +2093,8 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, * the second nfs_namei() call, in case it is remapped. */ saved_uid = cred->cr_uid; - error = nfs_namei(&fromnd, cred, NAMEI_DELETE, NULL, NULL, + error = nfs_namei(&fromnd, cred, NLC_RENAME_SRC, + NULL, NULL, ffhp, len, slp, nam, &md, &dpos, &fdirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); if (fdirp) { @@ -2119,7 +2120,7 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, nfsm_strsiz(len2, NFS_MAXNAMLEN); cred->cr_uid = saved_uid; - error = nfs_namei(&tond, cred, NAMEI_RENAME, NULL, NULL, + error = nfs_namei(&tond, cred, NLC_RENAME_DST, NULL, NULL, tfhp, len2, slp, nam, &md, &dpos, &tdirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); if (tdirp) { @@ -2324,7 +2325,7 @@ nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, goto out1; } - error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp, + error = nfs_namei(&nd, cred, NLC_CREATE, &dvp, &vp, dfhp, len, slp, nam, &md, &dpos, &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); if (dirp) { @@ -2418,7 +2419,7 @@ nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, nfsm_srvmtofh(fhp); nfsm_srvnamesiz(len); - error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp, + error = nfs_namei(&nd, cred, NLC_CREATE, &dvp, &vp, fhp, len, slp, nam, &md, &dpos, &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); if (dirp) { @@ -2548,7 +2549,7 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, nfsm_srvmtofh(fhp); nfsm_srvnamesiz(len); - error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp, + error = nfs_namei(&nd, cred, NLC_CREATE, &dvp, &vp, fhp, len, slp, nam, &md, &dpos, &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); if (dirp) { @@ -2667,7 +2668,7 @@ nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, nfsm_srvmtofh(fhp); nfsm_srvnamesiz(len); - error = nfs_namei(&nd, cred, NAMEI_DELETE, &dvp, &vp, + error = nfs_namei(&nd, cred, NLC_DELETE, &dvp, &vp, fhp, len, slp, nam, &md, &dpos, &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); if (dirp) { diff --git a/sys/vfs/nfs/nfs_subs.c b/sys/vfs/nfs/nfs_subs.c index a90a7cc5a6..64274f85f8 100644 --- a/sys/vfs/nfs/nfs_subs.c +++ b/sys/vfs/nfs/nfs_subs.c @@ -1443,7 +1443,7 @@ nfs_getattrcache(struct vnode *vp, struct vattr *vaper) * to cleanup. */ int -nfs_namei(struct nlookupdata *nd, struct ucred *cred, int nameiop, +nfs_namei(struct nlookupdata *nd, struct ucred *cred, int nflags, struct vnode **dvpp, struct vnode **vpp, fhandle_t *fhp, int len, struct nfssvc_sock *slp, struct sockaddr *nam, struct mbuf **mdp, @@ -1451,7 +1451,6 @@ nfs_namei(struct nlookupdata *nd, struct ucred *cred, int nameiop, int kerbflag, int pubflag) { int i, rem; - int flags; struct mbuf *md; char *fromcp, *tocp, *cp; char *namebuf; @@ -1461,7 +1460,6 @@ nfs_namei(struct nlookupdata *nd, struct ucred *cred, int nameiop, int error, rdonly; namebuf = objcache_get(namei_oc, M_WAITOK); - flags = 0; *dirpp = NULL; /* @@ -1575,15 +1573,11 @@ nfs_namei(struct nlookupdata *nd, struct ucred *cred, int nameiop, * that dp is ref'd, but we no longer 'own' the ref (*dirpp owns it). */ if (pubflag == 0) { - flags |= NLC_NFS_NOSOFTLINKTRAV; - flags |= NLC_NOCROSSMOUNT; + nflags |= NLC_NFS_NOSOFTLINKTRAV; + nflags |= NLC_NOCROSSMOUNT; } if (rdonly) - flags |= NLC_NFS_RDONLY; - if (nameiop == NAMEI_CREATE) - flags |= NLC_CREATE; - if (nameiop == NAMEI_RENAME) - flags |= NLC_RENAME; + nflags |= NLC_NFS_RDONLY; /* * We need a starting ncp from the directory vnode dp. dp must not @@ -1595,7 +1589,7 @@ nfs_namei(struct nlookupdata *nd, struct ucred *cred, int nameiop, */ if ((error = cache_fromdvp(dp, cred, 1, &nch)) != 0) goto out; - nlookup_init_raw(nd, namebuf, UIO_SYSSPACE, flags, cred, &nch); + nlookup_init_raw(nd, namebuf, UIO_SYSSPACE, nflags, cred, &nch); cache_drop(&nch); /* diff --git a/sys/vfs/nfs/nfs_vnops.c b/sys/vfs/nfs/nfs_vnops.c index 656190b139..666d04acb5 100644 --- a/sys/vfs/nfs/nfs_vnops.c +++ b/sys/vfs/nfs/nfs_vnops.c @@ -472,6 +472,22 @@ nfs_open(struct vop_open_args *ap) return (EOPNOTSUPP); } + /* + * Save valid creds for reading and writing for later RPCs. + */ + if ((ap->a_mode & FREAD) && ap->a_cred != np->n_rucred) { + crhold(ap->a_cred); + if (np->n_rucred) + crfree(np->n_rucred); + np->n_rucred = ap->a_cred; + } + if ((ap->a_mode & FWRITE) && ap->a_cred != np->n_wucred) { + crhold(ap->a_cred); + if (np->n_wucred) + crfree(np->n_wucred); + np->n_wucred = ap->a_cred; + } + /* * Clear the attribute cache only if opening with write access. It * is unclear if we should do this at all here, but we certainly @@ -1133,14 +1149,6 @@ nfs_read(struct vop_read_args *ap) struct vnode *vp = ap->a_vp; return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag)); - switch (vp->v_type) { - case VREG: - return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag)); - case VDIR: - return (EISDIR); - default: - return EOPNOTSUPP; - } } /* diff --git a/sys/vfs/ntfs/ntfs_vnops.c b/sys/vfs/ntfs/ntfs_vnops.c index c1246fe395..af1a2d1b25 100644 --- a/sys/vfs/ntfs/ntfs_vnops.c +++ b/sys/vfs/ntfs/ntfs_vnops.c @@ -460,8 +460,6 @@ ntfs_access(struct vop_access_args *ap) /* Otherwise, check the owner. */ if (cred->cr_uid == ip->i_mp->ntm_uid) { - if (mode & VOWN) - return (0); if (mode & VEXEC) mask |= S_IXUSR; if (mode & VREAD) diff --git a/sys/vfs/nwfs/nwfs_vnops.c b/sys/vfs/nwfs/nwfs_vnops.c index 1faaaae90a..0a1ce190eb 100644 --- a/sys/vfs/nwfs/nwfs_vnops.c +++ b/sys/vfs/nwfs/nwfs_vnops.c @@ -145,8 +145,6 @@ nwfs_access(struct vop_access_args *ap) mode >>= 3; if (!groupmember(nmp->m.gid, cred)) mode >>= 3; - } else if (mode & VOWN) { - return (0); } error = (((vp->v_type == VREG) ? nmp->m.file_mode : nmp->m.dir_mode) & mode) == mode ? 0 : EACCES; return error; diff --git a/sys/vfs/smbfs/smbfs_vnops.c b/sys/vfs/smbfs/smbfs_vnops.c index eab915b155..e3a5068614 100644 --- a/sys/vfs/smbfs/smbfs_vnops.c +++ b/sys/vfs/smbfs/smbfs_vnops.c @@ -148,8 +148,6 @@ smbfs_access(struct vop_access_args *ap) mode >>= 3; if (!groupmember(smp->sm_args.gid, cred)) mode >>= 3; - } else if (mode & VOWN) { - return (0); } error = (((vp->v_type == VREG) ? smp->sm_args.file_mode : smp->sm_args.dir_mode) & mode) == mode ? 0 : EACCES; return error; diff --git a/sys/vfs/udf/udf_vnops.c b/sys/vfs/udf/udf_vnops.c index d358741ddc..dc9e49cdbf 100644 --- a/sys/vfs/udf/udf_vnops.c +++ b/sys/vfs/udf/udf_vnops.c @@ -240,8 +240,6 @@ udf_access(struct vop_access_args *a) /* Otherwise, check the owner. */ if (cred->cr_uid == node->fentry->uid) { - if (a_mode & VOWN) - return (0); if (a_mode & VEXEC) mask |= S_IXUSR; if (a_mode & VREAD) diff --git a/sys/vfs/ufs/ufs_vnops.c b/sys/vfs/ufs/ufs_vnops.c index bb0ef4f760..14ca305acb 100644 --- a/sys/vfs/ufs/ufs_vnops.c +++ b/sys/vfs/ufs/ufs_vnops.c @@ -94,7 +94,6 @@ static int ufs_missingop (struct vop_generic_args *ap); static int ufs_mkdir (struct vop_old_mkdir_args *); static int ufs_mknod (struct vop_old_mknod_args *); static int ufs_mmap (struct vop_mmap_args *); -static int ufs_open (struct vop_open_args *); static int ufs_print (struct vop_print_args *); static int ufs_readdir (struct vop_readdir_args *); static int ufs_readlink (struct vop_readlink_args *); @@ -265,32 +264,6 @@ ufs_mknod(struct vop_old_mknod_args *ap) return (0); } -/* - * Open called. - * - * Nothing to do. - * - * ufs_open(struct vnode *a_vp, int a_mode, struct ucred *a_cred, - * struct file *a_fp) - */ -/* ARGSUSED */ -static -int -ufs_open(struct vop_open_args *ap) -{ - struct vnode *vp = ap->a_vp; - - /* - * Files marked append-only must be opened for appending. - */ - if ((VTOI(vp)->i_flags & APPEND) && - (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE) { - return (EPERM); - } - - return (vop_stdopen(ap)); -} - /* * Close called. * @@ -349,9 +322,11 @@ ufs_access(struct vop_access_args *ap) } } +#if 0 /* handled by kernel now */ /* If immutable bit set, nobody gets to write it. */ if ((mode & VWRITE) && (ip->i_flags & IMMUTABLE)) return (EPERM); +#endif /* Otherwise, user id 0 always gets access. */ if (cred->cr_uid == 0) @@ -361,8 +336,6 @@ ufs_access(struct vop_access_args *ap) /* Otherwise, check the owner. */ if (cred->cr_uid == ip->i_uid) { - if (mode & VOWN) - return (0); if (mode & VEXEC) mask |= S_IXUSR; if (mode & VREAD) @@ -741,15 +714,19 @@ ufs_remove(struct vop_old_remove_args *ap) int error; ip = VTOI(vp); +#if 0 /* handled by kernel now */ if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) || (VTOI(dvp)->i_flags & APPEND)) { error = EPERM; goto out; } +#endif error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0); VN_KNOTE(vp, NOTE_DELETE); VN_KNOTE(dvp, NOTE_WRITE); +#if 0 out: +#endif return (error); } @@ -782,10 +759,12 @@ ufs_link(struct vop_old_link_args *ap) error = EMLINK; goto out1; } +#if 0 /* handled by kernel now, also DragonFly allows this */ if (ip->i_flags & (IMMUTABLE | APPEND)) { error = EPERM; goto out1; } +#endif ip->i_effnlink++; ip->i_nlink++; ip->i_flag |= IN_CHANGE; @@ -926,11 +905,13 @@ abortit: return (error); } +#if 0 /* handled by kernel now */ if (tvp && ((VTOI(tvp)->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) || (VTOI(tdvp)->i_flags & APPEND))) { error = EPERM; goto abortit; } +#endif /* * Renaming a file to itself has no effect. The upper layers should @@ -956,12 +937,14 @@ abortit: error = EMLINK; goto abortit; } +#if 0 /* handled by kernel now */ if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) || (dp->i_flags & APPEND)) { vn_unlock(fvp); error = EPERM; goto abortit; } +#endif if ((ip->i_mode & IFMT) == IFDIR) { /* * Avoid ".", "..", and aliases of "." for obvious reasons. @@ -1563,11 +1546,13 @@ ufs_rmdir(struct vop_old_rmdir_args *ap) error = ENOTEMPTY; goto out; } +#if 0 /* handled by kernel now */ if ((dp->i_flags & APPEND) || (ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))) { error = EPERM; goto out; } +#endif /* * Delete reference to directory before purging * inode. If we crash in between, the directory @@ -2375,7 +2360,7 @@ static struct vop_ops ufs_vnode_vops = { .vop_old_mkdir = ufs_mkdir, .vop_old_mknod = ufs_mknod, .vop_mmap = ufs_mmap, - .vop_open = ufs_open, + .vop_open = vop_stdopen, .vop_pathconf = vop_stdpathconf, .vop_poll = vop_stdpoll, .vop_kqfilter = ufs_kqfilter, diff --git a/sys/vm/vm_contig.c b/sys/vm/vm_contig.c index f45ad0f583..4de57af92d 100644 --- a/sys/vm/vm_contig.c +++ b/sys/vm/vm_contig.c @@ -474,7 +474,10 @@ contigmalloc_map( index = vm_contig_pg_alloc(size, low, high, alignment, boundary, flags); if (index < 0) { - kprintf("contigmalloc_map: failed in index < 0 case!\n"); + kprintf("contigmalloc_map: failed size %lu low=%llx " + "high=%llx align=%lu boundary=%lu flags=%08x\n", + size, (long long)low, (long long)high, + alignment, boundary, flags); return NULL; } diff --git a/sys/vm/vm_meter.c b/sys/vm/vm_meter.c index b456195dd8..7a92f18178 100644 --- a/sys/vm/vm_meter.c +++ b/sys/vm/vm_meter.c @@ -223,6 +223,7 @@ do_vmmeter(SYSCTL_HANDLER_ARGS) } } + vmm.v_intr += vmm.v_ipi + vmm.v_timer; return (sysctl_handle_opaque(oidp, &vmm, sizeof(vmm), req)); } @@ -251,6 +252,21 @@ vcnt(SYSCTL_HANDLER_ARGS) return(SYSCTL_OUT(req, &count, sizeof(int))); } +static int +vcnt_intr(SYSCTL_HANDLER_ARGS) +{ + int i; + int count = 0; + + for (i = 0; i < ncpus; ++i) { + struct globaldata *gd = globaldata_find(i); + + count += gd->gd_cnt.v_intr + gd->gd_cnt.v_ipi + + gd->gd_cnt.v_timer; + } + return(SYSCTL_OUT(req, &count, sizeof(int))); +} + #define VMMETEROFF(var) offsetof(struct vmmeter, var) SYSCTL_PROC(_vm, OID_AUTO, vmtotal, CTLTYPE_OPAQUE|CTLFLAG_RD, @@ -261,7 +277,7 @@ SYSCTL_PROC(_vm, OID_AUTO, vmstats, CTLTYPE_OPAQUE|CTLFLAG_RD, "System virtual memory statistics"); SYSCTL_PROC(_vm, OID_AUTO, vmmeter, CTLTYPE_OPAQUE|CTLFLAG_RD, 0, sizeof(struct vmmeter), do_vmmeter, "S,vmmeter", - "System per-cpu statistics"); + "System statistics"); SYSCTL_NODE(_vm, OID_AUTO, stats, CTLFLAG_RW, 0, "VM meter stats"); SYSCTL_NODE(_vm_stats, OID_AUTO, sys, CTLFLAG_RW, 0, "VM meter sys stats"); SYSCTL_NODE(_vm_stats, OID_AUTO, vm, CTLFLAG_RW, 0, "VM meter vm stats"); @@ -284,7 +300,11 @@ SYSCTL_PROC(_vm_stats_sys, OID_AUTO, v_trap, CTLTYPE_UINT|CTLFLAG_RD, SYSCTL_PROC(_vm_stats_sys, OID_AUTO, v_syscall, CTLTYPE_UINT|CTLFLAG_RD, 0, VMMETEROFF(v_syscall), vcnt, "IU", "Syscalls"); SYSCTL_PROC(_vm_stats_sys, OID_AUTO, v_intr, CTLTYPE_UINT|CTLFLAG_RD, - 0, VMMETEROFF(v_intr), vcnt, "IU", "Hardware interrupts"); + 0, VMMETEROFF(v_intr), vcnt_intr, "IU", "Hardware interrupts"); +SYSCTL_PROC(_vm_stats_sys, OID_AUTO, v_ipi, CTLTYPE_UINT|CTLFLAG_RD, + 0, VMMETEROFF(v_ipi), vcnt, "IU", "Inter-processor interrupts"); +SYSCTL_PROC(_vm_stats_sys, OID_AUTO, v_timer, CTLTYPE_UINT|CTLFLAG_RD, + 0, VMMETEROFF(v_timer), vcnt, "IU", "LAPIC timer interrupts"); SYSCTL_PROC(_vm_stats_sys, OID_AUTO, v_soft, CTLTYPE_UINT|CTLFLAG_RD, 0, VMMETEROFF(v_soft), vcnt, "IU", "Software interrupts"); SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_vm_faults, CTLTYPE_UINT|CTLFLAG_RD, @@ -376,3 +396,48 @@ SYSCTL_UINT(_vm_stats_vm, OID_AUTO, v_interrupt_free_min, CTLFLAG_RD, &vmstats.v_interrupt_free_min, 0, ""); SYSCTL_INT(_vm_stats_misc, OID_AUTO, zero_page_count, CTLFLAG_RD, &vm_page_zero_count, 0, ""); + +static int +do_vmmeter_pcpu(SYSCTL_HANDLER_ARGS) +{ + int boffset = offsetof(struct vmmeter, vmmeter_uint_begin); + int eoffset = offsetof(struct vmmeter, vmmeter_uint_end); + struct globaldata *gd = arg1; + struct vmmeter vmm; + int off; + + bzero(&vmm, sizeof(vmm)); + for (off = boffset; off <= eoffset; off += sizeof(u_int)) { + *(u_int *)((char *)&vmm + off) += + *(u_int *)((char *)&gd->gd_cnt + off); + } + vmm.v_intr += vmm.v_ipi + vmm.v_timer; + return (sysctl_handle_opaque(oidp, &vmm, sizeof(vmm), req)); +} + +static void +vmmeter_init(void *dummy __unused) +{ + int i; + + for (i = 0; i < ncpus; ++i) { + struct sysctl_ctx_list *ctx; + struct sysctl_oid *oid; + struct globaldata *gd; + char name[32]; + + ksnprintf(name, sizeof(name), "cpu%d", i); + + ctx = kmalloc(sizeof(*ctx), M_TEMP, M_WAITOK); + sysctl_ctx_init(ctx); + oid = SYSCTL_ADD_NODE(ctx, SYSCTL_STATIC_CHILDREN(_vm), + OID_AUTO, name, CTLFLAG_RD, 0, ""); + + gd = globaldata_find(i); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "vmmeter", CTLTYPE_OPAQUE|CTLFLAG_RD, + gd, sizeof(struct vmmeter), do_vmmeter_pcpu, + "S,vmmeter", "System per-cpu statistics"); + } +} +SYSINIT(vmmeter, SI_SUB_PSEUDO, SI_ORDER_ANY, vmmeter_init, 0); diff --git a/test/amd64/Makefile b/test/amd64/Makefile index 8bdd0e6a48..56b64dd014 100644 --- a/test/amd64/Makefile +++ b/test/amd64/Makefile @@ -148,6 +148,8 @@ quickkernel64: checkq # Build and mount an empty filesystem for the emulated root disk # +# NOTE: root64 must umount when done because a later dependency may +# have a dependency on mount. # root64: check vnconfig -c -T -S ${ROOTSIZE} -s labels \ @@ -161,6 +163,7 @@ root64: check disklabel -B `cat ${QEMUDIR}/vn.which`s1 newfs /dev/`cat ${QEMUDIR}/vn.which`s1a mkdir -p ${QEMUDIR}/root + vnconfig -u `cat ${QEMUDIR}/vn.which` > /dev/null 2>&1 mount: check vnconfig -c -s labels `cat ${QEMUDIR}/vn.which` ${QEMUDIR}/root.img diff --git a/test/vkernel/Makefile b/test/vkernel/Makefile new file mode 100644 index 0000000000..9ffc4dfde5 --- /dev/null +++ b/test/vkernel/Makefile @@ -0,0 +1,175 @@ +# Makefile - set up a vkernel environment for testing the vkernel +# + +# require it to be specified +SRCDIR ?= ${.CURDIR}/../.. +ROOTSIZE ?= 512M +NETADDR= 10.3.1.1 + +all: help + +scratch: world32 kernel32 install32 + @echo "Run the environment with:" + @echo "make VKDIR=${VKDIR} run" + +quickw: quickworld32 quickkernel32 reinstall32 reinstallkernel32 + @echo "Run the environment with:" + @echo "make VKDIR=${VKDIR} run" + +quick: quickkernel32 reinstallkernel32 + @echo "Run the environment with:" + @echo "make VKDIR=${VKDIR} run" + +help: + @echo "Setup Instructions:" + @echo "" + @echo " setenv VKDIR target_dir" + @echo "" + @echo "Meta target components:" + @echo "" + @echo " help - this help" + @echo " clean - clean up" + @echo " scratch - build and install everything from scratch" + @echo " (this is absolutely everything)" + @echo " quick - incremental kernel build & reinstall" + @echo " quickw - incremental world & kernel build & reinstall" + @echo " run - run vkernel with VKDIR/root.img" + @echo " mount - mount VKDIR/root.img at VKDIR/root" + @echo " umount - unmount" + @echo "" + @echo "Individual target components:" + @echo "" + @echo " world32 - build the 32 bit world from scratch" + @echo " root32 - create a new, empty root.img" + @echo " install32 - install a 32 bit world & kernel" + @echo " into root.img" + @echo " kernel32 - build 32 bit vkernel" + @echo " quickworld32 - incremental rebuild world32" + @echo " quickkernel32 - incremental rebuild kernel32" + @echo " reinstall32 - reinstall world32 into root.img" + @echo " (just the installworld piece)" + @echo " reinstallkernel32 - reinstall kernel32 into root.img" + @echo "" + +# Unmount everything, de-configured VN, and clean up. +# (check handles umounting/deconfiguring) +# +clean: check + rm -rf ${VKDIR}/root.img ${VKDIR}/root + +# Build the 32 bit world and kernel +# +# +world32: checkq + cd ${SRCDIR} && make -j 4 buildworld + +kernel32: checkq + cd ${SRCDIR} && make -j 4 KERNCONF=VKERNEL buildkernel + +# Quick build - just rebuild the kernel quickly +# +# +quickworld32: checkq + cd ${SRCDIR} && make -j 4 quickworld + +quickkernel32: checkq + cd ${SRCDIR} && make KERNCONF=VKERNEL quickkernel + +# Build and mount an empty filesystem for the emulated root disk +# +# NOTE: root32 must umount when done because a later dependency may +# have a dependency on mount. +# +root32: check + vnconfig -c -T -S ${ROOTSIZE} -s labels \ + `cat ${VKDIR}/vn.which` ${VKDIR}/root.img + dd if=/dev/zero of=/dev/`cat ${VKDIR}/vn.which` bs=32k count=4 + fdisk -IB `cat ${VKDIR}/vn.which` + disklabel -r -w `cat ${VKDIR}/vn.which`s1 auto + disklabel `cat ${VKDIR}/vn.which`s1 > ${VKDIR}/label.tmp + echo 'a: * 0 4.2BSD' >> ${VKDIR}/label.tmp + disklabel -R `cat ${VKDIR}/vn.which`s1 ${VKDIR}/label.tmp + disklabel -B `cat ${VKDIR}/vn.which`s1 + newfs /dev/`cat ${VKDIR}/vn.which`s1a + mkdir -p ${VKDIR}/root + vnconfig -u `cat ${VKDIR}/vn.which` > /dev/null 2>&1 + +mount: check + vnconfig -c -s labels `cat ${VKDIR}/vn.which` ${VKDIR}/root.img + fsck -p /dev/`cat ${VKDIR}/vn.which`s1a + mount /dev/`cat ${VKDIR}/vn.which`s1a ${VKDIR}/root + @echo "Mounted ${VKDIR}/root" + +umount: check + +# Install a fresh 32 bit world & distribution, and kernel +# +install32: mount + cd ${SRCDIR} && \ + make -j 4 DESTDIR=${VKDIR}/root installworld + cd ${SRCDIR}/etc && \ + make -j 4 DESTDIR=${VKDIR}/root distribution + echo '/dev/vkd0s1a / ufs rw 1 1' > ${VKDIR}/root/etc/fstab + echo 'proc /proc procfs rw 0 0' >> ${VKDIR}/root/etc/fstab + echo 'vfs.root.mountfrom="ufs:vkds1a"' > ${VKDIR}/root/boot/loader.conf + #(egrep -v '^console' ${VKDIR}/root/etc/ttys; echo 'console "/usr/libexec/getty Pc" cons25 on secure') > ${VKDIR}/root/etc/ttys.new + #mv -f ${VKDIR}/root/etc/ttys.new ${VKDIR}/root/etc/ttys + cd ${SRCDIR} && \ + make -j 4 \ + DESTDIR=${VKDIR}/root KERNCONF=VKERNEL \ + NO_MODULES= \ + installkernel + cp ${VKDIR}/root/boot/kernel ${VKDIR}/vkernel + +# Quick reinstall - just install a new kernel on top of an existing image +# +# +reinstall32: mount + cd ${SRCDIR} && make -j 4 DESTDIR=${VKDIR}/root installworld + +reinstallkernel32: mount + cd ${SRCDIR} && \ + make -j 4 DESTDIR=${VKDIR}/root KERNCONF=VKERNEL \ + NO_MODULES= installkernel + cp ${VKDIR}/root/boot/kernel ${VKDIR}/vkernel + +sysloader: mount + cp /boot/loader ${VKDIR}/root/boot/loader + sync + +# Run the vkernel on our image. Make sure we are unmounted so +# we do not compete against the emulated kernel when writing to root.img. +# (check does this for us) +# +run: check + cd ${VKDIR} && ./vkernel -m 128m -n 2 \ + -r root.img -U -v \ + -I /dev/vknet +# -I /dev/vknet:0.0.0.0:${NETADDR}/16 + +# Make sure we are not mounted and the VN device is unconfigured, +# +# Find an unused VN device but do not do anything with it yet. +# +checkq: +.if !defined(VKDIR) + @(echo "must specify VKDIR=target or as an environment variable"; exit 1) +.endif +.if exists(${VKDIR}) + @echo "${VKDIR} found" +.else + mkdir -p ${VKDIR} +.endif + +check: checkq +.if exists(${VKDIR}/vn.which) + -umount ${VKDIR}/root > /dev/null 2>&1 + -vnconfig -u `cat ${VKDIR}/vn.which` > /dev/null 2>&1 + rm -f ${VKDIR}/vn.which +.endif + (vnconfig -l | fgrep "not in use" > /dev/null) || \ + (echo "Cannot find unused VN"; exit 1) + vnconfig -l | fgrep "not in use" | \ + cut -f 1 -d : | head -1 > ${VKDIR}/vn.which + egrep '^vn' ${VKDIR}/vn.which > /dev/null || \ + (echo "VN device selection is bad"; exit 1) diff --git a/usr.bin/Makefile b/usr.bin/Makefile index c19ca50920..bede38278a 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -42,6 +42,7 @@ SUBDIR= alias \ compile_et \ compress \ cpio \ + crunch \ csplit \ ctags \ cut \ diff --git a/usr.sbin/crunch/COPYRIGHT b/usr.bin/crunch/COPYRIGHT similarity index 100% rename from usr.sbin/crunch/COPYRIGHT rename to usr.bin/crunch/COPYRIGHT diff --git a/usr.sbin/crunch/Makefile b/usr.bin/crunch/Makefile similarity index 100% rename from usr.sbin/crunch/Makefile rename to usr.bin/crunch/Makefile diff --git a/usr.bin/crunch/Makefile.inc b/usr.bin/crunch/Makefile.inc new file mode 100644 index 0000000000..ad6e982e6d --- /dev/null +++ b/usr.bin/crunch/Makefile.inc @@ -0,0 +1,3 @@ +WARNS?= 1 + +.include "../Makefile.inc" diff --git a/usr.sbin/crunch/README b/usr.bin/crunch/README similarity index 100% rename from usr.sbin/crunch/README rename to usr.bin/crunch/README diff --git a/usr.sbin/crunch/crunchgen/Makefile b/usr.bin/crunch/crunchgen/Makefile similarity index 100% rename from usr.sbin/crunch/crunchgen/Makefile rename to usr.bin/crunch/crunchgen/Makefile diff --git a/usr.sbin/crunch/crunchgen/crunched_main.c b/usr.bin/crunch/crunchgen/crunched_main.c similarity index 99% rename from usr.sbin/crunch/crunchgen/crunched_main.c rename to usr.bin/crunch/crunchgen/crunched_main.c index a3190553e4..c3bfe07509 100644 --- a/usr.sbin/crunch/crunchgen/crunched_main.c +++ b/usr.bin/crunch/crunchgen/crunched_main.c @@ -121,4 +121,3 @@ crunched_usage(void) } /* end of crunched_main.c */ - diff --git a/usr.sbin/crunch/crunchgen/crunchgen.1 b/usr.bin/crunch/crunchgen/crunchgen.1 similarity index 100% rename from usr.sbin/crunch/crunchgen/crunchgen.1 rename to usr.bin/crunch/crunchgen/crunchgen.1 diff --git a/usr.sbin/crunch/crunchgen/crunchgen.c b/usr.bin/crunch/crunchgen/crunchgen.c similarity index 99% rename from usr.sbin/crunch/crunchgen/crunchgen.c rename to usr.bin/crunch/crunchgen/crunchgen.c index 0cf03ab783..3e20625a8e 100644 --- a/usr.sbin/crunch/crunchgen/crunchgen.c +++ b/usr.bin/crunch/crunchgen/crunchgen.c @@ -48,7 +48,7 @@ #define CRUNCH_VERSION "0.2" #define MAXLINELEN 16384 -#define MAXFIELDS 2048 +#define MAXFIELDS 2048 /* internal representation of conf file: */ @@ -1123,7 +1123,7 @@ add_string(strlst_t **listp, char *str) if (p2) { p2->next = NULL; p2->str = strdup(str); - } + } if (!p2 || !p2->str) out_of_memory(); diff --git a/usr.sbin/crunch/crunchgen/mkskel.sh b/usr.bin/crunch/crunchgen/mkskel.sh similarity index 100% rename from usr.sbin/crunch/crunchgen/mkskel.sh rename to usr.bin/crunch/crunchgen/mkskel.sh diff --git a/usr.sbin/crunch/crunchide/Makefile b/usr.bin/crunch/crunchide/Makefile similarity index 100% rename from usr.sbin/crunch/crunchide/Makefile rename to usr.bin/crunch/crunchide/Makefile diff --git a/usr.sbin/crunch/crunchide/crunchide.1 b/usr.bin/crunch/crunchide/crunchide.1 similarity index 100% rename from usr.sbin/crunch/crunchide/crunchide.1 rename to usr.bin/crunch/crunchide/crunchide.1 diff --git a/usr.sbin/crunch/crunchide/crunchide.c b/usr.bin/crunch/crunchide/crunchide.c similarity index 100% rename from usr.sbin/crunch/crunchide/crunchide.c rename to usr.bin/crunch/crunchide/crunchide.c diff --git a/usr.sbin/crunch/crunchide/exec_aout.c b/usr.bin/crunch/crunchide/exec_aout.c similarity index 99% rename from usr.sbin/crunch/crunchide/exec_aout.c rename to usr.bin/crunch/crunchide/exec_aout.c index caa78e72f4..ab49da93d4 100644 --- a/usr.sbin/crunch/crunchide/exec_aout.c +++ b/usr.bin/crunch/crunchide/exec_aout.c @@ -30,14 +30,14 @@ * $DragonFly: src/usr.sbin/crunch/crunchide/exec_aout.c,v 1.5 2004/02/08 10:48:30 rob Exp $ */ #include - + #include #include #include #include #include #include -#include +#include #include #include "extern.h" diff --git a/usr.sbin/crunch/crunchide/exec_elf32.c b/usr.bin/crunch/crunchide/exec_elf32.c similarity index 99% rename from usr.sbin/crunch/crunchide/exec_elf32.c rename to usr.bin/crunch/crunchide/exec_elf32.c index a3a158e144..b0c3782962 100644 --- a/usr.sbin/crunch/crunchide/exec_elf32.c +++ b/usr.bin/crunch/crunchide/exec_elf32.c @@ -33,7 +33,7 @@ */ #include - + #ifndef ELFSIZE #define ELFSIZE 32 #endif diff --git a/usr.sbin/crunch/crunchide/exec_elf64.c b/usr.bin/crunch/crunchide/exec_elf64.c similarity index 99% rename from usr.sbin/crunch/crunchide/exec_elf64.c rename to usr.bin/crunch/crunchide/exec_elf64.c index cb9284a1b7..a0c0329142 100644 --- a/usr.sbin/crunch/crunchide/exec_elf64.c +++ b/usr.bin/crunch/crunchide/exec_elf64.c @@ -33,7 +33,7 @@ */ #include - + #define ELFSIZE 64 #include "exec_elf32.c" diff --git a/usr.sbin/crunch/crunchide/extern.h b/usr.bin/crunch/crunchide/extern.h similarity index 100% rename from usr.sbin/crunch/crunchide/extern.h rename to usr.bin/crunch/crunchide/extern.h diff --git a/usr.sbin/crunch/examples/Makefile b/usr.bin/crunch/examples/Makefile similarity index 100% rename from usr.sbin/crunch/examples/Makefile rename to usr.bin/crunch/examples/Makefile diff --git a/usr.sbin/crunch/examples/filesystem.conf b/usr.bin/crunch/examples/filesystem.conf similarity index 100% rename from usr.sbin/crunch/examples/filesystem.conf rename to usr.bin/crunch/examples/filesystem.conf diff --git a/usr.sbin/crunch/examples/fixit.conf b/usr.bin/crunch/examples/fixit.conf similarity index 98% rename from usr.sbin/crunch/examples/fixit.conf rename to usr.bin/crunch/examples/fixit.conf index 80a2346e34..26543c3b65 100644 --- a/usr.sbin/crunch/examples/fixit.conf +++ b/usr.bin/crunch/examples/fixit.conf @@ -9,7 +9,7 @@ srcdirs /usr/src/sbin/i386 # second, we list all the programs we want to include in our crunched binary. # The order doesn't matter. Any program that needs hard links to it gets an -# `ln' directive. +# `ln' directive. # /bin stuff diff --git a/usr.sbin/crunch/examples/kcopy.conf b/usr.bin/crunch/examples/kcopy.conf similarity index 100% rename from usr.sbin/crunch/examples/kcopy.conf rename to usr.bin/crunch/examples/kcopy.conf diff --git a/usr.sbin/crunch/examples/really-big.conf b/usr.bin/crunch/examples/really-big.conf similarity index 98% rename from usr.sbin/crunch/examples/really-big.conf rename to usr.bin/crunch/examples/really-big.conf index 3f7fd21483..b9b543ae42 100644 --- a/usr.sbin/crunch/examples/really-big.conf +++ b/usr.bin/crunch/examples/really-big.conf @@ -25,7 +25,7 @@ srcdirs /usr/src/sbin progs badsect bim clri disklabel dmesg dump dumpfs fdisk fsck halt progs ifconfig init mknod modload modunload mount mount_fdesc mount_isofs -progs mount_lofs mount_msdos mount_portal mount_procfs mountd +progs mount_lofs mount_msdos mount_portal mount_procfs mountd progs newfs nfsd nfsiod ping quotacheck reboot restore route routed savecore progs shutdown slattach swapon ttyflags tunefs umount # shell scripts: fastboot @@ -54,7 +54,7 @@ progs vacation vgrind vi vis vmstat w wall wc what whatis whereis who progs whois window write xargs xinstall xstr yacc yes ypcat ypmatch ypwhich # shell scripts: lorder mkdep shar which -# problems: rdist uses libcompat.a(regex.o), which conflicts with +# problems: rdist uses libcompat.a(regex.o), which conflicts with # libedit(readline.o) over regerror(). # special requirements @@ -145,5 +145,5 @@ special cc1 objpaths /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-parse.o /usr/src/gnu/us ln gzip gunzip ln gzip gzcat -libs -ledit -lgnumalloc -lc -lcrypt -ltermcap -lcurses -ltelnet -lutil -lkvm +libs -ledit -lgnumalloc -lc -lcrypt -ltermcap -lcurses -ltelnet -lutil -lkvm libs -ll -ly -lm -lresolv -lrpcsvc -lcompat diff --git a/usr.bin/doscmd/Makefile b/usr.bin/doscmd/Makefile index 23c5a425f8..2b5bedab7c 100644 --- a/usr.bin/doscmd/Makefile +++ b/usr.bin/doscmd/Makefile @@ -21,6 +21,7 @@ EXEGRP:= ${BINGRP} EXEMODE= ${NOBINMODE} #BINGRP= kmem #BINMODE= 2555 +WARNS?= 1 .if !defined(NO_X) && exists(${XINCDIR}/X11/X.h) && exists(${XLIBDIR}/libX11.a) CFLAGS+= -I${XINCDIR} diff --git a/usr.bin/fetch/fetch.1 b/usr.bin/fetch/fetch.1 index 68d4a17cc5..e8da991eed 100644 --- a/usr.bin/fetch/fetch.1 +++ b/usr.bin/fetch/fetch.1 @@ -27,10 +27,10 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $FreeBSD: src/usr.bin/fetch/fetch.1,v 1.67 2006/04/22 03:04:24 jkoshy Exp $ +.\" $FreeBSD: src/usr.bin/fetch/fetch.1,v 1.70 2008/12/15 08:27:44 murray Exp $ .\" $DragonFly: src/usr.bin/fetch/fetch.1,v 1.4 2007/08/05 21:48:12 swildner Exp $ .\" -.Dd August 5, 2007 +.Dd May 10, 2009 .Dt FETCH 1 .Os .Sh NAME @@ -38,17 +38,25 @@ .Nd retrieve a file by Uniform Resource Locator .Sh SYNOPSIS .Nm -.Op Fl 146AFMPRUadlmnpqrsv +.Op Fl 146AadFlMmnPpqRrsUv .Op Fl B Ar bytes +.Op Fl i Ar file +.Op Fl N Ar file +.Op Fl o Ar file .Op Fl S Ar bytes .Op Fl T Ar seconds +.Op Fl w Ar seconds +.Ar URL ... +.Nm +.Op Fl 146AadFlMmnPpqRrsUv +.Op Fl B Ar bytes +.Op Fl i Ar file .Op Fl N Ar file .Op Fl o Ar file +.Op Fl S Ar bytes +.Op Fl T Ar seconds .Op Fl w Ar seconds -.Op Fl h Ar host -.Op Fl c Ar dir -.Op Fl f Ar file -.Op Ar URL ... +.Fl h Ar host Fl f Ar file Oo Fl c Ar dir Oc .Sh DESCRIPTION The .Nm @@ -60,7 +68,7 @@ command line. .Pp The following options are available: .Bl -tag -width Fl -.It Fl \&1 +.It Fl 1 Stop and return exit code 0 at the first successfully retrieved file. .It Fl 4 Forces @@ -111,6 +119,12 @@ The file to retrieve is located on the host .Ar host . This option is deprecated and is provided for backward compatibility only. +.It Fl i Ar file +If-Modified-Since mode: the remote file will only be retrieved if it +is newer than +.Ar file +on the local host. +(HTTP only) .It Fl l If the target is a file-scheme URL, make a symbolic link to the target rather than trying to copy it. @@ -213,19 +227,29 @@ message. .Sh ENVIRONMENT .Bl -tag -width HTTP_TIMEOUT .It Ev FTP_TIMEOUT -maximum time, in seconds, to wait before aborting an FTP connection. +Maximum time, in seconds, to wait before aborting an FTP connection. .It Ev HTTP_TIMEOUT -maximum time, in seconds, to wait before aborting an HTTP connection. +Maximum time, in seconds, to wait before aborting an HTTP connection. .El .Pp -All environment variables mentioned in the documentation for the -.Xr fetch 3 -library are supported. -A number of these are quite important to the proper operation of -.Nm ; -you are strongly encouraged to read +See .Xr fetch 3 -as well. +for a description of additional environment variables, including +.Ev FETCH_BIND_ADDRESS , +.Ev FTP_LOGIN , +.Ev FTP_PASSIVE_MODE , +.Ev FTP_PASSWORD , +.Ev FTP_PROXY , +.Ev ftp_proxy , +.Ev HTTP_AUTH , +.Ev HTTP_PROXY , +.Ev http_proxy , +.Ev HTTP_PROXY_AUTH , +.Ev HTTP_REFERER , +.Ev HTTP_USER_AGENT , +.Ev NETRC , +.Ev NO_PROXY and +.Ev no_proxy . .Sh EXIT STATUS The .Nm @@ -234,6 +258,12 @@ If multiple URLs are listed on the command line, .Nm will attempt to retrieve each one of them in turn, and will return zero only if they were all successfully retrieved. +.Pp +If the +.Fl i +argument is used and the remote file is not newer than the +specified file then the command will still return success, +although no file is transferred. .Sh SEE ALSO .Xr fetch 3 .Sh HISTORY diff --git a/usr.bin/fetch/fetch.c b/usr.bin/fetch/fetch.c index 817219faf3..a3f32b0144 100644 --- a/usr.bin/fetch/fetch.c +++ b/usr.bin/fetch/fetch.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2000-2004 Dag-Erling Coïdan Smørgrav + * Copyright (c) 2000-2004 Dag-Erling Coïdan Smørgrav * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/usr.bin/fetch/fetch.c,v 1.78 2006/11/10 22:05:41 des Exp $ + * $FreeBSD: src/usr.bin/fetch/fetch.c,v 1.84 2009/01/17 13:34:56 des Exp $ * $DragonFly: src/usr.bin/fetch/fetch.c,v 1.8 2007/08/05 21:48:12 swildner Exp $ */ @@ -42,13 +42,13 @@ #include #include #include -#include #include #include #include #define MINBUFSIZE 4096 +#define TIMEOUT 120 /* Option flags */ int A_flag; /* -A: do not follow 302 redirects */ @@ -60,6 +60,8 @@ int d_flag; /* -d: direct connection */ int F_flag; /* -F: restart without checking mtime */ char *f_filename; /* -f: file to fetch */ char *h_hostname; /* -h: host to fetch from */ +int i_flag; /* -i: specify input file for mtime comparison */ +char *i_filename; /* name of input file */ int l_flag; /* -l: link rather than copy file: URLs */ int m_flag; /* -[Mm]: mirror mode */ char *N_filename; /* -N: netrc file name */ @@ -74,7 +76,7 @@ int R_flag; /* -R: don't delete partially transferred files */ int r_flag; /* -r: restart previously interrupted transfer */ off_t S_size; /* -S: require size to match */ int s_flag; /* -s: show size, don't fetch */ -long T_secs = 120; /* -T: transfer timeout in seconds */ +long T_secs; /* -T: transfer timeout in seconds */ int t_flag; /*! -t: workaround TCP bug */ int U_flag; /* -U: do not use high ports */ int v_level = 1; /* -v: verbosity level */ @@ -87,8 +89,8 @@ int sigalrm; /* SIGALRM received */ int siginfo; /* SIGINFO received */ int sigint; /* SIGINT received */ -long ftp_timeout; /* default timeout for FTP transfers */ -long http_timeout; /* default timeout for HTTP transfers */ +long ftp_timeout = TIMEOUT; /* default timeout for FTP transfers */ +long http_timeout = TIMEOUT; /* default timeout for HTTP transfers */ char *buf; /* transfer buffer */ @@ -364,7 +366,7 @@ fetch(char *URL, const char *path) } /* FTP specific flags */ - if (strcmp(url->scheme, "ftp") == 0) { + if (strcmp(url->scheme, SCHEME_FTP) == 0) { if (p_flag) strcat(flags, "p"); if (d_flag) @@ -375,12 +377,21 @@ fetch(char *URL, const char *path) } /* HTTP specific flags */ - if (strcmp(url->scheme, "http") == 0) { + if (strcmp(url->scheme, SCHEME_HTTP) == 0 || + strcmp(url->scheme, SCHEME_HTTPS) == 0) { if (d_flag) strcat(flags, "d"); if (A_flag) strcat(flags, "A"); timeout = T_secs ? T_secs : http_timeout; + if (i_flag) { + if (stat(i_filename, &sb)) { + warn("%s: stat()", i_filename); + goto failure; + } + url->ims_time = sb.st_mtime; + strcat(flags, "i"); + } } /* set the protocol timeout. */ @@ -448,7 +459,14 @@ fetch(char *URL, const char *path) goto signal; if (f == NULL) { warnx("%s: %s", URL, fetchLastErrString); - goto failure; + if (i_flag && strcmp(url->scheme, SCHEME_HTTP) == 0 + && fetchLastErrCode == FETCH_OK + && strcmp(fetchLastErrString, "Not Modified") == 0) { + /* HTTP Not Modified Response, return OK. */ + r = 0; + goto done; + } else + goto failure; } if (sigint) goto signal; @@ -714,10 +732,11 @@ fetch(char *URL, const char *path) static void usage(void) { - fprintf(stderr, "%s\n%s\n%s\n", - "usage: fetch [-146AFMPRUadlmnpqrsv] [-N netrc] [-o outputfile]", - " [-S bytes] [-B bytes] [-T seconds] [-w seconds]", - " [-h host -f file [-c dir] | URL ...]"); + fprintf(stderr, "%s\n%s\n%s\n%s\n", +"usage: fetch [-146AadFlMmnPpqRrsUv] [-B bytes] [-N file] [-o file] [-S bytes]", +" [-T seconds] [-w seconds] [-i file] URL ...", +" fetch [-146AadFlMmnPpqRrsUv] [-B bytes] [-N file] [-o file] [-S bytes]", +" [-T seconds] [-w seconds] [-i file] -h host -f file [-c dir]"); } @@ -734,7 +753,7 @@ main(int argc, char *argv[]) int c, e, r; while ((c = getopt(argc, argv, - "146AaB:bc:dFf:Hh:lMmN:nPpo:qRrS:sT:tUvw:")) != -1) + "146AaB:bc:dFf:Hh:i:lMmN:nPpo:qRrS:sT:tUvw:")) != -1) switch (c) { case '1': once_flag = 1; @@ -779,6 +798,10 @@ main(int argc, char *argv[]) case 'h': h_hostname = optarg; break; + case 'i': + i_flag = 1; + i_filename = optarg; + break; case 'l': l_flag = 1; break; @@ -846,7 +869,7 @@ main(int argc, char *argv[]) break; default: usage(); - exit(EX_USAGE); + exit(1); } argc -= optind; @@ -855,7 +878,7 @@ main(int argc, char *argv[]) if (h_hostname || f_filename || c_dirname) { if (!h_hostname || !f_filename || argc) { usage(); - exit(EX_USAGE); + exit(1); } /* XXX this is a hack. */ if (strcspn(h_hostname, "@:/") != strlen(h_hostname)) @@ -868,7 +891,7 @@ main(int argc, char *argv[]) if (!argc) { usage(); - exit(EX_USAGE); + exit(1); } /* allocate buffer */ @@ -909,10 +932,10 @@ main(int argc, char *argv[]) } else if (stat(o_filename, &sb) == -1) { if (errno == ENOENT) { if (argc > 1) - errx(EX_USAGE, "%s is not a directory", + errx(1, "%s is not a directory", o_filename); } else { - err(EX_IOERR, "%s", o_filename); + err(1, "%s", o_filename); } } else { if (sb.st_mode & S_IFDIR) diff --git a/usr.bin/gzip/zuncompress.c b/usr.bin/gzip/zuncompress.c index a5b021ffc5..f6c386855c 100644 --- a/usr.bin/gzip/zuncompress.c +++ b/usr.bin/gzip/zuncompress.c @@ -147,7 +147,7 @@ zuncompress(FILE *in, FILE *out, char *pre, size_t prelen, compressed_pre = NULL; while ((bin = fread(buf, 1, sizeof(buf), in)) != 0) { - if (fwrite(buf, 1, bin, out) != bin) { + if (fwrite(buf, 1, bin, out) != (size_t)bin) { free(buf); return -1; } diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c index 89e578d9bc..b3777ef7ef 100644 --- a/usr.bin/kdump/kdump.c +++ b/usr.bin/kdump/kdump.c @@ -413,12 +413,13 @@ ktrsyscall(struct ktr_syscall *ktr) ip++; narg--; } else if (ktr->ktr_code == SYS_setpriority) { - print_number(ip,narg,c); - print_number(ip,narg,c); - (void)putchar(','); + (void)putchar('('); prioname((int)*ip); ip++; narg--; + c = ','; + print_number(ip,narg,c); + print_number(ip,narg,c); } else if (ktr->ktr_code == SYS_fcntl) { int cmd; int arg; diff --git a/usr.bin/kenv/kenv.c b/usr.bin/kenv/kenv.c index b9d6dbd124..d50a24da3a 100644 --- a/usr.bin/kenv/kenv.c +++ b/usr.bin/kenv/kenv.c @@ -47,8 +47,8 @@ int main(int argc, char **argv) { int real_oid[CTL_MAXNAME]; - size_t oidlen; - int ch, error, hflag, i, slen; + size_t oidlen, slen; + int ch, error, hflag, i; char *env, *eq, *var, *val; hflag = 0; diff --git a/usr.bin/lex/Makefile b/usr.bin/lex/Makefile index 7c825645d7..855ffcc557 100644 --- a/usr.bin/lex/Makefile +++ b/usr.bin/lex/Makefile @@ -24,7 +24,6 @@ INCSDIR= ${INCLUDEDIR}/c++ MLINKS+= lex.1 flex.1 MLINKS+= lex.1 flex++.1 MLINKS+= lex.1 lex++.1 -WARNS?= 1 CLEANFILES= scan.c skel.c @@ -47,4 +46,5 @@ check: $(PROG) | diff $(.CURDIR)/initscan.c - @echo "Check successful" +.include "Makefile.inc" .include diff --git a/usr.bin/lex/Makefile.inc b/usr.bin/lex/Makefile.inc new file mode 100644 index 0000000000..2cbbd82cfc --- /dev/null +++ b/usr.bin/lex/Makefile.inc @@ -0,0 +1 @@ +WARNS?= 1 diff --git a/usr.bin/locate/Makefile.inc b/usr.bin/locate/Makefile.inc index 8af7baafd3..077d296e3e 100644 --- a/usr.bin/locate/Makefile.inc +++ b/usr.bin/locate/Makefile.inc @@ -2,3 +2,6 @@ # $DragonFly: src/usr.bin/locate/Makefile.inc,v 1.2 2003/06/17 04:29:28 dillon Exp $ LIBEXECDIR?= /usr/libexec +WARNS?= 2 + +.include "../Makefile.inc" diff --git a/usr.bin/locate/bigram/Makefile b/usr.bin/locate/bigram/Makefile index d929ee9ece..d6717dd7cf 100644 --- a/usr.bin/locate/bigram/Makefile +++ b/usr.bin/locate/bigram/Makefile @@ -7,5 +7,4 @@ NOMAN= noman BINDIR= ${LIBEXECDIR} CFLAGS+= -I${.CURDIR}/../locate -.include "../../Makefile.inc" .include diff --git a/usr.bin/locate/code/Makefile b/usr.bin/locate/code/Makefile index 91713c7f3a..232d2fdc81 100644 --- a/usr.bin/locate/code/Makefile +++ b/usr.bin/locate/code/Makefile @@ -6,7 +6,5 @@ PROG= locate.code CFLAGS+=-I${.CURDIR}/../locate NOMAN= noman BINDIR= ${LIBEXECDIR} -WARNS?= 2 -.include "../../Makefile.inc" .include diff --git a/usr.bin/locate/locate/Makefile b/usr.bin/locate/locate/Makefile index 29bcc45efd..a498763d29 100644 --- a/usr.bin/locate/locate/Makefile +++ b/usr.bin/locate/locate/Makefile @@ -7,7 +7,6 @@ SRCS= util.c locate.c CFLAGS+= -I${.CURDIR} -DMMAP # -DDEBUG (print time) -O2 (10% faster) SCRIPTS=updatedb.sh mklocatedb.sh concatdb.sh MAN= locate.1 locate.updatedb.8 -WARNS?= 2 SCRIPTSDIR= ${LIBEXECDIR} .for script in ${SCRIPTS} @@ -19,5 +18,4 @@ MLINKS+= locate.updatedb.8 updatedb.8 # ${INSTALL} -o root -g wheel -m 644 \ # ${.CURDIR}/locate.rc ${DESTDIR}/etc -.include "../../Makefile.inc" .include diff --git a/usr.bin/ncal/Makefile b/usr.bin/ncal/Makefile index ebdbc15230..37f69e05c1 100644 --- a/usr.bin/ncal/Makefile +++ b/usr.bin/ncal/Makefile @@ -4,8 +4,8 @@ PROG= ncal WARNS?= 1 -DPADD+= ${LIBCALENDAR} -LDADD+= -lcalendar +DPADD+= ${LIBCALENDAR} ${LIBTERMCAP} +LDADD+= -lcalendar -ltermcap LINKS= ${BINDIR}/ncal ${BINDIR}/cal MLINKS= ncal.1 cal.1 diff --git a/usr.bin/ncal/ncal.1 b/usr.bin/ncal/ncal.1 index d6353921d1..f5bf63cad8 100644 --- a/usr.bin/ncal/ncal.1 +++ b/usr.bin/ncal/ncal.1 @@ -25,7 +25,7 @@ .\" $FreeBSD: src/usr.bin/ncal/ncal.1,v 1.8.2.7 2002/10/23 08:10:00 roam Exp $ .\" $DragonFly: src/usr.bin/ncal/ncal.1,v 1.4 2005/07/31 11:46:52 asmodai Exp $ .\" -.Dd December 16, 1997 +.Dd March 12, 2009 .Dt CAL 1 .Os .Sh NAME @@ -35,12 +35,14 @@ .Sh SYNOPSIS .Nm .Op Fl jy +.Op Fl m Ar month .Oo .Op Ar month .Ar year .Oc .Nm ncal .Op Fl jJpwy +.Op Fl m Ar month .Op Fl s Ar country_code .Oo .Op Ar month @@ -70,6 +72,9 @@ option, display date of easter according to the Julian Calendar. Display date of easter (for western churches). .It Fl j Display Julian days (days one-based, numbered from January 1). +.It Fl m Ar month +Display the specified +.Ar month . .It Fl o Display date of orthodox easter (Greek and Russian Orthodox Churches). @@ -96,8 +101,15 @@ Display a calendar for the current year. .Pp A single parameter specifies the year (1 - 9999) to be displayed; note the year must be fully specified. -Two parameters denote the month and year; the month is either a number between +Two parameters denote the month and year; the +.Ar month +is either a number between 1 and 12, or a full or abbreviated name as specified by the current locale. +A single dot, +.Ql \&. , +for the +.Ar year +parameter refers to the current year. .Pp A year starts on Jan 1. .Sh DIAGNOSTICS diff --git a/usr.bin/ncal/ncal.c b/usr.bin/ncal/ncal.c index 4db51f2564..be43a5058b 100644 --- a/usr.bin/ncal/ncal.c +++ b/usr.bin/ncal/ncal.c @@ -38,6 +38,8 @@ #include #include #include +#include +#undef lines /* term.h defines this */ /* Width of one month with backward compatibility */ #define MONTH_WIDTH_B_J 27 @@ -46,7 +48,7 @@ #define MONTH_WIDTH_J 24 #define MONTH_WIDTH 18 -#define MAX_WIDTH 28 +#define MAX_WIDTH 64 typedef struct date date; @@ -155,6 +157,8 @@ char jdaystr[] = " 1 2 3 4 5 6 7 8 9" int flag_weeks; /* user wants number of week */ int nswitch; /* user defined switch date */ int nswitchb; /* switch date for backward compatibility */ +const char *term_so, *term_se; +int today; char *center(char *s, char *t, int w); void mkmonth(int year, int month, int jd_flag, struct monthlines * monthl); @@ -181,6 +185,7 @@ main(int argc, char *argv[]) struct djswitch *p, *q; /* to search user defined switch date */ date never = {10000, 1, 1}; /* outside valid range of dates */ date ukswitch = {1752, 9, 2};/* switch date for Great Britain */ + date dt; /* today as date */ int ch; /* holds the option character */ int m = 0; /* month */ int y = 0; /* year */ @@ -192,7 +197,25 @@ main(int argc, char *argv[]) int flag_orthodox = 0; /* use wants Orthodox easter */ int flag_easter = 0; /* use wants easter date */ char *cp; /* character pointer */ + char *flag_month = NULL; /* requested month as string */ char *locale; /* locale to get country code */ + char tbuf[1024], cbuf[512], *b; + time_t t; + struct tm *tm1; + + term_se = term_so = NULL; + today = 0; + t = time(NULL); + tm1 = localtime(&t); + y = dt.y = tm1->tm_year + 1900; + m = dt.m = tm1->tm_mon + 1; + dt.d = tm1->tm_mday; + if (isatty(STDOUT_FILENO) && tgetent(tbuf, NULL) == 1) { + b = cbuf; + term_so = tgetstr("so", &b); + term_se = tgetstr("se", &b); + today = sndaysb(&dt); + } /* * Use locale to determine the country code, @@ -235,7 +258,7 @@ main(int argc, char *argv[]) if (flag_backward) nswitchb = ndaysj(&ukswitch); - while ((ch = getopt(argc, argv, "Jejops:wy")) != -1) + while ((ch = getopt(argc, argv, "Jejm:ops:wy")) != -1) switch (ch) { case 'J': if (flag_backward) @@ -251,6 +274,9 @@ main(int argc, char *argv[]) case 'j': flag_julian_day = 1; break; + case 'm': + flag_month = optarg; + break; case 'o': if (flag_backward) usage(); @@ -291,28 +317,18 @@ main(int argc, char *argv[]) argc -= optind; argv += optind; - if (argc == 0) { - time_t t; - struct tm *tm; - - t = time(NULL); - tm = localtime(&t); - y = tm->tm_year + 1900; - m = tm->tm_mon + 1; - } - switch (argc) { case 2: if (flag_easter) usage(); - m = parsemonth(*argv++); - if (m < 1 || m > 12) - errx(EX_USAGE, - "%s is neither a month number (1..12) nor a name", - argv[-1]); + flag_month = *argv++; /* FALLTHROUGH */ case 1: - y = atoi(*argv++); + if (strcmp(*argv, ".") == 0) + /* year was already set above */ + argv++; + else + y = atoi(*argv++); if (y < 1 || y > 9999) errx(EX_USAGE, "year %d not in range 1..9999", y); break; @@ -322,14 +338,22 @@ main(int argc, char *argv[]) usage(); } + if (flag_month != NULL) { + m = parsemonth(flag_month); + if (m < 1 || m > 12) + errx(EX_USAGE, + "%s is neither a month number (1..12) nor a name", + flag_month); + } + if (flag_easter) printeaster(y, flag_julian_cal, flag_orthodox); - else if (argc == 1 || flag_hole_year) + else if (argc == 1 || flag_hole_year) { if (flag_backward) printyearb(y, flag_julian_day); else printyear(y, flag_julian_day); - else + } else if (flag_backward) printmonthb(y, m, flag_julian_day); else @@ -477,28 +501,28 @@ printyear(int y, int jd_flag) mw, year[j + 2].name, year[j + 3].name); for (i = 0; i != 7; i++) { - printf("%.2s%-*s%-*s", + printf("%.2s%s%s", wds.names[i], - mw, year[j].lines[i], - mw, year[j + 1].lines[i]); + year[j].lines[i], + year[j + 1].lines[i]); if (mpl == 3) printf("%s\n", year[j + 2].lines[i]); else - printf("%-*s%s\n", - mw, year[j + 2].lines[i], + printf("%s%s\n", + year[j + 2].lines[i], year[j + 3].lines[i]); } if (flag_weeks) { if (mpl == 3) - printf(" %-*s%-*s%-s\n", - mw, year[j].weeks, - mw, year[j + 1].weeks, + printf(" %s%s%-s\n", + year[j].weeks, + year[j + 1].weeks, year[j + 2].weeks); else - printf(" %-*s%-*s%-*s%-s\n", - mw, year[j].weeks, - mw, year[j + 1].weeks, - mw, year[j + 2].weeks, + printf(" %s%s%s%-s\n", + year[j].weeks, + year[j + 1].weeks, + year[j + 2].weeks, year[j + 3].weeks); } } @@ -556,13 +580,13 @@ printyearb(int y, int jd_flag) wds.names[5]); for (i = 0; i != 6; i++) { if (mpl == 2) - printf("%-*s %s\n", - mw, year[j].lines[i]+1, + printf("%s %s\n", + year[j].lines[i]+1, year[j + 1].lines[i]+1); else - printf("%-*s %-*s %s\n", - mw, year[j].lines[i]+1, - mw, year[j + 1].lines[i]+1, + printf("%s %s %s\n", + year[j].lines[i]+1, + year[j + 1].lines[i]+1, year[j + 2].lines[i]+1); } @@ -579,8 +603,9 @@ mkmonth(int y, int m, int jd_flag, struct monthlines *mlines) int dw; /* width of numbers */ int first; /* first day of month */ int firstm; /* first day of first week of month */ - int i, j, k; /* just indices */ + int i, j, k, l; /* just indices */ int last; /* the first day of next month */ + int lastm; /* first day of first week of next month */ int jan1 = 0; /* the first day of this year */ char *ds; /* pointer to day strings (daystr or * jdaystr) */ @@ -608,8 +633,11 @@ mkmonth(int y, int m, int jd_flag, struct monthlines *mlines) /* * Set firstm to the day number of monday of the first week of * this month. (This might be in the last month) + * Set lastm to the day number of monday of the first week of + * the next month. Our canvas spans [firstm, lastm). */ firstm = first - weekday(first); + lastm = last + 7 - weekday(last); /* Set ds (daystring) and dw (daywidth) according to the jd_flag */ if (jd_flag) { @@ -626,24 +654,40 @@ mkmonth(int y, int m, int jd_flag, struct monthlines *mlines) * column is one day number. print column index: k. */ for (i = 0; i != 7; i++) { - for (j = firstm + i, k = 0; j < last; j += 7, k += dw) - if (j >= first) { + l = 0; + for (j = firstm + i, k = 0; j < lastm; j += 7, k += dw) { + if (j >= first && j < last) { if (jd_flag) dt.d = j - jan1 + 1; else sdate(j, &dt); - memcpy(mlines->lines[i] + k, - ds + dt.d * dw, dw); + if (j == today && (term_so != NULL && term_se != NULL)) { + l = strlen(term_so); + /* separator */ + mlines->lines[i][k] = ' '; + } + /* the actual text */ + memcpy(mlines->lines[i] + k + l, + ds + dt.d * dw, dw); + if (j == today && (term_so != NULL && term_se != NULL)) { + /* highlight on */ + memcpy(mlines->lines[i] + k + 1, term_so, l); + /* highlight off */ + memcpy(mlines->lines[i] + k + l + dw, term_se, + strlen(term_se)); + l = strlen(term_se) + strlen(term_so); + } } else - memcpy(mlines->lines[i] + k, " ", dw); - mlines->lines[i][k] = '\0'; + memcpy(mlines->lines[i] + k + l, " ", dw); + } + mlines->lines[i][k + l] = '\0'; } /* fill the weeknumbers */ if (flag_weeks) { - for (j = firstm, k = 0; j < last; k += dw, j += 7) - if (j <= nswitch) + for (j = firstm, k = 0; j < lastm; k += dw, j += 7) + if (j <= nswitch || j >= last) memset(mlines->weeks + k, ' ', dw); else memcpy(mlines->weeks + k, @@ -662,7 +706,7 @@ mkmonthb(int y, int m, int jd_flag, struct monthlines *mlines) int dw; /* width of numbers */ int first; /* first day of month */ int firsts; /* sunday of first week of month */ - int i, j, k; /* just indices */ + int i, j, k, l; /* just indices */ int jan1 = 0; /* the first day of this year */ int last; /* the first day of next month */ char *ds; /* pointer to day strings (daystr or @@ -722,21 +766,37 @@ mkmonthb(int y, int m, int jd_flag, struct monthlines *mlines) * column is one day number. print column index: k. */ for (i = 0; i != 6; i++) { - for (j = firsts + 7 * i, k = 0; j < last && k != dw * 7; - j++, k += dw) - if (j >= first) { + l = 0; + for (j = firsts + 7 * i, k = 0; k != dw * 7; + j++, k += dw) { + if (j >= first && j < last) { if (jd_flag) dt.d = j - jan1 + 1; else sdateb(j, &dt); - memcpy(mlines->lines[i] + k, - ds + dt.d * dw, dw); + if (j == today && (term_so != NULL && term_se != NULL)) { + l = strlen(term_so); + /* separator */ + mlines->lines[i][k] = ' '; + } + /* the actual text */ + memcpy(mlines->lines[i] + k + l, + ds + dt.d * dw, dw); + if (j == today && (term_so != NULL && term_se != NULL)) { + /* highlight on */ + memcpy(mlines->lines[i] + k + 1, term_so, l); + /* highlight off */ + memcpy(mlines->lines[i] + k + l + dw, term_se, + strlen(term_se)); + l = strlen(term_se) + strlen(term_so); + } } else - memcpy(mlines->lines[i] + k, " ", dw); + memcpy(mlines->lines[i] + k + l, " ", dw); + } if (k == 0) mlines->lines[i][1] = '\0'; else - mlines->lines[i][k] = '\0'; + mlines->lines[i][k + l] = '\0'; } } diff --git a/usr.bin/netstat/Makefile b/usr.bin/netstat/Makefile index 798e360846..5e908b136d 100644 --- a/usr.bin/netstat/Makefile +++ b/usr.bin/netstat/Makefile @@ -7,7 +7,6 @@ SRCS= if.c inet.c inet6.c main.c mbuf.c mroute.c ipx.c route.c \ unix.c atalk.c netgraph.c mroute6.c ipsec.c # iso.c ns.c tp_astring.c CFLAGS+=-DIPSEC CFLAGS+=-DINET6 -WARNS?= 0 #CFLAGS+=-g #.PATH: ${.CURDIR}/../../sys/netiso diff --git a/usr.bin/netstat/atalk.c b/usr.bin/netstat/atalk.c index 59b6ae97ca..86a4e787e8 100644 --- a/usr.bin/netstat/atalk.c +++ b/usr.bin/netstat/atalk.c @@ -66,7 +66,7 @@ static int first = 1; * -a (all) flag is specified. */ -static char * +static const char * at_pr_net(struct sockaddr_at *sat, int numeric) { static char mybuf[50]; @@ -83,7 +83,7 @@ static char mybuf[50]; return mybuf; } -static char * +static const char * at_pr_host(struct sockaddr_at *sat, int numeric) { static char mybuf[50]; @@ -100,7 +100,7 @@ static char mybuf[50]; return mybuf; } -static char * +static const char * at_pr_port(struct sockaddr_at *sat) { static char mybuf[50]; @@ -209,7 +209,7 @@ atalk_print2(struct sockaddr *sa, struct sockaddr *mask, int what) } void -atalkprotopr(u_long off __unused, char *name, int af __unused) +atalkprotopr(u_long off __unused, const char *name, int af1 __unused) { struct ddpcb *this, *next; @@ -258,7 +258,7 @@ atalkprotopr(u_long off __unused, char *name, int af __unused) * Dump DDP statistics structure. */ void -ddp_stats(u_long off __unused, char *name, int af __unused) +ddp_stats(u_long off __unused, const char *name, int af1 __unused) { struct ddpstat ddpstat; diff --git a/usr.bin/netstat/if.c b/usr.bin/netstat/if.c index 3864a3fc36..496f5bf844 100644 --- a/usr.bin/netstat/if.c +++ b/usr.bin/netstat/if.c @@ -75,7 +75,6 @@ static void sidewaysintpr (u_int, u_long); static void catchalarm (int); #ifdef INET6 -char *netname6 (struct sockaddr_in6 *, struct in6_addr *); static char ntop_buf[INET6_ADDRSTRLEN]; /* for inet_ntop() */ #endif @@ -104,7 +103,7 @@ show_stat(const char *fmt, int width, u_long value, short showvalue) * Print a description of the network interfaces. */ void -intpr(int interval, u_long ifnetaddr, void (*pfunc)(char *)) +intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *)) { struct ifnet ifnet; struct ifaddr_container ifac; @@ -145,8 +144,8 @@ intpr(int interval, u_long ifnetaddr, void (*pfunc)(char *)) printf("ifnet: symbol not defined\n"); return; } - if (interval) { - sidewaysintpr((unsigned)interval, ifnetaddr); + if (interval1) { + sidewaysintpr((unsigned)interval1, ifnetaddr); return; } if (kread(ifnetaddr, (char *)&ifnethead, sizeof ifnethead)) @@ -295,7 +294,7 @@ intpr(int interval, u_long ifnetaddr, void (*pfunc)(char *)) netname6(&ifaddr.in6.ia_addr, &ifaddr.in6.ia_prefixmask.sin6_addr)); printf("%-17.17s ", - (char *)inet_ntop(AF_INET6, + inet_ntop(AF_INET6, &sin6->sin6_addr, ntop_buf, sizeof(ntop_buf))); @@ -497,13 +496,13 @@ u_char signalled; /* set if alarm goes off "early" */ /* * Print a running summary of interface statistics. - * Repeat display every interval seconds, showing statistics - * collected over that interval. Assumes that interval is non-zero. + * Repeat display every interval1 seconds, showing statistics + * collected over that interval. Assumes that interval1 is non-zero. * First line printed at top of screen is always cumulative. * XXX - should be rewritten to use ifmib(4). */ static void -sidewaysintpr(unsigned interval, u_long off) +sidewaysintpr(unsigned interval1, u_long off) { struct ifnet ifnet; u_long firstifnet; @@ -559,7 +558,7 @@ sidewaysintpr(unsigned interval, u_long off) (void)signal(SIGALRM, catchalarm); signalled = NO; - (void)alarm(interval); + (void)alarm(interval1); first = 1; banner: printf("%17s %14s %16s", "input", @@ -648,7 +647,7 @@ loop: } sigsetmask(oldmask); signalled = NO; - (void)alarm(interval); + (void)alarm(interval1); line++; first = 0; if (line == 21) diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c index c6984ced62..1f7fc36117 100644 --- a/usr.bin/netstat/inet.c +++ b/usr.bin/netstat/inet.c @@ -97,13 +97,12 @@ static int ppr_first = 1; static void outputpcb(int proto, const char *name, struct inpcb *inp, struct xsocket *so, struct tcpcb *tp); void -protopr(u_long proto, char *name, int af) +protopr(u_long proto, const char *name, int af1 __unused) { int istcp; - int i; void *buf; const char *mibvar; - size_t len; + size_t i, len; istcp = 0; switch (proto) { @@ -180,7 +179,7 @@ outputpcb(int proto, const char *name, struct inpcb *inp, struct xsocket *so, st static struct clockinfo clockinfo; if (clockinfo.hz == 0) { - int size = sizeof(clockinfo); + size_t size = sizeof(clockinfo); sysctlbyname("kern.clockrate", &clockinfo, &size, NULL, 0); if (clockinfo.hz == 0) clockinfo.hz = 100; @@ -395,7 +394,7 @@ CPU_STATS_FUNC(ip, struct ip_stats); * Dump TCP statistics structure. */ void -tcp_stats(u_long off __unused, char *name, int af __unused) +tcp_stats(u_long off __unused, const char *name, int af1 __unused) { struct tcp_stats tcpstat, *stattmp; struct tcp_stats zerostat[SMP_MAXCPU]; @@ -536,7 +535,7 @@ tcp_stats(u_long off __unused, char *name, int af __unused) * Dump UDP statistics structure. */ void -udp_stats(u_long off __unused, char *name, int af __unused) +udp_stats(u_long off __unused, const char *name, int af1 __unused) { struct udpstat udpstat, zerostat; size_t len = sizeof udpstat; @@ -590,7 +589,7 @@ udp_stats(u_long off __unused, char *name, int af __unused) * Dump CARP statistics structure. */ void -carp_stats(u_long off, const char *name, int af1 __unused) +carp_stats(u_long off __unused, const char *name, int af1 __unused) { struct carpstats carpstat, zerostat; size_t len = sizeof(struct carpstats); @@ -606,23 +605,23 @@ carp_stats(u_long off, const char *name, int af1 __unused) printf("%s:\n", name); #define p(f, m) if (carpstat.f || sflag <= 1) \ - printf(m, (unsigned long long)carpstat.f, plural((int)carpstat.f)) + printf(m, (uintmax_t)carpstat.f, plural((int)carpstat.f)) #define p2(f, m) if (carpstat.f || sflag <= 1) \ - printf(m, (unsigned long long)carpstat.f) - - p(carps_ipackets, "\t%llu packet%s received (IPv4)\n"); - p(carps_ipackets6, "\t%llu packet%s received (IPv6)\n"); - p(carps_badttl, "\t\t%llu packet%s discarded for wrong TTL\n"); - p(carps_hdrops, "\t\t%llu packet%s shorter than header\n"); - p(carps_badsum, "\t\t%llu discarded for bad checksum%s\n"); - p(carps_badver, "\t\t%llu discarded packet%s with a bad version\n"); - p2(carps_badlen, "\t\t%llu discarded because packet too short\n"); - p2(carps_badauth, "\t\t%llu discarded for bad authentication\n"); - p2(carps_badvhid, "\t\t%llu discarded for bad vhid\n"); - p2(carps_badaddrs, "\t\t%llu discarded because of a bad address list\n"); - p(carps_opackets, "\t%llu packet%s sent (IPv4)\n"); - p(carps_opackets6, "\t%llu packet%s sent (IPv6)\n"); - p2(carps_onomem, "\t\t%llu send failed due to mbuf memory error\n"); + printf(m, (uintmax_t)carpstat.f) + + p(carps_ipackets, "\t%ju packet%s received (IPv4)\n"); + p(carps_ipackets6, "\t%ju packet%s received (IPv6)\n"); + p(carps_badttl, "\t\t%ju packet%s discarded for wrong TTL\n"); + p(carps_hdrops, "\t\t%ju packet%s shorter than header\n"); + p(carps_badsum, "\t\t%ju discarded for bad checksum%s\n"); + p(carps_badver, "\t\t%ju discarded packet%s with a bad version\n"); + p2(carps_badlen, "\t\t%ju discarded because packet too short\n"); + p2(carps_badauth, "\t\t%ju discarded for bad authentication\n"); + p2(carps_badvhid, "\t\t%ju discarded for bad vhid\n"); + p2(carps_badaddrs, "\t\t%ju discarded because of a bad address list\n"); + p(carps_opackets, "\t%ju packet%s sent (IPv4)\n"); + p(carps_opackets6, "\t%ju packet%s sent (IPv6)\n"); + p2(carps_onomem, "\t\t%ju send failed due to mbuf memory error\n"); #if notyet p(carps_ostates, "\t\t%s state update%s sent\n"); #endif @@ -634,7 +633,7 @@ carp_stats(u_long off, const char *name, int af1 __unused) * Dump IP statistics structure. */ void -ip_stats(u_long off __unused, char *name, int af __unused) +ip_stats(u_long off __unused, const char *name, int af1 __unused) { struct ip_stats ipstat, *stattmp; struct ip_stats zerostat[SMP_MAXCPU]; @@ -706,7 +705,7 @@ ip_stats(u_long off __unused, char *name, int af __unused) #undef p1a } -static char *icmpnames[] = { +static const char *icmpnames[] = { "echo reply", "#1", "#2", @@ -732,7 +731,7 @@ static char *icmpnames[] = { * Dump ICMP statistics. */ void -icmp_stats(u_long off __unused, char *name, int af __unused) +icmp_stats(u_long off __unused, const char *name, int af1 __unused) { struct icmpstat icmpstat, zerostat; int i, first; @@ -807,7 +806,7 @@ icmp_stats(u_long off __unused, char *name, int af __unused) * Dump IGMP statistics structure. */ void -igmp_stats(u_long off __unused, char *name, int af __unused) +igmp_stats(u_long off __unused, const char *name, int af1 __unused) { struct igmpstat igmpstat, zerostat; size_t len = sizeof igmpstat; @@ -843,7 +842,7 @@ igmp_stats(u_long off __unused, char *name, int af __unused) * Dump PIM statistics structure. */ void -pim_stats(u_long off __unused, char *name, int af1 __unused) +pim_stats(u_long off __unused, const char *name, int af1 __unused) { struct pimstat pimstat, zerostat; size_t len = sizeof pimstat; @@ -860,20 +859,20 @@ pim_stats(u_long off __unused, char *name, int af1 __unused) printf("%s:\n", name); #define p(f, m) if (pimstat.f || sflag <= 1) \ - printf(m, pimstat.f, plural(pimstat.f)) + printf(m, (uintmax_t)pimstat.f, plural(pimstat.f)) #define py(f, m) if (pimstat.f || sflag <= 1) \ - printf(m, pimstat.f, pimstat.f != 1 ? "ies" : "y") - p(pims_rcv_total_msgs, "\t%llu message%s received\n"); - p(pims_rcv_total_bytes, "\t%llu byte%s received\n"); - p(pims_rcv_tooshort, "\t%llu message%s received with too few bytes\n"); - p(pims_rcv_badsum, "\t%llu message%s received with bad checksum\n"); - p(pims_rcv_badversion, "\t%llu message%s received with bad version\n"); - p(pims_rcv_registers_msgs, "\t%llu data register message%s received\n"); - p(pims_rcv_registers_bytes, "\t%llu data register byte%s received\n"); - p(pims_rcv_registers_wrongiif, "\t%llu data register message%s received on wrong iif\n"); - p(pims_rcv_badregisters, "\t%llu bad register%s received\n"); - p(pims_snd_registers_msgs, "\t%llu data register message%s sent\n"); - p(pims_snd_registers_bytes, "\t%llu data register byte%s sent\n"); + printf(m, (uintmax_t)pimstat.f, pimstat.f != 1 ? "ies" : "y") + p(pims_rcv_total_msgs, "\t%ju message%s received\n"); + p(pims_rcv_total_bytes, "\t%ju byte%s received\n"); + p(pims_rcv_tooshort, "\t%ju message%s received with too few bytes\n"); + p(pims_rcv_badsum, "\t%ju message%s received with bad checksum\n"); + p(pims_rcv_badversion, "\t%ju message%s received with bad version\n"); + p(pims_rcv_registers_msgs, "\t%ju data register message%s received\n"); + p(pims_rcv_registers_bytes, "\t%ju data register byte%s received\n"); + p(pims_rcv_registers_wrongiif, "\t%ju data register message%s received on wrong iif\n"); + p(pims_rcv_badregisters, "\t%ju bad register%s received\n"); + p(pims_snd_registers_msgs, "\t%ju data register message%s sent\n"); + p(pims_snd_registers_bytes, "\t%ju data register byte%s sent\n"); #undef p #undef py } @@ -882,7 +881,7 @@ pim_stats(u_long off __unused, char *name, int af1 __unused) * Pretty print an Internet address (net address + port). */ void -inetprint(struct in_addr *in, int port, const char *proto, int numeric_port) +inetprint(struct in_addr *in, int port, const char *proto, int num_port) { struct servent *sp = 0; char line[80], *cp; @@ -891,9 +890,9 @@ inetprint(struct in_addr *in, int port, const char *proto, int numeric_port) if (Wflag) sprintf(line, "%s.", inetname(in)); else - sprintf(line, "%.*s.", (Aflag && !numeric_port) ? 12 : 16, inetname(in)); + sprintf(line, "%.*s.", (Aflag && !num_port) ? 12 : 16, inetname(in)); cp = strchr(line, '\0'); - if (!numeric_port && port) + if (!num_port && port) sp = getservbyport((int)port, proto); if (sp || port == 0) sprintf(cp, "%.15s ", sp ? sp->s_name : "*"); diff --git a/usr.bin/netstat/inet6.c b/usr.bin/netstat/inet6.c index 558e6995ed..e9ff2541c2 100644 --- a/usr.bin/netstat/inet6.c +++ b/usr.bin/netstat/inet6.c @@ -76,7 +76,7 @@ void inet6print (struct in6_addr *, int, char *, int); static char ntop_buf[INET6_ADDRSTRLEN]; -static char *ip6nh[] = { +static const char *ip6nh[] = { "hop by hop", "ICMP", "IGMP", @@ -339,7 +339,7 @@ static char *ip6nh[] = { * Dump IP6 statistics structure. */ void -ip6_stats(u_long off __unused, char *name, int af __unused) +ip6_stats(u_long off __unused, const char *name, int af1 __unused) { struct ip6stat ip6stat; int first, i; @@ -549,7 +549,7 @@ ip6_ifstats(char *ifname) #undef p_5 } -static char *icmp6names[] = { +static const char *icmp6names[] = { "#0", "unreach", "packet too big", @@ -812,12 +812,12 @@ static char *icmp6names[] = { * Dump ICMP6 statistics. */ void -icmp6_stats(u_long off __unused, char *name, int af __unused) +icmp6_stats(u_long off __unused, const char *name, int af1 __unused) { struct icmp6stat icmp6stat; - int i, first; + int first; int mib[4]; - size_t len; + size_t i, len; mib[0] = CTL_NET; mib[1] = PF_INET6; @@ -962,7 +962,7 @@ icmp6_ifstats(char *ifname) * Dump PIM statistics structure. */ void -pim6_stats(u_long off __unused, char *name, int af __unused) +pim6_stats(u_long off __unused, const char *name, int af1 __unused) { struct pim6stat pim6stat; @@ -987,7 +987,7 @@ pim6_stats(u_long off __unused, char *name, int af __unused) * Dump raw ip6 statistics structure. */ void -rip6_stats(u_long off __unused, char *name, int af __unused) +rip6_stats(u_long off __unused, const char *name, int af1 __unused) { struct rip6stat rip6stat; u_quad_t delivered; diff --git a/usr.bin/netstat/ipsec.c b/usr.bin/netstat/ipsec.c index eaf49ee958..6fb7dda160 100644 --- a/usr.bin/netstat/ipsec.c +++ b/usr.bin/netstat/ipsec.c @@ -233,7 +233,7 @@ print_ipsecstats(void) } void -ipsec_stats(u_long off __unused, char *name, int af __unused) +ipsec_stats(u_long off __unused, const char *name, int af1 __unused) { if (off == 0) return; @@ -257,7 +257,7 @@ pfkey_msgtype_names(int x) } void -pfkey_stats(u_long off __unused, char *name, int af __unused) +pfkey_stats(u_long off __unused, const char *name, int af1 __unused) { struct pfkeystat pfkeystat; unsigned first, type; diff --git a/usr.bin/netstat/ipx.c b/usr.bin/netstat/ipx.c index 15d6f0ee31..93e98309da 100644 --- a/usr.bin/netstat/ipx.c +++ b/usr.bin/netstat/ipx.c @@ -64,6 +64,8 @@ #include #include "netstat.h" +extern char *tcpstates[]; + struct ipxpcb ipxpcb; struct spxpcb spxpcb; struct socket sockb; @@ -80,7 +82,7 @@ static int first = 1; */ void -ipxprotopr(u_long off, char *name, int af __unused) +ipxprotopr(u_long off, const char *name, int af1 __unused) { struct ipxpcb cb; struct ipxpcb *prev, *next; @@ -136,7 +138,6 @@ ipxprotopr(u_long off, char *name, int af __unused) printf(Aflag?" %-18.18s":" %-22.22s", ipx_prpr(&ipxpcb.ipxp_laddr)); printf(Aflag?" %-18.18s":" %-22.22s", ipx_prpr(&ipxpcb.ipxp_faddr)); if (isspx) { - extern char *tcpstates[]; if (spxpcb.s_state >= TCP_NSTATES) printf(" %d", spxpcb.s_state); else @@ -156,7 +157,7 @@ ipxprotopr(u_long off, char *name, int af __unused) * Dump SPX statistics structure. */ void -spx_stats(u_long off, char *name, int af __unused) +spx_stats(u_long off, const char *name, int af1 __unused) { struct spx_istat spx_istat; #define spxstat spx_istat.newstats @@ -232,7 +233,7 @@ spx_stats(u_long off, char *name, int af __unused) * Dump IPX statistics structure. */ void -ipx_stats(u_long off, char *name, int af __unused) +ipx_stats(u_long off, const char *name, int af1 __unused) { struct ipxstat ipxstat; @@ -340,7 +341,7 @@ ipx_erputil(int z, int c) } #endif /* IPXERRORMSGS */ -static struct sockaddr_ipx ssipx = {AF_IPX}; +static struct sockaddr_ipx ssipx = { .sipx_family = AF_IPX }; static char *ipx_prpr(struct ipx_addr *x) diff --git a/usr.bin/netstat/iso.c b/usr.bin/netstat/iso.c index 26348b63b3..b831f7e60f 100644 --- a/usr.bin/netstat/iso.c +++ b/usr.bin/netstat/iso.c @@ -208,7 +208,7 @@ static int first = 1; * -a (all) flag is specified. */ void -iso_protopr(u_long off, char *name, int af __unused) +iso_protopr(u_long off, const char *name, int af __unused) { struct isopcb cb; struct isopcb *prev, *next; @@ -292,7 +292,7 @@ iso_protopr1(u_long kern_addr, int istp) } void -tp_protopr(u_long off, char *name, int af __unused) +tp_protopr(u_long off, const char *name, int af __unused) { extern char *tp_sstring[]; struct tp_ref *tpr, *tpr_base; @@ -443,7 +443,7 @@ isonetprint(struct iso_addr *iso, char *sufx, u_short sufxlen, int islocal) #ifdef notdef static void -x25_protopr(u_long off, char *name, int af __unused) +x25_protopr(u_long off, const char *name, int af __unused) { static char *xpcb_states[] = { "CLOSED", diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c index 8737217e09..6f2f1642f6 100644 --- a/usr.bin/netstat/main.c +++ b/usr.bin/netstat/main.c @@ -61,109 +61,109 @@ static struct nlist nl[] = { #define N_IFNET 0 - { "_ifnet" }, + { .n_name = "_ifnet" }, #define N_IMP 1 - { "_imp_softc" }, + { .n_name = "_imp_softc" }, #define N_RTSTAT 2 - { "_rtstat" }, + { .n_name = "_rtstat" }, #define N_UNIXSW 3 - { "_localsw" }, + { .n_name = "_localsw" }, #define N_IDP 4 - { "_nspcb"}, + { .n_name = "_nspcb"}, #define N_IDPSTAT 5 - { "_idpstat"}, + { .n_name = "_idpstat"}, #define N_SPPSTAT 6 - { "_spp_istat"}, + { .n_name = "_spp_istat"}, #define N_NSERR 7 - { "_ns_errstat"}, + { .n_name = "_ns_errstat"}, #define N_CLNPSTAT 8 - { "_clnp_stat"}, + { .n_name = "_clnp_stat"}, #define IN_NOTUSED 9 - { "_tp_inpcb" }, + { .n_name = "_tp_inpcb" }, #define ISO_TP 10 - { "_tp_refinfo" }, + { .n_name = "_tp_refinfo" }, #define N_TPSTAT 11 - { "_tp_stat" }, + { .n_name = "_tp_stat" }, #define N_ESISSTAT 12 - { "_esis_stat"}, + { .n_name = "_esis_stat"}, #define N_NIMP 13 - { "_nimp"}, + { .n_name = "_nimp"}, #define N_RTREE 14 - { "_rt_tables"}, + { .n_name = "_rt_tables"}, #define N_CLTP 15 - { "_cltb"}, + { .n_name = "_cltb"}, #define N_CLTPSTAT 16 - { "_cltpstat"}, + { .n_name = "_cltpstat"}, #define N_NFILE 17 - { "_nfile" }, + { .n_name = "_nfile" }, #define N_FILE 18 - { "_file" }, + { .n_name = "_file" }, #define N_MRTSTAT 19 - { "_mrtstat" }, + { .n_name = "_mrtstat" }, #define N_MFCTABLE 20 - { "_mfctable" }, + { .n_name = "_mfctable" }, #define N_VIFTABLE 21 - { "_viftable" }, + { .n_name = "_viftable" }, #define N_IPX 22 - { "_ipxpcb"}, + { .n_name = "_ipxpcb"}, #define N_IPXSTAT 23 - { "_ipxstat"}, + { .n_name = "_ipxstat"}, #define N_SPXSTAT 24 - { "_spx_istat"}, + { .n_name = "_spx_istat"}, #define N_DDPSTAT 25 - { "_ddpstat"}, + { .n_name = "_ddpstat"}, #define N_DDPCB 26 - { "_ddpcb"}, + { .n_name = "_ddpcb"}, #define N_NGSOCKS 27 - { "_ngsocklist"}, + { .n_name = "_ngsocklist"}, #define N_IP6STAT 28 - { "_ip6stat" }, + { .n_name = "_ip6stat" }, #define N_ICMP6STAT 29 - { "_icmp6stat" }, + { .n_name = "_icmp6stat" }, #define N_IPSECSTAT 30 - { "_ipsecstat" }, + { .n_name = "_ipsecstat" }, #define N_IPSEC6STAT 31 - { "_ipsec6stat" }, + { .n_name = "_ipsec6stat" }, #define N_PIM6STAT 32 - { "_pim6stat" }, + { .n_name = "_pim6stat" }, #define N_MRT6PROTO 33 - { "_ip6_mrtproto" }, + { .n_name = "_ip6_mrtproto" }, #define N_MRT6STAT 34 - { "_mrt6stat" }, + { .n_name = "_mrt6stat" }, #define N_MF6CTABLE 35 - { "_mf6ctable" }, + { .n_name = "_mf6ctable" }, #define N_MIF6TABLE 36 - { "_mif6table" }, + { .n_name = "_mif6table" }, #define N_PFKEYSTAT 37 - { "_pfkeystat" }, + { .n_name = "_pfkeystat" }, #define N_MBSTAT 38 - { "_mbstat" }, + { .n_name = "_mbstat" }, #define N_MBTYPES 39 - { "_mbtypes" }, + { .n_name = "_mbtypes" }, #define N_NMBCLUSTERS 40 - { "_nmbclusters" }, + { .n_name = "_nmbclusters" }, #define N_NMBUFS 41 - { "_nmbufs" }, + { .n_name = "_nmbufs" }, #define N_RTTRASH 42 - { "_rttrash" }, + { .n_name = "_rttrash" }, #define N_NCPUS 43 - { "_ncpus" }, + { .n_name = "_ncpus" }, #define N_CARPSTAT 44 - { "_carpstats" }, - { "" }, + { .n_name = "_carpstats" }, + { .n_name = NULL }, }; struct protox { u_char pr_index; /* index into nlist of cb head */ u_char pr_sindex; /* index into nlist of stat block */ u_char pr_wanted; /* 1 if wanted, 0 otherwise */ - void (*pr_cblocks)(u_long, char *, int); + void (*pr_cblocks)(u_long, const char *, int); /* control blocks printing routine */ - void (*pr_stats)(u_long, char *, int); + void (*pr_stats)(u_long, const char *, int); /* statistics printing routine */ void (*pr_istats)(char *); /* per/if statistics printing routine */ - char *pr_name; /* well-known name */ - int pr_usesysctl; /* true if we use sysctl, not kvm */ + const char *pr_name; /* well-known name */ + u_int pr_usesysctl; /* true if we use sysctl, not kvm */ } protox[] = { { -1, -1, 1, protopr, tcp_stats, NULL, "tcp", IPPROTO_TCP }, @@ -184,7 +184,7 @@ struct protox { { -1, N_CARPSTAT, 1, 0, carp_stats, NULL, "carp", 0}, { -1, -1, 0, 0, - 0, NULL, 0 } + 0, NULL, NULL, 0} }; #ifdef INET6 @@ -225,18 +225,18 @@ struct protox pfkeyprotox[] = { struct protox atalkprotox[] = { { N_DDPCB, N_DDPSTAT, 1, atalkprotopr, - ddp_stats, NULL, "ddp" }, + ddp_stats, NULL, "ddp", 0 }, { -1, -1, 0, 0, - 0, NULL, 0 } + 0, NULL, NULL, 0 } }; struct protox netgraphprotox[] = { { N_NGSOCKS, -1, 1, netgraphprotopr, - NULL, NULL, "ctrl" }, + NULL, NULL, "ctrl", 0 }, { N_NGSOCKS, -1, 1, netgraphprotopr, - NULL, NULL, "data" }, + NULL, NULL, "data", 0 }, { -1, -1, 0, 0, - 0, NULL, 0 } + 0, NULL, NULL, 0 } }; struct protox ipxprotox[] = { @@ -293,7 +293,7 @@ struct protox *protoprotox[] = { #endif NULL }; -static void printproto (struct protox *, char *); +static void printproto (struct protox *, const char *); static void usage (void); static struct protox *name2protox (char *); static struct protox *knownname (char *); @@ -607,9 +607,9 @@ main(int argc, char **argv) * is not in the namelist, ignore this one. */ static void -printproto(struct protox *tp, char *name) +printproto(struct protox *tp, const char *name) { - void (*pr)(u_long, char *, int); + void (*pr)(u_long, const char *, int); u_long off; if (sflag) { @@ -687,13 +687,13 @@ kread(u_long addr, char *buf, int size) return (0); } -char * +const char * plural(int n) { return (n != 1 ? "s" : ""); } -char * +const char * plurales(int n) { return (n != 1 ? "es" : ""); diff --git a/usr.bin/netstat/mbuf.c b/usr.bin/netstat/mbuf.c index 59c8fc80b4..a9fbbacfe8 100644 --- a/usr.bin/netstat/mbuf.c +++ b/usr.bin/netstat/mbuf.c @@ -52,7 +52,7 @@ typedef int bool; static struct mbtypenames { int mt_type; - char *mt_name; + const char *mt_name; } mbtypenames[] = { { MT_DATA, "data" }, { MT_OOBDATA, "oob data" }, diff --git a/usr.bin/netstat/mroute.c b/usr.bin/netstat/mroute.c index 739caa3512..68e3aa8f0c 100644 --- a/usr.bin/netstat/mroute.c +++ b/usr.bin/netstat/mroute.c @@ -187,11 +187,11 @@ print_bw_meter(struct bw_meter *bw_meter, int *banner_printed) /* The measured values */ if (bw_meter->bm_flags & BW_METER_UNIT_PACKETS) - sprintf(s1, "%llu", bw_meter->bm_measured.b_packets); + sprintf(s1, "%ju", (uintmax_t)bw_meter->bm_measured.b_packets); else sprintf(s1, "?"); if (bw_meter->bm_flags & BW_METER_UNIT_BYTES) - sprintf(s2, "%llu", bw_meter->bm_measured.b_bytes); + sprintf(s2, "%ju", (uintmax_t)bw_meter->bm_measured.b_bytes); else sprintf(s2, "?"); sprintf(s0, "%lu.%lu|%s|%s", @@ -210,11 +210,11 @@ print_bw_meter(struct bw_meter *bw_meter, int *banner_printed) /* The threshold values */ if (bw_meter->bm_flags & BW_METER_UNIT_PACKETS) - sprintf(s1, "%llu", bw_meter->bm_threshold.b_packets); + sprintf(s1, "%ju", (uintmax_t)bw_meter->bm_threshold.b_packets); else sprintf(s1, "?"); if (bw_meter->bm_flags & BW_METER_UNIT_BYTES) - sprintf(s2, "%llu", bw_meter->bm_threshold.b_bytes); + sprintf(s2, "%ju", (uintmax_t)bw_meter->bm_threshold.b_bytes); else sprintf(s2, "?"); sprintf(s0, "%lu.%lu|%s|%s", diff --git a/usr.bin/netstat/netgraph.c b/usr.bin/netstat/netgraph.c index f8d8a3ac22..50f8fee464 100644 --- a/usr.bin/netstat/netgraph.c +++ b/usr.bin/netstat/netgraph.c @@ -64,7 +64,7 @@ static int first = 1; static int csock = -1; void -netgraphprotopr(u_long off, char *name, int af __unused) +netgraphprotopr(u_long off, const char *name, int af1 __unused) { struct ngpcb *this, *next; struct ngpcb ngpcb; @@ -77,7 +77,8 @@ netgraphprotopr(u_long off, char *name, int af __unused) const char *const modname = "ng_socket.ko"; /* XXX We should get "mpath" from "sysctl kern.module_path" */ const char *mpath[] = { "/", "/boot/", "/boot/modules/", NULL }; - struct nlist sym[] = { { "_ngsocklist" }, { NULL } }; + struct nlist sym[] = { { .n_name = "_ngsocklist" }, + { .n_name = NULL } }; const char **pre; struct kld_file_stat ks; int fileid; diff --git a/usr.bin/netstat/netstat.h b/usr.bin/netstat/netstat.h index a50b473934..e019d35027 100644 --- a/usr.bin/netstat/netstat.h +++ b/usr.bin/netstat/netstat.h @@ -63,39 +63,39 @@ extern int unit; /* unit number for above */ extern int af; /* address family */ int kread (u_long addr, char *buf, int size); -char *plural (int); -char *plurales (int); - -void protopr (u_long, char *, int); -void tcp_stats (u_long, char *, int); -void udp_stats (u_long, char *, int); -void ip_stats (u_long, char *, int); -void icmp_stats (u_long, char *, int); -void igmp_stats (u_long, char *, int); -void pim_stats (u_long, char *, int); +const char *plural (int); +const char *plurales (int); + +void protopr (u_long, const char *, int); +void tcp_stats (u_long, const char *, int); +void udp_stats (u_long, const char *, int); +void ip_stats (u_long, const char *, int); +void icmp_stats (u_long, const char *, int); +void igmp_stats (u_long, const char *, int); +void pim_stats (u_long, const char *, int); void carp_stats (u_long, const char *, int); #ifdef IPSEC -void ipsec_stats (u_long, char *, int); +void ipsec_stats (u_long, const char *, int); #endif #ifdef INET6 -void ip6_stats (u_long, char *, int); +void ip6_stats (u_long, const char *, int); void ip6_ifstats (char *); -void icmp6_stats (u_long, char *, int); +void icmp6_stats (u_long, const char *, int); void icmp6_ifstats (char *); -void pim6_stats (u_long, char *, int); -void rip6_stats (u_long, char *, int); +void pim6_stats (u_long, const char *, int); +void rip6_stats (u_long, const char *, int); void mroute6pr (u_long, u_long); void mrt6_stats (u_long); struct sockaddr_in6; struct in6_addr; char *routename6 (struct sockaddr_in6 *); -char *netname6 (struct sockaddr_in6 *, struct in6_addr *); +const char *netname6 (struct sockaddr_in6 *, struct in6_addr *); #endif /*INET6*/ #ifdef IPSEC -void pfkey_stats (u_long, char *, int); +void pfkey_stats (u_long, const char *, int); #endif void mbpr (u_long, u_long, u_long, u_long); @@ -121,9 +121,9 @@ char *ipx_print (struct sockaddr *); char *ns_print (struct sockaddr *); void routepr (u_long); -void ipxprotopr (u_long, char *, int); -void spx_stats (u_long, char *, int); -void ipx_stats (u_long, char *, int); +void ipxprotopr (u_long, const char *, int); +void spx_stats (u_long, const char *, int); +void ipx_stats (u_long, const char *, int); void ipxerr_stats (u_long, char *, int); void nsprotopr (u_long, char *, int); @@ -131,10 +131,10 @@ void spp_stats (u_long, char *, int); void idp_stats (u_long, char *, int); void nserr_stats (u_long, char *, int); -void atalkprotopr (u_long, char *, int); -void ddp_stats (u_long, char *, int); +void atalkprotopr (u_long, const char *, int); +void ddp_stats (u_long, const char *, int); -void netgraphprotopr (u_long, char *, int); +void netgraphprotopr (u_long, const char *, int); void unixpr (void); diff --git a/usr.bin/netstat/route.c b/usr.bin/netstat/route.c index 03647ee789..0536935204 100644 --- a/usr.bin/netstat/route.c +++ b/usr.bin/netstat/route.c @@ -106,7 +106,7 @@ struct bits { { RTF_BLACKHOLE,'B' }, { RTF_BROADCAST,'b' }, { RTF_MPLSOPS, 'm' }, - { 0 } + { 0, 0 } }; typedef union { @@ -136,7 +136,7 @@ static void np_rtentry (struct rt_msghdr *); static void p_sockaddr (struct sockaddr *, struct sockaddr *, int, int); static const char *fmt_sockaddr (struct sockaddr *sa, struct sockaddr *mask, int flags); -static void p_flags (int, char *); +static void p_flags (int, const char *); static const char *fmt_flags(int f); static void p_rtentry (struct rtentry *); static u_long forgemask (u_long); @@ -192,11 +192,11 @@ routepr(u_long rtree) * Print address family header before a section of the routing table. */ void -pr_family(int af) +pr_family(int af1) { - char *afname; + const char *afname; - switch (af) { + switch (af1) { case AF_INET: afname = "Internet"; break; @@ -235,7 +235,7 @@ pr_family(int af) if (afname) printf("\n%s:\n", afname); else - printf("\nProtocol Family %d:\n", af); + printf("\nProtocol Family %d:\n", af1); } /* column widths; each followed by one space */ @@ -306,7 +306,7 @@ size_cols_rtentry(struct rtentry *rt) const char *bp; struct sockaddr *sa; sa_u addr, mask; - int len, i; + int len; /* * Don't print protocol-cloned routes unless -a. @@ -374,12 +374,12 @@ size_cols_rtentry(struct rtentry *rt) * Print header for routing table columns. */ void -pr_rthdr(int af) +pr_rthdr(int af1) { if (Aflag) printf("%-8.8s ","Address"); - if (af == AF_INET || Wflag) { + if (af1 == AF_INET || Wflag) { if (Wflag) { printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*.*s %*s %-*s\n", wid_dst, wid_dst, "Destination", @@ -542,7 +542,7 @@ np_rtentry(struct rt_msghdr *rtm) static int masks_done, banner_printed; #endif static int old_af; - int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST; + int af1 = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST; #ifdef notdef /* for the moment, netmasks are skipped over */ @@ -553,14 +553,14 @@ np_rtentry(struct rt_msghdr *rtm) if (masks_done == 0) { if (rtm->rtm_addrs != RTA_DST ) { masks_done = 1; - af = sa->sa_family; + af1 = sa->sa_family; } } else #endif - af = sa->sa_family; - if (af != old_af) { - pr_family(af); - old_af = af; + af1 = sa->sa_family; + if (af1 != old_af) { + pr_family(af1); + old_af = af1; } if (rtm->rtm_addrs == RTA_DST) p_sockaddr(sa, NULL, 0, 36); @@ -594,8 +594,7 @@ static const char * fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags) { static char workbuf[128]; - char *cplim; - char *cp = workbuf; + const char *cp = workbuf; switch(sa->sa_family) { case AF_INET: @@ -711,14 +710,16 @@ fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags) default: { u_char *s = (u_char *)sa->sa_data, *slim; + char *cq, *cqlim; + cq = workbuf; slim = sa->sa_len + (u_char *) sa; - cplim = cp + sizeof(workbuf) - 6; - cp += sprintf(cp, "(%d)", sa->sa_family); - while (s < slim && cp < cplim) { - cp += sprintf(cp, " %02x", *s++); + cqlim = cq + sizeof(workbuf) - 6; + cq += sprintf(cq, "(%d)", sa->sa_family); + while (s < slim && cq < cqlim) { + cq += sprintf(cq, " %02x", *s++); if (s < slim) - cp += sprintf(cp, "%02x", *s++); + cq += sprintf(cq, "%02x", *s++); } cp = workbuf; } @@ -728,7 +729,7 @@ fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags) } static void -p_flags(int f, char *format) +p_flags(int f, const char *format) { printf(format, fmt_flags(f)); } @@ -937,7 +938,7 @@ netname(u_long in, u_long mask) } #ifdef INET6 -char * +const char * netname6(struct sockaddr_in6 *sa6, struct in6_addr *mask) { static char line[MAXHOSTNAMELEN]; @@ -1005,8 +1006,10 @@ routename6(struct sockaddr_in6 *sa6) static char line[MAXHOSTNAMELEN]; int flag = NI_WITHSCOPEID; /* use local variable for safety */ - struct sockaddr_in6 sa6_local = {AF_INET6, sizeof(sa6_local),}; + struct sockaddr_in6 sa6_local; + sa6_local.sin6_family = AF_INET6; + sa6_local.sin6_len = sizeof(sa6_local); sa6_local.sin6_addr = sa6->sin6_addr; sa6_local.sin6_scope_id = sa6->sin6_scope_id; @@ -1052,7 +1055,7 @@ ipx_print(struct sockaddr *sa) { u_short port; struct servent *sp = 0; - char *net = "", *host = ""; + const char *net = "", *host = ""; char *p; u_char *q; struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr; @@ -1227,7 +1230,7 @@ upHex(char *p0) static const char * labelops(struct rtentry *rt) { - char *lops[] = { "push", "pop", "swap", "pop all" }; + const char *lops[] = { "push", "pop", "swap", "pop all" }; static char buffer[100]; char *cp = buffer; struct sockaddr_mpls *smpls; diff --git a/usr.bin/objformat/objformat.1 b/usr.bin/objformat/objformat.1 index bcf037397d..6c557d48e5 100644 --- a/usr.bin/objformat/objformat.1 +++ b/usr.bin/objformat/objformat.1 @@ -26,7 +26,7 @@ .\" $FreeBSD: src/usr.bin/objformat/objformat.1,v 1.3.2.4 2002/06/21 15:28:32 charnier Exp $ .\" $DragonFly: src/usr.bin/objformat/objformat.1,v 1.3 2006/02/17 19:39:10 swildner Exp $ .\" -.Dd October 25, 1998 +.Dd May 23, 2009 .Os .Dt OBJFORMAT 1 .Sh NAME @@ -38,38 +38,62 @@ .Sh DESCRIPTION If run as .Nm -the default object file format is reported. The two different object file -formats are -.Ar aout -and +the default object file format is reported. +The only supported object file format is .Ar elf . .Pp -If invoked by any other name, +If invoked by any other name, the path of the +.Nm prog +that will be executed is determined as follows: +.Pp +If .Nm prog -is expanded to -.Pa /usr/libexec//prog +is a binutil (such as +.Xr as 1 +and +.Xr ld 1 ) , +it is expanded to +.Pa /usr/libexec//elf/ Ns Nm prog and executed. +.Dq +defaults to the current binutils version used by +.Dx +and can be overridden using the +.Ev BINUTILSVER +environment variable. +.Pp +If +.Nm prog +is a compiler (such as +.Xr gcc 1 ) , +it is expanded to +.Pa /usr/libexec// Ns Nm prog +and executed. +.Dq +defaults to the current compiler used by +.Dx +and can be overridden using the +.Ev CCVER +environment variable. .Sh ENVIRONMENT .Bl -tag -width OBJFORMAT_PATH -.It Ev OBJFORMAT -If the environment variable -.Ev OBJFORMAT -is set, it overrides the default object file format. -.Ev OBJFORMAT takes precedence over -.Pa /etc/objformat . +.It Ev BINUTILSVER +The +.Dq +component to be used for binutils paths. +.It Ev CCVER +The +.Dq +component to be used for compiler paths. .It Ev OBJFORMAT_PATH -If the environment variable +If .Ev OBJFORMAT_PATH -is set, its value is used as the base path to -.Nm prog . -The default is -.Pa /usr/libexec . -.El -.Sh FILES -.Bl -tag -width /etc/objformat -compact -.It Pa /etc/objformat -If present, specifies the object file format to use. Syntax is -.Ql OBJFORMAT=xxx . +is set, its value is prepended to the path name determined by the +.Nm +rules. +If it is a sequence of colon separated paths, each of +.Ev OBJFORMAT_PATH Ap s +elements is prepended to the path name until execution succeeds. .El .Sh DIAGNOSTICS The @@ -81,7 +105,6 @@ could not be executed. .Sh SEE ALSO .Xr file 1 , .Xr getobjformat 3 -.\" .Sh STANDARDS .Sh HISTORY The .Nm @@ -95,4 +118,3 @@ utility was written by .An Peter Wemm Aq peter@netplex.com.au . This manual page was written by .An David O'Brien Aq obrien@NUXI.com . -.\" .Sh BUGS diff --git a/usr.bin/objformat/objformat.c b/usr.bin/objformat/objformat.c index d7c4093052..f2e4d0e317 100644 --- a/usr.bin/objformat/objformat.c +++ b/usr.bin/objformat/objformat.c @@ -103,7 +103,7 @@ main(int argc, char **argv) errx(1, "Invalid object format"); /* - * Get the last path elemenet of the program name being executed + * Get the last path element of the program name being executed */ cmd = strrchr(argv[0], '/'); if (cmd != NULL) @@ -198,4 +198,3 @@ main(int argc, char **argv) objformat_path, base_path, env_value, cmd); } } - diff --git a/usr.bin/pkg_radd/pkg_radd.sh b/usr.bin/pkg_radd/pkg_radd.sh index 2f3eabf56b..e92cb7e5d7 100644 --- a/usr.bin/pkg_radd/pkg_radd.sh +++ b/usr.bin/pkg_radd/pkg_radd.sh @@ -34,7 +34,7 @@ if [ -z "$BINPKG_SITES" ] then osver=`uname -r | awk -F - '{ print $1; }'` - BINPKG_SITES=http://pkgbox.dragonflybsd.org/DragonFly-$osver + BINPKG_SITES=http://avalon.dragonflybsd.org/packages/DragonFly-$osver/stable [ -f /etc/settings.conf ] && . /etc/settings.conf fi diff --git a/usr.bin/pkg_search/pkg_search.sh b/usr.bin/pkg_search/pkg_search.sh index e30b715fc7..305df9b6eb 100644 --- a/usr.bin/pkg_search/pkg_search.sh +++ b/usr.bin/pkg_search/pkg_search.sh @@ -38,8 +38,8 @@ VERSION=`uname -r | cut -d '.' -f 1,2` NO_INDEX=0 PORTSDIR=/usr/pkgsrc PKGSUM=${PORTSDIR}/pkg_summary -PKGSRCBOX1=http://pkgbox.dragonflybsd.org/packages/${UNAME}-${VERSION}/stable/ -PKGSRCBOX2=http://pkgbox.dragonflybsd.org/packages/DragonFly-2.2/stable/ +PKGSRCBOX1=http://avalon.dragonflybsd.org/packages/${UNAME}-${VERSION}/stable/ +PKGSRCBOX2=http://avalon.dragonflybsd.org/packages/DragonFly-2.2/stable/ INDEXFILE=INDEX # Download the pkg_summary file diff --git a/usr.bin/pkill/pkill.c b/usr.bin/pkill/pkill.c index d567202591..bf519a4a28 100644 --- a/usr.bin/pkill/pkill.c +++ b/usr.bin/pkill/pkill.c @@ -286,7 +286,7 @@ main(int argc, char **argv) if (rv == 0) { if (fullmatch) { if (regmatch.rm_so == 0 && - regmatch.rm_eo == strlen(mstr)) + regmatch.rm_eo == (regoff_t)strlen(mstr)) selected[i] = 1; } else selected[i] = 1; diff --git a/usr.bin/systat/Makefile b/usr.bin/systat/Makefile index 28c4631c6c..e8f4619a0d 100644 --- a/usr.bin/systat/Makefile +++ b/usr.bin/systat/Makefile @@ -5,7 +5,7 @@ PROG= systat CFLAGS+=-DINET6 -I${.CURDIR}/../../sys SRCS= cmds.c cmdtab.c convtbl.c devs.c fetch.c ifcmds.c ifstat.c iostat.c \ keyboard.c main.c mbufs.c netcmds.c netstat.c pigs.c sensors.c swap.c \ - icmp.c mode.c ip.c tcp.c vmstat.c ip6.c icmp6.c + icmp.c mode.c ip.c tcp.c vmstat.c ip6.c icmp6.c vmmeter.c DPADD= ${LIBCURSES} ${LIBTERMCAP} ${LIBM} ${LIBKVM} ${LIBDEVSTAT} ${LIBKINFO} LDADD= -lcurses -ltermcap -lm -lkvm -ldevstat -lkinfo BINGRP= kmem diff --git a/usr.bin/systat/cmdtab.c b/usr.bin/systat/cmdtab.c index e8838ab023..1d9eb9f345 100644 --- a/usr.bin/systat/cmdtab.c +++ b/usr.bin/systat/cmdtab.c @@ -55,6 +55,9 @@ struct cmdtab cmdtab[] = { { "vmstat", showkre, fetchkre, labelkre, initkre, openkre, closekre, cmdkre, NULL, 0 }, + { "pvmmeter", showvmm, fetchvmm, labelvmm, + initvmm, openvmm, closevmm, NULL, + NULL, 0 }, { "netstat", shownetstat, fetchnetstat, labelnetstat, initnetstat, opennetstat, closenetstat, cmdnetstat, NULL, CF_LOADAV }, diff --git a/usr.bin/systat/extern.h b/usr.bin/systat/extern.h index d02c10ef23..93530fa5d3 100644 --- a/usr.bin/systat/extern.h +++ b/usr.bin/systat/extern.h @@ -84,6 +84,7 @@ void closepigs(WINDOW *); void closesensors(WINDOW *); void closeswap(WINDOW *); void closetcp(WINDOW *); +void closevmm(WINDOW *); int cmdiostat(const char *, char *); int cmdifstat(const char *, char *); int cmdkre(const char *, char *); @@ -108,6 +109,7 @@ void fetchpigs(void); void fetchsensors(void); void fetchswap(void); void fetchtcp(void); +void fetchvmm(void); int ifcmd(const char *, const char *); int initicmp(void); int initicmp6(void); @@ -122,6 +124,7 @@ int initpigs(void); int initsensors(void); int initswap(void); int inittcp(void); +int initvmm(void); int keyboard(void); int kvm_ckread(void *, void *, int); void labelicmp(void); @@ -138,6 +141,7 @@ void labels(void); void labelsensors(void); void labelswap(void); void labeltcp(void); +void labelvmm(void); void load(void); int netcmd(const char *, char *); void nlisterr(struct nlist []); @@ -154,6 +158,7 @@ WINDOW *openpigs(void); WINDOW *opensensors(void); WINDOW *openswap(void); WINDOW *opentcp(void); +WINDOW *openvmm(void); int prefix(const char *, const char *); void reseticmp(void); void reseticmp6(void); @@ -173,5 +178,6 @@ void showpigs(void); void showsensors(void); void showswap(void); void showtcp(void); +void showvmm(void); void status(void); void suspend(int); diff --git a/usr.bin/systat/vmmeter.c b/usr.bin/systat/vmmeter.c new file mode 100644 index 0000000000..d798549e4f --- /dev/null +++ b/usr.bin/systat/vmmeter.c @@ -0,0 +1,192 @@ +#define _KERNEL_STRUCTURES +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "systat.h" +#include "extern.h" + +#define X_START 1 +#define CPU_START 1 +#define CPU_LABEL_W 7 + +#define DRAW_ROW(n, y, w, fmt, args...) \ +do { \ + mvprintw(y, n, fmt, w, args); \ + n += w; \ +} while (0) + +static int vmm_ncpus; +static int vmm_fetched; +static struct vmmeter *vmm_cur, *vmm_prev; +static struct kinfo_cputime *vmm_cptime_cur, *vmm_cptime_prev; + +static void +getvmm(void) +{ + size_t sz; + int i; + + for (i = 0; i < vmm_ncpus; ++i) { + struct vmmeter *vmm = &vmm_cur[i]; + char buf[64]; + + sz = sizeof(*vmm); + snprintf(buf, sizeof(buf), "vm.cpu%d.vmmeter", i); + if (sysctlbyname(buf, vmm, &sz, NULL, 0)) + err(1, "sysctlbyname(cpu%d)", i); + + vmm->v_intr -= (vmm->v_timer + vmm->v_ipi); + } + + sz = vmm_ncpus * sizeof(struct kinfo_cputime); + if (sysctlbyname("kern.cputime", vmm_cptime_cur, &sz, NULL, 0)) + err(1, "kern.cputime"); +} + +int +initvmm(void) +{ + return 1; +} + +void +showvmm(void) +{ + int i, n; + + if (!vmm_fetched) + return; + + for (i = 0; i < vmm_ncpus; ++i) { + struct kinfo_cputime d; + uint64_t cp_total = 0; + + n = X_START + CPU_LABEL_W; + +#define D(idx, field) \ + (vmm_cur[idx].field - vmm_prev[idx].field) / (u_int)naptime + + DRAW_ROW(n, CPU_START + i, 6, "%*u", D(i, v_timer)); + DRAW_ROW(n, CPU_START + i, 8, "%*u", D(i, v_ipi)); + DRAW_ROW(n, CPU_START + i, 8, "%*u", D(i, v_intr)); + +#undef D + +#define CPUD(dif, idx, field) \ +do { \ + dif.cp_##field = vmm_cptime_cur[idx].cp_##field - \ + vmm_cptime_prev[idx].cp_##field; \ + cp_total += dif.cp_##field; \ +} while (0) + +#define CPUV(dif, field) \ + (dif.cp_##field * 100.0) / cp_total + + CPUD(d, i, user); + CPUD(d, i, idle); + CPUD(d, i, intr); + CPUD(d, i, nice); + CPUD(d, i, sys); + + if (cp_total == 0) + cp_total = 1; + + DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, user)); + DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, nice)); + DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, sys)); + DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, intr)); + DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, idle)); + +#undef CPUV +#undef CPUD + } +} + +void +fetchvmm(void) +{ + vmm_fetched = 1; + + memcpy(vmm_prev, vmm_cur, sizeof(struct vmmeter) * vmm_ncpus); + memcpy(vmm_cptime_prev, vmm_cptime_cur, + sizeof(struct kinfo_cputime) * vmm_ncpus); + getvmm(); +} + +void +labelvmm(void) +{ + int i, n; + + clear(); + + n = X_START + CPU_LABEL_W; + + DRAW_ROW(n, 0, 6, "%*s", "timer"); + DRAW_ROW(n, 0, 8, "%*s", "ipi"); + DRAW_ROW(n, 0, 8, "%*s", "extint"); + DRAW_ROW(n, 0, 7, "%*s", "user%"); + DRAW_ROW(n, 0, 7, "%*s", "nice%"); + DRAW_ROW(n, 0, 7, "%*s", "sys%"); + DRAW_ROW(n, 0, 7, "%*s", "intr%"); + DRAW_ROW(n, 0, 7, "%*s", "idle%"); + + for (i = 0; i < vmm_ncpus; ++i) + mvprintw(CPU_START + i, X_START, "cpu%d", i); +} + +WINDOW * +openvmm(void) +{ + if (kinfo_get_cpus(&vmm_ncpus)) + err(1, "kinfo_get_cpus"); + + vmm_cur = calloc(vmm_ncpus, sizeof(*vmm_cur)); + if (vmm_cur == NULL) + err(1, "calloc vmm_cur"); + + vmm_prev = calloc(vmm_ncpus, sizeof(*vmm_prev)); + if (vmm_prev == NULL) + err(1, "calloc vmm_prev"); + + vmm_cptime_cur = calloc(vmm_ncpus, sizeof(*vmm_cptime_cur)); + if (vmm_cptime_cur == NULL) + err(1, "calloc vmm_cptime_cur"); + + vmm_cptime_prev = calloc(vmm_ncpus, sizeof(*vmm_cptime_prev)); + if (vmm_cptime_prev == NULL) + err(1, "calloc vmm_cptime_prev"); + + getvmm(); + + return (stdscr); +} + +void +closevmm(WINDOW *w) +{ + if (vmm_cur != NULL) + free(vmm_cur); + if (vmm_prev != NULL) + free(vmm_prev); + + if (vmm_cptime_cur != NULL) + free(vmm_cptime_cur); + if (vmm_cptime_prev != NULL) + free(vmm_cptime_prev); + + vmm_fetched = 0; + + if (w == NULL) + return; + wclear(w); + wrefresh(w); +} diff --git a/usr.bin/systat/vmstat.c b/usr.bin/systat/vmstat.c index 012ab13d56..50918b9797 100644 --- a/usr.bin/systat/vmstat.c +++ b/usr.bin/systat/vmstat.c @@ -173,7 +173,7 @@ static struct nlist namelist[] = { #define PROCSROW 7 /* uses 2 rows and 20 cols */ #define PROCSCOL 0 #define GENSTATROW 7 /* uses 2 rows and 30 cols */ -#define GENSTATCOL 20 +#define GENSTATCOL 16 #define VMSTATROW 6 /* uses 17 rows and 12 cols */ #define VMSTATCOL 48 #define GRAPHROW 10 /* uses 3 rows and 51 cols */ @@ -311,11 +311,11 @@ labelkre(void) mvprintw(VMSTATROW + 16, VMSTATCOL + 10, "numvnodes"); mvprintw(VMSTATROW + 17, VMSTATCOL + 10, "freevnodes"); - mvprintw(GENSTATROW, GENSTATCOL, " Csw Trp Sys Int Sof Flt"); + mvprintw(GENSTATROW, GENSTATCOL, " Csw Trp Sys Int Sof Flt"); mvprintw(GRAPHROW, GRAPHCOL, " . %%Sys . %%Intr . %%User . %%Nice . %%Idle"); - mvprintw(PROCSROW, PROCSCOL, "Proc:r p d s w"); + mvprintw(PROCSROW, PROCSCOL, " r p d s w"); mvprintw(GRAPHROW + 1, GRAPHCOL, "| | | | | | | | | | |"); @@ -491,11 +491,11 @@ showkre(void) putint(pgtokb(total.t_vm), MEMROW + 3, MEMCOL + 19, 9); putint(pgtokb(total.t_vmshr), MEMROW + 3, MEMCOL + 28, 9); putint(pgtokb(total.t_free), MEMROW + 2, MEMCOL + 37, 8); - putint(total.t_rq - 1, PROCSROW + 1, PROCSCOL + 3, 3); - putint(total.t_pw, PROCSROW + 1, PROCSCOL + 6, 3); - putint(total.t_dw, PROCSROW + 1, PROCSCOL + 9, 3); - putint(total.t_sl, PROCSROW + 1, PROCSCOL + 12, 3); - putint(total.t_sw, PROCSROW + 1, PROCSCOL + 15, 3); + putint(total.t_rq - 1, PROCSROW + 1, PROCSCOL + 0, 3); + putint(total.t_pw, PROCSROW + 1, PROCSCOL + 3, 3); + putint(total.t_dw, PROCSROW + 1, PROCSCOL + 6, 3); + putint(total.t_sl, PROCSROW + 1, PROCSCOL + 9, 3); + putint(total.t_sw, PROCSROW + 1, PROCSCOL + 12, 3); if (extended_vm_stats == 0) { PUTRATE(Vmm.v_zfod, VMSTATROW + 0, VMSTATCOL + 4, 5); } @@ -541,11 +541,11 @@ showkre(void) PUTRATE(Vmm.v_swappgsin, PAGEROW + 3, PAGECOL + 17, 5); PUTRATE(Vmm.v_swappgsout, PAGEROW + 3, PAGECOL + 22, 5); PUTRATE(Vmm.v_swtch, GENSTATROW + 1, GENSTATCOL, 5); - PUTRATE(Vmm.v_trap, GENSTATROW + 1, GENSTATCOL + 5, 5); - PUTRATE(Vmm.v_syscall, GENSTATROW + 1, GENSTATCOL + 10, 5); - PUTRATE(Vmm.v_intr, GENSTATROW + 1, GENSTATCOL + 15, 5); - PUTRATE(Vmm.v_soft, GENSTATROW + 1, GENSTATCOL + 20, 5); - PUTRATE(Vmm.v_vm_faults, GENSTATROW + 1, GENSTATCOL + 25, 5); + PUTRATE(Vmm.v_trap, GENSTATROW + 1, GENSTATCOL + 6, 5); + PUTRATE(Vmm.v_syscall, GENSTATROW + 1, GENSTATCOL + 12, 5); + PUTRATE(Vmm.v_intr, GENSTATROW + 1, GENSTATCOL + 18, 5); + PUTRATE(Vmm.v_soft, GENSTATROW + 1, GENSTATCOL + 23, 5); + PUTRATE(Vmm.v_vm_faults, GENSTATROW + 1, GENSTATCOL + 29, 5); mvprintw(DISKROW, DISKCOL + 5, " "); for (i = 0, lc = 0; i < num_devices && lc < MAXDRIVES; i++) if (dev_select[i].selected) { diff --git a/usr.bin/tip/Makefile.inc b/usr.bin/tip/Makefile.inc new file mode 100644 index 0000000000..2cbbd82cfc --- /dev/null +++ b/usr.bin/tip/Makefile.inc @@ -0,0 +1 @@ +WARNS?= 1 diff --git a/usr.bin/tip/libacu/Makefile b/usr.bin/tip/libacu/Makefile index 1cf4c7d7f1..446971fcc0 100644 --- a/usr.bin/tip/libacu/Makefile +++ b/usr.bin/tip/libacu/Makefile @@ -6,8 +6,6 @@ INTERNALLIB= YES CFLAGS+= -I${.CURDIR}/../tip SRCS= acucommon.c biz22.c courier.c df.c dn11.c hayes.c \ multitech.c t3000.c tod.c unidialer.c v3451.c v831.c ventel.c -WARNS?= 0 - $(OBJS): ${.CURDIR}/../tip/tipconf.h .include diff --git a/usr.bin/tip/libacu/v3451.c b/usr.bin/tip/libacu/v3451.c index 78bcc6a462..2983034bdb 100644 --- a/usr.bin/tip/libacu/v3451.c +++ b/usr.bin/tip/libacu/v3451.c @@ -43,7 +43,7 @@ static int expect(char *); static void vawrite(char *, int); static int notin(char *, char *); -static void alarmtr(void); +static void alarmtr(int); static int prefix(char *, char *); static jmp_buf Sjbuf; @@ -186,7 +186,7 @@ expect(cp) } static void -alarmtr() +alarmtr(int signo __unused) { longjmp(Sjbuf, 1); } diff --git a/usr.bin/tip/tip/Makefile b/usr.bin/tip/tip/Makefile index e925814b51..3f42271b75 100644 --- a/usr.bin/tip/tip/Makefile +++ b/usr.bin/tip/tip/Makefile @@ -23,7 +23,6 @@ MLINKS= tip.1 cu.1 MAN= tip.1 modems.5 SRCS= acu.c acutab.c cmds.c cmdtab.c cu.c hunt.c log.c partab.c \ remote.c tip.c tipout.c value.c vars.c -WARNS?= 1 BINDIR?= /usr/bin BINOWN= uucp diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c index 733d5c768c..2ece09449c 100644 --- a/usr.bin/top/machine.c +++ b/usr.bin/top/machine.c @@ -364,8 +364,8 @@ get_system_info(struct system_info *si) { struct vmmeter vmm; struct vmstats vms; - int vms_size = sizeof(vms); - int vmm_size = sizeof(vmm); + size_t vms_size = sizeof(vms); + size_t vmm_size = sizeof(vmm); static unsigned int swap_delay = 0; static int swapavail = 0; static int swapfree = 0; diff --git a/usr.bin/undo/undo.c b/usr.bin/undo/undo.c index 485560e00c..2005a3b2df 100644 --- a/usr.bin/undo/undo.c +++ b/usr.bin/undo/undo.c @@ -262,11 +262,16 @@ doiterate(const char *filename, const char *outFileName, */ collect_dir_history(filename, &error, &dir_tree); RB_FOREACH(tse1, undo_hist_entry_rb_tree, &dir_tree) { - asprintf(&path, "%s@@0x%016llx", filename, tse1->tse.tid); + asprintf(&path, "%s@@0x%016jx", filename, (uintmax_t)tse1->tse.tid); if ((fd = open(path, O_RDONLY)) > 0) { collect_history(fd, &error, &tse_tree); close(fd); } + free(path); + } + if ((fd = open(filename, O_RDONLY)) > 0) { + collect_history(fd, &error, &tse_tree); + close(fd); } if (cmd == CMD_DUMP) { if ((ts1.tid == 0 || @@ -360,8 +365,6 @@ doiterate(const char *filename, const char *outFileName, printf("%s: ITERATE ENTIRE HISTORY: %s\n", filename, strerror(error)); } - if (path) - free(path); clean_tree(&dir_tree); clean_tree(&tse_tree); } @@ -400,12 +403,12 @@ dogenerate(const char *filename, const char *outFileName, if (ts1.tid == 0) asprintf(&ipath1, "%s", filename); else - asprintf(&ipath1, "%s@@0x%016llx", filename, ts1.tid); + asprintf(&ipath1, "%s@@0x%016jx", filename, (uintmax_t)ts1.tid); if (ts2.tid == 0) asprintf(&ipath2, "%s", filename); else - asprintf(&ipath2, "%s@@0x%016llx", filename, ts2.tid); + asprintf(&ipath2, "%s@@0x%016jx", filename, (uintmax_t)ts2.tid); if (lstat(ipath1, &st) < 0 && lstat(ipath2, &st) < 0) { if (idx == 0 || VerboseOpt) { @@ -460,15 +463,18 @@ dogenerate(const char *filename, const char *outFileName, } else { if ((flags & UNDO_FLAG_MULT) && type == TYPE_FILE) { if (idx >= 0) { - printf("\n>>> %s %04d 0x%016llx %s\n\n", - filename, idx, ts1.tid, timestamp(&ts1)); + printf("\n>>> %s %04d 0x%016jx %s\n\n", + filename, idx, (uintmax_t)ts1.tid, + timestamp(&ts1)); } else { - printf("\n>>> %s ---- 0x%016llx %s\n\n", - filename, ts1.tid, timestamp(&ts1)); + printf("\n>>> %s ---- 0x%016jx %s\n\n", + filename, (uintmax_t)ts1.tid, + timestamp(&ts1)); } } else if (idx >= 0 && type == TYPE_FILE) { - printf("\n>>> %s %04d 0x%016llx %s\n\n", - filename, idx, ts1.tid, timestamp(&ts1)); + printf("\n>>> %s %04d 0x%016jx %s\n\n", + filename, idx, (uintmax_t)ts1.tid, + timestamp(&ts1)); } fp = stdout; } @@ -496,7 +502,7 @@ dogenerate(const char *filename, const char *outFileName, t = (time_t)ts1.time32; tp = localtime(&t); strftime(datestr, sizeof(datestr), "%d-%b-%Y %H:%M:%S", tp); - printf("\t0x%016llx %s", ts1.tid, datestr); + printf("\t0x%016jx %s", (uintmax_t)ts1.tid, datestr); if (flags & UNDO_FLAG_INOCHG) printf(" inode-change"); if (lstat(ipath1, &st) < 0) diff --git a/usr.bin/vmstat/vmstat.c b/usr.bin/vmstat/vmstat.c index eea2623287..41da4df802 100644 --- a/usr.bin/vmstat/vmstat.c +++ b/usr.bin/vmstat/vmstat.c @@ -390,9 +390,9 @@ dovmstat(u_int interval, int reps) struct vmtotal total; time_t uptime, halfuptime; struct devinfo *tmp_dinfo; - int vmm_size = sizeof(vmm); - int vms_size = sizeof(vms); - int vmt_size = sizeof(total); + size_t vmm_size = sizeof(vmm); + size_t vms_size = sizeof(vms); + size_t vmt_size = sizeof(total); uptime = getuptime(); halfuptime = uptime / 2; @@ -554,8 +554,8 @@ static void dosum(void) { struct nchstats *nch_tmp, nchstats; - int vms_size = sizeof(vms); - int vmm_size = sizeof(vmm); + size_t vms_size = sizeof(vms); + size_t vmm_size = sizeof(vmm); int cpucnt; u_long nchtotal; size_t nch_size = sizeof(struct nchstats) * SMP_MAXCPU; diff --git a/usr.bin/window/Makefile b/usr.bin/window/Makefile index af921c9764..9446be51fe 100644 --- a/usr.bin/window/Makefile +++ b/usr.bin/window/Makefile @@ -17,8 +17,7 @@ SRCS= char.c cmd.c cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c \ wwterminfo.c wwtty.c wwunframe.c wwupdate.c wwwrite.c xx.c xxflush.c \ compress.c -DPADD= ${LIBTERMCAP} -LDADD= -ltermcap -WARNS?= 0 +DPADD= ${LIBTERMCAP} ${LIBUTIL} +LDADD= -ltermcap -lutil .include diff --git a/usr.bin/window/README b/usr.bin/window/README index 42d45b368a..1044ef197a 100644 --- a/usr.bin/window/README +++ b/usr.bin/window/README @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -110,12 +106,12 @@ Emacs. The IO system is semi-synchronous. Terminal input is signal driven, and everything else is done synchronously with a single -select(). It is roughly event-driven, though not in a clean way. +poll(). It is roughly event-driven, though not in a clean way. Normally, in both conversation mode and command mode, window -sleeps in a select() in wwiomux() waiting for data from the +sleeps in a poll() in wwiomux() waiting for data from the pseudo-terminals. At the same time, terminal input causes SIGIO which -is caught by wwrint(). The select() returns when at least one of the +is caught by wwrint(). The poll() returns when at least one of the pseudo-terminals becomes ready for reading. Wwrint() is the interrupt handler for tty input. It reads input @@ -133,7 +129,7 @@ Wwrint() appends characters at the end and increments wwibq (*wwibq++ wwgetc() and wwpeekc() macros. As is the convention in C, wwibq and wwibe point to one position beyond the end. In addition, wwrint() will do a longjmp(wwjmpbuf) if wwsetjmp is true. This is -used by wwiomux() to interrupt the select() which would otherwise +used by wwiomux() to interrupt the poll() which would otherwise resume after the interrupt. (Actually, I hear this is not true, but the longjmp feature is used to avoid a race condition as well. Anyway, it means I didn't have to depend on a feature in a @@ -156,15 +152,15 @@ can check for this condition with wwinterrupt() or by arranging that a longjmp() be done. Wwiomux() copies pseudo-terminal output into their corresponding -windows. Without anything to do, it blocks in a select(), waiting for +windows. Without anything to do, it blocks in a poll(), waiting for read ready on pseudo-terminals. Reads are done into per-window buffers in the window structures. When there is at least one buffer non-empty, wwiomux() finds the top most of these windows and writes it using -wwwrite(). Then the process is repeated. A non-blocking select() is +wwwrite(). Then the process is repeated. A non-blocking poll() is done after a wwwrite() to pick up any output that may have come in during the write, which may take a long time. Specifically, we use this to stop output or flush buffer when a pseudo-terminal tells us to -(we use pty packet mode). The select() blocks only when all of the +(we use pty packet mode). The poll() blocks only when all of the windows' buffers are empty. A wwupdate() is done prior to this, which is the only time the screen is guaranteed to be completely up to date. Wwiomux() loops until wwinterrupt() becomes true. diff --git a/usr.bin/window/alias.h b/usr.bin/window/alias.h index 178d3b3ad4..0be2a3a0ce 100644 --- a/usr.bin/window/alias.h +++ b/usr.bin/window/alias.h @@ -1,3 +1,5 @@ +/* $NetBSD: alias.h,v 1.5 2003/08/07 11:17:21 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,10 +32,12 @@ * SUCH DAMAGE. * * @(#)alias.h 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/alias.h,v 1.1.1.1.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/alias.h,v 1.2 2003/06/17 04:29:33 dillon Exp $ */ +#ifndef EXTERN +#define EXTERN extern +#endif + #define alias var #define a_name r_name #define a_buf r_val.v_str @@ -51,4 +51,4 @@ #define alias_unset(n) var_unset1(&alias_head, n) #define alias_lookup(n) (*var_lookup1(&alias_head, n)) -struct var *alias_head; +EXTERN struct var *alias_head; diff --git a/usr.bin/window/char.c b/usr.bin/window/char.c index eb247d2f54..8727df150e 100644 --- a/usr.bin/window/char.c +++ b/usr.bin/window/char.c @@ -1,3 +1,5 @@ +/* $NetBSD: char.c,v 1.6 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,15 +30,94 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)char.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/char.c,v 1.2.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/char.c,v 1.2 2003/06/17 04:29:33 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)char.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: char.c,v 1.6 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + #include "char.h" -char *_unctrl[] = { +char _cmap[] = { + _C|_U, _C|_U, _C|_U, _C|_U, /* ^@ - ^C */ + _C|_U, _C|_U, _C|_U, _C|_U, /* ^D - ^G */ + _C, _C|_P, _C, _C|_U, /* ^H - ^K */ + _C|_U, _C, _C|_U, _C|_U, /* ^L - ^O */ + _C|_U, _C|_U, _C|_U, _C|_U, /* ^P - ^S */ + _C|_U, _C|_U, _C|_U, _C|_U, /* ^T - ^W */ + _C|_U, _C|_U, _C|_U, _C|_U, /* ^U - ^[ */ + _C|_U, _C|_U, _C|_U, _C|_U, /* ^\ - ^_ */ + + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _C|_U, + + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U +}; + +const char *_unctrl[] = { "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", "^H", "^I", "^J", "^K", "^L", "^M", "^N", "^O", "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W", diff --git a/usr.bin/window/char.h b/usr.bin/window/char.h index 86f3e91aa3..36645bdfcd 100644 --- a/usr.bin/window/char.h +++ b/usr.bin/window/char.h @@ -1,3 +1,5 @@ +/* $NetBSD: char.h,v 1.5 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,8 +32,6 @@ * SUCH DAMAGE. * * @(#)char.h 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/char.h,v 1.3.6.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/char.h,v 1.2 2003/06/17 04:29:33 dillon Exp $ */ /* @@ -51,13 +47,13 @@ * using unctrl() by wwwrite() if ww_unctrl is set. */ -#include -#include -#include - -extern char *_unctrl[]; +extern const char *_unctrl[]; +extern char _cmap[]; #define ctrl(c) (c & 0x1f) #define unctrl(c) (_unctrl[(unsigned char) (c)]) -#define isctrl(c) iscntrl((unsigned char)(c)) -#define isprt(c) (isprint((unsigned char)(c)) || (c) == '\t') -#define isunctrl(c) (strchr("\b\t\n\r", (c)) == NULL && isctrl(c)) +#define _C 0x01 +#define _P 0x02 +#define _U 0x04 +#define isctrl(c) (_cmap[(unsigned char) (c)] & _C) +#define isprt(c) (_cmap[(unsigned char) (c)] & _P) +#define isunctrl(c) (_cmap[(unsigned char) (c)] & _U) diff --git a/usr.bin/window/cmd.c b/usr.bin/window/cmd.c index 97fcce587d..deec51dd0c 100644 --- a/usr.bin/window/cmd.c +++ b/usr.bin/window/cmd.c @@ -1,3 +1,5 @@ +/* $NetBSD: cmd.c,v 1.8 2003/08/07 11:17:21 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,18 +30,27 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)cmd.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/cmd.c,v 1.2.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/cmd.c,v 1.3 2005/04/15 17:55:29 drhodus Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)cmd.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: cmd.c,v 1.8 2003/08/07 11:17:21 agc Exp $"); +#endif +#endif /* not lint */ + +#include #include "defs.h" #include "char.h" -docmd() +int checkproc(struct ww *); + +void +docmd(void) { - register c; + int c; struct ww *w; char out = 0; @@ -213,7 +220,7 @@ docmd() } struct ww * -getwin() +getwin(void) { int c; struct ww *w = 0; @@ -242,8 +249,8 @@ getwin() return w; } -checkproc(w) -struct ww *w; +int +checkproc(struct ww *w) { if (w->ww_state != WWS_HASPROC) { error("No process in window."); @@ -252,8 +259,8 @@ struct ww *w; return 0; } -setcmd(new) -char new; +void +setcmd(char new) { if (new && !incmd) { if (!terse) @@ -273,23 +280,24 @@ char new; incmd = new; } -setterse(new) -char new; +void +setterse(char new) { - if (incmd) + if (incmd) { if (new && !terse) { wwdelete(cmdwin); reframe(); } else if (!new && terse) wwadd(cmdwin, &wwhead); + } terse = new; } /* * Set the current window. */ -setselwin(w) -struct ww *w; +void +setselwin(struct ww *w) { if (selwin == w) return; diff --git a/usr.bin/window/cmd1.c b/usr.bin/window/cmd1.c index 345ee445a6..d31997e3e2 100644 --- a/usr.bin/window/cmd1.c +++ b/usr.bin/window/cmd1.c @@ -1,3 +1,5 @@ +/* $NetBSD: cmd1.c,v 1.7 2003/08/07 11:17:22 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,16 +30,22 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)cmd1.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/cmd1.c,v 1.2.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/cmd1.c,v 1.3 2005/04/15 17:55:29 drhodus Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)cmd1.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: cmd1.c,v 1.7 2003/08/07 11:17:22 agc Exp $"); +#endif +#endif /* not lint */ + #include "defs.h" #include "char.h" -c_window() +void +c_window(void) { int col, row, xcol, xrow; int id; @@ -105,13 +109,12 @@ c_window() wwputc('\n', cmdwin); wwcurtowin(cmdwin); (void) openwin(id, row, col, xrow-row+1, xcol-col+1, default_nline, - NULL, 1, 1, default_shellfile, default_shell); + (char *) 0, WWT_PTY, WWU_HASFRAME, default_shellfile, + default_shell); } -getpos(row, col, minrow, mincol, maxrow, maxcol) -int *row, *col; -int minrow, mincol; -int maxrow, maxcol; +int +getpos(int *row, int *col, int minrow, int mincol, int maxrow, int maxcol) { static int scount; int count; diff --git a/usr.bin/window/cmd2.c b/usr.bin/window/cmd2.c index 2283660e17..333c92c3b5 100644 --- a/usr.bin/window/cmd2.c +++ b/usr.bin/window/cmd2.c @@ -1,3 +1,5 @@ +/* $NetBSD: cmd2.c,v 1.7 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,15 +30,20 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)cmd2.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/cmd2.c,v 1.1.1.1.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/cmd2.c,v 1.3 2005/04/15 17:55:29 drhodus Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)cmd2.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: cmd2.c,v 1.7 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + #include "defs.h" -char *help_shortcmd[] = { +const char *help_shortcmd[] = { "# Select window # and return to conversation mode", "%# Select window # but stay in command mode", "escape Return to conversation mode without changing window", @@ -71,7 +74,8 @@ char *help_shortcmd[] = { ": Enter a long command", 0 }; -char *help_longcmd[] = { + +const char *help_longcmd[] = { ":alias name string ... Make `name' an alias for `string ...'", ":alias Show all aliases", ":close # ... Close windows", @@ -100,7 +104,10 @@ char *help_longcmd[] = { 0 }; -c_help() +int help_print(struct ww *, const char *, const char **); + +void +c_help(void) { struct ww *w; @@ -115,10 +122,8 @@ c_help() closeiwin(w); } -help_print(w, name, list) -struct ww *w; -char *name; -char **list; +int +help_print(struct ww *w, const char *name, const char **list) { wwprintf(w, "%s:\n\n", name); while (*list) @@ -136,7 +141,8 @@ char **list; return more(w, 1) == 2 ? -1 : 0; } -c_quit() +void +c_quit(void) { char oldterse = terse; diff --git a/usr.bin/window/cmd3.c b/usr.bin/window/cmd3.c index 62e48db561..cac5d7f647 100644 --- a/usr.bin/window/cmd3.c +++ b/usr.bin/window/cmd3.c @@ -1,3 +1,5 @@ +/* $NetBSD: cmd3.c,v 1.8 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,17 +30,22 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)cmd3.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/cmd3.c,v 1.1.1.1.14.2 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/cmd3.c,v 1.3 2005/04/15 17:55:29 drhodus Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)cmd3.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: cmd3.c,v 1.8 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + #include "defs.h" -#include "mystring.h" +#include "window_string.h" -setescape(esc) -char *esc; +void +setescape(const char *esc) { if (*esc == '^') { if (esc[1] != 0) @@ -53,9 +56,8 @@ char *esc; escapec = *esc; } -setlabel(w, label) -struct ww *w; -char *label; +int +setlabel(struct ww *w, const char *label) { if (w->ww_label != 0) str_free(w->ww_label); diff --git a/usr.bin/window/cmd4.c b/usr.bin/window/cmd4.c index dc2fe0f10f..270ab4b090 100644 --- a/usr.bin/window/cmd4.c +++ b/usr.bin/window/cmd4.c @@ -1,3 +1,5 @@ +/* $NetBSD: cmd4.c,v 1.6 2003/08/07 11:17:22 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,15 +30,21 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)cmd4.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/cmd4.c,v 1.1.1.1.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/cmd4.c,v 1.2 2003/06/17 04:29:33 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)cmd4.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: cmd4.c,v 1.6 2003/08/07 11:17:22 agc Exp $"); +#endif +#endif /* not lint */ + #include "defs.h" -c_colon() +void +c_colon(void) { char oldterse = terse; char buf[512]; @@ -51,6 +55,6 @@ c_colon() wwputc('\n', cmdwin); wwcurtowin(cmdwin); setterse(oldterse); - if (dolongcmd(buf, NULL, 0) < 0) + if (dolongcmd(buf, (struct value *)0, 0) < 0) error("Out of memory."); } diff --git a/usr.bin/window/cmd5.c b/usr.bin/window/cmd5.c index d17728b66a..1a64864627 100644 --- a/usr.bin/window/cmd5.c +++ b/usr.bin/window/cmd5.c @@ -1,3 +1,5 @@ +/* $NetBSD: cmd5.c,v 1.7 2003/08/07 11:17:23 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,20 +30,27 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)cmd5.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/cmd5.c,v 1.1.1.1.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/cmd5.c,v 1.3 2005/04/15 17:55:29 drhodus Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)cmd5.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: cmd5.c,v 1.7 2003/08/07 11:17:23 agc Exp $"); +#endif +#endif /* not lint */ + #include "defs.h" /* * Window movement. */ -c_move(w) -struct ww *w; +void getminmax(int, int, int, int, int *, int *, int *); + +void +c_move(struct ww *w) { int col, row; int mincol, minrow; @@ -88,8 +93,8 @@ struct ww *w; movewin(w, row, col); } -movewin(w, row, col) -struct ww *w; +void +movewin(struct ww *w, int row, int col) { struct ww *back = w->ww_back; @@ -104,9 +109,8 @@ struct ww *w; /* * Weird stufff, don't ask. */ -getminmax(x, n, a, b, curx, minx, maxx) -register x, n, a, b; -int *curx, *minx, *maxx; +void +getminmax(int x, int n, int a, int b, int *curx, int *minx, int *maxx) { if (x < 0) *curx = x + n - 1; diff --git a/usr.bin/window/cmd6.c b/usr.bin/window/cmd6.c index 0c52190070..e747723540 100644 --- a/usr.bin/window/cmd6.c +++ b/usr.bin/window/cmd6.c @@ -1,3 +1,5 @@ +/* $NetBSD: cmd6.c,v 1.8 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,26 +30,35 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)cmd6.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/cmd6.c,v 1.1.1.1.14.2 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/cmd6.c,v 1.3 2005/04/15 17:55:29 drhodus Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)cmd6.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: cmd6.c,v 1.8 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + #include "defs.h" -#include "mystring.h" +#include "window_string.h" #include "char.h" /* * Debugging commands. */ -c_debug() +void debug_str(void); + +void +c_debug(void) { struct ww *w; if (!terse) - wwputs("[m(smap) n(ns) o(os) s(string) v(nvis) w(win)]? ", cmdwin); + wwputs("[m(smap) n(ns) o(os) s(string) v(nvis) w(win)]? ", + cmdwin); wwcurtowin(cmdwin); while (wwpeekc() < 0) wwiomux(); @@ -83,11 +90,12 @@ c_debug() } } -#ifdef STR_DEBUG -debug_str() +void +debug_str(void) { +#ifdef STR_DEBUG struct ww *w; - struct mystring *s; + struct string *s; if ((w = openiwin(wwnrow - 3, "Allocated Strings")) == 0) { error("Can't open string window: %s.", wwerror()); @@ -96,15 +104,12 @@ debug_str() for (s = str_head.s_forw; s != &str_head; s = s->s_forw) { if (more(w, 0) == 2) goto out; - wwprintf(w, "(0x%x)\t\"%s\"\n", s->s_data, s->s_data); + wwprintf(w, "(%p)\t\"%s\"\n", s->s_data, s->s_data); } waitnl(w); out: closeiwin(w); -} #else -debug_str() -{ error("No string debugging."); -} #endif +} diff --git a/usr.bin/window/cmd7.c b/usr.bin/window/cmd7.c index 9f5bd8ec5f..f69593b593 100644 --- a/usr.bin/window/cmd7.c +++ b/usr.bin/window/cmd7.c @@ -1,3 +1,5 @@ +/* $NetBSD: cmd7.c,v 1.8 2006/05/02 22:30:25 christos Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,22 +30,32 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)cmd7.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/cmd7.c,v 1.2.6.2 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/cmd7.c,v 1.3 2005/04/15 17:55:29 drhodus Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)cmd7.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: cmd7.c,v 1.8 2006/05/02 22:30:25 christos Exp $"); +#endif +#endif /* not lint */ + #include +#include #include "defs.h" -#include "mystring.h" +#include "window_string.h" + +void unyank(void); +void yank_highlight(int, int, int, int); +void yank_highlight_line(int, int, int); +void yank_line(int, int, int); /* * Window size. */ - -c_size(w) -struct ww *w; +void +c_size(struct ww *w) { int col, row; @@ -96,7 +104,8 @@ struct yb { }; struct yb *yb_head, *yb_tail; -c_yank() +void +c_yank(void) { struct ww *w = selwin; int col1, row1; @@ -149,7 +158,7 @@ c_yank() } break; } - if (row2 < row1 || row2 == row1 && col2 < col1) { + if (row2 < row1 || (row2 == row1 && col2 < col1)) { r = row1; c = col1; row1 = row2; @@ -171,14 +180,15 @@ out: wwcursor(w, 1); } -yank_highlight(row1, col1, row2, col2) +void +yank_highlight(int row1, int col1, int row2, int col2) { struct ww *w = selwin; int r, c; if ((wwavailmodes & WWM_REV) == 0) return; - if (row2 < row1 || row2 == row1 && col2 < col1) { + if (row2 < row1 || (row2 == row1 && col2 < col1)) { r = row1; c = col1; row1 = row2; @@ -194,7 +204,8 @@ yank_highlight(row1, col1, row2, col2) yank_highlight_line(r, c, col2); } -yank_highlight_line(r, c, cend) +void +yank_highlight_line(int r, int c, int cend) { struct ww *w = selwin; char *win; @@ -218,7 +229,8 @@ yank_highlight_line(r, c, cend) } } -unyank() +void +unyank(void) { struct yb *yp, *yq; @@ -230,7 +242,8 @@ unyank() yb_head = yb_tail = 0; } -yank_line(r, c, cend) +void +yank_line(int r, int c, int cend) { struct yb *yp; int nl = 0; @@ -251,7 +264,10 @@ yank_line(r, c, cend) yp->length = n = cend - c + 1; if (nl) yp->length++; - yp->line = str_alloc(yp->length + 1); + if ((yp->line = str_alloc(yp->length + 1)) == NULL) { + free(yp); + return; + } for (bp += c, cp = yp->line; --n >= 0;) *cp++ = bp++->c_c; if (nl) @@ -263,7 +279,8 @@ yank_line(r, c, cend) yb_head = yb_tail = yp; } -c_put() +void +c_put(void) { struct yb *yp; diff --git a/usr.bin/window/compress.c b/usr.bin/window/compress.c index 3371f0b954..5e907fb9a5 100644 --- a/usr.bin/window/compress.c +++ b/usr.bin/window/compress.c @@ -1,3 +1,5 @@ +/* $NetBSD: compress.c,v 1.7 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,21 +30,25 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)compress.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/compress.c,v 1.2.12.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/compress.c,v 1.2 2003/06/17 04:29:33 dillon Exp $ */ - /* special */ -#include +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)compress.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: compress.c,v 1.7 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + #include +#include #include #include - -#include "ww.h" +#include "defs.h" #include "tt.h" + /* special */ int cc_trace = 0; FILE *cc_trace_fp; @@ -111,13 +113,13 @@ short cc_wlimits[TOKEN_MAX + 1]; int cc_score_adjustments[TOKEN_MAX + 1][8]; /* XXX, 8 > max of cc_thresholds */ #define score_adjust(score, p) \ do { \ - int length = (p)->length; \ - int ccount = (p)->ccount; \ - if (threshp((p)->code, ccount, length) || \ - wthreshp((p)->weight, length)) /* XXX */ \ - (score) -= length - tt.tt_put_token_cost; \ + int _length = (p)->length; \ + int _ccount = (p)->ccount; \ + if (threshp((p)->code, _ccount, _length) || \ + wthreshp((p)->weight, _length)) /* XXX */ \ + (score) -= _length - tt.tt_put_token_cost; \ else \ - (score) += cc_score_adjustments[length][ccount]; \ + (score) += cc_score_adjustments[_length][_ccount]; \ } while (0) int cc_initial_scores[TOKEN_MAX + 1][8]; /* XXX, 8 > max of cc_thresholds */ @@ -126,8 +128,8 @@ struct cc cc_q0a, cc_q0b, cc_q1a, cc_q1b; #define qinsert(p1, p2) \ do { \ - register struct cc *forw = (p1)->qforw; \ - register struct cc *back = (p1)->qback; \ + struct cc *forw = (p1)->qforw; \ + struct cc *back = (p1)->qback; \ back->qforw = forw; \ forw->qback = back; \ forw = (p2)->qforw; \ @@ -148,7 +150,7 @@ struct cc cc_q0a, cc_q0b, cc_q1a, cc_q1b; #define H (14) #define HSIZE (1 << H) -#define hash(h, c) ((((h) >> H - 8 | (h) << 8) ^ (c)) & HSIZE - 1) +#define hash(h, c) (((((h) >> (H - 8)) | (h) << 8) ^ (c)) & (HSIZE - 1)) char *cc_buffer; struct cc **cc_output; /* the output array */ @@ -165,10 +167,22 @@ long cc_time, cc_time0; char *cc_tt_ob, *cc_tt_obe; -ccinit() +int cc_compress(struct cc **, struct cc **, char); +void cc_compress_cleanup(struct cc **, int); +void cc_compress_phase(struct cc **, int, struct cc **, int); +void cc_compress_phase1(struct cc **, struct cc **, int, int); +void cc_output_phase(char *, struct cc **, int); +int cc_sweep(char *, int, struct cc **, int); +void cc_sweep0(char *, int, int); +int cc_sweep_phase(char *, int, struct cc **); +void cc_sweep_reverse(struct cc **, short *); +int cc_token_compare(const void *, const void *); + +int +ccinit(void) { - register i, j; - register struct cc *p; + int i, j; + struct cc *p; if (tt.tt_token_max > cc_token_max) tt.tt_token_max = cc_token_max; @@ -181,7 +195,7 @@ ccinit() if (tt.tt_ntoken > cc_ntoken / 2) /* not likely */ tt.tt_ntoken = cc_ntoken / 2; #define C(x) (sizeof (x) / sizeof *(x)) - for (i = 0; i < C(cc_thresholds); i++) { + for (i = 0; i < (int)C(cc_thresholds); i++) { int h = i - tt.tt_put_token_cost; if (h > 0) cc_thresholds[i] = @@ -189,9 +203,9 @@ ccinit() else cc_thresholds[i] = 0; } - for (i = 0; i < C(cc_score_adjustments); i++) { + for (i = 0; i < (int)C(cc_score_adjustments); i++) { int t = cc_thresholds[i]; - for (j = 0; j < C(*cc_score_adjustments); j++) { + for (j = 0; j < (int)C(*cc_score_adjustments); j++) { if (j >= t) cc_score_adjustments[i][j] = - (i - tt.tt_put_token_cost); @@ -288,10 +302,9 @@ nomem: return -1; } -ccstart() +void +ccstart(void) { - int ccflush(); - ttflush(); tt_obp = tt_ob = cc_buffer; tt_obe = tt_ob + cc_bufsize; @@ -303,18 +316,20 @@ ccstart() ccreset(); } -ccreset() +void +ccreset(void) { - register struct cc *p; + struct cc *p; - bzero((char *) cc_htab, HSIZE * sizeof *cc_htab); + memset((char *) cc_htab, 0, HSIZE * sizeof *cc_htab); for (p = cc_q0a.qforw; p != &cc_q0a; p = p->qforw) p->hback = 0; for (p = cc_q1a.qforw; p != &cc_q1a; p = p->qforw) p->hback = 0; } -ccend() +void +ccend(void) { ttflush(); @@ -327,7 +342,8 @@ ccend() } } -ccflush() +void +ccflush(void) { int bufsize = tt_obp - tt_ob; int n; @@ -359,12 +375,11 @@ out: tt.tt_flush = ccflush; } -cc_sweep_phase(buffer, bufsize, tokens) - char *buffer; - struct cc **tokens; +int +cc_sweep_phase(char *buffer, int bufsize, struct cc **tokens) { - register struct cc **pp = tokens; - register i, n; + struct cc **pp = tokens; + int i, n; #ifdef STATS int nn, ii; #endif @@ -416,14 +431,14 @@ cc_sweep_phase(buffer, bufsize, tokens) return pp - tokens; } -cc_sweep0(buffer, n, length) - char *buffer; +void +cc_sweep0(char *buffer, int n, int length) { - register char *p; - register short *hc; - register i; - register short c; - register short pc = tt.tt_padc; + char *p; + short *hc; + int i; + short c; + short pc = tt.tt_padc; /* n and length are at least 1 */ p = buffer++; @@ -446,14 +461,12 @@ cc_sweep0(buffer, n, length) } } -cc_sweep(buffer, bufsize, tokens, length) - char *buffer; - struct cc **tokens; - register length; +int +cc_sweep(char *buffer, int bufsize, struct cc **tokens, int length) { - register struct cc *p; - register char *cp; - register i; + struct cc *p; + char *cp; + int i; short *hc; short *places = cc_places[length]; struct cc **pp = tokens; @@ -462,21 +475,21 @@ cc_sweep(buffer, bufsize, tokens, length) short wthreshold = wthresh(length); short limit = wlimit(length); #endif - int time; + int time0; short pc = tt.tt_padc; i = length - 1; bufsize -= i; cp = buffer + i; hc = cc_hashcodes; - time = cc_time0; - for (i = 0; i < bufsize; i++, time++) { + time0 = cc_time0; + for (i = 0; i < bufsize; i++, time0++) { struct cc **h; { - register short *hc1 = hc; - register short c = *cp++; - register short hh; + short *hc1 = hc; + short c = *cp++; + short hh; if ((hh = *hc1) < 0 || c == pc) { *hc1++ = -1; hc = hc1; @@ -487,9 +500,9 @@ cc_sweep(buffer, bufsize, tokens, length) } for (p = *h; p != 0; p = p->hforw) if (p->length == (char) length) { - register char *p1 = p->string; - register char *p2 = cp - length; - register n = length; + char *p1 = p->string; + char *p2 = cp - length; + int n = length; do if (*p1++ != *p2++) goto fail; @@ -500,15 +513,15 @@ cc_sweep(buffer, bufsize, tokens, length) if (p == 0) { p = cc_q1a.qback; if (p == &cc_q1a || - p->time >= cc_time0 && p->length == (char) length) + (p->time >= cc_time0 && p->length == (char) length)) continue; if (p->hback != 0) if ((*p->hback = p->hforw) != 0) p->hforw->hback = p->hback; { - register char *p1 = p->string; - register char *p2 = cp - length; - register n = length; + char *p1 = p->string; + char *p2 = cp - length; + int n = length; do *p1++ = *p2++; while (--n); @@ -517,7 +530,7 @@ cc_sweep(buffer, bufsize, tokens, length) #ifndef cc_weight p->weight = cc_weight; #endif - p->time = time; + p->time = time0; p->bcount = 1; p->ccount = 0; p->flag = 0; @@ -533,12 +546,12 @@ cc_sweep(buffer, bufsize, tokens, length) #endif } else if (p->time < cc_time0) { #ifndef cc_weight - if ((p->weight += p->time - time) < 0) + if ((p->weight += p->time - time0) < 0) p->weight = cc_weight; else if ((p->weight += cc_weight) > limit) p->weight = limit; #endif - p->time = time; + p->time = time0; p->bcount = 1; p->ccount = 0; if (p->code >= 0) { @@ -561,15 +574,15 @@ cc_sweep(buffer, bufsize, tokens, length) #ifdef STATS ntoken_stat++; #endif - } else if (p->time + length > time) { + } else if (p->time + length > time0) { /* * overlapping token, don't count as two and - * don't update time, but do adjust weight to offset + * don't update time0, but do adjust weight to offset * the difference */ #ifndef cc_weight if (cc_weight != 0) { /* XXX */ - p->weight += time - p->time; + p->weight += time0 - p->time; if (!p->flag && p->weight >= wthreshold) { p->flag = 1; *pp++ = p; @@ -581,12 +594,12 @@ cc_sweep(buffer, bufsize, tokens, length) p->places = i; } else { #ifndef cc_weight - if ((p->weight += p->time - time) < 0) + if ((p->weight += p->time - time0) < 0) p->weight = cc_weight; else if ((p->weight += cc_weight) > limit) p->weight = limit; #endif - p->time = time; + p->time = time0; p->bcount++; if (!p->flag && /* code must be < 0 if flag false here */ @@ -608,7 +621,6 @@ cc_sweep(buffer, bufsize, tokens, length) if (cc_reverse) cc_sweep_reverse(tokens, places); if (cc_sort && i > 1) { - int cc_token_compare(); qsort((char *) tokens, i, sizeof *tokens, cc_token_compare); } @@ -622,33 +634,31 @@ cc_sweep(buffer, bufsize, tokens, length) return i; } -cc_sweep_reverse(pp, places) - register struct cc **pp; - register short *places; +void +cc_sweep_reverse(struct cc **pp, short int *places) { - register struct cc *p; - register short front, back, t; + struct cc *p; + short frnt, back, t; while ((p = *pp++) != 0) { back = -1; t = p->places; /* the list is never empty */ do { - front = places[t]; + frnt = places[t]; places[t] = back; back = t; - } while ((t = front) >= 0); + } while ((t = frnt) >= 0); p->places = back; } } -cc_compress_phase(output, bufsize, tokens, ntoken) - struct cc **output; - struct cc **tokens; +void +cc_compress_phase(struct cc **output, int bufsize, struct cc **tokens, int ntoken) { - register i; + int i; - bzero((char *) output, bufsize * sizeof *output); + memset((char *) output, 0, bufsize * sizeof *output); for (i = 0; i < cc_npass0; i++) cc_compress_phase1(output, tokens, ntoken, 0); for (i = 0; i < cc_npass1; i++) @@ -656,13 +666,12 @@ cc_compress_phase(output, bufsize, tokens, ntoken) cc_compress_cleanup(output, bufsize); } -cc_compress_phase1(output, tokens, ntoken, flag) - register struct cc **output; - struct cc **tokens; +void +cc_compress_phase1(struct cc **output, struct cc **tokens, int ntoken, int flag) { - register struct cc **pp; + struct cc **pp; #ifdef STATS - register int i = 0; + int i = 0; int nt = 0, cc = 0, nc = 0; #endif @@ -707,16 +716,16 @@ cc_compress_phase1(output, tokens, ntoken, flag) #endif } -cc_compress_cleanup(output, bufsize) - register struct cc **output; +void +cc_compress_cleanup(struct cc **output, int bufsize) { - register struct cc **end; + struct cc **end; /* the previous output phase may have been interrupted */ qinsertq(&cc_q0b, &cc_q0a); for (end = output + bufsize; output < end;) { - register struct cc *p; - register length; + struct cc *p; + int length; if ((p = *output) == 0) { output++; continue; @@ -742,13 +751,11 @@ cc_compress_cleanup(output, bufsize) } } -cc_compress(output, tokens, flag) - struct cc **output; - struct cc **tokens; - char flag; +int +cc_compress(struct cc **output, struct cc **tokens, char flag) { struct cc **pp = tokens; - register struct cc *p = *pp++; + struct cc *p = *pp++; int length = p->length; int threshold = thresh(length); #ifndef cc_weight @@ -760,7 +767,7 @@ cc_compress(output, tokens, flag) do { int score; - register struct cc_undo *undop; + struct cc_undo *undop; int ccount; #ifdef STATS int ncover; @@ -785,10 +792,10 @@ cc_compress(output, tokens, flag) ncover = 0; #endif for (i = p->places; i >= 0; i = places[i]) { - register struct cc **jp; - register struct cc *x; - register struct cc **ip = output + i; - register score0 = initial_score0; + struct cc **jp; + struct cc *x; + struct cc **ip = output + i; + int score0 = initial_score0; struct cc **iip = ip + length; struct cc_undo *undop1 = undop; @@ -831,7 +838,7 @@ cc_compress(output, tokens, flag) continue; undo: while (--undop >= undop1) - if (*undop->pos = x = undop->val) + if ((*undop->pos = x = undop->val)) x->ccount++; undop++; } @@ -843,10 +850,10 @@ cc_compress(output, tokens, flag) #endif p->ccount = ccount; } else { - register struct cc_undo *u = cc_undo; + struct cc_undo *u = cc_undo; while (--undop >= u) { - register struct cc *x; - if (*undop->pos = x = undop->val) + struct cc *x; + if ((*undop->pos = x = undop->val)) x->ccount++; } } @@ -854,13 +861,11 @@ cc_compress(output, tokens, flag) return pp - tokens; } -cc_output_phase(buffer, output, bufsize) - register char *buffer; - register struct cc **output; - register bufsize; +void +cc_output_phase(char *buffer, struct cc **output, int bufsize) { - register i; - register struct cc *p, *p1; + int i; + struct cc *p, *p1; for (i = 0; i < bufsize;) { if ((p = output[i]) == 0) { @@ -895,8 +900,10 @@ cc_output_phase(buffer, output, bufsize) wwntokc += bufsize; } -cc_token_compare(p1, p2) - struct cc **p1, **p2; +int +cc_token_compare(const void *p1, const void *p2) { - return (*p2)->bcount - (*p1)->bcount; + const struct cc * const * vp1 = p1; + const struct cc * const * vp2 = p2; + return (*vp2)->bcount - (*vp1)->bcount; } diff --git a/usr.bin/window/context.c b/usr.bin/window/context.c index 97ee409f00..6de15c0af9 100644 --- a/usr.bin/window/context.c +++ b/usr.bin/window/context.c @@ -1,3 +1,5 @@ +/* $NetBSD: context.c,v 1.7 2003/08/07 11:17:24 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,24 +30,34 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)context.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/context.c,v 1.1.1.1.14.2 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/context.c,v 1.4 2005/04/15 17:55:29 drhodus Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)context.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: context.c,v 1.7 2003/08/07 11:17:24 agc Exp $"); +#endif +#endif /* not lint */ + #include #include - -#include "value.h" -#include "mystring.h" +#include "defs.h" +#include "window_string.h" +#undef EXTERN +#define EXTERN #include "context.h" +#undef EXTERN /* * Context push/pop for nested command files. */ +int cx_alloc(void); +void cx_free(void); -cx_alloc() +int +cx_alloc(void) { struct context *xp; @@ -68,7 +76,8 @@ cx_alloc() return 0; } -cx_free() +void +cx_free(void) { struct context *xp; @@ -79,8 +88,8 @@ cx_free() cx.x_type = 0; } -cx_beginfile(filename) -char *filename; +int +cx_beginfile(char *filename) { if (cx_alloc() < 0) return -1; @@ -103,10 +112,8 @@ bad: return -1; } -cx_beginbuf(buf, arg, narg) -char *buf; -struct value *arg; -int narg; +int +cx_beginbuf(char *buf, struct value *arg, int narg) { if (cx_alloc() < 0) return -1; @@ -117,7 +124,8 @@ int narg; return 0; } -cx_end() +void +cx_end(void) { switch (cx.x_type) { case X_BUF: diff --git a/usr.bin/window/context.h b/usr.bin/window/context.h index 9e80328c45..bddde1c2d3 100644 --- a/usr.bin/window/context.h +++ b/usr.bin/window/context.h @@ -1,3 +1,5 @@ +/* $NetBSD: context.h,v 1.5 2003/08/07 11:17:25 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,12 +32,14 @@ * SUCH DAMAGE. * * @(#)context.h 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/context.h,v 1.1.1.1.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/context.h,v 1.2 2003/06/17 04:29:33 dillon Exp $ */ #include +#ifndef EXTERN +#define EXTERN extern +#endif + struct context { struct context *x_link; /* nested contexts */ char x_type; /* tag for union */ @@ -82,4 +82,4 @@ struct context { #define X_FILE 1 /* input is a file */ #define X_BUF 2 /* input is a buffer */ -struct context cx; /* the current context */ +EXTERN struct context cx; /* the current context */ diff --git a/usr.bin/window/defs.h b/usr.bin/window/defs.h index c28c1a994b..6ecdd5e9de 100644 --- a/usr.bin/window/defs.h +++ b/usr.bin/window/defs.h @@ -1,3 +1,5 @@ +/* $NetBSD: defs.h,v 1.8 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,40 +32,97 @@ * SUCH DAMAGE. * * @(#)defs.h 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/defs.h,v 1.1.1.1.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/defs.h,v 1.2 2003/06/17 04:29:33 dillon Exp $ */ -#include "ww.h" #include +#include "value.h" +#include "ww.h" + +#ifndef EXTERN +#define EXTERN extern +#endif #define NWINDOW 9 -struct timeval starttime; +EXTERN struct timeval starttime; -struct ww *window[NWINDOW]; /* the windows */ -struct ww *selwin; /* the selected window */ -struct ww *lastselwin; /* the last selected window */ -struct ww *cmdwin; /* the command window */ -struct ww *framewin; /* the window for framing */ -struct ww *boxwin; /* the window for the box */ -struct ww *fgwin; /* the last foreground window */ +EXTERN struct ww *window[NWINDOW]; /* the windows */ +EXTERN struct ww *selwin; /* the selected window */ +EXTERN struct ww *lastselwin; /* the last selected window */ +EXTERN struct ww *cmdwin; /* the command window */ +EXTERN struct ww *framewin; /* the window for framing */ +EXTERN struct ww *boxwin; /* the window for the box */ +EXTERN struct ww *fgwin; /* the last foreground window */ #define isfg(w) ((w)->ww_order <= fgwin->ww_order) -char *default_shell[128]; /* default shell argv */ -char *default_shellfile; /* default shell program */ -int default_nline; /* default buffer size for new windows */ -int default_smooth; /* default "smooth" parameter */ -char escapec; /* the escape character */ +EXTERN char *default_shell[128]; /* default shell argv */ +EXTERN char *default_shellfile; /* default shell program */ +EXTERN int default_nline; /* default buffer size for new windows */ +EXTERN int default_smooth; /* default "smooth" parameter */ +EXTERN char escapec; /* the escape character */ - /* flags */ -char quit; /* quit command issued */ -char terse; /* terse mode */ -char debug; /* debug mode */ -char incmd; /* in command mode */ +/* flags */ +EXTERN char quit; /* quit command issued */ +EXTERN char terse; /* terse mode */ +EXTERN char debug; /* debug mode */ +EXTERN char incmd; /* in command mode */ -struct ww *getwin(); -struct ww *openwin(); -struct ww *vtowin(); -struct ww *openiwin(); +void addwin(struct ww *, char); +int ccinit(void); +void ccend(void); +void ccflush(void); +void ccreset(void); +void ccstart(void); +void c_colon(void); +void c_debug(void); +void c_help(void); +void c_move(struct ww *); +void c_put(void); +void c_quit(void); +void c_size(struct ww *); +void c_window(void); +void c_yank(void); +void closeiwin(struct ww *); +void closewin(struct ww *); +void closewin1(struct ww *); +int cx_beginbuf(char *, struct value *, int); +int cx_beginfile(char *); +void cx_end(void); +void deletewin(struct ww *); +void docmd(void); +int doconfig(void); +void dodefault(void); +int dolongcmd(char *, struct value *, int); +int dosource(char *); +void error(const char *, ...) + __attribute__((__format__(__printf__, 1, 2))); +void err_end(void); +int findid(void); +struct ww *findselwin(void); +void front(struct ww *, char); +int getpos(int *, int *, int, int, int, int); +struct ww *getwin(void); +void labelwin(struct ww *); +void mloop(void); +int more(struct ww *, char); +void movewin(struct ww *, int, int); +struct ww *openwin(int, int, int, int, int, int, char *, int, int, + char *, char **); +struct ww *openiwin(int, const char *); +void p_memerror(void); +void p_start(void); +void reframe(void); +void setcmd(char); +void setescape(const char *); +int setlabel(struct ww *, const char *); +void setselwin(struct ww *); +void setterse(char); +void setvars(void); +void sizewin(struct ww *, int, int); +void startwin(struct ww *); +void stopwin(struct ww *); +int s_gettok(void); +void verror(const char *, va_list); +void waitnl(struct ww *); +int waitnl1(struct ww *, const char *); diff --git a/usr.bin/window/error.c b/usr.bin/window/error.c index a5bfec4364..40d84980f7 100644 --- a/usr.bin/window/error.c +++ b/usr.bin/window/error.c @@ -1,3 +1,5 @@ +/* $NetBSD: error.c,v 1.6 2003/08/07 11:17:25 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,22 +30,35 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)error.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/error.c,v 1.1.1.1.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/error.c,v 1.3 2005/04/15 17:55:29 drhodus Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)error.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: error.c,v 1.6 2003/08/07 11:17:25 agc Exp $"); +#endif +#endif /* not lint */ + #include "defs.h" -#include "value.h" #include "context.h" #include "char.h" #define ERRLINES 10 /* number of lines for errwin */ -/*VARARGS1*/ -error(fmt, a, b, c, d, e, f, g, h) -char *fmt; +void +error(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + verror(fmt, ap); + va_end(ap); +} + +void +verror(const char *fmt, va_list ap) { struct context *x; struct ww *w; @@ -58,7 +69,7 @@ char *fmt; if (terse) wwbell(); else { - wwprintf(cmdwin, fmt, a, b, c, d, e, f, g, h); + wwvprintf(cmdwin, fmt, ap); wwputs(" ", cmdwin); } return; @@ -68,7 +79,8 @@ char *fmt; if ((w = x->x_errwin) == 0) { char buf[512]; - (void) sprintf(buf, "Errors from %s", x->x_filename); + (void) snprintf(buf, sizeof(buf), "Errors from %s", + x->x_filename); if ((w = x->x_errwin = openiwin(ERRLINES, buf)) == 0) { wwputs("Can't open error window. ", cmdwin); x->x_noerr = 1; @@ -80,11 +92,12 @@ char *fmt; return; } wwprintf(w, "line %d: ", x->x_lineno); - wwprintf(w, fmt, a, b, c, d, e, f, g, h); + wwvprintf(w, fmt, ap); wwputc('\n', w); } -err_end() +void +err_end(void) { if (cx.x_type == X_FILE && cx.x_errwin != 0) { if (!cx.x_noerr) diff --git a/usr.bin/window/lcmd.c b/usr.bin/window/lcmd.c index 05ac81e1c6..8fecadfff3 100644 --- a/usr.bin/window/lcmd.c +++ b/usr.bin/window/lcmd.c @@ -1,3 +1,5 @@ +/* $NetBSD: lcmd.c,v 1.9 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,39 +30,20 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)lcmd.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/lcmd.c,v 1.1.1.1.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/lcmd.c,v 1.3 2005/04/15 17:55:29 drhodus Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)lcmd.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: lcmd.c,v 1.9 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + #include "defs.h" -#include "value.h" #include "lcmd.h" - -int l_alias(); -int l_close(); -int l_cursormodes(); -int l_debug(); -int l_def_nline(); -int l_def_shell(); -int l_def_smooth(); -int l_echo(); -int l_escape(); -int l_foreground(); -int l_iostat(); -int l_label(); -int l_list(); -int l_select(); -int l_smooth(); -int l_source(); -int l_terse(); -int l_time(); -int l_unalias(); -int l_unset(); -int l_variable(); -int l_window(); -int l_write(); +#include "window_string.h" extern struct lcmd_arg arg_alias[]; extern struct lcmd_arg arg_cursormodes[]; @@ -86,40 +65,39 @@ extern struct lcmd_arg arg_unalias[]; extern struct lcmd_arg arg_unset[]; extern struct lcmd_arg arg_window[]; extern struct lcmd_arg arg_write[]; -struct lcmd_arg arg_null[1] = { { 0 } }; +struct lcmd_arg arg_null[1] = { { NULL, 0, 0 } }; struct lcmd_tab lcmd_tab[] = { - "alias", 1, l_alias, arg_alias, - "close", 2, l_close, arg_close, - "cursormodes", 2, l_cursormodes, arg_cursormodes, - "debug", 1, l_debug, arg_debug, - "default_nlines", 9, l_def_nline, arg_def_nline, - "default_shell", 10, l_def_shell, arg_def_shell, - "default_smooth", 10, l_def_smooth, arg_def_smooth, - "echo", 2, l_echo, arg_echo, - "escape", 2, l_escape, arg_escape, - "foreground", 1, l_foreground, arg_foreground, - "iostat", 1, l_iostat, arg_null, - "label", 2, l_label, arg_label, - "list", 2, l_list, arg_null, - "nlines", 1, l_def_nline, arg_def_nline, - "select", 2, l_select, arg_select, - "shell", 2, l_def_shell, arg_def_shell, - "smooth", 2, l_smooth, arg_smooth, - "source", 2, l_source, arg_source, - "terse", 2, l_terse, arg_terse, - "time", 2, l_time, arg_time, - "unalias", 3, l_unalias, arg_unalias, - "unset", 3, l_unset, arg_unset, - "variable", 1, l_variable, arg_null, - "window", 2, l_window, arg_window, - "write", 2, l_write, arg_write, - 0 + { "alias", 1, l_alias, arg_alias }, + { "close", 2, l_close, arg_close }, + { "cursormodes", 2, l_cursormodes, arg_cursormodes }, + { "debug", 1, l_debug, arg_debug }, + { "default_nlines", 9, l_def_nline, arg_def_nline }, + { "default_shell", 10, l_def_shell, arg_def_shell }, + { "default_smooth", 10, l_def_smooth, arg_def_smooth }, + { "echo", 2, l_echo, arg_echo }, + { "escape", 2, l_escape, arg_escape }, + { "foreground", 1, l_foreground, arg_foreground }, + { "iostat", 1, l_iostat, arg_null }, + { "label", 2, l_label, arg_label }, + { "list", 2, l_list, arg_null }, + { "nlines", 1, l_def_nline, arg_def_nline }, + { "select", 2, l_select, arg_select }, + { "shell", 2, l_def_shell, arg_def_shell }, + { "smooth", 2, l_smooth, arg_smooth }, + { "source", 2, l_source, arg_source }, + { "terse", 2, l_terse, arg_terse }, + { "time", 2, l_time, arg_time }, + { "unalias", 3, l_unalias, arg_unalias }, + { "unset", 3, l_unset, arg_unset }, + { "variable", 1, l_variable, arg_null }, + { "window", 2, l_window, arg_window }, + { "write", 2, l_write, arg_write }, + { 0, 0, 0, 0 } }; struct lcmd_tab * -lcmd_lookup(name) -char *name; +lcmd_lookup(const char *name) { struct lcmd_tab *p; @@ -129,8 +107,8 @@ char *name; return 0; } -dosource(filename) -char *filename; +int +dosource(char *filename) { if (cx_beginfile(filename) < 0) return -1; @@ -140,10 +118,8 @@ char *filename; return 0; } -dolongcmd(buffer, arg, narg) -char *buffer; -struct value *arg; -int narg; +int +dolongcmd(char *buffer, struct value *arg, int narg) { if (cx_beginbuf(buffer, arg, narg) < 0) return -1; diff --git a/usr.bin/window/lcmd.h b/usr.bin/window/lcmd.h index a8f901ed89..5036fa6a08 100644 --- a/usr.bin/window/lcmd.h +++ b/usr.bin/window/lcmd.h @@ -1,3 +1,5 @@ +/* $NetBSD: lcmd.h,v 1.7 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,21 +32,19 @@ * SUCH DAMAGE. * * @(#)lcmd.h 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/lcmd.h,v 1.1.1.1.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/lcmd.h,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ #define LCMD_NARG 20 /* maximum number of arguments */ struct lcmd_tab { - char *lc_name; + const char *lc_name; int lc_minlen; - int (*lc_func)(); + void (*lc_func)(struct value *, struct value *); struct lcmd_arg *lc_arg; }; struct lcmd_arg { - char *arg_name; + const char *arg_name; int arg_minlen; int arg_flags; }; @@ -60,4 +56,28 @@ struct lcmd_arg { #define ARG_STR 0x02 /* must be a string */ #define ARG_LIST 0x10 /* this arg can be a list */ -struct lcmd_tab *lcmd_lookup(); +struct lcmd_tab *lcmd_lookup(const char *); +void l_alias(struct value *, struct value *); +void l_close(struct value *, struct value *); +void l_cursormodes(struct value *, struct value *); +void l_debug(struct value *, struct value *); +void l_def_nline(struct value *, struct value *); +void l_def_shell(struct value *, struct value *); +void l_def_smooth(struct value *, struct value *); +void l_echo(struct value *, struct value *); +void l_escape(struct value *, struct value *); +void l_foreground(struct value *, struct value *); +void l_iostat(struct value *, struct value *); +void l_label(struct value *, struct value *); +void l_list(struct value *, struct value *); +void l_select(struct value *, struct value *); +void l_smooth(struct value *, struct value *); +void l_source(struct value *, struct value *); +void l_terse(struct value *, struct value *); +void l_time(struct value *, struct value *); +void l_unalias(struct value *, struct value *); +void l_unset(struct value *, struct value *); +void l_variable(struct value *, struct value *); +void l_window(struct value *, struct value *); +void l_write(struct value *, struct value *); +struct ww *vtowin(struct value *, struct ww *); diff --git a/usr.bin/window/lcmd1.c b/usr.bin/window/lcmd1.c index e072777850..489e373c01 100644 --- a/usr.bin/window/lcmd1.c +++ b/usr.bin/window/lcmd1.c @@ -1,3 +1,5 @@ +/* $NetBSD: lcmd1.c,v 1.11 2006/12/18 20:04:55 christos Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,21 +30,26 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)lcmd1.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/lcmd1.c,v 1.2.6.2 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/lcmd1.c,v 1.4 2005/04/15 17:55:29 drhodus Exp $ */ -#include -#include /* System string definitions. */ - +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)lcmd1.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: lcmd1.c,v 1.11 2006/12/18 20:04:55 christos Exp $"); +#endif +#endif /* not lint */ + +#include +#include #include "defs.h" -#include "mystring.h" /* Local string definitions. */ -#include "value.h" +#include "window_string.h" #include "lcmd.h" #include "var.h" +char vtobool(struct value *, char, char); + struct lcmd_arg arg_window[] = { { "row", 1, ARG_NUM }, { "column", 1, ARG_NUM }, @@ -60,17 +63,16 @@ struct lcmd_arg arg_window[] = { { "keepopen", 1, ARG_ANY }, { "smooth", 1, ARG_ANY }, { "shell", 1, ARG_STR|ARG_LIST }, - 0 + { NULL, 0, 0 } }; -l_window(v, a) -struct value *v; -struct value *a; +void +l_window(struct value *v, struct value *a) { struct ww *w; int col, row, ncol, nrow, id, nline; char *label; - char haspty, hasframe, mapnl, keepopen, smooth; + int haspty, hasframe, mapnl, keepopen, smooth; char *shf, **sh; char *argv[sizeof default_shell / sizeof *default_shell]; char **pp; @@ -104,7 +106,7 @@ struct value *a; *pp = a->v_str; *pp = 0; shf = *(sh = argv); - if (*sh = strrchr(shf, '/')) + if ((*sh = strrchr(shf, '/'))) (*sh)++; else *sh = shf; @@ -112,23 +114,33 @@ struct value *a; sh = default_shell; shf = default_shellfile; } - if ((w = openwin(id, row, col, nrow, ncol, nline, label, haspty, - hasframe, shf, sh)) == 0) + if ((w = openwin(id, row, col, nrow, ncol, nline, label, + haspty ? WWT_PTY : WWT_SOCKET, hasframe ? WWU_HASFRAME : 0, shf, + sh)) == 0) return; - w->ww_mapnl = mapnl; - w->ww_keepopen = keepopen; - w->ww_noupdate = !smooth; + if (mapnl) + SET(w->ww_wflags, WWW_MAPNL); + else + CLR(w->ww_wflags, WWW_MAPNL); + if (keepopen) + SET(w->ww_uflags, WWU_KEEPOPEN); + else + CLR(w->ww_uflags, WWU_KEEPOPEN); + if (!smooth) + SET(w->ww_wflags, WWW_NOUPDATE); + else + CLR(w->ww_wflags, WWW_NOUPDATE); v->v_type = V_NUM; v->v_num = id + 1; } struct lcmd_arg arg_def_nline[] = { { "nlines", 1, ARG_NUM }, - 0 + { NULL, 0, 0 } }; -l_def_nline(v, a) -struct value *v, *a; +void +l_def_nline(struct value *v, struct value *a) { v->v_num = default_nline; v->v_type = V_NUM; @@ -139,11 +151,11 @@ struct value *v, *a; struct lcmd_arg arg_smooth[] = { { "window", 1, ARG_NUM }, { "flag", 1, ARG_ANY }, - 0 + { NULL, 0, 0 } }; -l_smooth(v, a) -struct value *v, *a; +void +l_smooth(struct value *v, struct value *a) { struct ww *w; @@ -151,17 +163,20 @@ struct value *v, *a; v->v_num = 0; if ((w = vtowin(a++, selwin)) == 0) return; - v->v_num = !w->ww_noupdate; - w->ww_noupdate = !vtobool(a, v->v_num, v->v_num); + v->v_num = ISSET(w->ww_wflags, WWW_NOUPDATE) == 0; + if (!vtobool(a, v->v_num, v->v_num)) + SET(w->ww_wflags, WWW_NOUPDATE); + else + CLR(w->ww_wflags, WWW_NOUPDATE); } struct lcmd_arg arg_def_smooth[] = { { "flag", 1, ARG_ANY }, - 0 + { NULL, 0, 0 } }; -l_def_smooth(v, a) -struct value *v, *a; +void +l_def_smooth(struct value *v, struct value *a) { v->v_type = V_NUM; v->v_num = default_smooth; @@ -170,11 +185,11 @@ struct value *v, *a; struct lcmd_arg arg_select[] = { { "window", 1, ARG_NUM }, - 0 + { NULL, 0, 0 } }; -l_select(v, a) -struct value *v, *a; +void +l_select(struct value *v, struct value *a) { struct ww *w; @@ -182,18 +197,18 @@ struct value *v, *a; v->v_num = selwin ? selwin->ww_id + 1 : -1; if (a->v_type == V_ERR) return; - if ((w = vtowin(a, NULL)) == 0) + if ((w = vtowin(a, (struct ww *)0)) == 0) return; setselwin(w); } struct lcmd_arg arg_debug[] = { { "flag", 1, ARG_ANY }, - 0 + { NULL, 0, 0 } }; -l_debug(v, a) -struct value *v, *a; +void +l_debug(struct value *v, struct value *a) { v->v_type = V_NUM; v->v_num = debug; @@ -202,11 +217,11 @@ struct value *v, *a; struct lcmd_arg arg_escape[] = { { "escapec", 1, ARG_STR }, - 0 + { NULL, 0, 0 } }; -l_escape(v, a) -struct value *v, *a; +void +l_escape(struct value *v, struct value *a) { char buf[2]; @@ -224,13 +239,11 @@ struct value *v, *a; struct lcmd_arg arg_label[] = { { "window", 1, ARG_NUM }, { "label", 1, ARG_STR }, - 0 + { NULL, 0, 0 } }; -/*ARGSUSED*/ -l_label(v, a) -struct value *v; -struct value *a; +void +l_label(struct value *v __unused, struct value *a) { struct ww *w; @@ -244,11 +257,11 @@ struct value *a; struct lcmd_arg arg_foreground[] = { { "window", 1, ARG_NUM }, { "flag", 1, ARG_ANY }, - 0 + { NULL, 0, 0 } }; -l_foreground(v, a) -struct value *v, *a; +void +l_foreground(struct value *v, struct value *a) { struct ww *w; char flag; @@ -267,11 +280,11 @@ struct value *v, *a; struct lcmd_arg arg_terse[] = { { "flag", 1, ARG_ANY }, - 0 + { NULL, 0, 0 } }; -l_terse(v, a) -struct value *v, *a; +void +l_terse(struct value *v, struct value *a) { v->v_type = V_NUM; v->v_num = terse; @@ -280,11 +293,11 @@ struct value *v, *a; struct lcmd_arg arg_source[] = { { "filename", 1, ARG_STR }, - 0 + { NULL, 0, 0 } }; -l_source(v, a) -struct value *v, *a; +void +l_source(struct value *v, struct value *a) { v->v_type = V_NUM; if (a->v_type != V_ERR && dosource(a->v_str) < 0) { @@ -297,13 +310,11 @@ struct value *v, *a; struct lcmd_arg arg_write[] = { { "window", 1, ARG_NUM }, { "", 0, ARG_ANY|ARG_LIST }, - 0 + { NULL, 0, 0 } }; -/*ARGSUSED*/ -l_write(v, a) -struct value *v; -struct value *a; +void +l_write(struct value *v __unused, struct value *a) { char buf[20]; struct ww *w; @@ -323,31 +334,29 @@ struct value *a; struct lcmd_arg arg_close[] = { { "window", 1, ARG_ANY|ARG_LIST }, - 0 + { NULL, 0, 0 } }; -/*ARGSUSED*/ -l_close(v, a) -struct value *v; -struct value *a; +void +l_close(struct value *v __unused, struct value *a) { struct ww *w; if (a->v_type == V_STR && str_match(a->v_str, "all", 3)) - closewin(NULL); + closewin((struct ww *)0); else for (; a->v_type != V_ERR; a++) - if ((w = vtowin(a, NULL)) != 0) + if ((w = vtowin(a, (struct ww *)0)) != 0) closewin(w); } struct lcmd_arg arg_cursormodes[] = { { "modes", 1, ARG_NUM }, - 0 + { NULL, 0, 0 } }; -l_cursormodes(v, a) -struct value *v, *a; +void +l_cursormodes(struct value *v, struct value *a) { v->v_type = V_NUM; @@ -358,11 +367,11 @@ struct value *v, *a; struct lcmd_arg arg_unset[] = { { "variable", 1, ARG_ANY }, - 0 + { NULL, 0, 0 } }; -l_unset(v, a) -struct value *v, *a; +void +l_unset(struct value *v, struct value *a) { v->v_type = V_NUM; switch (a->v_type) { @@ -382,9 +391,7 @@ struct value *v, *a; } struct ww * -vtowin(v, w) -struct value *v; -struct ww *w; +vtowin(struct value *v, struct ww *w) { switch (v->v_type) { case V_ERR: @@ -404,9 +411,8 @@ struct ww *w; return w; } -vtobool(v, def, err) -struct value *v; -char def, err; +char +vtobool(struct value *v, char def, char err) { switch (v->v_type) { case V_NUM: @@ -429,4 +435,5 @@ char def, err; return def; } /*NOTREACHED*/ + return (0); } diff --git a/usr.bin/window/lcmd2.c b/usr.bin/window/lcmd2.c index 6e723f564d..25f28e8983 100644 --- a/usr.bin/window/lcmd2.c +++ b/usr.bin/window/lcmd2.c @@ -1,3 +1,5 @@ +/* $NetBSD: lcmd2.c,v 1.15 2008/12/29 01:53:35 christos Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,28 +30,33 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)lcmd2.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/lcmd2.c,v 1.2.6.2 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/lcmd2.c,v 1.4 2005/04/15 17:55:29 drhodus Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)lcmd2.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: lcmd2.c,v 1.15 2008/12/29 01:53:35 christos Exp $"); +#endif +#endif /* not lint */ + #include +#include #include - -#include -#include /* System string definitions. */ - +#include #include "defs.h" -#include "mystring.h" /* Local string definitions. */ -#include "value.h" +#include "window_string.h" #include "var.h" #include "lcmd.h" #include "alias.h" -/*ARGSUSED*/ -l_iostat(v, a) -struct value *v, *a; +int printalias(void *, struct var *); +int printvar(void *, struct var *); +char *strtime(struct timeval *t); + +void +l_iostat(struct value *v __unused, struct value *a __unused) { struct ww *w; @@ -101,30 +104,23 @@ struct value *v, *a; struct lcmd_arg arg_time[] = { { "who", 1, ARG_STR }, - 0 + { NULL, 0, 0 } }; -/*ARGSUSED*/ -l_time(v, a) -struct value *v; -struct value *a; +void +l_time(struct value *v __unused, struct value *a) { struct ww *w; struct rusage rusage; struct timeval timeval; - char *strtime(); if ((w = openiwin(8, "Timing and Resource Usage")) == 0) { error("Can't open time window: %s.", wwerror()); return; } - (void) gettimeofday(&timeval, NULL); - timeval.tv_sec -= starttime.tv_sec; - if ((timeval.tv_usec -= starttime.tv_usec) < 0) { - timeval.tv_sec--; - timeval.tv_usec += 1000000; - } + (void) gettimeofday(&timeval, (struct timezone *)0); + timersub(&timeval, &starttime, &timeval); (void) getrusage(a->v_type == V_STR && str_match(a->v_str, "children", 1) ? RUSAGE_CHILDREN : RUSAGE_SELF, &rusage); @@ -153,15 +149,14 @@ struct value *a; } char * -strtime(t) -struct timeval *t; +strtime(struct timeval *t) { char fill = 0; static char buf[20]; char *p = buf; if (t->tv_sec > 60*60) { - (void) sprintf(p, "%ld:", t->tv_sec / (60*60)); + (void) sprintf(p, "%ld:", (long int)t->tv_sec / (60*60)); while (*p++) ; p--; @@ -169,24 +164,24 @@ struct timeval *t; fill++; } if (t->tv_sec > 60) { - (void) sprintf(p, fill ? "%02ld:" : "%ld:", t->tv_sec / 60); + (void) sprintf(p, fill ? "%02lld:" : "%lld:", + (long long)t->tv_sec / 60); while (*p++) ; p--; t->tv_sec %= 60; fill++; } - (void) sprintf(p, fill ? "%02ld.%02d" : "%ld.%02ld", - t->tv_sec, t->tv_usec / 10000); + (void) sprintf(p, fill ? "%02lld.%02ld" : "%lld.%02ld", + (long long)t->tv_sec, (long)t->tv_usec / 10000); return buf; } -/*ARGSUSED*/ -l_list(v, a) -struct value *v, *a; +void +l_list(struct value *v __unused, struct value *a __unused) { struct ww *w, *wp; - register i; + int i; int n; for (n = 0, i = 0; i < NWINDOW; i++) @@ -214,26 +209,24 @@ struct value *v, *a; closeiwin(w); } -/*ARGSUSED*/ -l_variable(v, a) -struct value *v, *a; +void +l_variable(struct value *v __unused, struct value *a __unused) { struct ww *w; - int printvar(); if ((w = openiwin(wwnrow - 3, "Variables")) == 0) { error("Can't open variable window: %s.", wwerror()); return; } - if (var_walk(printvar, (long)w) >= 0) + if (var_walk(printvar, (void *)w) >= 0) waitnl(w); closeiwin(w); } -printvar(w, r) -struct ww *w; -struct var *r; +int +printvar(void *vw, struct var *r) { + struct ww *w = vw; if (more(w, 0) == 2) return -1; wwprintf(w, "%16s ", r->r_name); @@ -253,11 +246,11 @@ struct var *r; struct lcmd_arg arg_def_shell[] = { { "", 0, ARG_ANY|ARG_LIST }, - 0 + { NULL, 0, 0 } }; -l_def_shell(v, a) - struct value *v, *a; +void +l_def_shell(struct value *v, struct value *a) { char **pp; struct value *vp; @@ -267,7 +260,7 @@ l_def_shell(v, a) v->v_type = V_STR; return; } - if (v->v_str = default_shellfile) { + if ((v->v_str = default_shellfile)) { v->v_type = V_STR; for (pp = default_shell + 1; *pp; pp++) { str_free(*pp); @@ -284,37 +277,37 @@ l_def_shell(v, a) p_memerror(); break; } - if (default_shellfile = *default_shell) - if (*default_shell = strrchr(default_shellfile, '/')) + if ((default_shellfile = *default_shell)) { + if ((*default_shell = strrchr(default_shellfile, '/'))) (*default_shell)++; else *default_shell = default_shellfile; + } } struct lcmd_arg arg_alias[] = { { "", 0, ARG_STR }, { "", 0, ARG_STR|ARG_LIST }, - 0 + { NULL, 0, 0 } }; -l_alias(v, a) - struct value *v, *a; +void +l_alias(struct value *v, struct value *a) { if (a->v_type == V_ERR) { struct ww *w; - int printalias(); if ((w = openiwin(wwnrow - 3, "Aliases")) == 0) { error("Can't open alias window: %s.", wwerror()); return; } - if (alias_walk(printalias, (long)w) >= 0) + if (alias_walk(printalias, (void *)w) >= 0) waitnl(w); closeiwin(w); } else { struct alias *ap = 0; - if (ap = alias_lookup(a->v_str)) { + if ((ap = alias_lookup(a->v_str))) { if ((v->v_str = str_cpy(ap->a_buf)) == 0) { p_memerror(); return; @@ -325,7 +318,7 @@ l_alias(v, a) struct value *vp; char *p, *q; char *str; - register n; + int n; for (n = 0, vp = a + 1; vp->v_type != V_ERR; vp++, n++) for (p = vp->v_str; *p; p++, n++) @@ -336,10 +329,10 @@ l_alias(v, a) } for (q = str, vp = a + 1; vp->v_type != V_ERR; vp++, q[-1] = ' ') - for (p = vp->v_str; *q++ = *p++;) + for (p = vp->v_str; (*q++ = *p++);) ; q[-1] = 0; - if ((ap = alias_set(a[0].v_str, NULL)) == 0) { + if ((ap = alias_set(a[0].v_str, (char *)0)) == 0) { p_memerror(); str_free(str); return; @@ -349,10 +342,10 @@ l_alias(v, a) } } -printalias(w, a) -struct ww *w; -struct alias *a; +int +printalias(void *vw, struct var *a) { + struct ww *w = vw; if (more(w, 0) == 2) return -1; wwprintf(w, "%16s %s\n", a->a_name, a->a_buf); @@ -361,11 +354,11 @@ struct alias *a; struct lcmd_arg arg_unalias[] = { { "alias", 1, ARG_STR }, - 0 + { NULL, 0, 0 } }; -l_unalias(v, a) -struct value *v, *a; +void +l_unalias(struct value *v, struct value *a) { if (a->v_type == ARG_STR) v->v_num = alias_unset(a->v_str); @@ -375,13 +368,11 @@ struct value *v, *a; struct lcmd_arg arg_echo[] = { { "window", 1, ARG_NUM }, { "", 0, ARG_ANY|ARG_LIST }, - 0 + { NULL, 0, 0 } }; -/*ARGSUSED*/ -l_echo(v, a) -struct value *v; -struct value *a; +void +l_echo(struct value *v __unused, struct value *a) { char buf[20]; struct ww *w; diff --git a/usr.bin/window/local.h b/usr.bin/window/local.h index deb0eefd4d..ce9f67da45 100644 --- a/usr.bin/window/local.h +++ b/usr.bin/window/local.h @@ -1,3 +1,5 @@ +/* $NetBSD: local.h,v 1.4 2003/08/07 11:17:26 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,8 +32,6 @@ * SUCH DAMAGE. * * @(#)local.h 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/local.h,v 1.1.1.1.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/local.h,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ /* diff --git a/usr.bin/window/main.c b/usr.bin/window/main.c index 7f0c43595d..1696ee7271 100644 --- a/usr.bin/window/main.c +++ b/usr.bin/window/main.c @@ -1,3 +1,5 @@ +/* $NetBSD: main.c,v 1.15 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,83 +30,87 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#) Copyright (c) 1983, 1993 The Regents of the University of California. All rights reserved. - * @(#)main.c 8.2 (Berkeley) 4/2/94 - * $FreeBSD: src/usr.bin/window/main.c,v 1.5.6.2 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/main.c,v 1.3 2004/08/30 18:06:50 eirikn Exp $ */ -#include "defs.h" +#include +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1983, 1993\ + The Regents of the University of California. All rights reserved."); +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 4/2/94"; +#else +__RCSID("$NetBSD: main.c,v 1.15 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + +#include #include -#include #include -#include /* System string definitions. */ -#include "mystring.h" /* Local string definitions. */ +#include +#include +#include + +#include "defs.h" +#include "window_string.h" #include "char.h" #include "local.h" -#define next(a) (*++*(a) ? *(a) : (*++(a) ? *(a) : (char *)usage())) +int main(int, char **); +void usage(void); -/*ARGSUSED*/ -main(argc, argv) -char **argv; +int +main(int argc, char **argv) { - register char *p; + char *p; + const char *kp; char fflag = 0; char dflag = 0; char xflag = 0; char *cmd = 0; char tflag = 0; + int ch; escapec = ESCAPEC; - if (p = strrchr(*argv, '/')) - p++; - else - p = *argv; - debug = strcmp(p, "a.out") == 0; - while (*++argv) { - if (**argv == '-') { - switch (*++*argv) { - case 'f': - fflag++; - break; - case 'c': - if (cmd != 0) { - (void) fprintf(stderr, - "Only one -c allowed.\n"); - (void) usage(); - } - cmd = next(argv); - break; - case 'e': - setescape(next(argv)); - break; - case 't': - tflag++; - break; - case 'd': - dflag++; - break; - case 'D': - debug = !debug; - break; - case 'x': - xflag++; - break; - default: - (void) usage(); + debug = strcmp(getprogname(), "a.out") == 0; + while ((ch = getopt(argc, argv, "fc:e:tdDx")) != -1) { + switch (ch) { + case 'f': + fflag++; + break; + case 'c': + if (cmd != 0) { + warnx("Only one -c allowed"); + usage(); } - } else - (void) usage(); - } - if ((p = getenv("SHELL")) == 0) - p = _PATH_BSHELL; - if ((default_shellfile = str_cpy(p)) == 0) { - (void) fprintf(stderr, "Out of memory.\n"); - exit(1); + cmd = optarg; + break; + case 'e': + setescape(optarg); + break; + case 't': + tflag++; + break; + case 'd': + dflag++; + break; + case 'D': + debug = !debug; + break; + case 'x': + xflag++; + break; + default: + usage(); + } } - if (p = strrchr(default_shellfile, '/')) + if ((kp = getenv("SHELL")) == 0) + kp = _PATH_BSHELL; + if ((default_shellfile = str_cpy(kp)) == 0) + errx(1, "Out of memory."); + if ((p = strrchr(default_shellfile, '/'))) p++; else p = default_shellfile; @@ -116,12 +118,9 @@ char **argv; default_shell[1] = 0; default_nline = NLINE; default_smooth = 1; - (void) gettimeofday(&starttime, NULL); - (void) setlocale(LC_CTYPE, ""); - if (wwinit() < 0) { - (void) fprintf(stderr, "%s.\n", wwerror()); - exit(1); - } + (void) gettimeofday(&starttime, (struct timezone *)0); + if (wwinit() < 0) + errx(1, "%s", wwerror()); #ifdef OLD_TTY if (debug) @@ -147,26 +146,25 @@ char **argv; if (debug || xflag) (void) wwsettty(0, &wwnewtty); - if ((cmdwin = wwopen(wwbaud > 2400 ? WWO_REVERSE : 0, 1, wwncol, - 0, 0, 0)) == 0) { + if ((cmdwin = wwopen(WWT_INTERNAL, wwbaud > 2400 ? WWO_REVERSE : 0, 1, + wwncol, 0, 0, 0)) == 0) { wwflush(); - (void) fprintf(stderr, "%s.\r\n", wwerror()); + warnx("%s.\r", wwerror()); goto bad; } - cmdwin->ww_mapnl = 1; - cmdwin->ww_nointr = 1; - cmdwin->ww_noupdate = 1; - cmdwin->ww_unctrl = 1; - if ((framewin = wwopen(WWO_GLASS|WWO_FRAME, wwnrow, wwncol, 0, 0, 0)) - == 0) { + SET(cmdwin->ww_wflags, + WWW_MAPNL | WWW_NOINTR | WWW_NOUPDATE | WWW_UNCTRL); + if ((framewin = wwopen(WWT_INTERNAL, WWO_GLASS|WWO_FRAME, wwnrow, + wwncol, 0, 0, 0)) == 0) { wwflush(); - (void) fprintf(stderr, "%s.\r\n", wwerror()); + warnx("%s.\r", wwerror()); goto bad; } wwadd(framewin, &wwhead); - if ((boxwin = wwopen(WWO_GLASS, wwnrow, wwncol, 0, 0, 0)) == 0) { + if ((boxwin = wwopen(WWT_INTERNAL, WWO_GLASS, wwnrow, wwncol, 0, 0, 0)) + == 0) { wwflush(); - (void) fprintf(stderr, "%s.\r\n", wwerror()); + warnx("%s.\r", wwerror()); goto bad; } fgwin = framewin; @@ -178,7 +176,7 @@ char **argv; setterse(tflag); setcmd(1); if (cmd != 0) - (void) dolongcmd(cmd, NULL, 0); + (void) dolongcmd(cmd, (struct value *)0, 0); if (!fflag) if (dflag || doconfig() < 0) dodefault(); @@ -192,9 +190,11 @@ bad: return 0; } -usage() +void +usage(void) { - (void) fprintf(stderr, "usage: window [-e escape-char] [-c command] [-t] [-f] [-d]\n"); + (void) fprintf(stderr, + "usage: %s [-e escape-char] [-c command] [-t] [-f] [-d]\n", + getprogname()); exit(1); - return 0; /* for lint */ } diff --git a/usr.bin/window/mloop.c b/usr.bin/window/mloop.c index e8f6d43593..89852155b1 100644 --- a/usr.bin/window/mloop.c +++ b/usr.bin/window/mloop.c @@ -1,3 +1,5 @@ +/* $NetBSD: mloop.c,v 1.8 2003/08/07 11:17:27 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,39 +30,49 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)mloop.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/mloop.c,v 1.1.1.1.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/mloop.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)mloop.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: mloop.c,v 1.8 2003/08/07 11:17:27 agc Exp $"); +#endif +#endif /* not lint */ + #include +#include #include "defs.h" -mloop() +void +mloop(void) { while (!quit) { if (incmd) { docmd(); } else if (wwcurwin->ww_state != WWS_HASPROC) { - if (!wwcurwin->ww_keepopen) + if (!ISSET(wwcurwin->ww_uflags, WWU_KEEPOPEN)) closewin(wwcurwin); setcmd(1); if (wwpeekc() == escapec) (void) wwgetc(); error("Process died."); } else { - register struct ww *w = wwcurwin; - register char *p; - register n; + struct ww *w = wwcurwin; + char *p; + int n; - if (wwibp >= wwibq) + if (wwibp >= wwibq) { + wwibp = wwibq = wwib; wwiomux(); + } for (p = wwibp; p < wwibq && wwmaskc(*p) != escapec; p++) ; if ((n = p - wwibp) > 0) { - if (!w->ww_ispty && w->ww_stopped) + if (w->ww_type != WWT_PTY && + ISSET(w->ww_pflags, WWP_STOPPED)) startwin(w); #if defined(sun) && !defined(BSD) /* workaround for SunOS pty bug */ diff --git a/usr.bin/window/parser.h b/usr.bin/window/parser.h index c651a2a2a8..f4f2381847 100644 --- a/usr.bin/window/parser.h +++ b/usr.bin/window/parser.h @@ -1,3 +1,5 @@ +/* $NetBSD: parser.h,v 1.8 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,16 +32,31 @@ * SUCH DAMAGE. * * @(#)parser.h 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/parser.h,v 1.1.1.1.14.2 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/parser.h,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ -#include "value.h" #include "context.h" #include "token.h" -#include "mystring.h" +#include "window_string.h" #define p_erred() (cx.x_erred) #define p_synerred() (cx.x_synerred) #define p_clearerr() (cx.x_erred = cx.x_synerred = 0) #define p_abort() (cx.x_abort) + +int p_assign(const char *, struct value *, int); +int p_convstr(struct value *v); +void p_error(const char *msg, ...) + __attribute__((__format__(__printf__, 1, 2))); +int p_expr(struct value *, char); +int p_expr0(struct value *, char); +int p_expr1(struct value *, char); +int p_expr11(struct value *, char); +int p_expr12(struct value *, char); +int p_expr2(struct value *, char); +int p_expr3_10(int, struct value *, char); +int p_expression(char); +int p_function(const char *, struct value *, int); +int p_if(char); +int p_statement(char); +void p_statementlist(char); +void p_synerror(void); diff --git a/usr.bin/window/parser1.c b/usr.bin/window/parser1.c index 92307f2e5a..6586bc3439 100644 --- a/usr.bin/window/parser1.c +++ b/usr.bin/window/parser1.c @@ -1,3 +1,5 @@ +/* $NetBSD: parser1.c,v 1.6 2003/08/07 11:17:28 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,15 +30,22 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)parser1.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/parser1.c,v 1.1.1.1.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/parser1.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)parser1.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: parser1.c,v 1.6 2003/08/07 11:17:28 agc Exp $"); +#endif +#endif /* not lint */ + +#include "defs.h" #include "parser.h" -p_start() +void +p_start(void) { char flag = 1; @@ -62,15 +67,15 @@ p_start() } } -p_statementlist(flag) -char flag; +void +p_statementlist(char flag) { for (; p_statement(flag) >= 0; p_clearerr()) ; } -p_statement(flag) -char flag; +int +p_statement(char flag) { switch (token) { case T_EOL: @@ -83,8 +88,8 @@ char flag; } } -p_if(flag) -char flag; +int +p_if(char flag) { struct value t; char true = 0; @@ -137,12 +142,11 @@ top: return -1; } -p_expression(flag) -char flag; +int +p_expression(char flag) { struct value t; char *cmd; - int p_function(), p_assign(); switch (token) { case T_NUM: @@ -183,8 +187,8 @@ char flag; return 0; } -p_convstr(v) -register struct value *v; +int +p_convstr(struct value *v) { if (v->v_type != V_NUM) return 0; @@ -197,7 +201,8 @@ register struct value *v; return 0; } -p_synerror() +void +p_synerror(void) { if (!cx.x_synerred) { cx.x_synerred = cx.x_erred = 1; @@ -205,17 +210,21 @@ p_synerror() } } -/*VARARGS1*/ -p_error(msg, a, b, c) -char *msg; +void +p_error(const char *msg, ...) { + va_list ap; + + va_start(ap, msg); if (!cx.x_erred) { cx.x_erred = 1; - error(msg, a, b, c); + verror(msg, ap); } + va_end(ap); } -p_memerror() +void +p_memerror(void) { cx.x_erred = cx.x_abort = 1; error("Out of memory."); diff --git a/usr.bin/window/parser2.c b/usr.bin/window/parser2.c index b065515b4c..1f3c43ea7c 100644 --- a/usr.bin/window/parser2.c +++ b/usr.bin/window/parser2.c @@ -1,3 +1,5 @@ +/* $NetBSD: parser2.c,v 1.11 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,44 +30,52 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)parser2.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/parser2.c,v 1.1.1.1.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/parser2.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)parser2.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: parser2.c,v 1.11 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + +#define EXTERN +#include "ww.h" +#include "defs.h" +#include "alias.h" +#undef EXTERN #include "parser.h" #include "var.h" #include "lcmd.h" -#include "alias.h" /* * name == 0 means we don't have a function name but * want to parse the arguments anyway. flag == 0 in this case. */ -p_function(name, v, flag) -char *name; -register struct value *v; +int +p_function(const char *name, struct value *v, int flag) { struct value t; - register struct lcmd_tab *c = 0; - register struct alias *a = 0; - register struct lcmd_arg *ap; /* this arg */ + struct lcmd_tab *c = 0; + struct alias *a = 0; + struct lcmd_arg *ap; /* this arg */ struct lcmd_arg *lp = 0; /* list arg */ - register i; + int i; struct value av[LCMD_NARG + 1]; - register struct value *vp; + struct value *vp; - if (name != 0) - if (c = lcmd_lookup(name)) + if (name != 0) { + if ((c = lcmd_lookup(name))) name = c->lc_name; - else if (a = alias_lookup(name)) + else if ((a = alias_lookup(name))) name = a->a_name; else { p_error("%s: No such command or alias.", name); flag = 0; } - + } for (vp = av; vp < &av[LCMD_NARG + 1]; vp++) vp->v_type = V_ERR; @@ -89,8 +95,8 @@ register struct value *v; } if (token != T_ASSIGN) { if (i >= LCMD_NARG || - c != 0 && (ap = lp) == 0 && - (ap = c->lc_arg + i)->arg_name == 0) { + (c != 0 && (ap = lp) == 0 && + (ap = c->lc_arg + i)->arg_name == 0)) { p_error("%s: Too many arguments.", name); flag = 0; } else @@ -138,29 +144,29 @@ register struct value *v; i = vp - av + 1; lp = ap; } - if (vp->v_type != V_ERR) { + if (vp && vp->v_type != V_ERR) { if (*ap->arg_name) p_error("%s: Argument %d (%s) duplicated.", - name, vp - av + 1, + name, (int)(vp - av + 1), ap->arg_name); else p_error("%s: Argument %d duplicated.", - name, vp - av + 1); + name, (int)(vp - av + 1)); flag = 0; vp = 0; } else if (t.v_type == V_ERR) { /* do nothing */ - } else if ((ap->arg_flags&ARG_TYPE) == ARG_NUM && - t.v_type != V_NUM || - (ap->arg_flags&ARG_TYPE) == ARG_STR && - t.v_type != V_STR) { + } else if (((ap->arg_flags&ARG_TYPE) == ARG_NUM && + t.v_type != V_NUM) || + ((ap->arg_flags&ARG_TYPE) == ARG_STR && + t.v_type != V_STR)) { if (*ap->arg_name) p_error("%s: Argument %d (%s) type mismatch.", - name, vp - av + 1, + name, (int)(vp - av + 1), ap->arg_name); else p_error("%s: Argument %d type mismatch.", - name, vp - av + 1); + name, (int)(vp - av + 1)); flag = 0; vp = 0; } @@ -180,10 +186,10 @@ register struct value *v; else if (token != T_EOL && token != T_EOF) flag = 0; /* look for legal follow set */ v->v_type = V_ERR; - if (flag) + if (flag) { if (c != 0) (*c->lc_func)(v, av); - else + else { if (a->a_flags & A_INUSE) p_error("%s: Recursive alias.", a->a_name); else { @@ -192,6 +198,8 @@ register struct value *v; p_memerror(); a->a_flags &= ~A_INUSE; } + } + } if (p_abort()) { val_free(*v); v->v_type = V_ERR; @@ -206,10 +214,8 @@ abort: return -1; } -p_assign(name, v, flag) -char *name; -struct value *v; -char flag; +int +p_assign(const char *name, struct value *v, int flag) { (void) s_gettok(); @@ -220,7 +226,7 @@ char flag; switch (v->v_type) { case V_STR: case V_NUM: - if (flag && var_set(name, v) == 0) { + if (name && flag && var_set(name, v) == 0) { p_memerror(); val_free(*v); return -1; diff --git a/usr.bin/window/parser3.c b/usr.bin/window/parser3.c index ffbec32d30..a1bc0dfdc0 100644 --- a/usr.bin/window/parser3.c +++ b/usr.bin/window/parser3.c @@ -1,3 +1,5 @@ +/* $NetBSD: parser3.c,v 1.6 2003/08/07 11:17:28 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,12 +30,18 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)parser3.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/parser3.c,v 1.1.1.1.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/parser3.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)parser3.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: parser3.c,v 1.6 2003/08/07 11:17:28 agc Exp $"); +#endif +#endif /* not lint */ + +#include "defs.h" #include "parser.h" /* @@ -55,9 +59,8 @@ * * / % * unary - + ~ ! */ -p_expr(v, flag) -register struct value *v; -char flag; +int +p_expr(struct value *v, char flag) { struct value t; int ret; @@ -85,12 +88,11 @@ char flag; /* * ? : */ -p_expr0(v, flag) -register struct value *v; -char flag; +int +p_expr0(struct value *v, char flag) { struct value t; - char true; + char true = 0; if (p_expr1(v, flag) < 0) return -1; @@ -124,9 +126,8 @@ char flag; /* * || */ -p_expr1(v, flag) -register struct value *v; -char flag; +int +p_expr1(struct value *v, char flag) { char true = 0; @@ -158,9 +159,8 @@ char flag; /* * && */ -p_expr2(v, flag) -register struct value *v; -char flag; +int +p_expr2(struct value *v, char flag) { char true = 1; diff --git a/usr.bin/window/parser4.c b/usr.bin/window/parser4.c index 78fe731db0..423deff772 100644 --- a/usr.bin/window/parser4.c +++ b/usr.bin/window/parser4.c @@ -1,3 +1,5 @@ +/* $NetBSD: parser4.c,v 1.9 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,13 +30,19 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)parser4.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/parser4.c,v 1.2.6.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/parser4.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)parser4.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: parser4.c,v 1.9 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + #include +#include "defs.h" #include "parser.h" /* @@ -51,13 +55,12 @@ * + - 9 * * / % 10 */ -p_expr3_10(level, v, flag) -register struct value *v; -char flag; +int +p_expr3_10(int level, struct value *v, char flag) { struct value l, r; int op; - char *opname; + const char *opname = 0; if ((level == 10 ? p_expr11(v, flag) : p_expr3_10(level + 1, v, flag)) < 0) diff --git a/usr.bin/window/parser5.c b/usr.bin/window/parser5.c index 76bf810610..3a835505d8 100644 --- a/usr.bin/window/parser5.c +++ b/usr.bin/window/parser5.c @@ -1,3 +1,5 @@ +/* $NetBSD: parser5.c,v 1.7 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,24 +30,29 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)parser5.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/parser5.c,v 1.1.1.1.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/parser5.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)parser5.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: parser5.c,v 1.7 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + +#include "defs.h" #include "parser.h" #include "var.h" /* * unary $ $? + - ! ~ */ -p_expr11(v, flag) -register struct value *v; -char flag; +int +p_expr11(struct value *v, char flag) { int op; - char *opname; + const char *opname; switch (token) { case T_DOLLAR: @@ -146,9 +149,8 @@ char flag; * * Always return v_type == V_ERR when flag == 0. */ -p_expr12(v, flag) -register struct value *v; -char flag; +int +p_expr12(struct value *v, char flag) { v->v_type = V_ERR; switch (token) { diff --git a/usr.bin/window/scanner.c b/usr.bin/window/scanner.c index 145c7ea4d5..7cbfe4a533 100644 --- a/usr.bin/window/scanner.c +++ b/usr.bin/window/scanner.c @@ -1,3 +1,5 @@ +/* $NetBSD: scanner.c,v 1.9 2003/08/07 11:17:29 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,24 +30,32 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)scanner.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/scanner.c,v 1.2.14.2 2001/05/17 09:46:29 obrien Exp $ - * $DragonFly: src/usr.bin/window/scanner.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ -#include +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)scanner.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: scanner.c,v 1.9 2003/08/07 11:17:29 agc Exp $"); +#endif +#endif /* not lint */ + #include -#include "value.h" +#include "defs.h" #include "token.h" #include "context.h" -#include "string.h" -#include "mystring.h" +#include "window_string.h" -s_getc() +int s_getc(void); +int s_gettok1(void); +int s_ungetc(int); + +int +s_getc(void) { - register c; + int c; switch (cx.x_type) { case X_FILE: @@ -68,9 +74,11 @@ s_getc() return EOF; } /*NOTREACHED*/ + return(0); /* XXX: placate gcc */ } -s_ungetc(c) +int +s_ungetc(int c) { if (c == EOF) return EOF; @@ -85,14 +93,16 @@ s_ungetc(c) return EOF; } /*NOTREACHED*/ + return(0); /* XXX: placate gcc */ } -s_gettok() +int +s_gettok(void) { char buf[100]; - register char *p = buf; - register c; - register state = 0; + char *p = buf; + int c; + int state = 0; loop: c = s_getc(); @@ -114,6 +124,22 @@ loop: cx.x_token = T_EOF; state = -1; break; + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': + case '_': case '.': + *p++ = c; + state = 2; + break; case '"': state = 3; break; @@ -219,11 +245,6 @@ loop: state = -1; break; default: - if (isalpha(c) || c == '_' || c == '.') { - *p++ = c; - state = 2; - break; - } cx.x_val.v_num = c; cx.x_token = T_CHAR; state = -1; @@ -238,6 +259,24 @@ loop: break; case 2: /* unquoted string */ switch (c) { + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': + case '_': case '.': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (p < buf + sizeof buf - 1) + *p++ = c; + break; case '"': state = 3; break; @@ -256,11 +295,6 @@ loop: } break; default: - if (isalnum(c) || c == '_' || c == '.') { - if (p < buf + sizeof buf - 1) - *p++ = c; - break; - } (void) s_ungetc(c); case EOF: *p = 0; @@ -280,12 +314,20 @@ loop: && buf[3] == 'i' && buf[4] == 'f' && buf[5] == 0) cx.x_token = T_ENDIF; - else if (buf[1] == 'l' && buf[2] == 's') - if (buf[3] == 'i' && buf[4] == 'f' - && buf[5] == 0) - cx.x_token = T_ELSIF; - else if (buf[3] == 'e' && buf[4] == 0) - cx.x_token = T_ELSE; + else { + if (buf[1] == 'l' && buf[2] == 's') { + if (buf[3] == 'i' + && buf[4] == 'f' + && buf[5] == 0) + cx.x_token = T_ELSIF; + else { + if (buf[3] == 'e' + && buf[4] == 0) + cx.x_token = + T_ELSE; + } + } + } break; } if (cx.x_token == T_STR @@ -509,10 +551,11 @@ loop: return cx.x_token; } -s_gettok1() +int +s_gettok1(void) { - register c; - register n; + int c; + int n; c = s_getc(); /* got \ */ switch (c) { diff --git a/usr.bin/window/startup.c b/usr.bin/window/startup.c index 1d5dee6c80..3b683d5f62 100644 --- a/usr.bin/window/startup.c +++ b/usr.bin/window/startup.c @@ -1,3 +1,5 @@ +/* $NetBSD: startup.c,v 1.8 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,30 +30,34 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)startup.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/startup.c,v 1.1.1.1.14.1 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/startup.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ -#include +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)startup.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: startup.c,v 1.8 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ +#include #include "defs.h" -#include "value.h" #include "var.h" #include "char.h" #include "local.h" -doconfig() +int +doconfig(void) { char buf[100]; - char *home; + const char *home; static char runcom[] = RUNCOM; if ((home = getenv("HOME")) == 0) home = "."; (void) sprintf(buf, "%.*s/%s", - (sizeof buf - sizeof runcom) / sizeof (char) - 1, + (int)((sizeof buf - sizeof runcom) / sizeof (char) - 1), home, runcom); return dosource(buf); } @@ -63,21 +65,25 @@ doconfig() /* * The default is two windows of equal size. */ -dodefault() +void +dodefault(void) { struct ww *w; - register r = wwnrow / 2 - 1; + int r = wwnrow / 2 - 1; if (openwin(1, r + 2, 0, wwnrow - r - 2, wwncol, default_nline, - NULL, 1, 1, default_shellfile, default_shell) == 0) + (char *) 0, WWT_PTY, WWU_HASFRAME, default_shellfile, + default_shell) == 0) return; if ((w = openwin(0, 1, 0, r, wwncol, default_nline, - NULL, 1, 1, default_shellfile, default_shell)) == 0) + (char *) 0, WWT_PTY, WWU_HASFRAME, default_shellfile, + default_shell)) == 0) return; wwprintf(w, "Escape character is %s.\r\n", unctrl(escapec)); } -setvars() +void +setvars(void) { /* try to use a random ordering to balance the tree */ (void) var_setnum("nrow", wwnrow); diff --git a/usr.bin/window/string.c b/usr.bin/window/string.c index dbce1f8154..625d3c208a 100644 --- a/usr.bin/window/string.c +++ b/usr.bin/window/string.c @@ -1,3 +1,5 @@ +/* $NetBSD: string.c,v 1.10 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,41 +30,44 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)string.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/string.c,v 1.2.6.2 2001/05/17 09:45:00 obrien Exp $ - * $DragonFly: src/usr.bin/window/string.c,v 1.3 2005/02/28 13:57:05 joerg Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)string.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: string.c,v 1.10 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + #include #include -#include /* System string definitions. */ - -#include "mystring.h" /* Local string definitions. */ +#include +#define EXTERN +#include "window_string.h" +#undef EXTERN char * -str_cpy(s) -register char *s; +str_cpy(const char *s) { char *str; - register char *p; + char *p; str = p = str_alloc(strlen(s) + 1); if (p == 0) return 0; - while (*p++ = *s++) + while ((*p++ = *s++)) ; return str; } char * -str_ncpy(s, n) -register char *s; -register n; +str_ncpy(const char *s, int n) { int l = strlen(s); char *str; - register char *p; + char *p; if (n > l) n = l; @@ -80,28 +81,27 @@ register n; } char * -str_itoa(i) -int i; +str_itoa(int i) { char buf[30]; - (void) sprintf(buf, "%d", i); + (void) snprintf(buf, sizeof(buf), "%d", i); return str_cpy(buf); } char * -str_cat(s1, s2) -char *s1, *s2; +str_cat(const char *s1, const char *s2) { char *str; - register char *p, *q; + char *p; + const char *q; str = p = str_alloc(strlen(s1) + strlen(s2) + 1); if (p == 0) return 0; - for (q = s1; *p++ = *q++;) + for (q = s1; (*p++ = *q++);) ; - for (q = s2, p--; *p++ = *q++;) + for (q = s2, p--; (*p++ = *q++);) ; return str; } @@ -110,23 +110,21 @@ char *s1, *s2; * match s against p. * s can be a prefix of p with at least min characters. */ -str_match(s, p, min) -register char *s, *p; -register min; +int +str_match(const char *s, const char *p, int min) { for (; *s && *p && *s == *p; s++, p++, min--) ; - return *s == *p || *s == 0 && min <= 0; + return *s == *p || (*s == 0 && min <= 0); } #ifdef STR_DEBUG char * -str_alloc(l) -int l; +str_alloc(size_t l) { - register struct mystring *s; + struct string *s; - s = (struct mystring *) malloc((unsigned)l + str_offset); + s = (struct string *) malloc(l + str_offset); if (s == 0) return 0; if (str_head.s_forw == 0) @@ -138,10 +136,10 @@ int l; return s->s_data; } -str_free(str) -char *str; +void +str_free(char *str) { - register struct mystring *s; + struct string *s; for (s = str_head.s_forw; s != &str_head && s->s_data != str; s = s->s_forw) diff --git a/usr.bin/window/token.h b/usr.bin/window/token.h index cdf95dbfc8..939f6e6a92 100644 --- a/usr.bin/window/token.h +++ b/usr.bin/window/token.h @@ -1,3 +1,5 @@ +/* $NetBSD: token.h,v 1.4 2003/08/07 11:17:30 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,8 +32,6 @@ * SUCH DAMAGE. * * @(#)token.h 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/token.h,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/token.h,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ #define token (cx.x_token) diff --git a/usr.bin/window/tt.h b/usr.bin/window/tt.h index a217ec5bcc..72e71fe05e 100644 --- a/usr.bin/window/tt.h +++ b/usr.bin/window/tt.h @@ -1,3 +1,5 @@ +/* $NetBSD: tt.h,v 1.9 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,41 +32,48 @@ * SUCH DAMAGE. * * @(#)tt.h 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/tt.h,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/tt.h,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include + +#ifndef EXTERN +#define EXTERN extern +#endif + /* * Interface structure for the terminal drivers. */ struct tt { /* startup and cleanup */ - int (*tt_start)(); - int (*tt_reset)(); - int (*tt_end)(); + void (*tt_start)(void); + void (*tt_reset)(void); + void (*tt_end)(void); /* terminal functions */ - int (*tt_move)(); - int (*tt_insline)(); - int (*tt_delline)(); - int (*tt_inschar)(); - int (*tt_insspace)(); - int (*tt_delchar)(); - int (*tt_write)(); /* write a whole block */ - int (*tt_putc)(); /* write one character */ - int (*tt_clreol)(); - int (*tt_clreos)(); - int (*tt_clear)(); - int (*tt_scroll_down)(); - int (*tt_scroll_up)(); - int (*tt_setscroll)(); /* set scrolling region */ - int (*tt_setmodes)(); /* set display modes */ - int (*tt_set_token)(); /* define a token */ - int (*tt_put_token)(); /* refer to a defined token */ - int (*tt_compress)(); /* begin, end compression */ - int (*tt_checksum)(); /* compute checksum */ - int (*tt_checkpoint)(); /* checkpoint protocol */ - int (*tt_rint)(); /* input processing */ + void (*tt_move)(int, int); + void (*tt_insline)(int); + void (*tt_delline)(int); + void (*tt_inschar)(char); + void (*tt_insspace)(int); + void (*tt_delchar)(int); + void (*tt_write)(const char *, int); /* write a whole block */ + void (*tt_putc)(char); /* write one character */ + void (*tt_clreol)(void); + void (*tt_clreos)(void); + void (*tt_clear)(void); + void (*tt_scroll_down)(int); + void (*tt_scroll_up)(int); + void (*tt_setscroll)(int, int);/* set scrolling region */ + void (*tt_setmodes)(int); /* set display modes */ + void (*tt_set_token)(int, char *, int); + /* define a token */ + void (*tt_put_token)(int, const char *, int); + /* refer to a defined token */ + void (*tt_compress)(int); /* begin, end compression */ + void (*tt_checksum)(char *, int); + /* compute checksum */ + void (*tt_checkpoint)(void); /* checkpoint protocol */ + int (*tt_rint)(char *, int); /* input processing */ /* internal variables */ char tt_modes; /* the current display modes */ @@ -97,9 +102,9 @@ struct tt { short *tt_frame; /* ttflush() hook */ - int (*tt_flush)(); + void (*tt_flush)(void); }; -struct tt tt; +EXTERN struct tt tt; /* * tt_padc is used by the compression routine. @@ -111,28 +116,46 @@ struct tt tt; * List of terminal drivers. */ struct tt_tab { - char *tt_name; + const char *tt_name; int tt_len; - int (*tt_func)(); + int (*tt_func)(void); }; -extern struct tt_tab tt_tab[]; +EXTERN struct tt_tab tt_tab[]; /* * Clean interface to termcap routines. * Too may t's. */ -char tt_strings[1024]; /* string buffer */ -char *tt_strp; /* pointer for it */ +EXTERN char tt_strings[1024]; /* string buffer */ +EXTERN char *tt_strp; /* pointer for it */ struct tt_str { - char *ts_str; + const char *ts_str; int ts_n; }; -struct tt_str *tttgetstr(); -struct tt_str *ttxgetstr(); /* tgetstr() and expand delays */ +struct tt_str *tttgetstr(const char *); +struct tt_str *ttxgetstr(const char *); /* tgetstr() and expand delays */ + +int tt_f100(void); +int tt_generic(void); +int tt_h19(void); +int tt_h29(void); +int tt_tvi925(void); +int tt_wyse60(void); +int tt_wyse75(void); +int tt_zapple(void); +int tt_zentec(void); +void ttflush(void); +int ttinit(void); +void ttpgoto(struct tt_str *, int, int, int); +void ttputs(const char *); +int ttstrcmp(struct tt_str *, struct tt_str *); +void tttgoto(struct tt_str *, int, int); +int tttputc(int); +void ttwrite(const char *, int); +int ttxputc(int); -int tttputc(); #define tttputs(s, n) tputs((s)->ts_str, (n), tttputc) #define ttxputs(s) ttwrite((s)->ts_str, (s)->ts_n) @@ -141,9 +164,9 @@ int tttputc(); * These variables have different meanings from the ww_ob* variables. * But I'm too lazy to think up different names. */ -char *tt_ob; -char *tt_obp; -char *tt_obe; +EXTERN char *tt_ob; +EXTERN char *tt_obp; +EXTERN char *tt_obe; #define ttputc(c) (tt_obp < tt_obe ? (*tt_obp++ = (c)) \ : (ttflush(), *tt_obp++ = (c))) diff --git a/usr.bin/window/ttf100.c b/usr.bin/window/ttf100.c index 71fec66e6a..c8941ab733 100644 --- a/usr.bin/window/ttf100.c +++ b/usr.bin/window/ttf100.c @@ -1,3 +1,5 @@ +/* $NetBSD: ttf100.c,v 1.6 2003/08/07 11:17:30 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,12 +30,17 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)ttf100.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/ttf100.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/ttf100.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ttf100.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: ttf100.c,v 1.6 2003/08/07 11:17:30 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" @@ -54,7 +57,8 @@ short f100_frame[16] = { }; extern struct tt_str *gen_AE, *gen_AS; -tt_f100() +int +tt_f100(void) { static struct tt_str ae = { "\033%", 2 }; static struct tt_str as = { "\033$", 2 }; diff --git a/usr.bin/window/ttgeneric.c b/usr.bin/window/ttgeneric.c index 28ae088ebf..d2d6d5c89a 100644 --- a/usr.bin/window/ttgeneric.c +++ b/usr.bin/window/ttgeneric.c @@ -1,3 +1,5 @@ +/* $NetBSD: ttgeneric.c,v 1.10 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,16 +30,25 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)ttgeneric.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/ttgeneric.c,v 1.2.8.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/ttgeneric.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ttgeneric.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: ttgeneric.c,v 1.10 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + +#include +#include +#include #include "ww.h" #include "tt.h" char PC, *BC, *UP; +short ospeed; /* normal frame */ short gen_frame[16] = { @@ -118,8 +125,27 @@ int gen_LI; int gen_UG; int gen_SG; -gen_setinsert(new) -char new; +void gen_clear(void); +void gen_clreol(void); +void gen_clreos(void); +void gen_delchar(int); +void gen_delline(int); +void gen_end(void); +void gen_inschar(char); +void gen_insline(int); +void gen_insspace(int); +void gen_move(int, int); +void gen_putc(char); +void gen_scroll_down(int); +void gen_scroll_up(int); +void gen_setinsert(char); +void gen_setmodes(int); +void gen_setscroll(int, int); +void gen_start(void); +void gen_write(const char *, int); + +void +gen_setinsert(char new) { if (new) { if (gen_IM) @@ -130,10 +156,10 @@ char new; tt.tt_insert = new; } -gen_setmodes(new) -register new; +void +gen_setmodes(int new) { - register diff; + int diff; diff = new ^ tt.tt_modes; if (diff & WWM_REV) { @@ -141,16 +167,24 @@ register new; if (gen_SO) ttxputs(gen_SO); } else - if (gen_SE) + if (gen_SE) { ttxputs(gen_SE); + if (!strcmp(gen_SE->ts_str, gen_UE->ts_str) && + gen_UE && gen_US && new & WWM_UL) + ttxputs(gen_US); + } } if (diff & WWM_UL) { if (new & WWM_UL) { if (gen_US) ttxputs(gen_US); } else - if (gen_UE) + if (gen_UE) { ttxputs(gen_UE); + if (!strcmp(gen_UE->ts_str, gen_SE->ts_str) && + gen_SE && gen_SO && new & WWM_REV) + ttxputs(gen_SO); + } } if (diff & WWM_GRP) { if (new & WWM_GRP) { @@ -171,7 +205,8 @@ register new; tt.tt_modes = new; } -gen_insline(n) +void +gen_insline(int n) { if (tt.tt_modes) /* for concept 100 */ gen_setmodes(0); @@ -182,7 +217,8 @@ gen_insline(n) tttputs(gen_AL, gen_LI - tt.tt_row); } -gen_delline(n) +void +gen_delline(int n) { if (tt.tt_modes) /* for concept 100 */ gen_setmodes(0); @@ -193,26 +229,26 @@ gen_delline(n) tttputs(gen_DL, gen_LI - tt.tt_row); } -gen_putc(c) -register char c; +void +gen_putc(char c) { if (tt.tt_insert) gen_setinsert(0); if (tt.tt_nmodes != tt.tt_modes) gen_setmodes(tt.tt_nmodes); ttputc(c); - if (++tt.tt_col == gen_CO) + if (++tt.tt_col == gen_CO) { if (gen_XN) tt.tt_col = tt.tt_row = -10; else if (gen_AM) tt.tt_col = 0, tt.tt_row++; else tt.tt_col--; + } } -gen_write(p, n) - register char *p; - register n; +void +gen_write(const char *p, int n) { if (tt.tt_insert) gen_setinsert(0); @@ -220,17 +256,18 @@ gen_write(p, n) gen_setmodes(tt.tt_nmodes); ttwrite(p, n); tt.tt_col += n; - if (tt.tt_col == gen_CO) + if (tt.tt_col == gen_CO) { if (gen_XN) tt.tt_col = tt.tt_row = -10; else if (gen_AM) tt.tt_col = 0, tt.tt_row++; else tt.tt_col--; + } } -gen_move(row, col) -register int row, col; +void +gen_move(int row, int col) { if (tt.tt_row == row && tt.tt_col == col) return; @@ -278,7 +315,8 @@ out: tt.tt_row = row; } -gen_start() +void +gen_start(void) { if (gen_VS) ttxputs(gen_VS); @@ -290,7 +328,8 @@ gen_start() tt.tt_nmodes = tt.tt_modes = 0; } -gen_end() +void +gen_end(void) { if (tt.tt_insert) gen_setinsert(0); @@ -300,29 +339,32 @@ gen_end() ttxputs(gen_VE); } -gen_clreol() +void +gen_clreol(void) { if (tt.tt_modes) /* for concept 100 */ gen_setmodes(0); tttputs(gen_CE, gen_CO - tt.tt_col); } -gen_clreos() +void +gen_clreos(void) { if (tt.tt_modes) /* for concept 100 */ gen_setmodes(0); tttputs(gen_CD, gen_LI - tt.tt_row); } -gen_clear() +void +gen_clear(void) { if (tt.tt_modes) /* for concept 100 */ gen_setmodes(0); ttxputs(gen_CL); } -gen_inschar(c) -register char c; +void +gen_inschar(char c) { if (!tt.tt_insert) gen_setinsert(1); @@ -333,16 +375,18 @@ register char c; ttputc(c); if (gen_IP) tttputs(gen_IP, gen_CO - tt.tt_col); - if (++tt.tt_col == gen_CO) + if (++tt.tt_col == gen_CO) { if (gen_XN) tt.tt_col = tt.tt_row = -10; else if (gen_AM) tt.tt_col = 0, tt.tt_row++; else tt.tt_col--; + } } -gen_insspace(n) +void +gen_insspace(int n) { if (gen_ICn) ttpgoto(gen_ICn, 0, n, gen_CO - tt.tt_col); @@ -351,7 +395,8 @@ gen_insspace(n) tttputs(gen_IC, gen_CO - tt.tt_col); } -gen_delchar(n) +void +gen_delchar(int n) { if (gen_DCn) ttpgoto(gen_DCn, 0, n, gen_CO - tt.tt_col); @@ -360,7 +405,8 @@ gen_delchar(n) tttputs(gen_DC, gen_CO - tt.tt_col); } -gen_scroll_down(n) +void +gen_scroll_down(int n) { gen_move(tt.tt_scroll_bot, 0); if (gen_SFn) @@ -370,7 +416,8 @@ gen_scroll_down(n) ttxputs(gen_SF); } -gen_scroll_up(n) +void +gen_scroll_up(int n) { gen_move(tt.tt_scroll_top, 0); if (gen_SRn) @@ -380,7 +427,8 @@ gen_scroll_up(n) ttxputs(gen_SR); } -gen_setscroll(top, bot) +void +gen_setscroll(int top, int bot) { tttgoto(gen_CS, bot, top); tt.tt_scroll_top = top; @@ -388,10 +436,12 @@ gen_setscroll(top, bot) tt.tt_row = tt.tt_col = -10; } -tt_generic() +int +tt_generic(void) { gen_PC = tttgetstr("pc"); PC = gen_PC ? *gen_PC->ts_str : 0; + ospeed = wwospeed; gen_CM = ttxgetstr("cm"); /* may not work */ gen_IM = ttxgetstr("im"); @@ -452,13 +502,14 @@ tt_generic() /* * Deal with obsolete termcap fields. */ - if (gen_LE == 0) + if (gen_LE == 0) { if (gen_BC) gen_LE = gen_BC; else if (gen_BS) { static struct tt_str bc = { "\b", 1 }; gen_BC = &bc; } + } if (gen_NL == 0) { static struct tt_str nl = { "\n", 1 }; gen_NL = &nl; @@ -475,15 +526,15 @@ tt_generic() */ if (gen_SF == 0 && !gen_NS) gen_SF = gen_NL; - BC = gen_LE ? gen_LE->ts_str : 0; - UP = gen_UP ? gen_UP->ts_str : 0; + BC = gen_LE ? __DECONST(char *, gen_LE->ts_str) : 0; + UP = gen_UP ? __DECONST(char *, gen_UP->ts_str) : 0; /* * Fix up display attributes that we can't handle, or don't * really exist. */ if (gen_SG > 0) gen_SO = 0; - if (gen_UG > 0 || gen_US && gen_SO && ttstrcmp(gen_US, gen_SO) == 0) + if (gen_UG > 0 || (gen_US && gen_SO && ttstrcmp(gen_US, gen_SO) == 0)) gen_US = 0; if (gen_IM && gen_IM->ts_n == 0) { @@ -518,7 +569,7 @@ tt_generic() * Don't allow scroll_up if da or db but not cs. * See comment in wwscroll.c. */ - if (gen_SR && (gen_CS || !gen_DA && !gen_DB)) + if (gen_SR && (gen_CS || (!gen_DA && !gen_DB))) tt.tt_scroll_up = gen_scroll_up; if (gen_CS) tt.tt_setscroll = gen_setscroll; diff --git a/usr.bin/window/tth19.c b/usr.bin/window/tth19.c index 240bf6683d..956af6aa93 100644 --- a/usr.bin/window/tth19.c +++ b/usr.bin/window/tth19.c @@ -1,3 +1,5 @@ +/* $NetBSD: tth19.c,v 1.7 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,12 +30,17 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)tth19.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/tth19.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/tth19.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)tth19.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: tth19.c,v 1.7 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" #include "char.h" @@ -71,7 +74,7 @@ extern struct tt_str *gen_VE; int h19_msp10c; #define PAD(ms10) { \ - register i; \ + int i; \ for (i = ((ms10) + 5) / h19_msp10c; --i >= 0;) \ ttputc('\0'); \ } @@ -80,10 +83,26 @@ int h19_msp10c; #define H19_SETINSERT(m) ttesc((tt.tt_insert = (m)) ? '@' : 'O') -h19_setmodes(new) -register new; +void h19_clear(void); +void h19_clreol(void); +void h19_clreos(void); +void h19_delchar(int); +void h19_delline(int); +void h19_end(void); +void h19_inschar(char); +void h19_insline(int); +void h19_move(int, int); +void h19_putc(char); +void h19_scroll_up(int); +void h19_scroll_down(int); +void h19_setmodes(int); +void h19_start(void); +void h19_write(const char *, int); + +void +h19_setmodes(int new) { - register diff; + int diff; diff = new ^ tt.tt_modes; if (diff & WWM_REV) @@ -93,7 +112,8 @@ register new; tt.tt_modes = new; } -h19_insline(n) +void +h19_insline(int n) { while (--n >= 0) { ttesc('L'); @@ -101,7 +121,8 @@ h19_insline(n) } } -h19_delline(n) +void +h19_delline(int n) { while (--n >= 0) { ttesc('M'); @@ -109,8 +130,8 @@ h19_delline(n) } } -h19_putc(c) -register char c; +void +h19_putc(char c) { if (tt.tt_nmodes != tt.tt_modes) (*tt.tt_setmodes)(tt.tt_nmodes); @@ -121,9 +142,8 @@ register char c; tt.tt_col = NCOL - 1; } -h19_write(p, n) -register char *p; -register n; +void +h19_write(const char *p, int n) { if (tt.tt_nmodes != tt.tt_modes) (*tt.tt_setmodes)(tt.tt_nmodes); @@ -135,8 +155,8 @@ register n; tt.tt_col = NCOL - 1; } -h19_move(row, col) -register char row, col; +void +h19_move(int row, int col) { if (tt.tt_row == row) { if (tt.tt_col == col) @@ -176,7 +196,8 @@ out: tt.tt_row = row; } -h19_start() +void +h19_start(void) { if (gen_VS) ttxputs(gen_VS); @@ -187,7 +208,8 @@ h19_start() tt.tt_nmodes = tt.tt_modes = 0; } -h19_end() +void +h19_end(void) { if (tt.tt_insert) H19_SETINSERT(0); @@ -196,23 +218,26 @@ h19_end() ttesc('v'); } -h19_clreol() +void +h19_clreol(void) { ttesc('K'); } -h19_clreos() +void +h19_clreos(void) { ttesc('J'); } -h19_clear() +void +h19_clear(void) { ttesc('E'); } -h19_inschar(c) -register char c; +void +h19_inschar(char c) { if (tt.tt_nmodes != tt.tt_modes) (*tt.tt_setmodes)(tt.tt_nmodes); @@ -225,27 +250,31 @@ register char c; tt.tt_col = NCOL - 1; } -h19_delchar(n) +void +h19_delchar(int n) { while (--n >= 0) ttesc('N'); } -h19_scroll_down(n) +void +h19_scroll_down(int n) { h19_move(NROW - 1, 0); while (--n >= 0) ttctrl('j'); } -h19_scroll_up(n) +void +h19_scroll_up(int n) { h19_move(0, 0); while (--n >= 0) ttesc('I'); } -tt_h19() +int +tt_h19(void) { float cpms = (float) wwbaud / 10000; /* char per ms */ diff --git a/usr.bin/window/tth29.c b/usr.bin/window/tth29.c index 0b9a2fa452..b230407c4a 100644 --- a/usr.bin/window/tth29.c +++ b/usr.bin/window/tth29.c @@ -1,3 +1,5 @@ +/* $NetBSD: tth29.c,v 1.6 2003/08/07 11:17:31 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,12 +30,17 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)tth29.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/tth29.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/tth29.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)tth29.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: tth29.c,v 1.6 2003/08/07 11:17:31 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" #include "char.h" @@ -58,10 +61,12 @@ kC|h29|heath-29|z29|zenith-29:\ * */ -h29_setmodes(new) -register new; +void h29_setmodes(int); + +void +h29_setmodes(int new) { - register modes = '0'; + int modes = '0'; if (new & WWM_REV) modes += 0x01; @@ -84,7 +89,8 @@ register new; tt.tt_modes = new; } -tt_h29() +int +tt_h29(void) { if (tt_h19() < 0) return -1; diff --git a/usr.bin/window/ttinit.c b/usr.bin/window/ttinit.c index 10ba13c81c..67a5cfe4aa 100644 --- a/usr.bin/window/ttinit.c +++ b/usr.bin/window/ttinit.c @@ -1,3 +1,5 @@ +/* $NetBSD: ttinit.c,v 1.9 2003/08/13 15:21:07 itojun Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,25 +30,29 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)ttinit.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/ttinit.c,v 1.2.12.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/ttinit.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ttinit.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: ttinit.c,v 1.9 2003/08/13 15:21:07 itojun Exp $"); +#endif +#endif /* not lint */ + +#include +#include #include "ww.h" #include "tt.h" -#include -int tt_h19(); -int tt_h29(); -int tt_f100(); -int tt_tvi925(); -int tt_wyse75(); -int tt_wyse60(); -int tt_zapple(); -int tt_zentec(); -int tt_generic(); +struct tt tt; +char tt_strings[1024]; /* string buffer */ +char *tt_strp; /* pointer for it */ +char *tt_ob; +char *tt_obp; +char *tt_obe; + struct tt_tab tt_tab[] = { { "h19", 3, tt_h19 }, { "h29", 3, tt_h29 }, @@ -62,15 +64,16 @@ struct tt_tab tt_tab[] = { { "zapple", 6, tt_zapple }, { "zentec", 6, tt_zentec }, { "generic", 0, tt_generic }, - 0 + { 0, 0, 0 } }; -ttinit() +int +ttinit(void) { int i; - register struct tt_tab *tp; - register char *p, *q; - register char *t; + struct tt_tab *tp; + char *p, *q; + char *t; tt_strp = tt_strings; diff --git a/usr.bin/window/ttoutput.c b/usr.bin/window/ttoutput.c index 111e0ac780..2e1281a1f2 100644 --- a/usr.bin/window/ttoutput.c +++ b/usr.bin/window/ttoutput.c @@ -1,3 +1,5 @@ +/* $NetBSD: ttoutput.c,v 1.9 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,15 +30,20 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)ttoutput.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/ttoutput.c,v 1.1.1.1.14.2 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/ttoutput.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ttoutput.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: ttoutput.c,v 1.9 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + #include #include - +#include #include "ww.h" #include "tt.h" @@ -49,10 +52,11 @@ * We need this because stdio fails on non-blocking writes. */ -ttflush() +void +ttflush(void) { - register char *p; - register n = tt_obp - tt_ob; + char *p; + int n = tt_obp - tt_ob; if (n == 0) return; @@ -83,16 +87,15 @@ ttflush() tt_obp = tt_ob; } -ttputs(s) -register char *s; +void +ttputs(const char *s) { while (*s) ttputc(*s++); } -ttwrite(s, n) - register char *s; - register n; +void +ttwrite(const char *s, int n) { switch (n) { case 0: @@ -132,13 +135,13 @@ ttwrite(s, n) break; default: while (n > 0) { - register m; + int m; while ((m = tt_obe - tt_obp) == 0) ttflush(); if ((m = tt_obe - tt_obp) > n) m = n; - bcopy(s, tt_obp, m); + memmove(tt_obp, s, m); tt_obp += m; s += m; n -= m; diff --git a/usr.bin/window/tttermcap.c b/usr.bin/window/tttermcap.c index a39fc1b6ad..bdf1da2042 100644 --- a/usr.bin/window/tttermcap.c +++ b/usr.bin/window/tttermcap.c @@ -1,3 +1,5 @@ +/* $NetBSD: tttermcap.c,v 1.9 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,34 +30,40 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)tttermcap.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/tttermcap.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/tttermcap.c,v 1.3 2005/02/28 13:57:05 joerg Exp $ */ -#include +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)tttermcap.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: tttermcap.c,v 1.9 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ +#include +#include +#include #include "tt.h" -char *tgetstr(); -char *tgoto(); - -tttputc(c) +int +tttputc(int c) { ttputc(c); + return (0); } -ttxputc(c) +int +ttxputc(int c) { *tt_strp++ = c; + return (0); } struct tt_str * -tttgetstr(str) - char *str; +tttgetstr(const char *str) { - register struct tt_str *s; + struct tt_str *s; if ((str = tgetstr(str, &tt_strp)) == 0) return 0; @@ -71,10 +75,9 @@ tttgetstr(str) } struct tt_str * -ttxgetstr(str) - char *str; +ttxgetstr(const char *str) { - register struct tt_str *s; + struct tt_str *s; char buf[100]; char *bufp = buf; @@ -89,30 +92,30 @@ ttxgetstr(str) return s; } -tttgoto(s, col, row) - struct tt_str *s; +void +tttgoto(struct tt_str *s, int col, int row) { - register char *p = s->ts_str; + const char *p = s->ts_str; ttputs(tgoto(p, col, row)); for (p += s->ts_n; *--p == 0;) ttputc(0); } -ttpgoto(s, col, row, n) - struct tt_str *s; +void +ttpgoto(struct tt_str *s, int col, int row, int n) { tputs(tgoto(s->ts_str, col, row), n, tttputc); } -ttstrcmp(a, b) - register struct tt_str *a, *b; +int +ttstrcmp(struct tt_str *a, struct tt_str *b) { int n, r; - if (r = bcmp(a->ts_str, b->ts_str, - (n = a->ts_n - b->ts_n) < 0 ? a->ts_n : b->ts_n)) + if ((r = memcmp(a->ts_str, b->ts_str, + (n = a->ts_n - b->ts_n) < 0 ? a->ts_n : b->ts_n))) return r; return n; } diff --git a/usr.bin/window/tttvi925.c b/usr.bin/window/tttvi925.c index 47d172025b..602f7be9f9 100644 --- a/usr.bin/window/tttvi925.c +++ b/usr.bin/window/tttvi925.c @@ -1,3 +1,5 @@ +/* $NetBSD: tttvi925.c,v 1.6 2003/08/07 11:17:32 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,12 +30,17 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)tttvi925.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/tttvi925.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/tttvi925.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)tttvi925.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: tttvi925.c,v 1.6 2003/08/07 11:17:32 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" @@ -53,7 +56,8 @@ short tvi925_frame[16] = { 'b'|G, 'f'|G, 'h'|G, 'd'|G }; -tt_tvi925() +int +tt_tvi925(void) { if (tt_generic() < 0) diff --git a/usr.bin/window/ttwyse60.c b/usr.bin/window/ttwyse60.c index b467d6a74a..b818a6bcee 100644 --- a/usr.bin/window/ttwyse60.c +++ b/usr.bin/window/ttwyse60.c @@ -1,12 +1,10 @@ +/* $NetBSD: ttwyse60.c,v 1.6 2003/08/07 11:17:32 agc Exp $ */ + /* * Copyright 1987 by David C. Elliott, MIPS Computer Systems. * * Unlimited redistribution allowed as long as this notice * is kept intact. - * - * @(#)ttwyse60.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/ttwyse60.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/ttwyse60.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ /* @@ -24,11 +22,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -45,6 +39,15 @@ * SUCH DAMAGE. */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ttwyse60.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: ttwyse60.c,v 1.6 2003/08/07 11:17:32 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" @@ -59,7 +62,8 @@ short wyse60_frame[16] = { extern struct tt_str *gen_AS; extern struct tt_str *gen_AE; -tt_wyse60() +int +tt_wyse60(void) { static struct tt_str ae = { "\033H\003", 3 }; static struct tt_str as = { "\033H\002", 3 }; diff --git a/usr.bin/window/ttwyse75.c b/usr.bin/window/ttwyse75.c index d84c21ba90..d8037b6e7b 100644 --- a/usr.bin/window/ttwyse75.c +++ b/usr.bin/window/ttwyse75.c @@ -1,12 +1,10 @@ +/* $NetBSD: ttwyse75.c,v 1.6 2003/08/07 11:17:32 agc Exp $ */ + /* * Copyright 1987 by David C. Elliott, MIPS Computer Systems. * * Unlimited redistribution allowed as long as this notice * is kept intact. - * - * @(#)ttwyse75.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/ttwyse75.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/ttwyse75.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ /* @@ -24,11 +22,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -45,6 +39,15 @@ * SUCH DAMAGE. */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ttwyse75.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: ttwyse75.c,v 1.6 2003/08/07 11:17:32 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" @@ -59,7 +62,8 @@ short wyse75_frame[16] = { extern struct tt_str *gen_AS; extern struct tt_str *gen_AE; -tt_wyse75() +int +tt_wyse75(void) { static struct tt_str ae = { "\033(B", 3 }; static struct tt_str as = { "\033(0", 3 }; diff --git a/usr.bin/window/ttzapple.c b/usr.bin/window/ttzapple.c index c2b6d4c444..98d339a47f 100644 --- a/usr.bin/window/ttzapple.c +++ b/usr.bin/window/ttzapple.c @@ -1,3 +1,5 @@ +/* $NetBSD: ttzapple.c,v 1.9 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,14 +30,18 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)ttzapple.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/ttzapple.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/ttzapple.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ -#include +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ttzapple.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: ttzapple.c,v 1.9 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ +#include #include "ww.h" #include "tt.h" #include "char.h" @@ -69,7 +71,32 @@ int zz_lastc; /* for checkpointing */ int zz_sum; -zz_setmodes(new) +void zz_checkpoint(void); +void zz_checksum(char *, int); +void zz_clear(void); +void zz_clreol(void); +void zz_clreos(void); +void zz_compress(int); +void zz_delchar(int); +void zz_delline(int); +void zz_end(void); +void zz_insline(int); +void zz_insspace(int); +void zz_move(int, int); +void zz_put_token(int, const char *, int); +void zz_putc(char); +void zz_reset(void); +int zz_rint(char *, int); +void zz_scroll_down(int); +void zz_scroll_up(int); +void zz_setmodes(int); +void zz_setscroll(int, int); +void zz_set_token(int, char *, int); +void zz_start(void); +void zz_write(const char *, int); + +void +zz_setmodes(int new) { if (new & WWM_REV) { if ((tt.tt_modes & WWM_REV) == 0) @@ -80,7 +107,8 @@ zz_setmodes(new) tt.tt_modes = new; } -zz_insline(n) +void +zz_insline(int n) { if (n == 1) ttesc('a'); @@ -90,7 +118,8 @@ zz_insline(n) } } -zz_delline(n) +void +zz_delline(int n) { if (n == 1) ttesc('d'); @@ -100,8 +129,8 @@ zz_delline(n) } } -zz_putc(c) - char c; +void +zz_putc(char c) { if (tt.tt_nmodes != tt.tt_modes) zz_setmodes(tt.tt_nmodes); @@ -110,9 +139,8 @@ zz_putc(c) tt.tt_col = 0, tt.tt_row++; } -zz_write(p, n) - register char *p; - register n; +void +zz_write(const char *p, int n) { if (tt.tt_nmodes != tt.tt_modes) zz_setmodes(tt.tt_nmodes); @@ -122,10 +150,10 @@ zz_write(p, n) tt.tt_col = 0, tt.tt_row++; } -zz_move(row, col) - register row, col; +void +zz_move(int row, int col) { - register x; + int x; if (tt.tt_row == row) { same_row: @@ -218,7 +246,8 @@ out: tt.tt_row = row; } -zz_start() +void +zz_start(void) { ttesc('T'); ttputc(TOKEN_MAX + ' '); @@ -234,7 +263,8 @@ zz_start() zz_setmodes(0); } -zz_reset() +void +zz_reset(void) { zz_setscroll(0, NROW - 1); tt.tt_modes = WWM_REV; @@ -242,7 +272,8 @@ zz_reset() tt.tt_col = tt.tt_row = -10; } -zz_end() +void +zz_end(void) { ttesc('T'); ttputc(' '); @@ -251,23 +282,27 @@ zz_end() zz_ecc = 0; } -zz_clreol() +void +zz_clreol(void) { ttesc('2'); } -zz_clreos() +void +zz_clreos(void) { ttesc('3'); } -zz_clear() +void +zz_clear(void) { ttesc('4'); tt.tt_col = tt.tt_row = 0; } -zz_insspace(n) +void +zz_insspace(int n) { if (n == 1) ttesc('i'); @@ -277,7 +312,8 @@ zz_insspace(n) } } -zz_delchar(n) +void +zz_delchar(int n) { if (n == 1) ttesc('c'); @@ -287,20 +323,22 @@ zz_delchar(n) } } -zz_scroll_down(n) +void +zz_scroll_down(int n) { - if (n == 1) + if (n == 1) { if (tt.tt_row == NROW - 1) ttctrl('j'); else ttesc('f'); - else { + } else { ttesc('F'); ttputc(n + ' '); } } -zz_scroll_up(n) +void +zz_scroll_up(int n) { if (n == 1) ttesc('r'); @@ -310,7 +348,8 @@ zz_scroll_up(n) } } -zz_setscroll(top, bot) +void +zz_setscroll(int top, int bot) { ttesc('?'); ttputc(top + ' '); @@ -321,8 +360,8 @@ zz_setscroll(top, bot) int zz_debug = 0; -zz_set_token(t, s, n) - char *s; +void +zz_set_token(int t, char *s, int n) { if (tt.tt_nmodes != tt.tt_modes) zz_setmodes(tt.tt_nmodes); @@ -340,9 +379,8 @@ zz_set_token(t, s, n) s[n - 1] &= ~0x80; } -/*ARGSUSED*/ -zz_put_token(t, s, n) - char *s; +void +zz_put_token(int t, const char *s __unused, int n __unused) { if (tt.tt_nmodes != tt.tt_modes) zz_setmodes(tt.tt_nmodes); @@ -356,16 +394,16 @@ zz_put_token(t, s, n) ttputc(t + 0x81); } -zz_rint(p, n) - char *p; +int +zz_rint(char *p, int n) { - register i; - register char *q; + int i; + char *q; if (!zz_ecc) return n; for (i = n, q = p; --i >= 0;) { - register c = (unsigned char) *p++; + int c = (unsigned char) *p++; if (zz_lastc == 0) { switch (c) { @@ -412,18 +450,18 @@ zz_rint(p, n) return q - (p - n); } -zz_checksum(p, n) - register char *p; - register n; +void +zz_checksum(char *p, int n) { while (--n >= 0) { - register c = *p++ & 0x7f; + int c = *p++ & 0x7f; c ^= zz_sum; - zz_sum = c << 1 | c >> 11 & 1; + zz_sum = c << 1 | (c >> 11 & 1); } } -zz_compress(flag) +void +zz_compress(int flag) { if (flag) tt.tt_checksum = 0; @@ -431,7 +469,8 @@ zz_compress(flag) tt.tt_checksum = zz_checksum; } -zz_checkpoint() +void +zz_checkpoint(void) { static char x[] = { ctrl('['), 'V', 0, 0 }; @@ -443,7 +482,8 @@ zz_checkpoint() zz_sum = 0; } -tt_zapple() +int +tt_zapple(void) { tt.tt_insspace = zz_insspace; tt.tt_delchar = zz_delchar; diff --git a/usr.bin/window/ttzentec.c b/usr.bin/window/ttzentec.c index 1fce95df25..33d666d88b 100644 --- a/usr.bin/window/ttzentec.c +++ b/usr.bin/window/ttzentec.c @@ -1,3 +1,5 @@ +/* $NetBSD: ttzentec.c,v 1.6 2003/08/07 11:17:33 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,12 +30,17 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)ttzentec.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/ttzentec.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/ttzentec.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ttzentec.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: ttzentec.c,v 1.6 2003/08/07 11:17:33 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" @@ -56,7 +59,8 @@ short zentec_frame[16] = { 'k'|G, 'u'|G, 'w'|G, 'n'|G }; -tt_zentec() +int +tt_zentec(void) { if (tt_generic() < 0) return -1; diff --git a/usr.bin/window/value.h b/usr.bin/window/value.h index 329012f677..99d51c802f 100644 --- a/usr.bin/window/value.h +++ b/usr.bin/window/value.h @@ -1,3 +1,5 @@ +/* $NetBSD: value.h,v 1.6 2008/07/25 06:53:43 gmcgarry Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,8 +32,6 @@ * SUCH DAMAGE. * * @(#)value.h 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/value.h,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/value.h,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ struct value { @@ -52,4 +48,5 @@ struct value { #define V_STR 2 #define V_ERR 3 -#define val_free(v) ((v).v_type == V_STR ? str_free((v).v_str) : 0) +#define val_free(v) (((v).v_type == V_STR && (v).v_str) ? \ + str_free((v).v_str) : (void)0) diff --git a/usr.bin/window/var.c b/usr.bin/window/var.c index 1c30fda431..74cd3422b9 100644 --- a/usr.bin/window/var.c +++ b/usr.bin/window/var.c @@ -1,3 +1,5 @@ +/* $NetBSD: var.c,v 1.10 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,26 +30,30 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)var.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/var.c,v 1.2.6.2 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/var.c,v 1.3 2005/02/28 13:57:05 joerg Exp $ */ -#include +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)var.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: var.c,v 1.10 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ +#include +#include #include "value.h" +#define EXTERN #include "var.h" -#include "mystring.h" +#undef EXTERN +#include "window_string.h" struct var * -var_set1(head, name, v) -struct var **head; -char *name; -struct value *v; +var_set1(struct var **head, const char *name, struct value *v) { - register struct var **p; - register struct var *r; + struct var **p; + struct var *r; struct value val; /* do this first, easier to recover */ @@ -81,10 +83,7 @@ struct value *v; } struct var * -var_setstr1(head, name, str) -struct var **head; -char *name; -char *str; +var_setstr1(struct var **head, const char *name, char *str) { struct value v; @@ -94,10 +93,7 @@ char *str; } struct var * -var_setnum1(head, name, num) -struct var **head; -char *name; -int num; +var_setnum1(struct var **head, const char *name, int num) { struct value v; @@ -106,12 +102,11 @@ int num; return var_set1(head, name, &v); } -var_unset1(head, name) -struct var **head; -char *name; +int +var_unset1(struct var **head, const char *name) { - register struct var **p; - register struct var *r; + struct var **p; + struct var *r; if (*(p = var_lookup1(head, name)) == 0) return -1; @@ -127,11 +122,9 @@ char *name; } struct var ** -var_lookup1(p, name) -register struct var **p; -register char *name; +var_lookup1(struct var **p, const char *name) { - register cmp; + int cmp; while (*p != 0) { if ((cmp = strcmp(name, (*p)->r_name)) < 0) @@ -144,10 +137,8 @@ register char *name; return p; } -var_walk1(r, func, a) -register struct var *r; -int (*func)(); -long a; +int +var_walk1(struct var *r, int (*func) (void *, struct var *), void *a) { if (r == 0) return 0; diff --git a/usr.bin/window/var.h b/usr.bin/window/var.h index 8106a9fd14..7e7bad8842 100644 --- a/usr.bin/window/var.h +++ b/usr.bin/window/var.h @@ -1,3 +1,5 @@ +/* $NetBSD: var.h,v 1.8 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,10 +32,12 @@ * SUCH DAMAGE. * * @(#)var.h 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/var.h,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/var.h,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#ifndef EXTERN +#define EXTERN extern +#endif + struct var { struct var *r_left; struct var *r_right; @@ -45,10 +45,13 @@ struct var { struct value r_val; }; -struct var *var_set1(); -struct var *var_setstr1(); -struct var *var_setnum1(); -struct var **var_lookup1(); +struct var **var_lookup1(struct var **, const char *); +struct var *var_set1(struct var **, const char *, struct value *); +struct var *var_setnum1(struct var **, const char *, int); +struct var *var_setstr1(struct var **, const char *, char *); +int var_unset1(struct var **, const char *); +int var_walk1(struct var *, int (*func)(void *, struct var *), + void *); #define var_set(n, v) var_set1(&var_head, n, v) #define var_setstr(n, s) var_setstr1(&var_head, n, s) @@ -57,4 +60,4 @@ struct var **var_lookup1(); #define var_lookup(n) (*var_lookup1(&var_head, n)) #define var_walk(f, a) var_walk1(var_head, f, a) -struct var *var_head; /* secret, shhh */ +EXTERN struct var *var_head; /* secret, shhh */ diff --git a/usr.bin/window/win.c b/usr.bin/window/win.c index 68580b74f8..ed0efff5a8 100644 --- a/usr.bin/window/win.c +++ b/usr.bin/window/win.c @@ -1,3 +1,5 @@ +/* $NetBSD: win.c,v 1.14 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,14 +30,21 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)win.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/win.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/win.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)win.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: win.c,v 1.14 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + +#include #include "defs.h" #include "char.h" +#include "window_string.h" /* * Higher level routines for dealing with windows. @@ -61,12 +66,9 @@ * Open a user window. */ struct ww * -openwin(id, row, col, nrow, ncol, nline, label, haspty, hasframe, shf, sh) -char *label; -char haspty, hasframe; -char *shf, **sh; +openwin(int id, int row, int col, int nrow, int ncol, int nline, char *label, int type, int uflags, char *shf, char **sh) { - register struct ww *w; + struct ww *w; if (id < 0 && (id = findid()) < 0) return 0; @@ -75,14 +77,15 @@ char *shf, **sh; error("Illegal window position."); return 0; } - w = wwopen(haspty ? WWO_PTY : WWO_SOCKET, nrow, ncol, row, col, nline); + w = wwopen(type, 0, nrow, ncol, row, col, nline); if (w == 0) { error("Can't open window: %s.", wwerror()); return 0; } w->ww_id = id; window[id] = w; - w->ww_hasframe = hasframe; + CLR(w->ww_uflags, WWU_ALLFLAGS); + SET(w->ww_uflags, uflags); w->ww_alt = w->ww_w; if (label != 0 && setlabel(w, label) < 0) error("No memory for label."); @@ -92,7 +95,7 @@ char *shf, **sh; * addwin() puts w at the top, so we don't waste an * insert and delete operation. */ - setselwin(NULL); + setselwin((struct ww *)0); addwin(w, 0); setselwin(w); if (wwspawn(w, shf, sh) < 0) { @@ -103,9 +106,10 @@ char *shf, **sh; return w; } -findid() +int +findid(void) { - register i; + int i; for (i = 0; i < NWINDOW && window[i] != 0; i++) ; @@ -117,15 +121,15 @@ findid() } struct ww * -findselwin() +findselwin(void) { - register struct ww *w, *s = 0; - register i; + struct ww *w, *s = 0; + int i; for (i = 0; i < NWINDOW; i++) if ((w = window[i]) != 0 && w != selwin && (s == 0 || - !isfg(w) && (w->ww_order < s->ww_order || isfg(s)))) + (!isfg(w) && (w->ww_order < s->ww_order || isfg(s))))) s = w; return s; } @@ -133,11 +137,11 @@ findselwin() /* * Close a user window. Close all if w == 0. */ -closewin(w) -register struct ww *w; +void +closewin(struct ww *w) { char didit = 0; - register i; + int i; if (w != 0) { closewin1(w); @@ -150,14 +154,15 @@ register struct ww *w; didit++; } if (didit) { - if (selwin == 0) + if (selwin == 0) { if (lastselwin != 0) { setselwin(lastselwin); lastselwin = 0; - } else if (w = findselwin()) + } else if ((w = findselwin())) setselwin(w); + } if (lastselwin == 0 && selwin) - if (w = findselwin()) + if ((w = findselwin())) lastselwin = w; reframe(); } @@ -167,20 +172,15 @@ register struct ww *w; * Open an information (display) window. */ struct ww * -openiwin(nrow, label) -char *label; +openiwin(int nrow, const char *label) { - register struct ww *w; + struct ww *w; - if ((w = wwopen(0, nrow, wwncol, 2, 0, 0)) == 0) + if ((w = wwopen(WWT_INTERNAL, 0, nrow, wwncol, 2, 0, 0)) == 0) return 0; - w->ww_mapnl = 1; - w->ww_hasframe = 1; - w->ww_nointr = 1; - w->ww_noupdate = 1; - w->ww_unctrl = 1; + SET(w->ww_wflags, WWW_MAPNL | WWW_NOINTR | WWW_NOUPDATE | WWW_UNCTRL); + SET(w->ww_uflags, WWU_HASFRAME | WWU_CENTER); w->ww_id = -1; - w->ww_center = 1; (void) setlabel(w, label); addwin(w, 1); reframe(); @@ -190,15 +190,15 @@ char *label; /* * Close an information window. */ -closeiwin(w) -struct ww *w; +void +closeiwin(struct ww *w) { closewin1(w); reframe(); } -closewin1(w) -register struct ww *w; +void +closewin1(struct ww *w) { if (w == selwin) selwin = 0; @@ -219,9 +219,8 @@ register struct ww *w; * But anything to make it faster. * Always reframe() if doreframe is true. */ -front(w, doreframe) -register struct ww *w; -char doreframe; +void +front(struct ww *w, char doreframe) { if (w->ww_back != (isfg(w) ? framewin : fgwin) && !wwvisible(w)) { deletewin(w); @@ -236,9 +235,8 @@ char doreframe; * Add a window at the top of normal windows or foreground windows. * For normal windows, we put it behind the current window. */ -addwin(w, fg) -register struct ww *w; -char fg; +void +addwin(struct ww *w, char fg) { if (fg) { wwadd(w, framewin); @@ -252,32 +250,33 @@ char fg; /* * Delete a window. */ -deletewin(w) -register struct ww *w; +void +deletewin(struct ww *w) { if (fgwin == w) fgwin = w->ww_back; wwdelete(w); } -reframe() +void +reframe(void) { - register struct ww *w; + struct ww *w; wwunframe(framewin); for (w = wwhead.ww_back; w != &wwhead; w = w->ww_back) - if (w->ww_hasframe) { + if (ISSET(w->ww_uflags, WWU_HASFRAME)) { wwframe(w, framewin); labelwin(w); } } -labelwin(w) -register struct ww *w; +void +labelwin(struct ww *w) { int mode = w == selwin ? WWM_REV : 0; - if (!w->ww_hasframe) + if (!ISSET(w->ww_uflags, WWU_HASFRAME)) return; if (w->ww_id >= 0) { char buf[2]; @@ -289,7 +288,7 @@ register struct ww *w; if (w->ww_label) { int col; - if (w->ww_center) { + if (ISSET(w->ww_uflags, WWU_CENTER)) { col = (w->ww_w.nc - strlen(w->ww_label)) / 2; col = MAX(3, col); } else @@ -298,26 +297,27 @@ register struct ww *w; } } -stopwin(w) - register struct ww *w; +void +stopwin(struct ww *w) { - if (w->ww_pty >= 0 && w->ww_ispty && wwstoptty(w->ww_pty) < 0) + if (w->ww_pty >= 0 && w->ww_type == WWT_PTY && wwstoptty(w->ww_pty) < 0) error("Can't stop output: %s.", wwerror()); else - w->ww_stopped = 1; + SET(w->ww_pflags, WWP_STOPPED); } -startwin(w) - register struct ww *w; +void +startwin(struct ww *w) { - if (w->ww_pty >= 0 && w->ww_ispty && wwstarttty(w->ww_pty) < 0) + if (w->ww_pty >= 0 && w->ww_type == WWT_PTY && + wwstarttty(w->ww_pty) < 0) error("Can't start output: %s.", wwerror()); else - w->ww_stopped = 0; + CLR(w->ww_pflags, WWP_STOPPED); } -sizewin(w, nrow, ncol) -register struct ww *w; +void +sizewin(struct ww *w, int nrow, int ncol) { struct ww *back = w->ww_back; @@ -330,41 +330,39 @@ register struct ww *w; reframe(); } -waitnl(w) -struct ww *w; +void +waitnl(struct ww *w) { (void) waitnl1(w, "[Type any key to continue]"); } -more(w, always) -register struct ww *w; -char always; +int +more(struct ww *w, char always) { int c; - char uc = w->ww_unctrl; + int uc = ISSET(w->ww_wflags, WWW_UNCTRL); if (!always && w->ww_cur.r < w->ww_w.b - 2) return 0; c = waitnl1(w, "[Type escape to abort, any other key to continue]"); - w->ww_unctrl = 0; + CLR(w->ww_wflags, WWW_UNCTRL); wwputs("\033E", w); - w->ww_unctrl = uc; + SET(w->ww_wflags, uc); return c == ctrl('[') ? 2 : 1; } -waitnl1(w, prompt) -register struct ww *w; -char *prompt; +int +waitnl1(struct ww *w, const char *prompt) { - char uc = w->ww_unctrl; + int uc = ISSET(w->ww_wflags, WWW_UNCTRL); - w->ww_unctrl = 0; + CLR(w->ww_wflags, WWW_UNCTRL); front(w, 0); wwprintf(w, "\033Y%c%c\033sA%s\033rA ", w->ww_w.nr - 1 + ' ', ' ', prompt); /* print on last line */ wwcurtowin(w); while (wwpeekc() < 0) wwiomux(); - w->ww_unctrl = uc; + SET(w->ww_wflags, uc); return wwgetc(); } diff --git a/usr.bin/window/window.1 b/usr.bin/window/window.1 index a4174d059c..3a460f4567 100644 --- a/usr.bin/window/window.1 +++ b/usr.bin/window/window.1 @@ -1,3 +1,5 @@ +.\" $NetBSD: window.1,v 1.16 2009/03/10 21:18:35 joerg Exp $ +.\" .\" Copyright (c) 1985, 1990, 1993 .\" The Regents of the University of California. All rights reserved. .\" @@ -12,11 +14,7 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors +.\" 3. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" @@ -33,8 +31,6 @@ .\" SUCH DAMAGE. .\" .\" @(#)window.1 8.2 (Berkeley) 12/30/93 -.\" $FreeBSD: src/usr.bin/window/window.1,v 1.5.2.6 2002/06/21 15:30:19 charnier Exp $ -.\" $DragonFly: src/usr.bin/window/window.1,v 1.3 2006/02/17 19:39:17 swildner Exp $ .\" .Dd December 30, 1993 .Dt WINDOW 1 @@ -50,20 +46,22 @@ .Op Fl e Ar escape-char .Op Fl c Ar command .Sh DESCRIPTION -The .Nm -utility implements a window environment on +implements a window environment on .Tn ASCII terminals. .Pp A window is a rectangular portion of the physical terminal -screen associated with a set of processes. Its size and -position can be changed by the user at any time. Processes +screen associated with a set of processes. +Its size and position can be changed by the user at any time. +Processes communicate with their window in the same way they normally interact with a terminal\-through their standard input, output, -and diagnostic file descriptors. The window program handles the +and diagnostic file descriptors. +The window program handles the details of redirecting input and output to and from the -windows. At any one time, only one window can receive +windows. +At any one time, only one window can receive input from the keyboard, but all windows can simultaneously send output to the display. .Pp @@ -73,7 +71,8 @@ starts up, the commands (see long commands below) contained in the file .Pa .windowrc in the user's home directory are -executed. If it does not exist, two equal sized windows spanning +executed. +If it does not exist, two equal sized windows spanning the terminal screen are created by default. .Pp The command line options are @@ -83,7 +82,8 @@ Turn on terse mode (see .Ic terse command below). .It Fl f -Fast. Don't perform any startup action. +Fast. +Don't perform any startup action. .It Fl d Ignore .Pa .windowrc @@ -106,30 +106,38 @@ as a long command (see below) before doing anything else. .El .Pp -Windows can overlap and are framed as necessary. Each window -is named by one of the digits ``1'' to ``9''. This one-character +Windows can overlap and are framed as necessary. +Each window +is named by one of the digits +.Dq 1 +to +.Dq 9 . +This one-character identifier, as well as a user definable label string, are displayed -with the window on the top edge of its frame. A window can be -designated to be in the +with the window on the top edge of its frame. +A window can be designated to be in the .Ar foreground , in which case it will always be on top of all normal, non-foreground windows, and can be covered -only by other foreground windows. A window need not be completely -within the edges of the terminal screen. Thus a large window +only by other foreground windows. +A window need not be completely within the edges of the terminal screen. +Thus a large window (possibly larger than the screen) may be positioned to show only a portion of its full size. .Pp -Each window has a cursor and a set of control functions. Most intelligent -terminal operations such as line and -character deletion and insertion are supported. Display modes +Each window has a cursor and a set of control functions. +Most intelligent terminal operations such as line and +character deletion and insertion are supported. +Display modes such as underlining and reverse video are available if they are -supported by the terminal. In addition, -similar to terminals with multiple pages of memory, +supported by the terminal. +In addition, similar to terminals with multiple pages of memory, each window has a text buffer which can have more lines than the window itself. .Ss Process Environment With each newly created window, a shell program is spawned with its -process environment tailored to that window. Its standard input, +process environment tailored to that window. +Its standard input, output, and diagnostic file descriptors are bound to one end of either a pseudo-terminal (see .Xr pty 4 ) @@ -141,7 +149,8 @@ If a pseudo-terminal is used, then its special characters and modes (see .Xr stty 1 ) are copied from the physical -terminal. A +terminal. +A .Xr termcap 5 entry tailored to this window is created and passed as environment (see @@ -152,9 +161,11 @@ The termcap entry contains the window's size and characteristics as well as information from the physical terminal, such as the existence of underline, reverse video, and other display modes, and the codes produced by the terminal's function keys, -if any. In addition, the window size attributes of the pseudo-terminal +if any. +In addition, the window size attributes of the pseudo-terminal are set to reflect the size of this window, and updated whenever -it is changed by the user. In particular, the editor +it is changed by the user. +In particular, the editor .Xr vi 1 uses this information to redraw its display. @@ -162,11 +173,14 @@ this information to redraw its display. During normal execution, .Nm can be in one of two states: -conversation mode and command mode. In conversation mode, the +conversation mode and command mode. +In conversation mode, the terminal's real cursor is placed at the cursor position of a particular window--called the current window--and input from the keyboard is sent -to the process in that window. The current window is always -on top of all other windows, except those in foreground. In addition, +to the process in that window. +The current window is always +on top of all other windows, except those in foreground. +In addition, it is set apart by highlighting its identifier and label in reverse video. .Pp Typing @@ -174,7 +188,8 @@ Typing escape character (normally .Ic ^P ) in conversation -mode switches it into command mode. In command mode, the top line of +mode switches it into command mode. +In command mode, the top line of the terminal screen becomes the command prompt window, and .Nm interprets input from the keyboard as commands to manipulate windows. @@ -189,14 +204,18 @@ below). .Ss Short Commands Below, .Ar \&# -represents one of the digits ``1'' to ``9'' +represents one of the digits +.Dq 1 +to +.Dq 9 corresponding to the windows 1 to 9. .Ic ^X means .No control\- Ns Ar X , where .Ar X -is any character. In particular, +is any character. +In particular, .Ic ^^ is .Li control\-^ . @@ -214,18 +233,18 @@ Select window .Ar # but stay in command mode. .It Ic ^^ -Select the previous window and return to conversation -mode. This is useful for toggling between two windows. +Select the previous window and return to conversation mode. +This is useful for toggling between two windows. .It Ic escape Return to conversation mode. .It Ic ^P Return to conversation mode and write .Ic ^P -to the -current window. Thus, typing two +to the current window. +Thus, typing two .Ic ^P Ns 's -in conversation -mode sends one to the current window. If the +in conversation mode sends one to the current window. +If the .Nm escape is changed to some other character, that character takes the place of @@ -243,24 +262,37 @@ Confirmation is requested. Suspend .Nm . .It Ic w -Create a new window. The user is prompted for the positions +Create a new window. +The user is prompted for the positions of the upper left and lower right corners of the window. -The cursor is placed on the screen and the keys ``h'', ``j'', -``k'', and ``l'' +The cursor is placed on the screen and the keys +.Dq h , +.Dq j , +.Dq k , +and +.Dq l move the cursor left, down, up, and right, respectively. -The keys ``H'', ``J'', ``K'', and ``L'' move the cursor to the respective -limits of the screen. Typing a number before the movement keys -repeats the movement that number of times. Return enters the cursor position -as the upper left corner of the window. The lower right corner -is entered in the same manner. During this process, +The keys +.Dq H , +.Dq J , +.Dq K , +and +.Dq L +move the cursor to the respective limits of the screen. +Typing a number before the movement keys +repeats the movement that number of times. +Return enters the cursor position +as the upper left corner of the window. +The lower right corner is entered in the same manner. +During this process, the placement of the new window is indicated by a rectangular box drawn on the screen, corresponding to where the new window -will be framed. Typing escape at any point -cancels this command. +will be framed. +Typing escape at any point cancels this command. .Pp This window becomes the current window, -and is given the first available ID. The default buffer size -is used (see +and is given the first available ID. +The default buffer size is used (see .Ar default_nline command below). .Pp @@ -271,19 +303,19 @@ Close window The process in the window is sent the hangup signal (see .Xr kill 1 ) . -.Xr Csh 1 +.Xr csh 1 should handle this signal correctly and cause no problems. .It Ic m Ns Ar # Move window .Ar # -to another location. A box in the shape -of the window is drawn on +to another location. +A box in the shape of the window is drawn on the screen to indicate the new position of the window, and the same keys as those for the .Ic w -command are used to position the box. The -window can be moved partially off-screen. +command are used to position the box. +The window can be moved partially off-screen. .It Ic M Ns Ar # Move window .Ar # @@ -292,9 +324,9 @@ to its previous position. Change the size of window .Ar # . The user is prompted -to enter the new lower right corner of the window. A box -is drawn to indicate the new window size. The same -keys used in +to enter the new lower right corner of the window. +A box is drawn to indicate the new window size. +The same keys used in .Ic w and .Ic m @@ -324,17 +356,18 @@ Move the cursor of the current window up by one line. .It Ic l Move the cursor of the current window right by one column. .It Ic y -Yank. The user is prompted to enter two points within the current -window. Then the content of the current window between those two points +Yank. +The user is prompted to enter two points within the current window. +Then the content of the current window between those two points is saved in the yank buffer. .It Ic p -Put. The content of the yank buffer is written to the current -window as input. +Put. +The content of the yank buffer is written to the current window as input. .It Ic ^S Stop output in the current window. .It Ic ^Q Start output in the current window. -.It Ic : +.It Ic \&: Enter a line to be executed as long commands. Normal line editing characters (erase character, erase word, erase line) @@ -343,46 +376,69 @@ are supported. .Ss Long Commands Long commands are a sequence of statements parsed much like a programming language, with a syntax -similar to that of C. Numeric and string expressions and variables +similar to that of C. +Numeric and string expressions and variables are supported, as well as conditional statements. .Pp -There are two data types: string and number. A string is a sequence -of letters or digits beginning with a letter. ``_'' and ``.'' are -considered letters. Alternately, non-alphanumeric characters can -be included in strings by quoting them in ``"'' or escaping them -with ``\\''. In addition, the ``\\'' sequences of C are supported, -both inside and outside quotes (e.g., ``\\n'' is a new line, -``\\r'' a carriage return). For example, these are legal strings: -abcde01234, "&#$^*&#", ab"$#"cd, ab\\$\\#cd, "/usr/ucb/window". +There are two data types: string and number. +A string is a sequence +of letters or digits beginning with a letter. +.Dq _ +and +.Dq \&\. +are considered letters. +Alternatively, non-alphanumeric characters can +be included in strings by quoting them in double +.Pq Dq \&" +quotes or escaping them with backslash +.Pq Dq \e . +In addition, the +.Dq \e +sequences of C are supported, +both inside and outside quotes (e.g., +.Dq \en +is a new line, +.Dq \er +a carriage return). +For example, these are legal strings: +abcde01234, "\*[Am]#$^*\*[Am]#", ab"$#"cd, ab\\$\\#cd, "/usr/ucb/window". .Pp A number is an integer value in one of three forms: -a decimal number, an octal number preceded by ``0'', -or a hexadecimal number preceded by ``0x'' or ``0X''. The natural -machine integer size is used (i.e., the signed integer type -of the C compiler). As in C, a non-zero number represents -a boolean true. +a decimal number, an octal number preceded by +.Dq 0 , +or a hexadecimal number preceded by +.Dq 0x +or +.Dq 0X . +The natural machine integer size is used (i.e., the signed integer type +of the C compiler). +As in C, a non-zero number represents a boolean true. .Pp -The character ``#'' begins a comment which terminates at the +The character +.Dq # +begins a comment which terminates at the end of the line. .Pp -A statement is either a conditional or an expression. Expression -statements are terminated with a new line or ``;''. To continue -an expression on the next line, terminate the first line with ``\\''. +A statement is either a conditional or an expression. +Expression statements are terminated with a new line or +.Dq \&; . +To continue +an expression on the next line, terminate the first line with +.Dq \e . .Ss Conditional Statement -The .Nm -utility has a single control structure: +has a single control structure: the fully bracketed if statement in the form .Pp .Bd -literal -offset indent -compact -if then -\t +if \*[Lt]expr\*[Gt] then +\t\*[Lt]statement\*[Gt] \t... -elsif then -\t +elsif \*[Lt]expr\*[Gt] then +\t\*[Lt]statement\*[Gt] \t... else -\t +\t\*[Lt]statement\*[Gt] \t... endif .Ed @@ -393,22 +449,25 @@ and .Ic elsif parts are optional, and the latter can be repeated any number of times. - +\*[Lt]Expr\*[Gt] must be numeric. .Ss Expressions Expressions in .Nm are similar to those in the C language, with most C operators supported on numeric -operands. In addition, some are overloaded to operate on strings. +operands. +In addition, some are overloaded to operate on strings. .Pp When an expression is used as a statement, its value is discarded -after evaluation. Therefore, only expressions with side +after evaluation. +Therefore, only expressions with side effects (assignments and function calls) are useful as statements. .Pp Single valued (no arrays) variables are supported, of both -numeric and string values. Some variables are predefined. They -are listed below. +numeric and string values. +Some variables are predefined. +They are listed below. .Pp The operators in order of increasing precedence: .Bl -tag -width Fl @@ -417,7 +476,8 @@ The operators in order of increasing precedence: .Ic = .Aq Va expr2 .Xc -Assignment. The variable of name +Assignment. +The variable of name .Aq Va expr1 , which must be string valued, is assigned the result of @@ -438,8 +498,8 @@ if evaluates true (non-zero numeric value); returns the value of .Aq Va expr3 -otherwise. Only -one of +otherwise. +Only one of .Aq Va expr2 and .Aq Va expr3 @@ -452,7 +512,9 @@ be numeric. .Ic \&|\&| .Aq Va expr2 .Xc -Logical or. Numeric values only. Short circuit evaluation is supported +Logical or. +Numeric values only. +Short circuit evaluation is supported (i.e., if .Aq Va expr1 evaluates true, then @@ -460,28 +522,32 @@ evaluates true, then is not evaluated). .It Xo .Aq Va expr1 -.Ic \&&\&& +.Ic \&\*[Am]\&\*[Am] .Aq Va expr2 .Xc -Logical and with short circuit evaluation. Numeric values only. +Logical and with short circuit evaluation. +Numeric values only. .It Xo .Aq Va expr1 .Ic \&| .Aq Va expr2 .Xc -Bitwise or. Numeric values only. +Bitwise or. +Numeric values only. .It Xo .Aq Va expr1 .Ic ^ .Aq Va expr2 .Xc -Bitwise exclusive or. Numeric values only. +Bitwise exclusive or. +Numeric values only. .It Xo .Aq Va expr1 -.Ic \&& +.Ic \&\*[Am] .Aq Va expr2 .Xc -Bitwise and. Numeric values only. +Bitwise and. +Numeric values only. .It Xo .Aq Va expr1 .Ic == @@ -490,30 +556,32 @@ Bitwise and. Numeric values only. .Ic != .Aq expr2 .Xc -Comparison (equal and not equal, respectively). The boolean -result (either 1 or 0) of the comparison is returned. The -operands can be numeric or string valued. One string operand +Comparison (equal and not equal, respectively). +The boolean result (either 1 or 0) of the comparison is returned. +The operands can be numeric or string valued. +One string operand forces the other to be converted to a string in necessary. .It Xo .Aq Va expr1 -.Ic < +.Ic \*[Lt] .Aq Va expr2 , .Aq Va expr1 -.Ic > +.Ic \*[Gt] .Aq Va expr2 , .Aq Va expr1 -.Ic <= +.Ic \*[Le] .Aq Va expr2 , .Xc Less than, greater than, less than or equal to, -greater than or equal to. Both numeric and string values, with +greater than or equal to. +Both numeric and string values, with automatic conversion as above. .It Xo .Aq Va expr1 -.Ic << +.Ic \*[Lt]\*[Lt] .Aq Va expr2 , .Aq Va expr1 -.Ic >> +.Ic \*[Gt]\*[Gt] .Aq Va expr2 .Xc If both operands are numbers, @@ -521,7 +589,8 @@ If both operands are numbers, is bit shifted left (or right) by .Aq Va expr2 -bits. If +bits. +If .Aq Va expr1 is a string, then its first (or last) @@ -539,7 +608,10 @@ in place of its value). .Ic - .Aq Va expr2 .Xc -Addition and subtraction on numbers. For ``+'', if one +Addition and subtraction on numbers. +For +.Dq + , +if one argument is a string, then the other is converted to a string, and the result is the concatenation of the two strings. .It Xo @@ -553,7 +625,8 @@ and the result is the concatenation of the two strings. .Ic \&% .Aq Va expr2 .Xc -Multiplication, division, modulo. Numbers only. +Multiplication, division, modulo. +Numbers only. .It Xo .Ic \- Ns Aq Va expr , .Ic ~ Ns Aq Va expr , @@ -562,16 +635,21 @@ Multiplication, division, modulo. Numbers only. .Ic \&$? Ns Aq Va expr .Xc The first three are unary minus, bitwise complement and logical complement -on numbers only. The operator, ``$'', takes +on numbers only. +The operator, +.Dq $ , +takes .Aq Va expr and returns -the value of the variable of that name. If +the value of the variable of that name. +If .Aq Va expr is numeric with value .Ar n and it appears within an alias macro (see below), -then it refers to the nth argument of the alias invocation. ``$?'' +then it refers to the nth argument of the alias invocation. +.Dq $? tests for the existence of the variable .Aq Va expr , and returns 1 @@ -585,42 +663,49 @@ must be a string that is the unique prefix of the name of a builtin .Nm function -or the full name of a user defined alias macro. In the case of a builtin -function, +or the full name of a user defined alias macro. +In the case of a builtin function, .Aq Ar arglist can be in one of two forms: .Bd -literal -offset indent -, , ... -argname1 = , argname2 = , ... +\*[Lt]expr1\*[Gt], \*[Lt]expr2\*[Gt], ... +argname1 = \*[Lt]expr1\*[Gt], argname2 = \*[Lt]expr2\*[Gt], ... .Ed .Pp The two forms can in fact be intermixed, but the result is -unpredictable. Most arguments can be omitted; default values will -be supplied for them. The +unpredictable. +Most arguments can be omitted; default values will +be supplied for them. +The .Ar argnames can be unique prefixes -of the argument names. The commas separating +of the argument names. +The commas separating arguments are used only to disambiguate, and can usually be omitted. .Pp -Only the first argument form is valid for user defined aliases. Aliases -are defined using the +Only the first argument form is valid for user defined aliases. +Aliases are defined using the .Ic alias -builtin function (see below). Arguments -are accessed via a variant of the variable mechanism (see ``$'' operator -above). +builtin function (see below). +Arguments +are accessed via a variant of the variable mechanism (see +.Dq $ +operator above). .Pp Most functions return value, but some are used for side effect -only and so must be used as statements. When a function or an alias is used +only and so must be used as statements. +When a function or an alias is used as a statement, the parentheses surrounding -the argument list may be omitted. Aliases return no value. +the argument list may be omitted. +Aliases return no value. .El .Ss Builtin Functions -The arguments are listed by name in their natural -order. Optional arguments are in square brackets +The arguments are listed by name in their natural order. +Optional arguments are in square brackets .Sq Op . Arguments that have no names are in angle brackets -.Sq <> . +.Sq \*[Lt]\*[Gt] . An argument meant to be a boolean flag (often named .Ar flag ) can be one of @@ -635,19 +720,21 @@ with obvious meanings, or it can be a numeric expression, in which case a non-zero value is true. .Bl -tag -width Fl -.It Ic alias Ns Po -.Bq Aq Ar string , -.Bq Aq Ar string\-list -.Pc +.It Xo +.Ic alias Ns Po Bq Aq Ar string , +.Bq Aq Ar string\-list Pc +.Xc If no argument is given, all currently defined alias macros are -listed. Otherwise, +listed. +Otherwise, .Aq Ar string is defined as an alias, with expansion -.Aq Ar string\-list > . +.Aq Ar string\-list \*[Gt] . The previous definition of .Aq Ar string , -if any, is returned. Default for +if any, is returned. +Default for .Aq Ar string\-list is no change. .It Ic close Ns Pq Aq Ar window\-list @@ -657,7 +744,8 @@ If .Aq Ar window\-list is the word .Ar all , -than all windows are closed. No value is returned. +than all windows are closed. +No value is returned. .It Ic cursormodes Ns Pq Bq Ar modes Set the window cursor to .Ar modes . @@ -672,8 +760,9 @@ or of the mode bits defined as the variables (blinking), and .Ar m_grp -(graphics, terminal dependent). Return -value is the previous modes. Default is no change. +(graphics, terminal dependent). +Return value is the previous modes. +Default is no change. For example, .Li cursor($m_rev$m_blk) sets the window cursors to blinking @@ -682,15 +771,17 @@ reverse video. Set the default buffer size to .Ar nline . Initially, it is -48 lines. Returns the old default buffer size. Default is -no change. Using a very large buffer can slow the program down -considerably. +48 lines. +Returns the old default buffer size. +Default is no change. +Using a very large buffer can slow the program down considerably. .It Ic default_shell Ns Pq Bq Aq Ar string\-list Set the default window shell program to .Aq Ar string\-list . Returns -the first string in the old shell setting. Default is no change. Initially, -the default shell is taken from the environment variable +the first string in the old shell setting. +Default is no change. +Initially, the default shell is taken from the environment variable .Ev SHELL . .It Ic default_smooth Ns Pq Bq Ar flag Set the default value of the @@ -698,8 +789,8 @@ Set the default value of the argument to the command .Nm -(see below). The argument -is a boolean flag (one of +(see below). +The argument is a boolean flag (one of .Ar on , .Ar off , .Ar yes , @@ -707,7 +798,8 @@ is a boolean flag (one of .Ar true , .Ar false , or a number, -as described above). Default is no change. +as described above). +Default is no change. The old value (as a number) is returned. The initial value is 1 (true). .It Xo @@ -719,18 +811,20 @@ Write the list of strings, to .Nm , separated -by spaces and terminated with a new line. The strings are only +by spaces and terminated with a new line. +The strings are only displayed in the window, the processes in the window are not involved (see .Ic write -below). No value is returned. Default -is the current window. +below). +No value is returned. +Default is the current window. .It Ic escape Ns Pq Bq Ar escapec Set the escape character to .Ar escape-char . Returns the old -escape character as a one-character string. Default is no -change. +escape character as a one-character string. +Default is no change. .Ar Escapec can be a string of a single character, or in the form @@ -745,8 +839,9 @@ Move .Nm in or out of foreground. .Ar Flag -is a boolean value. The old foreground flag -is returned. Default for +is a boolean value. +The old foreground flag is returned. +Default for .Nm is the current window, default for @@ -761,21 +856,24 @@ Set the label of to .Ar label . Returns the old -label as a string. Default for +label as a string. +Default for .Nm is the current window, default for .Ar label -is no change. To turn -off a label, set it to an empty string (""). +is no change. +To turn off a label, set it to an empty string (""). .It Ic list Ns Pq -No arguments. List the identifiers and labels of all windows. No -value is returned. +No arguments. +List the identifiers and labels of all windows. +No value is returned. .It Ic select Ns Pq Bq Ar window Make .Nm -the current window. The previous current window -is returned. Default is no change. +the current window. +The previous current window is returned. +Default is no change. .It Ic source Ns Pq Ar filename Read and execute the long commands in .Ar filename . @@ -790,7 +888,8 @@ sounding the terminal's bell. can take on the same values as in .Ar foreground -above. Returns the old terse flag. +above. +Returns the old terse flag. Default is no change. .It Ic unalias Ns Pq Ar alias Undefine @@ -807,7 +906,9 @@ Returns -1 if does not exist, 0 otherwise. .It Ic variables Ns Pq -No arguments. List all variables. No value is returned. +No arguments. +List all variables. +No value is returned. .It Xo .Ic window Ns ( Bq Ar row , .Bq Ar column , @@ -831,8 +932,9 @@ and size If .Ar nline is specified, -then that many lines are allocated for the text buffer. Otherwise, -the default buffer size is used. Default values for +then that many lines are allocated for the text buffer. +Otherwise, the default buffer size is used. +Default values for .Ar row , .Ar column , .Ar nrow , @@ -856,10 +958,11 @@ allocate pseudo-terminal for this window rather than socketpair (default true), and map new line characters in this window to carriage return and line feed (default true if socketpair is used, false otherwise). Normally, a window is automatically closed when its process -exits. Setting +exits. +Setting .Ar keepopen -to true (default false) prevents this -action. When +to true (default false) prevents this action. +When .Ar smooth is true, the screen is updated more frequently (for this window) to produce a more terminal-like behavior. @@ -873,8 +976,8 @@ is a list of strings that will be used as the shell program to place in the window (default is the program specified by .Ar default_shell , -see above). The created window's identifier -is returned as a number. +see above). +The created window's identifier is returned as a number. .It Xo .Ic write Ns ( Bq Ar window , .Bq Aq Ar string\-list ) @@ -884,20 +987,22 @@ Send the list of strings, to .Nm , separated -by spaces but not terminated with a new line. The strings are actually -given to the window as input. No value is returned. Default -is the current window. +by spaces but not terminated with a new line. +The strings are actually given to the window as input. +No value is returned. +Default is the current window. .El .Ss Predefined Variables -These variables are for information only. Redefining them does -not affect the internal operation of +These variables are for information only. +Redefining them does not affect the internal operation of .Nm . .Bl -tag -width modes .It Ar baud The baud rate as a number between 50 and 38400. .It Ar modes The display modes (reverse video, underline, blinking, graphics) -supported by the physical terminal. The value of +supported by the physical terminal. +The value of .Ar modes is the bitwise or of some of the one bit values, .Ar m_blk , @@ -923,15 +1028,14 @@ The number of columns on the physical screen. .It Ar nrow The number of rows on the physical screen. .It Ar term -The terminal type. The standard name, found in the second name -field of the terminal's +The terminal type. +The standard name, found in the second name field of the terminal's .Ev TERMCAP entry, is used. .El .Sh ENVIRONMENT -The .Nm -utility utilizes these environment variables: +uses these environment variables: .Ev HOME , .Ev SHELL , .Ev TERM , diff --git a/usr.bin/window/wwend.c b/usr.bin/window/window_string.h similarity index 64% copy from usr.bin/window/wwend.c copy to usr.bin/window/window_string.h index 2aec04efc6..493580fa8a 100644 --- a/usr.bin/window/wwend.c +++ b/usr.bin/window/window_string.h @@ -1,3 +1,5 @@ +/* $NetBSD: window_string.h,v 1.8 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,36 +31,45 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)wwend.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwend.c,v 1.2.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwend.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ + * @(#)string.h 8.1 (Berkeley) 6/6/93 */ -#include -#include +#ifndef _W_STRING_H_ +#define _W_STRING_H_ + +#include + +#ifndef EXTERN +#define EXTERN extern +#endif + +#define STR_DEBUG + +char *str_cat(const char *, const char *); +char *str_cpy(const char *); +char *str_itoa(int); +int str_match(const char *, const char *, int); +char *str_ncpy(const char *, int); + +#define str_cmp(a, b) strcmp(a, b) + +#ifdef STR_DEBUG +struct string { + struct string *s_forw; + struct string *s_back; + char s_data[1]; +}; + +EXTERN struct string str_head; -#include "ww.h" -#include "tt.h" +#define str_offset ((unsigned)str_head.s_data - (unsigned)&str_head) +#define str_stos(s) ((struct string *)((unsigned)(s) - str_offset)) -/*ARGSUSED*/ -wwend(exit) -{ - if (tt.tt_checkpoint) { - (void) alarm(0); - wwdocheckpoint = 0; - } - xxend(); - (void) signal(SIGIO, SIG_DFL); - (void) wwsettty(0, &wwoldtty); -#ifdef TERMINFO - if (exit) - wwterminfoend(); +char *str_alloc(size_t); +void str_free(char *); +#else +#define str_free(s) free(s) +#define str_alloc(s) malloc(s) #endif -} -void -wwquit() -{ - wwend(1); - exit(1); -} +#endif /* _W_STRING_H_ */ diff --git a/usr.bin/window/windowrc b/usr.bin/window/windowrc index 57c695a722..e18e01748b 100644 --- a/usr.bin/window/windowrc +++ b/usr.bin/window/windowrc @@ -1,3 +1,5 @@ +# $NetBSD: windowrc,v 1.3 1999/02/15 04:54:37 hubertf Exp $ + # Copyright (c) 1983, 1993 # The Regents of the University of California. All rights reserved. # @@ -29,6 +31,7 @@ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # +# $NetBSD: windowrc,v 1.3 1999/02/15 04:54:37 hubertf Exp $ # @(#)windowrc 8.1 (Berkeley) 6/6/93 # diff --git a/usr.bin/window/ww.h b/usr.bin/window/ww.h index 65c213c875..8bcbd25c85 100644 --- a/usr.bin/window/ww.h +++ b/usr.bin/window/ww.h @@ -1,3 +1,5 @@ +/* $NetBSD: ww.h,v 1.18 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,20 +32,33 @@ * SUCH DAMAGE. * * @(#)ww.h 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/ww.h,v 1.3.12.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/ww.h,v 1.4 2004/09/03 20:38:01 dillon Exp $ */ +#ifndef __WW_H__ +#define __WW_H__ + +#include #ifdef OLD_TTY #include #else #include #endif #include -#include +#include +#include +#include + +#ifndef EXTERN +#define EXTERN extern +#endif #define NWW 30 /* maximum number of windows */ +/* Macros to clear/set/test flags. */ +#define SET(t, f) (t) |= (f) +#define CLR(t, f) (t) &= ~(f) +#define ISSET(t, f) ((t) & (f)) + /* a rectangle */ struct ww_dim { int nr; /* number of rows */ @@ -64,15 +75,25 @@ struct ww_pos { /* the window structure */ struct ww { + int ww_flags; + /* general flags and states */ - char ww_state; /* state of window */ - char ww_oflags; /* wwopen flags */ + int ww_state; /* state of window */ +#define WWS_INITIAL 0 /* just opened */ +#define WWS_HASPROC 1 /* has process on pty */ +#define WWS_DEAD 3 /* child died */ +#define ww_oflags ww_flags +#define WWO_REVERSE 0x0001 /* make it all reverse video */ +#define WWO_GLASS 0x0002 /* make it all glass */ +#define WWO_FRAME 0x0004 /* this is a frame window */ +#define WWO_ALLFLAGS 0x0007 /* information for overlap */ struct ww *ww_forw; /* doubly linked list, for overlapping info */ struct ww *ww_back; - char ww_index; /* the window index, for wwindex[] */ - char ww_order; /* the overlapping order */ + unsigned char ww_index; /* the window index, for wwindex[] */ +#define WWX_NOBODY NWW + int ww_order; /* the overlapping order */ /* sizes and positions */ struct ww_dim ww_w; /* window size and pos */ @@ -87,18 +108,23 @@ struct ww { short *ww_nvis; /* how many ww_buf chars are visible per row */ /* information for wwwrite() and company */ - char ww_wstate; /* state for outputting characters */ + int ww_wstate; /* state for outputting characters */ char ww_modes; /* current display modes */ - char ww_insert; /* insert mode */ - char ww_mapnl; /* map \n to \r\n */ - char ww_noupdate; /* don't do updates in wwwrite() */ - char ww_unctrl; /* expand control characters */ - char ww_nointr; /* wwwrite() not interruptable */ - char ww_hascursor; /* has fake cursor */ +#define ww_wflags ww_flags +#define WWW_INSERT 0x0008 /* insert mode */ +#define WWW_MAPNL 0x0010 /* map \n to \r\n */ +#define WWW_NOUPDATE 0x0020 /* don't do updates in wwwrite() */ +#define WWW_UNCTRL 0x0040 /* expand control characters */ +#define WWW_NOINTR 0x0080 /* wwwrite() not interruptable */ +#define WWW_HASCURSOR 0x0100 /* has fake cursor */ /* things for the window process and io */ - char ww_ispty; /* ww_pty is really a pty, not socket pair */ - char ww_stopped; /* output stopped */ + int ww_type; +#define WWT_PTY 0 /* pty */ +#define WWT_SOCKET 1 /* socket pair */ +#define WWT_INTERNAL 2 +#define ww_pflags ww_flags +#define WWP_STOPPED 0x0200 /* output stopped */ int ww_pty; /* file descriptor of pty or socket pair */ int ww_socket; /* other end of socket pair */ int ww_pid; /* pid of process, if WWS_HASPROC true */ @@ -109,10 +135,12 @@ struct ww { char *ww_obq; /* current write position in ww_ob */ /* things for the user, they really don't belong here */ - char ww_id; /* the user window id */ - char ww_center; /* center the label */ - char ww_hasframe; /* frame it */ - char ww_keepopen; /* keep it open after the process dies */ + int ww_id; /* the user window id */ +#define ww_uflags ww_flags +#define WWU_CENTER 0x0400 /* center the label */ +#define WWU_HASFRAME 0x0800 /* frame it */ +#define WWU_KEEPOPEN 0x1000 /* keep it open after the process dies */ +#define WWU_ALLFLAGS 0x1c00 char *ww_label; /* the user supplied label */ struct ww_dim ww_alt; /* alternate position and size */ }; @@ -128,7 +156,6 @@ struct ww_tty { #else struct termios ww_termios; #endif - int ww_fflags; }; union ww_char { @@ -168,11 +195,6 @@ struct ww_update { #define WWM_USR 0x20 /* user specified mode */ #define WWM_GLS 0x40 /* window only, glass, i.e., transparent */ - /* ww_state values */ -#define WWS_INITIAL 0 /* just opened */ -#define WWS_HASPROC 1 /* has process on pty */ -#define WWS_DEAD 3 /* child died */ - /* flags for ww_fmap */ #define WWF_U 0x01 #define WWF_R 0x02 @@ -182,16 +204,6 @@ struct ww_update { #define WWF_LABEL 0x40 #define WWF_TOP 0x80 - /* flags to wwopen() */ -#define WWO_PTY 0x01 /* want pty */ -#define WWO_SOCKET 0x02 /* want socket pair */ -#define WWO_REVERSE 0x04 /* make it all reverse video */ -#define WWO_GLASS 0x08 /* make it all glass */ -#define WWO_FRAME 0x10 /* this is a frame window */ - - /* special ww_index value */ -#define WWX_NOBODY NWW - /* error codes */ #define WWE_NOERR 0 #define WWE_SYS 1 /* system error */ @@ -206,44 +218,44 @@ struct ww_update { #define WWU_TOUCHED 0x01 /* touched */ /* the window structures */ -struct ww wwhead; -struct ww *wwindex[NWW + 1]; /* last location is for wwnobody */ -struct ww wwnobody; +EXTERN struct ww wwhead; +EXTERN struct ww *wwindex[NWW + 1]; /* last location is for wwnobody */ +EXTERN struct ww wwnobody; /* tty things */ -struct ww_tty wwoldtty; /* the old (saved) terminal settings */ -struct ww_tty wwnewtty; /* the new (current) terminal settings */ -struct ww_tty wwwintty; /* the terminal settings for windows */ -char *wwterm; /* the terminal name */ -char wwtermcap[1024]; /* place for the termcap */ +EXTERN struct ww_tty wwoldtty; /* the old (saved) terminal settings */ +EXTERN struct ww_tty wwnewtty; /* the new (current) terminal settings */ +EXTERN struct ww_tty wwwintty; /* the terminal settings for windows */ +EXTERN char *wwterm; /* the terminal name */ +EXTERN char wwtermcap[1024]; /* place for the termcap */ /* generally useful variables */ -int wwnrow, wwncol; /* the screen size */ -char wwavailmodes; /* actually supported modes */ -char wwcursormodes; /* the modes for the fake cursor */ -char wwwrap; /* terminal has auto wrap around */ -int wwdtablesize; /* result of getdtablesize() call */ -char **wwsmap; /* the screen map */ -union ww_char **wwos; /* the old (current) screen */ -union ww_char **wwns; /* the new (desired) screen */ -union ww_char **wwcs; /* the checkpointed screen */ -char *wwtouched; /* wwns changed flags */ -struct ww_update *wwupd; /* for display update */ -int wwospeed; /* output baud rate, copied from wwoldtty */ -int wwbaud; /* wwospeed converted into actual number */ -int wwcursorrow, wwcursorcol; /* where we want the cursor to be */ -int wwerrno; /* error number */ +EXTERN int wwnrow, wwncol; /* the screen size */ +EXTERN char wwavailmodes; /* actually supported modes */ +EXTERN char wwcursormodes; /* the modes for the fake cursor */ +EXTERN char wwwrap; /* terminal has auto wrap around */ +EXTERN int wwdtablesize; /* result of getdtablesize() call */ +EXTERN unsigned char **wwsmap; /* the screen map */ +EXTERN union ww_char **wwos; /* the old (current) screen */ +EXTERN union ww_char **wwns; /* the new (desired) screen */ +EXTERN union ww_char **wwcs; /* the checkpointed screen */ +EXTERN char *wwtouched; /* wwns changed flags */ +EXTERN struct ww_update *wwupd; /* for display update */ +EXTERN int wwospeed; /* output baud rate, copied from wwoldtty */ +EXTERN int wwbaud; /* wwospeed converted into actual number */ +EXTERN int wwcursorrow, wwcursorcol; /* where we want the cursor to be */ +EXTERN int wwerrno; /* error number */ /* statistics */ -int wwnflush, wwnwr, wwnwre, wwnwrz, wwnwrc; -int wwnwwr, wwnwwra, wwnwwrc; -int wwntokdef, wwntokuse, wwntokbad, wwntoksave, wwntokc; -int wwnupdate, wwnupdline, wwnupdmiss; -int wwnupdscan, wwnupdclreol, wwnupdclreos, wwnupdclreosmiss, wwnupdclreosline; -int wwnread, wwnreade, wwnreadz; -int wwnreadc, wwnreadack, wwnreadnack, wwnreadstat, wwnreadec; -int wwnwread, wwnwreade, wwnwreadz, wwnwreadd, wwnwreadc, wwnwreadp; -int wwnselect, wwnselecte, wwnselectz; +EXTERN int wwnflush, wwnwr, wwnwre, wwnwrz, wwnwrc; +EXTERN int wwnwwr, wwnwwra, wwnwwrc; +EXTERN int wwntokdef, wwntokuse, wwntokbad, wwntoksave, wwntokc; +EXTERN int wwnupdate, wwnupdline, wwnupdmiss; +EXTERN int wwnupdscan, wwnupdclreol, wwnupdclreos, wwnupdclreosmiss, wwnupdclreosline; +EXTERN int wwnread, wwnreade, wwnreadz; +EXTERN int wwnreadc, wwnreadack, wwnreadnack, wwnreadstat, wwnreadec; +EXTERN int wwnwread, wwnwreade, wwnwreadz, wwnwreadd, wwnwreadc, wwnwreadp; +EXTERN int wwnselect, wwnselecte, wwnselectz; /* quicky macros */ #define wwsetcursor(r,c) (wwcursorrow = (r), wwcursorcol = (c)) @@ -254,28 +266,27 @@ int wwnselect, wwnselecte, wwnselectz; #define wwupdate() wwupdate1(0, wwnrow); /* things for handling input */ -void wwrint(); /* interrupt handler */ -struct ww *wwcurwin; /* window to copy input into */ -char *wwib; /* input (keyboard) buffer */ -char *wwibe; /* wwib + sizeof buffer */ -char *wwibp; /* current read position in buffer */ -char *wwibq; /* current write position in buffer */ -#define wwmaskc(c) ((c) & 0xff) +EXTERN struct ww *wwcurwin; /* window to copy input into */ +EXTERN char *wwib; /* input (keyboard) buffer */ +EXTERN char *wwibe; /* wwib + sizeof buffer */ +EXTERN char *wwibp; /* current read position in buffer */ +EXTERN char *wwibq; /* current write position in buffer */ +#define wwmaskc(c) ((c) & 0x7f) #define wwgetc() (wwibp < wwibq ? wwmaskc(*wwibp++) : -1) #define wwpeekc() (wwibp < wwibq ? wwmaskc(*wwibp) : -1) #define wwungetc(c) (wwibp > wwib ? *--wwibp = (c) : -1) /* things for short circuiting wwiomux() */ -char wwintr; /* interrupting */ -char wwsetjmp; /* want a longjmp() from wwrint() and wwchild() */ -jmp_buf wwjmpbuf; /* jmpbuf for above */ +EXTERN char wwintr; /* interrupting */ +EXTERN char wwsetjmp; /* want a longjmp() from wwrint() and wwchild() */ +EXTERN jmp_buf wwjmpbuf; /* jmpbuf for above */ #define wwinterrupt() wwintr #define wwsetintr() do { wwintr = 1; if (wwsetjmp) longjmp(wwjmpbuf, 1); } \ while (0) #define wwclrintr() (wwintr = 0) /* checkpointing */ -int wwdocheckpoint; +EXTERN int wwdocheckpoint; /* the window virtual terminal */ #define WWT_TERM "window-v2" @@ -293,22 +304,89 @@ int wwdocheckpoint; #define WWT_IMEI "im=\\E@:ei=\\EO:ic=:mi:" /* XXX, ic for emacs bug */ #define WWT_IC "ic=\\EP:" #define WWT_DC "dc=\\EN:" -char wwwintermcap[1024]; /* terminal-specific but window-independent +EXTERN char wwwintermcap[1024]; /* terminal-specific but window-independent part of the window termcap */ #ifdef TERMINFO /* where to put the temporary terminfo directory */ -char wwterminfopath[1024]; +EXTERN char wwterminfopath[1024]; #endif - /* our functions */ -struct ww *wwopen(); -void wwchild(); -void wwalarm(); -void wwquit(); -char **wwalloc(); -char *wwerror(); +struct ww *wwopen(int, int, int, int, int, int, int); +void wwadd(struct ww *, struct ww *); +void wwaddcap(const char *, char **); +void wwaddcap1(const char *, char **); +void wwalarm(int); +char **wwalloc(int, int, int, int, int); +void wwbell(void); +void wwbox(struct ww *, int, int, int, int); +void wwcheckpoint(void); +void wwchild(int); +void wwclose(struct ww *); +void wwclreol1(struct ww *, int, int, char); +void wwclreos(struct ww *, int, int); +void wwcopyscreen(union ww_char **s1, union ww_char **s2); +void wwcursor(struct ww *, int); +void wwdelchar(struct ww *, int, int); +void wwdelete(struct ww *); +void wwdelete1(struct ww *, int, int, int, int); +void wwdelline(struct ww *, int); +void wwdumpns(void); +void wwdumpnvis(struct ww *); +void wwdumpos(void); +void wwdumpsmap(void); +void wwdumpwin(struct ww *); +void wwend(int); +int wwenviron(struct ww *); +const char * + wwerror(void); +void wwflush(void); +void wwframe(struct ww *, struct ww *); +void wwframec(struct ww *, int, int, char); +void wwfree(char **, int); +int wwgetpty(struct ww *); +int wwgettty(int, struct ww_tty *); +int wwgetttysize(int, int *, int *); +void wwgets(char *, int, struct ww *); +int wwinit(void); +void wwinschar(struct ww *, int, int, char, char); +void wwinsline(struct ww *, int); +void wwiomux(void); +void wwlabel(struct ww *, struct ww *, int, char *, int); +void wwmove(struct ww *, int, int); +void wwprintf(struct ww *, const char *, ...) + __attribute__((__format__(__printf__, 2, 3))); +void wwputc(char, struct ww *); +void wwputs(const char *, struct ww *); +void wwredraw(void); +void wwredrawwin1(struct ww *,int, int, int); +void wwquit(int); +void wwreset(void); +void wwrint(void); +void wwscroll(struct ww *, int); +int wwscroll1(struct ww *, int, int, int, int); +void wwsetcursormodes(int); +int wwsettty(int, struct ww_tty *); +int wwsetttysize(int, int, int); +int wwsize(struct ww *, int, int); +int wwspawn(struct ww *, char *, char **); +void wwstart(void); +void wwstart1(void); +int wwstarttty(int); +int wwstoptty(int); +void wwsuspend(void); +void wwunframe(struct ww *); +void wwupdate1(int, int); +int wwvisible(struct ww *); +void wwvprintf(struct ww *, const char *, va_list); +int wwwrite(struct ww *, const char *, int); +#ifdef TERMINFO +int wwterminfoinit(void); +int wwterminfoend(void); +#endif #undef MIN #undef MAX #define MIN(x, y) ((x) > (y) ? (y) : (x)) #define MAX(x, y) ((x) > (y) ? (x) : (y)) + +#endif /* __WW_H__ */ diff --git a/usr.bin/window/wwadd.c b/usr.bin/window/wwadd.c index fbfd4bc4de..d505e7afd9 100644 --- a/usr.bin/window/wwadd.c +++ b/usr.bin/window/wwadd.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwadd.c,v 1.7 2003/08/07 11:17:35 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,23 +30,27 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwadd.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwadd.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwadd.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwadd.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwadd.c,v 1.7 2003/08/07 11:17:35 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" /* * Stick w1 behind w2. */ -wwadd(w1, w2) -register struct ww *w1; -struct ww *w2; +void +wwadd(struct ww *w1, struct ww *w2) { - register i; - register struct ww *w; + int i; + struct ww *w; w1->ww_order = w2->ww_order + 1; w1->ww_back = w2; @@ -59,9 +61,9 @@ struct ww *w2; for (w = w1->ww_forw; w != &wwhead; w = w->ww_forw) w->ww_order++; for (i = w1->ww_i.t; i < w1->ww_i.b; i++) { - register j; - register char *smap = wwsmap[i]; - register char *win = w1->ww_win[i]; + int j; + unsigned char *smap = wwsmap[i]; + char *win = w1->ww_win[i]; union ww_char *ns = wwns[i]; union ww_char *buf = w1->ww_buf[i]; int nvis = 0; diff --git a/usr.bin/window/wwalloc.c b/usr.bin/window/wwalloc.c index 8d862b6b02..09637b9246 100644 --- a/usr.bin/window/wwalloc.c +++ b/usr.bin/window/wwalloc.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwalloc.c,v 1.6 2003/08/07 11:17:36 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,20 +30,25 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwalloc.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwalloc.c,v 1.2.6.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwalloc.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwalloc.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwalloc.c,v 1.6 2003/08/07 11:17:36 agc Exp $"); +#endif +#endif /* not lint */ + #include #include "ww.h" char ** -wwalloc(row, col, nrow, ncol, size) +wwalloc(int row, int col, int nrow, int ncol, int size) { - register char *p, **pp; - register int i; + char *p, **pp; + int i; /* fast, call malloc only once */ pp = (char **) @@ -65,8 +68,8 @@ wwalloc(row, col, nrow, ncol, size) return pp - row; } -wwfree(p, row) -register char **p; +void +wwfree(char **p, int row) { free((char *)(p + row)); } diff --git a/usr.bin/window/wwbox.c b/usr.bin/window/wwbox.c index 7dfcfe6d95..40e7a79282 100644 --- a/usr.bin/window/wwbox.c +++ b/usr.bin/window/wwbox.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwbox.c,v 1.6 2003/08/07 11:17:36 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,22 +30,25 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwbox.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwbox.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwbox.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwbox.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwbox.c,v 1.6 2003/08/07 11:17:36 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" -wwbox(w, r, c, nr, nc) -register struct ww *w; -register r, c; -int nr, nc; +void +wwbox(struct ww *w, int r, int c, int nr, int nc) { - register r1, c1; - register i; + int r1, c1; + int i; r1 = r + nr - 1; c1 = c + nc - 1; diff --git a/usr.bin/window/wwchild.c b/usr.bin/window/wwchild.c index 2079be535d..1e4cee78e2 100644 --- a/usr.bin/window/wwchild.c +++ b/usr.bin/window/wwchild.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwchild.c,v 1.8 2006/12/18 20:04:55 christos Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,30 +30,34 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwchild.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwchild.c,v 1.1.1.1.14.2 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwchild.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ -#include "ww.h" -#include -#include +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwchild.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwchild.c,v 1.8 2006/12/18 20:04:55 christos Exp $"); +#endif +#endif /* not lint */ + #include #include +#include +#include "ww.h" void -wwchild() +wwchild(int dummy __unused) { int olderrno; - register struct ww **wp; - union wait w; + struct ww **wp; + int status; int pid; char collected = 0; olderrno = errno; while ((pid = - wait3((int *)&w, WNOHANG|WUNTRACED, NULL)) > 0) { + wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0)) > 0) { for (wp = wwindex; wp < &wwindex[NWW]; wp++) { if (*wp && (*wp)->ww_state == WWS_HASPROC && (*wp)->ww_pid == pid) { diff --git a/usr.bin/window/wwclose.c b/usr.bin/window/wwclose.c index 08c859f7e7..ac5f25da8e 100644 --- a/usr.bin/window/wwclose.c +++ b/usr.bin/window/wwclose.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwclose.c,v 1.6 2003/08/07 11:17:36 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,16 +30,23 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwclose.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwclose.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwclose.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwclose.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwclose.c,v 1.6 2003/08/07 11:17:36 agc Exp $"); +#endif +#endif /* not lint */ + +#include +#include #include "ww.h" -wwclose(w) -register struct ww *w; +void +wwclose(struct ww *w) { wwindex[w->ww_index] = 0; if (w->ww_pty >= 0) diff --git a/usr.bin/window/wwclreol.c b/usr.bin/window/wwclreol.c index dd7052d898..d9e5a105e7 100644 --- a/usr.bin/window/wwclreol.c +++ b/usr.bin/window/wwclreol.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwclreol.c,v 1.7 2003/08/07 11:17:37 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,12 +30,17 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwclreol.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwclreol.c,v 1.2.12.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwclreol.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwclreol.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwclreol.c,v 1.7 2003/08/07 11:17:37 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" @@ -45,18 +48,16 @@ * Clear w to the end of line. * If cleared is true, then the screen line has already been cleared. */ -wwclreol1(w, row, col, cleared) -register struct ww *w; -int row, col; -char cleared; +void +wwclreol1(struct ww *w, int row, int col, char cleared) { - register i; + int i; /* * Clear the buffer right off */ { - register union ww_char *buf; + union ww_char *buf; buf = &w->ww_buf[row][col]; for (i = w->ww_b.r - col; --i >= 0;) @@ -77,8 +78,9 @@ char cleared; * Now fix wwns. */ { - register union ww_char *s; - register char *smap, *win; + union ww_char *s; + unsigned char *smap; + char *win; i = col; smap = &wwsmap[row][i]; diff --git a/usr.bin/window/wwclreos.c b/usr.bin/window/wwclreos.c index 18027ca51d..c8cb430767 100644 --- a/usr.bin/window/wwclreos.c +++ b/usr.bin/window/wwclreos.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwclreos.c,v 1.7 2003/08/07 11:17:37 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,24 +30,29 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwclreos.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwclreos.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwclreos.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwclreos.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwclreos.c,v 1.7 2003/08/07 11:17:37 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" -wwclreos(w, row, col) -register struct ww *w; +void +wwclreos(struct ww *w, int row, int col) { - register i; + int i; wwclreol(w, row, col); for (i = row + 1; i < w->ww_b.b; i++) wwclreol(w, i, w->ww_b.l); /* XXX */ - if (!w->ww_noupdate) + if (!ISSET(w->ww_wflags, WWW_NOUPDATE)) wwupdate1(w->ww_i.t, w->ww_i.b); } diff --git a/usr.bin/window/wwcursor.c b/usr.bin/window/wwcursor.c index e6f313056a..d68b1d06cd 100644 --- a/usr.bin/window/wwcursor.c +++ b/usr.bin/window/wwcursor.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwcursor.c,v 1.7 2003/08/07 11:17:37 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,27 +30,32 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwcursor.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwcursor.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwcursor.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwcursor.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwcursor.c,v 1.7 2003/08/07 11:17:37 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" -wwcursor(w, on) -register struct ww *w; +void +wwcursor(struct ww *w, int on) { - register char *win; + char *win; if (on) { - if (w->ww_hascursor) + if (ISSET(w->ww_wflags, WWW_HASCURSOR)) return; - w->ww_hascursor = 1; + SET(w->ww_wflags, WWW_HASCURSOR); } else { - if (!w->ww_hascursor) + if (!ISSET(w->ww_wflags, WWW_HASCURSOR)) return; - w->ww_hascursor = 0; + CLR(w->ww_wflags, WWW_HASCURSOR); } if (wwcursormodes != 0) { win = &w->ww_win[w->ww_cur.r][w->ww_cur.c]; @@ -71,18 +74,19 @@ register struct ww *w; } } -wwsetcursormodes(new) -register new; +void +wwsetcursormodes(int new) { - register i; - register struct ww *w; - register old = wwcursormodes; + int i; + struct ww *w; + int old = wwcursormodes; new &= wwavailmodes; if (new == wwcursormodes) return; for (i = 0; i < NWW; i++) - if (wwindex[i] != 0 && (w = wwindex[i])->ww_hascursor) { + if (wwindex[i] != 0 && + ISSET((w = wwindex[i])->ww_wflags, WWW_HASCURSOR)) { wwcursor(w, 0); wwcursormodes = new; wwcursor(w, 1); diff --git a/usr.bin/window/wwdata.c b/usr.bin/window/wwdata.c index a7279452e4..7a3054473f 100644 --- a/usr.bin/window/wwdata.c +++ b/usr.bin/window/wwdata.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwdata.c,v 1.5 2003/08/07 11:17:37 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,9 +30,13 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwdata.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwdata.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwdata.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwdata.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwdata.c,v 1.5 2003/08/07 11:17:37 agc Exp $"); +#endif +#endif /* not lint */ diff --git a/usr.bin/window/wwdelchar.c b/usr.bin/window/wwdelchar.c index 02beb7fa0e..ed70f9d064 100644 --- a/usr.bin/window/wwdelchar.c +++ b/usr.bin/window/wwdelchar.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwdelchar.c,v 1.7 2003/08/07 11:17:38 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,26 +30,32 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwdelchar.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwdelchar.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwdelchar.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwdelchar.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwdelchar.c,v 1.7 2003/08/07 11:17:38 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" +#include "xx.h" -wwdelchar(w, row, col) -register struct ww *w; +void +wwdelchar(struct ww *w, int row, int col) { - register i; + int i; int nvis; /* * First, shift the line. */ { - register union ww_char *p, *q; + union ww_char *p, *q; p = &w->ww_buf[row][col]; q = p + 1; @@ -74,10 +78,10 @@ register struct ww *w; * Now find out how much is actually changed, and fix wwns. */ { - register union ww_char *buf; - register char *win; - register union ww_char *ns; - register char *smap; + union ww_char *buf; + char *win; + union ww_char *ns; + unsigned char *smap; char touched; nvis = 0; @@ -111,7 +115,7 @@ register struct ww *w; * Can/Should we use delete character? */ if (tt.tt_delchar != 0 && nvis > (wwncol - col) / 2) { - register union ww_char *p, *q; + union ww_char *p, *q; xxdelchar(row, col); p = &wwos[row][col]; diff --git a/usr.bin/window/wwdelete.c b/usr.bin/window/wwdelete.c index 3344cb9294..9bdfc5b38b 100644 --- a/usr.bin/window/wwdelete.c +++ b/usr.bin/window/wwdelete.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwdelete.c,v 1.7 2003/08/07 11:17:38 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,27 +30,32 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwdelete.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwdelete.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwdelete.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwdelete.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwdelete.c,v 1.7 2003/08/07 11:17:38 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" /* * Pull w free from the cover list. */ -wwdelete(w) -register struct ww *w; +void +wwdelete(struct ww *w) { - register i; + int i; for (i = w->ww_i.t; i < w->ww_i.b; i++) { - register j; - register char *smap = wwsmap[i]; - register union ww_char *ns = wwns[i]; - register int nchanged = 0; + int j; + unsigned char *smap = wwsmap[i]; + union ww_char *ns = wwns[i]; + int nchanged = 0; for (j = w->ww_i.l; j < w->ww_i.r; j++) if (smap[j] == w->ww_index) { @@ -65,7 +68,7 @@ register struct ww *w; } { - register struct ww *wp; + struct ww *wp; for (wp = w->ww_forw; wp != &wwhead; wp = wp->ww_forw) wp->ww_order--; @@ -80,8 +83,8 @@ register struct ww *w; w->ww_forw = w->ww_back = 0; } -wwdelete1(w, t, b, l, r) -register struct ww *w; +void +wwdelete1(struct ww *w, int t, int b, int l, int r) { int i; int tt, bb, ll, rr; @@ -99,11 +102,11 @@ again: goto again; } for (i = tt; i < bb; i++) { - register j; - register char *smap = wwsmap[i]; - register union ww_char *ns = wwns[i]; - register char *win = w->ww_win[i]; - register union ww_char *buf = w->ww_buf[i]; + int j; + unsigned char *smap = wwsmap[i]; + union ww_char *ns = wwns[i]; + char *win = w->ww_win[i]; + union ww_char *buf = w->ww_buf[i]; int nvis = w->ww_nvis[i]; int nchanged = 0; diff --git a/usr.bin/window/wwdelline.c b/usr.bin/window/wwdelline.c index b1ad1e8c0b..604b000610 100644 --- a/usr.bin/window/wwdelline.c +++ b/usr.bin/window/wwdelline.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwdelline.c,v 1.6 2003/08/07 11:17:38 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,21 +30,25 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwdelline.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwdelline.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwdelline.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwdelline.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwdelline.c,v 1.6 2003/08/07 11:17:38 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" -wwdelline(w, row) -register struct ww *w; -int row; +void +wwdelline(struct ww *w, int row) { - register i; - register union ww_char **cpp, **cqq; - register union ww_char *cp; + int i; + union ww_char **cpp, **cqq; + union ww_char *cp; int row1, row2; char deleted; int visible; diff --git a/usr.bin/window/wwdump.c b/usr.bin/window/wwdump.c index 734f61ced6..c83d5d69cc 100644 --- a/usr.bin/window/wwdump.c +++ b/usr.bin/window/wwdump.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwdump.c,v 1.8 2003/08/07 11:17:38 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,24 +30,28 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwdump.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwdump.c,v 1.2.6.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwdump.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwdump.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwdump.c,v 1.8 2003/08/07 11:17:38 agc Exp $"); +#endif +#endif /* not lint */ + #include #include - #include "ww.h" #include "tt.h" static char cmap[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -wwdumpwin(w) -register struct ww *w; +void +wwdumpwin(struct ww *w) { - register i, j; + int i, j; tt.tt_nmodes = 0; (*tt.tt_clear)(); @@ -60,10 +62,10 @@ register struct ww *w; } } -wwdumpnvis(w) -register struct ww *w; +void +wwdumpnvis(struct ww *w) { - register i; + int i; char buf[20]; tt.tt_nmodes = 0; @@ -75,9 +77,10 @@ register struct ww *w; } } -wwdumpsmap() +void +wwdumpsmap(void) { - register i, j; + int i, j; tt.tt_nmodes = 0; (*tt.tt_clear)(); @@ -88,9 +91,10 @@ wwdumpsmap() } } -wwdumpns() +void +wwdumpns(void) { - register i, j; + int i, j; (*tt.tt_clear)(); for (i = 0; i < wwnrow; i++) { @@ -102,9 +106,10 @@ wwdumpns() } } -wwdumpos() +void +wwdumpos(void) { - register i, j; + int i, j; (*tt.tt_clear)(); for (i = 0; i < wwnrow; i++) { diff --git a/usr.bin/window/wwend.c b/usr.bin/window/wwend.c index 2aec04efc6..82658294de 100644 --- a/usr.bin/window/wwend.c +++ b/usr.bin/window/wwend.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwend.c,v 1.8 2006/12/18 20:04:55 christos Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,36 +30,40 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwend.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwend.c,v 1.2.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwend.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ -#include -#include +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwend.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwend.c,v 1.8 2006/12/18 20:04:55 christos Exp $"); +#endif +#endif /* not lint */ +#include +#include #include "ww.h" #include "tt.h" +#include "xx.h" -/*ARGSUSED*/ -wwend(exit) +void +wwend(int quit __unused) { if (tt.tt_checkpoint) { (void) alarm(0); wwdocheckpoint = 0; } xxend(); - (void) signal(SIGIO, SIG_DFL); (void) wwsettty(0, &wwoldtty); #ifdef TERMINFO - if (exit) + if (quit) wwterminfoend(); #endif } void -wwquit() +wwquit(int dummy __unused) { wwend(1); exit(1); diff --git a/usr.bin/window/wwenviron.c b/usr.bin/window/wwenviron.c index 912366a6a7..18dceae0d6 100644 --- a/usr.bin/window/wwenviron.c +++ b/usr.bin/window/wwenviron.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwenviron.c,v 1.9 2003/08/07 11:17:39 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,37 +30,45 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwenviron.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwenviron.c,v 1.2.6.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwenviron.c,v 1.3 2006/01/12 13:43:11 corecode Exp $ */ -#include - -#include "ww.h" +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwenviron.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwenviron.c,v 1.9 2003/08/07 11:17:39 agc Exp $"); +#endif +#endif /* not lint */ +#include #if !defined(OLD_TTY) && !defined(TIOCSCTTY) && !defined(TIOCNOTTY) #include #endif +#include #include +#include +#include +#include +#include "ww.h" /* * Set up the environment of this process to run in window 'wp'. */ -wwenviron(wp) -register struct ww *wp; +int +wwenviron(struct ww *wp) { - register i; + int i; #ifndef TIOCSCTTY int pgrp = getpid(); #endif char buf[1024]; + sigset_t nsigset; #ifndef TIOCSCTTY if ((i = open("/dev/tty", 0)) < 0) goto bad; - if (ioctl(i, TIOCNOTTY, NULL) < 0) + if (ioctl(i, TIOCNOTTY, (char *)0) < 0) goto bad; (void) close(i); #endif @@ -83,11 +89,12 @@ register struct ww *wp; (void) ioctl(0, TIOCSCTTY, 0); #else (void) ioctl(0, TIOCSPGRP, (char *)&pgrp); - (void) setpgrp(pgrp, pgrp); + (void) setpgid(pgrp, pgrp); #endif /* SIGPIPE is the only one we ignore */ (void) signal(SIGPIPE, SIG_DFL); - (void) sigsetmask(0); + sigemptyset(&nsigset); + sigprocmask(SIG_SETMASK, &nsigset, (sigset_t *)0); /* * Two conditions that make destructive setenv ok: * 1. setenv() copies the string, @@ -95,11 +102,9 @@ register struct ww *wp; */ (void) sprintf(buf, "%sco#%d:li#%d:%s", WWT_TERMCAP, wp->ww_w.nc, wp->ww_w.nr, wwwintermcap); - if (setenv("TERMCAP", buf, 1) == -1) - err(1, "setenv: cannot set TERMCAP=%s", buf); + (void) setenv("TERMCAP", buf, 1); (void) sprintf(buf, "%d", wp->ww_id + 1); - if (setenv("WINDOW_ID", buf, 1) == -1) - err(1, "setenv: cannot set WINDOW_ID=%s", buf); + (void) setenv("WINDOW_ID", buf, 1); return 0; bad: wwerrno = WWE_SYS; diff --git a/usr.bin/window/wwerror.c b/usr.bin/window/wwerror.c index 4bcc12d976..fd505b74b6 100644 --- a/usr.bin/window/wwerror.c +++ b/usr.bin/window/wwerror.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwerror.c,v 1.7 2003/08/07 11:17:39 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,20 +30,24 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwerror.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwerror.c,v 1.1.1.1.14.2 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwerror.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwerror.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwerror.c,v 1.7 2003/08/07 11:17:39 agc Exp $"); +#endif +#endif /* not lint */ + #include +#include #include "ww.h" -char * -wwerror() +const char * +wwerror(void) { - char *strerror(); - switch (wwerrno) { case WWE_NOERR: return "No error"; diff --git a/usr.bin/window/wwflush.c b/usr.bin/window/wwflush.c index 0373e74108..f5c35dc798 100644 --- a/usr.bin/window/wwflush.c +++ b/usr.bin/window/wwflush.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwflush.c,v 1.10 2006/12/18 20:04:55 christos Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,21 +30,28 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwflush.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwflush.c,v 1.2.6.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwflush.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwflush.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwflush.c,v 1.10 2006/12/18 20:04:55 christos Exp $"); +#endif +#endif /* not lint */ + #include #include - +#include #include "ww.h" #include "tt.h" +#include "xx.h" -wwflush() +void +wwflush(void) { - register row, col; + int row, col; if ((row = wwcursorrow) < 0) row = 0; @@ -64,9 +69,14 @@ wwflush() xxflush(1); } -wwcheckpoint() +void +wwcheckpoint(void) { - int s = sigblock(sigmask(SIGALRM) | sigmask(SIGIO)); + sigset_t nsigset, osigset; + + sigemptyset(&nsigset); + sigaddset(&nsigset, SIGALRM); + sigprocmask(SIG_BLOCK, &nsigset, &osigset); tt.tt_ack = 0; do { @@ -76,7 +86,7 @@ wwcheckpoint() #endif (void) alarm(3); for (wwdocheckpoint = 0; !wwdocheckpoint && tt.tt_ack == 0;) - (void) sigpause(s); + sigsuspend(&osigset); } while (tt.tt_ack == 0); (void) alarm(0); wwdocheckpoint = 0; @@ -90,21 +100,22 @@ wwcheckpoint() wwcopyscreen(wwos, wwcs); (void) alarm(3); } - (void) sigsetmask(s); + + sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); } -wwcopyscreen(s1, s2) - register union ww_char **s1, **s2; +void +wwcopyscreen(union ww_char **s1, union ww_char **s2) { - register i; - register s = wwncol * sizeof **s1; + int i; + int s = wwncol * sizeof **s1; for (i = wwnrow; --i >= 0;) - bcopy((char *) *s1++, (char *) *s2++, s); + memmove((char *) *s2++, (char *) *s1++, s); } void -wwalarm() +wwalarm(int dummy __unused) { wwdocheckpoint = 1; } diff --git a/usr.bin/window/wwframe.c b/usr.bin/window/wwframe.c index 15853555d0..a67c71b47f 100644 --- a/usr.bin/window/wwframe.c +++ b/usr.bin/window/wwframe.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwframe.c,v 1.7 2003/08/07 11:17:39 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,33 +30,35 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwframe.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwframe.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwframe.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwframe.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwframe.c,v 1.7 2003/08/07 11:17:39 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" #define frameok(w, r, c) (w1 = wwindex[wwsmap[r][c]], \ w1->ww_fmap || w1->ww_order > (w)->ww_order) -wwframe(w, wframe) -register struct ww *w; -struct ww *wframe; +void +wwframe(struct ww *w, struct ww *wframe) { - register r, c; + int r, c; char a1, a2, a3; char b1, b2, b3; - register char *smap; - register code; - register struct ww *w1; + int code; + struct ww *w1; if (w->ww_w.t > 0) { r = w->ww_w.t - 1; c = w->ww_i.l - 1; - smap = &wwsmap[r + 1][c + 1]; a1 = 0; a2 = 0; b1 = 0; @@ -69,7 +69,7 @@ struct ww *wframe; a3 = 1; b3 = 1; } else { - a3 = w->ww_index == *smap++; + a3 = w->ww_index == wwsmap[r + 1][c + 1]; b3 = frameok(w, r, c + 1); } if (b2) { @@ -93,7 +93,6 @@ struct ww *wframe; if (w->ww_w.b < wwnrow) { r = w->ww_w.b; c = w->ww_i.l - 1; - smap = &wwsmap[r - 1][c + 1]; a1 = 0; a2 = 0; b1 = 0; @@ -104,7 +103,7 @@ struct ww *wframe; a3 = 1; b3 = 1; } else { - a3 = w->ww_index == *smap++; + a3 = w->ww_index == wwsmap[r - 1][c + 1]; b3 = frameok(w, r, c + 1); } if (b2) { @@ -194,13 +193,11 @@ struct ww *wframe; } } -wwframec(f, r, c, code) -register struct ww *f; -register r, c; -char code; +void +wwframec(struct ww *f, int r, int c, char code) { char oldcode; - register char *smap; + unsigned char *smap; if (r < f->ww_i.t || r >= f->ww_i.b || c < f->ww_i.l || c >= f->ww_i.r) return; @@ -208,7 +205,7 @@ char code; smap = &wwsmap[r][c]; { - register struct ww *w; + struct ww *w; w = wwindex[*smap]; if (w->ww_order > f->ww_order) { @@ -219,7 +216,7 @@ char code; } if (f->ww_fmap != 0) { - register char *fmap; + char *fmap; fmap = &f->ww_fmap[r][c]; oldcode = *fmap; @@ -230,14 +227,14 @@ char code; } else oldcode = 0; { - register char *win = &f->ww_win[r][c]; + char *win = &f->ww_win[r][c]; if (*win == WWM_GLS && *smap == f->ww_index) f->ww_nvis[r]++; *win &= ~WWM_GLS; } if (oldcode != code && (code & WWF_LABEL) == 0) { - register short frame; + short frame; frame = tt.tt_frame[code & WWF_MASK]; f->ww_buf[r][c].c_w = frame; diff --git a/usr.bin/window/wwgets.c b/usr.bin/window/wwgets.c index 1eb9805dfa..f60e40212d 100644 --- a/usr.bin/window/wwgets.c +++ b/usr.bin/window/wwgets.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwgets.c,v 1.9 2003/08/07 11:17:40 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,27 +30,31 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwgets.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwgets.c,v 1.3.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwgets.c,v 1.3 2005/05/07 23:20:43 corecode Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwgets.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwgets.c,v 1.9 2003/08/07 11:17:40 agc Exp $"); +#endif +#endif /* not lint */ + +#include #include "ww.h" #include "char.h" static void rub(int, struct ww *); -wwgets(buf, n, w) -char *buf; -int n; -register struct ww *w; +void +wwgets(char *buf, int n, struct ww *w) { - register char *p = buf; - register int c; - char uc = w->ww_unctrl; + char *p = buf; + int c; + int uc = ISSET(w->ww_wflags, WWW_UNCTRL); - w->ww_unctrl = 0; + CLR(w->ww_wflags, WWW_UNCTRL); for (;;) { wwcurtowin(w); while ((c = wwgetc()) < 0) @@ -92,22 +94,18 @@ register struct ww *w; if (p >= buf + n - 1) wwputc(ctrl('g'), w); else - if (isctrl(c)) - wwputs(unctrl(*p++ = c), w); - else - wwputc(*p++ = c, w); + wwputs(unctrl(*p++ = c), w); } } *p = 0; - w->ww_unctrl = uc; + SET(w->ww_wflags, uc); } static void -rub(c, w) -struct ww *w; +rub(int c, struct ww *w) { - register i; + int i; - for (i = isctrl(c) ? strlen(unctrl(c)) : 1; --i >= 0;) + for (i = strlen(unctrl(c)); --i >= 0;) (void) wwwrite(w, "\b \b", 3); } diff --git a/usr.bin/window/wwinit.c b/usr.bin/window/wwinit.c index 4903183819..d83f5caa87 100644 --- a/usr.bin/window/wwinit.c +++ b/usr.bin/window/wwinit.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwinit.c,v 1.19 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,38 +30,49 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwinit.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwinit.c,v 1.11.2.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwinit.c,v 1.3 2006/01/12 13:43:11 corecode Exp $ */ -#include +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwinit.c 8.2 (Berkeley) 4/28/95"; +#else +__RCSID("$NetBSD: wwinit.c,v 1.19 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + #include +#include +#include #include #include - #include "ww.h" #include "tt.h" +#include "xx.h" #include "char.h" -wwinit() +int +wwinit(void) { - register i, j; + int i, j; char *kp; - int s; + sigset_t nsigset, osigset; - wwdtablesize = getdtablesize(); + wwdtablesize = 3; wwhead.ww_forw = &wwhead; wwhead.ww_back = &wwhead; - s = sigblock(sigmask(SIGIO) | sigmask(SIGCHLD) | sigmask(SIGALRM) | - sigmask(SIGHUP) | sigmask(SIGTERM)); - if (signal(SIGIO, wwrint) == BADSIG || - signal(SIGCHLD, wwchild) == BADSIG || - signal(SIGHUP, wwquit) == BADSIG || - signal(SIGTERM, wwquit) == BADSIG || - signal(SIGPIPE, SIG_IGN) == BADSIG) { + sigemptyset(&nsigset); + sigaddset(&nsigset, SIGCHLD); + sigaddset(&nsigset, SIGALRM); + sigaddset(&nsigset, SIGHUP); + sigaddset(&nsigset, SIGTERM); + sigprocmask(SIG_BLOCK, &nsigset, &osigset); + + if (signal(SIGCHLD, wwchild) == SIG_ERR || + signal(SIGHUP, wwquit) == SIG_ERR || + signal(SIGTERM, wwquit) == SIG_ERR || + signal(SIGPIPE, SIG_IGN) == SIG_ERR) { wwerrno = WWE_SYS; return -1; } @@ -100,6 +109,8 @@ wwinit() #define _POSIX_VDISABLE -1 #endif wwwintty.ww_termios.c_oflag &= ~OXTABS; + wwwintty.ww_termios.c_cflag &= ~CLOCAL; + wwwintty.ww_termios.c_cflag |= HUPCL; wwnewtty.ww_termios = wwoldtty.ww_termios; wwnewtty.ww_termios.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IMAXBEL); @@ -109,10 +120,9 @@ wwinit() wwnewtty.ww_termios.c_lflag = 0; for (i = 0; i < NCCS; i++) wwnewtty.ww_termios.c_cc[i] = _POSIX_VDISABLE; - wwnewtty.ww_termios.c_cc[VMIN] = 0; + wwnewtty.ww_termios.c_cc[VMIN] = 1; wwnewtty.ww_termios.c_cc[VTIME] = 0; #endif - wwnewtty.ww_fflags = wwoldtty.ww_fflags | FASYNC; if (wwsettty(0, &wwnewtty) < 0) goto bad; @@ -125,11 +135,16 @@ wwinit() goto bad; } #ifdef OLD_TTY - ospeed = wwoldtty.ww_sgttyb.sg_ospeed; - switch (ospeed) { + wwospeed = wwoldtty.ww_sgttyb.sg_ospeed; +#else + wwospeed = cfgetospeed(&wwoldtty.ww_termios); + wwbaud = wwospeed; +#endif + switch (wwospeed) { default: case B0: - goto bad; + wwbaud = 9600; + break; case B50: wwbaud = 50; break; @@ -194,11 +209,6 @@ wwinit() break; #endif } -#else - if ((wwbaud = cfgetospeed(&wwoldtty.ww_termios)) == B0) - goto bad; -#endif - wwospeed = ospeed; if (xxinit() < 0) goto bad; @@ -208,7 +218,7 @@ wwinit() wwwrap = tt.tt_wrap; if (wwavailmodes & WWM_REV) - wwcursormodes = WWM_REV | wwavailmodes & WWM_BLK; + wwcursormodes = WWM_REV | (wwavailmodes & WWM_BLK); else if (wwavailmodes & WWM_UL) wwcursormodes = WWM_UL; @@ -217,7 +227,9 @@ wwinit() wwibe = wwib + 512; wwibq = wwibp = wwib; - if ((wwsmap = wwalloc(0, 0, wwnrow, wwncol, sizeof (char))) == 0) + wwsmap = (unsigned char **) + wwalloc(0, 0, wwnrow, wwncol, sizeof (unsigned char)); + if (wwsmap == 0) goto bad; for (i = 0; i < wwnrow; i++) for (j = 0; j < wwncol; j++) @@ -273,7 +285,7 @@ wwinit() wwaddcap1(WWT_DIM, &kp); if (wwavailmodes & WWM_USR) wwaddcap1(WWT_USR, &kp); - if (tt.tt_insline && tt.tt_delline || tt.tt_setscroll) + if ((tt.tt_insline && tt.tt_delline) || tt.tt_setscroll) wwaddcap1(WWT_ALDL, &kp); if (tt.tt_inschar) wwaddcap1(WWT_IMEI, &kp); @@ -282,10 +294,10 @@ wwinit() if (tt.tt_delchar) wwaddcap1(WWT_DC, &kp); wwaddcap("kb", &kp); - wwaddcap2("ku", &kp); - wwaddcap2("kd", &kp); - wwaddcap2("kl", &kp); - wwaddcap2("kr", &kp); + wwaddcap("ku", &kp); + wwaddcap("kd", &kp); + wwaddcap("kl", &kp); + wwaddcap("kr", &kp); wwaddcap("kh", &kp); if ((j = tgetnum("kn")) >= 0) { char cap[32]; @@ -305,49 +317,47 @@ wwinit() * since tt_init() has already made its own copy of it and * wwterm now points to the copy. */ - if (setenv("TERM", WWT_TERM, 1) == -1) - err(1, "setenv: cannot set TERM=%s", WWT_TERM); + (void) setenv("TERM", WWT_TERM, 1); #ifdef TERMINFO if (wwterminfoinit() < 0) goto bad; #endif if (tt.tt_checkpoint) - if (signal(SIGALRM, wwalarm) == BADSIG) { + if (signal(SIGALRM, wwalarm) == SIG_ERR) { wwerrno = WWE_SYS; goto bad; } - fcntl(0, F_SETOWN, getpid()); - /* catch typeahead before ASYNC was set */ - (void) kill(getpid(), SIGIO); wwstart1(); - (void) sigsetmask(s); + + sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); return 0; + bad: /* * Don't bother to free storage. We're supposed * to exit when wwinit fails anyway. */ - (void) signal(SIGIO, SIG_DFL); (void) wwsettty(0, &wwoldtty); - (void) sigsetmask(s); + + sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); return -1; } -wwaddcap(cap, kp) - register char *cap; - register char **kp; +void +wwaddcap(const char *cap, char **kp) { char tbuf[512]; char *tp = tbuf; - register char *str, *p; + char *str; + const char *p; if ((str = tgetstr(cap, &tp)) != 0) { - while (*(*kp)++ = *cap++) + while ((*(*kp)++ = *cap++)) ; (*kp)[-1] = '='; while (*str) { - for (p = unctrl(*str++); *(*kp)++ = *p++;) + for (p = unctrl(*str++); (*(*kp)++ = *p++);) ; (*kp)--; } @@ -356,54 +366,29 @@ wwaddcap(cap, kp) } } -wwaddcap1(cap, kp) - register char *cap; - register char **kp; +void +wwaddcap1(const char *cap, char **kp) { - while (*(*kp)++ = *cap++) + while ((*(*kp)++ = *cap++)) ; (*kp)--; } -wwaddcap2(cap, kp) - register char *cap; - register char **kp; -{ - char tbuf[512]; - char *tp = tbuf; - register char *str, *p; - - if ((str = tgetstr(cap, &tp)) != 0) { - /* we don't support vt100's application key mode, remap */ - if (str[0] == ctrl('[') && str[1] == 'O') - str[1] = '['; - while (*(*kp)++ = *cap++) - ; - (*kp)[-1] = '='; - while (*str) { - for (p = unctrl(*str++); *(*kp)++ = *p++;) - ; - (*kp)--; - } - *(*kp)++ = ':'; - **kp = 0; - } -} - -wwstart() +void +wwstart(void) { - register i; + int i; (void) wwsettty(0, &wwnewtty); - signal(SIGIO, wwrint); for (i = 0; i < wwnrow; i++) wwtouched[i] = WWU_TOUCHED; wwstart1(); } -wwstart1() +void +wwstart1(void) { - register i, j; + int i, j; for (i = 0; i < wwnrow; i++) for (j = 0; j < wwncol; j++) { @@ -420,9 +405,10 @@ wwstart1() * Reset data structures and terminal from an unknown state. * Restoring wwos has been taken care of elsewhere. */ -wwreset() +void +wwreset(void) { - register i; + int i; xxreset(); for (i = 0; i < wwnrow; i++) diff --git a/usr.bin/window/wwinschar.c b/usr.bin/window/wwinschar.c index 3d3412fce0..aea243843d 100644 --- a/usr.bin/window/wwinschar.c +++ b/usr.bin/window/wwinschar.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwinschar.c,v 1.7 2003/08/07 11:17:40 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,20 +30,25 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwinschar.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwinschar.c,v 1.2.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwinschar.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwinschar.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwinschar.c,v 1.7 2003/08/07 11:17:40 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" +#include "xx.h" -wwinschar(w, row, col, c, m) -register struct ww *w; -unsigned char c, m; +void +wwinschar(struct ww *w, int row, int col, char c, char m) { - register i; + int i; int nvis; short x = c | m << WWC_MSHIFT; @@ -53,7 +56,7 @@ unsigned char c, m; * First, shift the line. */ { - register union ww_char *p, *q; + union ww_char *p, *q; p = &w->ww_buf[row][w->ww_b.r]; q = p - 1; @@ -76,10 +79,10 @@ unsigned char c, m; * Now find out how much is actually changed, and fix wwns. */ { - register union ww_char *buf; - register char *win; - register union ww_char *ns; - register char *smap; + union ww_char *buf; + char *win; + union ww_char *ns; + unsigned char *smap; char touched; nvis = 0; @@ -113,7 +116,7 @@ unsigned char c, m; * Can/Should we use delete character? */ if ((tt.tt_inschar || tt.tt_insspace) && nvis > (wwncol - col) / 2) { - register union ww_char *p, *q; + union ww_char *p, *q; if (tt.tt_inschar) xxinschar(row, col, c, m); diff --git a/usr.bin/window/wwinsline.c b/usr.bin/window/wwinsline.c index 2db3b6a6a8..17c97af8a0 100644 --- a/usr.bin/window/wwinsline.c +++ b/usr.bin/window/wwinsline.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwinsline.c,v 1.6 2003/08/07 11:17:40 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,21 +30,25 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwinsline.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwinsline.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwinsline.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwinsline.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwinsline.c,v 1.6 2003/08/07 11:17:40 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" -wwinsline(w, row) -register struct ww *w; -int row; +void +wwinsline(struct ww *w, int row) { - register i; - register union ww_char **cpp, **cqq; - register union ww_char *cp; + int i; + union ww_char **cpp, **cqq; + union ww_char *cp; int row1, row2; char deleted; int visible; diff --git a/usr.bin/window/wwiomux.c b/usr.bin/window/wwiomux.c index ecf87bdb32..f75474d6af 100644 --- a/usr.bin/window/wwiomux.c +++ b/usr.bin/window/wwiomux.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwiomux.c,v 1.14 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,42 +30,54 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwiomux.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwiomux.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwiomux.c,v 1.3 2008/05/19 10:19:49 corecode Exp $ */ -#include "ww.h" -#include +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwiomux.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwiomux.c,v 1.14 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + #include -#include #if !defined(OLD_TTY) && !defined(TIOCPKT_DATA) #include #endif +#include +#include +#include #include +#include +#include +#include +#include "ww.h" /* * Multiple window output handler. * The idea is to copy window outputs to the terminal, via the * display package. We try to give wwcurwin highest priority. * The only return conditions are when there is keyboard input - * and when a child process dies, which are serviced by signal - * catchers (wwrint() and wwchild()). + * and when a child process dies. * When there's nothing to do, we sleep in a select(). - * This can be done better with interrupt driven io. But that's - * not supported on ptys, yet. * The history of this routine is interesting. */ -wwiomux() +void +wwiomux(void) { - register struct ww *w; - fd_set imask; - register n; - register char *p; - char c; - struct timeval tv; + struct ww *w; + nfds_t nfd; + int i; + int volatile dostdin; /* avoid longjmp clobbering */ + char volatile c; /* avoid longjmp clobbering */ + char *p; + int millis; char noblock = 0; + static struct pollfd *pfd = NULL; + static nfds_t maxfds = 0; + + c = 0; /* XXXGCC -Wuninitialized */ for (;;) { if (wwinterrupt()) { @@ -75,19 +85,48 @@ wwiomux() return; } - FD_ZERO(&imask); - n = -1; + nfd = 0; + for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) { + if (w->ww_pty < 0 || w->ww_obq >= w->ww_obe) + continue; + nfd++; + } + + if (maxfds <= ++nfd) { /* One more for the fd=0 case below */ + struct pollfd *npfd = pfd == NULL ? + malloc(sizeof(*pfd) * nfd) : + realloc(pfd, sizeof(*pfd) * nfd); + if (npfd == NULL) { + warn("will retry"); + if (pfd) + free(pfd); + pfd = NULL; + maxfds = 0; + return; + } + pfd = npfd; + maxfds = nfd; + } + + nfd = 0; for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) { if (w->ww_pty < 0) continue; if (w->ww_obq < w->ww_obe) { - if (w->ww_pty > n) - n = w->ww_pty; - FD_SET(w->ww_pty, &imask); + pfd[nfd].fd = w->ww_pty; + pfd[nfd++].events = POLLIN; } - if (w->ww_obq > w->ww_obp && !w->ww_stopped) + if (w->ww_obq > w->ww_obp && + !ISSET(w->ww_pflags, WWP_STOPPED)) noblock = 1; } + if (wwibq < wwibe) { + dostdin = nfd; + pfd[nfd].fd = 0; + pfd[nfd++].events = POLLIN; + } else { + dostdin = -1; + } if (!noblock) { if (wwcurwin != 0) @@ -101,39 +140,37 @@ wwiomux() wwclrintr(); return; } - /* - * Defensive code. If somebody else (for example, - * wall) clears the ASYNC flag on us, we will block - * forever. So we need a finite timeout and set - * the flag again. Anything more clever will probably - * need even more system calls. (This is a bug - * in the kernel.) - * I don't like this one bit. - */ - (void) fcntl(0, F_SETFL, wwnewtty.ww_fflags); - tv.tv_sec = 30; - tv.tv_usec = 0; + /* XXXX */ + millis = 30000; } else { - tv.tv_sec = 0; - tv.tv_usec = 10000; + millis = 10; } wwnselect++; - n = select(n + 1, &imask, NULL, NULL, &tv); + i = poll(pfd, nfd, millis); wwsetjmp = 0; noblock = 0; - if (n < 0) + if (i < 0) wwnselecte++; - else if (n == 0) + else if (i == 0) wwnselectz++; - else + else { + if (dostdin != -1 && (pfd[dostdin].revents & POLLIN) != 0) + wwrint(); + + nfd = 0; for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) { - if (w->ww_pty < 0 || - !FD_ISSET(w->ww_pty, &imask)) + int n; + + if (w->ww_pty < 0) + continue; + if (w->ww_pty != pfd[nfd].fd) + continue; + if ((pfd[nfd++].revents & POLLIN) == 0) continue; wwnwread++; p = w->ww_obq; - if (w->ww_ispty) { + if (w->ww_type == WWT_PTY) { if (p == w->ww_ob) { w->ww_obp++; w->ww_obq++; @@ -150,7 +187,7 @@ wwiomux() wwnwreadz++; (void) close(w->ww_pty); w->ww_pty = -1; - } else if (!w->ww_ispty) { + } else if (w->ww_type != WWT_PTY) { wwnwreadd++; wwnwreadc += n; w->ww_obq += n; @@ -162,18 +199,19 @@ wwiomux() } else { wwnwreadp++; if (*p & TIOCPKT_STOP) - w->ww_stopped = 1; + SET(w->ww_pflags, WWP_STOPPED); if (*p & TIOCPKT_START) - w->ww_stopped = 0; + CLR(w->ww_pflags, WWP_STOPPED); if (*p & TIOCPKT_FLUSHWRITE) { - w->ww_stopped = 0; + CLR(w->ww_pflags, WWP_STOPPED); w->ww_obq = w->ww_obp = w->ww_ob; } } - if (w->ww_ispty) + if (w->ww_type == WWT_PTY) *p = c; } + } /* * Try the current window first, if there is output * then process it and go back to the top to try again. @@ -183,8 +221,9 @@ wwiomux() * dies down. */ if ((w = wwcurwin) != 0 && w->ww_pty >= 0 && - w->ww_obq > w->ww_obp && !w->ww_stopped) { - n = wwwrite(w, w->ww_obp, w->ww_obq - w->ww_obp); + w->ww_obq > w->ww_obp && + !ISSET(w->ww_pflags, WWP_STOPPED)) { + int n = wwwrite(w, w->ww_obp, w->ww_obq - w->ww_obp); if ((w->ww_obp += n) == w->ww_obq) w->ww_obq = w->ww_obp = w->ww_ob; noblock = 1; @@ -192,8 +231,8 @@ wwiomux() } for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) if (w->ww_pty >= 0 && w->ww_obq > w->ww_obp && - !w->ww_stopped) { - n = wwwrite(w, w->ww_obp, + !ISSET(w->ww_pflags, WWP_STOPPED)) { + int n = wwwrite(w, w->ww_obp, w->ww_obq - w->ww_obp); if ((w->ww_obp += n) == w->ww_obq) w->ww_obq = w->ww_obp = w->ww_ob; diff --git a/usr.bin/window/wwlabel.c b/usr.bin/window/wwlabel.c index b2146c340b..8a54d2d8f1 100644 --- a/usr.bin/window/wwlabel.c +++ b/usr.bin/window/wwlabel.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwlabel.c,v 1.8 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,12 +30,17 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwlabel.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwlabel.c,v 1.3.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwlabel.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwlabel.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwlabel.c,v 1.8 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "char.h" @@ -46,22 +49,19 @@ * at 1 line above w and 'where' columns from it's left edge. * Gross, but it works. */ -wwlabel(w, f, where, l, mode) -struct ww *w; -struct ww *f; -char *l; +void +wwlabel(struct ww *w, struct ww *f, int where, char *l, int mode) { int row; - register j; + int j; int jj; - register char *win; - register union ww_char *buf; - register union ww_char *ns; - register char *fmap; - register char *smap; + char *win; + union ww_char *buf; + union ww_char *ns; + char *fmap; + unsigned char *smap; char touched; - unsigned char *p; - static unsigned char cbuf[2]; + const char *p; if (f->ww_fmap == 0) return; @@ -79,14 +79,8 @@ char *l; jj = MIN(w->ww_i.r, f->ww_i.r); j = w->ww_i.l + where; - while (j < jj && *l) { - if (isctrl(*l)) - p = unctrl(*l); - else { - cbuf[0] = *l; - p = cbuf; - } - for (l++; j < jj && *p; j++, p++) { + while (j < jj && *l) + for (p = unctrl(*l++); j < jj && *p; j++, p++) { /* can't label if not already framed */ if (win[j] & WWM_GLS) continue; @@ -99,6 +93,5 @@ char *l; } fmap[j] |= WWF_LABEL; } - } wwtouched[row] = touched; } diff --git a/usr.bin/window/wwmisc.c b/usr.bin/window/wwmisc.c index b7db34fd93..c48e04b10f 100644 --- a/usr.bin/window/wwmisc.c +++ b/usr.bin/window/wwmisc.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwmisc.c,v 1.7 2003/08/07 11:17:41 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,12 +30,17 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwmisc.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwmisc.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwmisc.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwmisc.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwmisc.c,v 1.7 2003/08/07 11:17:41 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" #include "char.h" @@ -45,15 +48,15 @@ /* * Sufficient but not necessary test for total visibility. */ -wwvisible(w) -register struct ww *w; +int +wwvisible(struct ww *w) { - register i; - register nvis = 0; + int i; + int nvis = 0; for (i = w->ww_i.t; i < w->ww_i.b; i++) nvis += w->ww_nvis[i]; - if (w->ww_hascursor + if (ISSET(w->ww_wflags, WWW_HASCURSOR) && w->ww_cur.r >= w->ww_i.t && w->ww_cur.r < w->ww_i.b && w->ww_cur.c >= w->ww_i.l && w->ww_cur.c < w->ww_i.r && wwsmap[w->ww_cur.r][w->ww_cur.c] == w->ww_index) @@ -61,7 +64,8 @@ register struct ww *w; return nvis == w->ww_i.nr * w->ww_i.nc; } -wwbell() +void +wwbell(void) { ttputc(ctrl('g')); } diff --git a/usr.bin/window/wwmove.c b/usr.bin/window/wwmove.c index b0d351b062..e6d17ed874 100644 --- a/usr.bin/window/wwmove.c +++ b/usr.bin/window/wwmove.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwmove.c,v 1.7 2003/08/07 11:17:42 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,22 +30,27 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwmove.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwmove.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwmove.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwmove.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwmove.c,v 1.7 2003/08/07 11:17:42 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" /* * Move a window. Should be unattached. */ -wwmove(w, row, col) -register struct ww *w; +void +wwmove(struct ww *w, int row, int col) { - register dr, dc; - register i; + int dr, dc; + int i; dr = row - w->ww_w.t; dc = col - w->ww_w.l; @@ -82,9 +85,9 @@ register struct ww *w; } w->ww_nvis -= dr; for (i = w->ww_i.t; i < w->ww_i.b; i++) { - register j = w->ww_i.l; - register char *win = &w->ww_win[i][j]; - register char *smap = &wwsmap[i][j]; + int j = w->ww_i.l; + char *win = &w->ww_win[i][j]; + unsigned char *smap = &wwsmap[i][j]; int nvis = 0; for (; j < w->ww_i.r; j++, win++, smap++) diff --git a/usr.bin/window/wwopen.c b/usr.bin/window/wwopen.c index e5fe407a13..9825f9b533 100644 --- a/usr.bin/window/wwopen.c +++ b/usr.bin/window/wwopen.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwopen.c,v 1.12 2003/08/07 11:17:42 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,27 +30,33 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwopen.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwopen.c,v 1.2.12.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwopen.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ -#include "ww.h" +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwopen.c 8.2 (Berkeley) 4/28/95"; +#else +__RCSID("$NetBSD: wwopen.c,v 1.12 2003/08/07 11:17:42 agc Exp $"); +#endif +#endif /* not lint */ + #include #include #include #include +#include +#include "ww.h" struct ww * -wwopen(flags, nrow, ncol, row, col, nline) +wwopen(int type, int oflags, int nrow, int ncol, int row, int col, int nline) { - register struct ww *w; - register i, j; + struct ww *w; + int i, j; char m; short nvis; - w = (struct ww *)calloc(sizeof (struct ww), 1); + w = (struct ww *)calloc(1, sizeof (struct ww)); if (w == 0) { wwerrno = WWE_NOMEM; goto bad; @@ -95,13 +99,16 @@ wwopen(flags, nrow, ncol, row, col, nline) w->ww_cur.r = w->ww_w.t; w->ww_cur.c = w->ww_w.l; - if (flags & WWO_PTY) { + w->ww_type = type; + switch (type) { + case WWT_PTY: if (wwgetpty(w) < 0) goto bad; - w->ww_ispty = 1; - } else if (flags & WWO_SOCKET) { + break; + case WWT_SOCKET: + { int d[2]; - if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, d) < 0) { + if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, d) < 0) { wwerrno = WWE_SYS; goto bad; } @@ -109,14 +116,18 @@ wwopen(flags, nrow, ncol, row, col, nline) (void) fcntl(d[1], F_SETFD, 1); w->ww_pty = d[0]; w->ww_socket = d[1]; + break; + } } - if (flags & (WWO_PTY|WWO_SOCKET)) { + if (type != WWT_INTERNAL) { if ((w->ww_ob = malloc(512)) == 0) { wwerrno = WWE_NOMEM; goto bad; } w->ww_obe = w->ww_ob + 512; w->ww_obp = w->ww_obq = w->ww_ob; + if (w->ww_pty >= wwdtablesize) + wwdtablesize = w->ww_pty + 1; } w->ww_win = wwalloc(w->ww_w.t, w->ww_w.l, @@ -124,18 +135,18 @@ wwopen(flags, nrow, ncol, row, col, nline) if (w->ww_win == 0) goto bad; m = 0; - if (flags & WWO_GLASS) + if (oflags & WWO_GLASS) m |= WWM_GLS; - if (flags & WWO_REVERSE) + if (oflags & WWO_REVERSE) { if (wwavailmodes & WWM_REV) m |= WWM_REV; - else - flags &= ~WWO_REVERSE; + else oflags &= ~WWO_REVERSE; + } for (i = w->ww_w.t; i < w->ww_w.b; i++) for (j = w->ww_w.l; j < w->ww_w.r; j++) w->ww_win[i][j] = m; - if (flags & WWO_FRAME) { + if (oflags & WWO_FRAME) { w->ww_fmap = wwalloc(w->ww_w.t, w->ww_w.l, w->ww_w.nr, w->ww_w.nc, sizeof (char)); if (w->ww_fmap == 0) @@ -165,7 +176,8 @@ wwopen(flags, nrow, ncol, row, col, nline) w->ww_nvis[i] = nvis; w->ww_state = WWS_INITIAL; - w->ww_oflags = flags; + CLR(w->ww_oflags, WWO_ALLFLAGS); + SET(w->ww_oflags, oflags); return wwindex[w->ww_index] = w; bad: if (w != 0) { diff --git a/usr.bin/window/wwprintf.c b/usr.bin/window/wwprintf.c index b6d068972e..27baeae821 100644 --- a/usr.bin/window/wwprintf.c +++ b/usr.bin/window/wwprintf.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwprintf.c,v 1.6 2003/08/07 11:17:42 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,23 +30,33 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwprintf.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwprintf.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwprintf.c,v 1.3 2004/01/24 22:40:58 joerg Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwprintf.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwprintf.c,v 1.6 2003/08/07 11:17:42 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" -#include -/*VARARGS2*/ -wwprintf(struct ww *w, char *fmt, ...) +void +wwprintf(struct ww *w, const char *fmt, ...) { - char buf[1024]; va_list ap; va_start(ap, fmt); - /* buffer can overflow */ - (void) wwwrite(w, buf, vsprintf(buf, fmt, ap)); + (void) wwvprintf(w, fmt, ap); va_end(ap); } + +void +wwvprintf(struct ww *w, const char *fmt, va_list ap) +{ + char buf[1024]; + + (void) wwwrite(w, buf, vsnprintf(buf, sizeof(buf), fmt, ap)); +} diff --git a/usr.bin/window/wwpty.c b/usr.bin/window/wwpty.c index de66ebb558..ea926f6e92 100644 --- a/usr.bin/window/wwpty.c +++ b/usr.bin/window/wwpty.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwpty.c,v 1.8 2003/08/07 11:17:42 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,59 +30,38 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwpty.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwpty.c,v 1.2.2.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwpty.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ -#include -#include - -#include "ww.h" +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwpty.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwpty.c,v 1.8 2003/08/07 11:17:42 agc Exp $"); +#endif +#endif /* not lint */ #if !defined(OLD_TTY) && !defined(TIOCPKT) #include #endif +#include +#include +#include "ww.h" -wwgetpty(w) -register struct ww *w; +int +wwgetpty(struct ww *w) { - register char c, *p; - int tty; int on = 1; -#define PTY "/dev/XtyXX" -#define _PT 5 -#define _PQRS 8 -#define _0_9 9 + int result, tty; - (void) strcpy(w->ww_ttyname, PTY); - for (c = 'p'; c <= 'u'; c++) { - w->ww_ttyname[_PT] = 'p'; - w->ww_ttyname[_PQRS] = c; - w->ww_ttyname[_0_9] = '0'; - if (access(w->ww_ttyname, 0) < 0) - break; - for (p = "0123456789abcdefghijklmnopqrstuv"; *p; p++) { - w->ww_ttyname[_PT] = 'p'; - w->ww_ttyname[_0_9] = *p; - if ((w->ww_pty = open(w->ww_ttyname, 2)) < 0) - continue; - w->ww_ttyname[_PT] = 't'; - if ((tty = open(w->ww_ttyname, 2)) < 0) { - (void) close(w->ww_pty); - continue; - } - (void) close(tty); - if (ioctl(w->ww_pty, TIOCPKT, (char *)&on) < 0) { - (void) close(w->ww_pty); - continue; - } - (void) fcntl(w->ww_pty, F_SETFD, 1); - return 0; - } + result = openpty(&w->ww_pty, &tty, w->ww_ttyname, NULL, NULL); + if (result < 0) { + w->ww_pty = -1; + wwerrno = WWE_NOPTY; + return -1; + } else { + (void) ioctl(w->ww_pty, TIOCPKT, (char *)&on); + (void) fcntl(w->ww_pty, F_SETFD, 1); + return 0; } - w->ww_pty = -1; - wwerrno = WWE_NOPTY; - return -1; } diff --git a/usr.bin/window/wwputc.c b/usr.bin/window/wwputc.c index 34fe1bfd1e..0d8619c4d0 100644 --- a/usr.bin/window/wwputc.c +++ b/usr.bin/window/wwputc.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwputc.c,v 1.6 2003/08/07 11:17:43 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,17 +30,21 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwputc.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwputc.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwputc.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwputc.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwputc.c,v 1.6 2003/08/07 11:17:43 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" -wwputc(c, w) -char c; -struct ww *w; +void +wwputc(char c, struct ww *w) { (void) wwwrite(w, &c, sizeof c); } diff --git a/usr.bin/window/wwputs.c b/usr.bin/window/wwputs.c index b6ec2409e6..408189d2a9 100644 --- a/usr.bin/window/wwputs.c +++ b/usr.bin/window/wwputs.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwputs.c,v 1.7 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,19 +30,23 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwputs.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwputs.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwputs.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwputs.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwputs.c,v 1.7 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" -wwputs(s, w) -register char *s; -struct ww *w; +void +wwputs(const char *s, struct ww *w) { - register char *p = s; + const char *p = s; while (*p++) ; diff --git a/usr.bin/window/wwredraw.c b/usr.bin/window/wwredraw.c index ff523dfa21..45e80d7853 100644 --- a/usr.bin/window/wwredraw.c +++ b/usr.bin/window/wwredraw.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwredraw.c,v 1.6 2003/08/07 11:17:43 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,19 +30,26 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwredraw.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwredraw.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwredraw.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwredraw.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwredraw.c,v 1.6 2003/08/07 11:17:43 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" +#include "xx.h" -wwredraw() +void +wwredraw(void) { - register i, j; - register union ww_char *os; + int i, j; + union ww_char *os; xxclear(); for (i = 0; i < wwnrow; i++) { diff --git a/usr.bin/window/wwredrawwin.c b/usr.bin/window/wwredrawwin.c index c7ff064740..055f5235c3 100644 --- a/usr.bin/window/wwredrawwin.c +++ b/usr.bin/window/wwredrawwin.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwredrawwin.c,v 1.7 2003/08/07 11:17:44 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,24 +30,28 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwredrawwin.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwredrawwin.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwredrawwin.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwredrawwin.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwredrawwin.c,v 1.7 2003/08/07 11:17:44 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" -wwredrawwin1(w, row1, row2, offset) -register struct ww *w; -int row1, row2, offset; +void +wwredrawwin1(struct ww *w, int row1, int row2, int offset) { int row; - register col; - register char *smap; - register union ww_char *buf; - register char *win; - register union ww_char *ns; + int col; + unsigned char *smap; + union ww_char *buf; + char *win; + union ww_char *ns; int x; int nchanged; diff --git a/usr.bin/window/wwrint.c b/usr.bin/window/wwrint.c index fedb6909bb..94266b1cd9 100644 --- a/usr.bin/window/wwrint.c +++ b/usr.bin/window/wwrint.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwrint.c,v 1.7 2003/08/07 11:17:44 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,17 +30,20 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwrint.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwrint.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwrint.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwrint.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwrint.c,v 1.7 2003/08/07 11:17:44 agc Exp $"); +#endif +#endif /* not lint */ + +#include #include "ww.h" #include "tt.h" -#if defined(OLD_TTY) || defined(VMIN_BUG) -#include -#endif /* * Tty input interrupt handler. @@ -55,21 +56,12 @@ * It should be completely safe. */ void -wwrint() +wwrint(void) { - register n; + int n; - if (wwibp == wwibq) - wwibp = wwibq = wwib; wwnread++; -#if defined(OLD_TTY) || defined(VMIN_BUG) - /* we have set c_cc[VMIN] to 0 */ - (void) fcntl(0, F_SETFL, O_NONBLOCK|wwnewtty.ww_fflags); -#endif n = read(0, wwibq, wwibe - wwibq); -#if defined(OLD_TTY) || defined(VMIN_BUG) - (void) fcntl(0, F_SETFL, wwnewtty.ww_fflags); -#endif if (n > 0) { if (tt.tt_rint) n = (*tt.tt_rint)(wwibq, n); diff --git a/usr.bin/window/wwscroll.c b/usr.bin/window/wwscroll.c index d66fbe9866..bff11107ed 100644 --- a/usr.bin/window/wwscroll.c +++ b/usr.bin/window/wwscroll.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwscroll.c,v 1.7 2003/08/07 11:17:44 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,21 +30,28 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwscroll.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwscroll.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwscroll.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwscroll.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwscroll.c,v 1.7 2003/08/07 11:17:44 agc Exp $"); +#endif +#endif /* not lint */ + +#include + #include "ww.h" #include "tt.h" +#include "xx.h" -wwscroll(w, n) -register struct ww *w; -int n; +void +wwscroll(struct ww *w, int n) { - register dir; - register top; + int dir; + int top; if (n == 0) return; @@ -77,12 +82,10 @@ int n; * Don't adjust ww_scroll. * And don't redraw 'leaveit' lines. */ -wwscroll1(w, row1, row2, dir, leaveit) -register struct ww *w; -int row1, row2, dir; -int leaveit; +int +wwscroll1(struct ww *w, int row1, int row2, int dir, int leaveit) { - register i; + int i; int row1x, row2x; int nvis; int nvismax; @@ -117,8 +120,8 @@ int leaveit; if (nvis < nvismax / 2) goto no_scroll; /* not worth it */ if ((dir > 0 ? tt.tt_scroll_down == 0 : tt.tt_scroll_up == 0) || - (tt.tt_scroll_top != row1x || tt.tt_scroll_bot != row2x - 1) && - tt.tt_setscroll == 0) + ((tt.tt_scroll_top != row1x || tt.tt_scroll_bot != row2x - 1) && + tt.tt_setscroll == 0)) if (tt.tt_delline == 0 || tt.tt_insline == 0) goto no_scroll; xxscroll(dir, row1x, row2x); @@ -127,8 +130,8 @@ int leaveit; * Fix up the old screen. */ { - register union ww_char *tmp; - register union ww_char **cpp, **cqq; + union ww_char *tmp; + union ww_char **cpp, **cqq; if (dir > 0) { cpp = &wwos[row1x]; @@ -159,8 +162,8 @@ no_scroll: */ if (dir > 0) { { - register union ww_char *tmp; - register union ww_char **cpp, **cqq; + union ww_char *tmp; + union ww_char **cpp, **cqq; cpp = &wwns[row1x]; cqq = cpp + 1; @@ -170,7 +173,7 @@ no_scroll: *cpp = tmp; } if (scrolled) { - register char *p, *q; + char *p, *q; p = &wwtouched[row1x]; q = p + 1; @@ -178,7 +181,7 @@ no_scroll: *p++ = *q++; *p |= WWU_TOUCHED; } else { - register char *p; + char *p; p = &wwtouched[row1x]; for (i = row2x - row1x; --i >= 0;) @@ -188,8 +191,8 @@ no_scroll: wwredrawwin1(w, row2x - 1, row2 - leaveit, dir); } else { { - register union ww_char *tmp; - register union ww_char **cpp, **cqq; + union ww_char *tmp; + union ww_char **cpp, **cqq; cpp = &wwns[row2x]; cqq = cpp - 1; @@ -199,7 +202,7 @@ no_scroll: *cqq = tmp; } if (scrolled) { - register char *p, *q; + char *p, *q; p = &wwtouched[row2x]; q = p - 1; @@ -207,7 +210,7 @@ no_scroll: *--p = *--q; *q |= WWU_TOUCHED; } else { - register char *p; + char *p; p = &wwtouched[row1x]; for (i = row2x - row1x; --i >= 0;) @@ -218,7 +221,7 @@ no_scroll: } } else { if (scrolled) { - register char *p; + char *p; p = &wwtouched[row1x]; for (i = row2x - row1x; --i >= 0;) diff --git a/usr.bin/window/wwsize.c b/usr.bin/window/wwsize.c index 1f9c5713e0..23bbe1a25a 100644 --- a/usr.bin/window/wwsize.c +++ b/usr.bin/window/wwsize.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwsize.c,v 1.9 2006/05/02 22:24:05 christos Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,23 +30,28 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwsize.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwsize.c,v 1.2.6.1 2001/05/17 09:45:01 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwsize.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwsize.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwsize.c,v 1.9 2006/05/02 22:24:05 christos Exp $"); +#endif +#endif /* not lint */ + #include #include "ww.h" /* * Resize a window. Should be unattached. */ -wwsize(w, nrow, ncol) -register struct ww *w; +int +wwsize(struct ww *w, int nrow, int ncol) { - register i, j; - int nline; + int i, j; + int nline = 0; union ww_char **buf = 0; char **win = 0; short *nvis = 0; @@ -169,14 +172,14 @@ register struct ww *w; /* * Put cursor back. */ - if (w->ww_hascursor) { - w->ww_hascursor = 0; + if (ISSET(w->ww_wflags, WWW_HASCURSOR)) { + CLR(w->ww_wflags, WWW_HASCURSOR); wwcursor(w, 1); } /* * Fool with pty. */ - if (w->ww_ispty && w->ww_pty >= 0) + if (w->ww_type == WWT_PTY && w->ww_pty >= 0) (void) wwsetttysize(w->ww_pty, nrow, ncol); return 0; bad: @@ -186,7 +189,5 @@ bad: wwfree(fmap, w->ww_w.t); if (buf != 0) wwfree((char **)buf, w->ww_b.t); - if (nvis != 0) - free((char *)(nvis + w->ww_w.t)); return -1; } diff --git a/usr.bin/window/wwspawn.c b/usr.bin/window/wwspawn.c index e1df53efd8..4038275603 100644 --- a/usr.bin/window/wwspawn.c +++ b/usr.bin/window/wwspawn.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwspawn.c,v 1.10 2006/12/18 20:04:55 christos Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,32 +30,39 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwspawn.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwspawn.c,v 1.4.2.1 2001/05/17 09:45:02 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwspawn.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwspawn.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwspawn.c,v 1.10 2006/12/18 20:04:55 christos Exp $"); +#endif +#endif /* not lint */ + #include #include - #include "ww.h" /* * There is a dead lock with vfork and closing of pseudo-ports. * So we have to be sneaky about error reporting. */ -wwspawn(wp, file, argv) -register struct ww *wp; -char *file; -char **argv; +int +wwspawn(struct ww *wp, char *file, char **argv) { int pid; int ret; - char erred = 0; - int s; + char volatile erred; + sigset_t nsigset, osigset; + + erred = 0; + + sigemptyset(&nsigset); + sigaddset(&nsigset, SIGCHLD); + sigprocmask(SIG_BLOCK, &nsigset, &osigset); - s = sigblock(sigmask(SIGCHLD)); switch (pid = vfork()) { case -1: wwerrno = WWE_SYS; @@ -78,7 +83,9 @@ char **argv; ret = pid; } } - (void) sigsetmask(s); + + sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); + if (wp->ww_socket >= 0) { (void) close(wp->ww_socket); wp->ww_socket = -1; diff --git a/usr.bin/window/wwsuspend.c b/usr.bin/window/wwsuspend.c index d36b74162c..96e30c559e 100644 --- a/usr.bin/window/wwsuspend.c +++ b/usr.bin/window/wwsuspend.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwsuspend.c,v 1.6 2003/08/07 11:17:45 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,17 +30,23 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwsuspend.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwsuspend.c,v 1.2.6.1 2001/05/17 09:45:02 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwsuspend.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwsuspend.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwsuspend.c,v 1.6 2003/08/07 11:17:45 agc Exp $"); +#endif +#endif /* not lint */ + +#include #include "ww.h" #include "tt.h" -#include -wwsuspend() +void +wwsuspend(void) { sig_t oldsig; diff --git a/usr.bin/window/wwterminfo.c b/usr.bin/window/wwterminfo.c index 48520b59cb..de38f13efb 100644 --- a/usr.bin/window/wwterminfo.c +++ b/usr.bin/window/wwterminfo.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwterminfo.c,v 1.5 2003/08/07 11:17:45 agc Exp $ */ + /* * Copyright (c) 1982, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,18 +30,29 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwterminfo.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwterminfo.c,v 1.3.6.2 2001/05/17 19:40:13 eric Exp $ - * $DragonFly: src/usr.bin/window/wwterminfo.c,v 1.3 2006/01/12 13:43:11 corecode Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwterminfo.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwterminfo.c,v 1.5 2003/08/07 11:17:45 agc Exp $"); +#endif +#endif /* not lint */ + #ifdef TERMINFO -#include "ww.h" +#include +#include +#include + #include +#include #include +#include #include "local.h" +#include "ww.h" /* * Terminfo support @@ -56,6 +65,7 @@ /* * Initialize the working terminfo directory */ +int wwterminfoinit() { FILE *fp; @@ -63,13 +73,12 @@ wwterminfoinit() /* make the directory */ (void) sprintf(wwterminfopath, "%swwinXXXXXX", _PATH_TMP); - if (mkdtemp(wwterminfopath) < 0 || - chmod(wwterminfopath, 00755) < 0) { + if (mkdtemp(wwterminfopath) == NULL) || + chmod(wwterminfopath, 0755) < 0) { wwerrno = WWE_SYS; return -1; } - if (setenv("TERMINFO", wwterminfopath, 1) == -1) - err(1, "setenv: cannot set TERMINFO=%s", wwterminfopath); + (void) setenv("TERMINFO", wwterminfopath, 1); /* make a termcap entry and turn it into terminfo */ (void) sprintf(buf, "%s/cap", wwterminfopath); if ((fp = fopen(buf, "w")) == NULL) { @@ -89,24 +98,25 @@ wwterminfoinit() /* * Delete the working terminfo directory at shutdown */ +int wwterminfoend() { - char *args[4]; - args[0] = _PATH_RM; - args[1] = "-rf"; - args[2] = wwterminfopath; - args[3] = NULL; - switch (vfork()) { + int pstat; + pid_t pid; + + pid = vfork(); + switch (pid) { case -1: /* can't really do (or say) anything about errors */ return -1; case 0: - execv(args[0], args); - _exit(0); - default: - wait(NULL); - return 0; + execl(_PATH_RM, _PATH_RM, "-rf", wwterminfopath, 0); + _exit(1); } + pid = waitpid(pid, &pstat, 0); + if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0) + return -1; + return 0; } #endif /* TERMINFO */ diff --git a/usr.bin/window/wwtty.c b/usr.bin/window/wwtty.c index 59a6cc67e2..ef2475cc8f 100644 --- a/usr.bin/window/wwtty.c +++ b/usr.bin/window/wwtty.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwtty.c,v 1.7 2003/08/07 11:17:46 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,21 +30,26 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwtty.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwtty.c,v 1.1.1.1.14.1 2001/05/17 09:45:02 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwtty.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ -#include "ww.h" +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwtty.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwtty.c,v 1.7 2003/08/07 11:17:46 agc Exp $"); +#endif +#endif /* not lint */ + #include -#include #if !defined(OLD_TTY) && !defined(TIOCGWINSZ) #include #endif +#include +#include "ww.h" -wwgettty(d, t) -register struct ww_tty *t; +int +wwgettty(int d, struct ww_tty *t) { #ifdef OLD_TTY if (ioctl(d, TIOCGETP, (char *)&t->ww_sgttyb) < 0) @@ -63,8 +66,6 @@ register struct ww_tty *t; if (tcgetattr(d, &t->ww_termios) < 0) goto bad; #endif - if ((t->ww_fflags = fcntl(d, F_GETFL, 0)) < 0) - goto bad; return 0; bad: wwerrno = WWE_SYS; @@ -76,8 +77,8 @@ bad: * 'o' is the current modes. We set the line discipline only if * it changes, to avoid unnecessary flushing of typeahead. */ -wwsettty(d, t) -register struct ww_tty *t; +int +wwsettty(int d, struct ww_tty *t) { #ifdef OLD_TTY int i; @@ -106,8 +107,6 @@ register struct ww_tty *t; if (tcsetattr(d, TCSADRAIN, &t->ww_termios) < 0) goto bad; #endif - if (fcntl(d, F_SETFL, t->ww_fflags) < 0) - goto bad; return 0; bad: wwerrno = WWE_SYS; @@ -119,8 +118,8 @@ bad: * on the control side of pseudoterminals. */ -wwgetttysize(d, r, c) - int *r, *c; +int +wwgetttysize(int d, int *r, int *c) { struct winsize winsize; @@ -135,7 +134,8 @@ wwgetttysize(d, r, c) return 0; } -wwsetttysize(d, r, c) +int +wwsetttysize(int d, int r, int c) { struct winsize winsize; @@ -149,13 +149,14 @@ wwsetttysize(d, r, c) return 0; } -wwstoptty(d) +int +wwstoptty(int d) { #if !defined(OLD_TTY) && defined(TCOOFF) /* not guaranteed to work on the pty side */ if (tcflow(d, TCOOFF) < 0) #else - if (ioctl(d, TIOCSTOP, NULL) < 0) + if (ioctl(d, TIOCSTOP, (char *)0) < 0) #endif { wwerrno = WWE_SYS; @@ -164,13 +165,14 @@ wwstoptty(d) return 0; } -wwstarttty(d) +int +wwstarttty(int d) { #if !defined(OLD_TTY) && defined(TCOON) /* not guaranteed to work on the pty side */ if (tcflow(d, TCOON) < 0) #else - if (ioctl(d, TIOCSTART, NULL) < 0) + if (ioctl(d, TIOCSTART, (char *)0) < 0) #endif { wwerrno = WWE_SYS; diff --git a/usr.bin/window/wwunframe.c b/usr.bin/window/wwunframe.c index 34be86102c..a241cbfc4f 100644 --- a/usr.bin/window/wwunframe.c +++ b/usr.bin/window/wwunframe.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwunframe.c,v 1.7 2003/08/07 11:17:46 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,25 +30,30 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwunframe.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwunframe.c,v 1.1.1.1.14.1 2001/05/17 09:45:02 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwunframe.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwunframe.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwunframe.c,v 1.7 2003/08/07 11:17:46 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" -wwunframe(w) -register struct ww *w; +void +wwunframe(struct ww *w) { int i; for (i = w->ww_i.t; i < w->ww_i.b; i++) { - register j; - register char *win = w->ww_win[i]; - register char *fmap = w->ww_fmap ? w->ww_fmap[i] : 0; - register char *smap = wwsmap[i]; - register union ww_char *ns = wwns[i]; + int j; + char *win = w->ww_win[i]; + char *fmap = w->ww_fmap ? w->ww_fmap[i] : 0; + unsigned char *smap = wwsmap[i]; + union ww_char *ns = wwns[i]; int nchanged = 0; for (j = w->ww_i.l; j < w->ww_i.r; j++) { diff --git a/usr.bin/window/wwupdate.c b/usr.bin/window/wwupdate.c index acfbdcec8e..f0759167a3 100644 --- a/usr.bin/window/wwupdate.c +++ b/usr.bin/window/wwupdate.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwupdate.c,v 1.6 2003/08/07 11:17:46 agc Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,19 +30,26 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwupdate.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwupdate.c,v 1.1.1.1.14.1 2001/05/17 09:45:02 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwupdate.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwupdate.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwupdate.c,v 1.6 2003/08/07 11:17:46 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" +#include "xx.h" -wwupdate1(top, bot) +void +wwupdate1(int top, int bot) { int i; - register j; + int j; char *touched; struct ww_update *upd; char check_clreos = 0; @@ -52,8 +57,8 @@ wwupdate1(top, bot) wwnupdate++; { - register char *t1 = wwtouched + top, *t2 = wwtouched + bot; - register n; + char *t1 = wwtouched + top, *t2 = wwtouched + bot; + int n; while (!*t1++) if (t1 == t2) @@ -77,7 +82,7 @@ wwupdate1(top, bot) * If we can't clreos then we try for clearing * the whole screen. */ - if (check_clreos = n * 10 > (wwnrow - st) * 9) { + if ((check_clreos = n * 10 > (wwnrow - st) * 9)) { scan_top = st; scan_bot = wwnrow; } @@ -88,10 +93,10 @@ wwupdate1(top, bot) for (i = scan_top, touched = &wwtouched[i], upd = &wwupd[i]; i < scan_bot; i++, touched++, upd++) { - register gain = 0; - register best_gain = 0; - register best_col; - register union ww_char *ns, *os; + int gain = 0; + int best_gain = 0; + int best_col = 0; + union ww_char *ns, *os; if (wwinterrupt()) return; @@ -127,11 +132,11 @@ wwupdate1(top, bot) upd->gain = gain; } if (check_clreos) { - register struct ww_update *u; - register gain = 0; - register best_gain = 0; - int best_row; - register simple_gain = 0; + struct ww_update *u; + int gain = 0; + int best_gain = 0; + int best_row = 0; + int simple_gain = 0; char didit = 0; /* @@ -143,7 +148,7 @@ wwupdate1(top, bot) * undefined when u->best_gain is 0 so we can't use it. */ for (j = scan_bot - 1, u = wwupd + j; j >= top; j--, u--) { - register g = gain + u->best_gain; + int g = gain + u->best_gain; if (g > best_gain) { best_gain = g; @@ -173,7 +178,7 @@ wwupdate1(top, bot) wwnupdclreosline += wwnrow - i; u = wwupd + i; while (i < scan_bot) { - register union ww_char *os = &wwos[i][j]; + union ww_char *os = &wwos[i][j]; for (j = wwncol - j; --j >= 0;) os++->c_w = ' '; @@ -187,7 +192,7 @@ wwupdate1(top, bot) simple: for (i = top, touched = &wwtouched[i], upd = &wwupd[i]; i < bot; i++, touched++, upd++) { - register union ww_char *os, *ns; + union ww_char *os, *ns; char didit; if (!*touched) @@ -205,10 +210,10 @@ simple: ns = wwns[i]; os = wwos[i]; for (j = 0; j < wwncol;) { - register char *p, *q; + char *p, *q; char m; int c; - register n; + int n; char buf[512]; /* > wwncol */ union ww_char lastc; diff --git a/usr.bin/window/wwwrite.c b/usr.bin/window/wwwrite.c index 28c5576985..6cfe5cfd79 100644 --- a/usr.bin/window/wwwrite.c +++ b/usr.bin/window/wwwrite.c @@ -1,3 +1,5 @@ +/* $NetBSD: wwwrite.c,v 1.9 2009/04/14 08:50:06 lukem Exp $ */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,19 +30,25 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)wwwrite.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/wwwrite.c,v 1.2.14.1 2001/05/17 09:45:02 obrien Exp $ - * $DragonFly: src/usr.bin/window/wwwrite.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)wwwrite.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: wwwrite.c,v 1.9 2009/04/14 08:50:06 lukem Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "tt.h" +#include "xx.h" #include "char.h" #define UPDATE() \ - if (!w->ww_noupdate && w->ww_cur.r >= 0 && w->ww_cur.r < wwnrow && \ - wwtouched[w->ww_cur.r]) \ + if (!ISSET(w->ww_wflags, WWW_NOUPDATE) && w->ww_cur.r >= 0 && \ + w->ww_cur.r < wwnrow && wwtouched[w->ww_cur.r]) \ wwupdate1(w->ww_cur.r, w->ww_cur.r + 1) /* @@ -56,23 +60,23 @@ * p and q. Essentially, we implement a stack of depth 2, * to avoid recursion, which might be a better idea. */ -wwwrite(w, p, n) -register struct ww *w; -register unsigned char *p; -int n; +int +wwwrite(struct ww *w, const char *p, int n) { - char hascursor; - unsigned char *savep = p; - unsigned char *q = p + n; - char *r = 0; - char *s; + int hascursor; + const char *savep = p; + const char *q = p + n; + const char *r = 0; + const char *s = 0; #ifdef lint s = 0; /* define it before possible use */ #endif - if (hascursor = w->ww_hascursor) + hascursor = ISSET(w->ww_wflags, WWW_HASCURSOR); + if (hascursor) wwcursor(w, 0); - while (p < q && !w->ww_stopped && (!wwinterrupt() || w->ww_nointr)) { + while (p < q && !ISSET(w->ww_pflags, WWP_STOPPED) && + (!wwinterrupt() || ISSET(w->ww_wflags, WWW_NOINTR))) { if (r && !*p) { p = r; q = s; @@ -80,16 +84,18 @@ int n; continue; } if (w->ww_wstate == 0 && - (isprt(*p) || w->ww_unctrl && isunctrl(*p))) { - register i; - register union ww_char *bp; + (isprt(*p) || + (ISSET(w->ww_wflags, WWW_UNCTRL) && isunctrl(*p)))) { + int i; + union ww_char *bp; int col, col1; - if (w->ww_insert) { /* this is very slow */ + if (ISSET(w->ww_wflags, WWW_INSERT)) { + /* this is very slow */ if (*p == '\t') { p++; w->ww_cur.c += 8 - - (w->ww_cur.c - w->ww_w.l & 7); + ((w->ww_cur.c - w->ww_w.l) & 7); goto chklf; } if (!isprt(*p)) { @@ -111,7 +117,7 @@ int n; q = s; r = 0; } else if (*p == '\t') { - register tmp = 8 - (i - w->ww_w.l & 7); + int tmp = 8 - ((i - w->ww_w.l) & 7); p++; i += tmp; bp += tmp; @@ -119,7 +125,8 @@ int n; bp++->c_w = *p++ | w->ww_modes << WWC_MSHIFT; i++; - } else if (w->ww_unctrl && isunctrl(*p)) { + } else if (ISSET(w->ww_wflags, WWW_UNCTRL) && + isunctrl(*p)) { r = p + 1; s = q; p = unctrl(*p); @@ -131,9 +138,10 @@ int n; w->ww_cur.c = i; if (w->ww_cur.r >= w->ww_i.t && w->ww_cur.r < w->ww_i.b) { - register union ww_char *ns = wwns[w->ww_cur.r]; - register char *smap = &wwsmap[w->ww_cur.r][col]; - register char *win = w->ww_win[w->ww_cur.r]; + union ww_char *ns = wwns[w->ww_cur.r]; + unsigned char *smap = + &wwsmap[w->ww_cur.r][col]; + char *win = w->ww_win[w->ww_cur.r]; int nchanged = 0; bp = w->ww_buf[w->ww_cur.r]; @@ -153,7 +161,7 @@ int n; case 0: switch (*p++) { case '\n': - if (w->ww_mapnl) + if (ISSET(w->ww_wflags, WWW_MAPNL)) crlf: w->ww_cur.c = w->ww_w.l; lf: @@ -191,7 +199,7 @@ int n; w->ww_wstate = 0; switch (*p++) { case '@': - w->ww_insert = 1; + SET(w->ww_wflags, WWW_INSERT); break; case 'A': up: @@ -244,7 +252,7 @@ int n; wwdelchar(w, w->ww_cur.r, w->ww_cur.c); break; case 'O': - w->ww_insert = 0; + CLR(w->ww_wflags, WWW_INSERT); break; case 'P': wwinschar(w, w->ww_cur.r, w->ww_cur.c, ' ', 0); diff --git a/usr.bin/window/xx.c b/usr.bin/window/xx.c index 1de9abbb77..5e66e17e29 100644 --- a/usr.bin/window/xx.c +++ b/usr.bin/window/xx.c @@ -1,3 +1,5 @@ +/* $NetBSD: xx.c,v 1.7 2003/08/07 11:17:46 agc Exp $ */ + /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,20 +30,27 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)xx.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/xx.c,v 1.2.12.1 2001/05/17 09:45:02 obrien Exp $ - * $DragonFly: src/usr.bin/window/xx.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)xx.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: xx.c,v 1.7 2003/08/07 11:17:46 agc Exp $"); +#endif +#endif /* not lint */ + #include #include - -#include "ww.h" +#define EXTERN #include "xx.h" +#undef EXTERN +#include "defs.h" #include "tt.h" -xxinit() +int +xxinit(void) { if (ttinit() < 0) return -1; @@ -63,7 +68,8 @@ xxinit() return 0; } -xxstart() +void +xxstart(void) { (*tt.tt_start)(); if (tt.tt_ntoken > 0) @@ -71,7 +77,8 @@ xxstart() xxreset1(); /* might be a restart */ } -xxreset() +void +xxreset(void) { if (tt.tt_ntoken > 0) ccreset(); @@ -79,9 +86,10 @@ xxreset() (*tt.tt_reset)(); } -xxreset1() +void +xxreset1(void) { - register struct xx *xp, *xq; + struct xx *xp, *xq; for (xp = xx_head; xp != 0; xp = xq) { xq = xp->link; @@ -91,7 +99,8 @@ xxreset1() xxbufp = xxbuf; } -xxend() +void +xxend(void) { if (tt.tt_scroll_top != 0 || tt.tt_scroll_bot != tt.tt_nrow - 1) /* tt.tt_setscroll is known to be defined */ @@ -108,9 +117,9 @@ xxend() } struct xx * -xxalloc() +xxalloc(void) { - register struct xx *xp; + struct xx *xp; if (xxbufp > xxbufe) abort(); @@ -128,16 +137,17 @@ xxalloc() return xp; } -xxfree(xp) - register struct xx *xp; +void +xxfree(struct xx *xp) { xp->link = xx_freelist; xx_freelist = xp; } -xxmove(row, col) +void +xxmove(int row, int col) { - register struct xx *xp = xx_tail; + struct xx *xp = xx_tail; if (xp == 0 || xp->cmd != xc_move) { xp = xxalloc(); @@ -147,13 +157,14 @@ xxmove(row, col) xp->arg1 = col; } -xxscroll(dir, top, bot) +void +xxscroll(int dir, int top, int bot) { - register struct xx *xp = xx_tail; + struct xx *xp = xx_tail; if (xp != 0 && xp->cmd == xc_scroll && xp->arg1 == top && xp->arg2 == bot && - (xp->arg0 < 0 && dir < 0 || xp->arg0 > 0 && dir > 0)) { + ((xp->arg0 < 0 && dir < 0) || (xp->arg0 > 0 && dir > 0))) { xp->arg0 += dir; return; } @@ -164,9 +175,10 @@ xxscroll(dir, top, bot) xp->arg2 = bot; } -xxinschar(row, col, c, m) +void +xxinschar(int row, int col, int c, int m) { - register struct xx *xp; + struct xx *xp; xp = xxalloc(); xp->cmd = xc_inschar; @@ -176,9 +188,10 @@ xxinschar(row, col, c, m) xp->arg3 = m; } -xxinsspace(row, col) +void +xxinsspace(int row, int col) { - register struct xx *xp = xx_tail; + struct xx *xp = xx_tail; if (xp != 0 && xp->cmd == xc_insspace && xp->arg0 == row && col >= xp->arg1 && col <= xp->arg1 + xp->arg2) { @@ -192,9 +205,10 @@ xxinsspace(row, col) xp->arg2 = 1; } -xxdelchar(row, col) +void +xxdelchar(int row, int col) { - register struct xx *xp = xx_tail; + struct xx *xp = xx_tail; if (xp != 0 && xp->cmd == xc_delchar && xp->arg0 == row && xp->arg1 == col) { @@ -208,37 +222,40 @@ xxdelchar(row, col) xp->arg2 = 1; } -xxclear() +void +xxclear(void) { - register struct xx *xp; + struct xx *xp; xxreset1(); xp = xxalloc(); xp->cmd = xc_clear; } -xxclreos(row, col) +void +xxclreos(int row, int col) { - register struct xx *xp = xxalloc(); + struct xx *xp = xxalloc(); xp->cmd = xc_clreos; xp->arg0 = row; xp->arg1 = col; } -xxclreol(row, col) +void +xxclreol(int row, int col) { - register struct xx *xp = xxalloc(); + struct xx *xp = xxalloc(); xp->cmd = xc_clreol; xp->arg0 = row; xp->arg1 = col; } -xxwrite(row, col, p, n, m) - char *p; +void +xxwrite(int row, int col, char *p, int n, int m) { - register struct xx *xp; + struct xx *xp; if (xxbufp + n + 1 > xxbufe) xxflush(0); @@ -249,7 +266,7 @@ xxwrite(row, col, p, n, m) xp->arg2 = n; xp->arg3 = m; xp->buf = xxbufp; - bcopy(p, xxbufp, n); + memmove(xxbufp, p, n); xxbufp += n; *xxbufp++ = char_sep; } diff --git a/usr.bin/window/xx.h b/usr.bin/window/xx.h index ebb98d6ccd..c4d9caf2e9 100644 --- a/usr.bin/window/xx.h +++ b/usr.bin/window/xx.h @@ -1,3 +1,5 @@ +/* $NetBSD: xx.h,v 1.7 2003/08/07 11:17:47 agc Exp $ */ + /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,10 +32,12 @@ * SUCH DAMAGE. * * @(#)xx.h 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/xx.h,v 1.1.1.1.14.1 2001/05/17 09:45:02 obrien Exp $ - * $DragonFly: src/usr.bin/window/xx.h,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#ifndef EXTERN +#define EXTERN extern +#endif + struct xx { enum { xc_move, xc_scroll, xc_inschar, xc_insspace, xc_delchar, xc_clear, xc_clreos, xc_clreol, xc_write } cmd; @@ -49,12 +49,29 @@ struct xx { struct xx *link; }; -struct xx *xxalloc(); +EXTERN struct xx *xx_head, *xx_tail; +EXTERN struct xx *xx_freelist; -struct xx *xx_head, *xx_tail; -struct xx *xx_freelist; - -char *xxbuf, *xxbufp, *xxbufe; -int xxbufsize; +EXTERN char *xxbuf, *xxbufp, *xxbufe; +EXTERN int xxbufsize; #define char_sep '\0' + +struct xx *xxalloc(void); +void xxclear(void); +void xxclreol(int, int); +void xxclreos(int, int); +void xxdelchar(int, int); +void xxend(void); +void xxflush(int); +void xxflush_scroll(struct xx *); +void xxfree(struct xx *); +int xxinit(void); +void xxinschar(int, int, int, int); +void xxinsspace(int, int); +void xxmove(int, int); +void xxreset(void); +void xxreset1(void); +void xxscroll(int, int, int); +void xxstart(void); +void xxwrite(int, int, char *, int, int); diff --git a/usr.bin/window/xxflush.c b/usr.bin/window/xxflush.c index 8dd2f2f703..71feef53a7 100644 --- a/usr.bin/window/xxflush.c +++ b/usr.bin/window/xxflush.c @@ -1,3 +1,5 @@ +/* $NetBSD: xxflush.c,v 1.6 2003/08/07 11:17:47 agc Exp $ */ + /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,20 +30,25 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)xxflush.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/window/xxflush.c,v 1.1.1.1.14.1 2001/05/17 09:45:02 obrien Exp $ - * $DragonFly: src/usr.bin/window/xxflush.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ */ +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)xxflush.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: xxflush.c,v 1.6 2003/08/07 11:17:47 agc Exp $"); +#endif +#endif /* not lint */ + #include "ww.h" #include "xx.h" #include "tt.h" -xxflush(intr) - register intr; +void +xxflush(int intr) { - register struct xx *xp, *xq; + struct xx *xp, *xq; for (xp = xx_head; xp != 0 && !(intr && wwinterrupt()); xp = xq) { switch (xp->cmd) { @@ -96,10 +99,10 @@ xxflush(intr) ttflush(); } -xxflush_scroll(xp) - register struct xx *xp; +void +xxflush_scroll(struct xx *xp) { - register struct xx *xq; + struct xx *xq; top: if (xp->arg0 == 0) diff --git a/usr.bin/xlint/Makefile.inc b/usr.bin/xlint/Makefile.inc new file mode 100644 index 0000000000..ad6e982e6d --- /dev/null +++ b/usr.bin/xlint/Makefile.inc @@ -0,0 +1,3 @@ +WARNS?= 1 + +.include "../Makefile.inc" diff --git a/usr.bin/xlint/lint1/Makefile b/usr.bin/xlint/lint1/Makefile index 224390c486..7da5035ba6 100644 --- a/usr.bin/xlint/lint1/Makefile +++ b/usr.bin/xlint/lint1/Makefile @@ -5,7 +5,6 @@ PROG= lint1 SRCS= cgram.y scan.l mem1.c mem.c err.c main1.c decl.c tree.c func.c \ init.c emit.c emit1.c y.tab.h -WARNS?= 1 NOMAN= LDADD+= -ll DPADD+= ${LIBL} diff --git a/usr.bin/xlint/lint2/Makefile b/usr.bin/xlint/lint2/Makefile index f315d65b53..ca88191bf5 100644 --- a/usr.bin/xlint/lint2/Makefile +++ b/usr.bin/xlint/lint2/Makefile @@ -5,7 +5,6 @@ PROG= lint2 SRCS= main2.c hash.c read.c mem.c mem2.c chk.c msg.c emit.c emit2.c -WARNS?= 1 NOMAN= CFLAGS+=-I${.CURDIR}/../lint1 LINTFLAGS=-abehrz diff --git a/usr.bin/xlint/xlint/Makefile b/usr.bin/xlint/xlint/Makefile index e932b4a032..a36e1543cd 100644 --- a/usr.bin/xlint/xlint/Makefile +++ b/usr.bin/xlint/xlint/Makefile @@ -8,9 +8,7 @@ PROG= xlint PROGNAME=lint SRCS= xlint.c mem.c MAN= lint.1 -WARNS?= 2 CFLAGS+=-I${.CURDIR}/../lint1 -.include "${.CURDIR}/../../Makefile.inc" .include diff --git a/usr.sbin/802_11/Makefile.inc b/usr.sbin/802_11/Makefile.inc index e7b8609699..5b4af7a2f1 100644 --- a/usr.sbin/802_11/Makefile.inc +++ b/usr.sbin/802_11/Makefile.inc @@ -1,3 +1,5 @@ # $DragonFly: src/usr.sbin/802_11/Makefile.inc,v 1.1 2006/06/24 07:29:44 sephe Exp $ +WARNS?= 0 + .include "../Makefile.inc" diff --git a/usr.sbin/IPXrouted/Makefile b/usr.sbin/IPXrouted/Makefile index 9d977a64e2..d1f64ece9f 100644 --- a/usr.sbin/IPXrouted/Makefile +++ b/usr.sbin/IPXrouted/Makefile @@ -9,4 +9,6 @@ SRCS+= sap_input.c sap_tables.c sap_output.c DPADD= ${LIBCOMPAT} ${LIBIPX} LDADD= -lcompat -lipx +WARNS?= 1 + .include diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 9640b5ebe6..97e627736e 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -29,7 +29,6 @@ SUBDIR= 802_11 \ clog \ config \ cron \ - crunch \ daemon \ dconschat \ devinfo \ diff --git a/usr.sbin/Makefile.inc b/usr.sbin/Makefile.inc index fd92864744..b0f724d2d6 100644 --- a/usr.sbin/Makefile.inc +++ b/usr.sbin/Makefile.inc @@ -1,3 +1,4 @@ # @(#)Makefile.inc 8.1 (Berkeley) 6/6/93 BINDIR?= /usr/sbin +WARNS?= 6 diff --git a/usr.sbin/ac/Makefile b/usr.sbin/ac/Makefile index fa3b5460a2..9a5e35cfb0 100644 --- a/usr.sbin/ac/Makefile +++ b/usr.sbin/ac/Makefile @@ -3,6 +3,7 @@ PROG= ac MAN= ac.8 +WARNS?= 3 # If "CONSOLE_TTY" is not defined, this program is compatible with the # traditional implementation (using SunOS 4.x as the sample traditional diff --git a/usr.sbin/accton/Makefile b/usr.sbin/accton/Makefile index 330f03d75a..ac78414c3a 100644 --- a/usr.sbin/accton/Makefile +++ b/usr.sbin/accton/Makefile @@ -4,6 +4,5 @@ PROG= accton MAN= accton.8 -WARNS?= 6 .include diff --git a/usr.sbin/acpi/Makefile.inc b/usr.sbin/acpi/Makefile.inc index 4f4ff9bb5a..68e40966da 100644 --- a/usr.sbin/acpi/Makefile.inc +++ b/usr.sbin/acpi/Makefile.inc @@ -18,6 +18,8 @@ SRCS+= ${.OBJDIR}/acpi.h ${.OBJDIR}/platform/acenv.h CLEANFILES+= ${.OBJDIR}/acpi.h CLEANDIRS+= ${.OBJDIR}/platform +WARNS?= 1 + .if exists(${.CURDIR}/../../Makefile.inc) .include "${.CURDIR}/../../Makefile.inc" .endif diff --git a/usr.sbin/acpi/acpidump/Makefile b/usr.sbin/acpi/acpidump/Makefile index 3cf5b509e4..e1a7609439 100644 --- a/usr.sbin/acpi/acpidump/Makefile +++ b/usr.sbin/acpi/acpidump/Makefile @@ -4,6 +4,5 @@ PROG= acpidump MAN= acpidump.8 SRCS= acpi.c acpi_user.c acpidump.c -WARNS?= 6 .include diff --git a/usr.sbin/amd/Makefile.inc b/usr.sbin/amd/Makefile.inc index 42a2ea2948..add2c42b3d 100644 --- a/usr.sbin/amd/Makefile.inc +++ b/usr.sbin/amd/Makefile.inc @@ -31,6 +31,7 @@ RPCCOM= rpcgen MOUNT_X= ${DESTDIR}/usr/include/rpcsvc/mount.x NFS_PROT_X= ${DESTDIR}/usr/include/rpcsvc/nfs_prot.x +WARNS?= 0 .if exists(${.CURDIR}/../../Makefile.inc) .include "${.CURDIR}/../../Makefile.inc" diff --git a/usr.sbin/ancontrol/Makefile b/usr.sbin/ancontrol/Makefile index fec37afc3e..96bdb5d5f0 100644 --- a/usr.sbin/ancontrol/Makefile +++ b/usr.sbin/ancontrol/Makefile @@ -8,6 +8,4 @@ CFLAGS+= -I${.CURDIR}/../../sys -DANCACHE DPADD= ${LIBMD} LDADD= -lmd -WARNS?= 6 - .include diff --git a/usr.sbin/apm/Makefile b/usr.sbin/apm/Makefile index cd518c3505..08e029c24a 100644 --- a/usr.sbin/apm/Makefile +++ b/usr.sbin/apm/Makefile @@ -6,5 +6,4 @@ LINKS= ${BINDIR}/apm ${BINDIR}/zzz MAN= apm.8 MLINKS= apm.8 apmconf.8 apm.8 zzz.8 -WARNS?= 6 .include diff --git a/usr.sbin/apmd/Makefile b/usr.sbin/apmd/Makefile index c645f12a82..0f18a67b6e 100644 --- a/usr.sbin/apmd/Makefile +++ b/usr.sbin/apmd/Makefile @@ -3,6 +3,7 @@ PROG= apmd SRCS= apmd.c apmdlex.l apmdparse.y y.tab.h +WARNS?= 0 DPADD= ${LIBL} ${LIBUTIL} LDADD= -ll -lutil diff --git a/usr.sbin/arp/Makefile b/usr.sbin/arp/Makefile index 680aba3a8a..199b109295 100644 --- a/usr.sbin/arp/Makefile +++ b/usr.sbin/arp/Makefile @@ -3,7 +3,6 @@ # $DragonFly: src/usr.sbin/arp/Makefile,v 1.3 2005/01/17 01:49:24 cpressey Exp $ PROG= arp -WARNS?= 6 MAN= arp.4 arp.8 .include diff --git a/usr.sbin/asf/asf.c b/usr.sbin/asf/asf.c index fc24625e5b..6fbd9698c3 100644 --- a/usr.sbin/asf/asf.c +++ b/usr.sbin/asf/asf.c @@ -94,15 +94,15 @@ tokenize(char *cptr, char *token[], int maxtoken) } static char * -findmodule(char *modules_path, const char *module_name) +findmodule(char *mod_path, const char *module_name) { - char *const path_argv[2] = { modules_path, NULL }; + char *const path_argv[2] = { mod_path, NULL }; char *module_path = NULL; - int module_name_len = strlen(module_name); + size_t module_name_len = strlen(module_name); FTS *fts; FTSENT *ftsent; - if (modules_path == NULL) { + if (mod_path == NULL) { fprintf(stderr, "Can't allocate memory to traverse a path: %s (%d)\n", strerror(errno), @@ -113,7 +113,7 @@ findmodule(char *modules_path, const char *module_name) if (fts == NULL) { fprintf(stderr, "Can't begin traversing path %s: %s (%d)\n", - modules_path, + mod_path, strerror(errno), errno); exit(1); @@ -124,7 +124,7 @@ findmodule(char *modules_path, const char *module_name) ftsent->fts_info == FTS_NS) { fprintf(stderr, "Error while traversing path %s: %s (%d)\n", - modules_path, + mod_path, strerror(errno), errno); exit(1); @@ -135,11 +135,11 @@ findmodule(char *modules_path, const char *module_name) continue; if (asprintf(&module_path, "%.*s", - ftsent->fts_pathlen, + (int)ftsent->fts_pathlen, ftsent->fts_path) == -1) { fprintf(stderr, "Can't allocate memory traversing path %s: %s (%d)\n", - modules_path, + mod_path, strerror(errno), errno); exit(1); @@ -149,13 +149,13 @@ findmodule(char *modules_path, const char *module_name) if (ftsent == NULL && errno != 0) { fprintf(stderr, "Couldn't complete traversing path %s: %s (%d)\n", - modules_path, + mod_path, strerror(errno), errno); exit(1); } fts_close(fts); - free(modules_path); + free(mod_path); return (module_path); } @@ -245,10 +245,10 @@ main(int argc, char *argv[]) while (fgets(buf, MAXLINE, kldstat)) { if ((!(strstr(buf, "kernel"))) && buf[0] != 'I') { - quad_t base; - quad_t textaddr; - quad_t dataaddr; - quad_t bssaddr; + long long base; + long long textaddr = 0; + long long dataaddr = 0; + long long bssaddr = 0; tokens = tokenize(buf, token, MAXTOKEN); if (tokens <= 1) diff --git a/usr.sbin/atm/Makefile.inc b/usr.sbin/atm/Makefile.inc index a946230a84..d31d170dac 100644 --- a/usr.sbin/atm/Makefile.inc +++ b/usr.sbin/atm/Makefile.inc @@ -28,4 +28,6 @@ # # +WARNS?= 2 + .include "../Makefile.inc" diff --git a/usr.sbin/atm/atmarpd/atmarpd.c b/usr.sbin/atm/atmarpd/atmarpd.c index 8c27fa18a1..9d030f791a 100644 --- a/usr.sbin/atm/atmarpd/atmarpd.c +++ b/usr.sbin/atm/atmarpd/atmarpd.c @@ -287,8 +287,7 @@ daemon_bypass: /* * Set up signal handlers */ - rc = (int)signal(SIGINT, atmarp_sigint); - if (rc == -1) { + if (signal(SIGINT, atmarp_sigint) == SIG_ERR) { atmarp_log(LOG_ERR, "SIGINT signal setup failed"); exit(1); } diff --git a/usr.sbin/atm/scspd/scspd.c b/usr.sbin/atm/scspd/scspd.c index fdf6ef4743..4d1787eae5 100644 --- a/usr.sbin/atm/scspd/scspd.c +++ b/usr.sbin/atm/scspd/scspd.c @@ -311,14 +311,12 @@ daemon_bypass: /* * Set up signal handlers */ - rc = (int)signal(SIGHUP, scsp_sighup); - if (rc == -1) { + if (signal(SIGHUP, scsp_sighup) == SIG_ERR) { scsp_log(LOG_ERR, "SIGHUP signal setup failed"); exit(1); } - rc = (int)signal(SIGINT, scsp_sigint); - if (rc == -1) { + if (signal(SIGINT, scsp_sigint) == SIG_ERR) { scsp_log(LOG_ERR, "SIGINT signal setup failed"); exit(1); } diff --git a/usr.sbin/authpf/Makefile b/usr.sbin/authpf/Makefile index e18e6e395a..7dbe01d289 100644 --- a/usr.sbin/authpf/Makefile +++ b/usr.sbin/authpf/Makefile @@ -9,7 +9,6 @@ BINMODE= 6555 SRCS= authpf.c parse.y pfctl_parser.c pf_print_state.c SRCS+= pfctl_radix.c pfctl_osfp.c SRCS+= pfctl_altq.c -WARNS?= 6 .PATH: ${.CURDIR}/../pfctl CFLAGS+= -I${.CURDIR}/../pfctl diff --git a/usr.sbin/battd/Makefile b/usr.sbin/battd/Makefile index d98157189b..d0a2e68ebf 100644 --- a/usr.sbin/battd/Makefile +++ b/usr.sbin/battd/Makefile @@ -6,6 +6,5 @@ MAN= battd.8 LDADD+= -lutil DPADD+= ${LIBUTIL} -WARNS?= 6 .include diff --git a/usr.sbin/boot0cfg/Makefile b/usr.sbin/boot0cfg/Makefile index 497e87c6d9..4c73efea2a 100644 --- a/usr.sbin/boot0cfg/Makefile +++ b/usr.sbin/boot0cfg/Makefile @@ -2,7 +2,6 @@ # $DragonFly: src/usr.sbin/boot0cfg/Makefile,v 1.3 2005/01/17 01:49:24 cpressey Exp $ PROG= boot0cfg -WARNS?= 6 MAN= boot0cfg.8 .include diff --git a/usr.sbin/bootparamd/Makefile.inc b/usr.sbin/bootparamd/Makefile.inc index 26c6f1c71b..9ab33bd7c6 100644 --- a/usr.sbin/bootparamd/Makefile.inc +++ b/usr.sbin/bootparamd/Makefile.inc @@ -1,3 +1,5 @@ # @(#)Makefile.inc 5.1 (Berkeley) 5/11/90 -BINDIR?= /usr/sbin +WARNS?= 1 + +.include "../Makefile.inc" diff --git a/usr.sbin/btconfig/Makefile b/usr.sbin/btconfig/Makefile index ff8fb14232..621b7380ec 100644 --- a/usr.sbin/btconfig/Makefile +++ b/usr.sbin/btconfig/Makefile @@ -8,6 +8,5 @@ MAN = btconfig.8 CFLAGS+= -I${.CURDIR}/../../sys DPADD+= ${LIBBLUETOOTH} LDADD+= -lbluetooth -WARNS?= 6 .include diff --git a/usr.sbin/bthcid/Makefile b/usr.sbin/bthcid/Makefile index fd67c17665..e8140ca9a5 100644 --- a/usr.sbin/bthcid/Makefile +++ b/usr.sbin/bthcid/Makefile @@ -4,6 +4,7 @@ PROG= bthcid MAN= bthcid.8 bthcid.conf.5 SRCS= bthcid.c hci.c client.c config.c lexer.l parser.y +WARNS?= 0 DPADD+= ${LIBBLUETOOTH} ${LIBEVENT} ${LIBUTIL} LDADD+= -lbluetooth -levent -lutil diff --git a/usr.sbin/burncd/Makefile b/usr.sbin/burncd/Makefile index 619628a5c3..1451dfc718 100644 --- a/usr.sbin/burncd/Makefile +++ b/usr.sbin/burncd/Makefile @@ -3,5 +3,6 @@ PROG= burncd MAN= burncd.8 +WARNS?= 2 .include diff --git a/usr.sbin/cdcontrol/Makefile b/usr.sbin/cdcontrol/Makefile index 3e0b3d46f2..9111e38bdd 100644 --- a/usr.sbin/cdcontrol/Makefile +++ b/usr.sbin/cdcontrol/Makefile @@ -2,7 +2,6 @@ # $DragonFly: src/usr.sbin/cdcontrol/Makefile,v 1.3 2005/01/17 01:49:24 cpressey Exp $ PROG= cdcontrol -WARNS?= 6 DPADD= ${LIBEDIT} ${LIBTERMCAP} LDADD= -ledit -ltermcap diff --git a/usr.sbin/chkgrp/Makefile b/usr.sbin/chkgrp/Makefile index bb12b31580..475a0e3b17 100644 --- a/usr.sbin/chkgrp/Makefile +++ b/usr.sbin/chkgrp/Makefile @@ -4,5 +4,4 @@ PROG= chkgrp MAN= chkgrp.8 -WARNS?= 6 .include diff --git a/usr.sbin/chown/Makefile b/usr.sbin/chown/Makefile index 02e24e27eb..703e1ac71f 100644 --- a/usr.sbin/chown/Makefile +++ b/usr.sbin/chown/Makefile @@ -7,5 +7,4 @@ CFLAGS+=-DSUPPORT_DOT MAN= chgrp.1 chown.8 LINKS= ${BINDIR}/chown /usr/bin/chgrp -WARNS?= 6 .include diff --git a/usr.sbin/chroot/Makefile b/usr.sbin/chroot/Makefile index 363b4df1cc..e73e42f0e6 100644 --- a/usr.sbin/chroot/Makefile +++ b/usr.sbin/chroot/Makefile @@ -3,7 +3,6 @@ # $DragonFly: src/usr.sbin/chroot/Makefile,v 1.3 2004/11/28 16:38:21 liamfoy Exp $ PROG= chroot -WARNS?= 6 MAN= chroot.8 .include diff --git a/usr.sbin/ckdist/Makefile b/usr.sbin/ckdist/Makefile index ec034f84cf..726c2b2873 100644 --- a/usr.sbin/ckdist/Makefile +++ b/usr.sbin/ckdist/Makefile @@ -1,11 +1,11 @@ # $FreeBSD: src/usr.sbin/ckdist/Makefile,v 1.2 1999/08/28 01:15:46 peter Exp $ # $DragonFly: src/usr.sbin/ckdist/Makefile,v 1.2 2003/06/17 04:29:52 dillon Exp $ -PROG= ckdist - .PATH: ${.CURDIR}/../../usr.bin/cksum +PROG= ckdist SRCS= ckdist.c crc.c +WARNS?= 3 DPADD= ${LIBMD} LDADD= -lmd diff --git a/usr.sbin/clog/Makefile b/usr.sbin/clog/Makefile index 580810fe6d..9744a5e7b2 100644 --- a/usr.sbin/clog/Makefile +++ b/usr.sbin/clog/Makefile @@ -3,8 +3,6 @@ # $DragonFly: src/usr.sbin/clog/Makefile,v 1.3 2007/04/09 09:45:12 swildner Exp $ PROG= clog -WARNS?= 6 -SRCS= clog.c MAN8= clog.8 .include diff --git a/usr.sbin/config/Makefile b/usr.sbin/config/Makefile index b3b475d52c..5e53eab7b9 100644 --- a/usr.sbin/config/Makefile +++ b/usr.sbin/config/Makefile @@ -3,7 +3,6 @@ # $DragonFly: src/usr.sbin/config/Makefile,v 1.5 2005/01/12 04:03:46 cpressey Exp $ PROG= config -WARNS?= 6 CFLAGS+=-I. -I${.CURDIR} SRCS= config.y main.c lang.l mkioconf.c mkmakefile.c mkheaders.c \ mkoptions.c y.tab.h diff --git a/usr.sbin/cron/Makefile.inc b/usr.sbin/cron/Makefile.inc index eec03de23c..9570c7b51e 100644 --- a/usr.sbin/cron/Makefile.inc +++ b/usr.sbin/cron/Makefile.inc @@ -7,4 +7,6 @@ LIBCRON=${.OBJDIR}/../lib/libcron.a LIBCRON=${.CURDIR}/../lib/libcron.a .endif +WARNS?= 1 + .include "../Makefile.inc" diff --git a/usr.sbin/crunch/Makefile.inc b/usr.sbin/crunch/Makefile.inc deleted file mode 100644 index da42105052..0000000000 --- a/usr.sbin/crunch/Makefile.inc +++ /dev/null @@ -1,2 +0,0 @@ -# modify to taste -BINDIR?= /usr/bin diff --git a/usr.sbin/daemon/Makefile b/usr.sbin/daemon/Makefile index 1f54ea2aba..4ad9690f16 100644 --- a/usr.sbin/daemon/Makefile +++ b/usr.sbin/daemon/Makefile @@ -2,7 +2,6 @@ # $DragonFly: src/usr.sbin/daemon/Makefile,v 1.3 2004/12/21 23:30:57 liamfoy Exp $ PROG= daemon -WARNS?= 6 MAN= daemon.8 .include diff --git a/usr.sbin/dconschat/Makefile b/usr.sbin/dconschat/Makefile index 25aecd87fa..0c4c5f9200 100644 --- a/usr.sbin/dconschat/Makefile +++ b/usr.sbin/dconschat/Makefile @@ -2,8 +2,8 @@ # $DragonFly: src/usr.sbin/dconschat/Makefile,v 1.1 2004/09/23 06:38:29 simokawa Exp $ PROG= dconschat -SRCS= dconschat.c MAN= dconschat.8 +WARNS?= 1 CFLAGS+= -I${.CURDIR}/../../sys diff --git a/usr.sbin/dev_mkdb/Makefile b/usr.sbin/dev_mkdb/Makefile index e93b774c49..d508c966ef 100644 --- a/usr.sbin/dev_mkdb/Makefile +++ b/usr.sbin/dev_mkdb/Makefile @@ -4,6 +4,5 @@ PROG= dev_mkdb MAN= dev_mkdb.8 -WARNS?= 6 .include diff --git a/usr.sbin/devinfo/Makefile b/usr.sbin/devinfo/Makefile index a8931121da..d637de97d4 100644 --- a/usr.sbin/devinfo/Makefile +++ b/usr.sbin/devinfo/Makefile @@ -4,8 +4,6 @@ PROG= devinfo MAN= devinfo.8 -WARNS?= 6 - DPADD= ${LIBDEVINFO} LDADD= -ldevinfo diff --git a/usr.sbin/dntpd/Makefile b/usr.sbin/dntpd/Makefile index 107dfdeef8..72783a5ccc 100644 --- a/usr.sbin/dntpd/Makefile +++ b/usr.sbin/dntpd/Makefile @@ -5,7 +5,6 @@ SRCS= main.c socket.c ntpreq.c convert.c log.c client.c system.c LDADD += -lm -WARNS?= 6 MAN= dntpd.8 .include diff --git a/usr.sbin/editmap/Makefile b/usr.sbin/editmap/Makefile index 94ac430be8..94b7736a90 100644 --- a/usr.sbin/editmap/Makefile +++ b/usr.sbin/editmap/Makefile @@ -7,6 +7,7 @@ SENDMAIL_DIR=${.CURDIR}/../../contrib/sendmail-8.14 PROG= editmap SRCS= editmap.c MAN= editmap.8 +WARNS?= 2 CFLAGS+= -I${SENDMAIL_DIR}/sendmail -I${SENDMAIL_DIR}/include -I. CFLAGS+= -DNEWDB -DNOT_SENDMAIL diff --git a/usr.sbin/fdcontrol/Makefile b/usr.sbin/fdcontrol/Makefile index 141f30c7f3..a7f058d58e 100644 --- a/usr.sbin/fdcontrol/Makefile +++ b/usr.sbin/fdcontrol/Makefile @@ -1,7 +1,8 @@ # $FreeBSD: src/usr.sbin/fdcontrol/Makefile,v 1.1.1.1.14.1 2001/04/25 12:09:33 ru Exp $ # $DragonFly: src/usr.sbin/fdcontrol/Makefile,v 1.2 2003/06/17 04:29:53 dillon Exp $ -PROG = fdcontrol -MAN = fdcontrol.8 +PROG= fdcontrol +MAN= fdcontrol.8 +WARNS?= 2 .include diff --git a/usr.sbin/fdformat/Makefile b/usr.sbin/fdformat/Makefile index 74f2eb5efd..feeeea5672 100644 --- a/usr.sbin/fdformat/Makefile +++ b/usr.sbin/fdformat/Makefile @@ -2,6 +2,5 @@ # $DragonFly: src/usr.sbin/fdformat/Makefile,v 1.3 2007/10/01 08:25:12 swildner Exp $ PROG= fdformat -WARNS?= 6 .include diff --git a/usr.sbin/fdwrite/Makefile b/usr.sbin/fdwrite/Makefile index 4aa33b3c76..3cdc072a58 100644 --- a/usr.sbin/fdwrite/Makefile +++ b/usr.sbin/fdwrite/Makefile @@ -12,5 +12,5 @@ # PROG= fdwrite -WARNS?= 6 + .include diff --git a/usr.sbin/fwcontrol/Makefile b/usr.sbin/fwcontrol/Makefile index 08a97913b4..f206226bde 100644 --- a/usr.sbin/fwcontrol/Makefile +++ b/usr.sbin/fwcontrol/Makefile @@ -4,6 +4,7 @@ PROG= fwcontrol SRCS= fwcontrol.c fwcrom.c fwdv.c MAN= fwcontrol.8 +WARNS?= 1 .PATH: ${.CURDIR}/../../sys/bus/firewire diff --git a/usr.sbin/gifconfig/Makefile b/usr.sbin/gifconfig/Makefile index 1ae9318db9..b1b2767712 100644 --- a/usr.sbin/gifconfig/Makefile +++ b/usr.sbin/gifconfig/Makefile @@ -16,6 +16,7 @@ PROG= gifconfig MAN= gifconfig.8 +WARNS?= 2 CFLAGS+=-DINET6 diff --git a/usr.sbin/i4b/Makefile.inc b/usr.sbin/i4b/Makefile.inc index 3715a3b459..5a9be6f8ec 100644 --- a/usr.sbin/i4b/Makefile.inc +++ b/usr.sbin/i4b/Makefile.inc @@ -14,4 +14,6 @@ I4B_EXTERNAL_MONITOR = 1 # at all #I4B_NOTCPIP_MONITOR = 1 +WARNS?= 1 + .include "${.CURDIR}/../../Makefile.inc" diff --git a/usr.sbin/i4b/isdnd/log.c b/usr.sbin/i4b/isdnd/log.c index ebb6af0dc9..29583dcce4 100644 --- a/usr.sbin/i4b/isdnd/log.c +++ b/usr.sbin/i4b/isdnd/log.c @@ -167,15 +167,7 @@ dolog(int what, const char *fmt, ...) * to write to the last column in the logfilewindow without causing an * automatic newline to occur resulting in a blank line in that window. */ -#ifdef __DragonFly__ -#include -#endif -#if defined(__DragonFly__) -#warning "FreeBSD ncurses is buggy: write to last column = auto newline!" COLS-((strlen(dp))+(strlen(logtab[what].text))+3), buffer); -#else - (int)(COLS-((strlen(dp))+(strlen(logtab[what].text))+2)), buffer); -#endif wrefresh(lower_w); } #endif diff --git a/usr.sbin/i4b/isdnmonitor/main.c b/usr.sbin/i4b/isdnmonitor/main.c index 52484e248b..a70cf06910 100644 --- a/usr.sbin/i4b/isdnmonitor/main.c +++ b/usr.sbin/i4b/isdnmonitor/main.c @@ -521,17 +521,8 @@ print_logevent(time_t tstamp, int prio, char * what, char * msg) * to write to the last column in the logfilewindow without causing an * automatic newline to occur resulting in a blank line in that window. */ -#ifdef __DragonFly__ -#include -#endif -#if defined(__DragonFly__) -#warning "FreeBSD ncurses is buggy: write to last column = auto newline!" wprintw(lower_w, "%s %s %-.*s\n", buf, what, COLS-((strlen(buf))+(strlen(what))+3), msg); -#else - wprintw(lower_w, "%s %s %-.*s\n", buf, what, - (int)(COLS-((strlen(buf))+(strlen(what))+2)), msg); -#endif wrefresh(lower_w); } } diff --git a/usr.sbin/ifmcstat/Makefile b/usr.sbin/ifmcstat/Makefile index 629e55207a..66af8f6fb8 100644 --- a/usr.sbin/ifmcstat/Makefile +++ b/usr.sbin/ifmcstat/Makefile @@ -4,6 +4,7 @@ PROG= ifmcstat MAN= ifmcstat.8 +WARNS?= 1 BINMODE=550 LDADD= -lkvm diff --git a/usr.sbin/inetd/Makefile b/usr.sbin/inetd/Makefile index 7313b6a335..56a491fb69 100644 --- a/usr.sbin/inetd/Makefile +++ b/usr.sbin/inetd/Makefile @@ -6,7 +6,6 @@ PROG= inetd SRCS= inetd.c builtins.c MAN= inetd.8 MLINKS= inetd.8 inetd.conf.5 -WARNS?= 6 CFLAGS+= -DLOGIN_CAP #CFLAGS+= -DSANITY_CHECK diff --git a/usr.sbin/installer/Makefile.inc b/usr.sbin/installer/Makefile.inc new file mode 100644 index 0000000000..1f5b79aa2c --- /dev/null +++ b/usr.sbin/installer/Makefile.inc @@ -0,0 +1,3 @@ +WARNS?= 2 + +.include "../Makefile.inc" diff --git a/usr.sbin/installer/dfuibe_installer/Makefile b/usr.sbin/installer/dfuibe_installer/Makefile index 9a3cb8c3ed..57e40e204c 100644 --- a/usr.sbin/installer/dfuibe_installer/Makefile +++ b/usr.sbin/installer/dfuibe_installer/Makefile @@ -4,7 +4,7 @@ PROG= dfuibe_installer NOMAN= SRCS= flow.c fn_diagnostic.c fn_install.c fn_zonetab.c \ - fn_configure.c fn_disk.c fn_subpart_hammer.c fn_subpart.c main.c + fn_configure.c fn_disk.c fn_subpart_hammer.c fn_subpart_ufs.c main.c CFLAGS+=-I${.CURDIR}/.. @@ -29,5 +29,4 @@ LIBINSTALLER=${.CURDIR}/../libinstaller/libinstaller.a DPADD+= ${LIBINSTALLER} ${LIBDFUI} ${LIBAURA} LDADD+= ${LIBINSTALLER} ${LIBDFUI} ${LIBAURA} -.include "../../Makefile.inc" .include diff --git a/usr.sbin/installer/dfuibe_installer/flow.h b/usr.sbin/installer/dfuibe_installer/flow.h index c436cc7342..1215147382 100644 --- a/usr.sbin/installer/dfuibe_installer/flow.h +++ b/usr.sbin/installer/dfuibe_installer/flow.h @@ -41,8 +41,6 @@ #define DISK_MIN 340 #define HAMMER_MIN 50000 -#define INSTALL_USR_LOCAL -#define INSTALL_USR_X11R6 #define MTPT_ROOT 0 #define MTPT_SWAP 1 diff --git a/usr.sbin/installer/dfuibe_installer/fn_subpart_hammer.c b/usr.sbin/installer/dfuibe_installer/fn_subpart_hammer.c index c5a6962fbd..4f6cb35e88 100644 --- a/usr.sbin/installer/dfuibe_installer/fn_subpart_hammer.c +++ b/usr.sbin/installer/dfuibe_installer/fn_subpart_hammer.c @@ -76,8 +76,6 @@ static struct dfui_form *make_create_subpartitions_form(struct i_fn_args *); static int show_create_subpartitions_form(struct dfui_form *, struct i_fn_args *); static const char *def_mountpt[7] = {"/", "swap", "/var", "/tmp", "/usr", "/home", NULL}; -static long def_capacity[7] = {-1, 128, 128, 128, 256, 128, 0}; - static int expert = 0; /* @@ -90,7 +88,6 @@ create_subpartitions(struct i_fn_args *a) struct subpartition *sp; struct commands *cmds; int result = 0; - int copied_original = 0; int num_partitions; cmds = commands_new(); @@ -321,7 +318,6 @@ check_subpartition_selections(struct dfui_response *r, struct i_fn_args *a) struct aura_dict *d; const char *mountpoint, *capstring; long capacity = 0; - long bsize, fsize; int found_root = 0; int valid = 1; @@ -339,20 +335,7 @@ check_subpartition_selections(struct dfui_response *r, struct i_fn_args *a) #endif mountpoint = dfui_dataset_get_value(ds, "mountpoint"); capstring = dfui_dataset_get_value(ds, "capacity"); -#if 0 - if (expert) { - softupdates = - (strcmp(dfui_dataset_get_value(ds, "softupdates"), "Y") == 0); - fsize = atol(dfui_dataset_get_value(ds, "fsize")); - bsize = atol(dfui_dataset_get_value(ds, "bsize")); - mfsbacked = (strcmp(dfui_dataset_get_value(ds, "mfsbacked"), "Y") == 0); - } else { - softupdates = (strcmp(mountpoint, "/") == 0 ? 0 : 1); - mfsbacked = (strcmp(mountpoint, "/tmp") == 0 ? 0 : 1); - fsize = -1; - bsize = -1; - } -#endif + if (aura_dict_exists(d, mountpoint, strlen(mountpoint) + 1)) { inform(a->c, _("The same mount point cannot be specified " "for two different subpartitions.")); @@ -434,10 +417,8 @@ static void save_subpartition_selections(struct dfui_response *r, struct i_fn_args *a) { struct dfui_dataset *ds; - char mfsbacked; const char *mountpoint, *capstring; long capacity; - long bsize, fsize; int valid = 1; subpartitions_free(storage_get_selected_slice(a->s)); @@ -446,20 +427,7 @@ save_subpartition_selections(struct dfui_response *r, struct i_fn_args *a) ds = dfui_dataset_get_next(ds)) { mountpoint = dfui_dataset_get_value(ds, "mountpoint"); capstring = dfui_dataset_get_value(ds, "capacity"); -#if 0 - if (expert) { - softupdates = - (strcmp(dfui_dataset_get_value(ds, "softupdates"), "Y") == 0); - fsize = atol(dfui_dataset_get_value(ds, "fsize")); - bsize = atol(dfui_dataset_get_value(ds, "bsize")); - mfsbacked = (strcmp(dfui_dataset_get_value(ds, "mfsbacked"), "Y") == 0); - } else { - softupdates = (strcmp(mountpoint, "/") == 0 ? 0 : 1); - mfsbacked = 0; - fsize = -1; - bsize = -1; - } -#endif + if (string_to_capacity(capstring, &capacity)) { subpartition_new_hammer(storage_get_selected_slice(a->s), mountpoint, capacity); @@ -472,7 +440,6 @@ populate_create_subpartitions_form(struct dfui_form *f, struct i_fn_args *a) { struct subpartition *sp; struct dfui_dataset *ds; - char temp[32]; int mtpt; long capacity; @@ -574,7 +541,6 @@ warn_subpartition_selections(struct i_fn_args *a) static struct dfui_form * make_create_subpartitions_form(struct i_fn_args *a) { - struct dfui_field *fi; struct dfui_form *f; char msg_buf[1][1024]; diff --git a/usr.sbin/installer/dfuibe_installer/fn_subpart.c b/usr.sbin/installer/dfuibe_installer/fn_subpart_ufs.c similarity index 99% rename from usr.sbin/installer/dfuibe_installer/fn_subpart.c rename to usr.sbin/installer/dfuibe_installer/fn_subpart_ufs.c index 7b42bc3f82..93fa750d8e 100644 --- a/usr.sbin/installer/dfuibe_installer/fn_subpart.c +++ b/usr.sbin/installer/dfuibe_installer/fn_subpart_ufs.c @@ -77,8 +77,6 @@ static struct dfui_form *make_create_subpartitions_form(struct i_fn_args *); static int show_create_subpartitions_form(struct dfui_form *, struct i_fn_args *); static const char *def_mountpt[7] = {"/", "swap", "/var", "/tmp", "/usr", "/home", NULL}; -static long def_capacity[7] = {128, 128, 128, 128, 256, -1, 0}; - static int expert = 0; /* diff --git a/usr.sbin/installer/dfuife_curses/Makefile b/usr.sbin/installer/dfuife_curses/Makefile index e92a7b1209..3742a50ffb 100644 --- a/usr.sbin/installer/dfuife_curses/Makefile +++ b/usr.sbin/installer/dfuife_curses/Makefile @@ -29,5 +29,4 @@ LIBINSTALLER=${.CURDIR}/../libinstaller/libinstaller.a DPADD+= ${LIBINSTALLER} ${LIBDFUI} ${LIBAURA} ${LIBPANEL} ${LIBNCURSES} LDADD+= ${LIBINSTALLER} ${LIBDFUI} ${LIBAURA} -lpanel -lcurses -.include "../../Makefile.inc" .include diff --git a/usr.sbin/installer/libdfui/encode.c b/usr.sbin/installer/libdfui/encode.c index 0702d0b3a1..7467d6b8b2 100644 --- a/usr.sbin/installer/libdfui/encode.c +++ b/usr.sbin/installer/libdfui/encode.c @@ -57,7 +57,7 @@ dfui_encode_string(struct aura_buffer *e, const char *str) if (str == NULL) { aura_buffer_cat(e, "0:"); } else { - snprintf(fmt, 16, "%d", strlen(str)); + snprintf(fmt, 16, "%zu", strlen(str)); aura_buffer_cat(e, fmt); aura_buffer_cat(e, ":"); aura_buffer_cat(e, str); diff --git a/usr.sbin/iostat/Makefile b/usr.sbin/iostat/Makefile index ca4a7f1c05..c1190ff338 100644 --- a/usr.sbin/iostat/Makefile +++ b/usr.sbin/iostat/Makefile @@ -7,6 +7,5 @@ MAN= iostat.8 CFLAGS+=-I${.CURDIR}/../../sys DPADD= ${LIBDEVSTAT} ${LIBKINFO} LDADD= -ldevstat -lkinfo -WARNS?= 6 .include diff --git a/usr.sbin/ipftest/Makefile b/usr.sbin/ipftest/Makefile index 9dacbeb5c4..604955da04 100644 --- a/usr.sbin/ipftest/Makefile +++ b/usr.sbin/ipftest/Makefile @@ -9,6 +9,7 @@ SRCS= ipt.c parse.c fil.c ipft_sn.c ipft_ef.c ipft_td.c ipft_pc.c opt.c \ ipft_tx.c misc.c ip_frag.c ip_state.c ip_nat.c ip_proxy.c ip_log.c \ ip_auth.c ipft_hx.c ip_fil.c natparse.c facpri.c common.c \ printstate.c printnat.c +WARNS?= 0 CFLAGS+=-DUSE_INET6 -DIPL_NAME=\"/dev/ipl\" -DIPFILTER_LOG CFLAGS+= -I${.CURDIR}/../../sys/contrib/ipfilter/netinet diff --git a/usr.sbin/ipresend/Makefile b/usr.sbin/ipresend/Makefile index 3d4ec3afa9..95b7d1fb54 100644 --- a/usr.sbin/ipresend/Makefile +++ b/usr.sbin/ipresend/Makefile @@ -6,6 +6,7 @@ PROG= ipresend SRCS= ipresend.c ip.c resend.c opt.c ipft_ef.c ipft_hx.c ipft_sn.c ipft_td.c ipft_tx.c sbpf.c 44arp.c ipft_pc.c +WARNS?= 0 CFLAGS+=-DDOSOCKET -DIPL_NAME=\"/dev/ipl\" -DUSE_INET6 CFLAGS+=-I${.CURDIR}/../../sys/contrib/ipfilter diff --git a/usr.sbin/ipsend/Makefile b/usr.sbin/ipsend/Makefile index c784d07a00..1263bf5c6b 100644 --- a/usr.sbin/ipsend/Makefile +++ b/usr.sbin/ipsend/Makefile @@ -9,6 +9,7 @@ PROG= ipsend SRCS= ipsend.c ip.c ipsopt.c sbpf.c sock.c 44arp.c iplang_y.y iplang_l.l \ y.tab.h MAN= ipsend.1 ipsend.5 +WARNS?= 1 CFLAGS+=-DDOSOCKET -DIPL_NAME=\"/dev/ipl\" -DUSE_INET6 CFLAGS+=-I${.CURDIR}/../../sys/contrib/ipfilter/netinet diff --git a/usr.sbin/iptest/Makefile b/usr.sbin/iptest/Makefile index 7c1d20e553..0a0408f216 100644 --- a/usr.sbin/iptest/Makefile +++ b/usr.sbin/iptest/Makefile @@ -6,6 +6,7 @@ PROG= iptest SRCS= iptest.c iptests.c ip.c sbpf.c 44arp.c sock.c +WARNS?= 2 CFLAGS+=-DDOSOCKET -DIPL_NAME=\"/dev/ipl\" -DUSE_INET6 CFLAGS+=-I${.CURDIR}/../../sys/contrib/ipfilter/netinet diff --git a/usr.sbin/jail/Makefile b/usr.sbin/jail/Makefile index 7c3c84de40..6f568f09b6 100644 --- a/usr.sbin/jail/Makefile +++ b/usr.sbin/jail/Makefile @@ -5,6 +5,5 @@ PROG= jail MAN= jail.8 DPADD= ${LIBUTIL} LDADD= -lutil -WARNS?= 6 .include diff --git a/usr.sbin/jexec/Makefile b/usr.sbin/jexec/Makefile index f89e96ea5d..ff60d77bf3 100644 --- a/usr.sbin/jexec/Makefile +++ b/usr.sbin/jexec/Makefile @@ -3,6 +3,5 @@ PROG= jexec MAN= jexec.8 -WARNS?= 6 .include diff --git a/usr.sbin/jls/Makefile b/usr.sbin/jls/Makefile index c6718a076b..455221911c 100644 --- a/usr.sbin/jls/Makefile +++ b/usr.sbin/jls/Makefile @@ -3,6 +3,5 @@ PROG= jls MAN= jls.8 -WARNS?= 6 .include diff --git a/usr.sbin/kbdcontrol/Makefile b/usr.sbin/kbdcontrol/Makefile index 3c489393a1..f22e83d098 100644 --- a/usr.sbin/kbdcontrol/Makefile +++ b/usr.sbin/kbdcontrol/Makefile @@ -8,5 +8,6 @@ MLINKS= kbdmap.5 keymap.5 CFLAGS+=-I${.CURDIR} DPADD= ${LIBL} LDADD= -ll +WARNS?= 1 .include diff --git a/usr.sbin/kbdmap/Makefile b/usr.sbin/kbdmap/Makefile index 98d4d57ab5..8d4ba1648d 100644 --- a/usr.sbin/kbdmap/Makefile +++ b/usr.sbin/kbdmap/Makefile @@ -2,7 +2,6 @@ # $DragonFly: src/usr.sbin/kbdmap/Makefile,v 1.5 2005/01/17 01:49:24 cpressey Exp $ PROG= kbdmap -WARNS?= 6 LINKS= ${BINDIR}/kbdmap ${BINDIR}/vidfont MAN= kbdmap.1 MLINKS= kbdmap.1 vidfont.1 diff --git a/usr.sbin/kernbb/Makefile b/usr.sbin/kernbb/Makefile index ae2d212ea5..785329d314 100644 --- a/usr.sbin/kernbb/Makefile +++ b/usr.sbin/kernbb/Makefile @@ -5,7 +5,6 @@ PROG= kernbb MAN= kernbb.8 DPADD= ${LIBKVM} LDADD= -lkvm -WARNS?= 6 .include diff --git a/usr.sbin/kgmon/Makefile b/usr.sbin/kgmon/Makefile index 9d500b5f51..8ca9fa5e85 100644 --- a/usr.sbin/kgmon/Makefile +++ b/usr.sbin/kgmon/Makefile @@ -6,6 +6,8 @@ PROG= kgmon MAN= kgmon.8 DPADD= ${LIBKVM} LDADD= -lkvm +WARNS?= 1 + # # This program may safely be run setuid-root to allow non-root # users to start, stop, and reset profiling buffers. diff --git a/usr.sbin/kgzip/Makefile b/usr.sbin/kgzip/Makefile index 88074af6bb..0e588554e5 100644 --- a/usr.sbin/kgzip/Makefile +++ b/usr.sbin/kgzip/Makefile @@ -4,6 +4,5 @@ PROG= kgzip SRCS= kgzip.c aouthdr.c elfhdr.c kgzcmp.c kgzld.c xio.c MAN= kgzip.8 -WARNS?= 6 .include diff --git a/usr.sbin/lastlogin/Makefile b/usr.sbin/lastlogin/Makefile index 4954ca08f7..3b09b7d039 100644 --- a/usr.sbin/lastlogin/Makefile +++ b/usr.sbin/lastlogin/Makefile @@ -4,5 +4,4 @@ PROG= lastlogin MAN= lastlogin.8 -WARNS?= 6 .include diff --git a/usr.sbin/lpr/filters.ru/Makefile.inc b/usr.sbin/lpr/filters.ru/Makefile.inc index c4eb9fd203..630ab2c8e2 100644 --- a/usr.sbin/lpr/filters.ru/Makefile.inc +++ b/usr.sbin/lpr/filters.ru/Makefile.inc @@ -2,3 +2,5 @@ # $DragonFly: src/usr.sbin/lpr/filters.ru/Makefile.inc,v 1.2 2003/06/17 04:29:56 dillon Exp $ BINDIR= /usr/libexec/lpr/ru + +.include "../Makefile.inc" diff --git a/usr.sbin/lpr/filters.ru/koi2855/koi2855.c b/usr.sbin/lpr/filters.ru/koi2855/koi2855.c index 6f99ea8220..f5b5988e50 100644 --- a/usr.sbin/lpr/filters.ru/koi2855/koi2855.c +++ b/usr.sbin/lpr/filters.ru/koi2855/koi2855.c @@ -35,6 +35,7 @@ #include #include #include +#include #include int length = 66; diff --git a/usr.sbin/lpr/filters.ru/koi2alt/koi2alt.c b/usr.sbin/lpr/filters.ru/koi2alt/koi2alt.c index 46a97afc4f..a94f899c59 100644 --- a/usr.sbin/lpr/filters.ru/koi2alt/koi2alt.c +++ b/usr.sbin/lpr/filters.ru/koi2alt/koi2alt.c @@ -33,6 +33,7 @@ #include #include #include +#include #include int length = 66; diff --git a/usr.sbin/lptcontrol/Makefile b/usr.sbin/lptcontrol/Makefile index d342aba2f1..2c42934ff2 100644 --- a/usr.sbin/lptcontrol/Makefile +++ b/usr.sbin/lptcontrol/Makefile @@ -2,7 +2,6 @@ # $DragonFly: src/usr.sbin/lptcontrol/Makefile,v 1.3 2005/01/17 01:49:24 cpressey Exp $ PROG= lptcontrol -WARNS?= 6 MAN= lptcontrol.8 .include diff --git a/usr.sbin/mailstats/Makefile b/usr.sbin/mailstats/Makefile index 16a0893266..608fee4c6a 100644 --- a/usr.sbin/mailstats/Makefile +++ b/usr.sbin/mailstats/Makefile @@ -8,6 +8,7 @@ SENDMAIL_DIR=${.CURDIR}/../../contrib/sendmail-8.14 PROG= mailstats SRCS= mailstats.c MAN= mailstats.8 +WARNS?= 2 CFLAGS+= -I${SENDMAIL_DIR}/sendmail -I${SENDMAIL_DIR}/include -I. CFLAGS+= -DNOT_SENDMAIL diff --git a/usr.sbin/mailwrapper/Makefile b/usr.sbin/mailwrapper/Makefile index 4d5300ba49..efe1651e66 100644 --- a/usr.sbin/mailwrapper/Makefile +++ b/usr.sbin/mailwrapper/Makefile @@ -3,7 +3,6 @@ .if !defined(NO_MAILWRAPPER) PROG= mailwrapper -WARNS?= 6 MAN= mailwrapper.8 DPADD= ${LIBUTIL} diff --git a/usr.sbin/makemap/Makefile b/usr.sbin/makemap/Makefile index 1a39448486..28fc59be97 100644 --- a/usr.sbin/makemap/Makefile +++ b/usr.sbin/makemap/Makefile @@ -8,6 +8,8 @@ SENDMAIL_DIR=${.CURDIR}/../../contrib/sendmail-8.14 PROG= makemap SRCS= makemap.c MAN= makemap.8 +WARNS?= 2 + CFLAGS+=-I${SENDMAIL_DIR}/sendmail -I${SENDMAIL_DIR}/include -I. CFLAGS+=-DNEWDB -DNOT_SENDMAIL diff --git a/usr.sbin/makewhatis/Makefile b/usr.sbin/makewhatis/Makefile index 5ab1001ea7..847d8416f0 100644 --- a/usr.sbin/makewhatis/Makefile +++ b/usr.sbin/makewhatis/Makefile @@ -2,7 +2,6 @@ # $DragonFly: src/usr.sbin/makewhatis/Makefile,v 1.2 2005/01/16 04:59:53 cpressey Exp $ PROG= makewhatis -WARNS?= 6 DPADD= ${LIBZ} LDADD= -lz MAN= makewhatis.8 diff --git a/usr.sbin/makewhatis/makewhatis.c b/usr.sbin/makewhatis/makewhatis.c index a4602ed8b4..1295c2676f 100644 --- a/usr.sbin/makewhatis/makewhatis.c +++ b/usr.sbin/makewhatis/makewhatis.c @@ -1003,7 +1003,9 @@ main(int argc, char **argv) char *sep = strchr(locale, '_'); if (sep != NULL && isupper(sep[1]) && isupper(sep[2])) { - asprintf(&lang_locale, "%.*s%s", sep - locale, locale, &sep[3]); + asprintf(&lang_locale, "%.*s%s", + (int)(sep - locale), + locale, &sep[3]); } } break; diff --git a/usr.sbin/memcontrol/Makefile b/usr.sbin/memcontrol/Makefile index 8046e0b967..d3b9e1e200 100644 --- a/usr.sbin/memcontrol/Makefile +++ b/usr.sbin/memcontrol/Makefile @@ -2,7 +2,6 @@ # $DragonFly: src/usr.sbin/memcontrol/Makefile,v 1.3 2005/03/18 01:57:58 cpressey Exp $ PROG= memcontrol -WARNS?= 6 MAN= memcontrol.8 .include diff --git a/usr.sbin/mixer/Makefile b/usr.sbin/mixer/Makefile index 0bded029d1..65faff85c0 100644 --- a/usr.sbin/mixer/Makefile +++ b/usr.sbin/mixer/Makefile @@ -2,7 +2,6 @@ # $DragonFly: src/usr.sbin/mixer/Makefile,v 1.3 2005/01/17 01:49:24 cpressey Exp $ PROG= mixer -WARNS?= 6 MAN= mixer.8 .include diff --git a/usr.sbin/mld6query/Makefile b/usr.sbin/mld6query/Makefile index f341d5ba5b..3efdc12dde 100644 --- a/usr.sbin/mld6query/Makefile +++ b/usr.sbin/mld6query/Makefile @@ -18,6 +18,7 @@ PROG= mld6query SRCS= mld6.c MAN= mld6query.8 +WARNS?= 2 CFLAGS+= -DINET6 -DIPSEC diff --git a/usr.sbin/mlxcontrol/Makefile b/usr.sbin/mlxcontrol/Makefile index ec5b994cc5..cd5cff7590 100644 --- a/usr.sbin/mlxcontrol/Makefile +++ b/usr.sbin/mlxcontrol/Makefile @@ -5,6 +5,7 @@ PROG= mlxcontrol SRCS= command.c config.c interface.c util.c MAN= mlxcontrol.8 CFLAGS+= -I${.CURDIR}/../../sys +WARNS?= 2 .include diff --git a/usr.sbin/moused/Makefile b/usr.sbin/moused/Makefile index 311ae5a6ad..4f23ddc607 100644 --- a/usr.sbin/moused/Makefile +++ b/usr.sbin/moused/Makefile @@ -3,6 +3,7 @@ PROG= moused MAN= moused.8 +WARNS?= 2 #BINMODE=4555 #INSTALLFLAGS=-fschg diff --git a/usr.sbin/mptable/Makefile b/usr.sbin/mptable/Makefile index 2556ec36d2..d78e485341 100644 --- a/usr.sbin/mptable/Makefile +++ b/usr.sbin/mptable/Makefile @@ -2,6 +2,7 @@ # $DragonFly: src/usr.sbin/mptable/Makefile,v 1.2 2003/06/17 04:29:57 dillon Exp $ PROG = mptable +WARNS?= 1 BINMODE = 550 diff --git a/usr.sbin/mrouted/Makefile.inc b/usr.sbin/mrouted/Makefile.inc index 99c55efd13..14ac8f7fa6 100644 --- a/usr.sbin/mrouted/Makefile.inc +++ b/usr.sbin/mrouted/Makefile.inc @@ -1,6 +1,8 @@ # $FreeBSD: src/usr.sbin/mrouted/Makefile.inc,v 1.4 1999/08/28 01:17:02 peter Exp $ # $DragonFly: src/usr.sbin/mrouted/Makefile.inc,v 1.2 2003/06/17 04:29:57 dillon Exp $ +WARNS?= 1 + CFLAGS+= -DRSRR .if exists(${.OBJDIR}/../common) diff --git a/usr.sbin/mrouted/kern.c b/usr.sbin/mrouted/kern.c index 1a4227a95d..174175ee78 100644 --- a/usr.sbin/mrouted/kern.c +++ b/usr.sbin/mrouted/kern.c @@ -209,8 +209,7 @@ k_add_rg(u_int32 origin, struct gtable *g) #ifdef DEBUG_MFC md_log(MD_ADD_FAIL, origin, g->gt_mcastgrp); #endif - dolog(LOG_WARNING, errno, "setsockopt MRT_ADD_MFC", - inet_fmt(origin, s1), inet_fmt(g->gt_mcastgrp, s2)); + dolog(LOG_WARNING, errno, "setsockopt MRT_ADD_MFC"); } } diff --git a/usr.sbin/mrouted/main.c b/usr.sbin/mrouted/main.c index 1e61d1f912..8be7886fee 100644 --- a/usr.sbin/mrouted/main.c +++ b/usr.sbin/mrouted/main.c @@ -696,7 +696,7 @@ timer(void *i) static void cleanup(void) { - static in_cleanup = 0; + static int in_cleanup = 0; if (!in_cleanup) { in_cleanup++; diff --git a/usr.sbin/mtest/Makefile b/usr.sbin/mtest/Makefile index 5da103dcb3..6c876a0e52 100644 --- a/usr.sbin/mtest/Makefile +++ b/usr.sbin/mtest/Makefile @@ -3,5 +3,6 @@ PROG= mtest MAN= mtest.8 +WARNS?= 3 .include diff --git a/usr.sbin/mtree/Makefile b/usr.sbin/mtree/Makefile index 819fe39a06..c563c93e9a 100644 --- a/usr.sbin/mtree/Makefile +++ b/usr.sbin/mtree/Makefile @@ -7,7 +7,6 @@ PROG= mtree MAN= mtree.8 SRCS= compare.c crc.c create.c excludes.c misc.c mtree.c spec.c verify.c -WARNS?= 6 .if defined(BOOTSTRAPPING) .PATH: ${.CURDIR}/../../lib/libc/gen diff --git a/usr.sbin/named/Makefile b/usr.sbin/named/Makefile index b253882fe2..6ccddac603 100644 --- a/usr.sbin/named/Makefile +++ b/usr.sbin/named/Makefile @@ -23,6 +23,7 @@ SRCS= aclconf.c builtin.c client.c config.c control.c \ .PATH: ${BIND_DIR}/bin/named/unix SRCS+= os.c +WARNS?= 3 CFLAGS+= -I${BIND_DIR}/bin/named/include \ -I${BIND_DIR}/lib/bind9/include diff --git a/usr.sbin/ndiscvt/Makefile b/usr.sbin/ndiscvt/Makefile index 7a49905e63..88bc93ddd5 100644 --- a/usr.sbin/ndiscvt/Makefile +++ b/usr.sbin/ndiscvt/Makefile @@ -10,8 +10,6 @@ SRCS+= inf.c inf-token.l inf-parse.y y.tab.h MAN8= ndiscvt.8 -WARNS?= 6 - DPADD= ${LIBL} LDADD= -ll diff --git a/usr.sbin/ndp/Makefile b/usr.sbin/ndp/Makefile index 4bd5208771..55d4a55042 100644 --- a/usr.sbin/ndp/Makefile +++ b/usr.sbin/ndp/Makefile @@ -19,6 +19,7 @@ PROG= ndp SRCS= ndp.c gmt2local.c MAN= ndp.8 +WARNS?= 2 CFLAGS+=-DINET6 CFLAGS+=-I. -I${.CURDIR} -I${.CURDIR}/../tcpdump/tcpdump -I${.CURDIR}/../../contrib/tcpdump-3.9 diff --git a/usr.sbin/newsyslog/Makefile b/usr.sbin/newsyslog/Makefile index d5eeef0c23..b1d761f609 100644 --- a/usr.sbin/newsyslog/Makefile +++ b/usr.sbin/newsyslog/Makefile @@ -4,6 +4,5 @@ PROG= newsyslog MAN= newsyslog.8 newsyslog.conf.5 SRCS= newsyslog.c ptimes.c -WARNS?= 6 .include diff --git a/usr.sbin/ngctl/Makefile b/usr.sbin/ngctl/Makefile index 10e8d55a5a..1fab2035e8 100644 --- a/usr.sbin/ngctl/Makefile +++ b/usr.sbin/ngctl/Makefile @@ -8,6 +8,5 @@ SRCS= main.c mkpeer.c config.c connect.c name.c show.c list.c \ MAN= ngctl.8 DPADD+= ${LIBNETGRAPH} LDADD+= -lnetgraph -WARNS?= 6 .include diff --git a/usr.sbin/nghook/Makefile b/usr.sbin/nghook/Makefile index c72b554600..2fdf2523de 100644 --- a/usr.sbin/nghook/Makefile +++ b/usr.sbin/nghook/Makefile @@ -7,6 +7,5 @@ SRCS= main.c MAN= nghook.8 DPADD= ${LIBNETGRAPH} LDADD= -lnetgraph -WARNS?= 6 .include diff --git a/usr.sbin/nscd/Makefile b/usr.sbin/nscd/Makefile index b135b4844a..d58045390d 100644 --- a/usr.sbin/nscd/Makefile +++ b/usr.sbin/nscd/Makefile @@ -3,7 +3,7 @@ PROG= nscd MAN= nscd.conf.5 nscd.8 -WARNS?= 0 +WARNS?= 2 CFLAGS+=-fno-strict-aliasing SRCS= agent.c cachelib.c cacheplcs.c config.c debug.c log.c \ mp_rs_query.c mp_ws_query.c nscd.c nscdcli.c parser.c pidfile.c \ diff --git a/usr.sbin/nslookup/Makefile b/usr.sbin/nslookup/Makefile index 290d3c7f2b..2b5227f18b 100644 --- a/usr.sbin/nslookup/Makefile +++ b/usr.sbin/nslookup/Makefile @@ -12,6 +12,7 @@ USE_LIBISC= yes PROG= nslookup SRCS= nslookup.c dighost.c MAN= +WARNS?= 3 CFLAGS+= -I${.CURDIR}/../../usr.sbin/named \ -I${.CURDIR}/../../usr.sbin/named/include \ diff --git a/usr.sbin/pciconf/Makefile b/usr.sbin/pciconf/Makefile index 19045bf13c..5ddb8bcddd 100644 --- a/usr.sbin/pciconf/Makefile +++ b/usr.sbin/pciconf/Makefile @@ -5,6 +5,5 @@ PROG= pciconf MAN= pciconf.8 CFLAGS+= -I${.CURDIR}/../../sys -WARNS?= 6 .include diff --git a/usr.sbin/pfctl/Makefile b/usr.sbin/pfctl/Makefile index b92e0cf724..896d30cd1e 100644 --- a/usr.sbin/pfctl/Makefile +++ b/usr.sbin/pfctl/Makefile @@ -6,7 +6,6 @@ SRCS= pfctl.c parse.y pfctl_parser.c pf_print_state.c pfctl_altq.c SRCS+= pfctl_osfp.c pfctl_radix.c pfctl_table.c pfctl_qstats.c CFLAGS+= -I${.CURDIR} MAN= pfctl.8 pf.conf.5 pf.os.5 -WARNS?= 6 LDADD+= -lmd -lm DPADD+= ${LIBM} diff --git a/usr.sbin/pnpinfo/Makefile b/usr.sbin/pnpinfo/Makefile index 3ff864ab32..fe2dcaca86 100644 --- a/usr.sbin/pnpinfo/Makefile +++ b/usr.sbin/pnpinfo/Makefile @@ -2,10 +2,10 @@ # $DragonFly: src/usr.sbin/pnpinfo/Makefile,v 1.3 2005/02/19 01:44:06 swildner Exp $ PROG= pnpinfo +MAN= pnpinfo.8 +WARNS?= 1 -SRCS= pnpinfo.c CFLAGS+=-I${.CURDIR}/../../sys -MAN= pnpinfo.8 .PATH: ${.CURDIR}/../../contrib/pnpinfo diff --git a/usr.sbin/pppd/Makefile b/usr.sbin/pppd/Makefile index a6d54c8000..a0ea66a12e 100644 --- a/usr.sbin/pppd/Makefile +++ b/usr.sbin/pppd/Makefile @@ -10,6 +10,7 @@ MAN= pppd.8 BINMODE=4550 BINOWN= root BINGRP= dialer +WARNS?= 0 LDADD= -lcrypt -lutil -lmd DPADD= ${LIBCRYPT} ${LIBUTIL} ${LIBMD} diff --git a/usr.sbin/pppstats/Makefile b/usr.sbin/pppstats/Makefile index 2ad52d25ce..97addde96f 100644 --- a/usr.sbin/pppstats/Makefile +++ b/usr.sbin/pppstats/Makefile @@ -3,5 +3,6 @@ PROG= pppstats MAN= pppstats.8 +WARNS?= 3 .include diff --git a/usr.sbin/praliases/Makefile b/usr.sbin/praliases/Makefile index 2bbc8e8b38..d78466406c 100644 --- a/usr.sbin/praliases/Makefile +++ b/usr.sbin/praliases/Makefile @@ -8,6 +8,8 @@ SENDMAIL_DIR=${.CURDIR}/../../contrib/sendmail-8.14 PROG= praliases SRCS= praliases.c MAN= praliases.8 +WARNS?= 2 + CFLAGS+=-I${SENDMAIL_DIR}/sendmail -I${SENDMAIL_DIR}/include -I. CFLAGS+=-DNEWDB -DNOT_SENDMAIL diff --git a/usr.sbin/procctl/Makefile b/usr.sbin/procctl/Makefile index e6c97a261e..a311714a51 100644 --- a/usr.sbin/procctl/Makefile +++ b/usr.sbin/procctl/Makefile @@ -4,5 +4,4 @@ PROG= procctl MAN= procctl.8 -WARNS?= 6 .include diff --git a/usr.sbin/pwd_mkdb/Makefile b/usr.sbin/pwd_mkdb/Makefile index fe497b83ad..4deae8524e 100644 --- a/usr.sbin/pwd_mkdb/Makefile +++ b/usr.sbin/pwd_mkdb/Makefile @@ -8,7 +8,6 @@ PROG= pwd_mkdb MAN= pwd_mkdb.8 SRCS= pw_scan.c pwd_mkdb.c -WARNS?= 6 CFLAGS+= -I${.CURDIR}/../../lib/libc/gen # for pw_scan.h .include diff --git a/usr.sbin/quot/Makefile b/usr.sbin/quot/Makefile index f9bee5fc5c..6aed712c31 100644 --- a/usr.sbin/quot/Makefile +++ b/usr.sbin/quot/Makefile @@ -2,7 +2,6 @@ # $DragonFly: src/usr.sbin/quot/Makefile,v 1.3 2005/01/17 01:49:24 cpressey Exp $ PROG= quot -WARNS?= 6 MAN= quot.8 .include diff --git a/usr.sbin/quotaon/Makefile b/usr.sbin/quotaon/Makefile index b530ba8754..3abb5e66b8 100644 --- a/usr.sbin/quotaon/Makefile +++ b/usr.sbin/quotaon/Makefile @@ -6,6 +6,5 @@ PROG= quotaon MAN= quotaon.8 MLINKS= quotaon.8 quotaoff.8 LINKS= ${BINDIR}/quotaon ${BINDIR}/quotaoff -WARNS?= 6 .include diff --git a/usr.sbin/rarpd/Makefile b/usr.sbin/rarpd/Makefile index 7198e92a46..eceb38eac5 100644 --- a/usr.sbin/rarpd/Makefile +++ b/usr.sbin/rarpd/Makefile @@ -4,5 +4,6 @@ PROG= rarpd MAN= rarpd.8 +WARNS?= 2 .include diff --git a/usr.sbin/rdate/Makefile b/usr.sbin/rdate/Makefile index f15c61e5c5..959ec75584 100644 --- a/usr.sbin/rdate/Makefile +++ b/usr.sbin/rdate/Makefile @@ -5,7 +5,6 @@ PROG= rdate SRCS= rdate.c rfc868time.c ntp.c ntpleaps.c DPADD+= ${LIBUTIL} LDADD+= -lutil -WARNS?= 6 MAN= rdate.8 diff --git a/usr.sbin/repquota/Makefile b/usr.sbin/repquota/Makefile index cc8af08e95..233c60a28c 100644 --- a/usr.sbin/repquota/Makefile +++ b/usr.sbin/repquota/Makefile @@ -3,7 +3,6 @@ # $DragonFly: src/usr.sbin/repquota/Makefile,v 1.3 2005/01/17 01:49:24 cpressey Exp $ PROG= repquota -WARNS?= 6 MAN= repquota.8 .include diff --git a/usr.sbin/resident/Makefile b/usr.sbin/resident/Makefile index 94ba1304a7..fc1dfe4a59 100644 --- a/usr.sbin/resident/Makefile +++ b/usr.sbin/resident/Makefile @@ -1,8 +1,6 @@ # $DragonFly: src/usr.sbin/resident/Makefile,v 1.2 2005/01/17 01:49:24 cpressey Exp $ PROG= resident -SRCS= resident.c -WARNS?= 6 MAN= resident.8 .include diff --git a/usr.sbin/resident/resident.c b/usr.sbin/resident/resident.c index 2bea465af3..ed6e8df72d 100644 --- a/usr.sbin/resident/resident.c +++ b/usr.sbin/resident/resident.c @@ -57,8 +57,8 @@ list_residents(void) { const char *mib = "vm.resident"; struct xresident *buf; - int res_count, res_total; - int error, i; + size_t res_count, res_total, i; + int error; /* get the number of resident binaries */ error = sysctlbyname(mib, NULL, &res_count, NULL, 0); diff --git a/usr.sbin/rip6query/Makefile b/usr.sbin/rip6query/Makefile index 65b888d32a..13da664a71 100644 --- a/usr.sbin/rip6query/Makefile +++ b/usr.sbin/rip6query/Makefile @@ -4,7 +4,6 @@ # $DragonFly: src/usr.sbin/rip6query/Makefile,v 1.3 2005/01/17 01:49:24 cpressey Exp $ PROG= rip6query -WARNS?= 6 MAN= rip6query.8 CFLAGS+=-DINET6 -I${.CURDIR}/../route6d diff --git a/usr.sbin/rmt/Makefile b/usr.sbin/rmt/Makefile index 5fc64be76c..db378e0de9 100644 --- a/usr.sbin/rmt/Makefile +++ b/usr.sbin/rmt/Makefile @@ -4,6 +4,7 @@ PROG= rmt MAN= rmt.8 +WARNS?= 3 # called from /usr/src/etc/Makefile etc-rmt: diff --git a/usr.sbin/rndc-confgen/Makefile b/usr.sbin/rndc-confgen/Makefile index 4a692b7b70..77abe71f13 100644 --- a/usr.sbin/rndc-confgen/Makefile +++ b/usr.sbin/rndc-confgen/Makefile @@ -11,6 +11,7 @@ USE_LIBISC= yes PROG= rndc-confgen SRCS= rndc-confgen.c os.c util.c MAN= rndc-confgen.8 +WARNS?= 3 CFLAGS+= -I${.CURDIR}/../../usr.sbin/named \ -I${.CURDIR}/../../usr.sbin/named/include \ diff --git a/usr.sbin/rndc/Makefile b/usr.sbin/rndc/Makefile index 3dba034110..a854df7459 100644 --- a/usr.sbin/rndc/Makefile +++ b/usr.sbin/rndc/Makefile @@ -12,6 +12,7 @@ USE_LIBISC= yes PROG= rndc SRCS= rndc.c os.c util.c MAN= rndc.8 +WARNS?= 2 CFLAGS+= -I${.CURDIR}/../../usr.sbin/named \ -I${.CURDIR}/../../usr.sbin/named/include \ diff --git a/usr.sbin/rndcontrol/Makefile b/usr.sbin/rndcontrol/Makefile index d5001ebbb9..b90727f4d6 100644 --- a/usr.sbin/rndcontrol/Makefile +++ b/usr.sbin/rndcontrol/Makefile @@ -4,6 +4,5 @@ PROG= rndcontrol MAN= random.4 rndcontrol.8 MLINKS+= random.4 urandom.4 -WARNS?= 6 .include diff --git a/usr.sbin/route6d/Makefile b/usr.sbin/route6d/Makefile index 5dcb9c8dc8..542704f485 100644 --- a/usr.sbin/route6d/Makefile +++ b/usr.sbin/route6d/Makefile @@ -4,6 +4,7 @@ PROG= route6d MAN= route6d.8 +WARNS?= 2 CFLAGS+= -Dss_len=__ss_len -Dss_family=__ss_family -DINET6 \ -DHAVE_GETIFADDRS diff --git a/usr.sbin/rpc.statd/Makefile b/usr.sbin/rpc.statd/Makefile index 7e6abe9ce3..b893acd026 100644 --- a/usr.sbin/rpc.statd/Makefile +++ b/usr.sbin/rpc.statd/Makefile @@ -4,6 +4,7 @@ PROG = rpc.statd SRCS = file.c sm_inter_svc.c sm_inter.h statd.c procs.c MAN = rpc.statd.8 +WARNS?= 1 DPADD= ${LIBRPCSVC} LDADD= -lrpcsvc diff --git a/usr.sbin/rpc.umntall/Makefile b/usr.sbin/rpc.umntall/Makefile index 10136fe72f..469246e4c4 100644 --- a/usr.sbin/rpc.umntall/Makefile +++ b/usr.sbin/rpc.umntall/Makefile @@ -5,6 +5,5 @@ PROG= rpc.umntall SRCS= rpc.umntall.c mounttab.c MAN= rpc.umntall.8 -WARNS?= 6 .include diff --git a/usr.sbin/rpc.ypupdated/Makefile b/usr.sbin/rpc.ypupdated/Makefile index cbc9c8eff5..643c9a37e8 100644 --- a/usr.sbin/rpc.ypupdated/Makefile +++ b/usr.sbin/rpc.ypupdated/Makefile @@ -8,6 +8,7 @@ NOMAN= SRCS= ypupdate_prot_svc.c ypupdate_prot.h ypupdated_main.c \ yp_error.c update.c ypupdated_server.c \ yp_dblookup.c yp_dbwrite.c yp_dbdelete.c yp_dbupdate.c +WARNS?= 2 #CFLAGS+= -DYP CFLAGS+= -I${.CURDIR}/../ypserv -I. -I${.CURDIR}/../../libexec/ypxfr diff --git a/usr.sbin/rpc.ypxfrd/Makefile b/usr.sbin/rpc.ypxfrd/Makefile index 0245846cb0..141fc03118 100644 --- a/usr.sbin/rpc.ypxfrd/Makefile +++ b/usr.sbin/rpc.ypxfrd/Makefile @@ -4,6 +4,7 @@ PROG= rpc.ypxfrd SRCS= ypxfrd_svc.c ypxfrd.h ypxfrd_server.c yp_error.c \ yp_access.c ypxfrd_main.c +WARNS?= 1 RPCDIR= ${.CURDIR}/../../include/rpcsvc diff --git a/usr.sbin/rpcbind/Makefile b/usr.sbin/rpcbind/Makefile index 2b977278ad..618c3ee538 100644 --- a/usr.sbin/rpcbind/Makefile +++ b/usr.sbin/rpcbind/Makefile @@ -6,6 +6,7 @@ PROG= rpcbind MAN= rpcbind.8 SRCS= check_bound.c rpcb_stat.c rpcb_svc_4.c rpcbind.c pmap_svc.c \ rpcb_svc.c rpcb_svc_com.c security.c warmstart.c util.c +WARNS?= 1 CFLAGS+= -DPORTMAP -DLIBWRAP diff --git a/usr.sbin/rrenumd/Makefile b/usr.sbin/rrenumd/Makefile index 82fc34849e..a280019b9f 100644 --- a/usr.sbin/rrenumd/Makefile +++ b/usr.sbin/rrenumd/Makefile @@ -17,6 +17,7 @@ PROG= rrenumd SRCS= rrenumd.c parser.y lexer.l YFLAGS+= -d +WARNS?= 2 CFLAGS+= -DINET6 -DIPSEC -I. -I${.CURDIR} LDADD= -lipsec -lcompat -ll diff --git a/usr.sbin/rtadvd/Makefile b/usr.sbin/rtadvd/Makefile index ecf9e3b3f4..250926e01a 100644 --- a/usr.sbin/rtadvd/Makefile +++ b/usr.sbin/rtadvd/Makefile @@ -16,6 +16,7 @@ PROG= rtadvd SRCS= rtadvd.c rrenum.c advcap.c if.c config.c timer.c dump.c +WARNS?= 1 CFLAGS+=-DINET6 LDADD+= -lcompat diff --git a/usr.sbin/rtprio/Makefile b/usr.sbin/rtprio/Makefile index 54e0370324..e04bd1f00f 100644 --- a/usr.sbin/rtprio/Makefile +++ b/usr.sbin/rtprio/Makefile @@ -3,7 +3,6 @@ # $DragonFly: src/usr.sbin/rtprio/Makefile,v 1.3 2005/02/04 21:32:55 cpressey Exp $ PROG= rtprio -WARNS?= 6 LINKS= ${BINDIR}/rtprio ${BINDIR}/idprio MLINKS= rtprio.1 idprio.1 diff --git a/usr.sbin/rtsold/Makefile b/usr.sbin/rtsold/Makefile index f0909539d2..d57c41813f 100644 --- a/usr.sbin/rtsold/Makefile +++ b/usr.sbin/rtsold/Makefile @@ -15,7 +15,6 @@ # $DragonFly: src/usr.sbin/rtsold/Makefile,v 1.3 2005/02/15 00:26:00 cpressey Exp $ PROG= rtsold -WARNS?= 6 SRCS= rtsold.c rtsol.c if.c probe.c dump.c rtsock.c CFLAGS+=-DINET6 -DHAVE_GETIFADDRS diff --git a/usr.sbin/rwhod/Makefile b/usr.sbin/rwhod/Makefile index 98dfb421a5..65b7ff4458 100644 --- a/usr.sbin/rwhod/Makefile +++ b/usr.sbin/rwhod/Makefile @@ -4,7 +4,6 @@ PROG= rwhod MAN= rwhod.8 -WARNS?= 6 LDADD+= -lutil DPADD+= ${LIBUTIL} diff --git a/usr.sbin/sa/Makefile b/usr.sbin/sa/Makefile index 78ee72da45..83953bc667 100644 --- a/usr.sbin/sa/Makefile +++ b/usr.sbin/sa/Makefile @@ -4,5 +4,6 @@ PROG= sa MAN= sa.8 SRCS= main.c pdb.c usrdb.c +WARNS?= 1 .include diff --git a/usr.sbin/sdpd/Makefile b/usr.sbin/sdpd/Makefile index a09437ae79..94bc8f7967 100644 --- a/usr.sbin/sdpd/Makefile +++ b/usr.sbin/sdpd/Makefile @@ -6,6 +6,7 @@ MAN= sdpd.8 SRCS= bgd.c dun.c ftrn.c hf.c hset.c irmc.c irmc_command.c lan.c \ log.c main.c opush.c profile.c provider.c sar.c scr.c \ sd.c server.c sp.c srr.c ssar.c ssr.c sur.c uuid.c +WARNS?= 1 CFLAGS+= -I${.CURDIR}/../../sys diff --git a/usr.sbin/sendmail/Makefile b/usr.sbin/sendmail/Makefile index 0b46f39c8b..b1e291968d 100644 --- a/usr.sbin/sendmail/Makefile +++ b/usr.sbin/sendmail/Makefile @@ -21,6 +21,7 @@ SRCS= alias.c arpadate.c bf.c collect.c conf.c control.c \ ratectrl.c readcf.c recipient.c savemail.c sasl.c sfsasl.c \ shmticklib.c sm_resolve.c srvrsmtp.c stab.c stats.c sysexits.c \ timers.c tls.c trace.c udb.c usersmtp.c util.c version.c ${PATCHES} +WARNS?= 2 BINOWN= root BINGRP= smmsp .ifdef SENDMAIL_SET_USER_ID diff --git a/usr.sbin/sensorsd/Makefile b/usr.sbin/sensorsd/Makefile index 169f80a4f8..0b723df72b 100644 --- a/usr.sbin/sensorsd/Makefile +++ b/usr.sbin/sensorsd/Makefile @@ -3,5 +3,6 @@ PROG= sensorsd MAN= sensorsd.8 sensorsd.conf.5 +WARNS?= 1 .include diff --git a/usr.sbin/setkey/Makefile b/usr.sbin/setkey/Makefile index 6a37f8a3ec..363a7d7660 100644 --- a/usr.sbin/setkey/Makefile +++ b/usr.sbin/setkey/Makefile @@ -35,6 +35,7 @@ DPADD= ${LIBL} LDADD= -ll CLEANFILES+= y.tab.c y.tab.h key_test.o keytest YFLAGS+=-d +WARNS?= 2 # libpfkey. # ipsec_strerror.c is for avoiding shlib reference to non-exported function. diff --git a/usr.sbin/sgsc/Makefile b/usr.sbin/sgsc/Makefile index 5fdc4909f6..ff9acac639 100644 --- a/usr.sbin/sgsc/Makefile +++ b/usr.sbin/sgsc/Makefile @@ -2,5 +2,6 @@ # $DragonFly: src/usr.sbin/sgsc/Makefile,v 1.2 2003/06/17 04:30:03 dillon Exp $ PROG= sgsc +WARNS?= 3 .include diff --git a/usr.sbin/sicontrol/Makefile b/usr.sbin/sicontrol/Makefile index bdac8181ab..b5ed78064b 100644 --- a/usr.sbin/sicontrol/Makefile +++ b/usr.sbin/sicontrol/Makefile @@ -3,7 +3,6 @@ PROG= sicontrol MAN= sicontrol.8 -WARNS?= 6 CFLAGS+= -I${.CURDIR}/../../sys .include diff --git a/usr.sbin/sliplogin/Makefile b/usr.sbin/sliplogin/Makefile index 696c4912d2..a1bb2d76e6 100644 --- a/usr.sbin/sliplogin/Makefile +++ b/usr.sbin/sliplogin/Makefile @@ -9,5 +9,6 @@ BINMODE=4550 .if !defined(NOFSCHG) INSTALLFLAGS=-fschg .endif +WARNS?= 1 .include diff --git a/usr.sbin/slstat/Makefile b/usr.sbin/slstat/Makefile index 03690ad071..3f4c587544 100644 --- a/usr.sbin/slstat/Makefile +++ b/usr.sbin/slstat/Makefile @@ -4,5 +4,6 @@ PROG= slstat MAN= slstat.8 +WARNS?= 2 .include diff --git a/usr.sbin/spray/Makefile b/usr.sbin/spray/Makefile index 1edf12da50..6a20b91ac2 100644 --- a/usr.sbin/spray/Makefile +++ b/usr.sbin/spray/Makefile @@ -6,5 +6,4 @@ MAN= spray.8 DPADD= ${LIBRPCSVC} LDADD= -lrpcsvc -WARNS?= 6 .include diff --git a/usr.sbin/stallion/Makefile.inc b/usr.sbin/stallion/Makefile.inc index d99053e01c..3664efa106 100644 --- a/usr.sbin/stallion/Makefile.inc +++ b/usr.sbin/stallion/Makefile.inc @@ -2,6 +2,7 @@ # $DragonFly: src/usr.sbin/stallion/Makefile.inc,v 1.2 2003/06/17 04:30:03 dillon Exp $ BOOTDIR= /usr/libdata/stallion +WARNS?= 1 .if exists(${.CURDIR}/../../Makefile.inc) .include "${.CURDIR}/../../Makefile.inc" diff --git a/usr.sbin/tcpdchk/Makefile b/usr.sbin/tcpdchk/Makefile index 0350bd022b..53198244a2 100644 --- a/usr.sbin/tcpdchk/Makefile +++ b/usr.sbin/tcpdchk/Makefile @@ -6,6 +6,7 @@ PROG= tcpdchk MAN= tcpdchk.8 SRCS= tcpdchk.c fakelog.c inetcf.c scaffold.c +WARNS?= 0 CFLAGS= -DREAL_DAEMON_DIR=\"/usr/libexec\" \ -DSEVERITY=LOG_INFO -DRFC931_TIMEOUT=10 \ diff --git a/usr.sbin/tcpdmatch/Makefile b/usr.sbin/tcpdmatch/Makefile index 4b22e8b7af..c126534fbb 100644 --- a/usr.sbin/tcpdmatch/Makefile +++ b/usr.sbin/tcpdmatch/Makefile @@ -6,6 +6,7 @@ PROG= tcpdmatch MAN= tcpdmatch.8 SRCS= tcpdmatch.c fakelog.c inetcf.c scaffold.c +WARNS?= 0 CFLAGS= -DREAL_DAEMON_DIR=\"/usr/libexec\" \ -DSEVERITY=LOG_INFO -DRFC931_TIMEOUT=10 diff --git a/usr.sbin/tcpdump/Makefile.inc b/usr.sbin/tcpdump/Makefile.inc index 26c6f1c71b..e01a12b7f7 100644 --- a/usr.sbin/tcpdump/Makefile.inc +++ b/usr.sbin/tcpdump/Makefile.inc @@ -1,3 +1,5 @@ # @(#)Makefile.inc 5.1 (Berkeley) 5/11/90 -BINDIR?= /usr/sbin +WARNS?= 2 + +.include "../Makefile.inc" diff --git a/usr.sbin/timed/Makefile.inc b/usr.sbin/timed/Makefile.inc new file mode 100644 index 0000000000..1f5b79aa2c --- /dev/null +++ b/usr.sbin/timed/Makefile.inc @@ -0,0 +1,3 @@ +WARNS?= 2 + +.include "../Makefile.inc" diff --git a/usr.sbin/timed/timed/Makefile b/usr.sbin/timed/timed/Makefile index 79db841fd8..fe8a0ba692 100644 --- a/usr.sbin/timed/timed/Makefile +++ b/usr.sbin/timed/timed/Makefile @@ -10,7 +10,5 @@ SRCS= acksend.c candidate.c correct.c master.c networkdelta.c readmsg.c \ DPADD= ${LIBUTIL} LDADD= -lutil MAN= timed.8 -WARNS?= 3 -.include "../../Makefile.inc" .include diff --git a/usr.sbin/timed/timedc/Makefile b/usr.sbin/timed/timedc/Makefile index bfd5ed689a..0f3c5f38ba 100644 --- a/usr.sbin/timed/timedc/Makefile +++ b/usr.sbin/timed/timedc/Makefile @@ -8,5 +8,4 @@ MAN= timedc.8 BINMODE=4555 .PATH: ${.CURDIR}/../timed -.include "../../Makefile.inc" .include diff --git a/usr.sbin/traceroute/Makefile b/usr.sbin/traceroute/Makefile index 5518fc7311..f47b5daaf2 100644 --- a/usr.sbin/traceroute/Makefile +++ b/usr.sbin/traceroute/Makefile @@ -5,8 +5,4 @@ PROG= traceroute MAN= traceroute.8 BINMODE=4555 -SRCS= traceroute.c - -WARNS?= 6 - .include diff --git a/usr.sbin/traceroute6/Makefile b/usr.sbin/traceroute6/Makefile index f4e0537eba..0dda497ace 100644 --- a/usr.sbin/traceroute6/Makefile +++ b/usr.sbin/traceroute6/Makefile @@ -18,6 +18,7 @@ PROG= traceroute6 MAN= traceroute6.8 BINOWN= root BINMODE=4555 +WARNS?= 2 CFLAGS+=-DINET6 -DIPSEC -DHAVE_POLL -DUSE_RFC3542 diff --git a/usr.sbin/trpt/Makefile b/usr.sbin/trpt/Makefile index 39e5fb54aa..6fffb0fd21 100644 --- a/usr.sbin/trpt/Makefile +++ b/usr.sbin/trpt/Makefile @@ -7,6 +7,5 @@ MAN= trpt.8 BINGRP= kmem BINMODE=2555 CFLAGS+=-DINET6 -WARNS?= 6 .include diff --git a/usr.sbin/tzsetup/Makefile b/usr.sbin/tzsetup/Makefile index 52e66670f6..8edde07b91 100644 --- a/usr.sbin/tzsetup/Makefile +++ b/usr.sbin/tzsetup/Makefile @@ -6,5 +6,6 @@ MAN= tzsetup.8 CFLAGS+= -I${.CURDIR} LDADD+= -ldialog -lncurses -lmytinfo DPADD+= ${LIBDIALOG} ${LIBNCURSES} ${LIBMYTINFO} +WARNS?= 2 .include diff --git a/usr.sbin/tzsetup/tzsetup.c b/usr.sbin/tzsetup/tzsetup.c index 3d1a5d8847..37c618c6a0 100644 --- a/usr.sbin/tzsetup/tzsetup.c +++ b/usr.sbin/tzsetup/tzsetup.c @@ -91,7 +91,7 @@ static dialogMenuItem continents[] = { { "9", "Indian Ocean", 0, continent_country_menu, 0, &indian }, { "0", "Pacific Ocean", 0, continent_country_menu, 0, &pacific } }; -#define NCONTINENTS ((sizeof continents)/(sizeof continents[0])) +#define NCONTINENTS (int)((sizeof continents)/(sizeof continents[0])) #define OCEANP(x) ((x) == 3 || (x) == 5 || (x) == 8 || (x) == 9) static int diff --git a/usr.sbin/usbd/Makefile b/usr.sbin/usbd/Makefile index 3d56c84d72..da4f16530a 100644 --- a/usr.sbin/usbd/Makefile +++ b/usr.sbin/usbd/Makefile @@ -4,5 +4,6 @@ PROG= usbd MAN= usbd.conf.5 usbd.8 CFLAGS+=-I${.CURDIR}/../../sys +WARNS?= 1 .include diff --git a/usr.sbin/usbdevs/Makefile b/usr.sbin/usbdevs/Makefile index 2eb08372cd..f4ae4f8d7d 100644 --- a/usr.sbin/usbdevs/Makefile +++ b/usr.sbin/usbdevs/Makefile @@ -3,7 +3,6 @@ # $DragonFly: src/usr.sbin/usbdevs/Makefile,v 1.4 2005/01/17 01:49:24 cpressey Exp $ PROG= usbdevs -WARNS?= 6 MAN= usbdevs.8 CFLAGS+=-I${.CURDIR}/../../sys diff --git a/usr.sbin/vidcontrol/Makefile b/usr.sbin/vidcontrol/Makefile index 38756269e0..88d9e1d765 100644 --- a/usr.sbin/vidcontrol/Makefile +++ b/usr.sbin/vidcontrol/Makefile @@ -3,6 +3,5 @@ PROG= vidcontrol SRCS= vidcontrol.c decode.c -WARNS?= 6 .include diff --git a/usr.sbin/vipw/Makefile b/usr.sbin/vipw/Makefile index fe04569f88..11f8164414 100644 --- a/usr.sbin/vipw/Makefile +++ b/usr.sbin/vipw/Makefile @@ -5,5 +5,6 @@ PROG= vipw SRCS= pw_util.c vipw.c MAN= vipw.8 +WARNS?= 2 .include diff --git a/usr.sbin/vknetd/Makefile b/usr.sbin/vknetd/Makefile index b69cb034af..a96c9261e7 100644 --- a/usr.sbin/vknetd/Makefile +++ b/usr.sbin/vknetd/Makefile @@ -5,5 +5,6 @@ PROG= vknetd MAN= vknetd.8 CFLAGS += -DUSE_PTHREADS=1 -pthread SRCS= vknetd.c bridge.c mac.c filter.c +WARNS?= 1 .include diff --git a/usr.sbin/vknetd/filter.c b/usr.sbin/vknetd/filter.c index fc5c2636af..2d80b88b17 100644 --- a/usr.sbin/vknetd/filter.c +++ b/usr.sbin/vknetd/filter.c @@ -38,6 +38,7 @@ */ #include "vknetd.h" #include +#include /* * Return on-zero if the packet should be passed through, zero if it should @@ -70,12 +71,17 @@ filter_ok(u_int8_t *pkt, int bytes) case 1: /* ICMP */ /* XXX fix me */ break; - case 6: /* TCP */ case 17: /* UDP */ + case 6: /* TCP */ /* - * ip_src must represent our network. + * ip_src must represent our network or be 0. + * 0 is a special case, mainly so bootp (dhclient) gets + * through. */ - if ((ip->ip_src.s_addr & NetMask.s_addr) != + if (ip->ip_src.s_addr == 0) + break; + if (SecureOpt && + (ip->ip_src.s_addr & NetMask.s_addr) != (NetAddress.s_addr & NetMask.s_addr)) { fprintf(stderr, "Filtered Address: %08x\n", ntohl(ip->ip_src.s_addr)); diff --git a/usr.sbin/vknetd/vknetd.8 b/usr.sbin/vknetd/vknetd.8 index 5574a21557..afaa63c7dd 100644 --- a/usr.sbin/vknetd/vknetd.8 +++ b/usr.sbin/vknetd/vknetd.8 @@ -33,12 +33,12 @@ .\" .\" $DragonFly: src/usr.sbin/vknetd/vknetd.8,v 1.3 2008/05/31 12:04:15 swildner Exp $ .\" -.Dd May 26, 2008 +.Dd May 21, 2009 .Dt vknetd 8 .Os .Sh NAME .Nm vknetd -.Nd create a bridged network for (typically user-run) vkernel's +.Nd create a bridged network for (typically user-run) vkernels .Sh SYNOPSIS .Nm .Op Fl cdU @@ -63,21 +63,27 @@ interface. Any number of vkernels may connect to the virtual network. .Pp .Nm -Implements a simple bridge for all entities connected to it. A cache +Implements a simple bridge for all entities connected to it. +A cache of MAC addresses is built up (just like an etherswitch does) and matching packets will be forwarded directly to the proper 'port' (connected clients -or TAP interface). Unknown MACs will be broadcast. +or TAP interface). +Unknown MACs will be broadcast. .Pp The following options are available: .Bl -tag -width flag .It Fl c -Connect into the bridge and monitor activity. This option currently only -monitors broadcast packets. Packets with cached MACs are not monitored. +Connect into the bridge and monitor activity. +This option currently only monitors broadcast packets. +Packets with cached MACs are not monitored. .It Fl d -Debug mode. Do not go into the background. +Debug mode. +Do not go into the background. .It Fl U -Unsecure mode. Act as a pure bridge and do not try to secure the IP -space from host visibility. This is typically used with the +Unsecure mode. +Act as a pure bridge and do not try to secure the IP +space from host visibility. +This is typically used with the .Fl b option to directly bridge .Nm @@ -94,18 +100,26 @@ By default the socket is called .It Fl t Ar tapN Specify a particular .Xr tap 4 -interface to use. If not specified, +interface to use. +If not specified, .Nm will search for an unused tap interface. .It Ar address/cidrbits When operating in secure mode (which is the default), a CIDR block must be -specified. The address is the address you wish to assign to the TAP +specified. +It is optional in unsecure mode. +The address is the address you wish to assign to the TAP interface and will sit on both the host and virtual networks if not bridged. The .Ar cidrbits -is the number of bits representing the virtual subnet. For example, +is the number of bits representing the virtual subnet. +For example, 10.1.0.1/24 places the tap interface on 10.1.0.1 and gives you an 8 bit subnet capable of handling 254 hosts. +An address of 0.0.0.0 is allowed as a special case in secure mode so that +bootp +.Xr ( dhclient 8 ) +can get through. .El .Sh EXAMPLES .Li "vknetd 10.1.0.1/16" @@ -121,8 +135,8 @@ In addition, a 'vknet' group must exist in /etc/groups. .Bl -tag -width /var/log/lastlog -compact .It Pa /dev/tap* TAP interface used to route packets from userland providers back into the -real machine. If not otherwise specified an unused tap interface will be -selected. +real machine. +If not otherwise specified an unused tap interface will be selected. .It Pa /dev/vknet Default socket .Nm diff --git a/usr.sbin/vknetd/vknetd.c b/usr.sbin/vknetd/vknetd.c index d871305e66..af8108ea8d 100644 --- a/usr.sbin/vknetd/vknetd.c +++ b/usr.sbin/vknetd/vknetd.c @@ -55,6 +55,7 @@ pthread_mutex_t BridgeMutex; int SecureOpt = 1; int DebugOpt = 0; +int SetAddrOpt = 0; struct in_addr NetAddress; struct in_addr NetMask; @@ -96,6 +97,8 @@ main(int ac, char **av) } av += optind; ac -= optind; + if (ac) + SetAddrOpt = 1; /* * Special connect/debug mode @@ -114,8 +117,10 @@ main(int ac, char **av) * In secure mode (the default), a network address/mask must be * specified. e.g. 10.1.0.0/16. Any traffic going out the TAP * interface will be filtered. + * + * If non-secure mode the network address/mask is optional. */ - if (SecureOpt) { + if (SecureOpt || SetAddrOpt) { char *str; int masklen; u_int32_t mask; @@ -214,7 +219,7 @@ vknet_tap(const char *tapName, const char *bridgeName) /* * Set the interface address if in Secure mode. */ - if (SecureOpt) { + if (SetAddrOpt) { struct sockaddr_in *in; in = (void *)&ifra.ifra_addr; diff --git a/usr.sbin/vnconfig/Makefile b/usr.sbin/vnconfig/Makefile index af30a54e56..67c25481cf 100644 --- a/usr.sbin/vnconfig/Makefile +++ b/usr.sbin/vnconfig/Makefile @@ -5,6 +5,4 @@ PROG= vnconfig MAN= vnconfig.8 MLINKS= vnconfig.8 swapfile.8 -WARNS?= 6 - .include diff --git a/usr.sbin/watch/Makefile b/usr.sbin/watch/Makefile index a9787b24d1..297578f82e 100644 --- a/usr.sbin/watch/Makefile +++ b/usr.sbin/watch/Makefile @@ -4,8 +4,6 @@ PROG= watch MAN= watch.8 -WARNS?= 6 - LDADD= -ltermcap DPADD= ${LIBTERMCAP} diff --git a/usr.sbin/xten/Makefile b/usr.sbin/xten/Makefile index 40126754dc..a35f5db59c 100644 --- a/usr.sbin/xten/Makefile +++ b/usr.sbin/xten/Makefile @@ -4,5 +4,6 @@ PROG= xten CFLAGS+= -I${.CURDIR}/../../libexec/xtend +WARNS?= 2 .include diff --git a/usr.sbin/yp_mkdb/Makefile b/usr.sbin/yp_mkdb/Makefile index a30f38075f..74bec589aa 100644 --- a/usr.sbin/yp_mkdb/Makefile +++ b/usr.sbin/yp_mkdb/Makefile @@ -3,6 +3,7 @@ PROG= yp_mkdb SRCS= yp_mkdb.c yp_dblookup.c yp_dbwrite.c +WARNS?= 1 MAN= yp_mkdb.8 diff --git a/usr.sbin/ypbind/Makefile b/usr.sbin/ypbind/Makefile index cdf55e6540..9b1b27673f 100644 --- a/usr.sbin/ypbind/Makefile +++ b/usr.sbin/ypbind/Makefile @@ -6,5 +6,6 @@ SRCS= ypbind.c yp_ping.c PROG= ypbind MAN= ypbind.8 CFLAGS+=-DDAEMON +WARNS?= 2 .include diff --git a/usr.sbin/yppoll/Makefile b/usr.sbin/yppoll/Makefile index 2a72e1d455..eaee0593a2 100644 --- a/usr.sbin/yppoll/Makefile +++ b/usr.sbin/yppoll/Makefile @@ -4,5 +4,6 @@ PROG= yppoll MAN= yppoll.8 +WARNS?= 3 .include diff --git a/usr.sbin/yppush/Makefile b/usr.sbin/yppush/Makefile index 2732488336..88aec973f0 100644 --- a/usr.sbin/yppush/Makefile +++ b/usr.sbin/yppush/Makefile @@ -10,6 +10,7 @@ MAN= yppush.8 SRCS= ypxfr_getmap.c yp_dblookup.c yp_error.c ypxfr_misc.c yppush_main.c \ ${GENSRCS} GENSRCS=yp.h yp_clnt.c yppush_svc.c +WARNS?= 1 CFLAGS+= -I. -I${.CURDIR}/../../libexec/ypxfr diff --git a/usr.sbin/ypserv/Makefile b/usr.sbin/ypserv/Makefile index 44cc8b05b2..1e80cd57be 100644 --- a/usr.sbin/ypserv/Makefile +++ b/usr.sbin/ypserv/Makefile @@ -8,6 +8,7 @@ PROG= ypserv MAN= ypserv.8 ypinit.8 SRCS= yp_svc.c yp_server.c yp_dblookup.c yp_dnslookup.c \ ypxfr_clnt.c yp.h yp_main.c yp_error.c yp_access.c yp_svc_udp.c +WARNS?= 1 CFLAGS+= -DDB_CACHE -DTCP_WRAPPER -I. diff --git a/usr.sbin/ypset/Makefile b/usr.sbin/ypset/Makefile index 7b20d83a84..825d2ae2da 100644 --- a/usr.sbin/ypset/Makefile +++ b/usr.sbin/ypset/Makefile @@ -4,5 +4,6 @@ PROG= ypset MAN= ypset.8 +WARNS?= 2 .include diff --git a/usr.sbin/zic/Makefile.inc b/usr.sbin/zic/Makefile.inc index a03e78ef5e..b98e6b1e95 100644 --- a/usr.sbin/zic/Makefile.inc +++ b/usr.sbin/zic/Makefile.inc @@ -1,4 +1,6 @@ # $FreeBSD: src/usr.sbin/zic/Makefile.inc,v 1.4 1999/08/28 01:21:18 peter Exp $ # $DragonFly: src/usr.sbin/zic/Makefile.inc,v 1.2 2003/06/17 04:30:05 dillon Exp $ +WARNS?= 2 + .include "${.CURDIR}/../../Makefile.inc" diff --git a/usr.sbin/zic/zdump.c b/usr.sbin/zic/zdump.c index 6a6ef4c839..a690704d2b 100644 --- a/usr.sbin/zic/zdump.c +++ b/usr.sbin/zic/zdump.c @@ -258,7 +258,7 @@ main(int argc, char *argv[]) cuthiyear = hi; } else { errx(EXIT_FAILURE, - _("%s: wild -c argument %s\n"), + _("wild -c argument %s\n"), cutarg); } }