1*9af351f9SAdrian Chadd /*- 2*9af351f9SAdrian Chadd * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org> 3*9af351f9SAdrian Chadd * All rights reserved. 4*9af351f9SAdrian Chadd * 5*9af351f9SAdrian Chadd * Redistribution and use in source and binary forms, with or without 6*9af351f9SAdrian Chadd * modification, are permitted provided that the following conditions 7*9af351f9SAdrian Chadd * are met: 8*9af351f9SAdrian Chadd * 1. Redistributions of source code must retain the above copyright 9*9af351f9SAdrian Chadd * notice, this list of conditions and the following disclaimer, 10*9af351f9SAdrian Chadd * without modification. 11*9af351f9SAdrian Chadd * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12*9af351f9SAdrian Chadd * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13*9af351f9SAdrian Chadd * redistribution must be conditioned upon including a substantially 14*9af351f9SAdrian Chadd * similar Disclaimer requirement for further binary redistribution. 15*9af351f9SAdrian Chadd * 16*9af351f9SAdrian Chadd * NO WARRANTY 17*9af351f9SAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18*9af351f9SAdrian Chadd * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19*9af351f9SAdrian Chadd * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20*9af351f9SAdrian Chadd * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21*9af351f9SAdrian Chadd * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22*9af351f9SAdrian Chadd * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23*9af351f9SAdrian Chadd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24*9af351f9SAdrian Chadd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25*9af351f9SAdrian Chadd * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26*9af351f9SAdrian Chadd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27*9af351f9SAdrian Chadd * THE POSSIBILITY OF SUCH DAMAGES. 28*9af351f9SAdrian Chadd * 29*9af351f9SAdrian Chadd * $FreeBSD$ 30*9af351f9SAdrian Chadd */ 31*9af351f9SAdrian Chadd #include <sys/cdefs.h> 32*9af351f9SAdrian Chadd __FBSDID("$FreeBSD$"); 33*9af351f9SAdrian Chadd 34*9af351f9SAdrian Chadd /* 35*9af351f9SAdrian Chadd * Implement some basic spectral scan control logic. 36*9af351f9SAdrian Chadd */ 37*9af351f9SAdrian Chadd #include "opt_ath.h" 38*9af351f9SAdrian Chadd #include "opt_inet.h" 39*9af351f9SAdrian Chadd #include "opt_wlan.h" 40*9af351f9SAdrian Chadd 41*9af351f9SAdrian Chadd #include <sys/param.h> 42*9af351f9SAdrian Chadd #include <sys/systm.h> 43*9af351f9SAdrian Chadd #include <sys/sysctl.h> 44*9af351f9SAdrian Chadd #include <sys/kernel.h> 45*9af351f9SAdrian Chadd #include <sys/lock.h> 46*9af351f9SAdrian Chadd #include <sys/mutex.h> 47*9af351f9SAdrian Chadd #include <sys/errno.h> 48*9af351f9SAdrian Chadd 49*9af351f9SAdrian Chadd #include <machine/bus.h> 50*9af351f9SAdrian Chadd #include <machine/resource.h> 51*9af351f9SAdrian Chadd #include <sys/bus.h> 52*9af351f9SAdrian Chadd 53*9af351f9SAdrian Chadd #include <sys/socket.h> 54*9af351f9SAdrian Chadd 55*9af351f9SAdrian Chadd #include <net/if.h> 56*9af351f9SAdrian Chadd #include <net/if_media.h> 57*9af351f9SAdrian Chadd #include <net/if_arp.h> 58*9af351f9SAdrian Chadd #include <net/ethernet.h> /* XXX for ether_sprintf */ 59*9af351f9SAdrian Chadd 60*9af351f9SAdrian Chadd #include <net80211/ieee80211_var.h> 61*9af351f9SAdrian Chadd 62*9af351f9SAdrian Chadd #include <net/bpf.h> 63*9af351f9SAdrian Chadd 64*9af351f9SAdrian Chadd #ifdef INET 65*9af351f9SAdrian Chadd #include <netinet/in.h> 66*9af351f9SAdrian Chadd #include <netinet/if_ether.h> 67*9af351f9SAdrian Chadd #endif 68*9af351f9SAdrian Chadd 69*9af351f9SAdrian Chadd #include <dev/ath/if_athvar.h> 70*9af351f9SAdrian Chadd #include <dev/ath/if_ath_spectral.h> 71*9af351f9SAdrian Chadd 72*9af351f9SAdrian Chadd #include <dev/ath/ath_hal/ah_desc.h> 73*9af351f9SAdrian Chadd 74*9af351f9SAdrian Chadd struct ath_spectral_state { 75*9af351f9SAdrian Chadd HAL_SPECTRAL_PARAM spectral_state; 76*9af351f9SAdrian Chadd int spectral_active; 77*9af351f9SAdrian Chadd int spectral_enabled; 78*9af351f9SAdrian Chadd }; 79*9af351f9SAdrian Chadd 80*9af351f9SAdrian Chadd /* 81*9af351f9SAdrian Chadd * Methods which are required 82*9af351f9SAdrian Chadd */ 83*9af351f9SAdrian Chadd 84*9af351f9SAdrian Chadd /* 85*9af351f9SAdrian Chadd * Attach DFS to the given interface 86*9af351f9SAdrian Chadd */ 87*9af351f9SAdrian Chadd int 88*9af351f9SAdrian Chadd ath_spectral_attach(struct ath_softc *sc) 89*9af351f9SAdrian Chadd { 90*9af351f9SAdrian Chadd struct ath_spectral_state *ss; 91*9af351f9SAdrian Chadd 92*9af351f9SAdrian Chadd ss = malloc(sizeof(struct ath_spectral_state), 93*9af351f9SAdrian Chadd M_TEMP, M_WAITOK | M_ZERO); 94*9af351f9SAdrian Chadd 95*9af351f9SAdrian Chadd if (ss == NULL) { 96*9af351f9SAdrian Chadd device_printf(sc->sc_dev, "%s: failed to alloc memory\n", 97*9af351f9SAdrian Chadd __func__); 98*9af351f9SAdrian Chadd return (-ENOMEM); 99*9af351f9SAdrian Chadd } 100*9af351f9SAdrian Chadd 101*9af351f9SAdrian Chadd sc->sc_spectral = ss; 102*9af351f9SAdrian Chadd 103*9af351f9SAdrian Chadd (void) ath_hal_spectral_get_config(sc->sc_ah, &ss->spectral_state); 104*9af351f9SAdrian Chadd 105*9af351f9SAdrian Chadd return (0); 106*9af351f9SAdrian Chadd } 107*9af351f9SAdrian Chadd 108*9af351f9SAdrian Chadd /* 109*9af351f9SAdrian Chadd * Detach DFS from the given interface 110*9af351f9SAdrian Chadd */ 111*9af351f9SAdrian Chadd int 112*9af351f9SAdrian Chadd ath_spectral_detach(struct ath_softc *sc) 113*9af351f9SAdrian Chadd { 114*9af351f9SAdrian Chadd if (sc->sc_spectral != NULL) { 115*9af351f9SAdrian Chadd free(sc->sc_spectral, M_TEMP); 116*9af351f9SAdrian Chadd } 117*9af351f9SAdrian Chadd return (0); 118*9af351f9SAdrian Chadd } 119*9af351f9SAdrian Chadd 120*9af351f9SAdrian Chadd /* 121*9af351f9SAdrian Chadd * Check whether spectral needs enabling and if so, 122*9af351f9SAdrian Chadd * flip it on. 123*9af351f9SAdrian Chadd */ 124*9af351f9SAdrian Chadd int 125*9af351f9SAdrian Chadd ath_spectral_enable(struct ath_softc *sc, struct ieee80211_channel *ch) 126*9af351f9SAdrian Chadd { 127*9af351f9SAdrian Chadd 128*9af351f9SAdrian Chadd return (0); 129*9af351f9SAdrian Chadd } 130*9af351f9SAdrian Chadd 131*9af351f9SAdrian Chadd /* 132*9af351f9SAdrian Chadd * Handle ioctl requests from the diagnostic interface. 133*9af351f9SAdrian Chadd * 134*9af351f9SAdrian Chadd * The initial part of this code resembles ath_ioctl_diag(); 135*9af351f9SAdrian Chadd * it's likely a good idea to reduce duplication between 136*9af351f9SAdrian Chadd * these two routines. 137*9af351f9SAdrian Chadd */ 138*9af351f9SAdrian Chadd int 139*9af351f9SAdrian Chadd ath_ioctl_spectral(struct ath_softc *sc, struct ath_diag *ad) 140*9af351f9SAdrian Chadd { 141*9af351f9SAdrian Chadd unsigned int id = ad->ad_id & ATH_DIAG_ID; 142*9af351f9SAdrian Chadd void *indata = NULL; 143*9af351f9SAdrian Chadd void *outdata = NULL; 144*9af351f9SAdrian Chadd u_int32_t insize = ad->ad_in_size; 145*9af351f9SAdrian Chadd u_int32_t outsize = ad->ad_out_size; 146*9af351f9SAdrian Chadd int error = 0; 147*9af351f9SAdrian Chadd HAL_SPECTRAL_PARAM peout; 148*9af351f9SAdrian Chadd HAL_SPECTRAL_PARAM *pe; 149*9af351f9SAdrian Chadd struct ath_spectral_state *ss = sc->sc_spectral; 150*9af351f9SAdrian Chadd 151*9af351f9SAdrian Chadd if (ad->ad_id & ATH_DIAG_IN) { 152*9af351f9SAdrian Chadd /* 153*9af351f9SAdrian Chadd * Copy in data. 154*9af351f9SAdrian Chadd */ 155*9af351f9SAdrian Chadd indata = malloc(insize, M_TEMP, M_NOWAIT); 156*9af351f9SAdrian Chadd if (indata == NULL) { 157*9af351f9SAdrian Chadd error = ENOMEM; 158*9af351f9SAdrian Chadd goto bad; 159*9af351f9SAdrian Chadd } 160*9af351f9SAdrian Chadd error = copyin(ad->ad_in_data, indata, insize); 161*9af351f9SAdrian Chadd if (error) 162*9af351f9SAdrian Chadd goto bad; 163*9af351f9SAdrian Chadd } 164*9af351f9SAdrian Chadd if (ad->ad_id & ATH_DIAG_DYN) { 165*9af351f9SAdrian Chadd /* 166*9af351f9SAdrian Chadd * Allocate a buffer for the results (otherwise the HAL 167*9af351f9SAdrian Chadd * returns a pointer to a buffer where we can read the 168*9af351f9SAdrian Chadd * results). Note that we depend on the HAL leaving this 169*9af351f9SAdrian Chadd * pointer for us to use below in reclaiming the buffer; 170*9af351f9SAdrian Chadd * may want to be more defensive. 171*9af351f9SAdrian Chadd */ 172*9af351f9SAdrian Chadd outdata = malloc(outsize, M_TEMP, M_NOWAIT); 173*9af351f9SAdrian Chadd if (outdata == NULL) { 174*9af351f9SAdrian Chadd error = ENOMEM; 175*9af351f9SAdrian Chadd goto bad; 176*9af351f9SAdrian Chadd } 177*9af351f9SAdrian Chadd } 178*9af351f9SAdrian Chadd switch (id) { 179*9af351f9SAdrian Chadd case SPECTRAL_CONTROL_GET_PARAMS: 180*9af351f9SAdrian Chadd memset(&peout, 0, sizeof(peout)); 181*9af351f9SAdrian Chadd outsize = sizeof(HAL_SPECTRAL_PARAM); 182*9af351f9SAdrian Chadd ath_hal_spectral_get_config(sc->sc_ah, &peout); 183*9af351f9SAdrian Chadd pe = (HAL_SPECTRAL_PARAM *) outdata; 184*9af351f9SAdrian Chadd memcpy(pe, &peout, sizeof(*pe)); 185*9af351f9SAdrian Chadd break; 186*9af351f9SAdrian Chadd case SPECTRAL_CONTROL_SET_PARAMS: 187*9af351f9SAdrian Chadd if (insize < sizeof(HAL_SPECTRAL_PARAM)) { 188*9af351f9SAdrian Chadd error = EINVAL; 189*9af351f9SAdrian Chadd break; 190*9af351f9SAdrian Chadd } 191*9af351f9SAdrian Chadd pe = (HAL_SPECTRAL_PARAM *) indata; 192*9af351f9SAdrian Chadd ath_hal_spectral_configure(sc->sc_ah, pe); 193*9af351f9SAdrian Chadd /* Save a local copy of the updated parameters */ 194*9af351f9SAdrian Chadd ath_hal_spectral_get_config(sc->sc_ah, 195*9af351f9SAdrian Chadd &ss->spectral_state); 196*9af351f9SAdrian Chadd break; 197*9af351f9SAdrian Chadd case SPECTRAL_CONTROL_START: 198*9af351f9SAdrian Chadd ath_hal_spectral_configure(sc->sc_ah, 199*9af351f9SAdrian Chadd &ss->spectral_state); 200*9af351f9SAdrian Chadd (void) ath_hal_spectral_start(sc->sc_ah); 201*9af351f9SAdrian Chadd break; 202*9af351f9SAdrian Chadd case SPECTRAL_CONTROL_STOP: 203*9af351f9SAdrian Chadd (void) ath_hal_spectral_stop(sc->sc_ah); 204*9af351f9SAdrian Chadd break; 205*9af351f9SAdrian Chadd case SPECTRAL_CONTROL_ENABLE: 206*9af351f9SAdrian Chadd /* XXX TODO */ 207*9af351f9SAdrian Chadd case SPECTRAL_CONTROL_DISABLE: 208*9af351f9SAdrian Chadd /* XXX TODO */ 209*9af351f9SAdrian Chadd break; 210*9af351f9SAdrian Chadd default: 211*9af351f9SAdrian Chadd error = EINVAL; 212*9af351f9SAdrian Chadd } 213*9af351f9SAdrian Chadd if (outsize < ad->ad_out_size) 214*9af351f9SAdrian Chadd ad->ad_out_size = outsize; 215*9af351f9SAdrian Chadd if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size)) 216*9af351f9SAdrian Chadd error = EFAULT; 217*9af351f9SAdrian Chadd bad: 218*9af351f9SAdrian Chadd if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL) 219*9af351f9SAdrian Chadd free(indata, M_TEMP); 220*9af351f9SAdrian Chadd if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL) 221*9af351f9SAdrian Chadd free(outdata, M_TEMP); 222*9af351f9SAdrian Chadd return (error); 223*9af351f9SAdrian Chadd } 224*9af351f9SAdrian Chadd 225