summaryrefslogtreecommitdiff
path: root/sys/dev/usb/if_atu.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb/if_atu.c')
-rw-r--r--sys/dev/usb/if_atu.c510
1 files changed, 290 insertions, 220 deletions
diff --git a/sys/dev/usb/if_atu.c b/sys/dev/usb/if_atu.c
index 43dec93d31a..32ae612ac59 100644
--- a/sys/dev/usb/if_atu.c
+++ b/sys/dev/usb/if_atu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_atu.c,v 1.26 2004/11/23 02:40:34 dlg Exp $ */
+/* $OpenBSD: if_atu.c,v 1.27 2004/12/04 08:02:02 dlg Exp $ */
/*
* Copyright (c) 2003, 2004
* Daan Vreeken <Danovitsch@Vitsch.net>. All rights reserved.
@@ -95,7 +95,7 @@
#ifdef ATU_DEBUG
#define DPRINTF(x) do { if (atudebug) printf x; } while (0)
#define DPRINTFN(n,x) do { if (atudebug>(n)) printf x; } while (0)
-int atudebug = 11;
+int atudebug = 40;
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
@@ -142,8 +142,8 @@ void atu_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
void atu_start(struct ifnet *);
void atu_mgmt_loop(void *arg);
int atu_ioctl(struct ifnet *, u_long, caddr_t);
-void atu_init(void *);
-void atu_stop(struct atu_softc *);
+int atu_init(struct ifnet *);
+void atu_stop(struct ifnet *, int);
void atu_watchdog(struct ifnet *);
void atu_msleep(struct atu_softc *, int);
usbd_status atu_usb_request(struct atu_softc *sc, u_int8_t type,
@@ -162,7 +162,7 @@ int atu_start_ibss(struct atu_softc *sc);
int atu_start_scan(struct atu_softc *sc);
int atu_switch_radio(struct atu_softc *sc, int state);
int atu_initial_config(struct atu_softc *sc);
-int atu_join(struct atu_softc *sc);
+int atu_join(struct atu_softc *sc, struct ieee80211_node *node);
int atu_send_packet(struct atu_softc *sc, struct atu_chain *c);
int atu_send_mgmt_packet(struct atu_softc *sc,
struct atu_chain *c, u_int16_t length);
@@ -186,6 +186,10 @@ void atu_handle_mgmt_packet(struct atu_softc *sc, struct atu_rxpkt *pkt);
void atu_print_a_bunch_of_debug_things(struct atu_softc *sc);
int atu_set_wepkey(struct atu_softc *sc, int nr, u_int8_t *key, int len);
+int atu_newstate(struct ieee80211com *, enum ieee80211_state, int);
+/* XXX stolen from iwi */
+void atu_fix_channel(struct ieee80211com *, struct mbuf *);
+
void
atu_msleep(struct atu_softc *sc, int ms)
{
@@ -692,7 +696,7 @@ atu_initial_config(struct atu_softc *sc)
}
int
-atu_join(struct atu_softc *sc)
+atu_join(struct atu_softc *sc, struct ieee80211_node *node)
{
struct atu_cmd_join join;
u_int8_t status;
@@ -706,12 +710,15 @@ atu_join(struct atu_softc *sc)
USBDEVNAME(sc->atu_dev), ether_sprintf(sc->atu_bssid)));
DPRINTFN(15, ("%s: mode=%d\n", USBDEVNAME(sc->atu_dev),
sc->atu_mode));
- memcpy(join.bssid, sc->atu_bssid, ETHER_ADDR_LEN);
+ memcpy(join.bssid, node->ni_bssid, IEEE80211_ADDR_LEN);
memset(join.essid, 0x00, 32);
- memcpy(join.essid, sc->atu_ssid, sc->atu_ssidlen);
- join.essid_size = sc->atu_ssidlen;
- join.bss_type = sc->atu_mode;
- join.channel = sc->atu_channel;
+ memcpy(join.essid, node->ni_essid, node->ni_esslen);
+ join.essid_size = node->ni_esslen;
+ if (node->ni_capinfo & IEEE80211_CAPINFO_IBSS)
+ join.bss_type = AD_HOC_MODE;
+ else
+ join.bss_type = INFRASTRUCTURE_MODE;
+ join.channel = ieee80211_chan2ieee(&sc->sc_ic, node->ni_chan);
join.timeout = ATU_JOIN_TIMEOUT;
join.reserved = 0x00;
@@ -760,7 +767,7 @@ atu_send_packet(struct atu_softc *sc, struct atu_chain *c)
c->atu_in_xfer = 1;
err = usbd_transfer(c->atu_xfer);
if (err != USBD_IN_PROGRESS) {
- atu_stop(sc);
+ atu_stop(&sc->sc_ic.ic_if, 0);
return(EIO);
}
@@ -1375,7 +1382,7 @@ atu_mgmt_state_machine(struct atu_softc *sc)
case STATE_JOINING:
DPRINTFN(10, ("%s: going to join\n",
USBDEVNAME(sc->atu_dev)));
- err = atu_join(sc);
+ //err = atu_join(sc, );
if (err) {
if (vars->retry++ > ATU_JOIN_RETRIES) {
if (sc->atu_mode == AD_HOC_MODE)
@@ -1517,7 +1524,6 @@ atu_media_change(struct ifnet *ifp)
USBDEVNAME(sc->atu_dev)));
sc->atu_mode = AD_HOC_MODE;
sc->atu_mgmt_flags |= ATU_CHANGED_SETTINGS;
- wakeup(sc);
}
if ((!(ime->ifm_media & IFM_IEEE80211_ADHOC)) &&
@@ -1526,7 +1532,6 @@ atu_media_change(struct ifnet *ifp)
USBDEVNAME(sc->atu_dev)));
sc->atu_mode = INFRASTRUCTURE_MODE;
sc->atu_mgmt_flags |= ATU_CHANGED_SETTINGS;
- wakeup(sc);
}
DPRINTFN(10, ("%s: media_change...\n", USBDEVNAME(sc->atu_dev)));
@@ -1556,6 +1561,29 @@ atu_media_status(struct ifnet *ifp, struct ifmediareq *req)
DPRINTFN(10, ("%s: atu_media_status\n", USBDEVNAME(sc->atu_dev)));
}
+int
+atu_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
+{
+ struct ifnet *ifp = &ic->ic_if;
+ struct atu_softc *sc = ifp->if_softc;
+ enum ieee80211_state ostate = ic->ic_state;
+
+ DPRINTFN(10, ("%s: atu_newstate: %s -> %s\n", USBDEVNAME(sc->atu_dev),
+ ieee80211_state_name[ostate], ieee80211_state_name[nstate]));
+
+ if ((ostate == IEEE80211_S_SCAN) && ((nstate == IEEE80211_S_AUTH) ||
+ (nstate == IEEE80211_S_RUN))) {
+
+ /*
+ * The BSSID has changed. Join it first before net80211 starts
+ * sending packets...
+ */
+
+ atu_join(sc, ic->ic_bss);
+ }
+ return (*sc->sc_newstate)(ic, nstate, arg);
+}
+
/*
* Attach the interface. Allocate softc structures, do
* setup and ethernet/BPF attach.
@@ -1572,8 +1600,14 @@ USB_ATTACH(atu)
usb_endpoint_descriptor_t *ed;
int i;
u_int8_t mode;
- struct atu_type *t;
+ struct atu_type *t;
struct atu_fw fw;
+ /* XXX gotta clean this up later */
+#ifdef IEEE80211_DEBUG
+ extern int ieee80211_debug;
+
+ ieee80211_debug = 11;
+#endif
usbd_devinfo(uaa->device, 0, devinfo, sizeof devinfo);
USB_ATTACH_SETUP;
@@ -1718,7 +1752,7 @@ USB_ATTACH(atu)
ic->ic_phytype = IEEE80211_T_DS;
ic->ic_opmode = IEEE80211_M_STA;
ic->ic_state = IEEE80211_S_INIT;
- ic->ic_caps = IEEE80211_C_IBSS | IEEE80211_C_PMGT | IEEE80211_C_WEP;
+ ic->ic_caps = IEEE80211_C_IBSS | IEEE80211_C_WEP;
i = 0;
ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[i++] = 2;
@@ -1728,7 +1762,8 @@ USB_ATTACH(atu)
ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = i;
for (i = 1; i <= 14; i++) {
- ic->ic_channels[i].ic_flags = IEEE80211_CHAN_B;
+ ic->ic_channels[i].ic_flags = IEEE80211_CHAN_B |
+ IEEE80211_F_ASCAN;
ic->ic_channels[i].ic_freq = ieee80211_ieee2mhz(i,
ic->ic_channels[i].ic_flags);
}
@@ -1738,6 +1773,7 @@ USB_ATTACH(atu)
ifp->if_softc = sc;
memcpy(ifp->if_xname, USBDEVNAME(sc->atu_dev), IFNAMSIZ);
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_start = atu_start;
ifp->if_ioctl = atu_ioctl;
ifp->if_start = atu_start;
ifp->if_watchdog = atu_watchdog;
@@ -1748,6 +1784,9 @@ USB_ATTACH(atu)
if_attach(ifp);
ieee80211_ifattach(ifp);
+ sc->sc_newstate = ic->ic_newstate;
+ ic->ic_newstate = atu_newstate;
+
/* setup ifmedia interface */
ieee80211_media_init(ifp, atu_media_change, atu_media_status);
@@ -1761,7 +1800,7 @@ USB_DETACH(atu)
USB_DETACH_START(atu, sc);
struct ifnet *ifp = &sc->sc_ic.ic_if;
- atu_stop(sc);
+ atu_stop(ifp, 1);
ieee80211_ifdetach(ifp);
if_detach(ifp);
@@ -2225,6 +2264,44 @@ atu_handle_mgmt_packet(struct atu_softc *sc, struct atu_rxpkt *pkt)
}
}
+/* XXX Horrible hack to fix channel number of beacons and probe responses */
+void
+atu_fix_channel(struct ieee80211com *ic, struct mbuf *m)
+{
+ struct ieee80211_frame *wh;
+ u_int8_t subtype;
+ u_int8_t *frm, *efrm;
+
+ DPRINTFN(10, ("atu_fix_channel\n"));
+
+ wh = mtod(m, struct ieee80211_frame *);
+
+ if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT)
+ return;
+
+ DPRINTFN(10, ("atu_fix_channel: beacon/resp\n"));
+
+ subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
+
+ if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
+ subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
+ return;
+
+ frm = (u_int8_t *)(wh + 1);
+ efrm = mtod(m, u_int8_t *) + m->m_len;
+
+ frm += 12; /* skip tstamp, bintval and capinfo */
+ while (frm < efrm) {
+ if (*frm == IEEE80211_ELEMID_DSPARMS)
+#if IEEE80211_CHAN_MAX < 255
+ if (frm[2] <= IEEE80211_CHAN_MAX)
+#endif
+ ic->ic_bss->ni_chan = &ic->ic_channels[frm[2]];
+
+ frm += frm[1] + 2;
+ }
+}
+
/*
* A frame has been uploaded: pass the resulting mbuf chain up to
* the higher level protocols.
@@ -2235,21 +2312,24 @@ atu_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
struct atu_chain *c = (struct atu_chain *)priv;
struct atu_softc *sc = c->atu_sc;
struct ifnet *ifp = &sc->sc_ic.ic_if;
+ struct ieee80211com *ic = &sc->sc_ic;
struct mbuf *m;
u_int32_t total_len;
int s;
struct atu_rxpkt *pkt;
- struct ether_header *eth_hdr;
int offset;
+ struct ieee80211_frame *wh;
+ struct ieee80211_node *ni;
+
DPRINTFN(25, ("%s: atu_rxeof: enter\n", USBDEVNAME(sc->atu_dev)));
if (sc->atu_dying)
return;
if (!(ifp->if_flags & IFF_RUNNING))
- return;
+ goto done;
DPRINTFN(25, ("%s: got a packet\n", USBDEVNAME(sc->atu_dev)));
@@ -2307,48 +2387,11 @@ atu_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
ether_sprintf(pkt->WiHeader.addr3)));
DPRINTFN(25, (" bssid=%s\n", ether_sprintf(pkt->WiHeader.addr2)));
- if (pkt->WiHeader.frame_ctl & WI_FCTL_WEP) {
- DPRINTFN(25, ("%s: WEP enabled on RX\n",
- USBDEVNAME(sc->atu_dev)));
- }
-
- /* Is it a managment packet? */
- if ((pkt->WiHeader.frame_ctl & WI_FCTL_FTYPE) == WI_FTYPE_MGMT) {
- atu_handle_mgmt_packet(sc, pkt);
- goto done;
- }
-
- /* Everything but data packets we just ignore from here */
- if ((pkt->WiHeader.frame_ctl & WI_FCTL_FTYPE) != WI_FTYPE_DATA) {
- DPRINTFN(25, ("%s: ---- not a data packet? ---\n",
- USBDEVNAME(sc->atu_dev)));
- goto done;
- }
-
- /* Woohaa! It's an ethernet packet! */
- DPRINTFN(25, ("%s: received a packet! rx-rate: %d\n",
- USBDEVNAME(sc->atu_dev), pkt->AtHeader.rx_rate));
-
- /* drop non-encrypted packets if wep-mode=on */
- if ((!(pkt->WiHeader.frame_ctl & WI_FCTL_WEP)) &&
- (sc->atu_encrypt & ATU_WEP_RX)) {
- DPRINTFN(25, ("%s: dropping RX packet. (wep=off)\n",
- USBDEVNAME(sc->atu_dev)));
- goto done;
- }
-
DPRINTFN(25, ("%s: rx frag:%02x rssi:%02x q:%02x nl:%02x time:%d\n",
USBDEVNAME(sc->atu_dev), pkt->AtHeader.fragmentation,
pkt->AtHeader.rssi, pkt->AtHeader.link_quality,
pkt->AtHeader.noise_level, pkt->AtHeader.rx_time));
- /* Do some sanity checking... */
- if (total_len < sizeof(struct ether_header)) {
- DPRINTFN(25, ("%s: Packet too small?? (size:%d)\n",
- USBDEVNAME(sc->atu_dev), total_len));
- ifp->if_ierrors++;
- goto done;
- }
/* if (total_len > 1514) { */
if (total_len > 1548) {
DPRINTF(("%s: AAARRRGGGHHH!! Invalid packet size? (%d)\n",
@@ -2357,65 +2400,48 @@ atu_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
goto done;
}
- /*
- * Copy src & dest mac to the right place (overwriting part of the
- * 802.11 header)
- */
- eth_hdr = (struct ether_header *)(pkt->Packet - 2 * ETHER_ADDR_LEN);
-
- switch (pkt->WiHeader.frame_ctl & (WI_FCTL_TODS | WI_FCTL_FROMDS)) {
- case 0:
- /* ad-hoc: copy order doesn't matter here */
- memcpy(eth_hdr->ether_shost, pkt->WiHeader.addr2,
- ETHER_ADDR_LEN);
- memcpy(eth_hdr->ether_dhost, pkt->WiHeader.addr1,
- ETHER_ADDR_LEN);
- break;
-
- case WI_FCTL_FROMDS:
- /* infra mode: MUST be done in this order! */
- memcpy(eth_hdr->ether_shost, pkt->WiHeader.addr3,
- ETHER_ADDR_LEN);
- memcpy(eth_hdr->ether_dhost, pkt->WiHeader.addr1,
- ETHER_ADDR_LEN);
-
- DPRINTFN(25, ("%s: infra decap (%d bytes)\n",
- USBDEVNAME(sc->atu_dev), pkt->AtHeader.wlength));
- DPRINTFN(25, ("%s: RX: %50D\n", USBDEVNAME(sc->atu_dev),
- (u_int8_t *)&pkt->WiHeader, " "));
- break;
-
- default:
- DPRINTFN(25, ("%s: we shouldn't receive this (f_cntl=%02x)\n",
- USBDEVNAME(sc->atu_dev), pkt->WiHeader.frame_ctl));
- }
-
- /* calculate 802.3 packet length (= packet - 802.11 hdr - fcs) */
- total_len = pkt->AtHeader.wlength - sizeof(struct wi_80211_hdr) +
- 2 * ETHER_ADDR_LEN - 4;
+ total_len = pkt->AtHeader.wlength - 4;
ifp->if_ipackets++;
m->m_pkthdr.rcvif = ifp;
/* Adjust mbuf for headers */
- offset = sizeof(struct at76c503_rx_buffer) +
- sizeof(struct wi_80211_hdr) - 12;
+ offset = sizeof(pkt->AtHeader);
m->m_pkthdr.len = m->m_len = total_len + offset;
+ /* cut off Atmel header */
m_adj(m, offset);
- s = splnet();
+ /*
+ * XXX stolen from iwi, needs fixing
+ * Management frames (beacons or probe responses) received during
+ * scanning have an invalid channel field. Thus these frames are
+ * rejected by the 802.11 layer which breaks AP detection.
+ */
+ if (ic->ic_state == IEEE80211_S_SCAN)
+ atu_fix_channel(ic, m);
- if (atu_newbuf(sc, c, NULL) == ENOBUFS) {
- ifp->if_ierrors++;
- goto done1;
- }
+ wh = mtod(m, struct ieee80211_frame *);
+ ni = ieee80211_find_rxnode(ic, wh);
+
+ s = splnet();
#if NBPFILTER > 0
if (ifp->if_bpf)
BPF_MTAP(ifp, m);
#endif
- IF_INPUT(ifp, m);
+ ieee80211_input(ifp, m, ni, pkt->AtHeader.rssi,
+ pkt->AtHeader.rx_time);
+
+ if (ni == ic->ic_bss)
+ ieee80211_unref_node(&ni);
+ else
+ ieee80211_free_node(ic, ni);
+
+ if (atu_newbuf(sc, c, NULL) == ENOBUFS) {
+ ifp->if_ierrors++;
+ goto done1;
+ }
done1:
splx(s);
@@ -2517,7 +2543,6 @@ atu_encap(struct atu_softc *sc, struct mbuf *m, struct atu_chain *c)
{
int total_len;
struct atu_txpkt *pkt;
- struct ether_header *eth_hdr;
#ifdef ATU_TX_PADDING
u_int8_t padding;
#endif /* ATU_TX_PADDING */
@@ -2528,59 +2553,13 @@ atu_encap(struct atu_softc *sc, struct mbuf *m, struct atu_chain *c)
*/
total_len = m->m_pkthdr.len;
- m_copydata(m, 0, m->m_pkthdr.len, c->atu_buf +
- sizeof(pkt->AtHeader) + sizeof(struct wi_80211_hdr) -
- 2 * ETHER_ADDR_LEN);
-
- total_len += sizeof(struct wi_80211_hdr) - 2 * ETHER_ADDR_LEN;
+ m_copydata(m, 0, m->m_pkthdr.len, c->atu_buf + sizeof(pkt->AtHeader));
pkt = (struct atu_txpkt *)c->atu_buf;
pkt->AtHeader.wlength = total_len;
pkt->AtHeader.tx_rate = 4; /* rate = auto */
pkt->AtHeader.padding = 0;
- memset(pkt->AtHeader.reserved, 0x00, 4);
-
- pkt->WiHeader.dur_id = 0x0000; /* ? */
- pkt->WiHeader.frame_ctl = WI_FTYPE_DATA;
-
- eth_hdr = (struct ether_header *)(pkt->Packet - 2 * ETHER_ADDR_LEN);
-
- switch(sc->atu_mode) {
- case AD_HOC_MODE:
- /* dest */
- memcpy(pkt->WiHeader.addr1, eth_hdr->ether_dhost,
- ETHER_ADDR_LEN);
- /* src */
- memcpy(pkt->WiHeader.addr2, eth_hdr->ether_shost,
- ETHER_ADDR_LEN);
- /* bssid */
- memcpy(pkt->WiHeader.addr3, sc->atu_bssid, ETHER_ADDR_LEN);
- DPRINTFN(25, ("%s: adhoc encap (bssid=%s)\n",
- USBDEVNAME(sc->atu_dev), ether_sprintf(sc->atu_bssid)));
- break;
-
- case INFRASTRUCTURE_MODE:
- pkt->WiHeader.frame_ctl|=WI_FCTL_TODS;
- /* bssid */
- memcpy(pkt->WiHeader.addr1, sc->atu_bssid, ETHER_ADDR_LEN);
- /* src */
- memcpy(pkt->WiHeader.addr2, eth_hdr->ether_shost,
- ETHER_ADDR_LEN);
- /* dst */
- memcpy(pkt->WiHeader.addr3, eth_hdr->ether_dhost,
- ETHER_ADDR_LEN);
-
- DPRINTFN(25, ("%s: infra encap (bssid=%s)\n",
- USBDEVNAME(sc->atu_dev), ether_sprintf(sc->atu_bssid)));
- }
- memset(pkt->WiHeader.addr4, 0x00, ETHER_ADDR_LEN);
- pkt->WiHeader.seq_ctl = 0;
-
- if (sc->atu_encrypt & ATU_WEP_TX) {
- pkt->WiHeader.frame_ctl |= WI_FCTL_WEP;
- DPRINTFN(25, ("%s: turning WEP on on packet\n",
- USBDEVNAME(sc->atu_dev)));
- }
+ memset(pkt->AtHeader.reserved, 0x00, sizeof(pkt->AtHeader.reserved));
total_len += sizeof(pkt->AtHeader);
#ifdef ATU_TX_PADDING
@@ -2597,24 +2576,22 @@ void
atu_start(struct ifnet *ifp)
{
struct atu_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211_node *ni;
struct mbuf *m_head = NULL;
- struct atu_cdata *cd;
+ struct atu_cdata *cd = &sc->atu_cdata;
struct atu_chain *entry;
usbd_status err;
int s;
+ DPRINTFN(10, ("%s: atu_start: enter\n", USBDEVNAME(sc->atu_dev)));
+
s = splnet();
if (ifp->if_flags & IFF_OACTIVE) {
splx(s);
return;
}
- IFQ_POLL(&ifp->if_snd, m_head);
- if (m_head == NULL) {
- splx(s);
- return;
- }
-
entry = SLIST_FIRST(&sc->atu_cdata.atu_tx_free);
while (entry) {
if (entry == NULL) {
@@ -2623,19 +2600,35 @@ atu_start(struct ifnet *ifp)
return;
}
- if (sc->atu_mgmt_vars.state != STATE_HAPPY_NETWORKING) {
- /* don't try to send if we're not associated */
- splx(s);
- return;
- }
+ IF_DEQUEUE(&ic->ic_mgtq, m_head);
+ if (m_head != NULL) {
+ DPRINTFN(10, ("%s: atu_start: mgmt\n",
+ USBDEVNAME(sc->atu_dev)));
- cd = &sc->atu_cdata;
+ ni = (struct ieee80211_node *)m_head->m_pkthdr.rcvif;
+ m_head->m_pkthdr.rcvif = NULL;
+ } else {
+ DPRINTFN(10, ("%s: atu_start: data\n",
+ USBDEVNAME(sc->atu_dev)));
+ if (ic->ic_state != IEEE80211_S_RUN) {
+ splx(s);
+ return;
+ }
+ IF_DEQUEUE(&ifp->if_snd, m_head);
+ if (m_head == NULL) {
+ /* no packets on queues */
+ splx(s);
+ return;
+ }
+ DPRINTFN(10, ("%s: atu_start: data\n",
+ USBDEVNAME(sc->atu_dev)));
- IF_DEQUEUE(&ifp->if_snd, m_head);
- if (m_head == NULL) {
- /* no packets on queue */
- splx(s);
- return;
+ m_head = ieee80211_encap(ifp, m_head, &ni);
+ if (m_head == NULL) {
+ /* no packets on queues */
+ splx(s);
+ return;
+ }
}
SLIST_REMOVE_HEAD(&sc->atu_cdata.atu_tx_free, atu_list);
@@ -2665,6 +2658,9 @@ atu_start(struct ifnet *ifp)
return;
}
+ if ((ni != NULL) && (ni != ic->ic_bss))
+ ieee80211_free_node(ic, ni);
+
#if NBPFILTER > 0
if (ifp->if_bpf)
BPF_MTAP(ifp, m_head);
@@ -2679,12 +2675,11 @@ atu_start(struct ifnet *ifp)
splx(s);
}
-void
-atu_init(void *xsc)
+int
+atu_init(struct ifnet *ifp)
{
- struct atu_softc *sc = xsc;
+ struct atu_softc *sc = ifp->if_softc;
struct ieee80211com *ic = &sc->sc_ic;
- struct ifnet *ifp = &ic->ic_if;
struct atu_cdata *cd = &sc->atu_cdata;
struct atu_chain *c;
usbd_status err;
@@ -2696,7 +2691,7 @@ atu_init(void *xsc)
if (ifp->if_flags & IFF_RUNNING) {
splx(s);
- return;
+ return(0);
}
/* Init TX ring */
@@ -2728,7 +2723,7 @@ atu_init(void *xsc)
DPRINTF(("%s: open rx pipe failed: %s\n",
USBDEVNAME(sc->atu_dev), usbd_errstr(err)));
splx(s);
- return;
+ return(EIO);
}
err = usbd_open_pipe(sc->atu_iface, sc->atu_ed[ATU_ENDPT_TX],
@@ -2737,7 +2732,7 @@ atu_init(void *xsc)
DPRINTF(("%s: open tx pipe failed: %s\n",
USBDEVNAME(sc->atu_dev), usbd_errstr(err)));
splx(s);
- return;
+ return(EIO);
}
/* Start up the receive pipe. */
@@ -2760,26 +2755,11 @@ atu_init(void *xsc)
DPRINTF(("%s: initial config failed!\n",
USBDEVNAME(sc->atu_dev)));
splx(s);
- return;
+ return(EIO);
}
DPRINTFN(10, ("%s: initialised transceiver\n",
USBDEVNAME(sc->atu_dev)));
- /* Fire up managment task */
- DPRINTFN(10, ("%s: trying to start mgmt task...\n",
- USBDEVNAME(sc->atu_dev)));
- if (!(sc->atu_mgmt_flags & ATU_TASK_RUNNING)) {
- sc->atu_dying = 0;
- err = kthread_create(atu_mgmt_loop, sc,
- &sc->atu_mgmt_thread, USBDEVNAME(sc->atu_dev));
- if (err) {
- DPRINTF(("%s: failed to create kthread\n",
- USBDEVNAME(sc->atu_dev)));
- }
-
- sc->atu_mgmt_flags |= ATU_TASK_RUNNING;
- }
-
/* sc->atu_rxfilt = ATU_RXFILT_UNICAST|ATU_RXFILT_BROADCAST; */
/* If we want promiscuous mode, set the allframes bit. */
@@ -2789,11 +2769,55 @@ atu_init(void *xsc)
*/
sc->atu_mgmt_flags |= ATU_CHANGED_SETTINGS;
- wakeup(sc);
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
splx(s);
+
+ /* XXX the following HAS to be replaced */
+ s = splnet();
+ err = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
+ if (err) {
+ DPRINTFN(1, ("%s: atu_init: error calling "
+ "ieee80211_net_state", USBDEVNAME(sc->atu_dev)));
+ }
+ splx(s);
+
+ err = atu_start_scan(sc);
+ if (err) {
+ DPRINTFN(1, ("%s: atu_init: couldn't start scan!\n",
+ USBDEVNAME(sc->atu_dev)));
+ return(EIO);
+ }
+
+ /* Start a timer to check when the scan is done */
+ /* timeout_add(&sc->atu_scan_timer, (1000 * hz) / 1000); */
+ /*
+ * Hmmm... sleeping in a timeout handler crashes the system :)
+ * let's just wait here for the scan to finish
+ */
+
+ err = atu_wait_completion(sc, CMD_START_SCAN, NULL);
+ if (err) {
+ DPRINTF(("%s: atu_init: error waiting for scan\n",
+ USBDEVNAME(sc->atu_dev)));
+ return(err);
+ }
+
+ DPRINTF(("%s: ==========================> END OF SCAN!\n",
+ USBDEVNAME(sc->atu_dev)));
+
+ ifp->if_flags |= IFF_DEBUG;
+
+ s = splnet();
+ /* ieee80211_next_scan(ifp); */
+ ieee80211_end_scan(ifp);
+ splx(s);
+
+ DPRINTF(("%s: ----------------------======> END OF SCAN2!\n",
+ USBDEVNAME(sc->atu_dev)));
+
+ return 0;
}
void
@@ -2930,7 +2954,74 @@ atu_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
DPRINTFN(15, ("%s: SIOCSIFADDR\n", USBDEVNAME(sc->atu_dev)));
ifp->if_flags |= IFF_UP;
- atu_init(sc);
+ atu_init(ifp);
+
+ switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ arp_ifinit(&sc->sc_ic.ic_ac, ifa);
+ break;
+#endif /* INET */
+ }
+ break;
+
+ case SIOCSIFFLAGS:
+ DPRINTFN(15, ("%s: SIOCSIFFLAGS\n", USBDEVNAME(sc->atu_dev)));
+
+ if (ifp->if_flags & IFF_UP) {
+ if (ifp->if_flags & IFF_RUNNING &&
+ ifp->if_flags & IFF_PROMISC &&
+ !(sc->atu_if_flags & IFF_PROMISC)) {
+/* enable promisc */
+#if 0
+ sc->atu_rxfilt |= ATU_RXFILT_PROMISC;
+ atu_setword(sc, ATU_CMD_SET_PKT_FILTER,
+ sc->atu_rxfilt);
+#endif
+ } else if (ifp->if_flags & IFF_RUNNING &&
+ !(ifp->if_flags & IFF_PROMISC) &&
+ sc->atu_if_flags & IFF_PROMISC) {
+/* disable promisc */
+#if 0
+ sc->atu_rxfilt &= ~ATU_RXFILT_PROMISC;
+ atu_setword(sc, ATU_CMD_SET_PKT_FILTER,
+ sc->atu_rxfilt);
+#endif
+ } else if (!(ifp->if_flags & IFF_RUNNING))
+ atu_init(ifp);
+
+#if 0
+ DPRINTFN(15, ("%s: ioctl calling atu_init()\n",
+ USBDEVNAME(sc->atu_dev)));
+ atu_init(ifp);
+ err = atu_switch_radio(sc, 1);
+#endif
+ } else {
+ if (ifp->if_flags & IFF_RUNNING)
+ atu_stop(ifp, 0);
+ err = atu_switch_radio(sc, 0);
+ }
+ sc->atu_if_flags = ifp->if_flags;
+
+ err = 0;
+ break;
+
+ default:
+ err = ieee80211_ioctl(ifp, command, data);
+ break;
+ }
+
+ splx(s);
+
+ /* XXX need to check if we need a config change */
+ return (err);
+
+ switch (command) {
+ case SIOCSIFADDR:
+ DPRINTFN(15, ("%s: SIOCSIFADDR\n", USBDEVNAME(sc->atu_dev)));
+
+ ifp->if_flags |= IFF_UP;
+ atu_init(ifp);
switch (ifa->ifa_addr->sa_family) {
#ifdef INET
@@ -2971,17 +3062,17 @@ atu_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
sc->atu_rxfilt);
#endif
} else if (!(ifp->if_flags & IFF_RUNNING))
- atu_init(sc);
+ atu_init(ifp);
#if 0
DPRINTFN(15, ("%s: ioctl calling atu_init()\n",
USBDEVNAME(sc->atu_dev)));
- atu_init(sc);
+ atu_init(ifp);
err = atu_switch_radio(sc, 1);
#endif
} else {
if (ifp->if_flags & IFF_RUNNING)
- atu_stop(sc);
+ atu_stop(ifp, 0);
err = atu_switch_radio(sc, 0);
}
sc->atu_if_flags = ifp->if_flags;
@@ -3014,7 +3105,6 @@ atu_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
sc->atu_ssidlen = nwid.i_len;
memcpy(sc->atu_ssid, nwid.i_nwid, nwid.i_len);
sc->atu_mgmt_flags |= ATU_CHANGED_SETTINGS;
- wakeup(sc);
break;
case SIOCG80211NWID:
@@ -3050,7 +3140,6 @@ atu_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
/* restart scan / join / etc now */
sc->atu_desired_channel = chanreq->i_channel;
sc->atu_mgmt_flags |= ATU_CHANGED_SETTINGS;
- wakeup(sc);
break;
case SIOCG80211CHANNEL:
DPRINTF(("%s: ioctl 80211 get CHANNEL\n",
@@ -3170,7 +3259,6 @@ atu_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
memcpy(sc->atu_ssid, tmp, ireq->i_len);
sc->atu_mgmt_flags |= ATU_CHANGED_SETTINGS;
- wakeup(sc);
break;
case IEEE80211_IOC_CHANNEL:
@@ -3183,7 +3271,6 @@ atu_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
/* restart scan / join / etc now */
sc->atu_mgmt_flags |= ATU_CHANGED_SETTINGS;
- wakeup(sc);
break;
case IEEE80211_IOC_WEP:
@@ -3214,7 +3301,6 @@ atu_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
* restart the entire join/assoc/auth state-machine.
*/
sc->atu_mgmt_flags |= ATU_CHANGED_SETTINGS;
- wakeup(sc);
break;
case IEEE80211_IOC_WEPKEY:
@@ -3340,32 +3426,16 @@ atu_watchdog(struct ifnet *ifp)
* RX and TX lists.
*/
void
-atu_stop(struct atu_softc *sc)
+atu_stop(struct ifnet *ifp, int disable)
{
usbd_status err;
- struct ifnet *ifp = &sc->sc_ic.ic_if;
+ struct atu_softc *sc = ifp->if_softc;
struct atu_cdata *cd;
int s;
s = splnet();
ifp->if_timer = 0;
- /* there must be a better way to clean up the mgmt task... */
- sc->atu_dying = 1;
- splx(s);
-
- if (sc->atu_mgmt_flags & ATU_TASK_RUNNING) {
- DPRINTFN(10, ("%s: waiting for mgmt task to die\n",
- USBDEVNAME(sc->atu_dev)));
- wakeup(sc);
- while (sc->atu_dying == 1) {
- atu_msleep(sc, 100);
- }
- }
- s = splnet();
- DPRINTFN(10, ("%s: stopped managment thread\n",
- USBDEVNAME(sc->atu_dev)));
-
/* Stop transfers. */
if (sc->atu_ep[ATU_ENDPT_RX] != NULL) {
err = usbd_abort_pipe(sc->atu_ep[ATU_ENDPT_RX]);