xref: /freebsd/sys/dev/ath/if_ath_spectral.c (revision 9af351f9e8b9ff056899a2aa0c7e9a140d44d243)
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