if_ath_spectral.c revision 244951
1244951Sadrian/*-
2244951Sadrian * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
3244951Sadrian * All rights reserved.
4244951Sadrian *
5244951Sadrian * Redistribution and use in source and binary forms, with or without
6244951Sadrian * modification, are permitted provided that the following conditions
7244951Sadrian * are met:
8244951Sadrian * 1. Redistributions of source code must retain the above copyright
9244951Sadrian *    notice, this list of conditions and the following disclaimer,
10244951Sadrian *    without modification.
11244951Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12244951Sadrian *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13244951Sadrian *    redistribution must be conditioned upon including a substantially
14244951Sadrian *    similar Disclaimer requirement for further binary redistribution.
15244951Sadrian *
16244951Sadrian * NO WARRANTY
17244951Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18244951Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19244951Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20244951Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21244951Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22244951Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23244951Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24244951Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25244951Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26244951Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27244951Sadrian * THE POSSIBILITY OF SUCH DAMAGES.
28244951Sadrian *
29244951Sadrian * $FreeBSD: head/sys/dev/ath/if_ath_spectral.c 244951 2013-01-02 03:59:02Z adrian $
30244951Sadrian */
31244951Sadrian#include <sys/cdefs.h>
32244951Sadrian__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_spectral.c 244951 2013-01-02 03:59:02Z adrian $");
33244951Sadrian
34244951Sadrian/*
35244951Sadrian * Implement some basic spectral scan control logic.
36244951Sadrian */
37244951Sadrian#include "opt_ath.h"
38244951Sadrian#include "opt_inet.h"
39244951Sadrian#include "opt_wlan.h"
40244951Sadrian
41244951Sadrian#include <sys/param.h>
42244951Sadrian#include <sys/systm.h>
43244951Sadrian#include <sys/sysctl.h>
44244951Sadrian#include <sys/kernel.h>
45244951Sadrian#include <sys/lock.h>
46244951Sadrian#include <sys/mutex.h>
47244951Sadrian#include <sys/errno.h>
48244951Sadrian
49244951Sadrian#include <machine/bus.h>
50244951Sadrian#include <machine/resource.h>
51244951Sadrian#include <sys/bus.h>
52244951Sadrian
53244951Sadrian#include <sys/socket.h>
54244951Sadrian
55244951Sadrian#include <net/if.h>
56244951Sadrian#include <net/if_media.h>
57244951Sadrian#include <net/if_arp.h>
58244951Sadrian#include <net/ethernet.h>		/* XXX for ether_sprintf */
59244951Sadrian
60244951Sadrian#include <net80211/ieee80211_var.h>
61244951Sadrian
62244951Sadrian#include <net/bpf.h>
63244951Sadrian
64244951Sadrian#ifdef INET
65244951Sadrian#include <netinet/in.h>
66244951Sadrian#include <netinet/if_ether.h>
67244951Sadrian#endif
68244951Sadrian
69244951Sadrian#include <dev/ath/if_athvar.h>
70244951Sadrian#include <dev/ath/if_ath_spectral.h>
71244951Sadrian
72244951Sadrian#include <dev/ath/ath_hal/ah_desc.h>
73244951Sadrian
74244951Sadrianstruct ath_spectral_state {
75244951Sadrian	HAL_SPECTRAL_PARAM	spectral_state;
76244951Sadrian	int	spectral_active;
77244951Sadrian	int	spectral_enabled;
78244951Sadrian};
79244951Sadrian
80244951Sadrian/*
81244951Sadrian * Methods which are required
82244951Sadrian */
83244951Sadrian
84244951Sadrian/*
85244951Sadrian * Attach DFS to the given interface
86244951Sadrian */
87244951Sadrianint
88244951Sadrianath_spectral_attach(struct ath_softc *sc)
89244951Sadrian{
90244951Sadrian	struct ath_spectral_state *ss;
91244951Sadrian
92244951Sadrian	ss = malloc(sizeof(struct ath_spectral_state),
93244951Sadrian	    M_TEMP, M_WAITOK | M_ZERO);
94244951Sadrian
95244951Sadrian	if (ss == NULL) {
96244951Sadrian		device_printf(sc->sc_dev, "%s: failed to alloc memory\n",
97244951Sadrian		    __func__);
98244951Sadrian		return (-ENOMEM);
99244951Sadrian	}
100244951Sadrian
101244951Sadrian	sc->sc_spectral = ss;
102244951Sadrian
103244951Sadrian	(void) ath_hal_spectral_get_config(sc->sc_ah, &ss->spectral_state);
104244951Sadrian
105244951Sadrian	return (0);
106244951Sadrian}
107244951Sadrian
108244951Sadrian/*
109244951Sadrian * Detach DFS from the given interface
110244951Sadrian */
111244951Sadrianint
112244951Sadrianath_spectral_detach(struct ath_softc *sc)
113244951Sadrian{
114244951Sadrian	if (sc->sc_spectral != NULL) {
115244951Sadrian		free(sc->sc_spectral, M_TEMP);
116244951Sadrian	}
117244951Sadrian	return (0);
118244951Sadrian}
119244951Sadrian
120244951Sadrian/*
121244951Sadrian * Check whether spectral needs enabling and if so,
122244951Sadrian * flip it on.
123244951Sadrian */
124244951Sadrianint
125244951Sadrianath_spectral_enable(struct ath_softc *sc, struct ieee80211_channel *ch)
126244951Sadrian{
127244951Sadrian
128244951Sadrian	return (0);
129244951Sadrian}
130244951Sadrian
131244951Sadrian/*
132244951Sadrian * Handle ioctl requests from the diagnostic interface.
133244951Sadrian *
134244951Sadrian * The initial part of this code resembles ath_ioctl_diag();
135244951Sadrian * it's likely a good idea to reduce duplication between
136244951Sadrian * these two routines.
137244951Sadrian */
138244951Sadrianint
139244951Sadrianath_ioctl_spectral(struct ath_softc *sc, struct ath_diag *ad)
140244951Sadrian{
141244951Sadrian	unsigned int id = ad->ad_id & ATH_DIAG_ID;
142244951Sadrian	void *indata = NULL;
143244951Sadrian	void *outdata = NULL;
144244951Sadrian	u_int32_t insize = ad->ad_in_size;
145244951Sadrian	u_int32_t outsize = ad->ad_out_size;
146244951Sadrian	int error = 0;
147244951Sadrian	HAL_SPECTRAL_PARAM peout;
148244951Sadrian	HAL_SPECTRAL_PARAM *pe;
149244951Sadrian	struct ath_spectral_state *ss = sc->sc_spectral;
150244951Sadrian
151244951Sadrian	if (ad->ad_id & ATH_DIAG_IN) {
152244951Sadrian		/*
153244951Sadrian		 * Copy in data.
154244951Sadrian		 */
155244951Sadrian		indata = malloc(insize, M_TEMP, M_NOWAIT);
156244951Sadrian		if (indata == NULL) {
157244951Sadrian			error = ENOMEM;
158244951Sadrian			goto bad;
159244951Sadrian		}
160244951Sadrian		error = copyin(ad->ad_in_data, indata, insize);
161244951Sadrian		if (error)
162244951Sadrian			goto bad;
163244951Sadrian	}
164244951Sadrian	if (ad->ad_id & ATH_DIAG_DYN) {
165244951Sadrian		/*
166244951Sadrian		 * Allocate a buffer for the results (otherwise the HAL
167244951Sadrian		 * returns a pointer to a buffer where we can read the
168244951Sadrian		 * results).  Note that we depend on the HAL leaving this
169244951Sadrian		 * pointer for us to use below in reclaiming the buffer;
170244951Sadrian		 * may want to be more defensive.
171244951Sadrian		 */
172244951Sadrian		outdata = malloc(outsize, M_TEMP, M_NOWAIT);
173244951Sadrian		if (outdata == NULL) {
174244951Sadrian			error = ENOMEM;
175244951Sadrian			goto bad;
176244951Sadrian		}
177244951Sadrian	}
178244951Sadrian	switch (id) {
179244951Sadrian		case SPECTRAL_CONTROL_GET_PARAMS:
180244951Sadrian			memset(&peout, 0, sizeof(peout));
181244951Sadrian			outsize = sizeof(HAL_SPECTRAL_PARAM);
182244951Sadrian			ath_hal_spectral_get_config(sc->sc_ah, &peout);
183244951Sadrian			pe = (HAL_SPECTRAL_PARAM *) outdata;
184244951Sadrian			memcpy(pe, &peout, sizeof(*pe));
185244951Sadrian			break;
186244951Sadrian		case SPECTRAL_CONTROL_SET_PARAMS:
187244951Sadrian			if (insize < sizeof(HAL_SPECTRAL_PARAM)) {
188244951Sadrian				error = EINVAL;
189244951Sadrian				break;
190244951Sadrian			}
191244951Sadrian			pe = (HAL_SPECTRAL_PARAM *) indata;
192244951Sadrian			ath_hal_spectral_configure(sc->sc_ah, pe);
193244951Sadrian			/* Save a local copy of the updated parameters */
194244951Sadrian			ath_hal_spectral_get_config(sc->sc_ah,
195244951Sadrian			    &ss->spectral_state);
196244951Sadrian			break;
197244951Sadrian		case SPECTRAL_CONTROL_START:
198244951Sadrian			ath_hal_spectral_configure(sc->sc_ah,
199244951Sadrian			    &ss->spectral_state);
200244951Sadrian			(void) ath_hal_spectral_start(sc->sc_ah);
201244951Sadrian			break;
202244951Sadrian		case SPECTRAL_CONTROL_STOP:
203244951Sadrian			(void) ath_hal_spectral_stop(sc->sc_ah);
204244951Sadrian			break;
205244951Sadrian		case SPECTRAL_CONTROL_ENABLE:
206244951Sadrian			/* XXX TODO */
207244951Sadrian		case SPECTRAL_CONTROL_DISABLE:
208244951Sadrian			/* XXX TODO */
209244951Sadrian		break;
210244951Sadrian		default:
211244951Sadrian			error = EINVAL;
212244951Sadrian	}
213244951Sadrian	if (outsize < ad->ad_out_size)
214244951Sadrian		ad->ad_out_size = outsize;
215244951Sadrian	if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size))
216244951Sadrian		error = EFAULT;
217244951Sadrianbad:
218244951Sadrian	if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL)
219244951Sadrian		free(indata, M_TEMP);
220244951Sadrian	if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL)
221244951Sadrian		free(outdata, M_TEMP);
222244951Sadrian	return (error);
223244951Sadrian}
224244951Sadrian
225