Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 20 Feb 2008 00:25:09 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 135761 for review
Message-ID:  <200802200025.m1K0P93x041839@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=135761

Change 135761 by sam@sam_ebb on 2008/02/20 00:25:08

	hookup regdomain support

Affected files ...

.. //depot/projects/vap/sys/dev/ath/if_ath.c#29 edit
.. //depot/projects/vap/sys/dev/ath/if_athvar.h#15 edit

Differences ...

==== //depot/projects/vap/sys/dev/ath/if_ath.c#29 (text+ko) ====

@@ -178,8 +178,12 @@
 static int	ath_newstate(struct ieee80211vap *, enum ieee80211_state, int);
 static void	ath_setup_stationkey(struct ieee80211_node *);
 static void	ath_newassoc(struct ieee80211_node *, int);
-static int	ath_getchannels(struct ath_softc *,
-			HAL_REG_DOMAIN, HAL_CTRY_CODE, HAL_BOOL, HAL_BOOL);
+static int	ath_setregdomain(struct ieee80211com *,
+		    struct ieee80211_regdomain *, int,
+		    struct ieee80211_channel []);
+static void	ath_getradiocaps(struct ieee80211com *, int *,
+		    struct ieee80211_channel []);
+static int	ath_getchannels(struct ath_softc *);
 static void	ath_led_event(struct ath_softc *, int);
 
 static int	ath_rate_setup(struct ath_softc *, u_int mode);
@@ -197,21 +201,6 @@
 static	int ath_calinterval = 30;		/* calibrate every 30 secs */
 SYSCTL_INT(_hw_ath, OID_AUTO, calibrate, CTLFLAG_RW, &ath_calinterval,
 	    0, "chip calibration interval (secs)");
-static	int ath_outdoor = AH_TRUE;		/* outdoor operation */
-SYSCTL_INT(_hw_ath, OID_AUTO, outdoor, CTLFLAG_RW, &ath_outdoor,
-	    0, "outdoor operation");
-TUNABLE_INT("hw.ath.outdoor", &ath_outdoor);
-static	int ath_xchanmode = AH_TRUE;		/* extended channel use */
-SYSCTL_INT(_hw_ath, OID_AUTO, xchanmode, CTLFLAG_RW, &ath_xchanmode,
-	    0, "extended channel mode");
-TUNABLE_INT("hw.ath.xchanmode", &ath_xchanmode);
-static	int ath_countrycode = CTRY_DEFAULT;	/* country code */
-SYSCTL_INT(_hw_ath, OID_AUTO, countrycode, CTLFLAG_RW, &ath_countrycode,
-	    0, "country code");
-TUNABLE_INT("hw.ath.countrycode", &ath_countrycode);
-static	int ath_regdomain = 0;			/* regulatory domain */
-SYSCTL_INT(_hw_ath, OID_AUTO, regdomain, CTLFLAG_RD, &ath_regdomain,
-	    0, "regulatory domain");
 
 static	int ath_rxbuf = ATH_RXBUF;		/* # rx buffers to allocate */
 SYSCTL_INT(_hw_ath, OID_AUTO, rxbuf, CTLFLAG_RW, &ath_rxbuf,
@@ -350,13 +339,9 @@
 		ath_hal_keyreset(ah, i);
 
 	/*
-	 * Collect the channel list using the default country
-	 * code and including outdoor channels.  The 802.11 layer
-	 * is resposible for filtering this list based on settings
-	 * like the phy mode.
+	 * Collect the default channel list.
 	 */
-	error = ath_getchannels(sc, ath_regdomain, ath_countrycode,
-			ath_outdoor != 0, ath_xchanmode != 0);
+	error = ath_getchannels(sc);
 	if (error != 0)
 		goto bad;
 
@@ -583,7 +568,7 @@
 	sc->sc_hastsfadd = ath_hal_hastsfadjust(ah);
 	if (ath_hal_hasfastframes(ah))
 		ic->ic_caps |= IEEE80211_C_FF;
-	if (ath_hal_getwirelessmodes(ah, ath_countrycode) & (HAL_MODE_108G|HAL_MODE_TURBO))
+	if (ath_hal_getwirelessmodes(ah, ic->ic_regdomain.country) & (HAL_MODE_108G|HAL_MODE_TURBO))
 		ic->ic_caps |= IEEE80211_C_TURBOP;
 
 	/*
@@ -610,6 +595,8 @@
 	ic->ic_max_keyix = sc->sc_keymax;
 	/* call MI attach routine. */
 	ieee80211_ifattach(ic);
+	ic->ic_setregdomain = ath_setregdomain;
+	ic->ic_getradiocaps = ath_getradiocaps;
 	sc->sc_opmode = HAL_M_STA;
 
 	/* override default methods */
@@ -5694,43 +5681,40 @@
 }
 
 static int
