Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
1d90ac41
Commit
1d90ac41
authored
Jul 24, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net/jgarzik/net-drivers-2.6
into home.osdl.org:/home/torvalds/v2.5/linux
parents
50692f8c
c4f0fddf
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
3558 additions
and
347 deletions
+3558
-347
Documentation/networking/ifenslave.c
Documentation/networking/ifenslave.c
+232
-114
MAINTAINERS
MAINTAINERS
+2
-2
drivers/net/8139too.c
drivers/net/8139too.c
+4
-0
drivers/net/b44.c
drivers/net/b44.c
+38
-16
drivers/net/b44.h
drivers/net/b44.h
+1
-1
drivers/net/e1000/e1000_ethtool.c
drivers/net/e1000/e1000_ethtool.c
+101
-0
drivers/net/e1000/e1000_main.c
drivers/net/e1000/e1000_main.c
+1
-1
drivers/net/ne2k-pci.c
drivers/net/ne2k-pci.c
+1
-0
drivers/net/pcmcia/3c574_cs.c
drivers/net/pcmcia/3c574_cs.c
+2
-1
drivers/net/sk_mca.c
drivers/net/sk_mca.c
+8
-9
drivers/net/sk_mca.h
drivers/net/sk_mca.h
+1
-0
drivers/net/via-rhine.c
drivers/net/via-rhine.c
+12
-5
drivers/net/wan/Kconfig
drivers/net/wan/Kconfig
+2
-1
drivers/net/wireless/Kconfig
drivers/net/wireless/Kconfig
+8
-0
drivers/net/wireless/Makefile
drivers/net/wireless/Makefile
+1
-1
drivers/net/wireless/airo.c
drivers/net/wireless/airo.c
+294
-196
drivers/net/wireless/wl3501.h
drivers/net/wireless/wl3501.h
+552
-0
drivers/net/wireless/wl3501_cs.c
drivers/net/wireless/wl3501_cs.c
+2296
-0
include/linux/ethtool.h
include/linux/ethtool.h
+2
-0
No files found.
Documentation/networking/ifenslave.c
View file @
1d90ac41
...
@@ -27,7 +27,7 @@
...
@@ -27,7 +27,7 @@
* - 2001/02/16 Chad N. Tindel <ctindel at ieee dot org> :
* - 2001/02/16 Chad N. Tindel <ctindel at ieee dot org> :
* - Master is now brought down before setting the MAC address. In
* - Master is now brought down before setting the MAC address. In
* the 2.4 kernel you can't change the MAC address while the device is
* the 2.4 kernel you can't change the MAC address while the device is
* up because you get EBUSY.
* up because you get EBUSY.
*
*
* - 2001/09/13 Takao Indoh <indou dot takao at jp dot fujitsu dot com>
* - 2001/09/13 Takao Indoh <indou dot takao at jp dot fujitsu dot com>
* - Added the ability to change the active interface on a mode 1 bond
* - Added the ability to change the active interface on a mode 1 bond
...
@@ -44,17 +44,60 @@
...
@@ -44,17 +44,60 @@
*
*
* - 2002/10/31 Tony Cureington <tony.cureington * hp_com> :
* - 2002/10/31 Tony Cureington <tony.cureington * hp_com> :
* - If the master does not have a hardware address when the first slave
* - If the master does not have a hardware address when the first slave
* is enslaved, the master is assigned the hardware address of that
* is enslaved, the master is assigned the hardware address of that
* slave - there is a comment in bonding.c stating "ifenslave takes
* slave - there is a comment in bonding.c stating "ifenslave takes
* care of this now." This corrects the problem of slaves having
* care of this now." This corrects the problem of slaves having
* different hardware addresses in active-backup mode when
* different hardware addresses in active-backup mode when
* multiple interfaces are specified on a single ifenslave command
* multiple interfaces are specified on a single ifenslave command
* (ifenslave bond0 eth0 eth1).
* (ifenslave bond0 eth0 eth1).
*
*
* - 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
* Shmulik Hen <shmulik.hen at intel dot com>
* - Moved setting the slave's mac address and openning it, from
* the application to the driver. This enables support of modes
* that need to use the unique mac address of each slave.
* The driver also takes care of closing the slave and restoring its
* original mac address upon release.
* In addition, block possibility of enslaving before the master is up.
* This prevents putting the system in an undefined state.
*
* - 2003/05/01 - Amir Noam <amir.noam at intel dot com>
* - Added ABI version control to restore compatibility between
* new/old ifenslave and new/old bonding.
* - Prevent adding an adapter that is already a slave.
* Fixes the problem of stalling the transmission and leaving
* the slave in a down state.
*
* - 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
* - Prevent enslaving if the bond device is down.
* Fixes the problem of leaving the system in unstable state and
* halting when trying to remove the module.
* - Close socket on all abnormal exists.
* - Add versioning scheme that follows that of the bonding driver.
* current version is 1.0.0 as a base line.
*
* - 2003/05/22 - Jay Vosburgh <fubar at us dot ibm dot com>
* - ifenslave -c was broken; it's now fixed
* - Fixed problem with routes vanishing from master during enslave
* processing.
*
* - 2003/05/27 - Amir Noam <amir.noam at intel dot com>
* - Fix backward compatibility issues:
* For drivers not using ABI versions, slave was set down while
* it should be left up before enslaving.
* Also, master was not set down and the default set_mac_address()
* would fail and generate an error message in the system log.
* - For opt_c: slave should not be set to the master's setting
* while it is running. It was already set during enslave. To
* simplify things, it is now handeled separately.
*/
*/
#define APP_VERSION "1.0.12"
#define APP_RELDATE "June 30, 2003"
#define APP_NAME "ifenslave"
static
char
*
version
=
static
char
*
version
=
"ifenslave.c:v0.07 9/9/97
Donald Becker (becker@cesdis.gsfc.nasa.gov).
\n
"
APP_NAME
".c:v"
APP_VERSION
" ("
APP_RELDATE
") "
"
\n
Donald Becker (becker@cesdis.gsfc.nasa.gov).
\n
"
"detach support added on 2000/10/02 by Willy Tarreau (willy at meta-x.org).
\n
"
"detach support added on 2000/10/02 by Willy Tarreau (willy at meta-x.org).
\n
"
"2.4 kernel support added on 2001/02/16 by Chad N. Tindel (ctindel at ieee dot org.
\n
"
;
"2.4 kernel support added on 2001/02/16 by Chad N. Tindel (ctindel at ieee dot org.
\n
"
;
...
@@ -103,6 +146,12 @@ static const char *howto_msg =
...
@@ -103,6 +146,12 @@ static const char *howto_msg =
#include <linux/if_bonding.h>
#include <linux/if_bonding.h>
#include <linux/sockios.h>
#include <linux/sockios.h>
typedef
unsigned
long
long
u64
;
/* hack, so we may include kernel's ethtool.h */
typedef
__uint32_t
u32
;
/* ditto */
typedef
__uint16_t
u16
;
/* ditto */
typedef
__uint8_t
u8
;
/* ditto */
#include <linux/ethtool.h>
struct
option
longopts
[]
=
{
struct
option
longopts
[]
=
{
/* { name has_arg *flag val } */
/* { name has_arg *flag val } */
{
"all-interfaces"
,
0
,
0
,
'a'
},
/* Show all interfaces. */
{
"all-interfaces"
,
0
,
0
,
'a'
},
/* Show all interfaces. */
...
@@ -130,18 +179,19 @@ opt_howto = 0;
...
@@ -130,18 +179,19 @@ opt_howto = 0;
int
skfd
=
-
1
;
/* AF_INET socket for ioctl() calls. */
int
skfd
=
-
1
;
/* AF_INET socket for ioctl() calls. */
static
void
if_print
(
char
*
ifname
);
static
void
if_print
(
char
*
ifname
);
static
int
get_abi_ver
(
char
*
master_ifname
);
int
int
main
(
int
argc
,
char
**
argv
)
main
(
int
argc
,
char
**
argv
)
{
{
struct
ifreq
ifr2
,
if_hwaddr
,
if_ipaddr
,
if_metric
,
if_mtu
,
if_dstaddr
;
struct
ifreq
ifr2
,
if_hwaddr
,
if_ipaddr
,
if_metric
,
if_mtu
,
if_dstaddr
;
struct
ifreq
if_netmask
,
if_brdaddr
,
if_flags
;
struct
ifreq
if_netmask
,
if_brdaddr
,
if_flags
;
int
goterr
=
0
;
int
rv
,
goterr
=
0
;
int
c
,
errflag
=
0
;
int
c
,
errflag
=
0
;
sa_family_t
master_family
;
sa_family_t
master_family
;
char
**
spp
,
*
master_ifname
,
*
slave_ifname
;
char
**
spp
,
*
master_ifname
,
*
slave_ifname
;
int
hwaddr_notset
;
int
hwaddr_notset
;
int
master_up
;
int
abi_ver
=
0
;
while
((
c
=
getopt_long
(
argc
,
argv
,
"acdfrvV?h"
,
longopts
,
0
))
!=
EOF
)
while
((
c
=
getopt_long
(
argc
,
argv
,
"acdfrvV?h"
,
longopts
,
0
))
!=
EOF
)
switch
(
c
)
{
switch
(
c
)
{
...
@@ -207,6 +257,7 @@ main(int argc, char **argv)
...
@@ -207,6 +257,7 @@ main(int argc, char **argv)
char
**
tempp
=
spp
;
char
**
tempp
=
spp
;
if
((
master_ifname
==
NULL
)
||
(
slave_ifname
==
NULL
)
||
(
*
tempp
++
!=
NULL
))
{
if
((
master_ifname
==
NULL
)
||
(
slave_ifname
==
NULL
)
||
(
*
tempp
++
!=
NULL
))
{
fprintf
(
stderr
,
usage_msg
);
fprintf
(
stderr
,
usage_msg
);
(
void
)
close
(
skfd
);
return
2
;
return
2
;
}
}
}
}
...
@@ -218,6 +269,13 @@ main(int argc, char **argv)
...
@@ -218,6 +269,13 @@ main(int argc, char **argv)
exit
(
0
);
exit
(
0
);
}
}
/* exchange abi version with bonding driver */
abi_ver
=
get_abi_ver
(
master_ifname
);
if
(
abi_ver
<
0
)
{
(
void
)
close
(
skfd
);
exit
(
1
);
}
/* Get the vitals from the master interface. */
/* Get the vitals from the master interface. */
{
{
struct
ifreq
*
ifra
[
7
]
=
{
&
if_ipaddr
,
&
if_mtu
,
&
if_dstaddr
,
struct
ifreq
*
ifra
[
7
]
=
{
&
if_ipaddr
,
&
if_mtu
,
&
if_dstaddr
,
...
@@ -242,6 +300,13 @@ main(int argc, char **argv)
...
@@ -242,6 +300,13 @@ main(int argc, char **argv)
}
}
}
}
/* check if master is up; if not then fail any operation */
if
(
!
(
if_flags
.
ifr_flags
&
IFF_UP
))
{
fprintf
(
stderr
,
"Illegal operation; the specified master interface '%s' is not up.
\n
"
,
master_ifname
);
(
void
)
close
(
skfd
);
exit
(
1
);
}
hwaddr_notset
=
1
;
/* assume master's address not set yet */
hwaddr_notset
=
1
;
/* assume master's address not set yet */
for
(
i
=
0
;
hwaddr_notset
&&
(
i
<
6
);
i
++
)
{
for
(
i
=
0
;
hwaddr_notset
&&
(
i
<
6
);
i
++
)
{
hwaddr_notset
&=
((
unsigned
char
*
)
if_hwaddr
.
ifr_hwaddr
.
sa_data
)[
i
]
==
0
;
hwaddr_notset
&=
((
unsigned
char
*
)
if_hwaddr
.
ifr_hwaddr
.
sa_data
)[
i
]
==
0
;
...
@@ -254,7 +319,7 @@ main(int argc, char **argv)
...
@@ -254,7 +319,7 @@ main(int argc, char **argv)
" with ethernet-like network interfaces.
\n
"
" with ethernet-like network interfaces.
\n
"
" Use the '-f' option to force the operation.
\n
"
,
" Use the '-f' option to force the operation.
\n
"
,
master_ifname
);
master_ifname
);
(
void
)
close
(
skfd
);
exit
(
1
);
exit
(
1
);
}
}
master_family
=
if_hwaddr
.
ifr_hwaddr
.
sa_family
;
master_family
=
if_hwaddr
.
ifr_hwaddr
.
sa_family
;
...
@@ -278,143 +343,153 @@ main(int argc, char **argv)
...
@@ -278,143 +343,153 @@ main(int argc, char **argv)
fprintf
(
stderr
,
"SIOCBONDRELEASE: cannot detach %s from %s. errno=%s.
\n
"
,
fprintf
(
stderr
,
"SIOCBONDRELEASE: cannot detach %s from %s. errno=%s.
\n
"
,
slave_ifname
,
master_ifname
,
strerror
(
errno
));
slave_ifname
,
master_ifname
,
strerror
(
errno
));
}
}
else
{
/* we'll set the interface down to avoid any conflicts due to
else
if
(
abi_ver
<
1
)
{
same IP/MAC */
/* The driver is using an old ABI, so we'll set the interface
* down to avoid any conflicts due to same IP/MAC
*/
strncpy
(
ifr2
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
);
strncpy
(
ifr2
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
);
if
(
ioctl
(
skfd
,
SIOCGIFFLAGS
,
&
ifr2
)
<
0
)
{
if
(
ioctl
(
skfd
,
SIOCGIFFLAGS
,
&
ifr2
)
<
0
)
{
int
saved_errno
=
errno
;
int
saved_errno
=
errno
;
fprintf
(
stderr
,
"SIOCGIFFLAGS on %s failed: %s
\n
"
,
slave_ifname
,
fprintf
(
stderr
,
"SIOCGIFFLAGS on %s failed: %s
\n
"
,
slave_ifname
,
strerror
(
saved_errno
));
strerror
(
saved_errno
));
}
}
else
{
else
{
ifr2
.
ifr_flags
&=
~
(
IFF_UP
|
IFF_RUNNING
);
ifr2
.
ifr_flags
&=
~
(
IFF_UP
|
IFF_RUNNING
);
if
(
ioctl
(
skfd
,
SIOCSIFFLAGS
,
&
ifr2
)
<
0
)
{
if
(
ioctl
(
skfd
,
SIOCSIFFLAGS
,
&
ifr2
)
<
0
)
{
int
saved_errno
=
errno
;
int
saved_errno
=
errno
;
fprintf
(
stderr
,
"Shutting down interface %s failed: %s
\n
"
,
fprintf
(
stderr
,
"Shutting down interface %s failed: %s
\n
"
,
slave_ifname
,
strerror
(
saved_errno
));
slave_ifname
,
strerror
(
saved_errno
));
}
}
}
}
}
}
}
}
else
if
(
opt_c
)
{
/* change primary slave */
else
{
/* attach a slave interface to the master */
strncpy
(
if_flags
.
ifr_name
,
master_ifname
,
IFNAMSIZ
);
/* two possibilities :
strncpy
(
if_flags
.
ifr_slave
,
slave_ifname
,
IFNAMSIZ
);
- if hwaddr_notset, do nothing. The bond will assign the
if
((
ioctl
(
skfd
,
SIOCBONDCHANGEACTIVE
,
&
if_flags
)
<
0
)
&&
hwaddr from its first slave.
(
ioctl
(
skfd
,
BOND_CHANGE_ACTIVE_OLD
,
&
if_flags
)
<
0
))
{
- if !hwaddr_notset, assign the master's hwaddr to each slave
fprintf
(
stderr
,
"SIOCBONDCHANGEACTIVE: %s.
\n
"
,
strerror
(
errno
));
*/
}
}
else
{
/* attach a slave interface to the master */
strncpy
(
ifr2
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
);
strncpy
(
ifr2
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
);
if
(
ioctl
(
skfd
,
SIOCGIFFLAGS
,
&
ifr2
)
<
0
)
{
if
(
ioctl
(
skfd
,
SIOCGIFFLAGS
,
&
ifr2
)
<
0
)
{
int
saved_errno
=
errno
;
int
saved_errno
=
errno
;
fprintf
(
stderr
,
"SIOCGIFFLAGS on %s failed: %s
\n
"
,
slave_ifname
,
fprintf
(
stderr
,
"SIOCGIFFLAGS on %s failed: %s
\n
"
,
slave_ifname
,
strerror
(
saved_errno
));
strerror
(
saved_errno
));
(
void
)
close
(
skfd
);
return
1
;
return
1
;
}
}
if
((
ifr2
.
ifr_flags
&
IFF_SLAVE
)
&&
!
opt_r
)
{
fprintf
(
stderr
,
"%s is already a slave
\n
"
,
slave_ifname
);
(
void
)
close
(
skfd
);
return
1
;
}
/* if hwaddr_notset, assign the slave hw address to the master */
if
(
hwaddr_notset
)
{
if
(
hwaddr_notset
)
{
/* assign the slave hw address to the
/* assign the slave hw address to the
* master since it currently does not
* master since it currently does not
* have one; otherwise, slaves may
* have one; otherwise, slaves may
* have different hw addresses in
* have different hw addresses in
* active-backup mode as seen when enslaving
* active-backup mode as seen when enslaving
* using "ifenslave bond0 eth0 eth1" because
* using "ifenslave bond0 eth0 eth1" because
* hwaddr_notset is set outside this loop.
* hwaddr_notset is set outside this loop.
* TODO: put this and the "else" portion in
* TODO: put this and the "else" portion in
* a function.
* a function.
*/
*/
goterr
=
0
;
/* get the slaves MAC address */
master_up
=
0
;
strncpy
(
if_hwaddr
.
ifr_name
,
slave_ifname
,
if
(
if_flags
.
ifr_flags
&
IFF_UP
)
{
IFNAMSIZ
);
if_flags
.
ifr_flags
&=
~
IFF_UP
;
rv
=
ioctl
(
skfd
,
SIOCGIFHWADDR
,
&
if_hwaddr
);
if
(
ioctl
(
skfd
,
SIOCSIFFLAGS
,
if
(
-
1
==
rv
)
{
&
if_flags
)
<
0
)
{
fprintf
(
stderr
,
"Could not get MAC "
goterr
=
1
;
"address of %s: %s
\n
"
,
fprintf
(
stderr
,
slave_ifname
,
"Shutting down "
strerror
(
errno
));
"interface %s failed: "
strncpy
(
if_hwaddr
.
ifr_name
,
"%s
\n
"
,
master_ifname
,
IFNAMSIZ
);
master_ifname
,
goterr
=
1
;
strerror
(
errno
));
}
else
{
/* we took the master down,
* so we must bring it up
*/
master_up
=
1
;
}
}
}
if
(
!
goterr
)
{
if
(
!
goterr
)
{
/* get the slaves MAC address */
if
(
abi_ver
<
1
)
{
strncpy
(
if_hwaddr
.
ifr_name
,
/* In ABI versions older than 1, the
slave_ifname
,
IFNAMSIZ
);
* master's set_mac routine couldn't
if
(
ioctl
(
skfd
,
SIOCGIFHWADDR
,
* work if it was up, because it
&
if_hwaddr
)
<
0
)
{
* used the default ethernet set_mac
fprintf
(
stderr
,
* function.
"Could not get MAC "
*/
"address of %s: %s
\n
"
,
/* bring master down */
slave_ifname
,
if_flags
.
ifr_flags
&=
~
IFF_UP
;
strerror
(
errno
));
if
(
ioctl
(
skfd
,
SIOCSIFFLAGS
,
strncpy
(
if_hwaddr
.
ifr_name
,
&
if_flags
)
<
0
)
{
master_ifname
,
goterr
=
1
;
IFNAMSIZ
);
fprintf
(
stderr
,
goterr
=
1
;
"Shutting down "
"interface %s failed: "
"%s
\n
"
,
master_ifname
,
strerror
(
errno
));
}
}
}
}
if
(
!
goterr
)
{
strncpy
(
if_hwaddr
.
ifr_name
,
strncpy
(
if_hwaddr
.
ifr_name
,
master_ifname
,
IFNAMSIZ
);
master_ifname
,
IFNAMSIZ
);
if
(
ioctl
(
skfd
,
SIOCSIFHWADDR
,
if
(
ioctl
(
skfd
,
SIOCSIFHWADDR
,
&
if_hwaddr
)
<
0
)
{
&
if_hwaddr
)
<
0
)
{
fprintf
(
stderr
,
fprintf
(
stderr
,
"Could not set MAC "
"Could not set MAC "
"address of %s: %s
\n
"
,
"address of %s: %s
\n
"
,
master_ifname
,
master_ifname
,
strerror
(
errno
));
strerror
(
errno
));
goterr
=
1
;
goterr
=
1
;
}
else
{
}
else
{
hwaddr_notset
=
0
;
hwaddr_notset
=
0
;
}
}
}
if
(
master_up
)
{
if
(
abi_ver
<
1
)
{
if_flags
.
ifr_flags
|=
IFF_UP
;
/* bring master back up */
if
(
ioctl
(
skfd
,
SIOCSIFFLAGS
,
if_flags
.
ifr_flags
|=
IFF_UP
;
&
if_flags
)
<
0
)
{
if
(
ioctl
(
skfd
,
SIOCSIFFLAGS
,
fprintf
(
stderr
,
&
if_flags
)
<
0
)
{
"Bringing up interface "
fprintf
(
stderr
,
"%s failed: %s
\n
"
,
"Bringing up interface "
master_ifname
,
"%s failed: %s
\n
"
,
strerror
(
errno
));
master_ifname
,
strerror
(
errno
));
}
}
}
}
}
}
else
if
(
abi_ver
<
1
)
{
/* if (hwaddr_notset) */
}
else
{
/* The driver is using an old ABI, so we'll set the interface
/* we'll assign master's hwaddr to this slave */
* down and assign the master's hwaddr to it
*/
if
(
ifr2
.
ifr_flags
&
IFF_UP
)
{
if
(
ifr2
.
ifr_flags
&
IFF_UP
)
{
ifr2
.
ifr_flags
&=
~
IFF_UP
;
ifr2
.
ifr_flags
&=
~
IFF_UP
;
if
(
ioctl
(
skfd
,
SIOCSIFFLAGS
,
&
ifr2
)
<
0
)
{
if
(
ioctl
(
skfd
,
SIOCSIFFLAGS
,
&
ifr2
)
<
0
)
{
int
saved_errno
=
errno
;
int
saved_errno
=
errno
;
fprintf
(
stderr
,
"Shutting down interface %s failed: %s
\n
"
,
fprintf
(
stderr
,
"Shutting down interface %s failed: %s
\n
"
,
slave_ifname
,
strerror
(
saved_errno
));
slave_ifname
,
strerror
(
saved_errno
));
}
}
}
}
strncpy
(
if_hwaddr
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
);
strncpy
(
if_hwaddr
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
);
if
(
ioctl
(
skfd
,
SIOCSIFHWADDR
,
&
if_hwaddr
)
<
0
)
{
if
(
ioctl
(
skfd
,
SIOCSIFHWADDR
,
&
if_hwaddr
)
<
0
)
{
int
saved_errno
=
errno
;
int
saved_errno
=
errno
;
fprintf
(
stderr
,
"SIOCSIFHWADDR on %s failed: %s
\n
"
,
if_hwaddr
.
ifr_name
,
fprintf
(
stderr
,
"SIOCSIFHWADDR on %s failed: %s
\n
"
,
if_hwaddr
.
ifr_name
,
strerror
(
saved_errno
));
strerror
(
saved_errno
));
if
(
saved_errno
==
EBUSY
)
if
(
saved_errno
==
EBUSY
)
fprintf
(
stderr
,
" The slave device %s is busy: it must be"
fprintf
(
stderr
,
" The slave device %s is busy: it must be"
" idle before running this command.
\n
"
,
slave_ifname
);
" idle before running this command.
\n
"
,
slave_ifname
);
else
if
(
saved_errno
==
EOPNOTSUPP
)
else
if
(
saved_errno
==
EOPNOTSUPP
)
fprintf
(
stderr
,
" The slave device you specified does not support"
fprintf
(
stderr
,
" The slave device you specified does not support"
" setting the MAC address.
\n
Your kernel likely does not"
" setting the MAC address.
\n
Your kernel likely does not"
" support slave devices.
\n
"
);
" support slave devices.
\n
"
);
else
if
(
saved_errno
==
EINVAL
)
else
if
(
saved_errno
==
EINVAL
)
fprintf
(
stderr
,
" The slave device's address type does not match"
fprintf
(
stderr
,
" The slave device's address type does not match"
" the master's address type.
\n
"
);
" the master's address type.
\n
"
);
}
else
{
}
else
{
if
(
verbose
)
{
if
(
verbose
)
{
unsigned
char
*
hwaddr
=
if_hwaddr
.
ifr_hwaddr
.
sa_data
;
unsigned
char
*
hwaddr
=
if_hwaddr
.
ifr_hwaddr
.
sa_data
;
...
@@ -424,10 +499,11 @@ main(int argc, char **argv)
...
@@ -424,10 +499,11 @@ main(int argc, char **argv)
}
}
}
}
}
}
if
(
*
spp
&&
!
strcmp
(
*
spp
,
"metric"
))
{
if
(
*
spp
&&
!
strcmp
(
*
spp
,
"metric"
))
{
if
(
*++
spp
==
NULL
)
{
if
(
*++
spp
==
NULL
)
{
fprintf
(
stderr
,
usage_msg
);
fprintf
(
stderr
,
usage_msg
);
(
void
)
close
(
skfd
);
exit
(
2
);
exit
(
2
);
}
}
if_metric
.
ifr_metric
=
atoi
(
*
spp
);
if_metric
.
ifr_metric
=
atoi
(
*
spp
);
...
@@ -439,7 +515,7 @@ main(int argc, char **argv)
...
@@ -439,7 +515,7 @@ main(int argc, char **argv)
}
}
spp
++
;
spp
++
;
}
}
if
(
strncpy
(
if_ipaddr
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
)
<=
0
if
(
strncpy
(
if_ipaddr
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
)
<=
0
||
ioctl
(
skfd
,
SIOCSIFADDR
,
&
if_ipaddr
)
<
0
)
{
||
ioctl
(
skfd
,
SIOCSIFADDR
,
&
if_ipaddr
)
<
0
)
{
fprintf
(
stderr
,
fprintf
(
stderr
,
...
@@ -452,16 +528,16 @@ main(int argc, char **argv)
...
@@ -452,16 +528,16 @@ main(int argc, char **argv)
slave_ifname
,
ipaddr
[
0
],
ipaddr
[
1
],
ipaddr
[
2
],
ipaddr
[
3
]);
slave_ifname
,
ipaddr
[
0
],
ipaddr
[
1
],
ipaddr
[
2
],
ipaddr
[
3
]);
}
}
}
}
if
(
strncpy
(
if_mtu
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
)
<=
0
if
(
strncpy
(
if_mtu
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
)
<=
0
||
ioctl
(
skfd
,
SIOCSIFMTU
,
&
if_mtu
)
<
0
)
{
||
ioctl
(
skfd
,
SIOCSIFMTU
,
&
if_mtu
)
<
0
)
{
fprintf
(
stderr
,
"Something broke setting the slave MTU: %s.
\n
"
,
fprintf
(
stderr
,
"Something broke setting the slave MTU: %s.
\n
"
,
strerror
(
errno
));
strerror
(
errno
));
}
else
{
}
else
{
if
(
verbose
)
if
(
verbose
)
printf
(
"Set the slave's (%s) MTU to %d.
\n
"
,
slave_ifname
,
if_mtu
.
ifr_mtu
);
printf
(
"Set the slave's (%s) MTU to %d.
\n
"
,
slave_ifname
,
if_mtu
.
ifr_mtu
);
}
}
if
(
strncpy
(
if_dstaddr
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
)
<=
0
if
(
strncpy
(
if_dstaddr
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
)
<=
0
||
ioctl
(
skfd
,
SIOCSIFDSTADDR
,
&
if_dstaddr
)
<
0
)
{
||
ioctl
(
skfd
,
SIOCSIFDSTADDR
,
&
if_dstaddr
)
<
0
)
{
fprintf
(
stderr
,
"Error setting the slave (%s) with SIOCSIFDSTADDR: %s.
\n
"
,
fprintf
(
stderr
,
"Error setting the slave (%s) with SIOCSIFDSTADDR: %s.
\n
"
,
...
@@ -473,7 +549,7 @@ main(int argc, char **argv)
...
@@ -473,7 +549,7 @@ main(int argc, char **argv)
slave_ifname
,
ipaddr
[
0
],
ipaddr
[
1
],
ipaddr
[
2
],
ipaddr
[
3
]);
slave_ifname
,
ipaddr
[
0
],
ipaddr
[
1
],
ipaddr
[
2
],
ipaddr
[
3
]);
}
}
}
}
if
(
strncpy
(
if_brdaddr
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
)
<=
0
if
(
strncpy
(
if_brdaddr
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
)
<=
0
||
ioctl
(
skfd
,
SIOCSIFBRDADDR
,
&
if_brdaddr
)
<
0
)
{
||
ioctl
(
skfd
,
SIOCSIFBRDADDR
,
&
if_brdaddr
)
<
0
)
{
fprintf
(
stderr
,
fprintf
(
stderr
,
...
@@ -486,7 +562,7 @@ main(int argc, char **argv)
...
@@ -486,7 +562,7 @@ main(int argc, char **argv)
slave_ifname
,
ipaddr
[
0
],
ipaddr
[
1
],
ipaddr
[
2
],
ipaddr
[
3
]);
slave_ifname
,
ipaddr
[
0
],
ipaddr
[
1
],
ipaddr
[
2
],
ipaddr
[
3
]);
}
}
}
}
if
(
strncpy
(
if_netmask
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
)
<=
0
if
(
strncpy
(
if_netmask
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
)
<=
0
||
ioctl
(
skfd
,
SIOCSIFNETMASK
,
&
if_netmask
)
<
0
)
{
||
ioctl
(
skfd
,
SIOCSIFNETMASK
,
&
if_netmask
)
<
0
)
{
fprintf
(
stderr
,
fprintf
(
stderr
,
...
@@ -499,34 +575,45 @@ main(int argc, char **argv)
...
@@ -499,34 +575,45 @@ main(int argc, char **argv)
slave_ifname
,
ipaddr
[
0
],
ipaddr
[
1
],
ipaddr
[
2
],
ipaddr
[
3
]);
slave_ifname
,
ipaddr
[
0
],
ipaddr
[
1
],
ipaddr
[
2
],
ipaddr
[
3
]);
}
}
}
}
ifr2
.
ifr_flags
|=
IFF_UP
;
/* the interface will need to be up to be bonded */
if
(
abi_ver
<
1
)
{
if
((
ifr2
.
ifr_flags
&=
~
(
IFF_SLAVE
|
IFF_MASTER
))
==
0
||
strncpy
(
ifr2
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
)
<=
0
/* The driver is using an old ABI, so we'll set the interface
||
ioctl
(
skfd
,
SIOCSIFFLAGS
,
&
ifr2
)
<
0
)
{
* up before enslaving it
fprintf
(
stderr
,
*/
"Something broke setting the slave (%s) flags: %s.
\n
"
,
ifr2
.
ifr_flags
|=
IFF_UP
;
slave_ifname
,
strerror
(
errno
));
if
((
ifr2
.
ifr_flags
&=
~
(
IFF_SLAVE
|
IFF_MASTER
))
==
0
||
strncpy
(
ifr2
.
ifr_name
,
slave_ifname
,
IFNAMSIZ
)
<=
0
||
ioctl
(
skfd
,
SIOCSIFFLAGS
,
&
ifr2
)
<
0
)
{
fprintf
(
stderr
,
"Something broke setting the slave (%s) flags: %s.
\n
"
,
slave_ifname
,
strerror
(
errno
));
}
else
{
if
(
verbose
)
printf
(
"Set the slave's (%s) flags %4.4x.
\n
"
,
slave_ifname
,
if_flags
.
ifr_flags
);
}
}
else
{
}
else
{
if
(
verbose
)
/* the bonding module takes care of setting the slave's mac address
printf
(
"Set the slave's (%s) flags %4.4x.
\n
"
,
slave_ifname
,
if_flags
.
ifr_flags
);
* and opening its interface
*/
if
(
ifr2
.
ifr_flags
&
IFF_UP
)
{
/* the interface will need to be down */
ifr2
.
ifr_flags
&=
~
IFF_UP
;
if
(
ioctl
(
skfd
,
SIOCSIFFLAGS
,
&
ifr2
)
<
0
)
{
int
saved_errno
=
errno
;
fprintf
(
stderr
,
"Shutting down interface %s failed: %s
\n
"
,
slave_ifname
,
strerror
(
saved_errno
));
}
}
}
}
/* Do the real thing */
/* Do the real thing */
if
(
!
opt_r
)
{
if
(
!
opt_r
)
{
strncpy
(
if_flags
.
ifr_name
,
master_ifname
,
IFNAMSIZ
);
strncpy
(
if_flags
.
ifr_name
,
master_ifname
,
IFNAMSIZ
);
strncpy
(
if_flags
.
ifr_slave
,
slave_ifname
,
IFNAMSIZ
);
strncpy
(
if_flags
.
ifr_slave
,
slave_ifname
,
IFNAMSIZ
);
if
(
!
opt_c
)
{
if
((
ioctl
(
skfd
,
SIOCBONDENSLAVE
,
&
if_flags
)
<
0
)
&&
if
((
ioctl
(
skfd
,
SIOCBONDENSLAVE
,
&
if_flags
)
<
0
)
&&
(
ioctl
(
skfd
,
BOND_ENSLAVE_OLD
,
&
if_flags
)
<
0
))
{
(
ioctl
(
skfd
,
BOND_ENSLAVE_OLD
,
&
if_flags
)
<
0
))
{
fprintf
(
stderr
,
"SIOCBONDENSLAVE: %s.
\n
"
,
strerror
(
errno
));
fprintf
(
stderr
,
"SIOCBONDENSLAVE: %s.
\n
"
,
strerror
(
errno
));
}
}
else
{
if
((
ioctl
(
skfd
,
SIOCBONDCHANGEACTIVE
,
&
if_flags
)
<
0
)
&&
(
ioctl
(
skfd
,
BOND_CHANGE_ACTIVE_OLD
,
&
if_flags
)
<
0
))
{
fprintf
(
stderr
,
"SIOCBONDCHANGEACTIVE: %s.
\n
"
,
strerror
(
errno
));
}
}
}
}
}
}
}
...
@@ -540,7 +627,7 @@ main(int argc, char **argv)
...
@@ -540,7 +627,7 @@ main(int argc, char **argv)
static
short
mif_flags
;
static
short
mif_flags
;
/* Get the inte
r
face configuration from the kernel. */
/* Get the inteface configuration from the kernel. */
static
int
if_getconfig
(
char
*
ifname
)
static
int
if_getconfig
(
char
*
ifname
)
{
{
struct
ifreq
ifr
;
struct
ifreq
ifr
;
...
@@ -639,7 +726,38 @@ static void if_print(char *ifname)
...
@@ -639,7 +726,38 @@ static void if_print(char *ifname)
}
}
}
}
static
int
get_abi_ver
(
char
*
master_ifname
)
{
struct
ifreq
ifr
;
struct
ethtool_drvinfo
info
;
int
abi_ver
=
0
;
memset
(
&
ifr
,
0
,
sizeof
(
ifr
));
strncpy
(
ifr
.
ifr_name
,
master_ifname
,
IFNAMSIZ
);
ifr
.
ifr_data
=
(
caddr_t
)
&
info
;
info
.
cmd
=
ETHTOOL_GDRVINFO
;
strncpy
(
info
.
driver
,
"ifenslave"
,
32
);
snprintf
(
info
.
fw_version
,
32
,
"%d"
,
BOND_ABI_VERSION
);
if
(
ioctl
(
skfd
,
SIOCETHTOOL
,
&
ifr
)
>=
0
)
{
char
*
endptr
;
abi_ver
=
strtoul
(
info
.
fw_version
,
&
endptr
,
0
);
if
(
*
endptr
)
{
fprintf
(
stderr
,
"Error: got invalid string as an ABI "
"version from the bonding module
\n
"
);
return
-
1
;
}
}
if
(
verbose
)
{
printf
(
"ABI ver is %d
\n
"
,
abi_ver
);
}
return
abi_ver
;
}
/*
/*
* Local variables:
* Local variables:
* version-control: t
* version-control: t
...
...
MAINTAINERS
View file @
1d90ac41
...
@@ -420,8 +420,8 @@ L: linux-computone@lazuli.wittsend.com
...
@@ -420,8 +420,8 @@ L: linux-computone@lazuli.wittsend.com
S: Supported
S: Supported
COMX/MULTIGATE SYNC SERIAL DRIVERS
COMX/MULTIGATE SYNC SERIAL DRIVERS
P:
Gergely Madarasz
P:
Pasztor Szilard
M:
Gergely Madarasz <gorgo
@itc.hu>
M:
Pasztor Szilard <don
@itc.hu>
S: Supported
S: Supported
COSA/SRP SYNC SERIAL DRIVER
COSA/SRP SYNC SERIAL DRIVER
...
...
drivers/net/8139too.c
View file @
1d90ac41
...
@@ -110,6 +110,7 @@
...
@@ -110,6 +110,7 @@
#include <linux/mii.h>
#include <linux/mii.h>
#include <linux/completion.h>
#include <linux/completion.h>
#include <linux/crc32.h>
#include <linux/crc32.h>
#include <linux/suspend.h>
#include <asm/io.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
...
@@ -1597,6 +1598,9 @@ static int rtl8139_thread (void *data)
...
@@ -1597,6 +1598,9 @@ static int rtl8139_thread (void *data)
timeout
=
next_tick
;
timeout
=
next_tick
;
do
{
do
{
timeout
=
interruptible_sleep_on_timeout
(
&
tp
->
thr_wait
,
timeout
);
timeout
=
interruptible_sleep_on_timeout
(
&
tp
->
thr_wait
,
timeout
);
/* make swsusp happy with our thread */
if
(
current
->
flags
&
PF_FREEZE
)
refrigerator
(
PF_IOTHREAD
);
}
while
(
!
signal_pending
(
current
)
&&
(
timeout
>
0
));
}
while
(
!
signal_pending
(
current
)
&&
(
timeout
>
0
));
if
(
signal_pending
(
current
))
{
if
(
signal_pending
(
current
))
{
...
...
drivers/net/b44.c
View file @
1d90ac41
/* b44.c: Broadcom 4400 device driver.
/* b44.c: Broadcom 4400 device driver.
*
*
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
* Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
*/
*/
#include <linux/kernel.h>
#include <linux/kernel.h>
...
@@ -14,6 +15,7 @@
...
@@ -14,6 +15,7 @@
#include <linux/pci.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/version.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/io.h>
...
@@ -23,8 +25,8 @@
...
@@ -23,8 +25,8 @@
#define DRV_MODULE_NAME "b44"
#define DRV_MODULE_NAME "b44"
#define PFX DRV_MODULE_NAME ": "
#define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "0.
6
"
#define DRV_MODULE_VERSION "0.
9
"
#define DRV_MODULE_RELDATE "
Nov 11, 2002
"
#define DRV_MODULE_RELDATE "
Jul 14, 2003
"
#define B44_DEF_MSG_ENABLE \
#define B44_DEF_MSG_ENABLE \
(NETIF_MSG_DRV | \
(NETIF_MSG_DRV | \
...
@@ -78,6 +80,15 @@ MODULE_PARM_DESC(b44_debug, "B44 bitmapped debugging message enable value");
...
@@ -78,6 +80,15 @@ MODULE_PARM_DESC(b44_debug, "B44 bitmapped debugging message enable value");
static
int
b44_debug
=
-
1
;
/* -1 == use B44_DEF_MSG_ENABLE as value */
static
int
b44_debug
=
-
1
;
/* -1 == use B44_DEF_MSG_ENABLE as value */
#ifndef PCI_DEVICE_ID_BCM4401
#define PCI_DEVICE_ID_BCM4401 0x4401
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#define IRQ_RETVAL(x)
#define irqreturn_t void
#endif
static
struct
pci_device_id
b44_pci_tbl
[]
__devinitdata
=
{
static
struct
pci_device_id
b44_pci_tbl
[]
__devinitdata
=
{
{
PCI_VENDOR_ID_BROADCOM
,
PCI_DEVICE_ID_BCM4401
,
{
PCI_VENDOR_ID_BROADCOM
,
PCI_DEVICE_ID_BCM4401
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0UL
},
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0UL
},
...
@@ -259,7 +270,7 @@ static int ssb_is_core_up(struct b44 *bp)
...
@@ -259,7 +270,7 @@ static int ssb_is_core_up(struct b44 *bp)
==
SBTMSLOW_CLOCK
);
==
SBTMSLOW_CLOCK
);
}
}
static
void
__b44_cam_write
(
struct
b44
*
bp
,
char
*
data
,
int
index
)
static
void
__b44_cam_write
(
struct
b44
*
bp
,
unsigned
char
*
data
,
int
index
)
{
{
u32
val
;
u32
val
;
...
@@ -521,7 +532,7 @@ static void b44_check_phy(struct b44 *bp)
...
@@ -521,7 +532,7 @@ static void b44_check_phy(struct b44 *bp)
/* Link now up */
/* Link now up */
netif_carrier_on
(
bp
->
dev
);
netif_carrier_on
(
bp
->
dev
);
b44_link_report
(
bp
);
b44_link_report
(
bp
);
}
else
if
(
netif_carrier_ok
(
bp
->
dev
))
{
}
else
if
(
netif_carrier_ok
(
bp
->
dev
)
&&
!
(
bmsr
&
BMSR_LSTATUS
)
)
{
/* Link now down */
/* Link now down */
netif_carrier_off
(
bp
->
dev
);
netif_carrier_off
(
bp
->
dev
);
b44_link_report
(
bp
);
b44_link_report
(
bp
);
...
@@ -650,8 +661,7 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
...
@@ -650,8 +661,7 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
src_map
=
&
bp
->
rx_buffers
[
src_idx
];
src_map
=
&
bp
->
rx_buffers
[
src_idx
];
dest_map
->
skb
=
src_map
->
skb
;
dest_map
->
skb
=
src_map
->
skb
;
rh
=
(
struct
rx_header
*
)
rh
=
(
struct
rx_header
*
)
src_map
->
skb
->
data
;
(
src_map
->
skb
->
data
-
bp
->
rx_offset
);
rh
->
len
=
0
;
rh
->
len
=
0
;
rh
->
flags
=
0
;
rh
->
flags
=
0
;
pci_unmap_addr_set
(
dest_map
,
mapping
,
pci_unmap_addr_set
(
dest_map
,
mapping
,
...
@@ -660,9 +670,12 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
...
@@ -660,9 +670,12 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
ctrl
=
src_desc
->
ctrl
;
ctrl
=
src_desc
->
ctrl
;
if
(
dest_idx
==
(
B44_RX_RING_SIZE
-
1
))
if
(
dest_idx
==
(
B44_RX_RING_SIZE
-
1
))
ctrl
|=
cpu_to_le32
(
DESC_CTRL_EOT
);
ctrl
|=
cpu_to_le32
(
DESC_CTRL_EOT
);
else
ctrl
&=
cpu_to_le32
(
~
DESC_CTRL_EOT
);
dest_desc
->
ctrl
=
ctrl
;
dest_desc
->
ctrl
=
ctrl
;
dest_desc
->
addr
=
src_desc
->
addr
;
dest_desc
->
addr
=
src_desc
->
addr
;
src_map
->
skb
=
NULL
;
}
}
static
int
b44_rx
(
struct
b44
*
bp
,
int
budget
)
static
int
b44_rx
(
struct
b44
*
bp
,
int
budget
)
...
@@ -685,7 +698,7 @@ static int b44_rx(struct b44 *bp, int budget)
...
@@ -685,7 +698,7 @@ static int b44_rx(struct b44 *bp, int budget)
pci_dma_sync_single
(
bp
->
pdev
,
map
,
pci_dma_sync_single
(
bp
->
pdev
,
map
,
RX_PKT_BUF_SZ
,
RX_PKT_BUF_SZ
,
PCI_DMA_FROMDEVICE
);
PCI_DMA_FROMDEVICE
);
rh
=
(
struct
rx_header
*
)
(
skb
->
data
-
bp
->
rx_offset
)
;
rh
=
(
struct
rx_header
*
)
skb
->
data
;
len
=
cpu_to_le16
(
rh
->
len
);
len
=
cpu_to_le16
(
rh
->
len
);
if
((
len
>
(
RX_PKT_BUF_SZ
-
bp
->
rx_offset
))
||
if
((
len
>
(
RX_PKT_BUF_SZ
-
bp
->
rx_offset
))
||
(
rh
->
flags
&
cpu_to_le16
(
RX_FLAG_ERRORS
)))
{
(
rh
->
flags
&
cpu_to_le16
(
RX_FLAG_ERRORS
)))
{
...
@@ -718,7 +731,9 @@ static int b44_rx(struct b44 *bp, int budget)
...
@@ -718,7 +731,9 @@ static int b44_rx(struct b44 *bp, int budget)
goto
drop_it
;
goto
drop_it
;
pci_unmap_single
(
bp
->
pdev
,
map
,
pci_unmap_single
(
bp
->
pdev
,
map
,
skb_size
,
PCI_DMA_FROMDEVICE
);
skb_size
,
PCI_DMA_FROMDEVICE
);
skb_put
(
skb
,
len
);
/* Leave out rx_header */
skb_put
(
skb
,
len
+
bp
->
rx_offset
);
skb_pull
(
skb
,
bp
->
rx_offset
);
}
else
{
}
else
{
struct
sk_buff
*
copy_skb
;
struct
sk_buff
*
copy_skb
;
...
@@ -730,8 +745,8 @@ static int b44_rx(struct b44 *bp, int budget)
...
@@ -730,8 +745,8 @@ static int b44_rx(struct b44 *bp, int budget)
copy_skb
->
dev
=
bp
->
dev
;
copy_skb
->
dev
=
bp
->
dev
;
skb_reserve
(
copy_skb
,
2
);
skb_reserve
(
copy_skb
,
2
);
skb_put
(
copy_skb
,
len
);
skb_put
(
copy_skb
,
len
);
/* DMA sync done above */
/* DMA sync done above
, copy just the actual packet
*/
memcpy
(
copy_skb
->
data
,
skb
->
data
,
len
);
memcpy
(
copy_skb
->
data
,
skb
->
data
+
bp
->
rx_offset
,
len
);
skb
=
copy_skb
;
skb
=
copy_skb
;
}
}
...
@@ -748,6 +763,7 @@ static int b44_rx(struct b44 *bp, int budget)
...
@@ -748,6 +763,7 @@ static int b44_rx(struct b44 *bp, int budget)
}
}
bp
->
rx_cons
=
cons
;
bp
->
rx_cons
=
cons
;
bw32
(
B44_DMARX_PTR
,
cons
*
sizeof
(
struct
dma_desc
));
return
received
;
return
received
;
}
}
...
@@ -764,6 +780,7 @@ static int b44_poll(struct net_device *netdev, int *budget)
...
@@ -764,6 +780,7 @@ static int b44_poll(struct net_device *netdev, int *budget)
b44_tx
(
bp
);
b44_tx
(
bp
);
/* spin_unlock(&bp->tx_lock); */
/* spin_unlock(&bp->tx_lock); */
}
}
spin_unlock_irq
(
&
bp
->
lock
);
done
=
1
;
done
=
1
;
if
(
bp
->
istat
&
ISTAT_RX
)
{
if
(
bp
->
istat
&
ISTAT_RX
)
{
...
@@ -783,10 +800,12 @@ static int b44_poll(struct net_device *netdev, int *budget)
...
@@ -783,10 +800,12 @@ static int b44_poll(struct net_device *netdev, int *budget)
}
}
if
(
bp
->
istat
&
ISTAT_ERRORS
)
{
if
(
bp
->
istat
&
ISTAT_ERRORS
)
{
spin_lock_irq
(
&
bp
->
lock
);
b44_halt
(
bp
);
b44_halt
(
bp
);
b44_init_rings
(
bp
);
b44_init_rings
(
bp
);
b44_init_hw
(
bp
);
b44_init_hw
(
bp
);
netif_wake_queue
(
bp
->
dev
);
netif_wake_queue
(
bp
->
dev
);
spin_unlock_irq
(
&
bp
->
lock
);
done
=
1
;
done
=
1
;
}
}
...
@@ -794,7 +813,6 @@ static int b44_poll(struct net_device *netdev, int *budget)
...
@@ -794,7 +813,6 @@ static int b44_poll(struct net_device *netdev, int *budget)
netif_rx_complete
(
netdev
);
netif_rx_complete
(
netdev
);
b44_enable_ints
(
bp
);
b44_enable_ints
(
bp
);
}
}
spin_unlock_irq
(
&
bp
->
lock
);
return
(
done
?
0
:
1
);
return
(
done
?
0
:
1
);
}
}
...
@@ -885,7 +903,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
...
@@ -885,7 +903,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
ctrl
|=
DESC_CTRL_EOT
;
ctrl
|=
DESC_CTRL_EOT
;
bp
->
tx_ring
[
entry
].
ctrl
=
cpu_to_le32
(
ctrl
);
bp
->
tx_ring
[
entry
].
ctrl
=
cpu_to_le32
(
ctrl
);
bp
->
tx_ring
[
entry
].
addr
=
cpu_to_le32
((
u32
)
mapping
);
bp
->
tx_ring
[
entry
].
addr
=
cpu_to_le32
((
u32
)
mapping
+
bp
->
dma_offset
);
entry
=
NEXT_TX
(
entry
);
entry
=
NEXT_TX
(
entry
);
...
@@ -1173,8 +1191,8 @@ static int b44_init_hw(struct b44 *bp)
...
@@ -1173,8 +1191,8 @@ static int b44_init_hw(struct b44 *bp)
__b44_set_rx_mode
(
bp
->
dev
);
__b44_set_rx_mode
(
bp
->
dev
);
/* MTU + eth header + possible VLAN tag + struct rx_header */
/* MTU + eth header + possible VLAN tag + struct rx_header */
bw32
(
B44_RXMAXLEN
,
bp
->
dev
->
mtu
+
ETH_HLEN
+
8
+
24
);
bw32
(
B44_RXMAXLEN
,
bp
->
dev
->
mtu
+
ETH_HLEN
+
8
+
RX_HEADER_LEN
);
bw32
(
B44_TXMAXLEN
,
bp
->
dev
->
mtu
+
ETH_HLEN
+
8
+
24
);
bw32
(
B44_TXMAXLEN
,
bp
->
dev
->
mtu
+
ETH_HLEN
+
8
+
RX_HEADER_LEN
);
bw32
(
B44_TX_WMARK
,
56
);
/* XXX magic */
bw32
(
B44_TX_WMARK
,
56
);
/* XXX magic */
bw32
(
B44_DMATX_CTRL
,
DMATX_CTRL_ENABLE
);
bw32
(
B44_DMATX_CTRL
,
DMATX_CTRL_ENABLE
);
...
@@ -1184,6 +1202,7 @@ static int b44_init_hw(struct b44 *bp)
...
@@ -1184,6 +1202,7 @@ static int b44_init_hw(struct b44 *bp)
bw32
(
B44_DMARX_ADDR
,
bp
->
rx_ring_dma
+
bp
->
dma_offset
);
bw32
(
B44_DMARX_ADDR
,
bp
->
rx_ring_dma
+
bp
->
dma_offset
);
bw32
(
B44_DMARX_PTR
,
bp
->
rx_pending
);
bw32
(
B44_DMARX_PTR
,
bp
->
rx_pending
);
bp
->
rx_prod
=
bp
->
rx_pending
;
bw32
(
B44_MIB_CTRL
,
MIB_CTRL_CLR_ON_READ
);
bw32
(
B44_MIB_CTRL
,
MIB_CTRL_CLR_ON_READ
);
...
@@ -1345,6 +1364,8 @@ static void __b44_set_rx_mode(struct net_device *dev)
...
@@ -1345,6 +1364,8 @@ static void __b44_set_rx_mode(struct net_device *dev)
__b44_load_mcast
(
bp
,
dev
);
__b44_load_mcast
(
bp
,
dev
);
bw32
(
B44_RXCONFIG
,
val
);
bw32
(
B44_RXCONFIG
,
val
);
val
=
br32
(
B44_CAM_CTRL
);
bw32
(
B44_CAM_CTRL
,
val
|
CAM_CTRL_ENABLE
);
}
}
}
}
...
@@ -1678,8 +1699,9 @@ static int __devinit b44_get_invariants(struct b44 *bp)
...
@@ -1678,8 +1699,9 @@ static int __devinit b44_get_invariants(struct b44 *bp)
bp
->
core_unit
=
ssb_core_unit
(
bp
);
bp
->
core_unit
=
ssb_core_unit
(
bp
);
bp
->
dma_offset
=
ssb_get_addr
(
bp
,
SBID_PCI_DMA
,
0
);
bp
->
dma_offset
=
ssb_get_addr
(
bp
,
SBID_PCI_DMA
,
0
);
bp
->
flags
|=
B44_FLAG_BUGGY_TXPTR
;
/* XXX - really required?
bp->flags |= B44_FLAG_BUGGY_TXPTR;
*/
out:
out:
return
err
;
return
err
;
}
}
...
...
drivers/net/b44.h
View file @
1d90ac41
...
@@ -142,7 +142,7 @@
...
@@ -142,7 +142,7 @@
#define MDIO_OP_READ 2
#define MDIO_OP_READ 2
#define MDIO_DATA_SB_MASK 0xc0000000
/* Start Bits */
#define MDIO_DATA_SB_MASK 0xc0000000
/* Start Bits */
#define MDIO_DATA_SB_SHIFT 30
#define MDIO_DATA_SB_SHIFT 30
#define MDIO_DATA_SB_START 0x
1
0000000
/* Start Of Frame */
#define MDIO_DATA_SB_START 0x
4
0000000
/* Start Of Frame */
#define B44_EMAC_IMASK 0x0418UL
/* EMAC Interrupt Mask */
#define B44_EMAC_IMASK 0x0418UL
/* EMAC Interrupt Mask */
#define B44_EMAC_ISTAT 0x041CUL
/* EMAC Interrupt Status */
#define B44_EMAC_ISTAT 0x041CUL
/* EMAC Interrupt Status */
#define EMAC_INT_MII 0x00000001
/* MII MDIO Interrupt */
#define EMAC_INT_MII 0x00000001
/* MII MDIO Interrupt */
...
...
drivers/net/e1000/e1000_ethtool.c
View file @
1d90ac41
...
@@ -1475,6 +1475,107 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
...
@@ -1475,6 +1475,107 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
return
-
EFAULT
;
return
-
EFAULT
;
return
0
;
return
0
;
}
}
case
ETHTOOL_GRXCSUM
:
{
struct
ethtool_value
edata
=
{
ETHTOOL_GRXCSUM
};
edata
.
data
=
adapter
->
rx_csum
;
if
(
copy_to_user
(
addr
,
&
edata
,
sizeof
(
edata
)))
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_SRXCSUM
:
{
struct
ethtool_value
edata
;
if
(
copy_from_user
(
&
edata
,
addr
,
sizeof
(
edata
)))
return
-
EFAULT
;
adapter
->
rx_csum
=
edata
.
data
;
if
(
netif_running
(
netdev
))
{
e1000_down
(
adapter
);
e1000_up
(
adapter
);
}
else
e1000_reset
(
adapter
);
return
0
;
}
case
ETHTOOL_GTXCSUM
:
{
struct
ethtool_value
edata
=
{
ETHTOOL_GTXCSUM
};
edata
.
data
=
(
netdev
->
features
&
NETIF_F_HW_CSUM
)
!=
0
;
if
(
copy_to_user
(
addr
,
&
edata
,
sizeof
(
edata
)))
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_STXCSUM
:
{
struct
ethtool_value
edata
;
if
(
copy_from_user
(
&
edata
,
addr
,
sizeof
(
edata
)))
return
-
EFAULT
;
if
(
adapter
->
hw
.
mac_type
<
e1000_82543
)
{
if
(
edata
.
data
!=
0
)
return
-
EINVAL
;
return
0
;
}
if
(
edata
.
data
)
netdev
->
features
|=
NETIF_F_HW_CSUM
;
else
netdev
->
features
&=
~
NETIF_F_HW_CSUM
;
return
0
;
}
case
ETHTOOL_GSG
:
{
struct
ethtool_value
edata
=
{
ETHTOOL_GSG
};
edata
.
data
=
(
netdev
->
features
&
NETIF_F_SG
)
!=
0
;
if
(
copy_to_user
(
addr
,
&
edata
,
sizeof
(
edata
)))
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_SSG
:
{
struct
ethtool_value
edata
;
if
(
copy_from_user
(
&
edata
,
addr
,
sizeof
(
edata
)))
return
-
EFAULT
;
if
(
edata
.
data
)
netdev
->
features
|=
NETIF_F_SG
;
else
netdev
->
features
&=
~
NETIF_F_SG
;
return
0
;
}
#ifdef NETIF_F_TSO
case
ETHTOOL_GTSO
:
{
struct
ethtool_value
edata
=
{
ETHTOOL_GTSO
};
edata
.
data
=
(
netdev
->
features
&
NETIF_F_TSO
)
!=
0
;
if
(
copy_to_user
(
addr
,
&
edata
,
sizeof
(
edata
)))
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_STSO
:
{
struct
ethtool_value
edata
;
if
(
copy_from_user
(
&
edata
,
addr
,
sizeof
(
edata
)))
return
-
EFAULT
;
if
((
adapter
->
hw
.
mac_type
<
e1000_82544
)
||
(
adapter
->
hw
.
mac_type
==
e1000_82547
))
{
if
(
edata
.
data
!=
0
)
return
-
EINVAL
;
return
0
;
}
if
(
edata
.
data
)
netdev
->
features
|=
NETIF_F_TSO
;
else
netdev
->
features
&=
~
NETIF_F_TSO
;
return
0
;
}
#endif
default:
default:
return
-
EOPNOTSUPP
;
return
-
EOPNOTSUPP
;
}
}
...
...
drivers/net/e1000/e1000_main.c
View file @
1d90ac41
...
@@ -50,7 +50,7 @@
...
@@ -50,7 +50,7 @@
char
e1000_driver_name
[]
=
"e1000"
;
char
e1000_driver_name
[]
=
"e1000"
;
char
e1000_driver_string
[]
=
"Intel(R) PRO/1000 Network Driver"
;
char
e1000_driver_string
[]
=
"Intel(R) PRO/1000 Network Driver"
;
char
e1000_driver_version
[]
=
"5.1.13-k
1
"
;
char
e1000_driver_version
[]
=
"5.1.13-k
2
"
;
char
e1000_copyright
[]
=
"Copyright (c) 1999-2003 Intel Corporation."
;
char
e1000_copyright
[]
=
"Copyright (c) 1999-2003 Intel Corporation."
;
/* e1000_pci_tbl - PCI Device ID Table
/* e1000_pci_tbl - PCI Device ID Table
...
...
drivers/net/ne2k-pci.c
View file @
1d90ac41
...
@@ -635,6 +635,7 @@ static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
...
@@ -635,6 +635,7 @@ static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
unregister_netdev
(
dev
);
unregister_netdev
(
dev
);
release_region
(
dev
->
base_addr
,
NE_IO_EXTENT
);
release_region
(
dev
->
base_addr
,
NE_IO_EXTENT
);
kfree
(
dev
->
priv
);
kfree
(
dev
);
kfree
(
dev
);
pci_set_drvdata
(
pdev
,
NULL
);
pci_set_drvdata
(
pdev
,
NULL
);
}
}
...
...
drivers/net/pcmcia/3c574_cs.c
View file @
1d90ac41
...
@@ -296,7 +296,8 @@ static dev_link_t *tc574_attach(void)
...
@@ -296,7 +296,8 @@ static dev_link_t *tc574_attach(void)
lp
=
dev
->
priv
;
lp
=
dev
->
priv
;
link
=
&
lp
->
link
;
link
=
&
lp
->
link
;
link
->
priv
=
dev
;
link
->
priv
=
dev
;
spin_lock_init
(
&
lp
->
window_lock
);
init_timer
(
&
link
->
release
);
init_timer
(
&
link
->
release
);
link
->
release
.
function
=
&
tc574_release
;
link
->
release
.
function
=
&
tc574_release
;
link
->
release
.
data
=
(
unsigned
long
)
link
;
link
->
release
.
data
=
(
unsigned
long
)
link
;
...
...
drivers/net/sk_mca.c
View file @
1d90ac41
...
@@ -254,8 +254,7 @@ static void SetLANCE(struct SKMCA_NETDEV *dev, u16 addr, u16 value)
...
@@ -254,8 +254,7 @@ static void SetLANCE(struct SKMCA_NETDEV *dev, u16 addr, u16 value)
/* disable interrupts */
/* disable interrupts */
save_flags
(
flags
);
spin_lock_irqsave
(
&
priv
->
lock
,
flags
);
cli
();
/* wait until no transfer is pending */
/* wait until no transfer is pending */
...
@@ -281,7 +280,7 @@ static void SetLANCE(struct SKMCA_NETDEV *dev, u16 addr, u16 value)
...
@@ -281,7 +280,7 @@ static void SetLANCE(struct SKMCA_NETDEV *dev, u16 addr, u16 value)
/* reenable interrupts */
/* reenable interrupts */
restore_flags
(
flags
);
spin_lock_irqrestore
(
&
priv
->
lock
,
flags
);
}
}
/* get LANCE register */
/* get LANCE register */
...
@@ -294,8 +293,7 @@ static u16 GetLANCE(struct SKMCA_NETDEV *dev, u16 addr)
...
@@ -294,8 +293,7 @@ static u16 GetLANCE(struct SKMCA_NETDEV *dev, u16 addr)
/* disable interrupts */
/* disable interrupts */
save_flags
(
flags
);
spin_lock_irqsave
(
&
priv
->
lock
,
flags
);
cli
();
/* wait until no transfer is pending */
/* wait until no transfer is pending */
...
@@ -321,7 +319,7 @@ static u16 GetLANCE(struct SKMCA_NETDEV *dev, u16 addr)
...
@@ -321,7 +319,7 @@ static u16 GetLANCE(struct SKMCA_NETDEV *dev, u16 addr)
/* reenable interrupts */
/* reenable interrupts */
restore_flags
(
flags
);
spin_lock_irqrestore
(
&
priv
->
lock
,
flags
);
return
res
;
return
res
;
}
}
...
@@ -968,8 +966,9 @@ static int skmca_tx(struct sk_buff *skb, struct SKMCA_NETDEV *dev)
...
@@ -968,8 +966,9 @@ static int skmca_tx(struct sk_buff *skb, struct SKMCA_NETDEV *dev)
#endif
#endif
/* one more descriptor busy */
/* one more descriptor busy */
save_flags
(
flags
);
cli
();
spin_lock_irqsave
(
&
priv
->
lock
,
flags
);
priv
->
nexttxput
++
;
priv
->
nexttxput
++
;
if
(
priv
->
nexttxput
>=
TXCOUNT
)
if
(
priv
->
nexttxput
>=
TXCOUNT
)
priv
->
nexttxput
=
0
;
priv
->
nexttxput
=
0
;
...
@@ -994,7 +993,7 @@ static int skmca_tx(struct sk_buff *skb, struct SKMCA_NETDEV *dev)
...
@@ -994,7 +993,7 @@ static int skmca_tx(struct sk_buff *skb, struct SKMCA_NETDEV *dev)
if
(
priv
->
txbusy
==
0
)
if
(
priv
->
txbusy
==
0
)
SetLANCE
(
dev
,
LANCE_CSR0
,
CSR0_INEA
|
CSR0_TDMD
);
SetLANCE
(
dev
,
LANCE_CSR0
,
CSR0_INEA
|
CSR0_TDMD
);
restore_flags
(
flags
);
spin_lock_irqrestore
(
&
priv
->
lock
,
flags
);
tx_done:
tx_done:
...
...
drivers/net/sk_mca.h
View file @
1d90ac41
...
@@ -53,6 +53,7 @@ typedef struct {
...
@@ -53,6 +53,7 @@ typedef struct {
int
realirq
;
/* memorizes actual IRQ, even when
int
realirq
;
/* memorizes actual IRQ, even when
currently not allocated */
currently not allocated */
skmca_medium
medium
;
/* physical cannector */
skmca_medium
medium
;
/* physical cannector */
spinlock_t
lock
;
}
skmca_priv
;
}
skmca_priv
;
/* card registers: control/status register bits */
/* card registers: control/status register bits */
...
...
drivers/net/via-rhine.c
View file @
1d90ac41
...
@@ -122,11 +122,14 @@
...
@@ -122,11 +122,14 @@
- No filtering multicast in promisc mode (Edward Peng)
- No filtering multicast in promisc mode (Edward Peng)
- Fix for Rhine-I Tx timeouts
- Fix for Rhine-I Tx timeouts
LK1.1.19 (Roger Luethi)
- Increase Tx threshold for unspecified errors
*/
*/
#define DRV_NAME "via-rhine"
#define DRV_NAME "via-rhine"
#define DRV_VERSION "1.1.1
8
-2.5"
#define DRV_VERSION "1.1.1
9
-2.5"
#define DRV_RELDATE "July-
4
-2003"
#define DRV_RELDATE "July-
12
-2003"
/* A few user-configurable values.
/* A few user-configurable values.
...
@@ -1664,9 +1667,13 @@ static void via_rhine_error(struct net_device *dev, int intr_status)
...
@@ -1664,9 +1667,13 @@ static void via_rhine_error(struct net_device *dev, int intr_status)
}
}
if
((
intr_status
&
IntrTxError
)
&&
~
(
IntrTxAborted
|
IntrTxUnderrun
|
if
((
intr_status
&
IntrTxError
)
&&
~
(
IntrTxAborted
|
IntrTxUnderrun
|
IntrTxDescRace
))
{
IntrTxDescRace
))
{
if
(
debug
>
2
)
if
(
np
->
tx_thresh
<
0xE0
)
{
printk
(
KERN_INFO
"%s: Unspecified error.
\n
"
,
writeb
(
np
->
tx_thresh
+=
0x20
,
ioaddr
+
TxConfig
);
dev
->
name
);
}
if
(
debug
>
1
)
printk
(
KERN_INFO
"%s: Unspecified error. Tx "
"threshold now %2.2x.
\n
"
,
dev
->
name
,
np
->
tx_thresh
);
}
}
if
(
intr_status
&
(
IntrTxAborted
|
IntrTxUnderrun
|
IntrTxDescRace
|
if
(
intr_status
&
(
IntrTxAborted
|
IntrTxUnderrun
|
IntrTxDescRace
|
IntrTxError
))
IntrTxError
))
...
...
drivers/net/wan/Kconfig
View file @
1d90ac41
...
@@ -60,9 +60,10 @@ config COSA
...
@@ -60,9 +60,10 @@ config COSA
#
#
# COMX drivers
# COMX drivers
#
#
# Not updated to 2.6.
config COMX
config COMX
tristate "MultiGate (COMX) synchronous serial boards support"
tristate "MultiGate (COMX) synchronous serial boards support"
depends on WAN && (ISA || PCI)
depends on WAN && (ISA || PCI)
&& OBSOLETE
---help---
---help---
Say Y if you want to use any board from the MultiGate (COMX) family.
Say Y if you want to use any board from the MultiGate (COMX) family.
These boards are synchronous serial adapters for the PC,
These boards are synchronous serial adapters for the PC,
...
...
drivers/net/wireless/Kconfig
View file @
1d90ac41
...
@@ -296,6 +296,14 @@ config PCMCIA_ATMEL
...
@@ -296,6 +296,14 @@ config PCMCIA_ATMEL
firmware package can be downloaded from
firmware package can be downloaded from
http://www.thekelleys.org.uk/atmel/atmel_firmware.tar.gz
http://www.thekelleys.org.uk/atmel/atmel_firmware.tar.gz
config PCMCIA_WL3501
tristate "Planet WL3501 PCMCIA cards"
depends on NET_RADIO && EXPERIMENTAL && PCMCIA
---help---
A driver for WL3501 PCMCIA 802.11 wireless cards made by Planet.
It has basic support for Linux wireless extensions and initial
micro support for ethtool.
# yes, this works even when no drivers are selected
# yes, this works even when no drivers are selected
config NET_WIRELESS
config NET_WIRELESS
bool
bool
...
...
drivers/net/wireless/Makefile
View file @
1d90ac41
...
@@ -23,4 +23,4 @@ obj-$(CONFIG_AIRO_CS) += airo_cs.o airo.o
...
@@ -23,4 +23,4 @@ obj-$(CONFIG_AIRO_CS) += airo_cs.o airo.o
# 16-bit wireless PCMCIA client drivers
# 16-bit wireless PCMCIA client drivers
obj-$(CONFIG_PCMCIA_RAYCS)
+=
ray_cs.o
obj-$(CONFIG_PCMCIA_RAYCS)
+=
ray_cs.o
obj-$(CONFIG_PCMCIA_ATMEL)
+=
atmel_cs.o atmel.o
obj-$(CONFIG_PCMCIA_ATMEL)
+=
atmel_cs.o atmel.o
obj-$(CONFIG_PCMCIA_WL3501)
+=
wl3501_cs.o
drivers/net/wireless/airo.c
View file @
1d90ac41
...
@@ -648,9 +648,38 @@ typedef struct {
...
@@ -648,9 +648,38 @@ typedef struct {
u16
currentXmitRate
;
u16
currentXmitRate
;
u16
apDevExtensions
;
u16
apDevExtensions
;
u16
normalizedSignalStrength
;
u16
normalizedSignalStrength
;
u16
_reserved1
;
u16
shortPreamble
;
u8
apIP
[
4
];
u8
apIP
[
4
];
u16
_reserved
[
7
];
u8
noisePercent
;
/* Noise percent in last second */
u8
noisedBm
;
/* Noise dBm in last second */
u8
noiseAvePercent
;
/* Noise percent in last minute */
u8
noiseAvedBm
;
/* Noise dBm in last minute */
u8
noiseMaxPercent
;
/* Highest noise percent in last minute */
u8
noiseMaxdBm
;
/* Highest noise dbm in last minute */
u16
load
;
u8
carrier
[
4
];
u16
assocStatus
;
#define STAT_NOPACKETS 0
#define STAT_NOCARRIERSET 10
#define STAT_GOTCARRIERSET 11
#define STAT_WRONGSSID 20
#define STAT_BADCHANNEL 25
#define STAT_BADBITRATES 30
#define STAT_BADPRIVACY 35
#define STAT_APFOUND 40
#define STAT_APREJECTED 50
#define STAT_AUTHENTICATING 60
#define STAT_DEAUTHENTICATED 61
#define STAT_AUTHTIMEOUT 62
#define STAT_ASSOCIATING 70
#define STAT_DEASSOCIATED 71
#define STAT_ASSOCTIMEOUT 72
#define STAT_NOTAIROAP 73
#define STAT_ASSOCIATED 80
#define STAT_LEAPING 90
#define STAT_LEAPFAILED 91
#define STAT_LEAPTIMEDOUT 92
#define STAT_LEAPCOMPLETE 93
}
StatusRid
;
}
StatusRid
;
typedef
struct
{
typedef
struct
{
...
@@ -923,8 +952,8 @@ static int get_dec_u16( char *buffer, int *start, int limit );
...
@@ -923,8 +952,8 @@ static int get_dec_u16( char *buffer, int *start, int limit );
static
void
OUT4500
(
struct
airo_info
*
,
u16
register
,
u16
value
);
static
void
OUT4500
(
struct
airo_info
*
,
u16
register
,
u16
value
);
static
unsigned
short
IN4500
(
struct
airo_info
*
,
u16
register
);
static
unsigned
short
IN4500
(
struct
airo_info
*
,
u16
register
);
static
u16
setup_card
(
struct
airo_info
*
,
u8
*
mac
);
static
u16
setup_card
(
struct
airo_info
*
,
u8
*
mac
);
static
int
enable_MAC
(
struct
airo_info
*
ai
,
Resp
*
rsp
);
static
int
enable_MAC
(
struct
airo_info
*
ai
,
Resp
*
rsp
,
int
lock
);
static
void
disable_MAC
(
struct
airo_info
*
ai
);
static
void
disable_MAC
(
struct
airo_info
*
ai
,
int
lock
);
static
void
enable_interrupts
(
struct
airo_info
*
);
static
void
enable_interrupts
(
struct
airo_info
*
);
static
void
disable_interrupts
(
struct
airo_info
*
);
static
void
disable_interrupts
(
struct
airo_info
*
);
static
u16
issuecommand
(
struct
airo_info
*
,
Cmd
*
pCmd
,
Resp
*
pRsp
);
static
u16
issuecommand
(
struct
airo_info
*
,
Cmd
*
pCmd
,
Resp
*
pRsp
);
...
@@ -938,11 +967,11 @@ static int fast_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen,
...
@@ -938,11 +967,11 @@ static int fast_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen,
static
int
bap_write
(
struct
airo_info
*
,
const
u16
*
pu16Src
,
int
bytelen
,
static
int
bap_write
(
struct
airo_info
*
,
const
u16
*
pu16Src
,
int
bytelen
,
int
whichbap
);
int
whichbap
);
static
int
PC4500_accessrid
(
struct
airo_info
*
,
u16
rid
,
u16
accmd
);
static
int
PC4500_accessrid
(
struct
airo_info
*
,
u16
rid
,
u16
accmd
);
static
int
PC4500_readrid
(
struct
airo_info
*
,
u16
rid
,
void
*
pBuf
,
int
len
);
static
int
PC4500_readrid
(
struct
airo_info
*
,
u16
rid
,
void
*
pBuf
,
int
len
,
int
lock
);
static
int
PC4500_writerid
(
struct
airo_info
*
,
u16
rid
,
const
void
static
int
PC4500_writerid
(
struct
airo_info
*
,
u16
rid
,
const
void
*
pBuf
,
int
len
);
*
pBuf
,
int
len
,
int
lock
);
static
int
do_writerid
(
struct
airo_info
*
,
u16
rid
,
const
void
*
rid_data
,
static
int
do_writerid
(
struct
airo_info
*
,
u16
rid
,
const
void
*
rid_data
,
int
len
);
int
len
,
int
dummy
);
static
u16
transmit_allocate
(
struct
airo_info
*
,
int
lenPayload
,
int
raw
);
static
u16
transmit_allocate
(
struct
airo_info
*
,
int
lenPayload
,
int
raw
);
static
int
transmit_802_3_packet
(
struct
airo_info
*
,
int
len
,
char
*
pPacket
);
static
int
transmit_802_3_packet
(
struct
airo_info
*
,
int
len
,
char
*
pPacket
);
static
int
transmit_802_11_packet
(
struct
airo_info
*
,
int
len
,
char
*
pPacket
);
static
int
transmit_802_11_packet
(
struct
airo_info
*
,
int
len
,
char
*
pPacket
);
...
@@ -986,7 +1015,6 @@ struct airo_info {
...
@@ -986,7 +1015,6 @@ struct airo_info {
#define FLAG_PROMISC IFF_PROMISC
/* 0x100 - include/linux/if.h */
#define FLAG_PROMISC IFF_PROMISC
/* 0x100 - include/linux/if.h */
#define FLAG_RADIO_OFF 0x02
/* User disabling of MAC */
#define FLAG_RADIO_OFF 0x02
/* User disabling of MAC */
#define FLAG_RADIO_DOWN 0x08
/* ifup/ifdown disabling of MAC */
#define FLAG_RADIO_DOWN 0x08
/* ifup/ifdown disabling of MAC */
#define FLAG_LOCKED 2
/* 0x04 - use as a bit offset */
#define FLAG_FLASHING 0x10
#define FLAG_FLASHING 0x10
#define FLAG_ADHOC 0x01
/* Needed by MIC */
#define FLAG_ADHOC 0x01
/* Needed by MIC */
#define FLAG_MIC_CAPABLE 0x20
#define FLAG_MIC_CAPABLE 0x20
...
@@ -999,6 +1027,7 @@ struct airo_info {
...
@@ -999,6 +1027,7 @@ struct airo_info {
tdsRssiEntry
*
rssi
;
tdsRssiEntry
*
rssi
;
struct
semaphore
sem
;
struct
semaphore
sem
;
struct
task_struct
*
task
;
struct
task_struct
*
task
;
struct
work_struct
stats_task
;
struct
work_struct
promisc_task
;
struct
work_struct
promisc_task
;
struct
{
struct
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
...
@@ -1056,7 +1085,7 @@ static int readBSSListRid(struct airo_info *ai, int first,
...
@@ -1056,7 +1085,7 @@ static int readBSSListRid(struct airo_info *ai, int first,
ai
->
task
=
NULL
;
ai
->
task
=
NULL
;
}
}
rc
=
PC4500_readrid
(
ai
,
first
?
RID_BSSLISTFIRST
:
RID_BSSLISTNEXT
,
rc
=
PC4500_readrid
(
ai
,
first
?
RID_BSSLISTFIRST
:
RID_BSSLISTNEXT
,
list
,
sizeof
(
*
list
));
list
,
sizeof
(
*
list
)
,
1
);
list
->
len
=
le16_to_cpu
(
list
->
len
);
list
->
len
=
le16_to_cpu
(
list
->
len
);
list
->
index
=
le16_to_cpu
(
list
->
index
);
list
->
index
=
le16_to_cpu
(
list
->
index
);
...
@@ -1071,7 +1100,7 @@ static int readBSSListRid(struct airo_info *ai, int first,
...
@@ -1071,7 +1100,7 @@ static int readBSSListRid(struct airo_info *ai, int first,
static
int
readWepKeyRid
(
struct
airo_info
*
ai
,
WepKeyRid
*
wkr
,
int
temp
)
{
static
int
readWepKeyRid
(
struct
airo_info
*
ai
,
WepKeyRid
*
wkr
,
int
temp
)
{
int
rc
=
PC4500_readrid
(
ai
,
temp
?
RID_WEP_TEMP
:
RID_WEP_PERM
,
int
rc
=
PC4500_readrid
(
ai
,
temp
?
RID_WEP_TEMP
:
RID_WEP_PERM
,
wkr
,
sizeof
(
*
wkr
));
wkr
,
sizeof
(
*
wkr
)
,
1
);
wkr
->
len
=
le16_to_cpu
(
wkr
->
len
);
wkr
->
len
=
le16_to_cpu
(
wkr
->
len
);
wkr
->
kindex
=
le16_to_cpu
(
wkr
->
kindex
);
wkr
->
kindex
=
le16_to_cpu
(
wkr
->
kindex
);
...
@@ -1080,17 +1109,17 @@ static int readWepKeyRid(struct airo_info*ai, WepKeyRid *wkr, int temp) {
...
@@ -1080,17 +1109,17 @@ static int readWepKeyRid(struct airo_info*ai, WepKeyRid *wkr, int temp) {
}
}
/* In the writeXXXRid routines we copy the rids so that we don't screwup
/* In the writeXXXRid routines we copy the rids so that we don't screwup
* the originals when we endian them... */
* the originals when we endian them... */
static
int
writeWepKeyRid
(
struct
airo_info
*
ai
,
WepKeyRid
*
pwkr
,
int
perm
)
{
static
int
writeWepKeyRid
(
struct
airo_info
*
ai
,
WepKeyRid
*
pwkr
,
int
perm
,
int
lock
)
{
int
rc
;
int
rc
;
WepKeyRid
wkr
=
*
pwkr
;
WepKeyRid
wkr
=
*
pwkr
;
wkr
.
len
=
cpu_to_le16
(
wkr
.
len
);
wkr
.
len
=
cpu_to_le16
(
wkr
.
len
);
wkr
.
kindex
=
cpu_to_le16
(
wkr
.
kindex
);
wkr
.
kindex
=
cpu_to_le16
(
wkr
.
kindex
);
wkr
.
klen
=
cpu_to_le16
(
wkr
.
klen
);
wkr
.
klen
=
cpu_to_le16
(
wkr
.
klen
);
rc
=
PC4500_writerid
(
ai
,
RID_WEP_TEMP
,
&
wkr
,
sizeof
(
wkr
));
rc
=
PC4500_writerid
(
ai
,
RID_WEP_TEMP
,
&
wkr
,
sizeof
(
wkr
)
,
lock
);
if
(
rc
!=
SUCCESS
)
printk
(
KERN_ERR
"airo: WEP_TEMP set %x
\n
"
,
rc
);
if
(
rc
!=
SUCCESS
)
printk
(
KERN_ERR
"airo: WEP_TEMP set %x
\n
"
,
rc
);
if
(
perm
)
{
if
(
perm
)
{
rc
=
PC4500_writerid
(
ai
,
RID_WEP_PERM
,
&
wkr
,
sizeof
(
wkr
));
rc
=
PC4500_writerid
(
ai
,
RID_WEP_PERM
,
&
wkr
,
sizeof
(
wkr
)
,
lock
);
if
(
rc
!=
SUCCESS
)
{
if
(
rc
!=
SUCCESS
)
{
printk
(
KERN_ERR
"airo: WEP_PERM set %x
\n
"
,
rc
);
printk
(
KERN_ERR
"airo: WEP_PERM set %x
\n
"
,
rc
);
}
}
...
@@ -1100,7 +1129,7 @@ static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm) {
...
@@ -1100,7 +1129,7 @@ static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm) {
static
int
readSsidRid
(
struct
airo_info
*
ai
,
SsidRid
*
ssidr
)
{
static
int
readSsidRid
(
struct
airo_info
*
ai
,
SsidRid
*
ssidr
)
{
int
i
;
int
i
;
int
rc
=
PC4500_readrid
(
ai
,
RID_SSID
,
ssidr
,
sizeof
(
*
ssidr
));
int
rc
=
PC4500_readrid
(
ai
,
RID_SSID
,
ssidr
,
sizeof
(
*
ssidr
)
,
1
);
ssidr
->
len
=
le16_to_cpu
(
ssidr
->
len
);
ssidr
->
len
=
le16_to_cpu
(
ssidr
->
len
);
for
(
i
=
0
;
i
<
3
;
i
++
)
{
for
(
i
=
0
;
i
<
3
;
i
++
)
{
...
@@ -1117,10 +1146,10 @@ static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr) {
...
@@ -1117,10 +1146,10 @@ static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr) {
for
(
i
=
0
;
i
<
3
;
i
++
)
{
for
(
i
=
0
;
i
<
3
;
i
++
)
{
ssidr
.
ssids
[
i
].
len
=
cpu_to_le16
(
ssidr
.
ssids
[
i
].
len
);
ssidr
.
ssids
[
i
].
len
=
cpu_to_le16
(
ssidr
.
ssids
[
i
].
len
);
}
}
rc
=
PC4500_writerid
(
ai
,
RID_SSID
,
&
ssidr
,
sizeof
(
ssidr
));
rc
=
PC4500_writerid
(
ai
,
RID_SSID
,
&
ssidr
,
sizeof
(
ssidr
)
,
1
);
return
rc
;
return
rc
;
}
}
static
int
readConfigRid
(
struct
airo_info
*
ai
)
{
static
int
readConfigRid
(
struct
airo_info
*
ai
,
int
lock
)
{
int
rc
;
int
rc
;
u16
*
s
;
u16
*
s
;
ConfigRid
cfg
;
ConfigRid
cfg
;
...
@@ -1128,7 +1157,7 @@ static int readConfigRid(struct airo_info*ai) {
...
@@ -1128,7 +1157,7 @@ static int readConfigRid(struct airo_info*ai) {
if
(
ai
->
config
.
len
)
if
(
ai
->
config
.
len
)
return
SUCCESS
;
return
SUCCESS
;
rc
=
PC4500_readrid
(
ai
,
RID_ACTUALCONFIG
,
&
cfg
,
sizeof
(
cfg
));
rc
=
PC4500_readrid
(
ai
,
RID_ACTUALCONFIG
,
&
cfg
,
sizeof
(
cfg
)
,
lock
);
if
(
rc
!=
SUCCESS
)
if
(
rc
!=
SUCCESS
)
return
rc
;
return
rc
;
...
@@ -1157,7 +1186,7 @@ static inline void checkThrottle(struct airo_info *ai) {
...
@@ -1157,7 +1186,7 @@ static inline void checkThrottle(struct airo_info *ai) {
}
}
}
}
}
}
static
int
writeConfigRid
(
struct
airo_info
*
ai
)
{
static
int
writeConfigRid
(
struct
airo_info
*
ai
,
int
lock
)
{
u16
*
s
;
u16
*
s
;
ConfigRid
cfgr
;
ConfigRid
cfgr
;
...
@@ -1184,33 +1213,34 @@ static int writeConfigRid(struct airo_info*ai) {
...
@@ -1184,33 +1213,34 @@ static int writeConfigRid(struct airo_info*ai) {
for
(
s
=
&
cfgr
.
arlThreshold
;
s
<=
&
cfgr
.
autoWake
;
s
++
)
for
(
s
=
&
cfgr
.
arlThreshold
;
s
<=
&
cfgr
.
autoWake
;
s
++
)
*
s
=
cpu_to_le16
(
*
s
);
*
s
=
cpu_to_le16
(
*
s
);
return
PC4500_writerid
(
ai
,
RID_CONFIG
,
&
cfgr
,
sizeof
(
cfgr
));
return
PC4500_writerid
(
ai
,
RID_CONFIG
,
&
cfgr
,
sizeof
(
cfgr
)
,
lock
);
}
}
static
int
readStatusRid
(
struct
airo_info
*
ai
,
StatusRid
*
statr
)
{
static
int
readStatusRid
(
struct
airo_info
*
ai
,
StatusRid
*
statr
)
{
int
rc
=
PC4500_readrid
(
ai
,
RID_STATUS
,
statr
,
sizeof
(
*
statr
));
int
rc
=
PC4500_readrid
(
ai
,
RID_STATUS
,
statr
,
sizeof
(
*
statr
)
,
1
);
u16
*
s
;
u16
*
s
;
statr
->
len
=
le16_to_cpu
(
statr
->
len
);
statr
->
len
=
le16_to_cpu
(
statr
->
len
);
for
(
s
=
&
statr
->
mode
;
s
<=
&
statr
->
SSIDlen
;
s
++
)
*
s
=
le16_to_cpu
(
*
s
);
for
(
s
=
&
statr
->
mode
;
s
<=
&
statr
->
SSIDlen
;
s
++
)
*
s
=
le16_to_cpu
(
*
s
);
for
(
s
=
&
statr
->
beaconPeriod
;
s
<=
&
statr
->
_reserved
[
9
]
;
s
++
)
for
(
s
=
&
statr
->
beaconPeriod
;
s
<=
&
statr
->
shortPreamble
;
s
++
)
*
s
=
le16_to_cpu
(
*
s
);
*
s
=
le16_to_cpu
(
*
s
);
statr
->
load
=
le16_to_cpu
(
statr
->
load
);
statr
->
assocStatus
=
le16_to_cpu
(
statr
->
assocStatus
);
return
rc
;
return
rc
;
}
}
static
int
readAPListRid
(
struct
airo_info
*
ai
,
APListRid
*
aplr
)
{
static
int
readAPListRid
(
struct
airo_info
*
ai
,
APListRid
*
aplr
)
{
int
rc
=
PC4500_readrid
(
ai
,
RID_APLIST
,
aplr
,
sizeof
(
*
aplr
));
int
rc
=
PC4500_readrid
(
ai
,
RID_APLIST
,
aplr
,
sizeof
(
*
aplr
)
,
1
);
aplr
->
len
=
le16_to_cpu
(
aplr
->
len
);
aplr
->
len
=
le16_to_cpu
(
aplr
->
len
);
return
rc
;
return
rc
;
}
}
static
int
writeAPListRid
(
struct
airo_info
*
ai
,
APListRid
*
aplr
)
{
static
int
writeAPListRid
(
struct
airo_info
*
ai
,
APListRid
*
aplr
)
{
int
rc
;
int
rc
;
aplr
->
len
=
cpu_to_le16
(
aplr
->
len
);
aplr
->
len
=
cpu_to_le16
(
aplr
->
len
);
rc
=
PC4500_writerid
(
ai
,
RID_APLIST
,
aplr
,
sizeof
(
*
aplr
));
rc
=
PC4500_writerid
(
ai
,
RID_APLIST
,
aplr
,
sizeof
(
*
aplr
)
,
1
);
return
rc
;
return
rc
;
}
}
static
int
readCapabilityRid
(
struct
airo_info
*
ai
,
CapabilityRid
*
capr
)
{
static
int
readCapabilityRid
(
struct
airo_info
*
ai
,
CapabilityRid
*
capr
)
{
int
rc
=
PC4500_readrid
(
ai
,
RID_CAPABILITIES
,
capr
,
sizeof
(
*
capr
));
int
rc
=
PC4500_readrid
(
ai
,
RID_CAPABILITIES
,
capr
,
sizeof
(
*
capr
)
,
1
);
u16
*
s
;
u16
*
s
;
capr
->
len
=
le16_to_cpu
(
capr
->
len
);
capr
->
len
=
le16_to_cpu
(
capr
->
len
);
...
@@ -1221,8 +1251,8 @@ static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr) {
...
@@ -1221,8 +1251,8 @@ static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr) {
*
s
=
le16_to_cpu
(
*
s
);
*
s
=
le16_to_cpu
(
*
s
);
return
rc
;
return
rc
;
}
}
static
int
readStatsRid
(
struct
airo_info
*
ai
,
StatsRid
*
sr
,
int
rid
)
{
static
int
readStatsRid
(
struct
airo_info
*
ai
,
StatsRid
*
sr
,
int
rid
,
int
lock
)
{
int
rc
=
PC4500_readrid
(
ai
,
rid
,
sr
,
sizeof
(
*
sr
));
int
rc
=
PC4500_readrid
(
ai
,
rid
,
sr
,
sizeof
(
*
sr
)
,
lock
);
u32
*
i
;
u32
*
i
;
sr
->
len
=
le16_to_cpu
(
sr
->
len
);
sr
->
len
=
le16_to_cpu
(
sr
->
len
);
...
@@ -1242,8 +1272,8 @@ static int airo_open(struct net_device *dev) {
...
@@ -1242,8 +1272,8 @@ static int airo_open(struct net_device *dev) {
* is open (to pipeline changes and speed-up card setup). If
* is open (to pipeline changes and speed-up card setup). If
* those changes are not yet commited, do it now - Jean II */
* those changes are not yet commited, do it now - Jean II */
if
(
info
->
need_commit
)
{
if
(
info
->
need_commit
)
{
disable_MAC
(
info
);
disable_MAC
(
info
,
1
);
writeConfigRid
(
info
);
writeConfigRid
(
info
,
1
);
}
}
if
(
info
->
wifidev
!=
dev
)
{
if
(
info
->
wifidev
!=
dev
)
{
...
@@ -1251,7 +1281,7 @@ static int airo_open(struct net_device *dev) {
...
@@ -1251,7 +1281,7 @@ static int airo_open(struct net_device *dev) {
info
->
flags
&=
~
FLAG_RADIO_DOWN
;
info
->
flags
&=
~
FLAG_RADIO_DOWN
;
enable_interrupts
(
info
);
enable_interrupts
(
info
);
}
}
enable_MAC
(
info
,
&
rsp
);
enable_MAC
(
info
,
&
rsp
,
1
);
netif_start_queue
(
dev
);
netif_start_queue
(
dev
);
return
0
;
return
0
;
...
@@ -1430,29 +1460,41 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
...
@@ -1430,29 +1460,41 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
return
0
;
return
0
;
}
}
static
void
airo_read_stats
(
struct
airo_info
*
ai
)
{
StatsRid
stats_rid
;
u32
*
vals
=
stats_rid
.
vals
;
if
(
down_trylock
(
&
ai
->
sem
)
==
0
)
{
readStatsRid
(
ai
,
&
stats_rid
,
RID_STATS
,
0
);
up
(
&
ai
->
sem
);
ai
->
stats
.
rx_packets
=
vals
[
43
]
+
vals
[
44
]
+
vals
[
45
];
ai
->
stats
.
tx_packets
=
vals
[
39
]
+
vals
[
40
]
+
vals
[
41
];
ai
->
stats
.
rx_bytes
=
vals
[
92
];
ai
->
stats
.
tx_bytes
=
vals
[
91
];
ai
->
stats
.
rx_errors
=
vals
[
0
]
+
vals
[
2
]
+
vals
[
3
]
+
vals
[
4
];
ai
->
stats
.
tx_errors
=
vals
[
42
]
+
ai
->
stats
.
tx_fifo_errors
;
ai
->
stats
.
multicast
=
vals
[
43
];
ai
->
stats
.
collisions
=
vals
[
89
];
/* detailed rx_errors: */
ai
->
stats
.
rx_length_errors
=
vals
[
3
];
ai
->
stats
.
rx_crc_errors
=
vals
[
4
];
ai
->
stats
.
rx_frame_errors
=
vals
[
2
];
ai
->
stats
.
rx_fifo_errors
=
vals
[
0
];
}
else
{
ai
->
stats_task
.
func
=
(
void
(
*
)(
void
*
))
airo_read_stats
;
ai
->
stats_task
.
data
=
(
void
*
)
ai
;
schedule_work
(
&
ai
->
stats_task
);
}
}
struct
net_device_stats
*
airo_get_stats
(
struct
net_device
*
dev
)
struct
net_device_stats
*
airo_get_stats
(
struct
net_device
*
dev
)
{
{
struct
airo_info
*
local
=
dev
->
priv
;
struct
airo_info
*
local
=
dev
->
priv
;
StatsRid
stats_rid
;
u32
*
vals
=
stats_rid
.
vals
;
/* Get stats out of the card */
/* Get stats out of the card if available */
readStatsRid
(
local
,
&
stats_rid
,
RID_STATS
);
airo_read_stats
(
local
);
local
->
stats
.
rx_packets
=
vals
[
43
]
+
vals
[
44
]
+
vals
[
45
];
local
->
stats
.
tx_packets
=
vals
[
39
]
+
vals
[
40
]
+
vals
[
41
];
local
->
stats
.
rx_bytes
=
vals
[
92
];
local
->
stats
.
tx_bytes
=
vals
[
91
];
local
->
stats
.
rx_errors
=
vals
[
0
]
+
vals
[
2
]
+
vals
[
3
]
+
vals
[
4
];
local
->
stats
.
tx_errors
=
vals
[
42
]
+
local
->
stats
.
tx_fifo_errors
;
local
->
stats
.
multicast
=
vals
[
43
];
local
->
stats
.
collisions
=
vals
[
89
];
/* detailed rx_errors: */
local
->
stats
.
rx_length_errors
=
vals
[
3
];
local
->
stats
.
rx_crc_errors
=
vals
[
4
];
local
->
stats
.
rx_frame_errors
=
vals
[
2
];
local
->
stats
.
rx_fifo_errors
=
vals
[
0
];
return
&
local
->
stats
;
return
&
local
->
stats
;
}
}
...
@@ -1507,9 +1549,9 @@ static int airo_set_mac_address(struct net_device *dev, void *p)
...
@@ -1507,9 +1549,9 @@ static int airo_set_mac_address(struct net_device *dev, void *p)
memcpy
(
ai
->
config
.
macAddr
,
addr
->
sa_data
,
dev
->
addr_len
);
memcpy
(
ai
->
config
.
macAddr
,
addr
->
sa_data
,
dev
->
addr_len
);
ai
->
need_commit
=
1
;
ai
->
need_commit
=
1
;
disable_MAC
(
ai
);
disable_MAC
(
ai
,
1
);
writeConfigRid
(
ai
);
writeConfigRid
(
ai
,
1
);
enable_MAC
(
ai
,
&
rsp
);
enable_MAC
(
ai
,
&
rsp
,
1
);
memcpy
(
ai
->
dev
->
dev_addr
,
addr
->
sa_data
,
dev
->
addr_len
);
memcpy
(
ai
->
dev
->
dev_addr
,
addr
->
sa_data
,
dev
->
addr_len
);
if
(
ai
->
wifidev
)
if
(
ai
->
wifidev
)
memcpy
(
ai
->
wifidev
->
dev_addr
,
addr
->
sa_data
,
dev
->
addr_len
);
memcpy
(
ai
->
wifidev
->
dev_addr
,
addr
->
sa_data
,
dev
->
addr_len
);
...
@@ -1538,7 +1580,7 @@ static int airo_close(struct net_device *dev) {
...
@@ -1538,7 +1580,7 @@ static int airo_close(struct net_device *dev) {
* stack (i.e. the network stack won't try to broadcast
* stack (i.e. the network stack won't try to broadcast
* anything on the interface and routes are gone. Jean II */
* anything on the interface and routes are gone. Jean II */
ai
->
flags
|=
FLAG_RADIO_DOWN
;
ai
->
flags
|=
FLAG_RADIO_DOWN
;
disable_MAC
(
ai
);
disable_MAC
(
ai
,
1
);
#endif
#endif
disable_interrupts
(
ai
);
disable_interrupts
(
ai
);
}
}
...
@@ -1762,6 +1804,9 @@ int reset_airo_card( struct net_device *dev ) {
...
@@ -1762,6 +1804,9 @@ int reset_airo_card( struct net_device *dev ) {
int
i
;
int
i
;
struct
airo_info
*
ai
=
dev
->
priv
;
struct
airo_info
*
ai
=
dev
->
priv
;
if
(
down_interruptible
(
&
ai
->
sem
))
return
-
1
;
waitbusy
(
ai
);
waitbusy
(
ai
);
OUT4500
(
ai
,
COMMAND
,
CMD_SOFTRESET
);
OUT4500
(
ai
,
COMMAND
,
CMD_SOFTRESET
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
...
@@ -1771,6 +1816,7 @@ int reset_airo_card( struct net_device *dev ) {
...
@@ -1771,6 +1816,7 @@ int reset_airo_card( struct net_device *dev ) {
schedule_timeout
(
HZ
/
5
);
schedule_timeout
(
HZ
/
5
);
if
(
setup_card
(
ai
,
dev
->
dev_addr
)
!=
SUCCESS
)
{
if
(
setup_card
(
ai
,
dev
->
dev_addr
)
!=
SUCCESS
)
{
printk
(
KERN_ERR
"airo: MAC could not be enabled
\n
"
);
printk
(
KERN_ERR
"airo: MAC could not be enabled
\n
"
);
up
(
&
ai
->
sem
);
return
-
1
;
return
-
1
;
}
else
{
}
else
{
printk
(
KERN_INFO
"airo: MAC enabled %s %x:%x:%x:%x:%x:%x
\n
"
,
printk
(
KERN_INFO
"airo: MAC enabled %s %x:%x:%x:%x:%x:%x
\n
"
,
...
@@ -1788,6 +1834,7 @@ int reset_airo_card( struct net_device *dev ) {
...
@@ -1788,6 +1834,7 @@ int reset_airo_card( struct net_device *dev ) {
}
}
enable_interrupts
(
ai
);
enable_interrupts
(
ai
);
netif_wake_queue
(
dev
);
netif_wake_queue
(
dev
);
up
(
&
ai
->
sem
);
return
0
;
return
0
;
}
}
...
@@ -1800,9 +1847,7 @@ static void airo_send_event(struct net_device *dev) {
...
@@ -1800,9 +1847,7 @@ static void airo_send_event(struct net_device *dev) {
StatusRid
status_rid
;
StatusRid
status_rid
;
if
(
down_trylock
(
&
ai
->
sem
)
==
0
)
{
if
(
down_trylock
(
&
ai
->
sem
)
==
0
)
{
__set_bit
(
FLAG_LOCKED
,
&
ai
->
flags
);
PC4500_readrid
(
ai
,
RID_STATUS
,
&
status_rid
,
sizeof
(
status_rid
),
0
);
PC4500_readrid
(
ai
,
RID_STATUS
,
&
status_rid
,
sizeof
(
status_rid
));
clear_bit
(
FLAG_LOCKED
,
&
ai
->
flags
);
up
(
&
ai
->
sem
);
up
(
&
ai
->
sem
);
wrqu
.
data
.
length
=
0
;
wrqu
.
data
.
length
=
0
;
wrqu
.
data
.
flags
=
0
;
wrqu
.
data
.
flags
=
0
;
...
@@ -1823,9 +1868,7 @@ static void airo_read_mic(struct airo_info *ai) {
...
@@ -1823,9 +1868,7 @@ static void airo_read_mic(struct airo_info *ai) {
MICRid
mic_rid
;
MICRid
mic_rid
;
if
(
down_trylock
(
&
ai
->
sem
)
==
0
)
{
if
(
down_trylock
(
&
ai
->
sem
)
==
0
)
{
__set_bit
(
FLAG_LOCKED
,
&
ai
->
flags
);
PC4500_readrid
(
ai
,
RID_MIC
,
&
mic_rid
,
sizeof
(
mic_rid
),
0
);
PC4500_readrid
(
ai
,
RID_MIC
,
&
mic_rid
,
sizeof
(
mic_rid
));
clear_bit
(
FLAG_LOCKED
,
&
ai
->
flags
);
up
(
&
ai
->
sem
);
up
(
&
ai
->
sem
);
#ifdef MICSUPPORT
#ifdef MICSUPPORT
micinit
(
ai
,
&
mic_rid
);
micinit
(
ai
,
&
mic_rid
);
...
@@ -1866,7 +1909,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
...
@@ -1866,7 +1909,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
if
(
status
&
EV_MIC
)
{
if
(
status
&
EV_MIC
)
{
OUT4500
(
apriv
,
EVACK
,
EV_MIC
);
OUT4500
(
apriv
,
EVACK
,
EV_MIC
);
airo_read_mic
(
apriv
);
if
(
apriv
->
flags
&
FLAG_MIC_CAPABLE
)
airo_read_mic
(
apriv
);
}
}
if
(
status
&
EV_LINK
)
{
if
(
status
&
EV_LINK
)
{
#if WIRELESS_EXT > 13
#if WIRELESS_EXT > 13
...
@@ -2057,6 +2101,28 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
...
@@ -2057,6 +2101,28 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
}
}
}
}
if
(
len
)
{
if
(
len
)
{
#if 0 && WIRELESS_EXT > 15
#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
if (apriv->spy_data.spy_number > 0) {
char *sa;
struct iw_quality wstats;
/* Prepare spy data : addr + qual */
sa = (char*)buffer + ((apriv->flags & FLAG_802_11) ? 10 : 6);
if (!(apriv->flags & FLAG_802_11)) {
bap_setup (apriv, fid, 8, BAP0);
bap_read (apriv, (u16*)hdr.rssi, 2, BAP0);
}
wstats.qual = hdr.rssi[0];
if (apriv->rssi)
wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm;
else
wstats.level = (hdr.rssi[1] + 321) / 2;
wstats.updated = 3;
/* Update spy records */
wireless_spy_update(dev, sa, &wstats);
}
#endif /* IW_WIRELESS_SPY */
#else
/* WIRELESS_EXT > 15 */
#ifdef WIRELESS_SPY
#ifdef WIRELESS_SPY
if
(
apriv
->
spy_number
>
0
)
{
if
(
apriv
->
spy_number
>
0
)
{
int
i
;
int
i
;
...
@@ -2082,6 +2148,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
...
@@ -2082,6 +2148,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
}
}
}
}
#endif
/* WIRELESS_SPY */
#endif
/* WIRELESS_SPY */
#endif
/* WIRELESS_EXT > 15 */
OUT4500
(
apriv
,
EVACK
,
EV_RX
);
OUT4500
(
apriv
,
EVACK
,
EV_RX
);
if
(
apriv
->
flags
&
FLAG_802_11
)
{
if
(
apriv
->
flags
&
FLAG_802_11
)
{
...
@@ -2113,17 +2180,17 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
...
@@ -2113,17 +2180,17 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
if
(
(
apriv
->
fids
[
i
]
&
0xffff
)
==
fid
)
{
if
(
(
apriv
->
fids
[
i
]
&
0xffff
)
==
fid
)
{
len
=
apriv
->
fids
[
i
]
>>
16
;
len
=
apriv
->
fids
[
i
]
>>
16
;
index
=
i
;
index
=
i
;
/* Set up to be used again */
apriv
->
fids
[
i
]
&=
0xffff
;
}
}
}
}
if
(
index
!=
-
1
)
{
if
(
index
!=
-
1
)
{
netif_wake_queue
(
dev
);
if
(
status
&
EV_TXEXC
)
if
(
status
&
EV_TXEXC
)
get_tx_error
(
apriv
,
index
);
get_tx_error
(
apriv
,
index
);
}
OUT4500
(
apriv
,
EVACK
,
status
&
(
EV_TX
|
EV_TXEXC
));
OUT4500
(
apriv
,
EVACK
,
status
&
(
EV_TX
|
EV_TXEXC
));
/* Set up to be used again */
if
(
index
==-
1
)
{
apriv
->
fids
[
index
]
&=
0xffff
;
netif_wake_queue
(
dev
);
}
else
{
OUT4500
(
apriv
,
EVACK
,
status
&
(
EV_TX
|
EV_TXEXC
));
printk
(
KERN_ERR
"airo: Unallocated FID was used to xmit
\n
"
);
printk
(
KERN_ERR
"airo: Unallocated FID was used to xmit
\n
"
);
}
}
}
}
...
@@ -2169,7 +2236,7 @@ static u16 IN4500( struct airo_info *ai, u16 reg ) {
...
@@ -2169,7 +2236,7 @@ static u16 IN4500( struct airo_info *ai, u16 reg ) {
return
rc
;
return
rc
;
}
}
static
int
enable_MAC
(
struct
airo_info
*
ai
,
Resp
*
rsp
)
{
static
int
enable_MAC
(
struct
airo_info
*
ai
,
Resp
*
rsp
,
int
lock
)
{
int
rc
;
int
rc
;
Cmd
cmd
;
Cmd
cmd
;
...
@@ -2182,7 +2249,7 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp ) {
...
@@ -2182,7 +2249,7 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp ) {
if
(
ai
->
flags
&
(
FLAG_RADIO_OFF
|
FLAG_RADIO_DOWN
))
return
SUCCESS
;
if
(
ai
->
flags
&
(
FLAG_RADIO_OFF
|
FLAG_RADIO_DOWN
))
return
SUCCESS
;
memset
(
&
cmd
,
0
,
sizeof
(
cmd
));
memset
(
&
cmd
,
0
,
sizeof
(
cmd
));
cmd
.
cmd
=
MAC_ENABLE
;
cmd
.
cmd
=
MAC_ENABLE
;
if
(
test_bit
(
FLAG_LOCKED
,
&
ai
->
flags
)
!=
0
)
if
(
!
lock
)
return
issuecommand
(
ai
,
&
cmd
,
rsp
);
return
issuecommand
(
ai
,
&
cmd
,
rsp
);
if
(
down_interruptible
(
&
ai
->
sem
))
if
(
down_interruptible
(
&
ai
->
sem
))
...
@@ -2192,13 +2259,13 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp ) {
...
@@ -2192,13 +2259,13 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp ) {
return
rc
;
return
rc
;
}
}
static
void
disable_MAC
(
struct
airo_info
*
ai
)
{
static
void
disable_MAC
(
struct
airo_info
*
ai
,
int
lock
)
{
Cmd
cmd
;
Cmd
cmd
;
Resp
rsp
;
Resp
rsp
;
memset
(
&
cmd
,
0
,
sizeof
(
cmd
));
memset
(
&
cmd
,
0
,
sizeof
(
cmd
));
cmd
.
cmd
=
MAC_DISABLE
;
// disable in case already enabled
cmd
.
cmd
=
MAC_DISABLE
;
// disable in case already enabled
if
(
test_bit
(
FLAG_LOCKED
,
&
ai
->
flags
)
!=
0
)
{
if
(
!
lock
)
{
issuecommand
(
ai
,
&
cmd
,
&
rsp
);
issuecommand
(
ai
,
&
cmd
,
&
rsp
);
return
;
return
;
}
}
...
@@ -2276,13 +2343,13 @@ static u16 setup_card(struct airo_info *ai, u8 *mac)
...
@@ -2276,13 +2343,13 @@ static u16 setup_card(struct airo_info *ai, u8 *mac)
CapabilityRid
cap_rid
;
CapabilityRid
cap_rid
;
// general configuration (read/modify/write)
// general configuration (read/modify/write)
status
=
readConfigRid
(
ai
);
status
=
readConfigRid
(
ai
,
1
);
if
(
status
!=
SUCCESS
)
return
ERROR
;
if
(
status
!=
SUCCESS
)
return
ERROR
;
status
=
readCapabilityRid
(
ai
,
&
cap_rid
);
status
=
readCapabilityRid
(
ai
,
&
cap_rid
);
if
(
status
!=
SUCCESS
)
return
ERROR
;
if
(
status
!=
SUCCESS
)
return
ERROR
;
status
=
PC4500_readrid
(
ai
,
RID_RSSI
,
&
rssi_rid
,
sizeof
(
rssi_rid
));
status
=
PC4500_readrid
(
ai
,
RID_RSSI
,
&
rssi_rid
,
sizeof
(
rssi_rid
)
,
1
);
if
(
status
==
SUCCESS
)
{
if
(
status
==
SUCCESS
)
{
if
(
ai
->
rssi
||
(
ai
->
rssi
=
kmalloc
(
512
,
GFP_KERNEL
))
!=
NULL
)
if
(
ai
->
rssi
||
(
ai
->
rssi
=
kmalloc
(
512
,
GFP_KERNEL
))
!=
NULL
)
memcpy
(
ai
->
rssi
,
(
u8
*
)
&
rssi_rid
+
2
,
512
);
memcpy
(
ai
->
rssi
,
(
u8
*
)
&
rssi_rid
+
2
,
512
);
...
@@ -2346,14 +2413,14 @@ static u16 setup_card(struct airo_info *ai, u8 *mac)
...
@@ -2346,14 +2413,14 @@ static u16 setup_card(struct airo_info *ai, u8 *mac)
}
}
}
}
status
=
writeConfigRid
(
ai
);
status
=
writeConfigRid
(
ai
,
1
);
if
(
status
!=
SUCCESS
)
return
ERROR
;
if
(
status
!=
SUCCESS
)
return
ERROR
;
/* Set up the SSID list */
/* Set up the SSID list */
status
=
writeSsidRid
(
ai
,
&
mySsid
);
status
=
writeSsidRid
(
ai
,
&
mySsid
);
if
(
status
!=
SUCCESS
)
return
ERROR
;
if
(
status
!=
SUCCESS
)
return
ERROR
;
status
=
enable_MAC
(
ai
,
&
rsp
);
status
=
enable_MAC
(
ai
,
&
rsp
,
1
);
if
(
status
!=
SUCCESS
||
(
rsp
.
status
&
0xFF00
)
!=
0
)
{
if
(
status
!=
SUCCESS
||
(
rsp
.
status
&
0xFF00
)
!=
0
)
{
printk
(
KERN_ERR
"airo: Bad MAC enable reason = %x, rid = %x, offset = %d
\n
"
,
rsp
.
rsp0
,
rsp
.
rsp1
,
rsp
.
rsp2
);
printk
(
KERN_ERR
"airo: Bad MAC enable reason = %x, rid = %x, offset = %d
\n
"
,
rsp
.
rsp0
,
rsp
.
rsp1
,
rsp
.
rsp2
);
return
ERROR
;
return
ERROR
;
...
@@ -2568,13 +2635,12 @@ static int PC4500_accessrid(struct airo_info *ai, u16 rid, u16 accmd)
...
@@ -2568,13 +2635,12 @@ static int PC4500_accessrid(struct airo_info *ai, u16 rid, u16 accmd)
/* Note, that we are using BAP1 which is also used by transmit, so
/* Note, that we are using BAP1 which is also used by transmit, so
* we must get a lock. */
* we must get a lock. */
static
int
PC4500_readrid
(
struct
airo_info
*
ai
,
u16
rid
,
void
*
pBuf
,
int
len
)
static
int
PC4500_readrid
(
struct
airo_info
*
ai
,
u16
rid
,
void
*
pBuf
,
int
len
,
int
lock
)
{
{
u16
status
,
dolock
=
0
;
u16
status
;
int
rc
=
SUCCESS
;
int
rc
=
SUCCESS
;
if
(
test_bit
(
FLAG_LOCKED
,
&
ai
->
flags
)
==
0
)
{
if
(
lock
)
{
dolock
=
1
;
if
(
down_interruptible
(
&
ai
->
sem
))
if
(
down_interruptible
(
&
ai
->
sem
))
return
ERROR
;
return
ERROR
;
}
}
...
@@ -2602,7 +2668,7 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len)
...
@@ -2602,7 +2668,7 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len)
// read remainder of the rid
// read remainder of the rid
rc
=
bap_read
(
ai
,
((
u16
*
)
pBuf
)
+
1
,
len
,
BAP1
);
rc
=
bap_read
(
ai
,
((
u16
*
)
pBuf
)
+
1
,
len
,
BAP1
);
done:
done:
if
(
do
lock
)
if
(
lock
)
up
(
&
ai
->
sem
);
up
(
&
ai
->
sem
);
return
rc
;
return
rc
;
}
}
...
@@ -2610,13 +2676,14 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len)
...
@@ -2610,13 +2676,14 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len)
/* Note, that we are using BAP1 which is also used by transmit, so
/* Note, that we are using BAP1 which is also used by transmit, so
* make sure this isnt called when a transmit is happening */
* make sure this isnt called when a transmit is happening */
static
int
PC4500_writerid
(
struct
airo_info
*
ai
,
u16
rid
,
static
int
PC4500_writerid
(
struct
airo_info
*
ai
,
u16
rid
,
const
void
*
pBuf
,
int
len
)
const
void
*
pBuf
,
int
len
,
int
lock
)
{
{
u16
status
,
dolock
=
0
;
u16
status
;
int
rc
=
SUCCESS
;
int
rc
=
SUCCESS
;
if
(
test_bit
(
FLAG_LOCKED
,
&
ai
->
flags
)
==
0
)
{
*
(
u16
*
)
pBuf
=
cpu_to_le16
((
u16
)
len
);
dolock
=
1
;
if
(
lock
)
{
if
(
down_interruptible
(
&
ai
->
sem
))
if
(
down_interruptible
(
&
ai
->
sem
))
return
ERROR
;
return
ERROR
;
}
}
...
@@ -2634,7 +2701,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
...
@@ -2634,7 +2701,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
// ---now commit the rid data
// ---now commit the rid data
rc
=
PC4500_accessrid
(
ai
,
rid
,
0x100
|
CMD_ACCESS
);
rc
=
PC4500_accessrid
(
ai
,
rid
,
0x100
|
CMD_ACCESS
);
done:
done:
if
(
do
lock
)
if
(
lock
)
up
(
&
ai
->
sem
);
up
(
&
ai
->
sem
);
return
rc
;
return
rc
;
}
}
...
@@ -2653,11 +2720,11 @@ static u16 transmit_allocate(struct airo_info *ai, int lenPayload, int raw)
...
@@ -2653,11 +2720,11 @@ static u16 transmit_allocate(struct airo_info *ai, int lenPayload, int raw)
if
(
down_interruptible
(
&
ai
->
sem
))
if
(
down_interruptible
(
&
ai
->
sem
))
return
ERROR
;
return
ERROR
;
if
(
issuecommand
(
ai
,
&
cmd
,
&
rsp
)
!=
SUCCESS
)
{
if
(
issuecommand
(
ai
,
&
cmd
,
&
rsp
)
!=
SUCCESS
)
{
txFid
=
0
;
txFid
=
ERROR
;
goto
done
;
goto
done
;
}
}
if
(
(
rsp
.
status
&
0xFF00
)
!=
0
)
{
if
(
(
rsp
.
status
&
0xFF00
)
!=
0
)
{
txFid
=
0
;
txFid
=
ERROR
;
goto
done
;
goto
done
;
}
}
/* wait for the allocate event/indication
/* wait for the allocate event/indication
...
@@ -2704,7 +2771,7 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket)
...
@@ -2704,7 +2771,7 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket)
len
>>=
16
;
len
>>=
16
;
if
(
len
<
ETH_ALEN
*
2
)
{
if
(
len
<
=
ETH_ALEN
*
2
)
{
printk
(
KERN_WARNING
"Short packet %d
\n
"
,
len
);
printk
(
KERN_WARNING
"Short packet %d
\n
"
,
len
);
return
ERROR
;
return
ERROR
;
}
}
...
@@ -3160,7 +3227,7 @@ static int proc_stats_rid_open( struct inode *inode,
...
@@ -3160,7 +3227,7 @@ static int proc_stats_rid_open( struct inode *inode,
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
readStatsRid
(
apriv
,
&
stats
,
rid
);
readStatsRid
(
apriv
,
&
stats
,
rid
,
1
);
j
=
0
;
j
=
0
;
for
(
i
=
0
;
statsLabels
[
i
]
!=
(
char
*
)
-
1
&&
for
(
i
=
0
;
statsLabels
[
i
]
!=
(
char
*
)
-
1
&&
...
@@ -3195,18 +3262,21 @@ static int get_dec_u16( char *buffer, int *start, int limit ) {
...
@@ -3195,18 +3262,21 @@ static int get_dec_u16( char *buffer, int *start, int limit ) {
return
value
;
return
value
;
}
}
static
int
airo_config_commit
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
void
*
zwrq
,
char
*
extra
);
static
void
proc_config_on_close
(
struct
inode
*
inode
,
struct
file
*
file
)
{
static
void
proc_config_on_close
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
proc_data
*
data
=
file
->
private_data
;
struct
proc_data
*
data
=
file
->
private_data
;
struct
proc_dir_entry
*
dp
=
PDE
(
inode
);
struct
proc_dir_entry
*
dp
=
PDE
(
inode
);
struct
net_device
*
dev
=
dp
->
data
;
struct
net_device
*
dev
=
dp
->
data
;
struct
airo_info
*
ai
=
dev
->
priv
;
struct
airo_info
*
ai
=
dev
->
priv
;
Resp
rsp
;
char
*
line
;
char
*
line
;
int
need_reset
=
0
;
if
(
!
data
->
writelen
)
return
;
if
(
!
data
->
writelen
)
return
;
readConfigRid
(
ai
);
readConfigRid
(
ai
,
1
);
ai
->
need_commit
=
1
;
line
=
data
->
wbuffer
;
line
=
data
->
wbuffer
;
while
(
line
[
0
]
)
{
while
(
line
[
0
]
)
{
...
@@ -3214,7 +3284,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
...
@@ -3214,7 +3284,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
if
(
!
strncmp
(
line
,
"Mode: "
,
6
)
)
{
if
(
!
strncmp
(
line
,
"Mode: "
,
6
)
)
{
line
+=
6
;
line
+=
6
;
if
((
ai
->
config
.
rmode
&
0xff
)
>=
RXMODE_RFMON
)
if
((
ai
->
config
.
rmode
&
0xff
)
>=
RXMODE_RFMON
)
need_reset
=
1
;
ai
->
need_commit
=
2
;
ai
->
config
.
rmode
&=
0xfe00
;
ai
->
config
.
rmode
&=
0xfe00
;
ai
->
flags
&=
~
FLAG_802_11
;
ai
->
flags
&=
~
FLAG_802_11
;
ai
->
config
.
opmode
&=
0xFF00
;
ai
->
config
.
opmode
&=
0xFF00
;
...
@@ -3392,22 +3462,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
...
@@ -3392,22 +3462,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
while
(
line
[
0
]
&&
line
[
0
]
!=
'\n'
)
line
++
;
while
(
line
[
0
]
&&
line
[
0
]
!=
'\n'
)
line
++
;
if
(
line
[
0
]
)
line
++
;
if
(
line
[
0
]
)
line
++
;
}
}
disable_MAC
(
ai
);
airo_config_commit
(
dev
,
NULL
,
NULL
,
NULL
);
if
(
need_reset
)
{
APListRid
APList_rid
;
SsidRid
SSID_rid
;
readAPListRid
(
ai
,
&
APList_rid
);
readSsidRid
(
ai
,
&
SSID_rid
);
reset_airo_card
(
dev
);
disable_MAC
(
ai
);
writeSsidRid
(
ai
,
&
SSID_rid
);
writeAPListRid
(
ai
,
&
APList_rid
);
}
writeConfigRid
(
ai
);
enable_MAC
(
ai
,
&
rsp
);
if
(
need_reset
)
airo_set_promisc
(
ai
);
}
}
static
char
*
get_rmode
(
u16
mode
)
{
static
char
*
get_rmode
(
u16
mode
)
{
...
@@ -3443,7 +3498,7 @@ static int proc_config_open( struct inode *inode, struct file *file ) {
...
@@ -3443,7 +3498,7 @@ static int proc_config_open( struct inode *inode, struct file *file ) {
data
->
maxwritelen
=
2048
;
data
->
maxwritelen
=
2048
;
data
->
on_close
=
proc_config_on_close
;
data
->
on_close
=
proc_config_on_close
;
readConfigRid
(
ai
);
readConfigRid
(
ai
,
1
);
i
=
sprintf
(
data
->
rbuffer
,
i
=
sprintf
(
data
->
rbuffer
,
"Mode: %s
\n
"
"Mode: %s
\n
"
...
@@ -3535,9 +3590,9 @@ static void proc_SSID_on_close( struct inode *inode, struct file *file ) {
...
@@ -3535,9 +3590,9 @@ static void proc_SSID_on_close( struct inode *inode, struct file *file ) {
offset
<
data
->
writelen
)
offset
++
;
offset
<
data
->
writelen
)
offset
++
;
offset
++
;
offset
++
;
}
}
disable_MAC
(
ai
);
disable_MAC
(
ai
,
1
);
writeSsidRid
(
ai
,
&
SSID_rid
);
writeSsidRid
(
ai
,
&
SSID_rid
);
enable_MAC
(
ai
,
&
rsp
);
enable_MAC
(
ai
,
&
rsp
,
1
);
}
}
inline
static
u8
hexVal
(
char
c
)
{
inline
static
u8
hexVal
(
char
c
)
{
...
@@ -3576,20 +3631,20 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) {
...
@@ -3576,20 +3631,20 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) {
}
}
}
}
}
}
disable_MAC
(
ai
);
disable_MAC
(
ai
,
1
);
writeAPListRid
(
ai
,
&
APList_rid
);
writeAPListRid
(
ai
,
&
APList_rid
);
enable_MAC
(
ai
,
&
rsp
);
enable_MAC
(
ai
,
&
rsp
,
1
);
}
}
/* This function wraps PC4500_writerid with a MAC disable */
/* This function wraps PC4500_writerid with a MAC disable */
static
int
do_writerid
(
struct
airo_info
*
ai
,
u16
rid
,
const
void
*
rid_data
,
static
int
do_writerid
(
struct
airo_info
*
ai
,
u16
rid
,
const
void
*
rid_data
,
int
len
)
{
int
len
,
int
dummy
)
{
int
rc
;
int
rc
;
Resp
rsp
;
Resp
rsp
;
disable_MAC
(
ai
);
disable_MAC
(
ai
,
1
);
rc
=
PC4500_writerid
(
ai
,
rid
,
rid_data
,
len
);
rc
=
PC4500_writerid
(
ai
,
rid
,
rid_data
,
len
,
1
);
enable_MAC
(
ai
,
&
rsp
);
enable_MAC
(
ai
,
&
rsp
,
1
);
return
rc
;
return
rc
;
}
}
...
@@ -3617,7 +3672,7 @@ static int get_wep_key(struct airo_info *ai, u16 index) {
...
@@ -3617,7 +3672,7 @@ static int get_wep_key(struct airo_info *ai, u16 index) {
}
}
static
int
set_wep_key
(
struct
airo_info
*
ai
,
u16
index
,
static
int
set_wep_key
(
struct
airo_info
*
ai
,
u16
index
,
const
char
*
key
,
u16
keylen
,
int
perm
)
{
const
char
*
key
,
u16
keylen
,
int
perm
,
int
lock
)
{
static
const
unsigned
char
macaddr
[
ETH_ALEN
]
=
{
0x01
,
0
,
0
,
0
,
0
,
0
};
static
const
unsigned
char
macaddr
[
ETH_ALEN
]
=
{
0x01
,
0
,
0
,
0
,
0
,
0
};
WepKeyRid
wkr
;
WepKeyRid
wkr
;
...
@@ -3639,7 +3694,7 @@ static int set_wep_key(struct airo_info *ai, u16 index,
...
@@ -3639,7 +3694,7 @@ static int set_wep_key(struct airo_info *ai, u16 index,
printk
(
KERN_INFO
"Setting key %d
\n
"
,
index
);
printk
(
KERN_INFO
"Setting key %d
\n
"
,
index
);
}
}
writeWepKeyRid
(
ai
,
&
wkr
,
perm
);
writeWepKeyRid
(
ai
,
&
wkr
,
perm
,
lock
);
return
0
;
return
0
;
}
}
...
@@ -3662,7 +3717,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
...
@@ -3662,7 +3717,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
(
data
->
wbuffer
[
1
]
==
' '
||
data
->
wbuffer
[
1
]
==
'\n'
))
{
(
data
->
wbuffer
[
1
]
==
' '
||
data
->
wbuffer
[
1
]
==
'\n'
))
{
index
=
data
->
wbuffer
[
0
]
-
'0'
;
index
=
data
->
wbuffer
[
0
]
-
'0'
;
if
(
data
->
wbuffer
[
1
]
==
'\n'
)
{
if
(
data
->
wbuffer
[
1
]
==
'\n'
)
{
set_wep_key
(
ai
,
index
,
0
,
0
,
1
);
set_wep_key
(
ai
,
index
,
0
,
0
,
1
,
1
);
return
;
return
;
}
}
j
=
2
;
j
=
2
;
...
@@ -3681,7 +3736,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
...
@@ -3681,7 +3736,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
break
;
break
;
}
}
}
}
set_wep_key
(
ai
,
index
,
key
,
i
/
3
,
1
);
set_wep_key
(
ai
,
index
,
key
,
i
/
3
,
1
,
1
);
}
}
static
int
proc_wepkey_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
static
int
proc_wepkey_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
...
@@ -3928,10 +3983,9 @@ static void timer_func( u_long data ) {
...
@@ -3928,10 +3983,9 @@ static void timer_func( u_long data ) {
add_timer
(
&
apriv
->
timer
);
add_timer
(
&
apriv
->
timer
);
return
;
return
;
}
}
__set_bit
(
FLAG_LOCKED
,
&
apriv
->
flags
);
readConfigRid
(
apriv
);
readConfigRid
(
apriv
,
0
);
disable_MAC
(
apriv
);
disable_MAC
(
apriv
,
0
);
switch
(
apriv
->
config
.
authType
)
{
switch
(
apriv
->
config
.
authType
)
{
case
AUTH_ENCRYPT
:
case
AUTH_ENCRYPT
:
/* So drop to OPEN */
/* So drop to OPEN */
...
@@ -3939,13 +3993,13 @@ static void timer_func( u_long data ) {
...
@@ -3939,13 +3993,13 @@ static void timer_func( u_long data ) {
break
;
break
;
case
AUTH_SHAREDKEY
:
case
AUTH_SHAREDKEY
:
if
(
apriv
->
keyindex
<
auto_wep
)
{
if
(
apriv
->
keyindex
<
auto_wep
)
{
set_wep_key
(
apriv
,
apriv
->
keyindex
,
0
,
0
,
0
);
set_wep_key
(
apriv
,
apriv
->
keyindex
,
0
,
0
,
0
,
0
);
apriv
->
config
.
authType
=
AUTH_SHAREDKEY
;
apriv
->
config
.
authType
=
AUTH_SHAREDKEY
;
apriv
->
keyindex
++
;
apriv
->
keyindex
++
;
}
else
{
}
else
{
/* Drop to ENCRYPT */
/* Drop to ENCRYPT */
apriv
->
keyindex
=
0
;
apriv
->
keyindex
=
0
;
set_wep_key
(
apriv
,
apriv
->
defindex
,
0
,
0
,
0
);
set_wep_key
(
apriv
,
apriv
->
defindex
,
0
,
0
,
0
,
0
);
apriv
->
config
.
authType
=
AUTH_ENCRYPT
;
apriv
->
config
.
authType
=
AUTH_ENCRYPT
;
}
}
break
;
break
;
...
@@ -3953,9 +4007,8 @@ static void timer_func( u_long data ) {
...
@@ -3953,9 +4007,8 @@ static void timer_func( u_long data ) {
apriv
->
config
.
authType
=
AUTH_SHAREDKEY
;
apriv
->
config
.
authType
=
AUTH_SHAREDKEY
;
}
}
apriv
->
need_commit
=
1
;
apriv
->
need_commit
=
1
;
writeConfigRid
(
apriv
);
writeConfigRid
(
apriv
,
0
);
enable_MAC
(
apriv
,
&
rsp
);
enable_MAC
(
apriv
,
&
rsp
,
0
);
clear_bit
(
FLAG_LOCKED
,
&
apriv
->
flags
);
up
(
&
apriv
->
sem
);
up
(
&
apriv
->
sem
);
/* Schedule check to see if the change worked */
/* Schedule check to see if the change worked */
...
@@ -4135,9 +4188,11 @@ static int airo_get_freq(struct net_device *dev,
...
@@ -4135,9 +4188,11 @@ static int airo_get_freq(struct net_device *dev,
struct
airo_info
*
local
=
dev
->
priv
;
struct
airo_info
*
local
=
dev
->
priv
;
StatusRid
status_rid
;
/* Card status info */
StatusRid
status_rid
;
/* Card status info */
readStatusRid
(
local
,
&
status_rid
);
if
((
local
->
config
.
opmode
&
0xFF
)
==
MODE_STA_ESS
)
status_rid
.
channel
=
local
->
config
.
channelSet
;
else
readStatusRid
(
local
,
&
status_rid
);
/* Will return zero in infrastructure mode */
#ifdef WEXT_USECHANNELS
#ifdef WEXT_USECHANNELS
fwrq
->
m
=
((
int
)
status_rid
.
channel
)
+
1
;
fwrq
->
m
=
((
int
)
status_rid
.
channel
)
+
1
;
fwrq
->
e
=
0
;
fwrq
->
e
=
0
;
...
@@ -4191,9 +4246,9 @@ static int airo_set_essid(struct net_device *dev,
...
@@ -4191,9 +4246,9 @@ static int airo_set_essid(struct net_device *dev,
SSID_rid
.
ssids
[
index
].
len
=
dwrq
->
length
-
1
;
SSID_rid
.
ssids
[
index
].
len
=
dwrq
->
length
-
1
;
}
}
/* Write it to the card */
/* Write it to the card */
disable_MAC
(
local
);
disable_MAC
(
local
,
1
);
writeSsidRid
(
local
,
&
SSID_rid
);
writeSsidRid
(
local
,
&
SSID_rid
);
enable_MAC
(
local
,
&
rsp
);
enable_MAC
(
local
,
&
rsp
,
1
);
return
0
;
return
0
;
}
}
...
@@ -4255,9 +4310,9 @@ static int airo_set_wap(struct net_device *dev,
...
@@ -4255,9 +4310,9 @@ static int airo_set_wap(struct net_device *dev,
memset
(
&
APList_rid
,
0
,
sizeof
(
APList_rid
));
memset
(
&
APList_rid
,
0
,
sizeof
(
APList_rid
));
APList_rid
.
len
=
sizeof
(
APList_rid
);
APList_rid
.
len
=
sizeof
(
APList_rid
);
memcpy
(
APList_rid
.
ap
[
0
],
awrq
->
sa_data
,
ETH_ALEN
);
memcpy
(
APList_rid
.
ap
[
0
],
awrq
->
sa_data
,
ETH_ALEN
);
disable_MAC
(
local
);
disable_MAC
(
local
,
1
);
writeAPListRid
(
local
,
&
APList_rid
);
writeAPListRid
(
local
,
&
APList_rid
);
enable_MAC
(
local
,
&
rsp
);
enable_MAC
(
local
,
&
rsp
,
1
);
}
}
return
0
;
return
0
;
}
}
...
@@ -4506,28 +4561,47 @@ static int airo_set_mode(struct net_device *dev,
...
@@ -4506,28 +4561,47 @@ static int airo_set_mode(struct net_device *dev,
char
*
extra
)
char
*
extra
)
{
{
struct
airo_info
*
local
=
dev
->
priv
;
struct
airo_info
*
local
=
dev
->
priv
;
int
commit
=
1
;
if
((
local
->
config
.
rmode
&
0xff
)
>=
RXMODE_RFMON
)
commit
=
2
;
switch
(
*
uwrq
)
{
switch
(
*
uwrq
)
{
case
IW_MODE_ADHOC
:
case
IW_MODE_ADHOC
:
local
->
config
.
opmode
&=
0xFF00
;
local
->
config
.
opmode
&=
0xFF00
;
local
->
config
.
opmode
|=
MODE_STA_IBSS
;
local
->
config
.
opmode
|=
MODE_STA_IBSS
;
local
->
config
.
rmode
&=
0xfe00
;
local
->
flags
&=
~
FLAG_802_11
;
break
;
break
;
case
IW_MODE_INFRA
:
case
IW_MODE_INFRA
:
local
->
config
.
opmode
&=
0xFF00
;
local
->
config
.
opmode
&=
0xFF00
;
local
->
config
.
opmode
|=
MODE_STA_ESS
;
local
->
config
.
opmode
|=
MODE_STA_ESS
;
local
->
config
.
rmode
&=
0xfe00
;
local
->
flags
&=
~
FLAG_802_11
;
break
;
break
;
case
IW_MODE_MASTER
:
case
IW_MODE_MASTER
:
local
->
config
.
opmode
&=
0xFF00
;
local
->
config
.
opmode
&=
0xFF00
;
local
->
config
.
opmode
|=
MODE_AP
;
local
->
config
.
opmode
|=
MODE_AP
;
local
->
config
.
rmode
&=
0xfe00
;
local
->
flags
&=
~
FLAG_802_11
;
break
;
break
;
case
IW_MODE_REPEAT
:
case
IW_MODE_REPEAT
:
local
->
config
.
opmode
&=
0xFF00
;
local
->
config
.
opmode
&=
0xFF00
;
local
->
config
.
opmode
|=
MODE_AP_RPTR
;
local
->
config
.
opmode
|=
MODE_AP_RPTR
;
local
->
config
.
rmode
&=
0xfe00
;
local
->
flags
&=
~
FLAG_802_11
;
break
;
case
IW_MODE_MONITOR
:
local
->
config
.
opmode
&=
0xFF00
;
local
->
config
.
opmode
|=
MODE_STA_ESS
;
local
->
config
.
rmode
&=
0xfe00
;
local
->
config
.
rmode
|=
RXMODE_RFMON
|
RXMODE_DISABLE_802_3_HEADER
;
local
->
flags
|=
FLAG_802_11
;
break
;
break
;
default:
default:
return
-
EINVAL
;
return
-
EINVAL
;
}
}
local
->
need_commit
=
1
;
local
->
need_commit
=
commit
;
return
-
EINPROGRESS
;
/* Call commit handler */
return
-
EINPROGRESS
;
/* Call commit handler */
}
}
...
@@ -4613,7 +4687,7 @@ static int airo_set_encode(struct net_device *dev,
...
@@ -4613,7 +4687,7 @@ static int airo_set_encode(struct net_device *dev,
/* Copy the key in the driver */
/* Copy the key in the driver */
memcpy
(
key
.
key
,
extra
,
dwrq
->
length
);
memcpy
(
key
.
key
,
extra
,
dwrq
->
length
);
/* Send the key to the card */
/* Send the key to the card */
set_wep_key
(
local
,
index
,
key
.
key
,
key
.
len
,
1
);
set_wep_key
(
local
,
index
,
key
.
key
,
key
.
len
,
1
,
1
);
}
}
/* WE specify that if a valid key is set, encryption
/* WE specify that if a valid key is set, encryption
* should be enabled (user may turn it off later)
* should be enabled (user may turn it off later)
...
@@ -4627,7 +4701,7 @@ static int airo_set_encode(struct net_device *dev,
...
@@ -4627,7 +4701,7 @@ static int airo_set_encode(struct net_device *dev,
/* Do we want to just set the transmit key index ? */
/* Do we want to just set the transmit key index ? */
int
index
=
(
dwrq
->
flags
&
IW_ENCODE_INDEX
)
-
1
;
int
index
=
(
dwrq
->
flags
&
IW_ENCODE_INDEX
)
-
1
;
if
((
index
>=
0
)
&&
(
index
<
(
cap_rid
.
softCap
&
0x80
)
?
4
:
1
))
{
if
((
index
>=
0
)
&&
(
index
<
(
cap_rid
.
softCap
&
0x80
)
?
4
:
1
))
{
set_wep_key
(
local
,
index
,
0
,
0
,
1
);
set_wep_key
(
local
,
index
,
0
,
0
,
1
,
1
);
}
else
}
else
/* Don't complain if only change the mode */
/* Don't complain if only change the mode */
if
(
!
dwrq
->
flags
&
IW_ENCODE_MODE
)
{
if
(
!
dwrq
->
flags
&
IW_ENCODE_MODE
)
{
...
@@ -5272,7 +5346,7 @@ static int airo_get_scan(struct net_device *dev,
...
@@ -5272,7 +5346,7 @@ static int airo_get_scan(struct net_device *dev,
* consequences are begnign. So I don't bother fixing it - Javier */
* consequences are begnign. So I don't bother fixing it - Javier */
/* Try to read the first entry of the scan result */
/* Try to read the first entry of the scan result */
rc
=
PC4500_readrid
(
ai
,
RID_BSSLISTFIRST
,
&
BSSList
,
sizeof
(
BSSList
));
rc
=
PC4500_readrid
(
ai
,
RID_BSSLISTFIRST
,
&
BSSList
,
sizeof
(
BSSList
)
,
1
);
if
((
rc
)
||
(
BSSList
.
index
==
0xffff
))
{
if
((
rc
)
||
(
BSSList
.
index
==
0xffff
))
{
/* Client error, no scan results...
/* Client error, no scan results...
* The caller need to restart the scan. */
* The caller need to restart the scan. */
...
@@ -5288,7 +5362,7 @@ static int airo_get_scan(struct net_device *dev,
...
@@ -5288,7 +5362,7 @@ static int airo_get_scan(struct net_device *dev,
/* Read next entry */
/* Read next entry */
rc
=
PC4500_readrid
(
ai
,
RID_BSSLISTNEXT
,
rc
=
PC4500_readrid
(
ai
,
RID_BSSLISTNEXT
,
&
BSSList
,
sizeof
(
BSSList
));
&
BSSList
,
sizeof
(
BSSList
)
,
1
);
}
}
/* Length of data */
/* Length of data */
dwrq
->
length
=
(
current_ev
-
extra
);
dwrq
->
length
=
(
current_ev
-
extra
);
...
@@ -5298,6 +5372,7 @@ static int airo_get_scan(struct net_device *dev,
...
@@ -5298,6 +5372,7 @@ static int airo_get_scan(struct net_device *dev,
}
}
#endif
/* WIRELESS_EXT > 13 */
#endif
/* WIRELESS_EXT > 13 */
#if WIRELESS_EXT <= 15
#ifdef WIRELESS_SPY
#ifdef WIRELESS_SPY
/*------------------------------------------------------------------*/
/*------------------------------------------------------------------*/
/*
/*
...
@@ -5360,6 +5435,7 @@ static int airo_get_spy(struct net_device *dev,
...
@@ -5360,6 +5435,7 @@ static int airo_get_spy(struct net_device *dev,
return
0
;
return
0
;
}
}
#endif
/* WIRELESS_SPY */
#endif
/* WIRELESS_SPY */
#endif
/* WIRELESS_EXT <= 15 */
/*------------------------------------------------------------------*/
/*------------------------------------------------------------------*/
/*
/*
...
@@ -5378,9 +5454,22 @@ static int airo_config_commit(struct net_device *dev,
...
@@ -5378,9 +5454,22 @@ static int airo_config_commit(struct net_device *dev,
/* Some of the "SET" function may have modified some of the
/* Some of the "SET" function may have modified some of the
* parameters. It's now time to commit them in the card */
* parameters. It's now time to commit them in the card */
disable_MAC
(
local
);
disable_MAC
(
local
,
1
);
writeConfigRid
(
local
);
if
(
local
->
need_commit
>
1
)
{
enable_MAC
(
local
,
&
rsp
);
APListRid
APList_rid
;
SsidRid
SSID_rid
;
readAPListRid
(
local
,
&
APList_rid
);
readSsidRid
(
local
,
&
SSID_rid
);
reset_airo_card
(
dev
);
disable_MAC
(
local
,
1
);
writeSsidRid
(
local
,
&
SSID_rid
);
writeAPListRid
(
local
,
&
APList_rid
);
}
writeConfigRid
(
local
,
1
);
enable_MAC
(
local
,
&
rsp
,
1
);
if
(
local
->
need_commit
>
1
)
airo_set_promisc
(
local
);
return
0
;
return
0
;
}
}
...
@@ -5417,6 +5506,12 @@ static const iw_handler airo_handler[] =
...
@@ -5417,6 +5506,12 @@ static const iw_handler airo_handler[] =
(
iw_handler
)
NULL
,
/* SIOCGIWPRIV */
(
iw_handler
)
NULL
,
/* SIOCGIWPRIV */
(
iw_handler
)
NULL
,
/* SIOCSIWSTATS */
(
iw_handler
)
NULL
,
/* SIOCSIWSTATS */
(
iw_handler
)
NULL
,
/* SIOCGIWSTATS */
(
iw_handler
)
NULL
,
/* SIOCGIWSTATS */
#if WIRELESS_EXT > 15
iw_handler_set_spy
,
/* SIOCSIWSPY */
iw_handler_get_spy
,
/* SIOCGIWSPY */
iw_handler_set_thrspy
,
/* SIOCSIWTHRSPY */
iw_handler_get_thrspy
,
/* SIOCGIWTHRSPY */
#else
/* WIRELESS_EXT > 15 */
#ifdef WIRELESS_SPY
#ifdef WIRELESS_SPY
(
iw_handler
)
airo_set_spy
,
/* SIOCSIWSPY */
(
iw_handler
)
airo_set_spy
,
/* SIOCSIWSPY */
(
iw_handler
)
airo_get_spy
,
/* SIOCGIWSPY */
(
iw_handler
)
airo_get_spy
,
/* SIOCGIWSPY */
...
@@ -5426,6 +5521,7 @@ static const iw_handler airo_handler[] =
...
@@ -5426,6 +5521,7 @@ static const iw_handler airo_handler[] =
#endif
/* WIRELESS_SPY */
#endif
/* WIRELESS_SPY */
(
iw_handler
)
NULL
,
/* -- hole -- */
(
iw_handler
)
NULL
,
/* -- hole -- */
(
iw_handler
)
NULL
,
/* -- hole -- */
(
iw_handler
)
NULL
,
/* -- hole -- */
#endif
/* WIRELESS_EXT > 15 */
(
iw_handler
)
airo_set_wap
,
/* SIOCSIWAP */
(
iw_handler
)
airo_set_wap
,
/* SIOCSIWAP */
(
iw_handler
)
airo_get_wap
,
/* SIOCGIWAP */
(
iw_handler
)
airo_get_wap
,
/* SIOCGIWAP */
(
iw_handler
)
NULL
,
/* -- hole -- */
(
iw_handler
)
NULL
,
/* -- hole -- */
...
@@ -5479,6 +5575,11 @@ static const struct iw_handler_def airo_handler_def =
...
@@ -5479,6 +5575,11 @@ static const struct iw_handler_def airo_handler_def =
.
standard
=
(
iw_handler
*
)
airo_handler
,
.
standard
=
(
iw_handler
*
)
airo_handler
,
.
private
=
(
iw_handler
*
)
airo_private_handler
,
.
private
=
(
iw_handler
*
)
airo_private_handler
,
.
private_args
=
(
struct
iw_priv_args
*
)
airo_private_args
,
.
private_args
=
(
struct
iw_priv_args
*
)
airo_private_args
,
#if 0 && WIRELESS_EXT > 15
.spy_offset = ((void *) (&((struct airo_info *) NULL)->spy_data) -
(void *) NULL),
#endif /* WIRELESS_EXT > 15 */
};
};
#endif
/* WIRELESS_EXT > 12 */
#endif
/* WIRELESS_EXT > 12 */
...
@@ -5864,7 +5965,7 @@ struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
...
@@ -5864,7 +5965,7 @@ struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
/* Get stats out of the card */
/* Get stats out of the card */
readStatusRid
(
local
,
&
status_rid
);
readStatusRid
(
local
,
&
status_rid
);
readStatsRid
(
local
,
&
stats_rid
,
RID_STATS
);
readStatsRid
(
local
,
&
stats_rid
,
RID_STATS
,
1
);
/* The status */
/* The status */
local
->
wstats
.
status
=
status_rid
.
mode
;
local
->
wstats
.
status
=
status_rid
.
mode
;
...
@@ -5902,18 +6003,14 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
...
@@ -5902,18 +6003,14 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
unsigned
short
ridcode
;
unsigned
short
ridcode
;
unsigned
char
*
iobuf
;
unsigned
char
*
iobuf
;
struct
airo_info
*
ai
=
dev
->
priv
;
struct
airo_info
*
ai
=
dev
->
priv
;
int
ret
=
0
;
if
(
ai
->
flags
&
FLAG_FLASHING
)
if
(
ai
->
flags
&
FLAG_FLASHING
)
return
-
EIO
;
return
-
EIO
;
iobuf
=
kmalloc
(
RIDS_SIZE
,
GFP_KERNEL
);
if
(
!
iobuf
)
return
-
ENOMEM
;
switch
(
comp
->
command
)
switch
(
comp
->
command
)
{
{
case
AIROGCAP
:
ridcode
=
RID_CAPABILITIES
;
break
;
case
AIROGCAP
:
ridcode
=
RID_CAPABILITIES
;
break
;
case
AIROGCFG
:
writeConfigRid
(
ai
);
case
AIROGCFG
:
writeConfigRid
(
ai
,
1
);
ridcode
=
RID_CONFIG
;
break
;
ridcode
=
RID_CONFIG
;
break
;
case
AIROGSLIST
:
ridcode
=
RID_SSID
;
break
;
case
AIROGSLIST
:
ridcode
=
RID_SSID
;
break
;
case
AIROGVLIST
:
ridcode
=
RID_APLIST
;
break
;
case
AIROGVLIST
:
ridcode
=
RID_APLIST
;
break
;
...
@@ -5921,17 +6018,13 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
...
@@ -5921,17 +6018,13 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
case
AIROGEHTENC
:
ridcode
=
RID_ETHERENCAP
;
break
;
case
AIROGEHTENC
:
ridcode
=
RID_ETHERENCAP
;
break
;
case
AIROGWEPKTMP
:
ridcode
=
RID_WEP_TEMP
;
case
AIROGWEPKTMP
:
ridcode
=
RID_WEP_TEMP
;
/* Only super-user can read WEP keys */
/* Only super-user can read WEP keys */
if
(
!
capable
(
CAP_NET_ADMIN
))
{
if
(
!
capable
(
CAP_NET_ADMIN
))
ret
=
-
EPERM
;
return
-
EPERM
;
goto
rr_free
;
}
break
;
break
;
case
AIROGWEPKNV
:
ridcode
=
RID_WEP_PERM
;
case
AIROGWEPKNV
:
ridcode
=
RID_WEP_PERM
;
/* Only super-user can read WEP keys */
/* Only super-user can read WEP keys */
if
(
!
capable
(
CAP_NET_ADMIN
))
{
if
(
!
capable
(
CAP_NET_ADMIN
))
ret
=
-
EPERM
;
return
-
EPERM
;
goto
rr_free
;
}
break
;
break
;
case
AIROGSTAT
:
ridcode
=
RID_STATUS
;
break
;
case
AIROGSTAT
:
ridcode
=
RID_STATUS
;
break
;
case
AIROGSTATSD32
:
ridcode
=
RID_STATSDELTA
;
break
;
case
AIROGSTATSD32
:
ridcode
=
RID_STATSDELTA
;
break
;
...
@@ -5939,25 +6032,29 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
...
@@ -5939,25 +6032,29 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
case
AIROGMICSTATS
:
case
AIROGMICSTATS
:
if
(
copy_to_user
(
comp
->
data
,
&
ai
->
micstats
,
if
(
copy_to_user
(
comp
->
data
,
&
ai
->
micstats
,
min
((
int
)
comp
->
len
,(
int
)
sizeof
(
ai
->
micstats
))))
min
((
int
)
comp
->
len
,(
int
)
sizeof
(
ai
->
micstats
))))
ret
=
-
EFAULT
;
ret
urn
-
EFAULT
;
goto
rr_free
;
return
0
;
default:
default:
ret
=
-
EINVAL
;
ret
urn
-
EINVAL
;
goto
rr_free
;
break
;
}
}
PC4500_readrid
(
ai
,
ridcode
,
iobuf
,
RIDS_SIZE
);
if
((
iobuf
=
kmalloc
(
RIDS_SIZE
,
GFP_KERNEL
))
==
NULL
)
return
-
ENOMEM
;
PC4500_readrid
(
ai
,
ridcode
,
iobuf
,
RIDS_SIZE
,
1
);
/* get the count of bytes in the rid docs say 1st 2 bytes is it.
/* get the count of bytes in the rid docs say 1st 2 bytes is it.
* then return it to the user
* then return it to the user
* 9/22/2000 Honor user given length
* 9/22/2000 Honor user given length
*/
*/
if
(
copy_to_user
(
comp
->
data
,
iobuf
,
if
(
copy_to_user
(
comp
->
data
,
iobuf
,
min
((
int
)
comp
->
len
,
(
int
)
RIDS_SIZE
)))
min
((
int
)
comp
->
len
,
(
int
)
RIDS_SIZE
)))
{
ret
=
-
EFAULT
;
kfree
(
iobuf
);
rr_free:
return
-
EFAULT
;
kfree
(
iobuf
);
}
return
ret
;
kfree
(
iobuf
);
return
0
;
}
}
/*
/*
...
@@ -5968,9 +6065,8 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
...
@@ -5968,9 +6065,8 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
struct
airo_info
*
ai
=
dev
->
priv
;
struct
airo_info
*
ai
=
dev
->
priv
;
int
ridcode
,
enabled
;
int
ridcode
,
enabled
;
Resp
rsp
;
Resp
rsp
;
static
int
(
*
writer
)(
struct
airo_info
*
,
u16
rid
,
const
void
*
,
int
);
static
int
(
*
writer
)(
struct
airo_info
*
,
u16
rid
,
const
void
*
,
int
,
int
);
unsigned
char
*
iobuf
;
unsigned
char
*
iobuf
;
int
ret
=
0
;
/* Only super-user can write RIDs */
/* Only super-user can write RIDs */
if
(
!
capable
(
CAP_NET_ADMIN
))
if
(
!
capable
(
CAP_NET_ADMIN
))
...
@@ -5979,10 +6075,6 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
...
@@ -5979,10 +6075,6 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
if
(
ai
->
flags
&
FLAG_FLASHING
)
if
(
ai
->
flags
&
FLAG_FLASHING
)
return
-
EIO
;
return
-
EIO
;
iobuf
=
kmalloc
(
RIDS_SIZE
,
GFP_KERNEL
);
if
(
!
iobuf
)
return
-
ENOMEM
;
ridcode
=
0
;
ridcode
=
0
;
writer
=
do_writerid
;
writer
=
do_writerid
;
...
@@ -6003,47 +6095,52 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
...
@@ -6003,47 +6095,52 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
* same with MAC off
* same with MAC off
*/
*/
case
AIROPMACON
:
case
AIROPMACON
:
if
(
enable_MAC
(
ai
,
&
rsp
)
!=
0
)
if
(
enable_MAC
(
ai
,
&
rsp
,
1
)
!=
0
)
ret
=
-
EIO
;
ret
urn
-
EIO
;
goto
wr_free
;
return
0
;
/*
/*
* Evidently this code in the airo driver does not get a symbol
* Evidently this code in the airo driver does not get a symbol
* as disable_MAC. it's probably so short the compiler does not gen one.
* as disable_MAC. it's probably so short the compiler does not gen one.
*/
*/
case
AIROPMACOFF
:
case
AIROPMACOFF
:
disable_MAC
(
ai
);
disable_MAC
(
ai
,
1
);
goto
wr_free
;
return
0
;
/* This command merely clears the counts does not actually store any data
/* This command merely clears the counts does not actually store any data
* only reads rid. But as it changes the cards state, I put it in the
* only reads rid. But as it changes the cards state, I put it in the
* writerid routines.
* writerid routines.
*/
*/
case
AIROPSTCLR
:
case
AIROPSTCLR
:
PC4500_readrid
(
ai
,
RID_STATSDELTACLEAR
,
iobuf
,
RIDS_SIZE
);
if
((
iobuf
=
kmalloc
(
RIDS_SIZE
,
GFP_KERNEL
))
==
NULL
)
return
-
ENOMEM
;
PC4500_readrid
(
ai
,
RID_STATSDELTACLEAR
,
iobuf
,
RIDS_SIZE
,
1
);
enabled
=
ai
->
micstats
.
enabled
;
enabled
=
ai
->
micstats
.
enabled
;
memset
(
&
ai
->
micstats
,
0
,
sizeof
(
ai
->
micstats
));
memset
(
&
ai
->
micstats
,
0
,
sizeof
(
ai
->
micstats
));
ai
->
micstats
.
enabled
=
enabled
;
ai
->
micstats
.
enabled
=
enabled
;
if
(
copy_to_user
(
comp
->
data
,
iobuf
,
if
(
copy_to_user
(
comp
->
data
,
iobuf
,
min
((
int
)
comp
->
len
,
(
int
)
RIDS_SIZE
)))
min
((
int
)
comp
->
len
,
(
int
)
RIDS_SIZE
)))
{
ret
=
-
EFAULT
;
kfree
(
iobuf
);
goto
wr_free
;
return
-
EFAULT
;
}
kfree
(
iobuf
);
return
0
;
default:
default:
ret
=
-
EOPNOTSUPP
;
/* Blarg! */
return
-
EOPNOTSUPP
;
/* Blarg! */
goto
wr_free
;
}
}
if
(
comp
->
len
>
RIDS_SIZE
)
return
-
EINVAL
;
if
(
comp
->
len
>
RIDS_SIZE
)
{
if
((
iobuf
=
kmalloc
(
RIDS_SIZE
,
GFP_KERNEL
))
==
NULL
)
ret
=
-
EINVAL
;
return
-
ENOMEM
;
goto
wr_free
;
}
if
(
copy_from_user
(
iobuf
,
comp
->
data
,
comp
->
len
))
{
if
(
copy_from_user
(
iobuf
,
comp
->
data
,
comp
->
len
))
{
ret
=
-
EFAULT
;
kfree
(
iobuf
)
;
goto
wr_free
;
return
-
EFAULT
;
}
}
if
(
comp
->
command
==
AIROPCFG
)
{
if
(
comp
->
command
==
AIROPCFG
)
{
...
@@ -6058,11 +6155,12 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
...
@@ -6058,11 +6155,12 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
ai
->
flags
&=
~
FLAG_ADHOC
;
ai
->
flags
&=
~
FLAG_ADHOC
;
}
}
if
((
*
writer
)(
ai
,
ridcode
,
iobuf
,
comp
->
len
))
if
((
*
writer
)(
ai
,
ridcode
,
iobuf
,
comp
->
len
,
1
))
{
ret
=
-
EIO
;
kfree
(
iobuf
);
wr_free:
return
-
EIO
;
kfree
(
iobuf
);
}
return
ret
;
kfree
(
iobuf
);
return
0
;
}
}
/*****************************************************************************
/*****************************************************************************
...
@@ -6140,7 +6238,7 @@ int flashcard(struct net_device *dev, aironet_ioctl *comp) {
...
@@ -6140,7 +6238,7 @@ int flashcard(struct net_device *dev, aironet_ioctl *comp) {
*/
*/
int
cmdreset
(
struct
airo_info
*
ai
)
{
int
cmdreset
(
struct
airo_info
*
ai
)
{
disable_MAC
(
ai
);
disable_MAC
(
ai
,
1
);
if
(
!
waitbusy
(
ai
)){
if
(
!
waitbusy
(
ai
)){
printk
(
KERN_INFO
"Waitbusy hang before RESET
\n
"
);
printk
(
KERN_INFO
"Waitbusy hang before RESET
\n
"
);
...
...
drivers/net/wireless/wl3501.h
0 → 100644
View file @
1d90ac41
#ifndef __WL3501_H__
#define __WL3501_H__
#include <linux/spinlock.h>
#include "ieee802_11.h"
/* define for WLA 2.0 */
#define WL3501_BLKSZ 256
/*
* ID for input Signals of DRIVER block
* bit[7-5] is block ID: 000
* bit[4-0] is signal ID
*/
enum
wl3501_signals
{
WL3501_SIG_ALARM
,
WL3501_SIG_MD_CONFIRM
,
WL3501_SIG_MD_IND
,
WL3501_SIG_ASSOC_CONFIRM
,
WL3501_SIG_ASSOC_IND
,
WL3501_SIG_AUTH_CONFIRM
,
WL3501_SIG_AUTH_IND
,
WL3501_SIG_DEAUTH_CONFIRM
,
WL3501_SIG_DEAUTH_IND
,
WL3501_SIG_DISASSOC_CONFIRM
,
WL3501_SIG_DISASSOC_IND
,
WL3501_SIG_GET_CONFIRM
,
WL3501_SIG_JOIN_CONFIRM
,
WL3501_SIG_PWR_MGMT_CONFIRM
,
WL3501_SIG_REASSOC_CONFIRM
,
WL3501_SIG_REASSOC_IND
,
WL3501_SIG_SCAN_CONFIRM
,
WL3501_SIG_SET_CONFIRM
,
WL3501_SIG_START_CONFIRM
,
WL3501_SIG_RESYNC_CONFIRM
,
WL3501_SIG_SITE_CONFIRM
,
WL3501_SIG_SAVE_CONFIRM
,
WL3501_SIG_RFTEST_CONFIRM
,
/*
* ID for input Signals of MLME block
* bit[7-5] is block ID: 010
* bit[4-0] is signal ID
*/
WL3501_SIG_ASSOC_REQ
=
0x20
,
WL3501_SIG_AUTH_REQ
,
WL3501_SIG_DEAUTH_REQ
,
WL3501_SIG_DISASSOC_REQ
,
WL3501_SIG_GET_REQ
,
WL3501_SIG_JOIN_REQ
,
WL3501_SIG_PWR_MGMT_REQ
,
WL3501_SIG_REASSOC_REQ
,
WL3501_SIG_SCAN_REQ
,
WL3501_SIG_SET_REQ
,
WL3501_SIG_START_REQ
,
WL3501_SIG_MD_REQ
,
WL3501_SIG_RESYNC_REQ
,
WL3501_SIG_SITE_REQ
,
WL3501_SIG_SAVE_REQ
,
WL3501_SIG_RF_TEST_REQ
,
WL3501_SIG_MM_CONFIRM
=
0x60
,
WL3501_SIG_MM_IND
,
};
enum
wl3501_mib_attribs
{
WL3501_MIB_ATTR_STATION_ID
,
WL3501_MIB_ATTR_AUTH_ALGORITHMS
,
WL3501_MIB_ATTR_AUTH_TYPE
,
WL3501_MIB_ATTR_MEDIUM_OCCUPANCY_LIMIT
,
WL3501_MIB_ATTR_CF_POLLABLE
,
WL3501_MIB_ATTR_CFP_PERIOD
,
WL3501_MIB_ATTR_CFPMAX_DURATION
,
WL3501_MIB_ATTR_AUTH_RESP_TMOUT
,
WL3501_MIB_ATTR_RX_DTIMS
,
WL3501_MIB_ATTR_PRIV_OPT_IMPLEMENTED
,
WL3501_MIB_ATTR_PRIV_INVOKED
,
WL3501_MIB_ATTR_WEP_DEFAULT_KEYS
,
WL3501_MIB_ATTR_WEP_DEFAULT_KEY_ID
,
WL3501_MIB_ATTR_WEP_KEY_MAPPINGS
,
WL3501_MIB_ATTR_WEP_KEY_MAPPINGS_LEN
,
WL3501_MIB_ATTR_EXCLUDE_UNENCRYPTED
,
WL3501_MIB_ATTR_WEP_ICV_ERROR_COUNT
,
WL3501_MIB_ATTR_WEP_UNDECRYPTABLE_COUNT
,
WL3501_MIB_ATTR_WEP_EXCLUDED_COUNT
,
WL3501_MIB_ATTR_MAC_ADDR
,
WL3501_MIB_ATTR_GROUP_ADDRS
,
WL3501_MIB_ATTR_RTS_THRESHOLD
,
WL3501_MIB_ATTR_SHORT_RETRY_LIMIT
,
WL3501_MIB_ATTR_LONG_RETRY_LIMIT
,
WL3501_MIB_ATTR_FRAG_THRESHOLD
,
WL3501_MIB_ATTR_MAX_TX_MSDU_LIFETIME
,
WL3501_MIB_ATTR_MAX_RX_LIFETIME
,
WL3501_MIB_ATTR_MANUFACTURER_ID
,
WL3501_MIB_ATTR_PRODUCT_ID
,
WL3501_MIB_ATTR_TX_FRAG_COUNT
,
WL3501_MIB_ATTR_MULTICAST_TX_FRAME_COUNT
,
WL3501_MIB_ATTR_FAILED_COUNT
,
WL3501_MIB_ATTR_RX_FRAG_COUNT
,
WL3501_MIB_ATTR_MULTICAST_RX_COUNT
,
WL3501_MIB_ATTR_FCS_ERROR_COUNT
,
WL3501_MIB_ATTR_RETRY_COUNT
,
WL3501_MIB_ATTR_MULTIPLE_RETRY_COUNT
,
WL3501_MIB_ATTR_RTS_SUCCESS_COUNT
,
WL3501_MIB_ATTR_RTS_FAILURE_COUNT
,
WL3501_MIB_ATTR_ACK_FAILURE_COUNT
,
WL3501_MIB_ATTR_FRAME_DUPLICATE_COUNT
,
WL3501_MIB_ATTR_PHY_TYPE
,
WL3501_MIB_ATTR_REG_DOMAINS_SUPPORT
,
WL3501_MIB_ATTR_CURRENT_REG_DOMAIN
,
WL3501_MIB_ATTR_SLOT_TIME
,
WL3501_MIB_ATTR_CCA_TIME
,
WL3501_MIB_ATTR_RX_TX_TURNAROUND_TIME
,
WL3501_MIB_ATTR_TX_PLCP_DELAY
,
WL3501_MIB_ATTR_RX_TX_SWITCH_TIME
,
WL3501_MIB_ATTR_TX_RAMP_ON_TIME
,
WL3501_MIB_ATTR_TX_RF_DELAY
,
WL3501_MIB_ATTR_SIFS_TIME
,
WL3501_MIB_ATTR_RX_RF_DELAY
,
WL3501_MIB_ATTR_RX_PLCP_DELAY
,
WL3501_MIB_ATTR_MAC_PROCESSING_DELAY
,
WL3501_MIB_ATTR_TX_RAMP_OFF_TIME
,
WL3501_MIB_ATTR_PREAMBLE_LEN
,
WL3501_MIB_ATTR_PLCP_HEADER_LEN
,
WL3501_MIB_ATTR_MPDU_DURATION_FACTOR
,
WL3501_MIB_ATTR_AIR_PROPAGATION_TIME
,
WL3501_MIB_ATTR_TEMP_TYPE
,
WL3501_MIB_ATTR_CW_MIN
,
WL3501_MIB_ATTR_CW_MAX
,
WL3501_MIB_ATTR_SUPPORT_DATA_RATES_TX
,
WL3501_MIB_ATTR_SUPPORT_DATA_RATES_RX
,
WL3501_MIB_ATTR_MPDU_MAX_LEN
,
WL3501_MIB_ATTR_SUPPORT_TX_ANTENNAS
,
WL3501_MIB_ATTR_CURRENT_TX_ANTENNA
,
WL3501_MIB_ATTR_SUPPORT_RX_ANTENNAS
,
WL3501_MIB_ATTR_DIVERSITY_SUPPORT
,
WL3501_MIB_ATTR_DIVERSITY_SELECTION_RS
,
WL3501_MIB_ATTR_NR_SUPPORTED_PWR_LEVELS
,
WL3501_MIB_ATTR_TX_PWR_LEVEL1
,
WL3501_MIB_ATTR_TX_PWR_LEVEL2
,
WL3501_MIB_ATTR_TX_PWR_LEVEL3
,
WL3501_MIB_ATTR_TX_PWR_LEVEL4
,
WL3501_MIB_ATTR_TX_PWR_LEVEL5
,
WL3501_MIB_ATTR_TX_PWR_LEVEL6
,
WL3501_MIB_ATTR_TX_PWR_LEVEL7
,
WL3501_MIB_ATTR_TX_PWR_LEVEL8
,
WL3501_MIB_ATTR_CURRENT_TX_PWR_LEVEL
,
WL3501_MIB_ATTR_CURRENT_CHAN
,
WL3501_MIB_ATTR_CCA_MODE_SUPPORTED
,
WL3501_MIB_ATTR_CURRENT_CCA_MODE
,
WL3501_MIB_ATTR_ED_THRESHOLD
,
WL3501_MIB_ATTR_SINTHESIZER_LOCKED
,
WL3501_MIB_ATTR_CURRENT_PWR_STATE
,
WL3501_MIB_ATTR_DOZE_TURNON_TIME
,
WL3501_MIB_ATTR_RCR33
,
WL3501_MIB_ATTR_DEFAULT_CHAN
,
WL3501_MIB_ATTR_SSID
,
WL3501_MIB_ATTR_PWR_MGMT_ENABLE
,
WL3501_MIB_ATTR_NET_CAPABILITY
,
WL3501_MIB_ATTR_ROUTING
,
};
enum
wl3501_net_type
{
WL3501_NET_TYPE_INFRA
,
WL3501_NET_TYPE_ADHOC
,
WL3501_NET_TYPE_ANY_BSS
,
};
enum
wl3501_scan_type
{
WL3501_SCAN_TYPE_ACTIVE
,
WL3501_SCAN_TYPE_PASSIVE
,
};
enum
wl3501_tx_result
{
WL3501_TX_RESULT_SUCCESS
,
WL3501_TX_RESULT_NO_BSS
,
WL3501_TX_RESULT_RETRY_LIMIT
,
};
enum
wl3501_sys_type
{
WL3501_SYS_TYPE_OPEN
,
WL3501_SYS_TYPE_SHARE_KEY
,
};
enum
wl3501_status
{
WL3501_STATUS_SUCCESS
,
WL3501_STATUS_INVALID
,
WL3501_STATUS_TIMEOUT
,
WL3501_STATUS_REFUSED
,
WL3501_STATUS_MANY_REQ
,
WL3501_STATUS_ALREADY_BSS
,
};
#define WL3501_MGMT_CAPABILITY_ESS 0x0001
/* see 802.11 p.58 */
#define WL3501_MGMT_CAPABILITY_IBSS 0x0002
/* - " - */
#define WL3501_MGMT_CAPABILITY_CF_POLLABLE 0x0004
/* - " - */
#define WL3501_MGMT_CAPABILITY_CF_POLL_REQUEST 0x0008
/* - " - */
#define WL3501_MGMT_CAPABILITY_PRIVACY 0x0010
/* - " - */
#define IW_REG_DOMAIN_FCC 0x10
/* Channel 1 to 11 USA */
#define IW_REG_DOMAIN_DOC 0x20
/* Channel 1 to 11 Canada */
#define IW_REG_DOMAIN_ETSI 0x30
/* Channel 1 to 13 Europe */
#define IW_REG_DOMAIN_SPAIN 0x31
/* Channel 10 to 11 Spain */
#define IW_REG_DOMAIN_FRANCE 0x32
/* Channel 10 to 13 France */
#define IW_REG_DOMAIN_MKK 0x40
/* Channel 14 Japan */
#define IW_REG_DOMAIN_MKK1 0x41
/* Channel 1-14 Japan */
#define IW_REG_DOMAIN_ISRAEL 0x50
/* Channel 3 - 9 Israel */
#define WL3501_ESSID_MAX_LEN (IW_ESSID_MAX_SIZE + 2)
struct
wl3501_tx_hdr
{
u16
tx_cnt
;
u8
sync
[
16
];
u16
sfd
;
u8
signal
;
u8
service
;
u16
len
;
u16
crc16
;
u16
frame_ctrl
;
u16
duration_id
;
u8
addr1
[
ETH_ALEN
];
u8
addr2
[
ETH_ALEN
];
u8
addr3
[
ETH_ALEN
];
u16
seq_ctrl
;
u8
addr4
[
ETH_ALEN
];
};
struct
wl3501_rx_hdr
{
u16
rx_next_blk
;
u16
rc_next_frame_blk
;
u8
rx_blk_ctrl
;
u8
rx_next_frame
;
u8
rx_next_frame1
;
u8
rssi
;
char
time
[
8
];
u8
signal
;
u8
service
;
u16
len
;
u16
crc16
;
u16
frame_ctrl
;
u16
duration
;
u8
addr1
[
ETH_ALEN
];
u8
addr2
[
ETH_ALEN
];
u8
addr3
[
ETH_ALEN
];
u16
seq
;
u8
addr4
[
ETH_ALEN
];
};
struct
wl3501_start_req
{
u16
next_blk
;
u8
sig_id
;
u8
bss_type
;
u16
beacon_period
;
u16
dtim_period
;
u16
probe_delay
;
u16
cap_info
;
char
ssid
[
WL3501_ESSID_MAX_LEN
];
u8
bss_basic_rate_set
[
10
];
u8
operational_rate_set
[
10
];
u8
cf_pset
[
8
];
u8
phy_pset
[
3
];
u8
ibss_pset
[
4
];
};
struct
wl3501_assoc_req
{
u16
next_blk
;
u8
sig_id
;
u8
reserved
;
u16
timeout
;
u16
cap_info
;
u16
listen_interval
;
u8
mac_addr
[
ETH_ALEN
];
};
struct
wl3501_assoc_confirm
{
u16
next_blk
;
u8
sig_id
;
u8
reserved
;
u16
status
;
};
struct
wl3501_assoc_ind
{
u16
next_blk
;
u8
sig_id
;
u8
mac_addr
[
ETH_ALEN
];
};
struct
wl3501_auth_req
{
u16
next_blk
;
u8
sig_id
;
u8
reserved
;
u16
type
;
u16
timeout
;
u8
mac_addr
[
ETH_ALEN
];
};
struct
wl3501_auth_confirm
{
u16
next_blk
;
u8
sig_id
;
u8
reserved
;
u16
type
;
u16
status
;
u8
mac_addr
[
ETH_ALEN
];
};
struct
wl3501_get_req
{
u16
next_blk
;
u8
sig_id
;
u8
reserved
;
u16
mib_attrib
;
};
struct
wl3501_get_confirm
{
u16
next_blk
;
u8
sig_id
;
u8
reserved
;
u16
mib_status
;
u16
mib_attrib
;
u8
mib_value
[
100
];
};
struct
wl3501_join_req
{
u16
next_blk
;
u8
sig_id
;
u8
reserved
;
u8
operational_rate_set
[
10
];
u16
reserved2
;
u16
timeout
;
u16
probe_delay
;
u8
timestamp
[
8
];
u8
local_time
[
8
];
u16
beacon_period
;
u16
dtim_period
;
u16
cap_info
;
u8
bss_type
;
u8
bssid
[
ETH_ALEN
];
char
ssid
[
WL3501_ESSID_MAX_LEN
];
u8
phy_pset
[
3
];
u8
cf_pset
[
8
];
u8
ibss_pset
[
4
];
u8
bss_basic_rate_set
[
10
];
};
struct
wl3501_join_confirm
{
u16
next_blk
;
u8
sig_id
;
u8
reserved
;
u16
status
;
};
struct
wl3501_pwr_mgmt_req
{
u16
next_blk
;
u8
sig_id
;
u8
pwr_save
;
u8
wake_up
;
u8
receive_dtims
;
};
struct
wl3501_pwr_mgmt_confirm
{
u16
next_blk
;
u8
sig_id
;
u8
reserved
;
u16
status
;
};
struct
wl3501_scan_req
{
u16
next_blk
;
u8
sig_id
;
u8
bss_type
;
u16
probe_delay
;
u16
min_chan_time
;
u16
max_chan_time
;
u8
chan_list
[
14
];
u8
bssid
[
ETH_ALEN
];
char
ssid
[
WL3501_ESSID_MAX_LEN
];
enum
wl3501_scan_type
scan_type
;
};
struct
wl3501_scan_confirm
{
u16
next_blk
;
u8
sig_id
;
u8
reserved
;
u16
status
;
char
timestamp
[
8
];
char
localtime
[
8
];
u16
beacon_period
;
u16
dtim_period
;
u16
cap_info
;
u8
bss_type
;
u8
bssid
[
ETH_ALEN
];
char
ssid
[
WL3501_ESSID_MAX_LEN
];
u8
phy_pset
[
3
];
u8
cf_pset
[
8
];
u8
ibss_pset
[
4
];
u8
bss_basic_rate_set
[
10
];
u8
rssi
;
};
struct
wl3501_start_confirm
{
u16
next_blk
;
u8
sig_id
;
u8
reserved
;
u16
status
;
};
struct
wl3501_md_req
{
u16
next_blk
;
u8
sig_id
;
u8
routing
;
u16
data
;
u16
size
;
u8
pri
;
u8
service_class
;
u8
daddr
[
ETH_ALEN
];
u8
saddr
[
ETH_ALEN
];
};
struct
wl3501_md_ind
{
u16
next_blk
;
u8
sig_id
;
u8
routing
;
u16
data
;
u16
size
;
u8
reception
;
u8
pri
;
u8
service_class
;
u8
daddr
[
ETH_ALEN
];
u8
saddr
[
ETH_ALEN
];
};
struct
wl3501_md_confirm
{
u16
next_blk
;
u8
sig_id
;
u8
reserved
;
u16
data
;
u8
status
;
u8
pri
;
u8
service_class
;
};
struct
wl3501_resync_req
{
u16
next_blk
;
u8
sig_id
;
};
/* Definitions for supporting clone adapters. */
/* System Interface Registers (SIR space) */
#define WL3501_NIC_GCR ((u8)0x00)
/* SIR0 - General Conf Register */
#define WL3501_NIC_BSS ((u8)0x01)
/* SIR1 - Bank Switching Select Reg */
#define WL3501_NIC_LMAL ((u8)0x02)
/* SIR2 - Local Mem addr Reg [7:0] */
#define WL3501_NIC_LMAH ((u8)0x03)
/* SIR3 - Local Mem addr Reg [14:8] */
#define WL3501_NIC_IODPA ((u8)0x04)
/* SIR4 - I/O Data Port A */
#define WL3501_NIC_IODPB ((u8)0x05)
/* SIR5 - I/O Data Port B */
#define WL3501_NIC_IODPC ((u8)0x06)
/* SIR6 - I/O Data Port C */
#define WL3501_NIC_IODPD ((u8)0x07)
/* SIR7 - I/O Data Port D */
/* Bits in GCR */
#define WL3501_GCR_SWRESET ((u8)0x80)
#define WL3501_GCR_CORESET ((u8)0x40)
#define WL3501_GCR_DISPWDN ((u8)0x20)
#define WL3501_GCR_ECWAIT ((u8)0x10)
#define WL3501_GCR_ECINT ((u8)0x08)
#define WL3501_GCR_INT2EC ((u8)0x04)
#define WL3501_GCR_ENECINT ((u8)0x02)
#define WL3501_GCR_DAM ((u8)0x01)
/* Bits in BSS (Bank Switching Select Register) */
#define WL3501_BSS_FPAGE0 ((u8)0x20)
/* Flash memory page0 */
#define WL3501_BSS_FPAGE1 ((u8)0x28)
#define WL3501_BSS_FPAGE2 ((u8)0x30)
#define WL3501_BSS_FPAGE3 ((u8)0x38)
#define WL3501_BSS_SPAGE0 ((u8)0x00)
/* SRAM page0 */
#define WL3501_BSS_SPAGE1 ((u8)0x08)
#define WL3501_BSS_SPAGE2 ((u8)0x10)
#define WL3501_BSS_SPAGE3 ((u8)0x18)
/* Define Driver Interface */
/* Refer IEEE 802.11 */
/* Tx packet header, include PLCP and MPDU */
/* Tx PLCP Header */
struct
wl3501_80211_tx_plcp_hdr
{
u8
sync
[
16
];
u16
sfd
;
u8
signal
;
u8
service
;
u16
len
;
u16
crc16
;
}
__attribute__
((
packed
));
struct
wl3501_80211_tx_hdr
{
struct
wl3501_80211_tx_plcp_hdr
pclp_hdr
;
struct
ieee802_11_hdr
mac_hdr
;
}
__attribute__
((
packed
));
/*
Reserve the beginning Tx space for descriptor use.
TxBlockOffset --> *----*----*----*----* \
(TxFreeDesc) | 0 | 1 | 2 | 3 | \
| 4 | 5 | 6 | 7 | |
| 8 | 9 | 10 | 11 | TX_DESC * 20
| 12 | 13 | 14 | 15 | |
| 16 | 17 | 18 | 19 | /
TxBufferBegin --> *----*----*----*----* /
(TxBufferHead) | |
(TxBufferTail) | |
| Send Buffer |
| |
| |
*-------------------*
TxBufferEnd -------------------------/
*/
struct
wl3501_card
{
int
base_addr
;
u8
mac_addr
[
ETH_ALEN
];
spinlock_t
lock
;
wait_queue_head_t
wait
;
struct
wl3501_get_confirm
sig_get_confirm
;
struct
wl3501_pwr_mgmt_confirm
sig_pwr_mgmt_confirm
;
u16
tx_buffer_size
;
u16
tx_buffer_head
;
u16
tx_buffer_tail
;
u16
tx_buffer_cnt
;
u16
esbq_req_start
;
u16
esbq_req_end
;
u16
esbq_req_head
;
u16
esbq_req_tail
;
u16
esbq_confirm_start
;
u16
esbq_confirm_end
;
u16
esbq_confirm
;
u8
essid
[
WL3501_ESSID_MAX_LEN
];
u8
bssid
[
ETH_ALEN
];
int
net_type
;
u8
keep_essid
[
WL3501_ESSID_MAX_LEN
];
char
nick
[
32
];
char
card_name
[
32
];
char
firmware_date
[
32
];
u8
chan
;
u8
cap_info
;
u16
start_seg
;
u16
bss_cnt
;
u16
join_sta_bss
;
u8
rssi
;
u8
adhoc_times
;
u8
reg_domain
;
u8
version
[
2
];
struct
wl3501_scan_confirm
bss_set
[
20
];
struct
net_device_stats
stats
;
struct
iw_statistics
wstats
;
struct
iw_spy_data
spy_data
;
struct
dev_node_t
node
;
};
#endif
drivers/net/wireless/wl3501_cs.c
0 → 100644
View file @
1d90ac41
/*
* WL3501 Wireless LAN PCMCIA Card Driver for Linux
* Written originally for Linux 2.0.30 by Fox Chen, mhchen@golf.ccl.itri.org.tw
* Ported to 2.2, 2.4 & 2.5 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
* Wireless extensions in 2.4 by Gustavo Niemeyer <niemeyer@conectiva.com>
*
* References used by Fox Chen while writing the original driver for 2.0.30:
*
* 1. WL24xx packet drivers (tooasm.asm)
* 2. Access Point Firmware Interface Specification for IEEE 802.11 SUTRO
* 3. IEEE 802.11
* 4. Linux network driver (/usr/src/linux/drivers/net)
* 5. ISA card driver - wl24.c
* 6. Linux PCMCIA skeleton driver - skeleton.c
* 7. Linux PCMCIA 3c589 network driver - 3c589_cs.c
*
* Tested with WL2400 firmware 1.2, Linux 2.0.30, and pcmcia-cs-2.9.12
* 1. Performance: about 165 Kbytes/sec in TCP/IP with Ad-Hoc mode.
* rsh 192.168.1.3 "dd if=/dev/zero bs=1k count=1000" > /dev/null
* (Specification 2M bits/sec. is about 250 Kbytes/sec., but we must deduct
* ETHER/IP/UDP/TCP header, and acknowledgement overhead)
*
* Tested with Planet AP in 2.4.17, 184 Kbytes/s in UDP in Infrastructure mode,
* 173 Kbytes/s in TCP.
*
* Tested with Planet AP in 2.5.73-bk, 216 Kbytes/s in Infrastructure mode
* with a SMP machine (dual pentium 100), using pktgen, 432 pps (pkt_size = 60)
*/
#undef REALLY_SLOW_IO
/* most systems can safely undef this */
#include <linux/config.h>
#include <linux/delay.h>
#include <linux/types.h>
#include <linux/ethtool.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fcntl.h>
#include <linux/if_arp.h>
#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/wireless.h>
#include <net/iw_handler.h>
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include "wl3501.h"
#ifndef __i386__
#define slow_down_io()
#endif
/* For rough constant delay */
#define WL3501_NOPLOOP(n) { int x = 0; while (x++ < n) slow_down_io(); }
/*
* All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If you do not
* define PCMCIA_DEBUG at all, all the debug code will be left out. If you
* compile with PCMCIA_DEBUG=0, the debug code will be present but disabled --
* but it can then be enabled for specific modules at load time with a
* 'pc_debug=#' option to insmod.
*/
#define PCMCIA_DEBUG 0
#ifdef PCMCIA_DEBUG
static
int
pc_debug
=
PCMCIA_DEBUG
;
MODULE_PARM
(
pc_debug
,
"i"
);
#define dprintk(n, format, args...) \
{ if (pc_debug > (n)) \
printk(KERN_INFO "%s: " format "\n", __FUNCTION__, ##args); }
#else
#define dprintk(n, format, args...)
#endif
#define wl3501_outb(a, b) { outb(a, b); slow_down_io(); }
#define wl3501_outb_p(a, b) { outb_p(a, b); slow_down_io(); }
#define wl3501_outsb(a, b, c) { outsb(a, b, c); slow_down_io(); }
#define WL3501_RELEASE_TIMEOUT (25 * HZ)
#define WL3501_MAX_ADHOC_TRIES 16
#define WL3501_RESUME 0
#define WL3501_SUSPEND 1
/* Parameters that can be set with 'insmod' */
/* Bit map of interrupts to choose from */
/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
static
unsigned
long
wl3501_irq_mask
=
0xdeb8
;
static
int
wl3501_irq_list
[
4
]
=
{
-
1
};
/*
* The event() function is this driver's Card Services event handler. It will
* be called by Card Services when an appropriate card status event is
* received. The config() and release() entry points are used to configure or
* release a socket, in response to card insertion and ejection events. They
* are invoked from the wl24 event handler.
*/
static
void
wl3501_config
(
dev_link_t
*
link
);
static
void
wl3501_release
(
unsigned
long
arg
);
static
int
wl3501_event
(
event_t
event
,
int
pri
,
event_callback_args_t
*
args
);
/*
* The dev_info variable is the "key" that is used to match up this
* device driver with appropriate cards, through the card configuration
* database.
*/
static
dev_info_t
wl3501_dev_info
=
"wl3501_cs"
;
static
int
wl3501_chan2freq
[]
=
{
[
0
]
=
2412
,
[
1
]
=
2417
,
[
2
]
=
2422
,
[
3
]
=
2427
,
[
4
]
=
2432
,
[
5
]
=
2437
,
[
6
]
=
2442
,
[
7
]
=
2447
,
[
8
]
=
2452
,
[
9
]
=
2457
,
[
10
]
=
2462
,
[
11
]
=
2467
,
[
12
]
=
2472
,
[
13
]
=
2477
,
};
static
const
struct
{
int
reg_domain
;
int
min
,
max
,
deflt
;
}
iw_channel_table
[]
=
{
{
.
reg_domain
=
IW_REG_DOMAIN_FCC
,
.
min
=
1
,
.
max
=
11
,
.
deflt
=
1
,
},
{
.
reg_domain
=
IW_REG_DOMAIN_DOC
,
.
min
=
1
,
.
max
=
11
,
.
deflt
=
1
,
},
{
.
reg_domain
=
IW_REG_DOMAIN_ETSI
,
.
min
=
1
,
.
max
=
13
,
.
deflt
=
1
,
},
{
.
reg_domain
=
IW_REG_DOMAIN_SPAIN
,
.
min
=
10
,
.
max
=
11
,
.
deflt
=
10
,
},
{
.
reg_domain
=
IW_REG_DOMAIN_FRANCE
,
.
min
=
10
,
.
max
=
13
,
.
deflt
=
10
,
},
{
.
reg_domain
=
IW_REG_DOMAIN_MKK
,
.
min
=
14
,
.
max
=
14
,
.
deflt
=
14
,
},
{
.
reg_domain
=
IW_REG_DOMAIN_MKK1
,
.
min
=
1
,
.
max
=
14
,
.
deflt
=
1
,
},
{
.
reg_domain
=
IW_REG_DOMAIN_ISRAEL
,
.
min
=
3
,
.
max
=
9
,
.
deflt
=
9
,
},
};
/**
* iw_valid_channel - validate channel in regulatory domain
* @reg_comain - regulatory domain
* @channel - channel to validate
*
* Returns 0 if invalid in the specified regulatory domain, non-zero if valid.
*/
static
int
iw_valid_channel
(
int
reg_domain
,
int
channel
)
{
int
i
,
rc
=
0
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
iw_channel_table
);
i
++
)
if
(
reg_domain
==
iw_channel_table
[
i
].
reg_domain
)
{
rc
=
channel
>=
iw_channel_table
[
i
].
min
&&
channel
<=
iw_channel_table
[
i
].
max
;
break
;
}
return
rc
;
}
/**
* iw_default_channel - get default channel for a regulatory domain
* @reg_comain - regulatory domain
*
* Returns the default channel for a regulatory domain
*/
static
int
iw_default_channel
(
int
reg_domain
)
{
int
i
,
rc
=
1
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
iw_channel_table
);
i
++
)
if
(
reg_domain
==
iw_channel_table
[
i
].
reg_domain
)
{
rc
=
iw_channel_table
[
i
].
deflt
;
break
;
}
return
rc
;
}
/*
* A linked list of "instances" of the wl24 device. Each actual PCMCIA card
* corresponds to one device instance, and is described by one dev_link_t
* structure (defined in ds.h).
*
* You may not want to use a linked list for this -- for example, the memory
* card driver uses an array of dev_link_t pointers, where minor device numbers
* are used to derive the corresponding array index.
*/
static
dev_link_t
*
wl3501_dev_list
;
static
inline
void
wl3501_switch_page
(
struct
wl3501_card
*
this
,
u8
page
)
{
wl3501_outb
(
page
,
this
->
base_addr
+
WL3501_NIC_BSS
);
}
/*
* Get Ethernet MAC addresss.
*
* WARNING: We switch to FPAGE0 and switc back again.
* Making sure there is no other WL function beening called by ISR.
*/
static
int
wl3501_get_flash_mac_addr
(
struct
wl3501_card
*
this
)
{
int
base_addr
=
this
->
base_addr
;
/* get MAC addr */
wl3501_outb
(
WL3501_BSS_FPAGE3
,
base_addr
+
WL3501_NIC_BSS
);
/* BSS */
wl3501_outb
(
0x00
,
base_addr
+
WL3501_NIC_LMAL
);
/* LMAL */
wl3501_outb
(
0x40
,
base_addr
+
WL3501_NIC_LMAH
);
/* LMAH */
/* wait for reading EEPROM */
WL3501_NOPLOOP
(
100
);
this
->
mac_addr
[
0
]
=
inb
(
base_addr
+
WL3501_NIC_IODPA
);
WL3501_NOPLOOP
(
100
);
this
->
mac_addr
[
1
]
=
inb
(
base_addr
+
WL3501_NIC_IODPA
);
WL3501_NOPLOOP
(
100
);
this
->
mac_addr
[
2
]
=
inb
(
base_addr
+
WL3501_NIC_IODPA
);
WL3501_NOPLOOP
(
100
);
this
->
mac_addr
[
3
]
=
inb
(
base_addr
+
WL3501_NIC_IODPA
);
WL3501_NOPLOOP
(
100
);
this
->
mac_addr
[
4
]
=
inb
(
base_addr
+
WL3501_NIC_IODPA
);
WL3501_NOPLOOP
(
100
);
this
->
mac_addr
[
5
]
=
inb
(
base_addr
+
WL3501_NIC_IODPA
);
WL3501_NOPLOOP
(
100
);
this
->
reg_domain
=
inb
(
base_addr
+
WL3501_NIC_IODPA
);
WL3501_NOPLOOP
(
100
);
wl3501_outb
(
WL3501_BSS_FPAGE0
,
base_addr
+
WL3501_NIC_BSS
);
wl3501_outb
(
0x04
,
base_addr
+
WL3501_NIC_LMAL
);
wl3501_outb
(
0x40
,
base_addr
+
WL3501_NIC_LMAH
);
WL3501_NOPLOOP
(
100
);
this
->
version
[
0
]
=
inb
(
base_addr
+
WL3501_NIC_IODPA
);
WL3501_NOPLOOP
(
100
);
this
->
version
[
1
]
=
inb
(
base_addr
+
WL3501_NIC_IODPA
);
/* switch to SRAM Page 0 (for safety) */
wl3501_switch_page
(
this
,
WL3501_BSS_SPAGE0
);
/* The MAC addr should be 00:60:... */
return
this
->
mac_addr
[
0
]
==
0x00
&&
this
->
mac_addr
[
1
]
==
0x60
;
}
/**
* wl3501_set_to_wla - Move 'size' bytes from PC to card
* @dest: Card addressing space
* @src: PC addressing space
* @size: Bytes to move
*
* Move 'size' bytes from PC to card. (Shouldn't be interrupted)
*/
void
wl3501_set_to_wla
(
struct
wl3501_card
*
this
,
u16
dest
,
void
*
src
,
int
size
)
{
/* switch to SRAM Page 0 */
wl3501_switch_page
(
this
,
(
dest
&
0x8000
)
?
WL3501_BSS_SPAGE1
:
WL3501_BSS_SPAGE0
);
/* set LMAL and LMAH */
wl3501_outb
(
dest
&
0xff
,
this
->
base_addr
+
WL3501_NIC_LMAL
);
wl3501_outb
(((
dest
>>
8
)
&
0x7f
),
this
->
base_addr
+
WL3501_NIC_LMAH
);
/* rep out to Port A */
wl3501_outsb
(
this
->
base_addr
+
WL3501_NIC_IODPA
,
src
,
size
);
}
/**
* wl3501_get_from_wla - Move 'size' bytes from card to PC
* @src: Card addressing space
* @dest: PC addressing space
* @size: Bytes to move
*
* Move 'size' bytes from card to PC. (Shouldn't be interrupted)
*/
void
wl3501_get_from_wla
(
struct
wl3501_card
*
this
,
u16
src
,
void
*
dest
,
int
size
)
{
/* switch to SRAM Page 0 */
wl3501_switch_page
(
this
,
(
src
&
0x8000
)
?
WL3501_BSS_SPAGE1
:
WL3501_BSS_SPAGE0
);
/* set LMAL and LMAH */
wl3501_outb
(
src
&
0xff
,
this
->
base_addr
+
WL3501_NIC_LMAL
);
wl3501_outb
((
src
>>
8
)
&
0x7f
,
this
->
base_addr
+
WL3501_NIC_LMAH
);
/* rep get from Port A */
insb
(
this
->
base_addr
+
WL3501_NIC_IODPA
,
dest
,
size
);
}
/*
* Get/Allocate a free Tx Data Buffer
*
* *--------------*-----------------*----------------------------------*
* | PLCP | MAC Header | DST SRC Data ... |
* | (24 bytes) | (30 bytes) | (6) (6) (Ethernet Row Data) |
* *--------------*-----------------*----------------------------------*
* \ \- IEEE 802.11 -/ \-------------- len --------------/
* \-struct wl3501_80211_tx_hdr--/ \-------- Ethernet Frame -------/
*
* Return = Postion in Card
*/
static
u16
wl3501_get_tx_buffer
(
struct
wl3501_card
*
this
,
u16
len
)
{
u16
next
,
blk_cnt
=
0
,
zero
=
0
;
u16
full_len
=
sizeof
(
struct
wl3501_80211_tx_hdr
)
+
len
;
u16
ret
=
0
;
if
(
full_len
>
this
->
tx_buffer_cnt
*
254
)
goto
out
;
ret
=
this
->
tx_buffer_head
;
while
(
full_len
)
{
if
(
full_len
<
254
)
full_len
=
0
;
else
full_len
-=
254
;
wl3501_get_from_wla
(
this
,
this
->
tx_buffer_head
,
&
next
,
sizeof
(
next
));
if
(
!
full_len
)
wl3501_set_to_wla
(
this
,
this
->
tx_buffer_head
,
&
zero
,
sizeof
(
zero
));
this
->
tx_buffer_head
=
next
;
blk_cnt
++
;
/* if buffer is not enough */
if
(
!
next
&&
full_len
)
{
this
->
tx_buffer_head
=
ret
;
ret
=
0
;
goto
out
;
}
}
this
->
tx_buffer_cnt
-=
blk_cnt
;
out:
return
ret
;
}
/*
* Free an allocated Tx Buffer. ptr must be correct position.
*/
static
void
wl3501_free_tx_buffer
(
struct
wl3501_card
*
this
,
u16
ptr
)
{
/* check if all space is not free */
if
(
!
this
->
tx_buffer_head
)
this
->
tx_buffer_head
=
ptr
;
else
wl3501_set_to_wla
(
this
,
this
->
tx_buffer_tail
,
&
ptr
,
sizeof
(
ptr
));
while
(
ptr
)
{
u16
next
;
this
->
tx_buffer_cnt
++
;
wl3501_get_from_wla
(
this
,
ptr
,
&
next
,
sizeof
(
next
));
this
->
tx_buffer_tail
=
ptr
;
ptr
=
next
;
}
}
static
int
wl3501_esbq_req_test
(
struct
wl3501_card
*
this
)
{
u8
tmp
;
wl3501_get_from_wla
(
this
,
this
->
esbq_req_head
+
3
,
&
tmp
,
sizeof
(
tmp
));
return
tmp
&
0x80
;
}
static
void
wl3501_esbq_req
(
struct
wl3501_card
*
this
,
u16
*
ptr
)
{
u16
tmp
=
0
;
wl3501_set_to_wla
(
this
,
this
->
esbq_req_head
,
ptr
,
2
);
wl3501_set_to_wla
(
this
,
this
->
esbq_req_head
+
2
,
&
tmp
,
sizeof
(
tmp
));
this
->
esbq_req_head
+=
4
;
if
(
this
->
esbq_req_head
>=
this
->
esbq_req_end
)
this
->
esbq_req_head
=
this
->
esbq_req_start
;
}
static
int
wl3501_esbq_exec
(
struct
wl3501_card
*
this
,
void
*
sig
,
int
sig_size
)
{
int
rc
=
-
EIO
;
if
(
wl3501_esbq_req_test
(
this
))
{
u16
ptr
=
wl3501_get_tx_buffer
(
this
,
sig_size
);
if
(
ptr
)
{
wl3501_set_to_wla
(
this
,
ptr
,
sig
,
sig_size
);
wl3501_esbq_req
(
this
,
&
ptr
);
rc
=
0
;
}
}
return
rc
;
}
static
int
wl3501_get_mib_value
(
struct
wl3501_card
*
this
,
u8
index
,
void
*
bf
,
int
size
)
{
struct
wl3501_get_req
sig
=
{
.
sig_id
=
WL3501_SIG_GET_REQ
,
.
mib_attrib
=
index
,
};
unsigned
long
flags
;
int
rc
=
-
EIO
;
spin_lock_irqsave
(
&
this
->
lock
,
flags
);
if
(
wl3501_esbq_req_test
(
this
))
{
u16
ptr
=
wl3501_get_tx_buffer
(
this
,
sizeof
(
sig
));
if
(
ptr
)
{
wl3501_set_to_wla
(
this
,
ptr
,
&
sig
,
sizeof
(
sig
));
wl3501_esbq_req
(
this
,
&
ptr
);
this
->
sig_get_confirm
.
mib_status
=
255
;
spin_unlock_irqrestore
(
&
this
->
lock
,
flags
);
rc
=
wait_event_interruptible
(
this
->
wait
,
this
->
sig_get_confirm
.
mib_status
!=
255
);
if
(
!
rc
)
memcpy
(
bf
,
this
->
sig_get_confirm
.
mib_value
,
size
);
goto
out
;
}
}
spin_unlock_irqrestore
(
&
this
->
lock
,
flags
);
out:
return
rc
;
}
static
int
wl3501_pwr_mgmt
(
struct
wl3501_card
*
this
,
int
suspend
)
{
struct
wl3501_pwr_mgmt_req
sig
=
{
.
sig_id
=
WL3501_SIG_PWR_MGMT_REQ
,
.
pwr_save
=
suspend
,
.
wake_up
=
!
suspend
,
.
receive_dtims
=
10
,
};
unsigned
long
flags
;
int
rc
=
-
EIO
;
spin_lock_irqsave
(
&
this
->
lock
,
flags
);
if
(
wl3501_esbq_req_test
(
this
))
{
u16
ptr
=
wl3501_get_tx_buffer
(
this
,
sizeof
(
sig
));
if
(
ptr
)
{
wl3501_set_to_wla
(
this
,
ptr
,
&
sig
,
sizeof
(
sig
));
wl3501_esbq_req
(
this
,
&
ptr
);
this
->
sig_pwr_mgmt_confirm
.
status
=
255
;
spin_unlock_irqrestore
(
&
this
->
lock
,
flags
);
rc
=
wait_event_interruptible
(
this
->
wait
,
this
->
sig_pwr_mgmt_confirm
.
status
!=
255
);
printk
(
KERN_INFO
"%s: %s status=%d
\n
"
,
__FUNCTION__
,
suspend
?
"suspend"
:
"resume"
,
this
->
sig_pwr_mgmt_confirm
.
status
);
goto
out
;
}
}
spin_unlock_irqrestore
(
&
this
->
lock
,
flags
);
out:
return
rc
;
}
/**
* wl3501_send_pkt - Send a packet.
* @this - card
*
* Send a packet.
*
* data = Ethernet raw frame. (e.g. data[0] - data[5] is Dest MAC Addr,
* data[6] - data[11] is Src MAC Addr)
* Ref: IEEE 802.11
*/
static
int
wl3501_send_pkt
(
struct
wl3501_card
*
this
,
u8
*
data
,
u16
len
)
{
u16
bf
,
sig_bf
,
next
,
tmplen
,
pktlen
;
struct
wl3501_md_req
sig
=
{
.
sig_id
=
WL3501_SIG_MD_REQ
,
};
u8
*
pdata
=
(
char
*
)
data
;
int
rc
=
-
EIO
;
if
(
wl3501_esbq_req_test
(
this
))
{
sig_bf
=
wl3501_get_tx_buffer
(
this
,
sizeof
(
sig
));
rc
=
-
ENOMEM
;
if
(
!
sig_bf
)
/* No free buffer available */
goto
out
;
bf
=
wl3501_get_tx_buffer
(
this
,
len
+
26
+
24
);
if
(
!
bf
)
{
/* No free buffer available */
wl3501_free_tx_buffer
(
this
,
sig_bf
);
goto
out
;
}
rc
=
0
;
memcpy
(
&
sig
.
daddr
[
0
],
pdata
,
12
);
pktlen
=
len
-
12
;
pdata
+=
12
;
sig
.
data
=
bf
;
if
(((
*
pdata
)
*
256
+
(
*
(
pdata
+
1
)))
>
1500
)
{
u8
addr4
[
ETH_ALEN
]
=
{
[
0
]
=
0xAA
,
[
1
]
=
0xAA
,
[
2
]
=
0x03
,
[
4
]
=
0x00
,
};
wl3501_set_to_wla
(
this
,
bf
+
2
+
offsetof
(
struct
wl3501_tx_hdr
,
addr4
),
addr4
,
sizeof
(
addr4
));
sig
.
size
=
pktlen
+
24
+
4
+
6
;
if
(
pktlen
>
(
254
-
sizeof
(
struct
wl3501_tx_hdr
)))
{
tmplen
=
254
-
sizeof
(
struct
wl3501_tx_hdr
);
pktlen
-=
tmplen
;
}
else
{
tmplen
=
pktlen
;
pktlen
=
0
;
}
wl3501_set_to_wla
(
this
,
bf
+
2
+
sizeof
(
struct
wl3501_tx_hdr
),
pdata
,
tmplen
);
pdata
+=
tmplen
;
wl3501_get_from_wla
(
this
,
bf
,
&
next
,
sizeof
(
next
));
bf
=
next
;
}
else
{
sig
.
size
=
pktlen
+
24
+
4
-
2
;
pdata
+=
2
;
pktlen
-=
2
;
if
(
pktlen
>
(
254
-
sizeof
(
struct
wl3501_tx_hdr
)
+
6
))
{
tmplen
=
254
-
sizeof
(
struct
wl3501_tx_hdr
)
+
6
;
pktlen
-=
tmplen
;
}
else
{
tmplen
=
pktlen
;
pktlen
=
0
;
}
wl3501_set_to_wla
(
this
,
bf
+
2
+
offsetof
(
struct
wl3501_tx_hdr
,
addr4
),
pdata
,
tmplen
);
pdata
+=
tmplen
;
wl3501_get_from_wla
(
this
,
bf
,
&
next
,
sizeof
(
next
));
bf
=
next
;
}
while
(
pktlen
>
0
)
{
if
(
pktlen
>
254
)
{
tmplen
=
254
;
pktlen
-=
254
;
}
else
{
tmplen
=
pktlen
;
pktlen
=
0
;
}
wl3501_set_to_wla
(
this
,
bf
+
2
,
pdata
,
tmplen
);
pdata
+=
tmplen
;
wl3501_get_from_wla
(
this
,
bf
,
&
next
,
sizeof
(
next
));
bf
=
next
;
}
wl3501_set_to_wla
(
this
,
sig_bf
,
&
sig
,
sizeof
(
sig
));
wl3501_esbq_req
(
this
,
&
sig_bf
);
}
out:
return
rc
;
}
static
int
wl3501_mgmt_resync
(
struct
wl3501_card
*
this
)
{
struct
wl3501_resync_req
sig
=
{
.
sig_id
=
WL3501_SIG_RESYNC_REQ
,
};
return
wl3501_esbq_exec
(
this
,
&
sig
,
sizeof
(
sig
));
}
static
inline
int
wl3501_fw_bss_type
(
struct
wl3501_card
*
this
)
{
return
this
->
net_type
==
IW_MODE_INFRA
?
WL3501_NET_TYPE_INFRA
:
WL3501_NET_TYPE_ADHOC
;
}
static
inline
int
wl3501_fw_cap_info
(
struct
wl3501_card
*
this
)
{
return
this
->
net_type
==
IW_MODE_INFRA
?
WL3501_MGMT_CAPABILITY_ESS
:
WL3501_MGMT_CAPABILITY_IBSS
;
}
static
int
wl3501_mgmt_scan
(
struct
wl3501_card
*
this
,
u16
chan_time
)
{
struct
wl3501_scan_req
sig
=
{
.
sig_id
=
WL3501_SIG_SCAN_REQ
,
.
scan_type
=
WL3501_SCAN_TYPE_ACTIVE
,
.
probe_delay
=
0x10
,
.
min_chan_time
=
chan_time
,
.
max_chan_time
=
chan_time
,
.
bss_type
=
wl3501_fw_bss_type
(
this
),
};
this
->
bss_cnt
=
this
->
join_sta_bss
=
0
;
return
wl3501_esbq_exec
(
this
,
&
sig
,
sizeof
(
sig
));
}
static
int
wl3501_mgmt_join
(
struct
wl3501_card
*
this
,
u16
stas
)
{
struct
wl3501_join_req
sig
=
{
.
sig_id
=
WL3501_SIG_JOIN_REQ
,
.
timeout
=
10
,
.
phy_pset
=
{
[
2
]
=
this
->
chan
,
},
};
memcpy
(
&
sig
.
beacon_period
,
&
this
->
bss_set
[
stas
].
beacon_period
,
72
);
return
wl3501_esbq_exec
(
this
,
&
sig
,
sizeof
(
sig
));
}
static
int
wl3501_mgmt_start
(
struct
wl3501_card
*
this
)
{
struct
wl3501_start_req
sig
=
{
.
sig_id
=
WL3501_SIG_START_REQ
,
.
beacon_period
=
400
,
.
dtim_period
=
1
,
.
phy_pset
=
{
[
0
]
=
3
,
[
1
]
=
1
,
[
2
]
=
this
->
chan
,
},
.
bss_basic_rate_set
=
{
[
0
]
=
0x01
,
[
1
]
=
0x02
,
[
2
]
=
0x82
,
[
3
]
=
0x84
,
},
.
operational_rate_set
=
{
[
0
]
=
0x01
,
[
1
]
=
0x02
,
[
2
]
=
0x82
,
[
3
]
=
0x84
,
},
.
ibss_pset
=
{
[
0
]
=
6
,
[
1
]
=
2
,
[
2
]
=
10
,
},
.
bss_type
=
wl3501_fw_bss_type
(
this
),
.
cap_info
=
wl3501_fw_cap_info
(
this
),
};
memcpy
(
sig
.
ssid
,
this
->
essid
,
WL3501_ESSID_MAX_LEN
);
memcpy
(
this
->
keep_essid
,
this
->
essid
,
WL3501_ESSID_MAX_LEN
);
return
wl3501_esbq_exec
(
this
,
&
sig
,
sizeof
(
sig
));
}
static
void
wl3501_mgmt_scan_confirm
(
struct
wl3501_card
*
this
,
u16
addr
)
{
u16
i
=
0
;
int
matchflag
=
0
;
struct
wl3501_scan_confirm
sig
;
dprintk
(
3
,
"entry"
);
wl3501_get_from_wla
(
this
,
addr
,
&
sig
,
sizeof
(
sig
));
if
(
sig
.
status
==
WL3501_STATUS_SUCCESS
)
{
dprintk
(
3
,
"success"
);
if
((
this
->
net_type
==
IW_MODE_INFRA
&&
(
sig
.
cap_info
&
WL3501_MGMT_CAPABILITY_ESS
))
||
(
this
->
net_type
==
IW_MODE_ADHOC
&&
(
sig
.
cap_info
&
WL3501_MGMT_CAPABILITY_IBSS
))
||
this
->
net_type
==
IW_MODE_AUTO
)
{
if
(
!
this
->
essid
[
1
])
matchflag
=
1
;
else
if
(
this
->
essid
[
1
]
==
3
&&
!
strncmp
((
char
*
)
&
this
->
essid
[
2
],
"ANY"
,
3
))
matchflag
=
1
;
else
if
(
this
->
essid
[
1
]
!=
sig
.
ssid
[
1
])
matchflag
=
0
;
else
if
(
memcmp
(
&
this
->
essid
[
2
],
&
sig
.
ssid
[
2
],
this
->
essid
[
1
]))
matchflag
=
0
;
else
matchflag
=
1
;
if
(
matchflag
)
{
for
(
i
=
0
;
i
<
this
->
bss_cnt
;
i
++
)
{
if
(
!
memcmp
(
this
->
bss_set
[
i
].
bssid
,
sig
.
bssid
,
ETH_ALEN
))
{
matchflag
=
0
;
break
;
}
}
}
if
(
matchflag
&&
(
i
<
20
))
{
memcpy
(
&
this
->
bss_set
[
i
].
beacon_period
,
&
sig
.
beacon_period
,
73
);
this
->
bss_cnt
++
;
this
->
rssi
=
sig
.
rssi
;
}
}
}
else
if
(
sig
.
status
==
WL3501_STATUS_TIMEOUT
)
{
dprintk
(
3
,
"timeout"
);
this
->
join_sta_bss
=
0
;
for
(
i
=
this
->
join_sta_bss
;
i
<
this
->
bss_cnt
;
i
++
)
if
(
!
wl3501_mgmt_join
(
this
,
i
))
break
;
this
->
join_sta_bss
=
i
;
if
(
this
->
join_sta_bss
==
this
->
bss_cnt
)
{
if
(
this
->
net_type
==
IW_MODE_INFRA
)
wl3501_mgmt_scan
(
this
,
100
);
else
{
this
->
adhoc_times
++
;
if
(
this
->
adhoc_times
>
WL3501_MAX_ADHOC_TRIES
)
wl3501_mgmt_start
(
this
);
else
wl3501_mgmt_scan
(
this
,
100
);
}
}
}
}
/**
* wl3501_block_interrupt - Mask interrupt from SUTRO
* @this - card
*
* Mask interrupt from SUTRO. (i.e. SUTRO cannot interrupt the HOST)
* Return: 1 if interrupt is originally enabled
*/
static
int
wl3501_block_interrupt
(
struct
wl3501_card
*
this
)
{
u8
old
=
inb
(
this
->
base_addr
+
WL3501_NIC_GCR
);
u8
new
=
old
&
(
~
(
WL3501_GCR_ECINT
|
WL3501_GCR_INT2EC
|
WL3501_GCR_ENECINT
));
wl3501_outb
(
new
,
this
->
base_addr
+
WL3501_NIC_GCR
);
return
old
&
WL3501_GCR_ENECINT
;
}
/**
* wl3501_unblock_interrupt - Enable interrupt from SUTRO
* @this - card
*
* Enable interrupt from SUTRO. (i.e. SUTRO can interrupt the HOST)
* Return: 1 if interrupt is originally enabled
*/
static
int
wl3501_unblock_interrupt
(
struct
wl3501_card
*
this
)
{
u8
old
=
inb
(
this
->
base_addr
+
WL3501_NIC_GCR
);
u8
new
=
(
old
&
~
(
WL3501_GCR_ECINT
|
WL3501_GCR_INT2EC
))
|
WL3501_GCR_ENECINT
;
wl3501_outb
(
new
,
this
->
base_addr
+
WL3501_NIC_GCR
);
return
old
&
WL3501_GCR_ENECINT
;
}
/**
* wl3501_receive - Receive data from Receive Queue.
*
* Receive data from Receive Queue.
*
* @this: card
* @bf: address of host
* @size: size of buffer.
*/
static
u16
wl3501_receive
(
struct
wl3501_card
*
this
,
u8
*
bf
,
u16
size
)
{
u16
next_addr
,
next_addr1
;
u8
*
data
=
bf
+
12
;
size
-=
12
;
wl3501_get_from_wla
(
this
,
this
->
start_seg
+
2
,
&
next_addr
,
sizeof
(
next_addr
));
if
(
size
>
WL3501_BLKSZ
-
sizeof
(
struct
wl3501_rx_hdr
))
{
wl3501_get_from_wla
(
this
,
this
->
start_seg
+
sizeof
(
struct
wl3501_rx_hdr
),
data
,
WL3501_BLKSZ
-
sizeof
(
struct
wl3501_rx_hdr
));
size
-=
WL3501_BLKSZ
-
sizeof
(
struct
wl3501_rx_hdr
);
data
+=
WL3501_BLKSZ
-
sizeof
(
struct
wl3501_rx_hdr
);
}
else
{
wl3501_get_from_wla
(
this
,
this
->
start_seg
+
sizeof
(
struct
wl3501_rx_hdr
),
data
,
size
);
size
=
0
;
}
while
(
size
>
0
)
{
if
(
size
>
WL3501_BLKSZ
-
5
)
{
wl3501_get_from_wla
(
this
,
next_addr
+
5
,
data
,
WL3501_BLKSZ
-
5
);
size
-=
WL3501_BLKSZ
-
5
;
data
+=
WL3501_BLKSZ
-
5
;
wl3501_get_from_wla
(
this
,
next_addr
+
2
,
&
next_addr1
,
sizeof
(
next_addr1
));
next_addr
=
next_addr1
;
}
else
{
wl3501_get_from_wla
(
this
,
next_addr
+
5
,
data
,
size
);
size
=
0
;
}
}
return
0
;
}
static
void
wl3501_esbq_req_free
(
struct
wl3501_card
*
this
)
{
u8
tmp
;
u16
addr
;
if
(
this
->
esbq_req_head
==
this
->
esbq_req_tail
)
goto
out
;
wl3501_get_from_wla
(
this
,
this
->
esbq_req_tail
+
3
,
&
tmp
,
sizeof
(
tmp
));
if
(
!
(
tmp
&
0x80
))
goto
out
;
wl3501_get_from_wla
(
this
,
this
->
esbq_req_tail
,
&
addr
,
sizeof
(
addr
));
wl3501_free_tx_buffer
(
this
,
addr
);
this
->
esbq_req_tail
+=
4
;
if
(
this
->
esbq_req_tail
>=
this
->
esbq_req_end
)
this
->
esbq_req_tail
=
this
->
esbq_req_start
;
out:
return
;
}
static
int
wl3501_esbq_confirm
(
struct
wl3501_card
*
this
)
{
u8
tmp
;
wl3501_get_from_wla
(
this
,
this
->
esbq_confirm
+
3
,
&
tmp
,
sizeof
(
tmp
));
return
tmp
&
0x80
;
}
static
void
wl3501_online
(
struct
net_device
*
dev
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
printk
(
KERN_INFO
"%s: Wireless LAN online. BSSID: "
"%02X %02X %02X %02X %02X %02X
\n
"
,
dev
->
name
,
this
->
bssid
[
0
],
this
->
bssid
[
1
],
this
->
bssid
[
2
],
this
->
bssid
[
3
],
this
->
bssid
[
4
],
this
->
bssid
[
5
]);
netif_wake_queue
(
dev
);
}
static
void
wl3501_esbq_confirm_done
(
struct
wl3501_card
*
this
)
{
u8
tmp
=
0
;
wl3501_set_to_wla
(
this
,
this
->
esbq_confirm
+
3
,
&
tmp
,
sizeof
(
tmp
));
this
->
esbq_confirm
+=
4
;
if
(
this
->
esbq_confirm
>=
this
->
esbq_confirm_end
)
this
->
esbq_confirm
=
this
->
esbq_confirm_start
;
}
static
int
wl3501_mgmt_auth
(
struct
wl3501_card
*
this
)
{
struct
wl3501_auth_req
sig
=
{
.
sig_id
=
WL3501_SIG_AUTH_REQ
,
.
type
=
WL3501_SYS_TYPE_OPEN
,
.
timeout
=
1000
,
};
dprintk
(
3
,
"entry"
);
memcpy
(
sig
.
mac_addr
,
this
->
bssid
,
ETH_ALEN
);
return
wl3501_esbq_exec
(
this
,
&
sig
,
sizeof
(
sig
));
}
static
int
wl3501_mgmt_association
(
struct
wl3501_card
*
this
)
{
struct
wl3501_assoc_req
sig
=
{
.
sig_id
=
WL3501_SIG_ASSOC_REQ
,
.
timeout
=
1000
,
.
listen_interval
=
5
,
.
cap_info
=
this
->
cap_info
,
};
dprintk
(
3
,
"entry"
);
memcpy
(
sig
.
mac_addr
,
this
->
bssid
,
ETH_ALEN
);
return
wl3501_esbq_exec
(
this
,
&
sig
,
sizeof
(
sig
));
}
static
void
wl3501_mgmt_join_confirm
(
struct
net_device
*
dev
,
u16
addr
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
struct
wl3501_join_confirm
sig
;
dprintk
(
3
,
"entry"
);
wl3501_get_from_wla
(
this
,
addr
,
&
sig
,
sizeof
(
sig
));
if
(
sig
.
status
==
WL3501_STATUS_SUCCESS
)
{
if
(
this
->
net_type
==
IW_MODE_INFRA
)
{
if
(
this
->
join_sta_bss
<
this
->
bss_cnt
)
{
const
int
i
=
this
->
join_sta_bss
;
memcpy
(
this
->
bssid
,
this
->
bss_set
[
i
].
bssid
,
ETH_ALEN
);
this
->
chan
=
this
->
bss_set
[
i
].
phy_pset
[
2
];
memcpy
(
this
->
keep_essid
,
this
->
bss_set
[
i
].
ssid
,
WL3501_ESSID_MAX_LEN
);
wl3501_mgmt_auth
(
this
);
}
}
else
{
const
int
i
=
this
->
join_sta_bss
;
memcpy
(
this
->
bssid
,
this
->
bss_set
[
i
].
bssid
,
ETH_ALEN
);
this
->
chan
=
this
->
bss_set
[
i
].
phy_pset
[
2
];
memcpy
(
this
->
keep_essid
,
this
->
bss_set
[
i
].
ssid
,
WL3501_ESSID_MAX_LEN
);
wl3501_online
(
dev
);
}
}
else
{
int
i
;
this
->
join_sta_bss
++
;
for
(
i
=
this
->
join_sta_bss
;
i
<
this
->
bss_cnt
;
i
++
)
if
(
!
wl3501_mgmt_join
(
this
,
i
))
break
;
this
->
join_sta_bss
=
i
;
if
(
this
->
join_sta_bss
==
this
->
bss_cnt
)
{
if
(
this
->
net_type
==
IW_MODE_INFRA
)
wl3501_mgmt_scan
(
this
,
100
);
else
{
this
->
adhoc_times
++
;
if
(
this
->
adhoc_times
>
WL3501_MAX_ADHOC_TRIES
)
wl3501_mgmt_start
(
this
);
else
wl3501_mgmt_scan
(
this
,
100
);
}
}
}
}
static
inline
void
wl3501_alarm_interrupt
(
struct
net_device
*
dev
,
struct
wl3501_card
*
this
)
{
if
(
this
->
net_type
==
IW_MODE_INFRA
)
{
printk
(
KERN_INFO
"Wireless LAN offline
\n
"
);
netif_stop_queue
(
dev
);
wl3501_mgmt_resync
(
this
);
}
}
static
inline
void
wl3501_md_confirm_interrupt
(
struct
net_device
*
dev
,
struct
wl3501_card
*
this
,
u16
addr
)
{
struct
wl3501_md_confirm
sig
;
dprintk
(
3
,
"entry"
);
wl3501_get_from_wla
(
this
,
addr
,
&
sig
,
sizeof
(
sig
));
wl3501_free_tx_buffer
(
this
,
sig
.
data
);
if
(
netif_queue_stopped
(
dev
))
netif_wake_queue
(
dev
);
}
static
inline
void
wl3501_md_ind_interrupt
(
struct
net_device
*
dev
,
struct
wl3501_card
*
this
,
u16
addr
)
{
struct
wl3501_md_ind
sig
;
struct
sk_buff
*
skb
;
u8
rssi
,
addr4
[
ETH_ALEN
];
u16
pkt_len
;
wl3501_get_from_wla
(
this
,
addr
,
&
sig
,
sizeof
(
sig
));
this
->
start_seg
=
sig
.
data
;
wl3501_get_from_wla
(
this
,
sig
.
data
+
offsetof
(
struct
wl3501_rx_hdr
,
rssi
),
&
rssi
,
sizeof
(
rssi
));
this
->
rssi
=
rssi
<=
63
?
(
rssi
*
100
)
/
64
:
255
;
wl3501_get_from_wla
(
this
,
sig
.
data
+
offsetof
(
struct
wl3501_rx_hdr
,
addr4
),
&
addr4
,
sizeof
(
addr4
));
if
(
!
(
addr4
[
0
]
==
0xAA
&&
addr4
[
1
]
==
0xAA
&&
addr4
[
2
]
==
0x03
&&
addr4
[
4
]
==
0x00
))
{
printk
(
KERN_INFO
"Insupported packet type!
\n
"
);
return
;
}
pkt_len
=
sig
.
size
+
12
-
24
-
4
-
6
;
skb
=
dev_alloc_skb
(
pkt_len
+
5
);
if
(
!
skb
)
{
printk
(
KERN_WARNING
"%s: Can't alloc a sk_buff of size %d.
\n
"
,
dev
->
name
,
pkt_len
);
this
->
stats
.
rx_dropped
++
;
}
else
{
skb
->
dev
=
dev
;
skb_reserve
(
skb
,
2
);
/* IP headers on 16 bytes boundaries */
eth_copy_and_sum
(
skb
,
(
unsigned
char
*
)
&
sig
.
daddr
,
12
,
0
);
wl3501_receive
(
this
,
skb
->
data
,
pkt_len
);
skb_put
(
skb
,
pkt_len
);
skb
->
protocol
=
eth_type_trans
(
skb
,
dev
);
dev
->
last_rx
=
jiffies
;
this
->
stats
.
rx_packets
++
;
this
->
stats
.
rx_bytes
+=
skb
->
len
;
netif_rx
(
skb
);
}
}
static
inline
void
wl3501_get_confirm_interrupt
(
struct
wl3501_card
*
this
,
u16
addr
,
void
*
sig
,
int
size
)
{
dprintk
(
3
,
"entry"
);
wl3501_get_from_wla
(
this
,
addr
,
&
this
->
sig_get_confirm
,
sizeof
(
this
->
sig_get_confirm
));
wake_up
(
&
this
->
wait
);
}
static
inline
void
wl3501_start_confirm_interrupt
(
struct
net_device
*
dev
,
struct
wl3501_card
*
this
,
u16
addr
)
{
struct
wl3501_start_confirm
sig
;
dprintk
(
3
,
"entry"
);
wl3501_get_from_wla
(
this
,
addr
,
&
sig
,
sizeof
(
sig
));
if
(
sig
.
status
==
WL3501_STATUS_SUCCESS
)
netif_wake_queue
(
dev
);
}
static
inline
void
wl3501_assoc_confirm_interrupt
(
struct
net_device
*
dev
,
u16
addr
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
struct
wl3501_assoc_confirm
sig
;
dprintk
(
3
,
"entry"
);
wl3501_get_from_wla
(
this
,
addr
,
&
sig
,
sizeof
(
sig
));
if
(
sig
.
status
==
WL3501_STATUS_SUCCESS
)
wl3501_online
(
dev
);
}
static
inline
void
wl3501_auth_confirm_interrupt
(
struct
wl3501_card
*
this
,
u16
addr
)
{
struct
wl3501_auth_confirm
sig
;
dprintk
(
3
,
"entry"
);
wl3501_get_from_wla
(
this
,
addr
,
&
sig
,
sizeof
(
sig
));
if
(
sig
.
status
==
WL3501_STATUS_SUCCESS
)
wl3501_mgmt_association
(
this
);
else
wl3501_mgmt_resync
(
this
);
}
static
inline
void
wl3501_rx_interrupt
(
struct
net_device
*
dev
)
{
int
morepkts
;
u16
addr
;
u8
sig_id
;
struct
wl3501_card
*
this
=
dev
->
priv
;
dprintk
(
3
,
"entry"
);
loop:
morepkts
=
0
;
if
(
!
wl3501_esbq_confirm
(
this
))
goto
free
;
wl3501_get_from_wla
(
this
,
this
->
esbq_confirm
,
&
addr
,
sizeof
(
addr
));
wl3501_get_from_wla
(
this
,
addr
+
2
,
&
sig_id
,
sizeof
(
sig_id
));
switch
(
sig_id
)
{
case
WL3501_SIG_DEAUTH_IND
:
case
WL3501_SIG_DISASSOC_IND
:
case
WL3501_SIG_ALARM
:
wl3501_alarm_interrupt
(
dev
,
this
);
break
;
case
WL3501_SIG_MD_CONFIRM
:
wl3501_md_confirm_interrupt
(
dev
,
this
,
addr
);
break
;
case
WL3501_SIG_MD_IND
:
wl3501_md_ind_interrupt
(
dev
,
this
,
addr
);
break
;
case
WL3501_SIG_GET_CONFIRM
:
wl3501_get_confirm_interrupt
(
this
,
addr
,
&
this
->
sig_get_confirm
,
sizeof
(
this
->
sig_get_confirm
));
break
;
case
WL3501_SIG_PWR_MGMT_CONFIRM
:
wl3501_get_confirm_interrupt
(
this
,
addr
,
&
this
->
sig_pwr_mgmt_confirm
,
sizeof
(
this
->
sig_pwr_mgmt_confirm
));
break
;
case
WL3501_SIG_START_CONFIRM
:
wl3501_start_confirm_interrupt
(
dev
,
this
,
addr
);
break
;
case
WL3501_SIG_SCAN_CONFIRM
:
wl3501_mgmt_scan_confirm
(
this
,
addr
);
break
;
case
WL3501_SIG_JOIN_CONFIRM
:
wl3501_mgmt_join_confirm
(
dev
,
addr
);
break
;
case
WL3501_SIG_ASSOC_CONFIRM
:
wl3501_assoc_confirm_interrupt
(
dev
,
addr
);
break
;
case
WL3501_SIG_AUTH_CONFIRM
:
wl3501_auth_confirm_interrupt
(
this
,
addr
);
break
;
case
WL3501_SIG_RESYNC_CONFIRM
:
wl3501_mgmt_resync
(
this
);
/* FIXME: should be resync_confirm */
break
;
}
wl3501_esbq_confirm_done
(
this
);
morepkts
=
1
;
/* free request if necessary */
free:
wl3501_esbq_req_free
(
this
);
if
(
morepkts
)
goto
loop
;
}
static
inline
void
wl3501_ack_interrupt
(
struct
wl3501_card
*
this
)
{
wl3501_outb
(
WL3501_GCR_ECINT
,
this
->
base_addr
+
WL3501_NIC_GCR
);
}
/**
* wl3501_interrupt - Hardware interrupt from card.
* @irq - Interrupt number
* @dev_id - net_device
* @regs - registers
*
* We must acknowledge the interrupt as soon as possible, and block the
* interrupt from the same card immediately to prevent re-entry.
*
* Before accessing the Control_Status_Block, we must lock SUTRO first.
* On the other hand, to prevent SUTRO from malfunctioning, we must
* unlock the SUTRO as soon as possible.
*/
static
irqreturn_t
wl3501_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
struct
net_device
*
dev
=
(
struct
net_device
*
)
dev_id
;
struct
wl3501_card
*
this
;
int
handled
=
1
;
if
(
!
dev
)
goto
unknown
;
this
=
dev
->
priv
;
spin_lock
(
&
this
->
lock
);
wl3501_ack_interrupt
(
this
);
wl3501_block_interrupt
(
this
);
wl3501_rx_interrupt
(
dev
);
wl3501_unblock_interrupt
(
this
);
spin_unlock
(
&
this
->
lock
);
out:
return
IRQ_RETVAL
(
handled
);
unknown:
handled
=
0
;
printk
(
KERN_ERR
"%s: irq %d for unknown device.
\n
"
,
__FUNCTION__
,
irq
);
goto
out
;
}
static
int
wl3501_reset_board
(
struct
wl3501_card
*
this
)
{
u8
tmp
=
0
;
int
i
,
rc
=
0
;
/* Coreset */
wl3501_outb_p
(
WL3501_GCR_CORESET
,
this
->
base_addr
+
WL3501_NIC_GCR
);
wl3501_outb_p
(
0
,
this
->
base_addr
+
WL3501_NIC_GCR
);
wl3501_outb_p
(
WL3501_GCR_CORESET
,
this
->
base_addr
+
WL3501_NIC_GCR
);
/* Reset SRAM 0x480 to zero */
wl3501_set_to_wla
(
this
,
0x480
,
&
tmp
,
sizeof
(
tmp
));
/* Start up */
wl3501_outb_p
(
0
,
this
->
base_addr
+
WL3501_NIC_GCR
);
WL3501_NOPLOOP
(
1024
*
50
);
wl3501_unblock_interrupt
(
this
);
/* acme: was commented */
/* Polling Self_Test_Status */
for
(
i
=
0
;
i
<
10000
;
i
++
)
{
wl3501_get_from_wla
(
this
,
0x480
,
&
tmp
,
sizeof
(
tmp
));
if
(
tmp
==
'W'
)
{
/* firmware complete all test successfully */
tmp
=
'A'
;
wl3501_set_to_wla
(
this
,
0x480
,
&
tmp
,
sizeof
(
tmp
));
goto
out
;
}
WL3501_NOPLOOP
(
10
);
}
printk
(
KERN_WARNING
"%s: failed to reset the board!
\n
"
,
__FUNCTION__
);
rc
=
-
ENODEV
;
out:
return
rc
;
}
static
int
wl3501_init_firmware
(
struct
wl3501_card
*
this
)
{
u16
ptr
,
next
;
int
rc
=
wl3501_reset_board
(
this
);
if
(
rc
)
goto
fail
;
this
->
card_name
[
0
]
=
'\0'
;
wl3501_get_from_wla
(
this
,
0x1a00
,
this
->
card_name
,
sizeof
(
this
->
card_name
));
this
->
card_name
[
sizeof
(
this
->
card_name
)
-
1
]
=
'\0'
;
this
->
firmware_date
[
0
]
=
'\0'
;
wl3501_get_from_wla
(
this
,
0x1a40
,
this
->
firmware_date
,
sizeof
(
this
->
firmware_date
));
this
->
firmware_date
[
sizeof
(
this
->
firmware_date
)
-
1
]
=
'\0'
;
/* Switch to SRAM Page 0 */
wl3501_switch_page
(
this
,
WL3501_BSS_SPAGE0
);
/* Read parameter from card */
wl3501_get_from_wla
(
this
,
0x482
,
&
this
->
esbq_req_start
,
2
);
wl3501_get_from_wla
(
this
,
0x486
,
&
this
->
esbq_req_end
,
2
);
wl3501_get_from_wla
(
this
,
0x488
,
&
this
->
esbq_confirm_start
,
2
);
wl3501_get_from_wla
(
this
,
0x48c
,
&
this
->
esbq_confirm_end
,
2
);
wl3501_get_from_wla
(
this
,
0x48e
,
&
this
->
tx_buffer_head
,
2
);
wl3501_get_from_wla
(
this
,
0x492
,
&
this
->
tx_buffer_size
,
2
);
this
->
esbq_req_tail
=
this
->
esbq_req_head
=
this
->
esbq_req_start
;
this
->
esbq_req_end
+=
this
->
esbq_req_start
;
this
->
esbq_confirm
=
this
->
esbq_confirm_start
;
this
->
esbq_confirm_end
+=
this
->
esbq_confirm_start
;
/* Initial Tx Buffer */
this
->
tx_buffer_cnt
=
1
;
ptr
=
this
->
tx_buffer_head
;
next
=
ptr
+
WL3501_BLKSZ
;
while
((
next
-
this
->
tx_buffer_head
)
<
this
->
tx_buffer_size
)
{
this
->
tx_buffer_cnt
++
;
wl3501_set_to_wla
(
this
,
ptr
,
&
next
,
sizeof
(
next
));
ptr
=
next
;
next
=
ptr
+
WL3501_BLKSZ
;
}
rc
=
0
;
next
=
0
;
wl3501_set_to_wla
(
this
,
ptr
,
&
next
,
sizeof
(
next
));
this
->
tx_buffer_tail
=
ptr
;
out:
return
rc
;
fail:
printk
(
KERN_WARNING
"%s: failed!
\n
"
,
__FUNCTION__
);
goto
out
;
}
static
int
wl3501_close
(
struct
net_device
*
dev
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
int
rc
=
-
ENODEV
;
unsigned
long
flags
;
dev_link_t
*
link
;
spin_lock_irqsave
(
&
this
->
lock
,
flags
);
/* Check if the device is in wl3501_dev_list */
for
(
link
=
wl3501_dev_list
;
link
;
link
=
link
->
next
)
if
(
link
->
priv
==
dev
)
break
;
if
(
!
link
)
goto
out
;
link
->
open
--
;
/* Stop wl3501_hard_start_xmit() from now on */
netif_stop_queue
(
dev
);
wl3501_ack_interrupt
(
this
);
/* Mask interrupts from the SUTRO */
wl3501_block_interrupt
(
this
);
if
(
link
->
state
&
DEV_STALE_CONFIG
)
{
link
->
release
.
expires
=
jiffies
+
WL3501_RELEASE_TIMEOUT
;
link
->
state
|=
DEV_RELEASE_PENDING
;
add_timer
(
&
link
->
release
);
}
rc
=
0
;
printk
(
KERN_INFO
"%s: WL3501 closed
\n
"
,
dev
->
name
);
out:
spin_unlock_irqrestore
(
&
this
->
lock
,
flags
);
return
rc
;
}
/**
* wl3501_reset - Reset the SUTRO.
* @dev - network device
*
* It is almost the same as wl3501_open(). In fact, we may just wl3501_close()
* and wl3501_open() again, but I wouldn't like to free_irq() when the driver
* is running. It seems to be dangerous.
*/
static
int
wl3501_reset
(
struct
net_device
*
dev
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
int
rc
=
-
ENODEV
;
wl3501_block_interrupt
(
this
);
if
(
wl3501_init_firmware
(
this
))
{
printk
(
KERN_WARNING
"%s: Can't initialize Firmware!
\n
"
,
dev
->
name
);
/* Free IRQ, and mark IRQ as unused */
free_irq
(
dev
->
irq
,
dev
);
goto
out
;
}
/*
* Queue has to be started only when the Card is Started
*/
netif_stop_queue
(
dev
);
this
->
adhoc_times
=
0
;
wl3501_ack_interrupt
(
this
);
wl3501_unblock_interrupt
(
this
);
wl3501_mgmt_scan
(
this
,
100
);
dprintk
(
1
,
"%s: device reset"
,
dev
->
name
);
rc
=
0
;
out:
return
rc
;
}
static
void
wl3501_tx_timeout
(
struct
net_device
*
dev
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
struct
net_device_stats
*
stats
=
&
this
->
stats
;
unsigned
long
flags
;
int
rc
;
stats
->
tx_errors
++
;
spin_lock_irqsave
(
&
this
->
lock
,
flags
);
rc
=
wl3501_reset
(
dev
);
spin_unlock_irqrestore
(
&
this
->
lock
,
flags
);
if
(
rc
)
printk
(
KERN_ERR
"%s: Error %d resetting card on Tx timeout!
\n
"
,
dev
->
name
,
rc
);
else
{
dev
->
trans_start
=
jiffies
;
netif_wake_queue
(
dev
);
}
}
/*
* Return : 0 - OK
* 1 - Could not transmit (dev_queue_xmit will queue it)
* and try to sent it later
*/
static
int
wl3501_hard_start_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
int
enabled
,
rc
;
struct
wl3501_card
*
this
=
dev
->
priv
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
this
->
lock
,
flags
);
enabled
=
wl3501_block_interrupt
(
this
);
dev
->
trans_start
=
jiffies
;
rc
=
wl3501_send_pkt
(
this
,
skb
->
data
,
skb
->
len
);
if
(
enabled
)
wl3501_unblock_interrupt
(
this
);
if
(
rc
)
{
++
this
->
stats
.
tx_dropped
;
netif_stop_queue
(
dev
);
}
else
{
++
this
->
stats
.
tx_packets
;
this
->
stats
.
tx_bytes
+=
skb
->
len
;
kfree_skb
(
skb
);
if
(
this
->
tx_buffer_cnt
<
2
)
netif_stop_queue
(
dev
);
}
spin_unlock_irqrestore
(
&
this
->
lock
,
flags
);
return
rc
;
}
static
int
wl3501_open
(
struct
net_device
*
dev
)
{
int
rc
=
-
ENODEV
;
struct
wl3501_card
*
this
=
dev
->
priv
;
unsigned
long
flags
;
dev_link_t
*
link
;
spin_lock_irqsave
(
&
this
->
lock
,
flags
);
/* Check if the device is in wl3501_dev_list */
for
(
link
=
wl3501_dev_list
;
link
;
link
=
link
->
next
)
if
(
link
->
priv
==
dev
)
break
;
if
(
!
DEV_OK
(
link
))
goto
out
;
netif_device_attach
(
dev
);
link
->
open
++
;
/* Initial WL3501 firmware */
dprintk
(
1
,
"%s: Initialize WL3501 firmware..."
,
dev
->
name
);
if
(
wl3501_init_firmware
(
this
))
goto
fail
;
/* Initial device variables */
this
->
adhoc_times
=
0
;
/* Acknowledge Interrupt, for cleaning last state */
wl3501_ack_interrupt
(
this
);
/* Enable interrupt from card after all */
wl3501_unblock_interrupt
(
this
);
wl3501_mgmt_scan
(
this
,
100
);
rc
=
0
;
dprintk
(
1
,
"%s: WL3501 opened"
,
dev
->
name
);
printk
(
KERN_INFO
"%s: Card Name: %s
\n
"
"%s: Firmware Date: %s
\n
"
,
dev
->
name
,
this
->
card_name
,
dev
->
name
,
this
->
firmware_date
);
out:
spin_unlock_irqrestore
(
&
this
->
lock
,
flags
);
return
rc
;
fail:
printk
(
KERN_WARNING
"%s: Can't initialize firmware!
\n
"
,
dev
->
name
);
goto
out
;
}
/**
* wl3501_init - "initialize" board
* @dev - network device
*
* We never need to do anything when a wl3501 device is "initialized" by the net
* software, because we only register already-found cards.
*/
static
int
wl3501_init
(
struct
net_device
*
dev
)
{
return
0
;
}
struct
net_device_stats
*
wl3501_get_stats
(
struct
net_device
*
dev
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
return
&
this
->
stats
;
}
struct
iw_statistics
*
wl3501_get_wireless_stats
(
struct
net_device
*
dev
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
struct
iw_statistics
*
wstats
=
&
this
->
wstats
;
u32
value
;
/* size checked: it is u32 */
memset
(
wstats
,
0
,
sizeof
(
*
wstats
));
wstats
->
status
=
netif_running
(
dev
);
if
(
!
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_WEP_ICV_ERROR_COUNT
,
&
value
,
sizeof
(
value
)))
wstats
->
discard
.
code
+=
value
;
if
(
!
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_WEP_UNDECRYPTABLE_COUNT
,
&
value
,
sizeof
(
value
)))
wstats
->
discard
.
code
+=
value
;
if
(
!
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_WEP_EXCLUDED_COUNT
,
&
value
,
sizeof
(
value
)))
wstats
->
discard
.
code
+=
value
;
if
(
!
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_RETRY_COUNT
,
&
value
,
sizeof
(
value
)))
wstats
->
discard
.
retries
=
value
;
if
(
!
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_FAILED_COUNT
,
&
value
,
sizeof
(
value
)))
wstats
->
discard
.
misc
+=
value
;
if
(
!
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_RTS_FAILURE_COUNT
,
&
value
,
sizeof
(
value
)))
wstats
->
discard
.
misc
+=
value
;
if
(
!
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_ACK_FAILURE_COUNT
,
&
value
,
sizeof
(
value
)))
wstats
->
discard
.
misc
+=
value
;
if
(
!
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_FRAME_DUPLICATE_COUNT
,
&
value
,
sizeof
(
value
)))
wstats
->
discard
.
misc
+=
value
;
return
wstats
;
}
static
inline
int
wl3501_ethtool_ioctl
(
struct
net_device
*
dev
,
void
*
uaddr
)
{
u32
ethcmd
;
int
rc
=
-
EFAULT
;
if
(
copy_from_user
(
&
ethcmd
,
uaddr
,
sizeof
(
ethcmd
)))
goto
out
;
switch
(
ethcmd
)
{
case
ETHTOOL_GDRVINFO
:
{
struct
ethtool_drvinfo
info
=
{
.
cmd
=
ETHTOOL_GDRVINFO
,
};
strlcpy
(
info
.
driver
,
wl3501_dev_info
,
sizeof
(
info
.
driver
));
rc
=
copy_to_user
(
uaddr
,
&
info
,
sizeof
(
info
))
?
-
EFAULT
:
1
;
}
default:
rc
=
-
EOPNOTSUPP
;
break
;
}
out:
return
rc
;
}
/**
* wl3501_ioctl - Perform IOCTL call functions
* @dev - network device
* @ifreq - request
* @cmd - command
*
* Perform IOCTL call functions here. Some are privileged operations and the
* effective uid is checked in those cases.
*
* This part is optional. Needed only if you want to run wlu (unix version).
*
* CAUTION: To prevent interrupted by wl3501_interrupt() and timer-based
* wl3501_hard_start_xmit() from other interrupts, this should be run
* single-threaded.
*/
static
int
wl3501_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
)
{
int
rc
=
-
ENODEV
;
if
(
netif_device_present
(
dev
))
{
rc
=
-
EOPNOTSUPP
;
if
(
cmd
==
SIOCETHTOOL
)
rc
=
wl3501_ethtool_ioctl
(
dev
,
(
void
*
)
rq
->
ifr_data
);
}
return
rc
;
}
/**
* wl3501_detach - deletes a driver "instance"
* @link - FILL_IN
*
* This deletes a driver "instance". The device is de-registered with Card
* Services. If it has been released, all local data structures are freed.
* Otherwise, the structures will be freed when the device is released.
*/
static
void
wl3501_detach
(
dev_link_t
*
link
)
{
dev_link_t
**
linkp
;
/* Locate device structure */
for
(
linkp
=
&
wl3501_dev_list
;
*
linkp
;
linkp
=
&
(
*
linkp
)
->
next
)
if
(
*
linkp
==
link
)
break
;
if
(
!*
linkp
)
goto
out
;
/* If the device is currently configured and active, we won't actually
* delete it yet. Instead, it is marked so that when the release()
* function is called, that will trigger a proper detach(). */
if
(
link
->
state
&
DEV_CONFIG
)
{
#ifdef PCMCIA_DEBUG
printk
(
KERN_DEBUG
"wl3501_cs: detach postponed, '%s' "
"still locked
\n
"
,
link
->
dev
->
dev_name
);
#endif
link
->
state
|=
DEV_STALE_LINK
;
goto
out
;
}
/* Break the link with Card Services */
if
(
link
->
handle
)
CardServices
(
DeregisterClient
,
link
->
handle
);
/* Unlink device structure, free pieces */
*
linkp
=
link
->
next
;
if
(
link
->
priv
)
kfree
(
link
->
priv
);
kfree
(
link
);
out:
return
;
}
/**
* wl3501_flush_stale_links - Remove zombie instances
*
* Remove zombie instances (card removed, detach pending)
*/
static
void
wl3501_flush_stale_links
(
void
)
{
dev_link_t
*
link
,
*
next
;
for
(
link
=
wl3501_dev_list
;
link
;
link
=
next
)
{
next
=
link
->
next
;
if
(
link
->
state
&
DEV_STALE_LINK
)
wl3501_detach
(
link
);
}
}
static
int
wl3501_get_name
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
strlcpy
(
wrqu
->
name
,
"IEEE 802.11-DS"
,
sizeof
(
wrqu
->
name
));
return
0
;
}
static
int
wl3501_set_freq
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
int
channel
=
wrqu
->
freq
.
m
;
int
rc
=
-
EINVAL
;
if
(
iw_valid_channel
(
this
->
reg_domain
,
channel
))
{
this
->
chan
=
channel
;
rc
=
wl3501_reset
(
dev
);
}
return
rc
;
}
static
int
wl3501_get_freq
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
wrqu
->
freq
.
m
=
wl3501_chan2freq
[
this
->
chan
-
1
]
*
100000
;
wrqu
->
freq
.
e
=
1
;
return
0
;
}
static
int
wl3501_set_mode
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
int
rc
=
-
EINVAL
;
if
(
wrqu
->
mode
==
IW_MODE_INFRA
||
wrqu
->
mode
==
IW_MODE_ADHOC
||
wrqu
->
mode
==
IW_MODE_AUTO
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
this
->
net_type
=
wrqu
->
mode
;
rc
=
wl3501_reset
(
dev
);
}
return
rc
;
}
static
int
wl3501_get_mode
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
wrqu
->
mode
=
this
->
net_type
;
return
0
;
}
static
int
wl3501_get_sens
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
wrqu
->
sens
.
value
=
this
->
rssi
;
wrqu
->
sens
.
disabled
=
!
wrqu
->
sens
.
value
;
wrqu
->
sens
.
fixed
=
1
;
return
0
;
}
static
int
wl3501_get_range
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
struct
iw_range
*
range
=
(
struct
iw_range
*
)
extra
;
/* Set the length (very important for backward compatibility) */
wrqu
->
data
.
length
=
sizeof
(
*
range
);
/* Set all the info we don't care or don't know about to zero */
memset
(
range
,
0
,
sizeof
(
*
range
));
/* Set the Wireless Extension versions */
range
->
we_version_compiled
=
WIRELESS_EXT
;
range
->
we_version_source
=
1
;
range
->
throughput
=
2
*
1000
*
1000
;
/* ~2 Mb/s */
/* FIXME: study the code to fill in more fields... */
return
0
;
}
static
int
wl3501_set_wap
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
static
const
u8
bcast
[
ETH_ALEN
]
=
{
255
,
255
,
255
,
255
,
255
,
255
};
int
rc
=
-
EINVAL
;
/* FIXME: we support other ARPHRDs...*/
if
(
wrqu
->
ap_addr
.
sa_family
!=
ARPHRD_ETHER
)
goto
out
;
if
(
!
memcmp
(
bcast
,
wrqu
->
ap_addr
.
sa_data
,
ETH_ALEN
))
{
/* FIXME: rescan? */
}
else
memcpy
(
this
->
bssid
,
wrqu
->
ap_addr
.
sa_data
,
ETH_ALEN
);
/* FIXME: rescan? deassoc & scan? */
rc
=
0
;
out:
return
rc
;
}
static
int
wl3501_get_wap
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
wrqu
->
ap_addr
.
sa_family
=
ARPHRD_ETHER
;
memcpy
(
wrqu
->
ap_addr
.
sa_data
,
this
->
bssid
,
ETH_ALEN
);
return
0
;
}
static
int
wl3501_set_essid
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
int
rc
=
0
;
if
(
wrqu
->
data
.
flags
)
{
strlcpy
(
this
->
essid
+
2
,
extra
,
min_t
(
u16
,
wrqu
->
data
.
length
,
IW_ESSID_MAX_SIZE
));
rc
=
wl3501_reset
(
dev
);
}
return
rc
;
}
static
int
wl3501_get_essid
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
this
->
lock
,
flags
);
wrqu
->
essid
.
flags
=
1
;
wrqu
->
essid
.
length
=
IW_ESSID_MAX_SIZE
;
strlcpy
(
extra
,
this
->
essid
+
2
,
IW_ESSID_MAX_SIZE
);
spin_unlock_irqrestore
(
&
this
->
lock
,
flags
);
return
0
;
}
static
int
wl3501_set_nick
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
if
(
wrqu
->
data
.
length
>
sizeof
(
this
->
nick
))
return
-
E2BIG
;
strlcpy
(
this
->
nick
,
extra
,
wrqu
->
data
.
length
);
return
0
;
}
static
int
wl3501_get_nick
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
struct
wl3501_card
*
this
=
dev
->
priv
;
strlcpy
(
extra
,
this
->
nick
,
32
);
wrqu
->
data
.
length
=
strlen
(
extra
);
return
0
;
}
static
int
wl3501_get_rate
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
/*
* FIXME: have to see from where to get this info, perhaps this card
* works at 1 Mbit/s too... for now leave at 2 Mbit/s that is the most
* common with the Planet Access Points. -acme
*/
wrqu
->
bitrate
.
value
=
2000000
;
wrqu
->
bitrate
.
fixed
=
1
;
return
0
;
}
static
int
wl3501_get_rts_threshold
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
u16
threshold
;
/* size checked: it is u16 */
struct
wl3501_card
*
this
=
dev
->
priv
;
int
rc
=
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_RTS_THRESHOLD
,
&
threshold
,
sizeof
(
threshold
));
if
(
!
rc
)
{
wrqu
->
rts
.
value
=
threshold
;
wrqu
->
rts
.
disabled
=
threshold
>=
2347
;
wrqu
->
rts
.
fixed
=
1
;
}
return
rc
;
}
static
int
wl3501_get_frag_threshold
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
u16
threshold
;
/* size checked: it is u16 */
struct
wl3501_card
*
this
=
dev
->
priv
;
int
rc
=
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_FRAG_THRESHOLD
,
&
threshold
,
sizeof
(
threshold
));
if
(
!
rc
)
{
wrqu
->
frag
.
value
=
threshold
;
wrqu
->
frag
.
disabled
=
threshold
>=
2346
;
wrqu
->
frag
.
fixed
=
1
;
}
return
rc
;
}
static
int
wl3501_get_txpow
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
u16
txpow
;
struct
wl3501_card
*
this
=
dev
->
priv
;
int
rc
=
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_CURRENT_TX_PWR_LEVEL
,
&
txpow
,
sizeof
(
txpow
));
if
(
!
rc
)
{
wrqu
->
txpower
.
value
=
txpow
;
wrqu
->
txpower
.
disabled
=
0
;
/*
* From the MIB values I think this can be configurable,
* as it lists several tx power levels -acme
*/
wrqu
->
txpower
.
fixed
=
0
;
wrqu
->
txpower
.
flags
=
IW_TXPOW_MWATT
;
}
return
rc
;
}
static
int
wl3501_get_retry
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
u8
retry
;
/* size checked: it is u8 */
struct
wl3501_card
*
this
=
dev
->
priv
;
int
rc
=
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_LONG_RETRY_LIMIT
,
&
retry
,
sizeof
(
retry
));
if
(
rc
)
goto
out
;
if
(
wrqu
->
retry
.
flags
&
IW_RETRY_MAX
)
{
wrqu
->
retry
.
flags
=
IW_RETRY_LIMIT
|
IW_RETRY_MAX
;
goto
set_value
;
}
rc
=
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_SHORT_RETRY_LIMIT
,
&
retry
,
sizeof
(
retry
));
if
(
rc
)
goto
out
;
wrqu
->
retry
.
flags
=
IW_RETRY_LIMIT
|
IW_RETRY_MIN
;
set_value:
wrqu
->
retry
.
value
=
retry
;
wrqu
->
retry
.
disabled
=
0
;
out:
return
rc
;
}
static
int
wl3501_get_encode
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
u8
implemented
,
restricted
,
keys
[
100
],
len_keys
,
tocopy
;
struct
wl3501_card
*
this
=
dev
->
priv
;
int
rc
=
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_PRIV_OPT_IMPLEMENTED
,
&
implemented
,
sizeof
(
implemented
));
if
(
rc
)
goto
out
;
if
(
!
implemented
)
{
wrqu
->
encoding
.
flags
=
IW_ENCODE_DISABLED
;
goto
out
;
}
rc
=
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_EXCLUDE_UNENCRYPTED
,
&
restricted
,
sizeof
(
restricted
));
if
(
rc
)
goto
out
;
wrqu
->
encoding
.
flags
=
restricted
?
IW_ENCODE_RESTRICTED
:
IW_ENCODE_OPEN
;
rc
=
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_WEP_KEY_MAPPINGS_LEN
,
&
len_keys
,
sizeof
(
len_keys
));
if
(
rc
)
goto
out
;
rc
=
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_WEP_KEY_MAPPINGS
,
keys
,
len_keys
);
if
(
rc
)
goto
out
;
tocopy
=
min_t
(
u8
,
len_keys
,
wrqu
->
encoding
.
length
);
tocopy
=
min_t
(
u8
,
tocopy
,
100
);
wrqu
->
encoding
.
length
=
tocopy
;
memset
(
extra
,
0
,
tocopy
);
memcpy
(
extra
,
keys
,
tocopy
);
out:
return
rc
;
}
static
int
wl3501_get_power
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
u8
pwr_state
;
struct
wl3501_card
*
this
=
dev
->
priv
;
int
rc
=
wl3501_get_mib_value
(
this
,
WL3501_MIB_ATTR_CURRENT_PWR_STATE
,
&
pwr_state
,
sizeof
(
pwr_state
));
if
(
rc
)
goto
out
;
wrqu
->
power
.
disabled
=
!
pwr_state
;
wrqu
->
power
.
flags
=
IW_POWER_ON
;
out:
return
rc
;
}
static
const
iw_handler
wl3501_handler
[]
=
{
[
SIOCGIWNAME
-
SIOCIWFIRST
]
=
wl3501_get_name
,
[
SIOCSIWFREQ
-
SIOCIWFIRST
]
=
wl3501_set_freq
,
[
SIOCGIWFREQ
-
SIOCIWFIRST
]
=
wl3501_get_freq
,
[
SIOCSIWMODE
-
SIOCIWFIRST
]
=
wl3501_set_mode
,
[
SIOCGIWMODE
-
SIOCIWFIRST
]
=
wl3501_get_mode
,
[
SIOCGIWSENS
-
SIOCIWFIRST
]
=
wl3501_get_sens
,
[
SIOCGIWRANGE
-
SIOCIWFIRST
]
=
wl3501_get_range
,
[
SIOCSIWSPY
-
SIOCIWFIRST
]
=
iw_handler_set_spy
,
[
SIOCGIWSPY
-
SIOCIWFIRST
]
=
iw_handler_get_spy
,
[
SIOCSIWTHRSPY
-
SIOCIWFIRST
]
=
iw_handler_set_thrspy
,
[
SIOCGIWTHRSPY
-
SIOCIWFIRST
]
=
iw_handler_get_thrspy
,
[
SIOCSIWAP
-
SIOCIWFIRST
]
=
wl3501_set_wap
,
[
SIOCGIWAP
-
SIOCIWFIRST
]
=
wl3501_get_wap
,
[
SIOCSIWESSID
-
SIOCIWFIRST
]
=
wl3501_set_essid
,
[
SIOCGIWESSID
-
SIOCIWFIRST
]
=
wl3501_get_essid
,
[
SIOCSIWNICKN
-
SIOCIWFIRST
]
=
wl3501_set_nick
,
[
SIOCGIWNICKN
-
SIOCIWFIRST
]
=
wl3501_get_nick
,
[
SIOCGIWRATE
-
SIOCIWFIRST
]
=
wl3501_get_rate
,
[
SIOCGIWRTS
-
SIOCIWFIRST
]
=
wl3501_get_rts_threshold
,
[
SIOCGIWFRAG
-
SIOCIWFIRST
]
=
wl3501_get_frag_threshold
,
[
SIOCGIWTXPOW
-
SIOCIWFIRST
]
=
wl3501_get_txpow
,
[
SIOCGIWRETRY
-
SIOCIWFIRST
]
=
wl3501_get_retry
,
[
SIOCGIWENCODE
-
SIOCIWFIRST
]
=
wl3501_get_encode
,
[
SIOCGIWPOWER
-
SIOCIWFIRST
]
=
wl3501_get_power
,
};
static
const
struct
iw_handler_def
wl3501_handler_def
=
{
.
num_standard
=
sizeof
(
wl3501_handler
)
/
sizeof
(
iw_handler
),
.
standard
=
(
iw_handler
*
)
wl3501_handler
,
.
spy_offset
=
offsetof
(
struct
wl3501_card
,
spy_data
),
};
/**
* wl3501_attach - creates an "instance" of the driver
*
* Creates an "instance" of the driver, allocating local data structures for
* one device. The device is registered with Card Services.
*
* The dev_link structure is initialized, but we don't actually configure the
* card at this point -- we wait until we receive a card insertion event.
*/
static
dev_link_t
*
wl3501_attach
(
void
)
{
client_reg_t
client_reg
;
dev_link_t
*
link
;
struct
net_device
*
dev
;
int
ret
,
i
;
wl3501_flush_stale_links
();
/* Initialize the dev_link_t structure */
link
=
kmalloc
(
sizeof
(
*
link
),
GFP_KERNEL
);
if
(
!
link
)
goto
out
;
memset
(
link
,
0
,
sizeof
(
struct
dev_link_t
));
init_timer
(
&
link
->
release
);
link
->
release
.
function
=
wl3501_release
;
link
->
release
.
data
=
(
unsigned
long
)
link
;
/* The io structure describes IO port mapping */
link
->
io
.
NumPorts1
=
16
;
link
->
io
.
Attributes1
=
IO_DATA_PATH_WIDTH_8
;
link
->
io
.
IOAddrLines
=
5
;
/* Interrupt setup */
link
->
irq
.
Attributes
=
IRQ_TYPE_EXCLUSIVE
|
IRQ_HANDLE_PRESENT
;
link
->
irq
.
IRQInfo1
=
IRQ_INFO2_VALID
|
IRQ_LEVEL_ID
;
link
->
irq
.
IRQInfo2
=
wl3501_irq_mask
;
if
(
wl3501_irq_list
[
0
]
!=
-
1
)
for
(
i
=
0
;
i
<
4
;
i
++
)
link
->
irq
.
IRQInfo2
|=
1
<<
wl3501_irq_list
[
i
];
link
->
irq
.
Handler
=
wl3501_interrupt
;
/* General socket configuration */
link
->
conf
.
Attributes
=
CONF_ENABLE_IRQ
;
link
->
conf
.
Vcc
=
50
;
link
->
conf
.
IntType
=
INT_MEMORY_AND_IO
;
link
->
conf
.
ConfigIndex
=
1
;
link
->
conf
.
Present
=
PRESENT_OPTION
;
dev
=
alloc_etherdev
(
sizeof
(
struct
wl3501_card
));
if
(
!
dev
)
goto
out_link
;
dev
->
init
=
wl3501_init
;
dev
->
open
=
wl3501_open
;
dev
->
stop
=
wl3501_close
;
dev
->
hard_start_xmit
=
wl3501_hard_start_xmit
;
dev
->
tx_timeout
=
wl3501_tx_timeout
;
dev
->
watchdog_timeo
=
5
*
HZ
;
dev
->
get_stats
=
wl3501_get_stats
;
dev
->
get_wireless_stats
=
wl3501_get_wireless_stats
;
dev
->
do_ioctl
=
wl3501_ioctl
;
dev
->
wireless_handlers
=
(
struct
iw_handler_def
*
)
&
wl3501_handler_def
;
netif_stop_queue
(
dev
);
link
->
priv
=
link
->
irq
.
Instance
=
dev
;
/* Register with Card Services */
link
->
next
=
wl3501_dev_list
;
wl3501_dev_list
=
link
;
client_reg
.
dev_info
=
&
wl3501_dev_info
;
client_reg
.
Attributes
=
INFO_IO_CLIENT
|
INFO_CARD_SHARE
;
client_reg
.
EventMask
=
CS_EVENT_CARD_INSERTION
|
CS_EVENT_RESET_PHYSICAL
|
CS_EVENT_CARD_RESET
|
CS_EVENT_CARD_REMOVAL
|
CS_EVENT_PM_SUSPEND
|
CS_EVENT_PM_RESUME
;
client_reg
.
event_handler
=
wl3501_event
;
client_reg
.
Version
=
0x0210
;
client_reg
.
event_callback_args
.
client_data
=
link
;
ret
=
CardServices
(
RegisterClient
,
&
link
->
handle
,
&
client_reg
);
if
(
ret
)
{
cs_error
(
link
->
handle
,
RegisterClient
,
ret
);
wl3501_detach
(
link
);
link
=
NULL
;
}
out:
return
link
;
out_link:
kfree
(
link
);
link
=
NULL
;
goto
out
;
}
#define CS_CHECK(fn, args...) \
while ((last_ret = CardServices(last_fn = (fn), args)) != 0) goto cs_failed
/**
* wl3501_config - configure the PCMCIA socket and make eth device available
* @link - FILL_IN
*
* wl3501_config() is scheduled to run after a CARD_INSERTION event is
* received, to configure the PCMCIA socket, and to make the ethernet device
* available to the system.
*/
static
void
wl3501_config
(
dev_link_t
*
link
)
{
tuple_t
tuple
;
cisparse_t
parse
;
client_handle_t
handle
=
link
->
handle
;
struct
net_device
*
dev
=
link
->
priv
;
int
i
=
0
,
j
,
last_fn
,
last_ret
;
unsigned
char
bf
[
64
];
struct
wl3501_card
*
this
;
/* This reads the card's CONFIG tuple to find its config registers. */
tuple
.
Attributes
=
0
;
tuple
.
DesiredTuple
=
CISTPL_CONFIG
;
CS_CHECK
(
GetFirstTuple
,
handle
,
&
tuple
);
tuple
.
TupleData
=
bf
;
tuple
.
TupleDataMax
=
sizeof
(
bf
);
tuple
.
TupleOffset
=
0
;
CS_CHECK
(
GetTupleData
,
handle
,
&
tuple
);
CS_CHECK
(
ParseTuple
,
handle
,
&
tuple
,
&
parse
);
link
->
conf
.
ConfigBase
=
parse
.
config
.
base
;
link
->
conf
.
Present
=
parse
.
config
.
rmask
[
0
];
/* Configure card */
link
->
state
|=
DEV_CONFIG
;
/* Try allocating IO ports. This tries a few fixed addresses. If you
* want, you can also read the card's config table to pick addresses --
* see the serial driver for an example. */
for
(
j
=
0x280
;
j
<
0x400
;
j
+=
0x20
)
{
/* The '^0x300' is so that we probe 0x300-0x3ff first, then
* 0x200-0x2ff, and so on, because this seems safer */
link
->
io
.
BasePort1
=
j
;
link
->
io
.
BasePort2
=
link
->
io
.
BasePort1
+
0x10
;
i
=
CardServices
(
RequestIO
,
link
->
handle
,
&
link
->
io
);
if
(
i
==
CS_SUCCESS
)
break
;
}
if
(
i
!=
CS_SUCCESS
)
{
cs_error
(
link
->
handle
,
RequestIO
,
i
);
goto
failed
;
}
/* Now allocate an interrupt line. Note that this does not actually
* assign a handler to the interrupt. */
CS_CHECK
(
RequestIRQ
,
link
->
handle
,
&
link
->
irq
);
/* This actually configures the PCMCIA socket -- setting up the I/O
* windows and the interrupt mapping. */
CS_CHECK
(
RequestConfiguration
,
link
->
handle
,
&
link
->
conf
);
dev
->
irq
=
link
->
irq
.
AssignedIRQ
;
dev
->
base_addr
=
link
->
io
.
BasePort1
;
if
(
register_netdev
(
dev
))
{
printk
(
KERN_NOTICE
"wl3501_cs: register_netdev() failed
\n
"
);
goto
failed
;
}
SET_MODULE_OWNER
(
dev
);
this
=
dev
->
priv
;
/*
* At this point, the dev_node_t structure(s) should be initialized and
* arranged in a linked list at link->dev.
*/
link
->
dev
=
&
this
->
node
;
link
->
state
&=
~
DEV_CONFIG_PENDING
;
this
->
base_addr
=
dev
->
base_addr
;
if
(
!
wl3501_get_flash_mac_addr
(
this
))
{
printk
(
KERN_WARNING
"%s: Cant read MAC addr in flash ROM?
\n
"
,
dev
->
name
);
goto
failed
;
}
strcpy
(
this
->
node
.
dev_name
,
dev
->
name
);
/* print probe information */
printk
(
KERN_INFO
"%s: wl3501 @ 0x%3.3x, IRQ %d, MAC addr in flash ROM:"
,
dev
->
name
,
this
->
base_addr
,
(
int
)
dev
->
irq
);
for
(
i
=
0
;
i
<
6
;
i
++
)
{
dev
->
dev_addr
[
i
]
=
((
char
*
)
&
this
->
mac_addr
)[
i
];
printk
(
"%c%02x"
,
i
?
':'
:
' '
,
dev
->
dev_addr
[
i
]);
}
printk
(
"
\n
"
);
/*
* Initialize card parameters - added by jss
*/
this
->
net_type
=
IW_MODE_INFRA
;
this
->
bss_cnt
=
0
;
this
->
join_sta_bss
=
0
;
this
->
adhoc_times
=
0
;
this
->
essid
[
0
]
=
0
;
this
->
essid
[
1
]
=
3
;
this
->
essid
[
2
]
=
'A'
;
this
->
essid
[
3
]
=
'N'
;
this
->
essid
[
4
]
=
'Y'
;
this
->
card_name
[
0
]
=
'\0'
;
this
->
firmware_date
[
0
]
=
'\0'
;
this
->
rssi
=
255
;
this
->
chan
=
iw_default_channel
(
this
->
reg_domain
);
strlcpy
(
this
->
nick
,
"Planet WL3501"
,
sizeof
(
this
->
nick
));
spin_lock_init
(
&
this
->
lock
);
init_waitqueue_head
(
&
this
->
wait
);
netif_start_queue
(
dev
);
goto
out
;
cs_failed:
cs_error
(
link
->
handle
,
last_fn
,
last_ret
);
failed:
wl3501_release
((
unsigned
long
)
link
);
out:
return
;
}
/**
* wl3501_release - unregister the net, release PCMCIA configuration
* @arg - link
*
* After a card is removed, wl3501_release() will unregister the net device,
* and release the PCMCIA configuration. If the device is still open, this
* will be postponed until it is closed.
*/
static
void
wl3501_release
(
unsigned
long
arg
)
{
dev_link_t
*
link
=
(
dev_link_t
*
)
arg
;
struct
net_device
*
dev
=
link
->
priv
;
/* If the device is currently in use, we won't release until it is
* actually closed. */
if
(
link
->
open
)
{
dprintk
(
1
,
"release postponed, '%s' still open"
,
link
->
dev
->
dev_name
);
link
->
state
|=
DEV_STALE_CONFIG
;
goto
out
;
}
/* Unlink the device chain */
if
(
link
->
dev
)
{
unregister_netdev
(
dev
);
link
->
dev
=
NULL
;
}
/* Don't bother checking to see if these succeed or not */
CardServices
(
ReleaseConfiguration
,
link
->
handle
);
CardServices
(
ReleaseIO
,
link
->
handle
,
&
link
->
io
);
CardServices
(
ReleaseIRQ
,
link
->
handle
,
&
link
->
irq
);
link
->
state
&=
~
DEV_CONFIG
;
if
(
link
->
state
&
DEV_STALE_LINK
)
wl3501_detach
(
link
);
out:
return
;
}
/**
* wl3501_event - The card status event handler
* @event - event
* @pri - priority
* @args - arguments for this event
*
* The card status event handler. Mostly, this schedules other stuff to run
* after an event is received. A CARD_REMOVAL event also sets some flags to
* discourage the net drivers from trying to talk to the card any more.
*
* When a CARD_REMOVAL event is received, we immediately set a flag to block
* future accesses to this device. All the functions that actually access the
* device should check this flag to make sure the card is still present.
*/
static
int
wl3501_event
(
event_t
event
,
int
pri
,
event_callback_args_t
*
args
)
{
dev_link_t
*
link
=
args
->
client_data
;
struct
net_device
*
dev
=
link
->
priv
;
switch
(
event
)
{
case
CS_EVENT_CARD_REMOVAL
:
link
->
state
&=
~
DEV_PRESENT
;
if
(
link
->
state
&
DEV_CONFIG
)
{
while
(
link
->
open
>
0
)
wl3501_close
(
dev
);
netif_device_detach
(
dev
);
link
->
release
.
expires
=
jiffies
+
WL3501_RELEASE_TIMEOUT
;
add_timer
(
&
link
->
release
);
}
break
;
case
CS_EVENT_CARD_INSERTION
:
link
->
state
|=
DEV_PRESENT
|
DEV_CONFIG_PENDING
;
wl3501_config
(
link
);
break
;
case
CS_EVENT_PM_SUSPEND
:
link
->
state
|=
DEV_SUSPEND
;
wl3501_pwr_mgmt
(
dev
->
priv
,
WL3501_SUSPEND
);
/* Fall through... */
case
CS_EVENT_RESET_PHYSICAL
:
if
(
link
->
state
&
DEV_CONFIG
)
{
if
(
link
->
open
)
netif_device_detach
(
dev
);
CardServices
(
ReleaseConfiguration
,
link
->
handle
);
}
break
;
case
CS_EVENT_PM_RESUME
:
link
->
state
&=
~
DEV_SUSPEND
;
wl3501_pwr_mgmt
(
dev
->
priv
,
WL3501_RESUME
);
/* Fall through... */
case
CS_EVENT_CARD_RESET
:
if
(
link
->
state
&
DEV_CONFIG
)
{
CardServices
(
RequestConfiguration
,
link
->
handle
,
&
link
->
conf
);
if
(
link
->
open
)
{
wl3501_reset
(
dev
);
netif_device_attach
(
dev
);
}
}
break
;
}
return
0
;
}
static
struct
pcmcia_driver
wl3501_driver
=
{
.
owner
=
THIS_MODULE
,
.
drv
=
{
.
name
=
"wl3501_cs"
,
},
.
attach
=
wl3501_attach
,
.
detach
=
wl3501_detach
,
};
static
int
__init
wl3501_init_module
(
void
)
{
servinfo_t
serv
;
dprintk
(
0
,
": loading"
);
CardServices
(
GetCardServicesInfo
,
&
serv
);
if
(
serv
.
Revision
!=
CS_RELEASE_CODE
)
{
printk
(
KERN_NOTICE
"wl3501_cs: Card Services release does not match!
\n
"
"Compiled with 0x%x, but current is 0x%lx
\n
"
,
CS_RELEASE_CODE
,
(
unsigned
long
)
serv
.
Revision
);
/* return -1; */
}
pcmcia_register_driver
(
&
wl3501_driver
);
return
0
;
}
static
void
__exit
wl3501_exit_module
(
void
)
{
dprintk
(
0
,
": unloading"
);
pcmcia_unregister_driver
(
&
wl3501_driver
);
while
(
wl3501_dev_list
)
{
del_timer
(
&
wl3501_dev_list
->
release
);
/* Mark the device as non-existing to minimize calls to card */
wl3501_dev_list
->
state
&=
~
DEV_PRESENT
;
if
(
wl3501_dev_list
->
state
&
DEV_CONFIG
)
wl3501_release
((
unsigned
long
)
wl3501_dev_list
);
wl3501_detach
(
wl3501_dev_list
);
}
}
module_init
(
wl3501_init_module
);
module_exit
(
wl3501_exit_module
);
MODULE_PARM
(
wl3501_irq_mask
,
"i"
);
MODULE_PARM
(
wl3501_irq_list
,
"1-4i"
);
MODULE_AUTHOR
(
"Fox Chen <mhchen@golf.ccl.itri.org.tw>, "
"Arnaldo Carvalho de Melo <acme@conectiva.com.br>,"
"Gustavo Niemeyer <niemeyer@conectiva.com>"
);
MODULE_DESCRIPTION
(
"Planet wl3501 wireless driver"
);
MODULE_LICENSE
(
"GPL"
);
include/linux/ethtool.h
View file @
1d90ac41
...
@@ -281,6 +281,8 @@ struct ethtool_stats {
...
@@ -281,6 +281,8 @@ struct ethtool_stats {
#define ETHTOOL_GSTRINGS 0x0000001b
/* get specified string set */
#define ETHTOOL_GSTRINGS 0x0000001b
/* get specified string set */
#define ETHTOOL_PHYS_ID 0x0000001c
/* identify the NIC */
#define ETHTOOL_PHYS_ID 0x0000001c
/* identify the NIC */
#define ETHTOOL_GSTATS 0x0000001d
/* get NIC-specific statistics */
#define ETHTOOL_GSTATS 0x0000001d
/* get NIC-specific statistics */
#define ETHTOOL_GTSO 0x0000001e
/* Get TSO enable (ethtool_value) */
#define ETHTOOL_STSO 0x0000001f
/* Set TSO enable (ethtool_value) */
/* compatibility with older code */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
#define SPARC_ETH_GSET ETHTOOL_GSET
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment