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
a5220ff4
Commit
a5220ff4
authored
Feb 20, 2002
by
Jean Tourrilhes
Committed by
Jeff Garzik
Feb 20, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update (ancient) wireless net drivers netwave_cs, wavelan,
and wavelan_cs to new wireless API.
parent
74a4e27a
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
2199 additions
and
1085 deletions
+2199
-1085
drivers/net/wireless/netwave_cs.c
drivers/net/wireless/netwave_cs.c
+350
-124
drivers/net/wireless/wavelan.c
drivers/net/wireless/wavelan.c
+651
-453
drivers/net/wireless/wavelan.p.h
drivers/net/wireless/wavelan.p.h
+10
-5
drivers/net/wireless/wavelan_cs.c
drivers/net/wireless/wavelan_cs.c
+1166
-500
drivers/net/wireless/wavelan_cs.p.h
drivers/net/wireless/wavelan_cs.p.h
+22
-3
No files found.
drivers/net/wireless/netwave_cs.c
View file @
a5220ff4
...
@@ -63,6 +63,9 @@
...
@@ -63,6 +63,9 @@
#ifdef CONFIG_NET_RADIO
#ifdef CONFIG_NET_RADIO
#include <linux/wireless.h>
#include <linux/wireless.h>
#if WIRELESS_EXT > 12
#include <net/iw_handler.h>
#endif
/* WIRELESS_EXT > 12 */
#endif
#endif
#include <pcmcia/version.h>
#include <pcmcia/version.h>
...
@@ -269,6 +272,16 @@ static dev_link_t *dev_list;
...
@@ -269,6 +272,16 @@ static dev_link_t *dev_list;
because they generally can't be allocated dynamically.
because they generally can't be allocated dynamically.
*/
*/
#if WIRELESS_EXT <= 12
/* Wireless extensions backward compatibility */
/* Part of iw_handler prototype we need */
struct
iw_request_info
{
__u16
cmd
;
/* Wireless Extension command */
__u16
flags
;
/* More to come ;-) */
};
/* Wireless Extension Backward compatibility - Jean II
/* Wireless Extension Backward compatibility - Jean II
* If the new wireless device private ioctl range is not defined,
* If the new wireless device private ioctl range is not defined,
* default to standard device private ioctl range */
* default to standard device private ioctl range */
...
@@ -276,8 +289,11 @@ static dev_link_t *dev_list;
...
@@ -276,8 +289,11 @@ static dev_link_t *dev_list;
#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE
#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE
#endif
/* SIOCIWFIRSTPRIV */
#endif
/* SIOCIWFIRSTPRIV */
#define SIOCGIPSNAP SIOCIWFIRSTPRIV
/* Site Survey Snapshot */
#else
/* WIRELESS_EXT <= 12 */
/*#define SIOCGIPQTHR SIOCIWFIRSTPRIV + 1*/
static
const
struct
iw_handler_def
netwave_handler_def
;
#endif
/* WIRELESS_EXT <= 12 */
#define SIOCGIPSNAP SIOCIWFIRSTPRIV + 1
/* Site Survey Snapshot */
#define MAX_ESA 10
#define MAX_ESA 10
...
@@ -483,7 +499,10 @@ static dev_link_t *netwave_attach(void)
...
@@ -483,7 +499,10 @@ static dev_link_t *netwave_attach(void)
/* wireless extensions */
/* wireless extensions */
#ifdef WIRELESS_EXT
#ifdef WIRELESS_EXT
dev
->
get_wireless_stats
=
&
netwave_get_wireless_stats
;
dev
->
get_wireless_stats
=
&
netwave_get_wireless_stats
;
#endif
#if WIRELESS_EXT > 12
dev
->
wireless_handlers
=
(
struct
iw_handler_def
*
)
&
netwave_handler_def
;
#endif
/* WIRELESS_EXT > 12 */
#endif
/* WIRELESS_EXT */
dev
->
do_ioctl
=
&
netwave_ioctl
;
dev
->
do_ioctl
=
&
netwave_ioctl
;
dev
->
tx_timeout
=
&
netwave_watchdog
;
dev
->
tx_timeout
=
&
netwave_watchdog
;
...
@@ -595,6 +614,303 @@ static void netwave_flush_stale_links(void)
...
@@ -595,6 +614,303 @@ static void netwave_flush_stale_links(void)
}
}
}
/* netwave_flush_stale_links */
}
/* netwave_flush_stale_links */
/*
* Wireless Handler : get protocol name
*/
static
int
netwave_get_name
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
strcpy
(
wrqu
->
name
,
"Netwave"
);
return
0
;
}
/*
* Wireless Handler : set Network ID
*/
static
int
netwave_set_nwid
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
unsigned
long
flags
;
ioaddr_t
iobase
=
dev
->
base_addr
;
netwave_private
*
priv
=
(
netwave_private
*
)
dev
->
priv
;
u_char
*
ramBase
=
priv
->
ramBase
;
/* Disable interrupts & save flags */
save_flags
(
flags
);
cli
();
#if WIRELESS_EXT > 8
if
(
!
wrqu
->
nwid
.
disabled
)
{
domain
=
wrqu
->
nwid
.
value
;
#else
/* WIRELESS_EXT > 8 */
if
(
wrqu
->
nwid
.
on
)
{
domain
=
wrqu
->
nwid
.
nwid
;
#endif
/* WIRELESS_EXT > 8 */
printk
(
KERN_DEBUG
"Setting domain to 0x%x%02x
\n
"
,
(
domain
>>
8
)
&
0x01
,
domain
&
0xff
);
wait_WOC
(
iobase
);
writeb
(
NETWAVE_CMD_SMD
,
ramBase
+
NETWAVE_EREG_CB
+
0
);
writeb
(
domain
&
0xff
,
ramBase
+
NETWAVE_EREG_CB
+
1
);
writeb
((
domain
>>
8
)
&
0x01
,
ramBase
+
NETWAVE_EREG_CB
+
2
);
writeb
(
NETWAVE_CMD_EOC
,
ramBase
+
NETWAVE_EREG_CB
+
3
);
}
/* ReEnable interrupts & restore flags */
restore_flags
(
flags
);
return
0
;
}
/*
* Wireless Handler : get Network ID
*/
static
int
netwave_get_nwid
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
#if WIRELESS_EXT > 8
wrqu
->
nwid
.
value
=
domain
;
wrqu
->
nwid
.
disabled
=
0
;
wrqu
->
nwid
.
fixed
=
1
;
#else
/* WIRELESS_EXT > 8 */
wrqu
->
nwid
.
nwid
=
domain
;
wrqu
->
nwid
.
on
=
1
;
#endif
/* WIRELESS_EXT > 8 */
return
0
;
}
/*
* Wireless Handler : set scramble key
*/
static
int
netwave_set_scramble
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
key
)
{
unsigned
long
flags
;
ioaddr_t
iobase
=
dev
->
base_addr
;
netwave_private
*
priv
=
(
netwave_private
*
)
dev
->
priv
;
u_char
*
ramBase
=
priv
->
ramBase
;
/* Disable interrupts & save flags */
save_flags
(
flags
);
cli
();
scramble_key
=
(
key
[
0
]
<<
8
)
|
key
[
1
];
wait_WOC
(
iobase
);
writeb
(
NETWAVE_CMD_SSK
,
ramBase
+
NETWAVE_EREG_CB
+
0
);
writeb
(
scramble_key
&
0xff
,
ramBase
+
NETWAVE_EREG_CB
+
1
);
writeb
((
scramble_key
>>
8
)
&
0xff
,
ramBase
+
NETWAVE_EREG_CB
+
2
);
writeb
(
NETWAVE_CMD_EOC
,
ramBase
+
NETWAVE_EREG_CB
+
3
);
/* ReEnable interrupts & restore flags */
restore_flags
(
flags
);
return
0
;
}
/*
* Wireless Handler : get scramble key
*/
static
int
netwave_get_scramble
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
key
)
{
key
[
1
]
=
scramble_key
&
0xff
;
key
[
0
]
=
(
scramble_key
>>
8
)
&
0xff
;
#if WIRELESS_EXT > 8
wrqu
->
encoding
.
flags
=
IW_ENCODE_ENABLED
;
wrqu
->
encoding
.
length
=
2
;
#else
/* WIRELESS_EXT > 8 */
wrqu
->
encoding
.
method
=
1
;
#endif
/* WIRELESS_EXT > 8 */
return
0
;
}
#if WIRELESS_EXT > 8
/*
* Wireless Handler : get mode
*/
static
int
netwave_get_mode
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
if
(
domain
&
0x100
)
wrqu
->
mode
=
IW_MODE_INFRA
;
else
wrqu
->
mode
=
IW_MODE_ADHOC
;
return
0
;
}
#endif
/* WIRELESS_EXT > 8 */
/*
* Wireless Handler : get range info
*/
static
int
netwave_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
;
int
ret
=
0
;
/* Set the length (very important for backward compatibility) */
wrqu
->
data
.
length
=
sizeof
(
struct
iw_range
);
/* Set all the info we don't care or don't know about to zero */
memset
(
range
,
0
,
sizeof
(
struct
iw_range
));
#if WIRELESS_EXT > 10
/* Set the Wireless Extension versions */
range
->
we_version_compiled
=
WIRELESS_EXT
;
range
->
we_version_source
=
9
;
/* Nothing for us in v10 and v11 */
#endif
/* WIRELESS_EXT > 10 */
/* Set information in the range struct */
range
->
throughput
=
450
*
1000
;
/* don't argue on this ! */
range
->
min_nwid
=
0x0000
;
range
->
max_nwid
=
0x01FF
;
range
->
num_channels
=
range
->
num_frequency
=
0
;
range
->
sensitivity
=
0x3F
;
range
->
max_qual
.
qual
=
255
;
range
->
max_qual
.
level
=
255
;
range
->
max_qual
.
noise
=
0
;
#if WIRELESS_EXT > 7
range
->
num_bitrates
=
1
;
range
->
bitrate
[
0
]
=
1000000
;
/* 1 Mb/s */
#endif
/* WIRELESS_EXT > 7 */
#if WIRELESS_EXT > 8
range
->
encoding_size
[
0
]
=
2
;
/* 16 bits scrambling */
range
->
num_encoding_sizes
=
1
;
range
->
max_encoding_tokens
=
1
;
/* Only one key possible */
#endif
/* WIRELESS_EXT > 8 */
return
ret
;
}
/*
* Wireless Private Handler : get snapshot
*/
static
int
netwave_get_snap
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
unsigned
long
flags
;
ioaddr_t
iobase
=
dev
->
base_addr
;
netwave_private
*
priv
=
(
netwave_private
*
)
dev
->
priv
;
u_char
*
ramBase
=
priv
->
ramBase
;
/* Disable interrupts & save flags */
save_flags
(
flags
);
cli
();
/* Take snapshot of environment */
netwave_snapshot
(
priv
,
ramBase
,
iobase
);
wrqu
->
data
.
length
=
priv
->
nss
.
length
;
memcpy
(
extra
,
(
u_char
*
)
&
priv
->
nss
,
sizeof
(
struct
site_survey
));
priv
->
lastExec
=
jiffies
;
/* ReEnable interrupts & restore flags */
restore_flags
(
flags
);
return
(
0
);
}
/*
* Structures to export the Wireless Handlers
* This is the stuff that are treated the wireless extensions (iwconfig)
*/
static
const
struct
iw_priv_args
netwave_private_args
[]
=
{
/*{ cmd, set_args, get_args, name } */
{
SIOCGIPSNAP
,
0
,
IW_PRIV_TYPE_BYTE
|
IW_PRIV_SIZE_FIXED
|
sizeof
(
struct
site_survey
),
"getsitesurvey"
},
};
#if WIRELESS_EXT > 12
static
const
iw_handler
netwave_handler
[]
=
{
NULL
,
/* SIOCSIWNAME */
netwave_get_name
,
/* SIOCGIWNAME */
netwave_set_nwid
,
/* SIOCSIWNWID */
netwave_get_nwid
,
/* SIOCGIWNWID */
NULL
,
/* SIOCSIWFREQ */
NULL
,
/* SIOCGIWFREQ */
NULL
,
/* SIOCSIWMODE */
netwave_get_mode
,
/* SIOCGIWMODE */
NULL
,
/* SIOCSIWSENS */
NULL
,
/* SIOCGIWSENS */
NULL
,
/* SIOCSIWRANGE */
netwave_get_range
,
/* SIOCGIWRANGE */
NULL
,
/* SIOCSIWPRIV */
NULL
,
/* SIOCGIWPRIV */
NULL
,
/* SIOCSIWSTATS */
NULL
,
/* SIOCGIWSTATS */
NULL
,
/* SIOCSIWSPY */
NULL
,
/* SIOCGIWSPY */
NULL
,
/* -- hole -- */
NULL
,
/* -- hole -- */
NULL
,
/* SIOCSIWAP */
NULL
,
/* SIOCGIWAP */
NULL
,
/* -- hole -- */
NULL
,
/* SIOCGIWAPLIST */
NULL
,
/* -- hole -- */
NULL
,
/* -- hole -- */
NULL
,
/* SIOCSIWESSID */
NULL
,
/* SIOCGIWESSID */
NULL
,
/* SIOCSIWNICKN */
NULL
,
/* SIOCGIWNICKN */
NULL
,
/* -- hole -- */
NULL
,
/* -- hole -- */
NULL
,
/* SIOCSIWRATE */
NULL
,
/* SIOCGIWRATE */
NULL
,
/* SIOCSIWRTS */
NULL
,
/* SIOCGIWRTS */
NULL
,
/* SIOCSIWFRAG */
NULL
,
/* SIOCGIWFRAG */
NULL
,
/* SIOCSIWTXPOW */
NULL
,
/* SIOCGIWTXPOW */
NULL
,
/* SIOCSIWRETRY */
NULL
,
/* SIOCGIWRETRY */
netwave_set_scramble
,
/* SIOCSIWENCODE */
netwave_get_scramble
,
/* SIOCGIWENCODE */
};
static
const
iw_handler
netwave_private_handler
[]
=
{
NULL
,
/* SIOCIWFIRSTPRIV */
netwave_get_snap
,
/* SIOCIWFIRSTPRIV + 1 */
};
static
const
struct
iw_handler_def
netwave_handler_def
=
{
num_standard:
sizeof
(
netwave_handler
)
/
sizeof
(
iw_handler
),
num_private:
sizeof
(
netwave_private_handler
)
/
sizeof
(
iw_handler
),
num_private_args:
sizeof
(
netwave_private_args
)
/
sizeof
(
struct
iw_priv_args
),
standard:
(
iw_handler
*
)
netwave_handler
,
private:
(
iw_handler
*
)
netwave_private_handler
,
private_args:
(
struct
iw_priv_args
*
)
netwave_private_args
,
};
#endif
/* WIRELESS_EXT > 12 */
/*
/*
* Function netwave_ioctl (dev, rq, cmd)
* Function netwave_ioctl (dev, rq, cmd)
*
*
...
@@ -606,56 +922,28 @@ static int netwave_ioctl(struct net_device *dev, /* ioctl device */
...
@@ -606,56 +922,28 @@ static int netwave_ioctl(struct net_device *dev, /* ioctl device */
struct
ifreq
*
rq
,
/* Data passed */
struct
ifreq
*
rq
,
/* Data passed */
int
cmd
)
/* Ioctl number */
int
cmd
)
/* Ioctl number */
{
{
unsigned
long
flags
;
int
ret
=
0
;
int
ret
=
0
;
#ifdef WIRELESS_EXT
#ifdef WIRELESS_EXT
ioaddr_t
iobase
=
dev
->
base_addr
;
#if WIRELESS_EXT <= 12
netwave_private
*
priv
=
(
netwave_private
*
)
dev
->
priv
;
u_char
*
ramBase
=
priv
->
ramBase
;
struct
iwreq
*
wrq
=
(
struct
iwreq
*
)
rq
;
struct
iwreq
*
wrq
=
(
struct
iwreq
*
)
rq
;
#endif
#endif
#endif
DEBUG
(
0
,
"%s: ->netwave_ioctl(cmd=0x%X)
\n
"
,
dev
->
name
,
cmd
);
DEBUG
(
0
,
"%s: ->netwave_ioctl(cmd=0x%X)
\n
"
,
dev
->
name
,
cmd
);
/* Disable interrupts & save flags */
save_flags
(
flags
);
cli
();
/* Look what is the request */
/* Look what is the request */
switch
(
cmd
)
{
switch
(
cmd
)
{
/* --------------- WIRELESS EXTENSIONS --------------- */
/* --------------- WIRELESS EXTENSIONS --------------- */
#ifdef WIRELESS_EXT
#ifdef WIRELESS_EXT
#if WIRELESS_EXT <= 12
case
SIOCGIWNAME
:
case
SIOCGIWNAME
:
/* Get name */
netwave_get_name
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
strcpy
(
wrq
->
u
.
name
,
"Netwave"
);
break
;
break
;
case
SIOCSIWNWID
:
case
SIOCSIWNWID
:
/* Set domain */
ret
=
netwave_set_nwid
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
#if WIRELESS_EXT > 8
break
;
if
(
!
wrq
->
u
.
nwid
.
disabled
)
{
domain
=
wrq
->
u
.
nwid
.
value
;
#else
/* WIRELESS_EXT > 8 */
if
(
wrq
->
u
.
nwid
.
on
)
{
domain
=
wrq
->
u
.
nwid
.
nwid
;
#endif
/* WIRELESS_EXT > 8 */
printk
(
KERN_DEBUG
"Setting domain to 0x%x%02x
\n
"
,
(
domain
>>
8
)
&
0x01
,
domain
&
0xff
);
wait_WOC
(
iobase
);
writeb
(
NETWAVE_CMD_SMD
,
ramBase
+
NETWAVE_EREG_CB
+
0
);
writeb
(
domain
&
0xff
,
ramBase
+
NETWAVE_EREG_CB
+
1
);
writeb
((
domain
>>
8
)
&
0x01
,
ramBase
+
NETWAVE_EREG_CB
+
2
);
writeb
(
NETWAVE_CMD_EOC
,
ramBase
+
NETWAVE_EREG_CB
+
3
);
}
break
;
case
SIOCGIWNWID
:
case
SIOCGIWNWID
:
/* Read domain*/
ret
=
netwave_get_nwid
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
#if WIRELESS_EXT > 8
wrq
->
u
.
nwid
.
value
=
domain
;
wrq
->
u
.
nwid
.
disabled
=
0
;
wrq
->
u
.
nwid
.
fixed
=
1
;
#else
/* WIRELESS_EXT > 8 */
wrq
->
u
.
nwid
.
nwid
=
domain
;
wrq
->
u
.
nwid
.
on
=
1
;
#endif
/* WIRELESS_EXT > 8 */
break
;
break
;
#if WIRELESS_EXT > 8
/* Note : The API did change... */
#if WIRELESS_EXT > 8
/* Note : The API did change... */
case
SIOCGIWENCODE
:
case
SIOCGIWENCODE
:
...
@@ -663,10 +951,7 @@ static int netwave_ioctl(struct net_device *dev, /* ioctl device */
...
@@ -663,10 +951,7 @@ static int netwave_ioctl(struct net_device *dev, /* ioctl device */
if
(
wrq
->
u
.
encoding
.
pointer
!=
(
caddr_t
)
0
)
if
(
wrq
->
u
.
encoding
.
pointer
!=
(
caddr_t
)
0
)
{
{
char
key
[
2
];
char
key
[
2
];
key
[
1
]
=
scramble_key
&
0xff
;
ret
=
netwave_get_scramble
(
dev
,
NULL
,
&
(
wrq
->
u
),
key
);
key
[
0
]
=
(
scramble_key
>>
8
)
&
0xff
;
wrq
->
u
.
encoding
.
flags
=
IW_ENCODE_ENABLED
;
wrq
->
u
.
encoding
.
length
=
2
;
if
(
copy_to_user
(
wrq
->
u
.
encoding
.
pointer
,
key
,
2
))
if
(
copy_to_user
(
wrq
->
u
.
encoding
.
pointer
,
key
,
2
))
ret
=
-
EFAULT
;
ret
=
-
EFAULT
;
}
}
...
@@ -681,127 +966,68 @@ static int netwave_ioctl(struct net_device *dev, /* ioctl device */
...
@@ -681,127 +966,68 @@ static int netwave_ioctl(struct net_device *dev, /* ioctl device */
ret
=
-
EFAULT
;
ret
=
-
EFAULT
;
break
;
break
;
}
}
scramble_key
=
(
key
[
0
]
<<
8
)
|
key
[
1
];
ret
=
netwave_set_scramble
(
dev
,
NULL
,
&
(
wrq
->
u
),
key
);
wait_WOC
(
iobase
);
writeb
(
NETWAVE_CMD_SSK
,
ramBase
+
NETWAVE_EREG_CB
+
0
);
writeb
(
scramble_key
&
0xff
,
ramBase
+
NETWAVE_EREG_CB
+
1
);
writeb
((
scramble_key
>>
8
)
&
0xff
,
ramBase
+
NETWAVE_EREG_CB
+
2
);
writeb
(
NETWAVE_CMD_EOC
,
ramBase
+
NETWAVE_EREG_CB
+
3
);
}
}
break
;
break
;
case
SIOCGIWMODE
:
case
SIOCGIWMODE
:
/* Mode of operation */
/* Mode of operation */
if
(
domain
&
0x100
)
ret
=
netwave_get_mode
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
wrq
->
u
.
mode
=
IW_MODE_INFRA
;
break
;
else
wrq
->
u
.
mode
=
IW_MODE_ADHOC
;
break
;
#else
/* WIRELESS_EXT > 8 */
#else
/* WIRELESS_EXT > 8 */
case
SIOCGIWENCODE
:
case
SIOCGIWENCODE
:
/* Get scramble key */
/* Get scramble key */
wrq
->
u
.
encoding
.
code
=
scramble_key
;
ret
=
netwave_get_scramble
(
dev
,
NULL
,
&
(
wrq
->
u
),
wrq
->
u
.
encoding
.
method
=
1
;
(
char
*
)
&
wrq
->
u
.
encoding
.
code
)
;
break
;
break
;
case
SIOCSIWENCODE
:
case
SIOCSIWENCODE
:
/* Set scramble key */
/* Set scramble key */
scramble_key
=
wrq
->
u
.
encoding
.
code
;
ret
=
netwave_set_scramble
(
dev
,
NULL
,
&
(
wrq
->
u
),
wait_WOC
(
iobase
);
(
char
*
)
&
wrq
->
u
.
encoding
.
code
);
writeb
(
NETWAVE_CMD_SSK
,
ramBase
+
NETWAVE_EREG_CB
+
0
);
writeb
(
scramble_key
&
0xff
,
ramBase
+
NETWAVE_EREG_CB
+
1
);
writeb
((
scramble_key
>>
8
)
&
0xff
,
ramBase
+
NETWAVE_EREG_CB
+
2
);
writeb
(
NETWAVE_CMD_EOC
,
ramBase
+
NETWAVE_EREG_CB
+
3
);
break
;
break
;
#endif
/* WIRELESS_EXT > 8 */
#endif
/* WIRELESS_EXT > 8 */
case
SIOCGIWRANGE
:
case
SIOCGIWRANGE
:
/* Basic checking... */
/* Basic checking... */
if
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
)
{
if
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
)
{
struct
iw_range
range
;
struct
iw_range
range
;
ret
=
netwave_get_range
(
dev
,
NULL
,
&
(
wrq
->
u
),
(
char
*
)
&
range
);
/* Set the length (very important for backward compatibility) */
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
&
range
,
wrq
->
u
.
data
.
length
=
sizeof
(
struct
iw_range
);
sizeof
(
struct
iw_range
)))
ret
=
-
EFAULT
;
/* Set all the info we don't care or don't know about to zero */
memset
(
&
range
,
0
,
sizeof
(
range
));
#if WIRELESS_EXT > 10
/* Set the Wireless Extension versions */
range
.
we_version_compiled
=
WIRELESS_EXT
;
range
.
we_version_source
=
9
;
/* Nothing for us in v10 and v11 */
#endif
/* WIRELESS_EXT > 10 */
/* Set information in the range struct */
range
.
throughput
=
450
*
1000
;
/* don't argue on this ! */
range
.
min_nwid
=
0x0000
;
range
.
max_nwid
=
0x01FF
;
range
.
num_channels
=
range
.
num_frequency
=
0
;
range
.
sensitivity
=
0x3F
;
range
.
max_qual
.
qual
=
255
;
range
.
max_qual
.
level
=
255
;
range
.
max_qual
.
noise
=
0
;
#if WIRELESS_EXT > 7
range
.
num_bitrates
=
1
;
range
.
bitrate
[
0
]
=
1000000
;
/* 1 Mb/s */
#endif
/* WIRELESS_EXT > 7 */
#if WIRELESS_EXT > 8
range
.
encoding_size
[
0
]
=
2
;
/* 16 bits scrambling */
range
.
num_encoding_sizes
=
1
;
range
.
max_encoding_tokens
=
1
;
/* Only one key possible */
#endif
/* WIRELESS_EXT > 8 */
/* Copy structure to the user buffer */
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
&
range
,
sizeof
(
struct
iw_range
)))
ret
=
-
EFAULT
;
}
}
break
;
break
;
case
SIOCGIWPRIV
:
case
SIOCGIWPRIV
:
/* Basic checking... */
/* Basic checking... */
if
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
)
{
if
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
)
{
struct
iw_priv_args
priv
[]
=
{
/* cmd, set_args, get_args, name */
{
SIOCGIPSNAP
,
IW_PRIV_TYPE_BYTE
|
IW_PRIV_SIZE_FIXED
|
0
,
sizeof
(
struct
site_survey
),
"getsitesurvey"
},
};
/* Set the number of ioctl available */
/* Set the number of ioctl available */
wrq
->
u
.
data
.
length
=
1
;
wrq
->
u
.
data
.
length
=
sizeof
(
netwave_private_args
)
/
sizeof
(
netwave_private_args
[
0
])
;
/* Copy structure to the user buffer */
/* Copy structure to the user buffer */
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
(
u_char
*
)
priv
,
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
sizeof
(
priv
)))
(
u_char
*
)
netwave_private_args
,
sizeof
(
netwave_private_args
)))
ret
=
-
EFAULT
;
ret
=
-
EFAULT
;
}
}
break
;
break
;
case
SIOCGIPSNAP
:
case
SIOCGIPSNAP
:
if
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
)
{
if
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
)
{
/* Take snapshot of environment */
char
buffer
[
sizeof
(
struct
site_survey
)];
netwave_snapshot
(
priv
,
ramBase
,
iobase
);
ret
=
netwave_get_snap
(
dev
,
NULL
,
&
(
wrq
->
u
),
buffer
);
wrq
->
u
.
data
.
length
=
priv
->
nss
.
length
;
/* Copy structure to the user buffer */
/* Copy structure to the user buffer */
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
(
u_char
*
)
&
priv
->
nss
,
buffer
,
sizeof
(
struct
site_survey
)))
sizeof
(
struct
site_survey
)))
{
{
printk
(
KERN_DEBUG
"Bad buffer!
\n
"
);
printk
(
KERN_DEBUG
"Bad buffer!
\n
"
);
break
;
break
;
}
}
priv
->
lastExec
=
jiffies
;
}
}
break
;
break
;
#endif
#endif
/* WIRELESS_EXT <= 12 */
#endif
/* WIRELESS_EXT */
default:
default:
ret
=
-
EOPNOTSUPP
;
ret
=
-
EOPNOTSUPP
;
}
}
/* ReEnable interrupts & restore flags */
restore_flags
(
flags
);
return
ret
;
return
ret
;
}
}
...
...
drivers/net/wireless/wavelan.c
View file @
a5220ff4
...
@@ -1786,170 +1786,287 @@ static inline void wl_his_gather(device * dev, u8 * stats)
...
@@ -1786,170 +1786,287 @@ static inline void wl_his_gather(device * dev, u8 * stats)
/*------------------------------------------------------------------*/
/*------------------------------------------------------------------*/
/*
/*
* Perform ioctl for configuration and information.
* Wireless Handler : get protocol name
* It is here that the wireless extensions are treated (iwconfig).
*/
*/
static
int
wavelan_ioctl
(
struct
net_device
*
dev
,
/* device on which the ioctl is applied */
static
int
wavelan_get_name
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
/* data passed */
struct
iw_request_info
*
info
,
int
cmd
)
union
iwreq_data
*
wrqu
,
{
/* ioctl number */
char
*
extra
)
{
strcpy
(
wrqu
->
name
,
"WaveLAN"
);
return
0
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : set NWID
*/
static
int
wavelan_set_nwid
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
unsigned
long
ioaddr
=
dev
->
base_addr
;
unsigned
long
ioaddr
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
struct
iwreq
*
wrq
=
(
struct
iwreq
*
)
rq
;
psa_t
psa
;
psa_t
psa
;
mm_t
m
;
mm_t
m
;
unsigned
long
flags
;
unsigned
long
flags
;
int
ret
=
0
;
int
ret
=
0
;
int
err
=
0
;
#ifdef DEBUG_IOCTL_TRACE
/* Disable interrupts and save flags. */
printk
(
KERN_DEBUG
"%s: ->wavelan_ioctl(cmd=0x%X)
\n
"
,
dev
->
name
,
wv_splhi
(
lp
,
&
flags
);
cmd
);
#endif
/* Set NWID in WaveLAN. */
if
(
!
wrqu
->
nwid
.
disabled
)
{
/* Set NWID in psa */
psa
.
psa_nwid
[
0
]
=
(
wrqu
->
nwid
.
value
&
0xFF00
)
>>
8
;
psa
.
psa_nwid
[
1
]
=
wrqu
->
nwid
.
value
&
0xFF
;
psa
.
psa_nwid_select
=
0x01
;
psa_write
(
ioaddr
,
lp
->
hacr
,
(
char
*
)
psa
.
psa_nwid
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
psa
.
psa_nwid
,
3
);
/* Set NWID in mmc. */
m
.
w
.
mmw_netw_id_l
=
psa
.
psa_nwid
[
1
];
m
.
w
.
mmw_netw_id_h
=
psa
.
psa_nwid
[
0
];
mmc_write
(
ioaddr
,
(
char
*
)
&
m
.
w
.
mmw_netw_id_l
-
(
char
*
)
&
m
,
(
unsigned
char
*
)
&
m
.
w
.
mmw_netw_id_l
,
2
);
mmc_out
(
ioaddr
,
mmwoff
(
0
,
mmw_loopt_sel
),
0x00
);
}
else
{
/* Disable NWID in the psa. */
psa
.
psa_nwid_select
=
0x00
;
psa_write
(
ioaddr
,
lp
->
hacr
,
(
char
*
)
&
psa
.
psa_nwid_select
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_nwid_select
,
1
);
/* Disable NWID in the mmc (no filtering). */
mmc_out
(
ioaddr
,
mmwoff
(
0
,
mmw_loopt_sel
),
MMW_LOOPT_SEL_DIS_NWID
);
}
/* update the Wavelan checksum */
update_psa_checksum
(
dev
,
ioaddr
,
lp
->
hacr
);
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : get NWID
*/
static
int
wavelan_get_nwid
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
unsigned
long
ioaddr
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa_t
psa
;
unsigned
long
flags
;
int
ret
=
0
;
/* Disable interrupts and save flags. */
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
wv_splhi
(
lp
,
&
flags
);
/* Look what is the request */
/* Read the NWID. */
switch
(
cmd
)
{
psa_read
(
ioaddr
,
lp
->
hacr
,
/* --------------- WIRELESS EXTENSIONS --------------- */
(
char
*
)
psa
.
psa_nwid
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
psa
.
psa_nwid
,
3
);
case
SIOCGIWNAME
:
wrqu
->
nwid
.
value
=
(
psa
.
psa_nwid
[
0
]
<<
8
)
+
psa
.
psa_nwid
[
1
];
strcpy
(
wrq
->
u
.
name
,
"WaveLAN"
);
wrqu
->
nwid
.
disabled
=
!
(
psa
.
psa_nwid_select
);
break
;
wrqu
->
nwid
.
fixed
=
1
;
/* Superfluous */
case
SIOCSIWNWID
:
/* Set NWID in WaveLAN. */
if
(
!
wrq
->
u
.
nwid
.
disabled
)
{
/* Set NWID in psa */
psa
.
psa_nwid
[
0
]
=
(
wrq
->
u
.
nwid
.
value
&
0xFF00
)
>>
8
;
psa
.
psa_nwid
[
1
]
=
wrq
->
u
.
nwid
.
value
&
0xFF
;
psa
.
psa_nwid_select
=
0x01
;
psa_write
(
ioaddr
,
lp
->
hacr
,
(
char
*
)
psa
.
psa_nwid
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
psa
.
psa_nwid
,
3
);
/* Set NWID in mmc. */
m
.
w
.
mmw_netw_id_l
=
psa
.
psa_nwid
[
1
];
m
.
w
.
mmw_netw_id_h
=
psa
.
psa_nwid
[
0
];
mmc_write
(
ioaddr
,
(
char
*
)
&
m
.
w
.
mmw_netw_id_l
-
(
char
*
)
&
m
,
(
unsigned
char
*
)
&
m
.
w
.
mmw_netw_id_l
,
2
);
mmc_out
(
ioaddr
,
mmwoff
(
0
,
mmw_loopt_sel
),
0x00
);
}
else
{
/* Disable NWID in the psa. */
psa
.
psa_nwid_select
=
0x00
;
psa_write
(
ioaddr
,
lp
->
hacr
,
(
char
*
)
&
psa
.
psa_nwid_select
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_nwid_select
,
1
);
/* Disable NWID in the mmc (no filtering). */
/* Enable interrupts and restore flags. */
mmc_out
(
ioaddr
,
mmwoff
(
0
,
mmw_loopt_sel
),
wv_splx
(
lp
,
&
flags
);
MMW_LOOPT_SEL_DIS_NWID
);
}
/* update the Wavelan checksum */
update_psa_checksum
(
dev
,
ioaddr
,
lp
->
hacr
);
break
;
case
SIOCGIWNWID
:
return
ret
;
/* Read the NWID. */
}
psa_read
(
ioaddr
,
lp
->
hacr
,
(
char
*
)
psa
.
psa_nwid
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
psa
.
psa_nwid
,
3
);
wrq
->
u
.
nwid
.
value
=
(
psa
.
psa_nwid
[
0
]
<<
8
)
+
psa
.
psa_nwid
[
1
];
wrq
->
u
.
nwid
.
disabled
=
!
(
psa
.
psa_nwid_select
);
wrq
->
u
.
nwid
.
fixed
=
1
;
/* Superfluous */
break
;
case
SIOCSIWFREQ
:
/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
if
(
!
(
mmc_in
(
ioaddr
,
mmroff
(
0
,
mmr_fee_status
))
&
(
MMR_FEE_STATUS_DWLD
|
MMR_FEE_STATUS_BUSY
)))
ret
=
wv_set_frequency
(
ioaddr
,
&
(
wrq
->
u
.
freq
));
else
ret
=
-
EOPNOTSUPP
;
break
;
case
SIOCGIWFREQ
:
/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable).
* Does it work for everybody, especially old cards? */
if
(
!
(
mmc_in
(
ioaddr
,
mmroff
(
0
,
mmr_fee_status
))
&
(
MMR_FEE_STATUS_DWLD
|
MMR_FEE_STATUS_BUSY
)))
{
unsigned
short
freq
;
/* Ask the EEPROM to read the frequency from the first area. */
fee_read
(
ioaddr
,
0x00
,
&
freq
,
1
);
wrq
->
u
.
freq
.
m
=
((
freq
>>
5
)
*
5
+
24000L
)
*
10000
;
wrq
->
u
.
freq
.
e
=
1
;
}
else
{
psa_read
(
ioaddr
,
lp
->
hacr
,
(
char
*
)
&
psa
.
psa_subband
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_subband
,
1
);
if
(
psa
.
psa_subband
<=
4
)
{
wrq
->
u
.
freq
.
m
=
fixed_bands
[
psa
.
psa_subband
];
wrq
->
u
.
freq
.
e
=
(
psa
.
psa_subband
!=
0
);
}
else
ret
=
-
EOPNOTSUPP
;
}
break
;
case
SIOCSIWSENS
:
/*------------------------------------------------------------------*/
/* Set the level threshold. */
/*
/* We should complain loudly if wrq->u.sens.fixed = 0, because we
* Wireless Handler : set frequency
* can't set auto mode...
*/
*/
psa
.
psa_thr_pre_set
=
wrq
->
u
.
sens
.
value
&
0x3F
;
static
int
wavelan_set_freq
(
struct
net_device
*
dev
,
psa_write
(
ioaddr
,
lp
->
hacr
,
struct
iw_request_info
*
info
,
(
char
*
)
&
psa
.
psa_thr_pre_set
-
(
char
*
)
&
psa
,
union
iwreq_data
*
wrqu
,
(
unsigned
char
*
)
&
psa
.
psa_thr_pre_set
,
1
);
char
*
extra
)
/* update the Wavelan checksum */
{
update_psa_checksum
(
dev
,
ioaddr
,
lp
->
hacr
)
;
unsigned
long
ioaddr
=
dev
->
base_addr
;
mmc_out
(
ioaddr
,
mmwoff
(
0
,
mmw_thr_pre_set
),
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa
.
psa_thr_pre_set
)
;
unsigned
long
flags
;
break
;
int
ret
;
case
SIOCGIWSENS
:
/* Disable interrupts and save flags. */
/* Read the level threshold. */
wv_splhi
(
lp
,
&
flags
);
/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
if
(
!
(
mmc_in
(
ioaddr
,
mmroff
(
0
,
mmr_fee_status
))
&
(
MMR_FEE_STATUS_DWLD
|
MMR_FEE_STATUS_BUSY
)))
ret
=
wv_set_frequency
(
ioaddr
,
&
(
wrqu
->
freq
));
else
ret
=
-
EOPNOTSUPP
;
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : get frequency
*/
static
int
wavelan_get_freq
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
unsigned
long
ioaddr
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa_t
psa
;
unsigned
long
flags
;
int
ret
=
0
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable).
* Does it work for everybody, especially old cards? */
if
(
!
(
mmc_in
(
ioaddr
,
mmroff
(
0
,
mmr_fee_status
))
&
(
MMR_FEE_STATUS_DWLD
|
MMR_FEE_STATUS_BUSY
)))
{
unsigned
short
freq
;
/* Ask the EEPROM to read the frequency from the first area. */
fee_read
(
ioaddr
,
0x00
,
&
freq
,
1
);
wrqu
->
freq
.
m
=
((
freq
>>
5
)
*
5
+
24000L
)
*
10000
;
wrqu
->
freq
.
e
=
1
;
}
else
{
psa_read
(
ioaddr
,
lp
->
hacr
,
psa_read
(
ioaddr
,
lp
->
hacr
,
(
char
*
)
&
psa
.
psa_thr_pre_set
-
(
char
*
)
&
psa
,
(
char
*
)
&
psa
.
psa_subband
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_thr_pre_set
,
1
);
(
unsigned
char
*
)
&
psa
.
psa_subband
,
1
);
wrq
->
u
.
sens
.
value
=
psa
.
psa_thr_pre_set
&
0x3F
;
wrq
->
u
.
sens
.
fixed
=
1
;
if
(
psa
.
psa_subband
<=
4
)
{
break
;
wrqu
->
freq
.
m
=
fixed_bands
[
psa
.
psa_subband
];
wrqu
->
freq
.
e
=
(
psa
.
psa_subband
!=
0
);
case
SIOCSIWENCODE
:
}
else
/* Set encryption key */
if
(
!
mmc_encr
(
ioaddr
))
{
ret
=
-
EOPNOTSUPP
;
ret
=
-
EOPNOTSUPP
;
break
;
}
}
/* Basic checking... */
/* Enable interrupts and restore flags. */
if
(
wrq
->
u
.
encoding
.
pointer
!=
(
caddr_t
)
0
)
{
wv_splx
(
lp
,
&
flags
);
/* Check the size of the key */
if
(
wrq
->
u
.
encoding
.
length
!=
8
)
{
ret
=
-
EINVAL
;
break
;
}
/* Copy the key in the driver */
return
ret
;
wv_splx
(
lp
,
&
flags
);
}
err
=
copy_from_user
(
psa
.
psa_encryption_key
,
wrq
->
u
.
encoding
.
pointer
,
/*------------------------------------------------------------------*/
wrq
->
u
.
encoding
.
length
);
/*
wv_splhi
(
lp
,
&
flags
);
* Wireless Handler : set level threshold
if
(
err
)
{
*/
ret
=
-
EFAULT
;
static
int
wavelan_set_sens
(
struct
net_device
*
dev
,
break
;
struct
iw_request_info
*
info
,
}
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
unsigned
long
ioaddr
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa_t
psa
;
unsigned
long
flags
;
int
ret
=
0
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Set the level threshold. */
/* We should complain loudly if wrqu->sens.fixed = 0, because we
* can't set auto mode... */
psa
.
psa_thr_pre_set
=
wrqu
->
sens
.
value
&
0x3F
;
psa_write
(
ioaddr
,
lp
->
hacr
,
(
char
*
)
&
psa
.
psa_thr_pre_set
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_thr_pre_set
,
1
);
/* update the Wavelan checksum */
update_psa_checksum
(
dev
,
ioaddr
,
lp
->
hacr
);
mmc_out
(
ioaddr
,
mmwoff
(
0
,
mmw_thr_pre_set
),
psa
.
psa_thr_pre_set
);
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : get level threshold
*/
static
int
wavelan_get_sens
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
unsigned
long
ioaddr
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa_t
psa
;
unsigned
long
flags
;
int
ret
=
0
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Read the level threshold. */
psa_read
(
ioaddr
,
lp
->
hacr
,
(
char
*
)
&
psa
.
psa_thr_pre_set
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_thr_pre_set
,
1
);
wrqu
->
sens
.
value
=
psa
.
psa_thr_pre_set
&
0x3F
;
wrqu
->
sens
.
fixed
=
1
;
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : set encryption key
*/
static
int
wavelan_set_encode
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
unsigned
long
ioaddr
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
unsigned
long
flags
;
psa_t
psa
;
int
ret
=
0
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Check if capable of encryption */
if
(
!
mmc_encr
(
ioaddr
))
{
ret
=
-
EOPNOTSUPP
;
}
/* Check the size of the key */
if
((
wrqu
->
encoding
.
length
!=
8
)
&&
(
wrqu
->
encoding
.
length
!=
0
))
{
ret
=
-
EINVAL
;
}
if
(
!
ret
)
{
/* Basic checking... */
if
(
wrqu
->
encoding
.
length
==
8
)
{
/* Copy the key in the driver */
memcpy
(
psa
.
psa_encryption_key
,
extra
,
wrqu
->
encoding
.
length
);
psa
.
psa_encryption_select
=
1
;
psa
.
psa_encryption_select
=
1
;
psa_write
(
ioaddr
,
lp
->
hacr
,
psa_write
(
ioaddr
,
lp
->
hacr
,
(
char
*
)
&
psa
.
psa_encryption_select
-
(
char
*
)
&
psa
.
psa_encryption_select
-
(
char
*
)
&
psa
,
(
char
*
)
&
psa
,
...
@@ -1963,7 +2080,8 @@ static int wavelan_ioctl(struct net_device *dev, /* device on which the ioctl is
...
@@ -1963,7 +2080,8 @@ static int wavelan_ioctl(struct net_device *dev, /* device on which the ioctl is
psa_encryption_key
,
8
);
psa_encryption_key
,
8
);
}
}
if
(
wrq
->
u
.
encoding
.
flags
&
IW_ENCODE_DISABLED
)
{
/* disable encryption */
/* disable encryption */
if
(
wrqu
->
encoding
.
flags
&
IW_ENCODE_DISABLED
)
{
psa
.
psa_encryption_select
=
0
;
psa
.
psa_encryption_select
=
0
;
psa_write
(
ioaddr
,
lp
->
hacr
,
psa_write
(
ioaddr
,
lp
->
hacr
,
(
char
*
)
&
psa
.
psa_encryption_select
-
(
char
*
)
&
psa
.
psa_encryption_select
-
...
@@ -1975,350 +2093,430 @@ static int wavelan_ioctl(struct net_device *dev, /* device on which the ioctl is
...
@@ -1975,350 +2093,430 @@ static int wavelan_ioctl(struct net_device *dev, /* device on which the ioctl is
}
}
/* update the Wavelan checksum */
/* update the Wavelan checksum */
update_psa_checksum
(
dev
,
ioaddr
,
lp
->
hacr
);
update_psa_checksum
(
dev
,
ioaddr
,
lp
->
hacr
);
break
;
}
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : get encryption key
*/
static
int
wavelan_get_encode
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
unsigned
long
ioaddr
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa_t
psa
;
unsigned
long
flags
;
int
ret
=
0
;
case
SIOCGIWENCODE
:
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Check if encryption is available */
if
(
!
mmc_encr
(
ioaddr
))
{
ret
=
-
EOPNOTSUPP
;
}
else
{
/* Read the encryption key */
/* Read the encryption key */
if
(
!
mmc_encr
(
ioaddr
))
{
psa_read
(
ioaddr
,
lp
->
hacr
,
ret
=
-
EOPNOTSUPP
;
(
char
*
)
&
psa
.
psa_encryption_select
-
break
;
(
char
*
)
&
psa
,
}
(
unsigned
char
*
)
&
psa
.
psa_encryption_select
,
1
+
8
);
/* encryption is enabled ? */
if
(
psa
.
psa_encryption_select
)
wrqu
->
encoding
.
flags
=
IW_ENCODE_ENABLED
;
else
wrqu
->
encoding
.
flags
=
IW_ENCODE_DISABLED
;
wrqu
->
encoding
.
flags
|=
mmc_encr
(
ioaddr
);
/* only super-user can see encryption key */
/* Copy the key to the user buffer */
if
(
!
capable
(
CAP_NET_ADMIN
))
{
wrqu
->
encoding
.
length
=
8
;
ret
=
-
EPERM
;
memcpy
(
extra
,
psa
.
psa_encryption_key
,
wrqu
->
encoding
.
length
);
break
;
}
}
/* Basic checking... */
/* Enable interrupts and restore flags. */
if
(
wrq
->
u
.
encoding
.
pointer
!=
(
caddr_t
)
0
)
{
wv_splx
(
lp
,
&
flags
);
/* Verify the user buffer */
ret
=
verify_area
(
VERIFY_WRITE
,
wrq
->
u
.
encoding
.
pointer
,
8
);
if
(
ret
)
break
;
psa_read
(
ioaddr
,
lp
->
hacr
,
return
ret
;
(
char
*
)
&
psa
.
psa_encryption_select
-
}
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_encryption_select
,
1
+
8
);
/* encryption is enabled ? */
/*------------------------------------------------------------------*/
if
(
psa
.
psa_encryption_select
)
/*
wrq
->
u
.
encoding
.
flags
=
IW_ENCODE_ENABLED
;
* Wireless Handler : get range info
else
*/
wrq
->
u
.
encoding
.
flags
=
IW_ENCODE_DISABLED
;
static
int
wavelan_get_range
(
struct
net_device
*
dev
,
wrq
->
u
.
encoding
.
flags
|=
mmc_encr
(
ioaddr
);
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
/* Copy the key to the user buffer */
char
*
extra
)
wrq
->
u
.
encoding
.
length
=
8
;
{
wv_splx
(
lp
,
&
flags
);
unsigned
long
ioaddr
=
dev
->
base_addr
;
if
(
copy_to_user
(
wrq
->
u
.
encoding
.
pointer
,
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa
.
psa_encryption_key
,
8
))
struct
iw_range
*
range
=
(
struct
iw_range
*
)
extra
;
ret
=
-
EFAULT
;
unsigned
long
flags
;
wv_splhi
(
lp
,
&
flags
);
int
ret
=
0
;
}
break
;
case
SIOCGIWRANGE
:
/* basic checking */
if
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
)
{
struct
iw_range
range
;
/* Set the length (very important for backward
* compatibility) */
wrq
->
u
.
data
.
length
=
sizeof
(
struct
iw_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
=
9
;
/* Set information in the range struct. */
range
.
throughput
=
1
.
6
*
1000
*
1000
;
/* don't argue on this ! */
range
.
min_nwid
=
0x0000
;
range
.
max_nwid
=
0xFFFF
;
/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
if
(
!
(
mmc_in
(
ioaddr
,
mmroff
(
0
,
mmr_fee_status
))
&
(
MMR_FEE_STATUS_DWLD
|
MMR_FEE_STATUS_BUSY
)))
{
range
.
num_channels
=
10
;
range
.
num_frequency
=
wv_frequency_list
(
ioaddr
,
range
.
freq
,
IW_MAX_FREQUENCIES
);
}
else
range
.
num_channels
=
range
.
num_frequency
=
0
;
range
.
sensitivity
=
0x3F
;
range
.
max_qual
.
qual
=
MMR_SGNL_QUAL
;
range
.
max_qual
.
level
=
MMR_SIGNAL_LVL
;
range
.
max_qual
.
noise
=
MMR_SILENCE_LVL
;
range
.
avg_qual
.
qual
=
MMR_SGNL_QUAL
;
/* Always max */
/* Need to get better values for those two */
range
.
avg_qual
.
level
=
30
;
range
.
avg_qual
.
noise
=
8
;
range
.
num_bitrates
=
1
;
range
.
bitrate
[
0
]
=
2000000
;
/* 2 Mb/s */
/* Encryption supported ? */
if
(
mmc_encr
(
ioaddr
))
{
range
.
encoding_size
[
0
]
=
8
;
/* DES = 64 bits key */
range
.
num_encoding_sizes
=
1
;
range
.
max_encoding_tokens
=
1
;
/* Only one key possible */
}
else
{
range
.
num_encoding_sizes
=
0
;
range
.
max_encoding_tokens
=
0
;
}
/* Copy structure to the user buffer. */
/* Set the length (very important for backward compatibility) */
wv_splx
(
lp
,
&
flags
);
wrqu
->
data
.
length
=
sizeof
(
struct
iw_range
);
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
&
range
,
/* Set all the info we don't care or don't know about to zero */
sizeof
(
struct
iw_range
)))
memset
(
range
,
0
,
sizeof
(
struct
iw_range
));
ret
=
-
EFAULT
;
wv_splhi
(
lp
,
&
flags
);
/* Set the Wireless Extension versions */
}
range
->
we_version_compiled
=
WIRELESS_EXT
;
break
;
range
->
we_version_source
=
9
;
case
SIOCGIWPRIV
:
/* Set information in the range struct. */
/* Basic checking */
range
->
throughput
=
1
.
6
*
1000
*
1000
;
/* don't argue on this ! */
if
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
)
{
range
->
min_nwid
=
0x0000
;
struct
iw_priv_args
priv
[]
=
{
range
->
max_nwid
=
0xFFFF
;
/* { cmd,
set_args,
range
->
sensitivity
=
0x3F
;
get_args,
range
->
max_qual
.
qual
=
MMR_SGNL_QUAL
;
name } */
range
->
max_qual
.
level
=
MMR_SIGNAL_LVL
;
{
SIOCSIPQTHR
,
range
->
max_qual
.
noise
=
MMR_SILENCE_LVL
;
IW_PRIV_TYPE_BYTE
|
IW_PRIV_SIZE_FIXED
|
1
,
range
->
avg_qual
.
qual
=
MMR_SGNL_QUAL
;
/* Always max */
0
,
/* Need to get better values for those two */
"setqualthr"
},
range
->
avg_qual
.
level
=
30
;
{
SIOCGIPQTHR
,
range
->
avg_qual
.
noise
=
8
;
0
,
IW_PRIV_TYPE_BYTE
|
IW_PRIV_SIZE_FIXED
|
1
,
range
->
num_bitrates
=
1
;
"getqualthr"
},
range
->
bitrate
[
0
]
=
2000000
;
/* 2 Mb/s */
{
SIOCSIPHISTO
,
IW_PRIV_TYPE_BYTE
|
16
,
/* Disable interrupts and save flags. */
0
,
wv_splhi
(
lp
,
&
flags
);
"sethisto"
},
{
SIOCGIPHISTO
,
/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
0
,
if
(
!
(
mmc_in
(
ioaddr
,
mmroff
(
0
,
mmr_fee_status
))
&
IW_PRIV_TYPE_INT
|
16
,
(
MMR_FEE_STATUS_DWLD
|
MMR_FEE_STATUS_BUSY
)))
{
"gethisto"
},
range
->
num_channels
=
10
;
};
range
->
num_frequency
=
wv_frequency_list
(
ioaddr
,
range
->
freq
,
IW_MAX_FREQUENCIES
);
/* Set the number of available ioctls. */
}
else
wrq
->
u
.
data
.
length
=
4
;
range
->
num_channels
=
range
->
num_frequency
=
0
;
/* Copy structure to the user buffer. */
/* Encryption supported ? */
wv_splx
(
lp
,
&
flags
);
if
(
mmc_encr
(
ioaddr
))
{
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
range
->
encoding_size
[
0
]
=
8
;
/* DES = 64 bits key */
(
u8
*
)
priv
,
range
->
num_encoding_sizes
=
1
;
sizeof
(
priv
)))
range
->
max_encoding_tokens
=
1
;
/* Only one key possible */
ret
=
-
EFAULT
;
}
else
{
wv_splhi
(
lp
,
&
flags
);
range
->
num_encoding_sizes
=
0
;
}
range
->
max_encoding_tokens
=
0
;
break
;
}
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
#ifdef WIRELESS_SPY
#ifdef WIRELESS_SPY
case
SIOCSIWSPY
:
/*------------------------------------------------------------------*/
/* Set the spy list */
/*
* Wireless Handler : set spy list
*/
static
int
wavelan_set_spy
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
struct
sockaddr
*
address
=
(
struct
sockaddr
*
)
extra
;
int
i
;
int
ret
=
0
;
/* Check the number of addresses. */
/* Disable spy while we copy the addresses.
if
(
wrq
->
u
.
data
.
length
>
IW_MAX_SPY
)
{
* As we don't disable interrupts, we need to do this */
ret
=
-
E2BIG
;
lp
->
spy_number
=
0
;
break
;
}
lp
->
spy_number
=
wrq
->
u
.
data
.
length
;
/* Are there are addresses to copy? */
if
(
lp
->
spy_number
>
0
)
{
struct
sockaddr
address
[
IW_MAX_SPY
];
int
i
;
/* Copy addresses to the driver. */
wv_splx
(
lp
,
&
flags
);
err
=
copy_from_user
(
address
,
wrq
->
u
.
data
.
pointer
,
sizeof
(
struct
sockaddr
)
*
lp
->
spy_number
);
wv_splhi
(
lp
,
&
flags
);
if
(
err
)
{
ret
=
-
EFAULT
;
break
;
}
/* Copy addresses to the lp structure. */
/* Are there are addresses to copy? */
for
(
i
=
0
;
i
<
lp
->
spy_number
;
i
++
)
{
if
(
wrqu
->
data
.
length
>
0
)
{
memcpy
(
lp
->
spy_address
[
i
],
/* Copy addresses to the lp structure. */
address
[
i
].
sa_data
,
for
(
i
=
0
;
i
<
wrqu
->
data
.
length
;
i
++
)
{
WAVELAN_ADDR_SIZE
);
memcpy
(
lp
->
spy_address
[
i
],
address
[
i
].
sa_data
,
}
WAVELAN_ADDR_SIZE
);
}
/* Reset structure. */
/* Reset structure. */
memset
(
lp
->
spy_stat
,
0x00
,
memset
(
lp
->
spy_stat
,
0x00
,
sizeof
(
iw_qual
)
*
IW_MAX_SPY
);
sizeof
(
iw_qual
)
*
IW_MAX_SPY
);
#ifdef DEBUG_IOCTL_INFO
#ifdef DEBUG_IOCTL_INFO
printk
(
KERN_DEBUG
"SetSpy: set of new addresses is:
\n
"
);
for
(
i
=
0
;
i
<
wrqu
->
data
.
length
;
i
++
)
printk
(
KERN_DEBUG
printk
(
KERN_DEBUG
"SetSpy: set of new addresses is:
\n
"
);
"%02X:%02X:%02X:%02X:%02X:%02X
\n
"
,
for
(
i
=
0
;
i
<
wrq
->
u
.
data
.
length
;
i
++
)
lp
->
spy_address
[
i
][
0
],
printk
(
KERN_DEBUG
lp
->
spy_address
[
i
][
1
],
"%02X:%02X:%02X:%02X:%02X:%02X
\n
"
,
lp
->
spy_address
[
i
][
2
],
lp
->
spy_address
[
i
][
0
],
lp
->
spy_address
[
i
][
3
],
lp
->
spy_address
[
i
][
1
],
lp
->
spy_address
[
i
][
4
],
lp
->
spy_address
[
i
][
2
],
lp
->
spy_address
[
i
][
5
]);
lp
->
spy_address
[
i
][
3
],
#endif
/* DEBUG_IOCTL_INFO */
lp
->
spy_address
[
i
][
4
],
}
lp
->
spy_address
[
i
][
5
]);
#endif
/* DEBUG_IOCTL_INFO */
}
break
;
/* Now we can set the number of addresses */
lp
->
spy_number
=
wrqu
->
data
.
length
;
case
SIOCGIWSPY
:
return
ret
;
/* Get the spy list and spy stats. */
}
/* Set the number of addresses */
/*------------------------------------------------------------------*/
wrq
->
u
.
data
.
length
=
lp
->
spy_number
;
/*
* Wireless Handler : get spy list
*/
static
int
wavelan_get_spy
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
struct
sockaddr
*
address
=
(
struct
sockaddr
*
)
extra
;
int
i
;
/* Does the user want to have the addresses back? */
/* Set the number of addresses */
if
((
lp
->
spy_number
>
0
)
wrqu
->
data
.
length
=
lp
->
spy_number
;
&&
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
))
{
struct
sockaddr
address
[
IW_MAX_SPY
];
int
i
;
/* Copy addresses from the lp structure. */
/* Copy addresses from the lp structure. */
for
(
i
=
0
;
i
<
lp
->
spy_number
;
i
++
)
{
for
(
i
=
0
;
i
<
lp
->
spy_number
;
i
++
)
{
memcpy
(
address
[
i
].
sa_data
,
memcpy
(
address
[
i
].
sa_data
,
lp
->
spy_address
[
i
],
lp
->
spy_address
[
i
],
WAVELAN_ADDR_SIZE
);
WAVELAN_ADDR_SIZE
);
address
[
i
].
sa_family
=
AF_UNIX
;
address
[
i
].
sa_family
=
AF_UNIX
;
}
}
/* Copy stats to the user buffer (just after). */
if
(
lp
->
spy_number
>
0
)
memcpy
(
extra
+
(
sizeof
(
struct
sockaddr
)
*
lp
->
spy_number
),
lp
->
spy_stat
,
sizeof
(
iw_qual
)
*
lp
->
spy_number
);
/* Copy addresses to the user buffer. */
/* Reset updated flags. */
wv_splx
(
lp
,
&
flags
);
for
(
i
=
0
;
i
<
lp
->
spy_number
;
i
++
)
err
=
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
lp
->
spy_stat
[
i
].
updated
=
0x0
;
address
,
sizeof
(
struct
sockaddr
)
*
lp
->
spy_number
);
/* Copy stats to the user buffer (just after). */
err
|=
copy_to_user
(
wrq
->
u
.
data
.
pointer
+
(
sizeof
(
struct
sockaddr
)
*
lp
->
spy_number
),
lp
->
spy_stat
,
sizeof
(
iw_qual
)
*
lp
->
spy_number
);
wv_splhi
(
lp
,
&
flags
);
if
(
err
)
{
ret
=
-
EFAULT
;
break
;
}
/* Reset updated flags. */
return
(
0
);
for
(
i
=
0
;
i
<
lp
->
spy_number
;
i
++
)
}
lp
->
spy_stat
[
i
].
updated
=
0x0
;
#endif
/* WIRELESS_SPY */
}
/* if(pointer != NULL) */
break
;
#endif
/* WIRELESS_SPY */
/* ------------------ PRIVATE IOCTL ------------------ */
/*------------------------------------------------------------------*/
/*
* Wireless Private Handler : set quality threshold
*/
static
int
wavelan_set_qthr
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
unsigned
long
ioaddr
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa_t
psa
;
unsigned
long
flags
;
case
SIOCSIPQTHR
:
/* Disable interrupts and save flags. */
if
(
!
capable
(
CAP_NET_ADMIN
))
{
wv_splhi
(
lp
,
&
flags
);
ret
=
-
EPERM
;
break
;
psa
.
psa_quality_thr
=
*
(
extra
)
&
0x0F
;
}
psa_write
(
ioaddr
,
lp
->
hacr
,
psa
.
psa_quality_thr
=
*
(
wrq
->
u
.
name
)
&
0x0F
;
(
char
*
)
&
psa
.
psa_quality_thr
-
(
char
*
)
&
psa
,
psa_write
(
ioaddr
,
lp
->
hacr
,
(
unsigned
char
*
)
&
psa
.
psa_quality_thr
,
1
);
(
char
*
)
&
psa
.
psa_quality_thr
-
(
char
*
)
&
psa
,
/* update the Wavelan checksum */
(
unsigned
char
*
)
&
psa
.
psa_quality_thr
,
1
);
update_psa_checksum
(
dev
,
ioaddr
,
lp
->
hacr
);
/* update the Wavelan checksum */
mmc_out
(
ioaddr
,
mmwoff
(
0
,
mmw_quality_thr
),
update_psa_checksum
(
dev
,
ioaddr
,
lp
->
hacr
);
psa
.
psa_quality_thr
);
mmc_out
(
ioaddr
,
mmwoff
(
0
,
mmw_quality_thr
),
psa
.
psa_quality_thr
);
break
;
case
SIOCGIPQTHR
:
/* Enable interrupts and restore flags. */
psa_read
(
ioaddr
,
lp
->
hacr
,
wv_splx
(
lp
,
&
flags
);
(
char
*
)
&
psa
.
psa_quality_thr
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_quality_thr
,
1
);
return
0
;
*
(
wrq
->
u
.
name
)
=
psa
.
psa_quality_thr
&
0x0F
;
}
break
;
/*------------------------------------------------------------------*/
/*
* Wireless Private Handler : get quality threshold
*/
static
int
wavelan_get_qthr
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
unsigned
long
ioaddr
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa_t
psa
;
unsigned
long
flags
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
psa_read
(
ioaddr
,
lp
->
hacr
,
(
char
*
)
&
psa
.
psa_quality_thr
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_quality_thr
,
1
);
*
(
extra
)
=
psa
.
psa_quality_thr
&
0x0F
;
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
0
;
}
#ifdef HISTOGRAM
#ifdef HISTOGRAM
case
SIOCSIPHISTO
:
/*------------------------------------------------------------------*/
/* Verify that the user is root. */
/*
if
(
!
capable
(
CAP_NET_ADMIN
))
{
* Wireless Private Handler : set histogram
ret
=
-
EPERM
;
*/
break
;
static
int
wavelan_set_histo
(
struct
net_device
*
dev
,
}
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
/* Check the number of intervals. */
/* Check the number of intervals. */
if
(
wrq
->
u
.
data
.
length
>
16
)
{
if
(
wrqu
->
data
.
length
>
16
)
{
ret
=
-
E2BIG
;
return
(
-
E2BIG
);
break
;
}
}
lp
->
his_number
=
wrq
->
u
.
data
.
length
;
/* Are there addresses to copy? */
if
(
lp
->
his_number
>
0
)
{
/* Copy interval ranges to the driver */
wv_splx
(
lp
,
&
flags
);
err
=
copy_from_user
(
lp
->
his_range
,
wrq
->
u
.
data
.
pointer
,
sizeof
(
char
)
*
lp
->
his_number
);
wv_splhi
(
lp
,
&
flags
);
if
(
err
)
{
ret
=
-
EFAULT
;
break
;
}
/* Reset structure. */
/* Disable histo while we copy the addresses.
memset
(
lp
->
his_sum
,
0x00
,
sizeof
(
long
)
*
16
);
* As we don't disable interrupts, we need to do this */
lp
->
his_number
=
0
;
/* Are there ranges to copy? */
if
(
wrqu
->
data
.
length
>
0
)
{
/* Copy interval ranges to the driver */
memcpy
(
lp
->
his_range
,
extra
,
wrqu
->
data
.
length
);
{
int
i
;
printk
(
KERN_DEBUG
"Histo :"
);
for
(
i
=
0
;
i
<
wrqu
->
data
.
length
;
i
++
)
printk
(
" %d"
,
lp
->
his_range
[
i
]);
printk
(
"
\n
"
);
}
}
break
;
case
SIOCGIPHISTO
:
/* Set the number of intervals. */
wrq
->
u
.
data
.
length
=
lp
->
his_number
;
/* Give back the distribution statistics */
if
((
lp
->
his_number
>
0
)
&&
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
))
{
/* Copy data to the user buffer. */
wv_splx
(
lp
,
&
flags
);
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
lp
->
his_sum
,
sizeof
(
long
)
*
lp
->
his_number
);
ret
=
-
EFAULT
;
wv_splhi
(
lp
,
&
flags
);
}
/* if(pointer != NULL) */
break
;
#endif
/* HISTOGRAM */
/* ------------------- OTHER IOCTL ------------------- */
/* Reset result structure. */
memset
(
lp
->
his_sum
,
0x00
,
sizeof
(
long
)
*
16
);
}
default:
/* Now we can set the number of ranges */
ret
=
-
EOPNOTSUPP
;
lp
->
his_number
=
wrqu
->
data
.
length
;
}
/* switch (cmd) */
/* Enable interrupts and restore flags. */
return
(
0
);
wv_splx
(
lp
,
&
flags
);
}
#ifdef DEBUG_IOCTL_TRACE
/*------------------------------------------------------------------*/
printk
(
KERN_DEBUG
"%s: <-wavelan_ioctl()
\n
"
,
dev
->
name
);
/*
#endif
* Wireless Private Handler : get histogram
return
ret
;
*/
static
int
wavelan_get_histo
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
/* Set the number of intervals. */
wrqu
->
data
.
length
=
lp
->
his_number
;
/* Give back the distribution statistics */
if
(
lp
->
his_number
>
0
)
memcpy
(
extra
,
lp
->
his_sum
,
sizeof
(
long
)
*
lp
->
his_number
);
return
(
0
);
}
}
#endif
/* HISTOGRAM */
/*------------------------------------------------------------------*/
/*
* Structures to export the Wireless Handlers
*/
static
const
iw_handler
wavelan_handler
[]
=
{
NULL
,
/* SIOCSIWNAME */
wavelan_get_name
,
/* SIOCGIWNAME */
wavelan_set_nwid
,
/* SIOCSIWNWID */
wavelan_get_nwid
,
/* SIOCGIWNWID */
wavelan_set_freq
,
/* SIOCSIWFREQ */
wavelan_get_freq
,
/* SIOCGIWFREQ */
NULL
,
/* SIOCSIWMODE */
NULL
,
/* SIOCGIWMODE */
wavelan_set_sens
,
/* SIOCSIWSENS */
wavelan_get_sens
,
/* SIOCGIWSENS */
NULL
,
/* SIOCSIWRANGE */
wavelan_get_range
,
/* SIOCGIWRANGE */
NULL
,
/* SIOCSIWPRIV */
NULL
,
/* SIOCGIWPRIV */
NULL
,
/* SIOCSIWSTATS */
NULL
,
/* SIOCGIWSTATS */
#ifdef WIRELESS_SPY
wavelan_set_spy
,
/* SIOCSIWSPY */
wavelan_get_spy
,
/* SIOCGIWSPY */
#else
/* WIRELESS_SPY */
NULL
,
/* SIOCSIWSPY */
NULL
,
/* SIOCGIWSPY */
#endif
/* WIRELESS_SPY */
NULL
,
/* -- hole -- */
NULL
,
/* -- hole -- */
NULL
,
/* SIOCSIWAP */
NULL
,
/* SIOCGIWAP */
NULL
,
/* -- hole -- */
NULL
,
/* SIOCGIWAPLIST */
NULL
,
/* -- hole -- */
NULL
,
/* -- hole -- */
NULL
,
/* SIOCSIWESSID */
NULL
,
/* SIOCGIWESSID */
NULL
,
/* SIOCSIWNICKN */
NULL
,
/* SIOCGIWNICKN */
NULL
,
/* -- hole -- */
NULL
,
/* -- hole -- */
NULL
,
/* SIOCSIWRATE */
NULL
,
/* SIOCGIWRATE */
NULL
,
/* SIOCSIWRTS */
NULL
,
/* SIOCGIWRTS */
NULL
,
/* SIOCSIWFRAG */
NULL
,
/* SIOCGIWFRAG */
NULL
,
/* SIOCSIWTXPOW */
NULL
,
/* SIOCGIWTXPOW */
NULL
,
/* SIOCSIWRETRY */
NULL
,
/* SIOCGIWRETRY */
/* Bummer ! Why those are only at the end ??? */
wavelan_set_encode
,
/* SIOCSIWENCODE */
wavelan_get_encode
,
/* SIOCGIWENCODE */
};
static
const
iw_handler
wavelan_private_handler
[]
=
{
wavelan_set_qthr
,
/* SIOCIWFIRSTPRIV */
wavelan_get_qthr
,
/* SIOCIWFIRSTPRIV + 1 */
#ifdef HISTOGRAM
wavelan_set_histo
,
/* SIOCIWFIRSTPRIV + 2 */
wavelan_get_histo
,
/* SIOCIWFIRSTPRIV + 3 */
#endif
/* HISTOGRAM */
};
static
const
struct
iw_priv_args
wavelan_private_args
[]
=
{
/*{ cmd, set_args, get_args, name } */
{
SIOCSIPQTHR
,
IW_PRIV_TYPE_BYTE
|
IW_PRIV_SIZE_FIXED
|
1
,
0
,
"setqualthr"
},
{
SIOCGIPQTHR
,
0
,
IW_PRIV_TYPE_BYTE
|
IW_PRIV_SIZE_FIXED
|
1
,
"getqualthr"
},
{
SIOCSIPHISTO
,
IW_PRIV_TYPE_BYTE
|
16
,
0
,
"sethisto"
},
{
SIOCGIPHISTO
,
0
,
IW_PRIV_TYPE_INT
|
16
,
"gethisto"
},
};
static
const
struct
iw_handler_def
wavelan_handler_def
=
{
num_standard:
sizeof
(
wavelan_handler
)
/
sizeof
(
iw_handler
),
num_private:
sizeof
(
wavelan_private_handler
)
/
sizeof
(
iw_handler
),
num_private_args:
sizeof
(
wavelan_private_args
)
/
sizeof
(
struct
iw_priv_args
),
standard:
(
iw_handler
*
)
wavelan_handler
,
private:
(
iw_handler
*
)
wavelan_private_handler
,
private_args:
(
struct
iw_priv_args
*
)
wavelan_private_args
,
};
/*------------------------------------------------------------------*/
/*------------------------------------------------------------------*/
/*
/*
...
@@ -4069,8 +4267,8 @@ static int __init wavelan_config(device * dev)
...
@@ -4069,8 +4267,8 @@ static int __init wavelan_config(device * dev)
#endif
/* SET_MAC_ADDRESS */
#endif
/* SET_MAC_ADDRESS */
#ifdef WIRELESS_EXT
/* if wireless extension exists in the kernel */
#ifdef WIRELESS_EXT
/* if wireless extension exists in the kernel */
dev
->
do_ioctl
=
wavelan_ioctl
;
dev
->
get_wireless_stats
=
wavelan_get_wireless_stats
;
dev
->
get_wireless_stats
=
wavelan_get_wireless_stats
;
dev
->
wireless_handlers
=
(
struct
iw_handler_def
*
)
&
wavelan_handler_def
;
#endif
#endif
dev
->
mtu
=
WAVELAN_MTU
;
dev
->
mtu
=
WAVELAN_MTU
;
...
...
drivers/net/wireless/wavelan.p.h
View file @
a5220ff4
...
@@ -345,6 +345,12 @@
...
@@ -345,6 +345,12 @@
* - Fix spinlock stupid bugs that I left in. The driver is now SMP
* - Fix spinlock stupid bugs that I left in. The driver is now SMP
* compliant and doesn't lockup at startup.
* compliant and doesn't lockup at startup.
*
*
* Changes made for release in 2.5.2 :
* ---------------------------------
* - Use new driver API for Wireless Extensions :
* o got rid of wavelan_ioctl()
* o use a bunch of iw_handler instead
*
* Wishes & dreams:
* Wishes & dreams:
* ----------------
* ----------------
* - roaming (see Pcmcia driver)
* - roaming (see Pcmcia driver)
...
@@ -379,6 +385,7 @@
...
@@ -379,6 +385,7 @@
#include <linux/init.h>
#include <linux/init.h>
#include <linux/wireless.h>
/* Wireless extensions */
#include <linux/wireless.h>
/* Wireless extensions */
#include <net/iw_handler.h>
/* Wireless handlers */
/* WaveLAN declarations */
/* WaveLAN declarations */
#include "i82586.h"
#include "i82586.h"
...
@@ -436,7 +443,7 @@
...
@@ -436,7 +443,7 @@
/************************ CONSTANTS & MACROS ************************/
/************************ CONSTANTS & MACROS ************************/
#ifdef DEBUG_VERSION_SHOW
#ifdef DEBUG_VERSION_SHOW
static
const
char
*
version
=
"wavelan.c : v2
3 (SMP + wireless extensions) 05/10/00
\n
"
;
static
const
char
*
version
=
"wavelan.c : v2
4 (SMP + wireless extensions) 11/12/01
\n
"
;
#endif
#endif
/* Watchdog temporisation */
/* Watchdog temporisation */
...
@@ -449,11 +456,9 @@ static const char *version = "wavelan.c : v23 (SMP + wireless extensions) 05/10/
...
@@ -449,11 +456,9 @@ static const char *version = "wavelan.c : v23 (SMP + wireless extensions) 05/10/
#define SIOCSIPQTHR SIOCIWFIRSTPRIV
/* Set quality threshold */
#define SIOCSIPQTHR SIOCIWFIRSTPRIV
/* Set quality threshold */
#define SIOCGIPQTHR SIOCIWFIRSTPRIV + 1
/* Get quality threshold */
#define SIOCGIPQTHR SIOCIWFIRSTPRIV + 1
/* Get quality threshold */
#define SIOCSIPLTHR SIOCIWFIRSTPRIV + 2
/* Set level threshold */
#define SIOCGIPLTHR SIOCIWFIRSTPRIV + 3
/* Get level threshold */
#define SIOCSIPHISTO SIOCIWFIRSTPRIV +
6
/* Set histogram ranges */
#define SIOCSIPHISTO SIOCIWFIRSTPRIV +
2
/* Set histogram ranges */
#define SIOCGIPHISTO SIOCIWFIRSTPRIV +
7
/* Get histogram values */
#define SIOCGIPHISTO SIOCIWFIRSTPRIV +
3
/* Get histogram values */
/****************************** TYPES ******************************/
/****************************** TYPES ******************************/
...
...
drivers/net/wireless/wavelan_cs.c
View file @
a5220ff4
...
@@ -1882,6 +1882,1017 @@ wl_his_gather(device * dev,
...
@@ -1882,6 +1882,1017 @@ wl_his_gather(device * dev,
}
}
#endif
/* HISTOGRAM */
#endif
/* HISTOGRAM */
/*------------------------------------------------------------------*/
/*
* Wireless Handler : get protocol name
*/
static
int
wavelan_get_name
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
strcpy
(
wrqu
->
name
,
"WaveLAN"
);
return
0
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : set NWID
*/
static
int
wavelan_set_nwid
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
ioaddr_t
base
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa_t
psa
;
mm_t
m
;
unsigned
long
flags
;
int
ret
=
0
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Set NWID in WaveLAN. */
#if WIRELESS_EXT > 8
if
(
!
wrqu
->
nwid
.
disabled
)
{
/* Set NWID in psa */
psa
.
psa_nwid
[
0
]
=
(
wrqu
->
nwid
.
value
&
0xFF00
)
>>
8
;
psa
.
psa_nwid
[
1
]
=
wrqu
->
nwid
.
value
&
0xFF
;
#else
/* WIRELESS_EXT > 8 */
if
(
wrq
->
u
.
nwid
.
on
)
{
/* Set NWID in psa */
psa
.
psa_nwid
[
0
]
=
(
wrq
->
u
.
nwid
.
nwid
&
0xFF00
)
>>
8
;
psa
.
psa_nwid
[
1
]
=
wrq
->
u
.
nwid
.
nwid
&
0xFF
;
#endif
/* WIRELESS_EXT > 8 */
psa
.
psa_nwid_select
=
0x01
;
psa_write
(
dev
,
(
char
*
)
psa
.
psa_nwid
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
psa
.
psa_nwid
,
3
);
/* Set NWID in mmc. */
m
.
w
.
mmw_netw_id_l
=
psa
.
psa_nwid
[
1
];
m
.
w
.
mmw_netw_id_h
=
psa
.
psa_nwid
[
0
];
mmc_write
(
base
,
(
char
*
)
&
m
.
w
.
mmw_netw_id_l
-
(
char
*
)
&
m
,
(
unsigned
char
*
)
&
m
.
w
.
mmw_netw_id_l
,
2
);
mmc_out
(
base
,
mmwoff
(
0
,
mmw_loopt_sel
),
0x00
);
}
else
{
/* Disable NWID in the psa. */
psa
.
psa_nwid_select
=
0x00
;
psa_write
(
dev
,
(
char
*
)
&
psa
.
psa_nwid_select
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_nwid_select
,
1
);
/* Disable NWID in the mmc (no filtering). */
mmc_out
(
base
,
mmwoff
(
0
,
mmw_loopt_sel
),
MMW_LOOPT_SEL_DIS_NWID
);
}
/* update the Wavelan checksum */
update_psa_checksum
(
dev
);
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : get NWID
*/
static
int
wavelan_get_nwid
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa_t
psa
;
unsigned
long
flags
;
int
ret
=
0
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Read the NWID. */
psa_read
(
dev
,
(
char
*
)
psa
.
psa_nwid
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
psa
.
psa_nwid
,
3
);
#if WIRELESS_EXT > 8
wrqu
->
nwid
.
value
=
(
psa
.
psa_nwid
[
0
]
<<
8
)
+
psa
.
psa_nwid
[
1
];
wrqu
->
nwid
.
disabled
=
!
(
psa
.
psa_nwid_select
);
wrqu
->
nwid
.
fixed
=
1
;
/* Superfluous */
#else
/* WIRELESS_EXT > 8 */
wrq
->
u
.
nwid
.
nwid
=
(
psa
.
psa_nwid
[
0
]
<<
8
)
+
psa
.
psa_nwid
[
1
];
wrq
->
u
.
nwid
.
on
=
psa
.
psa_nwid_select
;
#endif
/* WIRELESS_EXT > 8 */
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : set frequency
*/
static
int
wavelan_set_freq
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
ioaddr_t
base
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
unsigned
long
flags
;
int
ret
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
if
(
!
(
mmc_in
(
base
,
mmroff
(
0
,
mmr_fee_status
))
&
(
MMR_FEE_STATUS_DWLD
|
MMR_FEE_STATUS_BUSY
)))
ret
=
wv_set_frequency
(
base
,
&
(
wrqu
->
freq
));
else
ret
=
-
EOPNOTSUPP
;
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : get frequency
*/
static
int
wavelan_get_freq
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
ioaddr_t
base
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa_t
psa
;
unsigned
long
flags
;
int
ret
=
0
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable).
* Does it work for everybody, especially old cards? */
if
(
!
(
mmc_in
(
base
,
mmroff
(
0
,
mmr_fee_status
))
&
(
MMR_FEE_STATUS_DWLD
|
MMR_FEE_STATUS_BUSY
)))
{
unsigned
short
freq
;
/* Ask the EEPROM to read the frequency from the first area. */
fee_read
(
base
,
0x00
,
&
freq
,
1
);
wrqu
->
freq
.
m
=
((
freq
>>
5
)
*
5
+
24000L
)
*
10000
;
wrqu
->
freq
.
e
=
1
;
}
else
{
psa_read
(
dev
,
(
char
*
)
&
psa
.
psa_subband
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_subband
,
1
);
if
(
psa
.
psa_subband
<=
4
)
{
wrqu
->
freq
.
m
=
fixed_bands
[
psa
.
psa_subband
];
wrqu
->
freq
.
e
=
(
psa
.
psa_subband
!=
0
);
}
else
ret
=
-
EOPNOTSUPP
;
}
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : set level threshold
*/
static
int
wavelan_set_sens
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
ioaddr_t
base
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa_t
psa
;
unsigned
long
flags
;
int
ret
=
0
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Set the level threshold. */
#if WIRELESS_EXT > 7
/* We should complain loudly if wrqu->sens.fixed = 0, because we
* can't set auto mode... */
psa
.
psa_thr_pre_set
=
wrqu
->
sens
.
value
&
0x3F
;
#else
/* WIRELESS_EXT > 7 */
psa
.
psa_thr_pre_set
=
wrq
->
u
.
sensitivity
&
0x3F
;
#endif
/* WIRELESS_EXT > 7 */
psa_write
(
dev
,
(
char
*
)
&
psa
.
psa_thr_pre_set
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_thr_pre_set
,
1
);
/* update the Wavelan checksum */
update_psa_checksum
(
dev
);
mmc_out
(
base
,
mmwoff
(
0
,
mmw_thr_pre_set
),
psa
.
psa_thr_pre_set
);
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : get level threshold
*/
static
int
wavelan_get_sens
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa_t
psa
;
unsigned
long
flags
;
int
ret
=
0
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Read the level threshold. */
psa_read
(
dev
,
(
char
*
)
&
psa
.
psa_thr_pre_set
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_thr_pre_set
,
1
);
#if WIRELESS_EXT > 7
wrqu
->
sens
.
value
=
psa
.
psa_thr_pre_set
&
0x3F
;
wrqu
->
sens
.
fixed
=
1
;
#else
/* WIRELESS_EXT > 7 */
wrq
->
u
.
sensitivity
=
psa
.
psa_thr_pre_set
&
0x3F
;
#endif
/* WIRELESS_EXT > 7 */
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
#if WIRELESS_EXT > 8
/*------------------------------------------------------------------*/
/*
* Wireless Handler : set encryption key
*/
static
int
wavelan_set_encode
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
ioaddr_t
base
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
unsigned
long
flags
;
psa_t
psa
;
int
ret
=
0
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Check if capable of encryption */
if
(
!
mmc_encr
(
base
))
{
ret
=
-
EOPNOTSUPP
;
}
/* Check the size of the key */
if
((
wrqu
->
encoding
.
length
!=
8
)
&&
(
wrqu
->
encoding
.
length
!=
0
))
{
ret
=
-
EINVAL
;
}
if
(
!
ret
)
{
/* Basic checking... */
if
(
wrqu
->
encoding
.
length
==
8
)
{
/* Copy the key in the driver */
memcpy
(
psa
.
psa_encryption_key
,
extra
,
wrqu
->
encoding
.
length
);
psa
.
psa_encryption_select
=
1
;
psa_write
(
dev
,
(
char
*
)
&
psa
.
psa_encryption_select
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_encryption_select
,
8
+
1
);
mmc_out
(
base
,
mmwoff
(
0
,
mmw_encr_enable
),
MMW_ENCR_ENABLE_EN
|
MMW_ENCR_ENABLE_MODE
);
mmc_write
(
base
,
mmwoff
(
0
,
mmw_encr_key
),
(
unsigned
char
*
)
&
psa
.
psa_encryption_key
,
8
);
}
/* disable encryption */
if
(
wrqu
->
encoding
.
flags
&
IW_ENCODE_DISABLED
)
{
psa
.
psa_encryption_select
=
0
;
psa_write
(
dev
,
(
char
*
)
&
psa
.
psa_encryption_select
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_encryption_select
,
1
);
mmc_out
(
base
,
mmwoff
(
0
,
mmw_encr_enable
),
0
);
}
/* update the Wavelan checksum */
update_psa_checksum
(
dev
);
}
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : get encryption key
*/
static
int
wavelan_get_encode
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
ioaddr_t
base
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa_t
psa
;
unsigned
long
flags
;
int
ret
=
0
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Check if encryption is available */
if
(
!
mmc_encr
(
base
))
{
ret
=
-
EOPNOTSUPP
;
}
else
{
/* Read the encryption key */
psa_read
(
dev
,
(
char
*
)
&
psa
.
psa_encryption_select
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_encryption_select
,
1
+
8
);
/* encryption is enabled ? */
if
(
psa
.
psa_encryption_select
)
wrqu
->
encoding
.
flags
=
IW_ENCODE_ENABLED
;
else
wrqu
->
encoding
.
flags
=
IW_ENCODE_DISABLED
;
wrqu
->
encoding
.
flags
|=
mmc_encr
(
base
);
/* Copy the key to the user buffer */
wrqu
->
encoding
.
length
=
8
;
memcpy
(
extra
,
psa
.
psa_encryption_key
,
wrqu
->
encoding
.
length
);
}
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
#endif
/* WIRELESS_EXT > 8 */
#ifdef WAVELAN_ROAMING_EXT
#if WIRELESS_EXT > 5
/*------------------------------------------------------------------*/
/*
* Wireless Handler : set ESSID (domain)
*/
static
int
wavelan_set_essid
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
unsigned
long
flags
;
int
ret
=
0
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Check if disable */
if
(
wrqu
->
data
.
flags
==
0
)
lp
->
filter_domains
=
0
;
else
{
char
essid
[
IW_ESSID_MAX_SIZE
+
1
];
char
*
endp
;
/* Terminate the string */
memcpy
(
essid
,
extra
,
wrqu
->
data
.
length
);
essid
[
IW_ESSID_MAX_SIZE
]
=
'\0'
;
#ifdef DEBUG_IOCTL_INFO
printk
(
KERN_DEBUG
"SetEssid : ``%s''
\n
"
,
essid
);
#endif
/* DEBUG_IOCTL_INFO */
/* Convert to a number (note : Wavelan specific) */
lp
->
domain_id
=
simple_strtoul
(
essid
,
&
endp
,
16
);
/* Has it worked ? */
if
(
endp
>
essid
)
lp
->
filter_domains
=
1
;
else
{
lp
->
filter_domains
=
0
;
ret
=
-
EINVAL
;
}
}
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : get ESSID (domain)
*/
static
int
wavelan_get_essid
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
/* Is the domain ID active ? */
wrqu
->
data
.
flags
=
lp
->
filter_domains
;
/* Copy Domain ID into a string (Wavelan specific) */
/* Sound crazy, be we can't have a snprintf in the kernel !!! */
sprintf
(
extra
,
"%lX"
,
lp
->
domain_id
);
extra
[
IW_ESSID_MAX_SIZE
]
=
'\0'
;
/* Set the length */
wrqu
->
data
.
length
=
strlen
(
extra
)
+
1
;
return
0
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : set AP address
*/
static
int
wavelan_set_wap
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
#ifdef DEBUG_IOCTL_INFO
printk
(
KERN_DEBUG
"Set AP to : %02X:%02X:%02X:%02X:%02X:%02X
\n
"
,
wrqu
->
ap_addr
.
sa_data
[
0
],
wrqu
->
ap_addr
.
sa_data
[
1
],
wrqu
->
ap_addr
.
sa_data
[
2
],
wrqu
->
ap_addr
.
sa_data
[
3
],
wrqu
->
ap_addr
.
sa_data
[
4
],
wrqu
->
ap_addr
.
sa_data
[
5
]);
#endif
/* DEBUG_IOCTL_INFO */
return
-
EOPNOTSUPP
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : get AP address
*/
static
int
wavelan_get_wap
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
/* Should get the real McCoy instead of own Ethernet address */
memcpy
(
wrqu
->
ap_addr
.
sa_data
,
dev
->
dev_addr
,
WAVELAN_ADDR_SIZE
);
wrqu
->
ap_addr
.
sa_family
=
ARPHRD_ETHER
;
return
-
EOPNOTSUPP
;
}
#endif
/* WIRELESS_EXT > 5 */
#endif
/* WAVELAN_ROAMING_EXT */
#if WIRELESS_EXT > 8
#ifdef WAVELAN_ROAMING
/*------------------------------------------------------------------*/
/*
* Wireless Handler : set mode
*/
static
int
wavelan_set_mode
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
unsigned
long
flags
;
int
ret
=
0
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Check mode */
switch
(
wrqu
->
mode
)
{
case
IW_MODE_ADHOC
:
if
(
do_roaming
)
{
wv_roam_cleanup
(
dev
);
do_roaming
=
0
;
}
break
;
case
IW_MODE_INFRA
:
if
(
!
do_roaming
)
{
wv_roam_init
(
dev
);
do_roaming
=
1
;
}
break
;
default:
ret
=
-
EINVAL
;
}
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : get mode
*/
static
int
wavelan_get_mode
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
if
(
do_roaming
)
wrqu
->
mode
=
IW_MODE_INFRA
;
else
wrqu
->
mode
=
IW_MODE_ADHOC
;
return
0
;
}
#endif
/* WAVELAN_ROAMING */
#endif
/* WIRELESS_EXT > 8 */
/*------------------------------------------------------------------*/
/*
* Wireless Handler : get range info
*/
static
int
wavelan_get_range
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
ioaddr_t
base
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
struct
iw_range
*
range
=
(
struct
iw_range
*
)
extra
;
unsigned
long
flags
;
int
ret
=
0
;
/* Set the length (very important for backward compatibility) */
wrqu
->
data
.
length
=
sizeof
(
struct
iw_range
);
/* Set all the info we don't care or don't know about to zero */
memset
(
range
,
0
,
sizeof
(
struct
iw_range
));
#if WIRELESS_EXT > 10
/* Set the Wireless Extension versions */
range
->
we_version_compiled
=
WIRELESS_EXT
;
range
->
we_version_source
=
9
;
#endif
/* WIRELESS_EXT > 10 */
/* Set information in the range struct. */
range
->
throughput
=
1
.
4
*
1000
*
1000
;
/* don't argue on this ! */
range
->
min_nwid
=
0x0000
;
range
->
max_nwid
=
0xFFFF
;
range
->
sensitivity
=
0x3F
;
range
->
max_qual
.
qual
=
MMR_SGNL_QUAL
;
range
->
max_qual
.
level
=
MMR_SIGNAL_LVL
;
range
->
max_qual
.
noise
=
MMR_SILENCE_LVL
;
#if WIRELESS_EXT > 11
range
->
avg_qual
.
qual
=
MMR_SGNL_QUAL
;
/* Always max */
/* Need to get better values for those two */
range
->
avg_qual
.
level
=
30
;
range
->
avg_qual
.
noise
=
8
;
#endif
/* WIRELESS_EXT > 11 */
#if WIRELESS_EXT > 7
range
->
num_bitrates
=
1
;
range
->
bitrate
[
0
]
=
2000000
;
/* 2 Mb/s */
#endif
/* WIRELESS_EXT > 7 */
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
if
(
!
(
mmc_in
(
base
,
mmroff
(
0
,
mmr_fee_status
))
&
(
MMR_FEE_STATUS_DWLD
|
MMR_FEE_STATUS_BUSY
)))
{
range
->
num_channels
=
10
;
range
->
num_frequency
=
wv_frequency_list
(
base
,
range
->
freq
,
IW_MAX_FREQUENCIES
);
}
else
range
->
num_channels
=
range
->
num_frequency
=
0
;
#if WIRELESS_EXT > 8
/* Encryption supported ? */
if
(
mmc_encr
(
base
))
{
range
->
encoding_size
[
0
]
=
8
;
/* DES = 64 bits key */
range
->
num_encoding_sizes
=
1
;
range
->
max_encoding_tokens
=
1
;
/* Only one key possible */
}
else
{
range
->
num_encoding_sizes
=
0
;
range
->
max_encoding_tokens
=
0
;
}
#endif
/* WIRELESS_EXT > 8 */
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
ret
;
}
#ifdef WIRELESS_SPY
/*------------------------------------------------------------------*/
/*
* Wireless Handler : set spy list
*/
static
int
wavelan_set_spy
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
struct
sockaddr
*
address
=
(
struct
sockaddr
*
)
extra
;
int
i
;
int
ret
=
0
;
/* Disable spy while we copy the addresses.
* As we don't disable interrupts, we need to do this */
lp
->
spy_number
=
0
;
/* Are there are addresses to copy? */
if
(
wrqu
->
data
.
length
>
0
)
{
/* Copy addresses to the lp structure. */
for
(
i
=
0
;
i
<
wrqu
->
data
.
length
;
i
++
)
{
memcpy
(
lp
->
spy_address
[
i
],
address
[
i
].
sa_data
,
WAVELAN_ADDR_SIZE
);
}
/* Reset structure. */
memset
(
lp
->
spy_stat
,
0x00
,
sizeof
(
iw_qual
)
*
IW_MAX_SPY
);
#ifdef DEBUG_IOCTL_INFO
printk
(
KERN_DEBUG
"SetSpy: set of new addresses is:
\n
"
);
for
(
i
=
0
;
i
<
wrqu
->
data
.
length
;
i
++
)
printk
(
KERN_DEBUG
"%02X:%02X:%02X:%02X:%02X:%02X
\n
"
,
lp
->
spy_address
[
i
][
0
],
lp
->
spy_address
[
i
][
1
],
lp
->
spy_address
[
i
][
2
],
lp
->
spy_address
[
i
][
3
],
lp
->
spy_address
[
i
][
4
],
lp
->
spy_address
[
i
][
5
]);
#endif
/* DEBUG_IOCTL_INFO */
}
/* Now we can set the number of addresses */
lp
->
spy_number
=
wrqu
->
data
.
length
;
return
ret
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Handler : get spy list
*/
static
int
wavelan_get_spy
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
struct
sockaddr
*
address
=
(
struct
sockaddr
*
)
extra
;
int
i
;
/* Set the number of addresses */
wrqu
->
data
.
length
=
lp
->
spy_number
;
/* Copy addresses from the lp structure. */
for
(
i
=
0
;
i
<
lp
->
spy_number
;
i
++
)
{
memcpy
(
address
[
i
].
sa_data
,
lp
->
spy_address
[
i
],
WAVELAN_ADDR_SIZE
);
address
[
i
].
sa_family
=
AF_UNIX
;
}
/* Copy stats to the user buffer (just after). */
if
(
lp
->
spy_number
>
0
)
memcpy
(
extra
+
(
sizeof
(
struct
sockaddr
)
*
lp
->
spy_number
),
lp
->
spy_stat
,
sizeof
(
iw_qual
)
*
lp
->
spy_number
);
/* Reset updated flags. */
for
(
i
=
0
;
i
<
lp
->
spy_number
;
i
++
)
lp
->
spy_stat
[
i
].
updated
=
0x0
;
return
(
0
);
}
#endif
/* WIRELESS_SPY */
/*------------------------------------------------------------------*/
/*
* Wireless Private Handler : set quality threshold
*/
static
int
wavelan_set_qthr
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
ioaddr_t
base
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa_t
psa
;
unsigned
long
flags
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
psa
.
psa_quality_thr
=
*
(
extra
)
&
0x0F
;
psa_write
(
dev
,
(
char
*
)
&
psa
.
psa_quality_thr
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_quality_thr
,
1
);
/* update the Wavelan checksum */
update_psa_checksum
(
dev
);
mmc_out
(
base
,
mmwoff
(
0
,
mmw_quality_thr
),
psa
.
psa_quality_thr
);
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
0
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Private Handler : get quality threshold
*/
static
int
wavelan_get_qthr
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
psa_t
psa
;
unsigned
long
flags
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
psa_read
(
dev
,
(
char
*
)
&
psa
.
psa_quality_thr
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_quality_thr
,
1
);
*
(
extra
)
=
psa
.
psa_quality_thr
&
0x0F
;
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
0
;
}
#ifdef WAVELAN_ROAMING
/*------------------------------------------------------------------*/
/*
* Wireless Private Handler : set roaming
*/
static
int
wavelan_set_roam
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
unsigned
long
flags
;
/* Disable interrupts and save flags. */
wv_splhi
(
lp
,
&
flags
);
/* Note : should check if user == root */
if
(
do_roaming
&&
(
*
extra
)
==
0
)
wv_roam_cleanup
(
dev
);
else
if
(
do_roaming
==
0
&&
(
*
extra
)
!=
0
)
wv_roam_init
(
dev
);
do_roaming
=
(
*
extra
);
/* Enable interrupts and restore flags. */
wv_splx
(
lp
,
&
flags
);
return
0
;
}
/*------------------------------------------------------------------*/
/*
* Wireless Private Handler : get quality threshold
*/
static
int
wavelan_get_roam
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
*
(
extra
)
=
do_roaming
;
return
0
;
}
#endif
/* WAVELAN_ROAMING */
#ifdef HISTOGRAM
/*------------------------------------------------------------------*/
/*
* Wireless Private Handler : set histogram
*/
static
int
wavelan_set_histo
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
/* Check the number of intervals. */
if
(
wrqu
->
data
.
length
>
16
)
{
return
(
-
E2BIG
);
}
/* Disable histo while we copy the addresses.
* As we don't disable interrupts, we need to do this */
lp
->
his_number
=
0
;
/* Are there ranges to copy? */
if
(
wrqu
->
data
.
length
>
0
)
{
/* Copy interval ranges to the driver */
memcpy
(
lp
->
his_range
,
extra
,
wrqu
->
data
.
length
);
{
int
i
;
printk
(
KERN_DEBUG
"Histo :"
);
for
(
i
=
0
;
i
<
wrqu
->
data
.
length
;
i
++
)
printk
(
" %d"
,
lp
->
his_range
[
i
]);
printk
(
"
\n
"
);
}
/* Reset result structure. */
memset
(
lp
->
his_sum
,
0x00
,
sizeof
(
long
)
*
16
);
}
/* Now we can set the number of ranges */
lp
->
his_number
=
wrqu
->
data
.
length
;
return
(
0
);
}
/*------------------------------------------------------------------*/
/*
* Wireless Private Handler : get histogram
*/
static
int
wavelan_get_histo
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
/* Set the number of intervals. */
wrqu
->
data
.
length
=
lp
->
his_number
;
/* Give back the distribution statistics */
if
(
lp
->
his_number
>
0
)
memcpy
(
extra
,
lp
->
his_sum
,
sizeof
(
long
)
*
lp
->
his_number
);
return
(
0
);
}
#endif
/* HISTOGRAM */
/*------------------------------------------------------------------*/
/*
* Structures to export the Wireless Handlers
*/
static
const
struct
iw_priv_args
wavelan_private_args
[]
=
{
/*{ cmd, set_args, get_args, name } */
{
SIOCSIPQTHR
,
IW_PRIV_TYPE_BYTE
|
IW_PRIV_SIZE_FIXED
|
1
,
0
,
"setqualthr"
},
{
SIOCGIPQTHR
,
0
,
IW_PRIV_TYPE_BYTE
|
IW_PRIV_SIZE_FIXED
|
1
,
"getqualthr"
},
{
SIOCSIPROAM
,
IW_PRIV_TYPE_BYTE
|
IW_PRIV_SIZE_FIXED
|
1
,
0
,
"setroam"
},
{
SIOCGIPROAM
,
0
,
IW_PRIV_TYPE_BYTE
|
IW_PRIV_SIZE_FIXED
|
1
,
"getroam"
},
{
SIOCSIPHISTO
,
IW_PRIV_TYPE_BYTE
|
16
,
0
,
"sethisto"
},
{
SIOCGIPHISTO
,
0
,
IW_PRIV_TYPE_INT
|
16
,
"gethisto"
},
};
#if WIRELESS_EXT > 12
static
const
iw_handler
wavelan_handler
[]
=
{
NULL
,
/* SIOCSIWNAME */
wavelan_get_name
,
/* SIOCGIWNAME */
wavelan_set_nwid
,
/* SIOCSIWNWID */
wavelan_get_nwid
,
/* SIOCGIWNWID */
wavelan_set_freq
,
/* SIOCSIWFREQ */
wavelan_get_freq
,
/* SIOCGIWFREQ */
#ifdef WAVELAN_ROAMING
wavelan_set_mode
,
/* SIOCSIWMODE */
wavelan_get_mode
,
/* SIOCGIWMODE */
#else
/* WAVELAN_ROAMING */
NULL
,
/* SIOCSIWMODE */
NULL
,
/* SIOCGIWMODE */
#endif
/* WAVELAN_ROAMING */
wavelan_set_sens
,
/* SIOCSIWSENS */
wavelan_get_sens
,
/* SIOCGIWSENS */
NULL
,
/* SIOCSIWRANGE */
wavelan_get_range
,
/* SIOCGIWRANGE */
NULL
,
/* SIOCSIWPRIV */
NULL
,
/* SIOCGIWPRIV */
NULL
,
/* SIOCSIWSTATS */
NULL
,
/* SIOCGIWSTATS */
#ifdef WIRELESS_SPY
wavelan_set_spy
,
/* SIOCSIWSPY */
wavelan_get_spy
,
/* SIOCGIWSPY */
#else
/* WIRELESS_SPY */
NULL
,
/* SIOCSIWSPY */
NULL
,
/* SIOCGIWSPY */
#endif
/* WIRELESS_SPY */
NULL
,
/* -- hole -- */
NULL
,
/* -- hole -- */
#ifdef WAVELAN_ROAMING_EXT
wavelan_set_wap
,
/* SIOCSIWAP */
wavelan_get_wap
,
/* SIOCGIWAP */
NULL
,
/* -- hole -- */
NULL
,
/* SIOCGIWAPLIST */
NULL
,
/* -- hole -- */
NULL
,
/* -- hole -- */
wavelan_set_essid
,
/* SIOCSIWESSID */
wavelan_get_essid
,
/* SIOCGIWESSID */
#else
/* WAVELAN_ROAMING_EXT */
NULL
,
/* SIOCSIWAP */
NULL
,
/* SIOCGIWAP */
NULL
,
/* -- hole -- */
NULL
,
/* SIOCGIWAPLIST */
NULL
,
/* -- hole -- */
NULL
,
/* -- hole -- */
NULL
,
/* SIOCSIWESSID */
NULL
,
/* SIOCGIWESSID */
#endif
/* WAVELAN_ROAMING_EXT */
#if WIRELESS_EXT > 8
NULL
,
/* SIOCSIWNICKN */
NULL
,
/* SIOCGIWNICKN */
NULL
,
/* -- hole -- */
NULL
,
/* -- hole -- */
NULL
,
/* SIOCSIWRATE */
NULL
,
/* SIOCGIWRATE */
NULL
,
/* SIOCSIWRTS */
NULL
,
/* SIOCGIWRTS */
NULL
,
/* SIOCSIWFRAG */
NULL
,
/* SIOCGIWFRAG */
NULL
,
/* SIOCSIWTXPOW */
NULL
,
/* SIOCGIWTXPOW */
NULL
,
/* SIOCSIWRETRY */
NULL
,
/* SIOCGIWRETRY */
wavelan_set_encode
,
/* SIOCSIWENCODE */
wavelan_get_encode
,
/* SIOCGIWENCODE */
#endif
/* WIRELESS_EXT > 8 */
};
static
const
iw_handler
wavelan_private_handler
[]
=
{
wavelan_set_qthr
,
/* SIOCIWFIRSTPRIV */
wavelan_get_qthr
,
/* SIOCIWFIRSTPRIV + 1 */
#ifdef WAVELAN_ROAMING
wavelan_set_roam
,
/* SIOCIWFIRSTPRIV + 2 */
wavelan_get_roam
,
/* SIOCIWFIRSTPRIV + 3 */
#else
/* WAVELAN_ROAMING */
NULL
,
/* SIOCIWFIRSTPRIV + 2 */
NULL
,
/* SIOCIWFIRSTPRIV + 3 */
#endif
/* WAVELAN_ROAMING */
#ifdef HISTOGRAM
wavelan_set_histo
,
/* SIOCIWFIRSTPRIV + 4 */
wavelan_get_histo
,
/* SIOCIWFIRSTPRIV + 5 */
#endif
/* HISTOGRAM */
};
static
const
struct
iw_handler_def
wavelan_handler_def
=
{
num_standard:
sizeof
(
wavelan_handler
)
/
sizeof
(
iw_handler
),
num_private:
sizeof
(
wavelan_private_handler
)
/
sizeof
(
iw_handler
),
num_private_args:
sizeof
(
wavelan_private_args
)
/
sizeof
(
struct
iw_priv_args
),
standard:
(
iw_handler
*
)
wavelan_handler
,
private:
(
iw_handler
*
)
wavelan_private_handler
,
private_args:
(
struct
iw_priv_args
*
)
wavelan_private_args
,
};
#else
/* WIRELESS_EXT > 12 */
/*------------------------------------------------------------------*/
/*------------------------------------------------------------------*/
/*
/*
* Perform ioctl : config & info stuff
* Perform ioctl : config & info stuff
...
@@ -1892,323 +2903,130 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
...
@@ -1892,323 +2903,130 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
struct
ifreq
*
rq
,
/* Data passed */
struct
ifreq
*
rq
,
/* Data passed */
int
cmd
)
/* Ioctl number */
int
cmd
)
/* Ioctl number */
{
{
ioaddr_t
base
=
dev
->
base_addr
;
net_local
*
lp
=
(
net_local
*
)
dev
->
priv
;
/* lp is not unused */
struct
iwreq
*
wrq
=
(
struct
iwreq
*
)
rq
;
struct
iwreq
*
wrq
=
(
struct
iwreq
*
)
rq
;
psa_t
psa
;
mm_t
m
;
unsigned
long
flags
;
int
ret
=
0
;
int
ret
=
0
;
#ifdef DEBUG_IOCTL_TRACE
#ifdef DEBUG_IOCTL_TRACE
printk
(
KERN_DEBUG
"%s: ->wavelan_ioctl(cmd=0x%X)
\n
"
,
dev
->
name
,
cmd
);
printk
(
KERN_DEBUG
"%s: ->wavelan_ioctl(cmd=0x%X)
\n
"
,
dev
->
name
,
cmd
);
#endif
#endif
/* Disable interrupts & save flags */
wv_splhi
(
lp
,
&
flags
);
/* Look what is the request */
/* Look what is the request */
switch
(
cmd
)
switch
(
cmd
)
{
{
/* --------------- WIRELESS EXTENSIONS --------------- */
/* --------------- WIRELESS EXTENSIONS --------------- */
case
SIOCGIWNAME
:
case
SIOCGIWNAME
:
strcpy
(
wrq
->
u
.
name
,
"Wavelan"
);
wavelan_get_name
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
break
;
break
;
case
SIOCSIWNWID
:
case
SIOCSIWNWID
:
/* Set NWID in wavelan */
ret
=
wavelan_set_nwid
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
#if WIRELESS_EXT > 8
if
(
!
wrq
->
u
.
nwid
.
disabled
)
{
/* Set NWID in psa */
psa
.
psa_nwid
[
0
]
=
(
wrq
->
u
.
nwid
.
value
&
0xFF00
)
>>
8
;
psa
.
psa_nwid
[
1
]
=
wrq
->
u
.
nwid
.
value
&
0xFF
;
#else
/* WIRELESS_EXT > 8 */
if
(
wrq
->
u
.
nwid
.
on
)
{
/* Set NWID in psa */
psa
.
psa_nwid
[
0
]
=
(
wrq
->
u
.
nwid
.
nwid
&
0xFF00
)
>>
8
;
psa
.
psa_nwid
[
1
]
=
wrq
->
u
.
nwid
.
nwid
&
0xFF
;
#endif
/* WIRELESS_EXT > 8 */
psa
.
psa_nwid_select
=
0x01
;
psa_write
(
dev
,
(
char
*
)
psa
.
psa_nwid
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
psa
.
psa_nwid
,
3
);
/* Set NWID in mmc */
m
.
w
.
mmw_netw_id_l
=
psa
.
psa_nwid
[
1
];
m
.
w
.
mmw_netw_id_h
=
psa
.
psa_nwid
[
0
];
mmc_write
(
base
,
(
char
*
)
&
m
.
w
.
mmw_netw_id_l
-
(
char
*
)
&
m
,
(
unsigned
char
*
)
&
m
.
w
.
mmw_netw_id_l
,
2
);
mmc_out
(
base
,
mmwoff
(
0
,
mmw_loopt_sel
),
0x00
);
}
else
{
/* Disable nwid in the psa */
psa
.
psa_nwid_select
=
0x00
;
psa_write
(
dev
,
(
char
*
)
&
psa
.
psa_nwid_select
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_nwid_select
,
1
);
/* Disable nwid in the mmc (no filtering) */
mmc_out
(
base
,
mmwoff
(
0
,
mmw_loopt_sel
),
MMW_LOOPT_SEL_DIS_NWID
);
}
/* update the Wavelan checksum */
update_psa_checksum
(
dev
);
break
;
break
;
case
SIOCGIWNWID
:
case
SIOCGIWNWID
:
/* Read the NWID */
ret
=
wavelan_get_nwid
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
psa_read
(
dev
,
(
char
*
)
psa
.
psa_nwid
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
psa
.
psa_nwid
,
3
);
#if WIRELESS_EXT > 8
wrq
->
u
.
nwid
.
value
=
(
psa
.
psa_nwid
[
0
]
<<
8
)
+
psa
.
psa_nwid
[
1
];
wrq
->
u
.
nwid
.
disabled
=
!
(
psa
.
psa_nwid_select
);
wrq
->
u
.
nwid
.
fixed
=
1
;
/* Superfluous */
#else
/* WIRELESS_EXT > 8 */
wrq
->
u
.
nwid
.
nwid
=
(
psa
.
psa_nwid
[
0
]
<<
8
)
+
psa
.
psa_nwid
[
1
];
wrq
->
u
.
nwid
.
on
=
psa
.
psa_nwid_select
;
#endif
/* WIRELESS_EXT > 8 */
break
;
break
;
case
SIOCSIWFREQ
:
case
SIOCSIWFREQ
:
/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) */
ret
=
wavelan_set_freq
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
if
(
!
(
mmc_in
(
base
,
mmroff
(
0
,
mmr_fee_status
))
&
(
MMR_FEE_STATUS_DWLD
|
MMR_FEE_STATUS_BUSY
)))
ret
=
wv_set_frequency
(
base
,
&
(
wrq
->
u
.
freq
));
else
ret
=
-
EOPNOTSUPP
;
break
;
break
;
case
SIOCGIWFREQ
:
case
SIOCGIWFREQ
:
/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable)
ret
=
wavelan_get_freq
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
* (does it work for everybody ? - especially old cards...) */
if
(
!
(
mmc_in
(
base
,
mmroff
(
0
,
mmr_fee_status
))
&
(
MMR_FEE_STATUS_DWLD
|
MMR_FEE_STATUS_BUSY
)))
{
unsigned
short
freq
;
/* Ask the EEprom to read the frequency from the first area */
fee_read
(
base
,
0x00
/* 1st area - frequency... */
,
&
freq
,
1
);
wrq
->
u
.
freq
.
m
=
((
freq
>>
5
)
*
5
+
24000L
)
*
10000
;
wrq
->
u
.
freq
.
e
=
1
;
}
else
{
psa_read
(
dev
,
(
char
*
)
&
psa
.
psa_subband
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_subband
,
1
);
if
(
psa
.
psa_subband
<=
4
)
{
wrq
->
u
.
freq
.
m
=
fixed_bands
[
psa
.
psa_subband
];
wrq
->
u
.
freq
.
e
=
(
psa
.
psa_subband
!=
0
);
}
else
ret
=
-
EOPNOTSUPP
;
}
break
;
break
;
case
SIOCSIWSENS
:
case
SIOCSIWSENS
:
/* Set the level threshold */
ret
=
wavelan_set_sens
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
#if WIRELESS_EXT > 7
/* We should complain loudly if wrq->u.sens.fixed = 0, because we
* can't set auto mode... */
psa
.
psa_thr_pre_set
=
wrq
->
u
.
sens
.
value
&
0x3F
;
#else
/* WIRELESS_EXT > 7 */
psa
.
psa_thr_pre_set
=
wrq
->
u
.
sensitivity
&
0x3F
;
#endif
/* WIRELESS_EXT > 7 */
psa_write
(
dev
,
(
char
*
)
&
psa
.
psa_thr_pre_set
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_thr_pre_set
,
1
);
/* update the Wavelan checksum */
update_psa_checksum
(
dev
);
mmc_out
(
base
,
mmwoff
(
0
,
mmw_thr_pre_set
),
psa
.
psa_thr_pre_set
);
break
;
break
;
case
SIOCGIWSENS
:
case
SIOCGIWSENS
:
/* Read the level threshold */
ret
=
wavelan_get_sens
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
psa_read
(
dev
,
(
char
*
)
&
psa
.
psa_thr_pre_set
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_thr_pre_set
,
1
);
#if WIRELESS_EXT > 7
wrq
->
u
.
sens
.
value
=
psa
.
psa_thr_pre_set
&
0x3F
;
wrq
->
u
.
sens
.
fixed
=
1
;
#else
/* WIRELESS_EXT > 7 */
wrq
->
u
.
sensitivity
=
psa
.
psa_thr_pre_set
&
0x3F
;
#endif
/* WIRELESS_EXT > 7 */
break
;
break
;
#if WIRELESS_EXT > 8
#if WIRELESS_EXT > 8
case
SIOCSIWENCODE
:
case
SIOCSIWENCODE
:
/* Set encryption key */
{
if
(
!
mmc_encr
(
base
))
char
keybuf
[
8
];
{
if
(
wrq
->
u
.
encoding
.
pointer
)
{
ret
=
-
EOPNOTSUPP
;
/* We actually have a key to set */
if
(
wrq
->
u
.
encoding
.
length
!=
8
)
{
ret
=
-
EINVAL
;
break
;
}
if
(
copy_from_user
(
keybuf
,
wrq
->
u
.
encoding
.
pointer
,
wrq
->
u
.
encoding
.
length
))
{
ret
=
-
EFAULT
;
break
;
}
}
else
if
(
wrq
->
u
.
encoding
.
length
!=
0
)
{
ret
=
-
EINVAL
;
break
;
break
;
}
}
ret
=
wavelan_set_encode
(
dev
,
NULL
,
&
(
wrq
->
u
),
keybuf
);
/* Basic checking... */
}
if
(
wrq
->
u
.
encoding
.
pointer
!=
(
caddr_t
)
0
)
{
/* Check the size of the key */
if
(
wrq
->
u
.
encoding
.
length
!=
8
)
{
ret
=
-
EINVAL
;
break
;
}
/* Copy the key in the driver */
if
(
copy_from_user
(
psa
.
psa_encryption_key
,
wrq
->
u
.
encoding
.
pointer
,
wrq
->
u
.
encoding
.
length
))
{
ret
=
-
EFAULT
;
break
;
}
psa
.
psa_encryption_select
=
1
;
psa_write
(
dev
,
(
char
*
)
&
psa
.
psa_encryption_select
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_encryption_select
,
8
+
1
);
mmc_out
(
base
,
mmwoff
(
0
,
mmw_encr_enable
),
MMW_ENCR_ENABLE_EN
|
MMW_ENCR_ENABLE_MODE
);
mmc_write
(
base
,
mmwoff
(
0
,
mmw_encr_key
),
(
unsigned
char
*
)
&
psa
.
psa_encryption_key
,
8
);
}
if
(
wrq
->
u
.
encoding
.
flags
&
IW_ENCODE_DISABLED
)
{
/* disable encryption */
psa
.
psa_encryption_select
=
0
;
psa_write
(
dev
,
(
char
*
)
&
psa
.
psa_encryption_select
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_encryption_select
,
1
);
mmc_out
(
base
,
mmwoff
(
0
,
mmw_encr_enable
),
0
);
}
/* update the Wavelan checksum */
update_psa_checksum
(
dev
);
break
;
break
;
case
SIOCGIWENCODE
:
case
SIOCGIWENCODE
:
/* Read the encryption key */
if
(
!
capable
(
CAP_NET_ADMIN
))
{
if
(
!
mmc_encr
(
base
))
ret
=
-
EPERM
;
{
break
;
ret
=
-
EOPNOTSUPP
;
}
break
;
{
}
char
keybuf
[
8
];
ret
=
wavelan_get_encode
(
dev
,
NULL
,
/* only super-user can see encryption key */
&
(
wrq
->
u
),
if
(
!
capable
(
CAP_NET_ADMIN
))
keybuf
);
{
if
(
wrq
->
u
.
encoding
.
pointer
)
{
ret
=
-
EPERM
;
if
(
copy_to_user
(
wrq
->
u
.
encoding
.
pointer
,
break
;
keybuf
,
}
wrq
->
u
.
encoding
.
length
))
/* Basic checking... */
if
(
wrq
->
u
.
encoding
.
pointer
!=
(
caddr_t
)
0
)
{
psa_read
(
dev
,
(
char
*
)
&
psa
.
psa_encryption_select
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_encryption_select
,
1
+
8
);
/* encryption is enabled ? */
if
(
psa
.
psa_encryption_select
)
wrq
->
u
.
encoding
.
flags
=
IW_ENCODE_ENABLED
;
else
wrq
->
u
.
encoding
.
flags
=
IW_ENCODE_DISABLED
;
wrq
->
u
.
encoding
.
flags
|=
mmc_encr
(
base
);
/* Copy the key to the user buffer */
wrq
->
u
.
encoding
.
length
=
8
;
if
(
copy_to_user
(
wrq
->
u
.
encoding
.
pointer
,
psa
.
psa_encryption_key
,
8
))
ret
=
-
EFAULT
;
ret
=
-
EFAULT
;
}
}
}
break
;
break
;
#endif
/* WIRELESS_EXT > 8 */
#endif
/* WIRELESS_EXT > 8 */
#ifdef WAVELAN_ROAMING_EXT
#ifdef WAVELAN_ROAMING_EXT
#if WIRELESS_EXT > 5
#if WIRELESS_EXT > 5
case
SIOCSIWESSID
:
case
SIOCSIWESSID
:
/* Check if disable */
{
if
(
wrq
->
u
.
data
.
flags
==
0
)
char
essidbuf
[
IW_ESSID_MAX_SIZE
+
1
];
lp
->
filter_domains
=
0
;
if
(
wrq
->
u
.
essid
.
length
>
IW_ESSID_MAX_SIZE
)
{
else
ret
=
-
E2BIG
;
/* Basic checking... */
break
;
if
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
)
}
{
if
(
copy_from_user
(
essidbuf
,
wrq
->
u
.
essid
.
pointer
,
char
essid
[
IW_ESSID_MAX_SIZE
+
1
];
wrq
->
u
.
essid
.
length
))
{
char
*
endp
;
ret
=
-
EFAULT
;
break
;
/* Check the size of the string */
}
if
(
wrq
->
u
.
data
.
length
>
IW_ESSID_MAX_SIZE
+
1
)
ret
=
wavelan_set_essid
(
dev
,
NULL
,
{
&
(
wrq
->
u
),
ret
=
-
E2BIG
;
essidbuf
);
break
;
}
}
/* Copy the string in the driver */
if
(
copy_from_user
(
essid
,
wrq
->
u
.
data
.
pointer
,
wrq
->
u
.
data
.
length
))
{
ret
=
-
EFAULT
;
break
;
}
essid
[
IW_ESSID_MAX_SIZE
]
=
'\0'
;
#ifdef DEBUG_IOCTL_INFO
printk
(
KERN_DEBUG
"SetEssid : ``%s''
\n
"
,
essid
);
#endif
/* DEBUG_IOCTL_INFO */
/* Convert to a number (note : Wavelan specific) */
lp
->
domain_id
=
simple_strtoul
(
essid
,
&
endp
,
16
);
/* Has it worked ? */
if
(
endp
>
essid
)
lp
->
filter_domains
=
1
;
else
{
lp
->
filter_domains
=
0
;
ret
=
-
EINVAL
;
}
}
break
;
break
;
case
SIOCGIWESSID
:
case
SIOCGIWESSID
:
/* Basic checking... */
{
if
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
)
char
essidbuf
[
IW_ESSID_MAX_SIZE
+
1
];
{
ret
=
wavelan_get_essid
(
dev
,
NULL
,
char
essid
[
IW_ESSID_MAX_SIZE
+
1
];
&
(
wrq
->
u
),
essidbuf
);
/* Is the domain ID active ? */
if
(
wrq
->
u
.
essid
.
pointer
)
wrq
->
u
.
data
.
flags
=
lp
->
filter_domains
;
if
(
copy_to_user
(
wrq
->
u
.
essid
.
pointer
,
essidbuf
,
/* Copy Domain ID into a string (Wavelan specific) */
wrq
->
u
.
essid
.
length
)
)
/* Sound crazy, be we can't have a snprintf in the kernel !!! */
sprintf
(
essid
,
"%lX"
,
lp
->
domain_id
);
essid
[
IW_ESSID_MAX_SIZE
]
=
'\0'
;
/* Set the length */
wrq
->
u
.
data
.
length
=
strlen
(
essid
)
+
1
;
/* Copy structure to the user buffer */
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
essid
,
wrq
->
u
.
data
.
length
))
ret
=
-
EFAULT
;
ret
=
-
EFAULT
;
}
}
break
;
break
;
case
SIOCSIWAP
:
case
SIOCSIWAP
:
#ifdef DEBUG_IOCTL_INFO
ret
=
wavelan_set_wap
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
printk
(
KERN_DEBUG
"Set AP to : %02X:%02X:%02X:%02X:%02X:%02X
\n
"
,
wrq
->
u
.
ap_addr
.
sa_data
[
0
],
wrq
->
u
.
ap_addr
.
sa_data
[
1
],
wrq
->
u
.
ap_addr
.
sa_data
[
2
],
wrq
->
u
.
ap_addr
.
sa_data
[
3
],
wrq
->
u
.
ap_addr
.
sa_data
[
4
],
wrq
->
u
.
ap_addr
.
sa_data
[
5
]);
#endif
/* DEBUG_IOCTL_INFO */
ret
=
-
EOPNOTSUPP
;
/* Not supported yet */
break
;
break
;
case
SIOCGIWAP
:
case
SIOCGIWAP
:
/* Should get the real McCoy instead of own Ethernet address */
ret
=
wavelan_get_wap
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
memcpy
(
wrq
->
u
.
ap_addr
.
sa_data
,
dev
->
dev_addr
,
WAVELAN_ADDR_SIZE
);
wrq
->
u
.
ap_addr
.
sa_family
=
ARPHRD_ETHER
;
ret
=
-
EOPNOTSUPP
;
/* Not supported yet */
break
;
break
;
#endif
/* WIRELESS_EXT > 5 */
#endif
/* WIRELESS_EXT > 5 */
#endif
/* WAVELAN_ROAMING_EXT */
#endif
/* WAVELAN_ROAMING_EXT */
...
@@ -2216,225 +3034,84 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
...
@@ -2216,225 +3034,84 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
#if WIRELESS_EXT > 8
#if WIRELESS_EXT > 8
#ifdef WAVELAN_ROAMING
#ifdef WAVELAN_ROAMING
case
SIOCSIWMODE
:
case
SIOCSIWMODE
:
switch
(
wrq
->
u
.
mode
)
ret
=
wavelan_set_mode
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
{
case
IW_MODE_ADHOC
:
if
(
do_roaming
)
{
wv_roam_cleanup
(
dev
);
do_roaming
=
0
;
}
break
;
case
IW_MODE_INFRA
:
if
(
!
do_roaming
)
{
wv_roam_init
(
dev
);
do_roaming
=
1
;
}
break
;
default:
ret
=
-
EINVAL
;
}
break
;
break
;
case
SIOCGIWMODE
:
case
SIOCGIWMODE
:
if
(
do_roaming
)
ret
=
wavelan_get_mode
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
wrq
->
u
.
mode
=
IW_MODE_INFRA
;
else
wrq
->
u
.
mode
=
IW_MODE_ADHOC
;
break
;
break
;
#endif
/* WAVELAN_ROAMING */
#endif
/* WAVELAN_ROAMING */
#endif
/* WIRELESS_EXT > 8 */
#endif
/* WIRELESS_EXT > 8 */
case
SIOCGIWRANGE
:
case
SIOCGIWRANGE
:
/* Basic checking... */
{
if
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
)
struct
iw_range
range
;
{
ret
=
wavelan_get_range
(
dev
,
NULL
,
struct
iw_range
range
;
&
(
wrq
->
u
),
(
char
*
)
&
range
);
/* Set the length (very important for backward compatibility) */
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
&
range
,
wrq
->
u
.
data
.
length
=
sizeof
(
struct
iw_range
);
sizeof
(
struct
iw_range
)))
ret
=
-
EFAULT
;
/* Set all the info we don't care or don't know about to zero */
}
memset
(
&
range
,
0
,
sizeof
(
range
));
#if WIRELESS_EXT > 10
/* Set the Wireless Extension versions */
range
.
we_version_compiled
=
WIRELESS_EXT
;
range
.
we_version_source
=
9
;
/* Nothing for us in v10 and v11 */
#endif
/* WIRELESS_EXT > 10 */
/* Set information in the range struct */
range
.
throughput
=
1
.
4
*
1000
*
1000
;
/* don't argue on this ! */
range
.
min_nwid
=
0x0000
;
range
.
max_nwid
=
0xFFFF
;
/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) */
if
(
!
(
mmc_in
(
base
,
mmroff
(
0
,
mmr_fee_status
))
&
(
MMR_FEE_STATUS_DWLD
|
MMR_FEE_STATUS_BUSY
)))
{
range
.
num_channels
=
10
;
range
.
num_frequency
=
wv_frequency_list
(
base
,
range
.
freq
,
IW_MAX_FREQUENCIES
);
}
else
range
.
num_channels
=
range
.
num_frequency
=
0
;
range
.
sensitivity
=
0x3F
;
range
.
max_qual
.
qual
=
MMR_SGNL_QUAL
;
range
.
max_qual
.
level
=
MMR_SIGNAL_LVL
;
range
.
max_qual
.
noise
=
MMR_SILENCE_LVL
;
#if WIRELESS_EXT > 11
range
.
avg_qual
.
qual
=
MMR_SGNL_QUAL
;
/* Always max */
/* Need to get better values for those two */
range
.
avg_qual
.
level
=
30
;
range
.
avg_qual
.
noise
=
8
;
#endif
/* WIRELESS_EXT > 11 */
#if WIRELESS_EXT > 7
range
.
num_bitrates
=
1
;
range
.
bitrate
[
0
]
=
2000000
;
/* 2 Mb/s */
#endif
/* WIRELESS_EXT > 7 */
#if WIRELESS_EXT > 8
/* Encryption supported ? */
if
(
mmc_encr
(
base
))
{
range
.
encoding_size
[
0
]
=
8
;
/* DES = 64 bits key */
range
.
num_encoding_sizes
=
1
;
range
.
max_encoding_tokens
=
1
;
/* Only one key possible */
}
else
{
range
.
num_encoding_sizes
=
0
;
range
.
max_encoding_tokens
=
0
;
}
#endif
/* WIRELESS_EXT > 8 */
/* Copy structure to the user buffer */
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
&
range
,
sizeof
(
struct
iw_range
)))
ret
=
-
EFAULT
;
}
break
;
break
;
case
SIOCGIWPRIV
:
case
SIOCGIWPRIV
:
/* Basic checking... */
/* Basic checking... */
if
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
)
if
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
)
{
{
struct
iw_priv_args
priv
[]
=
{
/* cmd, set_args, get_args, name */
{
SIOCSIPQTHR
,
IW_PRIV_TYPE_BYTE
|
IW_PRIV_SIZE_FIXED
|
1
,
0
,
"setqualthr"
},
{
SIOCGIPQTHR
,
0
,
IW_PRIV_TYPE_BYTE
|
IW_PRIV_SIZE_FIXED
|
1
,
"getqualthr"
},
{
SIOCSIPHISTO
,
IW_PRIV_TYPE_BYTE
|
16
,
0
,
"sethisto"
},
{
SIOCGIPHISTO
,
0
,
IW_PRIV_TYPE_INT
|
16
,
"gethisto"
},
{
SIOCSIPROAM
,
IW_PRIV_TYPE_BYTE
|
IW_PRIV_SIZE_FIXED
|
1
,
0
,
"setroam"
},
{
SIOCGIPROAM
,
0
,
IW_PRIV_TYPE_BYTE
|
IW_PRIV_SIZE_FIXED
|
1
,
"getroam"
},
};
/* Set the number of ioctl available */
/* Set the number of ioctl available */
wrq
->
u
.
data
.
length
=
6
;
wrq
->
u
.
data
.
length
=
sizeof
(
wavelan_private_args
)
/
sizeof
(
wavelan_private_args
[
0
])
;
/* Copy structure to the user buffer */
/* Copy structure to the user buffer */
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
(
u_char
*
)
priv
,
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
(
u_char
*
)
wavelan_private_args
,
sizeof
(
priv
)))
sizeof
(
wavelan_private_args
)))
ret
=
-
EFAULT
;
ret
=
-
EFAULT
;
}
}
break
;
break
;
#ifdef WIRELESS_SPY
#ifdef WIRELESS_SPY
case
SIOCSIWSPY
:
case
SIOCSIWSPY
:
/* Set the spy list */
{
struct
sockaddr
address
[
IW_MAX_SPY
];
/* Check the number of addresses */
/* Check the number of addresses */
if
(
wrq
->
u
.
data
.
length
>
IW_MAX_SPY
)
if
(
wrq
->
u
.
data
.
length
>
IW_MAX_SPY
)
{
{
ret
=
-
E2BIG
;
ret
=
-
E2BIG
;
break
;
break
;
}
}
lp
->
spy_number
=
wrq
->
u
.
data
.
length
;
/* Get the data in the driver */
if
(
wrq
->
u
.
data
.
pointer
)
{
/* If there is some addresses to copy */
if
(
copy_from_user
((
char
*
)
address
,
if
(
lp
->
spy_number
>
0
)
wrq
->
u
.
data
.
pointer
,
{
sizeof
(
struct
sockaddr
)
*
struct
sockaddr
address
[
IW_MAX_SPY
];
wrq
->
u
.
data
.
length
))
{
int
i
;
ret
=
-
EFAULT
;
break
;
/* Copy addresses to the driver */
}
if
(
copy_from_user
(
address
,
wrq
->
u
.
data
.
pointer
,
}
else
if
(
wrq
->
u
.
data
.
length
!=
0
)
{
sizeof
(
struct
sockaddr
)
*
lp
->
spy_number
))
ret
=
-
EINVAL
;
{
break
;
ret
=
-
EFAULT
;
break
;
}
/* Copy addresses to the lp structure */
for
(
i
=
0
;
i
<
lp
->
spy_number
;
i
++
)
{
memcpy
(
lp
->
spy_address
[
i
],
address
[
i
].
sa_data
,
WAVELAN_ADDR_SIZE
);
}
/* Reset structure... */
memset
(
lp
->
spy_stat
,
0x00
,
sizeof
(
iw_qual
)
*
IW_MAX_SPY
);
#ifdef DEBUG_IOCTL_INFO
printk
(
KERN_DEBUG
"SetSpy - Set of new addresses is :
\n
"
);
for
(
i
=
0
;
i
<
wrq
->
u
.
data
.
length
;
i
++
)
printk
(
KERN_DEBUG
"%02X:%02X:%02X:%02X:%02X:%02X
\n
"
,
lp
->
spy_address
[
i
][
0
],
lp
->
spy_address
[
i
][
1
],
lp
->
spy_address
[
i
][
2
],
lp
->
spy_address
[
i
][
3
],
lp
->
spy_address
[
i
][
4
],
lp
->
spy_address
[
i
][
5
]);
#endif
/* DEBUG_IOCTL_INFO */
}
}
ret
=
wavelan_set_spy
(
dev
,
NULL
,
&
(
wrq
->
u
),
(
char
*
)
address
);
}
break
;
break
;
case
SIOCGIWSPY
:
case
SIOCGIWSPY
:
/* Get the spy list and spy stats */
{
char
buffer
[
IW_MAX_SPY
*
(
sizeof
(
struct
sockaddr
)
+
/* Set the number of addresses */
sizeof
(
struct
iw_quality
))];
wrq
->
u
.
data
.
length
=
lp
->
spy_number
;
ret
=
wavelan_get_spy
(
dev
,
NULL
,
&
(
wrq
->
u
),
buffer
);
/* If the user want to have the addresses back... */
if
(
wrq
->
u
.
data
.
pointer
)
{
if
((
lp
->
spy_number
>
0
)
&&
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
))
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
{
buffer
,
struct
sockaddr
address
[
IW_MAX_SPY
];
(
wrq
->
u
.
data
.
length
*
int
i
;
(
sizeof
(
struct
sockaddr
)
+
sizeof
(
struct
iw_quality
)))
/* Copy addresses from the lp structure */
))
for
(
i
=
0
;
i
<
lp
->
spy_number
;
i
++
)
ret
=
-
EFAULT
;
{
}
memcpy
(
address
[
i
].
sa_data
,
lp
->
spy_address
[
i
],
}
WAVELAN_ADDR_SIZE
);
address
[
i
].
sa_family
=
ARPHRD_ETHER
;
}
/* Copy addresses to the user buffer */
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
address
,
sizeof
(
struct
sockaddr
)
*
lp
->
spy_number
))
{
ret
=
-
EFAULT
;
break
;
}
/* Copy stats to the user buffer (just after) */
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
+
(
sizeof
(
struct
sockaddr
)
*
lp
->
spy_number
),
lp
->
spy_stat
,
sizeof
(
iw_qual
)
*
lp
->
spy_number
))
{
ret
=
-
EFAULT
;
break
;
}
/* Reset updated flags */
for
(
i
=
0
;
i
<
lp
->
spy_number
;
i
++
)
lp
->
spy_stat
[
i
].
updated
=
0x0
;
}
/* if(pointer != NULL) */
break
;
break
;
#endif
/* WIRELESS_SPY */
#endif
/* WIRELESS_SPY */
...
@@ -2446,34 +3123,21 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
...
@@ -2446,34 +3123,21 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
ret
=
-
EPERM
;
ret
=
-
EPERM
;
break
;
break
;
}
}
psa
.
psa_quality_thr
=
*
(
wrq
->
u
.
name
)
&
0x0F
;
ret
=
wavelan_set_qthr
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
psa_write
(
dev
,
(
char
*
)
&
psa
.
psa_quality_thr
-
(
char
*
)
&
psa
,
(
unsigned
char
*
)
&
psa
.
psa_quality_thr
,
1
);
/* update the Wavelan checksum */
update_psa_checksum
(
dev
);
mmc_out
(
base
,
mmwoff
(
0
,
mmw_quality_thr
),
psa
.
psa_quality_thr
);
break
;
break
;
case
SIOCGIPQTHR
:
case
SIOCGIPQTHR
:
psa_read
(
dev
,
(
char
*
)
&
psa
.
psa_quality_thr
-
(
char
*
)
&
psa
,
ret
=
wavelan_get_qthr
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
(
unsigned
char
*
)
&
psa
.
psa_quality_thr
,
1
);
*
(
wrq
->
u
.
name
)
=
psa
.
psa_quality_thr
&
0x0F
;
break
;
break
;
#ifdef WAVELAN_ROAMING
#ifdef WAVELAN_ROAMING
case
SIOCSIPROAM
:
case
SIOCSIPROAM
:
/* Note : should check if user == root */
/* Note : should check if user == root */
if
(
do_roaming
&&
(
*
wrq
->
u
.
name
)
==
0
)
ret
=
wavelan_set_roam
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
);
wv_roam_cleanup
(
dev
);
else
if
(
do_roaming
==
0
&&
(
*
wrq
->
u
.
name
)
!=
0
)
wv_roam_init
(
dev
);
do_roaming
=
(
*
wrq
->
u
.
name
);
break
;
break
;
case
SIOCGIPROAM
:
case
SIOCGIPROAM
:
*
(
wrq
->
u
.
name
)
=
do_roaming
;
ret
=
wavelan_get_roam
(
dev
,
NULL
,
&
(
wrq
->
u
),
NULL
)
;
break
;
break
;
#endif
/* WAVELAN_ROAMING */
#endif
/* WAVELAN_ROAMING */
...
@@ -2484,44 +3148,44 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
...
@@ -2484,44 +3148,44 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
{
{
ret
=
-
EPERM
;
ret
=
-
EPERM
;
}
}
{
/* Check the number of intervals */
char
buffer
[
16
];
if
(
wrq
->
u
.
data
.
length
>
16
)
/* Check the number of intervals */
{
if
(
wrq
->
u
.
data
.
length
>
16
)
ret
=
-
E2BIG
;
{
break
;
ret
=
-
E2BIG
;
break
;
}
}
lp
->
his_number
=
wrq
->
u
.
data
.
length
;
/* Get the data in the driver */
if
(
wrq
->
u
.
data
.
pointer
)
{
/* If there is some addresses to copy */
if
(
copy_from_user
(
buffer
,
if
(
lp
->
his_number
>
0
)
wrq
->
u
.
data
.
pointer
,
{
sizeof
(
struct
sockaddr
)
*
/* Copy interval ranges to the driver */
wrq
->
u
.
data
.
length
))
{
if
(
copy_from_user
(
lp
->
his_range
,
wrq
->
u
.
data
.
pointer
,
ret
=
-
EFAULT
;
sizeof
(
char
)
*
lp
->
his_number
))
break
;
{
}
ret
=
-
EFAULT
;
}
else
if
(
wrq
->
u
.
data
.
length
!=
0
)
{
break
;
ret
=
-
EINVAL
;
}
break
;
/* Reset structure... */
memset
(
lp
->
his_sum
,
0x00
,
sizeof
(
long
)
*
16
);
}
}
ret
=
wavelan_set_histo
(
dev
,
NULL
,
&
(
wrq
->
u
),
buffer
);
}
break
;
break
;
case
SIOCGIPHISTO
:
case
SIOCGIPHISTO
:
/* Set the number of intervals */
{
wrq
->
u
.
data
.
length
=
lp
->
his_number
;
long
buffer
[
16
];
ret
=
wavelan_get_histo
(
dev
,
NULL
,
&
(
wrq
->
u
),
/* Give back the distribution statistics */
(
char
*
)
buffer
);
if
((
lp
->
his_number
>
0
)
&&
(
wrq
->
u
.
data
.
pointer
!=
(
caddr_t
)
0
))
if
(
wrq
->
u
.
data
.
pointer
)
{
{
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
/* Copy data to the user buffer */
buffer
,
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
lp
->
his_sum
,
(
wrq
->
u
.
data
.
length
*
sizeof
(
long
))))
sizeof
(
long
)
*
lp
->
his_number
))
ret
=
-
EFAULT
;
ret
=
-
EFAULT
;
}
}
/* if(pointer != NULL) */
}
break
;
break
;
#endif
/* HISTOGRAM */
#endif
/* HISTOGRAM */
...
@@ -2531,14 +3195,12 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
...
@@ -2531,14 +3195,12 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
ret
=
-
EOPNOTSUPP
;
ret
=
-
EOPNOTSUPP
;
}
}
/* ReEnable interrupts & restore flags */
wv_splx
(
lp
,
&
flags
);
#ifdef DEBUG_IOCTL_TRACE
#ifdef DEBUG_IOCTL_TRACE
printk
(
KERN_DEBUG
"%s: <-wavelan_ioctl()
\n
"
,
dev
->
name
);
printk
(
KERN_DEBUG
"%s: <-wavelan_ioctl()
\n
"
,
dev
->
name
);
#endif
#endif
return
ret
;
return
ret
;
}
}
#endif
/* WIRELESS_EXT > 12 */
/*------------------------------------------------------------------*/
/*------------------------------------------------------------------*/
/*
/*
...
@@ -4530,7 +5192,11 @@ wavelan_attach(void)
...
@@ -4530,7 +5192,11 @@ wavelan_attach(void)
dev
->
watchdog_timeo
=
WATCHDOG_JIFFIES
;
dev
->
watchdog_timeo
=
WATCHDOG_JIFFIES
;
#ifdef WIRELESS_EXT
/* If wireless extension exist in the kernel */
#ifdef WIRELESS_EXT
/* If wireless extension exist in the kernel */
#if WIRELESS_EXT > 12
dev
->
wireless_handlers
=
(
struct
iw_handler_def
*
)
&
wavelan_handler_def
;
#else
/* WIRELESS_EXT > 12 */
dev
->
do_ioctl
=
wavelan_ioctl
;
/* wireless extensions */
dev
->
do_ioctl
=
wavelan_ioctl
;
/* wireless extensions */
#endif
/* WIRELESS_EXT > 12 */
dev
->
get_wireless_stats
=
wavelan_get_wireless_stats
;
dev
->
get_wireless_stats
=
wavelan_get_wireless_stats
;
#endif
#endif
...
...
drivers/net/wireless/wavelan_cs.p.h
View file @
a5220ff4
...
@@ -394,6 +394,12 @@
...
@@ -394,6 +394,12 @@
* o control first busy loop in wv_82593_cmd()
* o control first busy loop in wv_82593_cmd()
* o Extend spinlock protection in wv_hw_config()
* o Extend spinlock protection in wv_hw_config()
*
*
* Changes made for release in 3.1.33 :
* ----------------------------------
* - Optional use new driver API for Wireless Extensions :
* o got rid of wavelan_ioctl()
* o use a bunch of iw_handler instead
*
* Wishes & dreams:
* Wishes & dreams:
* ----------------
* ----------------
* - Cleanup and integrate the roaming code
* - Cleanup and integrate the roaming code
...
@@ -430,6 +436,9 @@
...
@@ -430,6 +436,9 @@
#ifdef CONFIG_NET_RADIO
#ifdef CONFIG_NET_RADIO
#include <linux/wireless.h>
/* Wireless extensions */
#include <linux/wireless.h>
/* Wireless extensions */
#if WIRELESS_EXT > 12
#include <net/iw_handler.h>
#endif
/* WIRELESS_EXT > 12 */
#endif
#endif
/* Pcmcia headers that we need */
/* Pcmcia headers that we need */
...
@@ -498,7 +507,7 @@
...
@@ -498,7 +507,7 @@
/************************ CONSTANTS & MACROS ************************/
/************************ CONSTANTS & MACROS ************************/
#ifdef DEBUG_VERSION_SHOW
#ifdef DEBUG_VERSION_SHOW
static
const
char
*
version
=
"wavelan_cs.c : v2
3 (SMP + wireless extensions) 20/12/00
\n
"
;
static
const
char
*
version
=
"wavelan_cs.c : v2
4 (SMP + wireless extensions) 11/1/02
\n
"
;
#endif
#endif
/* Watchdog temporisation */
/* Watchdog temporisation */
...
@@ -523,8 +532,8 @@ static const char *version = "wavelan_cs.c : v23 (SMP + wireless extensions) 20/
...
@@ -523,8 +532,8 @@ static const char *version = "wavelan_cs.c : v23 (SMP + wireless extensions) 20/
#define SIOCSIPROAM SIOCIWFIRSTPRIV + 2
/* Set roaming state */
#define SIOCSIPROAM SIOCIWFIRSTPRIV + 2
/* Set roaming state */
#define SIOCGIPROAM SIOCIWFIRSTPRIV + 3
/* Get roaming state */
#define SIOCGIPROAM SIOCIWFIRSTPRIV + 3
/* Get roaming state */
#define SIOCSIPHISTO SIOCIWFIRSTPRIV +
6
/* Set histogram ranges */
#define SIOCSIPHISTO SIOCIWFIRSTPRIV +
4
/* Set histogram ranges */
#define SIOCGIPHISTO SIOCIWFIRSTPRIV +
7
/* Get histogram values */
#define SIOCGIPHISTO SIOCIWFIRSTPRIV +
5
/* Get histogram values */
/*************************** WaveLAN Roaming **************************/
/*************************** WaveLAN Roaming **************************/
#ifdef WAVELAN_ROAMING
/* Conditional compile, see above in options */
#ifdef WAVELAN_ROAMING
/* Conditional compile, see above in options */
...
@@ -589,6 +598,16 @@ typedef struct iw_freq iw_freq;
...
@@ -589,6 +598,16 @@ typedef struct iw_freq iw_freq;
typedef
struct
net_local
net_local
;
typedef
struct
net_local
net_local
;
typedef
struct
timer_list
timer_list
;
typedef
struct
timer_list
timer_list
;
#if WIRELESS_EXT <= 12
/* Wireless extensions backward compatibility */
/* Part of iw_handler prototype we need */
struct
iw_request_info
{
__u16
cmd
;
/* Wireless Extension command */
__u16
flags
;
/* More to come ;-) */
};
#endif
/* WIRELESS_EXT <= 12 */
/* Basic types */
/* Basic types */
typedef
u_char
mac_addr
[
WAVELAN_ADDR_SIZE
];
/* Hardware address */
typedef
u_char
mac_addr
[
WAVELAN_ADDR_SIZE
];
/* Hardware address */
...
...
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