📄 wlandrv.c
字号:
} break; } if (ic->ic_opmode == IEEE80211_M_STA) { sc->sc_flags |= WI_FLAGS_OUTRANGE; } break; case WI_INFO_LINK_STAT_DISCONNECTED: case WI_INFO_LINK_STAT_ASSOC_FAILED: if (ic->ic_opmode == IEEE80211_M_STA) { ieee80211_new_state(ic, IEEE80211_S_INIT, -1); } break; } break; case WI_INFO_COUNTERS:#if 0 //@@MF later /* * I think we does not need the counter, * therefore it can be take longer to implement it. */ /* * some card versions have a larger stats structure */ len = min(le16toh(ltbuf[0]) - 1, sizeof(sc->sc_stats) / 4); ptr = (u_int32_t *) & sc->sc_stats; off = sizeof(ltbuf); for (i = 0; i < len; i++, off += 2, ptr++) { wi_read_bap(sc, fid, off, &stat, sizeof(stat));#ifdef WI_HERMES_STATS_WAR if (stat & 0xf000) { stat = ~stat; }#endif *ptr += stat; } ifp->if_collisions = sc->sc_stats.wi_tx_single_retries + sc->sc_stats.wi_tx_multi_retries + sc->sc_stats.wi_tx_retry_limit;#endif /* later */ break;#if 0 //@@MF later case WI_INFO_SCAN_RESULTS: case WI_INFO_HOST_SCAN_RESULTS: wi_scan_result(sc, fid, le16toh(ltbuf[0])); break;#endif /* later */ default: Debug(("wi_info_intr: got fid %x type %x len %d\n", fid, le16toh(ltbuf[1]), le16toh(ltbuf[0]))); break; } CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);}/************************************************************//* wi_rx_intr *//************************************************************/static NETBUF *wi_rx_intr(struct wi_softc *sc){ // struct ieee80211com *ic = &sc->sc_ic; /* Harald: Not used */ struct wi_frame frmhdr; int fid, len, off; u_int16_t status; int error; NETBUF *nb = 0; LLCS_SNAP_HEADER *pLLCSSNAPHeader; ETHERHDR LABBuffer; ETHERHDR MAC802_3; u_int8_t *pFrameBuffer = 0; /* Harald: Missing init */ u_int8_t *pBytePointer; int copy_size = 0; /* Harald: Missing init */ int size; int IPFrame = 0; if (sc->wi_gone) { Debug(("wi_rx_intr gone\r\n")); return (0); } fid = CSR_READ_2(sc, WI_RX_FID); /* * First read in the frame header */ if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) { CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); Debug(("wi_rx_intr: read fid %x failed\n", fid)); return 0; } /* * Drop undecryptable or packets with receive errors here */ status = le16toh(frmhdr.wi_status); if (status & WI_STAT_ERRSTAT) { CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); Debug(("wi_rx_intr: fid %x error status %x\n", fid, status)); return 0; } /* * Catch the MAC 802.3 header */ memcpy(MAC802_3.ether_dhost, frmhdr.wi_ehdr.ether_dhost, IEEE80211_ADDR_LEN); memcpy(MAC802_3.ether_shost, frmhdr.wi_ehdr.ether_shost, IEEE80211_ADDR_LEN); /* * The ether_type comes later */ /* * Get the frame length, at this point I don't know * if it is a RFC1024 or RFC894 frame. But Ethernut need * an RFC894 frame! So we will alloc the NetBuffer later. */ len = le16toh(frmhdr.wi_dat_len); off = sizeof(frmhdr); /* * Sometimes the PRISM2.x returns bogusly large frames. Except * in monitor mode, just throw them away. */ if (len > WLAN_MAX_ETHERNET_FRAME_LEN) { CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); Debug(("wi_rx_intr: oversized packet\n")); return (0); } /* * First read the LookAheadBuffer */ error = wi_read_bap(sc, fid, off, &LABBuffer, sizeof(LABBuffer)); off += sizeof(LABBuffer); if (error == 0) { /* * Check if this is a 802.2 LLC 802.2 SNAP IP-Header RFC1024 */ pLLCSSNAPHeader = (LLCS_SNAP_HEADER *) & LABBuffer; if ((pLLCSSNAPHeader->DSAPSSAP == 0xAAAA) && (pLLCSSNAPHeader->Control == 0x0003) && (pLLCSSNAPHeader->MustZero == 0x0000)) { if ((pLLCSSNAPHeader->Type == 0x0608) || (pLLCSSNAPHeader->Type == 0x0008)) {#if (WLAN_ENABLE_RX_FRAME_DUMP >= 1) Debug(("RFC1024 IP-Frame\n"));#endif IPFrame = 1; MAC802_3.ether_type = pLLCSSNAPHeader->Type; /* * Now we can calculate the wFrameLength. * It is a RFC1042 Frame, and we must discard the: * DSAP, SSAP, cntl, and the org. code * 1 + 1 + 1 + 3 = 6 */ len -= 6; /* * The Ethernut need the dest and source address, * therefore add 12 again. */ len += 12; /* * The MAC can not handle odd counts, test it. * */ len += 1; len &= ~1; /* * Now alloc the NetBuffer for Ethernut. */ nb = NutNetBufAlloc(0, NBAF_DATALINK, len); if (nb != 0) { pFrameBuffer = nb->nb_dl.vp; /* * We must copy wFrameLength out of the MAC */ copy_size = len; /* * Copy the MAC 802.3 Header */ memcpy(pFrameBuffer, &MAC802_3, sizeof(MAC802_3)); pFrameBuffer += sizeof(MAC802_3); copy_size -= sizeof(MAC802_3); /* This was already in the WLANHeader */ /* * Now we have some data in our LABBuffer which we need */ pBytePointer = (BYTE *) & LABBuffer; /* * jump over the header */ pBytePointer += sizeof(LLCS_SNAP_HEADER); /* * and copy the rest */ size = sizeof(LABBuffer) - sizeof(LLCS_SNAP_HEADER); memcpy(pFrameBuffer, pBytePointer, size); /* * Change the pointer for the "global copy" */ pFrameBuffer += size; copy_size -= size; /* This was already in the LookAheadBuffer */ } else { IPFrame = 0; } } /* only ARP and IP */ } else { /* * Check if this is a RFX894 Frame */ if ((LABBuffer.ether_type == 0x0608) || (LABBuffer.ether_type == 0x0008)) {#if (WLAN_ENABLE_RX_FRAME_DUMP >= 1) Debug(("RFC894 IP-Frame\n"));#endif IPFrame = 1; /* * The MAC can not handle odd counts, test it. * */ len += 1; len &= ~1; /* * The FrameLength is now the correct length for an RFC894 Frame, * Now alloc the NetBuffer for Ethernut. */ nb = NutNetBufAlloc(0, NBAF_DATALINK, len); if (nb != 0) { pFrameBuffer = nb->nb_dl.vp; /* * We must copy wFrameLength out of the MAC */ copy_size = len; /* * The LookAheadBuffer is the MAC-Header */ memcpy(pFrameBuffer, &LABBuffer, sizeof(LABBuffer)); pFrameBuffer += sizeof(LABBuffer); copy_size -= sizeof(LABBuffer); /* This was our LookAheadBuffer */ } else { IPFrame = 0; } /* NutNetBufAlloc */ } /* RFC894 Frame */ } /* Error read LookAheadBuffer */ /* * Do the rest here, "global copy" */ if (IPFrame == 1) { error = wi_read_bap(sc, fid, off, pFrameBuffer, copy_size); if (error != 0) { NutNetBufFree(nb); nb = NULL; } else {#if (WLAN_ENABLE_RX_FRAME_DUMP >= 1) Debug(("RxFrame: %d\n", len)); DumpWlanData(nb->nb_dl.vp, nb->nb_dl.sz);#endif } } } /* * At least, send a ack for the event */ CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); return (nb);}/************************************************************//* RxThread *//************************************************************/THREAD(RxThread, arg){ NUTDEVICE *dev; IFNET *ifn; NETBUF *nb; struct wi_softc *sc; u_int16_t EventStatus; dev = arg; ifn = (IFNET *) dev->dev_icb; sc = (struct wi_softc *) dev->dev_dcb; for (;;) { /* * Wait for the arrival of new packets or check * the receiver every two second. */ NutEventWait(&sc->InterruptEvent, 2000); EventStatus = sc->EventStatus; /* * Clear the sc-EventStatus. If the next time the * EventStatus is 0, it was the timeout and not * an interrupt. */ sc->EventStatus = 0; if (EventStatus != 0) { if (EventStatus & WI_EV_RX) { WI_LOCK(sc); nb = wi_rx_intr(sc); WI_UNLOCK(sc); if (nb != 0) { (*ifn->if_recv) (dev, nb); } } if (EventStatus & WI_EV_ALLOC) { WI_LOCK(sc); wi_tx_intr(sc); WI_UNLOCK(sc); } if (EventStatus & WI_EV_INFO) { WI_LOCK(sc); wi_info_intr(sc); WI_UNLOCK(sc); } if (EventStatus & WI_EV_TX_EXC) { Debug(("WI_EV_TX_EXC\n")); } CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS); } else { /* * It was the timeout, check if the card is alive */ if ((sc->sc_enabled == 1) && (sc->wi_gone == 1)) { /* * The card was enabled but we has lost the card, reinit... */ Debug(("Houston, we have a problem...\n")); sc->wi_gone = 0; wlandrv_Init(dev); } } /* (EventStatus != 0) */ } /* for */}/************************************************************//* wi_alloc_fid *//************************************************************/static int wi_alloc_fid(struct wi_softc *sc, int len, int *idp){ unsigned long i; /* Harald: Changed from int to long */ /* Oliver: Changed from signed to unsigned */ if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) { Debug(("failed to allocate %d bytes on NIC\n", len)); return ENOMEM; } for (i = 0; i < WI_TIMEOUT; i++) { if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC) { break; } if (i == WI_TIMEOUT) { Debug(("timeout in alloc\n")); return ETIMEDOUT; } DELAY(1); } *idp = CSR_READ_2(sc, WI_ALLOC_FID); CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC); return 0;}/************************************************************//* wi_write_ssid *//************************************************************/static int wi_write_ssid(struct wi_softc *sc, int rid, u_int8_t * buf, int buflen){ struct wi_ssid ssid; if (buflen > IEEE80211_NWID_LEN) { return ENOBUFS; } memset(&ssid, 0, sizeof(ssid)); ssid.wi_len = htole16(buflen); memcpy(ssid.wi_ssid, buf, buflen); return wi_write_rid(sc, rid, &ssid, sizeof(ssid));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -