1242781Sadrian/*- 2242781Sadrian * Copyright (c) 2012 Adrian Chadd 3242781Sadrian * All rights reserved. 4242781Sadrian * 5242781Sadrian * Redistribution and use in source and binary forms, with or without 6242781Sadrian * modification, are permitted provided that the following conditions 7242781Sadrian * are met: 8242781Sadrian * 1. Redistributions of source code must retain the above copyright 9242781Sadrian * notice, this list of conditions and the following disclaimer, 10242781Sadrian * without modification. 11242781Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12242781Sadrian * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13242781Sadrian * redistribution must be conditioned upon including a substantially 14242781Sadrian * similar Disclaimer requirement for further binary redistribution. 15242781Sadrian * 16242781Sadrian * NO WARRANTY 17242781Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18242781Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19242781Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20242781Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21242781Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22242781Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23242781Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24242781Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25242781Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26242781Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27242781Sadrian * THE POSSIBILITY OF SUCH DAMAGES. 28242781Sadrian * 29242781Sadrian * $FreeBSD$ 30242781Sadrian */ 31242781Sadrian#include "opt_ah.h" 32242781Sadrian#include "opt_ath.h" 33242781Sadrian 34242781Sadrian#include <sys/param.h> 35242781Sadrian#include <sys/systm.h> 36242781Sadrian#include <sys/kernel.h> 37242781Sadrian#include <sys/module.h> 38242781Sadrian#include <sys/sysctl.h> 39242781Sadrian#include <sys/bus.h> 40242781Sadrian#include <sys/malloc.h> 41242781Sadrian#include <sys/proc.h> 42242781Sadrian#include <sys/pcpu.h> 43242781Sadrian#include <sys/lock.h> 44242781Sadrian#include <sys/mutex.h> 45242781Sadrian#include <sys/alq.h> 46243158Sadrian#include <sys/endian.h> 47246648Sadrian#include <sys/time.h> 48242781Sadrian 49242781Sadrian#include <dev/ath/if_ath_alq.h> 50242781Sadrian 51242781Sadrian#ifdef ATH_DEBUG_ALQ 52242781Sadrianstatic struct ale * 53242781Sadrianif_ath_alq_get(struct if_ath_alq *alq, int len) 54242781Sadrian{ 55242781Sadrian struct ale *ale; 56242781Sadrian 57242781Sadrian if (alq->sc_alq_isactive == 0) 58242781Sadrian return (NULL); 59242781Sadrian 60242781Sadrian ale = alq_getn(alq->sc_alq_alq, len, ALQ_NOWAIT); 61242781Sadrian if (! ale) 62242781Sadrian alq->sc_alq_numlost++; 63242781Sadrian return (ale); 64242781Sadrian} 65242781Sadrian 66242781Sadrianvoid 67242781Sadrianif_ath_alq_init(struct if_ath_alq *alq, const char *devname) 68242781Sadrian{ 69242781Sadrian 70242781Sadrian bzero(alq, sizeof(*alq)); 71242781Sadrian 72242781Sadrian strncpy(alq->sc_alq_devname, devname, ATH_ALQ_DEVNAME_LEN); 73242813Sadrian printf("%s (%s): attached\n", __func__, alq->sc_alq_devname); 74242781Sadrian snprintf(alq->sc_alq_filename, ATH_ALQ_FILENAME_LEN, 75242781Sadrian "/tmp/ath_%s_alq.log", alq->sc_alq_devname); 76242781Sadrian 77242781Sadrian /* XXX too conservative, right? */ 78242781Sadrian alq->sc_alq_qsize = (64*1024); 79242781Sadrian} 80242781Sadrian 81242781Sadrianvoid 82243158Sadrianif_ath_alq_setcfg(struct if_ath_alq *alq, uint32_t macVer, 83243158Sadrian uint32_t macRev, uint32_t phyRev, uint32_t halMagic) 84243158Sadrian{ 85243158Sadrian 86243158Sadrian /* Store these in network order */ 87243158Sadrian alq->sc_alq_cfg.sc_mac_version = htobe32(macVer); 88243158Sadrian alq->sc_alq_cfg.sc_mac_revision = htobe32(macRev); 89243158Sadrian alq->sc_alq_cfg.sc_phy_rev = htobe32(phyRev); 90243158Sadrian alq->sc_alq_cfg.sc_hal_magic = htobe32(halMagic); 91243158Sadrian} 92243158Sadrian 93243158Sadrianvoid 94242781Sadrianif_ath_alq_tidyup(struct if_ath_alq *alq) 95242781Sadrian{ 96242781Sadrian 97242781Sadrian if_ath_alq_stop(alq); 98242781Sadrian printf("%s (%s): detached\n", __func__, alq->sc_alq_devname); 99242781Sadrian bzero(alq, sizeof(*alq)); 100242781Sadrian} 101242781Sadrian 102242781Sadrianint 103242781Sadrianif_ath_alq_start(struct if_ath_alq *alq) 104242781Sadrian{ 105242781Sadrian int error; 106242781Sadrian 107242781Sadrian if (alq->sc_alq_isactive) 108242781Sadrian return (0); 109242781Sadrian 110242781Sadrian /* 111242781Sadrian * Create a variable-length ALQ. 112242781Sadrian */ 113242781Sadrian error = alq_open(&alq->sc_alq_alq, alq->sc_alq_filename, 114242781Sadrian curthread->td_ucred, ALQ_DEFAULT_CMODE, 115242781Sadrian alq->sc_alq_qsize, 0); 116242781Sadrian 117242781Sadrian if (error != 0) { 118242781Sadrian printf("%s (%s): failed, err=%d\n", __func__, 119242781Sadrian alq->sc_alq_devname, error); 120242781Sadrian } else { 121242781Sadrian printf("%s (%s): opened\n", __func__, alq->sc_alq_devname); 122242781Sadrian alq->sc_alq_isactive = 1; 123243158Sadrian if_ath_alq_post(alq, ATH_ALQ_INIT_STATE, 124243158Sadrian sizeof (struct if_ath_alq_init_state), 125243158Sadrian (char *) &alq->sc_alq_cfg); 126242781Sadrian } 127242781Sadrian return (error); 128242781Sadrian} 129242781Sadrian 130242781Sadrianint 131242781Sadrianif_ath_alq_stop(struct if_ath_alq *alq) 132242781Sadrian{ 133242781Sadrian 134242781Sadrian if (alq->sc_alq_isactive == 0) 135242781Sadrian return (0); 136242781Sadrian 137242781Sadrian printf("%s (%s): closed\n", __func__, alq->sc_alq_devname); 138242781Sadrian 139242781Sadrian alq->sc_alq_isactive = 0; 140242781Sadrian alq_close(alq->sc_alq_alq); 141242781Sadrian alq->sc_alq_alq = NULL; 142242781Sadrian 143242781Sadrian return (0); 144242781Sadrian} 145242781Sadrian 146242781Sadrian/* 147242781Sadrian * Post a debug message to the ALQ. 148242781Sadrian * 149242781Sadrian * "len" is the size of the buf payload in bytes. 150242781Sadrian */ 151242781Sadrianvoid 152242781Sadrianif_ath_alq_post(struct if_ath_alq *alq, uint16_t op, uint16_t len, 153242781Sadrian const char *buf) 154242781Sadrian{ 155242781Sadrian struct if_ath_alq_hdr *ap; 156242781Sadrian struct ale *ale; 157246648Sadrian struct timeval tv; 158242781Sadrian 159242781Sadrian if (! if_ath_alq_checkdebug(alq, op)) 160242781Sadrian return; 161242781Sadrian 162246648Sadrian microtime(&tv); 163246648Sadrian 164242781Sadrian /* 165242781Sadrian * Enforce some semblence of sanity on 'len'. 166242781Sadrian * Although strictly speaking, any length is possible - 167242781Sadrian * just be conservative so things don't get out of hand. 168242781Sadrian */ 169242781Sadrian if (len > ATH_ALQ_PAYLOAD_LEN) 170242781Sadrian len = ATH_ALQ_PAYLOAD_LEN; 171242781Sadrian 172242781Sadrian ale = if_ath_alq_get(alq, len + sizeof(struct if_ath_alq_hdr)); 173242781Sadrian 174242781Sadrian if (ale == NULL) 175242781Sadrian return; 176242781Sadrian 177242781Sadrian ap = (struct if_ath_alq_hdr *) ale->ae_data; 178243158Sadrian ap->threadid = htobe64((uint64_t) curthread->td_tid); 179246648Sadrian ap->tstamp_sec = htobe32((uint32_t) tv.tv_sec); 180246648Sadrian ap->tstamp_usec = htobe32((uint32_t) tv.tv_usec); 181243158Sadrian ap->op = htobe16(op); 182243158Sadrian ap->len = htobe16(len); 183242781Sadrian 184242781Sadrian /* 185242781Sadrian * Copy the payload _after_ the header field. 186242781Sadrian */ 187250618Sadrian if (buf != NULL) { 188250618Sadrian memcpy(((char *) ap) + sizeof(struct if_ath_alq_hdr), 189250618Sadrian buf, 190250618Sadrian len); 191250618Sadrian } 192242781Sadrian 193242781Sadrian alq_post(alq->sc_alq_alq, ale); 194242781Sadrian} 195242781Sadrian#endif /* ATH_DEBUG */ 196