mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-06 00:20:29 +00:00
Add better mediaopt support for ibss and friends.
Now the driver is closer to matching the wi man page. Submitted by: jhay (who obtained it from OpenBSD).
This commit is contained in:
parent
0a9c401f9a
commit
d5ca4da61e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=98440
|
@ -312,6 +312,39 @@ wi_generic_attach(device_t dev)
|
|||
wi_read_record(sc, &gen);
|
||||
sc->wi_channel = gen.wi_val;
|
||||
|
||||
/*
|
||||
* Set flags based on firmware version.
|
||||
*/
|
||||
switch (sc->sc_firmware_type) {
|
||||
case WI_LUCENT:
|
||||
sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
|
||||
if (sc->sc_sta_firmware_ver >= 60000)
|
||||
sc->wi_flags |= WI_FLAGS_HAS_MOR;
|
||||
if (sc->sc_sta_firmware_ver >= 60006) {
|
||||
sc->wi_flags |= WI_FLAGS_HAS_IBSS;
|
||||
sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
|
||||
}
|
||||
sc->wi_ibss_port = htole16(1);
|
||||
break;
|
||||
case WI_INTERSIL:
|
||||
sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
|
||||
if (sc->sc_sta_firmware_ver >= 800) {
|
||||
sc->wi_flags |= WI_FLAGS_HAS_IBSS;
|
||||
sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
|
||||
}
|
||||
sc->wi_ibss_port = htole16(0);
|
||||
break;
|
||||
case WI_SYMBOL:
|
||||
sc->wi_flags |= WI_FLAGS_HAS_DIVERSITY;
|
||||
if (sc->sc_sta_firmware_ver >= 20000)
|
||||
sc->wi_flags |= WI_FLAGS_HAS_IBSS;
|
||||
/* Older Symbol firmware does not support IBSS creation. */
|
||||
if (sc->sc_sta_firmware_ver >= 25000)
|
||||
sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
|
||||
sc->wi_ibss_port = htole16(4);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find out if we support WEP on this card.
|
||||
*/
|
||||
|
@ -326,10 +359,13 @@ wi_generic_attach(device_t dev)
|
|||
/*
|
||||
* Find supported rates.
|
||||
*/
|
||||
gen.wi_type = WI_RID_TX_RATE;
|
||||
gen.wi_type = WI_RID_DATA_RATES;
|
||||
gen.wi_len = 2;
|
||||
wi_read_record(sc, &gen);
|
||||
sc->wi_supprates = gen.wi_val;
|
||||
if (wi_read_record(sc, &gen))
|
||||
sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M |
|
||||
WI_SUPPRATES_5M | WI_SUPPRATES_11M;
|
||||
else
|
||||
sc->wi_supprates = gen.wi_val;
|
||||
|
||||
bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
|
||||
|
||||
|
@ -337,36 +373,76 @@ wi_generic_attach(device_t dev)
|
|||
wi_stop(sc);
|
||||
|
||||
ifmedia_init(&sc->ifmedia, 0, wi_media_change, wi_media_status);
|
||||
/* XXX: Should read from card capabilities */
|
||||
#define ADD(m, c) ifmedia_add(&sc->ifmedia, (m), (c), NULL)
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
|
||||
IFM_IEEE80211_ADHOC, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
|
||||
IFM_IEEE80211_ADHOC, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
|
||||
IFM_IEEE80211_ADHOC, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
|
||||
IFM_IEEE80211_ADHOC, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
|
||||
IFM_IEEE80211_ADHOC, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
|
||||
if (sc->sc_firmware_type == WI_INTERSIL) {
|
||||
if (sc->wi_supprates & WI_SUPPRATES_1M) {
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
|
||||
IFM_IEEE80211_HOSTAP, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
|
||||
IFM_IEEE80211_HOSTAP, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
|
||||
IFM_IEEE80211_HOSTAP, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
|
||||
IFM_IEEE80211_HOSTAP, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
|
||||
IFM_IEEE80211_HOSTAP, 0), 0);
|
||||
IFM_IEEE80211_ADHOC, 0), 0);
|
||||
if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
|
||||
IFM_IEEE80211_IBSS, 0), 0);
|
||||
if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
|
||||
IFM_IEEE80211_IBSSMASTER, 0), 0);
|
||||
if (sc->sc_firmware_type == WI_INTERSIL)
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
|
||||
IFM_IEEE80211_HOSTAP, 0), 0);
|
||||
}
|
||||
#undef ADD
|
||||
if (sc->wi_supprates & WI_SUPPRATES_2M) {
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
|
||||
IFM_IEEE80211_ADHOC, 0), 0);
|
||||
if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
|
||||
IFM_IEEE80211_IBSS, 0), 0);
|
||||
if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
|
||||
IFM_IEEE80211_IBSSMASTER, 0), 0);
|
||||
if (sc->sc_firmware_type == WI_INTERSIL)
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
|
||||
IFM_IEEE80211_HOSTAP, 0), 0);
|
||||
}
|
||||
if (sc->wi_supprates & WI_SUPPRATES_5M) {
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
|
||||
IFM_IEEE80211_ADHOC, 0), 0);
|
||||
if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
|
||||
IFM_IEEE80211_IBSS, 0), 0);
|
||||
if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
|
||||
IFM_IEEE80211_IBSSMASTER, 0), 0);
|
||||
if (sc->sc_firmware_type == WI_INTERSIL)
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
|
||||
IFM_IEEE80211_HOSTAP, 0), 0);
|
||||
}
|
||||
if (sc->wi_supprates & WI_SUPPRATES_11M) {
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
|
||||
IFM_IEEE80211_ADHOC, 0), 0);
|
||||
if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
|
||||
IFM_IEEE80211_IBSS, 0), 0);
|
||||
if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
|
||||
IFM_IEEE80211_IBSSMASTER, 0), 0);
|
||||
if (sc->sc_firmware_type == WI_INTERSIL)
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
|
||||
IFM_IEEE80211_HOSTAP, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);
|
||||
}
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0);
|
||||
if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS,
|
||||
0), 0);
|
||||
if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
|
||||
IFM_IEEE80211_IBSSMASTER, 0), 0);
|
||||
if (sc->sc_firmware_type == WI_INTERSIL)
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
|
||||
IFM_IEEE80211_HOSTAP, 0), 0);
|
||||
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
|
||||
#undef ADD
|
||||
ifmedia_set(&sc->ifmedia, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
|
||||
0, 0));
|
||||
|
||||
|
@ -1065,7 +1141,15 @@ wi_read_record(sc, ltv)
|
|||
for (i = 0; i < ltv->wi_len - 1; i++)
|
||||
ptr[i] = CSR_READ_2(sc, WI_DATA1);
|
||||
|
||||
if (sc->sc_firmware_type != WI_LUCENT) {
|
||||
if (ltv->wi_type == WI_RID_PORTTYPE && sc->wi_ptype == WI_PORTTYPE_IBSS
|
||||
&& ltv->wi_val == sc->wi_ibss_port) {
|
||||
/*
|
||||
* Convert vendor IBSS port type to WI_PORTTYPE_IBSS.
|
||||
* Since Lucent uses port type 1 for BSS *and* IBSS we
|
||||
* have to rely on wi_ptype to distinguish this for us.
|
||||
*/
|
||||
ltv->wi_val = htole16(WI_PORTTYPE_IBSS);
|
||||
} else if (sc->sc_firmware_type != WI_LUCENT) {
|
||||
switch (oltv->wi_type) {
|
||||
case WI_RID_TX_RATE:
|
||||
case WI_RID_CUR_TX_RATE:
|
||||
|
@ -1116,7 +1200,14 @@ wi_write_record(sc, ltv)
|
|||
int i;
|
||||
struct wi_ltv_gen p2ltv;
|
||||
|
||||
if (sc->sc_firmware_type != WI_LUCENT) {
|
||||
if (ltv->wi_type == WI_RID_PORTTYPE &&
|
||||
le16toh(ltv->wi_val) == WI_PORTTYPE_IBSS) {
|
||||
/* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */
|
||||
p2ltv.wi_type = WI_RID_PORTTYPE;
|
||||
p2ltv.wi_len = 2;
|
||||
p2ltv.wi_val = sc->wi_ibss_port;
|
||||
ltv = &p2ltv;
|
||||
} else if (sc->sc_firmware_type != WI_LUCENT) {
|
||||
switch (ltv->wi_type) {
|
||||
case WI_RID_TX_RATE:
|
||||
p2ltv.wi_type = WI_RID_TX_RATE;
|
||||
|
@ -1935,12 +2026,12 @@ wi_init(xsc)
|
|||
/* Program max data length. */
|
||||
WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
|
||||
|
||||
/* Enable/disable IBSS creation. */
|
||||
WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
|
||||
|
||||
/* Set the port type. */
|
||||
WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
|
||||
|
||||
/* Enable/disable IBSS creation. */
|
||||
WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
|
||||
|
||||
/* Program the RTS/CTS threshold. */
|
||||
WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
|
||||
|
||||
|
@ -2725,13 +2816,37 @@ wi_media_change(ifp)
|
|||
struct wi_softc *sc = ifp->if_softc;
|
||||
int otype = sc->wi_ptype;
|
||||
int orate = sc->wi_tx_rate;
|
||||
int ocreate_ibss = sc->wi_create_ibss;
|
||||
|
||||
if ((sc->ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0)
|
||||
sc->wi_ptype = WI_PORTTYPE_ADHOC;
|
||||
else if ((sc->ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_HOSTAP) != 0)
|
||||
sc->wi_ptype = WI_PORTTYPE_AP;
|
||||
else
|
||||
if ((sc->ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_HOSTAP) &&
|
||||
sc->sc_firmware_type != WI_INTERSIL)
|
||||
return (EINVAL);
|
||||
|
||||
sc->wi_create_ibss = 0;
|
||||
|
||||
switch (sc->ifmedia.ifm_cur->ifm_media & IFM_OMASK) {
|
||||
case 0:
|
||||
sc->wi_ptype = WI_PORTTYPE_BSS;
|
||||
break;
|
||||
case IFM_IEEE80211_ADHOC:
|
||||
sc->wi_ptype = WI_PORTTYPE_ADHOC;
|
||||
break;
|
||||
case IFM_IEEE80211_HOSTAP:
|
||||
sc->wi_ptype = WI_PORTTYPE_AP;
|
||||
break;
|
||||
case IFM_IEEE80211_IBSSMASTER:
|
||||
case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS:
|
||||
if (!(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS))
|
||||
return (EINVAL);
|
||||
sc->wi_create_ibss = 1;
|
||||
/* FALLTHROUGH */
|
||||
case IFM_IEEE80211_IBSS:
|
||||
sc->wi_ptype = WI_PORTTYPE_IBSS;
|
||||
break;
|
||||
default:
|
||||
/* Invalid combination. */
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
switch (IFM_SUBTYPE(sc->ifmedia.ifm_cur->ifm_media)) {
|
||||
case IFM_IEEE80211_DS1:
|
||||
|
@ -2751,7 +2866,7 @@ wi_media_change(ifp)
|
|||
break;
|
||||
}
|
||||
|
||||
if (otype != sc->wi_ptype ||
|
||||
if (ocreate_ibss != sc->wi_create_ibss || otype != sc->wi_ptype ||
|
||||
orate != sc->wi_tx_rate)
|
||||
wi_init(sc);
|
||||
|
||||
|
@ -2772,6 +2887,12 @@ wi_media_status(ifp, imr)
|
|||
imr->ifm_active |= IFM_IEEE80211_ADHOC;
|
||||
else if (sc->wi_ptype == WI_PORTTYPE_AP)
|
||||
imr->ifm_active |= IFM_IEEE80211_HOSTAP;
|
||||
else if (sc->wi_ptype == WI_PORTTYPE_IBSS) {
|
||||
if (sc->wi_create_ibss)
|
||||
imr->ifm_active |= IFM_IEEE80211_IBSSMASTER;
|
||||
else
|
||||
imr->ifm_active |= IFM_IEEE80211_IBSS;
|
||||
}
|
||||
wreq.wi_type = WI_RID_CUR_TX_RATE;
|
||||
wreq.wi_len = WI_MAX_DATALEN;
|
||||
if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0) {
|
||||
|
@ -2795,7 +2916,8 @@ wi_media_status(ifp, imr)
|
|||
}
|
||||
|
||||
imr->ifm_status = IFM_AVALID;
|
||||
if (sc->wi_ptype == WI_PORTTYPE_ADHOC)
|
||||
if (sc->wi_ptype == WI_PORTTYPE_ADHOC ||
|
||||
sc->wi_ptype == WI_PORTTYPE_IBSS)
|
||||
/*
|
||||
* XXX: It would be nice if we could give some actually
|
||||
* useful status like whether we joined another IBSS or
|
||||
|
|
|
@ -497,10 +497,10 @@ struct wi_ltv_pcf {
|
|||
* (Only PRISM2; not 802.11 compliant mode, testing use only)
|
||||
* 6 == HOST AP (Only PRISM2)
|
||||
*/
|
||||
#define WI_PORTTYPE_IBSS 0x0
|
||||
#define WI_PORTTYPE_BSS 0x1
|
||||
#define WI_PORTTYPE_WDS 0x2
|
||||
#define WI_PORTTYPE_ADHOC 0x3
|
||||
#define WI_PORTTYPE_IBSS 0x4
|
||||
#define WI_PORTTYPE_AP 0x6
|
||||
|
||||
/*
|
||||
|
|
|
@ -123,6 +123,15 @@ struct wi_softc {
|
|||
int wi_tx_data_id;
|
||||
int wi_tx_mgmt_id;
|
||||
int wi_gone;
|
||||
int wi_flags;
|
||||
#define WI_FLAGS_ATTACHED 0x01
|
||||
#define WI_FLAGS_INITIALIZED 0x02
|
||||
#define WI_FLAGS_HAS_WEP 0x04
|
||||
#define WI_FLAGS_HAS_IBSS 0x08
|
||||
#define WI_FLAGS_HAS_CREATE_IBSS 0x10
|
||||
#define WI_FLAGS_HAS_MOR 0x20
|
||||
#define WI_FLAGS_HAS_ROAMING 0x30
|
||||
#define WI_FLAGS_HAS_DIVERSITY 0x40
|
||||
int wi_if_flags;
|
||||
u_int16_t wi_procframe;
|
||||
u_int16_t wi_ptype;
|
||||
|
@ -159,6 +168,7 @@ struct wi_softc {
|
|||
struct wihap_info wi_hostap_info;
|
||||
u_int32_t wi_icv;
|
||||
int wi_icv_flag;
|
||||
int wi_ibss_port;
|
||||
struct callout_handle wi_stat_ch;
|
||||
#if __FreeBSD_version >= 500000
|
||||
struct mtx wi_mtx;
|
||||
|
|
Loading…
Reference in a new issue