diff options
| author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-19 21:50:43 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-19 21:50:43 -0400 |
| commit | 2090af718014f3d434fb8b85b00eeea01ebcec19 (patch) | |
| tree | 97eb6e655a3c2d90c212de79b563fa35837a341f /drivers/net/wireless | |
| parent | 557240b48e2dc4f6fa878afc3fc767ad745ca7ed (diff) | |
| parent | 4b6ace7f02cddb8c363ad27bb1e5014c6791e34a (diff) | |
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6: (166 commits)
[PATCH] net: au1000_eth: PHY framework conversion
[PATCH] 3c5zz ethernet: fix section warnings
[PATCH] smc ethernet: fix section mismatch warnings
[PATCH] hp ethernet: fix section mismatches
[PATCH] Section mismatch in drivers/net/ne.o during modpost
[PATCH] e1000: prevent statistics from getting garbled during reset
[PATCH] smc911x Kconfig fix
[PATCH] forcedeth: new device ids
[PATCH] forcedeth config: version
[PATCH] forcedeth config: module parameters
[PATCH] forcedeth config: diagnostics
[PATCH] forcedeth config: move functions
[PATCH] forcedeth config: statistics
[PATCH] forcedeth config: csum
[PATCH] forcedeth config: wol
[PATCH] forcedeth config: phy
[PATCH] forcedeth config: flow control
[PATCH] forcedeth config: ring sizes
[PATCH] forcedeth config: tso cleanup
[DOC] Update bonding documentation with sysfs info
...
Diffstat (limited to 'drivers/net/wireless')
25 files changed, 3644 insertions, 1065 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index e0874cbfefea..30ec235e6935 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
| @@ -235,7 +235,35 @@ config IPW2200_MONITOR | |||
| 235 | promiscuous mode via the Wireless Tool's Monitor mode. While in this | 235 | promiscuous mode via the Wireless Tool's Monitor mode. While in this |
| 236 | mode, no packets can be sent. | 236 | mode, no packets can be sent. |
| 237 | 237 | ||
| 238 | config IPW_QOS | 238 | config IPW2200_RADIOTAP |
| 239 | bool "Enable radiotap format 802.11 raw packet support" | ||
| 240 | depends on IPW2200_MONITOR | ||
| 241 | |||
| 242 | config IPW2200_PROMISCUOUS | ||
| 243 | bool "Enable creation of a RF radiotap promiscuous interface" | ||
| 244 | depends on IPW2200_MONITOR | ||
| 245 | select IPW2200_RADIOTAP | ||
| 246 | ---help--- | ||
| 247 | Enables the creation of a second interface prefixed 'rtap'. | ||
| 248 | This second interface will provide every received in radiotap | ||
| 249 | format. | ||
| 250 | |||
| 251 | This is useful for performing wireless network analysis while | ||
| 252 | maintaining an active association. | ||
| 253 | |||
| 254 | Example usage: | ||
| 255 | |||
| 256 | % modprobe ipw2200 rtap_iface=1 | ||
| 257 | % ifconfig rtap0 up | ||
| 258 | % tethereal -i rtap0 | ||
| 259 | |||
| 260 | If you do not specify 'rtap_iface=1' as a module parameter then | ||
| 261 | the rtap interface will not be created and you will need to turn | ||
| 262 | it on via sysfs: | ||
| 263 | |||
| 264 | % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface | ||
| 265 | |||
| 266 | config IPW2200_QOS | ||
| 239 | bool "Enable QoS support" | 267 | bool "Enable QoS support" |
| 240 | depends on IPW2200 && EXPERIMENTAL | 268 | depends on IPW2200 && EXPERIMENTAL |
| 241 | 269 | ||
| @@ -503,6 +531,23 @@ config PRISM54 | |||
| 503 | say M here and read <file:Documentation/modules.txt>. The module | 531 | say M here and read <file:Documentation/modules.txt>. The module |
| 504 | will be called prism54.ko. | 532 | will be called prism54.ko. |
| 505 | 533 | ||
| 534 | config USB_ZD1201 | ||
| 535 | tristate "USB ZD1201 based Wireless device support" | ||
| 536 | depends on USB && NET_RADIO | ||
| 537 | select FW_LOADER | ||
| 538 | ---help--- | ||
| 539 | Say Y if you want to use wireless LAN adapters based on the ZyDAS | ||
| 540 | ZD1201 chip. | ||
| 541 | |||
| 542 | This driver makes the adapter appear as a normal Ethernet interface, | ||
| 543 | typically on wlan0. | ||
| 544 | |||
| 545 | The zd1201 device requires external firmware to be loaded. | ||
| 546 | This can be found at http://linux-lc100020.sourceforge.net/ | ||
| 547 | |||
| 548 | To compile this driver as a module, choose M here: the | ||
| 549 | module will be called zd1201. | ||
| 550 | |||
| 506 | source "drivers/net/wireless/hostap/Kconfig" | 551 | source "drivers/net/wireless/hostap/Kconfig" |
| 507 | source "drivers/net/wireless/bcm43xx/Kconfig" | 552 | source "drivers/net/wireless/bcm43xx/Kconfig" |
| 508 | 553 | ||
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index c86779879361..512603de309a 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile | |||
| @@ -40,3 +40,5 @@ obj-$(CONFIG_BCM43XX) += bcm43xx/ | |||
| 40 | # 16-bit wireless PCMCIA client drivers | 40 | # 16-bit wireless PCMCIA client drivers |
| 41 | obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o | 41 | obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o |
| 42 | obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o | 42 | obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o |
| 43 | |||
| 44 | obj-$(CONFIG_USB_ZD1201) += zd1201.o | ||
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 00764ddd74d8..4069b79d8259 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | #include <linux/ioport.h> | 47 | #include <linux/ioport.h> |
| 48 | #include <linux/pci.h> | 48 | #include <linux/pci.h> |
| 49 | #include <asm/uaccess.h> | 49 | #include <asm/uaccess.h> |
| 50 | #include <net/ieee80211.h> | ||
| 50 | 51 | ||
| 51 | #include "airo.h" | 52 | #include "airo.h" |
| 52 | 53 | ||
| @@ -467,6 +468,8 @@ static int do8bitIO = 0; | |||
| 467 | #define RID_ECHOTEST_RESULTS 0xFF71 | 468 | #define RID_ECHOTEST_RESULTS 0xFF71 |
| 468 | #define RID_BSSLISTFIRST 0xFF72 | 469 | #define RID_BSSLISTFIRST 0xFF72 |
| 469 | #define RID_BSSLISTNEXT 0xFF73 | 470 | #define RID_BSSLISTNEXT 0xFF73 |
| 471 | #define RID_WPA_BSSLISTFIRST 0xFF74 | ||
| 472 | #define RID_WPA_BSSLISTNEXT 0xFF75 | ||
| 470 | 473 | ||
| 471 | typedef struct { | 474 | typedef struct { |
| 472 | u16 cmd; | 475 | u16 cmd; |
| @@ -739,6 +742,14 @@ typedef struct { | |||
| 739 | u16 extSoftCap; | 742 | u16 extSoftCap; |
| 740 | } CapabilityRid; | 743 | } CapabilityRid; |
| 741 | 744 | ||
| 745 | |||
| 746 | /* Only present on firmware >= 5.30.17 */ | ||
| 747 | typedef struct { | ||
| 748 | u16 unknown[4]; | ||
| 749 | u8 fixed[12]; /* WLAN management frame */ | ||
| 750 | u8 iep[624]; | ||
| 751 | } BSSListRidExtra; | ||
| 752 | |||
| 742 | typedef struct { | 753 | typedef struct { |
| 743 | u16 len; | 754 | u16 len; |
| 744 | u16 index; /* First is 0 and 0xffff means end of list */ | 755 | u16 index; /* First is 0 and 0xffff means end of list */ |
| @@ -767,6 +778,9 @@ typedef struct { | |||
| 767 | } fh; | 778 | } fh; |
| 768 | u16 dsChannel; | 779 | u16 dsChannel; |
| 769 | u16 atimWindow; | 780 | u16 atimWindow; |
| 781 | |||
| 782 | /* Only present on firmware >= 5.30.17 */ | ||
| 783 | BSSListRidExtra extra; | ||
| 770 | } BSSListRid; | 784 | } BSSListRid; |
| 771 | 785 | ||
| 772 | typedef struct { | 786 | typedef struct { |
| @@ -1140,8 +1154,6 @@ struct airo_info { | |||
| 1140 | char defindex; // Used with auto wep | 1154 | char defindex; // Used with auto wep |
| 1141 | struct proc_dir_entry *proc_entry; | 1155 | struct proc_dir_entry *proc_entry; |
| 1142 | spinlock_t aux_lock; | 1156 | spinlock_t aux_lock; |
| 1143 | unsigned long flags; | ||
| 1144 | #define FLAG_PROMISC 8 /* IFF_PROMISC 0x100 - include/linux/if.h */ | ||
| 1145 | #define FLAG_RADIO_OFF 0 /* User disabling of MAC */ | 1157 | #define FLAG_RADIO_OFF 0 /* User disabling of MAC */ |
| 1146 | #define FLAG_RADIO_DOWN 1 /* ifup/ifdown disabling of MAC */ | 1158 | #define FLAG_RADIO_DOWN 1 /* ifup/ifdown disabling of MAC */ |
| 1147 | #define FLAG_RADIO_MASK 0x03 | 1159 | #define FLAG_RADIO_MASK 0x03 |
| @@ -1151,6 +1163,7 @@ struct airo_info { | |||
| 1151 | #define FLAG_UPDATE_MULTI 5 | 1163 | #define FLAG_UPDATE_MULTI 5 |
| 1152 | #define FLAG_UPDATE_UNI 6 | 1164 | #define FLAG_UPDATE_UNI 6 |
| 1153 | #define FLAG_802_11 7 | 1165 | #define FLAG_802_11 7 |
| 1166 | #define FLAG_PROMISC 8 /* IFF_PROMISC 0x100 - include/linux/if.h */ | ||
| 1154 | #define FLAG_PENDING_XMIT 9 | 1167 | #define FLAG_PENDING_XMIT 9 |
| 1155 | #define FLAG_PENDING_XMIT11 10 | 1168 | #define FLAG_PENDING_XMIT11 10 |
| 1156 | #define FLAG_MPI 11 | 1169 | #define FLAG_MPI 11 |
| @@ -1158,17 +1171,19 @@ struct airo_info { | |||
| 1158 | #define FLAG_COMMIT 13 | 1171 | #define FLAG_COMMIT 13 |
| 1159 | #define FLAG_RESET 14 | 1172 | #define FLAG_RESET 14 |
| 1160 | #define FLAG_FLASHING 15 | 1173 | #define FLAG_FLASHING 15 |
| 1161 | #define JOB_MASK 0x2ff0000 | 1174 | #define FLAG_WPA_CAPABLE 16 |
| 1162 | #define JOB_DIE 16 | 1175 | unsigned long flags; |
| 1163 | #define JOB_XMIT 17 | 1176 | #define JOB_DIE 0 |
| 1164 | #define JOB_XMIT11 18 | 1177 | #define JOB_XMIT 1 |
| 1165 | #define JOB_STATS 19 | 1178 | #define JOB_XMIT11 2 |
| 1166 | #define JOB_PROMISC 20 | 1179 | #define JOB_STATS 3 |
| 1167 | #define JOB_MIC 21 | 1180 | #define JOB_PROMISC 4 |
| 1168 | #define JOB_EVENT 22 | 1181 | #define JOB_MIC 5 |
| 1169 | #define JOB_AUTOWEP 23 | 1182 | #define JOB_EVENT 6 |
| 1170 | #define JOB_WSTATS 24 | 1183 | #define JOB_AUTOWEP 7 |
| 1171 | #define JOB_SCAN_RESULTS 25 | 1184 | #define JOB_WSTATS 8 |
| 1185 | #define JOB_SCAN_RESULTS 9 | ||
| 1186 | unsigned long jobs; | ||
| 1172 | int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen, | 1187 | int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen, |
| 1173 | int whichbap); | 1188 | int whichbap); |
| 1174 | unsigned short *flash; | 1189 | unsigned short *flash; |
| @@ -1208,6 +1223,11 @@ struct airo_info { | |||
| 1208 | #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE | 1223 | #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE |
| 1209 | char proc_name[IFNAMSIZ]; | 1224 | char proc_name[IFNAMSIZ]; |
| 1210 | 1225 | ||
| 1226 | /* WPA-related stuff */ | ||
| 1227 | unsigned int bssListFirst; | ||
| 1228 | unsigned int bssListNext; | ||
| 1229 | unsigned int bssListRidLen; | ||
| 1230 | |||
| 1211 | struct list_head network_list; | 1231 | struct list_head network_list; |
| 1212 | struct list_head network_free_list; | 1232 | struct list_head network_free_list; |
| 1213 | BSSListElement *networks; | 1233 | BSSListElement *networks; |
| @@ -1264,7 +1284,7 @@ static void micinit(struct airo_info *ai) | |||
| 1264 | { | 1284 | { |
| 1265 | MICRid mic_rid; | 1285 | MICRid mic_rid; |
| 1266 | 1286 | ||
| 1267 | clear_bit(JOB_MIC, &ai->flags); | 1287 | clear_bit(JOB_MIC, &ai->jobs); |
| 1268 | PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0); | 1288 | PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0); |
| 1269 | up(&ai->sem); | 1289 | up(&ai->sem); |
| 1270 | 1290 | ||
| @@ -1705,24 +1725,24 @@ static void emmh32_final(emmh32_context *context, u8 digest[4]) | |||
| 1705 | static int readBSSListRid(struct airo_info *ai, int first, | 1725 | static int readBSSListRid(struct airo_info *ai, int first, |
| 1706 | BSSListRid *list) { | 1726 | BSSListRid *list) { |
| 1707 | int rc; | 1727 | int rc; |
| 1708 | Cmd cmd; | 1728 | Cmd cmd; |
| 1709 | Resp rsp; | 1729 | Resp rsp; |
| 1710 | 1730 | ||
| 1711 | if (first == 1) { | 1731 | if (first == 1) { |
| 1712 | if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN; | 1732 | if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN; |
| 1713 | memset(&cmd, 0, sizeof(cmd)); | 1733 | memset(&cmd, 0, sizeof(cmd)); |
| 1714 | cmd.cmd=CMD_LISTBSS; | 1734 | cmd.cmd=CMD_LISTBSS; |
| 1715 | if (down_interruptible(&ai->sem)) | 1735 | if (down_interruptible(&ai->sem)) |
| 1716 | return -ERESTARTSYS; | 1736 | return -ERESTARTSYS; |
| 1717 | issuecommand(ai, &cmd, &rsp); | 1737 | issuecommand(ai, &cmd, &rsp); |
| 1718 | up(&ai->sem); | 1738 | up(&ai->sem); |
| 1719 | /* Let the command take effect */ | 1739 | /* Let the command take effect */ |
| 1720 | ai->task = current; | 1740 | ai->task = current; |
| 1721 | ssleep(3); | 1741 | ssleep(3); |
| 1722 | ai->task = NULL; | 1742 | ai->task = NULL; |
| 1723 | } | 1743 | } |
| 1724 | rc = PC4500_readrid(ai, first ? RID_BSSLISTFIRST : RID_BSSLISTNEXT, | 1744 | rc = PC4500_readrid(ai, first ? ai->bssListFirst : ai->bssListNext, |
| 1725 | list, sizeof(*list), 1); | 1745 | list, ai->bssListRidLen, 1); |
| 1726 | 1746 | ||
| 1727 | list->len = le16_to_cpu(list->len); | 1747 | list->len = le16_to_cpu(list->len); |
| 1728 | list->index = le16_to_cpu(list->index); | 1748 | list->index = le16_to_cpu(list->index); |
| @@ -2112,7 +2132,7 @@ static void airo_end_xmit(struct net_device *dev) { | |||
| 2112 | int fid = priv->xmit.fid; | 2132 | int fid = priv->xmit.fid; |
| 2113 | u32 *fids = priv->fids; | 2133 | u32 *fids = priv->fids; |
| 2114 | 2134 | ||
| 2115 | clear_bit(JOB_XMIT, &priv->flags); | 2135 | clear_bit(JOB_XMIT, &priv->jobs); |
| 2116 | clear_bit(FLAG_PENDING_XMIT, &priv->flags); | 2136 | clear_bit(FLAG_PENDING_XMIT, &priv->flags); |
| 2117 | status = transmit_802_3_packet (priv, fids[fid], skb->data); | 2137 | status = transmit_802_3_packet (priv, fids[fid], skb->data); |
| 2118 | up(&priv->sem); | 2138 | up(&priv->sem); |
| @@ -2162,7 +2182,7 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { | |||
| 2162 | if (down_trylock(&priv->sem) != 0) { | 2182 | if (down_trylock(&priv->sem) != 0) { |
| 2163 | set_bit(FLAG_PENDING_XMIT, &priv->flags); | 2183 | set_bit(FLAG_PENDING_XMIT, &priv->flags); |
| 2164 | netif_stop_queue(dev); | 2184 | netif_stop_queue(dev); |
| 2165 | set_bit(JOB_XMIT, &priv->flags); | 2185 | set_bit(JOB_XMIT, &priv->jobs); |
| 2166 | wake_up_interruptible(&priv->thr_wait); | 2186 | wake_up_interruptible(&priv->thr_wait); |
| 2167 | } else | 2187 | } else |
| 2168 | airo_end_xmit(dev); | 2188 | airo_end_xmit(dev); |
| @@ -2177,7 +2197,7 @@ static void airo_end_xmit11(struct net_device *dev) { | |||
| 2177 | int fid = priv->xmit11.fid; | 2197 | int fid = priv->xmit11.fid; |
| 2178 | u32 *fids = priv->fids; | 2198 | u32 *fids = priv->fids; |
| 2179 | 2199 | ||
| 2180 | clear_bit(JOB_XMIT11, &priv->flags); | 2200 | clear_bit(JOB_XMIT11, &priv->jobs); |
| 2181 | clear_bit(FLAG_PENDING_XMIT11, &priv->flags); | 2201 | clear_bit(FLAG_PENDING_XMIT11, &priv->flags); |
| 2182 | status = transmit_802_11_packet (priv, fids[fid], skb->data); | 2202 | status = transmit_802_11_packet (priv, fids[fid], skb->data); |
| 2183 | up(&priv->sem); | 2203 | up(&priv->sem); |
| @@ -2233,7 +2253,7 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { | |||
| 2233 | if (down_trylock(&priv->sem) != 0) { | 2253 | if (down_trylock(&priv->sem) != 0) { |
| 2234 | set_bit(FLAG_PENDING_XMIT11, &priv->flags); | 2254 | set_bit(FLAG_PENDING_XMIT11, &priv->flags); |
| 2235 | netif_stop_queue(dev); | 2255 | netif_stop_queue(dev); |
| 2236 | set_bit(JOB_XMIT11, &priv->flags); | 2256 | set_bit(JOB_XMIT11, &priv->jobs); |
| 2237 | wake_up_interruptible(&priv->thr_wait); | 2257 | wake_up_interruptible(&priv->thr_wait); |
| 2238 | } else | 2258 | } else |
| 2239 | airo_end_xmit11(dev); | 2259 | airo_end_xmit11(dev); |
| @@ -2244,7 +2264,7 @@ static void airo_read_stats(struct airo_info *ai) { | |||
| 2244 | StatsRid stats_rid; | 2264 | StatsRid stats_rid; |
| 2245 | u32 *vals = stats_rid.vals; | 2265 | u32 *vals = stats_rid.vals; |
| 2246 | 2266 | ||
| 2247 | clear_bit(JOB_STATS, &ai->flags); | 2267 | clear_bit(JOB_STATS, &ai->jobs); |
| 2248 | if (ai->power.event) { | 2268 | if (ai->power.event) { |
| 2249 | up(&ai->sem); | 2269 | up(&ai->sem); |
| 2250 | return; | 2270 | return; |
| @@ -2272,10 +2292,10 @@ static struct net_device_stats *airo_get_stats(struct net_device *dev) | |||
| 2272 | { | 2292 | { |
| 2273 | struct airo_info *local = dev->priv; | 2293 | struct airo_info *local = dev->priv; |
| 2274 | 2294 | ||
| 2275 | if (!test_bit(JOB_STATS, &local->flags)) { | 2295 | if (!test_bit(JOB_STATS, &local->jobs)) { |
| 2276 | /* Get stats out of the card if available */ | 2296 | /* Get stats out of the card if available */ |
| 2277 | if (down_trylock(&local->sem) != 0) { | 2297 | if (down_trylock(&local->sem) != 0) { |
| 2278 | set_bit(JOB_STATS, &local->flags); | 2298 | set_bit(JOB_STATS, &local->jobs); |
| 2279 | wake_up_interruptible(&local->thr_wait); | 2299 | wake_up_interruptible(&local->thr_wait); |
| 2280 | } else | 2300 | } else |
| 2281 | airo_read_stats(local); | 2301 | airo_read_stats(local); |
| @@ -2290,7 +2310,7 @@ static void airo_set_promisc(struct airo_info *ai) { | |||
| 2290 | 2310 | ||
| 2291 | memset(&cmd, 0, sizeof(cmd)); | 2311 | memset(&cmd, 0, sizeof(cmd)); |
| 2292 | cmd.cmd=CMD_SETMODE; | 2312 | cmd.cmd=CMD_SETMODE; |
| 2293 | clear_bit(JOB_PROMISC, &ai->flags); | 2313 | clear_bit(JOB_PROMISC, &ai->jobs); |
| 2294 | cmd.parm0=(ai->flags&IFF_PROMISC) ? PROMISC : NOPROMISC; | 2314 | cmd.parm0=(ai->flags&IFF_PROMISC) ? PROMISC : NOPROMISC; |
| 2295 | issuecommand(ai, &cmd, &rsp); | 2315 | issuecommand(ai, &cmd, &rsp); |
| 2296 | up(&ai->sem); | 2316 | up(&ai->sem); |
| @@ -2302,7 +2322,7 @@ static void airo_set_multicast_list(struct net_device *dev) { | |||
| 2302 | if ((dev->flags ^ ai->flags) & IFF_PROMISC) { | 2322 | if ((dev->flags ^ ai->flags) & IFF_PROMISC) { |
| 2303 | change_bit(FLAG_PROMISC, &ai->flags); | 2323 | change_bit(FLAG_PROMISC, &ai->flags); |
| 2304 | if (down_trylock(&ai->sem) != 0) { | 2324 | if (down_trylock(&ai->sem) != 0) { |
| 2305 | set_bit(JOB_PROMISC, &ai->flags); | 2325 | set_bit(JOB_PROMISC, &ai->jobs); |
| 2306 | wake_up_interruptible(&ai->thr_wait); | 2326 | wake_up_interruptible(&ai->thr_wait); |
| 2307 | } else | 2327 | } else |
| 2308 | airo_set_promisc(ai); | 2328 | airo_set_promisc(ai); |
| @@ -2380,7 +2400,7 @@ void stop_airo_card( struct net_device *dev, int freeres ) | |||
| 2380 | } | 2400 | } |
| 2381 | clear_bit(FLAG_REGISTERED, &ai->flags); | 2401 | clear_bit(FLAG_REGISTERED, &ai->flags); |
| 2382 | } | 2402 | } |
| 2383 | set_bit(JOB_DIE, &ai->flags); | 2403 | set_bit(JOB_DIE, &ai->jobs); |
| 2384 | kill_proc(ai->thr_pid, SIGTERM, 1); | 2404 | kill_proc(ai->thr_pid, SIGTERM, 1); |
| 2385 | wait_for_completion(&ai->thr_exited); | 2405 | wait_for_completion(&ai->thr_exited); |
| 2386 | 2406 | ||
| @@ -2701,14 +2721,14 @@ static int reset_card( struct net_device *dev , int lock) { | |||
| 2701 | return 0; | 2721 | return 0; |
| 2702 | } | 2722 | } |
| 2703 | 2723 | ||
| 2704 | #define MAX_NETWORK_COUNT 64 | 2724 | #define AIRO_MAX_NETWORK_COUNT 64 |
| 2705 | static int airo_networks_allocate(struct airo_info *ai) | 2725 | static int airo_networks_allocate(struct airo_info *ai) |
| 2706 | { | 2726 | { |
| 2707 | if (ai->networks) | 2727 | if (ai->networks) |
| 2708 | return 0; | 2728 | return 0; |
| 2709 | 2729 | ||
| 2710 | ai->networks = | 2730 | ai->networks = |
| 2711 | kzalloc(MAX_NETWORK_COUNT * sizeof(BSSListElement), | 2731 | kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement), |
| 2712 | GFP_KERNEL); | 2732 | GFP_KERNEL); |
| 2713 | if (!ai->networks) { | 2733 | if (!ai->networks) { |
| 2714 | airo_print_warn(ai->dev->name, "Out of memory allocating beacons"); | 2734 | airo_print_warn(ai->dev->name, "Out of memory allocating beacons"); |
| @@ -2732,11 +2752,33 @@ static void airo_networks_initialize(struct airo_info *ai) | |||
| 2732 | 2752 | ||
| 2733 | INIT_LIST_HEAD(&ai->network_free_list); | 2753 | INIT_LIST_HEAD(&ai->network_free_list); |
| 2734 | INIT_LIST_HEAD(&ai->network_list); | 2754 | INIT_LIST_HEAD(&ai->network_list); |
| 2735 | for (i = 0; i < MAX_NETWORK_COUNT; i++) | 2755 | for (i = 0; i < AIRO_MAX_NETWORK_COUNT; i++) |
| 2736 | list_add_tail(&ai->networks[i].list, | 2756 | list_add_tail(&ai->networks[i].list, |
| 2737 | &ai->network_free_list); | 2757 | &ai->network_free_list); |
| 2738 | } | 2758 | } |
| 2739 | 2759 | ||
| 2760 | static int airo_test_wpa_capable(struct airo_info *ai) | ||
| 2761 | { | ||
| 2762 | int status; | ||
| 2763 | CapabilityRid cap_rid; | ||
| 2764 | const char *name = ai->dev->name; | ||
| 2765 | |||
| 2766 | status = readCapabilityRid(ai, &cap_rid, 1); | ||
| 2767 | if (status != SUCCESS) return 0; | ||
| 2768 | |||
| 2769 | /* Only firmware versions 5.30.17 or better can do WPA */ | ||
| 2770 | if ((cap_rid.softVer > 0x530) | ||
| 2771 | || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) { | ||
| 2772 | airo_print_info(name, "WPA is supported."); | ||
| 2773 | return 1; | ||
| 2774 | } | ||
| 2775 | |||
| 2776 | /* No WPA support */ | ||
| 2777 | airo_print_info(name, "WPA unsupported (only firmware versions 5.30.17" | ||
| 2778 | " and greater support WPA. Detected %s)", cap_rid.prodVer); | ||
| 2779 | return 0; | ||
| 2780 | } | ||
| 2781 | |||
| 2740 | static struct net_device *_init_airo_card( unsigned short irq, int port, | 2782 | static struct net_device *_init_airo_card( unsigned short irq, int port, |
| 2741 | int is_pcmcia, struct pci_dev *pci, | 2783 | int is_pcmcia, struct pci_dev *pci, |
| 2742 | struct device *dmdev ) | 2784 | struct device *dmdev ) |
| @@ -2759,6 +2801,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, | |||
| 2759 | ai = dev->priv; | 2801 | ai = dev->priv; |
| 2760 | ai->wifidev = NULL; | 2802 | ai->wifidev = NULL; |
| 2761 | ai->flags = 0; | 2803 | ai->flags = 0; |
| 2804 | ai->jobs = 0; | ||
| 2762 | ai->dev = dev; | 2805 | ai->dev = dev; |
| 2763 | if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) { | 2806 | if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) { |
| 2764 | airo_print_dbg(dev->name, "Found an MPI350 card"); | 2807 | airo_print_dbg(dev->name, "Found an MPI350 card"); |
| @@ -2838,6 +2881,18 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, | |||
| 2838 | set_bit(FLAG_FLASHING, &ai->flags); | 2881 | set_bit(FLAG_FLASHING, &ai->flags); |
| 2839 | } | 2882 | } |
| 2840 | 2883 | ||
| 2884 | /* Test for WPA support */ | ||
| 2885 | if (airo_test_wpa_capable(ai)) { | ||
| 2886 | set_bit(FLAG_WPA_CAPABLE, &ai->flags); | ||
| 2887 | ai->bssListFirst = RID_WPA_BSSLISTFIRST; | ||
| 2888 | ai->bssListNext = RID_WPA_BSSLISTNEXT; | ||
| 2889 | ai->bssListRidLen = sizeof(BSSListRid); | ||
| 2890 | } else { | ||
| 2891 | ai->bssListFirst = RID_BSSLISTFIRST; | ||
| 2892 | ai->bssListNext = RID_BSSLISTNEXT; | ||
| 2893 | ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra); | ||
| 2894 | } | ||
| 2895 | |||
| 2841 | rc = register_netdev(dev); | 2896 | rc = register_netdev(dev); |
| 2842 | if (rc) { | 2897 | if (rc) { |
| 2843 | airo_print_err(dev->name, "Couldn't register_netdev"); | 2898 | airo_print_err(dev->name, "Couldn't register_netdev"); |
| @@ -2875,7 +2930,7 @@ err_out_irq: | |||
| 2875 | err_out_unlink: | 2930 | err_out_unlink: |
| 2876 | del_airo_dev(dev); | 2931 | del_airo_dev(dev); |
| 2877 | err_out_thr: | 2932 | err_out_thr: |
| 2878 | set_bit(JOB_DIE, &ai->flags); | 2933 | set_bit(JOB_DIE, &ai->jobs); |
| 2879 | kill_proc(ai->thr_pid, SIGTERM, 1); | 2934 | kill_proc(ai->thr_pid, SIGTERM, 1); |
| 2880 | wait_for_completion(&ai->thr_exited); | 2935 | wait_for_completion(&ai->thr_exited); |
| 2881 | err_out_free: | 2936 | err_out_free: |
| @@ -2933,7 +2988,7 @@ static void airo_send_event(struct net_device *dev) { | |||
| 2933 | union iwreq_data wrqu; | 2988 | union iwreq_data wrqu; |
| 2934 | StatusRid status_rid; | 2989 | StatusRid status_rid; |
| 2935 | 2990 | ||
| 2936 | clear_bit(JOB_EVENT, &ai->flags); | 2991 | clear_bit(JOB_EVENT, &ai->jobs); |
| 2937 | PC4500_readrid(ai, RID_STATUS, &status_rid, sizeof(status_rid), 0); | 2992 | PC4500_readrid(ai, RID_STATUS, &status_rid, sizeof(status_rid), 0); |
| 2938 | up(&ai->sem); | 2993 | up(&ai->sem); |
| 2939 | wrqu.data.length = 0; | 2994 | wrqu.data.length = 0; |
| @@ -2947,7 +3002,7 @@ static void airo_send_event(struct net_device *dev) { | |||
| 2947 | 3002 | ||
| 2948 | static void airo_process_scan_results (struct airo_info *ai) { | 3003 | static void airo_process_scan_results (struct airo_info *ai) { |
| 2949 | union iwreq_data wrqu; | 3004 | union iwreq_data wrqu; |
| 2950 | BSSListRid BSSList; | 3005 | BSSListRid bss; |
| 2951 | int rc; | 3006 | int rc; |
| 2952 | BSSListElement * loop_net; | 3007 | BSSListElement * loop_net; |
| 2953 | BSSListElement * tmp_net; | 3008 | BSSListElement * tmp_net; |
| @@ -2960,15 +3015,15 @@ static void airo_process_scan_results (struct airo_info *ai) { | |||
| 2960 | } | 3015 | } |
| 2961 | 3016 | ||
| 2962 | /* Try to read the first entry of the scan result */ | 3017 | /* Try to read the first entry of the scan result */ |
| 2963 | rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 0); | 3018 | rc = PC4500_readrid(ai, ai->bssListFirst, &bss, ai->bssListRidLen, 0); |
| 2964 | if((rc) || (BSSList.index == 0xffff)) { | 3019 | if((rc) || (bss.index == 0xffff)) { |
| 2965 | /* No scan results */ | 3020 | /* No scan results */ |
| 2966 | goto out; | 3021 | goto out; |
| 2967 | } | 3022 | } |
| 2968 | 3023 | ||
| 2969 | /* Read and parse all entries */ | 3024 | /* Read and parse all entries */ |
| 2970 | tmp_net = NULL; | 3025 | tmp_net = NULL; |
| 2971 | while((!rc) && (BSSList.index != 0xffff)) { | 3026 | while((!rc) && (bss.index != 0xffff)) { |
| 2972 | /* Grab a network off the free list */ | 3027 | /* Grab a network off the free list */ |
| 2973 | if (!list_empty(&ai->network_free_list)) { | 3028 | if (!list_empty(&ai->network_free_list)) { |
| 2974 | tmp_net = list_entry(ai->network_free_list.next, | 3029 | tmp_net = list_entry(ai->network_free_list.next, |
| @@ -2977,19 +3032,19 @@ static void airo_process_scan_results (struct airo_info *ai) { | |||
| 2977 | } | 3032 | } |
| 2978 | 3033 | ||
| 2979 | if (tmp_net != NULL) { | 3034 | if (tmp_net != NULL) { |
| 2980 | memcpy(tmp_net, &BSSList, sizeof(tmp_net->bss)); | 3035 | memcpy(tmp_net, &bss, sizeof(tmp_net->bss)); |
| 2981 | list_add_tail(&tmp_net->list, &ai->network_list); | 3036 | list_add_tail(&tmp_net->list, &ai->network_list); |
| 2982 | tmp_net = NULL; | 3037 | tmp_net = NULL; |
| 2983 | } | 3038 | } |
| 2984 | 3039 | ||
| 2985 | /* Read next entry */ | 3040 | /* Read next entry */ |
| 2986 | rc = PC4500_readrid(ai, RID_BSSLISTNEXT, | 3041 | rc = PC4500_readrid(ai, ai->bssListNext, |
| 2987 | &BSSList, sizeof(BSSList), 0); | 3042 | &bss, ai->bssListRidLen, 0); |
| 2988 | } | 3043 | } |
| 2989 | 3044 | ||
| 2990 | out: | 3045 | out: |
| 2991 | ai->scan_timeout = 0; | 3046 | ai->scan_timeout = 0; |
| 2992 | clear_bit(JOB_SCAN_RESULTS, &ai->flags); | 3047 | clear_bit(JOB_SCAN_RESULTS, &ai->jobs); |
| 2993 | up(&ai->sem); | 3048 | up(&ai->sem); |
| 2994 | 3049 | ||
| 2995 | /* Send an empty event to user space. | 3050 | /* Send an empty event to user space. |
| @@ -3019,10 +3074,10 @@ static int airo_thread(void *data) { | |||
| 3019 | /* make swsusp happy with our thread */ | 3074 | /* make swsusp happy with our thread */ |
| 3020 | try_to_freeze(); | 3075 | try_to_freeze(); |
| 3021 | 3076 | ||
| 3022 | if (test_bit(JOB_DIE, &ai->flags)) | 3077 | if (test_bit(JOB_DIE, &ai->jobs)) |
| 3023 | break; | 3078 | break; |
| 3024 | 3079 | ||
| 3025 | if (ai->flags & JOB_MASK) { | 3080 | if (ai->jobs) { |
| 3026 | locked = down_interruptible(&ai->sem); | 3081 | locked = down_interruptible(&ai->sem); |
| 3027 | } else { | 3082 | } else { |
| 3028 | wait_queue_t wait; | 3083 | wait_queue_t wait; |
| @@ -3031,16 +3086,16 @@ static int airo_thread(void *data) { | |||
| 3031 | add_wait_queue(&ai->thr_wait, &wait); | 3086 | add_wait_queue(&ai->thr_wait, &wait); |
| 3032 | for (;;) { | 3087 | for (;;) { |
| 3033 | set_current_state(TASK_INTERRUPTIBLE); | 3088 | set_current_state(TASK_INTERRUPTIBLE); |
| 3034 | if (ai->flags & JOB_MASK) | 3089 | if (ai->jobs) |
| 3035 | break; | 3090 | break; |
| 3036 | if (ai->expires || ai->scan_timeout) { | 3091 | if (ai->expires || ai->scan_timeout) { |
| 3037 | if (ai->scan_timeout && | 3092 | if (ai->scan_timeout && |
| 3038 | time_after_eq(jiffies,ai->scan_timeout)){ | 3093 | time_after_eq(jiffies,ai->scan_timeout)){ |
| 3039 | set_bit(JOB_SCAN_RESULTS,&ai->flags); | 3094 | set_bit(JOB_SCAN_RESULTS, &ai->jobs); |
| 3040 | break; | 3095 | break; |
| 3041 | } else if (ai->expires && | 3096 | } else if (ai->expires && |
| 3042 | time_after_eq(jiffies,ai->expires)){ | 3097 | time_after_eq(jiffies,ai->expires)){ |
| 3043 | set_bit(JOB_AUTOWEP,&ai->flags); | 3098 | set_bit(JOB_AUTOWEP, &ai->jobs); |
| 3044 | break; | 3099 | break; |
| 3045 | } | 3100 | } |
| 3046 | if (!signal_pending(current)) { | 3101 | if (!signal_pending(current)) { |
| @@ -3069,7 +3124,7 @@ static int airo_thread(void *data) { | |||
| 3069 | if (locked) | 3124 | if (locked) |
| 3070 | continue; | 3125 | continue; |
| 3071 | 3126 | ||
| 3072 | if (test_bit(JOB_DIE, &ai->flags)) { | 3127 | if (test_bit(JOB_DIE, &ai->jobs)) { |
| 3073 | up(&ai->sem); | 3128 | up(&ai->sem); |
| 3074 | break; | 3129 | break; |
| 3075 | } | 3130 | } |
| @@ -3079,23 +3134,23 @@ static int airo_thread(void *data) { | |||
| 3079 | continue; | 3134 | continue; |
| 3080 | } | 3135 | } |
| 3081 | 3136 | ||
| 3082 | if (test_bit(JOB_XMIT, &ai->flags)) | 3137 | if (test_bit(JOB_XMIT, &ai->jobs)) |
| 3083 | airo_end_xmit(dev); | 3138 | airo_end_xmit(dev); |
| 3084 | else if (test_bit(JOB_XMIT11, &ai->flags)) | 3139 | else if (test_bit(JOB_XMIT11, &ai->jobs)) |
| 3085 | airo_end_xmit11(dev); | 3140 | airo_end_xmit11(dev); |
| 3086 | else if (test_bit(JOB_STATS, &ai->flags)) | 3141 | else if (test_bit(JOB_STATS, &ai->jobs)) |
| 3087 | airo_read_stats(ai); | 3142 | airo_read_stats(ai); |
| 3088 | else if (test_bit(JOB_WSTATS, &ai->flags)) | 3143 | else if (test_bit(JOB_WSTATS, &ai->jobs)) |
| 3089 | airo_read_wireless_stats(ai); | 3144 | airo_read_wireless_stats(ai); |
| 3090 | else if (test_bit(JOB_PROMISC, &ai->flags)) | 3145 | else if (test_bit(JOB_PROMISC, &ai->jobs)) |
| 3091 | airo_set_promisc(ai); | 3146 | airo_set_promisc(ai); |
| 3092 | else if (test_bit(JOB_MIC, &ai->flags)) | 3147 | else if (test_bit(JOB_MIC, &ai->jobs)) |
| 3093 | micinit(ai); | 3148 | micinit(ai); |
| 3094 | else if (test_bit(JOB_EVENT, &ai->flags)) | 3149 | else if (test_bit(JOB_EVENT, &ai->jobs)) |
| 3095 | airo_send_event(dev); | 3150 | airo_send_event(dev); |
| 3096 | else if (test_bit(JOB_AUTOWEP, &ai->flags)) | 3151 | else if (test_bit(JOB_AUTOWEP, &ai->jobs)) |
| 3097 | timer_func(dev); | 3152 | timer_func(dev); |
| 3098 | else if (test_bit(JOB_SCAN_RESULTS, &ai->flags)) | 3153 | else if (test_bit(JOB_SCAN_RESULTS, &ai->jobs)) |
| 3099 | airo_process_scan_results(ai); | 3154 | airo_process_scan_results(ai); |
| 3100 | else /* Shouldn't get here, but we make sure to unlock */ | 3155 | else /* Shouldn't get here, but we make sure to unlock */ |
| 3101 | up(&ai->sem); | 3156 | up(&ai->sem); |
| @@ -3133,7 +3188,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) | |||
| 3133 | if ( status & EV_MIC ) { | 3188 | if ( status & EV_MIC ) { |
| 3134 | OUT4500( apriv, EVACK, EV_MIC ); | 3189 | OUT4500( apriv, EVACK, EV_MIC ); |
| 3135 | if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) { | 3190 | if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) { |
| 3136 | set_bit(JOB_MIC, &apriv->flags); | 3191 | set_bit(JOB_MIC, &apriv->jobs); |
| 3137 | wake_up_interruptible(&apriv->thr_wait); | 3192 | wake_up_interruptible(&apriv->thr_wait); |
| 3138 | } | 3193 | } |
| 3139 | } | 3194 | } |
| @@ -3187,7 +3242,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) | |||
| 3187 | set_bit(FLAG_UPDATE_MULTI, &apriv->flags); | 3242 | set_bit(FLAG_UPDATE_MULTI, &apriv->flags); |
| 3188 | 3243 | ||
| 3189 | if (down_trylock(&apriv->sem) != 0) { | 3244 | if (down_trylock(&apriv->sem) != 0) { |
| 3190 | set_bit(JOB_EVENT, &apriv->flags); | 3245 | set_bit(JOB_EVENT, &apriv->jobs); |
| 3191 | wake_up_interruptible(&apriv->thr_wait); | 3246 | wake_up_interruptible(&apriv->thr_wait); |
| 3192 | } else | 3247 | } else |
| 3193 | airo_send_event(dev); | 3248 | airo_send_event(dev); |
| @@ -5485,7 +5540,7 @@ static void timer_func( struct net_device *dev ) { | |||
| 5485 | up(&apriv->sem); | 5540 | up(&apriv->sem); |
| 5486 | 5541 | ||
| 5487 | /* Schedule check to see if the change worked */ | 5542 | /* Schedule check to see if the change worked */ |
| 5488 | clear_bit(JOB_AUTOWEP, &apriv->flags); | 5543 | clear_bit(JOB_AUTOWEP, &apriv->jobs); |
| 5489 | apriv->expires = RUN_AT(HZ*3); | 5544 | apriv->expires = RUN_AT(HZ*3); |
| 5490 | } | 5545 | } |
| 5491 | 5546 | ||
| @@ -6876,7 +6931,7 @@ static int airo_get_range(struct net_device *dev, | |||
| 6876 | } | 6931 | } |
| 6877 | range->num_txpower = i; | 6932 | range->num_txpower = i; |
| 6878 | range->txpower_capa = IW_TXPOW_MWATT; | 6933 | range->txpower_capa = IW_TXPOW_MWATT; |
| 6879 | range->we_version_source = 12; | 6934 | range->we_version_source = 19; |
| 6880 | range->we_version_compiled = WIRELESS_EXT; | 6935 | range->we_version_compiled = WIRELESS_EXT; |
| 6881 | range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; | 6936 | range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; |
| 6882 | range->retry_flags = IW_RETRY_LIMIT; | 6937 | range->retry_flags = IW_RETRY_LIMIT; |
| @@ -7152,6 +7207,7 @@ static inline char *airo_translate_scan(struct net_device *dev, | |||
| 7152 | u16 capabilities; | 7207 | u16 capabilities; |
| 7153 | char * current_val; /* For rates */ | 7208 | char * current_val; /* For rates */ |
| 7154 | int i; | 7209 | int i; |
| 7210 | char * buf; | ||
| 7155 | 7211 | ||
| 7156 | /* First entry *MUST* be the AP MAC address */ | 7212 | /* First entry *MUST* be the AP MAC address */ |
| 7157 | iwe.cmd = SIOCGIWAP; | 7213 | iwe.cmd = SIOCGIWAP; |
| @@ -7238,8 +7294,69 @@ static inline char *airo_translate_scan(struct net_device *dev, | |||
| 7238 | if((current_val - current_ev) > IW_EV_LCP_LEN) | 7294 | if((current_val - current_ev) > IW_EV_LCP_LEN) |
| 7239 | current_ev = current_val; | 7295 | current_ev = current_val; |
| 7240 | 7296 | ||
| 7241 | /* The other data in the scan result are not really | 7297 | /* Beacon interval */ |
| 7242 | * interesting, so for now drop it - Jean II */ | 7298 | buf = kmalloc(30, GFP_KERNEL); |
| 7299 | if (buf) { | ||
| 7300 | iwe.cmd = IWEVCUSTOM; | ||
| 7301 | sprintf(buf, "bcn_int=%d", bss->beaconInterval); | ||
| 7302 | iwe.u.data.length = strlen(buf); | ||
| 7303 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); | ||
| 7304 | kfree(buf); | ||
| 7305 | } | ||
| 7306 | |||
| 7307 | /* Put WPA/RSN Information Elements into the event stream */ | ||
| 7308 | if (test_bit(FLAG_WPA_CAPABLE, &ai->flags)) { | ||
| 7309 | unsigned int num_null_ies = 0; | ||
| 7310 | u16 length = sizeof (bss->extra.iep); | ||
| 7311 | struct ieee80211_info_element *info_element = | ||
| 7312 | (struct ieee80211_info_element *) &bss->extra.iep; | ||
| 7313 | |||
| 7314 | while ((length >= sizeof(*info_element)) && (num_null_ies < 2)) { | ||
| 7315 | if (sizeof(*info_element) + info_element->len > length) { | ||
| 7316 | /* Invalid element, don't continue parsing IE */ | ||
| 7317 | break; | ||
| 7318 | } | ||
| 7319 | |||
| 7320 | switch (info_element->id) { | ||
| 7321 | case MFIE_TYPE_SSID: | ||
| 7322 | /* Two zero-length SSID elements | ||
| 7323 | * mean we're done parsing elements */ | ||
| 7324 | if (!info_element->len) | ||
| 7325 | num_null_ies++; | ||
| 7326 | break; | ||
| 7327 | |||
| 7328 | case MFIE_TYPE_GENERIC: | ||
| 7329 | if (info_element->len >= 4 && | ||
| 7330 | info_element->data[0] == 0x00 && | ||
| 7331 | info_element->data[1] == 0x50 && | ||
| 7332 | info_element->data[2] == 0xf2 && | ||
| 7333 | info_element->data[3] == 0x01) { | ||
| 7334 | iwe.cmd = IWEVGENIE; | ||
| 7335 | iwe.u.data.length = min(info_element->len + 2, | ||
| 7336 | MAX_WPA_IE_LEN); | ||
| 7337 | current_ev = iwe_stream_add_point(current_ev, end_buf, | ||
| 7338 | &iwe, (char *) info_element); | ||
| 7339 | } | ||
| 7340 | break; | ||
| 7341 | |||
| 7342 | case MFIE_TYPE_RSN: | ||
| 7343 | iwe.cmd = IWEVGENIE; | ||
| 7344 | iwe.u.data.length = min(info_element->len + 2, | ||
| 7345 | MAX_WPA_IE_LEN); | ||
| 7346 | current_ev = iwe_stream_add_point(current_ev, end_buf, | ||
| 7347 | &iwe, (char *) info_element); | ||
| 7348 | break; | ||
| 7349 | |||
| 7350 | default: | ||
| 7351 | break; | ||
| 7352 | } | ||
| 7353 | |||
| 7354 | length -= sizeof(*info_element) + info_element->len; | ||
| 7355 | info_element = | ||
| 7356 | (struct ieee80211_info_element *)&info_element-> | ||
| 7357 | data[info_element->len]; | ||
| 7358 | } | ||
| 7359 | } | ||
| 7243 | return current_ev; | 7360 | return current_ev; |
| 7244 | } | 7361 | } |
| 7245 | 7362 | ||
| @@ -7521,7 +7638,7 @@ static void airo_read_wireless_stats(struct airo_info *local) | |||
| 7521 | u32 *vals = stats_rid.vals; | 7638 | u32 *vals = stats_rid.vals; |
| 7522 | 7639 | ||
| 7523 | /* Get stats out of the card */ | 7640 | /* Get stats out of the card */ |
| 7524 | clear_bit(JOB_WSTATS, &local->flags); | 7641 | clear_bit(JOB_WSTATS, &local->jobs); |
| 7525 | if (local->power.event) { | 7642 | if (local->power.event) { |
| 7526 | up(&local->sem); | 7643 | up(&local->sem); |
| 7527 | return; | 7644 | return; |
| @@ -7565,10 +7682,10 @@ static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev) | |||
| 7565 | { | 7682 | { |
| 7566 | struct airo_info *local = dev->priv; | 7683 | struct airo_info *local = dev->priv; |
| 7567 | 7684 | ||
| 7568 | if (!test_bit(JOB_WSTATS, &local->flags)) { | 7685 | if (!test_bit(JOB_WSTATS, &local->jobs)) { |
| 7569 | /* Get stats out of the card if available */ | 7686 | /* Get stats out of the card if available */ |
| 7570 | if (down_trylock(&local->sem) != 0) { | 7687 | if (down_trylock(&local->sem) != 0) { |
| 7571 | set_bit(JOB_WSTATS, &local->flags); | 7688 | set_bit(JOB_WSTATS, &local->jobs); |
| 7572 | wake_up_interruptible(&local->thr_wait); | 7689 | wake_up_interruptible(&local->thr_wait); |
| 7573 | } else | 7690 | } else |
| 7574 | airo_read_wireless_stats(local); | 7691 | airo_read_wireless_stats(local); |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 2e83083935e1..e66fdb1f3cfd 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h | |||
| @@ -645,7 +645,6 @@ struct bcm43xx_private { | |||
| 645 | unsigned int irq; | 645 | unsigned int irq; |
| 646 | 646 | ||
| 647 | void __iomem *mmio_addr; | 647 | void __iomem *mmio_addr; |
| 648 | unsigned int mmio_len; | ||
| 649 | 648 | ||
| 650 | /* Do not use the lock directly. Use the bcm43xx_lock* helper | 649 | /* Do not use the lock directly. Use the bcm43xx_lock* helper |
| 651 | * functions, to be MMIO-safe. */ | 650 | * functions, to be MMIO-safe. */ |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index 35a4fcb6d923..7497fb16076e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | |||
| @@ -92,7 +92,7 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, | |||
| 92 | fappend("subsystem_vendor: 0x%04x subsystem_device: 0x%04x\n", | 92 | fappend("subsystem_vendor: 0x%04x subsystem_device: 0x%04x\n", |
| 93 | pci_dev->subsystem_vendor, pci_dev->subsystem_device); | 93 | pci_dev->subsystem_vendor, pci_dev->subsystem_device); |
| 94 | fappend("IRQ: %d\n", bcm->irq); | 94 | fappend("IRQ: %d\n", bcm->irq); |
| 95 | fappend("mmio_addr: 0x%p mmio_len: %u\n", bcm->mmio_addr, bcm->mmio_len); | 95 | fappend("mmio_addr: 0x%p\n", bcm->mmio_addr); |
| 96 | fappend("chip_id: 0x%04x chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev); | 96 | fappend("chip_id: 0x%04x chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev); |
| 97 | if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16))) | 97 | if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16))) |
| 98 | fappend("Radio disabled by hardware!\n"); | 98 | fappend("Radio disabled by hardware!\n"); |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 7ed18cad29f7..736dde96c4a3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c | |||
| @@ -128,13 +128,15 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging."); | |||
| 128 | static struct pci_device_id bcm43xx_pci_tbl[] = { | 128 | static struct pci_device_id bcm43xx_pci_tbl[] = { |
| 129 | /* Broadcom 4303 802.11b */ | 129 | /* Broadcom 4303 802.11b */ |
| 130 | { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 130 | { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
| 131 | /* Broadcom 4307 802.11b */ | 131 | /* Broadcom 4307 802.11b */ |
| 132 | { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 132 | { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
| 133 | /* Broadcom 4318 802.11b/g */ | 133 | /* Broadcom 4318 802.11b/g */ |
| 134 | { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 134 | { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
| 135 | /* Broadcom 4319 802.11a/b/g */ | ||
| 136 | { PCI_VENDOR_ID_BROADCOM, 0x4319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
| 135 | /* Broadcom 4306 802.11b/g */ | 137 | /* Broadcom 4306 802.11b/g */ |
| 136 | { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 138 | { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
| 137 | /* Broadcom 4306 802.11a */ | 139 | /* Broadcom 4306 802.11a */ |
| 138 | // { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 140 | // { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
| 139 | /* Broadcom 4309 802.11a/b/g */ | 141 | /* Broadcom 4309 802.11a/b/g */ |
| 140 | { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 142 | { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
| @@ -3299,8 +3301,7 @@ static void bcm43xx_detach_board(struct bcm43xx_private *bcm) | |||
| 3299 | 3301 | ||
| 3300 | bcm43xx_chipset_detach(bcm); | 3302 | bcm43xx_chipset_detach(bcm); |
| 3301 | /* Do _not_ access the chip, after it is detached. */ | 3303 | /* Do _not_ access the chip, after it is detached. */ |
| 3302 | iounmap(bcm->mmio_addr); | 3304 | pci_iounmap(pci_dev, bcm->mmio_addr); |
| 3303 | |||
| 3304 | pci_release_regions(pci_dev); | 3305 | pci_release_regions(pci_dev); |
| 3305 | pci_disable_device(pci_dev); | 3306 | pci_disable_device(pci_dev); |
| 3306 | 3307 | ||
| @@ -3390,40 +3391,26 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) | |||
| 3390 | struct net_device *net_dev = bcm->net_dev; | 3391 | struct net_device *net_dev = bcm->net_dev; |
| 3391 | int err; | 3392 | int err; |
| 3392 | int i; | 3393 | int i; |
| 3393 | unsigned long mmio_start, mmio_flags, mmio_len; | ||
| 3394 | u32 coremask; | 3394 | u32 coremask; |
| 3395 | 3395 | ||
| 3396 | err = pci_enable_device(pci_dev); | 3396 | err = pci_enable_device(pci_dev); |
| 3397 | if (err) { | 3397 | if (err) { |
| 3398 | printk(KERN_ERR PFX "unable to wake up pci device (%i)\n", err); | 3398 | printk(KERN_ERR PFX "pci_enable_device() failed\n"); |
| 3399 | goto out; | 3399 | goto out; |
| 3400 | } | 3400 | } |
| 3401 | mmio_start = pci_resource_start(pci_dev, 0); | ||
| 3402 | mmio_flags = pci_resource_flags(pci_dev, 0); | ||
| 3403 | mmio_len = pci_resource_len(pci_dev, 0); | ||
| 3404 | if (!(mmio_flags & IORESOURCE_MEM)) { | ||
| 3405 | printk(KERN_ERR PFX | ||
| 3406 | "%s, region #0 not an MMIO resource, aborting\n", | ||
| 3407 | pci_name(pci_dev)); | ||
| 3408 | err = -ENODEV; | ||
| 3409 | goto err_pci_disable; | ||
| 3410 | } | ||
| 3411 | err = pci_request_regions(pci_dev, KBUILD_MODNAME); | 3401 | err = pci_request_regions(pci_dev, KBUILD_MODNAME); |
| 3412 | if (err) { | 3402 | if (err) { |
| 3413 | printk(KERN_ERR PFX | 3403 | printk(KERN_ERR PFX "pci_request_regions() failed\n"); |
| 3414 | "could not access PCI resources (%i)\n", err); | ||
| 3415 | goto err_pci_disable; | 3404 | goto err_pci_disable; |
| 3416 | } | 3405 | } |
| 3417 | /* enable PCI bus-mastering */ | 3406 | /* enable PCI bus-mastering */ |
| 3418 | pci_set_master(pci_dev); | 3407 | pci_set_master(pci_dev); |
| 3419 | bcm->mmio_addr = ioremap(mmio_start, mmio_len); | 3408 | bcm->mmio_addr = pci_iomap(pci_dev, 0, ~0UL); |
| 3420 | if (!bcm->mmio_addr) { | 3409 | if (!bcm->mmio_addr) { |
| 3421 | printk(KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", | 3410 | printk(KERN_ERR PFX "pci_iomap() failed\n"); |
| 3422 | pci_name(pci_dev)); | ||
| 3423 | err = -EIO; | 3411 | err = -EIO; |
| 3424 | goto err_pci_release; | 3412 | goto err_pci_release; |
| 3425 | } | 3413 | } |
| 3426 | bcm->mmio_len = mmio_len; | ||
| 3427 | net_dev->base_addr = (unsigned long)bcm->mmio_addr; | 3414 | net_dev->base_addr = (unsigned long)bcm->mmio_addr; |
| 3428 | 3415 | ||
| 3429 | bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID, | 3416 | bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID, |
| @@ -3517,7 +3504,7 @@ err_80211_unwind: | |||
| 3517 | err_chipset_detach: | 3504 | err_chipset_detach: |
| 3518 | bcm43xx_chipset_detach(bcm); | 3505 | bcm43xx_chipset_detach(bcm); |
| 3519 | err_iounmap: | 3506 | err_iounmap: |
| 3520 | iounmap(bcm->mmio_addr); | 3507 | pci_iounmap(pci_dev, bcm->mmio_addr); |
| 3521 | err_pci_release: | 3508 | err_pci_release: |
| 3522 | pci_release_regions(pci_dev); | 3509 | pci_release_regions(pci_dev); |
| 3523 | err_pci_disable: | 3510 | err_pci_disable: |
| @@ -3568,7 +3555,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, | |||
| 3568 | unsigned long flags; | 3555 | unsigned long flags; |
| 3569 | int keyidx; | 3556 | int keyidx; |
| 3570 | 3557 | ||
| 3571 | dprintk(KERN_INFO PFX "set security called\n"); | 3558 | dprintk(KERN_INFO PFX "set security called"); |
| 3572 | 3559 | ||
| 3573 | bcm43xx_lock_mmio(bcm, flags); | 3560 | bcm43xx_lock_mmio(bcm, flags); |
| 3574 | 3561 | ||
| @@ -3581,24 +3568,25 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, | |||
| 3581 | 3568 | ||
| 3582 | if (sec->flags & SEC_ACTIVE_KEY) { | 3569 | if (sec->flags & SEC_ACTIVE_KEY) { |
| 3583 | secinfo->active_key = sec->active_key; | 3570 | secinfo->active_key = sec->active_key; |
| 3584 | dprintk(KERN_INFO PFX " .active_key = %d\n", sec->active_key); | 3571 | dprintk(", .active_key = %d", sec->active_key); |
| 3585 | } | 3572 | } |
| 3586 | if (sec->flags & SEC_UNICAST_GROUP) { | 3573 | if (sec->flags & SEC_UNICAST_GROUP) { |
| 3587 | secinfo->unicast_uses_group = sec->unicast_uses_group; | 3574 | secinfo->unicast_uses_group = sec->unicast_uses_group; |
| 3588 | dprintk(KERN_INFO PFX " .unicast_uses_group = %d\n", sec->unicast_uses_group); | 3575 | dprintk(", .unicast_uses_group = %d", sec->unicast_uses_group); |
| 3589 | } | 3576 | } |
| 3590 | if (sec->flags & SEC_LEVEL) { | 3577 | if (sec->flags & SEC_LEVEL) { |
| 3591 | secinfo->level = sec->level; | 3578 | secinfo->level = sec->level; |
| 3592 | dprintk(KERN_INFO PFX " .level = %d\n", sec->level); | 3579 | dprintk(", .level = %d", sec->level); |
| 3593 | } | 3580 | } |
| 3594 | if (sec->flags & SEC_ENABLED) { | 3581 | if (sec->flags & SEC_ENABLED) { |
| 3595 | secinfo->enabled = sec->enabled; | 3582 | secinfo->enabled = sec->enabled; |
| 3596 | dprintk(KERN_INFO PFX " .enabled = %d\n", sec->enabled); | 3583 | dprintk(", .enabled = %d", sec->enabled); |
| 3597 | } | 3584 | } |
| 3598 | if (sec->flags & SEC_ENCRYPT) { | 3585 | if (sec->flags & SEC_ENCRYPT) { |
| 3599 | secinfo->encrypt = sec->encrypt; | 3586 | secinfo->encrypt = sec->encrypt; |
| 3600 | dprintk(KERN_INFO PFX " .encrypt = %d\n", sec->encrypt); | 3587 | dprintk(", .encrypt = %d", sec->encrypt); |
| 3601 | } | 3588 | } |
| 3589 | dprintk("\n"); | ||
| 3602 | if (bcm->initialized && !bcm->ieee->host_encrypt) { | 3590 | if (bcm->initialized && !bcm->ieee->host_encrypt) { |
| 3603 | if (secinfo->enabled) { | 3591 | if (secinfo->enabled) { |
| 3604 | /* upload WEP keys to hardware */ | 3592 | /* upload WEP keys to hardware */ |
diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c index 346c6febb033..2aa2f389c0d5 100644 --- a/drivers/net/wireless/hermes.c +++ b/drivers/net/wireless/hermes.c | |||
| @@ -121,12 +121,6 @@ void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing) | |||
| 121 | hw->iobase = address; | 121 | hw->iobase = address; |
| 122 | hw->reg_spacing = reg_spacing; | 122 | hw->reg_spacing = reg_spacing; |
| 123 | hw->inten = 0x0; | 123 | hw->inten = 0x0; |
| 124 | |||
| 125 | #ifdef HERMES_DEBUG_BUFFER | ||
| 126 | hw->dbufp = 0; | ||
| 127 | memset(&hw->dbuf, 0xff, sizeof(hw->dbuf)); | ||
| 128 | memset(&hw->profile, 0, sizeof(hw->profile)); | ||
| 129 | #endif | ||
| 130 | } | 124 | } |
| 131 | 125 | ||
| 132 | int hermes_init(hermes_t *hw) | 126 | int hermes_init(hermes_t *hw) |
| @@ -347,19 +341,6 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset) | |||
| 347 | reg = hermes_read_reg(hw, oreg); | 341 | reg = hermes_read_reg(hw, oreg); |
| 348 | } | 342 | } |
| 349 | 343 | ||
| 350 | #ifdef HERMES_DEBUG_BUFFER | ||
| 351 | hw->profile[HERMES_BAP_BUSY_TIMEOUT - k]++; | ||
| 352 | |||
| 353 | if (k < HERMES_BAP_BUSY_TIMEOUT) { | ||
| 354 | struct hermes_debug_entry *e = | ||
| 355 | &hw->dbuf[(hw->dbufp++) % HERMES_DEBUG_BUFSIZE]; | ||
| 356 | e->bap = bap; | ||
| 357 | e->id = id; | ||
| 358 | e->offset = offset; | ||
| 359 | e->cycles = HERMES_BAP_BUSY_TIMEOUT - k; | ||
| 360 | } | ||
| 361 | #endif | ||
| 362 | |||
| 363 | if (reg & HERMES_OFFSET_BUSY) | 344 | if (reg & HERMES_OFFSET_BUSY) |
| 364 | return -ETIMEDOUT; | 345 | return -ETIMEDOUT; |
| 365 | 346 | ||
| @@ -419,8 +400,7 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, | |||
| 419 | } | 400 | } |
| 420 | 401 | ||
| 421 | /* Write a block of data to the chip's buffer, via the | 402 | /* Write a block of data to the chip's buffer, via the |
| 422 | * BAP. Synchronization/serialization is the caller's problem. len | 403 | * BAP. Synchronization/serialization is the caller's problem. |
| 423 | * must be even. | ||
| 424 | * | 404 | * |
| 425 | * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware | 405 | * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware |
| 426 | */ | 406 | */ |
| @@ -430,7 +410,7 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, | |||
| 430 | int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; | 410 | int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; |
| 431 | int err = 0; | 411 | int err = 0; |
| 432 | 412 | ||
| 433 | if ( (len < 0) || (len % 2) ) | 413 | if (len < 0) |
| 434 | return -EINVAL; | 414 | return -EINVAL; |
| 435 | 415 | ||
| 436 | err = hermes_bap_seek(hw, bap, id, offset); | 416 | err = hermes_bap_seek(hw, bap, id, offset); |
| @@ -438,49 +418,12 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, | |||
| 438 | goto out; | 418 | goto out; |
| 439 | 419 | ||
| 440 | /* Actually do the transfer */ | 420 | /* Actually do the transfer */ |
| 441 | hermes_write_words(hw, dreg, buf, len/2); | 421 | hermes_write_bytes(hw, dreg, buf, len); |
| 442 | 422 | ||
| 443 | out: | 423 | out: |
| 444 | return err; | 424 | return err; |
| 445 | } | 425 | } |
| 446 | 426 | ||
| 447 | /* Write a block of data to the chip's buffer with padding if | ||
| 448 | * neccessary, via the BAP. Synchronization/serialization is the | ||
| 449 | * caller's problem. len must be even. | ||
| 450 | * | ||
| 451 | * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware | ||
| 452 | */ | ||
| 453 | int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf, unsigned data_len, int len, | ||
| 454 | u16 id, u16 offset) | ||
| 455 | { | ||
| 456 | int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; | ||
| 457 | int err = 0; | ||
| 458 | |||
| 459 | if (len < 0 || len % 2 || data_len > len) | ||
| 460 | return -EINVAL; | ||
| 461 | |||
| 462 | err = hermes_bap_seek(hw, bap, id, offset); | ||
| 463 | if (err) | ||
| 464 | goto out; | ||
| 465 | |||
| 466 | /* Transfer all the complete words of data */ | ||
| 467 | hermes_write_words(hw, dreg, buf, data_len/2); | ||
| 468 | /* If there is an odd byte left over pad and transfer it */ | ||
| 469 | if (data_len & 1) { | ||
| 470 | u8 end[2]; | ||
| 471 | end[1] = 0; | ||
| 472 | end[0] = ((unsigned char *)buf)[data_len - 1]; | ||
| 473 | hermes_write_words(hw, dreg, end, 1); | ||
| 474 | data_len ++; | ||
| 475 | } | ||
| 476 | /* Now send zeros for the padding */ | ||
| 477 | if (data_len < len) | ||
| 478 | hermes_clear_words(hw, dreg, (len - data_len) / 2); | ||
| 479 | /* Complete */ | ||
| 480 | out: | ||
| 481 | return err; | ||
| 482 | } | ||
| 483 | |||
| 484 | /* Read a Length-Type-Value record from the card. | 427 | /* Read a Length-Type-Value record from the card. |
| 485 | * | 428 | * |
| 486 | * If length is NULL, we ignore the length read from the card, and | 429 | * If length is NULL, we ignore the length read from the card, and |
| @@ -553,7 +496,7 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, | |||
| 553 | 496 | ||
| 554 | count = length - 1; | 497 | count = length - 1; |
| 555 | 498 | ||
| 556 | hermes_write_words(hw, dreg, value, count); | 499 | hermes_write_bytes(hw, dreg, value, count << 1); |
| 557 | 500 | ||
| 558 | err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE, | 501 | err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE, |
| 559 | rid, NULL); | 502 | rid, NULL); |
| @@ -568,7 +511,6 @@ EXPORT_SYMBOL(hermes_allocate); | |||
| 568 | 511 | ||
| 569 | EXPORT_SYMBOL(hermes_bap_pread); | 512 | EXPORT_SYMBOL(hermes_bap_pread); |
| 570 | EXPORT_SYMBOL(hermes_bap_pwrite); | 513 | EXPORT_SYMBOL(hermes_bap_pwrite); |
| 571 | EXPORT_SYMBOL(hermes_bap_pwrite_pad); | ||
| 572 | EXPORT_SYMBOL(hermes_read_ltv); | 514 | EXPORT_SYMBOL(hermes_read_ltv); |
| 573 | EXPORT_SYMBOL(hermes_write_ltv); | 515 | EXPORT_SYMBOL(hermes_write_ltv); |
| 574 | 516 | ||
diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h index 7644f72a9f4e..8e3f0e3edb58 100644 --- a/drivers/net/wireless/hermes.h +++ b/drivers/net/wireless/hermes.h | |||
| @@ -328,16 +328,6 @@ struct hermes_multicast { | |||
| 328 | u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN]; | 328 | u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN]; |
| 329 | } __attribute__ ((packed)); | 329 | } __attribute__ ((packed)); |
| 330 | 330 | ||
| 331 | // #define HERMES_DEBUG_BUFFER 1 | ||
| 332 | #define HERMES_DEBUG_BUFSIZE 4096 | ||
| 333 | struct hermes_debug_entry { | ||
| 334 | int bap; | ||
| 335 | u16 id, offset; | ||
| 336 | int cycles; | ||
| 337 | }; | ||
| 338 | |||
| 339 | #ifdef __KERNEL__ | ||
| 340 | |||
| 341 | /* Timeouts */ | 331 | /* Timeouts */ |
| 342 | #define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */ | 332 | #define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */ |
| 343 | 333 | ||
| @@ -347,14 +337,7 @@ typedef struct hermes { | |||
| 347 | int reg_spacing; | 337 | int reg_spacing; |
| 348 | #define HERMES_16BIT_REGSPACING 0 | 338 | #define HERMES_16BIT_REGSPACING 0 |
| 349 | #define HERMES_32BIT_REGSPACING 1 | 339 | #define HERMES_32BIT_REGSPACING 1 |
| 350 | |||
| 351 | u16 inten; /* Which interrupts should be enabled? */ | 340 | u16 inten; /* Which interrupts should be enabled? */ |
| 352 | |||
| 353 | #ifdef HERMES_DEBUG_BUFFER | ||
| 354 | struct hermes_debug_entry dbuf[HERMES_DEBUG_BUFSIZE]; | ||
| 355 | unsigned long dbufp; | ||
| 356 | unsigned long profile[HERMES_BAP_BUSY_TIMEOUT+1]; | ||
| 357 | #endif | ||
| 358 | } hermes_t; | 341 | } hermes_t; |
| 359 | 342 | ||
| 360 | /* Register access convenience macros */ | 343 | /* Register access convenience macros */ |
| @@ -376,8 +359,6 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, | |||
| 376 | u16 id, u16 offset); | 359 | u16 id, u16 offset); |
| 377 | int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, | 360 | int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, |
| 378 | u16 id, u16 offset); | 361 | u16 id, u16 offset); |
| 379 | int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf, | ||
| 380 | unsigned data_len, int len, u16 id, u16 offset); | ||
| 381 | int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen, | 362 | int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen, |
| 382 | u16 *length, void *buf); | 363 | u16 *length, void *buf); |
| 383 | int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, | 364 | int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, |
| @@ -425,10 +406,13 @@ static inline void hermes_read_words(struct hermes *hw, int off, void *buf, unsi | |||
| 425 | ioread16_rep(hw->iobase + off, buf, count); | 406 | ioread16_rep(hw->iobase + off, buf, count); |
| 426 | } | 407 | } |
| 427 | 408 | ||
| 428 | static inline void hermes_write_words(struct hermes *hw, int off, const void *buf, unsigned count) | 409 | static inline void hermes_write_bytes(struct hermes *hw, int off, |
| 410 | const char *buf, unsigned count) | ||
| 429 | { | 411 | { |
| 430 | off = off << hw->reg_spacing; | 412 | off = off << hw->reg_spacing; |
| 431 | iowrite16_rep(hw->iobase + off, buf, count); | 413 | iowrite16_rep(hw->iobase + off, buf, count >> 1); |
| 414 | if (unlikely(count & 1)) | ||
| 415 | iowrite8(buf[count - 1], hw->iobase + off); | ||
| 432 | } | 416 | } |
| 433 | 417 | ||
| 434 | static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count) | 418 | static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count) |
| @@ -462,21 +446,4 @@ static inline int hermes_write_wordrec(hermes_t *hw, int bap, u16 rid, u16 word) | |||
| 462 | return HERMES_WRITE_RECORD(hw, bap, rid, &rec); | 446 | return HERMES_WRITE_RECORD(hw, bap, rid, &rec); |
| 463 | } | 447 | } |
| 464 | 448 | ||
| 465 | #else /* ! __KERNEL__ */ | ||
| 466 | |||
| 467 | /* These are provided for the benefit of userspace drivers and testing programs | ||
| 468 | which use ioperm() or iopl() */ | ||
| 469 | |||
| 470 | #define hermes_read_reg(base, off) (inw((base) + (off))) | ||
| 471 | #define hermes_write_reg(base, off, val) (outw((val), (base) + (off))) | ||
| 472 | |||
| 473 | #define hermes_read_regn(base, name) (hermes_read_reg((base), HERMES_##name)) | ||
| 474 | #define hermes_write_regn(base, name, val) (hermes_write_reg((base), HERMES_##name, (val))) | ||
| 475 | |||
| 476 | /* Note that for the next two, the count is in 16-bit words, not bytes */ | ||
| 477 | #define hermes_read_data(base, off, buf, count) (insw((base) + (off), (buf), (count))) | ||
| 478 | #define hermes_write_data(base, off, buf, count) (outsw((base) + (off), (buf), (count))) | ||
| 479 | |||
| 480 | #endif /* ! __KERNEL__ */ | ||
| 481 | |||
| 482 | #endif /* _HERMES_H */ | 449 | #endif /* _HERMES_H */ |
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c index 06a5214145e3..4a5be70c0419 100644 --- a/drivers/net/wireless/hostap/hostap_80211_tx.c +++ b/drivers/net/wireless/hostap/hostap_80211_tx.c | |||
| @@ -534,5 +534,4 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 534 | } | 534 | } |
| 535 | 535 | ||
| 536 | 536 | ||
| 537 | EXPORT_SYMBOL(hostap_dump_tx_80211); | ||
| 538 | EXPORT_SYMBOL(hostap_master_start_xmit); | 537 | EXPORT_SYMBOL(hostap_master_start_xmit); |
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index 06c3fa32b310..ba13125024cb 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c | |||
| @@ -3276,17 +3276,6 @@ EXPORT_SYMBOL(hostap_init_data); | |||
| 3276 | EXPORT_SYMBOL(hostap_init_ap_proc); | 3276 | EXPORT_SYMBOL(hostap_init_ap_proc); |
| 3277 | EXPORT_SYMBOL(hostap_free_data); | 3277 | EXPORT_SYMBOL(hostap_free_data); |
| 3278 | EXPORT_SYMBOL(hostap_check_sta_fw_version); | 3278 | EXPORT_SYMBOL(hostap_check_sta_fw_version); |
| 3279 | EXPORT_SYMBOL(hostap_handle_sta_tx); | ||
| 3280 | EXPORT_SYMBOL(hostap_handle_sta_release); | ||
| 3281 | EXPORT_SYMBOL(hostap_handle_sta_tx_exc); | 3279 | EXPORT_SYMBOL(hostap_handle_sta_tx_exc); |
| 3282 | EXPORT_SYMBOL(hostap_update_sta_ps); | ||
| 3283 | EXPORT_SYMBOL(hostap_handle_sta_rx); | ||
| 3284 | EXPORT_SYMBOL(hostap_is_sta_assoc); | ||
| 3285 | EXPORT_SYMBOL(hostap_is_sta_authorized); | ||
| 3286 | EXPORT_SYMBOL(hostap_add_sta); | ||
| 3287 | EXPORT_SYMBOL(hostap_update_rates); | ||
| 3288 | EXPORT_SYMBOL(hostap_add_wds_links); | ||
| 3289 | EXPORT_SYMBOL(hostap_wds_link_oper); | ||
| 3290 | #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT | 3280 | #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT |
| 3291 | EXPORT_SYMBOL(hostap_deauth_all_stas); | ||
| 3292 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ | 3281 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ |
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 55bed923fbe9..db03dc2646df 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c | |||
| @@ -881,6 +881,12 @@ static struct pcmcia_device_id hostap_cs_ids[] = { | |||
| 881 | PCMCIA_DEVICE_PROD_ID12( | 881 | PCMCIA_DEVICE_PROD_ID12( |
| 882 | "ZoomAir 11Mbps High", "Rate wireless Networking", | 882 | "ZoomAir 11Mbps High", "Rate wireless Networking", |
| 883 | 0x273fe3db, 0x32a1eaee), | 883 | 0x273fe3db, 0x32a1eaee), |
| 884 | PCMCIA_DEVICE_PROD_ID123( | ||
| 885 | "Pretec", "CompactWLAN Card 802.11b", "2.5", | ||
| 886 | 0x1cadd3e5, 0xe697636c, 0x7a5bfcf1), | ||
| 887 | PCMCIA_DEVICE_PROD_ID123( | ||
| 888 | "U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02", | ||
| 889 | 0xc7b8df9d, 0x1700d087, 0x4b74baa0), | ||
| 884 | PCMCIA_DEVICE_NULL | 890 | PCMCIA_DEVICE_NULL |
| 885 | }; | 891 | }; |
| 886 | MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids); | 892 | MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids); |
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index 8dd4c4446a64..93786f4218f0 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c | |||
| @@ -1125,11 +1125,9 @@ EXPORT_SYMBOL(hostap_set_auth_algs); | |||
| 1125 | EXPORT_SYMBOL(hostap_dump_rx_header); | 1125 | EXPORT_SYMBOL(hostap_dump_rx_header); |
| 1126 | EXPORT_SYMBOL(hostap_dump_tx_header); | 1126 | EXPORT_SYMBOL(hostap_dump_tx_header); |
| 1127 | EXPORT_SYMBOL(hostap_80211_header_parse); | 1127 | EXPORT_SYMBOL(hostap_80211_header_parse); |
| 1128 | EXPORT_SYMBOL(hostap_80211_prism_header_parse); | ||
| 1129 | EXPORT_SYMBOL(hostap_80211_get_hdrlen); | 1128 | EXPORT_SYMBOL(hostap_80211_get_hdrlen); |
| 1130 | EXPORT_SYMBOL(hostap_get_stats); | 1129 | EXPORT_SYMBOL(hostap_get_stats); |
| 1131 | EXPORT_SYMBOL(hostap_setup_dev); | 1130 | EXPORT_SYMBOL(hostap_setup_dev); |
| 1132 | EXPORT_SYMBOL(hostap_proc); | ||
| 1133 | EXPORT_SYMBOL(hostap_set_multicast_list_queue); | 1131 | EXPORT_SYMBOL(hostap_set_multicast_list_queue); |
| 1134 | EXPORT_SYMBOL(hostap_set_hostapd); | 1132 | EXPORT_SYMBOL(hostap_set_hostapd); |
| 1135 | EXPORT_SYMBOL(hostap_set_hostapd_sta); | 1133 | EXPORT_SYMBOL(hostap_set_hostapd_sta); |
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index bca89cff85a6..39f82f219749 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c | |||
| @@ -33,7 +33,44 @@ | |||
| 33 | #include "ipw2200.h" | 33 | #include "ipw2200.h" |
| 34 | #include <linux/version.h> | 34 | #include <linux/version.h> |
| 35 | 35 | ||
| 36 | #define IPW2200_VERSION "git-1.1.1" | 36 | |
| 37 | #ifndef KBUILD_EXTMOD | ||
| 38 | #define VK "k" | ||
| 39 | #else | ||
| 40 | #define VK | ||
| 41 | #endif | ||
| 42 | |||
| 43 | #ifdef CONFIG_IPW2200_DEBUG | ||
| 44 | #define VD "d" | ||
| 45 | #else | ||
| 46 | #define VD | ||
| 47 | #endif | ||
| 48 | |||
| 49 | #ifdef CONFIG_IPW2200_MONITOR | ||
| 50 | #define VM "m" | ||
| 51 | #else | ||
| 52 | #define VM | ||
| 53 | #endif | ||
| 54 | |||
| 55 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 56 | #define VP "p" | ||
| 57 | #else | ||
| 58 | #define VP | ||
| 59 | #endif | ||
| 60 | |||
| 61 | #ifdef CONFIG_IPW2200_RADIOTAP | ||
| 62 | #define VR "r" | ||
| 63 | #else | ||
| 64 | #define VR | ||
| 65 | #endif | ||
| 66 | |||
| 67 | #ifdef CONFIG_IPW2200_QOS | ||
| 68 | #define VQ "q" | ||
| 69 | #else | ||
| 70 | #define VQ | ||
| 71 | #endif | ||
| 72 | |||
| 73 | #define IPW2200_VERSION "1.1.2" VK VD VM VP VR VQ | ||
| 37 | #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" | 74 | #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" |
| 38 | #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" | 75 | #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" |
| 39 | #define DRV_VERSION IPW2200_VERSION | 76 | #define DRV_VERSION IPW2200_VERSION |
| @@ -46,7 +83,9 @@ MODULE_AUTHOR(DRV_COPYRIGHT); | |||
| 46 | MODULE_LICENSE("GPL"); | 83 | MODULE_LICENSE("GPL"); |
| 47 | 84 | ||
| 48 | static int cmdlog = 0; | 85 | static int cmdlog = 0; |
| 86 | #ifdef CONFIG_IPW2200_DEBUG | ||
| 49 | static int debug = 0; | 87 | static int debug = 0; |
| 88 | #endif | ||
| 50 | static int channel = 0; | 89 | static int channel = 0; |
| 51 | static int mode = 0; | 90 | static int mode = 0; |
| 52 | 91 | ||
| @@ -61,8 +100,14 @@ static int roaming = 1; | |||
| 61 | static const char ipw_modes[] = { | 100 | static const char ipw_modes[] = { |
| 62 | 'a', 'b', 'g', '?' | 101 | 'a', 'b', 'g', '?' |
| 63 | }; | 102 | }; |
| 103 | static int antenna = CFG_SYS_ANTENNA_BOTH; | ||
| 64 | 104 | ||
| 65 | #ifdef CONFIG_IPW_QOS | 105 | #ifdef CONFIG_IPW2200_PROMISCUOUS |
| 106 | static int rtap_iface = 0; /* def: 0 -- do not create rtap interface */ | ||
| 107 | #endif | ||
| 108 | |||
| 109 | |||
| 110 | #ifdef CONFIG_IPW2200_QOS | ||
| 66 | static int qos_enable = 0; | 111 | static int qos_enable = 0; |
| 67 | static int qos_burst_enable = 0; | 112 | static int qos_burst_enable = 0; |
| 68 | static int qos_no_ack_mask = 0; | 113 | static int qos_no_ack_mask = 0; |
| @@ -126,7 +171,7 @@ static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_q | |||
| 126 | *qos_param); | 171 | *qos_param); |
| 127 | static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element | 172 | static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element |
| 128 | *qos_param); | 173 | *qos_param); |
| 129 | #endif /* CONFIG_IPW_QOS */ | 174 | #endif /* CONFIG_IPW2200_QOS */ |
| 130 | 175 | ||
| 131 | static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev); | 176 | static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev); |
| 132 | static void ipw_remove_current_network(struct ipw_priv *priv); | 177 | static void ipw_remove_current_network(struct ipw_priv *priv); |
| @@ -1269,6 +1314,105 @@ static ssize_t show_cmd_log(struct device *d, | |||
| 1269 | 1314 | ||
| 1270 | static DEVICE_ATTR(cmd_log, S_IRUGO, show_cmd_log, NULL); | 1315 | static DEVICE_ATTR(cmd_log, S_IRUGO, show_cmd_log, NULL); |
| 1271 | 1316 | ||
| 1317 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 1318 | static void ipw_prom_free(struct ipw_priv *priv); | ||
| 1319 | static int ipw_prom_alloc(struct ipw_priv *priv); | ||
| 1320 | static ssize_t store_rtap_iface(struct device *d, | ||
| 1321 | struct device_attribute *attr, | ||
| 1322 | const char *buf, size_t count) | ||
| 1323 | { | ||
| 1324 | struct ipw_priv *priv = dev_get_drvdata(d); | ||
| 1325 | int rc = 0; | ||
| 1326 | |||
| 1327 | if (count < 1) | ||
| 1328 | return -EINVAL; | ||
| 1329 | |||
| 1330 | switch (buf[0]) { | ||
| 1331 | case '0': | ||
| 1332 | if (!rtap_iface) | ||
| 1333 | return count; | ||
| 1334 | |||
| 1335 | if (netif_running(priv->prom_net_dev)) { | ||
| 1336 | IPW_WARNING("Interface is up. Cannot unregister.\n"); | ||
| 1337 | return count; | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | ipw_prom_free(priv); | ||
| 1341 | rtap_iface = 0; | ||
| 1342 | break; | ||
| 1343 | |||
| 1344 | case '1': | ||
| 1345 | if (rtap_iface) | ||
| 1346 | return count; | ||
| 1347 | |||
| 1348 | rc = ipw_prom_alloc(priv); | ||
| 1349 | if (!rc) | ||
| 1350 | rtap_iface = 1; | ||
| 1351 | break; | ||
| 1352 | |||
| 1353 | default: | ||
| 1354 | return -EINVAL; | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | if (rc) { | ||
| 1358 | IPW_ERROR("Failed to register promiscuous network " | ||
| 1359 | "device (error %d).\n", rc); | ||
| 1360 | } | ||
| 1361 | |||
| 1362 | return count; | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | static ssize_t show_rtap_iface(struct device *d, | ||
| 1366 | struct device_attribute *attr, | ||
| 1367 | char *buf) | ||
| 1368 | { | ||
| 1369 | struct ipw_priv *priv = dev_get_drvdata(d); | ||
| 1370 | if (rtap_iface) | ||
| 1371 | return sprintf(buf, "%s", priv->prom_net_dev->name); | ||
| 1372 | else { | ||
| 1373 | buf[0] = '-'; | ||
| 1374 | buf[1] = '1'; | ||
| 1375 | buf[2] = '\0'; | ||
| 1376 | return 3; | ||
| 1377 | } | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | static DEVICE_ATTR(rtap_iface, S_IWUSR | S_IRUSR, show_rtap_iface, | ||
| 1381 | store_rtap_iface); | ||
| 1382 | |||
| 1383 | static ssize_t store_rtap_filter(struct device *d, | ||
| 1384 | struct device_attribute *attr, | ||
| 1385 | const char *buf, size_t count) | ||
| 1386 | { | ||
| 1387 | struct ipw_priv *priv = dev_get_drvdata(d); | ||
| 1388 | |||
| 1389 | if (!priv->prom_priv) { | ||
| 1390 | IPW_ERROR("Attempting to set filter without " | ||
| 1391 | "rtap_iface enabled.\n"); | ||
| 1392 | return -EPERM; | ||
| 1393 | } | ||
| 1394 | |||
| 1395 | priv->prom_priv->filter = simple_strtol(buf, NULL, 0); | ||
| 1396 | |||
| 1397 | IPW_DEBUG_INFO("Setting rtap filter to " BIT_FMT16 "\n", | ||
| 1398 | BIT_ARG16(priv->prom_priv->filter)); | ||
| 1399 | |||
| 1400 | return count; | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | static ssize_t show_rtap_filter(struct device *d, | ||
| 1404 | struct device_attribute *attr, | ||
| 1405 | char *buf) | ||
| 1406 | { | ||
| 1407 | struct ipw_priv *priv = dev_get_drvdata(d); | ||
| 1408 | return sprintf(buf, "0x%04X", | ||
| 1409 | priv->prom_priv ? priv->prom_priv->filter : 0); | ||
| 1410 | } | ||
| 1411 | |||
| 1412 | static DEVICE_ATTR(rtap_filter, S_IWUSR | S_IRUSR, show_rtap_filter, | ||
| 1413 | store_rtap_filter); | ||
| 1414 | #endif | ||
| 1415 | |||
| 1272 | static ssize_t show_scan_age(struct device *d, struct device_attribute *attr, | 1416 | static ssize_t show_scan_age(struct device *d, struct device_attribute *attr, |
| 1273 | char *buf) | 1417 | char *buf) |
| 1274 | { | 1418 | { |
| @@ -2025,16 +2169,11 @@ static int ipw_send_host_complete(struct ipw_priv *priv) | |||
| 2025 | return ipw_send_cmd_simple(priv, IPW_CMD_HOST_COMPLETE); | 2169 | return ipw_send_cmd_simple(priv, IPW_CMD_HOST_COMPLETE); |
| 2026 | } | 2170 | } |
| 2027 | 2171 | ||
| 2028 | static int ipw_send_system_config(struct ipw_priv *priv, | 2172 | static int ipw_send_system_config(struct ipw_priv *priv) |
| 2029 | struct ipw_sys_config *config) | ||
| 2030 | { | 2173 | { |
| 2031 | if (!priv || !config) { | 2174 | return ipw_send_cmd_pdu(priv, IPW_CMD_SYSTEM_CONFIG, |
| 2032 | IPW_ERROR("Invalid args\n"); | 2175 | sizeof(priv->sys_config), |
| 2033 | return -1; | 2176 | &priv->sys_config); |
| 2034 | } | ||
| 2035 | |||
| 2036 | return ipw_send_cmd_pdu(priv, IPW_CMD_SYSTEM_CONFIG, sizeof(*config), | ||
| 2037 | config); | ||
| 2038 | } | 2177 | } |
| 2039 | 2178 | ||
| 2040 | static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len) | 2179 | static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len) |
| @@ -3104,10 +3243,10 @@ static int ipw_reset_nic(struct ipw_priv *priv) | |||
| 3104 | 3243 | ||
| 3105 | 3244 | ||
| 3106 | struct ipw_fw { | 3245 | struct ipw_fw { |
| 3107 | u32 ver; | 3246 | __le32 ver; |
| 3108 | u32 boot_size; | 3247 | __le32 boot_size; |
| 3109 | u32 ucode_size; | 3248 | __le32 ucode_size; |
| 3110 | u32 fw_size; | 3249 | __le32 fw_size; |
| 3111 | u8 data[0]; | 3250 | u8 data[0]; |
| 3112 | }; | 3251 | }; |
| 3113 | 3252 | ||
| @@ -3131,8 +3270,8 @@ static int ipw_get_fw(struct ipw_priv *priv, | |||
| 3131 | 3270 | ||
| 3132 | fw = (void *)(*raw)->data; | 3271 | fw = (void *)(*raw)->data; |
| 3133 | 3272 | ||
| 3134 | if ((*raw)->size < sizeof(*fw) + | 3273 | if ((*raw)->size < sizeof(*fw) + le32_to_cpu(fw->boot_size) + |
| 3135 | fw->boot_size + fw->ucode_size + fw->fw_size) { | 3274 | le32_to_cpu(fw->ucode_size) + le32_to_cpu(fw->fw_size)) { |
| 3136 | IPW_ERROR("%s is too small or corrupt (%zd)\n", | 3275 | IPW_ERROR("%s is too small or corrupt (%zd)\n", |
| 3137 | name, (*raw)->size); | 3276 | name, (*raw)->size); |
| 3138 | return -EINVAL; | 3277 | return -EINVAL; |
| @@ -3237,8 +3376,9 @@ static int ipw_load(struct ipw_priv *priv) | |||
| 3237 | 3376 | ||
| 3238 | fw = (void *)raw->data; | 3377 | fw = (void *)raw->data; |
| 3239 | boot_img = &fw->data[0]; | 3378 | boot_img = &fw->data[0]; |
| 3240 | ucode_img = &fw->data[fw->boot_size]; | 3379 | ucode_img = &fw->data[le32_to_cpu(fw->boot_size)]; |
| 3241 | fw_img = &fw->data[fw->boot_size + fw->ucode_size]; | 3380 | fw_img = &fw->data[le32_to_cpu(fw->boot_size) + |
| 3381 | le32_to_cpu(fw->ucode_size)]; | ||
| 3242 | 3382 | ||
| 3243 | if (rc < 0) | 3383 | if (rc < 0) |
| 3244 | goto error; | 3384 | goto error; |
| @@ -3272,7 +3412,7 @@ static int ipw_load(struct ipw_priv *priv) | |||
| 3272 | IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND); | 3412 | IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND); |
| 3273 | 3413 | ||
| 3274 | /* DMA the initial boot firmware into the device */ | 3414 | /* DMA the initial boot firmware into the device */ |
| 3275 | rc = ipw_load_firmware(priv, boot_img, fw->boot_size); | 3415 | rc = ipw_load_firmware(priv, boot_img, le32_to_cpu(fw->boot_size)); |
| 3276 | if (rc < 0) { | 3416 | if (rc < 0) { |
| 3277 | IPW_ERROR("Unable to load boot firmware: %d\n", rc); | 3417 | IPW_ERROR("Unable to load boot firmware: %d\n", rc); |
| 3278 | goto error; | 3418 | goto error; |
| @@ -3294,7 +3434,7 @@ static int ipw_load(struct ipw_priv *priv) | |||
| 3294 | ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); | 3434 | ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); |
| 3295 | 3435 | ||
| 3296 | /* DMA the ucode into the device */ | 3436 | /* DMA the ucode into the device */ |
| 3297 | rc = ipw_load_ucode(priv, ucode_img, fw->ucode_size); | 3437 | rc = ipw_load_ucode(priv, ucode_img, le32_to_cpu(fw->ucode_size)); |
| 3298 | if (rc < 0) { | 3438 | if (rc < 0) { |
| 3299 | IPW_ERROR("Unable to load ucode: %d\n", rc); | 3439 | IPW_ERROR("Unable to load ucode: %d\n", rc); |
| 3300 | goto error; | 3440 | goto error; |
| @@ -3304,7 +3444,7 @@ static int ipw_load(struct ipw_priv *priv) | |||
| 3304 | ipw_stop_nic(priv); | 3444 | ipw_stop_nic(priv); |
| 3305 | 3445 | ||
| 3306 | /* DMA bss firmware into the device */ | 3446 | /* DMA bss firmware into the device */ |
| 3307 | rc = ipw_load_firmware(priv, fw_img, fw->fw_size); | 3447 | rc = ipw_load_firmware(priv, fw_img, le32_to_cpu(fw->fw_size)); |
| 3308 | if (rc < 0) { | 3448 | if (rc < 0) { |
| 3309 | IPW_ERROR("Unable to load firmware: %d\n", rc); | 3449 | IPW_ERROR("Unable to load firmware: %d\n", rc); |
| 3310 | goto error; | 3450 | goto error; |
| @@ -3700,7 +3840,17 @@ static void ipw_bg_disassociate(void *data) | |||
| 3700 | static void ipw_system_config(void *data) | 3840 | static void ipw_system_config(void *data) |
| 3701 | { | 3841 | { |
| 3702 | struct ipw_priv *priv = data; | 3842 | struct ipw_priv *priv = data; |
| 3703 | ipw_send_system_config(priv, &priv->sys_config); | 3843 | |
| 3844 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 3845 | if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) { | ||
| 3846 | priv->sys_config.accept_all_data_frames = 1; | ||
| 3847 | priv->sys_config.accept_non_directed_frames = 1; | ||
| 3848 | priv->sys_config.accept_all_mgmt_bcpr = 1; | ||
| 3849 | priv->sys_config.accept_all_mgmt_frames = 1; | ||
| 3850 | } | ||
| 3851 | #endif | ||
| 3852 | |||
| 3853 | ipw_send_system_config(priv); | ||
| 3704 | } | 3854 | } |
| 3705 | 3855 | ||
| 3706 | struct ipw_status_code { | 3856 | struct ipw_status_code { |
| @@ -3771,6 +3921,13 @@ static void inline average_init(struct average *avg) | |||
| 3771 | memset(avg, 0, sizeof(*avg)); | 3921 | memset(avg, 0, sizeof(*avg)); |
| 3772 | } | 3922 | } |
| 3773 | 3923 | ||
| 3924 | #define DEPTH_RSSI 8 | ||
| 3925 | #define DEPTH_NOISE 16 | ||
| 3926 | static s16 exponential_average(s16 prev_avg, s16 val, u8 depth) | ||
| 3927 | { | ||
| 3928 | return ((depth-1)*prev_avg + val)/depth; | ||
| 3929 | } | ||
| 3930 | |||
| 3774 | static void average_add(struct average *avg, s16 val) | 3931 | static void average_add(struct average *avg, s16 val) |
| 3775 | { | 3932 | { |
| 3776 | avg->sum -= avg->entries[avg->pos]; | 3933 | avg->sum -= avg->entries[avg->pos]; |
| @@ -3800,8 +3957,8 @@ static void ipw_reset_stats(struct ipw_priv *priv) | |||
| 3800 | priv->quality = 0; | 3957 | priv->quality = 0; |
| 3801 | 3958 | ||
| 3802 | average_init(&priv->average_missed_beacons); | 3959 | average_init(&priv->average_missed_beacons); |
| 3803 | average_init(&priv->average_rssi); | 3960 | priv->exp_avg_rssi = -60; |
| 3804 | average_init(&priv->average_noise); | 3961 | priv->exp_avg_noise = -85 + 0x100; |
| 3805 | 3962 | ||
| 3806 | priv->last_rate = 0; | 3963 | priv->last_rate = 0; |
| 3807 | priv->last_missed_beacons = 0; | 3964 | priv->last_missed_beacons = 0; |
| @@ -4008,7 +4165,7 @@ static void ipw_gather_stats(struct ipw_priv *priv) | |||
| 4008 | IPW_DEBUG_STATS("Tx quality : %3d%% (%u errors, %u packets)\n", | 4165 | IPW_DEBUG_STATS("Tx quality : %3d%% (%u errors, %u packets)\n", |
| 4009 | tx_quality, tx_failures_delta, tx_packets_delta); | 4166 | tx_quality, tx_failures_delta, tx_packets_delta); |
| 4010 | 4167 | ||
| 4011 | rssi = average_value(&priv->average_rssi); | 4168 | rssi = priv->exp_avg_rssi; |
| 4012 | signal_quality = | 4169 | signal_quality = |
| 4013 | (100 * | 4170 | (100 * |
| 4014 | (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) * | 4171 | (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) * |
| @@ -4185,7 +4342,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
| 4185 | queue_work(priv->workqueue, | 4342 | queue_work(priv->workqueue, |
| 4186 | &priv->system_config); | 4343 | &priv->system_config); |
| 4187 | 4344 | ||
| 4188 | #ifdef CONFIG_IPW_QOS | 4345 | #ifdef CONFIG_IPW2200_QOS |
| 4189 | #define IPW_GET_PACKET_STYPE(x) WLAN_FC_GET_STYPE( \ | 4346 | #define IPW_GET_PACKET_STYPE(x) WLAN_FC_GET_STYPE( \ |
| 4190 | le16_to_cpu(((struct ieee80211_hdr *)(x))->frame_ctl)) | 4347 | le16_to_cpu(((struct ieee80211_hdr *)(x))->frame_ctl)) |
| 4191 | if ((priv->status & STATUS_AUTH) && | 4348 | if ((priv->status & STATUS_AUTH) && |
| @@ -4482,6 +4639,24 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
| 4482 | && priv->status & STATUS_ASSOCIATED) | 4639 | && priv->status & STATUS_ASSOCIATED) |
| 4483 | queue_delayed_work(priv->workqueue, | 4640 | queue_delayed_work(priv->workqueue, |
| 4484 | &priv->request_scan, HZ); | 4641 | &priv->request_scan, HZ); |
| 4642 | |||
| 4643 | /* Send an empty event to user space. | ||
| 4644 | * We don't send the received data on the event because | ||
| 4645 | * it would require us to do complex transcoding, and | ||
| 4646 | * we want to minimise the work done in the irq handler | ||
| 4647 | * Use a request to extract the data. | ||
| 4648 | * Also, we generate this even for any scan, regardless | ||
| 4649 | * on how the scan was initiated. User space can just | ||
| 4650 | * sync on periodic scan to get fresh data... | ||
| 4651 | * Jean II */ | ||
| 4652 | if (x->status == SCAN_COMPLETED_STATUS_COMPLETE) { | ||
| 4653 | union iwreq_data wrqu; | ||
| 4654 | |||
| 4655 | wrqu.data.length = 0; | ||
| 4656 | wrqu.data.flags = 0; | ||
| 4657 | wireless_send_event(priv->net_dev, SIOCGIWSCAN, | ||
| 4658 | &wrqu, NULL); | ||
| 4659 | } | ||
| 4485 | break; | 4660 | break; |
| 4486 | } | 4661 | } |
| 4487 | 4662 | ||
| @@ -4577,11 +4752,10 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
| 4577 | 4752 | ||
| 4578 | case HOST_NOTIFICATION_NOISE_STATS:{ | 4753 | case HOST_NOTIFICATION_NOISE_STATS:{ |
| 4579 | if (notif->size == sizeof(u32)) { | 4754 | if (notif->size == sizeof(u32)) { |
| 4580 | priv->last_noise = | 4755 | priv->exp_avg_noise = |
| 4581 | (u8) (le32_to_cpu(notif->u.noise.value) & | 4756 | exponential_average(priv->exp_avg_noise, |
| 4582 | 0xff); | 4757 | (u8) (le32_to_cpu(notif->u.noise.value) & 0xff), |
| 4583 | average_add(&priv->average_noise, | 4758 | DEPTH_NOISE); |
| 4584 | priv->last_noise); | ||
| 4585 | break; | 4759 | break; |
| 4586 | } | 4760 | } |
| 4587 | 4761 | ||
| @@ -6170,8 +6344,6 @@ static void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, | |||
| 6170 | { | 6344 | { |
| 6171 | /* make sure WPA is enabled */ | 6345 | /* make sure WPA is enabled */ |
| 6172 | ipw_wpa_enable(priv, 1); | 6346 | ipw_wpa_enable(priv, 1); |
| 6173 | |||
| 6174 | ipw_disassociate(priv); | ||
| 6175 | } | 6347 | } |
| 6176 | 6348 | ||
| 6177 | static int ipw_set_rsn_capa(struct ipw_priv *priv, | 6349 | static int ipw_set_rsn_capa(struct ipw_priv *priv, |
| @@ -6365,6 +6537,7 @@ static int ipw_wx_set_auth(struct net_device *dev, | |||
| 6365 | 6537 | ||
| 6366 | case IW_AUTH_WPA_ENABLED: | 6538 | case IW_AUTH_WPA_ENABLED: |
| 6367 | ret = ipw_wpa_enable(priv, param->value); | 6539 | ret = ipw_wpa_enable(priv, param->value); |
| 6540 | ipw_disassociate(priv); | ||
| 6368 | break; | 6541 | break; |
| 6369 | 6542 | ||
| 6370 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: | 6543 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: |
| @@ -6506,7 +6679,7 @@ static int ipw_wx_set_mlme(struct net_device *dev, | |||
| 6506 | return 0; | 6679 | return 0; |
| 6507 | } | 6680 | } |
| 6508 | 6681 | ||
| 6509 | #ifdef CONFIG_IPW_QOS | 6682 | #ifdef CONFIG_IPW2200_QOS |
| 6510 | 6683 | ||
| 6511 | /* QoS */ | 6684 | /* QoS */ |
| 6512 | /* | 6685 | /* |
| @@ -6853,61 +7026,55 @@ static int ipw_get_tx_queue_number(struct ipw_priv *priv, u16 priority) | |||
| 6853 | return from_priority_to_tx_queue[priority] - 1; | 7026 | return from_priority_to_tx_queue[priority] - 1; |
| 6854 | } | 7027 | } |
| 6855 | 7028 | ||
| 6856 | /* | 7029 | static int ipw_is_qos_active(struct net_device *dev, |
| 6857 | * add QoS parameter to the TX command | 7030 | struct sk_buff *skb) |
| 6858 | */ | ||
| 6859 | static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv, | ||
| 6860 | u16 priority, | ||
| 6861 | struct tfd_data *tfd, u8 unicast) | ||
| 6862 | { | 7031 | { |
| 6863 | int ret = 0; | 7032 | struct ipw_priv *priv = ieee80211_priv(dev); |
| 6864 | int tx_queue_id = 0; | ||
| 6865 | struct ieee80211_qos_data *qos_data = NULL; | 7033 | struct ieee80211_qos_data *qos_data = NULL; |
| 6866 | int active, supported; | 7034 | int active, supported; |
| 6867 | unsigned long flags; | 7035 | u8 *daddr = skb->data + ETH_ALEN; |
| 7036 | int unicast = !is_multicast_ether_addr(daddr); | ||
| 6868 | 7037 | ||
| 6869 | if (!(priv->status & STATUS_ASSOCIATED)) | 7038 | if (!(priv->status & STATUS_ASSOCIATED)) |
| 6870 | return 0; | 7039 | return 0; |
| 6871 | 7040 | ||
| 6872 | qos_data = &priv->assoc_network->qos_data; | 7041 | qos_data = &priv->assoc_network->qos_data; |
| 6873 | 7042 | ||
| 6874 | spin_lock_irqsave(&priv->ieee->lock, flags); | ||
| 6875 | |||
| 6876 | if (priv->ieee->iw_mode == IW_MODE_ADHOC) { | 7043 | if (priv->ieee->iw_mode == IW_MODE_ADHOC) { |
| 6877 | if (unicast == 0) | 7044 | if (unicast == 0) |
| 6878 | qos_data->active = 0; | 7045 | qos_data->active = 0; |
| 6879 | else | 7046 | else |
| 6880 | qos_data->active = qos_data->supported; | 7047 | qos_data->active = qos_data->supported; |
| 6881 | } | 7048 | } |
| 6882 | |||
| 6883 | active = qos_data->active; | 7049 | active = qos_data->active; |
| 6884 | supported = qos_data->supported; | 7050 | supported = qos_data->supported; |
| 6885 | |||
| 6886 | spin_unlock_irqrestore(&priv->ieee->lock, flags); | ||
| 6887 | |||
| 6888 | IPW_DEBUG_QOS("QoS %d network is QoS active %d supported %d " | 7051 | IPW_DEBUG_QOS("QoS %d network is QoS active %d supported %d " |
| 6889 | "unicast %d\n", | 7052 | "unicast %d\n", |
| 6890 | priv->qos_data.qos_enable, active, supported, unicast); | 7053 | priv->qos_data.qos_enable, active, supported, unicast); |
| 6891 | if (active && priv->qos_data.qos_enable) { | 7054 | if (active && priv->qos_data.qos_enable) |
| 6892 | ret = from_priority_to_tx_queue[priority]; | 7055 | return 1; |
| 6893 | tx_queue_id = ret - 1; | ||
| 6894 | IPW_DEBUG_QOS("QoS packet priority is %d \n", priority); | ||
| 6895 | if (priority <= 7) { | ||
| 6896 | tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED; | ||
| 6897 | tfd->tfd.tfd_26.mchdr.qos_ctrl = priority; | ||
| 6898 | tfd->tfd.tfd_26.mchdr.frame_ctl |= | ||
| 6899 | IEEE80211_STYPE_QOS_DATA; | ||
| 6900 | |||
| 6901 | if (priv->qos_data.qos_no_ack_mask & | ||
| 6902 | (1UL << tx_queue_id)) { | ||
| 6903 | tfd->tx_flags &= ~DCT_FLAG_ACK_REQD; | ||
| 6904 | tfd->tfd.tfd_26.mchdr.qos_ctrl |= | ||
| 6905 | CTRL_QOS_NO_ACK; | ||
| 6906 | } | ||
| 6907 | } | ||
| 6908 | } | ||
| 6909 | 7056 | ||
| 6910 | return ret; | 7057 | return 0; |
| 7058 | |||
| 7059 | } | ||
| 7060 | /* | ||
| 7061 | * add QoS parameter to the TX command | ||
| 7062 | */ | ||
| 7063 | static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv, | ||
| 7064 | u16 priority, | ||
| 7065 | struct tfd_data *tfd) | ||
| 7066 | { | ||
| 7067 | int tx_queue_id = 0; | ||
| 7068 | |||
| 7069 | |||
| 7070 | tx_queue_id = from_priority_to_tx_queue[priority] - 1; | ||
| 7071 | tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED; | ||
| 7072 | |||
| 7073 | if (priv->qos_data.qos_no_ack_mask & (1UL << tx_queue_id)) { | ||
| 7074 | tfd->tx_flags &= ~DCT_FLAG_ACK_REQD; | ||
| 7075 | tfd->tfd.tfd_26.mchdr.qos_ctrl |= CTRL_QOS_NO_ACK; | ||
| 7076 | } | ||
| 7077 | return 0; | ||
| 6911 | } | 7078 | } |
| 6912 | 7079 | ||
| 6913 | /* | 7080 | /* |
| @@ -6977,7 +7144,7 @@ static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos | |||
| 6977 | qos_param); | 7144 | qos_param); |
| 6978 | } | 7145 | } |
| 6979 | 7146 | ||
| 6980 | #endif /* CONFIG_IPW_QOS */ | 7147 | #endif /* CONFIG_IPW2200_QOS */ |
| 6981 | 7148 | ||
| 6982 | static int ipw_associate_network(struct ipw_priv *priv, | 7149 | static int ipw_associate_network(struct ipw_priv *priv, |
| 6983 | struct ieee80211_network *network, | 7150 | struct ieee80211_network *network, |
| @@ -7116,7 +7283,7 @@ static int ipw_associate_network(struct ipw_priv *priv, | |||
| 7116 | else | 7283 | else |
| 7117 | priv->sys_config.answer_broadcast_ssid_probe = 0; | 7284 | priv->sys_config.answer_broadcast_ssid_probe = 0; |
| 7118 | 7285 | ||
| 7119 | err = ipw_send_system_config(priv, &priv->sys_config); | 7286 | err = ipw_send_system_config(priv); |
| 7120 | if (err) { | 7287 | if (err) { |
| 7121 | IPW_DEBUG_HC("Attempt to send sys config command failed.\n"); | 7288 | IPW_DEBUG_HC("Attempt to send sys config command failed.\n"); |
| 7122 | return err; | 7289 | return err; |
| @@ -7141,7 +7308,7 @@ static int ipw_associate_network(struct ipw_priv *priv, | |||
| 7141 | 7308 | ||
| 7142 | priv->assoc_network = network; | 7309 | priv->assoc_network = network; |
| 7143 | 7310 | ||
| 7144 | #ifdef CONFIG_IPW_QOS | 7311 | #ifdef CONFIG_IPW2200_QOS |
| 7145 | ipw_qos_association(priv, network); | 7312 | ipw_qos_association(priv, network); |
| 7146 | #endif | 7313 | #endif |
| 7147 | 7314 | ||
| @@ -7415,7 +7582,7 @@ static void ipw_handle_data_packet(struct ipw_priv *priv, | |||
| 7415 | } | 7582 | } |
| 7416 | } | 7583 | } |
| 7417 | 7584 | ||
| 7418 | #ifdef CONFIG_IEEE80211_RADIOTAP | 7585 | #ifdef CONFIG_IPW2200_RADIOTAP |
| 7419 | static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, | 7586 | static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, |
| 7420 | struct ipw_rx_mem_buffer *rxb, | 7587 | struct ipw_rx_mem_buffer *rxb, |
| 7421 | struct ieee80211_rx_stats *stats) | 7588 | struct ieee80211_rx_stats *stats) |
| @@ -7432,15 +7599,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, | |||
| 7432 | /* Magic struct that slots into the radiotap header -- no reason | 7599 | /* Magic struct that slots into the radiotap header -- no reason |
| 7433 | * to build this manually element by element, we can write it much | 7600 | * to build this manually element by element, we can write it much |
| 7434 | * more efficiently than we can parse it. ORDER MATTERS HERE */ | 7601 | * more efficiently than we can parse it. ORDER MATTERS HERE */ |
| 7435 | struct ipw_rt_hdr { | 7602 | struct ipw_rt_hdr *ipw_rt; |
| 7436 | struct ieee80211_radiotap_header rt_hdr; | ||
| 7437 | u8 rt_flags; /* radiotap packet flags */ | ||
| 7438 | u8 rt_rate; /* rate in 500kb/s */ | ||
| 7439 | u16 rt_channel; /* channel in mhz */ | ||
| 7440 | u16 rt_chbitmask; /* channel bitfield */ | ||
| 7441 | s8 rt_dbmsignal; /* signal in dbM, kluged to signed */ | ||
| 7442 | u8 rt_antenna; /* antenna number */ | ||
| 7443 | } *ipw_rt; | ||
| 7444 | 7603 | ||
| 7445 | short len = le16_to_cpu(pkt->u.frame.length); | 7604 | short len = le16_to_cpu(pkt->u.frame.length); |
| 7446 | 7605 | ||
| @@ -7494,9 +7653,11 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, | |||
| 7494 | /* Big bitfield of all the fields we provide in radiotap */ | 7653 | /* Big bitfield of all the fields we provide in radiotap */ |
| 7495 | ipw_rt->rt_hdr.it_present = | 7654 | ipw_rt->rt_hdr.it_present = |
| 7496 | ((1 << IEEE80211_RADIOTAP_FLAGS) | | 7655 | ((1 << IEEE80211_RADIOTAP_FLAGS) | |
| 7656 | (1 << IEEE80211_RADIOTAP_TSFT) | | ||
| 7497 | (1 << IEEE80211_RADIOTAP_RATE) | | 7657 | (1 << IEEE80211_RADIOTAP_RATE) | |
| 7498 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | 7658 | (1 << IEEE80211_RADIOTAP_CHANNEL) | |
| 7499 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | | 7659 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | |
| 7660 | (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | | ||
| 7500 | (1 << IEEE80211_RADIOTAP_ANTENNA)); | 7661 | (1 << IEEE80211_RADIOTAP_ANTENNA)); |
| 7501 | 7662 | ||
| 7502 | /* Zero the flags, we'll add to them as we go */ | 7663 | /* Zero the flags, we'll add to them as we go */ |
| @@ -7582,6 +7743,217 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, | |||
| 7582 | } | 7743 | } |
| 7583 | #endif | 7744 | #endif |
| 7584 | 7745 | ||
| 7746 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 7747 | #define ieee80211_is_probe_response(fc) \ | ||
| 7748 | ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT && \ | ||
| 7749 | (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP ) | ||
| 7750 | |||
| 7751 | #define ieee80211_is_management(fc) \ | ||
| 7752 | ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) | ||
| 7753 | |||
| 7754 | #define ieee80211_is_control(fc) \ | ||
| 7755 | ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) | ||
| 7756 | |||
| 7757 | #define ieee80211_is_data(fc) \ | ||
| 7758 | ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) | ||
| 7759 | |||
| 7760 | #define ieee80211_is_assoc_request(fc) \ | ||
| 7761 | ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ) | ||
| 7762 | |||
| 7763 | #define ieee80211_is_reassoc_request(fc) \ | ||
| 7764 | ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ) | ||
| 7765 | |||
| 7766 | static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, | ||
| 7767 | struct ipw_rx_mem_buffer *rxb, | ||
| 7768 | struct ieee80211_rx_stats *stats) | ||
| 7769 | { | ||
| 7770 | struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; | ||
| 7771 | struct ipw_rx_frame *frame = &pkt->u.frame; | ||
| 7772 | struct ipw_rt_hdr *ipw_rt; | ||
| 7773 | |||
| 7774 | /* First cache any information we need before we overwrite | ||
| 7775 | * the information provided in the skb from the hardware */ | ||
| 7776 | struct ieee80211_hdr *hdr; | ||
| 7777 | u16 channel = frame->received_channel; | ||
| 7778 | u8 phy_flags = frame->antennaAndPhy; | ||
| 7779 | s8 signal = frame->rssi_dbm - IPW_RSSI_TO_DBM; | ||
| 7780 | s8 noise = frame->noise; | ||
| 7781 | u8 rate = frame->rate; | ||
| 7782 | short len = le16_to_cpu(pkt->u.frame.length); | ||
| 7783 | u64 tsf = 0; | ||
| 7784 | struct sk_buff *skb; | ||
| 7785 | int hdr_only = 0; | ||
| 7786 | u16 filter = priv->prom_priv->filter; | ||
| 7787 | |||
| 7788 | /* If the filter is set to not include Rx frames then return */ | ||
| 7789 | if (filter & IPW_PROM_NO_RX) | ||
| 7790 | return; | ||
| 7791 | |||
| 7792 | /* We received data from the HW, so stop the watchdog */ | ||
| 7793 | priv->prom_net_dev->trans_start = jiffies; | ||
| 7794 | |||
| 7795 | if (unlikely((len + IPW_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { | ||
| 7796 | priv->prom_priv->ieee->stats.rx_errors++; | ||
| 7797 | IPW_DEBUG_DROP("Corruption detected! Oh no!\n"); | ||
| 7798 | return; | ||
| 7799 | } | ||
| 7800 | |||
| 7801 | /* We only process data packets if the interface is open */ | ||
| 7802 | if (unlikely(!netif_running(priv->prom_net_dev))) { | ||
| 7803 | priv->prom_priv->ieee->stats.rx_dropped++; | ||
| 7804 | IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); | ||
| 7805 | return; | ||
| 7806 | } | ||
| 7807 | |||
| 7808 | /* Libpcap 0.9.3+ can handle variable length radiotap, so we'll use | ||
| 7809 | * that now */ | ||
| 7810 | if (len > IPW_RX_BUF_SIZE - sizeof(struct ipw_rt_hdr)) { | ||
| 7811 | /* FIXME: Should alloc bigger skb instead */ | ||
| 7812 | priv->prom_priv->ieee->stats.rx_dropped++; | ||
| 7813 | IPW_DEBUG_DROP("Dropping too large packet in monitor\n"); | ||
| 7814 | return; | ||
| 7815 | } | ||
| 7816 | |||
| 7817 | hdr = (void *)rxb->skb->data + IPW_RX_FRAME_SIZE; | ||
| 7818 | if (ieee80211_is_management(hdr->frame_ctl)) { | ||
| 7819 | if (filter & IPW_PROM_NO_MGMT) | ||
| 7820 | return; | ||
| 7821 | if (filter & IPW_PROM_MGMT_HEADER_ONLY) | ||
| 7822 | hdr_only = 1; | ||
| 7823 | } else if (ieee80211_is_control(hdr->frame_ctl)) { | ||
| 7824 | if (filter & IPW_PROM_NO_CTL) | ||
| 7825 | return; | ||
| 7826 | if (filter & IPW_PROM_CTL_HEADER_ONLY) | ||
| 7827 | hdr_only = 1; | ||
| 7828 | } else if (ieee80211_is_data(hdr->frame_ctl)) { | ||
| 7829 | if (filter & IPW_PROM_NO_DATA) | ||
| 7830 | return; | ||
| 7831 | if (filter & IPW_PROM_DATA_HEADER_ONLY) | ||
| 7832 | hdr_only = 1; | ||
| 7833 | } | ||
| 7834 | |||
| 7835 | /* Copy the SKB since this is for the promiscuous side */ | ||
| 7836 | skb = skb_copy(rxb->skb, GFP_ATOMIC); | ||
| 7837 | if (skb == NULL) { | ||
| 7838 | IPW_ERROR("skb_clone failed for promiscuous copy.\n"); | ||
| 7839 | return; | ||
| 7840 | } | ||
| 7841 | |||
| 7842 | /* copy the frame data to write after where the radiotap header goes */ | ||
| 7843 | ipw_rt = (void *)skb->data; | ||
| 7844 | |||
| 7845 | if (hdr_only) | ||
| 7846 | len = ieee80211_get_hdrlen(hdr->frame_ctl); | ||
| 7847 | |||
| 7848 | memcpy(ipw_rt->payload, hdr, len); | ||
| 7849 | |||
| 7850 | /* Zero the radiotap static buffer ... We only need to zero the bytes | ||
| 7851 | * NOT part of our real header, saves a little time. | ||
| 7852 | * | ||
| 7853 | * No longer necessary since we fill in all our data. Purge before | ||
| 7854 | * merging patch officially. | ||
| 7855 | * memset(rxb->skb->data + sizeof(struct ipw_rt_hdr), 0, | ||
| 7856 | * IEEE80211_RADIOTAP_HDRLEN - sizeof(struct ipw_rt_hdr)); | ||
| 7857 | */ | ||
| 7858 | |||
| 7859 | ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; | ||
| 7860 | ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */ | ||
| 7861 | ipw_rt->rt_hdr.it_len = sizeof(*ipw_rt); /* total header+data */ | ||
| 7862 | |||
| 7863 | /* Set the size of the skb to the size of the frame */ | ||
| 7864 | skb_put(skb, ipw_rt->rt_hdr.it_len + len); | ||
| 7865 | |||
| 7866 | /* Big bitfield of all the fields we provide in radiotap */ | ||
| 7867 | ipw_rt->rt_hdr.it_present = | ||
| 7868 | ((1 << IEEE80211_RADIOTAP_FLAGS) | | ||
| 7869 | (1 << IEEE80211_RADIOTAP_TSFT) | | ||
| 7870 | (1 << IEEE80211_RADIOTAP_RATE) | | ||
| 7871 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | ||
| 7872 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | | ||
| 7873 | (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | | ||
| 7874 | (1 << IEEE80211_RADIOTAP_ANTENNA)); | ||
| 7875 | |||
| 7876 | /* Zero the flags, we'll add to them as we go */ | ||
| 7877 | ipw_rt->rt_flags = 0; | ||
| 7878 | |||
| 7879 | ipw_rt->rt_tsf = tsf; | ||
| 7880 | |||
| 7881 | /* Convert to DBM */ | ||
| 7882 | ipw_rt->rt_dbmsignal = signal; | ||
| 7883 | ipw_rt->rt_dbmnoise = noise; | ||
| 7884 | |||
| 7885 | /* Convert the channel data and set the flags */ | ||
| 7886 | ipw_rt->rt_channel = cpu_to_le16(ieee80211chan2mhz(channel)); | ||
| 7887 | if (channel > 14) { /* 802.11a */ | ||
| 7888 | ipw_rt->rt_chbitmask = | ||
| 7889 | cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ)); | ||
| 7890 | } else if (phy_flags & (1 << 5)) { /* 802.11b */ | ||
| 7891 | ipw_rt->rt_chbitmask = | ||
| 7892 | cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ)); | ||
| 7893 | } else { /* 802.11g */ | ||
| 7894 | ipw_rt->rt_chbitmask = | ||
| 7895 | (IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ); | ||
| 7896 | } | ||
| 7897 | |||
| 7898 | /* set the rate in multiples of 500k/s */ | ||
| 7899 | switch (rate) { | ||
| 7900 | case IPW_TX_RATE_1MB: | ||
| 7901 | ipw_rt->rt_rate = 2; | ||
| 7902 | break; | ||
| 7903 | case IPW_TX_RATE_2MB: | ||
| 7904 | ipw_rt->rt_rate = 4; | ||
| 7905 | break; | ||
| 7906 | case IPW_TX_RATE_5MB: | ||
| 7907 | ipw_rt->rt_rate = 10; | ||
| 7908 | break; | ||
| 7909 | case IPW_TX_RATE_6MB: | ||
| 7910 | ipw_rt->rt_rate = 12; | ||
| 7911 | break; | ||
| 7912 | case IPW_TX_RATE_9MB: | ||
| 7913 | ipw_rt->rt_rate = 18; | ||
| 7914 | break; | ||
| 7915 | case IPW_TX_RATE_11MB: | ||
| 7916 | ipw_rt->rt_rate = 22; | ||
| 7917 | break; | ||
| 7918 | case IPW_TX_RATE_12MB: | ||
| 7919 | ipw_rt->rt_rate = 24; | ||
| 7920 | break; | ||
| 7921 | case IPW_TX_RATE_18MB: | ||
| 7922 | ipw_rt->rt_rate = 36; | ||
| 7923 | break; | ||
| 7924 | case IPW_TX_RATE_24MB: | ||
| 7925 | ipw_rt->rt_rate = 48; | ||
| 7926 | break; | ||
| 7927 | case IPW_TX_RATE_36MB: | ||
| 7928 | ipw_rt->rt_rate = 72; | ||
| 7929 | break; | ||
| 7930 | case IPW_TX_RATE_48MB: | ||
| 7931 | ipw_rt->rt_rate = 96; | ||
| 7932 | break; | ||
| 7933 | case IPW_TX_RATE_54MB: | ||
| 7934 | ipw_rt->rt_rate = 108; | ||
| 7935 | break; | ||
| 7936 | default: | ||
| 7937 | ipw_rt->rt_rate = 0; | ||
| 7938 | break; | ||
| 7939 | } | ||
| 7940 | |||
| 7941 | /* antenna number */ | ||
| 7942 | ipw_rt->rt_antenna = (phy_flags & 3); | ||
| 7943 | |||
| 7944 | /* set the preamble flag if we have it */ | ||
| 7945 | if (phy_flags & (1 << 6)) | ||
| 7946 | ipw_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; | ||
| 7947 | |||
| 7948 | IPW_DEBUG_RX("Rx packet of %d bytes.\n", skb->len); | ||
| 7949 | |||
| 7950 | if (!ieee80211_rx(priv->prom_priv->ieee, skb, stats)) { | ||
| 7951 | priv->prom_priv->ieee->stats.rx_errors++; | ||
| 7952 | dev_kfree_skb_any(skb); | ||
| 7953 | } | ||
| 7954 | } | ||
| 7955 | #endif | ||
| 7956 | |||
| 7585 | static int is_network_packet(struct ipw_priv *priv, | 7957 | static int is_network_packet(struct ipw_priv *priv, |
| 7586 | struct ieee80211_hdr_4addr *header) | 7958 | struct ieee80211_hdr_4addr *header) |
| 7587 | { | 7959 | { |
| @@ -7808,15 +8180,21 @@ static void ipw_rx(struct ipw_priv *priv) | |||
| 7808 | 8180 | ||
| 7809 | priv->rx_packets++; | 8181 | priv->rx_packets++; |
| 7810 | 8182 | ||
| 8183 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 8184 | if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) | ||
| 8185 | ipw_handle_promiscuous_rx(priv, rxb, &stats); | ||
| 8186 | #endif | ||
| 8187 | |||
| 7811 | #ifdef CONFIG_IPW2200_MONITOR | 8188 | #ifdef CONFIG_IPW2200_MONITOR |
| 7812 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) { | 8189 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) { |
| 7813 | #ifdef CONFIG_IEEE80211_RADIOTAP | 8190 | #ifdef CONFIG_IPW2200_RADIOTAP |
| 7814 | ipw_handle_data_packet_monitor(priv, | 8191 | |
| 7815 | rxb, | 8192 | ipw_handle_data_packet_monitor(priv, |
| 7816 | &stats); | 8193 | rxb, |
| 8194 | &stats); | ||
| 7817 | #else | 8195 | #else |
| 7818 | ipw_handle_data_packet(priv, rxb, | 8196 | ipw_handle_data_packet(priv, rxb, |
| 7819 | &stats); | 8197 | &stats); |
| 7820 | #endif | 8198 | #endif |
| 7821 | break; | 8199 | break; |
| 7822 | } | 8200 | } |
| @@ -7837,9 +8215,9 @@ static void ipw_rx(struct ipw_priv *priv) | |||
| 7837 | if (network_packet && priv->assoc_network) { | 8215 | if (network_packet && priv->assoc_network) { |
| 7838 | priv->assoc_network->stats.rssi = | 8216 | priv->assoc_network->stats.rssi = |
| 7839 | stats.rssi; | 8217 | stats.rssi; |
| 7840 | average_add(&priv->average_rssi, | 8218 | priv->exp_avg_rssi = |
| 7841 | stats.rssi); | 8219 | exponential_average(priv->exp_avg_rssi, |
| 7842 | priv->last_rx_rssi = stats.rssi; | 8220 | stats.rssi, DEPTH_RSSI); |
| 7843 | } | 8221 | } |
| 7844 | 8222 | ||
| 7845 | IPW_DEBUG_RX("Frame: len=%u\n", | 8223 | IPW_DEBUG_RX("Frame: len=%u\n", |
| @@ -7982,10 +8360,10 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option) | |||
| 7982 | IPW_DEBUG_INFO("Bind to static channel %d\n", channel); | 8360 | IPW_DEBUG_INFO("Bind to static channel %d\n", channel); |
| 7983 | /* TODO: Validate that provided channel is in range */ | 8361 | /* TODO: Validate that provided channel is in range */ |
| 7984 | } | 8362 | } |
| 7985 | #ifdef CONFIG_IPW_QOS | 8363 | #ifdef CONFIG_IPW2200_QOS |
| 7986 | ipw_qos_init(priv, qos_enable, qos_burst_enable, | 8364 | ipw_qos_init(priv, qos_enable, qos_burst_enable, |
| 7987 | burst_duration_CCK, burst_duration_OFDM); | 8365 | burst_duration_CCK, burst_duration_OFDM); |
| 7988 | #endif /* CONFIG_IPW_QOS */ | 8366 | #endif /* CONFIG_IPW2200_QOS */ |
| 7989 | 8367 | ||
| 7990 | switch (mode) { | 8368 | switch (mode) { |
| 7991 | case 1: | 8369 | case 1: |
| @@ -7996,7 +8374,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option) | |||
| 7996 | #ifdef CONFIG_IPW2200_MONITOR | 8374 | #ifdef CONFIG_IPW2200_MONITOR |
| 7997 | case 2: | 8375 | case 2: |
| 7998 | priv->ieee->iw_mode = IW_MODE_MONITOR; | 8376 | priv->ieee->iw_mode = IW_MODE_MONITOR; |
| 7999 | #ifdef CONFIG_IEEE80211_RADIOTAP | 8377 | #ifdef CONFIG_IPW2200_RADIOTAP |
| 8000 | priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; | 8378 | priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; |
| 8001 | #else | 8379 | #else |
| 8002 | priv->net_dev->type = ARPHRD_IEEE80211; | 8380 | priv->net_dev->type = ARPHRD_IEEE80211; |
| @@ -8251,7 +8629,7 @@ static int ipw_wx_set_mode(struct net_device *dev, | |||
| 8251 | priv->net_dev->type = ARPHRD_ETHER; | 8629 | priv->net_dev->type = ARPHRD_ETHER; |
| 8252 | 8630 | ||
| 8253 | if (wrqu->mode == IW_MODE_MONITOR) | 8631 | if (wrqu->mode == IW_MODE_MONITOR) |
| 8254 | #ifdef CONFIG_IEEE80211_RADIOTAP | 8632 | #ifdef CONFIG_IPW2200_RADIOTAP |
| 8255 | priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; | 8633 | priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; |
| 8256 | #else | 8634 | #else |
| 8257 | priv->net_dev->type = ARPHRD_IEEE80211; | 8635 | priv->net_dev->type = ARPHRD_IEEE80211; |
| @@ -8379,7 +8757,8 @@ static int ipw_wx_get_range(struct net_device *dev, | |||
| 8379 | /* Event capability (kernel + driver) */ | 8757 | /* Event capability (kernel + driver) */ |
| 8380 | range->event_capa[0] = (IW_EVENT_CAPA_K_0 | | 8758 | range->event_capa[0] = (IW_EVENT_CAPA_K_0 | |
| 8381 | IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | | 8759 | IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | |
| 8382 | IW_EVENT_CAPA_MASK(SIOCGIWAP)); | 8760 | IW_EVENT_CAPA_MASK(SIOCGIWAP) | |
| 8761 | IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); | ||
| 8383 | range->event_capa[1] = IW_EVENT_CAPA_K_1; | 8762 | range->event_capa[1] = IW_EVENT_CAPA_K_1; |
| 8384 | 8763 | ||
| 8385 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | | 8764 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | |
| @@ -8734,6 +9113,7 @@ static int ipw_wx_get_rate(struct net_device *dev, | |||
| 8734 | struct ipw_priv *priv = ieee80211_priv(dev); | 9113 | struct ipw_priv *priv = ieee80211_priv(dev); |
| 8735 | mutex_lock(&priv->mutex); | 9114 | mutex_lock(&priv->mutex); |
| 8736 | wrqu->bitrate.value = priv->last_rate; | 9115 | wrqu->bitrate.value = priv->last_rate; |
| 9116 | wrqu->bitrate.fixed = (priv->config & CFG_FIXED_RATE) ? 1 : 0; | ||
| 8737 | mutex_unlock(&priv->mutex); | 9117 | mutex_unlock(&priv->mutex); |
| 8738 | IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); | 9118 | IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); |
| 8739 | return 0; | 9119 | return 0; |
| @@ -9351,7 +9731,7 @@ static int ipw_wx_set_monitor(struct net_device *dev, | |||
| 9351 | IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]); | 9731 | IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]); |
| 9352 | if (enable) { | 9732 | if (enable) { |
| 9353 | if (priv->ieee->iw_mode != IW_MODE_MONITOR) { | 9733 | if (priv->ieee->iw_mode != IW_MODE_MONITOR) { |
| 9354 | #ifdef CONFIG_IEEE80211_RADIOTAP | 9734 | #ifdef CONFIG_IPW2200_RADIOTAP |
| 9355 | priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; | 9735 | priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; |
| 9356 | #else | 9736 | #else |
| 9357 | priv->net_dev->type = ARPHRD_IEEE80211; | 9737 | priv->net_dev->type = ARPHRD_IEEE80211; |
| @@ -9579,8 +9959,8 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev) | |||
| 9579 | } | 9959 | } |
| 9580 | 9960 | ||
| 9581 | wstats->qual.qual = priv->quality; | 9961 | wstats->qual.qual = priv->quality; |
| 9582 | wstats->qual.level = average_value(&priv->average_rssi); | 9962 | wstats->qual.level = priv->exp_avg_rssi; |
| 9583 | wstats->qual.noise = average_value(&priv->average_noise); | 9963 | wstats->qual.noise = priv->exp_avg_noise; |
| 9584 | wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | | 9964 | wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | |
| 9585 | IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM; | 9965 | IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM; |
| 9586 | 9966 | ||
| @@ -9608,7 +9988,9 @@ static void init_sys_config(struct ipw_sys_config *sys_config) | |||
| 9608 | sys_config->disable_unicast_decryption = 1; | 9988 | sys_config->disable_unicast_decryption = 1; |
| 9609 | sys_config->exclude_multicast_unencrypted = 0; | 9989 | sys_config->exclude_multicast_unencrypted = 0; |
| 9610 | sys_config->disable_multicast_decryption = 1; | 9990 | sys_config->disable_multicast_decryption = 1; |
| 9611 | sys_config->antenna_diversity = CFG_SYS_ANTENNA_SLOW_DIV; | 9991 | if (antenna < CFG_SYS_ANTENNA_BOTH || antenna > CFG_SYS_ANTENNA_B) |
| 9992 | antenna = CFG_SYS_ANTENNA_BOTH; | ||
| 9993 | sys_config->antenna_diversity = antenna; | ||
| 9612 | sys_config->pass_crc_to_host = 0; /* TODO: See if 1 gives us FCS */ | 9994 | sys_config->pass_crc_to_host = 0; /* TODO: See if 1 gives us FCS */ |
| 9613 | sys_config->dot11g_auto_detection = 0; | 9995 | sys_config->dot11g_auto_detection = 0; |
| 9614 | sys_config->enable_cts_to_self = 0; | 9996 | sys_config->enable_cts_to_self = 0; |
| @@ -9647,11 +10029,11 @@ we need to heavily modify the ieee80211_skb_to_txb. | |||
| 9647 | static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | 10029 | static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, |
| 9648 | int pri) | 10030 | int pri) |
| 9649 | { | 10031 | { |
| 9650 | struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *) | 10032 | struct ieee80211_hdr_3addrqos *hdr = (struct ieee80211_hdr_3addrqos *) |
| 9651 | txb->fragments[0]->data; | 10033 | txb->fragments[0]->data; |
| 9652 | int i = 0; | 10034 | int i = 0; |
| 9653 | struct tfd_frame *tfd; | 10035 | struct tfd_frame *tfd; |
| 9654 | #ifdef CONFIG_IPW_QOS | 10036 | #ifdef CONFIG_IPW2200_QOS |
| 9655 | int tx_id = ipw_get_tx_queue_number(priv, pri); | 10037 | int tx_id = ipw_get_tx_queue_number(priv, pri); |
| 9656 | struct clx2_tx_queue *txq = &priv->txq[tx_id]; | 10038 | struct clx2_tx_queue *txq = &priv->txq[tx_id]; |
| 9657 | #else | 10039 | #else |
| @@ -9662,9 +10044,9 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | |||
| 9662 | u16 remaining_bytes; | 10044 | u16 remaining_bytes; |
| 9663 | int fc; | 10045 | int fc; |
| 9664 | 10046 | ||
| 10047 | hdr_len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); | ||
| 9665 | switch (priv->ieee->iw_mode) { | 10048 | switch (priv->ieee->iw_mode) { |
| 9666 | case IW_MODE_ADHOC: | 10049 | case IW_MODE_ADHOC: |
| 9667 | hdr_len = IEEE80211_3ADDR_LEN; | ||
| 9668 | unicast = !is_multicast_ether_addr(hdr->addr1); | 10050 | unicast = !is_multicast_ether_addr(hdr->addr1); |
| 9669 | id = ipw_find_station(priv, hdr->addr1); | 10051 | id = ipw_find_station(priv, hdr->addr1); |
| 9670 | if (id == IPW_INVALID_STATION) { | 10052 | if (id == IPW_INVALID_STATION) { |
| @@ -9681,7 +10063,6 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | |||
| 9681 | case IW_MODE_INFRA: | 10063 | case IW_MODE_INFRA: |
| 9682 | default: | 10064 | default: |
| 9683 | unicast = !is_multicast_ether_addr(hdr->addr3); | 10065 | unicast = !is_multicast_ether_addr(hdr->addr3); |
| 9684 | hdr_len = IEEE80211_3ADDR_LEN; | ||
| 9685 | id = 0; | 10066 | id = 0; |
| 9686 | break; | 10067 | break; |
| 9687 | } | 10068 | } |
| @@ -9759,9 +10140,10 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | |||
| 9759 | /* No hardware encryption */ | 10140 | /* No hardware encryption */ |
| 9760 | tfd->u.data.tx_flags |= DCT_FLAG_NO_WEP; | 10141 | tfd->u.data.tx_flags |= DCT_FLAG_NO_WEP; |
| 9761 | 10142 | ||
| 9762 | #ifdef CONFIG_IPW_QOS | 10143 | #ifdef CONFIG_IPW2200_QOS |
| 9763 | ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data), unicast); | 10144 | if (fc & IEEE80211_STYPE_QOS_DATA) |
| 9764 | #endif /* CONFIG_IPW_QOS */ | 10145 | ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data)); |
| 10146 | #endif /* CONFIG_IPW2200_QOS */ | ||
| 9765 | 10147 | ||
| 9766 | /* payload */ | 10148 | /* payload */ |
| 9767 | tfd->u.data.num_chunks = cpu_to_le32(min((u8) (NUM_TFD_CHUNKS - 2), | 10149 | tfd->u.data.num_chunks = cpu_to_le32(min((u8) (NUM_TFD_CHUNKS - 2), |
| @@ -9841,12 +10223,12 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | |||
| 9841 | static int ipw_net_is_queue_full(struct net_device *dev, int pri) | 10223 | static int ipw_net_is_queue_full(struct net_device *dev, int pri) |
| 9842 | { | 10224 | { |
| 9843 | struct ipw_priv *priv = ieee80211_priv(dev); | 10225 | struct ipw_priv *priv = ieee80211_priv(dev); |
| 9844 | #ifdef CONFIG_IPW_QOS | 10226 | #ifdef CONFIG_IPW2200_QOS |
| 9845 | int tx_id = ipw_get_tx_queue_number(priv, pri); | 10227 | int tx_id = ipw_get_tx_queue_number(priv, pri); |
| 9846 | struct clx2_tx_queue *txq = &priv->txq[tx_id]; | 10228 | struct clx2_tx_queue *txq = &priv->txq[tx_id]; |
| 9847 | #else | 10229 | #else |
| 9848 | struct clx2_tx_queue *txq = &priv->txq[0]; | 10230 | struct clx2_tx_queue *txq = &priv->txq[0]; |
| 9849 | #endif /* CONFIG_IPW_QOS */ | 10231 | #endif /* CONFIG_IPW2200_QOS */ |
| 9850 | 10232 | ||
| 9851 | if (ipw_queue_space(&txq->q) < txq->q.high_mark) | 10233 | if (ipw_queue_space(&txq->q) < txq->q.high_mark) |
| 9852 | return 1; | 10234 | return 1; |
| @@ -9854,6 +10236,88 @@ static int ipw_net_is_queue_full(struct net_device *dev, int pri) | |||
| 9854 | return 0; | 10236 | return 0; |
| 9855 | } | 10237 | } |
| 9856 | 10238 | ||
| 10239 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 10240 | static void ipw_handle_promiscuous_tx(struct ipw_priv *priv, | ||
| 10241 | struct ieee80211_txb *txb) | ||
| 10242 | { | ||
| 10243 | struct ieee80211_rx_stats dummystats; | ||
| 10244 | struct ieee80211_hdr *hdr; | ||
| 10245 | u8 n; | ||
| 10246 | u16 filter = priv->prom_priv->filter; | ||
| 10247 | int hdr_only = 0; | ||
| 10248 | |||
| 10249 | if (filter & IPW_PROM_NO_TX) | ||
| 10250 | return; | ||
| 10251 | |||
| 10252 | memset(&dummystats, 0, sizeof(dummystats)); | ||
| 10253 | |||
| 10254 | /* Filtering of fragment chains is done agains the first fragment */ | ||
| 10255 | hdr = (void *)txb->fragments[0]->data; | ||
| 10256 | if (ieee80211_is_management(hdr->frame_ctl)) { | ||
| 10257 | if (filter & IPW_PROM_NO_MGMT) | ||
| 10258 | return; | ||
| 10259 | if (filter & IPW_PROM_MGMT_HEADER_ONLY) | ||
| 10260 | hdr_only = 1; | ||
| 10261 | } else if (ieee80211_is_control(hdr->frame_ctl)) { | ||
| 10262 | if (filter & IPW_PROM_NO_CTL) | ||
| 10263 | return; | ||
| 10264 | if (filter & IPW_PROM_CTL_HEADER_ONLY) | ||
| 10265 | hdr_only = 1; | ||
| 10266 | } else if (ieee80211_is_data(hdr->frame_ctl)) { | ||
| 10267 | if (filter & IPW_PROM_NO_DATA) | ||
| 10268 | return; | ||
| 10269 | if (filter & IPW_PROM_DATA_HEADER_ONLY) | ||
| 10270 | hdr_only = 1; | ||
| 10271 | } | ||
| 10272 | |||
| 10273 | for(n=0; n<txb->nr_frags; ++n) { | ||
| 10274 | struct sk_buff *src = txb->fragments[n]; | ||
| 10275 | struct sk_buff *dst; | ||
| 10276 | struct ieee80211_radiotap_header *rt_hdr; | ||
| 10277 | int len; | ||
| 10278 | |||
| 10279 | if (hdr_only) { | ||
| 10280 | hdr = (void *)src->data; | ||
| 10281 | len = ieee80211_get_hdrlen(hdr->frame_ctl); | ||
| 10282 | } else | ||
| 10283 | len = src->len; | ||
| 10284 | |||
| 10285 | dst = alloc_skb( | ||
| 10286 | len + IEEE80211_RADIOTAP_HDRLEN, GFP_ATOMIC); | ||
| 10287 | if (!dst) continue; | ||
| 10288 | |||
| 10289 | rt_hdr = (void *)skb_put(dst, sizeof(*rt_hdr)); | ||
| 10290 | |||
| 10291 | rt_hdr->it_version = PKTHDR_RADIOTAP_VERSION; | ||
| 10292 | rt_hdr->it_pad = 0; | ||
| 10293 | rt_hdr->it_present = 0; /* after all, it's just an idea */ | ||
| 10294 | rt_hdr->it_present |= (1 << IEEE80211_RADIOTAP_CHANNEL); | ||
| 10295 | |||
| 10296 | *(u16*)skb_put(dst, sizeof(u16)) = cpu_to_le16( | ||
| 10297 | ieee80211chan2mhz(priv->channel)); | ||
| 10298 | if (priv->channel > 14) /* 802.11a */ | ||
| 10299 | *(u16*)skb_put(dst, sizeof(u16)) = | ||
| 10300 | cpu_to_le16(IEEE80211_CHAN_OFDM | | ||
| 10301 | IEEE80211_CHAN_5GHZ); | ||
| 10302 | else if (priv->ieee->mode == IEEE_B) /* 802.11b */ | ||
| 10303 | *(u16*)skb_put(dst, sizeof(u16)) = | ||
| 10304 | cpu_to_le16(IEEE80211_CHAN_CCK | | ||
| 10305 | IEEE80211_CHAN_2GHZ); | ||
| 10306 | else /* 802.11g */ | ||
| 10307 | *(u16*)skb_put(dst, sizeof(u16)) = | ||
| 10308 | cpu_to_le16(IEEE80211_CHAN_OFDM | | ||
| 10309 | IEEE80211_CHAN_2GHZ); | ||
| 10310 | |||
| 10311 | rt_hdr->it_len = dst->len; | ||
| 10312 | |||
| 10313 | memcpy(skb_put(dst, len), src->data, len); | ||
| 10314 | |||
| 10315 | if (!ieee80211_rx(priv->prom_priv->ieee, dst, &dummystats)) | ||
| 10316 | dev_kfree_skb_any(dst); | ||
| 10317 | } | ||
| 10318 | } | ||
| 10319 | #endif | ||
| 10320 | |||
| 9857 | static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, | 10321 | static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, |
| 9858 | struct net_device *dev, int pri) | 10322 | struct net_device *dev, int pri) |
| 9859 | { | 10323 | { |
| @@ -9871,6 +10335,11 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, | |||
| 9871 | goto fail_unlock; | 10335 | goto fail_unlock; |
| 9872 | } | 10336 | } |
| 9873 | 10337 | ||
| 10338 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 10339 | if (rtap_iface && netif_running(priv->prom_net_dev)) | ||
| 10340 | ipw_handle_promiscuous_tx(priv, txb); | ||
| 10341 | #endif | ||
| 10342 | |||
| 9874 | ret = ipw_tx_skb(priv, txb, pri); | 10343 | ret = ipw_tx_skb(priv, txb, pri); |
| 9875 | if (ret == NETDEV_TX_OK) | 10344 | if (ret == NETDEV_TX_OK) |
| 9876 | __ipw_led_activity_on(priv); | 10345 | __ipw_led_activity_on(priv); |
| @@ -10169,10 +10638,10 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) | |||
| 10169 | INIT_WORK(&priv->merge_networks, | 10638 | INIT_WORK(&priv->merge_networks, |
| 10170 | (void (*)(void *))ipw_merge_adhoc_network, priv); | 10639 | (void (*)(void *))ipw_merge_adhoc_network, priv); |
| 10171 | 10640 | ||
| 10172 | #ifdef CONFIG_IPW_QOS | 10641 | #ifdef CONFIG_IPW2200_QOS |
| 10173 | INIT_WORK(&priv->qos_activate, (void (*)(void *))ipw_bg_qos_activate, | 10642 | INIT_WORK(&priv->qos_activate, (void (*)(void *))ipw_bg_qos_activate, |
| 10174 | priv); | 10643 | priv); |
| 10175 | #endif /* CONFIG_IPW_QOS */ | 10644 | #endif /* CONFIG_IPW2200_QOS */ |
| 10176 | 10645 | ||
| 10177 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | 10646 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) |
| 10178 | ipw_irq_tasklet, (unsigned long)priv); | 10647 | ipw_irq_tasklet, (unsigned long)priv); |
| @@ -10318,12 +10787,21 @@ static int ipw_config(struct ipw_priv *priv) | |||
| 10318 | |= CFG_BT_COEXISTENCE_OOB; | 10787 | |= CFG_BT_COEXISTENCE_OOB; |
| 10319 | } | 10788 | } |
| 10320 | 10789 | ||
| 10790 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 10791 | if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) { | ||
| 10792 | priv->sys_config.accept_all_data_frames = 1; | ||
| 10793 | priv->sys_config.accept_non_directed_frames = 1; | ||
| 10794 | priv->sys_config.accept_all_mgmt_bcpr = 1; | ||
| 10795 | priv->sys_config.accept_all_mgmt_frames = 1; | ||
| 10796 | } | ||
| 10797 | #endif | ||
| 10798 | |||
| 10321 | if (priv->ieee->iw_mode == IW_MODE_ADHOC) | 10799 | if (priv->ieee->iw_mode == IW_MODE_ADHOC) |
| 10322 | priv->sys_config.answer_broadcast_ssid_probe = 1; | 10800 | priv->sys_config.answer_broadcast_ssid_probe = 1; |
| 10323 | else | 10801 | else |
| 10324 | priv->sys_config.answer_broadcast_ssid_probe = 0; | 10802 | priv->sys_config.answer_broadcast_ssid_probe = 0; |
| 10325 | 10803 | ||
| 10326 | if (ipw_send_system_config(priv, &priv->sys_config)) | 10804 | if (ipw_send_system_config(priv)) |
| 10327 | goto error; | 10805 | goto error; |
| 10328 | 10806 | ||
| 10329 | init_supported_rates(priv, &priv->rates); | 10807 | init_supported_rates(priv, &priv->rates); |
| @@ -10335,10 +10813,10 @@ static int ipw_config(struct ipw_priv *priv) | |||
| 10335 | if (ipw_send_rts_threshold(priv, priv->rts_threshold)) | 10813 | if (ipw_send_rts_threshold(priv, priv->rts_threshold)) |
| 10336 | goto error; | 10814 | goto error; |
| 10337 | } | 10815 | } |
| 10338 | #ifdef CONFIG_IPW_QOS | 10816 | #ifdef CONFIG_IPW2200_QOS |
| 10339 | IPW_DEBUG_QOS("QoS: call ipw_qos_activate\n"); | 10817 | IPW_DEBUG_QOS("QoS: call ipw_qos_activate\n"); |
| 10340 | ipw_qos_activate(priv, NULL); | 10818 | ipw_qos_activate(priv, NULL); |
| 10341 | #endif /* CONFIG_IPW_QOS */ | 10819 | #endif /* CONFIG_IPW2200_QOS */ |
| 10342 | 10820 | ||
| 10343 | if (ipw_set_random_seed(priv)) | 10821 | if (ipw_set_random_seed(priv)) |
| 10344 | goto error; | 10822 | goto error; |
| @@ -10639,6 +11117,7 @@ static int ipw_up(struct ipw_priv *priv) | |||
| 10639 | if (priv->cmdlog == NULL) { | 11117 | if (priv->cmdlog == NULL) { |
| 10640 | IPW_ERROR("Error allocating %d command log entries.\n", | 11118 | IPW_ERROR("Error allocating %d command log entries.\n", |
| 10641 | cmdlog); | 11119 | cmdlog); |
| 11120 | return -ENOMEM; | ||
| 10642 | } else { | 11121 | } else { |
| 10643 | memset(priv->cmdlog, 0, sizeof(*priv->cmdlog) * cmdlog); | 11122 | memset(priv->cmdlog, 0, sizeof(*priv->cmdlog) * cmdlog); |
| 10644 | priv->cmdlog_len = cmdlog; | 11123 | priv->cmdlog_len = cmdlog; |
| @@ -10860,6 +11339,10 @@ static struct attribute *ipw_sysfs_entries[] = { | |||
| 10860 | &dev_attr_led.attr, | 11339 | &dev_attr_led.attr, |
| 10861 | &dev_attr_speed_scan.attr, | 11340 | &dev_attr_speed_scan.attr, |
| 10862 | &dev_attr_net_stats.attr, | 11341 | &dev_attr_net_stats.attr, |
| 11342 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 11343 | &dev_attr_rtap_iface.attr, | ||
| 11344 | &dev_attr_rtap_filter.attr, | ||
| 11345 | #endif | ||
| 10863 | NULL | 11346 | NULL |
| 10864 | }; | 11347 | }; |
| 10865 | 11348 | ||
| @@ -10868,6 +11351,109 @@ static struct attribute_group ipw_attribute_group = { | |||
| 10868 | .attrs = ipw_sysfs_entries, | 11351 | .attrs = ipw_sysfs_entries, |
| 10869 | }; | 11352 | }; |
| 10870 | 11353 | ||
| 11354 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 11355 | static int ipw_prom_open(struct net_device *dev) | ||
| 11356 | { | ||
| 11357 | struct ipw_prom_priv *prom_priv = ieee80211_priv(dev); | ||
| 11358 | struct ipw_priv *priv = prom_priv->priv; | ||
| 11359 | |||
| 11360 | IPW_DEBUG_INFO("prom dev->open\n"); | ||
| 11361 | netif_carrier_off(dev); | ||
| 11362 | netif_stop_queue(dev); | ||
| 11363 | |||
| 11364 | if (priv->ieee->iw_mode != IW_MODE_MONITOR) { | ||
| 11365 | priv->sys_config.accept_all_data_frames = 1; | ||
| 11366 | priv->sys_config.accept_non_directed_frames = 1; | ||
| 11367 | priv->sys_config.accept_all_mgmt_bcpr = 1; | ||
| 11368 | priv->sys_config.accept_all_mgmt_frames = 1; | ||
| 11369 | |||
| 11370 | ipw_send_system_config(priv); | ||
| 11371 | } | ||
| 11372 | |||
| 11373 | return 0; | ||
| 11374 | } | ||
| 11375 | |||
| 11376 | static int ipw_prom_stop(struct net_device *dev) | ||
| 11377 | { | ||
| 11378 | struct ipw_prom_priv *prom_priv = ieee80211_priv(dev); | ||
| 11379 | struct ipw_priv *priv = prom_priv->priv; | ||
| 11380 | |||
| 11381 | IPW_DEBUG_INFO("prom dev->stop\n"); | ||
| 11382 | |||
| 11383 | if (priv->ieee->iw_mode != IW_MODE_MONITOR) { | ||
| 11384 | priv->sys_config.accept_all_data_frames = 0; | ||
| 11385 | priv->sys_config.accept_non_directed_frames = 0; | ||
| 11386 | priv->sys_config.accept_all_mgmt_bcpr = 0; | ||
| 11387 | priv->sys_config.accept_all_mgmt_frames = 0; | ||
| 11388 | |||
| 11389 | ipw_send_system_config(priv); | ||
| 11390 | } | ||
| 11391 | |||
| 11392 | return 0; | ||
| 11393 | } | ||
| 11394 | |||
| 11395 | static int ipw_prom_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
| 11396 | { | ||
| 11397 | IPW_DEBUG_INFO("prom dev->xmit\n"); | ||
| 11398 | netif_stop_queue(dev); | ||
| 11399 | return -EOPNOTSUPP; | ||
| 11400 | } | ||
| 11401 | |||
| 11402 | static struct net_device_stats *ipw_prom_get_stats(struct net_device *dev) | ||
| 11403 | { | ||
| 11404 | struct ipw_prom_priv *prom_priv = ieee80211_priv(dev); | ||
| 11405 | return &prom_priv->ieee->stats; | ||
| 11406 | } | ||
| 11407 | |||
| 11408 | static int ipw_prom_alloc(struct ipw_priv *priv) | ||
| 11409 | { | ||
| 11410 | int rc = 0; | ||
| 11411 | |||
| 11412 | if (priv->prom_net_dev) | ||
| 11413 | return -EPERM; | ||
| 11414 | |||
| 11415 | priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv)); | ||
| 11416 | if (priv->prom_net_dev == NULL) | ||
| 11417 | return -ENOMEM; | ||
| 11418 | |||
| 11419 | priv->prom_priv = ieee80211_priv(priv->prom_net_dev); | ||
| 11420 | priv->prom_priv->ieee = netdev_priv(priv->prom_net_dev); | ||
| 11421 | priv->prom_priv->priv = priv; | ||
| 11422 | |||
| 11423 | strcpy(priv->prom_net_dev->name, "rtap%d"); | ||
| 11424 | |||
| 11425 | priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP; | ||
| 11426 | priv->prom_net_dev->open = ipw_prom_open; | ||
| 11427 | priv->prom_net_dev->stop = ipw_prom_stop; | ||
| 11428 | priv->prom_net_dev->get_stats = ipw_prom_get_stats; | ||
| 11429 | priv->prom_net_dev->hard_start_xmit = ipw_prom_hard_start_xmit; | ||
| 11430 | |||
| 11431 | priv->prom_priv->ieee->iw_mode = IW_MODE_MONITOR; | ||
| 11432 | |||
| 11433 | rc = register_netdev(priv->prom_net_dev); | ||
| 11434 | if (rc) { | ||
| 11435 | free_ieee80211(priv->prom_net_dev); | ||
| 11436 | priv->prom_net_dev = NULL; | ||
| 11437 | return rc; | ||
| 11438 | } | ||
| 11439 | |||
| 11440 | return 0; | ||
| 11441 | } | ||
| 11442 | |||
| 11443 | static void ipw_prom_free(struct ipw_priv *priv) | ||
| 11444 | { | ||
| 11445 | if (!priv->prom_net_dev) | ||
| 11446 | return; | ||
| 11447 | |||
| 11448 | unregister_netdev(priv->prom_net_dev); | ||
| 11449 | free_ieee80211(priv->prom_net_dev); | ||
| 11450 | |||
| 11451 | priv->prom_net_dev = NULL; | ||
| 11452 | } | ||
| 11453 | |||
| 11454 | #endif | ||
| 11455 | |||
| 11456 | |||
| 10871 | static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 11457 | static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
| 10872 | { | 11458 | { |
| 10873 | int err = 0; | 11459 | int err = 0; |
| @@ -10959,11 +11545,12 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 10959 | priv->ieee->set_security = shim__set_security; | 11545 | priv->ieee->set_security = shim__set_security; |
| 10960 | priv->ieee->is_queue_full = ipw_net_is_queue_full; | 11546 | priv->ieee->is_queue_full = ipw_net_is_queue_full; |
| 10961 | 11547 | ||
| 10962 | #ifdef CONFIG_IPW_QOS | 11548 | #ifdef CONFIG_IPW2200_QOS |
| 11549 | priv->ieee->is_qos_active = ipw_is_qos_active; | ||
| 10963 | priv->ieee->handle_probe_response = ipw_handle_beacon; | 11550 | priv->ieee->handle_probe_response = ipw_handle_beacon; |
| 10964 | priv->ieee->handle_beacon = ipw_handle_probe_response; | 11551 | priv->ieee->handle_beacon = ipw_handle_probe_response; |
| 10965 | priv->ieee->handle_assoc_response = ipw_handle_assoc_response; | 11552 | priv->ieee->handle_assoc_response = ipw_handle_assoc_response; |
| 10966 | #endif /* CONFIG_IPW_QOS */ | 11553 | #endif /* CONFIG_IPW2200_QOS */ |
| 10967 | 11554 | ||
| 10968 | priv->ieee->perfect_rssi = -20; | 11555 | priv->ieee->perfect_rssi = -20; |
| 10969 | priv->ieee->worst_rssi = -85; | 11556 | priv->ieee->worst_rssi = -85; |
| @@ -10997,6 +11584,18 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 10997 | goto out_remove_sysfs; | 11584 | goto out_remove_sysfs; |
| 10998 | } | 11585 | } |
| 10999 | 11586 | ||
| 11587 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 11588 | if (rtap_iface) { | ||
| 11589 | err = ipw_prom_alloc(priv); | ||
| 11590 | if (err) { | ||
| 11591 | IPW_ERROR("Failed to register promiscuous network " | ||
| 11592 | "device (error %d).\n", err); | ||
| 11593 | unregister_netdev(priv->net_dev); | ||
| 11594 | goto out_remove_sysfs; | ||
| 11595 | } | ||
| 11596 | } | ||
| 11597 | #endif | ||
| 11598 | |||
| 11000 | printk(KERN_INFO DRV_NAME ": Detected geography %s (%d 802.11bg " | 11599 | printk(KERN_INFO DRV_NAME ": Detected geography %s (%d 802.11bg " |
| 11001 | "channels, %d 802.11a channels)\n", | 11600 | "channels, %d 802.11a channels)\n", |
| 11002 | priv->ieee->geo.name, priv->ieee->geo.bg_channels, | 11601 | priv->ieee->geo.name, priv->ieee->geo.bg_channels, |
| @@ -11076,6 +11675,10 @@ static void ipw_pci_remove(struct pci_dev *pdev) | |||
| 11076 | priv->error = NULL; | 11675 | priv->error = NULL; |
| 11077 | } | 11676 | } |
| 11078 | 11677 | ||
| 11678 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 11679 | ipw_prom_free(priv); | ||
| 11680 | #endif | ||
| 11681 | |||
| 11079 | free_irq(pdev->irq, priv); | 11682 | free_irq(pdev->irq, priv); |
| 11080 | iounmap(priv->hw_base); | 11683 | iounmap(priv->hw_base); |
| 11081 | pci_release_regions(pdev); | 11684 | pci_release_regions(pdev); |
| @@ -11200,7 +11803,12 @@ MODULE_PARM_DESC(debug, "debug output mask"); | |||
| 11200 | module_param(channel, int, 0444); | 11803 | module_param(channel, int, 0444); |
| 11201 | MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); | 11804 | MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); |
| 11202 | 11805 | ||
| 11203 | #ifdef CONFIG_IPW_QOS | 11806 | #ifdef CONFIG_IPW2200_PROMISCUOUS |
| 11807 | module_param(rtap_iface, int, 0444); | ||
| 11808 | MODULE_PARM_DESC(rtap_iface, "create the rtap interface (1 - create, default 0)"); | ||
| 11809 | #endif | ||
| 11810 | |||
| 11811 | #ifdef CONFIG_IPW2200_QOS | ||
| 11204 | module_param(qos_enable, int, 0444); | 11812 | module_param(qos_enable, int, 0444); |
| 11205 | MODULE_PARM_DESC(qos_enable, "enable all QoS functionalitis"); | 11813 | MODULE_PARM_DESC(qos_enable, "enable all QoS functionalitis"); |
| 11206 | 11814 | ||
| @@ -11215,7 +11823,7 @@ MODULE_PARM_DESC(burst_duration_CCK, "set CCK burst value"); | |||
| 11215 | 11823 | ||
| 11216 | module_param(burst_duration_OFDM, int, 0444); | 11824 | module_param(burst_duration_OFDM, int, 0444); |
| 11217 | MODULE_PARM_DESC(burst_duration_OFDM, "set OFDM burst value"); | 11825 | MODULE_PARM_DESC(burst_duration_OFDM, "set OFDM burst value"); |
| 11218 | #endif /* CONFIG_IPW_QOS */ | 11826 | #endif /* CONFIG_IPW2200_QOS */ |
| 11219 | 11827 | ||
| 11220 | #ifdef CONFIG_IPW2200_MONITOR | 11828 | #ifdef CONFIG_IPW2200_MONITOR |
| 11221 | module_param(mode, int, 0444); | 11829 | module_param(mode, int, 0444); |
| @@ -11238,5 +11846,8 @@ MODULE_PARM_DESC(cmdlog, | |||
| 11238 | module_param(roaming, int, 0444); | 11846 | module_param(roaming, int, 0444); |
| 11239 | MODULE_PARM_DESC(roaming, "enable roaming support (default on)"); | 11847 | MODULE_PARM_DESC(roaming, "enable roaming support (default on)"); |
| 11240 | 11848 | ||
| 11849 | module_param(antenna, int, 0444); | ||
| 11850 | MODULE_PARM_DESC(antenna, "select antenna 1=Main, 3=Aux, default 0 [both], 2=slow_diversity (choose the one with lower background noise)"); | ||
| 11851 | |||
| 11241 | module_exit(ipw_exit); | 11852 | module_exit(ipw_exit); |
| 11242 | module_init(ipw_init); | 11853 | module_init(ipw_init); |
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 4b9804900702..6044c0be2c80 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h | |||
| @@ -789,7 +789,7 @@ struct ipw_sys_config { | |||
| 789 | u8 bt_coexist_collision_thr; | 789 | u8 bt_coexist_collision_thr; |
| 790 | u8 silence_threshold; | 790 | u8 silence_threshold; |
| 791 | u8 accept_all_mgmt_bcpr; | 791 | u8 accept_all_mgmt_bcpr; |
| 792 | u8 accept_all_mgtm_frames; | 792 | u8 accept_all_mgmt_frames; |
| 793 | u8 pass_noise_stats_to_host; | 793 | u8 pass_noise_stats_to_host; |
| 794 | u8 reserved3; | 794 | u8 reserved3; |
| 795 | } __attribute__ ((packed)); | 795 | } __attribute__ ((packed)); |
| @@ -1122,6 +1122,52 @@ struct ipw_fw_error { | |||
| 1122 | u8 payload[0]; | 1122 | u8 payload[0]; |
| 1123 | } __attribute__ ((packed)); | 1123 | } __attribute__ ((packed)); |
| 1124 | 1124 | ||
| 1125 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 1126 | |||
| 1127 | enum ipw_prom_filter { | ||
| 1128 | IPW_PROM_CTL_HEADER_ONLY = (1 << 0), | ||
| 1129 | IPW_PROM_MGMT_HEADER_ONLY = (1 << 1), | ||
| 1130 | IPW_PROM_DATA_HEADER_ONLY = (1 << 2), | ||
| 1131 | IPW_PROM_ALL_HEADER_ONLY = 0xf, /* bits 0..3 */ | ||
| 1132 | IPW_PROM_NO_TX = (1 << 4), | ||
| 1133 | IPW_PROM_NO_RX = (1 << 5), | ||
| 1134 | IPW_PROM_NO_CTL = (1 << 6), | ||
| 1135 | IPW_PROM_NO_MGMT = (1 << 7), | ||
| 1136 | IPW_PROM_NO_DATA = (1 << 8), | ||
| 1137 | }; | ||
| 1138 | |||
| 1139 | struct ipw_priv; | ||
| 1140 | struct ipw_prom_priv { | ||
| 1141 | struct ipw_priv *priv; | ||
| 1142 | struct ieee80211_device *ieee; | ||
| 1143 | enum ipw_prom_filter filter; | ||
| 1144 | int tx_packets; | ||
| 1145 | int rx_packets; | ||
| 1146 | }; | ||
| 1147 | #endif | ||
| 1148 | |||
| 1149 | #if defined(CONFIG_IPW2200_RADIOTAP) || defined(CONFIG_IPW2200_PROMISCUOUS) | ||
| 1150 | /* Magic struct that slots into the radiotap header -- no reason | ||
| 1151 | * to build this manually element by element, we can write it much | ||
| 1152 | * more efficiently than we can parse it. ORDER MATTERS HERE | ||
| 1153 | * | ||
| 1154 | * When sent to us via the simulated Rx interface in sysfs, the entire | ||
| 1155 | * structure is provided regardless of any bits unset. | ||
| 1156 | */ | ||
| 1157 | struct ipw_rt_hdr { | ||
| 1158 | struct ieee80211_radiotap_header rt_hdr; | ||
| 1159 | u64 rt_tsf; /* TSF */ | ||
| 1160 | u8 rt_flags; /* radiotap packet flags */ | ||
| 1161 | u8 rt_rate; /* rate in 500kb/s */ | ||
| 1162 | u16 rt_channel; /* channel in mhz */ | ||
| 1163 | u16 rt_chbitmask; /* channel bitfield */ | ||
| 1164 | s8 rt_dbmsignal; /* signal in dbM, kluged to signed */ | ||
| 1165 | s8 rt_dbmnoise; | ||
| 1166 | u8 rt_antenna; /* antenna number */ | ||
| 1167 | u8 payload[0]; /* payload... */ | ||
| 1168 | } __attribute__ ((packed)); | ||
| 1169 | #endif | ||
| 1170 | |||
| 1125 | struct ipw_priv { | 1171 | struct ipw_priv { |
| 1126 | /* ieee device used by generic ieee processing code */ | 1172 | /* ieee device used by generic ieee processing code */ |
| 1127 | struct ieee80211_device *ieee; | 1173 | struct ieee80211_device *ieee; |
| @@ -1133,6 +1179,12 @@ struct ipw_priv { | |||
| 1133 | struct pci_dev *pci_dev; | 1179 | struct pci_dev *pci_dev; |
| 1134 | struct net_device *net_dev; | 1180 | struct net_device *net_dev; |
| 1135 | 1181 | ||
| 1182 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 1183 | /* Promiscuous mode */ | ||
| 1184 | struct ipw_prom_priv *prom_priv; | ||
| 1185 | struct net_device *prom_net_dev; | ||
| 1186 | #endif | ||
| 1187 | |||
| 1136 | /* pci hardware address support */ | 1188 | /* pci hardware address support */ |
| 1137 | void __iomem *hw_base; | 1189 | void __iomem *hw_base; |
| 1138 | unsigned long hw_len; | 1190 | unsigned long hw_len; |
| @@ -1153,11 +1205,9 @@ struct ipw_priv { | |||
| 1153 | u32 config; | 1205 | u32 config; |
| 1154 | u32 capability; | 1206 | u32 capability; |
| 1155 | 1207 | ||
| 1156 | u8 last_rx_rssi; | ||
| 1157 | u8 last_noise; | ||
| 1158 | struct average average_missed_beacons; | 1208 | struct average average_missed_beacons; |
| 1159 | struct average average_rssi; | 1209 | s16 exp_avg_rssi; |
| 1160 | struct average average_noise; | 1210 | s16 exp_avg_noise; |
| 1161 | u32 port_type; | 1211 | u32 port_type; |
| 1162 | int rx_bufs_min; /**< minimum number of bufs in Rx queue */ | 1212 | int rx_bufs_min; /**< minimum number of bufs in Rx queue */ |
| 1163 | int rx_pend_max; /**< maximum pending buffers for one IRQ */ | 1213 | int rx_pend_max; /**< maximum pending buffers for one IRQ */ |
| @@ -1308,6 +1358,29 @@ struct ipw_priv { | |||
| 1308 | 1358 | ||
| 1309 | /* debug macros */ | 1359 | /* debug macros */ |
| 1310 | 1360 | ||
| 1361 | /* Debug and printf string expansion helpers for printing bitfields */ | ||
| 1362 | #define BIT_FMT8 "%c%c%c%c-%c%c%c%c" | ||
| 1363 | #define BIT_FMT16 BIT_FMT8 ":" BIT_FMT8 | ||
| 1364 | #define BIT_FMT32 BIT_FMT16 " " BIT_FMT16 | ||
| 1365 | |||
| 1366 | #define BITC(x,y) (((x>>y)&1)?'1':'0') | ||
| 1367 | #define BIT_ARG8(x) \ | ||
| 1368 | BITC(x,7),BITC(x,6),BITC(x,5),BITC(x,4),\ | ||
| 1369 | BITC(x,3),BITC(x,2),BITC(x,1),BITC(x,0) | ||
| 1370 | |||
| 1371 | #define BIT_ARG16(x) \ | ||
| 1372 | BITC(x,15),BITC(x,14),BITC(x,13),BITC(x,12),\ | ||
| 1373 | BITC(x,11),BITC(x,10),BITC(x,9),BITC(x,8),\ | ||
| 1374 | BIT_ARG8(x) | ||
| 1375 | |||
| 1376 | #define BIT_ARG32(x) \ | ||
| 1377 | BITC(x,31),BITC(x,30),BITC(x,29),BITC(x,28),\ | ||
| 1378 | BITC(x,27),BITC(x,26),BITC(x,25),BITC(x,24),\ | ||
| 1379 | BITC(x,23),BITC(x,22),BITC(x,21),BITC(x,20),\ | ||
| 1380 | BITC(x,19),BITC(x,18),BITC(x,17),BITC(x,16),\ | ||
| 1381 | BIT_ARG16(x) | ||
| 1382 | |||
| 1383 | |||
| 1311 | #ifdef CONFIG_IPW2200_DEBUG | 1384 | #ifdef CONFIG_IPW2200_DEBUG |
| 1312 | #define IPW_DEBUG(level, fmt, args...) \ | 1385 | #define IPW_DEBUG(level, fmt, args...) \ |
| 1313 | do { if (ipw_debug_level & (level)) \ | 1386 | do { if (ipw_debug_level & (level)) \ |
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index c2d0b09e0418..b563decf599e 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c | |||
| @@ -201,41 +201,12 @@ static struct { | |||
| 201 | /* Data types */ | 201 | /* Data types */ |
| 202 | /********************************************************************/ | 202 | /********************************************************************/ |
| 203 | 203 | ||
| 204 | /* Used in Event handling. | 204 | /* Beginning of the Tx descriptor, used in TxExc handling */ |
| 205 | * We avoid nested structures as they break on ARM -- Moustafa */ | 205 | struct hermes_txexc_data { |
| 206 | struct hermes_tx_descriptor_802_11 { | 206 | struct hermes_tx_descriptor desc; |
| 207 | /* hermes_tx_descriptor */ | ||
| 208 | __le16 status; | ||
| 209 | __le16 reserved1; | ||
| 210 | __le16 reserved2; | ||
| 211 | __le32 sw_support; | ||
| 212 | u8 retry_count; | ||
| 213 | u8 tx_rate; | ||
| 214 | __le16 tx_control; | ||
| 215 | |||
| 216 | /* ieee80211_hdr */ | ||
| 217 | __le16 frame_ctl; | 207 | __le16 frame_ctl; |
| 218 | __le16 duration_id; | 208 | __le16 duration_id; |
| 219 | u8 addr1[ETH_ALEN]; | 209 | u8 addr1[ETH_ALEN]; |
| 220 | u8 addr2[ETH_ALEN]; | ||
| 221 | u8 addr3[ETH_ALEN]; | ||
| 222 | __le16 seq_ctl; | ||
| 223 | u8 addr4[ETH_ALEN]; | ||
| 224 | |||
| 225 | __le16 data_len; | ||
| 226 | |||
| 227 | /* ethhdr */ | ||
| 228 | u8 h_dest[ETH_ALEN]; /* destination eth addr */ | ||
| 229 | u8 h_source[ETH_ALEN]; /* source ether addr */ | ||
| 230 | __be16 h_proto; /* packet type ID field */ | ||
| 231 | |||
| 232 | /* p8022_hdr */ | ||
| 233 | u8 dsap; | ||
| 234 | u8 ssap; | ||
| 235 | u8 ctrl; | ||
| 236 | u8 oui[3]; | ||
| 237 | |||
| 238 | __be16 ethertype; | ||
| 239 | } __attribute__ ((packed)); | 210 | } __attribute__ ((packed)); |
| 240 | 211 | ||
| 241 | /* Rx frame header except compatibility 802.3 header */ | 212 | /* Rx frame header except compatibility 802.3 header */ |
| @@ -450,53 +421,39 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 450 | hermes_t *hw = &priv->hw; | 421 | hermes_t *hw = &priv->hw; |
| 451 | int err = 0; | 422 | int err = 0; |
| 452 | u16 txfid = priv->txfid; | 423 | u16 txfid = priv->txfid; |
| 453 | char *p; | ||
| 454 | struct ethhdr *eh; | 424 | struct ethhdr *eh; |
| 455 | int len, data_len, data_off; | 425 | int data_off; |
| 456 | struct hermes_tx_descriptor desc; | 426 | struct hermes_tx_descriptor desc; |
| 457 | unsigned long flags; | 427 | unsigned long flags; |
| 458 | 428 | ||
| 459 | TRACE_ENTER(dev->name); | ||
| 460 | |||
| 461 | if (! netif_running(dev)) { | 429 | if (! netif_running(dev)) { |
| 462 | printk(KERN_ERR "%s: Tx on stopped device!\n", | 430 | printk(KERN_ERR "%s: Tx on stopped device!\n", |
| 463 | dev->name); | 431 | dev->name); |
| 464 | TRACE_EXIT(dev->name); | 432 | return NETDEV_TX_BUSY; |
| 465 | return 1; | ||
| 466 | } | 433 | } |
| 467 | 434 | ||
| 468 | if (netif_queue_stopped(dev)) { | 435 | if (netif_queue_stopped(dev)) { |
| 469 | printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", | 436 | printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", |
| 470 | dev->name); | 437 | dev->name); |
| 471 | TRACE_EXIT(dev->name); | 438 | return NETDEV_TX_BUSY; |
| 472 | return 1; | ||
| 473 | } | 439 | } |
| 474 | 440 | ||
| 475 | if (orinoco_lock(priv, &flags) != 0) { | 441 | if (orinoco_lock(priv, &flags) != 0) { |
| 476 | printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n", | 442 | printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n", |
| 477 | dev->name); | 443 | dev->name); |
| 478 | TRACE_EXIT(dev->name); | 444 | return NETDEV_TX_BUSY; |
| 479 | return 1; | ||
| 480 | } | 445 | } |
| 481 | 446 | ||
| 482 | if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) { | 447 | if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) { |
| 483 | /* Oops, the firmware hasn't established a connection, | 448 | /* Oops, the firmware hasn't established a connection, |
| 484 | silently drop the packet (this seems to be the | 449 | silently drop the packet (this seems to be the |
| 485 | safest approach). */ | 450 | safest approach). */ |
| 486 | stats->tx_errors++; | 451 | goto drop; |
| 487 | orinoco_unlock(priv, &flags); | ||
| 488 | dev_kfree_skb(skb); | ||
| 489 | TRACE_EXIT(dev->name); | ||
| 490 | return 0; | ||
| 491 | } | 452 | } |
| 492 | 453 | ||
| 493 | /* Length of the packet body */ | 454 | /* Check packet length */ |
| 494 | /* FIXME: what if the skb is smaller than this? */ | 455 | if (skb->len < ETH_HLEN) |
| 495 | len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN); | 456 | goto drop; |
| 496 | skb = skb_padto(skb, len); | ||
| 497 | if (skb == NULL) | ||
| 498 | goto fail; | ||
| 499 | len -= ETH_HLEN; | ||
| 500 | 457 | ||
| 501 | eh = (struct ethhdr *)skb->data; | 458 | eh = (struct ethhdr *)skb->data; |
| 502 | 459 | ||
| @@ -507,8 +464,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 507 | if (net_ratelimit()) | 464 | if (net_ratelimit()) |
| 508 | printk(KERN_ERR "%s: Error %d writing Tx descriptor " | 465 | printk(KERN_ERR "%s: Error %d writing Tx descriptor " |
| 509 | "to BAP\n", dev->name, err); | 466 | "to BAP\n", dev->name, err); |
| 510 | stats->tx_errors++; | 467 | goto busy; |
| 511 | goto fail; | ||
| 512 | } | 468 | } |
| 513 | 469 | ||
| 514 | /* Clear the 802.11 header and data length fields - some | 470 | /* Clear the 802.11 header and data length fields - some |
| @@ -519,50 +475,38 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 519 | 475 | ||
| 520 | /* Encapsulate Ethernet-II frames */ | 476 | /* Encapsulate Ethernet-II frames */ |
| 521 | if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ | 477 | if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ |
| 522 | struct header_struct hdr; | 478 | struct header_struct { |
| 523 | data_len = len; | 479 | struct ethhdr eth; /* 802.3 header */ |
| 524 | data_off = HERMES_802_3_OFFSET + sizeof(hdr); | 480 | u8 encap[6]; /* 802.2 header */ |
| 525 | p = skb->data + ETH_HLEN; | 481 | } __attribute__ ((packed)) hdr; |
| 526 | 482 | ||
| 527 | /* 802.3 header */ | 483 | /* Strip destination and source from the data */ |
| 528 | memcpy(hdr.dest, eh->h_dest, ETH_ALEN); | 484 | skb_pull(skb, 2 * ETH_ALEN); |
| 529 | memcpy(hdr.src, eh->h_source, ETH_ALEN); | 485 | data_off = HERMES_802_2_OFFSET + sizeof(encaps_hdr); |
| 530 | hdr.len = htons(data_len + ENCAPS_OVERHEAD); | 486 | |
| 531 | 487 | /* And move them to a separate header */ | |
| 532 | /* 802.2 header */ | 488 | memcpy(&hdr.eth, eh, 2 * ETH_ALEN); |
| 533 | memcpy(&hdr.dsap, &encaps_hdr, sizeof(encaps_hdr)); | 489 | hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len); |
| 534 | 490 | memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr)); | |
| 535 | hdr.ethertype = eh->h_proto; | 491 | |
| 536 | err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr), | 492 | err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr), |
| 537 | txfid, HERMES_802_3_OFFSET); | 493 | txfid, HERMES_802_3_OFFSET); |
| 538 | if (err) { | 494 | if (err) { |
| 539 | if (net_ratelimit()) | 495 | if (net_ratelimit()) |
| 540 | printk(KERN_ERR "%s: Error %d writing packet " | 496 | printk(KERN_ERR "%s: Error %d writing packet " |
| 541 | "header to BAP\n", dev->name, err); | 497 | "header to BAP\n", dev->name, err); |
| 542 | stats->tx_errors++; | 498 | goto busy; |
| 543 | goto fail; | ||
| 544 | } | 499 | } |
| 545 | /* Actual xfer length - allow for padding */ | ||
| 546 | len = ALIGN(data_len, 2); | ||
| 547 | if (len < ETH_ZLEN - ETH_HLEN) | ||
| 548 | len = ETH_ZLEN - ETH_HLEN; | ||
| 549 | } else { /* IEEE 802.3 frame */ | 500 | } else { /* IEEE 802.3 frame */ |
| 550 | data_len = len + ETH_HLEN; | ||
| 551 | data_off = HERMES_802_3_OFFSET; | 501 | data_off = HERMES_802_3_OFFSET; |
| 552 | p = skb->data; | ||
| 553 | /* Actual xfer length - round up for odd length packets */ | ||
| 554 | len = ALIGN(data_len, 2); | ||
| 555 | if (len < ETH_ZLEN) | ||
| 556 | len = ETH_ZLEN; | ||
| 557 | } | 502 | } |
| 558 | 503 | ||
| 559 | err = hermes_bap_pwrite_pad(hw, USER_BAP, p, data_len, len, | 504 | err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len, |
| 560 | txfid, data_off); | 505 | txfid, data_off); |
| 561 | if (err) { | 506 | if (err) { |
| 562 | printk(KERN_ERR "%s: Error %d writing packet to BAP\n", | 507 | printk(KERN_ERR "%s: Error %d writing packet to BAP\n", |
| 563 | dev->name, err); | 508 | dev->name, err); |
| 564 | stats->tx_errors++; | 509 | goto busy; |
| 565 | goto fail; | ||
| 566 | } | 510 | } |
| 567 | 511 | ||
| 568 | /* Finally, we actually initiate the send */ | 512 | /* Finally, we actually initiate the send */ |
| @@ -575,25 +519,27 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 575 | if (net_ratelimit()) | 519 | if (net_ratelimit()) |
| 576 | printk(KERN_ERR "%s: Error %d transmitting packet\n", | 520 | printk(KERN_ERR "%s: Error %d transmitting packet\n", |
| 577 | dev->name, err); | 521 | dev->name, err); |
| 578 | stats->tx_errors++; | 522 | goto busy; |
| 579 | goto fail; | ||
| 580 | } | 523 | } |
| 581 | 524 | ||
| 582 | dev->trans_start = jiffies; | 525 | dev->trans_start = jiffies; |
| 583 | stats->tx_bytes += data_off + data_len; | 526 | stats->tx_bytes += data_off + skb->len; |
| 527 | goto ok; | ||
| 584 | 528 | ||
| 585 | orinoco_unlock(priv, &flags); | 529 | drop: |
| 530 | stats->tx_errors++; | ||
| 531 | stats->tx_dropped++; | ||
| 586 | 532 | ||
| 533 | ok: | ||
| 534 | orinoco_unlock(priv, &flags); | ||
| 587 | dev_kfree_skb(skb); | 535 | dev_kfree_skb(skb); |
| 536 | return NETDEV_TX_OK; | ||
| 588 | 537 | ||
| 589 | TRACE_EXIT(dev->name); | 538 | busy: |
| 590 | 539 | if (err == -EIO) | |
| 591 | return 0; | 540 | schedule_work(&priv->reset_work); |
| 592 | fail: | ||
| 593 | TRACE_EXIT(dev->name); | ||
| 594 | |||
| 595 | orinoco_unlock(priv, &flags); | 541 | orinoco_unlock(priv, &flags); |
| 596 | return err; | 542 | return NETDEV_TX_BUSY; |
| 597 | } | 543 | } |
| 598 | 544 | ||
| 599 | static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw) | 545 | static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw) |
| @@ -629,7 +575,7 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) | |||
| 629 | struct net_device_stats *stats = &priv->stats; | 575 | struct net_device_stats *stats = &priv->stats; |
| 630 | u16 fid = hermes_read_regn(hw, TXCOMPLFID); | 576 | u16 fid = hermes_read_regn(hw, TXCOMPLFID); |
| 631 | u16 status; | 577 | u16 status; |
| 632 | struct hermes_tx_descriptor_802_11 hdr; | 578 | struct hermes_txexc_data hdr; |
| 633 | int err = 0; | 579 | int err = 0; |
| 634 | 580 | ||
| 635 | if (fid == DUMMY_FID) | 581 | if (fid == DUMMY_FID) |
| @@ -637,8 +583,7 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) | |||
| 637 | 583 | ||
| 638 | /* Read part of the frame header - we need status and addr1 */ | 584 | /* Read part of the frame header - we need status and addr1 */ |
| 639 | err = hermes_bap_pread(hw, IRQ_BAP, &hdr, | 585 | err = hermes_bap_pread(hw, IRQ_BAP, &hdr, |
| 640 | offsetof(struct hermes_tx_descriptor_802_11, | 586 | sizeof(struct hermes_txexc_data), |
| 641 | addr2), | ||
| 642 | fid, 0); | 587 | fid, 0); |
| 643 | 588 | ||
| 644 | hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); | 589 | hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); |
| @@ -658,7 +603,7 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) | |||
| 658 | * exceeded, because that's the only status that really mean | 603 | * exceeded, because that's the only status that really mean |
| 659 | * that this particular node went away. | 604 | * that this particular node went away. |
| 660 | * Other errors means that *we* screwed up. - Jean II */ | 605 | * Other errors means that *we* screwed up. - Jean II */ |
| 661 | status = le16_to_cpu(hdr.status); | 606 | status = le16_to_cpu(hdr.desc.status); |
| 662 | if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) { | 607 | if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) { |
| 663 | union iwreq_data wrqu; | 608 | union iwreq_data wrqu; |
| 664 | 609 | ||
| @@ -1398,16 +1343,12 @@ int __orinoco_down(struct net_device *dev) | |||
| 1398 | return 0; | 1343 | return 0; |
| 1399 | } | 1344 | } |
| 1400 | 1345 | ||
| 1401 | int orinoco_reinit_firmware(struct net_device *dev) | 1346 | static int orinoco_allocate_fid(struct net_device *dev) |
| 1402 | { | 1347 | { |
| 1403 | struct orinoco_private *priv = netdev_priv(dev); | 1348 | struct orinoco_private *priv = netdev_priv(dev); |
| 1404 | struct hermes *hw = &priv->hw; | 1349 | struct hermes *hw = &priv->hw; |
| 1405 | int err; | 1350 | int err; |
| 1406 | 1351 | ||
| 1407 | err = hermes_init(hw); | ||
| 1408 | if (err) | ||
| 1409 | return err; | ||
| 1410 | |||
| 1411 | err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); | 1352 | err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); |
| 1412 | if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) { | 1353 | if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) { |
| 1413 | /* Try workaround for old Symbol firmware bug */ | 1354 | /* Try workaround for old Symbol firmware bug */ |
| @@ -1426,6 +1367,19 @@ int orinoco_reinit_firmware(struct net_device *dev) | |||
| 1426 | return err; | 1367 | return err; |
| 1427 | } | 1368 | } |
| 1428 | 1369 | ||
| 1370 | int orinoco_reinit_firmware(struct net_device *dev) | ||
| 1371 | { | ||
| 1372 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 1373 | struct hermes *hw = &priv->hw; | ||
| 1374 | int err; | ||
| 1375 | |||
| 1376 | err = hermes_init(hw); | ||
| 1377 | if (!err) | ||
| 1378 | err = orinoco_allocate_fid(dev); | ||
| 1379 | |||
| 1380 | return err; | ||
| 1381 | } | ||
| 1382 | |||
| 1429 | static int __orinoco_hw_set_bitrate(struct orinoco_private *priv) | 1383 | static int __orinoco_hw_set_bitrate(struct orinoco_private *priv) |
| 1430 | { | 1384 | { |
| 1431 | hermes_t *hw = &priv->hw; | 1385 | hermes_t *hw = &priv->hw; |
| @@ -2272,14 +2226,12 @@ static int orinoco_init(struct net_device *dev) | |||
| 2272 | u16 reclen; | 2226 | u16 reclen; |
| 2273 | int len; | 2227 | int len; |
| 2274 | 2228 | ||
| 2275 | TRACE_ENTER(dev->name); | ||
| 2276 | |||
| 2277 | /* No need to lock, the hw_unavailable flag is already set in | 2229 | /* No need to lock, the hw_unavailable flag is already set in |
| 2278 | * alloc_orinocodev() */ | 2230 | * alloc_orinocodev() */ |
| 2279 | priv->nicbuf_size = IEEE80211_FRAME_LEN + ETH_HLEN; | 2231 | priv->nicbuf_size = IEEE80211_FRAME_LEN + ETH_HLEN; |
| 2280 | 2232 | ||
| 2281 | /* Initialize the firmware */ | 2233 | /* Initialize the firmware */ |
| 2282 | err = orinoco_reinit_firmware(dev); | 2234 | err = hermes_init(hw); |
| 2283 | if (err != 0) { | 2235 | if (err != 0) { |
| 2284 | printk(KERN_ERR "%s: failed to initialize firmware (err = %d)\n", | 2236 | printk(KERN_ERR "%s: failed to initialize firmware (err = %d)\n", |
| 2285 | dev->name, err); | 2237 | dev->name, err); |
| @@ -2337,6 +2289,13 @@ static int orinoco_init(struct net_device *dev) | |||
| 2337 | 2289 | ||
| 2338 | printk(KERN_DEBUG "%s: Station name \"%s\"\n", dev->name, priv->nick); | 2290 | printk(KERN_DEBUG "%s: Station name \"%s\"\n", dev->name, priv->nick); |
| 2339 | 2291 | ||
| 2292 | err = orinoco_allocate_fid(dev); | ||
| 2293 | if (err) { | ||
| 2294 | printk(KERN_ERR "%s: failed to allocate NIC buffer!\n", | ||
| 2295 | dev->name); | ||
| 2296 | goto out; | ||
| 2297 | } | ||
| 2298 | |||
| 2340 | /* Get allowed channels */ | 2299 | /* Get allowed channels */ |
| 2341 | err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST, | 2300 | err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST, |
| 2342 | &priv->channel_mask); | 2301 | &priv->channel_mask); |
| @@ -2427,7 +2386,6 @@ static int orinoco_init(struct net_device *dev) | |||
| 2427 | printk(KERN_DEBUG "%s: ready\n", dev->name); | 2386 | printk(KERN_DEBUG "%s: ready\n", dev->name); |
| 2428 | 2387 | ||
| 2429 | out: | 2388 | out: |
| 2430 | TRACE_EXIT(dev->name); | ||
| 2431 | return err; | 2389 | return err; |
| 2432 | } | 2390 | } |
| 2433 | 2391 | ||
| @@ -2795,8 +2753,6 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, | |||
| 2795 | int numrates; | 2753 | int numrates; |
| 2796 | int i, k; | 2754 | int i, k; |
| 2797 | 2755 | ||
| 2798 | TRACE_ENTER(dev->name); | ||
| 2799 | |||
| 2800 | rrq->length = sizeof(struct iw_range); | 2756 | rrq->length = sizeof(struct iw_range); |
| 2801 | memset(range, 0, sizeof(struct iw_range)); | 2757 | memset(range, 0, sizeof(struct iw_range)); |
| 2802 | 2758 | ||
| @@ -2886,8 +2842,6 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, | |||
| 2886 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); | 2842 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); |
| 2887 | IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP); | 2843 | IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP); |
| 2888 | 2844 | ||
| 2889 | TRACE_EXIT(dev->name); | ||
| 2890 | |||
| 2891 | return 0; | 2845 | return 0; |
| 2892 | } | 2846 | } |
| 2893 | 2847 | ||
| @@ -3069,8 +3023,6 @@ static int orinoco_ioctl_getessid(struct net_device *dev, | |||
| 3069 | int err = 0; | 3023 | int err = 0; |
| 3070 | unsigned long flags; | 3024 | unsigned long flags; |
| 3071 | 3025 | ||
| 3072 | TRACE_ENTER(dev->name); | ||
| 3073 | |||
| 3074 | if (netif_running(dev)) { | 3026 | if (netif_running(dev)) { |
| 3075 | err = orinoco_hw_get_essid(priv, &active, essidbuf); | 3027 | err = orinoco_hw_get_essid(priv, &active, essidbuf); |
| 3076 | if (err) | 3028 | if (err) |
| @@ -3085,8 +3037,6 @@ static int orinoco_ioctl_getessid(struct net_device *dev, | |||
| 3085 | erq->flags = 1; | 3037 | erq->flags = 1; |
| 3086 | erq->length = strlen(essidbuf) + 1; | 3038 | erq->length = strlen(essidbuf) + 1; |
| 3087 | 3039 | ||
| 3088 | TRACE_EXIT(dev->name); | ||
| 3089 | |||
| 3090 | return 0; | 3040 | return 0; |
| 3091 | } | 3041 | } |
| 3092 | 3042 | ||
| @@ -4347,69 +4297,6 @@ static struct ethtool_ops orinoco_ethtool_ops = { | |||
| 4347 | }; | 4297 | }; |
| 4348 | 4298 | ||
| 4349 | /********************************************************************/ | 4299 | /********************************************************************/ |
| 4350 | /* Debugging */ | ||
| 4351 | /********************************************************************/ | ||
| 4352 | |||
| 4353 | #if 0 | ||
| 4354 | static void show_rx_frame(struct orinoco_rxframe_hdr *frame) | ||
| 4355 | { | ||
| 4356 | printk(KERN_DEBUG "RX descriptor:\n"); | ||
| 4357 | printk(KERN_DEBUG " status = 0x%04x\n", frame->desc.status); | ||
| 4358 | printk(KERN_DEBUG " time = 0x%08x\n", frame->desc.time); | ||
| 4359 | printk(KERN_DEBUG " silence = 0x%02x\n", frame->desc.silence); | ||
| 4360 | printk(KERN_DEBUG " signal = 0x%02x\n", frame->desc.signal); | ||
| 4361 | printk(KERN_DEBUG " rate = 0x%02x\n", frame->desc.rate); | ||
| 4362 | printk(KERN_DEBUG " rxflow = 0x%02x\n", frame->desc.rxflow); | ||
| 4363 | printk(KERN_DEBUG " reserved = 0x%08x\n", frame->desc.reserved); | ||
| 4364 | |||
| 4365 | printk(KERN_DEBUG "IEEE 802.11 header:\n"); | ||
| 4366 | printk(KERN_DEBUG " frame_ctl = 0x%04x\n", | ||
| 4367 | frame->p80211.frame_ctl); | ||
| 4368 | printk(KERN_DEBUG " duration_id = 0x%04x\n", | ||
| 4369 | frame->p80211.duration_id); | ||
| 4370 | printk(KERN_DEBUG " addr1 = %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
| 4371 | frame->p80211.addr1[0], frame->p80211.addr1[1], | ||
| 4372 | frame->p80211.addr1[2], frame->p80211.addr1[3], | ||
| 4373 | frame->p80211.addr1[4], frame->p80211.addr1[5]); | ||
| 4374 | printk(KERN_DEBUG " addr2 = %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
| 4375 | frame->p80211.addr2[0], frame->p80211.addr2[1], | ||
| 4376 | frame->p80211.addr2[2], frame->p80211.addr2[3], | ||
| 4377 | frame->p80211.addr2[4], frame->p80211.addr2[5]); | ||
| 4378 | printk(KERN_DEBUG " addr3 = %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
| 4379 | frame->p80211.addr3[0], frame->p80211.addr3[1], | ||
| 4380 | frame->p80211.addr3[2], frame->p80211.addr3[3], | ||
| 4381 | frame->p80211.addr3[4], frame->p80211.addr3[5]); | ||
| 4382 | printk(KERN_DEBUG " seq_ctl = 0x%04x\n", | ||
| 4383 | frame->p80211.seq_ctl); | ||
| 4384 | printk(KERN_DEBUG " addr4 = %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
| 4385 | frame->p80211.addr4[0], frame->p80211.addr4[1], | ||
| 4386 | frame->p80211.addr4[2], frame->p80211.addr4[3], | ||
| 4387 | frame->p80211.addr4[4], frame->p80211.addr4[5]); | ||
| 4388 | printk(KERN_DEBUG " data_len = 0x%04x\n", | ||
| 4389 | frame->p80211.data_len); | ||
| 4390 | |||
| 4391 | printk(KERN_DEBUG "IEEE 802.3 header:\n"); | ||
| 4392 | printk(KERN_DEBUG " dest = %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
| 4393 | frame->p8023.h_dest[0], frame->p8023.h_dest[1], | ||
| 4394 | frame->p8023.h_dest[2], frame->p8023.h_dest[3], | ||
| 4395 | frame->p8023.h_dest[4], frame->p8023.h_dest[5]); | ||
| 4396 | printk(KERN_DEBUG " src = %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
| 4397 | frame->p8023.h_source[0], frame->p8023.h_source[1], | ||
| 4398 | frame->p8023.h_source[2], frame->p8023.h_source[3], | ||
| 4399 | frame->p8023.h_source[4], frame->p8023.h_source[5]); | ||
| 4400 | printk(KERN_DEBUG " len = 0x%04x\n", frame->p8023.h_proto); | ||
| 4401 | |||
| 4402 | printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n"); | ||
| 4403 | printk(KERN_DEBUG " DSAP = 0x%02x\n", frame->p8022.dsap); | ||
| 4404 | printk(KERN_DEBUG " SSAP = 0x%02x\n", frame->p8022.ssap); | ||
| 4405 | printk(KERN_DEBUG " ctrl = 0x%02x\n", frame->p8022.ctrl); | ||
| 4406 | printk(KERN_DEBUG " OUI = %02x:%02x:%02x\n", | ||
| 4407 | frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]); | ||
| 4408 | printk(KERN_DEBUG " ethertype = 0x%04x\n", frame->ethertype); | ||
| 4409 | } | ||
| 4410 | #endif /* 0 */ | ||
| 4411 | |||
| 4412 | /********************************************************************/ | ||
| 4413 | /* Module initialization */ | 4300 | /* Module initialization */ |
| 4414 | /********************************************************************/ | 4301 | /********************************************************************/ |
| 4415 | 4302 | ||
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h index f5d856db92a1..16db3e14b7d2 100644 --- a/drivers/net/wireless/orinoco.h +++ b/drivers/net/wireless/orinoco.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #ifndef _ORINOCO_H | 7 | #ifndef _ORINOCO_H |
| 8 | #define _ORINOCO_H | 8 | #define _ORINOCO_H |
| 9 | 9 | ||
| 10 | #define DRIVER_VERSION "0.15rc3" | 10 | #define DRIVER_VERSION "0.15" |
| 11 | 11 | ||
| 12 | #include <linux/netdevice.h> | 12 | #include <linux/netdevice.h> |
| 13 | #include <linux/wireless.h> | 13 | #include <linux/wireless.h> |
| @@ -30,20 +30,6 @@ struct orinoco_key { | |||
| 30 | char data[ORINOCO_MAX_KEY_SIZE]; | 30 | char data[ORINOCO_MAX_KEY_SIZE]; |
| 31 | } __attribute__ ((packed)); | 31 | } __attribute__ ((packed)); |
| 32 | 32 | ||
| 33 | struct header_struct { | ||
| 34 | /* 802.3 */ | ||
| 35 | u8 dest[ETH_ALEN]; | ||
| 36 | u8 src[ETH_ALEN]; | ||
| 37 | __be16 len; | ||
| 38 | /* 802.2 */ | ||
| 39 | u8 dsap; | ||
| 40 | u8 ssap; | ||
| 41 | u8 ctrl; | ||
| 42 | /* SNAP */ | ||
| 43 | u8 oui[3]; | ||
| 44 | unsigned short ethertype; | ||
| 45 | } __attribute__ ((packed)); | ||
| 46 | |||
| 47 | typedef enum { | 33 | typedef enum { |
| 48 | FIRMWARE_TYPE_AGERE, | 34 | FIRMWARE_TYPE_AGERE, |
| 49 | FIRMWARE_TYPE_INTERSIL, | 35 | FIRMWARE_TYPE_INTERSIL, |
| @@ -132,9 +118,6 @@ extern int orinoco_debug; | |||
| 132 | #define DEBUG(n, args...) do { } while (0) | 118 | #define DEBUG(n, args...) do { } while (0) |
| 133 | #endif /* ORINOCO_DEBUG */ | 119 | #endif /* ORINOCO_DEBUG */ |
| 134 | 120 | ||
| 135 | #define TRACE_ENTER(devname) DEBUG(2, "%s: -> %s()\n", devname, __FUNCTION__); | ||
| 136 | #define TRACE_EXIT(devname) DEBUG(2, "%s: <- %s()\n", devname, __FUNCTION__); | ||
| 137 | |||
| 138 | /********************************************************************/ | 121 | /********************************************************************/ |
| 139 | /* Exported prototypes */ | 122 | /* Exported prototypes */ |
| 140 | /********************************************************************/ | 123 | /********************************************************************/ |
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 434f7d7ad841..b2aec4d9fbb1 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c | |||
| @@ -147,14 +147,11 @@ static void orinoco_cs_detach(struct pcmcia_device *link) | |||
| 147 | { | 147 | { |
| 148 | struct net_device *dev = link->priv; | 148 | struct net_device *dev = link->priv; |
| 149 | 149 | ||
| 150 | if (link->dev_node) | ||
| 151 | unregister_netdev(dev); | ||
| 152 | |||
| 150 | orinoco_cs_release(link); | 153 | orinoco_cs_release(link); |
| 151 | 154 | ||
| 152 | DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node); | ||
| 153 | if (link->dev_node) { | ||
| 154 | DEBUG(0, PFX "About to unregister net device %p\n", | ||
| 155 | dev); | ||
| 156 | unregister_netdev(dev); | ||
| 157 | } | ||
| 158 | free_orinocodev(dev); | 155 | free_orinocodev(dev); |
| 159 | } /* orinoco_cs_detach */ | 156 | } /* orinoco_cs_detach */ |
| 160 | 157 | ||
| @@ -178,13 +175,10 @@ orinoco_cs_config(struct pcmcia_device *link) | |||
| 178 | int last_fn, last_ret; | 175 | int last_fn, last_ret; |
| 179 | u_char buf[64]; | 176 | u_char buf[64]; |
| 180 | config_info_t conf; | 177 | config_info_t conf; |
| 181 | cisinfo_t info; | ||
| 182 | tuple_t tuple; | 178 | tuple_t tuple; |
| 183 | cisparse_t parse; | 179 | cisparse_t parse; |
| 184 | void __iomem *mem; | 180 | void __iomem *mem; |
| 185 | 181 | ||
| 186 | CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info)); | ||
| 187 | |||
| 188 | /* | 182 | /* |
| 189 | * This reads the card's CONFIG tuple to find its | 183 | * This reads the card's CONFIG tuple to find its |
| 190 | * configuration registers. | 184 | * configuration registers. |
| @@ -234,12 +228,6 @@ orinoco_cs_config(struct pcmcia_device *link) | |||
| 234 | goto next_entry; | 228 | goto next_entry; |
| 235 | link->conf.ConfigIndex = cfg->index; | 229 | link->conf.ConfigIndex = cfg->index; |
| 236 | 230 | ||
| 237 | /* Does this card need audio output? */ | ||
| 238 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
| 239 | link->conf.Attributes |= CONF_ENABLE_SPKR; | ||
| 240 | link->conf.Status = CCSR_AUDIO_ENA; | ||
| 241 | } | ||
| 242 | |||
| 243 | /* Use power settings for Vcc and Vpp if present */ | 231 | /* Use power settings for Vcc and Vpp if present */ |
| 244 | /* Note that the CIS values need to be rescaled */ | 232 | /* Note that the CIS values need to be rescaled */ |
| 245 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | 233 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { |
| @@ -355,19 +343,10 @@ orinoco_cs_config(struct pcmcia_device *link) | |||
| 355 | net_device has been registered */ | 343 | net_device has been registered */ |
| 356 | 344 | ||
| 357 | /* Finally, report what we've done */ | 345 | /* Finally, report what we've done */ |
| 358 | printk(KERN_DEBUG "%s: index 0x%02x: ", | 346 | printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io " |
| 359 | dev->name, link->conf.ConfigIndex); | 347 | "0x%04x-0x%04x\n", dev->name, dev->class_dev.dev->bus_id, |
| 360 | if (link->conf.Vpp) | 348 | link->irq.AssignedIRQ, link->io.BasePort1, |
| 361 | printk(", Vpp %d.%d", link->conf.Vpp / 10, | 349 | link->io.BasePort1 + link->io.NumPorts1 - 1); |
| 362 | link->conf.Vpp % 10); | ||
| 363 | printk(", irq %d", link->irq.AssignedIRQ); | ||
| 364 | if (link->io.NumPorts1) | ||
| 365 | printk(", io 0x%04x-0x%04x", link->io.BasePort1, | ||
| 366 | link->io.BasePort1 + link->io.NumPorts1 - 1); | ||
| 367 | if (link->io.NumPorts2) | ||
| 368 | printk(" & 0x%04x-0x%04x", link->io.BasePort2, | ||
| 369 | link->io.BasePort2 + link->io.NumPorts2 - 1); | ||
| 370 | printk("\n"); | ||
| 371 | 350 | ||
| 372 | return 0; | 351 | return 0; |
| 373 | 352 | ||
| @@ -436,7 +415,6 @@ static int orinoco_cs_resume(struct pcmcia_device *link) | |||
| 436 | struct orinoco_private *priv = netdev_priv(dev); | 415 | struct orinoco_private *priv = netdev_priv(dev); |
| 437 | struct orinoco_pccard *card = priv->card; | 416 | struct orinoco_pccard *card = priv->card; |
| 438 | int err = 0; | 417 | int err = 0; |
| 439 | unsigned long flags; | ||
| 440 | 418 | ||
| 441 | if (! test_bit(0, &card->hard_reset_in_progress)) { | 419 | if (! test_bit(0, &card->hard_reset_in_progress)) { |
| 442 | err = orinoco_reinit_firmware(dev); | 420 | err = orinoco_reinit_firmware(dev); |
| @@ -446,7 +424,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link) | |||
| 446 | return -EIO; | 424 | return -EIO; |
| 447 | } | 425 | } |
| 448 | 426 | ||
| 449 | spin_lock_irqsave(&priv->lock, flags); | 427 | spin_lock(&priv->lock); |
| 450 | 428 | ||
| 451 | netif_device_attach(dev); | 429 | netif_device_attach(dev); |
| 452 | priv->hw_unavailable--; | 430 | priv->hw_unavailable--; |
| @@ -458,10 +436,10 @@ static int orinoco_cs_resume(struct pcmcia_device *link) | |||
| 458 | dev->name, err); | 436 | dev->name, err); |
| 459 | } | 437 | } |
| 460 | 438 | ||
| 461 | spin_unlock_irqrestore(&priv->lock, flags); | 439 | spin_unlock(&priv->lock); |
| 462 | } | 440 | } |
| 463 | 441 | ||
| 464 | return 0; | 442 | return err; |
| 465 | } | 443 | } |
| 466 | 444 | ||
| 467 | 445 | ||
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c index d1a670b35338..74b9d5b2ba9e 100644 --- a/drivers/net/wireless/orinoco_nortel.c +++ b/drivers/net/wireless/orinoco_nortel.c | |||
| @@ -1,9 +1,8 @@ | |||
| 1 | /* orinoco_nortel.c | 1 | /* orinoco_nortel.c |
| 2 | * | 2 | * |
| 3 | * Driver for Prism II devices which would usually be driven by orinoco_cs, | 3 | * Driver for Prism II devices which would usually be driven by orinoco_cs, |
| 4 | * but are connected to the PCI bus by a PCI-to-PCMCIA adapter used in | 4 | * but are connected to the PCI bus by a PCI-to-PCMCIA adapter used in |
| 5 | * Nortel emobility, Symbol LA-4113 and Symbol LA-4123. | 5 | * Nortel emobility, Symbol LA-4113 and Symbol LA-4123. |
| 6 | * but are connected to the PCI bus by a Nortel PCI-PCMCIA-Adapter. | ||
| 7 | * | 6 | * |
| 8 | * Copyright (C) 2002 Tobias Hoffmann | 7 | * Copyright (C) 2002 Tobias Hoffmann |
| 9 | * (C) 2003 Christoph Jungegger <disdos@traum404.de> | 8 | * (C) 2003 Christoph Jungegger <disdos@traum404.de> |
| @@ -50,67 +49,62 @@ | |||
| 50 | #include <pcmcia/cisreg.h> | 49 | #include <pcmcia/cisreg.h> |
| 51 | 50 | ||
| 52 | #include "orinoco.h" | 51 | #include "orinoco.h" |
| 52 | #include "orinoco_pci.h" | ||
| 53 | 53 | ||
| 54 | #define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */ | 54 | #define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */ |
| 55 | #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ | 55 | #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ |
| 56 | 56 | ||
| 57 | 57 | ||
| 58 | /* Nortel specific data */ | ||
| 59 | struct nortel_pci_card { | ||
| 60 | unsigned long iobase1; | ||
| 61 | unsigned long iobase2; | ||
| 62 | }; | ||
| 63 | |||
| 64 | /* | 58 | /* |
| 65 | * Do a soft reset of the PCI card using the Configuration Option Register | 59 | * Do a soft reset of the card using the Configuration Option Register |
| 66 | * We need this to get going... | 60 | * We need this to get going... |
| 67 | * This is the part of the code that is strongly inspired from wlan-ng | 61 | * This is the part of the code that is strongly inspired from wlan-ng |
| 68 | * | 62 | * |
| 69 | * Note bis : Don't try to access HERMES_CMD during the reset phase. | 63 | * Note bis : Don't try to access HERMES_CMD during the reset phase. |
| 70 | * It just won't work ! | 64 | * It just won't work ! |
| 71 | */ | 65 | */ |
| 72 | static int nortel_pci_cor_reset(struct orinoco_private *priv) | 66 | static int orinoco_nortel_cor_reset(struct orinoco_private *priv) |
| 73 | { | 67 | { |
| 74 | struct nortel_pci_card *card = priv->card; | 68 | struct orinoco_pci_card *card = priv->card; |
| 75 | 69 | ||
| 76 | /* Assert the reset until the card notice */ | 70 | /* Assert the reset until the card notices */ |
| 77 | outw_p(8, card->iobase1 + 2); | 71 | iowrite16(8, card->bridge_io + 2); |
| 78 | inw(card->iobase2 + COR_OFFSET); | 72 | ioread16(card->attr_io + COR_OFFSET); |
| 79 | outw_p(0x80, card->iobase2 + COR_OFFSET); | 73 | iowrite16(0x80, card->attr_io + COR_OFFSET); |
| 80 | mdelay(1); | 74 | mdelay(1); |
| 81 | 75 | ||
| 82 | /* Give time for the card to recover from this hard effort */ | 76 | /* Give time for the card to recover from this hard effort */ |
| 83 | outw_p(0, card->iobase2 + COR_OFFSET); | 77 | iowrite16(0, card->attr_io + COR_OFFSET); |
| 84 | outw_p(0, card->iobase2 + COR_OFFSET); | 78 | iowrite16(0, card->attr_io + COR_OFFSET); |
| 85 | mdelay(1); | 79 | mdelay(1); |
| 86 | 80 | ||
| 87 | /* set COR as usual */ | 81 | /* Set COR as usual */ |
| 88 | outw_p(COR_VALUE, card->iobase2 + COR_OFFSET); | 82 | iowrite16(COR_VALUE, card->attr_io + COR_OFFSET); |
| 89 | outw_p(COR_VALUE, card->iobase2 + COR_OFFSET); | 83 | iowrite16(COR_VALUE, card->attr_io + COR_OFFSET); |
| 90 | mdelay(1); | 84 | mdelay(1); |
| 91 | 85 | ||
| 92 | outw_p(0x228, card->iobase1 + 2); | 86 | iowrite16(0x228, card->bridge_io + 2); |
| 93 | 87 | ||
| 94 | return 0; | 88 | return 0; |
| 95 | } | 89 | } |
| 96 | 90 | ||
| 97 | static int nortel_pci_hw_init(struct nortel_pci_card *card) | 91 | static int orinoco_nortel_hw_init(struct orinoco_pci_card *card) |
| 98 | { | 92 | { |
| 99 | int i; | 93 | int i; |
| 100 | u32 reg; | 94 | u32 reg; |
| 101 | 95 | ||
| 102 | /* setup bridge */ | 96 | /* Setup bridge */ |
| 103 | if (inw(card->iobase1) & 1) { | 97 | if (ioread16(card->bridge_io) & 1) { |
| 104 | printk(KERN_ERR PFX "brg1 answer1 wrong\n"); | 98 | printk(KERN_ERR PFX "brg1 answer1 wrong\n"); |
| 105 | return -EBUSY; | 99 | return -EBUSY; |
| 106 | } | 100 | } |
| 107 | outw_p(0x118, card->iobase1 + 2); | 101 | iowrite16(0x118, card->bridge_io + 2); |
| 108 | outw_p(0x108, card->iobase1 + 2); | 102 | iowrite16(0x108, card->bridge_io + 2); |
| 109 | mdelay(30); | 103 | mdelay(30); |
| 110 | outw_p(0x8, card->iobase1 + 2); | 104 | iowrite16(0x8, card->bridge_io + 2); |
| 111 | for (i = 0; i < 30; i++) { | 105 | for (i = 0; i < 30; i++) { |
| 112 | mdelay(30); | 106 | mdelay(30); |
| 113 | if (inw(card->iobase1) & 0x10) { | 107 | if (ioread16(card->bridge_io) & 0x10) { |
| 114 | break; | 108 | break; |
| 115 | } | 109 | } |
| 116 | } | 110 | } |
| @@ -118,42 +112,42 @@ static int nortel_pci_hw_init(struct nortel_pci_card *card) | |||
| 118 | printk(KERN_ERR PFX "brg1 timed out\n"); | 112 | printk(KERN_ERR PFX "brg1 timed out\n"); |
| 119 | return -EBUSY; | 113 | return -EBUSY; |
| 120 | } | 114 | } |
| 121 | if (inw(card->iobase2 + 0xe0) & 1) { | 115 | if (ioread16(card->attr_io + COR_OFFSET) & 1) { |
| 122 | printk(KERN_ERR PFX "brg2 answer1 wrong\n"); | 116 | printk(KERN_ERR PFX "brg2 answer1 wrong\n"); |
| 123 | return -EBUSY; | 117 | return -EBUSY; |
| 124 | } | 118 | } |
| 125 | if (inw(card->iobase2 + 0xe2) & 1) { | 119 | if (ioread16(card->attr_io + COR_OFFSET + 2) & 1) { |
| 126 | printk(KERN_ERR PFX "brg2 answer2 wrong\n"); | 120 | printk(KERN_ERR PFX "brg2 answer2 wrong\n"); |
| 127 | return -EBUSY; | 121 | return -EBUSY; |
| 128 | } | 122 | } |
| 129 | if (inw(card->iobase2 + 0xe4) & 1) { | 123 | if (ioread16(card->attr_io + COR_OFFSET + 4) & 1) { |
| 130 | printk(KERN_ERR PFX "brg2 answer3 wrong\n"); | 124 | printk(KERN_ERR PFX "brg2 answer3 wrong\n"); |
| 131 | return -EBUSY; | 125 | return -EBUSY; |
| 132 | } | 126 | } |
| 133 | 127 | ||
| 134 | /* set the PCMCIA COR-Register */ | 128 | /* Set the PCMCIA COR register */ |
| 135 | outw_p(COR_VALUE, card->iobase2 + COR_OFFSET); | 129 | iowrite16(COR_VALUE, card->attr_io + COR_OFFSET); |
| 136 | mdelay(1); | 130 | mdelay(1); |
| 137 | reg = inw(card->iobase2 + COR_OFFSET); | 131 | reg = ioread16(card->attr_io + COR_OFFSET); |
| 138 | if (reg != COR_VALUE) { | 132 | if (reg != COR_VALUE) { |
| 139 | printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n", | 133 | printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n", |
| 140 | reg); | 134 | reg); |
| 141 | return -EBUSY; | 135 | return -EBUSY; |
| 142 | } | 136 | } |
| 143 | 137 | ||
| 144 | /* set leds */ | 138 | /* Set LEDs */ |
| 145 | outw_p(1, card->iobase1 + 10); | 139 | iowrite16(1, card->bridge_io + 10); |
| 146 | return 0; | 140 | return 0; |
| 147 | } | 141 | } |
| 148 | 142 | ||
| 149 | static int nortel_pci_init_one(struct pci_dev *pdev, | 143 | static int orinoco_nortel_init_one(struct pci_dev *pdev, |
| 150 | const struct pci_device_id *ent) | 144 | const struct pci_device_id *ent) |
| 151 | { | 145 | { |
| 152 | int err; | 146 | int err; |
| 153 | struct orinoco_private *priv; | 147 | struct orinoco_private *priv; |
| 154 | struct nortel_pci_card *card; | 148 | struct orinoco_pci_card *card; |
| 155 | struct net_device *dev; | 149 | struct net_device *dev; |
| 156 | void __iomem *iomem; | 150 | void __iomem *hermes_io, *bridge_io, *attr_io; |
| 157 | 151 | ||
| 158 | err = pci_enable_device(pdev); | 152 | err = pci_enable_device(pdev); |
| 159 | if (err) { | 153 | if (err) { |
| @@ -162,19 +156,34 @@ static int nortel_pci_init_one(struct pci_dev *pdev, | |||
| 162 | } | 156 | } |
| 163 | 157 | ||
| 164 | err = pci_request_regions(pdev, DRIVER_NAME); | 158 | err = pci_request_regions(pdev, DRIVER_NAME); |
| 165 | if (err != 0) { | 159 | if (err) { |
| 166 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); | 160 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); |
| 167 | goto fail_resources; | 161 | goto fail_resources; |
| 168 | } | 162 | } |
| 169 | 163 | ||
| 170 | iomem = pci_iomap(pdev, 2, 0); | 164 | bridge_io = pci_iomap(pdev, 0, 0); |
| 171 | if (!iomem) { | 165 | if (!bridge_io) { |
| 172 | err = -ENOMEM; | 166 | printk(KERN_ERR PFX "Cannot map bridge registers\n"); |
| 173 | goto fail_map_io; | 167 | err = -EIO; |
| 168 | goto fail_map_bridge; | ||
| 169 | } | ||
| 170 | |||
| 171 | attr_io = pci_iomap(pdev, 1, 0); | ||
| 172 | if (!attr_io) { | ||
| 173 | printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n"); | ||
| 174 | err = -EIO; | ||
| 175 | goto fail_map_attr; | ||
| 176 | } | ||
| 177 | |||
| 178 | hermes_io = pci_iomap(pdev, 2, 0); | ||
| 179 | if (!hermes_io) { | ||
| 180 | printk(KERN_ERR PFX "Cannot map chipset registers\n"); | ||
| 181 | err = -EIO; | ||
| 182 | goto fail_map_hermes; | ||
| 174 | } | 183 | } |
| 175 | 184 | ||
| 176 | /* Allocate network device */ | 185 | /* Allocate network device */ |
| 177 | dev = alloc_orinocodev(sizeof(*card), nortel_pci_cor_reset); | 186 | dev = alloc_orinocodev(sizeof(*card), orinoco_nortel_cor_reset); |
| 178 | if (!dev) { | 187 | if (!dev) { |
| 179 | printk(KERN_ERR PFX "Cannot allocate network device\n"); | 188 | printk(KERN_ERR PFX "Cannot allocate network device\n"); |
| 180 | err = -ENOMEM; | 189 | err = -ENOMEM; |
| @@ -183,16 +192,12 @@ static int nortel_pci_init_one(struct pci_dev *pdev, | |||
| 183 | 192 | ||
| 184 | priv = netdev_priv(dev); | 193 | priv = netdev_priv(dev); |
| 185 | card = priv->card; | 194 | card = priv->card; |
| 186 | card->iobase1 = pci_resource_start(pdev, 0); | 195 | card->bridge_io = bridge_io; |
| 187 | card->iobase2 = pci_resource_start(pdev, 1); | 196 | card->attr_io = attr_io; |
| 188 | dev->base_addr = pci_resource_start(pdev, 2); | ||
| 189 | SET_MODULE_OWNER(dev); | 197 | SET_MODULE_OWNER(dev); |
| 190 | SET_NETDEV_DEV(dev, &pdev->dev); | 198 | SET_NETDEV_DEV(dev, &pdev->dev); |
| 191 | 199 | ||
| 192 | hermes_struct_init(&priv->hw, iomem, HERMES_16BIT_REGSPACING); | 200 | hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING); |
| 193 | |||
| 194 | printk(KERN_DEBUG PFX "Detected Nortel PCI device at %s irq:%d, " | ||
| 195 | "io addr:0x%lx\n", pci_name(pdev), pdev->irq, dev->base_addr); | ||
| 196 | 201 | ||
| 197 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, | 202 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, |
| 198 | dev->name, dev); | 203 | dev->name, dev); |
| @@ -201,21 +206,19 @@ static int nortel_pci_init_one(struct pci_dev *pdev, | |||
| 201 | err = -EBUSY; | 206 | err = -EBUSY; |
| 202 | goto fail_irq; | 207 | goto fail_irq; |
| 203 | } | 208 | } |
| 204 | dev->irq = pdev->irq; | ||
| 205 | 209 | ||
| 206 | err = nortel_pci_hw_init(card); | 210 | err = orinoco_nortel_hw_init(card); |
| 207 | if (err) { | 211 | if (err) { |
| 208 | printk(KERN_ERR PFX "Hardware initialization failed\n"); | 212 | printk(KERN_ERR PFX "Hardware initialization failed\n"); |
| 209 | goto fail; | 213 | goto fail; |
| 210 | } | 214 | } |
| 211 | 215 | ||
| 212 | err = nortel_pci_cor_reset(priv); | 216 | err = orinoco_nortel_cor_reset(priv); |
| 213 | if (err) { | 217 | if (err) { |
| 214 | printk(KERN_ERR PFX "Initial reset failed\n"); | 218 | printk(KERN_ERR PFX "Initial reset failed\n"); |
| 215 | goto fail; | 219 | goto fail; |
| 216 | } | 220 | } |
| 217 | 221 | ||
| 218 | |||
| 219 | err = register_netdev(dev); | 222 | err = register_netdev(dev); |
| 220 | if (err) { | 223 | if (err) { |
| 221 | printk(KERN_ERR PFX "Cannot register network device\n"); | 224 | printk(KERN_ERR PFX "Cannot register network device\n"); |
| @@ -223,6 +226,8 @@ static int nortel_pci_init_one(struct pci_dev *pdev, | |||
| 223 | } | 226 | } |
| 224 | 227 | ||
| 225 | pci_set_drvdata(pdev, dev); | 228 | pci_set_drvdata(pdev, dev); |
| 229 | printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name, | ||
| 230 | pci_name(pdev)); | ||
| 226 | 231 | ||
| 227 | return 0; | 232 | return 0; |
| 228 | 233 | ||
| @@ -234,9 +239,15 @@ static int nortel_pci_init_one(struct pci_dev *pdev, | |||
| 234 | free_orinocodev(dev); | 239 | free_orinocodev(dev); |
| 235 | 240 | ||
| 236 | fail_alloc: | 241 | fail_alloc: |
| 237 | pci_iounmap(pdev, iomem); | 242 | pci_iounmap(pdev, hermes_io); |
| 238 | 243 | ||
| 239 | fail_map_io: | 244 | fail_map_hermes: |
| 245 | pci_iounmap(pdev, attr_io); | ||
| 246 | |||
| 247 | fail_map_attr: | ||
| 248 | pci_iounmap(pdev, bridge_io); | ||
| 249 | |||
| 250 | fail_map_bridge: | ||
| 240 | pci_release_regions(pdev); | 251 | pci_release_regions(pdev); |
| 241 | 252 | ||
| 242 | fail_resources: | 253 | fail_resources: |
| @@ -245,26 +256,27 @@ static int nortel_pci_init_one(struct pci_dev *pdev, | |||
| 245 | return err; | 256 | return err; |
| 246 | } | 257 | } |
| 247 | 258 | ||
| 248 | static void __devexit nortel_pci_remove_one(struct pci_dev *pdev) | 259 | static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev) |
| 249 | { | 260 | { |
| 250 | struct net_device *dev = pci_get_drvdata(pdev); | 261 | struct net_device *dev = pci_get_drvdata(pdev); |
| 251 | struct orinoco_private *priv = netdev_priv(dev); | 262 | struct orinoco_private *priv = netdev_priv(dev); |
| 252 | struct nortel_pci_card *card = priv->card; | 263 | struct orinoco_pci_card *card = priv->card; |
| 253 | 264 | ||
| 254 | /* clear leds */ | 265 | /* Clear LEDs */ |
| 255 | outw_p(0, card->iobase1 + 10); | 266 | iowrite16(0, card->bridge_io + 10); |
| 256 | 267 | ||
| 257 | unregister_netdev(dev); | 268 | unregister_netdev(dev); |
| 258 | free_irq(dev->irq, dev); | 269 | free_irq(pdev->irq, dev); |
| 259 | pci_set_drvdata(pdev, NULL); | 270 | pci_set_drvdata(pdev, NULL); |
| 260 | free_orinocodev(dev); | 271 | free_orinocodev(dev); |
| 261 | pci_iounmap(pdev, priv->hw.iobase); | 272 | pci_iounmap(pdev, priv->hw.iobase); |
| 273 | pci_iounmap(pdev, card->attr_io); | ||
| 274 | pci_iounmap(pdev, card->bridge_io); | ||
| 262 | pci_release_regions(pdev); | 275 | pci_release_regions(pdev); |
| 263 | pci_disable_device(pdev); | 276 | pci_disable_device(pdev); |
| 264 | } | 277 | } |
| 265 | 278 | ||
| 266 | 279 | static struct pci_device_id orinoco_nortel_id_table[] = { | |
| 267 | static struct pci_device_id nortel_pci_id_table[] = { | ||
| 268 | /* Nortel emobility PCI */ | 280 | /* Nortel emobility PCI */ |
| 269 | {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,}, | 281 | {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,}, |
| 270 | /* Symbol LA-4123 PCI */ | 282 | /* Symbol LA-4123 PCI */ |
| @@ -272,13 +284,15 @@ static struct pci_device_id nortel_pci_id_table[] = { | |||
| 272 | {0,}, | 284 | {0,}, |
| 273 | }; | 285 | }; |
| 274 | 286 | ||
| 275 | MODULE_DEVICE_TABLE(pci, nortel_pci_id_table); | 287 | MODULE_DEVICE_TABLE(pci, orinoco_nortel_id_table); |
| 276 | 288 | ||
| 277 | static struct pci_driver nortel_pci_driver = { | 289 | static struct pci_driver orinoco_nortel_driver = { |
| 278 | .name = DRIVER_NAME, | 290 | .name = DRIVER_NAME, |
| 279 | .id_table = nortel_pci_id_table, | 291 | .id_table = orinoco_nortel_id_table, |
| 280 | .probe = nortel_pci_init_one, | 292 | .probe = orinoco_nortel_init_one, |
| 281 | .remove = __devexit_p(nortel_pci_remove_one), | 293 | .remove = __devexit_p(orinoco_nortel_remove_one), |
| 294 | .suspend = orinoco_pci_suspend, | ||
| 295 | .resume = orinoco_pci_resume, | ||
| 282 | }; | 296 | }; |
| 283 | 297 | ||
| 284 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION | 298 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION |
| @@ -288,20 +302,19 @@ MODULE_DESCRIPTION | |||
| 288 | ("Driver for wireless LAN cards using the Nortel PCI bridge"); | 302 | ("Driver for wireless LAN cards using the Nortel PCI bridge"); |
| 289 | MODULE_LICENSE("Dual MPL/GPL"); | 303 | MODULE_LICENSE("Dual MPL/GPL"); |
| 290 | 304 | ||
| 291 | static int __init nortel_pci_init(void) | 305 | static int __init orinoco_nortel_init(void) |
| 292 | { | 306 | { |
| 293 | printk(KERN_DEBUG "%s\n", version); | 307 | printk(KERN_DEBUG "%s\n", version); |
| 294 | return pci_module_init(&nortel_pci_driver); | 308 | return pci_module_init(&orinoco_nortel_driver); |
| 295 | } | 309 | } |
| 296 | 310 | ||
| 297 | static void __exit nortel_pci_exit(void) | 311 | static void __exit orinoco_nortel_exit(void) |
| 298 | { | 312 | { |
| 299 | pci_unregister_driver(&nortel_pci_driver); | 313 | pci_unregister_driver(&orinoco_nortel_driver); |
| 300 | ssleep(1); | ||
| 301 | } | 314 | } |
| 302 | 315 | ||
| 303 | module_init(nortel_pci_init); | 316 | module_init(orinoco_nortel_init); |
| 304 | module_exit(nortel_pci_exit); | 317 | module_exit(orinoco_nortel_exit); |
| 305 | 318 | ||
| 306 | /* | 319 | /* |
| 307 | * Local variables: | 320 | * Local variables: |
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c index 5362c214fc8e..1c105f40f8d5 100644 --- a/drivers/net/wireless/orinoco_pci.c +++ b/drivers/net/wireless/orinoco_pci.c | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | /* orinoco_pci.c | 1 | /* orinoco_pci.c |
| 2 | * | 2 | * |
| 3 | * Driver for Prism II devices that have a direct PCI interface | 3 | * Driver for Prism 2.5/3 devices that have a direct PCI interface |
| 4 | * (i.e., not in a Pcmcia or PLX bridge) | 4 | * (i.e. these are not PCMCIA cards in a PCMCIA-to-PCI bridge). |
| 5 | * | 5 | * The card contains only one PCI region, which contains all the usual |
| 6 | * Specifically here we're talking about the Linksys WMP11 | 6 | * hermes registers, as well as the COR register. |
| 7 | * | 7 | * |
| 8 | * Current maintainers (as of 29 September 2003) are: | 8 | * Current maintainers are: |
| 9 | * Pavel Roskin <proski AT gnu.org> | 9 | * Pavel Roskin <proski AT gnu.org> |
| 10 | * and David Gibson <hermes AT gibson.dropbear.id.au> | 10 | * and David Gibson <hermes AT gibson.dropbear.id.au> |
| 11 | * | 11 | * |
| @@ -41,54 +41,6 @@ | |||
| 41 | * under either the MPL or the GPL. | 41 | * under either the MPL or the GPL. |
| 42 | */ | 42 | */ |
| 43 | 43 | ||
| 44 | /* | ||
| 45 | * Theory of operation... | ||
| 46 | * ------------------- | ||
| 47 | * Maybe you had a look in orinoco_plx. Well, this is totally different... | ||
| 48 | * | ||
| 49 | * The card contains only one PCI region, which contains all the usual | ||
| 50 | * hermes registers. | ||
| 51 | * | ||
| 52 | * The driver will memory map this region in normal memory. Because | ||
| 53 | * the hermes registers are mapped in normal memory and not in ISA I/O | ||
| 54 | * post space, we can't use the usual inw/outw macros and we need to | ||
| 55 | * use readw/writew. | ||
| 56 | * This slight difference force us to compile our own version of | ||
| 57 | * hermes.c with the register access macro changed. That's a bit | ||
| 58 | * hackish but works fine. | ||
| 59 | * | ||
| 60 | * Note that the PCI region is pretty big (4K). That's much more than | ||
| 61 | * the usual set of hermes register (0x0 -> 0x3E). I've got a strong | ||
| 62 | * suspicion that the whole memory space of the adapter is in fact in | ||
| 63 | * this region. Accessing directly the adapter memory instead of going | ||
| 64 | * through the usual register would speed up significantely the | ||
| 65 | * operations... | ||
| 66 | * | ||
| 67 | * Finally, the card looks like this : | ||
| 68 | ----------------------- | ||
| 69 | Bus 0, device 14, function 0: | ||
| 70 | Network controller: PCI device 1260:3873 (Harris Semiconductor) (rev 1). | ||
| 71 | IRQ 11. | ||
| 72 | Master Capable. Latency=248. | ||
| 73 | Prefetchable 32 bit memory at 0xffbcc000 [0xffbccfff]. | ||
| 74 | ----------------------- | ||
| 75 | 00:0e.0 Network controller: Harris Semiconductor: Unknown device 3873 (rev 01) | ||
| 76 | Subsystem: Unknown device 1737:3874 | ||
| 77 | Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- | ||
| 78 | Status: Cap+ 66Mhz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- | ||
| 79 | Latency: 248 set, cache line size 08 | ||
| 80 | Interrupt: pin A routed to IRQ 11 | ||
| 81 | Region 0: Memory at ffbcc000 (32-bit, prefetchable) [size=4K] | ||
| 82 | Capabilities: [dc] Power Management version 2 | ||
| 83 | Flags: PMEClk- AuxPwr- DSI- D1+ D2+ PME+ | ||
| 84 | Status: D0 PME-Enable- DSel=0 DScale=0 PME- | ||
| 85 | ----------------------- | ||
| 86 | * | ||
| 87 | * That's all.. | ||
| 88 | * | ||
| 89 | * Jean II | ||
| 90 | */ | ||
| 91 | |||
| 92 | #define DRIVER_NAME "orinoco_pci" | 44 | #define DRIVER_NAME "orinoco_pci" |
| 93 | #define PFX DRIVER_NAME ": " | 45 | #define PFX DRIVER_NAME ": " |
| 94 | 46 | ||
| @@ -100,12 +52,14 @@ | |||
| 100 | #include <linux/pci.h> | 52 | #include <linux/pci.h> |
| 101 | 53 | ||
| 102 | #include "orinoco.h" | 54 | #include "orinoco.h" |
| 55 | #include "orinoco_pci.h" | ||
| 103 | 56 | ||
| 104 | /* All the magic there is from wlan-ng */ | 57 | /* Offset of the COR register of the PCI card */ |
| 105 | /* Magic offset of the reset register of the PCI card */ | ||
| 106 | #define HERMES_PCI_COR (0x26) | 58 | #define HERMES_PCI_COR (0x26) |
| 107 | /* Magic bitmask to reset the card */ | 59 | |
| 60 | /* Bitmask to reset the card */ | ||
| 108 | #define HERMES_PCI_COR_MASK (0x0080) | 61 | #define HERMES_PCI_COR_MASK (0x0080) |
| 62 | |||
| 109 | /* Magic timeouts for doing the reset. | 63 | /* Magic timeouts for doing the reset. |
| 110 | * Those times are straight from wlan-ng, and it is claimed that they | 64 | * Those times are straight from wlan-ng, and it is claimed that they |
| 111 | * are necessary. Alan will kill me. Take your time and grab a coffee. */ | 65 | * are necessary. Alan will kill me. Take your time and grab a coffee. */ |
| @@ -113,13 +67,8 @@ | |||
| 113 | #define HERMES_PCI_COR_OFFT (500) /* ms */ | 67 | #define HERMES_PCI_COR_OFFT (500) /* ms */ |
| 114 | #define HERMES_PCI_COR_BUSYT (500) /* ms */ | 68 | #define HERMES_PCI_COR_BUSYT (500) /* ms */ |
| 115 | 69 | ||
| 116 | /* Orinoco PCI specific data */ | ||
| 117 | struct orinoco_pci_card { | ||
| 118 | void __iomem *pci_ioaddr; | ||
| 119 | }; | ||
| 120 | |||
| 121 | /* | 70 | /* |
| 122 | * Do a soft reset of the PCI card using the Configuration Option Register | 71 | * Do a soft reset of the card using the Configuration Option Register |
| 123 | * We need this to get going... | 72 | * We need this to get going... |
| 124 | * This is the part of the code that is strongly inspired from wlan-ng | 73 | * This is the part of the code that is strongly inspired from wlan-ng |
| 125 | * | 74 | * |
| @@ -131,14 +80,13 @@ struct orinoco_pci_card { | |||
| 131 | * Note bis : Don't try to access HERMES_CMD during the reset phase. | 80 | * Note bis : Don't try to access HERMES_CMD during the reset phase. |
| 132 | * It just won't work ! | 81 | * It just won't work ! |
| 133 | */ | 82 | */ |
| 134 | static int | 83 | static int orinoco_pci_cor_reset(struct orinoco_private *priv) |
| 135 | orinoco_pci_cor_reset(struct orinoco_private *priv) | ||
| 136 | { | 84 | { |
| 137 | hermes_t *hw = &priv->hw; | 85 | hermes_t *hw = &priv->hw; |
| 138 | unsigned long timeout; | 86 | unsigned long timeout; |
| 139 | u16 reg; | 87 | u16 reg; |
| 140 | 88 | ||
| 141 | /* Assert the reset until the card notice */ | 89 | /* Assert the reset until the card notices */ |
| 142 | hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK); | 90 | hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK); |
| 143 | mdelay(HERMES_PCI_COR_ONT); | 91 | mdelay(HERMES_PCI_COR_ONT); |
| 144 | 92 | ||
| @@ -163,19 +111,14 @@ orinoco_pci_cor_reset(struct orinoco_private *priv) | |||
| 163 | return 0; | 111 | return 0; |
| 164 | } | 112 | } |
| 165 | 113 | ||
| 166 | /* | ||
| 167 | * Initialise a card. Mostly similar to PLX code. | ||
| 168 | */ | ||
| 169 | static int orinoco_pci_init_one(struct pci_dev *pdev, | 114 | static int orinoco_pci_init_one(struct pci_dev *pdev, |
| 170 | const struct pci_device_id *ent) | 115 | const struct pci_device_id *ent) |
| 171 | { | 116 | { |
| 172 | int err = 0; | 117 | int err; |
| 173 | unsigned long pci_iorange; | 118 | struct orinoco_private *priv; |
| 174 | u16 __iomem *pci_ioaddr = NULL; | ||
| 175 | unsigned long pci_iolen; | ||
| 176 | struct orinoco_private *priv = NULL; | ||
| 177 | struct orinoco_pci_card *card; | 119 | struct orinoco_pci_card *card; |
| 178 | struct net_device *dev = NULL; | 120 | struct net_device *dev; |
| 121 | void __iomem *hermes_io; | ||
| 179 | 122 | ||
| 180 | err = pci_enable_device(pdev); | 123 | err = pci_enable_device(pdev); |
| 181 | if (err) { | 124 | if (err) { |
| @@ -184,39 +127,32 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, | |||
| 184 | } | 127 | } |
| 185 | 128 | ||
| 186 | err = pci_request_regions(pdev, DRIVER_NAME); | 129 | err = pci_request_regions(pdev, DRIVER_NAME); |
| 187 | if (err != 0) { | 130 | if (err) { |
| 188 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); | 131 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); |
| 189 | goto fail_resources; | 132 | goto fail_resources; |
| 190 | } | 133 | } |
| 191 | 134 | ||
| 192 | /* Resource 0 is mapped to the hermes registers */ | 135 | hermes_io = pci_iomap(pdev, 0, 0); |
| 193 | pci_iorange = pci_resource_start(pdev, 0); | 136 | if (!hermes_io) { |
| 194 | pci_iolen = pci_resource_len(pdev, 0); | 137 | printk(KERN_ERR PFX "Cannot remap chipset registers\n"); |
| 195 | pci_ioaddr = ioremap(pci_iorange, pci_iolen); | 138 | err = -EIO; |
| 196 | if (!pci_iorange) { | 139 | goto fail_map_hermes; |
| 197 | printk(KERN_ERR PFX "Cannot remap hardware registers\n"); | ||
| 198 | goto fail_map; | ||
| 199 | } | 140 | } |
| 200 | 141 | ||
| 201 | /* Allocate network device */ | 142 | /* Allocate network device */ |
| 202 | dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset); | 143 | dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset); |
| 203 | if (! dev) { | 144 | if (!dev) { |
| 145 | printk(KERN_ERR PFX "Cannot allocate network device\n"); | ||
| 204 | err = -ENOMEM; | 146 | err = -ENOMEM; |
| 205 | goto fail_alloc; | 147 | goto fail_alloc; |
| 206 | } | 148 | } |
| 207 | 149 | ||
| 208 | priv = netdev_priv(dev); | 150 | priv = netdev_priv(dev); |
| 209 | card = priv->card; | 151 | card = priv->card; |
| 210 | card->pci_ioaddr = pci_ioaddr; | ||
| 211 | dev->mem_start = pci_iorange; | ||
| 212 | dev->mem_end = pci_iorange + pci_iolen - 1; | ||
| 213 | SET_MODULE_OWNER(dev); | 152 | SET_MODULE_OWNER(dev); |
| 214 | SET_NETDEV_DEV(dev, &pdev->dev); | 153 | SET_NETDEV_DEV(dev, &pdev->dev); |
| 215 | 154 | ||
| 216 | hermes_struct_init(&priv->hw, pci_ioaddr, HERMES_32BIT_REGSPACING); | 155 | hermes_struct_init(&priv->hw, hermes_io, HERMES_32BIT_REGSPACING); |
| 217 | |||
| 218 | printk(KERN_DEBUG PFX "Detected device %s, mem:0x%lx-0x%lx, irq %d\n", | ||
| 219 | pci_name(pdev), dev->mem_start, dev->mem_end, pdev->irq); | ||
| 220 | 156 | ||
| 221 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, | 157 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, |
| 222 | dev->name, dev); | 158 | dev->name, dev); |
| @@ -225,9 +161,7 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, | |||
| 225 | err = -EBUSY; | 161 | err = -EBUSY; |
| 226 | goto fail_irq; | 162 | goto fail_irq; |
| 227 | } | 163 | } |
| 228 | dev->irq = pdev->irq; | ||
| 229 | 164 | ||
| 230 | /* Perform a COR reset to start the card */ | ||
| 231 | err = orinoco_pci_cor_reset(priv); | 165 | err = orinoco_pci_cor_reset(priv); |
| 232 | if (err) { | 166 | if (err) { |
| 233 | printk(KERN_ERR PFX "Initial reset failed\n"); | 167 | printk(KERN_ERR PFX "Initial reset failed\n"); |
| @@ -236,11 +170,13 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, | |||
| 236 | 170 | ||
| 237 | err = register_netdev(dev); | 171 | err = register_netdev(dev); |
| 238 | if (err) { | 172 | if (err) { |
| 239 | printk(KERN_ERR PFX "Failed to register net device\n"); | 173 | printk(KERN_ERR PFX "Cannot register network device\n"); |
| 240 | goto fail; | 174 | goto fail; |
| 241 | } | 175 | } |
| 242 | 176 | ||
| 243 | pci_set_drvdata(pdev, dev); | 177 | pci_set_drvdata(pdev, dev); |
| 178 | printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name, | ||
| 179 | pci_name(pdev)); | ||
| 244 | 180 | ||
| 245 | return 0; | 181 | return 0; |
| 246 | 182 | ||
| @@ -252,9 +188,9 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, | |||
| 252 | free_orinocodev(dev); | 188 | free_orinocodev(dev); |
| 253 | 189 | ||
| 254 | fail_alloc: | 190 | fail_alloc: |
| 255 | iounmap(pci_ioaddr); | 191 | pci_iounmap(pdev, hermes_io); |
| 256 | 192 | ||
| 257 | fail_map: | 193 | fail_map_hermes: |
| 258 | pci_release_regions(pdev); | 194 | pci_release_regions(pdev); |
| 259 | 195 | ||
| 260 | fail_resources: | 196 | fail_resources: |
| @@ -267,87 +203,17 @@ static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev) | |||
| 267 | { | 203 | { |
| 268 | struct net_device *dev = pci_get_drvdata(pdev); | 204 | struct net_device *dev = pci_get_drvdata(pdev); |
| 269 | struct orinoco_private *priv = netdev_priv(dev); | 205 | struct orinoco_private *priv = netdev_priv(dev); |
| 270 | struct orinoco_pci_card *card = priv->card; | ||
| 271 | 206 | ||
| 272 | unregister_netdev(dev); | 207 | unregister_netdev(dev); |
| 273 | free_irq(dev->irq, dev); | 208 | free_irq(pdev->irq, dev); |
| 274 | pci_set_drvdata(pdev, NULL); | 209 | pci_set_drvdata(pdev, NULL); |
| 275 | free_orinocodev(dev); | 210 | free_orinocodev(dev); |
| 276 | iounmap(card->pci_ioaddr); | 211 | pci_iounmap(pdev, priv->hw.iobase); |
| 277 | pci_release_regions(pdev); | 212 | pci_release_regions(pdev); |
| 278 | pci_disable_device(pdev); | 213 | pci_disable_device(pdev); |
| 279 | } | 214 | } |
| 280 | 215 | ||
| 281 | static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state) | 216 | static struct pci_device_id orinoco_pci_id_table[] = { |
| 282 | { | ||
| 283 | struct net_device *dev = pci_get_drvdata(pdev); | ||
| 284 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 285 | unsigned long flags; | ||
| 286 | int err; | ||
| 287 | |||
| 288 | |||
| 289 | err = orinoco_lock(priv, &flags); | ||
| 290 | if (err) { | ||
| 291 | printk(KERN_ERR "%s: hw_unavailable on orinoco_pci_suspend\n", | ||
| 292 | dev->name); | ||
| 293 | return err; | ||
| 294 | } | ||
| 295 | |||
| 296 | err = __orinoco_down(dev); | ||
| 297 | if (err) | ||
| 298 | printk(KERN_WARNING "%s: orinoco_pci_suspend(): Error %d downing interface\n", | ||
| 299 | dev->name, err); | ||
| 300 | |||
| 301 | netif_device_detach(dev); | ||
| 302 | |||
| 303 | priv->hw_unavailable++; | ||
| 304 | |||
| 305 | orinoco_unlock(priv, &flags); | ||
| 306 | |||
| 307 | pci_save_state(pdev); | ||
| 308 | pci_set_power_state(pdev, PCI_D3hot); | ||
| 309 | |||
| 310 | return 0; | ||
| 311 | } | ||
| 312 | |||
| 313 | static int orinoco_pci_resume(struct pci_dev *pdev) | ||
| 314 | { | ||
| 315 | struct net_device *dev = pci_get_drvdata(pdev); | ||
| 316 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 317 | unsigned long flags; | ||
| 318 | int err; | ||
| 319 | |||
| 320 | printk(KERN_DEBUG "%s: Orinoco-PCI waking up\n", dev->name); | ||
| 321 | |||
| 322 | pci_set_power_state(pdev, 0); | ||
| 323 | pci_restore_state(pdev); | ||
| 324 | |||
| 325 | err = orinoco_reinit_firmware(dev); | ||
| 326 | if (err) { | ||
| 327 | printk(KERN_ERR "%s: Error %d re-initializing firmware on orinoco_pci_resume()\n", | ||
| 328 | dev->name, err); | ||
| 329 | return err; | ||
| 330 | } | ||
| 331 | |||
| 332 | spin_lock_irqsave(&priv->lock, flags); | ||
| 333 | |||
| 334 | netif_device_attach(dev); | ||
| 335 | |||
| 336 | priv->hw_unavailable--; | ||
| 337 | |||
| 338 | if (priv->open && (! priv->hw_unavailable)) { | ||
| 339 | err = __orinoco_up(dev); | ||
| 340 | if (err) | ||
| 341 | printk(KERN_ERR "%s: Error %d restarting card on orinoco_pci_resume()\n", | ||
| 342 | dev->name, err); | ||
| 343 | } | ||
| 344 | |||
| 345 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 346 | |||
| 347 | return 0; | ||
| 348 | } | ||
| 349 | |||
| 350 | static struct pci_device_id orinoco_pci_pci_id_table[] = { | ||
| 351 | /* Intersil Prism 3 */ | 217 | /* Intersil Prism 3 */ |
| 352 | {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,}, | 218 | {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,}, |
| 353 | /* Intersil Prism 2.5 */ | 219 | /* Intersil Prism 2.5 */ |
| @@ -357,11 +223,11 @@ static struct pci_device_id orinoco_pci_pci_id_table[] = { | |||
| 357 | {0,}, | 223 | {0,}, |
| 358 | }; | 224 | }; |
| 359 | 225 | ||
| 360 | MODULE_DEVICE_TABLE(pci, orinoco_pci_pci_id_table); | 226 | MODULE_DEVICE_TABLE(pci, orinoco_pci_id_table); |
| 361 | 227 | ||
| 362 | static struct pci_driver orinoco_pci_driver = { | 228 | static struct pci_driver orinoco_pci_driver = { |
| 363 | .name = DRIVER_NAME, | 229 | .name = DRIVER_NAME, |
| 364 | .id_table = orinoco_pci_pci_id_table, | 230 | .id_table = orinoco_pci_id_table, |
| 365 | .probe = orinoco_pci_init_one, | 231 | .probe = orinoco_pci_init_one, |
| 366 | .remove = __devexit_p(orinoco_pci_remove_one), | 232 | .remove = __devexit_p(orinoco_pci_remove_one), |
| 367 | .suspend = orinoco_pci_suspend, | 233 | .suspend = orinoco_pci_suspend, |
diff --git a/drivers/net/wireless/orinoco_pci.h b/drivers/net/wireless/orinoco_pci.h new file mode 100644 index 000000000000..7eb1e08113e0 --- /dev/null +++ b/drivers/net/wireless/orinoco_pci.h | |||
| @@ -0,0 +1,104 @@ | |||
| 1 | /* orinoco_pci.h | ||
| 2 | * | ||
| 3 | * Common code for all Orinoco drivers for PCI devices, including | ||
| 4 | * both native PCI and PCMCIA-to-PCI bridges. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2005, Pavel Roskin. | ||
| 7 | * See orinoco.c for license. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #ifndef _ORINOCO_PCI_H | ||
| 11 | #define _ORINOCO_PCI_H | ||
| 12 | |||
| 13 | #include <linux/netdevice.h> | ||
| 14 | |||
| 15 | /* Driver specific data */ | ||
| 16 | struct orinoco_pci_card { | ||
| 17 | void __iomem *bridge_io; | ||
| 18 | void __iomem *attr_io; | ||
| 19 | }; | ||
| 20 | |||
| 21 | #ifdef CONFIG_PM | ||
| 22 | static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
| 23 | { | ||
| 24 | struct net_device *dev = pci_get_drvdata(pdev); | ||
| 25 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 26 | unsigned long flags; | ||
| 27 | int err; | ||
| 28 | |||
| 29 | err = orinoco_lock(priv, &flags); | ||
| 30 | if (err) { | ||
| 31 | printk(KERN_ERR "%s: cannot lock hardware for suspend\n", | ||
| 32 | dev->name); | ||
| 33 | return err; | ||
| 34 | } | ||
| 35 | |||
| 36 | err = __orinoco_down(dev); | ||
| 37 | if (err) | ||
| 38 | printk(KERN_WARNING "%s: error %d bringing interface down " | ||
| 39 | "for suspend\n", dev->name, err); | ||
| 40 | |||
| 41 | netif_device_detach(dev); | ||
| 42 | |||
| 43 | priv->hw_unavailable++; | ||
| 44 | |||
| 45 | orinoco_unlock(priv, &flags); | ||
| 46 | |||
| 47 | free_irq(pdev->irq, dev); | ||
| 48 | pci_save_state(pdev); | ||
| 49 | pci_disable_device(pdev); | ||
| 50 | pci_set_power_state(pdev, PCI_D3hot); | ||
| 51 | |||
| 52 | return 0; | ||
| 53 | } | ||
| 54 | |||
| 55 | static int orinoco_pci_resume(struct pci_dev *pdev) | ||
| 56 | { | ||
| 57 | struct net_device *dev = pci_get_drvdata(pdev); | ||
| 58 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 59 | unsigned long flags; | ||
| 60 | int err; | ||
| 61 | |||
| 62 | pci_set_power_state(pdev, 0); | ||
| 63 | pci_enable_device(pdev); | ||
| 64 | pci_restore_state(pdev); | ||
| 65 | |||
| 66 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, | ||
| 67 | dev->name, dev); | ||
| 68 | if (err) { | ||
| 69 | printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n", | ||
| 70 | dev->name); | ||
| 71 | pci_disable_device(pdev); | ||
| 72 | return -EBUSY; | ||
| 73 | } | ||
| 74 | |||
| 75 | err = orinoco_reinit_firmware(dev); | ||
| 76 | if (err) { | ||
| 77 | printk(KERN_ERR "%s: error %d re-initializing firmware " | ||
| 78 | "on resume\n", dev->name, err); | ||
| 79 | return err; | ||
| 80 | } | ||
| 81 | |||
| 82 | spin_lock_irqsave(&priv->lock, flags); | ||
| 83 | |||
| 84 | netif_device_attach(dev); | ||
| 85 | |||
| 86 | priv->hw_unavailable--; | ||
| 87 | |||
| 88 | if (priv->open && (! priv->hw_unavailable)) { | ||
| 89 | err = __orinoco_up(dev); | ||
| 90 | if (err) | ||
| 91 | printk(KERN_ERR "%s: Error %d restarting card on resume\n", | ||
| 92 | dev->name, err); | ||
| 93 | } | ||
| 94 | |||
| 95 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 96 | |||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | #else | ||
| 100 | #define orinoco_pci_suspend NULL | ||
| 101 | #define orinoco_pci_resume NULL | ||
| 102 | #endif | ||
| 103 | |||
| 104 | #endif /* _ORINOCO_PCI_H */ | ||
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c index 210e73776545..84f696c77551 100644 --- a/drivers/net/wireless/orinoco_plx.c +++ b/drivers/net/wireless/orinoco_plx.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * Driver for Prism II devices which would usually be driven by orinoco_cs, | 3 | * Driver for Prism II devices which would usually be driven by orinoco_cs, |
| 4 | * but are connected to the PCI bus by a PLX9052. | 4 | * but are connected to the PCI bus by a PLX9052. |
| 5 | * | 5 | * |
| 6 | * Current maintainers (as of 29 September 2003) are: | 6 | * Current maintainers are: |
| 7 | * Pavel Roskin <proski AT gnu.org> | 7 | * Pavel Roskin <proski AT gnu.org> |
| 8 | * and David Gibson <hermes AT gibson.dropbear.id.au> | 8 | * and David Gibson <hermes AT gibson.dropbear.id.au> |
| 9 | * | 9 | * |
| @@ -30,38 +30,18 @@ | |||
| 30 | * other provisions required by the GPL. If you do not delete the | 30 | * other provisions required by the GPL. If you do not delete the |
| 31 | * provisions above, a recipient may use your version of this file | 31 | * provisions above, a recipient may use your version of this file |
| 32 | * under either the MPL or the GPL. | 32 | * under either the MPL or the GPL. |
| 33 | |||
| 34 | * Caution: this is experimental and probably buggy. For success and | ||
| 35 | * failure reports for different cards and adaptors, see | ||
| 36 | * orinoco_plx_pci_id_table near the end of the file. If you have a | ||
| 37 | * card we don't have the PCI id for, and looks like it should work, | ||
| 38 | * drop me mail with the id and "it works"/"it doesn't work". | ||
| 39 | * | ||
| 40 | * Note: if everything gets detected fine but it doesn't actually send | ||
| 41 | * or receive packets, your first port of call should probably be to | ||
| 42 | * try newer firmware in the card. Especially if you're doing Ad-Hoc | ||
| 43 | * modes. | ||
| 44 | * | ||
| 45 | * The actual driving is done by orinoco.c, this is just resource | ||
| 46 | * allocation stuff. The explanation below is courtesy of Ryan Niemi | ||
| 47 | * on the linux-wlan-ng list at | ||
| 48 | * http://archives.neohapsis.com/archives/dev/linux-wlan/2001-q1/0026.html | ||
| 49 | * | 33 | * |
| 50 | * The PLX9052-based cards (WL11000 and several others) are a | 34 | * Here's the general details on how the PLX9052 adapter works: |
| 51 | * different beast than the usual PCMCIA-based PRISM2 configuration | ||
| 52 | * expected by wlan-ng. Here's the general details on how the WL11000 | ||
| 53 | * PCI adapter works: | ||
| 54 | * | 35 | * |
| 55 | * - Two PCI I/O address spaces, one 0x80 long which contains the | 36 | * - Two PCI I/O address spaces, one 0x80 long which contains the |
| 56 | * PLX9052 registers, and one that's 0x40 long mapped to the PCMCIA | 37 | * PLX9052 registers, and one that's 0x40 long mapped to the PCMCIA |
| 57 | * slot I/O address space. | 38 | * slot I/O address space. |
| 58 | * | 39 | * |
| 59 | * - One PCI memory address space, mapped to the PCMCIA memory space | 40 | * - One PCI memory address space, mapped to the PCMCIA attribute space |
| 60 | * (containing the CIS). | 41 | * (containing the CIS). |
| 61 | * | 42 | * |
| 62 | * After identifying the I/O and memory space, you can read through | 43 | * Using the later, you can read through the CIS data to make sure the |
| 63 | * the memory space to confirm the CIS's device ID or manufacturer ID | 44 | * card is compatible with the driver. Keep in mind that the PCMCIA |
| 64 | * to make sure it's the expected card. qKeep in mind that the PCMCIA | ||
| 65 | * spec specifies the CIS as the lower 8 bits of each word read from | 45 | * spec specifies the CIS as the lower 8 bits of each word read from |
| 66 | * the CIS, so to read the bytes of the CIS, read every other byte | 46 | * the CIS, so to read the bytes of the CIS, read every other byte |
| 67 | * (0,2,4,...). Passing that test, you need to enable the I/O address | 47 | * (0,2,4,...). Passing that test, you need to enable the I/O address |
| @@ -71,7 +51,7 @@ | |||
| 71 | * within the PCI memory space. Write 0x41 to the COR register to | 51 | * within the PCI memory space. Write 0x41 to the COR register to |
| 72 | * enable I/O mode and to select level triggered interrupts. To | 52 | * enable I/O mode and to select level triggered interrupts. To |
| 73 | * confirm you actually succeeded, read the COR register back and make | 53 | * confirm you actually succeeded, read the COR register back and make |
| 74 | * sure it actually got set to 0x41, incase you have an unexpected | 54 | * sure it actually got set to 0x41, in case you have an unexpected |
| 75 | * card inserted. | 55 | * card inserted. |
| 76 | * | 56 | * |
| 77 | * Following that, you can treat the second PCI I/O address space (the | 57 | * Following that, you can treat the second PCI I/O address space (the |
| @@ -101,16 +81,6 @@ | |||
| 101 | * that, I've hot-swapped a number of times during debugging and | 81 | * that, I've hot-swapped a number of times during debugging and |
| 102 | * driver development for various reasons (stuck WAIT# line after the | 82 | * driver development for various reasons (stuck WAIT# line after the |
| 103 | * radio card's firmware locks up). | 83 | * radio card's firmware locks up). |
| 104 | * | ||
| 105 | * Hope this is enough info for someone to add PLX9052 support to the | ||
| 106 | * wlan-ng card. In the case of the WL11000, the PCI ID's are | ||
| 107 | * 0x1639/0x0200, with matching subsystem ID's. Other PLX9052-based | ||
| 108 | * manufacturers other than Eumitcom (or on cards other than the | ||
| 109 | * WL11000) may have different PCI ID's. | ||
| 110 | * | ||
| 111 | * If anyone needs any more specific info, let me know. I haven't had | ||
| 112 | * time to implement support myself yet, and with the way things are | ||
| 113 | * going, might not have time for a while.. | ||
| 114 | */ | 84 | */ |
| 115 | 85 | ||
| 116 | #define DRIVER_NAME "orinoco_plx" | 86 | #define DRIVER_NAME "orinoco_plx" |
| @@ -125,6 +95,7 @@ | |||
| 125 | #include <pcmcia/cisreg.h> | 95 | #include <pcmcia/cisreg.h> |
| 126 | 96 | ||
| 127 | #include "orinoco.h" | 97 | #include "orinoco.h" |
| 98 | #include "orinoco_pci.h" | ||
| 128 | 99 | ||
| 129 | #define COR_OFFSET (0x3e0) /* COR attribute offset of Prism2 PC card */ | 100 | #define COR_OFFSET (0x3e0) /* COR attribute offset of Prism2 PC card */ |
| 130 | #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ | 101 | #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ |
| @@ -134,30 +105,20 @@ | |||
| 134 | #define PLX_INTCSR 0x4c /* Interrupt Control & Status Register */ | 105 | #define PLX_INTCSR 0x4c /* Interrupt Control & Status Register */ |
| 135 | #define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */ | 106 | #define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */ |
| 136 | 107 | ||
| 137 | static const u8 cis_magic[] = { | ||
| 138 | 0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67 | ||
| 139 | }; | ||
| 140 | |||
| 141 | /* Orinoco PLX specific data */ | ||
| 142 | struct orinoco_plx_card { | ||
| 143 | void __iomem *attr_mem; | ||
| 144 | }; | ||
| 145 | |||
| 146 | /* | 108 | /* |
| 147 | * Do a soft reset of the card using the Configuration Option Register | 109 | * Do a soft reset of the card using the Configuration Option Register |
| 148 | */ | 110 | */ |
| 149 | static int orinoco_plx_cor_reset(struct orinoco_private *priv) | 111 | static int orinoco_plx_cor_reset(struct orinoco_private *priv) |
| 150 | { | 112 | { |
| 151 | hermes_t *hw = &priv->hw; | 113 | hermes_t *hw = &priv->hw; |
| 152 | struct orinoco_plx_card *card = priv->card; | 114 | struct orinoco_pci_card *card = priv->card; |
| 153 | u8 __iomem *attr_mem = card->attr_mem; | ||
| 154 | unsigned long timeout; | 115 | unsigned long timeout; |
| 155 | u16 reg; | 116 | u16 reg; |
| 156 | 117 | ||
| 157 | writeb(COR_VALUE | COR_RESET, attr_mem + COR_OFFSET); | 118 | iowrite8(COR_VALUE | COR_RESET, card->attr_io + COR_OFFSET); |
| 158 | mdelay(1); | 119 | mdelay(1); |
| 159 | 120 | ||
| 160 | writeb(COR_VALUE, attr_mem + COR_OFFSET); | 121 | iowrite8(COR_VALUE, card->attr_io + COR_OFFSET); |
| 161 | mdelay(1); | 122 | mdelay(1); |
| 162 | 123 | ||
| 163 | /* Just in case, wait more until the card is no longer busy */ | 124 | /* Just in case, wait more until the card is no longer busy */ |
| @@ -168,7 +129,7 @@ static int orinoco_plx_cor_reset(struct orinoco_private *priv) | |||
| 168 | reg = hermes_read_regn(hw, CMD); | 129 | reg = hermes_read_regn(hw, CMD); |
| 169 | } | 130 | } |
| 170 | 131 | ||
| 171 | /* Did we timeout ? */ | 132 | /* Still busy? */ |
| 172 | if (reg & HERMES_CMD_BUSY) { | 133 | if (reg & HERMES_CMD_BUSY) { |
| 173 | printk(KERN_ERR PFX "Busy timeout\n"); | 134 | printk(KERN_ERR PFX "Busy timeout\n"); |
| 174 | return -ETIMEDOUT; | 135 | return -ETIMEDOUT; |
| @@ -177,20 +138,55 @@ static int orinoco_plx_cor_reset(struct orinoco_private *priv) | |||
| 177 | return 0; | 138 | return 0; |
| 178 | } | 139 | } |
| 179 | 140 | ||
| 141 | static int orinoco_plx_hw_init(struct orinoco_pci_card *card) | ||
| 142 | { | ||
| 143 | int i; | ||
| 144 | u32 csr_reg; | ||
| 145 | static const u8 cis_magic[] = { | ||
| 146 | 0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67 | ||
| 147 | }; | ||
| 148 | |||
| 149 | printk(KERN_DEBUG PFX "CIS: "); | ||
| 150 | for (i = 0; i < 16; i++) { | ||
| 151 | printk("%02X:", ioread8(card->attr_io + (i << 1))); | ||
| 152 | } | ||
| 153 | printk("\n"); | ||
| 154 | |||
| 155 | /* Verify whether a supported PC card is present */ | ||
| 156 | /* FIXME: we probably need to be smarted about this */ | ||
| 157 | for (i = 0; i < sizeof(cis_magic); i++) { | ||
| 158 | if (cis_magic[i] != ioread8(card->attr_io + (i << 1))) { | ||
| 159 | printk(KERN_ERR PFX "The CIS value of Prism2 PC " | ||
| 160 | "card is unexpected\n"); | ||
| 161 | return -ENODEV; | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | /* bjoern: We need to tell the card to enable interrupts, in | ||
| 166 | case the serial eprom didn't do this already. See the | ||
| 167 | PLX9052 data book, p8-1 and 8-24 for reference. */ | ||
| 168 | csr_reg = ioread32(card->bridge_io + PLX_INTCSR); | ||
| 169 | if (!(csr_reg & PLX_INTCSR_INTEN)) { | ||
| 170 | csr_reg |= PLX_INTCSR_INTEN; | ||
| 171 | iowrite32(csr_reg, card->bridge_io + PLX_INTCSR); | ||
| 172 | csr_reg = ioread32(card->bridge_io + PLX_INTCSR); | ||
| 173 | if (!(csr_reg & PLX_INTCSR_INTEN)) { | ||
| 174 | printk(KERN_ERR PFX "Cannot enable interrupts\n"); | ||
| 175 | return -EIO; | ||
| 176 | } | ||
| 177 | } | ||
| 178 | |||
| 179 | return 0; | ||
| 180 | } | ||
| 180 | 181 | ||
| 181 | static int orinoco_plx_init_one(struct pci_dev *pdev, | 182 | static int orinoco_plx_init_one(struct pci_dev *pdev, |
| 182 | const struct pci_device_id *ent) | 183 | const struct pci_device_id *ent) |
| 183 | { | 184 | { |
| 184 | int err = 0; | 185 | int err; |
| 185 | u8 __iomem *attr_mem = NULL; | 186 | struct orinoco_private *priv; |
| 186 | u32 csr_reg, plx_addr; | 187 | struct orinoco_pci_card *card; |
| 187 | struct orinoco_private *priv = NULL; | 188 | struct net_device *dev; |
| 188 | struct orinoco_plx_card *card; | 189 | void __iomem *hermes_io, *attr_io, *bridge_io; |
| 189 | unsigned long pccard_ioaddr = 0; | ||
| 190 | unsigned long pccard_iolen = 0; | ||
| 191 | struct net_device *dev = NULL; | ||
| 192 | void __iomem *mem; | ||
| 193 | int i; | ||
| 194 | 190 | ||
| 195 | err = pci_enable_device(pdev); | 191 | err = pci_enable_device(pdev); |
| 196 | if (err) { | 192 | if (err) { |
| @@ -199,30 +195,30 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, | |||
| 199 | } | 195 | } |
| 200 | 196 | ||
| 201 | err = pci_request_regions(pdev, DRIVER_NAME); | 197 | err = pci_request_regions(pdev, DRIVER_NAME); |
| 202 | if (err != 0) { | 198 | if (err) { |
| 203 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); | 199 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); |
| 204 | goto fail_resources; | 200 | goto fail_resources; |
| 205 | } | 201 | } |
| 206 | 202 | ||
| 207 | /* Resource 1 is mapped to PLX-specific registers */ | 203 | bridge_io = pci_iomap(pdev, 1, 0); |
| 208 | plx_addr = pci_resource_start(pdev, 1); | 204 | if (!bridge_io) { |
| 205 | printk(KERN_ERR PFX "Cannot map bridge registers\n"); | ||
| 206 | err = -EIO; | ||
| 207 | goto fail_map_bridge; | ||
| 208 | } | ||
| 209 | 209 | ||
| 210 | /* Resource 2 is mapped to the PCMCIA attribute memory */ | 210 | attr_io = pci_iomap(pdev, 2, 0); |
| 211 | attr_mem = ioremap(pci_resource_start(pdev, 2), | 211 | if (!attr_io) { |
| 212 | pci_resource_len(pdev, 2)); | 212 | printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n"); |
| 213 | if (!attr_mem) { | 213 | err = -EIO; |
| 214 | printk(KERN_ERR PFX "Cannot remap PCMCIA space\n"); | ||
| 215 | goto fail_map_attr; | 214 | goto fail_map_attr; |
| 216 | } | 215 | } |
| 217 | 216 | ||
| 218 | /* Resource 3 is mapped to the PCMCIA I/O address space */ | 217 | hermes_io = pci_iomap(pdev, 3, 0); |
| 219 | pccard_ioaddr = pci_resource_start(pdev, 3); | 218 | if (!hermes_io) { |
| 220 | pccard_iolen = pci_resource_len(pdev, 3); | 219 | printk(KERN_ERR PFX "Cannot map chipset registers\n"); |
| 221 | 220 | err = -EIO; | |
| 222 | mem = pci_iomap(pdev, 3, 0); | 221 | goto fail_map_hermes; |
| 223 | if (!mem) { | ||
| 224 | err = -ENOMEM; | ||
| 225 | goto fail_map_io; | ||
| 226 | } | 222 | } |
| 227 | 223 | ||
| 228 | /* Allocate network device */ | 224 | /* Allocate network device */ |
| @@ -235,16 +231,12 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, | |||
| 235 | 231 | ||
| 236 | priv = netdev_priv(dev); | 232 | priv = netdev_priv(dev); |
| 237 | card = priv->card; | 233 | card = priv->card; |
| 238 | card->attr_mem = attr_mem; | 234 | card->bridge_io = bridge_io; |
| 239 | dev->base_addr = pccard_ioaddr; | 235 | card->attr_io = attr_io; |
| 240 | SET_MODULE_OWNER(dev); | 236 | SET_MODULE_OWNER(dev); |
| 241 | SET_NETDEV_DEV(dev, &pdev->dev); | 237 | SET_NETDEV_DEV(dev, &pdev->dev); |
| 242 | 238 | ||
| 243 | hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING); | 239 | hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING); |
| 244 | |||
| 245 | printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 PLX device " | ||
| 246 | "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq, | ||
| 247 | pccard_ioaddr); | ||
| 248 | 240 | ||
| 249 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, | 241 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, |
| 250 | dev->name, dev); | 242 | dev->name, dev); |
| @@ -253,20 +245,11 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, | |||
| 253 | err = -EBUSY; | 245 | err = -EBUSY; |
| 254 | goto fail_irq; | 246 | goto fail_irq; |
| 255 | } | 247 | } |
| 256 | dev->irq = pdev->irq; | ||
| 257 | 248 | ||
| 258 | /* bjoern: We need to tell the card to enable interrupts, in | 249 | err = orinoco_plx_hw_init(card); |
| 259 | case the serial eprom didn't do this already. See the | 250 | if (err) { |
| 260 | PLX9052 data book, p8-1 and 8-24 for reference. */ | 251 | printk(KERN_ERR PFX "Hardware initialization failed\n"); |
| 261 | csr_reg = inl(plx_addr + PLX_INTCSR); | 252 | goto fail; |
| 262 | if (!(csr_reg & PLX_INTCSR_INTEN)) { | ||
| 263 | csr_reg |= PLX_INTCSR_INTEN; | ||
| 264 | outl(csr_reg, plx_addr + PLX_INTCSR); | ||
| 265 | csr_reg = inl(plx_addr + PLX_INTCSR); | ||
| 266 | if (!(csr_reg & PLX_INTCSR_INTEN)) { | ||
| 267 | printk(KERN_ERR PFX "Cannot enable interrupts\n"); | ||
| 268 | goto fail; | ||
| 269 | } | ||
| 270 | } | 253 | } |
| 271 | 254 | ||
| 272 | err = orinoco_plx_cor_reset(priv); | 255 | err = orinoco_plx_cor_reset(priv); |
| @@ -275,23 +258,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, | |||
| 275 | goto fail; | 258 | goto fail; |
| 276 | } | 259 | } |
| 277 | 260 | ||
| 278 | printk(KERN_DEBUG PFX "CIS: "); | ||
| 279 | for (i = 0; i < 16; i++) { | ||
| 280 | printk("%02X:", readb(attr_mem + 2*i)); | ||
| 281 | } | ||
| 282 | printk("\n"); | ||
| 283 | |||
| 284 | /* Verify whether a supported PC card is present */ | ||
| 285 | /* FIXME: we probably need to be smarted about this */ | ||
| 286 | for (i = 0; i < sizeof(cis_magic); i++) { | ||
| 287 | if (cis_magic[i] != readb(attr_mem +2*i)) { | ||
| 288 | printk(KERN_ERR PFX "The CIS value of Prism2 PC " | ||
| 289 | "card is unexpected\n"); | ||
| 290 | err = -EIO; | ||
| 291 | goto fail; | ||
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 295 | err = register_netdev(dev); | 261 | err = register_netdev(dev); |
| 296 | if (err) { | 262 | if (err) { |
| 297 | printk(KERN_ERR PFX "Cannot register network device\n"); | 263 | printk(KERN_ERR PFX "Cannot register network device\n"); |
| @@ -299,6 +265,8 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, | |||
| 299 | } | 265 | } |
| 300 | 266 | ||
| 301 | pci_set_drvdata(pdev, dev); | 267 | pci_set_drvdata(pdev, dev); |
| 268 | printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name, | ||
| 269 | pci_name(pdev)); | ||
| 302 | 270 | ||
| 303 | return 0; | 271 | return 0; |
| 304 | 272 | ||
| @@ -310,12 +278,15 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, | |||
| 310 | free_orinocodev(dev); | 278 | free_orinocodev(dev); |
| 311 | 279 | ||
| 312 | fail_alloc: | 280 | fail_alloc: |
| 313 | pci_iounmap(pdev, mem); | 281 | pci_iounmap(pdev, hermes_io); |
| 314 | 282 | ||
| 315 | fail_map_io: | 283 | fail_map_hermes: |
| 316 | iounmap(attr_mem); | 284 | pci_iounmap(pdev, attr_io); |
| 317 | 285 | ||
| 318 | fail_map_attr: | 286 | fail_map_attr: |
| 287 | pci_iounmap(pdev, bridge_io); | ||
| 288 | |||
| 289 | fail_map_bridge: | ||
| 319 | pci_release_regions(pdev); | 290 | pci_release_regions(pdev); |
| 320 | 291 | ||
| 321 | fail_resources: | 292 | fail_resources: |
| @@ -328,23 +299,20 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev) | |||
| 328 | { | 299 | { |
| 329 | struct net_device *dev = pci_get_drvdata(pdev); | 300 | struct net_device *dev = pci_get_drvdata(pdev); |
| 330 | struct orinoco_private *priv = netdev_priv(dev); | 301 | struct orinoco_private *priv = netdev_priv(dev); |
| 331 | struct orinoco_plx_card *card = priv->card; | 302 | struct orinoco_pci_card *card = priv->card; |
| 332 | u8 __iomem *attr_mem = card->attr_mem; | ||
| 333 | |||
| 334 | BUG_ON(! dev); | ||
| 335 | 303 | ||
| 336 | unregister_netdev(dev); | 304 | unregister_netdev(dev); |
| 337 | free_irq(dev->irq, dev); | 305 | free_irq(pdev->irq, dev); |
| 338 | pci_set_drvdata(pdev, NULL); | 306 | pci_set_drvdata(pdev, NULL); |
| 339 | free_orinocodev(dev); | 307 | free_orinocodev(dev); |
| 340 | pci_iounmap(pdev, priv->hw.iobase); | 308 | pci_iounmap(pdev, priv->hw.iobase); |
| 341 | iounmap(attr_mem); | 309 | pci_iounmap(pdev, card->attr_io); |
| 310 | pci_iounmap(pdev, card->bridge_io); | ||
| 342 | pci_release_regions(pdev); | 311 | pci_release_regions(pdev); |
| 343 | pci_disable_device(pdev); | 312 | pci_disable_device(pdev); |
| 344 | } | 313 | } |
| 345 | 314 | ||
| 346 | 315 | static struct pci_device_id orinoco_plx_id_table[] = { | |
| 347 | static struct pci_device_id orinoco_plx_pci_id_table[] = { | ||
| 348 | {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */ | 316 | {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */ |
| 349 | {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */ | 317 | {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */ |
| 350 | {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */ | 318 | {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */ |
| @@ -362,13 +330,15 @@ static struct pci_device_id orinoco_plx_pci_id_table[] = { | |||
| 362 | {0,}, | 330 | {0,}, |
| 363 | }; | 331 | }; |
| 364 | 332 | ||
| 365 | MODULE_DEVICE_TABLE(pci, orinoco_plx_pci_id_table); | 333 | MODULE_DEVICE_TABLE(pci, orinoco_plx_id_table); |
| 366 | 334 | ||
| 367 | static struct pci_driver orinoco_plx_driver = { | 335 | static struct pci_driver orinoco_plx_driver = { |
| 368 | .name = DRIVER_NAME, | 336 | .name = DRIVER_NAME, |
| 369 | .id_table = orinoco_plx_pci_id_table, | 337 | .id_table = orinoco_plx_id_table, |
| 370 | .probe = orinoco_plx_init_one, | 338 | .probe = orinoco_plx_init_one, |
| 371 | .remove = __devexit_p(orinoco_plx_remove_one), | 339 | .remove = __devexit_p(orinoco_plx_remove_one), |
| 340 | .suspend = orinoco_pci_suspend, | ||
| 341 | .resume = orinoco_pci_resume, | ||
| 372 | }; | 342 | }; |
| 373 | 343 | ||
| 374 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION | 344 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION |
| @@ -388,7 +358,6 @@ static int __init orinoco_plx_init(void) | |||
| 388 | static void __exit orinoco_plx_exit(void) | 358 | static void __exit orinoco_plx_exit(void) |
| 389 | { | 359 | { |
| 390 | pci_unregister_driver(&orinoco_plx_driver); | 360 | pci_unregister_driver(&orinoco_plx_driver); |
| 391 | ssleep(1); | ||
| 392 | } | 361 | } |
| 393 | 362 | ||
| 394 | module_init(orinoco_plx_init); | 363 | module_init(orinoco_plx_init); |
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c index 5e68b7026186..d2b4decb7a7d 100644 --- a/drivers/net/wireless/orinoco_tmd.c +++ b/drivers/net/wireless/orinoco_tmd.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* orinoco_tmd.c | 1 | /* orinoco_tmd.c |
| 2 | * | 2 | * |
| 3 | * Driver for Prism II devices which would usually be driven by orinoco_cs, | 3 | * Driver for Prism II devices which would usually be driven by orinoco_cs, |
| 4 | * but are connected to the PCI bus by a TMD7160. | 4 | * but are connected to the PCI bus by a TMD7160. |
| 5 | * | 5 | * |
| @@ -26,25 +26,13 @@ | |||
| 26 | * other provisions required by the GPL. If you do not delete the | 26 | * other provisions required by the GPL. If you do not delete the |
| 27 | * provisions above, a recipient may use your version of this file | 27 | * provisions above, a recipient may use your version of this file |
| 28 | * under either the MPL or the GPL. | 28 | * under either the MPL or the GPL. |
| 29 | |||
| 30 | * Caution: this is experimental and probably buggy. For success and | ||
| 31 | * failure reports for different cards and adaptors, see | ||
| 32 | * orinoco_tmd_pci_id_table near the end of the file. If you have a | ||
| 33 | * card we don't have the PCI id for, and looks like it should work, | ||
| 34 | * drop me mail with the id and "it works"/"it doesn't work". | ||
| 35 | * | ||
| 36 | * Note: if everything gets detected fine but it doesn't actually send | ||
| 37 | * or receive packets, your first port of call should probably be to | ||
| 38 | * try newer firmware in the card. Especially if you're doing Ad-Hoc | ||
| 39 | * modes | ||
| 40 | * | 29 | * |
| 41 | * The actual driving is done by orinoco.c, this is just resource | 30 | * The actual driving is done by orinoco.c, this is just resource |
| 42 | * allocation stuff. | 31 | * allocation stuff. |
| 43 | * | 32 | * |
| 44 | * This driver is modeled after the orinoco_plx driver. The main | 33 | * This driver is modeled after the orinoco_plx driver. The main |
| 45 | * difference is that the TMD chip has only IO port ranges and no | 34 | * difference is that the TMD chip has only IO port ranges and doesn't |
| 46 | * memory space, i.e. no access to the CIS. Compared to the PLX chip, | 35 | * provide access to the PCMCIA attribute space. |
| 47 | * the io range functionalities are exchanged. | ||
| 48 | * | 36 | * |
| 49 | * Pheecom sells cards with the TMD chip as "ASIC version" | 37 | * Pheecom sells cards with the TMD chip as "ASIC version" |
| 50 | */ | 38 | */ |
| @@ -61,32 +49,26 @@ | |||
| 61 | #include <pcmcia/cisreg.h> | 49 | #include <pcmcia/cisreg.h> |
| 62 | 50 | ||
| 63 | #include "orinoco.h" | 51 | #include "orinoco.h" |
| 52 | #include "orinoco_pci.h" | ||
| 64 | 53 | ||
| 65 | #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ | 54 | #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ |
| 66 | #define COR_RESET (0x80) /* reset bit in the COR register */ | 55 | #define COR_RESET (0x80) /* reset bit in the COR register */ |
| 67 | #define TMD_RESET_TIME (500) /* milliseconds */ | 56 | #define TMD_RESET_TIME (500) /* milliseconds */ |
| 68 | 57 | ||
| 69 | /* Orinoco TMD specific data */ | ||
| 70 | struct orinoco_tmd_card { | ||
| 71 | u32 tmd_io; | ||
| 72 | }; | ||
| 73 | |||
| 74 | |||
| 75 | /* | 58 | /* |
| 76 | * Do a soft reset of the card using the Configuration Option Register | 59 | * Do a soft reset of the card using the Configuration Option Register |
| 77 | */ | 60 | */ |
| 78 | static int orinoco_tmd_cor_reset(struct orinoco_private *priv) | 61 | static int orinoco_tmd_cor_reset(struct orinoco_private *priv) |
| 79 | { | 62 | { |
| 80 | hermes_t *hw = &priv->hw; | 63 | hermes_t *hw = &priv->hw; |
| 81 | struct orinoco_tmd_card *card = priv->card; | 64 | struct orinoco_pci_card *card = priv->card; |
| 82 | u32 addr = card->tmd_io; | ||
| 83 | unsigned long timeout; | 65 | unsigned long timeout; |
| 84 | u16 reg; | 66 | u16 reg; |
| 85 | 67 | ||
| 86 | outb(COR_VALUE | COR_RESET, addr); | 68 | iowrite8(COR_VALUE | COR_RESET, card->bridge_io); |
| 87 | mdelay(1); | 69 | mdelay(1); |
| 88 | 70 | ||
| 89 | outb(COR_VALUE, addr); | 71 | iowrite8(COR_VALUE, card->bridge_io); |
| 90 | mdelay(1); | 72 | mdelay(1); |
| 91 | 73 | ||
| 92 | /* Just in case, wait more until the card is no longer busy */ | 74 | /* Just in case, wait more until the card is no longer busy */ |
| @@ -97,7 +79,7 @@ static int orinoco_tmd_cor_reset(struct orinoco_private *priv) | |||
| 97 | reg = hermes_read_regn(hw, CMD); | 79 | reg = hermes_read_regn(hw, CMD); |
| 98 | } | 80 | } |
| 99 | 81 | ||
| 100 | /* Did we timeout ? */ | 82 | /* Still busy? */ |
| 101 | if (reg & HERMES_CMD_BUSY) { | 83 | if (reg & HERMES_CMD_BUSY) { |
| 102 | printk(KERN_ERR PFX "Busy timeout\n"); | 84 | printk(KERN_ERR PFX "Busy timeout\n"); |
| 103 | return -ETIMEDOUT; | 85 | return -ETIMEDOUT; |
| @@ -110,11 +92,11 @@ static int orinoco_tmd_cor_reset(struct orinoco_private *priv) | |||
| 110 | static int orinoco_tmd_init_one(struct pci_dev *pdev, | 92 | static int orinoco_tmd_init_one(struct pci_dev *pdev, |
| 111 | const struct pci_device_id *ent) | 93 | const struct pci_device_id *ent) |
| 112 | { | 94 | { |
| 113 | int err = 0; | 95 | int err; |
| 114 | struct orinoco_private *priv = NULL; | 96 | struct orinoco_private *priv; |
| 115 | struct orinoco_tmd_card *card; | 97 | struct orinoco_pci_card *card; |
| 116 | struct net_device *dev = NULL; | 98 | struct net_device *dev; |
| 117 | void __iomem *mem; | 99 | void __iomem *hermes_io, *bridge_io; |
| 118 | 100 | ||
| 119 | err = pci_enable_device(pdev); | 101 | err = pci_enable_device(pdev); |
| 120 | if (err) { | 102 | if (err) { |
| @@ -123,20 +105,28 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, | |||
| 123 | } | 105 | } |
| 124 | 106 | ||
| 125 | err = pci_request_regions(pdev, DRIVER_NAME); | 107 | err = pci_request_regions(pdev, DRIVER_NAME); |
| 126 | if (err != 0) { | 108 | if (err) { |
| 127 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); | 109 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); |
| 128 | goto fail_resources; | 110 | goto fail_resources; |
| 129 | } | 111 | } |
| 130 | 112 | ||
| 131 | mem = pci_iomap(pdev, 2, 0); | 113 | bridge_io = pci_iomap(pdev, 1, 0); |
| 132 | if (! mem) { | 114 | if (!bridge_io) { |
| 133 | err = -ENOMEM; | 115 | printk(KERN_ERR PFX "Cannot map bridge registers\n"); |
| 134 | goto fail_iomap; | 116 | err = -EIO; |
| 117 | goto fail_map_bridge; | ||
| 118 | } | ||
| 119 | |||
| 120 | hermes_io = pci_iomap(pdev, 2, 0); | ||
| 121 | if (!hermes_io) { | ||
| 122 | printk(KERN_ERR PFX "Cannot map chipset registers\n"); | ||
| 123 | err = -EIO; | ||
| 124 | goto fail_map_hermes; | ||
| 135 | } | 125 | } |
| 136 | 126 | ||
| 137 | /* Allocate network device */ | 127 | /* Allocate network device */ |
| 138 | dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset); | 128 | dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset); |
| 139 | if (! dev) { | 129 | if (!dev) { |
| 140 | printk(KERN_ERR PFX "Cannot allocate network device\n"); | 130 | printk(KERN_ERR PFX "Cannot allocate network device\n"); |
| 141 | err = -ENOMEM; | 131 | err = -ENOMEM; |
| 142 | goto fail_alloc; | 132 | goto fail_alloc; |
| @@ -144,16 +134,11 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, | |||
| 144 | 134 | ||
| 145 | priv = netdev_priv(dev); | 135 | priv = netdev_priv(dev); |
| 146 | card = priv->card; | 136 | card = priv->card; |
| 147 | card->tmd_io = pci_resource_start(pdev, 1); | 137 | card->bridge_io = bridge_io; |
| 148 | dev->base_addr = pci_resource_start(pdev, 2); | ||
| 149 | SET_MODULE_OWNER(dev); | 138 | SET_MODULE_OWNER(dev); |
| 150 | SET_NETDEV_DEV(dev, &pdev->dev); | 139 | SET_NETDEV_DEV(dev, &pdev->dev); |
| 151 | 140 | ||
| 152 | hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING); | 141 | hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING); |
| 153 | |||
| 154 | printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 TMD device " | ||
| 155 | "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq, | ||
| 156 | dev->base_addr); | ||
| 157 | 142 | ||
| 158 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, | 143 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, |
| 159 | dev->name, dev); | 144 | dev->name, dev); |
| @@ -162,7 +147,6 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, | |||
| 162 | err = -EBUSY; | 147 | err = -EBUSY; |
| 163 | goto fail_irq; | 148 | goto fail_irq; |
| 164 | } | 149 | } |
| 165 | dev->irq = pdev->irq; | ||
| 166 | 150 | ||
| 167 | err = orinoco_tmd_cor_reset(priv); | 151 | err = orinoco_tmd_cor_reset(priv); |
| 168 | if (err) { | 152 | if (err) { |
| @@ -177,6 +161,8 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, | |||
| 177 | } | 161 | } |
| 178 | 162 | ||
| 179 | pci_set_drvdata(pdev, dev); | 163 | pci_set_drvdata(pdev, dev); |
| 164 | printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name, | ||
| 165 | pci_name(pdev)); | ||
| 180 | 166 | ||
| 181 | return 0; | 167 | return 0; |
| 182 | 168 | ||
| @@ -188,9 +174,12 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, | |||
| 188 | free_orinocodev(dev); | 174 | free_orinocodev(dev); |
| 189 | 175 | ||
| 190 | fail_alloc: | 176 | fail_alloc: |
| 191 | pci_iounmap(pdev, mem); | 177 | pci_iounmap(pdev, hermes_io); |
| 178 | |||
| 179 | fail_map_hermes: | ||
| 180 | pci_iounmap(pdev, bridge_io); | ||
| 192 | 181 | ||
| 193 | fail_iomap: | 182 | fail_map_bridge: |
| 194 | pci_release_regions(pdev); | 183 | pci_release_regions(pdev); |
| 195 | 184 | ||
| 196 | fail_resources: | 185 | fail_resources: |
| @@ -203,31 +192,32 @@ static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev) | |||
| 203 | { | 192 | { |
| 204 | struct net_device *dev = pci_get_drvdata(pdev); | 193 | struct net_device *dev = pci_get_drvdata(pdev); |
| 205 | struct orinoco_private *priv = dev->priv; | 194 | struct orinoco_private *priv = dev->priv; |
| 206 | 195 | struct orinoco_pci_card *card = priv->card; | |
| 207 | BUG_ON(! dev); | ||
| 208 | 196 | ||
| 209 | unregister_netdev(dev); | 197 | unregister_netdev(dev); |
| 210 | free_irq(dev->irq, dev); | 198 | free_irq(pdev->irq, dev); |
| 211 | pci_set_drvdata(pdev, NULL); | 199 | pci_set_drvdata(pdev, NULL); |
| 212 | free_orinocodev(dev); | 200 | free_orinocodev(dev); |
| 213 | pci_iounmap(pdev, priv->hw.iobase); | 201 | pci_iounmap(pdev, priv->hw.iobase); |
| 202 | pci_iounmap(pdev, card->bridge_io); | ||
| 214 | pci_release_regions(pdev); | 203 | pci_release_regions(pdev); |
| 215 | pci_disable_device(pdev); | 204 | pci_disable_device(pdev); |
| 216 | } | 205 | } |
| 217 | 206 | ||
| 218 | 207 | static struct pci_device_id orinoco_tmd_id_table[] = { | |
| 219 | static struct pci_device_id orinoco_tmd_pci_id_table[] = { | ||
| 220 | {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */ | 208 | {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */ |
| 221 | {0,}, | 209 | {0,}, |
| 222 | }; | 210 | }; |
| 223 | 211 | ||
| 224 | MODULE_DEVICE_TABLE(pci, orinoco_tmd_pci_id_table); | 212 | MODULE_DEVICE_TABLE(pci, orinoco_tmd_id_table); |
| 225 | 213 | ||
| 226 | static struct pci_driver orinoco_tmd_driver = { | 214 | static struct pci_driver orinoco_tmd_driver = { |
| 227 | .name = DRIVER_NAME, | 215 | .name = DRIVER_NAME, |
| 228 | .id_table = orinoco_tmd_pci_id_table, | 216 | .id_table = orinoco_tmd_id_table, |
| 229 | .probe = orinoco_tmd_init_one, | 217 | .probe = orinoco_tmd_init_one, |
| 230 | .remove = __devexit_p(orinoco_tmd_remove_one), | 218 | .remove = __devexit_p(orinoco_tmd_remove_one), |
| 219 | .suspend = orinoco_pci_suspend, | ||
| 220 | .resume = orinoco_pci_resume, | ||
| 231 | }; | 221 | }; |
| 232 | 222 | ||
| 233 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION | 223 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION |
| @@ -245,7 +235,6 @@ static int __init orinoco_tmd_init(void) | |||
| 245 | static void __exit orinoco_tmd_exit(void) | 235 | static void __exit orinoco_tmd_exit(void) |
| 246 | { | 236 | { |
| 247 | pci_unregister_driver(&orinoco_tmd_driver); | 237 | pci_unregister_driver(&orinoco_tmd_driver); |
| 248 | ssleep(1); | ||
| 249 | } | 238 | } |
| 250 | 239 | ||
| 251 | module_init(orinoco_tmd_init); | 240 | module_init(orinoco_tmd_init); |
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index f7b77ce54d7b..7f9aa139c347 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Driver for 802.11b cards using RAM-loadable Symbol firmware, such as | 2 | * Driver for 802.11b cards using RAM-loadable Symbol firmware, such as |
| 3 | * Symbol Wireless Networker LA4100, CompactFlash cards by Socket | 3 | * Symbol Wireless Networker LA4137, CompactFlash cards by Socket |
| 4 | * Communications and Intel PRO/Wireless 2011B. | 4 | * Communications and Intel PRO/Wireless 2011B. |
| 5 | * | 5 | * |
| 6 | * The driver implements Symbol firmware download. The rest is handled | 6 | * The driver implements Symbol firmware download. The rest is handled |
| @@ -120,8 +120,8 @@ static void spectrum_cs_release(struct pcmcia_device *link); | |||
| 120 | * Each block has the following structure. | 120 | * Each block has the following structure. |
| 121 | */ | 121 | */ |
| 122 | struct dblock { | 122 | struct dblock { |
| 123 | __le32 _addr; /* adapter address where to write the block */ | 123 | __le32 addr; /* adapter address where to write the block */ |
| 124 | __le16 _len; /* length of the data only, in bytes */ | 124 | __le16 len; /* length of the data only, in bytes */ |
| 125 | char data[0]; /* data to be written */ | 125 | char data[0]; /* data to be written */ |
| 126 | } __attribute__ ((packed)); | 126 | } __attribute__ ((packed)); |
| 127 | 127 | ||
| @@ -131,9 +131,9 @@ struct dblock { | |||
| 131 | * items with matching ID should be written. | 131 | * items with matching ID should be written. |
| 132 | */ | 132 | */ |
| 133 | struct pdr { | 133 | struct pdr { |
| 134 | __le32 _id; /* record ID */ | 134 | __le32 id; /* record ID */ |
| 135 | __le32 _addr; /* adapter address where to write the data */ | 135 | __le32 addr; /* adapter address where to write the data */ |
| 136 | __le32 _len; /* expected length of the data, in bytes */ | 136 | __le32 len; /* expected length of the data, in bytes */ |
| 137 | char next[0]; /* next PDR starts here */ | 137 | char next[0]; /* next PDR starts here */ |
| 138 | } __attribute__ ((packed)); | 138 | } __attribute__ ((packed)); |
| 139 | 139 | ||
| @@ -144,8 +144,8 @@ struct pdr { | |||
| 144 | * be plugged into the secondary firmware. | 144 | * be plugged into the secondary firmware. |
| 145 | */ | 145 | */ |
| 146 | struct pdi { | 146 | struct pdi { |
| 147 | __le16 _len; /* length of ID and data, in words */ | 147 | __le16 len; /* length of ID and data, in words */ |
| 148 | __le16 _id; /* record ID */ | 148 | __le16 id; /* record ID */ |
| 149 | char data[0]; /* plug data */ | 149 | char data[0]; /* plug data */ |
| 150 | } __attribute__ ((packed)); | 150 | } __attribute__ ((packed)); |
| 151 | 151 | ||
| @@ -154,44 +154,44 @@ struct pdi { | |||
| 154 | static inline u32 | 154 | static inline u32 |
| 155 | dblock_addr(const struct dblock *blk) | 155 | dblock_addr(const struct dblock *blk) |
| 156 | { | 156 | { |
| 157 | return le32_to_cpu(blk->_addr); | 157 | return le32_to_cpu(blk->addr); |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | static inline u32 | 160 | static inline u32 |
| 161 | dblock_len(const struct dblock *blk) | 161 | dblock_len(const struct dblock *blk) |
| 162 | { | 162 | { |
| 163 | return le16_to_cpu(blk->_len); | 163 | return le16_to_cpu(blk->len); |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | static inline u32 | 166 | static inline u32 |
| 167 | pdr_id(const struct pdr *pdr) | 167 | pdr_id(const struct pdr *pdr) |
| 168 | { | 168 | { |
| 169 | return le32_to_cpu(pdr->_id); | 169 | return le32_to_cpu(pdr->id); |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | static inline u32 | 172 | static inline u32 |
| 173 | pdr_addr(const struct pdr *pdr) | 173 | pdr_addr(const struct pdr *pdr) |
| 174 | { | 174 | { |
| 175 | return le32_to_cpu(pdr->_addr); | 175 | return le32_to_cpu(pdr->addr); |
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | static inline u32 | 178 | static inline u32 |
| 179 | pdr_len(const struct pdr *pdr) | 179 | pdr_len(const struct pdr *pdr) |
| 180 | { | 180 | { |
| 181 | return le32_to_cpu(pdr->_len); | 181 | return le32_to_cpu(pdr->len); |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | static inline u32 | 184 | static inline u32 |
| 185 | pdi_id(const struct pdi *pdi) | 185 | pdi_id(const struct pdi *pdi) |
| 186 | { | 186 | { |
| 187 | return le16_to_cpu(pdi->_id); | 187 | return le16_to_cpu(pdi->id); |
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | /* Return length of the data only, in bytes */ | 190 | /* Return length of the data only, in bytes */ |
| 191 | static inline u32 | 191 | static inline u32 |
| 192 | pdi_len(const struct pdi *pdi) | 192 | pdi_len(const struct pdi *pdi) |
| 193 | { | 193 | { |
| 194 | return 2 * (le16_to_cpu(pdi->_len) - 1); | 194 | return 2 * (le16_to_cpu(pdi->len) - 1); |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | 197 | ||
| @@ -343,8 +343,7 @@ spectrum_plug_pdi(hermes_t *hw, struct pdr *first_pdr, struct pdi *pdi) | |||
| 343 | 343 | ||
| 344 | /* do the actual plugging */ | 344 | /* do the actual plugging */ |
| 345 | spectrum_aux_setaddr(hw, pdr_addr(pdr)); | 345 | spectrum_aux_setaddr(hw, pdr_addr(pdr)); |
| 346 | hermes_write_words(hw, HERMES_AUXDATA, pdi->data, | 346 | hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi)); |
| 347 | pdi_len(pdi) / 2); | ||
| 348 | 347 | ||
| 349 | return 0; | 348 | return 0; |
| 350 | } | 349 | } |
| @@ -424,8 +423,8 @@ spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block) | |||
| 424 | 423 | ||
| 425 | while (dblock_addr(blk) != BLOCK_END) { | 424 | while (dblock_addr(blk) != BLOCK_END) { |
| 426 | spectrum_aux_setaddr(hw, blkaddr); | 425 | spectrum_aux_setaddr(hw, blkaddr); |
| 427 | hermes_write_words(hw, HERMES_AUXDATA, blk->data, | 426 | hermes_write_bytes(hw, HERMES_AUXDATA, blk->data, |
| 428 | blklen / 2); | 427 | blklen); |
| 429 | 428 | ||
| 430 | blk = (struct dblock *) &blk->data[blklen]; | 429 | blk = (struct dblock *) &blk->data[blklen]; |
| 431 | blkaddr = dblock_addr(blk); | 430 | blkaddr = dblock_addr(blk); |
| @@ -626,14 +625,11 @@ static void spectrum_cs_detach(struct pcmcia_device *link) | |||
| 626 | { | 625 | { |
| 627 | struct net_device *dev = link->priv; | 626 | struct net_device *dev = link->priv; |
| 628 | 627 | ||
| 628 | if (link->dev_node) | ||
| 629 | unregister_netdev(dev); | ||
| 630 | |||
| 629 | spectrum_cs_release(link); | 631 | spectrum_cs_release(link); |
| 630 | 632 | ||
| 631 | DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node); | ||
| 632 | if (link->dev_node) { | ||
| 633 | DEBUG(0, PFX "About to unregister net device %p\n", | ||
| 634 | dev); | ||
| 635 | unregister_netdev(dev); | ||
| 636 | } | ||
| 637 | free_orinocodev(dev); | 633 | free_orinocodev(dev); |
| 638 | } /* spectrum_cs_detach */ | 634 | } /* spectrum_cs_detach */ |
| 639 | 635 | ||
| @@ -653,13 +649,10 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
| 653 | int last_fn, last_ret; | 649 | int last_fn, last_ret; |
| 654 | u_char buf[64]; | 650 | u_char buf[64]; |
| 655 | config_info_t conf; | 651 | config_info_t conf; |
| 656 | cisinfo_t info; | ||
| 657 | tuple_t tuple; | 652 | tuple_t tuple; |
| 658 | cisparse_t parse; | 653 | cisparse_t parse; |
| 659 | void __iomem *mem; | 654 | void __iomem *mem; |
| 660 | 655 | ||
| 661 | CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info)); | ||
| 662 | |||
| 663 | /* | 656 | /* |
| 664 | * This reads the card's CONFIG tuple to find its | 657 | * This reads the card's CONFIG tuple to find its |
| 665 | * configuration registers. | 658 | * configuration registers. |
| @@ -709,12 +702,6 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
| 709 | goto next_entry; | 702 | goto next_entry; |
| 710 | link->conf.ConfigIndex = cfg->index; | 703 | link->conf.ConfigIndex = cfg->index; |
| 711 | 704 | ||
| 712 | /* Does this card need audio output? */ | ||
| 713 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
| 714 | link->conf.Attributes |= CONF_ENABLE_SPKR; | ||
| 715 | link->conf.Status = CCSR_AUDIO_ENA; | ||
| 716 | } | ||
| 717 | |||
| 718 | /* Use power settings for Vcc and Vpp if present */ | 705 | /* Use power settings for Vcc and Vpp if present */ |
| 719 | /* Note that the CIS values need to be rescaled */ | 706 | /* Note that the CIS values need to be rescaled */ |
| 720 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | 707 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { |
| @@ -835,19 +822,10 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
| 835 | net_device has been registered */ | 822 | net_device has been registered */ |
| 836 | 823 | ||
| 837 | /* Finally, report what we've done */ | 824 | /* Finally, report what we've done */ |
| 838 | printk(KERN_DEBUG "%s: index 0x%02x: ", | 825 | printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io " |
| 839 | dev->name, link->conf.ConfigIndex); | 826 | "0x%04x-0x%04x\n", dev->name, dev->class_dev.dev->bus_id, |
| 840 | if (link->conf.Vpp) | 827 | link->irq.AssignedIRQ, link->io.BasePort1, |
| 841 | printk(", Vpp %d.%d", link->conf.Vpp / 10, | 828 | link->io.BasePort1 + link->io.NumPorts1 - 1); |
| 842 | link->conf.Vpp % 10); | ||
| 843 | printk(", irq %d", link->irq.AssignedIRQ); | ||
| 844 | if (link->io.NumPorts1) | ||
| 845 | printk(", io 0x%04x-0x%04x", link->io.BasePort1, | ||
| 846 | link->io.BasePort1 + link->io.NumPorts1 - 1); | ||
| 847 | if (link->io.NumPorts2) | ||
| 848 | printk(" & 0x%04x-0x%04x", link->io.BasePort2, | ||
| 849 | link->io.BasePort2 + link->io.NumPorts2 - 1); | ||
| 850 | printk("\n"); | ||
| 851 | 829 | ||
| 852 | return 0; | 830 | return 0; |
| 853 | 831 | ||
| @@ -888,11 +866,10 @@ spectrum_cs_suspend(struct pcmcia_device *link) | |||
| 888 | { | 866 | { |
| 889 | struct net_device *dev = link->priv; | 867 | struct net_device *dev = link->priv; |
| 890 | struct orinoco_private *priv = netdev_priv(dev); | 868 | struct orinoco_private *priv = netdev_priv(dev); |
| 891 | unsigned long flags; | ||
| 892 | int err = 0; | 869 | int err = 0; |
| 893 | 870 | ||
| 894 | /* Mark the device as stopped, to block IO until later */ | 871 | /* Mark the device as stopped, to block IO until later */ |
| 895 | spin_lock_irqsave(&priv->lock, flags); | 872 | spin_lock(&priv->lock); |
| 896 | 873 | ||
| 897 | err = __orinoco_down(dev); | 874 | err = __orinoco_down(dev); |
| 898 | if (err) | 875 | if (err) |
| @@ -902,9 +879,9 @@ spectrum_cs_suspend(struct pcmcia_device *link) | |||
| 902 | netif_device_detach(dev); | 879 | netif_device_detach(dev); |
| 903 | priv->hw_unavailable++; | 880 | priv->hw_unavailable++; |
| 904 | 881 | ||
| 905 | spin_unlock_irqrestore(&priv->lock, flags); | 882 | spin_unlock(&priv->lock); |
| 906 | 883 | ||
| 907 | return 0; | 884 | return err; |
| 908 | } | 885 | } |
| 909 | 886 | ||
| 910 | static int | 887 | static int |
| @@ -932,7 +909,7 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION | |||
| 932 | " David Gibson <hermes@gibson.dropbear.id.au>, et al)"; | 909 | " David Gibson <hermes@gibson.dropbear.id.au>, et al)"; |
| 933 | 910 | ||
| 934 | static struct pcmcia_device_id spectrum_cs_ids[] = { | 911 | static struct pcmcia_device_id spectrum_cs_ids[] = { |
| 935 | PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4100 */ | 912 | PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4137 */ |
| 936 | PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */ | 913 | PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */ |
| 937 | PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */ | 914 | PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */ |
| 938 | PCMCIA_DEVICE_NULL, | 915 | PCMCIA_DEVICE_NULL, |
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c new file mode 100644 index 000000000000..662ecc8a33ff --- /dev/null +++ b/drivers/net/wireless/zd1201.c | |||
| @@ -0,0 +1,1929 @@ | |||
| 1 | /* | ||
| 2 | * Driver for ZyDAS zd1201 based wireless USB devices. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * version 2 as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * Parts of this driver have been derived from a wlan-ng version | ||
| 11 | * modified by ZyDAS. They also made documentation available, thanks! | ||
| 12 | * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/usb.h> | ||
| 17 | #include <linux/netdevice.h> | ||
| 18 | #include <linux/etherdevice.h> | ||
| 19 | #include <linux/wireless.h> | ||
| 20 | #include <net/iw_handler.h> | ||
| 21 | #include <linux/string.h> | ||
| 22 | #include <linux/if_arp.h> | ||
| 23 | #include <linux/firmware.h> | ||
| 24 | #include <net/ieee80211.h> | ||
| 25 | #include "zd1201.h" | ||
| 26 | |||
| 27 | static struct usb_device_id zd1201_table[] = { | ||
| 28 | {USB_DEVICE(0x0586, 0x3400)}, /* Peabird Wireless USB Adapter */ | ||
| 29 | {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */ | ||
| 30 | {USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb adapter */ | ||
| 31 | {USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb adapter */ | ||
| 32 | {USB_DEVICE(0x1044, 0x8005)}, /* GIGABYTE GN-WLBZ201 usb adapter */ | ||
| 33 | {} | ||
| 34 | }; | ||
| 35 | |||
| 36 | static int ap; /* Are we an AP or a normal station? */ | ||
| 37 | |||
| 38 | #define ZD1201_VERSION "0.15" | ||
| 39 | |||
| 40 | MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>"); | ||
| 41 | MODULE_DESCRIPTION("Driver for ZyDAS ZD1201 based USB Wireless adapters"); | ||
| 42 | MODULE_VERSION(ZD1201_VERSION); | ||
| 43 | MODULE_LICENSE("GPL"); | ||
| 44 | module_param(ap, int, 0); | ||
| 45 | MODULE_PARM_DESC(ap, "If non-zero Access Point firmware will be loaded"); | ||
| 46 | MODULE_DEVICE_TABLE(usb, zd1201_table); | ||
| 47 | |||
| 48 | |||
| 49 | static int zd1201_fw_upload(struct usb_device *dev, int apfw) | ||
| 50 | { | ||
| 51 | const struct firmware *fw_entry; | ||
| 52 | char *data; | ||
| 53 | unsigned long len; | ||
| 54 | int err; | ||
| 55 | unsigned char ret; | ||
| 56 | char *buf; | ||
| 57 | char *fwfile; | ||
| 58 | |||
| 59 | if (apfw) | ||
| 60 | fwfile = "zd1201-ap.fw"; | ||
| 61 | else | ||
| 62 | fwfile = "zd1201.fw"; | ||
| 63 | |||
| 64 | err = request_firmware(&fw_entry, fwfile, &dev->dev); | ||
| 65 | if (err) { | ||
| 66 | dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile); | ||
| 67 | dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n"); | ||
| 68 | dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info.\n"); | ||
| 69 | return err; | ||
| 70 | } | ||
| 71 | |||
| 72 | data = fw_entry->data; | ||
| 73 | len = fw_entry->size; | ||
| 74 | |||
| 75 | buf = kmalloc(1024, GFP_ATOMIC); | ||
| 76 | if (!buf) | ||
| 77 | goto exit; | ||
| 78 | |||
| 79 | while (len > 0) { | ||
| 80 | int translen = (len > 1024) ? 1024 : len; | ||
| 81 | memcpy(buf, data, translen); | ||
| 82 | |||
| 83 | err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0, | ||
| 84 | USB_DIR_OUT | 0x40, 0, 0, buf, translen, | ||
| 85 | ZD1201_FW_TIMEOUT); | ||
| 86 | if (err < 0) | ||
| 87 | goto exit; | ||
| 88 | |||
| 89 | len -= translen; | ||
| 90 | data += translen; | ||
| 91 | } | ||
| 92 | |||
| 93 | err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x2, | ||
| 94 | USB_DIR_OUT | 0x40, 0, 0, NULL, 0, ZD1201_FW_TIMEOUT); | ||
| 95 | if (err < 0) | ||
| 96 | goto exit; | ||
| 97 | |||
| 98 | err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4, | ||
| 99 | USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT); | ||
| 100 | if (err < 0) | ||
| 101 | goto exit; | ||
| 102 | |||
| 103 | if (ret & 0x80) { | ||
| 104 | err = -EIO; | ||
| 105 | goto exit; | ||
| 106 | } | ||
| 107 | |||
| 108 | err = 0; | ||
| 109 | exit: | ||
| 110 | kfree(buf); | ||
| 111 | release_firmware(fw_entry); | ||
| 112 | return err; | ||
| 113 | } | ||
| 114 | |||
| 115 | static void zd1201_usbfree(struct urb *urb, struct pt_regs *regs) | ||
| 116 | { | ||
| 117 | struct zd1201 *zd = urb->context; | ||
| 118 | |||
| 119 | switch(urb->status) { | ||
| 120 | case -EILSEQ: | ||
| 121 | case -ENODEV: | ||
| 122 | case -ETIMEDOUT: | ||
| 123 | case -ENOENT: | ||
| 124 | case -EPIPE: | ||
| 125 | case -EOVERFLOW: | ||
| 126 | case -ESHUTDOWN: | ||
| 127 | dev_warn(&zd->usb->dev, "%s: urb failed: %d\n", | ||
| 128 | zd->dev->name, urb->status); | ||
| 129 | } | ||
| 130 | |||
| 131 | kfree(urb->transfer_buffer); | ||
| 132 | usb_free_urb(urb); | ||
| 133 | return; | ||
| 134 | } | ||
| 135 | |||
| 136 | /* cmdreq message: | ||
| 137 | u32 type | ||
| 138 | u16 cmd | ||
| 139 | u16 parm0 | ||
| 140 | u16 parm1 | ||
| 141 | u16 parm2 | ||
| 142 | u8 pad[4] | ||
| 143 | |||
| 144 | total: 4 + 2 + 2 + 2 + 2 + 4 = 16 | ||
| 145 | */ | ||
| 146 | static int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0, | ||
| 147 | int parm1, int parm2) | ||
| 148 | { | ||
| 149 | unsigned char *command; | ||
| 150 | int ret; | ||
| 151 | struct urb *urb; | ||
| 152 | |||
| 153 | command = kmalloc(16, GFP_ATOMIC); | ||
| 154 | if (!command) | ||
| 155 | return -ENOMEM; | ||
| 156 | |||
| 157 | *((__le32*)command) = cpu_to_le32(ZD1201_USB_CMDREQ); | ||
| 158 | *((__le16*)&command[4]) = cpu_to_le16(cmd); | ||
| 159 | *((__le16*)&command[6]) = cpu_to_le16(parm0); | ||
| 160 | *((__le16*)&command[8]) = cpu_to_le16(parm1); | ||
| 161 | *((__le16*)&command[10])= cpu_to_le16(parm2); | ||
| 162 | |||
| 163 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
| 164 | if (!urb) { | ||
| 165 | kfree(command); | ||
| 166 | return -ENOMEM; | ||
| 167 | } | ||
| 168 | usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), | ||
| 169 | command, 16, zd1201_usbfree, zd); | ||
| 170 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
| 171 | if (ret) { | ||
| 172 | kfree(command); | ||
| 173 | usb_free_urb(urb); | ||
| 174 | } | ||
| 175 | |||
| 176 | return ret; | ||
| 177 | } | ||
| 178 | |||
| 179 | /* Callback after sending out a packet */ | ||
| 180 | static void zd1201_usbtx(struct urb *urb, struct pt_regs *regs) | ||
| 181 | { | ||
| 182 | struct zd1201 *zd = urb->context; | ||
| 183 | netif_wake_queue(zd->dev); | ||
| 184 | return; | ||
| 185 | } | ||
| 186 | |||
| 187 | /* Incoming data */ | ||
| 188 | static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs) | ||
| 189 | { | ||
| 190 | struct zd1201 *zd = urb->context; | ||
| 191 | int free = 0; | ||
| 192 | unsigned char *data = urb->transfer_buffer; | ||
| 193 | struct sk_buff *skb; | ||
| 194 | unsigned char type; | ||
| 195 | |||
| 196 | if (!zd) { | ||
| 197 | free = 1; | ||
| 198 | goto exit; | ||
| 199 | } | ||
| 200 | |||
| 201 | switch(urb->status) { | ||
| 202 | case -EILSEQ: | ||
| 203 | case -ENODEV: | ||
| 204 | case -ETIMEDOUT: | ||
| 205 | case -ENOENT: | ||
| 206 | case -EPIPE: | ||
| 207 | case -EOVERFLOW: | ||
| 208 | case -ESHUTDOWN: | ||
| 209 | dev_warn(&zd->usb->dev, "%s: rx urb failed: %d\n", | ||
| 210 | zd->dev->name, urb->status); | ||
| 211 | free = 1; | ||
| 212 | goto exit; | ||
| 213 | } | ||
| 214 | |||
| 215 | if (urb->status != 0 || urb->actual_length == 0) | ||
| 216 | goto resubmit; | ||
| 217 | |||
| 218 | type = data[0]; | ||
| 219 | if (type == ZD1201_PACKET_EVENTSTAT || type == ZD1201_PACKET_RESOURCE) { | ||
| 220 | memcpy(zd->rxdata, data, urb->actual_length); | ||
| 221 | zd->rxlen = urb->actual_length; | ||
| 222 | zd->rxdatas = 1; | ||
| 223 | wake_up(&zd->rxdataq); | ||
| 224 | } | ||
| 225 | /* Info frame */ | ||
| 226 | if (type == ZD1201_PACKET_INQUIRE) { | ||
| 227 | int i = 0; | ||
| 228 | unsigned short infotype, framelen, copylen; | ||
| 229 | framelen = le16_to_cpu(*(__le16*)&data[4]); | ||
| 230 | infotype = le16_to_cpu(*(__le16*)&data[6]); | ||
| 231 | |||
| 232 | if (infotype == ZD1201_INF_LINKSTATUS) { | ||
| 233 | short linkstatus; | ||
| 234 | |||
| 235 | linkstatus = le16_to_cpu(*(__le16*)&data[8]); | ||
| 236 | switch(linkstatus) { | ||
| 237 | case 1: | ||
| 238 | netif_carrier_on(zd->dev); | ||
| 239 | break; | ||
| 240 | case 2: | ||
| 241 | netif_carrier_off(zd->dev); | ||
| 242 | break; | ||
| 243 | case 3: | ||
| 244 | netif_carrier_off(zd->dev); | ||
| 245 | break; | ||
| 246 | case 4: | ||
| 247 | netif_carrier_on(zd->dev); | ||
| 248 | break; | ||
| 249 | default: | ||
| 250 | netif_carrier_off(zd->dev); | ||
| 251 | } | ||
| 252 | goto resubmit; | ||
| 253 | } | ||
| 254 | if (infotype == ZD1201_INF_ASSOCSTATUS) { | ||
| 255 | short status = le16_to_cpu(*(__le16*)(data+8)); | ||
| 256 | int event; | ||
| 257 | union iwreq_data wrqu; | ||
| 258 | |||
| 259 | switch (status) { | ||
| 260 | case ZD1201_ASSOCSTATUS_STAASSOC: | ||
| 261 | case ZD1201_ASSOCSTATUS_REASSOC: | ||
| 262 | event = IWEVREGISTERED; | ||
| 263 | break; | ||
| 264 | case ZD1201_ASSOCSTATUS_DISASSOC: | ||
| 265 | case ZD1201_ASSOCSTATUS_ASSOCFAIL: | ||
| 266 | case ZD1201_ASSOCSTATUS_AUTHFAIL: | ||
| 267 | default: | ||
| 268 | event = IWEVEXPIRED; | ||
| 269 | } | ||
| 270 | memcpy(wrqu.addr.sa_data, data+10, ETH_ALEN); | ||
| 271 | wrqu.addr.sa_family = ARPHRD_ETHER; | ||
| 272 | |||
| 273 | /* Send event to user space */ | ||
| 274 | wireless_send_event(zd->dev, event, &wrqu, NULL); | ||
| 275 | |||
| 276 | goto resubmit; | ||
| 277 | } | ||
| 278 | if (infotype == ZD1201_INF_AUTHREQ) { | ||
| 279 | union iwreq_data wrqu; | ||
| 280 | |||
| 281 | memcpy(wrqu.addr.sa_data, data+8, ETH_ALEN); | ||
| 282 | wrqu.addr.sa_family = ARPHRD_ETHER; | ||
| 283 | /* There isn't a event that trully fits this request. | ||
| 284 | We assume that userspace will be smart enough to | ||
| 285 | see a new station being expired and sends back a | ||
| 286 | authstation ioctl to authorize it. */ | ||
| 287 | wireless_send_event(zd->dev, IWEVEXPIRED, &wrqu, NULL); | ||
| 288 | goto resubmit; | ||
| 289 | } | ||
| 290 | /* Other infotypes are handled outside this handler */ | ||
| 291 | zd->rxlen = 0; | ||
| 292 | while (i < urb->actual_length) { | ||
| 293 | copylen = le16_to_cpu(*(__le16*)&data[i+2]); | ||
| 294 | /* Sanity check, sometimes we get junk */ | ||
| 295 | if (copylen+zd->rxlen > sizeof(zd->rxdata)) | ||
| 296 | break; | ||
| 297 | memcpy(zd->rxdata+zd->rxlen, data+i+4, copylen); | ||
| 298 | zd->rxlen += copylen; | ||
| 299 | i += 64; | ||
| 300 | } | ||
| 301 | if (i >= urb->actual_length) { | ||
| 302 | zd->rxdatas = 1; | ||
| 303 | wake_up(&zd->rxdataq); | ||
| 304 | } | ||
| 305 | goto resubmit; | ||
| 306 | } | ||
| 307 | /* Actual data */ | ||
| 308 | if (data[urb->actual_length-1] == ZD1201_PACKET_RXDATA) { | ||
| 309 | int datalen = urb->actual_length-1; | ||
| 310 | unsigned short len, fc, seq; | ||
| 311 | struct hlist_node *node; | ||
| 312 | |||
| 313 | len = ntohs(*(__be16 *)&data[datalen-2]); | ||
| 314 | if (len>datalen) | ||
| 315 | len=datalen; | ||
| 316 | fc = le16_to_cpu(*(__le16 *)&data[datalen-16]); | ||
| 317 | seq = le16_to_cpu(*(__le16 *)&data[datalen-24]); | ||
| 318 | |||
| 319 | if (zd->monitor) { | ||
| 320 | if (datalen < 24) | ||
| 321 | goto resubmit; | ||
| 322 | if (!(skb = dev_alloc_skb(datalen+24))) | ||
| 323 | goto resubmit; | ||
| 324 | |||
| 325 | memcpy(skb_put(skb, 2), &data[datalen-16], 2); | ||
| 326 | memcpy(skb_put(skb, 2), &data[datalen-2], 2); | ||
| 327 | memcpy(skb_put(skb, 6), &data[datalen-14], 6); | ||
| 328 | memcpy(skb_put(skb, 6), &data[datalen-22], 6); | ||
| 329 | memcpy(skb_put(skb, 6), &data[datalen-8], 6); | ||
| 330 | memcpy(skb_put(skb, 2), &data[datalen-24], 2); | ||
| 331 | memcpy(skb_put(skb, len), data, len); | ||
| 332 | skb->dev = zd->dev; | ||
| 333 | skb->dev->last_rx = jiffies; | ||
| 334 | skb->protocol = eth_type_trans(skb, zd->dev); | ||
| 335 | zd->stats.rx_packets++; | ||
| 336 | zd->stats.rx_bytes += skb->len; | ||
| 337 | netif_rx(skb); | ||
| 338 | goto resubmit; | ||
| 339 | } | ||
| 340 | |||
| 341 | if ((seq & IEEE80211_SCTL_FRAG) || | ||
| 342 | (fc & IEEE80211_FCTL_MOREFRAGS)) { | ||
| 343 | struct zd1201_frag *frag = NULL; | ||
| 344 | char *ptr; | ||
| 345 | |||
| 346 | if (datalen<14) | ||
| 347 | goto resubmit; | ||
| 348 | if ((seq & IEEE80211_SCTL_FRAG) == 0) { | ||
| 349 | frag = kmalloc(sizeof(*frag), GFP_ATOMIC); | ||
| 350 | if (!frag) | ||
| 351 | goto resubmit; | ||
| 352 | skb = dev_alloc_skb(IEEE80211_DATA_LEN +14+2); | ||
| 353 | if (!skb) { | ||
| 354 | kfree(frag); | ||
| 355 | goto resubmit; | ||
| 356 | } | ||
| 357 | frag->skb = skb; | ||
| 358 | frag->seq = seq & IEEE80211_SCTL_SEQ; | ||
| 359 | skb_reserve(skb, 2); | ||
| 360 | memcpy(skb_put(skb, 12), &data[datalen-14], 12); | ||
| 361 | memcpy(skb_put(skb, 2), &data[6], 2); | ||
| 362 | memcpy(skb_put(skb, len), data+8, len); | ||
| 363 | hlist_add_head(&frag->fnode, &zd->fraglist); | ||
| 364 | goto resubmit; | ||
| 365 | } | ||
| 366 | hlist_for_each_entry(frag, node, &zd->fraglist, fnode) | ||
| 367 | if (frag->seq == (seq&IEEE80211_SCTL_SEQ)) | ||
| 368 | break; | ||
| 369 | if (!frag) | ||
| 370 | goto resubmit; | ||
| 371 | skb = frag->skb; | ||
| 372 | ptr = skb_put(skb, len); | ||
| 373 | if (ptr) | ||
| 374 | memcpy(ptr, data+8, len); | ||
| 375 | if (fc & IEEE80211_FCTL_MOREFRAGS) | ||
| 376 | goto resubmit; | ||
| 377 | hlist_del_init(&frag->fnode); | ||
| 378 | kfree(frag); | ||
| 379 | } else { | ||
| 380 | if (datalen<14) | ||
| 381 | goto resubmit; | ||
| 382 | skb = dev_alloc_skb(len + 14 + 2); | ||
| 383 | if (!skb) | ||
| 384 | goto resubmit; | ||
| 385 | skb_reserve(skb, 2); | ||
| 386 | memcpy(skb_put(skb, 12), &data[datalen-14], 12); | ||
| 387 | memcpy(skb_put(skb, 2), &data[6], 2); | ||
| 388 | memcpy(skb_put(skb, len), data+8, len); | ||
| 389 | } | ||
| 390 | skb->dev = zd->dev; | ||
| 391 | skb->dev->last_rx = jiffies; | ||
| 392 | skb->protocol = eth_type_trans(skb, zd->dev); | ||
| 393 | zd->stats.rx_packets++; | ||
| 394 | zd->stats.rx_bytes += skb->len; | ||
| 395 | netif_rx(skb); | ||
| 396 | } | ||
| 397 | resubmit: | ||
| 398 | memset(data, 0, ZD1201_RXSIZE); | ||
| 399 | |||
| 400 | urb->status = 0; | ||
| 401 | urb->dev = zd->usb; | ||
| 402 | if(usb_submit_urb(urb, GFP_ATOMIC)) | ||
| 403 | free = 1; | ||
| 404 | |||
| 405 | exit: | ||
| 406 | if (free) { | ||
| 407 | zd->rxlen = 0; | ||
| 408 | zd->rxdatas = 1; | ||
| 409 | wake_up(&zd->rxdataq); | ||
| 410 | kfree(urb->transfer_buffer); | ||
| 411 | } | ||
| 412 | return; | ||
| 413 | } | ||
| 414 | |||
| 415 | static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata, | ||
| 416 | unsigned int riddatalen) | ||
| 417 | { | ||
| 418 | int err; | ||
| 419 | int i = 0; | ||
| 420 | int code; | ||
| 421 | int rid_fid; | ||
| 422 | int length; | ||
| 423 | unsigned char *pdata; | ||
| 424 | |||
| 425 | zd->rxdatas = 0; | ||
| 426 | err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0); | ||
| 427 | if (err) | ||
| 428 | return err; | ||
| 429 | |||
| 430 | wait_event_interruptible(zd->rxdataq, zd->rxdatas); | ||
| 431 | if (!zd->rxlen) | ||
| 432 | return -EIO; | ||
| 433 | |||
| 434 | code = le16_to_cpu(*(__le16*)(&zd->rxdata[4])); | ||
| 435 | rid_fid = le16_to_cpu(*(__le16*)(&zd->rxdata[6])); | ||
| 436 | length = le16_to_cpu(*(__le16*)(&zd->rxdata[8])); | ||
| 437 | if (length > zd->rxlen) | ||
| 438 | length = zd->rxlen-6; | ||
| 439 | |||
| 440 | /* If access bit is not on, then error */ | ||
| 441 | if ((code & ZD1201_ACCESSBIT) != ZD1201_ACCESSBIT || rid_fid != rid ) | ||
| 442 | return -EINVAL; | ||
| 443 | |||
| 444 | /* Not enough buffer for allocating data */ | ||
| 445 | if (riddatalen != (length - 4)) { | ||
| 446 | dev_dbg(&zd->usb->dev, "riddatalen mismatches, expected=%u, (packet=%u) length=%u, rid=0x%04X, rid_fid=0x%04X\n", | ||
| 447 | riddatalen, zd->rxlen, length, rid, rid_fid); | ||
| 448 | return -ENODATA; | ||
| 449 | } | ||
| 450 | |||
| 451 | zd->rxdatas = 0; | ||
| 452 | /* Issue SetRxRid commnd */ | ||
| 453 | err = zd1201_docmd(zd, ZD1201_CMDCODE_SETRXRID, rid, 0, length); | ||
| 454 | if (err) | ||
| 455 | return err; | ||
| 456 | |||
| 457 | /* Receive RID record from resource packets */ | ||
| 458 | wait_event_interruptible(zd->rxdataq, zd->rxdatas); | ||
| 459 | if (!zd->rxlen) | ||
| 460 | return -EIO; | ||
| 461 | |||
| 462 | if (zd->rxdata[zd->rxlen - 1] != ZD1201_PACKET_RESOURCE) { | ||
| 463 | dev_dbg(&zd->usb->dev, "Packet type mismatch: 0x%x not 0x3\n", | ||
| 464 | zd->rxdata[zd->rxlen-1]); | ||
| 465 | return -EINVAL; | ||
| 466 | } | ||
| 467 | |||
| 468 | /* Set the data pointer and received data length */ | ||
| 469 | pdata = zd->rxdata; | ||
| 470 | length = zd->rxlen; | ||
| 471 | |||
| 472 | do { | ||
| 473 | int actual_length; | ||
| 474 | |||
| 475 | actual_length = (length > 64) ? 64 : length; | ||
| 476 | |||
| 477 | if (pdata[0] != 0x3) { | ||
| 478 | dev_dbg(&zd->usb->dev, "Rx Resource packet type error: %02X\n", | ||
| 479 | pdata[0]); | ||
| 480 | return -EINVAL; | ||
| 481 | } | ||
| 482 | |||
| 483 | if (actual_length != 64) { | ||
| 484 | /* Trim the last packet type byte */ | ||
| 485 | actual_length--; | ||
| 486 | } | ||
| 487 | |||
| 488 | /* Skip the 4 bytes header (RID length and RID) */ | ||
| 489 | if (i == 0) { | ||
| 490 | pdata += 8; | ||
| 491 | actual_length -= 8; | ||
| 492 | } else { | ||
| 493 | pdata += 4; | ||
| 494 | actual_length -= 4; | ||
| 495 | } | ||
| 496 | |||
| 497 | memcpy(riddata, pdata, actual_length); | ||
| 498 | riddata += actual_length; | ||
| 499 | pdata += actual_length; | ||
| 500 | length -= 64; | ||
| 501 | i++; | ||
| 502 | } while (length > 0); | ||
| 503 | |||
| 504 | return 0; | ||
| 505 | } | ||
| 506 | |||
| 507 | /* | ||
| 508 | * resreq: | ||
| 509 | * byte type | ||
| 510 | * byte sequence | ||
| 511 | * u16 reserved | ||
| 512 | * byte data[12] | ||
| 513 | * total: 16 | ||
| 514 | */ | ||
| 515 | static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int wait) | ||
| 516 | { | ||
| 517 | int err; | ||
| 518 | unsigned char *request; | ||
| 519 | int reqlen; | ||
| 520 | char seq=0; | ||
| 521 | struct urb *urb; | ||
| 522 | gfp_t gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC; | ||
| 523 | |||
| 524 | len += 4; /* first 4 are for header */ | ||
| 525 | |||
| 526 | zd->rxdatas = 0; | ||
| 527 | zd->rxlen = 0; | ||
| 528 | for (seq=0; len > 0; seq++) { | ||
| 529 | request = kmalloc(16, gfp_mask); | ||
| 530 | if (!request) | ||
| 531 | return -ENOMEM; | ||
| 532 | urb = usb_alloc_urb(0, gfp_mask); | ||
| 533 | if (!urb) { | ||
| 534 | kfree(request); | ||
| 535 | return -ENOMEM; | ||
| 536 | } | ||
| 537 | memset(request, 0, 16); | ||
| 538 | reqlen = len>12 ? 12 : len; | ||
| 539 | request[0] = ZD1201_USB_RESREQ; | ||
| 540 | request[1] = seq; | ||
| 541 | request[2] = 0; | ||
| 542 | request[3] = 0; | ||
| 543 | if (request[1] == 0) { | ||
| 544 | /* add header */ | ||
| 545 | *(__le16*)&request[4] = cpu_to_le16((len-2+1)/2); | ||
| 546 | *(__le16*)&request[6] = cpu_to_le16(rid); | ||
| 547 | memcpy(request+8, buf, reqlen-4); | ||
| 548 | buf += reqlen-4; | ||
| 549 | } else { | ||
| 550 | memcpy(request+4, buf, reqlen); | ||
| 551 | buf += reqlen; | ||
| 552 | } | ||
| 553 | |||
| 554 | len -= reqlen; | ||
| 555 | |||
| 556 | usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, | ||
| 557 | zd->endp_out2), request, 16, zd1201_usbfree, zd); | ||
| 558 | err = usb_submit_urb(urb, gfp_mask); | ||
| 559 | if (err) | ||
| 560 | goto err; | ||
| 561 | } | ||
| 562 | |||
| 563 | request = kmalloc(16, gfp_mask); | ||
| 564 | if (!request) | ||
| 565 | return -ENOMEM; | ||
| 566 | urb = usb_alloc_urb(0, gfp_mask); | ||
| 567 | if (!urb) { | ||
| 568 | kfree(request); | ||
| 569 | return -ENOMEM; | ||
| 570 | } | ||
| 571 | *((__le32*)request) = cpu_to_le32(ZD1201_USB_CMDREQ); | ||
| 572 | *((__le16*)&request[4]) = | ||
| 573 | cpu_to_le16(ZD1201_CMDCODE_ACCESS|ZD1201_ACCESSBIT); | ||
| 574 | *((__le16*)&request[6]) = cpu_to_le16(rid); | ||
| 575 | *((__le16*)&request[8]) = cpu_to_le16(0); | ||
| 576 | *((__le16*)&request[10]) = cpu_to_le16(0); | ||
| 577 | usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), | ||
| 578 | request, 16, zd1201_usbfree, zd); | ||
| 579 | err = usb_submit_urb(urb, gfp_mask); | ||
| 580 | if (err) | ||
| 581 | goto err; | ||
| 582 | |||
| 583 | if (wait) { | ||
| 584 | wait_event_interruptible(zd->rxdataq, zd->rxdatas); | ||
| 585 | if (!zd->rxlen || le16_to_cpu(*(__le16*)&zd->rxdata[6]) != rid) { | ||
| 586 | dev_dbg(&zd->usb->dev, "wrong or no RID received\n"); | ||
| 587 | } | ||
| 588 | } | ||
| 589 | |||
| 590 | return 0; | ||
| 591 | err: | ||
| 592 | kfree(request); | ||
| 593 | usb_free_urb(urb); | ||
| 594 | return err; | ||
| 595 | } | ||
| 596 | |||
| 597 | static inline int zd1201_getconfig16(struct zd1201 *zd, int rid, short *val) | ||
| 598 | { | ||
| 599 | int err; | ||
| 600 | __le16 zdval; | ||
| 601 | |||
| 602 | err = zd1201_getconfig(zd, rid, &zdval, sizeof(__le16)); | ||
| 603 | if (err) | ||
| 604 | return err; | ||
| 605 | *val = le16_to_cpu(zdval); | ||
| 606 | return 0; | ||
| 607 | } | ||
| 608 | |||
| 609 | static inline int zd1201_setconfig16(struct zd1201 *zd, int rid, short val) | ||
| 610 | { | ||
| 611 | __le16 zdval = cpu_to_le16(val); | ||
| 612 | return (zd1201_setconfig(zd, rid, &zdval, sizeof(__le16), 1)); | ||
| 613 | } | ||
| 614 | |||
| 615 | static int zd1201_drvr_start(struct zd1201 *zd) | ||
| 616 | { | ||
| 617 | int err, i; | ||
| 618 | short max; | ||
| 619 | __le16 zdmax; | ||
| 620 | unsigned char *buffer; | ||
| 621 | |||
| 622 | buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL); | ||
| 623 | if (!buffer) | ||
| 624 | return -ENOMEM; | ||
| 625 | |||
| 626 | usb_fill_bulk_urb(zd->rx_urb, zd->usb, | ||
| 627 | usb_rcvbulkpipe(zd->usb, zd->endp_in), buffer, ZD1201_RXSIZE, | ||
| 628 | zd1201_usbrx, zd); | ||
| 629 | |||
| 630 | err = usb_submit_urb(zd->rx_urb, GFP_KERNEL); | ||
| 631 | if (err) | ||
| 632 | goto err_buffer; | ||
| 633 | |||
| 634 | err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); | ||
| 635 | if (err) | ||
| 636 | goto err_urb; | ||
| 637 | |||
| 638 | err = zd1201_getconfig(zd, ZD1201_RID_CNFMAXTXBUFFERNUMBER, &zdmax, | ||
| 639 | sizeof(__le16)); | ||
| 640 | if (err) | ||
| 641 | goto err_urb; | ||
| 642 | |||
| 643 | max = le16_to_cpu(zdmax); | ||
| 644 | for (i=0; i<max; i++) { | ||
| 645 | err = zd1201_docmd(zd, ZD1201_CMDCODE_ALLOC, 1514, 0, 0); | ||
| 646 | if (err) | ||
| 647 | goto err_urb; | ||
| 648 | } | ||
| 649 | |||
| 650 | return 0; | ||
| 651 | |||
| 652 | err_urb: | ||
| 653 | usb_kill_urb(zd->rx_urb); | ||
| 654 | return err; | ||
| 655 | err_buffer: | ||
| 656 | kfree(buffer); | ||
| 657 | return err; | ||
| 658 | } | ||
| 659 | |||
| 660 | /* Magic alert: The firmware doesn't seem to like the MAC state being | ||
| 661 | * toggled in promisc (aka monitor) mode. | ||
| 662 | * (It works a number of times, but will halt eventually) | ||
| 663 | * So we turn it of before disabling and on after enabling if needed. | ||
| 664 | */ | ||
| 665 | static int zd1201_enable(struct zd1201 *zd) | ||
| 666 | { | ||
| 667 | int err; | ||
| 668 | |||
| 669 | if (zd->mac_enabled) | ||
| 670 | return 0; | ||
| 671 | |||
| 672 | err = zd1201_docmd(zd, ZD1201_CMDCODE_ENABLE, 0, 0, 0); | ||
| 673 | if (!err) | ||
| 674 | zd->mac_enabled = 1; | ||
| 675 | |||
| 676 | if (zd->monitor) | ||
| 677 | err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 1); | ||
| 678 | |||
| 679 | return err; | ||
| 680 | } | ||
| 681 | |||
| 682 | static int zd1201_disable(struct zd1201 *zd) | ||
| 683 | { | ||
| 684 | int err; | ||
| 685 | |||
| 686 | if (!zd->mac_enabled) | ||
| 687 | return 0; | ||
| 688 | if (zd->monitor) { | ||
| 689 | err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); | ||
| 690 | if (err) | ||
| 691 | return err; | ||
| 692 | } | ||
| 693 | |||
| 694 | err = zd1201_docmd(zd, ZD1201_CMDCODE_DISABLE, 0, 0, 0); | ||
| 695 | if (!err) | ||
| 696 | zd->mac_enabled = 0; | ||
| 697 | return err; | ||
| 698 | } | ||
| 699 | |||
| 700 | static int zd1201_mac_reset(struct zd1201 *zd) | ||
| 701 | { | ||
| 702 | if (!zd->mac_enabled) | ||
| 703 | return 0; | ||
| 704 | zd1201_disable(zd); | ||
| 705 | return zd1201_enable(zd); | ||
| 706 | } | ||
| 707 | |||
| 708 | static int zd1201_join(struct zd1201 *zd, char *essid, int essidlen) | ||
| 709 | { | ||
| 710 | int err, val; | ||
| 711 | char buf[IW_ESSID_MAX_SIZE+2]; | ||
| 712 | |||
| 713 | err = zd1201_disable(zd); | ||
| 714 | if (err) | ||
| 715 | return err; | ||
| 716 | |||
| 717 | val = ZD1201_CNFAUTHENTICATION_OPENSYSTEM; | ||
| 718 | val |= ZD1201_CNFAUTHENTICATION_SHAREDKEY; | ||
| 719 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, val); | ||
| 720 | if (err) | ||
| 721 | return err; | ||
| 722 | |||
| 723 | *(__le16 *)buf = cpu_to_le16(essidlen); | ||
| 724 | memcpy(buf+2, essid, essidlen); | ||
| 725 | if (!zd->ap) { /* Normal station */ | ||
| 726 | err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, | ||
| 727 | IW_ESSID_MAX_SIZE+2, 1); | ||
| 728 | if (err) | ||
| 729 | return err; | ||
| 730 | } else { /* AP */ | ||
| 731 | err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNSSID, buf, | ||
| 732 | IW_ESSID_MAX_SIZE+2, 1); | ||
| 733 | if (err) | ||
| 734 | return err; | ||
| 735 | } | ||
| 736 | |||
| 737 | err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, | ||
| 738 | zd->dev->dev_addr, zd->dev->addr_len, 1); | ||
| 739 | if (err) | ||
| 740 | return err; | ||
| 741 | |||
| 742 | err = zd1201_enable(zd); | ||
| 743 | if (err) | ||
| 744 | return err; | ||
| 745 | |||
| 746 | msleep(100); | ||
| 747 | return 0; | ||
| 748 | } | ||
| 749 | |||
| 750 | static int zd1201_net_open(struct net_device *dev) | ||
| 751 | { | ||
| 752 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 753 | |||
| 754 | /* Start MAC with wildcard if no essid set */ | ||
| 755 | if (!zd->mac_enabled) | ||
| 756 | zd1201_join(zd, zd->essid, zd->essidlen); | ||
| 757 | netif_start_queue(dev); | ||
| 758 | |||
| 759 | return 0; | ||
| 760 | } | ||
| 761 | |||
| 762 | static int zd1201_net_stop(struct net_device *dev) | ||
| 763 | { | ||
| 764 | netif_stop_queue(dev); | ||
| 765 | return 0; | ||
| 766 | } | ||
| 767 | |||
| 768 | /* | ||
| 769 | RFC 1042 encapsulates Ethernet frames in 802.11 frames | ||
| 770 | by prefixing them with 0xaa, 0xaa, 0x03) followed by a SNAP OID of 0 | ||
| 771 | (0x00, 0x00, 0x00). Zd requires an additional padding, copy | ||
| 772 | of ethernet addresses, length of the standard RFC 1042 packet | ||
| 773 | and a command byte (which is nul for tx). | ||
| 774 | |||
| 775 | tx frame (from Wlan NG): | ||
| 776 | RFC 1042: | ||
| 777 | llc 0xAA 0xAA 0x03 (802.2 LLC) | ||
| 778 | snap 0x00 0x00 0x00 (Ethernet encapsulated) | ||
| 779 | type 2 bytes, Ethernet type field | ||
| 780 | payload (minus eth header) | ||
| 781 | Zydas specific: | ||
| 782 | padding 1B if (skb->len+8+1)%64==0 | ||
| 783 | Eth MAC addr 12 bytes, Ethernet MAC addresses | ||
| 784 | length 2 bytes, RFC 1042 packet length | ||
| 785 | (llc+snap+type+payload) | ||
| 786 | zd 1 null byte, zd1201 packet type | ||
| 787 | */ | ||
| 788 | static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
| 789 | { | ||
| 790 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 791 | unsigned char *txbuf = zd->txdata; | ||
| 792 | int txbuflen, pad = 0, err; | ||
| 793 | struct urb *urb = zd->tx_urb; | ||
| 794 | |||
| 795 | if (!zd->mac_enabled || zd->monitor) { | ||
| 796 | zd->stats.tx_dropped++; | ||
| 797 | kfree_skb(skb); | ||
| 798 | return 0; | ||
| 799 | } | ||
| 800 | netif_stop_queue(dev); | ||
| 801 | |||
| 802 | txbuflen = skb->len + 8 + 1; | ||
| 803 | if (txbuflen%64 == 0) { | ||
| 804 | pad = 1; | ||
| 805 | txbuflen++; | ||
| 806 | } | ||
| 807 | txbuf[0] = 0xAA; | ||
| 808 | txbuf[1] = 0xAA; | ||
| 809 | txbuf[2] = 0x03; | ||
| 810 | txbuf[3] = 0x00; /* rfc1042 */ | ||
| 811 | txbuf[4] = 0x00; | ||
| 812 | txbuf[5] = 0x00; | ||
| 813 | |||
| 814 | memcpy(txbuf+6, skb->data+12, skb->len-12); | ||
| 815 | if (pad) | ||
| 816 | txbuf[skb->len-12+6]=0; | ||
| 817 | memcpy(txbuf+skb->len-12+6+pad, skb->data, 12); | ||
| 818 | *(__be16*)&txbuf[skb->len+6+pad] = htons(skb->len-12+6); | ||
| 819 | txbuf[txbuflen-1] = 0; | ||
| 820 | |||
| 821 | usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out), | ||
| 822 | txbuf, txbuflen, zd1201_usbtx, zd); | ||
| 823 | |||
| 824 | err = usb_submit_urb(zd->tx_urb, GFP_ATOMIC); | ||
| 825 | if (err) { | ||
| 826 | zd->stats.tx_errors++; | ||
| 827 | netif_start_queue(dev); | ||
| 828 | return err; | ||
| 829 | } | ||
| 830 | zd->stats.tx_packets++; | ||
| 831 | zd->stats.tx_bytes += skb->len; | ||
| 832 | dev->trans_start = jiffies; | ||
| 833 | kfree_skb(skb); | ||
| 834 | |||
| 835 | return 0; | ||
| 836 | } | ||
| 837 | |||
| 838 | static void zd1201_tx_timeout(struct net_device *dev) | ||
| 839 | { | ||
| 840 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 841 | |||
| 842 | if (!zd) | ||
| 843 | return; | ||
| 844 | dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n", | ||
| 845 | dev->name); | ||
| 846 | usb_unlink_urb(zd->tx_urb); | ||
| 847 | zd->stats.tx_errors++; | ||
| 848 | /* Restart the timeout to quiet the watchdog: */ | ||
| 849 | dev->trans_start = jiffies; | ||
| 850 | } | ||
| 851 | |||
| 852 | static int zd1201_set_mac_address(struct net_device *dev, void *p) | ||
| 853 | { | ||
| 854 | struct sockaddr *addr = p; | ||
| 855 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 856 | int err; | ||
| 857 | |||
| 858 | if (!zd) | ||
| 859 | return -ENODEV; | ||
| 860 | |||
| 861 | err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, | ||
| 862 | addr->sa_data, dev->addr_len, 1); | ||
| 863 | if (err) | ||
| 864 | return err; | ||
| 865 | memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); | ||
| 866 | |||
| 867 | return zd1201_mac_reset(zd); | ||
| 868 | } | ||
| 869 | |||
| 870 | static struct net_device_stats *zd1201_get_stats(struct net_device *dev) | ||
| 871 | { | ||
| 872 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 873 | |||
| 874 | return &zd->stats; | ||
| 875 | } | ||
| 876 | |||
| 877 | static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev) | ||
| 878 | { | ||
| 879 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 880 | |||
| 881 | return &zd->iwstats; | ||
| 882 | } | ||
| 883 | |||
| 884 | static void zd1201_set_multicast(struct net_device *dev) | ||
| 885 | { | ||
| 886 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 887 | struct dev_mc_list *mc = dev->mc_list; | ||
| 888 | unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI]; | ||
| 889 | int i; | ||
| 890 | |||
| 891 | if (dev->mc_count > ZD1201_MAXMULTI) | ||
| 892 | return; | ||
| 893 | |||
| 894 | for (i=0; i<dev->mc_count; i++) { | ||
| 895 | memcpy(reqbuf+i*ETH_ALEN, mc->dmi_addr, ETH_ALEN); | ||
| 896 | mc = mc->next; | ||
| 897 | } | ||
| 898 | zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf, | ||
| 899 | dev->mc_count*ETH_ALEN, 0); | ||
| 900 | |||
| 901 | } | ||
| 902 | |||
| 903 | static int zd1201_config_commit(struct net_device *dev, | ||
| 904 | struct iw_request_info *info, struct iw_point *data, char *essid) | ||
| 905 | { | ||
| 906 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 907 | |||
| 908 | return zd1201_mac_reset(zd); | ||
| 909 | } | ||
| 910 | |||
| 911 | static int zd1201_get_name(struct net_device *dev, | ||
| 912 | struct iw_request_info *info, char *name, char *extra) | ||
| 913 | { | ||
| 914 | strcpy(name, "IEEE 802.11b"); | ||
| 915 | return 0; | ||
| 916 | } | ||
| 917 | |||
| 918 | static int zd1201_set_freq(struct net_device *dev, | ||
| 919 | struct iw_request_info *info, struct iw_freq *freq, char *extra) | ||
| 920 | { | ||
| 921 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 922 | short channel = 0; | ||
| 923 | int err; | ||
| 924 | |||
| 925 | if (freq->e == 0) | ||
| 926 | channel = freq->m; | ||
| 927 | else { | ||
| 928 | if (freq->m >= 2482) | ||
| 929 | channel = 14; | ||
| 930 | if (freq->m >= 2407) | ||
| 931 | channel = (freq->m-2407)/5; | ||
| 932 | } | ||
| 933 | |||
| 934 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel); | ||
| 935 | if (err) | ||
| 936 | return err; | ||
| 937 | |||
| 938 | zd1201_mac_reset(zd); | ||
| 939 | |||
| 940 | return 0; | ||
| 941 | } | ||
| 942 | |||
| 943 | static int zd1201_get_freq(struct net_device *dev, | ||
| 944 | struct iw_request_info *info, struct iw_freq *freq, char *extra) | ||
| 945 | { | ||
| 946 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 947 | short channel; | ||
| 948 | int err; | ||
| 949 | |||
| 950 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, &channel); | ||
| 951 | if (err) | ||
| 952 | return err; | ||
| 953 | freq->e = 0; | ||
| 954 | freq->m = channel; | ||
| 955 | |||
| 956 | return 0; | ||
| 957 | } | ||
| 958 | |||
| 959 | static int zd1201_set_mode(struct net_device *dev, | ||
| 960 | struct iw_request_info *info, __u32 *mode, char *extra) | ||
| 961 | { | ||
| 962 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 963 | short porttype, monitor = 0; | ||
| 964 | unsigned char buffer[IW_ESSID_MAX_SIZE+2]; | ||
| 965 | int err; | ||
| 966 | |||
| 967 | if (zd->ap) { | ||
| 968 | if (*mode != IW_MODE_MASTER) | ||
| 969 | return -EINVAL; | ||
| 970 | return 0; | ||
| 971 | } | ||
| 972 | |||
| 973 | err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); | ||
| 974 | if (err) | ||
| 975 | return err; | ||
| 976 | zd->dev->type = ARPHRD_ETHER; | ||
| 977 | switch(*mode) { | ||
| 978 | case IW_MODE_MONITOR: | ||
| 979 | monitor = 1; | ||
| 980 | zd->dev->type = ARPHRD_IEEE80211; | ||
| 981 | /* Make sure we are no longer associated with by | ||
| 982 | setting an 'impossible' essid. | ||
| 983 | (otherwise we mess up firmware) | ||
| 984 | */ | ||
| 985 | zd1201_join(zd, "\0-*#\0", 5); | ||
| 986 | /* Put port in pIBSS */ | ||
| 987 | case 8: /* No pseudo-IBSS in wireless extensions (yet) */ | ||
| 988 | porttype = ZD1201_PORTTYPE_PSEUDOIBSS; | ||
| 989 | break; | ||
| 990 | case IW_MODE_ADHOC: | ||
| 991 | porttype = ZD1201_PORTTYPE_IBSS; | ||
| 992 | break; | ||
| 993 | case IW_MODE_INFRA: | ||
| 994 | porttype = ZD1201_PORTTYPE_BSS; | ||
| 995 | break; | ||
| 996 | default: | ||
| 997 | return -EINVAL; | ||
| 998 | } | ||
| 999 | |||
| 1000 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); | ||
| 1001 | if (err) | ||
| 1002 | return err; | ||
| 1003 | if (zd->monitor && !monitor) { | ||
| 1004 | zd1201_disable(zd); | ||
| 1005 | *(__le16 *)buffer = cpu_to_le16(zd->essidlen); | ||
| 1006 | memcpy(buffer+2, zd->essid, zd->essidlen); | ||
| 1007 | err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, | ||
| 1008 | buffer, IW_ESSID_MAX_SIZE+2, 1); | ||
| 1009 | if (err) | ||
| 1010 | return err; | ||
| 1011 | } | ||
| 1012 | zd->monitor = monitor; | ||
| 1013 | /* If monitor mode is set we don't actually turn it on here since it | ||
| 1014 | * is done during mac reset anyway (see zd1201_mac_enable). | ||
| 1015 | */ | ||
| 1016 | zd1201_mac_reset(zd); | ||
| 1017 | |||
| 1018 | return 0; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | static int zd1201_get_mode(struct net_device *dev, | ||
| 1022 | struct iw_request_info *info, __u32 *mode, char *extra) | ||
| 1023 | { | ||
| 1024 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1025 | short porttype; | ||
| 1026 | int err; | ||
| 1027 | |||
| 1028 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFPORTTYPE, &porttype); | ||
| 1029 | if (err) | ||
| 1030 | return err; | ||
| 1031 | switch(porttype) { | ||
| 1032 | case ZD1201_PORTTYPE_IBSS: | ||
| 1033 | *mode = IW_MODE_ADHOC; | ||
| 1034 | break; | ||
| 1035 | case ZD1201_PORTTYPE_BSS: | ||
| 1036 | *mode = IW_MODE_INFRA; | ||
| 1037 | break; | ||
| 1038 | case ZD1201_PORTTYPE_WDS: | ||
| 1039 | *mode = IW_MODE_REPEAT; | ||
| 1040 | break; | ||
| 1041 | case ZD1201_PORTTYPE_PSEUDOIBSS: | ||
| 1042 | *mode = 8;/* No Pseudo-IBSS... */ | ||
| 1043 | break; | ||
| 1044 | case ZD1201_PORTTYPE_AP: | ||
| 1045 | *mode = IW_MODE_MASTER; | ||
| 1046 | break; | ||
| 1047 | default: | ||
| 1048 | dev_dbg(&zd->usb->dev, "Unknown porttype: %d\n", | ||
| 1049 | porttype); | ||
| 1050 | *mode = IW_MODE_AUTO; | ||
| 1051 | } | ||
| 1052 | if (zd->monitor) | ||
| 1053 | *mode = IW_MODE_MONITOR; | ||
| 1054 | |||
| 1055 | return 0; | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | static int zd1201_get_range(struct net_device *dev, | ||
| 1059 | struct iw_request_info *info, struct iw_point *wrq, char *extra) | ||
| 1060 | { | ||
| 1061 | struct iw_range *range = (struct iw_range *)extra; | ||
| 1062 | |||
| 1063 | wrq->length = sizeof(struct iw_range); | ||
| 1064 | memset(range, 0, sizeof(struct iw_range)); | ||
| 1065 | range->we_version_compiled = WIRELESS_EXT; | ||
| 1066 | range->we_version_source = WIRELESS_EXT; | ||
| 1067 | |||
| 1068 | range->max_qual.qual = 128; | ||
| 1069 | range->max_qual.level = 128; | ||
| 1070 | range->max_qual.noise = 128; | ||
| 1071 | range->max_qual.updated = 7; | ||
| 1072 | |||
| 1073 | range->encoding_size[0] = 5; | ||
| 1074 | range->encoding_size[1] = 13; | ||
| 1075 | range->num_encoding_sizes = 2; | ||
| 1076 | range->max_encoding_tokens = ZD1201_NUMKEYS; | ||
| 1077 | |||
| 1078 | range->num_bitrates = 4; | ||
| 1079 | range->bitrate[0] = 1000000; | ||
| 1080 | range->bitrate[1] = 2000000; | ||
| 1081 | range->bitrate[2] = 5500000; | ||
| 1082 | range->bitrate[3] = 11000000; | ||
| 1083 | |||
| 1084 | range->min_rts = 0; | ||
| 1085 | range->min_frag = ZD1201_FRAGMIN; | ||
| 1086 | range->max_rts = ZD1201_RTSMAX; | ||
| 1087 | range->min_frag = ZD1201_FRAGMAX; | ||
| 1088 | |||
| 1089 | return 0; | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | /* Little bit of magic here: we only get the quality if we poll | ||
| 1093 | * for it, and we never get an actual request to trigger such | ||
| 1094 | * a poll. Therefore we 'assume' that the user will soon ask for | ||
| 1095 | * the stats after asking the bssid. | ||
| 1096 | */ | ||
| 1097 | static int zd1201_get_wap(struct net_device *dev, | ||
| 1098 | struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) | ||
| 1099 | { | ||
| 1100 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1101 | unsigned char buffer[6]; | ||
| 1102 | |||
| 1103 | if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) { | ||
| 1104 | /* Unfortunately the quality and noise reported is useless. | ||
| 1105 | they seem to be accumulators that increase until you | ||
| 1106 | read them, unless we poll on a fixed interval we can't | ||
| 1107 | use them | ||
| 1108 | */ | ||
| 1109 | /*zd->iwstats.qual.qual = le16_to_cpu(((__le16 *)buffer)[0]);*/ | ||
| 1110 | zd->iwstats.qual.level = le16_to_cpu(((__le16 *)buffer)[1]); | ||
| 1111 | /*zd->iwstats.qual.noise = le16_to_cpu(((__le16 *)buffer)[2]);*/ | ||
| 1112 | zd->iwstats.qual.updated = 2; | ||
| 1113 | } | ||
| 1114 | |||
| 1115 | return zd1201_getconfig(zd, ZD1201_RID_CURRENTBSSID, ap_addr->sa_data, 6); | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | static int zd1201_set_scan(struct net_device *dev, | ||
| 1119 | struct iw_request_info *info, struct iw_point *srq, char *extra) | ||
| 1120 | { | ||
| 1121 | /* We do everything in get_scan */ | ||
| 1122 | return 0; | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | static int zd1201_get_scan(struct net_device *dev, | ||
| 1126 | struct iw_request_info *info, struct iw_point *srq, char *extra) | ||
| 1127 | { | ||
| 1128 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1129 | int err, i, j, enabled_save; | ||
| 1130 | struct iw_event iwe; | ||
| 1131 | char *cev = extra; | ||
| 1132 | char *end_buf = extra + IW_SCAN_MAX_DATA; | ||
| 1133 | |||
| 1134 | /* No scanning in AP mode */ | ||
| 1135 | if (zd->ap) | ||
| 1136 | return -EOPNOTSUPP; | ||
| 1137 | |||
| 1138 | /* Scan doesn't seem to work if disabled */ | ||
| 1139 | enabled_save = zd->mac_enabled; | ||
| 1140 | zd1201_enable(zd); | ||
| 1141 | |||
| 1142 | zd->rxdatas = 0; | ||
| 1143 | err = zd1201_docmd(zd, ZD1201_CMDCODE_INQUIRE, | ||
| 1144 | ZD1201_INQ_SCANRESULTS, 0, 0); | ||
| 1145 | if (err) | ||
| 1146 | return err; | ||
| 1147 | |||
| 1148 | wait_event_interruptible(zd->rxdataq, zd->rxdatas); | ||
| 1149 | if (!zd->rxlen) | ||
| 1150 | return -EIO; | ||
| 1151 | |||
| 1152 | if (le16_to_cpu(*(__le16*)&zd->rxdata[2]) != ZD1201_INQ_SCANRESULTS) | ||
| 1153 | return -EIO; | ||
| 1154 | |||
| 1155 | for(i=8; i<zd->rxlen; i+=62) { | ||
| 1156 | iwe.cmd = SIOCGIWAP; | ||
| 1157 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | ||
| 1158 | memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6); | ||
| 1159 | cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN); | ||
| 1160 | |||
| 1161 | iwe.cmd = SIOCGIWESSID; | ||
| 1162 | iwe.u.data.length = zd->rxdata[i+16]; | ||
| 1163 | iwe.u.data.flags = 1; | ||
| 1164 | cev = iwe_stream_add_point(cev, end_buf, &iwe, zd->rxdata+i+18); | ||
| 1165 | |||
| 1166 | iwe.cmd = SIOCGIWMODE; | ||
| 1167 | if (zd->rxdata[i+14]&0x01) | ||
| 1168 | iwe.u.mode = IW_MODE_MASTER; | ||
| 1169 | else | ||
| 1170 | iwe.u.mode = IW_MODE_ADHOC; | ||
| 1171 | cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN); | ||
| 1172 | |||
| 1173 | iwe.cmd = SIOCGIWFREQ; | ||
| 1174 | iwe.u.freq.m = zd->rxdata[i+0]; | ||
| 1175 | iwe.u.freq.e = 0; | ||
| 1176 | cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN); | ||
| 1177 | |||
| 1178 | iwe.cmd = SIOCGIWRATE; | ||
| 1179 | iwe.u.bitrate.fixed = 0; | ||
| 1180 | iwe.u.bitrate.disabled = 0; | ||
| 1181 | for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) { | ||
| 1182 | iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000; | ||
| 1183 | cev=iwe_stream_add_event(cev, end_buf, &iwe, | ||
| 1184 | IW_EV_PARAM_LEN); | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | iwe.cmd = SIOCGIWENCODE; | ||
| 1188 | iwe.u.data.length = 0; | ||
| 1189 | if (zd->rxdata[i+14]&0x10) | ||
| 1190 | iwe.u.data.flags = IW_ENCODE_ENABLED; | ||
| 1191 | else | ||
| 1192 | iwe.u.data.flags = IW_ENCODE_DISABLED; | ||
| 1193 | cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL); | ||
| 1194 | |||
| 1195 | iwe.cmd = IWEVQUAL; | ||
| 1196 | iwe.u.qual.qual = zd->rxdata[i+4]; | ||
| 1197 | iwe.u.qual.noise= zd->rxdata[i+2]/10-100; | ||
| 1198 | iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100; | ||
| 1199 | iwe.u.qual.updated = 7; | ||
| 1200 | cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN); | ||
| 1201 | } | ||
| 1202 | |||
| 1203 | if (!enabled_save) | ||
| 1204 | zd1201_disable(zd); | ||
| 1205 | |||
| 1206 | srq->length = cev - extra; | ||
| 1207 | srq->flags = 0; | ||
| 1208 | |||
| 1209 | return 0; | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | static int zd1201_set_essid(struct net_device *dev, | ||
| 1213 | struct iw_request_info *info, struct iw_point *data, char *essid) | ||
| 1214 | { | ||
| 1215 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1216 | |||
| 1217 | if (data->length > IW_ESSID_MAX_SIZE) | ||
| 1218 | return -EINVAL; | ||
| 1219 | if (data->length < 1) | ||
| 1220 | data->length = 1; | ||
| 1221 | zd->essidlen = data->length-1; | ||
| 1222 | memset(zd->essid, 0, IW_ESSID_MAX_SIZE+1); | ||
| 1223 | memcpy(zd->essid, essid, data->length); | ||
| 1224 | return zd1201_join(zd, zd->essid, zd->essidlen); | ||
| 1225 | } | ||
| 1226 | |||
| 1227 | static int zd1201_get_essid(struct net_device *dev, | ||
| 1228 | struct iw_request_info *info, struct iw_point *data, char *essid) | ||
| 1229 | { | ||
| 1230 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1231 | |||
| 1232 | memcpy(essid, zd->essid, zd->essidlen); | ||
| 1233 | data->flags = 1; | ||
| 1234 | data->length = zd->essidlen; | ||
| 1235 | |||
| 1236 | return 0; | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info, | ||
| 1240 | struct iw_point *data, char *nick) | ||
| 1241 | { | ||
| 1242 | strcpy(nick, "zd1201"); | ||
| 1243 | data->flags = 1; | ||
| 1244 | data->length = strlen(nick); | ||
| 1245 | return 0; | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | static int zd1201_set_rate(struct net_device *dev, | ||
| 1249 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | ||
| 1250 | { | ||
| 1251 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1252 | short rate; | ||
| 1253 | int err; | ||
| 1254 | |||
| 1255 | switch (rrq->value) { | ||
| 1256 | case 1000000: | ||
| 1257 | rate = ZD1201_RATEB1; | ||
| 1258 | break; | ||
| 1259 | case 2000000: | ||
| 1260 | rate = ZD1201_RATEB2; | ||
| 1261 | break; | ||
| 1262 | case 5500000: | ||
| 1263 | rate = ZD1201_RATEB5; | ||
| 1264 | break; | ||
| 1265 | case 11000000: | ||
| 1266 | default: | ||
| 1267 | rate = ZD1201_RATEB11; | ||
| 1268 | break; | ||
| 1269 | } | ||
| 1270 | if (!rrq->fixed) { /* Also enable all lower bitrates */ | ||
| 1271 | rate |= rate-1; | ||
| 1272 | } | ||
| 1273 | |||
| 1274 | err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate); | ||
| 1275 | if (err) | ||
| 1276 | return err; | ||
| 1277 | |||
| 1278 | return zd1201_mac_reset(zd); | ||
| 1279 | } | ||
| 1280 | |||
| 1281 | static int zd1201_get_rate(struct net_device *dev, | ||
| 1282 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | ||
| 1283 | { | ||
| 1284 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1285 | short rate; | ||
| 1286 | int err; | ||
| 1287 | |||
| 1288 | err = zd1201_getconfig16(zd, ZD1201_RID_CURRENTTXRATE, &rate); | ||
| 1289 | if (err) | ||
| 1290 | return err; | ||
| 1291 | |||
| 1292 | switch(rate) { | ||
| 1293 | case 1: | ||
| 1294 | rrq->value = 1000000; | ||
| 1295 | break; | ||
| 1296 | case 2: | ||
| 1297 | rrq->value = 2000000; | ||
| 1298 | break; | ||
| 1299 | case 5: | ||
| 1300 | rrq->value = 5500000; | ||
| 1301 | break; | ||
| 1302 | case 11: | ||
| 1303 | rrq->value = 11000000; | ||
| 1304 | break; | ||
| 1305 | default: | ||
| 1306 | rrq->value = 0; | ||
| 1307 | } | ||
| 1308 | rrq->fixed = 0; | ||
| 1309 | rrq->disabled = 0; | ||
| 1310 | |||
| 1311 | return 0; | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info, | ||
| 1315 | struct iw_param *rts, char *extra) | ||
| 1316 | { | ||
| 1317 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1318 | int err; | ||
| 1319 | short val = rts->value; | ||
| 1320 | |||
| 1321 | if (rts->disabled || !rts->fixed) | ||
| 1322 | val = ZD1201_RTSMAX; | ||
| 1323 | if (val > ZD1201_RTSMAX) | ||
| 1324 | return -EINVAL; | ||
| 1325 | if (val < 0) | ||
| 1326 | return -EINVAL; | ||
| 1327 | |||
| 1328 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, val); | ||
| 1329 | if (err) | ||
| 1330 | return err; | ||
| 1331 | return zd1201_mac_reset(zd); | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info, | ||
| 1335 | struct iw_param *rts, char *extra) | ||
| 1336 | { | ||
| 1337 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1338 | short rtst; | ||
| 1339 | int err; | ||
| 1340 | |||
| 1341 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, &rtst); | ||
| 1342 | if (err) | ||
| 1343 | return err; | ||
| 1344 | rts->value = rtst; | ||
| 1345 | rts->disabled = (rts->value == ZD1201_RTSMAX); | ||
| 1346 | rts->fixed = 1; | ||
| 1347 | |||
| 1348 | return 0; | ||
| 1349 | } | ||
| 1350 | |||
| 1351 | static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info, | ||
| 1352 | struct iw_param *frag, char *extra) | ||
| 1353 | { | ||
| 1354 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1355 | int err; | ||
| 1356 | short val = frag->value; | ||
| 1357 | |||
| 1358 | if (frag->disabled || !frag->fixed) | ||
| 1359 | val = ZD1201_FRAGMAX; | ||
| 1360 | if (val > ZD1201_FRAGMAX) | ||
| 1361 | return -EINVAL; | ||
| 1362 | if (val < ZD1201_FRAGMIN) | ||
| 1363 | return -EINVAL; | ||
| 1364 | if (val & 1) | ||
| 1365 | return -EINVAL; | ||
| 1366 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, val); | ||
| 1367 | if (err) | ||
| 1368 | return err; | ||
| 1369 | return zd1201_mac_reset(zd); | ||
| 1370 | } | ||
| 1371 | |||
| 1372 | static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info, | ||
| 1373 | struct iw_param *frag, char *extra) | ||
| 1374 | { | ||
| 1375 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1376 | short fragt; | ||
| 1377 | int err; | ||
| 1378 | |||
| 1379 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, &fragt); | ||
| 1380 | if (err) | ||
| 1381 | return err; | ||
| 1382 | frag->value = fragt; | ||
| 1383 | frag->disabled = (frag->value == ZD1201_FRAGMAX); | ||
| 1384 | frag->fixed = 1; | ||
| 1385 | |||
| 1386 | return 0; | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | static int zd1201_set_retry(struct net_device *dev, | ||
| 1390 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | ||
| 1391 | { | ||
| 1392 | return 0; | ||
| 1393 | } | ||
| 1394 | |||
| 1395 | static int zd1201_get_retry(struct net_device *dev, | ||
| 1396 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | ||
| 1397 | { | ||
| 1398 | return 0; | ||
| 1399 | } | ||
| 1400 | |||
| 1401 | static int zd1201_set_encode(struct net_device *dev, | ||
| 1402 | struct iw_request_info *info, struct iw_point *erq, char *key) | ||
| 1403 | { | ||
| 1404 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1405 | short i; | ||
| 1406 | int err, rid; | ||
| 1407 | |||
| 1408 | if (erq->length > ZD1201_MAXKEYLEN) | ||
| 1409 | return -EINVAL; | ||
| 1410 | |||
| 1411 | i = (erq->flags & IW_ENCODE_INDEX)-1; | ||
| 1412 | if (i == -1) { | ||
| 1413 | err = zd1201_getconfig16(zd,ZD1201_RID_CNFDEFAULTKEYID,&i); | ||
| 1414 | if (err) | ||
| 1415 | return err; | ||
| 1416 | } else { | ||
| 1417 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, i); | ||
| 1418 | if (err) | ||
| 1419 | return err; | ||
| 1420 | } | ||
| 1421 | |||
| 1422 | if (i < 0 || i >= ZD1201_NUMKEYS) | ||
| 1423 | return -EINVAL; | ||
| 1424 | |||
| 1425 | rid = ZD1201_RID_CNFDEFAULTKEY0 + i; | ||
| 1426 | err = zd1201_setconfig(zd, rid, key, erq->length, 1); | ||
| 1427 | if (err) | ||
| 1428 | return err; | ||
| 1429 | zd->encode_keylen[i] = erq->length; | ||
| 1430 | memcpy(zd->encode_keys[i], key, erq->length); | ||
| 1431 | |||
| 1432 | i=0; | ||
| 1433 | if (!(erq->flags & IW_ENCODE_DISABLED & IW_ENCODE_MODE)) { | ||
| 1434 | i |= 0x01; | ||
| 1435 | zd->encode_enabled = 1; | ||
| 1436 | } else | ||
| 1437 | zd->encode_enabled = 0; | ||
| 1438 | if (erq->flags & IW_ENCODE_RESTRICTED & IW_ENCODE_MODE) { | ||
| 1439 | i |= 0x02; | ||
| 1440 | zd->encode_restricted = 1; | ||
| 1441 | } else | ||
| 1442 | zd->encode_restricted = 0; | ||
| 1443 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFWEBFLAGS, i); | ||
| 1444 | if (err) | ||
| 1445 | return err; | ||
| 1446 | |||
| 1447 | if (zd->encode_enabled) | ||
| 1448 | i = ZD1201_CNFAUTHENTICATION_SHAREDKEY; | ||
| 1449 | else | ||
| 1450 | i = ZD1201_CNFAUTHENTICATION_OPENSYSTEM; | ||
| 1451 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, i); | ||
| 1452 | if (err) | ||
| 1453 | return err; | ||
| 1454 | |||
| 1455 | return zd1201_mac_reset(zd); | ||
| 1456 | } | ||
| 1457 | |||
| 1458 | static int zd1201_get_encode(struct net_device *dev, | ||
| 1459 | struct iw_request_info *info, struct iw_point *erq, char *key) | ||
| 1460 | { | ||
| 1461 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1462 | short i; | ||
| 1463 | int err; | ||
| 1464 | |||
| 1465 | if (zd->encode_enabled) | ||
| 1466 | erq->flags = IW_ENCODE_ENABLED; | ||
| 1467 | else | ||
| 1468 | erq->flags = IW_ENCODE_DISABLED; | ||
| 1469 | if (zd->encode_restricted) | ||
| 1470 | erq->flags |= IW_ENCODE_RESTRICTED; | ||
| 1471 | else | ||
| 1472 | erq->flags |= IW_ENCODE_OPEN; | ||
| 1473 | |||
| 1474 | i = (erq->flags & IW_ENCODE_INDEX) -1; | ||
| 1475 | if (i == -1) { | ||
| 1476 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, &i); | ||
| 1477 | if (err) | ||
| 1478 | return err; | ||
| 1479 | } | ||
| 1480 | if (i<0 || i>= ZD1201_NUMKEYS) | ||
| 1481 | return -EINVAL; | ||
| 1482 | |||
| 1483 | erq->flags |= i+1; | ||
| 1484 | |||
| 1485 | erq->length = zd->encode_keylen[i]; | ||
| 1486 | memcpy(key, zd->encode_keys[i], erq->length); | ||
| 1487 | |||
| 1488 | return 0; | ||
| 1489 | } | ||
| 1490 | |||
| 1491 | static int zd1201_set_power(struct net_device *dev, | ||
| 1492 | struct iw_request_info *info, struct iw_param *vwrq, char *extra) | ||
| 1493 | { | ||
| 1494 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1495 | short enabled, duration, level; | ||
| 1496 | int err; | ||
| 1497 | |||
| 1498 | enabled = vwrq->disabled ? 0 : 1; | ||
| 1499 | if (enabled) { | ||
| 1500 | if (vwrq->flags & IW_POWER_PERIOD) { | ||
| 1501 | duration = vwrq->value; | ||
| 1502 | err = zd1201_setconfig16(zd, | ||
| 1503 | ZD1201_RID_CNFMAXSLEEPDURATION, duration); | ||
| 1504 | if (err) | ||
| 1505 | return err; | ||
| 1506 | goto out; | ||
| 1507 | } | ||
| 1508 | if (vwrq->flags & IW_POWER_TIMEOUT) { | ||
| 1509 | err = zd1201_getconfig16(zd, | ||
| 1510 | ZD1201_RID_CNFMAXSLEEPDURATION, &duration); | ||
| 1511 | if (err) | ||
| 1512 | return err; | ||
| 1513 | level = vwrq->value * 4 / duration; | ||
| 1514 | if (level > 4) | ||
| 1515 | level = 4; | ||
| 1516 | if (level < 0) | ||
| 1517 | level = 0; | ||
| 1518 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMEPS, | ||
| 1519 | level); | ||
| 1520 | if (err) | ||
| 1521 | return err; | ||
| 1522 | goto out; | ||
| 1523 | } | ||
| 1524 | return -EINVAL; | ||
| 1525 | } | ||
| 1526 | out: | ||
| 1527 | return zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled); | ||
| 1528 | } | ||
| 1529 | |||
| 1530 | static int zd1201_get_power(struct net_device *dev, | ||
| 1531 | struct iw_request_info *info, struct iw_param *vwrq, char *extra) | ||
| 1532 | { | ||
| 1533 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1534 | short enabled, level, duration; | ||
| 1535 | int err; | ||
| 1536 | |||
| 1537 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMENABLED, &enabled); | ||
| 1538 | if (err) | ||
| 1539 | return err; | ||
| 1540 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMEPS, &level); | ||
| 1541 | if (err) | ||
| 1542 | return err; | ||
| 1543 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXSLEEPDURATION, &duration); | ||
| 1544 | if (err) | ||
| 1545 | return err; | ||
| 1546 | vwrq->disabled = enabled ? 0 : 1; | ||
| 1547 | if (vwrq->flags & IW_POWER_TYPE) { | ||
| 1548 | if (vwrq->flags & IW_POWER_PERIOD) { | ||
| 1549 | vwrq->value = duration; | ||
| 1550 | vwrq->flags = IW_POWER_PERIOD; | ||
| 1551 | } else { | ||
| 1552 | vwrq->value = duration * level / 4; | ||
| 1553 | vwrq->flags = IW_POWER_TIMEOUT; | ||
| 1554 | } | ||
| 1555 | } | ||
| 1556 | if (vwrq->flags & IW_POWER_MODE) { | ||
| 1557 | if (enabled && level) | ||
| 1558 | vwrq->flags = IW_POWER_UNICAST_R; | ||
| 1559 | else | ||
| 1560 | vwrq->flags = IW_POWER_ALL_R; | ||
| 1561 | } | ||
| 1562 | |||
| 1563 | return 0; | ||
| 1564 | } | ||
| 1565 | |||
| 1566 | |||
| 1567 | static const iw_handler zd1201_iw_handler[] = | ||
| 1568 | { | ||
| 1569 | (iw_handler) zd1201_config_commit, /* SIOCSIWCOMMIT */ | ||
| 1570 | (iw_handler) zd1201_get_name, /* SIOCGIWNAME */ | ||
| 1571 | (iw_handler) NULL, /* SIOCSIWNWID */ | ||
| 1572 | (iw_handler) NULL, /* SIOCGIWNWID */ | ||
| 1573 | (iw_handler) zd1201_set_freq, /* SIOCSIWFREQ */ | ||
| 1574 | (iw_handler) zd1201_get_freq, /* SIOCGIWFREQ */ | ||
| 1575 | (iw_handler) zd1201_set_mode, /* SIOCSIWMODE */ | ||
| 1576 | (iw_handler) zd1201_get_mode, /* SIOCGIWMODE */ | ||
| 1577 | (iw_handler) NULL, /* SIOCSIWSENS */ | ||
| 1578 | (iw_handler) NULL, /* SIOCGIWSENS */ | ||
| 1579 | (iw_handler) NULL, /* SIOCSIWRANGE */ | ||
| 1580 | (iw_handler) zd1201_get_range, /* SIOCGIWRANGE */ | ||
| 1581 | (iw_handler) NULL, /* SIOCSIWPRIV */ | ||
| 1582 | (iw_handler) NULL, /* SIOCGIWPRIV */ | ||
| 1583 | (iw_handler) NULL, /* SIOCSIWSTATS */ | ||
| 1584 | (iw_handler) NULL, /* SIOCGIWSTATS */ | ||
| 1585 | (iw_handler) NULL, /* SIOCSIWSPY */ | ||
| 1586 | (iw_handler) NULL, /* SIOCGIWSPY */ | ||
| 1587 | (iw_handler) NULL, /* -- hole -- */ | ||
| 1588 | (iw_handler) NULL, /* -- hole -- */ | ||
| 1589 | (iw_handler) NULL/*zd1201_set_wap*/, /* SIOCSIWAP */ | ||
| 1590 | (iw_handler) zd1201_get_wap, /* SIOCGIWAP */ | ||
| 1591 | (iw_handler) NULL, /* -- hole -- */ | ||
| 1592 | (iw_handler) NULL, /* SIOCGIWAPLIST */ | ||
| 1593 | (iw_handler) zd1201_set_scan, /* SIOCSIWSCAN */ | ||
| 1594 | (iw_handler) zd1201_get_scan, /* SIOCGIWSCAN */ | ||
| 1595 | (iw_handler) zd1201_set_essid, /* SIOCSIWESSID */ | ||
| 1596 | (iw_handler) zd1201_get_essid, /* SIOCGIWESSID */ | ||
| 1597 | (iw_handler) NULL, /* SIOCSIWNICKN */ | ||
| 1598 | (iw_handler) zd1201_get_nick, /* SIOCGIWNICKN */ | ||
| 1599 | (iw_handler) NULL, /* -- hole -- */ | ||
| 1600 | (iw_handler) NULL, /* -- hole -- */ | ||
| 1601 | (iw_handler) zd1201_set_rate, /* SIOCSIWRATE */ | ||
| 1602 | (iw_handler) zd1201_get_rate, /* SIOCGIWRATE */ | ||
| 1603 | (iw_handler) zd1201_set_rts, /* SIOCSIWRTS */ | ||
| 1604 | (iw_handler) zd1201_get_rts, /* SIOCGIWRTS */ | ||
| 1605 | (iw_handler) zd1201_set_frag, /* SIOCSIWFRAG */ | ||
| 1606 | (iw_handler) zd1201_get_frag, /* SIOCGIWFRAG */ | ||
| 1607 | (iw_handler) NULL, /* SIOCSIWTXPOW */ | ||
| 1608 | (iw_handler) NULL, /* SIOCGIWTXPOW */ | ||
| 1609 | (iw_handler) zd1201_set_retry, /* SIOCSIWRETRY */ | ||
| 1610 | (iw_handler) zd1201_get_retry, /* SIOCGIWRETRY */ | ||
| 1611 | (iw_handler) zd1201_set_encode, /* SIOCSIWENCODE */ | ||
| 1612 | (iw_handler) zd1201_get_encode, /* SIOCGIWENCODE */ | ||
| 1613 | (iw_handler) zd1201_set_power, /* SIOCSIWPOWER */ | ||
| 1614 | (iw_handler) zd1201_get_power, /* SIOCGIWPOWER */ | ||
| 1615 | }; | ||
| 1616 | |||
| 1617 | static int zd1201_set_hostauth(struct net_device *dev, | ||
| 1618 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | ||
| 1619 | { | ||
| 1620 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1621 | |||
| 1622 | if (!zd->ap) | ||
| 1623 | return -EOPNOTSUPP; | ||
| 1624 | |||
| 1625 | return zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value); | ||
| 1626 | } | ||
| 1627 | |||
| 1628 | static int zd1201_get_hostauth(struct net_device *dev, | ||
| 1629 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | ||
| 1630 | { | ||
| 1631 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1632 | short hostauth; | ||
| 1633 | int err; | ||
| 1634 | |||
| 1635 | if (!zd->ap) | ||
| 1636 | return -EOPNOTSUPP; | ||
| 1637 | |||
| 1638 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFHOSTAUTH, &hostauth); | ||
| 1639 | if (err) | ||
| 1640 | return err; | ||
| 1641 | rrq->value = hostauth; | ||
| 1642 | rrq->fixed = 1; | ||
| 1643 | |||
| 1644 | return 0; | ||
| 1645 | } | ||
| 1646 | |||
| 1647 | static int zd1201_auth_sta(struct net_device *dev, | ||
| 1648 | struct iw_request_info *info, struct sockaddr *sta, char *extra) | ||
| 1649 | { | ||
| 1650 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1651 | unsigned char buffer[10]; | ||
| 1652 | |||
| 1653 | if (!zd->ap) | ||
| 1654 | return -EOPNOTSUPP; | ||
| 1655 | |||
| 1656 | memcpy(buffer, sta->sa_data, ETH_ALEN); | ||
| 1657 | *(short*)(buffer+6) = 0; /* 0==success, 1==failure */ | ||
| 1658 | *(short*)(buffer+8) = 0; | ||
| 1659 | |||
| 1660 | return zd1201_setconfig(zd, ZD1201_RID_AUTHENTICATESTA, buffer, 10, 1); | ||
| 1661 | } | ||
| 1662 | |||
| 1663 | static int zd1201_set_maxassoc(struct net_device *dev, | ||
| 1664 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | ||
| 1665 | { | ||
| 1666 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1667 | int err; | ||
| 1668 | |||
| 1669 | if (!zd->ap) | ||
| 1670 | return -EOPNOTSUPP; | ||
| 1671 | |||
| 1672 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, rrq->value); | ||
| 1673 | if (err) | ||
| 1674 | return err; | ||
| 1675 | return 0; | ||
| 1676 | } | ||
| 1677 | |||
| 1678 | static int zd1201_get_maxassoc(struct net_device *dev, | ||
| 1679 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | ||
| 1680 | { | ||
| 1681 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
| 1682 | short maxassoc; | ||
| 1683 | int err; | ||
| 1684 | |||
| 1685 | if (!zd->ap) | ||
| 1686 | return -EOPNOTSUPP; | ||
| 1687 | |||
| 1688 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, &maxassoc); | ||
| 1689 | if (err) | ||
| 1690 | return err; | ||
| 1691 | rrq->value = maxassoc; | ||
| 1692 | rrq->fixed = 1; | ||
| 1693 | |||
| 1694 | return 0; | ||
| 1695 | } | ||
| 1696 | |||
| 1697 | static const iw_handler zd1201_private_handler[] = { | ||
| 1698 | (iw_handler) zd1201_set_hostauth, /* ZD1201SIWHOSTAUTH */ | ||
| 1699 | (iw_handler) zd1201_get_hostauth, /* ZD1201GIWHOSTAUTH */ | ||
| 1700 | (iw_handler) zd1201_auth_sta, /* ZD1201SIWAUTHSTA */ | ||
| 1701 | (iw_handler) NULL, /* nothing to get */ | ||
| 1702 | (iw_handler) zd1201_set_maxassoc, /* ZD1201SIMAXASSOC */ | ||
| 1703 | (iw_handler) zd1201_get_maxassoc, /* ZD1201GIMAXASSOC */ | ||
| 1704 | }; | ||
| 1705 | |||
| 1706 | static const struct iw_priv_args zd1201_private_args[] = { | ||
| 1707 | { ZD1201SIWHOSTAUTH, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
| 1708 | IW_PRIV_TYPE_NONE, "sethostauth" }, | ||
| 1709 | { ZD1201GIWHOSTAUTH, IW_PRIV_TYPE_NONE, | ||
| 1710 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostauth" }, | ||
| 1711 | { ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, | ||
| 1712 | IW_PRIV_TYPE_NONE, "authstation" }, | ||
| 1713 | { ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
| 1714 | IW_PRIV_TYPE_NONE, "setmaxassoc" }, | ||
| 1715 | { ZD1201GIWMAXASSOC, IW_PRIV_TYPE_NONE, | ||
| 1716 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmaxassoc" }, | ||
| 1717 | }; | ||
| 1718 | |||
| 1719 | static const struct iw_handler_def zd1201_iw_handlers = { | ||
| 1720 | .num_standard = ARRAY_SIZE(zd1201_iw_handler), | ||
| 1721 | .num_private = ARRAY_SIZE(zd1201_private_handler), | ||
| 1722 | .num_private_args = ARRAY_SIZE(zd1201_private_args), | ||
| 1723 | .standard = (iw_handler *)zd1201_iw_handler, | ||
| 1724 | .private = (iw_handler *)zd1201_private_handler, | ||
| 1725 | .private_args = (struct iw_priv_args *) zd1201_private_args, | ||
| 1726 | .get_wireless_stats = zd1201_get_wireless_stats, | ||
| 1727 | }; | ||
| 1728 | |||
| 1729 | static int zd1201_probe(struct usb_interface *interface, | ||
| 1730 | const struct usb_device_id *id) | ||
| 1731 | { | ||
| 1732 | struct zd1201 *zd; | ||
| 1733 | struct usb_device *usb; | ||
| 1734 | int err; | ||
| 1735 | short porttype; | ||
| 1736 | char buf[IW_ESSID_MAX_SIZE+2]; | ||
| 1737 | |||
| 1738 | usb = interface_to_usbdev(interface); | ||
| 1739 | |||
| 1740 | zd = kzalloc(sizeof(struct zd1201), GFP_KERNEL); | ||
| 1741 | if (!zd) | ||
| 1742 | return -ENOMEM; | ||
| 1743 | zd->ap = ap; | ||
| 1744 | zd->usb = usb; | ||
| 1745 | zd->removed = 0; | ||
| 1746 | init_waitqueue_head(&zd->rxdataq); | ||
| 1747 | INIT_HLIST_HEAD(&zd->fraglist); | ||
| 1748 | |||
| 1749 | err = zd1201_fw_upload(usb, zd->ap); | ||
| 1750 | if (err) { | ||
| 1751 | dev_err(&usb->dev, "zd1201 firmware upload failed: %d\n", err); | ||
| 1752 | goto err_zd; | ||
| 1753 | } | ||
| 1754 | |||
| 1755 | zd->endp_in = 1; | ||
| 1756 | zd->endp_out = 1; | ||
| 1757 | zd->endp_out2 = 2; | ||
| 1758 | zd->rx_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 1759 | zd->tx_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 1760 | if (!zd->rx_urb || !zd->tx_urb) | ||
| 1761 | goto err_zd; | ||
| 1762 | |||
| 1763 | mdelay(100); | ||
| 1764 | err = zd1201_drvr_start(zd); | ||
| 1765 | if (err) | ||
| 1766 | goto err_zd; | ||
| 1767 | |||
| 1768 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXDATALEN, 2312); | ||
| 1769 | if (err) | ||
| 1770 | goto err_start; | ||
| 1771 | |||
| 1772 | err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, | ||
| 1773 | ZD1201_RATEB1 | ZD1201_RATEB2 | ZD1201_RATEB5 | ZD1201_RATEB11); | ||
| 1774 | if (err) | ||
| 1775 | goto err_start; | ||
| 1776 | |||
| 1777 | zd->dev = alloc_etherdev(0); | ||
| 1778 | if (!zd->dev) | ||
| 1779 | goto err_start; | ||
| 1780 | |||
| 1781 | zd->dev->priv = zd; | ||
| 1782 | zd->dev->open = zd1201_net_open; | ||
| 1783 | zd->dev->stop = zd1201_net_stop; | ||
| 1784 | zd->dev->get_stats = zd1201_get_stats; | ||
| 1785 | zd->dev->wireless_handlers = | ||
| 1786 | (struct iw_handler_def *)&zd1201_iw_handlers; | ||
| 1787 | zd->dev->hard_start_xmit = zd1201_hard_start_xmit; | ||
| 1788 | zd->dev->watchdog_timeo = ZD1201_TX_TIMEOUT; | ||
| 1789 | zd->dev->tx_timeout = zd1201_tx_timeout; | ||
| 1790 | zd->dev->set_multicast_list = zd1201_set_multicast; | ||
| 1791 | zd->dev->set_mac_address = zd1201_set_mac_address; | ||
| 1792 | strcpy(zd->dev->name, "wlan%d"); | ||
| 1793 | |||
| 1794 | err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR, | ||
| 1795 | zd->dev->dev_addr, zd->dev->addr_len); | ||
| 1796 | if (err) | ||
| 1797 | goto err_net; | ||
| 1798 | |||
| 1799 | /* Set wildcard essid to match zd->essid */ | ||
| 1800 | *(__le16 *)buf = cpu_to_le16(0); | ||
| 1801 | err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, | ||
| 1802 | IW_ESSID_MAX_SIZE+2, 1); | ||
| 1803 | if (err) | ||
| 1804 | goto err_net; | ||
| 1805 | |||
| 1806 | if (zd->ap) | ||
| 1807 | porttype = ZD1201_PORTTYPE_AP; | ||
| 1808 | else | ||
| 1809 | porttype = ZD1201_PORTTYPE_BSS; | ||
| 1810 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); | ||
| 1811 | if (err) | ||
| 1812 | goto err_net; | ||
| 1813 | |||
| 1814 | SET_NETDEV_DEV(zd->dev, &usb->dev); | ||
| 1815 | |||
| 1816 | err = register_netdev(zd->dev); | ||
| 1817 | if (err) | ||
| 1818 | goto err_net; | ||
| 1819 | dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n", | ||
| 1820 | zd->dev->name); | ||
| 1821 | |||
| 1822 | usb_set_intfdata(interface, zd); | ||
| 1823 | return 0; | ||
| 1824 | |||
| 1825 | err_net: | ||
| 1826 | free_netdev(zd->dev); | ||
| 1827 | err_start: | ||
| 1828 | /* Leave the device in reset state */ | ||
| 1829 | zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); | ||
| 1830 | err_zd: | ||
| 1831 | if (zd->tx_urb) | ||
| 1832 | usb_free_urb(zd->tx_urb); | ||
| 1833 | if (zd->rx_urb) | ||
| 1834 | usb_free_urb(zd->rx_urb); | ||
| 1835 | kfree(zd); | ||
| 1836 | return err; | ||
| 1837 | } | ||
| 1838 | |||
| 1839 | static void zd1201_disconnect(struct usb_interface *interface) | ||
| 1840 | { | ||
| 1841 | struct zd1201 *zd=(struct zd1201 *)usb_get_intfdata(interface); | ||
| 1842 | struct hlist_node *node, *node2; | ||
| 1843 | struct zd1201_frag *frag; | ||
| 1844 | |||
| 1845 | if (!zd) | ||
| 1846 | return; | ||
| 1847 | usb_set_intfdata(interface, NULL); | ||
| 1848 | if (zd->dev) { | ||
| 1849 | unregister_netdev(zd->dev); | ||
| 1850 | free_netdev(zd->dev); | ||
| 1851 | } | ||
| 1852 | |||
| 1853 | hlist_for_each_entry_safe(frag, node, node2, &zd->fraglist, fnode) { | ||
| 1854 | hlist_del_init(&frag->fnode); | ||
| 1855 | kfree_skb(frag->skb); | ||
| 1856 | kfree(frag); | ||
| 1857 | } | ||
| 1858 | |||
| 1859 | if (zd->tx_urb) { | ||
| 1860 | usb_kill_urb(zd->tx_urb); | ||
| 1861 | usb_free_urb(zd->tx_urb); | ||
| 1862 | } | ||
| 1863 | if (zd->rx_urb) { | ||
| 1864 | usb_kill_urb(zd->rx_urb); | ||
| 1865 | usb_free_urb(zd->rx_urb); | ||
| 1866 | } | ||
| 1867 | kfree(zd); | ||
| 1868 | } | ||
| 1869 | |||
| 1870 | #ifdef CONFIG_PM | ||
| 1871 | |||
| 1872 | static int zd1201_suspend(struct usb_interface *interface, | ||
| 1873 | pm_message_t message) | ||
| 1874 | { | ||
| 1875 | struct zd1201 *zd = usb_get_intfdata(interface); | ||
| 1876 | |||
| 1877 | netif_device_detach(zd->dev); | ||
| 1878 | |||
| 1879 | zd->was_enabled = zd->mac_enabled; | ||
| 1880 | |||
| 1881 | if (zd->was_enabled) | ||
| 1882 | return zd1201_disable(zd); | ||
| 1883 | else | ||
| 1884 | return 0; | ||
| 1885 | } | ||
| 1886 | |||
| 1887 | static int zd1201_resume(struct usb_interface *interface) | ||
| 1888 | { | ||
| 1889 | struct zd1201 *zd = usb_get_intfdata(interface); | ||
| 1890 | |||
| 1891 | if (!zd || !zd->dev) | ||
| 1892 | return -ENODEV; | ||
| 1893 | |||
| 1894 | netif_device_attach(zd->dev); | ||
| 1895 | |||
| 1896 | if (zd->was_enabled) | ||
| 1897 | return zd1201_enable(zd); | ||
| 1898 | else | ||
| 1899 | return 0; | ||
| 1900 | } | ||
| 1901 | |||
| 1902 | #else | ||
| 1903 | |||
| 1904 | #define zd1201_suspend NULL | ||
| 1905 | #define zd1201_resume NULL | ||
| 1906 | |||
| 1907 | #endif | ||
| 1908 | |||
| 1909 | static struct usb_driver zd1201_usb = { | ||
| 1910 | .name = "zd1201", | ||
| 1911 | .probe = zd1201_probe, | ||
| 1912 | .disconnect = zd1201_disconnect, | ||
| 1913 | .id_table = zd1201_table, | ||
| 1914 | .suspend = zd1201_suspend, | ||
| 1915 | .resume = zd1201_resume, | ||
| 1916 | }; | ||
| 1917 | |||
| 1918 | static int __init zd1201_init(void) | ||
| 1919 | { | ||
| 1920 | return usb_register(&zd1201_usb); | ||
| 1921 | } | ||
| 1922 | |||
| 1923 | static void __exit zd1201_cleanup(void) | ||
| 1924 | { | ||
| 1925 | usb_deregister(&zd1201_usb); | ||
| 1926 | } | ||
| 1927 | |||
| 1928 | module_init(zd1201_init); | ||
| 1929 | module_exit(zd1201_cleanup); | ||
diff --git a/drivers/net/wireless/zd1201.h b/drivers/net/wireless/zd1201.h new file mode 100644 index 000000000000..235f0ee34b24 --- /dev/null +++ b/drivers/net/wireless/zd1201.h | |||
| @@ -0,0 +1,148 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org) | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License | ||
| 6 | * version 2 as published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * Parts of this driver have been derived from a wlan-ng version | ||
| 9 | * modified by ZyDAS. | ||
| 10 | * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef _INCLUDE_ZD1201_H_ | ||
| 14 | #define _INCLUDE_ZD1201_H_ | ||
| 15 | |||
| 16 | #define ZD1201_NUMKEYS 4 | ||
| 17 | #define ZD1201_MAXKEYLEN 13 | ||
| 18 | #define ZD1201_MAXMULTI 16 | ||
| 19 | #define ZD1201_FRAGMAX 2500 | ||
| 20 | #define ZD1201_FRAGMIN 256 | ||
| 21 | #define ZD1201_RTSMAX 2500 | ||
| 22 | |||
| 23 | #define ZD1201_RXSIZE 3000 | ||
| 24 | |||
| 25 | struct zd1201 { | ||
| 26 | struct usb_device *usb; | ||
| 27 | int removed; | ||
| 28 | struct net_device *dev; | ||
| 29 | struct net_device_stats stats; | ||
| 30 | struct iw_statistics iwstats; | ||
| 31 | |||
| 32 | int endp_in; | ||
| 33 | int endp_out; | ||
| 34 | int endp_out2; | ||
| 35 | struct urb *rx_urb; | ||
| 36 | struct urb *tx_urb; | ||
| 37 | |||
| 38 | unsigned char rxdata[ZD1201_RXSIZE]; | ||
| 39 | int rxlen; | ||
| 40 | wait_queue_head_t rxdataq; | ||
| 41 | int rxdatas; | ||
| 42 | struct hlist_head fraglist; | ||
| 43 | unsigned char txdata[ZD1201_RXSIZE]; | ||
| 44 | |||
| 45 | int ap; | ||
| 46 | char essid[IW_ESSID_MAX_SIZE+1]; | ||
| 47 | int essidlen; | ||
| 48 | int mac_enabled; | ||
| 49 | int was_enabled; | ||
| 50 | int monitor; | ||
| 51 | int encode_enabled; | ||
| 52 | int encode_restricted; | ||
| 53 | unsigned char encode_keys[ZD1201_NUMKEYS][ZD1201_MAXKEYLEN]; | ||
| 54 | int encode_keylen[ZD1201_NUMKEYS]; | ||
| 55 | }; | ||
| 56 | |||
| 57 | struct zd1201_frag { | ||
| 58 | struct hlist_node fnode; | ||
| 59 | int seq; | ||
| 60 | struct sk_buff *skb; | ||
| 61 | }; | ||
| 62 | |||
| 63 | #define ZD1201SIWHOSTAUTH SIOCIWFIRSTPRIV | ||
| 64 | #define ZD1201GIWHOSTAUTH ZD1201SIWHOSTAUTH+1 | ||
| 65 | #define ZD1201SIWAUTHSTA SIOCIWFIRSTPRIV+2 | ||
| 66 | #define ZD1201SIWMAXASSOC SIOCIWFIRSTPRIV+4 | ||
| 67 | #define ZD1201GIWMAXASSOC ZD1201SIWMAXASSOC+1 | ||
| 68 | |||
| 69 | #define ZD1201_FW_TIMEOUT (1000) | ||
| 70 | |||
| 71 | #define ZD1201_TX_TIMEOUT (2000) | ||
| 72 | |||
| 73 | #define ZD1201_USB_CMDREQ 0 | ||
| 74 | #define ZD1201_USB_RESREQ 1 | ||
| 75 | |||
| 76 | #define ZD1201_CMDCODE_INIT 0x00 | ||
| 77 | #define ZD1201_CMDCODE_ENABLE 0x01 | ||
| 78 | #define ZD1201_CMDCODE_DISABLE 0x02 | ||
| 79 | #define ZD1201_CMDCODE_ALLOC 0x0a | ||
| 80 | #define ZD1201_CMDCODE_INQUIRE 0x11 | ||
| 81 | #define ZD1201_CMDCODE_SETRXRID 0x17 | ||
| 82 | #define ZD1201_CMDCODE_ACCESS 0x21 | ||
| 83 | |||
| 84 | #define ZD1201_PACKET_EVENTSTAT 0x0 | ||
| 85 | #define ZD1201_PACKET_RXDATA 0x1 | ||
| 86 | #define ZD1201_PACKET_INQUIRE 0x2 | ||
| 87 | #define ZD1201_PACKET_RESOURCE 0x3 | ||
| 88 | |||
| 89 | #define ZD1201_ACCESSBIT 0x0100 | ||
| 90 | |||
| 91 | #define ZD1201_RID_CNFPORTTYPE 0xfc00 | ||
| 92 | #define ZD1201_RID_CNFOWNMACADDR 0xfc01 | ||
| 93 | #define ZD1201_RID_CNFDESIREDSSID 0xfc02 | ||
| 94 | #define ZD1201_RID_CNFOWNCHANNEL 0xfc03 | ||
| 95 | #define ZD1201_RID_CNFOWNSSID 0xfc04 | ||
| 96 | #define ZD1201_RID_CNFMAXDATALEN 0xfc07 | ||
| 97 | #define ZD1201_RID_CNFPMENABLED 0xfc09 | ||
| 98 | #define ZD1201_RID_CNFPMEPS 0xfc0a | ||
| 99 | #define ZD1201_RID_CNFMAXSLEEPDURATION 0xfc0c | ||
| 100 | #define ZD1201_RID_CNFDEFAULTKEYID 0xfc23 | ||
| 101 | #define ZD1201_RID_CNFDEFAULTKEY0 0xfc24 | ||
| 102 | #define ZD1201_RID_CNFDEFAULTKEY1 0xfc25 | ||
| 103 | #define ZD1201_RID_CNFDEFAULTKEY2 0xfc26 | ||
| 104 | #define ZD1201_RID_CNFDEFAULTKEY3 0xfc27 | ||
| 105 | #define ZD1201_RID_CNFWEBFLAGS 0xfc28 | ||
| 106 | #define ZD1201_RID_CNFAUTHENTICATION 0xfc2a | ||
| 107 | #define ZD1201_RID_CNFMAXASSOCSTATIONS 0xfc2b | ||
| 108 | #define ZD1201_RID_CNFHOSTAUTH 0xfc2e | ||
| 109 | #define ZD1201_RID_CNFGROUPADDRESS 0xfc80 | ||
| 110 | #define ZD1201_RID_CNFFRAGTHRESHOLD 0xfc82 | ||
| 111 | #define ZD1201_RID_CNFRTSTHRESHOLD 0xfc83 | ||
| 112 | #define ZD1201_RID_TXRATECNTL 0xfc84 | ||
| 113 | #define ZD1201_RID_PROMISCUOUSMODE 0xfc85 | ||
| 114 | #define ZD1201_RID_CNFBASICRATES 0xfcb3 | ||
| 115 | #define ZD1201_RID_AUTHENTICATESTA 0xfce3 | ||
| 116 | #define ZD1201_RID_CURRENTBSSID 0xfd42 | ||
| 117 | #define ZD1201_RID_COMMSQUALITY 0xfd43 | ||
| 118 | #define ZD1201_RID_CURRENTTXRATE 0xfd44 | ||
| 119 | #define ZD1201_RID_CNFMAXTXBUFFERNUMBER 0xfda0 | ||
| 120 | #define ZD1201_RID_CURRENTCHANNEL 0xfdc1 | ||
| 121 | |||
| 122 | #define ZD1201_INQ_SCANRESULTS 0xf101 | ||
| 123 | |||
| 124 | #define ZD1201_INF_LINKSTATUS 0xf200 | ||
| 125 | #define ZD1201_INF_ASSOCSTATUS 0xf201 | ||
| 126 | #define ZD1201_INF_AUTHREQ 0xf202 | ||
| 127 | |||
| 128 | #define ZD1201_ASSOCSTATUS_STAASSOC 0x1 | ||
| 129 | #define ZD1201_ASSOCSTATUS_REASSOC 0x2 | ||
| 130 | #define ZD1201_ASSOCSTATUS_DISASSOC 0x3 | ||
| 131 | #define ZD1201_ASSOCSTATUS_ASSOCFAIL 0x4 | ||
| 132 | #define ZD1201_ASSOCSTATUS_AUTHFAIL 0x5 | ||
| 133 | |||
| 134 | #define ZD1201_PORTTYPE_IBSS 0 | ||
| 135 | #define ZD1201_PORTTYPE_BSS 1 | ||
| 136 | #define ZD1201_PORTTYPE_WDS 2 | ||
| 137 | #define ZD1201_PORTTYPE_PSEUDOIBSS 3 | ||
| 138 | #define ZD1201_PORTTYPE_AP 6 | ||
| 139 | |||
| 140 | #define ZD1201_RATEB1 1 | ||
| 141 | #define ZD1201_RATEB2 2 | ||
| 142 | #define ZD1201_RATEB5 4 /* 5.5 really, but 5 is shorter :) */ | ||
| 143 | #define ZD1201_RATEB11 8 | ||
| 144 | |||
| 145 | #define ZD1201_CNFAUTHENTICATION_OPENSYSTEM 0x0001 | ||
| 146 | #define ZD1201_CNFAUTHENTICATION_SHAREDKEY 0x0002 | ||
| 147 | |||
| 148 | #endif /* _INCLUDE_ZD1201_H_ */ | ||
