📄 wlandrv.c
字号:
/***************************************************************************** This file is part of the WLAN-Ethernut device driver.** Copyright (c) 2004 by Michael Fischer. All rights reserved.** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions* are met:** 1. Redistributions of source code must retain the above copyright* notice, this list of conditions and the following disclaimer.* 2. Redistributions in binary form must reproduce the above copyright* notice, this list of conditions and the following disclaimer in the* documentation and/or other materials provided with the distribution.* 3. Neither the name of the author nor the names of its contributors may* be used to endorse or promote products derived from this software* without specific prior written permission.** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL* THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF* SUCH DAMAGE.****************************************************************************** Portions Copyright:** Copyright (c) 2002* M Warner Losh <imp@freebsd.org>. All rights reserved.* Copyright (c) 1997, 1998, 1999* Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions* are met:* 1. Redistributions of source code must retain the above copyright* notice, this list of conditions and the following disclaimer.* 2. Redistributions in binary form must reproduce the above copyright* notice, this list of conditions and the following disclaimer in the* documentation and/or other materials provided with the distribution.* 3. Neither the name of the author nor the names of any co-contributors* may be used to endorse or promote products derived from this software* without specific prior written permission.** THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE* ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF* THE POSSIBILITY OF SUCH DAMAGE.****************************************************************************** History:** 28.02.04 mifi First Version* If you like to see the original source. Take a look* in if_wi.c from FreeBSD.* 01.03.04 mifi Now we use a timeout in our Thread, and check if we lost* the card. In this case we try to Init it again.* 02.03.04 mifi Remove QuickHack for Networkname and WEP.* 03.03.04 mifi Use struct to config WLAN (WLAN_IOCTL_SET_CONFIG)* 04.03.04 mifi Add function to get WLAN_STATUS (WLAN_IOCTL_GET_STATUS)* 06.03.04 mifi Remove all @@MF later for monitor mode.* It does not work with my card, and I think we need a* special firmware for it.****************************************************************************/#define __WLANDRV_C__#include <compiler.h>#include <stdio.h>#include <stddef.h>#include <string.h>#include <sys/timer.h>#include <sys/thread.h>#include <sys/event.h>#include <errno.h>#include <netinet/if_ether.h>#include <net/ether.h>#include <net/if_var.h>#include <dev/irqreg.h>#include <dev/wlantypes.h>#include <dev/pcmcia.h>#include <dev/wlancfg.h>#include <dev/wlan.h>#include <dev/wlandrv.h>/*==========================================================*//* DEFINE: All Structures and Common Constants *//*==========================================================*/#if (_DEBUG >= 1)#define Debug(_x) if (bDebugState ) printf _x#define Debug2(_x) if (bDebugState > 1) printf _x#define panic printf#else#define Debug(_x)#define Debug2(_x)#define panic#endif#define WI_LOCK(sc) NutEventWait(&hDeviceSemaphore,0)#define WI_UNLOCK(sc) NutEventPost(&hDeviceSemaphore)#define ieee80211_new_state(_a,_b,_c) _a->ic_state=_b#define isset(_a,_b) (*_a & (1<<_b))#define CSR_WRITE_2(_a,_b,_c) pcmcia_WriteReg(_b,_c)#define CSR_READ_2(_a,_b) pcmcia_ReadReg(_b)/* * Length information */#define WLAN_MIN_ETHERNET_FRAME_LEN 60#define WLAN_MAX_ETHERNET_FRAME_LEN 1514#define WLAN_ETHERNET_HEADER_LEN 14/* * Interrupt define*/#define WI_INTRS (WI_EV_RX | WI_EV_ALLOC | WI_EV_INFO)struct wi_card_ident { u_int16_t card_id; char *card_name; u_int8_t firm_type;};struct ieee80211_frame_addr4 { u_int8_t i_fc[2]; u_int8_t i_dur[2]; u_int8_t i_addr1[IEEE80211_ADDR_LEN]; u_int8_t i_addr2[IEEE80211_ADDR_LEN]; u_int8_t i_addr3[IEEE80211_ADDR_LEN]; u_int8_t i_seq[2]; u_int8_t i_addr4[IEEE80211_ADDR_LEN];};/* * transmit/receive frame structure*/struct wi_frame { u_int16_t wi_status; /* 0x00 */ u_int16_t wi_rx_tstamp1; /* 0x02 */ u_int16_t wi_rx_tstamp0; /* 0x04 */ u_int8_t wi_rx_silence; /* 0x06 */ u_int8_t wi_rx_signal; /* 0x07 */ u_int8_t wi_rx_rate; /* 0x08 */ u_int8_t wi_rx_flow; /* 0x09 */ u_int8_t wi_tx_rtry; /* 0x0a *//* Prism2 AP Only */ u_int8_t wi_tx_rate; /* 0x0b *//* Prism2 AP Only */ u_int16_t wi_tx_ctl; /* 0x0c */ struct ieee80211_frame_addr4 wi_whdr; /* 0x0e */ u_int16_t wi_dat_len; /* 0x2c */ struct ether_header wi_ehdr; /* 0x2e */};/* * Station set identification (SSID). (0xFC02, 0xFC04)*/struct wi_ssid { u_int16_t wi_len; u_int8_t wi_ssid[32];};/* * Ethernet LLCS + SNAP header*/typedef struct { u_int16_t DSAPSSAP; u_int16_t Control; u_int16_t MustZero; u_int16_t Type;} LLCS_SNAP_HEADER;/*==========================================================*//* DEFINE: Prototypes *//*==========================================================*//*==========================================================*//* DEFINE: Definition of all local Data *//*==========================================================*/static HANDLE hDeviceSemaphore;static BYTE bDebugState = 0;struct wi_card_ident wi_card_ident[] = { /* * CARD_ID CARD_NAME FIRM_TYPE */#if (WLAN_SUPPORT_LUCENT >= 1) {WI_NIC_LUCENT_ID, WI_NIC_LUCENT_STR, WI_LUCENT}, {WI_NIC_SONY_ID, WI_NIC_SONY_STR, WI_LUCENT}, {WI_NIC_LUCENT_EMB_ID, WI_NIC_LUCENT_EMB_STR, WI_LUCENT},#endif /* (WLAN_SUPPORT_LUCENT >= 1) */#if (WLAN_SUPPORT_INTERSIL >= 1) {WI_NIC_EVB2_ID, WI_NIC_EVB2_STR, WI_INTERSIL}, {WI_NIC_HWB3763_ID, WI_NIC_HWB3763_STR, WI_INTERSIL}, {WI_NIC_HWB3163_ID, WI_NIC_HWB3163_STR, WI_INTERSIL}, {WI_NIC_HWB3163B_ID, WI_NIC_HWB3163B_STR, WI_INTERSIL}, {WI_NIC_EVB3_ID, WI_NIC_EVB3_STR, WI_INTERSIL}, {WI_NIC_HWB1153_ID, WI_NIC_HWB1153_STR, WI_INTERSIL}, {WI_NIC_P2_SST_ID, WI_NIC_P2_SST_STR, WI_INTERSIL}, {WI_NIC_EVB2_SST_ID, WI_NIC_EVB2_SST_STR, WI_INTERSIL}, {WI_NIC_3842_EVA_ID, WI_NIC_3842_EVA_STR, WI_INTERSIL}, {WI_NIC_3842_PCMCIA_AMD_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL}, {WI_NIC_3842_PCMCIA_SST_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL}, {WI_NIC_3842_PCMCIA_ATL_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL}, {WI_NIC_3842_PCMCIA_ATS_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL}, {WI_NIC_3842_MINI_AMD_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL}, {WI_NIC_3842_MINI_SST_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL}, {WI_NIC_3842_MINI_ATL_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL}, {WI_NIC_3842_MINI_ATS_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL}, {WI_NIC_3842_PCI_AMD_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL}, {WI_NIC_3842_PCI_SST_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL}, {WI_NIC_3842_PCI_ATS_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL}, {WI_NIC_3842_PCI_ATL_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL}, {WI_NIC_P3_PCMCIA_AMD_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL}, {WI_NIC_P3_PCMCIA_SST_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL}, {WI_NIC_P3_PCMCIA_ATL_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL}, {WI_NIC_P3_PCMCIA_ATS_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL}, {WI_NIC_P3_MINI_AMD_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL}, {WI_NIC_P3_MINI_SST_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL}, {WI_NIC_P3_MINI_ATL_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL}, {WI_NIC_P3_MINI_ATS_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL},#endif /* (WLAN_SUPPORT_INTERSIL >= 1) */ {0, NULL, 0},};/*==========================================================*//* DEFINE: Definition of all local Procedures *//*==========================================================*//************************************************************//* DELAY *//* *//* Delay in us. *//************************************************************/static void DELAY(u_int32_t delay_us){ delay_us = delay_us / 1000; delay_us++; NutSleep(delay_us);}/************************************************************//* DumpData *//* *//* Dump the Buffer to the Terminal *//************************************************************//* Harald: Not always used, but not sure how. Changedfron static to global and changed name to avoid conflicts */void DumpWlanData(BYTE * pBuffer, WORD wBufferSize){ u_int16_t x, MaxX = 16; u_int16_t y, MaxY; u_int16_t Size; if (bDebugState != 0) { Size = 0; MaxY = (wBufferSize / 16) + 1; for (y = 0; y < MaxY; y++) { Debug(("%04X: ", (y * 16))); for (x = 0; x < MaxX; x++) { Debug(("%02X ", pBuffer[Size])); Size++; if (Size >= wBufferSize) { Debug(("\r\n")); return; } } Debug(("\r\n")); } }}/************************************************************//* wi_cmd *//************************************************************/static int wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2){ unsigned long i; /* Harald: Changed from int to long. */ unsigned int s = 0; /* Oliver: Changed from signed to unsigned. */ static volatile int count = 0; if (sc->wi_gone) { return (ENODEV); } /* Harald: Removed this, it makes no sense */ //if (count > 0) { // panic("Hey partner, hold on there!"); //} count++; /* * wait for the busy bit to clear */ for (i = sc->wi_cmd_count; i > 0; i--) { /* 500ms */ if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) { break; } DELAY(1 * 1000); /* 1ms */ } if (i == 0) { Debug(("wi_cmd: busy bit won't clear.\n")); sc->wi_gone = 1; count--; return (ETIMEDOUT); } CSR_WRITE_2(sc, WI_PARAM0, val0); CSR_WRITE_2(sc, WI_PARAM1, val1); CSR_WRITE_2(sc, WI_PARAM2, val2); CSR_WRITE_2(sc, WI_COMMAND, cmd); if (cmd == WI_CMD_INI) { /* * XXX: should sleep here. */ /* Harald: Added UL specifiers, no idea how Michael's ICC accepted this */ DELAY(250UL * 1000UL); /* 250ms delay for init */ } for (i = 0; i < WI_TIMEOUT; i++) { /* * Wait for 'command complete' bit to be * set in the event status register. */ s = CSR_READ_2(sc, WI_EVENT_STAT); if (s & WI_EV_CMD) { /* * Ack the event and read result code. */ s = CSR_READ_2(sc, WI_STATUS); CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD); if (s & WI_STAT_CMD_RESULT) { count--; return (EIO); } break; } DELAY(WI_DELAY); } count--; if (i == WI_TIMEOUT) { Debug(("timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd, s)); if (s == 0xffff) { sc->wi_gone = 1; } return (ETIMEDOUT); } return (0);}/************************************************************//* wi_stop *//************************************************************/void wi_stop(struct wi_softc *sc, int disable){ struct ieee80211com *ic = &sc->sc_ic; DELAY(100000); ieee80211_new_state(ic, IEEE80211_S_INIT, -1); if (sc->sc_enabled && !sc->wi_gone) { CSR_WRITE_2(sc, WI_INT_EN, 0); wi_cmd(sc, WI_CMD_DISABLE | sc->sc_portnum, 0, 0, 0); if (disable) { sc->sc_enabled = 0; } } else { if (sc->wi_gone && disable) { /* gone --> not enabled */ sc->sc_enabled = 0; } } sc->sc_tx_timer = 0; sc->sc_scan_timer = 0;}/************************************************************//* wi_seek_bap *//************************************************************/static int wi_seek_bap(struct wi_softc *sc, int id, int off){ long i; /* Harald: from int to long */ unsigned int status; /* Oliver: from signed to unsigned */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -