From owner-svn-src-head@FreeBSD.ORG Wed Mar 11 17:41:47 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 10B39106567A; Wed, 11 Mar 2009 17:41:47 +0000 (UTC) (envelope-from sam@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id F15AB8FC33; Wed, 11 Mar 2009 17:41:46 +0000 (UTC) (envelope-from sam@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n2BHfkCT002381; Wed, 11 Mar 2009 17:41:46 GMT (envelope-from sam@svn.freebsd.org) Received: (from sam@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n2BHfkGQ002378; Wed, 11 Mar 2009 17:41:46 GMT (envelope-from sam@svn.freebsd.org) Message-Id: <200903111741.n2BHfkGQ002378@svn.freebsd.org> From: Sam Leffler Date: Wed, 11 Mar 2009 17:41:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r189704 - in head/tools/tools/ath: . athpoke X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 11 Mar 2009 17:41:48 -0000 Author: sam Date: Wed Mar 11 17:41:46 2009 New Revision: 189704 URL: http://svn.freebsd.org/changeset/base/189704 Log: add athpoke, a tool to peek/poke registers Added: head/tools/tools/ath/athpoke/ head/tools/tools/ath/athpoke/Makefile (contents, props changed) head/tools/tools/ath/athpoke/athpoke.c (contents, props changed) Modified: head/tools/tools/ath/Makefile Modified: head/tools/tools/ath/Makefile ============================================================================== --- head/tools/tools/ath/Makefile Wed Mar 11 17:40:39 2009 (r189703) +++ head/tools/tools/ath/Makefile Wed Mar 11 17:41:46 2009 (r189704) @@ -1,5 +1,5 @@ # $FreeBSD$ -SUBDIR= athdebug athdecode athkey athprom athrd athregs athstats +SUBDIR= athdebug athdecode athkey athpoke athprom athrd athregs athstats .include Added: head/tools/tools/ath/athpoke/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/tools/ath/athpoke/Makefile Wed Mar 11 17:41:46 2009 (r189704) @@ -0,0 +1,16 @@ +# $FreeBSD$ + +PROG= athpoke + +.PATH.c: ${.CURDIR}/../athregs +CFLAGS+=-I${.CURDIR}/../athregs + +SRCS= athpoke.c +SRCS+= dumpregs_5210.c +SRCS+= dumpregs_5211.c +SRCS+= dumpregs_5212.c +SRCS+= dumpregs_5416.c + +.include <../Makefile.inc> + +.include Added: head/tools/tools/ath/athpoke/athpoke.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/tools/ath/athpoke/athpoke.c Wed Mar 11 17:41:46 2009 (r189704) @@ -0,0 +1,239 @@ +/*- + * Copyright (c) 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: + * 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. + * + * 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. + * + * $FreeBSD$ + */ +#include "diag.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "dumpregs.h" + +#include +#include +#include +#include + +typedef struct { + HAL_REVS revs; +#define MAXREGS 5*1024 + struct dumpreg *regs[MAXREGS]; + u_int nregs; +} dumpregs_t; +static dumpregs_t state; + +static uint32_t regread(int s, struct ath_diag *atd, uint32_t r); +static void regwrite(int s, struct ath_diag *atd, uint32_t r, uint32_t v); +static const struct dumpreg *reglookup(const char *v); + +static void +usage(void) +{ + fprintf(stderr, "usage: athpoke [-i interface] [reg[=value]] ...\n"); + exit(-1); +} + +int +main(int argc, char *argv[]) +{ + struct ath_diag atd; + const char *ifname; + int c, s; + + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) + err(1, "socket"); + ifname = getenv("ATH"); + if (!ifname) + ifname = ATH_DEFAULT; + + while ((c = getopt(argc, argv, "i:")) != -1) + switch (c) { + case 'i': + ifname = optarg; + break; + default: + usage(); + /*NOTREACHED*/ + } + strncpy(atd.ad_name, ifname, sizeof (atd.ad_name)); + + atd.ad_id = HAL_DIAG_REVS; + atd.ad_out_data = (caddr_t) &state.revs; + atd.ad_out_size = sizeof(state.revs); + if (ioctl(s, SIOCGATHDIAG, &atd) < 0) + err(1, atd.ad_name); + + argc -= optind; + argv += optind; + + for (; argc > 0; argc--, argv++) { + char *cp; + const struct dumpreg *dr; + uint32_t reg; + + cp = strchr(argv[0], '='); + if (cp != NULL) + *cp++ = '\0'; + dr = reglookup(argv[0]); + reg = (dr != NULL) ? dr->addr : (uint32_t) strtoul(argv[0], NULL, 0); + if (cp != NULL) + regwrite(s, &atd, reg, (uint32_t) strtoul(cp, NULL, 0)); + else + printf("%s = %08x\n", argv[0], regread(s, &atd, reg)); + } + return 0; +} + +static uint32_t +regread(int s, struct ath_diag *atd, uint32_t r) +{ + HAL_REGRANGE ra; + uint32_t v[2]; + + ra.start = r; + ra.end = 0; + + atd->ad_in_data = (caddr_t) &ra; + atd->ad_in_size = sizeof(ra); + atd->ad_out_data = (caddr_t) v; + atd->ad_out_size = sizeof(v); + atd->ad_id = HAL_DIAG_REGS | ATH_DIAG_IN | ATH_DIAG_DYN; + if (ioctl(s, SIOCGATHDIAG, atd) < 0) + err(1, atd->ad_name); + return v[1]; +} + +static void +regwrite(int s, struct ath_diag *atd, uint32_t r, uint32_t v) +{ + HAL_REGWRITE rw; + + rw.addr = r; + rw.value = v; + atd->ad_in_data = (caddr_t) &rw; + atd->ad_in_size = sizeof(rw); + atd->ad_id = HAL_DIAG_SETREGS | ATH_DIAG_IN; + if (ioctl(s, SIOCGATHDIAG, atd) < 0) + err(1, atd->ad_name); +} + +static int +regcompar(const void *a, const void *b) +{ + const struct dumpreg *ra = *(const struct dumpreg **)a; + const struct dumpreg *rb = *(const struct dumpreg **)b; + return ra->addr - rb->addr; +} + +void +register_regs(struct dumpreg *chipregs, u_int nchipregs, + int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) +{ + const int existing_regs = state.nregs; + int i, j; + + for (i = 0; i < nchipregs; i++) { + struct dumpreg *nr = &chipregs[i]; + if (nr->srevMin == 0) + nr->srevMin = def_srev_min; + if (nr->srevMax == 0) + nr->srevMax = def_srev_max; + if (nr->phyMin == 0) + nr->phyMin = def_phy_min; + if (nr->phyMax == 0) + nr->phyMax = def_phy_max; + for (j = 0; j < existing_regs; j++) { + struct dumpreg *r = state.regs[j]; + /* + * Check if we can just expand the mac+phy + * coverage for the existing entry. + */ + if (nr->addr == r->addr && + (nr->name == r->name || + nr->name != NULL && r->name != NULL && + strcmp(nr->name, r->name) == 0)) { + if (nr->srevMin < r->srevMin && + (r->srevMin <= nr->srevMax && + nr->srevMax+1 <= r->srevMax)) { + r->srevMin = nr->srevMin; + goto skip; + } + if (nr->srevMax > r->srevMax && + (r->srevMin <= nr->srevMin && + nr->srevMin <= r->srevMax)) { + r->srevMax = nr->srevMax; + goto skip; + } + } + if (r->addr > nr->addr) + break; + } + /* + * New item, add to the end, it'll be sorted below. + */ + if (state.nregs == MAXREGS) + errx(-1, "too many registers; bump MAXREGS"); + state.regs[state.nregs++] = nr; + skip: + ; + } + qsort(state.regs, state.nregs, sizeof(struct dumpreg *), regcompar); +} + +void +register_keycache(u_int nslots, + int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) +{ + /* discard, no use */ +} + +void +register_range(u_int brange, u_int erange, int type, + int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) +{ + /* discard, no use */ +} + +static const struct dumpreg * +reglookup(const char *v) +{ + const HAL_REVS *revs = &state.revs; + int i; + + if (strncasecmp(v, "AR_", 3) == 0) + v += 3; + for (i = 0; i < state.nregs; i++) { + const struct dumpreg *dr = state.regs[i]; + if (MAC_MATCH(dr, revs->ah_macVersion, revs->ah_macRev) && + strcasecmp(v, dr->name) == 0) + return dr; + } + return NULL; +}