o wl3501: reorganization

. use enun instead of tons of #defines
. put the initial smp locking, still commented out
. use some defines for magic numbers
. break the rx_interrupt routine in multiple inlines for each signal
  type
. CodingStyle cleanups
. Activated the stupid loop, will now try without it, works? kill this
  stupidity
parent 8d7cfde3
#ifndef __WL3501_H__ #ifndef __WL3501_H__
#define __WL3501_H__ #define __WL3501_H__
#include <linux/spinlock.h>
#define WL3501_SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80") #define WL3501_SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80")
/* define for WLA 2.0 */ /* define for WLA 2.0 */
...@@ -11,77 +13,91 @@ ...@@ -11,77 +13,91 @@
* bit[7-5] is block ID: 000 * bit[7-5] is block ID: 000
* bit[4-0] is signal ID * bit[4-0] is signal ID
*/ */
#define WL3501_Alarm 0x00 enum wl3501_signals {
#define WL3501_MdConfirm 0x01 WL3501_SIG_ALARM,
#define WL3501_MdIndicate 0x02 WL3501_SIG_MD_CONFIRM,
#define WL3501_AssocConfirm 0x03 WL3501_SIG_MD_IND,
#define WL3501_AssocIndicate 0x04 WL3501_SIG_ASSOC_CONFIRM,
#define WL3501_AutheConfirm 0x05 WL3501_SIG_ASSOC_IND,
#define WL3501_AutheIndicate 0x06 WL3501_SIG_AUTH_CONFIRM,
#define WL3501_DeautheConfirm 0x07 WL3501_SIG_AUTH_IND,
#define WL3501_DeautheIndicate 0x08 WL3501_SIG_DEAUTH_CONFIRM,
#define WL3501_DisassocConfirm 0x09 WL3501_SIG_DEAUTH_IND,
#define WL3501_DisassocIndicate 0x0A WL3501_SIG_DISASSOC_CONFIRM,
#define WL3501_GetConfirm 0x0B WL3501_SIG_DISASSOC_IND,
#define WL3501_JoinConfirm 0x0C WL3501_SIG_GET_CONFIRM,
#define WL3501_PowermgtConfirm 0x0D WL3501_SIG_JOIN_CONFIRM,
#define WL3501_ReassocConfirm 0x0E WL3501_SIG_POWERMGT_CONFIRM,
#define WL3501_ReassocIndicate 0x0F WL3501_SIG_REASSOC_CONFIRM,
#define WL3501_ScanConfirm 0x10 WL3501_SIG_REASSOC_IND,
#define WL3501_SetConfirm 0x11 WL3501_SIG_SCAN_CONFIRM,
#define WL3501_StartConfirm 0x12 WL3501_SIG_SET_CONFIRM,
#define WL3501_ResyncConfirm 0x13 WL3501_SIG_START_CONFIRM,
#define WL3501_SiteConfirm 0x14 WL3501_SIG_RESYNC_CONFIRM,
#define WL3501_SaveConfirm 0x15 WL3501_SIG_SITE_CONFIRM,
#define WL3501_RFtestConfirm 0x16 WL3501_SIG_SAVE_CONFIRM,
WL3501_SIG_RFTEST_CONFIRM,
/* /*
* ID for input Signals of MLME block * ID for input Signals of MLME block
* bit[7-5] is block ID: 010 * bit[7-5] is block ID: 010
* bit[4-0] is signal ID * bit[4-0] is signal ID
*/ */
#define WL3501_AssocRequest 0x20 WL3501_SIG_ASSOC_REQ = 0x20,
#define WL3501_AutheRequest 0x21 WL3501_SIG_AUTH_REQ,
#define WL3501_DeautheRequest 0x22 WL3501_SIG_DEAUTH_REQ,
#define WL3501_DisassocRequest 0x23 WL3501_SIG_DISASSOC_REQ,
#define WL3501_GetRequest 0x24 WL3501_SIG_GET_REQ,
#define WL3501_JoinRequest 0x25 WL3501_SIG_JOIN_REQ,
#define WL3501_PowermgtRequest 0x26 WL3501_SIG_POWERMGT_REQ,
#define WL3501_ReassocRequest 0x27 WL3501_SIG_REASSOC_REQ,
#define WL3501_ScanRequest 0x28 WL3501_SIG_SCAN_REQ,
#define WL3501_SetRequest 0x29 WL3501_SIG_SET_REQ,
#define WL3501_StartRequest 0x2A WL3501_SIG_START_REQ,
#define WL3501_MdRequest 0x2B WL3501_SIG_MD_REQ,
#define WL3501_ResyncRequest 0x2C WL3501_SIG_RESYNC_REQ,
#define WL3501_SiteRequest 0x2D WL3501_SIG_SITE_REQ,
#define WL3501_SaveRequest 0x2E WL3501_SIG_SAVE_REQ,
#define WL3501_RFtestRequest 0x2F WL3501_SIG_RF_TEST_REQ,
WL3501_SIG_MM_CONFIRM = 0x60,
#define WL3501_MmConfirm 0x60 WL3501_SIG_MM_IND,
#define WL3501_MmIndicate 0x61 };
#define WL3501_Infrastructure 0 enum wl3501_net_type {
#define WL3501_Independent 1 WL3501_NET_TYPE_INFRASTRUCTURE,
#define WL3501_Any_bss 2 WL3501_NET_TYPE_INDEPENDENT,
#define WL3501_ActiveScan 0 WL3501_NET_TYPE_ANY_BSS,
#define WL3501_PassiveScan 1 };
#define WL3501_TxResult_Success 0
#define WL3501_TxResult_NoBss 1 enum wl3501_scan_type {
#define WL3501_TxResult_retryLimit 2 WL3501_SCAN_TYPE_ACTIVE,
WL3501_SCAN_TYPE_PASSIVE,
#define WL3501_Open_System 0 };
#define WL3501_Share_Key 1
enum wl3501_tx_result {
#define EtherII 0 WL3501_TX_RESULT_SUCCESS,
#define Ether802_3e 1 WL3501_TX_RESULT_NO_BSS,
#define Ether802_3f 2 WL3501_TX_RESULT_RETRY_LIMIT,
};
#define WL3501_STATUS_SUCCESS 0
#define WL3501_STATUS_INVALID 1 enum wl3501_sys_type {
#define WL3501_STATUS_TIMEOUT 2 WL3501_SYS_TYPE_OPEN,
#define WL3501_STATUS_REFUSED 3 WL3501_SYS_TYPE_SHARE_KEY,
#define WL3501_STATUS_MANYREQ 4 };
#define WL3501_STATUS_ALREADYBSS 5
enum wl3501_pkt_type {
WL3501_PKT_TYPE_ETHERII,
WL3501_PKT_TYPE_ETHER802_3E,
WL3501_PKT_TYPE_ETHER802_3F,
};
enum wl3501_status {
WL3501_STATUS_SUCCESS,
WL3501_STATUS_INVALID,
WL3501_STATUS_TIMEOUT,
WL3501_STATUS_REFUSED,
WL3501_STATUS_MANY_REQ,
WL3501_STATUS_ALREADY_BSS,
};
#define WL3501_FREQ_DOMAIN_FCC 0x10 /* Channel 1 to 11 */ #define WL3501_FREQ_DOMAIN_FCC 0x10 /* Channel 1 to 11 */
#define WL3501_FREQ_DOMAIN_IC 0x20 /* Channel 1 to 11 */ #define WL3501_FREQ_DOMAIN_IC 0x20 /* Channel 1 to 11 */
...@@ -91,216 +107,216 @@ ...@@ -91,216 +107,216 @@
#define WL3501_FREQ_DOMAIN_MKK 0x40 /* Channel 14 */ #define WL3501_FREQ_DOMAIN_MKK 0x40 /* Channel 14 */
struct wl3501_tx_hdr { struct wl3501_tx_hdr {
u16 tx_cnt; u16 tx_cnt;
unsigned char sync[16]; unsigned char sync[16];
u16 sfd; u16 sfd;
unsigned char signal; unsigned char signal;
unsigned char service; unsigned char service;
u16 len; u16 len;
u16 crc16; u16 crc16;
u16 frame_ctrl; u16 frame_ctrl;
u16 duration_id; u16 duration_id;
unsigned char addr1[6]; unsigned char addr1[ETH_ALEN];
unsigned char addr2[6]; unsigned char addr2[ETH_ALEN];
unsigned char addr3[6]; unsigned char addr3[ETH_ALEN];
u16 seq_ctrl; u16 seq_ctrl;
unsigned char addr4[6]; unsigned char addr4[ETH_ALEN];
}; };
struct wl3501_rx_hdr { struct wl3501_rx_hdr {
u16 rx_next_blk; u16 rx_next_blk;
u16 rc_next_frame_blk; u16 rc_next_frame_blk;
unsigned char rx_blk_ctrl; unsigned char rx_blk_ctrl;
unsigned char rx_next_frame; unsigned char rx_next_frame;
unsigned char rx_next_frame1; unsigned char rx_next_frame1;
unsigned char rssi; unsigned char rssi;
unsigned char time[8]; unsigned char time[8];
unsigned char signal; unsigned char signal;
unsigned char service; unsigned char service;
u16 len; u16 len;
u16 crc16; u16 crc16;
u16 frame_ctrl; u16 frame_ctrl;
u16 duration; u16 duration;
unsigned char addr1[6]; unsigned char addr1[ETH_ALEN];
unsigned char addr2[6]; unsigned char addr2[ETH_ALEN];
unsigned char addr3[6]; unsigned char addr3[ETH_ALEN];
u16 seq; u16 seq;
unsigned char addr4[6]; unsigned char addr4[ETH_ALEN];
}; };
struct wl3501_start_req { struct wl3501_start_req {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
unsigned char bss_type; unsigned char bss_type;
u16 beacon_period; u16 beacon_period;
u16 dtim_period; u16 dtim_period;
u16 probe_delay; u16 probe_delay;
u16 cap_info; u16 cap_info;
unsigned char ssid[34]; unsigned char ssid[34];
unsigned char bss_basic_rate_set[10]; unsigned char bss_basic_rate_set[10];
unsigned char operational_rate_set[10]; unsigned char operational_rate_set[10];
unsigned char cf_pset[8]; unsigned char cf_pset[8];
unsigned char phy_pset[3]; unsigned char phy_pset[3];
unsigned char ibss_pset[4]; unsigned char ibss_pset[4];
}; };
struct wl3501_assoc_req { struct wl3501_assoc_req {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
unsigned char reserved; unsigned char reserved;
u16 timeout; u16 timeout;
u16 cap_info; u16 cap_info;
u16 listen_interval; u16 listen_interval;
unsigned char mac_addr[6]; unsigned char mac_addr[ETH_ALEN];
}; };
struct wl3501_assoc_conf { struct wl3501_assoc_confirm {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
unsigned char reserved; unsigned char reserved;
u16 status; u16 status;
}; };
struct wl3501_assoc_ind { struct wl3501_assoc_ind {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
unsigned char mac_addr[6]; unsigned char mac_addr[ETH_ALEN];
}; };
struct wl3501_auth_req { struct wl3501_auth_req {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
unsigned char reserved; unsigned char reserved;
u16 type; u16 type;
u16 timeout; u16 timeout;
unsigned char mac_addr[6]; unsigned char mac_addr[ETH_ALEN];
}; };
struct wl3501_auth_conf { struct wl3501_auth_confirm {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
unsigned char reserved; unsigned char reserved;
u16 Type; u16 type;
u16 status; u16 status;
unsigned char mac_addr[6]; unsigned char mac_addr[ETH_ALEN];
}; };
struct wl3501_get_conf { struct wl3501_get_confirm {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
unsigned char reserved; unsigned char reserved;
u16 mib_status; u16 mib_status;
u16 mib_attrib; u16 mib_attrib;
unsigned char mib_value[100]; unsigned char mib_value[100];
}; };
struct wl3501_join_req { struct wl3501_join_req {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
unsigned char reserved; unsigned char reserved;
unsigned char operational_rate_set[10]; unsigned char operational_rate_set[10];
u16 reserved2; u16 reserved2;
u16 timeout; u16 timeout;
u16 probe_delay; u16 probe_delay;
unsigned char timestamp[8]; unsigned char timestamp[8];
unsigned char local_time[8]; unsigned char local_time[8];
u16 beacon_period; u16 beacon_period;
u16 dtim_period; u16 dtim_period;
u16 cap_info; u16 cap_info;
unsigned char bss_type; unsigned char bss_type;
unsigned char bssid[6]; unsigned char bssid[ETH_ALEN];
unsigned char ssid[34]; unsigned char ssid[34];
unsigned char phy_pset[3]; unsigned char phy_pset[3];
unsigned char cf_pset[8]; unsigned char cf_pset[8];
unsigned char ibss_pset[4]; unsigned char ibss_pset[4];
unsigned char bss_basic_rate_set[10]; unsigned char bss_basic_rate_set[10];
}; };
struct wl3501_join_conf { struct wl3501_join_confirm {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
unsigned char reserved; unsigned char reserved;
u16 status; u16 status;
}; };
struct wl3501_scan_req { struct wl3501_scan_req {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
unsigned char bss_type; unsigned char bss_type;
u16 probe_delay; u16 probe_delay;
u16 min_chan_time; u16 min_chan_time;
u16 max_chan_time; u16 max_chan_time;
unsigned char chan_list[14]; unsigned char chan_list[14];
unsigned char bssid[6]; unsigned char bssid[ETH_ALEN];
unsigned char ssid[34]; unsigned char ssid[34];
unsigned char scan_type; enum wl3501_scan_type scan_type;
}; };
struct wl3501_scan_conf { struct wl3501_scan_confirm {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
unsigned char reserved; unsigned char reserved;
u16 status; u16 status;
unsigned char timestamp[8]; unsigned char timestamp[8];
unsigned char localtime[8]; unsigned char localtime[8];
u16 beacon_period; u16 beacon_period;
u16 dtim_period; u16 dtim_period;
u16 cap_info; u16 cap_info;
unsigned char bss_type; unsigned char bss_type;
unsigned char bssid[6]; unsigned char bssid[ETH_ALEN];
unsigned char ssid[34]; unsigned char ssid[34];
unsigned char phy_pset[3]; unsigned char phy_pset[3];
unsigned char cf_pset[8]; unsigned char cf_pset[8];
unsigned char ibss_pset[4]; unsigned char ibss_pset[4];
unsigned char bss_basic_rate_set[10]; unsigned char bss_basic_rate_set[10];
unsigned char rssi; unsigned char rssi;
}; };
struct wl3501_start_conf { struct wl3501_start_confirm {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
unsigned char reserved; unsigned char reserved;
u16 status; u16 status;
}; };
struct wl3501_md_req { struct wl3501_md_req {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
unsigned char routing; unsigned char routing;
u16 data; u16 data;
u16 size; u16 size;
unsigned char pri; unsigned char pri;
unsigned char service_class; unsigned char service_class;
unsigned char daddr[6]; unsigned char daddr[ETH_ALEN];
unsigned char saddr[6]; unsigned char saddr[ETH_ALEN];
}; };
struct wl3501_md_ind { struct wl3501_md_ind {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
unsigned char routing; unsigned char routing;
u16 data; u16 data;
u16 size; u16 size;
unsigned char reception; unsigned char reception;
unsigned char pri; unsigned char pri;
unsigned char service_class; unsigned char service_class;
unsigned char daddr[6]; unsigned char daddr[ETH_ALEN];
unsigned char saddr[6]; unsigned char saddr[ETH_ALEN];
}; };
struct wl3501_md_conf { struct wl3501_md_confirm {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
unsigned char reserved; unsigned char reserved;
u16 data; u16 data;
unsigned char status; unsigned char status;
unsigned char pri; unsigned char pri;
unsigned char service_class; unsigned char service_class;
}; };
struct wl3501_resync_req { struct wl3501_resync_req {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
}; };
/* For rough constant delay */ /* For rough constant delay */
...@@ -310,12 +326,7 @@ struct wl3501_resync_req { ...@@ -310,12 +326,7 @@ struct wl3501_resync_req {
/* With this, we may simply write "x=y;" instead of "memcpy(x, y, 6);" */ /* With this, we may simply write "x=y;" instead of "memcpy(x, y, 6);" */
/* It's more efficiency with compiler's optimization and more clearly */ /* It's more efficiency with compiler's optimization and more clearly */
struct wl3501_mac_addr { struct wl3501_mac_addr {
u8 b0; u8 b0, b1, b2, b3, b4, b5;
u8 b1;
u8 b2;
u8 b3;
u8 b4;
u8 b5;
} __attribute__ ((packed)); } __attribute__ ((packed));
/* Definitions for supporting clone adapters. */ /* Definitions for supporting clone adapters. */
...@@ -354,12 +365,12 @@ struct wl3501_mac_addr { ...@@ -354,12 +365,12 @@ struct wl3501_mac_addr {
/* Tx packet header, include PLCP and MPDU */ /* Tx packet header, include PLCP and MPDU */
/* Tx PLCP Header */ /* Tx PLCP Header */
struct wl3501_80211_tx_plcp_hdr { struct wl3501_80211_tx_plcp_hdr {
u8 sync[16]; u8 sync[16];
u16 sfd; u16 sfd;
u8 signal; u8 signal;
u8 service; u8 service;
u16 len; u16 len;
u16 crc16; u16 crc16;
} __attribute__ ((packed)); } __attribute__ ((packed));
/* /*
...@@ -367,17 +378,17 @@ struct wl3501_80211_tx_plcp_hdr { ...@@ -367,17 +378,17 @@ struct wl3501_80211_tx_plcp_hdr {
* FIXME: try to use ieee_802_11_header (see linux/802_11.h) * FIXME: try to use ieee_802_11_header (see linux/802_11.h)
*/ */
struct wl3501_80211_data_mac_hdr { struct wl3501_80211_data_mac_hdr {
u16 frame_ctrl; u16 frame_ctrl;
u16 duration_id; u16 duration_id;
struct wl3501_mac_addr addr1; struct wl3501_mac_addr addr1;
struct wl3501_mac_addr addr2; struct wl3501_mac_addr addr2;
struct wl3501_mac_addr addr3; struct wl3501_mac_addr addr3;
u16 seq_ctrl; u16 seq_ctrl;
struct wl3501_mac_addr addr4; struct wl3501_mac_addr addr4;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct wl3501_80211_tx_hdr { struct wl3501_80211_tx_hdr {
struct wl3501_80211_tx_plcp_hdr pclp_hdr; struct wl3501_80211_tx_plcp_hdr pclp_hdr;
struct wl3501_80211_data_mac_hdr mac_hdr; struct wl3501_80211_data_mac_hdr mac_hdr;
} __attribute__ ((packed)); } __attribute__ ((packed));
...@@ -402,65 +413,72 @@ struct wl3501_80211_tx_hdr { ...@@ -402,65 +413,72 @@ struct wl3501_80211_tx_hdr {
*/ */
struct wl3501_card { struct wl3501_card {
int base_addr; int base_addr;
struct wl3501_mac_addr mac_addr; struct wl3501_mac_addr mac_addr;
u16 tx_buffer_size; spinlock_t lock;
u16 tx_buffer_head; u16 tx_buffer_size;
u16 tx_buffer_tail; u16 tx_buffer_head;
u16 tx_buffer_cnt; u16 tx_buffer_tail;
u16 esbq_req_start; u16 tx_buffer_cnt;
u16 esbq_req_end; u16 esbq_req_start;
u16 esbq_req_head; u16 esbq_req_end;
u16 esbq_req_tail; u16 esbq_req_head;
u16 esbq_confirm_start; u16 esbq_req_tail;
u16 esbq_confirm_end; u16 esbq_confirm_start;
u16 esbq_confirm; u16 esbq_confirm_end;
struct wl3501_mac_addr bssid; u16 esbq_confirm;
u8 llc_type; struct wl3501_mac_addr bssid;
u8 net_type; u8 llc_type;
u8 essid[34]; enum wl3501_net_type net_type;
u8 keep_essid[34]; u8 essid[34];
u8 ether_type; u8 keep_essid[34];
u8 chan; u8 ether_type;
u8 def_chan; u8 chan;
u16 start_seg; u8 def_chan;
u16 bss_cnt; u16 start_seg;
u16 join_sta_bss; u16 bss_cnt;
u8 cap_info; u16 join_sta_bss;
u8 adhoc_times; u8 cap_info;
int card_start; u8 adhoc_times;
struct wl3501_scan_conf bss_set[20]; int card_start;
u8 driver_state; struct wl3501_scan_confirm bss_set[20];
u8 freq_domain; u8 driver_state;
u8 version[2]; u8 freq_domain;
struct net_device_stats stats; u8 version[2];
struct iw_statistics wstats; struct net_device_stats stats;
dev_node_t node; struct iw_statistics wstats;
struct dev_node_t node;
}; };
/* /**
* struct wl3501_ioctl_blk - ioctl block
* @cmd - Command to run
* @len - Length of the data buffer
* @data - Pointer to the data buffer
*
* wl3501_ioctl_blk is put into ifreq.ifr_data which is a union (16 bytes) * wl3501_ioctl_blk is put into ifreq.ifr_data which is a union (16 bytes)
* sizeof(wl3501_ioctl_blk) must be less than 16 bytes. * sizeof(wl3501_ioctl_blk) must be less than 16 bytes.
*/ */
struct wl3501_ioctl_blk { struct wl3501_ioctl_blk {
u16 cmd; /* Command to run */ u16 cmd;
u16 len; /* Length of the data buffer */ u16 len;
unsigned char *data; /* Pointer to the data buffer */ unsigned char *data;
}; };
struct wl3501_ioctl_parm { struct wl3501_ioctl_parm {
u8 def_chan; u8 def_chan;
u8 chan; u8 chan;
u8 net_type; enum wl3501_net_type net_type;
u8 essid[34]; u8 essid[34];
u8 keep_essid[34]; u8 keep_essid[34];
u8 version[2]; u8 version[2];
u8 freq_domain; u8 freq_domain;
}; };
#define WL3501_IOCTL_GET_PARAMETER 0 /* Get parameter */ enum wl3501_ioctl_cmd {
#define WL3501_IOCTL_SET_PARAMETER 1 /* Get parameter */ WL3501_IOCTL_CMD_GET_PARAMETER,
#define WL3501_IOCTL_WRITE_FLASH 2 /* Write firmware into Flash ROM */ WL3501_IOCTL_CMD_SET_PARAMETER,
#define WL3501_IOCTL_SET_RESET 3 /* Reset the firmware */ WL3501_IOCTL_CMD_WRITE_FLASH,
WL3501_IOCTL_CMD_SET_RESET,
#endif /* __WL3501_H__ */ };
#endif
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
* but it can then be enabled for specific modules at load time with a * but it can then be enabled for specific modules at load time with a
* 'pc_debug=#' option to insmod. * 'pc_debug=#' option to insmod.
*/ */
//#define PCMCIA_DEBUG 100 #define PCMCIA_DEBUG 0
#ifdef PCMCIA_DEBUG #ifdef PCMCIA_DEBUG
static int pc_debug = PCMCIA_DEBUG; static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i"); MODULE_PARM(pc_debug, "i");
...@@ -75,13 +75,20 @@ MODULE_PARM(pc_debug, "i"); ...@@ -75,13 +75,20 @@ MODULE_PARM(pc_debug, "i");
#define dprintk(n, format, args...) #define dprintk(n, format, args...)
#endif #endif
static u8 wl3501_fpage[] = { WL3501_BSS_FPAGE0, WL3501_BSS_FPAGE1, static u8 wl3501_fpage[] = {
WL3501_BSS_FPAGE2, WL3501_BSS_FPAGE3 }; [0] = WL3501_BSS_FPAGE0,
[1] = WL3501_BSS_FPAGE1,
[2] = WL3501_BSS_FPAGE2,
[3] = WL3501_BSS_FPAGE3,
};
#define wl3501_outb(a, b) { outb(a, b); WL3501_SLOW_DOWN_IO; } #define wl3501_outb(a, b) { outb(a, b); WL3501_SLOW_DOWN_IO; }
#define wl3501_outb_p(a, b) { outb_p(a, b); WL3501_SLOW_DOWN_IO; } #define wl3501_outb_p(a, b) { outb_p(a, b); WL3501_SLOW_DOWN_IO; }
#define wl3501_outsb(a, b, c) { outsb(a, b, c); WL3501_SLOW_DOWN_IO; } #define wl3501_outsb(a, b, c) { outsb(a, b, c); WL3501_SLOW_DOWN_IO; }
#define WL3501_RELEASE_TIMEOUT (25 * HZ)
#define WL3501_MAX_ADHOC_TRIES 16
/* Parameters that can be set with 'insmod' */ /* Parameters that can be set with 'insmod' */
/* Bit map of interrupts to choose from */ /* Bit map of interrupts to choose from */
/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */ /* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
...@@ -92,7 +99,7 @@ MODULE_PARM(wl3501_irq_mask, "i"); ...@@ -92,7 +99,7 @@ MODULE_PARM(wl3501_irq_mask, "i");
MODULE_PARM(wl3501_irq_list, "1-4i"); MODULE_PARM(wl3501_irq_list, "1-4i");
MODULE_AUTHOR("Fox Chen <mhchen@golf.ccl.itri.org.tw>, " MODULE_AUTHOR("Fox Chen <mhchen@golf.ccl.itri.org.tw>, "
"Arnaldo Carvalho de Melo <acme@conectiva.com.br>," "Arnaldo Carvalho de Melo <acme@conectiva.com.br>,"
"Gustavo Niemeyer <niemeyer@conectiva.com.br>"); "Gustavo Niemeyer <niemeyer@conectiva.com>");
MODULE_DESCRIPTION("Planet wl3501 wireless driver"); MODULE_DESCRIPTION("Planet wl3501 wireless driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -523,31 +530,31 @@ static void wl3501_esbq_req(struct wl3501_card *this, u16 * ptr) ...@@ -523,31 +530,31 @@ static void wl3501_esbq_req(struct wl3501_card *this, u16 * ptr)
* data[6] - data[11] is Src MAC Addr) * data[6] - data[11] is Src MAC Addr)
* Ref: IEEE 802.11 * Ref: IEEE 802.11
*/ */
static int wl3501_send_pkt(struct wl3501_card *this, u8 * data, u16 len) static int wl3501_send_pkt(struct wl3501_card *this, u8 *data, u16 len)
{ {
u16 bf, sig, next, tmplen, pktlen, tmp; u16 bf, sig_bf, next, tmplen, pktlen, tmp;
struct wl3501_md_req signal; struct wl3501_md_req sig;
u8 *pdata = (char *)data; u8 *pdata = (char *)data;
if (wl3501_esbq_req_test(this)) { if (wl3501_esbq_req_test(this)) {
sig = wl3501_get_tx_buffer(this, sizeof(signal)); sig_bf = wl3501_get_tx_buffer(this, sizeof(sig));
if (!sig) /* No free buffer available */ if (!sig_bf) /* No free buffer available */
return 0; return -ENOMEM;
bf = wl3501_get_tx_buffer(this, len + 26 + 24); bf = wl3501_get_tx_buffer(this, len + 26 + 24);
if (!bf) { if (!bf) {
/* No free buffer available */ /* No free buffer available */
wl3501_free_tx_buffer(this, sig); wl3501_free_tx_buffer(this, sig_bf);
return 0; return -ENOMEM;
} }
memcpy((char *)&(signal.daddr[0]), pdata, 12); memcpy((char *)&(sig.daddr[0]), pdata, 12);
pktlen = len - 12; pktlen = len - 12;
pdata += 12; pdata += 12;
signal.next_blk = 0; sig.next_blk = 0;
signal.sig_id = WL3501_MdRequest; sig.sig_id = WL3501_SIG_MD_REQ;
signal.data = bf; sig.data = bf;
if (this->llc_type == 1) { if (this->llc_type == 1) {
if (((*pdata) * 256 + (*(pdata + 1))) > 1500) { if (((*pdata) * 256 + (*(pdata + 1))) > 1500) {
signal.size = pktlen + 24 + 4 + 6; sig.size = pktlen + 24 + 4 + 6;
tmp = 0xaaaa; tmp = 0xaaaa;
wl3501_set_to_wla(this, bf + 2 + wl3501_set_to_wla(this, bf + 2 +
sizeof(struct wl3501_tx_hdr) - sizeof(struct wl3501_tx_hdr) -
...@@ -577,7 +584,7 @@ static int wl3501_send_pkt(struct wl3501_card *this, u8 * data, u16 len) ...@@ -577,7 +584,7 @@ static int wl3501_send_pkt(struct wl3501_card *this, u8 * data, u16 len)
sizeof(next)); sizeof(next));
bf = next; bf = next;
} else { } else {
signal.size = pktlen + 24 + 4 - 2; sig.size = pktlen + 24 + 4 - 2;
pdata += 2; pdata += 2;
pktlen -= 2; pktlen -= 2;
if (pktlen > if (pktlen >
...@@ -599,7 +606,7 @@ static int wl3501_send_pkt(struct wl3501_card *this, u8 * data, u16 len) ...@@ -599,7 +606,7 @@ static int wl3501_send_pkt(struct wl3501_card *this, u8 * data, u16 len)
} }
} else { } else {
pktlen += 12; pktlen += 12;
signal.size = pktlen + 24 + 4; sig.size = pktlen + 24 + 4;
pdata -= 12; pdata -= 12;
if (pktlen > (254 - sizeof(struct wl3501_tx_hdr) + 6)) { if (pktlen > (254 - sizeof(struct wl3501_tx_hdr) + 6)) {
tmplen = 254 - sizeof(struct wl3501_tx_hdr) + 6; tmplen = 254 - sizeof(struct wl3501_tx_hdr) + 6;
...@@ -628,49 +635,51 @@ static int wl3501_send_pkt(struct wl3501_card *this, u8 * data, u16 len) ...@@ -628,49 +635,51 @@ static int wl3501_send_pkt(struct wl3501_card *this, u8 * data, u16 len)
wl3501_get_from_wla(this, bf, &next, sizeof(next)); wl3501_get_from_wla(this, bf, &next, sizeof(next));
bf = next; bf = next;
} }
wl3501_set_to_wla(this, sig, &signal, sizeof(signal)); wl3501_set_to_wla(this, sig_bf, &sig, sizeof(sig));
wl3501_esbq_req(this, &sig); wl3501_esbq_req(this, &sig_bf);
} }
return 1; return 0;
} }
static int wl3501_mgmt_resync(struct wl3501_card *this) static int wl3501_mgmt_resync(struct wl3501_card *this)
{ {
struct wl3501_resync_req signal; struct wl3501_resync_req signal;
u16 ptr; u16 ptr;
int rc = 1;
signal.next_blk = 0; signal.next_blk = 0;
signal.sig_id = WL3501_ResyncRequest; signal.sig_id = WL3501_SIG_RESYNC_REQ;
if (wl3501_esbq_req_test(this)) { if (wl3501_esbq_req_test(this)) {
ptr = wl3501_get_tx_buffer(this, sizeof(signal)); ptr = wl3501_get_tx_buffer(this, sizeof(signal));
if (ptr) { if (ptr) {
wl3501_set_to_wla(this, ptr, &signal, sizeof(signal)); wl3501_set_to_wla(this, ptr, &signal, sizeof(signal));
wl3501_esbq_req(this, &ptr); wl3501_esbq_req(this, &ptr);
return 1; rc = 0;
} }
} }
return 0; return rc;
} }
static int wl3501_mgmt_scan(struct wl3501_card *this, u16 chan_time) static int wl3501_mgmt_scan(struct wl3501_card *this, u16 chan_time)
{ {
struct wl3501_scan_req signal; struct wl3501_scan_req signal;
u16 ptr; u16 ptr;
int rc = 1;
signal.next_blk = 0; signal.next_blk = 0;
signal.sig_id = WL3501_ScanRequest; signal.sig_id = WL3501_SIG_SCAN_REQ;
signal.ssid[0] = 0; signal.ssid[0] = 0;
signal.ssid[1] = 0; signal.ssid[1] = 0;
signal.scan_type = WL3501_ActiveScan; signal.scan_type = WL3501_SCAN_TYPE_ACTIVE;
signal.probe_delay = 0x10; signal.probe_delay = 0x10;
signal.min_chan_time = chan_time; signal.min_chan_time = chan_time;
signal.max_chan_time = chan_time; signal.max_chan_time = chan_time;
if (this->net_type == WL3501_Infrastructure) if (this->net_type == WL3501_NET_TYPE_INFRASTRUCTURE)
signal.bss_type = WL3501_Infrastructure; signal.bss_type = WL3501_NET_TYPE_INFRASTRUCTURE;
else else
signal.bss_type = WL3501_Independent; signal.bss_type = WL3501_NET_TYPE_INDEPENDENT;
this->bss_cnt = this->join_sta_bss = 0; this->bss_cnt = this->join_sta_bss = 0;
...@@ -679,10 +688,10 @@ static int wl3501_mgmt_scan(struct wl3501_card *this, u16 chan_time) ...@@ -679,10 +688,10 @@ static int wl3501_mgmt_scan(struct wl3501_card *this, u16 chan_time)
if (ptr) { if (ptr) {
wl3501_set_to_wla(this, ptr, &signal, sizeof(signal)); wl3501_set_to_wla(this, ptr, &signal, sizeof(signal));
wl3501_esbq_req(this, &ptr); wl3501_esbq_req(this, &ptr);
return 1; rc = 0;
} }
} }
return 0; return rc;
} }
static int wl3501_mgmt_join(struct wl3501_card *this, u16 stas) static int wl3501_mgmt_join(struct wl3501_card *this, u16 stas)
...@@ -691,7 +700,7 @@ static int wl3501_mgmt_join(struct wl3501_card *this, u16 stas) ...@@ -691,7 +700,7 @@ static int wl3501_mgmt_join(struct wl3501_card *this, u16 stas)
u16 ptr; u16 ptr;
signal.next_blk = 0; signal.next_blk = 0;
signal.sig_id = WL3501_JoinRequest; signal.sig_id = WL3501_SIG_JOIN_REQ;
signal.timeout = 10; signal.timeout = 10;
memcpy((char *)&(signal.beacon_period), memcpy((char *)&(signal.beacon_period),
(char *)&(this->bss_set[stas].beacon_period), 72); (char *)&(this->bss_set[stas].beacon_period), 72);
...@@ -702,22 +711,23 @@ static int wl3501_mgmt_join(struct wl3501_card *this, u16 stas) ...@@ -702,22 +711,23 @@ static int wl3501_mgmt_join(struct wl3501_card *this, u16 stas)
if (ptr) { if (ptr) {
wl3501_set_to_wla(this, ptr, &signal, sizeof(signal)); wl3501_set_to_wla(this, ptr, &signal, sizeof(signal));
wl3501_esbq_req(this, &ptr); wl3501_esbq_req(this, &ptr);
return 1; return 0;
} }
} }
return 0; return 1;
} }
static int wl3501_mgmt_start(struct wl3501_card *this) static int wl3501_mgmt_start(struct wl3501_card *this)
{ {
struct wl3501_start_req signal; struct wl3501_start_req signal;
int rc = 1;
u16 ptr; u16 ptr;
signal.next_blk = 0; signal.next_blk = 0;
signal.sig_id = WL3501_StartRequest; signal.sig_id = WL3501_SIG_START_REQ;
memcpy((char *)signal.ssid, (char *)this->essid, 34); memcpy((char *)signal.ssid, (char *)this->essid, 34);
memcpy((char *)this->keep_essid, (char *)this->essid, 34); memcpy((char *)this->keep_essid, (char *)this->essid, 34);
signal.bss_type = WL3501_Independent; signal.bss_type = WL3501_NET_TYPE_INDEPENDENT;
signal.beacon_period = 400; signal.beacon_period = 400;
signal.dtim_period = 1; signal.dtim_period = 1;
signal.phy_pset[0] = 3; signal.phy_pset[0] = 3;
...@@ -741,36 +751,37 @@ static int wl3501_mgmt_start(struct wl3501_card *this) ...@@ -741,36 +751,37 @@ static int wl3501_mgmt_start(struct wl3501_card *this)
if (ptr) { if (ptr) {
wl3501_set_to_wla(this, ptr, &signal, sizeof(signal)); wl3501_set_to_wla(this, ptr, &signal, sizeof(signal));
wl3501_esbq_req(this, &ptr); wl3501_esbq_req(this, &ptr);
return 1; rc = 0;
} }
} }
return 0; return rc;
} }
#define WL3501_STUPID_LOOP
#ifdef WL3501_STUPID_LOOP #ifdef WL3501_STUPID_LOOP
#define wl3501_cmdloop(__cmd) \ #define wl3501_loop(__cmd) \
({ int i; \ ({ int i; \
for (i = 0; i < 3000; i++) \ for (i = 0; i < 3000; i++) \
if (__cmd) \ if (!__cmd) \
break; \ break; \
i != 3000; \ i == 3000; \
}) })
#else #else
#define wl3501_cmdloop(__cmd) ({ __cmd; 1; }) #define wl3501_loop(__cmd) ({ __cmd; 0; })
#endif #endif
static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr) static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr)
{ {
u16 i, j; u16 i, j;
int matchflag = 0; int matchflag = 0;
struct wl3501_scan_conf signal; struct wl3501_scan_confirm signal;
wl3501_get_from_wla(this, addr, &signal, sizeof(signal)); wl3501_get_from_wla(this, addr, &signal, sizeof(signal));
if (signal.status == WL3501_STATUS_SUCCESS) { if (signal.status == WL3501_STATUS_SUCCESS) {
if (this->driver_state == WL3501_ScanRequest) { if (this->driver_state == WL3501_SIG_SCAN_REQ) {
for (i = 0; i < this->bss_cnt; i++) { for (i = 0; i < this->bss_cnt; i++) {
if (!memcmp((char *)this->bss_set[i].bssid, if (!memcmp((char *)this->bss_set[i].bssid,
(char *)signal.bssid, 6)) (char *)signal.bssid, ETH_ALEN))
break; break;
} }
if ((i == this->bss_cnt) && i < 20) { if ((i == this->bss_cnt) && i < 20) {
...@@ -779,12 +790,12 @@ static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr) ...@@ -779,12 +790,12 @@ static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr)
(char *)&(signal.beacon_period), 73); (char *)&(signal.beacon_period), 73);
this->bss_cnt++; this->bss_cnt++;
} }
} else if (((this->net_type == WL3501_Infrastructure) && } else if ((this->net_type == WL3501_NET_TYPE_INFRASTRUCTURE &&
(signal.cap_info & 0x01)) || (signal.cap_info & 0x01)) ||
((this->net_type == WL3501_Independent) && (this->net_type == WL3501_NET_TYPE_INDEPENDENT &&
(signal.cap_info & 0x02)) || (signal.cap_info & 0x02)) ||
this->net_type == 2) { this->net_type == WL3501_NET_TYPE_ANY_BSS) {
if (this->essid[1] == 0) if (!this->essid[1])
matchflag = 1; matchflag = 1;
else if (this->essid[1] == 3 && else if (this->essid[1] == 3 &&
!strncmp((char *)&this->essid[2], "ANY", 3)) !strncmp((char *)&this->essid[2], "ANY", 3))
...@@ -799,9 +810,9 @@ static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr) ...@@ -799,9 +810,9 @@ static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr)
matchflag = 1; matchflag = 1;
if (matchflag) { if (matchflag) {
for (i = 0; i < this->bss_cnt; i++) { for (i = 0; i < this->bss_cnt; i++) {
if (memcmp if (!memcmp
((char *)this->bss_set[i].bssid, ((char *)this->bss_set[i].bssid,
(char *)signal.bssid, 6) == 0) { (char *)signal.bssid, ETH_ALEN)) {
matchflag = 0; matchflag = 0;
break; break;
} }
...@@ -814,28 +825,27 @@ static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr) ...@@ -814,28 +825,27 @@ static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr)
this->bss_cnt++; this->bss_cnt++;
} }
} }
} else if ((signal.status == WL3501_STATUS_TIMEOUT) && } else if (signal.status == WL3501_STATUS_TIMEOUT &&
(this->driver_state != WL3501_ScanRequest)) { this->driver_state != WL3501_SIG_SCAN_REQ) {
this->join_sta_bss = 0; this->join_sta_bss = 0;
for (j = this->join_sta_bss; j < this->bss_cnt; j++) for (j = this->join_sta_bss; j < this->bss_cnt; j++)
if (wl3501_cmdloop(wl3501_mgmt_join(this, j))) if (!wl3501_loop(wl3501_mgmt_join(this, j)))
break; break;
this->join_sta_bss = j; this->join_sta_bss = j;
if (this->join_sta_bss == this->bss_cnt) { if (this->join_sta_bss == this->bss_cnt) {
if (this->net_type == WL3501_Infrastructure) if (this->net_type == WL3501_NET_TYPE_INFRASTRUCTURE) {
wl3501_cmdloop(wl3501_mgmt_scan(this, 100)); wl3501_loop(wl3501_mgmt_scan(this, 100));
else { } else {
this->adhoc_times++; this->adhoc_times++;
if (this->adhoc_times > 8) if (this->adhoc_times > WL3501_MAX_ADHOC_TRIES)
wl3501_cmdloop(wl3501_mgmt_start(this)); wl3501_loop(wl3501_mgmt_start(this));
else else
wl3501_cmdloop(wl3501_mgmt_scan(this, 100)); wl3501_loop(wl3501_mgmt_scan(this,
100));
} }
} }
} }
} }
/** /**
...@@ -890,7 +900,7 @@ static u16 wl3501_receive(struct wl3501_card *this, u8 *bf, u16 size) ...@@ -890,7 +900,7 @@ static u16 wl3501_receive(struct wl3501_card *this, u8 *bf, u16 size)
wl3501_get_from_wla(this, this->start_seg + 2, wl3501_get_from_wla(this, this->start_seg + 2,
&next_addr, sizeof(next_addr)); &next_addr, sizeof(next_addr));
if (this->llc_type == 1) { if (this->llc_type == 1) {
if (this->ether_type == EtherII) { if (this->ether_type == WL3501_PKT_TYPE_ETHERII) {
if (size > if (size >
WL3501_BLKSZ - sizeof(struct wl3501_rx_hdr)) { WL3501_BLKSZ - sizeof(struct wl3501_rx_hdr)) {
wl3501_get_from_wla(this, this->start_seg + wl3501_get_from_wla(this, this->start_seg +
...@@ -1013,19 +1023,19 @@ static int wl3501_mgmt_auth(struct wl3501_card *this) ...@@ -1013,19 +1023,19 @@ static int wl3501_mgmt_auth(struct wl3501_card *this)
u16 ptr; u16 ptr;
signal.next_blk = 0; signal.next_blk = 0;
signal.sig_id = WL3501_AutheRequest; signal.sig_id = WL3501_SIG_AUTH_REQ;
signal.type = WL3501_Open_System; signal.type = WL3501_SYS_TYPE_OPEN;
signal.timeout = 1000; signal.timeout = 1000;
memcpy((char *)&(signal.mac_addr), (char *)&(this->bssid), 6); memcpy((char *)&(signal.mac_addr), (char *)&(this->bssid), ETH_ALEN);
if (wl3501_esbq_req_test(this)) { if (wl3501_esbq_req_test(this)) {
ptr = wl3501_get_tx_buffer(this, sizeof(signal)); ptr = wl3501_get_tx_buffer(this, sizeof(signal));
if (ptr) { if (ptr) {
wl3501_set_to_wla(this, ptr, &signal, sizeof(signal)); wl3501_set_to_wla(this, ptr, &signal, sizeof(signal));
wl3501_esbq_req(this, &ptr); wl3501_esbq_req(this, &ptr);
return 1; return 0;
} }
} }
return 0; return 1;
} }
static int wl3501_mgmt_association(struct wl3501_card *this) static int wl3501_mgmt_association(struct wl3501_card *this)
...@@ -1034,44 +1044,46 @@ static int wl3501_mgmt_association(struct wl3501_card *this) ...@@ -1034,44 +1044,46 @@ static int wl3501_mgmt_association(struct wl3501_card *this)
u16 ptr; u16 ptr;
signal.next_blk = 0; signal.next_blk = 0;
signal.sig_id = WL3501_AssocRequest; signal.sig_id = WL3501_SIG_ASSOC_REQ;
signal.timeout = 1000; signal.timeout = 1000;
signal.listen_interval = 5; signal.listen_interval = 5;
signal.cap_info = this->cap_info; signal.cap_info = this->cap_info;
memcpy((char *)&(signal.mac_addr), (char *)&(this->bssid), 6); memcpy((char *)&(signal.mac_addr), (char *)&(this->bssid), ETH_ALEN);
if (wl3501_esbq_req_test(this)) { if (wl3501_esbq_req_test(this)) {
ptr = wl3501_get_tx_buffer(this, sizeof(signal)); ptr = wl3501_get_tx_buffer(this, sizeof(signal));
if (ptr) { if (ptr) {
wl3501_set_to_wla(this, ptr, &signal, sizeof(signal)); wl3501_set_to_wla(this, ptr, &signal, sizeof(signal));
wl3501_esbq_req(this, &ptr); wl3501_esbq_req(this, &ptr);
return 1; return 0;
} }
} }
return 0; return 1;
} }
static void wl3501_mgmt_join_confirm(struct wl3501_card *this, u16 addr) static void wl3501_mgmt_join_confirm(struct net_device *dev,
struct wl3501_card *this, u16 addr)
{ {
u16 i, j; u16 i, j;
struct wl3501_join_conf signal; struct wl3501_join_confirm sig;
wl3501_get_from_wla(this, addr, &signal, sizeof(signal)); wl3501_get_from_wla(this, addr, &sig, sizeof(sig));
if (signal.status == WL3501_STATUS_SUCCESS) { if (sig.status == WL3501_STATUS_SUCCESS) {
if (this->net_type == WL3501_Infrastructure) { if (this->net_type == WL3501_NET_TYPE_INFRASTRUCTURE) {
if (this->join_sta_bss < this->bss_cnt) { if (this->join_sta_bss < this->bss_cnt) {
i = this->join_sta_bss; i = this->join_sta_bss;
memcpy((char *)&(this->bssid), memcpy((char *)&(this->bssid),
(char *)&(this->bss_set[i].bssid), 6); (char *)&(this->bss_set[i].bssid),
ETH_ALEN);
this->chan = this->bss_set[i].phy_pset[2]; this->chan = this->bss_set[i].phy_pset[2];
memcpy((char *)this->keep_essid, memcpy((char *)this->keep_essid,
(char *)this->bss_set[i].ssid, 34); (char *)this->bss_set[i].ssid, 34);
wl3501_cmdloop(wl3501_mgmt_auth(this)); wl3501_loop(wl3501_mgmt_auth(this));
} }
} else { } else {
this->card_start = 1; this->card_start = 1;
i = this->join_sta_bss; i = this->join_sta_bss;
memcpy((char *)&(this->bssid), memcpy((char *)&(this->bssid),
(char *)&(this->bss_set[i].bssid), 6); (char *)&(this->bss_set[i].bssid), ETH_ALEN);
this->chan = this->bss_set[i].phy_pset[2]; this->chan = this->bss_set[i].phy_pset[2];
memcpy((char *)this->keep_essid, memcpy((char *)this->keep_essid,
(char *)this->bss_set[i].ssid, 34); (char *)this->bss_set[i].ssid, 34);
...@@ -1083,167 +1095,216 @@ static void wl3501_mgmt_join_confirm(struct wl3501_card *this, u16 addr) ...@@ -1083,167 +1095,216 @@ static void wl3501_mgmt_join_confirm(struct wl3501_card *this, u16 addr)
} else { } else {
this->join_sta_bss++; this->join_sta_bss++;
for (j = this->join_sta_bss; j < this->bss_cnt; j++) for (j = this->join_sta_bss; j < this->bss_cnt; j++)
if (wl3501_cmdloop(wl3501_mgmt_join(this, j))) if (!wl3501_loop(wl3501_mgmt_join(this, j)))
break; break;
this->join_sta_bss = j; this->join_sta_bss = j;
if (this->join_sta_bss == this->bss_cnt) { if (this->join_sta_bss == this->bss_cnt) {
if (this->net_type == WL3501_Infrastructure) if (this->net_type == WL3501_NET_TYPE_INFRASTRUCTURE)
wl3501_cmdloop(wl3501_mgmt_scan(this, 100)); wl3501_loop(wl3501_mgmt_scan(this, 100));
else { else {
this->adhoc_times++; this->adhoc_times++;
if (this->adhoc_times > 8) if (this->adhoc_times > WL3501_MAX_ADHOC_TRIES)
wl3501_cmdloop(wl3501_mgmt_start(this)); wl3501_loop(wl3501_mgmt_start(this));
else else
wl3501_cmdloop(wl3501_mgmt_scan(this, 100)); wl3501_loop(wl3501_mgmt_scan(this,
100));
} }
} }
} }
if (this->card_start)
netif_wake_queue(dev);
else
netif_stop_queue(dev);
} }
static void wl3501_rx_interrupt(struct net_device *dev) static inline void wl3501_alarm_interrupt(struct net_device *dev,
struct wl3501_card *this)
{ {
int size; if (this->net_type == WL3501_NET_TYPE_INFRASTRUCTURE) {
int morepkts; printk(KERN_INFO "Wireless LAN Off-Line\n");
u16 addr, tmp, pkt_len; netif_stop_queue(dev);
u8 sig_id; wl3501_loop(wl3501_mgmt_resync(this));
struct wl3501_md_conf md_conf; }
struct wl3501_md_ind md_ind; }
struct wl3501_get_conf get_conf;
struct wl3501_start_conf start_conf;
struct wl3501_auth_conf auth_conf;
struct wl3501_assoc_conf assoc_conf;
struct sk_buff *skb;
struct wl3501_card *this = (struct wl3501_card *)dev->priv;
loop: static inline void wl3501_md_confirm_interrupt(struct net_device *dev,
morepkts = 0; struct wl3501_card *this,
if (!wl3501_esbq_confirm(this)) u16 addr)
goto free; {
wl3501_get_from_wla(this, this->esbq_confirm, &addr, sizeof(addr)); struct wl3501_md_confirm sig;
wl3501_get_from_wla(this, addr + 2, &sig_id, sizeof(sig_id));
switch (sig_id) { wl3501_get_from_wla(this, addr, &sig, sizeof(sig));
case WL3501_DeautheIndicate: wl3501_free_tx_buffer(this, sig.data);
case WL3501_DisassocIndicate: netif_wake_queue(dev);
case WL3501_Alarm: }
if (this->net_type == WL3501_Infrastructure) {
printk(KERN_INFO "Wireless LAN Off-Line\n");
netif_stop_queue(dev);
wl3501_cmdloop(wl3501_mgmt_resync(this));
}
break;
case WL3501_MdConfirm:
wl3501_get_from_wla(this, addr, &md_conf, sizeof(md_conf));
wl3501_free_tx_buffer(this, md_conf.data);
netif_wake_queue(dev);
break;
case WL3501_MdIndicate:
wl3501_get_from_wla(this, addr, &md_ind, sizeof(md_ind));
this->start_seg = md_ind.data;
if (this->llc_type == 1) { static inline void wl3501_md_ind_interrupt(struct net_device *dev,
wl3501_get_from_wla(this, md_ind.data + struct wl3501_card *this, u16 addr)
sizeof(struct wl3501_rx_hdr) - 6, {
&tmp, sizeof(tmp)); struct wl3501_md_ind sig;
if (tmp == 0xaaaa) { struct sk_buff *skb;
pkt_len = md_ind.size + 12 - 24 - 4 - 6; int size;
this->ether_type = EtherII; u16 tmp, pkt_len;
} else if (tmp == 0xe0e0) {
pkt_len = md_ind.size + 12 - 24 - 4 + 2;
this->ether_type = Ether802_3e;
} else {
pkt_len = md_ind.size + 12 - 24 - 4 + 2;
this->ether_type = Ether802_3f;
}
} else
pkt_len = md_ind.size - 24 - 4;
size = pkt_len; wl3501_get_from_wla(this, addr, &sig, sizeof(sig));
skb = dev_alloc_skb(size + 5); this->start_seg = sig.data;
if (!skb) { if (this->llc_type == 1) {
printk(KERN_WARNING wl3501_get_from_wla(this, sig.data +
"%s: Cannot allocate a sk_buff " sizeof(struct wl3501_rx_hdr) - 6,
"of size %d.\n", dev->name, size); &tmp, sizeof(tmp));
/* must drop this packet to ensure if (tmp == 0xaaaa) {
interrupt will come again */ pkt_len = sig.size + 12 - 24 - 4 - 6;
this->stats.rx_dropped++; this->ether_type = WL3501_PKT_TYPE_ETHERII;
break; } else if (tmp == 0xe0e0) {
pkt_len = sig.size + 12 - 24 - 4 + 2;
this->ether_type = WL3501_PKT_TYPE_ETHER802_3E;
} else {
pkt_len = sig.size + 12 - 24 - 4 + 2;
this->ether_type = WL3501_PKT_TYPE_ETHER802_3F;
} }
} else
pkt_len = sig.size - 24 - 4;
size = pkt_len;
skb = dev_alloc_skb(size + 5);
if (!skb) {
printk(KERN_WARNING "%s: Can't alloc a sk_buff of size %d.\n",
dev->name, size);
/*
* Must drop this packet to ensure interrupt will come again
*/
this->stats.rx_dropped++;
} else {
skb->dev = dev; skb->dev = dev;
skb_reserve(skb, 2); /* IP headers on 16 bytes skb_reserve(skb, 2); /* IP headers on 16 bytes
boundaries */ boundaries */
skb_put(skb, size); /* Make room */ skb_put(skb, size); /* Make room */
memcpy((char *)skb->data, (char *)&(md_ind.daddr), 12); memcpy((char *)skb->data, (char *)&(sig.daddr), 12);
wl3501_receive(this, skb->data, size); wl3501_receive(this, skb->data, size);
skb->protocol = eth_type_trans(skb, dev); skb->protocol = eth_type_trans(skb, dev);
dev->last_rx = jiffies; dev->last_rx = jiffies;
this->stats.rx_packets++; this->stats.rx_packets++;
this->stats.rx_bytes += skb->len; this->stats.rx_bytes += skb->len;
netif_rx(skb); netif_rx(skb);
break; }
case WL3501_GetConfirm: }
wl3501_get_from_wla(this, addr, &get_conf, sizeof(get_conf));
static inline void wl3501_get_confirm_interrupt(struct wl3501_card *this,
u16 addr)
{
struct wl3501_get_confirm sig;
wl3501_get_from_wla(this, addr, &sig, sizeof(sig));
#if 0 #if 0
if (!get_conf.mib_status) { if (!sig.mib_status) {
switch (get_conf.mib_attrib) { switch (sig.mib_attrib) {
case wl3501_mib_MacAddress: case wl3501_mib_mac_addr:
break; break;
case wl3501_mib_CurrentRegDomain: case wl3501_mib_current_reg_domain:
break; break;
}
} }
}
#endif #endif
break; }
case WL3501_StartConfirm:
wl3501_get_from_wla(this, addr, &start_conf,
sizeof(start_conf));
this->card_start = start_conf.status == WL3501_STATUS_SUCCESS; static inline void wl3501_start_confirm_interrupt(struct net_device *dev,
if (this->card_start) struct wl3501_card *this,
netif_wake_queue(dev); u16 addr)
else {
netif_stop_queue(dev); struct wl3501_start_confirm sig;
wl3501_get_from_wla(this, addr, &sig, sizeof(sig));
this->card_start = sig.status == WL3501_STATUS_SUCCESS;
if (this->card_start)
netif_wake_queue(dev);
else
netif_stop_queue(dev);
}
static inline void wl3501_assoc_confirm_interrupt(struct net_device *dev,
struct wl3501_card *this,
u16 addr)
{
struct wl3501_assoc_confirm sig;
wl3501_get_from_wla(this, addr, &sig, sizeof(sig));
if (sig.status == WL3501_STATUS_SUCCESS) {
printk(KERN_INFO "Wireless LAN On-Line Join:"
" %2X %2X %2X %2X %2X %2X\n",
this->bssid.b0, this->bssid.b1,
this->bssid.b2, this->bssid.b3,
this->bssid.b4, this->bssid.b5);
this->card_start = 1;
} else
this->card_start = 0;
if (this->card_start)
netif_wake_queue(dev);
else
netif_stop_queue(dev);
}
static inline void wl3501_auth_confirm_interrupt(struct wl3501_card *this,
u16 addr)
{
struct wl3501_auth_confirm sig;
wl3501_get_from_wla(this, addr, &sig, sizeof(sig));
if (sig.status == WL3501_STATUS_SUCCESS)
wl3501_loop(wl3501_mgmt_association(this));
else
wl3501_loop(wl3501_mgmt_resync(this));
}
static void wl3501_rx_interrupt(struct net_device *dev)
{
int morepkts;
u16 addr;
u8 sig_id;
struct wl3501_card *this = (struct wl3501_card *)dev->priv;
loop:
morepkts = 0;
if (!wl3501_esbq_confirm(this))
goto free;
wl3501_get_from_wla(this, this->esbq_confirm, &addr, sizeof(addr));
wl3501_get_from_wla(this, addr + 2, &sig_id, sizeof(sig_id));
switch (sig_id) {
case WL3501_SIG_DEAUTH_IND:
case WL3501_SIG_DISASSOC_IND:
case WL3501_SIG_ALARM:
wl3501_alarm_interrupt(dev, this);
break;
case WL3501_SIG_MD_CONFIRM:
wl3501_md_confirm_interrupt(dev, this, addr);
break;
case WL3501_SIG_MD_IND:
wl3501_md_ind_interrupt(dev, this, addr);
break; break;
case WL3501_ScanConfirm: case WL3501_SIG_GET_CONFIRM:
wl3501_get_confirm_interrupt(this, addr);
break;
case WL3501_SIG_START_CONFIRM:
wl3501_start_confirm_interrupt(dev, this, addr);
break;
case WL3501_SIG_SCAN_CONFIRM:
wl3501_mgmt_scan_confirm(this, addr); wl3501_mgmt_scan_confirm(this, addr);
break; break;
case WL3501_JoinConfirm: case WL3501_SIG_JOIN_CONFIRM:
wl3501_mgmt_join_confirm(this, addr); wl3501_mgmt_join_confirm(dev, this, addr);
if (this->card_start)
netif_wake_queue(dev);
else
netif_stop_queue(dev);
break; break;
case WL3501_AssocConfirm: case WL3501_SIG_ASSOC_CONFIRM:
wl3501_get_from_wla(this, addr, &assoc_conf, wl3501_assoc_confirm_interrupt(dev, this, addr);
sizeof(assoc_conf));
if (assoc_conf.status == WL3501_STATUS_SUCCESS) {
printk(KERN_INFO "Wireless LAN On-Line Join:"
" %2X %2X %2X %2X %2X %2X\n",
this->bssid.b0, this->bssid.b1,
this->bssid.b2, this->bssid.b3,
this->bssid.b4, this->bssid.b5);
this->card_start = 1;
} else
this->card_start = 0;
if (this->card_start)
netif_wake_queue(dev);
else
netif_stop_queue(dev);
break; break;
case WL3501_AutheConfirm: case WL3501_SIG_AUTH_CONFIRM:
wl3501_get_from_wla(this, addr, &auth_conf, sizeof(auth_conf)); wl3501_auth_confirm_interrupt(this, addr);
if (auth_conf.status == WL3501_STATUS_SUCCESS)
wl3501_cmdloop(wl3501_mgmt_association(this));
else
wl3501_cmdloop(wl3501_mgmt_resync(this));
break; break;
case WL3501_ResyncConfirm: case WL3501_SIG_RESYNC_CONFIRM:
wl3501_mgmt_resync(this); /* FIXME: should be resync_confirm */ wl3501_mgmt_resync(this); /* FIXME: should be resync_confirm */
break; break;
} }
...@@ -1274,7 +1335,7 @@ static __inline__ void wl3501_ack_interrupt(struct wl3501_card *this) ...@@ -1274,7 +1335,7 @@ static __inline__ void wl3501_ack_interrupt(struct wl3501_card *this)
* On the other hand, to prevent SUTRO from malfunctioning, we must * On the other hand, to prevent SUTRO from malfunctioning, we must
* unlock the SUTRO as soon as possible. * unlock the SUTRO as soon as possible.
*/ */
static void wl3501_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t wl3501_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct net_device *dev = (struct net_device *)dev_id; struct net_device *dev = (struct net_device *)dev_id;
struct wl3501_card *this; struct wl3501_card *this;
...@@ -1282,7 +1343,7 @@ static void wl3501_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1282,7 +1343,7 @@ static void wl3501_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (!dev) { if (!dev) {
printk(KERN_ERR "%s: irq %d for unknown device.\n", printk(KERN_ERR "%s: irq %d for unknown device.\n",
__FUNCTION__, irq); __FUNCTION__, irq);
return; return IRQ_NONE;
} }
this = (struct wl3501_card *)dev->priv; this = (struct wl3501_card *)dev->priv;
...@@ -1294,12 +1355,14 @@ static void wl3501_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1294,12 +1355,14 @@ static void wl3501_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* Clean Zone End */ /* Clean Zone End */
wl3501_unblock_interrupt(this); wl3501_unblock_interrupt(this);
return IRQ_HANDLED;
} }
static int wl3501_reset_board(struct wl3501_card *this) static int wl3501_reset_board(struct wl3501_card *this)
{ {
u8 tmp; u8 tmp;
u32 i; u32 i;
int rc = 0;
/* Coreset */ /* Coreset */
wl3501_outb_p(WL3501_GCR_CORESET, this->base_addr + WL3501_NIC_GCR); wl3501_outb_p(WL3501_GCR_CORESET, this->base_addr + WL3501_NIC_GCR);
...@@ -1325,21 +1388,23 @@ static int wl3501_reset_board(struct wl3501_card *this) ...@@ -1325,21 +1388,23 @@ static int wl3501_reset_board(struct wl3501_card *this)
/* firmware complete all test successfully */ /* firmware complete all test successfully */
tmp = 'A'; tmp = 'A';
wl3501_set_to_wla(this, 0x480, &tmp, sizeof(tmp)); wl3501_set_to_wla(this, 0x480, &tmp, sizeof(tmp));
return 1; goto out;
} }
WL3501_NOPLOOP(10); WL3501_NOPLOOP(10);
} }
return 0; printk(KERN_WARNING "%s: failed to reset the board!\n", __FUNCTION__);
rc = -ENODEV;
out:
return rc;
} }
static int wl3501_init_firmware(struct wl3501_card *this) static int wl3501_init_firmware(struct wl3501_card *this)
{ {
u16 ptr, next; u16 ptr, next;
int rc = wl3501_reset_board(this);
if (!wl3501_reset_board(this)) { if (rc)
printk(KERN_WARNING "wlapi.c: wl3501_reset_board failed!\n"); goto fail;
return 1;
}
/* Switch to SRAM Page 0 */ /* Switch to SRAM Page 0 */
wl3501_switch_page(this, WL3501_BSS_SPAGE0); wl3501_switch_page(this, WL3501_BSS_SPAGE0);
/* Read parameter from card */ /* Read parameter from card */
...@@ -1349,9 +1414,9 @@ static int wl3501_init_firmware(struct wl3501_card *this) ...@@ -1349,9 +1414,9 @@ static int wl3501_init_firmware(struct wl3501_card *this)
wl3501_get_from_wla(this, 0x48c, &this->esbq_confirm_end, 2); wl3501_get_from_wla(this, 0x48c, &this->esbq_confirm_end, 2);
wl3501_get_from_wla(this, 0x48e, &this->tx_buffer_head, 2); wl3501_get_from_wla(this, 0x48e, &this->tx_buffer_head, 2);
wl3501_get_from_wla(this, 0x492, &this->tx_buffer_size, 2); wl3501_get_from_wla(this, 0x492, &this->tx_buffer_size, 2);
this->esbq_req_tail = this->esbq_req_head = this->esbq_req_start; this->esbq_req_tail = this->esbq_req_head = this->esbq_req_start;
this->esbq_req_end += this->esbq_req_start; this->esbq_req_end += this->esbq_req_start;
this->esbq_confirm = this->esbq_confirm_start; this->esbq_confirm = this->esbq_confirm_start;
this->esbq_confirm_end += this->esbq_confirm_start; this->esbq_confirm_end += this->esbq_confirm_start;
/* Initial Tx Buffer */ /* Initial Tx Buffer */
this->tx_buffer_cnt = 1; this->tx_buffer_cnt = 1;
...@@ -1363,18 +1428,25 @@ static int wl3501_init_firmware(struct wl3501_card *this) ...@@ -1363,18 +1428,25 @@ static int wl3501_init_firmware(struct wl3501_card *this)
ptr = next; ptr = next;
next = ptr + WL3501_BLKSZ; next = ptr + WL3501_BLKSZ;
} }
rc = 0;
next = 0; next = 0;
wl3501_set_to_wla(this, ptr, &next, sizeof(next)); wl3501_set_to_wla(this, ptr, &next, sizeof(next));
this->tx_buffer_tail = ptr; this->tx_buffer_tail = ptr;
return 1; out:
return rc;
fail:
printk(KERN_WARNING "%s: failed!\n", __FUNCTION__);
goto out;
} }
static int wl3501_close(struct net_device *dev) static int wl3501_close(struct net_device *dev)
{ {
struct wl3501_card *this = (struct wl3501_card *)dev->priv; struct wl3501_card *this = (struct wl3501_card *)dev->priv;
dev_link_t *link;
int rc = -ENODEV; int rc = -ENODEV;
unsigned long flags;
dev_link_t *link;
//spin_lock_irqsave(&this->lock, flags);
/* Check if the device is in wl3501_dev_list */ /* Check if the device is in wl3501_dev_list */
for (link = wl3501_dev_list; link; link = link->next) for (link = wl3501_dev_list; link; link = link->next)
if (link->priv == dev) if (link->priv == dev)
...@@ -1392,13 +1464,14 @@ static int wl3501_close(struct net_device *dev) ...@@ -1392,13 +1464,14 @@ static int wl3501_close(struct net_device *dev)
wl3501_block_interrupt(this); wl3501_block_interrupt(this);
if (link->state & DEV_STALE_CONFIG) { if (link->state & DEV_STALE_CONFIG) {
link->release.expires = jiffies + HZ * 20; link->release.expires = jiffies + WL3501_RELEASE_TIMEOUT;
link->state |= DEV_RELEASE_PENDING; link->state |= DEV_RELEASE_PENDING;
add_timer(&link->release); add_timer(&link->release);
} }
rc = 0; rc = 0;
printk(KERN_INFO "%s : WL24xx closed\n", dev->name); printk(KERN_INFO "%s: WL3501 closed\n", dev->name);
out: out:
//spin_unlock_irqrestore(&this->lock, flags);
return rc; return rc;
} }
...@@ -1412,20 +1485,23 @@ static int wl3501_close(struct net_device *dev) ...@@ -1412,20 +1485,23 @@ static int wl3501_close(struct net_device *dev)
*/ */
static int wl3501_reset(struct net_device *dev) static int wl3501_reset(struct net_device *dev)
{ {
unsigned long flags;
struct wl3501_card *this = (struct wl3501_card *)dev->priv; struct wl3501_card *this = (struct wl3501_card *)dev->priv;
int rc = -ENODEV;
//spin_lock_irqsave(&this->lock, flags);
/* Stop processing interrupt from the card */ /* Stop processing interrupt from the card */
wl3501_block_interrupt(this); wl3501_block_interrupt(this);
/* Initial WL24 firmware */ /* Initial WL3501 firmware */
printk(KERN_INFO "%s: Initialize WL24xx firmware...\n", dev->name); printk(KERN_INFO "%s: Initialize WL3501 firmware...\n", dev->name);
if (!wl3501_init_firmware(this)) { if (wl3501_init_firmware(this)) {
printk(KERN_WARNING "%s: Can't initialize Firmware!\n", printk(KERN_WARNING "%s: Can't initialize Firmware!\n",
dev->name); dev->name);
/* Free IRQ, and mark IRQ as unused */ /* Free IRQ, and mark IRQ as unused */
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
return -ENODEV; goto out;
} }
/* Initial device variables */ /* Initial device variables */
...@@ -1437,9 +1513,12 @@ static int wl3501_reset(struct net_device *dev) ...@@ -1437,9 +1513,12 @@ static int wl3501_reset(struct net_device *dev)
/* Enable interrupt from card */ /* Enable interrupt from card */
wl3501_unblock_interrupt(this); wl3501_unblock_interrupt(this);
wl3501_cmdloop(wl3501_mgmt_scan(this, 100)); wl3501_loop(wl3501_mgmt_scan(this, 100));
printk(KERN_INFO "%s: device reset\n", dev->name); printk(KERN_INFO "%s: device reset\n", dev->name);
return 0; rc = 0;
out:
//spin_unlock_irqrestore(&this->lock, flags);
return rc;
} }
static void wl3501_tx_timeout(struct net_device *dev) static void wl3501_tx_timeout(struct net_device *dev)
...@@ -1448,7 +1527,6 @@ static void wl3501_tx_timeout(struct net_device *dev) ...@@ -1448,7 +1527,6 @@ static void wl3501_tx_timeout(struct net_device *dev)
struct net_device_stats *stats = &this->stats; struct net_device_stats *stats = &this->stats;
int rc; int rc;
// printk(KERN_WARNING "%s: Tx timeout! Resetting card.\n", dev->name);
stats->tx_errors++; stats->tx_errors++;
rc = wl3501_reset(dev); rc = wl3501_reset(dev);
if (rc) if (rc)
...@@ -1467,11 +1545,11 @@ static void wl3501_tx_timeout(struct net_device *dev) ...@@ -1467,11 +1545,11 @@ static void wl3501_tx_timeout(struct net_device *dev)
*/ */
static int wl3501_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) static int wl3501_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
int enabled, send; int enabled, fail_send;
struct wl3501_card *this = (struct wl3501_card *)dev->priv; struct wl3501_card *this = (struct wl3501_card *)dev->priv;
if (!netif_running(dev) || !this->card_start) { if (!netif_running(dev) || !this->card_start) {
// printk(KERN_ERR "%s: Tx on stopped device!\n", dev->name); //printk(KERN_ERR "%s: Tx on stopped device!\n", dev->name);
return 1; return 1;
} }
if (netif_queue_stopped(dev)) { if (netif_queue_stopped(dev)) {
...@@ -1481,14 +1559,18 @@ static int wl3501_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1481,14 +1559,18 @@ static int wl3501_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Avoid re-entry. Block a timer-based transmit from overlapping. */ /* Avoid re-entry. Block a timer-based transmit from overlapping. */
netif_stop_queue(dev); netif_stop_queue(dev);
/* Good! This packet owns the transmitter, block interrupt immediately. /*
* Good! This packet owns the transmitter, block interrupt immediately.
* wl3501_interrupt() has no chance to start the queue if it gets * wl3501_interrupt() has no chance to start the queue if it gets
* ISR_Tx. */ * ISR_Tx.
*/
/* Mask interrupts from the SUTRO! /*
* Mask interrupts from the SUTRO!
* We must mask interrupt from the same card, to prevent interrupt * We must mask interrupt from the same card, to prevent interrupt
* routine from accessing data structure and I/O port while * routine from accessing data structure and I/O port while
* wl3501_send_pkt is running. It's very important! */ * wl3501_send_pkt is running. It's very important!
*/
enabled = wl3501_block_interrupt(this); enabled = wl3501_block_interrupt(this);
...@@ -1496,7 +1578,7 @@ static int wl3501_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1496,7 +1578,7 @@ static int wl3501_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies; dev->trans_start = jiffies;
/* Send the packet with default speed */ /* Send the packet with default speed */
send = wl3501_send_pkt(this, skb->data, skb->len); fail_send = wl3501_send_pkt(this, skb->data, skb->len);
/* Turn SUTRO interrupt back on only if it is originally enabled */ /* Turn SUTRO interrupt back on only if it is originally enabled */
if (enabled) if (enabled)
...@@ -1505,7 +1587,7 @@ static int wl3501_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1505,7 +1587,7 @@ static int wl3501_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* If sent successfully, start queue. Otherwise, buffer is enqueued /* If sent successfully, start queue. Otherwise, buffer is enqueued
* and will be restarted again when the SUTRO interrupts us and * and will be restarted again when the SUTRO interrupts us and
* returns ISR_Tx */ * returns ISR_Tx */
if (send) { if (!fail_send) {
dev_kfree_skb(skb); dev_kfree_skb(skb);
netif_start_queue(dev); /* Let others own the transmitter */ netif_start_queue(dev); /* Let others own the transmitter */
return 0; return 0;
...@@ -1517,8 +1599,10 @@ static int wl3501_open(struct net_device *dev) ...@@ -1517,8 +1599,10 @@ static int wl3501_open(struct net_device *dev)
{ {
int rc = -ENODEV; int rc = -ENODEV;
struct wl3501_card *this = (struct wl3501_card *)dev->priv; struct wl3501_card *this = (struct wl3501_card *)dev->priv;
unsigned long flags;
dev_link_t *link; dev_link_t *link;
//spin_lock_irqsave(&this->lock, flags);
/* Check if the device is in wl3501_dev_list */ /* Check if the device is in wl3501_dev_list */
for (link = wl3501_dev_list; link; link = link->next) for (link = wl3501_dev_list; link; link = link->next)
if (link->priv == dev) if (link->priv == dev)
...@@ -1528,13 +1612,10 @@ static int wl3501_open(struct net_device *dev) ...@@ -1528,13 +1612,10 @@ static int wl3501_open(struct net_device *dev)
netif_device_attach(dev); netif_device_attach(dev);
link->open++; link->open++;
/* Initial WL24 firmware */ /* Initial WL3501 firmware */
printk(KERN_INFO "%s: Initialize WL24xx firmware...\n", dev->name); printk(KERN_INFO "%s: Initialize WL3501 firmware...\n", dev->name);
if (!wl3501_init_firmware(this)) { if (wl3501_init_firmware(this))
printk(KERN_WARNING "%s: Can't initialize firmware!\n", goto fail;
dev->name);
goto out;
}
/* Initial device variables */ /* Initial device variables */
netif_start_queue(dev); netif_start_queue(dev);
this->card_start = 0; this->card_start = 0;
...@@ -1544,11 +1625,15 @@ static int wl3501_open(struct net_device *dev) ...@@ -1544,11 +1625,15 @@ static int wl3501_open(struct net_device *dev)
/* Enable interrupt from card after all */ /* Enable interrupt from card after all */
wl3501_unblock_interrupt(this); wl3501_unblock_interrupt(this);
wl3501_cmdloop(wl3501_mgmt_scan(this, 100)); wl3501_loop(wl3501_mgmt_scan(this, 100));
rc = 0; rc = 0;
printk(KERN_INFO "%s: WL24xx opened\n", dev->name); printk(KERN_INFO "%s: WL3501 opened\n", dev->name);
out: out:
//spin_unlock_irqrestore(&this->lock, flags);
return rc; return rc;
fail:
printk(KERN_WARNING "%s: Can't initialize firmware!\n", dev->name);
goto out;
} }
/** /**
...@@ -1560,7 +1645,6 @@ static int wl3501_open(struct net_device *dev) ...@@ -1560,7 +1645,6 @@ static int wl3501_open(struct net_device *dev)
*/ */
static int wl3501_init(struct net_device *dev) static int wl3501_init(struct net_device *dev)
{ {
dprintk(0, "called");
return 0; return 0;
} }
...@@ -1595,8 +1679,7 @@ struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev) ...@@ -1595,8 +1679,7 @@ struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev)
* *
* CAUTION: To prevent interrupted by WL_Interrupt() and timer-based * CAUTION: To prevent interrupted by WL_Interrupt() and timer-based
* wl3501_hard_start_xmit() from other interrupts, this should be run * wl3501_hard_start_xmit() from other interrupts, this should be run
* single-threaded. This function is expected to be a rare operation, and it's * single-threaded.
* simpler to just use cli() to disable ALL interrupts.
*/ */
static void wl3501_set_multicast_list(struct net_device *dev) static void wl3501_set_multicast_list(struct net_device *dev)
{ {
...@@ -1611,13 +1694,11 @@ static void wl3501_set_multicast_list(struct net_device *dev) ...@@ -1611,13 +1694,11 @@ static void wl3501_set_multicast_list(struct net_device *dev)
/* Allow multicast */ /* Allow multicast */
filter |= RMR_ALL_MULTICAST; filter |= RMR_ALL_MULTICAST;
save_flags(flags); //spin_lock_irqsave(&this->lock, flags);
cli();
/* Must not be interrupted */ /* Must not be interrupted */
wl3501_set_mib_value(this, TYPE_EXTRA_MIB, IDX_RECEIVEMODE, wl3501_set_mib_value(this, TYPE_EXTRA_MIB, IDX_RECEIVEMODE,
&filter, sizeof(filter)); &filter, sizeof(filter));
restore_flags(flags); //spin_unlock_irqrestore(&this->lock, flags);
#endif #endif
} }
...@@ -1645,32 +1726,24 @@ static int wl3501_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1645,32 +1726,24 @@ static int wl3501_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
struct wl3501_ioctl_blk *blk = (struct wl3501_ioctl_blk *) struct wl3501_ioctl_blk *blk = (struct wl3501_ioctl_blk *)
&rq->ifr_data; &rq->ifr_data;
unsigned char bf[1028]; unsigned char bf[1028];
unsigned long flags;
/* Keep flags first, these are inline functions */
save_flags(flags);
cli();
switch (blk->cmd) { switch (blk->cmd) {
case WL3501_IOCTL_SET_RESET: /* Reset drv - needed after set */ case WL3501_IOCTL_CMD_SET_RESET: /* Reset drv - needed after set */
if (!capable(CAP_NET_ADMIN)) { rc = -EPERM;
rc = -EPERM; if (!capable(CAP_NET_ADMIN))
break; break;
}
rc = wl3501_reset(dev); rc = wl3501_reset(dev);
break; break;
case WL3501_IOCTL_WRITE_FLASH: /* Write firmware into Flash */ case WL3501_IOCTL_CMD_WRITE_FLASH: /* Write firmware into Flash */
if (!capable(CAP_NET_ADMIN)) { rc = -EPERM;
rc = -EPERM; if (!capable(CAP_NET_ADMIN))
break; break;
} rc = -EFAULT;
if (copy_from_user(bf, blk->data, blk->len)) { if (copy_from_user(bf, blk->data, blk->len))
rc = -EFAULT;
break; break;
}
rc = wl3501_write_flash(this, bf, blk->len) ? 0 : -EIO; rc = wl3501_write_flash(this, bf, blk->len) ? 0 : -EIO;
break; break;
case WL3501_IOCTL_GET_PARAMETER: case WL3501_IOCTL_CMD_GET_PARAMETER:
/* Get parameter */
parm.def_chan = this->def_chan; parm.def_chan = this->def_chan;
parm.chan = this->chan; parm.chan = this->chan;
parm.net_type = this->net_type; parm.net_type = this->net_type;
...@@ -1681,32 +1754,26 @@ static int wl3501_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1681,32 +1754,26 @@ static int wl3501_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
(char *)&(this->keep_essid[0]), 34); (char *)&(this->keep_essid[0]), 34);
memcpy((char *)&(parm.essid[0]), (char *)&(this->essid[0]), 34); memcpy((char *)&(parm.essid[0]), (char *)&(this->essid[0]), 34);
blk->len = sizeof(parm); blk->len = sizeof(parm);
if (copy_to_user(blk->data, &parm, blk->len)) { rc = -EFAULT;
rc = -EFAULT; if (copy_to_user(blk->data, &parm, blk->len))
break; break;
} rc = 0;
break; break;
case WL3501_IOCTL_SET_PARAMETER:{ case WL3501_IOCTL_CMD_SET_PARAMETER:
/* Set parameter */ rc = -EPERM;
if (!capable(CAP_NET_ADMIN)) { if (!capable(CAP_NET_ADMIN))
rc = -EPERM;
break;
}
if (copy_from_user(&parm, blk->data, sizeof(parm))) {
rc = -EFAULT;
break;
}
this->def_chan = parm.def_chan;
this->net_type = parm.net_type;
memcpy((char *)&(this->essid[0]),
(char *)&(parm.essid[0]), 34);
rc = wl3501_reset(dev);
break; break;
} rc = -EFAULT;
if (copy_from_user(&parm, blk->data, sizeof(parm)))
break;
this->def_chan = parm.def_chan;
this->net_type = parm.net_type;
memcpy((char *)&(this->essid[0]), (char *)&(parm.essid[0]), 34);
rc = wl3501_reset(dev);
break;
default: default:
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
} }
restore_flags(flags);
return rc; return rc;
} }
...@@ -1768,7 +1835,7 @@ static void wl3501_flush_stale_links(void) ...@@ -1768,7 +1835,7 @@ static void wl3501_flush_stale_links(void)
for (link = wl3501_dev_list; link; link = next) { for (link = wl3501_dev_list; link; link = next) {
next = link->next; next = link->next;
if (link->state & DEV_STALE_LINK) if (link->state & DEV_STALE_LINK)
wl3501_detach(link); wl3501_detach(link);
} }
} }
...@@ -1827,18 +1894,17 @@ static dev_link_t *wl3501_attach(void) ...@@ -1827,18 +1894,17 @@ static dev_link_t *wl3501_attach(void)
goto out_link; goto out_link;
memset(dev, 0, sizeof(*dev) + sizeof(struct wl3501_card)); memset(dev, 0, sizeof(*dev) + sizeof(struct wl3501_card));
ether_setup(dev); ether_setup(dev);
dev->priv = dev + 1; dev->priv = dev + 1;
dev->init = wl3501_init; dev->init = wl3501_init;
dev->open = wl3501_open; dev->open = wl3501_open;
dev->stop = wl3501_close; dev->stop = wl3501_close;
dev->hard_start_xmit = wl3501_hard_start_xmit; dev->hard_start_xmit = wl3501_hard_start_xmit;
dev->tx_timeout = wl3501_tx_timeout; dev->tx_timeout = wl3501_tx_timeout;
dev->watchdog_timeo = HZ; dev->watchdog_timeo = 10 * HZ;
dev->get_stats = wl3501_get_stats;
dev->get_stats = wl3501_get_stats;
dev->get_wireless_stats = wl3501_get_wireless_stats; dev->get_wireless_stats = wl3501_get_wireless_stats;
dev->set_multicast_list = wl3501_set_multicast_list; dev->set_multicast_list = wl3501_set_multicast_list;
dev->do_ioctl = wl3501_ioctl; dev->do_ioctl = wl3501_ioctl;
netif_stop_queue(dev); netif_stop_queue(dev);
link->priv = link->irq.Instance = dev; link->priv = link->irq.Instance = dev;
...@@ -1967,19 +2033,20 @@ static void wl3501_config(dev_link_t *link) ...@@ -1967,19 +2033,20 @@ static void wl3501_config(dev_link_t *link)
} }
printk("\n"); printk("\n");
/* initialize card parameter - add by jss */ /* initialize card parameter - add by jss */
this->net_type = WL3501_Infrastructure; this->net_type = WL3501_NET_TYPE_INFRASTRUCTURE;
this->llc_type = 1; this->llc_type = 1;
this->def_chan = 1; this->def_chan = 1;
this->bss_cnt = 0; this->bss_cnt = 0;
this->join_sta_bss = 0; this->join_sta_bss = 0;
this->adhoc_times = 0; this->adhoc_times = 0;
this->driver_state = 0; this->driver_state = 0;
this->card_start = 0; this->card_start = 0;
this->essid[0] = 0; this->essid[0] = 0;
this->essid[1] = 3; this->essid[1] = 3;
this->essid[2] = 'A'; this->essid[2] = 'A';
this->essid[3] = 'N'; this->essid[3] = 'N';
this->essid[4] = 'Y'; this->essid[4] = 'Y';
//spin_lock_init(&this->lock);
switch (this->freq_domain) { switch (this->freq_domain) {
case 0x31: case 0x31:
...@@ -2069,7 +2136,8 @@ static int wl3501_event(event_t event, int pri, event_callback_args_t *args) ...@@ -2069,7 +2136,8 @@ static int wl3501_event(event_t event, int pri, event_callback_args_t *args)
link->state &= ~DEV_PRESENT; link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
netif_stop_queue(dev); netif_stop_queue(dev);
link->release.expires = jiffies + HZ * 20; link->release.expires = jiffies +
WL3501_RELEASE_TIMEOUT;
add_timer(&link->release); add_timer(&link->release);
} }
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment