diff -u -p linux/drivers/net/pcmcia/wireless.25b/hermes.h linux/drivers/net/pcmcia/hermes.h --- linux/drivers/net/pcmcia/wireless.25b/hermes.h Tue Apr 24 15:57:48 2001 +++ linux/drivers/net/pcmcia/hermes.h Tue Apr 24 16:04:34 2001 @@ -35,18 +35,18 @@ /* * Limits and constants */ -#define HERMES_ALLOC_LEN_MIN ((uint16_t)4) -#define HERMES_ALLOC_LEN_MAX ((uint16_t)2400) +#define HERMES_ALLOC_LEN_MIN (4) +#define HERMES_ALLOC_LEN_MAX (2400) #define HERMES_LTV_LEN_MAX (34) -#define HERMES_BAP_DATALEN_MAX ((uint16_t)4096) -#define HERMES_BAP_OFFSET_MAX ((uint16_t)4096) -#define HERMES_PORTID_MAX ((uint16_t)7) -#define HERMES_NUMPORTS_MAX ((uint16_t)(HERMES_PORTID_MAX+1)) -#define HERMES_PDR_LEN_MAX ((uint16_t)260) /* in bytes, from EK */ -#define HERMES_PDA_RECS_MAX ((uint16_t)200) /* a guess */ -#define HERMES_PDA_LEN_MAX ((uint16_t)1024) /* in bytes, from EK */ -#define HERMES_SCANRESULT_MAX ((uint16_t)35) -#define HERMES_CHINFORESULT_MAX ((uint16_t)8) +#define HERMES_BAP_DATALEN_MAX (4096) +#define HERMES_BAP_OFFSET_MAX (4096) +#define HERMES_PORTID_MAX (7) +#define HERMES_NUMPORTS_MAX (HERMES_PORTID_MAX+1) +#define HERMES_PDR_LEN_MAX (260) /* in bytes, from EK */ +#define HERMES_PDA_RECS_MAX (200) /* a guess */ +#define HERMES_PDA_LEN_MAX (1024) /* in bytes, from EK */ +#define HERMES_SCANRESULT_MAX (35) +#define HERMES_CHINFORESULT_MAX (8) #define HERMES_FRAME_LEN_MAX (2304) #define HERMES_MAX_MULTICAST (16) #define HERMES_MAGIC (0x7d1f) @@ -86,122 +86,125 @@ /* * CMD register bitmasks */ -#define HERMES_CMD_BUSY ((uint16_t)0x8000) -#define HERMES_CMD_AINFO ((uint16_t)0x7f00) -#define HERMES_CMD_MACPORT ((uint16_t)0x0700) -#define HERMES_CMD_RECL ((uint16_t)0x0100) -#define HERMES_CMD_WRITE ((uint16_t)0x0100) -#define HERMES_CMD_PROGMODE ((uint16_t)0x0300) -#define HERMES_CMD_CMDCODE ((uint16_t)0x003f) +#define HERMES_CMD_BUSY (0x8000) +#define HERMES_CMD_AINFO (0x7f00) +#define HERMES_CMD_MACPORT (0x0700) +#define HERMES_CMD_RECL (0x0100) +#define HERMES_CMD_WRITE (0x0100) +#define HERMES_CMD_PROGMODE (0x0300) +#define HERMES_CMD_CMDCODE (0x003f) /* * STATUS register bitmasks */ -#define HERMES_STATUS_RESULT ((uint16_t)0x7f00) -#define HERMES_STATUS_CMDCODE ((uint16_t)0x003f) +#define HERMES_STATUS_RESULT (0x7f00) +#define HERMES_STATUS_CMDCODE (0x003f) /* * OFFSET refister bitmasks */ -#define HERMES_OFFSET_BUSY ((uint16_t)0x8000) -#define HERMES_OFFSET_ERR ((uint16_t)0x4000) -#define HERMES_OFFSET_DATAOFF ((uint16_t)0x0ffe) +#define HERMES_OFFSET_BUSY (0x8000) +#define HERMES_OFFSET_ERR (0x4000) +#define HERMES_OFFSET_DATAOFF (0x0ffe) /* * Event register bitmasks (INTEN, EVSTAT, EVACK) */ -#define HERMES_EV_TICK ((uint16_t)0x8000) -#define HERMES_EV_WTERR ((uint16_t)0x4000) -#define HERMES_EV_INFDROP ((uint16_t)0x2000) -#define HERMES_EV_INFO ((uint16_t)0x0080) -#define HERMES_EV_DTIM ((uint16_t)0x0020) -#define HERMES_EV_CMD ((uint16_t)0x0010) -#define HERMES_EV_ALLOC ((uint16_t)0x0008) -#define HERMES_EV_TXEXC ((uint16_t)0x0004) -#define HERMES_EV_TX ((uint16_t)0x0002) -#define HERMES_EV_RX ((uint16_t)0x0001) +#define HERMES_EV_TICK (0x8000) +#define HERMES_EV_WTERR (0x4000) +#define HERMES_EV_INFDROP (0x2000) +#define HERMES_EV_INFO (0x0080) +#define HERMES_EV_DTIM (0x0020) +#define HERMES_EV_CMD (0x0010) +#define HERMES_EV_ALLOC (0x0008) +#define HERMES_EV_TXEXC (0x0004) +#define HERMES_EV_TX (0x0002) +#define HERMES_EV_RX (0x0001) /* * Command codes */ /*--- Controller Commands --------------------------*/ -#define HERMES_CMD_INIT ((uint16_t)0x00) -#define HERMES_CMD_ENABLE ((uint16_t)0x01) -#define HERMES_CMD_DISABLE ((uint16_t)0x02) -#define HERMES_CMD_DIAG ((uint16_t)0x03) +#define HERMES_CMD_INIT (0x0000) +#define HERMES_CMD_ENABLE (0x0001) +#define HERMES_CMD_DISABLE (0x0002) +#define HERMES_CMD_DIAG (0x0003) /*--- Buffer Mgmt Commands --------------------------*/ -#define HERMES_CMD_ALLOC ((uint16_t)0x0A) -#define HERMES_CMD_TX ((uint16_t)0x0B) -#define HERMES_CMD_CLRPRST ((uint16_t)0x12) +#define HERMES_CMD_ALLOC (0x000A) +#define HERMES_CMD_TX (0x000B) +#define HERMES_CMD_CLRPRST (0x0012) /*--- Regulate Commands --------------------------*/ -#define HERMES_CMD_NOTIFY ((uint16_t)0x10) -#define HERMES_CMD_INQ ((uint16_t)0x11) +#define HERMES_CMD_NOTIFY (0x0010) +#define HERMES_CMD_INQ (0x0011) /*--- Configure Commands --------------------------*/ -#define HERMES_CMD_ACCESS ((uint16_t)0x21) -#define HERMES_CMD_DOWNLD ((uint16_t)0x22) +#define HERMES_CMD_ACCESS (0x0021) +#define HERMES_CMD_DOWNLD (0x0022) /*--- Debugging Commands -----------------------------*/ -#define HERMES_CMD_MONITOR ((uint16_t)(0x38)) -#define HERMES_MONITOR_ENABLE ((uint16_t)(0x0b)) -#define HERMES_MONITOR_DISABLE ((uint16_t)(0x0f)) +#define HERMES_CMD_MONITOR (0x0038) +#define HERMES_MONITOR_ENABLE (0x000b) +#define HERMES_MONITOR_DISABLE (0x000f) /* * Configuration RIDs */ -#define HERMES_RID_CNF_PORTTYPE ((uint16_t)0xfc00) -#define HERMES_RID_CNF_MACADDR ((uint16_t)0xfc01) -#define HERMES_RID_CNF_DESIRED_SSID ((uint16_t)0xfc02) -#define HERMES_RID_CNF_CHANNEL ((uint16_t)0xfc03) -#define HERMES_RID_CNF_OWN_SSID ((uint16_t)0xfc04) -#define HERMES_RID_CNF_SYSTEM_SCALE ((uint16_t)0xfc06) -#define HERMES_RID_CNF_MAX_DATA_LEN ((uint16_t)0xfc07) -#define HERMES_RID_CNF_PM_ENABLE ((uint16_t)0xfc09) -#define HERMES_RID_CNF_PM_MCAST_RX ((uint16_t)0xfc0b) -#define HERMES_RID_CNF_PM_PERIOD ((uint16_t)0xfc0c) -#define HERMES_RID_CNF_PM_HOLDOVER ((uint16_t)0xfc0d) -#define HERMES_RID_CNF_NICKNAME ((uint16_t)0xfc0e) -#define HERMES_RID_CNF_WEP_ON ((uint16_t)0xfc20) -#define HERMES_RID_CNF_MWO_ROBUST ((uint16_t)0xfc25) -#define HERMES_RID_CNF_PRISM2_WEP_ON ((uint16_t)0xfc28) -#define HERMES_RID_CNF_MULTICAST_LIST ((uint16_t)0xfc80) -#define HERMES_RID_CNF_CREATEIBSS ((uint16_t)0xfc81) -#define HERMES_RID_CNF_FRAG_THRESH ((uint16_t)0xfc82) -#define HERMES_RID_CNF_RTS_THRESH ((uint16_t)0xfc83) -#define HERMES_RID_CNF_TX_RATE_CTRL ((uint16_t)0xfc84) -#define HERMES_RID_CNF_PROMISCUOUS ((uint16_t)0xfc85) -#define HERMES_RID_CNF_KEYS ((uint16_t)0xfcb0) -#define HERMES_RID_CNF_TX_KEY ((uint16_t)0xfcb1) -#define HERMES_RID_CNF_TICKTIME ((uint16_t)0xfce0) - -#define HERMES_RID_CNF_PRISM2_TX_KEY ((uint16_t)0xfc23) -#define HERMES_RID_CNF_PRISM2_KEY0 ((uint16_t)0xfc24) -#define HERMES_RID_CNF_PRISM2_KEY1 ((uint16_t)0xfc25) -#define HERMES_RID_CNF_PRISM2_KEY2 ((uint16_t)0xfc26) -#define HERMES_RID_CNF_PRISM2_KEY3 ((uint16_t)0xfc27) -#define HERMES_RID_CNF_SYMBOL_AUTH_TYPE ((uint16_t)0xfc2A) -/* This one is read only */ -#define HERMES_RID_CNF_SYMBOL_KEY_LENGTH ((uint16_t)0xfc2B) -#define HERMES_RID_CNF_SYMBOL_BASIC_RATES ((uint16_t)0xfc8A) +#define HERMES_RID_CNF_PORTTYPE (0xfc00) +#define HERMES_RID_CNF_MACADDR (0xfc01) +#define HERMES_RID_CNF_DESIRED_SSID (0xfc02) +#define HERMES_RID_CNF_CHANNEL (0xfc03) +#define HERMES_RID_CNF_OWN_SSID (0xfc04) +#define HERMES_RID_CNF_SYSTEM_SCALE (0xfc06) +#define HERMES_RID_CNF_MAX_DATA_LEN (0xfc07) +#define HERMES_RID_CNF_PM_ENABLE (0xfc09) +#define HERMES_RID_CNF_PM_MCAST_RX (0xfc0b) +#define HERMES_RID_CNF_PM_PERIOD (0xfc0c) +#define HERMES_RID_CNF_PM_HOLDOVER (0xfc0d) +#define HERMES_RID_CNF_NICKNAME (0xfc0e) +#define HERMES_RID_CNF_WEP_ON (0xfc20) +#define HERMES_RID_CNF_MWO_ROBUST (0xfc25) +#define HERMES_RID_CNF_PRISM2_WEP_ON (0xfc28) +#define HERMES_RID_CNF_MULTICAST_LIST (0xfc80) +#define HERMES_RID_CNF_CREATEIBSS (0xfc81) +#define HERMES_RID_CNF_FRAG_THRESH (0xfc82) +#define HERMES_RID_CNF_RTS_THRESH (0xfc83) +#define HERMES_RID_CNF_TX_RATE_CTRL (0xfc84) +#define HERMES_RID_CNF_PROMISCUOUS (0xfc85) +#define HERMES_RID_CNF_KEYS (0xfcb0) +#define HERMES_RID_CNF_TX_KEY (0xfcb1) +#define HERMES_RID_CNF_TICKTIME (0xfce0) + +#define HERMES_RID_CNF_PRISM2_TX_KEY (0xfc23) +#define HERMES_RID_CNF_PRISM2_KEY0 (0xfc24) +#define HERMES_RID_CNF_PRISM2_KEY1 (0xfc25) +#define HERMES_RID_CNF_PRISM2_KEY2 (0xfc26) +#define HERMES_RID_CNF_PRISM2_KEY3 (0xfc27) +#define HERMES_RID_CNF_SYMBOL_MANDATORY_BSSID (0xfc21) +#define HERMES_RID_CNF_SYMBOL_AUTH_TYPE (0xfc2A) +#define HERMES_RID_CNF_SYMBOL_BASIC_RATES (0xfc8A) +#define HERMES_RID_CNF_SYMBOL_PREAMBLE (0xfc8C) /* * Information RIDs */ -#define HERMES_RID_CHANNEL_LIST ((uint16_t)0xfd10) -#define HERMES_RID_STAIDENTITY ((uint16_t)0xfd20) -#define HERMES_RID_CURRENT_SSID ((uint16_t)0xfd41) -#define HERMES_RID_CURRENT_BSSID ((uint16_t)0xfd42) -#define HERMES_RID_COMMSQUALITY ((uint16_t)0xfd43) -#define HERMES_RID_CURRENT_TX_RATE ((uint16_t)0xfd44) -#define HERMES_RID_SHORT_RETRY_LIMIT ((uint16_t)0xfd48) -#define HERMES_RID_LONG_RETRY_LIMIT ((uint16_t)0xfd49) -#define HERMES_RID_MAX_TX_LIFETIME ((uint16_t)0xfd4A) -#define HERMES_RID_WEP_AVAIL ((uint16_t)0xfd4f) -#define HERMES_RID_CURRENT_CHANNEL ((uint16_t)0xfdc1) -#define HERMES_RID_DATARATES ((uint16_t)0xfdc6) +#define HERMES_RID_CHANNEL_LIST (0xfd10) +#define HERMES_RID_STAIDENTITY (0xfd20) +#define HERMES_RID_CURRENT_SSID (0xfd41) +#define HERMES_RID_CURRENT_BSSID (0xfd42) +#define HERMES_RID_COMMSQUALITY (0xfd43) +#define HERMES_RID_CURRENT_TX_RATE (0xfd44) +#define HERMES_RID_SHORT_RETRY_LIMIT (0xfd48) +#define HERMES_RID_LONG_RETRY_LIMIT (0xfd49) +#define HERMES_RID_MAX_TX_LIFETIME (0xfd4A) +#define HERMES_RID_WEP_AVAIL (0xfd4f) +#define HERMES_RID_CURRENT_CHANNEL (0xfdc1) +#define HERMES_RID_DATARATES (0xfdc6) +#define HERMES_RID_SYMBOL_PRIMARY_VER (0xfd03) +#define HERMES_RID_SYMBOL_SECONDARY_VER (0xfd21) +#define HERMES_RID_SYMBOL_KEY_LENGTH (0xfc2B) /* * Frame structures and constants @@ -216,19 +219,19 @@ typedef struct hermes_frame_desc { uint16_t tx_ctl; /* 0xC */ } __attribute__ ((packed)) hermes_frame_desc_t; -#define HERMES_RXSTAT_ERR ((uint16_t)0x0003) -#define HERMES_RXSTAT_MACPORT ((uint16_t)0x0700) -#define HERMES_RXSTAT_MSGTYPE ((uint16_t)0xE000) +#define HERMES_RXSTAT_ERR (0x0003) +#define HERMES_RXSTAT_MACPORT (0x0700) +#define HERMES_RXSTAT_MSGTYPE (0xE000) -#define HERMES_RXSTAT_BADCRC ((uint16_t)0x0001) -#define HERMES_RXSTAT_UNDECRYPTABLE ((uint16_t)0x0002) +#define HERMES_RXSTAT_BADCRC (0x0001) +#define HERMES_RXSTAT_UNDECRYPTABLE (0x0002) /* RFC-1042 encoded frame */ -#define HERMES_RXSTAT_1042 ((uint16_t)0x2000) +#define HERMES_RXSTAT_1042 (0x2000) /* Bridge-tunnel encoded frame */ -#define HERMES_RXSTAT_TUNNEL ((uint16_t)0x4000) +#define HERMES_RXSTAT_TUNNEL (0x4000) /* Wavelan-II Management Protocol frame */ -#define HERMES_RXSTAT_WMP ((uint16_t)0x6000) +#define HERMES_RXSTAT_WMP (0x6000) #ifdef __KERNEL__ @@ -331,8 +334,6 @@ static inline int hermes_disable_port(he (hermes_read_ltv((hw),(bap),(rid), sizeof(*buf), NULL, (buf))) #define HERMES_WRITE_RECORD(hw, bap, rid, buf) \ (hermes_write_ltv((hw),(bap),(rid),HERMES_BYTES_TO_RECLEN(sizeof(*buf)),(buf))) -#define HERMES_WRITE_RECORD_LEN(hw, bap, rid, buf, len) \ - (hermes_write_ltv((hw),(bap),(rid),HERMES_BYTES_TO_RECLEN(len),(buf))) static inline int hermes_read_wordrec(hermes_t *hw, int bap, uint16_t rid, uint16_t *word) { diff -u -p linux/drivers/net/pcmcia/wireless.25b/hermes.c linux/drivers/net/pcmcia/hermes.c --- linux/drivers/net/pcmcia/wireless.25b/hermes.c Tue Apr 24 15:57:48 2001 +++ linux/drivers/net/pcmcia/hermes.c Tue Apr 24 16:00:24 2001 @@ -21,6 +21,7 @@ static const char *version = "hermes.c: #include #include +#include #include #include #include diff -u -p linux/drivers/net/pcmcia/wireless.25b/orinoco_cs.c linux/drivers/net/pcmcia/orinoco_cs.c --- linux/drivers/net/pcmcia/wireless.25b/orinoco_cs.c Tue Apr 24 15:57:48 2001 +++ linux/drivers/net/pcmcia/orinoco_cs.c Tue Apr 24 17:47:26 2001 @@ -1,4 +1,4 @@ -/* orinoco_cs.c 0.03 - (formerly known as dldwd_cs.c) +/* orinoco_cs.c 0.04 - (formerly known as dldwd_cs.c) * * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/ @@ -97,6 +97,28 @@ * o Finish external renaming to orinoco... * o Testing with various Wavelan firmwares * + * v0.03 -> v0.04 - 30/3/2001 - Jean II + * o Update to Wireless 11 -> add retry limit/lifetime support + * o Tested with a D-Link DWL 650 card, fill in firmware support + * o Warning on Vcc mismatch (D-Link 3.3v card in Lucent 5v only slot) + * o Fixed the Prims2 WEP bugs that I introduced in v0.03 :-( + * It work on D-Link *only* after a tcpdump. Weird... + * And still doesn't work on Intel card. Grrrr... + * o Update the mode after a setport3 + * o Add preamble setting for Symbol cards (not yet enabled) + * o Don't complain as much about Symbol cards... + * + * v0.04 -> v0.04b - 22/4/2001 - David Gibson + * o Removed the 'eth' parameter - always use ethXX as the + * interface name instead of dldwdXX. The other was racy + * anyway. + * o Clean up RID definitions in hermes.h, other cleanups + * + * v0.04b -> v0.04c - 24/4/2001 - Jean II + * o Tim Hurley reported a D-Link card + * with vendor 02 and firmware 0.08. Added in the capabilities... + * o Tested Lucent firmware 7.28, everything works... + * * TODO - Jean II * o inline functions (lot's of candidate, need to reorder code) * o Separate Pcmcia specific code to help Airport/Mini PCI driver @@ -133,7 +155,7 @@ #ifdef PCMCIA_DEBUG static int pc_debug = PCMCIA_DEBUG; -static char *version = "orinoco_cs.c 0.03 (David Gibson )"; +static char *version = "orinoco_cs.c 0.04 (David Gibson )"; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) #define DEBUGMORE(n, args...) do { if (pc_debug>(n)) printk(args); } while (0) @@ -165,12 +187,12 @@ MODULE_PARM(pc_debug, "i"); static uint irq_mask = 0xdeb8; /* Newer, simpler way of listing specific interrupts */ static int irq_list[4] = { -1 }; -/* Control device name allocation. 0 -> dldwdX ; 1 -> ethX */ -static int eth = 1; +/* Do a Pcmcia soft reset (may help some cards) */ +static int reset_cor = 0; MODULE_PARM(irq_mask, "i"); MODULE_PARM(irq_list, "1-4i"); -MODULE_PARM(eth, "i"); +MODULE_PARM(reset_cor, "i"); /*====================================================================*/ @@ -240,13 +262,14 @@ typedef struct dldwd_priv { int has_mwo; int has_pm; int has_retry; + int has_preamble; int broken_reset, broken_allocate; uint16_t channel_mask; /* Current configuration */ uint32_t iw_mode; int port_type, allow_ibss; - uint16_t wep_on, wep_auth, tx_key; + uint16_t wep_on, wep_restrict, tx_key; dldwd_keys_t keys; char nick[IW_ESSID_MAX_SIZE+1]; char desired_essid[IW_ESSID_MAX_SIZE+1]; @@ -256,6 +279,7 @@ typedef struct dldwd_priv { uint16_t tx_rate_ctrl; uint16_t pm_on, pm_mcast, pm_period, pm_timeout; uint16_t retry_short, retry_long, retry_time; + uint16_t preamble; int promiscuous, allmulti, mc_count; @@ -665,6 +689,16 @@ ESSID in IBSS-Ad-Hoc mode.\n", dev->name goto out; } + /* Set preamble - only for Symbol so far... */ + if (priv->has_preamble) { + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_PREAMBLE, + priv->preamble); + if (err) { + printk(KERN_WARNING "%s: Can't set preamble!\n", dev->name); + goto out; + } + } + /* Set promiscuity / multicast*/ priv->promiscuous = 0; priv->allmulti = 0; @@ -692,7 +726,8 @@ static int __dldwd_hw_setup_wep(dldwd_pr { hermes_t *hw = &priv->hw; int err = 0; - + int extra_wep_flag = 0; + switch (priv->firmware_type) { case FIRMWARE_TYPE_LUCENT: /* Lucent style WEP */ if (priv->wep_on) { @@ -716,33 +751,53 @@ static int __dldwd_hw_setup_wep(dldwd_pr int keylen; int i; - err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PRISM2_TX_KEY, - priv->tx_key); - if (err) - return err; - - keybuf[LARGE_KEY_SIZE] = '\0'; - /* Write all 4 keys */ for(i = 0; i < MAX_KEYS; i++) { keylen = priv->keys[i].len; - keybuf[SMALL_KEY_SIZE] = '\0'; + keybuf[keylen] = '\0'; memcpy(keybuf, priv->keys[i].data, keylen); - err = HERMES_WRITE_RECORD_LEN(hw, USER_BAP, HERMES_RID_CNF_PRISM2_KEY0, &keybuf, keylen); + err = hermes_write_ltv(hw, USER_BAP, + HERMES_RID_CNF_PRISM2_KEY0 + i, + HERMES_BYTES_TO_RECLEN(keylen + 1), + &keybuf); if (err) return err; } - /* Symbol cards : set the authentication : - * 0 -> no encryption, 1 -> open, - * 2 -> shared key, 3 -> shared key 128bit only */ + + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PRISM2_TX_KEY, + priv->tx_key); + if (err) + return err; + + /* Authentication is where Prism2 and Symbol + * firmware differ... */ if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) { - err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_AUTH_TYPE, priv->wep_auth); + /* Symbol cards : set the authentication : + * 0 -> no encryption, 1 -> open, + * 2 -> shared key, 3 -> shared key 128bit */ + if(priv->wep_restrict) { + if(priv->keys[priv->tx_key].len > + SMALL_KEY_SIZE) + extra_wep_flag = 3; + else + extra_wep_flag = 2; + } else + extra_wep_flag = 1; + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_AUTH_TYPE, priv->wep_restrict); if (err) return err; + } else { + /* Prism2 card : we need to modify master + * WEP setting */ + if(priv->wep_restrict) + extra_wep_flag = 2; + else + extra_wep_flag = 0; } } - err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PRISM2_WEP_ON, priv->wep_on); + /* Master WEP setting : on/off */ + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PRISM2_WEP_ON, (priv->wep_on | extra_wep_flag)); if (err) return err; break; @@ -1266,6 +1321,7 @@ static int dldwd_init(struct net_device } firmver = ((uint32_t)priv->firmware_info.major << 16) | priv->firmware_info.minor; + DEBUG(2, "%s: firmver = 0x%X\n", dev->name, firmver); /* Determine capabilities from the firmware version */ @@ -1279,7 +1335,7 @@ static int dldwd_init(struct net_device priv->firmware_type = FIRMWARE_TYPE_LUCENT; priv->broken_reset = 0; priv->broken_allocate = 0; - priv->has_port3 = 1; + priv->has_port3 = 1; /* Still works in 7.28 */ priv->has_ibss = (firmver >= 0x60006); priv->has_ibss_any = (firmver >= 0x60010); priv->has_wep = (firmver >= 0x40020); @@ -1288,27 +1344,51 @@ static int dldwd_init(struct net_device priv->has_mwo = (firmver >= 0x60000); priv->has_pm = (firmver >= 0x40020); priv->has_retry = 0; + priv->has_preamble = 0; /* Tested with Lucent firmware : - * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 => Jean II + * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II * Tested CableTron firmware : 4.32 => Anton */ break; case 0x2: vendor_str = "Generic Prism II"; - /* Note : my Intel card report this value, but I can't do - * much with it, so I guess it's broken - Jean II */ + /* Some D-Link cards report vendor 0x02... */ priv->firmware_type = FIRMWARE_TYPE_PRISM2; priv->broken_reset = 0; - priv->broken_allocate = (firmver <= 0x10001); + priv->broken_allocate = 0; priv->has_port3 = 1; - priv->has_ibss = 0; /* FIXME: no idea if this is right */ - priv->has_wep = (firmver >= 0x20000); - priv->has_big_wep = 1; + priv->has_ibss = (firmver >= 0x00007); /* FIXME */ + priv->has_wep = (firmver >= 0x00007); /* FIXME */ + priv->has_big_wep = 0; priv->has_mwo = 0; - priv->has_pm = (firmver >= 0x20000); + priv->has_pm = (firmver >= 0x00007); /* FIXME */ priv->has_retry = 0; - /* Tested with Intel firmware : 1.01 => Jean II */ - /* Note : firmware 1.01 is *seriously* broken */ + priv->has_preamble = 0; + + /* Tim Hurley -> D-Link card, vendor 02, firmware 0.08 */ + + /* Special case for Symbol cards */ + if(firmver == 0x10001) { + /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */ + vendor_str = "Symbol"; + /* Intel MAC : 00:02:B3:* */ + /* 3Com MAC : 00:50:DA:* */ + + /* FIXME : probably need to use SYMBOL_***ARY_VER + * to get proper firmware version */ + priv->firmware_type = FIRMWARE_TYPE_SYMBOL; + priv->broken_reset = 0; + priv->broken_allocate = 1; + priv->has_port3 = 1; + priv->has_ibss = 1; /* FIXME */ + priv->has_wep = 1; /* FIXME */ + priv->has_big_wep = 1; /* RID_SYMBOL_KEY_LENGTH */ + priv->has_mwo = 0; + priv->has_pm = 1; /* FIXME */ + priv->has_retry = 0; + priv->has_preamble = 0; /* FIXME */ + /* Tested with Intel firmware : v15 => Jean II */ + } break; case 0x3: vendor_str = "Samsung"; @@ -1324,39 +1404,27 @@ static int dldwd_init(struct net_device priv->has_mwo = 0; priv->has_pm = (firmver >= 0x20000); /* FIXME */ priv->has_retry = 0; + priv->has_preamble = 0; break; case 0x6: + /* D-Link DWL 650, ... */ vendor_str = "LinkSys/D-Link"; - /* To check */ + /* D-Link MAC : 00:40:05:* */ priv->firmware_type = FIRMWARE_TYPE_PRISM2; priv->broken_reset = 0; priv->broken_allocate = 0; priv->has_port3 = 1; - priv->has_ibss = 0; /* FIXME: available in later firmwares */ - priv->has_wep = (firmver >= 0x20000); /* FIXME */ + priv->has_ibss = (firmver >= 0x00007); /* FIXME */ + priv->has_wep = (firmver >= 0x00007); /* FIXME */ priv->has_big_wep = 0; priv->has_mwo = 0; - priv->has_pm = (firmver >= 0x20000); /* FIXME */ + priv->has_pm = (firmver >= 0x00007); /* FIXME */ priv->has_retry = 0; + priv->has_preamble = 0; + /* Tested with D-Link firmware 0.07 => Jean II */ + /* Note : with 0.07, IBSS to a Lucent card seem flaky */ break; -#if 0 - case 0x???: /* Could someone help here ??? */ - vendor_str = "Symbol"; - /* Symbol , 3Com AirConnect, Ericsson WLAN */ - - priv->firmware_type = FIRMWARE_TYPE_SYMBOL; - priv->broken_reset = 0; - priv->broken_allocate = 0; - priv->has_port3 = 1; - priv->has_ibss = 0; /* FIXME: available in later firmwares */ - priv->has_wep = (firmver >= 0x20000); /* FIXME */ - priv->has_big_wep = 1; /* Probably RID_SYMBOL_KEY_LENGTH */ - priv->has_mwo = 0; - priv->has_pm = (firmver >= 0x20000); - priv->has_retry = 0; - break; -#endif default: vendor_str = "UNKNOWN"; @@ -1370,14 +1438,13 @@ static int dldwd_init(struct net_device priv->has_mwo = 0; priv->has_pm = 0; priv->has_retry = 0; + priv->has_preamble = 0; } printk(KERN_INFO "%s: Firmware ID %02X vendor 0x%x (%s) version %d.%02d\n", dev->name, priv->firmware_info.id, priv->firmware_info.vendor, vendor_str, priv->firmware_info.major, priv->firmware_info.minor); - if ((priv->broken_reset) || (priv->broken_allocate)) - printk(KERN_INFO "%s: Buggy firmware, please upgrade ASAP.\n", dev->name); if (priv->has_port3) printk(KERN_INFO "%s: Ad-hoc demo mode supported.\n", dev->name); if (priv->has_ibss) @@ -1388,7 +1455,7 @@ static int dldwd_init(struct net_device if (priv->has_big_wep) printk("\"128\"-bit key.\n"); else - printk("40-bit key."); + printk("40-bit key.\n"); } /* Get the MAC address */ @@ -1478,7 +1545,7 @@ static int dldwd_init(struct net_device goto out; } } - + /* Retry setup */ if (priv->has_retry) { err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORT_RETRY_LIMIT, &priv->retry_short); @@ -1494,6 +1561,13 @@ static int dldwd_init(struct net_device goto out; } + /* Preamble setup */ + if (priv->has_preamble) { + err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_PREAMBLE, &priv->preamble); + if (err) + goto out; + } + /* Set up the default configuration */ priv->iw_mode = IW_MODE_INFRA; /* By default use IEEE/IBSS ad-hoc mode if we have it */ @@ -1951,7 +2025,7 @@ static int dldwd_ioctl_setiwencode(struc int index = (erq->flags & IW_ENCODE_INDEX) - 1; int setindex = priv->tx_key; int enable = priv->wep_on; - int auth = priv->wep_auth; + int restricted = priv->wep_restrict; uint16_t xlen = 0; int err = 0; char keybuf[MAX_KEY_SIZE]; @@ -2013,16 +2087,11 @@ static int dldwd_ioctl_setiwencode(struc if (erq->flags & IW_ENCODE_DISABLED) enable = 0; - /* Only for symbol cards (so far) - Jean II */ + /* Only for Prism2 & Symbol cards (so far) - Jean II */ if (erq->flags & IW_ENCODE_OPEN) - auth = 1; + restricted = 0; if (erq->flags & IW_ENCODE_RESTRICTED) - auth = 2; /* If all key are 128 -> should be 3 ??? */ - /* Agree with master wep setting */ - if (enable == 0) - auth = 0; - else if(auth == 0) - auth = 1; /* Encryption require some authentication */ + restricted = 1; if (erq->pointer) { priv->keys[index].len = cpu_to_le16(xlen); @@ -2031,7 +2100,7 @@ static int dldwd_ioctl_setiwencode(struc } priv->tx_key = setindex; priv->wep_on = enable; - priv->wep_auth = auth; + priv->wep_restrict = restricted; out: dldwd_unlock(priv); @@ -2058,19 +2127,11 @@ static int dldwd_ioctl_getiwencode(struc erq->flags |= index + 1; /* Only for symbol cards - Jean II */ - if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) { - switch(priv->wep_auth) { - case 1: - erq->flags |= IW_ENCODE_OPEN; - break; - case 2: - case 3: + if (priv->firmware_type != FIRMWARE_TYPE_LUCENT) { + if(priv->wep_restrict) erq->flags |= IW_ENCODE_RESTRICTED; - break; - case 0: - default: - break; - } + else + erq->flags |= IW_ENCODE_OPEN; } xlen = le16_to_cpu(priv->keys[index].len); @@ -2691,6 +2752,10 @@ static int dldwd_ioctl_setport3(struct n err = -EINVAL; } + if (! err) + /* Actually update the mode we are using */ + set_port_type(priv); + dldwd_unlock(priv); return err; @@ -3036,7 +3101,13 @@ static int dldwd_ioctl(struct net_device 0, "set_port3" }, { SIOCDEVPRIVATE + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_port3" } + "get_port3" }, + { SIOCDEVPRIVATE + 0x4, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_preamble" }, + { SIOCDEVPRIVATE + 0x5, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_preamble" } }; err = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(privtab)); @@ -3080,6 +3151,46 @@ static int dldwd_ioctl(struct net_device err = dldwd_ioctl_getport3(dev, wrq); break; + case SIOCDEVPRIVATE + 0x4: /* set_preamble */ + DEBUG(1, "%s: SIOCDEVPRIVATE + 0x4 (set_preamble)\n", + dev->name); + if (! capable(CAP_NET_ADMIN)) { + err = -EPERM; + break; + } + + /* 802.11b has recently defined some short preamble. + * Basically, the Phy header has been reduced in size. + * This increase performance, especially at high rates + * (the preamble is transmitted at 1Mb/s), unfortunately + * this give compatibility troubles... - Jean II */ + if(priv->has_preamble) { + int val = *( (int *) wrq->u.name ); + + dldwd_lock(priv); + if(val) + priv->preamble = 1; + else + priv->preamble = 0; + dldwd_unlock(priv); + changed = 1; + } else + err = -EOPNOTSUPP; + break; + + case SIOCDEVPRIVATE + 0x5: /* get_preamble */ + DEBUG(1, "%s: SIOCDEVPRIVATE + 0x5 (get_preamble)\n", + dev->name); + if(priv->has_preamble) { + int *val = (int *)wrq->u.name; + + dldwd_lock(priv); + *val = priv->preamble; + dldwd_unlock(priv); + } else + err = -EOPNOTSUPP; + break; + default: err = -EOPNOTSUPP; } @@ -3756,6 +3867,44 @@ static void dldwd_detach(dev_link_t * li TRACE_EXIT("dldwd"); } /* dldwd_detach */ +/* + * Do a soft reset of the Pcmcia card using the Configuration Option Register + * Can't do any harm, and actually may do some good on some cards... + */ +static int dldwd_cor_reset(dev_link_t *link) +{ + conf_reg_t reg; + u_long default_cor; + + /* Save original COR value */ + reg.Function = 0; + reg.Action = CS_READ; + reg.Offset = CISREG_COR; + reg.Value = 0; + CardServices(AccessConfigurationRegister, link->handle, ®); + default_cor = reg.Value; + + DEBUG(2, "dldwd : dldwd_cor_reset() : cor=0x%lX\n", default_cor); + + /* Soft-Reset card */ + reg.Action = CS_WRITE; + reg.Offset = CISREG_COR; + reg.Value = (default_cor | COR_SOFT_RESET); + CardServices(AccessConfigurationRegister, link->handle, ®); + + /* Wait until the card has acknowledged our reset */ + mdelay(1); + + /* Restore original COR configuration index */ + reg.Value = (default_cor & COR_CONFIG_MASK); + CardServices(AccessConfigurationRegister, link->handle, ®); + + /* Wait until the card has finished restarting */ + mdelay(1); + + return(0); +} + /*====================================================================== dldwd_config() is scheduled to run after a CARD_INSERTION event is received, to configure the PCMCIA socket, and to make the @@ -3779,6 +3928,7 @@ static void dldwd_config(dev_link_t * li int last_fn, last_ret; u_char buf[64]; config_info_t conf; + cistpl_cftable_entry_t dflt = { 0 }; cisinfo_t info; TRACE_ENTER("dldwd"); @@ -3825,7 +3975,6 @@ static void dldwd_config(dev_link_t * li tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, handle, &tuple); while (1) { - cistpl_cftable_entry_t dflt = { 0 }; cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); CFG_CHECK(GetTupleData, handle, &tuple); CFG_CHECK(ParseTuple, handle, &tuple, &parse); @@ -3849,12 +3998,16 @@ static void dldwd_config(dev_link_t * li /* Note that the CIS values need to be rescaled */ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { if (conf.Vcc != - cfg->vcc.param[CISTPL_POWER_VNOM] / - 10000) goto next_entry; + cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) { + DEBUG(2, "dldwd_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); + goto next_entry; + } } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { if (conf.Vcc != - dflt.vcc.param[CISTPL_POWER_VNOM] / - 10000) goto next_entry; + dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) { + DEBUG(2, "dldwd_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000); + goto next_entry; + } } if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) @@ -3945,12 +4098,12 @@ static void dldwd_config(dev_link_t * li ndev->base_addr = link->io.BasePort1; ndev->irq = link->irq.AssignedIRQ; - /* Instance name : by default, use hermesX, on demand use the - * regular ethX (less risky) - Jean II */ - if(!eth) - sprintf(ndev->name, "hermes%d", priv->instance); - else - ndev->name[0] = '\0'; + /* Do a Pcmcia soft reset of the card (optional) */ + if(reset_cor) + dldwd_cor_reset(link); + + /* register_netdev will give us an ethX name */ + ndev->name[0] = '\0'; /* Tell the stack we exist */ if (register_netdev(ndev) != 0) { printk(KERN_ERR "orinoco_cs: register_netdev() failed\n");