^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * WL3501 Wireless LAN PCMCIA Card Driver for Linux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Written originally for Linux 2.0.30 by Fox Chen, mhchen@golf.ccl.itri.org.tw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Ported to 2.2, 2.4 & 2.5 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Wireless extensions in 2.4 by Gustavo Niemeyer <niemeyer@conectiva.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * References used by Fox Chen while writing the original driver for 2.0.30:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * 1. WL24xx packet drivers (tooasm.asm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * 2. Access Point Firmware Interface Specification for IEEE 802.11 SUTRO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * 3. IEEE 802.11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * 4. Linux network driver (/usr/src/linux/drivers/net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * 5. ISA card driver - wl24.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * 6. Linux PCMCIA skeleton driver - skeleton.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * 7. Linux PCMCIA 3c589 network driver - 3c589_cs.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Tested with WL2400 firmware 1.2, Linux 2.0.30, and pcmcia-cs-2.9.12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * 1. Performance: about 165 Kbytes/sec in TCP/IP with Ad-Hoc mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * rsh 192.168.1.3 "dd if=/dev/zero bs=1k count=1000" > /dev/null
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * (Specification 2M bits/sec. is about 250 Kbytes/sec., but we must deduct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * ETHER/IP/UDP/TCP header, and acknowledgement overhead)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Tested with Planet AP in 2.4.17, 184 Kbytes/s in UDP in Infrastructure mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * 173 Kbytes/s in TCP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * Tested with Planet AP in 2.5.73-bk, 216 Kbytes/s in Infrastructure mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * with a SMP machine (dual pentium 100), using pktgen, 432 pps (pkt_size = 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/wireless.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <net/cfg80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <net/iw_handler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <pcmcia/cistpl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <pcmcia/cisreg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <pcmcia/ds.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include "wl3501.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #ifndef __i386__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define slow_down_io()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* For rough constant delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define WL3501_NOPLOOP(n) { int x = 0; while (x++ < n) slow_down_io(); }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define wl3501_outb(a, b) { outb(a, b); slow_down_io(); }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define wl3501_outb_p(a, b) { outb_p(a, b); slow_down_io(); }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define wl3501_outsb(a, b, c) { outsb(a, b, c); slow_down_io(); }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define WL3501_RELEASE_TIMEOUT (25 * HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define WL3501_MAX_ADHOC_TRIES 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define WL3501_RESUME 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define WL3501_SUSPEND 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static int wl3501_config(struct pcmcia_device *link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static void wl3501_release(struct pcmcia_device *link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static const struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int reg_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int min, max, deflt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) } iw_channel_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .reg_domain = IW_REG_DOMAIN_FCC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .max = 11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .deflt = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .reg_domain = IW_REG_DOMAIN_DOC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .max = 11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .deflt = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .reg_domain = IW_REG_DOMAIN_ETSI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .max = 13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .deflt = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .reg_domain = IW_REG_DOMAIN_SPAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .min = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .max = 11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .deflt = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .reg_domain = IW_REG_DOMAIN_FRANCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .min = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .max = 13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .deflt = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .reg_domain = IW_REG_DOMAIN_MKK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .min = 14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .max = 14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .deflt = 14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .reg_domain = IW_REG_DOMAIN_MKK1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .max = 14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .deflt = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .reg_domain = IW_REG_DOMAIN_ISRAEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .min = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .max = 9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .deflt = 9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * iw_valid_channel - validate channel in regulatory domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * @reg_comain: regulatory domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * @channel: channel to validate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * Returns 0 if invalid in the specified regulatory domain, non-zero if valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static int iw_valid_channel(int reg_domain, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int i, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) for (i = 0; i < ARRAY_SIZE(iw_channel_table); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (reg_domain == iw_channel_table[i].reg_domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) rc = channel >= iw_channel_table[i].min &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) channel <= iw_channel_table[i].max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * iw_default_channel - get default channel for a regulatory domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * @reg_domain: regulatory domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * Returns the default channel for a regulatory domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int iw_default_channel(int reg_domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) int i, rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) for (i = 0; i < ARRAY_SIZE(iw_channel_table); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (reg_domain == iw_channel_table[i].reg_domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) rc = iw_channel_table[i].deflt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static void iw_set_mgmt_info_element(enum iw_mgmt_info_element_ids id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct iw_mgmt_info_element *el,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) void *value, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) el->id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) el->len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) memcpy(el->data, value, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static void iw_copy_mgmt_info_element(struct iw_mgmt_info_element *to,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct iw_mgmt_info_element *from)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) iw_set_mgmt_info_element(from->id, to, from->data, from->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static inline void wl3501_switch_page(struct wl3501_card *this, u8 page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) wl3501_outb(page, this->base_addr + WL3501_NIC_BSS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * Get Ethernet MAC address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * WARNING: We switch to FPAGE0 and switc back again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * Making sure there is no other WL function beening called by ISR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static int wl3501_get_flash_mac_addr(struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) int base_addr = this->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /* get MAC addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) wl3501_outb(WL3501_BSS_FPAGE3, base_addr + WL3501_NIC_BSS); /* BSS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) wl3501_outb(0x00, base_addr + WL3501_NIC_LMAL); /* LMAL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) wl3501_outb(0x40, base_addr + WL3501_NIC_LMAH); /* LMAH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /* wait for reading EEPROM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) WL3501_NOPLOOP(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) this->mac_addr[0] = inb(base_addr + WL3501_NIC_IODPA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) WL3501_NOPLOOP(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) this->mac_addr[1] = inb(base_addr + WL3501_NIC_IODPA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) WL3501_NOPLOOP(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) this->mac_addr[2] = inb(base_addr + WL3501_NIC_IODPA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) WL3501_NOPLOOP(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) this->mac_addr[3] = inb(base_addr + WL3501_NIC_IODPA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) WL3501_NOPLOOP(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) this->mac_addr[4] = inb(base_addr + WL3501_NIC_IODPA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) WL3501_NOPLOOP(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) this->mac_addr[5] = inb(base_addr + WL3501_NIC_IODPA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) WL3501_NOPLOOP(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) this->reg_domain = inb(base_addr + WL3501_NIC_IODPA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) WL3501_NOPLOOP(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) wl3501_outb(WL3501_BSS_FPAGE0, base_addr + WL3501_NIC_BSS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) wl3501_outb(0x04, base_addr + WL3501_NIC_LMAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) wl3501_outb(0x40, base_addr + WL3501_NIC_LMAH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) WL3501_NOPLOOP(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) this->version[0] = inb(base_addr + WL3501_NIC_IODPA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) WL3501_NOPLOOP(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) this->version[1] = inb(base_addr + WL3501_NIC_IODPA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* switch to SRAM Page 0 (for safety) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) wl3501_switch_page(this, WL3501_BSS_SPAGE0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /* The MAC addr should be 00:60:... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return this->mac_addr[0] == 0x00 && this->mac_addr[1] == 0x60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * wl3501_set_to_wla - Move 'size' bytes from PC to card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * @this: Card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * @dest: Card addressing space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * @src: PC addressing space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * @size: Bytes to move
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * Move 'size' bytes from PC to card. (Shouldn't be interrupted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static void wl3501_set_to_wla(struct wl3501_card *this, u16 dest, void *src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* switch to SRAM Page 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) wl3501_switch_page(this, (dest & 0x8000) ? WL3501_BSS_SPAGE1 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) WL3501_BSS_SPAGE0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /* set LMAL and LMAH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) wl3501_outb(dest & 0xff, this->base_addr + WL3501_NIC_LMAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) wl3501_outb(((dest >> 8) & 0x7f), this->base_addr + WL3501_NIC_LMAH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* rep out to Port A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) wl3501_outsb(this->base_addr + WL3501_NIC_IODPA, src, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * wl3501_get_from_wla - Move 'size' bytes from card to PC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * @this: Card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * @src: Card addressing space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * @dest: PC addressing space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * @size: Bytes to move
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * Move 'size' bytes from card to PC. (Shouldn't be interrupted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static void wl3501_get_from_wla(struct wl3501_card *this, u16 src, void *dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* switch to SRAM Page 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) wl3501_switch_page(this, (src & 0x8000) ? WL3501_BSS_SPAGE1 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) WL3501_BSS_SPAGE0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /* set LMAL and LMAH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) wl3501_outb(src & 0xff, this->base_addr + WL3501_NIC_LMAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) wl3501_outb((src >> 8) & 0x7f, this->base_addr + WL3501_NIC_LMAH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /* rep get from Port A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) insb(this->base_addr + WL3501_NIC_IODPA, dest, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * Get/Allocate a free Tx Data Buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * *--------------*-----------------*----------------------------------*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * | PLCP | MAC Header | DST SRC Data ... |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * | (24 bytes) | (30 bytes) | (6) (6) (Ethernet Row Data) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * *--------------*-----------------*----------------------------------*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * \ \- IEEE 802.11 -/ \-------------- len --------------/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * \-struct wl3501_80211_tx_hdr--/ \-------- Ethernet Frame -------/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * Return = Position in Card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static u16 wl3501_get_tx_buffer(struct wl3501_card *this, u16 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) u16 next, blk_cnt = 0, zero = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) u16 full_len = sizeof(struct wl3501_80211_tx_hdr) + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) u16 ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (full_len > this->tx_buffer_cnt * 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ret = this->tx_buffer_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) while (full_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (full_len < 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) full_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) full_len -= 254;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) wl3501_get_from_wla(this, this->tx_buffer_head, &next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) sizeof(next));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (!full_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) wl3501_set_to_wla(this, this->tx_buffer_head, &zero,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) sizeof(zero));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) this->tx_buffer_head = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) blk_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /* if buffer is not enough */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (!next && full_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) this->tx_buffer_head = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) this->tx_buffer_cnt -= blk_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * Free an allocated Tx Buffer. ptr must be correct position.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) static void wl3501_free_tx_buffer(struct wl3501_card *this, u16 ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /* check if all space is not free */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (!this->tx_buffer_head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) this->tx_buffer_head = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) wl3501_set_to_wla(this, this->tx_buffer_tail,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) &ptr, sizeof(ptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) while (ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) u16 next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) this->tx_buffer_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) wl3501_get_from_wla(this, ptr, &next, sizeof(next));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) this->tx_buffer_tail = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) ptr = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) static int wl3501_esbq_req_test(struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) u8 tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) wl3501_get_from_wla(this, this->esbq_req_head + 3, &tmp, sizeof(tmp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return tmp & 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static void wl3501_esbq_req(struct wl3501_card *this, u16 *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) u16 tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) wl3501_set_to_wla(this, this->esbq_req_head, ptr, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) wl3501_set_to_wla(this, this->esbq_req_head + 2, &tmp, sizeof(tmp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) this->esbq_req_head += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (this->esbq_req_head >= this->esbq_req_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) this->esbq_req_head = this->esbq_req_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static int wl3501_esbq_exec(struct wl3501_card *this, void *sig, int sig_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) int rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (wl3501_esbq_req_test(this)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) u16 ptr = wl3501_get_tx_buffer(this, sig_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) wl3501_set_to_wla(this, ptr, sig, sig_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) wl3501_esbq_req(this, &ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static int wl3501_request_mib(struct wl3501_card *this, u8 index, void *bf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) struct wl3501_get_req sig = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) .sig_id = WL3501_SIG_GET_REQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) .mib_attrib = index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) int rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) spin_lock_irqsave(&this->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (wl3501_esbq_req_test(this)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) u16 ptr = wl3501_get_tx_buffer(this, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) wl3501_set_to_wla(this, ptr, &sig, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) wl3501_esbq_req(this, &ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) this->sig_get_confirm.mib_status = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) spin_unlock_irqrestore(&this->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static int wl3501_get_mib_value(struct wl3501_card *this, u8 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) void *bf, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) rc = wl3501_request_mib(this, index, bf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) rc = wait_event_interruptible(this->wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) this->sig_get_confirm.mib_status != 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) memcpy(bf, this->sig_get_confirm.mib_value, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) static int wl3501_pwr_mgmt(struct wl3501_card *this, int suspend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) struct wl3501_pwr_mgmt_req sig = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) .sig_id = WL3501_SIG_PWR_MGMT_REQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) .pwr_save = suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) .wake_up = !suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) .receive_dtims = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) int rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) spin_lock_irqsave(&this->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (wl3501_esbq_req_test(this)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) u16 ptr = wl3501_get_tx_buffer(this, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) wl3501_set_to_wla(this, ptr, &sig, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) wl3501_esbq_req(this, &ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) this->sig_pwr_mgmt_confirm.status = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) spin_unlock_irqrestore(&this->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) rc = wait_event_interruptible(this->wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) this->sig_pwr_mgmt_confirm.status != 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) printk(KERN_INFO "%s: %s status=%d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) suspend ? "suspend" : "resume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) this->sig_pwr_mgmt_confirm.status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) spin_unlock_irqrestore(&this->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * wl3501_send_pkt - Send a packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * @this: Card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) * Send a packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * data = Ethernet raw frame. (e.g. data[0] - data[5] is Dest MAC Addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * data[6] - data[11] is Src MAC Addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) * Ref: IEEE 802.11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static int wl3501_send_pkt(struct wl3501_card *this, u8 *data, u16 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) u16 bf, sig_bf, next, tmplen, pktlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct wl3501_md_req sig = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) .sig_id = WL3501_SIG_MD_REQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) size_t sig_addr_len = sizeof(sig.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) u8 *pdata = (char *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) int rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (wl3501_esbq_req_test(this)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) sig_bf = wl3501_get_tx_buffer(this, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (!sig_bf) /* No free buffer available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) bf = wl3501_get_tx_buffer(this, len + 26 + 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (!bf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) /* No free buffer available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) wl3501_free_tx_buffer(this, sig_bf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) memcpy(&sig.addr, pdata, sig_addr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) pktlen = len - sig_addr_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) pdata += sig_addr_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) sig.data = bf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (((*pdata) * 256 + (*(pdata + 1))) > 1500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) u8 addr4[ETH_ALEN] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) [0] = 0xAA, [1] = 0xAA, [2] = 0x03, [4] = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) wl3501_set_to_wla(this, bf + 2 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) offsetof(struct wl3501_tx_hdr, addr4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) addr4, sizeof(addr4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) sig.size = pktlen + 24 + 4 + 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (pktlen > (254 - sizeof(struct wl3501_tx_hdr))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) tmplen = 254 - sizeof(struct wl3501_tx_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) pktlen -= tmplen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) tmplen = pktlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) pktlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) wl3501_set_to_wla(this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) bf + 2 + sizeof(struct wl3501_tx_hdr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) pdata, tmplen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) pdata += tmplen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) wl3501_get_from_wla(this, bf, &next, sizeof(next));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) bf = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) sig.size = pktlen + 24 + 4 - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) pdata += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) pktlen -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (pktlen > (254 - sizeof(struct wl3501_tx_hdr) + 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) tmplen = 254 - sizeof(struct wl3501_tx_hdr) + 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) pktlen -= tmplen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) tmplen = pktlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) pktlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) wl3501_set_to_wla(this, bf + 2 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) offsetof(struct wl3501_tx_hdr, addr4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) pdata, tmplen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) pdata += tmplen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) wl3501_get_from_wla(this, bf, &next, sizeof(next));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) bf = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) while (pktlen > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (pktlen > 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) tmplen = 254;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) pktlen -= 254;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) tmplen = pktlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) pktlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) wl3501_set_to_wla(this, bf + 2, pdata, tmplen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) pdata += tmplen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) wl3501_get_from_wla(this, bf, &next, sizeof(next));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) bf = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) wl3501_set_to_wla(this, sig_bf, &sig, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) wl3501_esbq_req(this, &sig_bf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) static int wl3501_mgmt_resync(struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct wl3501_resync_req sig = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) .sig_id = WL3501_SIG_RESYNC_REQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return wl3501_esbq_exec(this, &sig, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) static inline int wl3501_fw_bss_type(struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) return this->net_type == IW_MODE_INFRA ? WL3501_NET_TYPE_INFRA :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) WL3501_NET_TYPE_ADHOC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) static inline int wl3501_fw_cap_info(struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return this->net_type == IW_MODE_INFRA ? WL3501_MGMT_CAPABILITY_ESS :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) WL3501_MGMT_CAPABILITY_IBSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) static int wl3501_mgmt_scan(struct wl3501_card *this, u16 chan_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct wl3501_scan_req sig = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) .sig_id = WL3501_SIG_SCAN_REQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) .scan_type = WL3501_SCAN_TYPE_ACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) .probe_delay = 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) .min_chan_time = chan_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) .max_chan_time = chan_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) .bss_type = wl3501_fw_bss_type(this),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) this->bss_cnt = this->join_sta_bss = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return wl3501_esbq_exec(this, &sig, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) static int wl3501_mgmt_join(struct wl3501_card *this, u16 stas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) struct wl3501_join_req sig = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) .sig_id = WL3501_SIG_JOIN_REQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) .timeout = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) .req.ds_pset = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) .el = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) .id = IW_MGMT_INFO_ELEMENT_DS_PARAMETER_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) .len = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) .chan = this->chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) memcpy(&sig.req, &this->bss_set[stas].req, sizeof(sig.req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return wl3501_esbq_exec(this, &sig, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) static int wl3501_mgmt_start(struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) struct wl3501_start_req sig = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) .sig_id = WL3501_SIG_START_REQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) .beacon_period = 400,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) .dtim_period = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) .ds_pset = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) .el = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) .id = IW_MGMT_INFO_ELEMENT_DS_PARAMETER_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) .len = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) .chan = this->chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) .bss_basic_rset = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) .el = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) .id = IW_MGMT_INFO_ELEMENT_SUPPORTED_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) .len = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) .data_rate_labels = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) [0] = IW_MGMT_RATE_LABEL_MANDATORY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) IW_MGMT_RATE_LABEL_1MBIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) [1] = IW_MGMT_RATE_LABEL_MANDATORY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) IW_MGMT_RATE_LABEL_2MBIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) .operational_rset = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) .el = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) .id = IW_MGMT_INFO_ELEMENT_SUPPORTED_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) .len = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) .data_rate_labels = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) [0] = IW_MGMT_RATE_LABEL_MANDATORY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) IW_MGMT_RATE_LABEL_1MBIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) [1] = IW_MGMT_RATE_LABEL_MANDATORY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) IW_MGMT_RATE_LABEL_2MBIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) .ibss_pset = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) .el = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) .id = IW_MGMT_INFO_ELEMENT_IBSS_PARAMETER_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) .len = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) .atim_window = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) .bss_type = wl3501_fw_bss_type(this),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) .cap_info = wl3501_fw_cap_info(this),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) iw_copy_mgmt_info_element(&sig.ssid.el, &this->essid.el);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) iw_copy_mgmt_info_element(&this->keep_essid.el, &this->essid.el);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return wl3501_esbq_exec(this, &sig, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) u16 i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) int matchflag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) struct wl3501_scan_confirm sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) pr_debug("entry");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) wl3501_get_from_wla(this, addr, &sig, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (sig.status == WL3501_STATUS_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) pr_debug("success");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if ((this->net_type == IW_MODE_INFRA &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) (sig.req.cap_info & WL3501_MGMT_CAPABILITY_ESS)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) (this->net_type == IW_MODE_ADHOC &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) (sig.req.cap_info & WL3501_MGMT_CAPABILITY_IBSS)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) this->net_type == IW_MODE_AUTO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (!this->essid.el.len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) matchflag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) else if (this->essid.el.len == 3 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) !memcmp(this->essid.essid, "ANY", 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) matchflag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) else if (this->essid.el.len != sig.req.ssid.el.len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) matchflag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) else if (memcmp(this->essid.essid, sig.req.ssid.essid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) this->essid.el.len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) matchflag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) matchflag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (matchflag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) for (i = 0; i < this->bss_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (ether_addr_equal_unaligned(this->bss_set[i].req.bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) sig.req.bssid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) matchflag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (matchflag && (i < 20)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) memcpy(&this->bss_set[i].req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) &sig.req, sizeof(sig.req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) this->bss_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) this->rssi = sig.rssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) this->bss_set[i].rssi = sig.rssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) } else if (sig.status == WL3501_STATUS_TIMEOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) pr_debug("timeout");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) this->join_sta_bss = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) for (i = this->join_sta_bss; i < this->bss_cnt; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (!wl3501_mgmt_join(this, i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) this->join_sta_bss = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (this->join_sta_bss == this->bss_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (this->net_type == IW_MODE_INFRA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) wl3501_mgmt_scan(this, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) this->adhoc_times++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (this->adhoc_times > WL3501_MAX_ADHOC_TRIES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) wl3501_mgmt_start(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) wl3501_mgmt_scan(this, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) * wl3501_block_interrupt - Mask interrupt from SUTRO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) * @this: Card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) * Mask interrupt from SUTRO. (i.e. SUTRO cannot interrupt the HOST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) * Return: 1 if interrupt is originally enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) static int wl3501_block_interrupt(struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) u8 old = inb(this->base_addr + WL3501_NIC_GCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) u8 new = old & (~(WL3501_GCR_ECINT | WL3501_GCR_INT2EC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) WL3501_GCR_ENECINT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) wl3501_outb(new, this->base_addr + WL3501_NIC_GCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return old & WL3501_GCR_ENECINT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) * wl3501_unblock_interrupt - Enable interrupt from SUTRO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) * @this: Card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) * Enable interrupt from SUTRO. (i.e. SUTRO can interrupt the HOST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) * Return: 1 if interrupt is originally enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) static int wl3501_unblock_interrupt(struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) u8 old = inb(this->base_addr + WL3501_NIC_GCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) u8 new = (old & ~(WL3501_GCR_ECINT | WL3501_GCR_INT2EC)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) WL3501_GCR_ENECINT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) wl3501_outb(new, this->base_addr + WL3501_NIC_GCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return old & WL3501_GCR_ENECINT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) * wl3501_receive - Receive data from Receive Queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) * Receive data from Receive Queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) * @this: card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) * @bf: address of host
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) * @size: size of buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) static u16 wl3501_receive(struct wl3501_card *this, u8 *bf, u16 size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) u16 next_addr, next_addr1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) u8 *data = bf + 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) size -= 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) wl3501_get_from_wla(this, this->start_seg + 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) &next_addr, sizeof(next_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (size > WL3501_BLKSZ - sizeof(struct wl3501_rx_hdr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) wl3501_get_from_wla(this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) this->start_seg +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) sizeof(struct wl3501_rx_hdr), data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) WL3501_BLKSZ -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) sizeof(struct wl3501_rx_hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) size -= WL3501_BLKSZ - sizeof(struct wl3501_rx_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) data += WL3501_BLKSZ - sizeof(struct wl3501_rx_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) wl3501_get_from_wla(this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) this->start_seg +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) sizeof(struct wl3501_rx_hdr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) while (size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) if (size > WL3501_BLKSZ - 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) wl3501_get_from_wla(this, next_addr + 5, data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) WL3501_BLKSZ - 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) size -= WL3501_BLKSZ - 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) data += WL3501_BLKSZ - 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) wl3501_get_from_wla(this, next_addr + 2, &next_addr1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) sizeof(next_addr1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) next_addr = next_addr1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) wl3501_get_from_wla(this, next_addr + 5, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) static void wl3501_esbq_req_free(struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) u8 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) u16 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (this->esbq_req_head == this->esbq_req_tail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) wl3501_get_from_wla(this, this->esbq_req_tail + 3, &tmp, sizeof(tmp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (!(tmp & 0x80))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) wl3501_get_from_wla(this, this->esbq_req_tail, &addr, sizeof(addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) wl3501_free_tx_buffer(this, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) this->esbq_req_tail += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (this->esbq_req_tail >= this->esbq_req_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) this->esbq_req_tail = this->esbq_req_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) static int wl3501_esbq_confirm(struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) u8 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) wl3501_get_from_wla(this, this->esbq_confirm + 3, &tmp, sizeof(tmp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) return tmp & 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) static void wl3501_online(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) printk(KERN_INFO "%s: Wireless LAN online. BSSID: %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) dev->name, this->bssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) static void wl3501_esbq_confirm_done(struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) u8 tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) wl3501_set_to_wla(this, this->esbq_confirm + 3, &tmp, sizeof(tmp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) this->esbq_confirm += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (this->esbq_confirm >= this->esbq_confirm_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) this->esbq_confirm = this->esbq_confirm_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) static int wl3501_mgmt_auth(struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) struct wl3501_auth_req sig = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) .sig_id = WL3501_SIG_AUTH_REQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) .type = WL3501_SYS_TYPE_OPEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) .timeout = 1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) pr_debug("entry");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) memcpy(sig.mac_addr, this->bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return wl3501_esbq_exec(this, &sig, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) static int wl3501_mgmt_association(struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) struct wl3501_assoc_req sig = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) .sig_id = WL3501_SIG_ASSOC_REQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) .timeout = 1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) .listen_interval = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) .cap_info = this->cap_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) pr_debug("entry");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) memcpy(sig.mac_addr, this->bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return wl3501_esbq_exec(this, &sig, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) static void wl3501_mgmt_join_confirm(struct net_device *dev, u16 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) struct wl3501_join_confirm sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) pr_debug("entry");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) wl3501_get_from_wla(this, addr, &sig, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (sig.status == WL3501_STATUS_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) if (this->net_type == IW_MODE_INFRA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (this->join_sta_bss < this->bss_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) const int i = this->join_sta_bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) memcpy(this->bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) this->bss_set[i].req.bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) this->chan = this->bss_set[i].req.ds_pset.chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) iw_copy_mgmt_info_element(&this->keep_essid.el,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) &this->bss_set[i].req.ssid.el);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) wl3501_mgmt_auth(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) const int i = this->join_sta_bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) memcpy(&this->bssid, &this->bss_set[i].req.bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) this->chan = this->bss_set[i].req.ds_pset.chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) iw_copy_mgmt_info_element(&this->keep_essid.el,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) &this->bss_set[i].req.ssid.el);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) wl3501_online(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) this->join_sta_bss++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) for (i = this->join_sta_bss; i < this->bss_cnt; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (!wl3501_mgmt_join(this, i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) this->join_sta_bss = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (this->join_sta_bss == this->bss_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (this->net_type == IW_MODE_INFRA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) wl3501_mgmt_scan(this, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) this->adhoc_times++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) if (this->adhoc_times > WL3501_MAX_ADHOC_TRIES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) wl3501_mgmt_start(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) wl3501_mgmt_scan(this, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) static inline void wl3501_alarm_interrupt(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) if (this->net_type == IW_MODE_INFRA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) printk(KERN_INFO "Wireless LAN offline\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) wl3501_mgmt_resync(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) static inline void wl3501_md_confirm_interrupt(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) struct wl3501_card *this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) u16 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct wl3501_md_confirm sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) pr_debug("entry");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) wl3501_get_from_wla(this, addr, &sig, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) wl3501_free_tx_buffer(this, sig.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (netif_queue_stopped(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) static inline void wl3501_md_ind_interrupt(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) struct wl3501_card *this, u16 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) struct wl3501_md_ind sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) u8 rssi, addr4[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) u16 pkt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) wl3501_get_from_wla(this, addr, &sig, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) this->start_seg = sig.data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) wl3501_get_from_wla(this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) sig.data + offsetof(struct wl3501_rx_hdr, rssi),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) &rssi, sizeof(rssi));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) this->rssi = rssi <= 63 ? (rssi * 100) / 64 : 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) wl3501_get_from_wla(this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) sig.data +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) offsetof(struct wl3501_rx_hdr, addr4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) &addr4, sizeof(addr4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) if (!(addr4[0] == 0xAA && addr4[1] == 0xAA &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) addr4[2] == 0x03 && addr4[4] == 0x00)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) printk(KERN_INFO "Unsupported packet type!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) pkt_len = sig.size + 12 - 24 - 4 - 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) skb = dev_alloc_skb(pkt_len + 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) printk(KERN_WARNING "%s: Can't alloc a sk_buff of size %d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) dev->name, pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) dev->stats.rx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) skb->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) skb_reserve(skb, 2); /* IP headers on 16 bytes boundaries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) skb_copy_to_linear_data(skb, (unsigned char *)&sig.addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) sizeof(sig.addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) wl3501_receive(this, skb->data, pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) skb_put(skb, pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) skb->protocol = eth_type_trans(skb, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) dev->stats.rx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) dev->stats.rx_bytes += skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) netif_rx(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) static inline void wl3501_get_confirm_interrupt(struct wl3501_card *this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) u16 addr, void *sig, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) pr_debug("entry");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) wl3501_get_from_wla(this, addr, &this->sig_get_confirm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) sizeof(this->sig_get_confirm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) wake_up(&this->wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) static inline void wl3501_start_confirm_interrupt(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) struct wl3501_card *this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) u16 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) struct wl3501_start_confirm sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) pr_debug("entry");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) wl3501_get_from_wla(this, addr, &sig, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (sig.status == WL3501_STATUS_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) static inline void wl3501_assoc_confirm_interrupt(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) u16 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) struct wl3501_assoc_confirm sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) pr_debug("entry");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) wl3501_get_from_wla(this, addr, &sig, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if (sig.status == WL3501_STATUS_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) wl3501_online(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) static inline void wl3501_auth_confirm_interrupt(struct wl3501_card *this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) u16 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) struct wl3501_auth_confirm sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) pr_debug("entry");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) wl3501_get_from_wla(this, addr, &sig, sizeof(sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if (sig.status == WL3501_STATUS_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) wl3501_mgmt_association(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) wl3501_mgmt_resync(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) static inline void wl3501_rx_interrupt(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) int morepkts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) u16 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) u8 sig_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) pr_debug("entry");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) morepkts = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (!wl3501_esbq_confirm(this))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) goto free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) wl3501_get_from_wla(this, this->esbq_confirm, &addr, sizeof(addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) wl3501_get_from_wla(this, addr + 2, &sig_id, sizeof(sig_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) switch (sig_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) case WL3501_SIG_DEAUTH_IND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) case WL3501_SIG_DISASSOC_IND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) case WL3501_SIG_ALARM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) wl3501_alarm_interrupt(dev, this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) case WL3501_SIG_MD_CONFIRM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) wl3501_md_confirm_interrupt(dev, this, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) case WL3501_SIG_MD_IND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) wl3501_md_ind_interrupt(dev, this, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) case WL3501_SIG_GET_CONFIRM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) wl3501_get_confirm_interrupt(this, addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) &this->sig_get_confirm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) sizeof(this->sig_get_confirm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) case WL3501_SIG_PWR_MGMT_CONFIRM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) wl3501_get_confirm_interrupt(this, addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) &this->sig_pwr_mgmt_confirm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) sizeof(this->sig_pwr_mgmt_confirm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) case WL3501_SIG_START_CONFIRM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) wl3501_start_confirm_interrupt(dev, this, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) case WL3501_SIG_SCAN_CONFIRM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) wl3501_mgmt_scan_confirm(this, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) case WL3501_SIG_JOIN_CONFIRM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) wl3501_mgmt_join_confirm(dev, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) case WL3501_SIG_ASSOC_CONFIRM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) wl3501_assoc_confirm_interrupt(dev, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) case WL3501_SIG_AUTH_CONFIRM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) wl3501_auth_confirm_interrupt(this, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) case WL3501_SIG_RESYNC_CONFIRM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) wl3501_mgmt_resync(this); /* FIXME: should be resync_confirm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) wl3501_esbq_confirm_done(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) morepkts = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) /* free request if necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) wl3501_esbq_req_free(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if (morepkts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) goto loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) static inline void wl3501_ack_interrupt(struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) wl3501_outb(WL3501_GCR_ECINT, this->base_addr + WL3501_NIC_GCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) * wl3501_interrupt - Hardware interrupt from card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) * @irq: Interrupt number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) * @dev_id: net_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) * We must acknowledge the interrupt as soon as possible, and block the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) * interrupt from the same card immediately to prevent re-entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) * Before accessing the Control_Status_Block, we must lock SUTRO first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) * On the other hand, to prevent SUTRO from malfunctioning, we must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) * unlock the SUTRO as soon as possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) static irqreturn_t wl3501_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) struct net_device *dev = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) struct wl3501_card *this;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) spin_lock(&this->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) wl3501_ack_interrupt(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) wl3501_block_interrupt(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) wl3501_rx_interrupt(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) wl3501_unblock_interrupt(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) spin_unlock(&this->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) static int wl3501_reset_board(struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) u8 tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) int i, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) /* Coreset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) wl3501_outb_p(WL3501_GCR_CORESET, this->base_addr + WL3501_NIC_GCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) wl3501_outb_p(0, this->base_addr + WL3501_NIC_GCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) wl3501_outb_p(WL3501_GCR_CORESET, this->base_addr + WL3501_NIC_GCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) /* Reset SRAM 0x480 to zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) wl3501_set_to_wla(this, 0x480, &tmp, sizeof(tmp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) /* Start up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) wl3501_outb_p(0, this->base_addr + WL3501_NIC_GCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) WL3501_NOPLOOP(1024 * 50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) wl3501_unblock_interrupt(this); /* acme: was commented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) /* Polling Self_Test_Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) for (i = 0; i < 10000; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) wl3501_get_from_wla(this, 0x480, &tmp, sizeof(tmp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) if (tmp == 'W') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) /* firmware complete all test successfully */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) tmp = 'A';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) wl3501_set_to_wla(this, 0x480, &tmp, sizeof(tmp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) WL3501_NOPLOOP(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) printk(KERN_WARNING "%s: failed to reset the board!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) static int wl3501_init_firmware(struct wl3501_card *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) u16 ptr, next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) int rc = wl3501_reset_board(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) this->card_name[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) wl3501_get_from_wla(this, 0x1a00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) this->card_name, sizeof(this->card_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) this->card_name[sizeof(this->card_name) - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) this->firmware_date[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) wl3501_get_from_wla(this, 0x1a40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) this->firmware_date, sizeof(this->firmware_date));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) this->firmware_date[sizeof(this->firmware_date) - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) /* Switch to SRAM Page 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) wl3501_switch_page(this, WL3501_BSS_SPAGE0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) /* Read parameter from card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) wl3501_get_from_wla(this, 0x482, &this->esbq_req_start, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) wl3501_get_from_wla(this, 0x486, &this->esbq_req_end, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) wl3501_get_from_wla(this, 0x488, &this->esbq_confirm_start, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) wl3501_get_from_wla(this, 0x48c, &this->esbq_confirm_end, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) wl3501_get_from_wla(this, 0x48e, &this->tx_buffer_head, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) wl3501_get_from_wla(this, 0x492, &this->tx_buffer_size, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) this->esbq_req_tail = this->esbq_req_head = this->esbq_req_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) this->esbq_req_end += this->esbq_req_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) this->esbq_confirm = this->esbq_confirm_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) this->esbq_confirm_end += this->esbq_confirm_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) /* Initial Tx Buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) this->tx_buffer_cnt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) ptr = this->tx_buffer_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) next = ptr + WL3501_BLKSZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) while ((next - this->tx_buffer_head) < this->tx_buffer_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) this->tx_buffer_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) wl3501_set_to_wla(this, ptr, &next, sizeof(next));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) ptr = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) next = ptr + WL3501_BLKSZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) next = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) wl3501_set_to_wla(this, ptr, &next, sizeof(next));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) this->tx_buffer_tail = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) printk(KERN_WARNING "%s: failed!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) static int wl3501_close(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) struct pcmcia_device *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) link = this->p_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) spin_lock_irqsave(&this->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) link->open--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) /* Stop wl3501_hard_start_xmit() from now on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) wl3501_ack_interrupt(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) /* Mask interrupts from the SUTRO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) wl3501_block_interrupt(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) printk(KERN_INFO "%s: WL3501 closed\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) spin_unlock_irqrestore(&this->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) * wl3501_reset - Reset the SUTRO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) * @dev: network device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) * It is almost the same as wl3501_open(). In fact, we may just wl3501_close()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) * and wl3501_open() again, but I wouldn't like to free_irq() when the driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) * is running. It seems to be dangerous.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) static int wl3501_reset(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) int rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) spin_lock_irqsave(&this->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) wl3501_block_interrupt(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (wl3501_init_firmware(this)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) printk(KERN_WARNING "%s: Can't initialize Firmware!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) /* Free IRQ, and mark IRQ as unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) free_irq(dev->irq, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) * Queue has to be started only when the Card is Started
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) this->adhoc_times = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) wl3501_ack_interrupt(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) wl3501_unblock_interrupt(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) wl3501_mgmt_scan(this, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) pr_debug("%s: device reset", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) spin_unlock_irqrestore(&this->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) static void wl3501_tx_timeout(struct net_device *dev, unsigned int txqueue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) struct net_device_stats *stats = &dev->stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) stats->tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) rc = wl3501_reset(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) printk(KERN_ERR "%s: Error %d resetting card on Tx timeout!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) dev->name, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) netif_trans_update(dev); /* prevent tx timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) * Return : 0 - OK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) * 1 - Could not transmit (dev_queue_xmit will queue it)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) * and try to sent it later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) static netdev_tx_t wl3501_hard_start_xmit(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) int enabled, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) spin_lock_irqsave(&this->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) enabled = wl3501_block_interrupt(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) rc = wl3501_send_pkt(this, skb->data, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) if (enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) wl3501_unblock_interrupt(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) ++dev->stats.tx_dropped;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) ++dev->stats.tx_packets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) dev->stats.tx_bytes += skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) if (this->tx_buffer_cnt < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) spin_unlock_irqrestore(&this->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) static int wl3501_open(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) int rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) struct pcmcia_device *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) link = this->p_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) spin_lock_irqsave(&this->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (!pcmcia_dev_present(link))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) netif_device_attach(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) link->open++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) /* Initial WL3501 firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) pr_debug("%s: Initialize WL3501 firmware...", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) if (wl3501_init_firmware(this))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) /* Initial device variables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) this->adhoc_times = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) /* Acknowledge Interrupt, for cleaning last state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) wl3501_ack_interrupt(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) /* Enable interrupt from card after all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) wl3501_unblock_interrupt(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) wl3501_mgmt_scan(this, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) pr_debug("%s: WL3501 opened", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) printk(KERN_INFO "%s: Card Name: %s\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) "%s: Firmware Date: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) dev->name, this->card_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) dev->name, this->firmware_date);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) spin_unlock_irqrestore(&this->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) printk(KERN_WARNING "%s: Can't initialize firmware!\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) static struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) struct iw_statistics *wstats = &this->wstats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) u32 value; /* size checked: it is u32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) memset(wstats, 0, sizeof(*wstats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) wstats->status = netif_running(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_WEP_ICV_ERROR_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) &value, sizeof(value)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) wstats->discard.code += value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_WEP_UNDECRYPTABLE_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) &value, sizeof(value)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) wstats->discard.code += value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_WEP_EXCLUDED_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) &value, sizeof(value)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) wstats->discard.code += value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_RETRY_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) &value, sizeof(value)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) wstats->discard.retries = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_FAILED_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) &value, sizeof(value)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) wstats->discard.misc += value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_RTS_FAILURE_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) &value, sizeof(value)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) wstats->discard.misc += value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_ACK_FAILURE_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) &value, sizeof(value)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) wstats->discard.misc += value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_FRAME_DUPLICATE_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) &value, sizeof(value)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) wstats->discard.misc += value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) return wstats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) * wl3501_detach - deletes a driver "instance"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) * @link: FILL_IN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) * This deletes a driver "instance". The device is de-registered with Card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) * Services. If it has been released, all local data structures are freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) * Otherwise, the structures will be freed when the device is released.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) static void wl3501_detach(struct pcmcia_device *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) struct net_device *dev = link->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) /* If the device is currently configured and active, we won't actually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) * delete it yet. Instead, it is marked so that when the release()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) * function is called, that will trigger a proper detach(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) while (link->open > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) wl3501_close(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) netif_device_detach(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) wl3501_release(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) unregister_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) static int wl3501_get_name(struct net_device *dev, struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) strlcpy(wrqu->name, "IEEE 802.11-DS", sizeof(wrqu->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) static int wl3501_set_freq(struct net_device *dev, struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) int channel = wrqu->freq.m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) if (iw_valid_channel(this->reg_domain, channel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) this->chan = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) rc = wl3501_reset(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) static int wl3501_get_freq(struct net_device *dev, struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) wrqu->freq.m = 100000 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) ieee80211_channel_to_frequency(this->chan, NL80211_BAND_2GHZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) wrqu->freq.e = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) static int wl3501_set_mode(struct net_device *dev, struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) if (wrqu->mode == IW_MODE_INFRA ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) wrqu->mode == IW_MODE_ADHOC ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) wrqu->mode == IW_MODE_AUTO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) this->net_type = wrqu->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) rc = wl3501_reset(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) static int wl3501_get_mode(struct net_device *dev, struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) wrqu->mode = this->net_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) static int wl3501_get_sens(struct net_device *dev, struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) wrqu->sens.value = this->rssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) wrqu->sens.disabled = !wrqu->sens.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) wrqu->sens.fixed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) static int wl3501_get_range(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) struct iw_range *range = (struct iw_range *)extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) /* Set the length (very important for backward compatibility) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) wrqu->data.length = sizeof(*range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) /* Set all the info we don't care or don't know about to zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) memset(range, 0, sizeof(*range));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) /* Set the Wireless Extension versions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) range->we_version_compiled = WIRELESS_EXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) range->we_version_source = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) range->throughput = 2 * 1000 * 1000; /* ~2 Mb/s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) /* FIXME: study the code to fill in more fields... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) static int wl3501_set_wap(struct net_device *dev, struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) /* FIXME: we support other ARPHRDs...*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) if (is_broadcast_ether_addr(wrqu->ap_addr.sa_data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) /* FIXME: rescan? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) memcpy(this->bssid, wrqu->ap_addr.sa_data, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) /* FIXME: rescan? deassoc & scan? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) static int wl3501_get_wap(struct net_device *dev, struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) wrqu->ap_addr.sa_family = ARPHRD_ETHER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) memcpy(wrqu->ap_addr.sa_data, this->bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) static int wl3501_set_scan(struct net_device *dev, struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) * FIXME: trigger scanning with a reset, yes, I'm lazy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) return wl3501_reset(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) static int wl3501_get_scan(struct net_device *dev, struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) char *current_ev = extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) struct iw_event iwe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) for (i = 0; i < this->bss_cnt; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) iwe.cmd = SIOCGIWAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) memcpy(iwe.u.ap_addr.sa_data, this->bss_set[i].req.bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) current_ev = iwe_stream_add_event(info, current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) extra + IW_SCAN_MAX_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) &iwe, IW_EV_ADDR_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) iwe.cmd = SIOCGIWESSID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) iwe.u.data.flags = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) iwe.u.data.length = this->bss_set[i].req.ssid.el.len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) current_ev = iwe_stream_add_point(info, current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) extra + IW_SCAN_MAX_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) &iwe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) this->bss_set[i].req.ssid.essid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) iwe.cmd = SIOCGIWMODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) iwe.u.mode = this->bss_set[i].req.bss_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) current_ev = iwe_stream_add_event(info, current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) extra + IW_SCAN_MAX_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) &iwe, IW_EV_UINT_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) iwe.cmd = SIOCGIWFREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) iwe.u.freq.m = this->bss_set[i].req.ds_pset.chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) iwe.u.freq.e = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) current_ev = iwe_stream_add_event(info, current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) extra + IW_SCAN_MAX_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) &iwe, IW_EV_FREQ_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) iwe.cmd = SIOCGIWENCODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) if (this->bss_set[i].req.cap_info & WL3501_MGMT_CAPABILITY_PRIVACY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) iwe.u.data.flags = IW_ENCODE_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) iwe.u.data.length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) current_ev = iwe_stream_add_point(info, current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) extra + IW_SCAN_MAX_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) &iwe, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) /* Length of data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) wrqu->data.length = (current_ev - extra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) wrqu->data.flags = 0; /* FIXME: set properly these flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) static int wl3501_set_essid(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) if (wrqu->data.flags) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) iw_set_mgmt_info_element(IW_MGMT_INFO_ELEMENT_SSID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) &this->essid.el,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) extra, wrqu->data.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) } else { /* We accept any ESSID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) iw_set_mgmt_info_element(IW_MGMT_INFO_ELEMENT_SSID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) &this->essid.el, "ANY", 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) return wl3501_reset(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) static int wl3501_get_essid(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) spin_lock_irqsave(&this->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) wrqu->essid.flags = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) wrqu->essid.length = this->essid.el.len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) memcpy(extra, this->essid.essid, this->essid.el.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) spin_unlock_irqrestore(&this->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) static int wl3501_set_nick(struct net_device *dev, struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) if (wrqu->data.length > sizeof(this->nick))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) return -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) strlcpy(this->nick, extra, wrqu->data.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) static int wl3501_get_nick(struct net_device *dev, struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) strlcpy(extra, this->nick, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) wrqu->data.length = strlen(extra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) static int wl3501_get_rate(struct net_device *dev, struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) * FIXME: have to see from where to get this info, perhaps this card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) * works at 1 Mbit/s too... for now leave at 2 Mbit/s that is the most
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) * common with the Planet Access Points. -acme
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) wrqu->bitrate.value = 2000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) wrqu->bitrate.fixed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) static int wl3501_get_rts_threshold(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) u16 threshold; /* size checked: it is u16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) int rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_RTS_THRESHOLD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) &threshold, sizeof(threshold));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) wrqu->rts.value = threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) wrqu->rts.disabled = threshold >= 2347;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) wrqu->rts.fixed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) static int wl3501_get_frag_threshold(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) u16 threshold; /* size checked: it is u16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) int rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_FRAG_THRESHOLD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) &threshold, sizeof(threshold));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) wrqu->frag.value = threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) wrqu->frag.disabled = threshold >= 2346;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) wrqu->frag.fixed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) static int wl3501_get_txpow(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) u16 txpow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) int rc = wl3501_get_mib_value(this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) WL3501_MIB_ATTR_CURRENT_TX_PWR_LEVEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) &txpow, sizeof(txpow));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) wrqu->txpower.value = txpow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) wrqu->txpower.disabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) * From the MIB values I think this can be configurable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) * as it lists several tx power levels -acme
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) wrqu->txpower.fixed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) wrqu->txpower.flags = IW_TXPOW_MWATT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) static int wl3501_get_retry(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) u8 retry; /* size checked: it is u8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) int rc = wl3501_get_mib_value(this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) WL3501_MIB_ATTR_LONG_RETRY_LIMIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) &retry, sizeof(retry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) if (wrqu->retry.flags & IW_RETRY_LONG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) goto set_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_SHORT_RETRY_LIMIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) &retry, sizeof(retry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) set_value:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) wrqu->retry.value = retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) wrqu->retry.disabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) static int wl3501_get_encode(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) u8 implemented, restricted, keys[100], len_keys, tocopy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) int rc = wl3501_get_mib_value(this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) WL3501_MIB_ATTR_PRIV_OPT_IMPLEMENTED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) &implemented, sizeof(implemented));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) if (!implemented) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) wrqu->encoding.flags = IW_ENCODE_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_EXCLUDE_UNENCRYPTED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) &restricted, sizeof(restricted));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) wrqu->encoding.flags = restricted ? IW_ENCODE_RESTRICTED :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) IW_ENCODE_OPEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_WEP_KEY_MAPPINGS_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) &len_keys, sizeof(len_keys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_WEP_KEY_MAPPINGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) keys, len_keys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) tocopy = min_t(u16, len_keys, wrqu->encoding.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) tocopy = min_t(u8, tocopy, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) wrqu->encoding.length = tocopy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) memcpy(extra, keys, tocopy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) static int wl3501_get_power(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) u8 pwr_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) struct wl3501_card *this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) int rc = wl3501_get_mib_value(this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) WL3501_MIB_ATTR_CURRENT_PWR_STATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) &pwr_state, sizeof(pwr_state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) wrqu->power.disabled = !pwr_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) wrqu->power.flags = IW_POWER_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) static const iw_handler wl3501_handler[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) IW_HANDLER(SIOCGIWNAME, wl3501_get_name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) IW_HANDLER(SIOCSIWFREQ, wl3501_set_freq),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) IW_HANDLER(SIOCGIWFREQ, wl3501_get_freq),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) IW_HANDLER(SIOCSIWMODE, wl3501_set_mode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) IW_HANDLER(SIOCGIWMODE, wl3501_get_mode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) IW_HANDLER(SIOCGIWSENS, wl3501_get_sens),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) IW_HANDLER(SIOCGIWRANGE, wl3501_get_range),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) IW_HANDLER(SIOCSIWAP, wl3501_set_wap),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) IW_HANDLER(SIOCGIWAP, wl3501_get_wap),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) IW_HANDLER(SIOCSIWSCAN, wl3501_set_scan),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) IW_HANDLER(SIOCGIWSCAN, wl3501_get_scan),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) IW_HANDLER(SIOCSIWESSID, wl3501_set_essid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) IW_HANDLER(SIOCGIWESSID, wl3501_get_essid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) IW_HANDLER(SIOCSIWNICKN, wl3501_set_nick),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) IW_HANDLER(SIOCGIWNICKN, wl3501_get_nick),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) IW_HANDLER(SIOCGIWRATE, wl3501_get_rate),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) IW_HANDLER(SIOCGIWRTS, wl3501_get_rts_threshold),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) IW_HANDLER(SIOCGIWFRAG, wl3501_get_frag_threshold),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) IW_HANDLER(SIOCGIWTXPOW, wl3501_get_txpow),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) IW_HANDLER(SIOCGIWRETRY, wl3501_get_retry),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) IW_HANDLER(SIOCGIWENCODE, wl3501_get_encode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) IW_HANDLER(SIOCGIWPOWER, wl3501_get_power),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) static const struct iw_handler_def wl3501_handler_def = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) .num_standard = ARRAY_SIZE(wl3501_handler),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) .standard = (iw_handler *)wl3501_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) .get_wireless_stats = wl3501_get_wireless_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) static const struct net_device_ops wl3501_netdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) .ndo_open = wl3501_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) .ndo_stop = wl3501_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) .ndo_start_xmit = wl3501_hard_start_xmit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) .ndo_tx_timeout = wl3501_tx_timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) .ndo_set_mac_address = eth_mac_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) .ndo_validate_addr = eth_validate_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) static int wl3501_probe(struct pcmcia_device *p_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) struct wl3501_card *this;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) /* The io structure describes IO port mapping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) p_dev->resource[0]->end = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) p_dev->resource[0]->flags = IO_DATA_PATH_WIDTH_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) /* General socket configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) p_dev->config_flags = CONF_ENABLE_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) p_dev->config_index = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) dev = alloc_etherdev(sizeof(struct wl3501_card));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) goto out_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) dev->netdev_ops = &wl3501_netdev_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) dev->watchdog_timeo = 5 * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) this->wireless_data.spy_data = &this->spy_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) this->p_dev = p_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) dev->wireless_data = &this->wireless_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) dev->wireless_handlers = &wl3501_handler_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) p_dev->priv = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) return wl3501_config(p_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) out_link:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) static int wl3501_config(struct pcmcia_device *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) struct net_device *dev = link->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) int i = 0, j, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) struct wl3501_card *this;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) /* Try allocating IO ports. This tries a few fixed addresses. If you
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) * want, you can also read the card's config table to pick addresses --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) * see the serial driver for an example. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) link->io_lines = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) for (j = 0x280; j < 0x400; j += 0x20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) /* The '^0x300' is so that we probe 0x300-0x3ff first, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) * 0x200-0x2ff, and so on, because this seems safer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) link->resource[0]->start = j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) link->resource[1]->start = link->resource[0]->start + 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) i = pcmcia_request_io(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) if (i == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) if (i != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) /* Now allocate an interrupt line. Note that this does not actually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) * assign a handler to the interrupt. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) ret = pcmcia_request_irq(link, wl3501_interrupt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) ret = pcmcia_enable_device(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) dev->irq = link->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) dev->base_addr = link->resource[0]->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) SET_NETDEV_DEV(dev, &link->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) if (register_netdev(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) this = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) this->base_addr = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) if (!wl3501_get_flash_mac_addr(this)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) printk(KERN_WARNING "%s: Can't read MAC addr in flash ROM?\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) unregister_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) for (i = 0; i < 6; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) dev->dev_addr[i] = ((char *)&this->mac_addr)[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) /* print probe information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) printk(KERN_INFO "%s: wl3501 @ 0x%3.3x, IRQ %d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) "MAC addr in flash ROM:%pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) dev->name, this->base_addr, (int)dev->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) dev->dev_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) * Initialize card parameters - added by jss
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) this->net_type = IW_MODE_INFRA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) this->bss_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) this->join_sta_bss = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) this->adhoc_times = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) iw_set_mgmt_info_element(IW_MGMT_INFO_ELEMENT_SSID, &this->essid.el,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) "ANY", 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) this->card_name[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) this->firmware_date[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) this->rssi = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) this->chan = iw_default_channel(this->reg_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) strlcpy(this->nick, "Planet WL3501", sizeof(this->nick));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) spin_lock_init(&this->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) init_waitqueue_head(&this->wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) netif_start_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) wl3501_release(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) static void wl3501_release(struct pcmcia_device *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) pcmcia_disable_device(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) static int wl3501_suspend(struct pcmcia_device *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) struct net_device *dev = link->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) wl3501_pwr_mgmt(netdev_priv(dev), WL3501_SUSPEND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) if (link->open)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) netif_device_detach(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) static int wl3501_resume(struct pcmcia_device *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) struct net_device *dev = link->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) wl3501_pwr_mgmt(netdev_priv(dev), WL3501_RESUME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) if (link->open) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) wl3501_reset(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) netif_device_attach(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) static const struct pcmcia_device_id wl3501_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0001),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) PCMCIA_DEVICE_NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) MODULE_DEVICE_TABLE(pcmcia, wl3501_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) static struct pcmcia_driver wl3501_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) .name = "wl3501_cs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) .probe = wl3501_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) .remove = wl3501_detach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) .id_table = wl3501_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) .suspend = wl3501_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) .resume = wl3501_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) module_pcmcia_driver(wl3501_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) MODULE_AUTHOR("Fox Chen <mhchen@golf.ccl.itri.org.tw>, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) "Arnaldo Carvalho de Melo <acme@conectiva.com.br>,"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) "Gustavo Niemeyer <niemeyer@conectiva.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) MODULE_DESCRIPTION("Planet wl3501 wireless driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) MODULE_LICENSE("GPL");