-ath_getchannels(struct ath_softc *sc,
-    HAL_REG_DOMAIN rd, HAL_CTRY_CODE cc, HAL_BOOL outdoor, HAL_BOOL xchanmode)
+getchannels(struct ath_softc *sc, int *nchans, struct ieee80211_channel chans[],
+	int cc, int ecm, int outdoor)
 {
-	struct ieee80211com *ic = &sc->sc_ic;
-	struct ifnet *ifp = sc->sc_ifp;
 	struct ath_hal *ah = sc->sc_ah;
-	HAL_CHANNEL *chans;
-	int i, nchan;
-	u_int32_t regdomain;
+	HAL_CHANNEL *halchans;
+	int i, nhalchans, error;
 
-	chans = malloc(IEEE80211_CHAN_MAX * sizeof(HAL_CHANNEL),
+	halchans = malloc(IEEE80211_CHAN_MAX * sizeof(HAL_CHANNEL),
 			M_TEMP, M_NOWAIT);
-	if (chans == NULL) {
-		if_printf(ifp, "unable to allocate channel table\n");
+	if (halchans == NULL) {
+		device_printf(sc->sc_dev,
+		    "%s: unable to allocate channel table\n", __func__);
 		return ENOMEM;
 	}
-	if (!ath_hal_init_channels(ah, chans, IEEE80211_CHAN_MAX, &nchan,
-	    NULL, 0, NULL, cc, HAL_MODE_ALL, outdoor, xchanmode)) {
-		(void) ath_hal_getregdomain(ah, &regdomain);
-		if_printf(ifp, "unable to collect channel list from hal; "
-			"regdomain likely %u country code %u\n", regdomain, cc);
-		free(chans, M_TEMP);
-		return EINVAL;
+	error = 0;
+	if (!ath_hal_init_channels(ah, halchans, IEEE80211_CHAN_MAX, &nhalchans,
+	    NULL, 0, NULL, CTRY_DEFAULT, HAL_MODE_ALL, AH_FALSE, AH_TRUE)) {
+		error = EINVAL;
+		goto done;
 	}
+	if (nchans == NULL)		/* no table requested */
+		goto done;
 
 	/*
 	 * Convert HAL channels to ieee80211 ones.
 	 */
-	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
-	for (i = 0; i < nchan; i++) {
-		HAL_CHANNEL *c = &chans[i];
-		struct ieee80211_channel *ichan = &ic->ic_channels[i];
+	for (i = 0; i < nhalchans; i++) {
+		HAL_CHANNEL *c = &halchans[i];
+		struct ieee80211_channel *ichan = &chans[i];
 
 		ichan->ic_ieee = ath_hal_mhz2ieee(ah, c->channel,
 					c->channelFlags);
 		if (bootverbose)
-			if_printf(ifp, "hal channel %u/%x -> %u\n",
+			device_printf(sc->sc_dev, "hal channel %u/%x -> %u\n",
 			    c->channel, c->channelFlags, ichan->ic_ieee);
 		ichan->ic_freq = c->channel;
 
@@ -5756,12 +5740,94 @@
 		ichan->ic_maxpower = c->maxTxPower;		/* 1/2 dBm */
 		ichan->ic_minpower = c->minTxPower;		/* 1/2 dBm */
 	}
-	ic->ic_nchans = nchan;
-	free(chans, M_TEMP);
-	(void) ath_hal_getregdomain(ah, &sc->sc_regdomain);
-	ath_hal_getcountrycode(ah, &sc->sc_countrycode);
-	sc->sc_xchanmode = xchanmode;
-	sc->sc_outdoor = outdoor;
+	*nchans = nhalchans;
+done:
+	free(halchans, M_TEMP);
+	return error;
+}
+
+static int
+ath_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *rd,
+	int nchans, struct ieee80211_channel chans[])
+{
+	struct ath_softc *sc = ic->ic_ifp->if_softc;
+	struct ath_hal *ah = sc->sc_ah;
+	u_int32_t ord;
+	int error;
+
+	(void) ath_hal_getregdomain(ah, &ord);
+	/* XXX map sku->rd */
+	ath_hal_setregdomain(ah, rd->regdomain);
+	error = getchannels(sc, &nchans, chans, rd->country,
+	     rd->ecm ? AH_TRUE : AH_FALSE,
+	     rd->location == 'O' ? AH_TRUE : AH_FALSE);
+	if (error != 0) {
+		/*
+		 * Restore previous state.
+		 */
+		ath_hal_setregdomain(ah, ord);
+		(void) getchannels(sc, NULL, NULL, ic->ic_regdomain.country,
+		     ic->ic_regdomain.ecm ? AH_TRUE : AH_FALSE,
+		     ic->ic_regdomain.location == 'O' ? AH_TRUE : AH_FALSE);
+		return error;
+	}
+	return 0;
+}
+
+static void
+ath_getradiocaps(struct ieee80211com *ic,
+	int *nchans, struct ieee80211_channel chans[])
+{
+	struct ath_softc *sc = ic->ic_ifp->if_softc;
+	struct ath_hal *ah = sc->sc_ah;
+	u_int32_t ord;
+
+	(void) ath_hal_getregdomain(ah, &ord);
+	ath_hal_setregdomain(ah, 0);
+	/* XXX not quite right but close enough for now */
+	getchannels(sc, nchans, chans, CTRY_DEBUG, AH_TRUE, AH_FALSE);
+	ath_hal_setregdomain(ah, ord);
+}
+
+static int
+ath_mapregdomain(struct ath_softc *sc, u_int32_t rd)
+{
+	/* map Atheros rd's to SKU's */
+	return rd;
+}
+
+static int
+ath_getchannels(struct ath_softc *sc)
+{
+	struct ieee80211com *ic = &sc->sc_ic;
+	struct ath_hal *ah = sc->sc_ah;
+	u_int32_t rd, cc;
+	int error;
+
+	/*
+	 * Convert HAL channels to ieee80211 ones.
+	 */
+	error = getchannels(sc, &ic->ic_nchans, ic->ic_channels,
+	    CTRY_DEFAULT, AH_TRUE, AH_FALSE);
+	(void) ath_hal_getregdomain(ah, &rd);
+	ath_hal_getcountrycode(ah, &cc);	/* NB: cannot fail */
+	if (error) {
+		device_printf(sc->sc_dev,
+		    "%s: unable to collect channel list from hal, error %d\n",
+		    __func__, error);
+		if (error == EINVAL) {
+			device_printf(sc->sc_dev,
+			    "%s: regdomain likely %u country code %u\n",
+			    __func__, rd, cc);
+		}
+		return error;
+	}
+	ic->ic_regdomain.regdomain = ath_mapregdomain(sc, rd);
+	ic->ic_regdomain.country = cc;
+	ic->ic_regdomain.ecm = 1;
+	ic->ic_regdomain.location = 'I';
+	ic->ic_regdomain.isocc[0] = ' ';	/* XXX don't know */
+	ic->ic_regdomain.isocc[1] = ' ';
 	return 0;
 }
 

==== //depot/projects/vap/sys/dev/ath/if_athvar.h#15 (text+ko) ====

@@ -209,8 +209,6 @@
 	u_int8_t		sc_nbssid0;	/* # vap's using base mac */
 	uint32_t		sc_bssidmask;	/* bssid mask */
 
-	u_int32_t		sc_countrycode;
-	u_int32_t		sc_regdomain;
 	void 			(*sc_node_free)(struct ieee80211_node *);
 	device_t		sc_dev;
 	HAL_BUS_TAG		sc_st;		/* bus space tag */
@@ -497,7 +495,7 @@
 #define	ath_hal_getregdomain(_ah, _prd) \
 	(ath_hal_getcapability(_ah, HAL_CAP_REG_DMN, 0, (_prd)) == HAL_OK)
 #define	ath_hal_setregdomain(_ah, _rd) \
-	((*(_ah)->ah_setRegulatoryDomain)((_ah), (_rd), NULL))
+	(*(uint16_t *)(((uint8_t *)(_ah)) + 520) = (_rd))
 #define	ath_hal_getcountrycode(_ah, _pcc) \
 	(*(_pcc) = (_ah)->ah_countryCode)
 #define	ath_hal_hastkipsplit(_ah) \



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200802200025.m1K0P93x041839>