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
5bb7978a
Commit
5bb7978a
authored
Sep 26, 2002
by
David Gibson
Committed by
Jeff Garzik
Sep 26, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] Orinoco driver update
This updates the orinoco wireless driver to version 0.13.
parent
aa3f2b33
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1151 additions
and
1096 deletions
+1151
-1096
drivers/net/wireless/airport.c
drivers/net/wireless/airport.c
+72
-103
drivers/net/wireless/hermes.c
drivers/net/wireless/hermes.c
+11
-24
drivers/net/wireless/hermes.h
drivers/net/wireless/hermes.h
+3
-8
drivers/net/wireless/ieee802_11.h
drivers/net/wireless/ieee802_11.h
+2
-2
drivers/net/wireless/orinoco.c
drivers/net/wireless/orinoco.c
+761
-526
drivers/net/wireless/orinoco.h
drivers/net/wireless/orinoco.h
+49
-26
drivers/net/wireless/orinoco_cs.c
drivers/net/wireless/orinoco_cs.c
+236
-349
drivers/net/wireless/orinoco_plx.c
drivers/net/wireless/orinoco_plx.c
+17
-58
No files found.
drivers/net/wireless/airport.c
View file @
5bb7978a
/* airport.c 0.1
1b
/* airport.c 0.1
3
*
*
* A driver for "Hermes" chipset based Apple Airport wireless
* A driver for "Hermes" chipset based Apple Airport wireless
* card.
* card.
...
@@ -30,7 +30,6 @@
...
@@ -30,7 +30,6 @@
#include <linux/if_arp.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/etherdevice.h>
#include <linux/wireless.h>
#include <linux/wireless.h>
#include <linux/list.h>
#include <linux/adb.h>
#include <linux/adb.h>
#include <linux/pmu.h>
#include <linux/pmu.h>
...
@@ -39,22 +38,15 @@
...
@@ -39,22 +38,15 @@
#include <asm/pmac_feature.h>
#include <asm/pmac_feature.h>
#include <asm/irq.h>
#include <asm/irq.h>
#include "hermes.h"
#include "orinoco.h"
#include "orinoco.h"
static
char
version
[]
__initdata
=
"airport.c 0.11b (Benjamin Herrenschmidt <benh@kernel.crashing.org>)"
;
MODULE_AUTHOR
(
"Benjamin Herrenschmidt <benh@kernel.crashing.org>"
);
MODULE_DESCRIPTION
(
"Driver for the Apple Airport wireless card."
);
MODULE_LICENSE
(
"Dual MPL/GPL"
);
#define AIRPORT_IO_LEN (0x1000)
/* one page */
#define AIRPORT_IO_LEN (0x1000)
/* one page */
struct
airport
{
struct
airport
{
struct
device_node
*
node
;
struct
device_node
*
node
;
void
*
vaddr
;
void
*
vaddr
;
int
irq_requested
;
int
irq_requested
;
int
ndev_registered
;
int
ndev_registered
;
int
open
;
};
};
#ifdef CONFIG_PMAC_PBOOK
#ifdef CONFIG_PMAC_PBOOK
...
@@ -70,101 +62,77 @@ static struct pmu_sleep_notifier airport_sleep_notifier = {
...
@@ -70,101 +62,77 @@ static struct pmu_sleep_notifier airport_sleep_notifier = {
static
struct
net_device
*
airport_attach
(
struct
device_node
*
of_node
);
static
struct
net_device
*
airport_attach
(
struct
device_node
*
of_node
);
static
void
airport_detach
(
struct
net_device
*
dev
);
static
void
airport_detach
(
struct
net_device
*
dev
);
static
int
airport_open
(
struct
net_device
*
dev
);
static
int
airport_stop
(
struct
net_device
*
dev
);
/*
A linked list of "instances" of the dummy device. Each actual
PCMCIA card corresponds to one device instance, and is described
by one dev_link_t structure (defined in ds.h).
You may not want to use a linked list for this -- for example, the
memory card driver uses an array of dev_link_t pointers, where minor
device numbers are used to derive the corresponding array index.
*/
static
struct
net_device
*
airport_dev
;
static
struct
net_device
*
airport_dev
;
static
int
airport_open
(
struct
net_device
*
dev
)
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
airport
*
card
=
(
struct
airport
*
)
priv
->
card
;
int
rc
;
TRACE_ENTER
(
dev
->
name
);
netif_device_attach
(
dev
);
rc
=
orinoco_reset
(
priv
);
if
(
rc
)
airport_stop
(
dev
);
else
{
card
->
open
=
1
;
netif_start_queue
(
dev
);
}
TRACE_EXIT
(
dev
->
name
);
return
rc
;
}
static
int
airport_stop
(
struct
net_device
*
dev
)
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
airport
*
card
=
(
struct
airport
*
)
priv
->
card
;
TRACE_ENTER
(
dev
->
name
);
netif_stop_queue
(
dev
);
orinoco_shutdown
(
priv
);
card
->
open
=
0
;
TRACE_EXIT
(
dev
->
name
);
return
0
;
}
#ifdef CONFIG_PMAC_PBOOK
#ifdef CONFIG_PMAC_PBOOK
static
int
static
int
airport_sleep_notify
(
struct
pmu_sleep_notifier
*
self
,
int
when
)
airport_sleep_notify
(
struct
pmu_sleep_notifier
*
self
,
int
when
)
{
{
struct
net_device
*
dev
=
airport_dev
;
struct
net_device
*
dev
=
airport_dev
;
struct
orinoco_private
*
priv
=
(
struct
orinoco_private
*
)
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
hermes
*
hw
=
&
priv
->
hw
;
struct
airport
*
card
=
priv
->
card
;
struct
airport
*
card
=
(
struct
airport
*
)
priv
->
card
;
unsigned
long
flags
;
int
rc
;
int
err
;
if
(
!
airport_dev
)
if
(
!
airport_dev
)
return
PBOOK_SLEEP_OK
;
return
PBOOK_SLEEP_OK
;
switch
(
when
)
{
switch
(
when
)
{
case
PBOOK_SLEEP_REQUEST
:
break
;
case
PBOOK_SLEEP_REJECT
:
break
;
case
PBOOK_SLEEP_NOW
:
case
PBOOK_SLEEP_NOW
:
printk
(
KERN_INFO
"%s: Airport entering sleep mode
\n
"
,
dev
->
name
);
printk
(
KERN_DEBUG
"%s: Airport entering sleep mode
\n
"
,
dev
->
name
);
if
(
card
->
open
)
{
netif_stop_queue
(
dev
);
err
=
orinoco_lock
(
priv
,
&
flags
);
orinoco_shutdown
(
priv
);
if
(
err
)
{
netif_device_detach
(
dev
);
printk
(
KERN_ERR
"%s: hw_unavailable on PBOOK_SLEEP_NOW
\n
"
,
dev
->
name
);
break
;
}
}
err
=
__orinoco_down
(
dev
);
if
(
err
)
printk
(
KERN_WARNING
"%s: PBOOK_SLEEP_NOW: Error %d downing interface
\n
"
,
dev
->
name
,
err
);
netif_device_detach
(
dev
);
priv
->
hw_unavailable
=
1
;
orinoco_unlock
(
priv
,
&
flags
);
disable_irq
(
dev
->
irq
);
disable_irq
(
dev
->
irq
);
pmac_call_feature
(
PMAC_FTR_AIRPORT_ENABLE
,
card
->
node
,
0
,
0
);
pmac_call_feature
(
PMAC_FTR_AIRPORT_ENABLE
,
card
->
node
,
0
,
0
);
break
;
break
;
case
PBOOK_WAKE
:
case
PBOOK_WAKE
:
printk
(
KERN_
INFO
"%s: Airport waking up
\n
"
,
dev
->
name
);
printk
(
KERN_
DEBUG
"%s: Airport waking up
\n
"
,
dev
->
name
);
pmac_call_feature
(
PMAC_FTR_AIRPORT_ENABLE
,
card
->
node
,
0
,
1
);
pmac_call_feature
(
PMAC_FTR_AIRPORT_ENABLE
,
card
->
node
,
0
,
1
);
mdelay
(
200
);
mdelay
(
200
);
hermes_reset
(
hw
);
rc
=
orinoco_reset
(
priv
);
if
(
rc
)
printk
(
KERN_ERR
"airport: Error %d re-initing card !
\n
"
,
rc
);
else
if
(
card
->
open
)
netif_device_attach
(
dev
);
enable_irq
(
dev
->
irq
);
enable_irq
(
dev
->
irq
);
err
=
orinoco_reinit_firmware
(
dev
);
if
(
err
)
{
printk
(
KERN_ERR
"%s: Error %d re-initializing firmware on PBOOK_WAKE
\n
"
,
dev
->
name
,
err
);
break
;
}
spin_lock_irqsave
(
&
priv
->
lock
,
flags
);
netif_device_attach
(
dev
);
if
(
priv
->
open
)
{
err
=
__orinoco_up
(
dev
);
if
(
err
)
printk
(
KERN_ERR
"%s: Error %d restarting card on PBOOK_WAKE
\n
"
,
dev
->
name
,
err
);
}
priv
->
hw_unavailable
=
0
;
spin_unlock_irqrestore
(
&
priv
->
lock
,
flags
);
break
;
break
;
}
}
return
PBOOK_SLEEP_OK
;
return
PBOOK_SLEEP_OK
;
...
@@ -172,7 +140,7 @@ airport_sleep_notify(struct pmu_sleep_notifier *self, int when)
...
@@ -172,7 +140,7 @@ airport_sleep_notify(struct pmu_sleep_notifier *self, int when)
#endif
/* CONFIG_PMAC_PBOOK */
#endif
/* CONFIG_PMAC_PBOOK */
static
struct
net_device
*
static
struct
net_device
*
airport_attach
(
struct
device_node
*
of_node
)
airport_attach
(
struct
device_node
*
of_node
)
{
{
struct
orinoco_private
*
priv
;
struct
orinoco_private
*
priv
;
struct
net_device
*
dev
;
struct
net_device
*
dev
;
...
@@ -180,15 +148,13 @@ airport_attach(struct device_node* of_node)
...
@@ -180,15 +148,13 @@ airport_attach(struct device_node* of_node)
unsigned
long
phys_addr
;
unsigned
long
phys_addr
;
hermes_t
*
hw
;
hermes_t
*
hw
;
TRACE_ENTER
(
"orinoco"
);
if
(
of_node
->
n_addrs
<
1
||
of_node
->
n_intrs
<
1
)
{
if
(
of_node
->
n_addrs
<
1
||
of_node
->
n_intrs
<
1
)
{
printk
(
KERN_ERR
"airport: wrong interrupt/addresses in OF tree
\n
"
);
printk
(
KERN_ERR
"airport: wrong interrupt/addresses in OF tree
\n
"
);
return
NULL
;
return
NULL
;
}
}
/* Allocate space for private device-specific data */
/* Allocate space for private device-specific data */
dev
=
alloc_orinocodev
(
sizeof
(
*
card
));
dev
=
alloc_orinocodev
(
sizeof
(
*
card
)
,
NULL
);
if
(
!
dev
)
{
if
(
!
dev
)
{
printk
(
KERN_ERR
"airport: can't allocate device datas
\n
"
);
printk
(
KERN_ERR
"airport: can't allocate device datas
\n
"
);
return
NULL
;
return
NULL
;
...
@@ -204,17 +170,14 @@ airport_attach(struct device_node* of_node)
...
@@ -204,17 +170,14 @@ airport_attach(struct device_node* of_node)
kfree
(
dev
);
kfree
(
dev
);
return
NULL
;
return
NULL
;
}
}
dev
->
name
[
0
]
=
'\0'
;
/* register_netdev will give us an ethX name */
dev
->
name
[
0
]
=
'\0'
;
/* register_netdev will give us an ethX name */
SET_MODULE_OWNER
(
dev
);
SET_MODULE_OWNER
(
dev
);
/* Overrides */
dev
->
open
=
airport_open
;
dev
->
stop
=
airport_stop
;
/* Setup interrupts & base address */
/* Setup interrupts & base address */
dev
->
irq
=
of_node
->
intrs
[
0
].
line
;
dev
->
irq
=
of_node
->
intrs
[
0
].
line
;
phys_addr
=
of_node
->
addrs
[
0
].
address
;
/* Physical address */
phys_addr
=
of_node
->
addrs
[
0
].
address
;
/* Physical address */
printk
(
KERN_DEBUG
"Airport at physical address %lx
\n
"
,
phys_addr
);
dev
->
base_addr
=
phys_addr
;
dev
->
base_addr
=
phys_addr
;
card
->
vaddr
=
ioremap
(
phys_addr
,
AIRPORT_IO_LEN
);
card
->
vaddr
=
ioremap
(
phys_addr
,
AIRPORT_IO_LEN
);
if
(
!
card
->
vaddr
)
{
if
(
!
card
->
vaddr
)
{
...
@@ -231,14 +194,14 @@ airport_attach(struct device_node* of_node)
...
@@ -231,14 +194,14 @@ airport_attach(struct device_node* of_node)
schedule_timeout
(
HZ
);
schedule_timeout
(
HZ
);
/* Reset it before we get the interrupt */
/* Reset it before we get the interrupt */
hermes_
rese
t
(
hw
);
hermes_
ini
t
(
hw
);
if
(
request_irq
(
dev
->
irq
,
orinoco_interrupt
,
0
,
"Airport"
,
(
void
*
)
priv
))
{
if
(
request_irq
(
dev
->
irq
,
orinoco_interrupt
,
0
,
"Airport"
,
(
void
*
)
priv
))
{
printk
(
KERN_ERR
"airport: Couldn't get IRQ %d
\n
"
,
dev
->
irq
);
printk
(
KERN_ERR
"airport: Couldn't get IRQ %d
\n
"
,
dev
->
irq
);
goto
failed
;
goto
failed
;
}
}
card
->
irq_requested
=
1
;
card
->
irq_requested
=
1
;
/* Tell the stack we exist */
/* Tell the stack we exist */
if
(
register_netdev
(
dev
)
!=
0
)
{
if
(
register_netdev
(
dev
)
!=
0
)
{
printk
(
KERN_ERR
"airport: register_netdev() failed
\n
"
);
printk
(
KERN_ERR
"airport: register_netdev() failed
\n
"
);
...
@@ -248,7 +211,7 @@ airport_attach(struct device_node* of_node)
...
@@ -248,7 +211,7 @@ airport_attach(struct device_node* of_node)
card
->
ndev_registered
=
1
;
card
->
ndev_registered
=
1
;
/* And give us the proc nodes for debugging */
/* And give us the proc nodes for debugging */
if
(
orinoco_proc_dev_init
(
pri
v
)
!=
0
)
if
(
orinoco_proc_dev_init
(
de
v
)
!=
0
)
printk
(
KERN_ERR
"airport: Failed to create /proc node for %s
\n
"
,
printk
(
KERN_ERR
"airport: Failed to create /proc node for %s
\n
"
,
dev
->
name
);
dev
->
name
);
...
@@ -257,7 +220,7 @@ airport_attach(struct device_node* of_node)
...
@@ -257,7 +220,7 @@ airport_attach(struct device_node* of_node)
#endif
#endif
return
dev
;
return
dev
;
failed:
failed:
airport_detach
(
dev
);
airport_detach
(
dev
);
return
NULL
;
return
NULL
;
}
/* airport_attach */
}
/* airport_attach */
...
@@ -273,7 +236,7 @@ airport_detach(struct net_device *dev)
...
@@ -273,7 +236,7 @@ airport_detach(struct net_device *dev)
struct
airport
*
card
=
priv
->
card
;
struct
airport
*
card
=
priv
->
card
;
/* Unregister proc entry */
/* Unregister proc entry */
orinoco_proc_dev_cleanup
(
pri
v
);
orinoco_proc_dev_cleanup
(
de
v
);
#ifdef CONFIG_PMAC_PBOOK
#ifdef CONFIG_PMAC_PBOOK
pmu_unregister_sleep_notifier
(
&
airport_sleep_notifier
);
pmu_unregister_sleep_notifier
(
&
airport_sleep_notifier
);
...
@@ -281,7 +244,7 @@ airport_detach(struct net_device *dev)
...
@@ -281,7 +244,7 @@ airport_detach(struct net_device *dev)
if
(
card
->
ndev_registered
)
if
(
card
->
ndev_registered
)
unregister_netdev
(
dev
);
unregister_netdev
(
dev
);
card
->
ndev_registered
=
0
;
card
->
ndev_registered
=
0
;
if
(
card
->
irq_requested
)
if
(
card
->
irq_requested
)
free_irq
(
dev
->
irq
,
priv
);
free_irq
(
dev
->
irq
,
priv
);
card
->
irq_requested
=
0
;
card
->
irq_requested
=
0
;
...
@@ -289,22 +252,28 @@ airport_detach(struct net_device *dev)
...
@@ -289,22 +252,28 @@ airport_detach(struct net_device *dev)
if
(
card
->
vaddr
)
if
(
card
->
vaddr
)
iounmap
(
card
->
vaddr
);
iounmap
(
card
->
vaddr
);
card
->
vaddr
=
0
;
card
->
vaddr
=
0
;
dev
->
base_addr
=
0
;
dev
->
base_addr
=
0
;
release_OF_resource
(
card
->
node
,
0
);
release_OF_resource
(
card
->
node
,
0
);
pmac_call_feature
(
PMAC_FTR_AIRPORT_ENABLE
,
card
->
node
,
0
,
0
);
pmac_call_feature
(
PMAC_FTR_AIRPORT_ENABLE
,
card
->
node
,
0
,
0
);
current
->
state
=
TASK_UNINTERRUPTIBLE
;
current
->
state
=
TASK_UNINTERRUPTIBLE
;
schedule_timeout
(
HZ
);
schedule_timeout
(
HZ
);
kfree
(
dev
);
kfree
(
dev
);
}
/* airport_detach */
}
/* airport_detach */
static
char
version
[]
__initdata
=
"airport.c 0.13 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)"
;
MODULE_AUTHOR
(
"Benjamin Herrenschmidt <benh@kernel.crashing.org>"
);
MODULE_DESCRIPTION
(
"Driver for the Apple Airport wireless card."
);
MODULE_LICENSE
(
"Dual MPL/GPL"
);
EXPORT_NO_SYMBOLS
;
static
int
__init
static
int
__init
init_airport
(
void
)
init_airport
(
void
)
{
{
struct
device_node
*
airport_node
;
struct
device_node
*
airport_node
;
printk
(
KERN_DEBUG
"%s
\n
"
,
version
);
printk
(
KERN_DEBUG
"%s
\n
"
,
version
);
...
...
drivers/net/wireless/hermes.c
View file @
5bb7978a
...
@@ -45,7 +45,6 @@
...
@@ -45,7 +45,6 @@
#include <linux/threads.h>
#include <linux/threads.h>
#include <linux/smp.h>
#include <linux/smp.h>
#include <asm/io.h>
#include <asm/io.h>
#include <linux/ptrace.h>
#include <linux/delay.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
...
@@ -53,7 +52,7 @@
...
@@ -53,7 +52,7 @@
#include "hermes.h"
#include "hermes.h"
static
char
version
[]
__initdata
=
"hermes.c:
5 Apr
2002 David Gibson <hermes@gibson.dropbear.id.au>"
;
static
char
version
[]
__initdata
=
"hermes.c:
4 Jul
2002 David Gibson <hermes@gibson.dropbear.id.au>"
;
MODULE_DESCRIPTION
(
"Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller"
);
MODULE_DESCRIPTION
(
"Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller"
);
MODULE_AUTHOR
(
"David Gibson <hermes@gibson.dropbear.id.au>"
);
MODULE_AUTHOR
(
"David Gibson <hermes@gibson.dropbear.id.au>"
);
#ifdef MODULE_LICENSE
#ifdef MODULE_LICENSE
...
@@ -70,14 +69,14 @@ MODULE_LICENSE("Dual MPL/GPL");
...
@@ -70,14 +69,14 @@ MODULE_LICENSE("Dual MPL/GPL");
* Debugging helpers
* Debugging helpers
*/
*/
#define IO_TYPE(hw) ((hw)->io_space ? "IO " : "MEM ")
#define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ %s0x%x: " , IO_TYPE(hw), hw->iobase); \
printk(stuff);} while (0)
#undef HERMES_DEBUG
#undef HERMES_DEBUG
#ifdef HERMES_DEBUG
#ifdef HERMES_DEBUG
#include <stdarg.h>
#include <stdarg.h>
#define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ 0x%x: " , hw->iobase); \
printk(stuff);} while (0)
#define DEBUG(lvl, stuff...) if ( (lvl) <= HERMES_DEBUG) DMSG(stuff)
#define DEBUG(lvl, stuff...) if ( (lvl) <= HERMES_DEBUG) DMSG(stuff)
#else
/* ! HERMES_DEBUG */
#else
/* ! HERMES_DEBUG */
...
@@ -86,7 +85,6 @@ MODULE_LICENSE("Dual MPL/GPL");
...
@@ -86,7 +85,6 @@ MODULE_LICENSE("Dual MPL/GPL");
#endif
/* ! HERMES_DEBUG */
#endif
/* ! HERMES_DEBUG */
#define IO_TYPE(hw) ((hw)->io_space ? "IO " : "MEM ")
/*
/*
* Internal functions
* Internal functions
...
@@ -111,7 +109,6 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0)
...
@@ -111,7 +109,6 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0)
udelay
(
1
);
udelay
(
1
);
reg
=
hermes_read_regn
(
hw
,
CMD
);
reg
=
hermes_read_regn
(
hw
,
CMD
);
}
}
DEBUG
(
3
,
"hermes_issue_cmd: did %d retries.
\n
"
,
CMD_BUSY_TIMEOUT
-
k
);
if
(
reg
&
HERMES_CMD_BUSY
)
{
if
(
reg
&
HERMES_CMD_BUSY
)
{
return
-
EBUSY
;
return
-
EBUSY
;
}
}
...
@@ -143,7 +140,7 @@ void hermes_struct_init(hermes_t *hw, ulong address,
...
@@ -143,7 +140,7 @@ void hermes_struct_init(hermes_t *hw, ulong address,
#endif
#endif
}
}
int
hermes_
rese
t
(
hermes_t
*
hw
)
int
hermes_
ini
t
(
hermes_t
*
hw
)
{
{
u16
status
,
reg
;
u16
status
,
reg
;
int
err
=
0
;
int
err
=
0
;
...
@@ -195,8 +192,6 @@ int hermes_reset(hermes_t *hw)
...
@@ -195,8 +192,6 @@ int hermes_reset(hermes_t *hw)
reg
=
hermes_read_regn
(
hw
,
EVSTAT
);
reg
=
hermes_read_regn
(
hw
,
EVSTAT
);
}
}
DEBUG
(
0
,
"Reset completed in %d iterations
\n
"
,
CMD_INIT_TIMEOUT
-
k
);
hermes_write_regn
(
hw
,
SWSUPPORT0
,
HERMES_MAGIC
);
hermes_write_regn
(
hw
,
SWSUPPORT0
,
HERMES_MAGIC
);
if
(
!
hermes_present
(
hw
))
{
if
(
!
hermes_present
(
hw
))
{
...
@@ -303,9 +298,6 @@ int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
...
@@ -303,9 +298,6 @@ int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
err
=
hermes_docmd_wait
(
hw
,
HERMES_CMD_ALLOC
,
size
,
NULL
);
err
=
hermes_docmd_wait
(
hw
,
HERMES_CMD_ALLOC
,
size
,
NULL
);
if
(
err
)
{
if
(
err
)
{
printk
(
KERN_WARNING
"hermes @ %s0x%lx: "
"Frame allocation command failed (0x%X).
\n
"
,
IO_TYPE
(
hw
),
hw
->
iobase
,
err
);
return
err
;
return
err
;
}
}
...
@@ -393,12 +385,10 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
...
@@ -393,12 +385,10 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
}
}
if
(
reg
&
HERMES_OFFSET_BUSY
)
{
if
(
reg
&
HERMES_OFFSET_BUSY
)
{
DEBUG
(
1
,
"hermes_bap_seek: timeout
\n
"
);
return
-
ETIMEDOUT
;
return
-
ETIMEDOUT
;
}
}
if
(
reg
&
HERMES_OFFSET_ERR
)
{
if
(
reg
&
HERMES_OFFSET_ERR
)
{
DEBUG
(
1
,
"hermes_bap_seek: BAP error
\n
"
);
return
-
EIO
;
return
-
EIO
;
}
}
...
@@ -472,6 +462,7 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, int bufsize,
...
@@ -472,6 +462,7 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, int bufsize,
int
err
=
0
;
int
err
=
0
;
int
dreg
=
bap
?
HERMES_DATA1
:
HERMES_DATA0
;
int
dreg
=
bap
?
HERMES_DATA1
:
HERMES_DATA0
;
u16
rlength
,
rtype
;
u16
rlength
,
rtype
;
int
nwords
;
if
(
(
bufsize
<
0
)
||
(
bufsize
%
2
)
)
if
(
(
bufsize
<
0
)
||
(
bufsize
%
2
)
)
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -500,10 +491,9 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, int bufsize,
...
@@ -500,10 +491,9 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, int bufsize,
"(rid=0x%04x, len=0x%04x)
\n
"
,
"(rid=0x%04x, len=0x%04x)
\n
"
,
IO_TYPE
(
hw
),
hw
->
iobase
,
IO_TYPE
(
hw
),
hw
->
iobase
,
HERMES_RECLEN_TO_BYTES
(
rlength
),
bufsize
,
rid
,
rlength
);
HERMES_RECLEN_TO_BYTES
(
rlength
),
bufsize
,
rid
,
rlength
);
/* FIXME: we should read the min of the requested length and
nwords
=
min_t
(
int
,
rlength
-
1
,
bufsize
/
2
);
the actual record length */
hermes_read_words
(
hw
,
dreg
,
buf
,
nwords
);
hermes_read_words
(
hw
,
dreg
,
buf
,
bufsize
/
2
);
out:
out:
return
err
;
return
err
;
...
@@ -516,9 +506,6 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
...
@@ -516,9 +506,6 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
int
err
=
0
;
int
err
=
0
;
int
count
;
int
count
;
DEBUG
(
3
,
"write_ltv(): bap=%d rid=0x%04x length=%d (value=0x%04x)
\n
"
,
bap
,
rid
,
length
,
*
((
u16
*
)
value
));
err
=
hermes_bap_seek
(
hw
,
bap
,
rid
,
0
);
err
=
hermes_bap_seek
(
hw
,
bap
,
rid
,
0
);
if
(
err
)
if
(
err
)
goto
out
;
goto
out
;
...
@@ -538,7 +525,7 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
...
@@ -538,7 +525,7 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
}
}
EXPORT_SYMBOL
(
hermes_struct_init
);
EXPORT_SYMBOL
(
hermes_struct_init
);
EXPORT_SYMBOL
(
hermes_
rese
t
);
EXPORT_SYMBOL
(
hermes_
ini
t
);
EXPORT_SYMBOL
(
hermes_docmd_wait
);
EXPORT_SYMBOL
(
hermes_docmd_wait
);
EXPORT_SYMBOL
(
hermes_allocate
);
EXPORT_SYMBOL
(
hermes_allocate
);
...
...
drivers/net/wireless/hermes.h
View file @
5bb7978a
...
@@ -171,6 +171,7 @@ struct hermes_rx_descriptor {
...
@@ -171,6 +171,7 @@ struct hermes_rx_descriptor {
#define HERMES_RXSTAT_BADCRC (0x0001)
#define HERMES_RXSTAT_BADCRC (0x0001)
#define HERMES_RXSTAT_UNDECRYPTABLE (0x0002)
#define HERMES_RXSTAT_UNDECRYPTABLE (0x0002)
#define HERMES_RXSTAT_MACPORT (0x0700)
#define HERMES_RXSTAT_MACPORT (0x0700)
#define HERMES_RXSTAT_PCF (0x1000)
/* Frame was received in CF period */
#define HERMES_RXSTAT_MSGTYPE (0xE000)
#define HERMES_RXSTAT_MSGTYPE (0xE000)
#define HERMES_RXSTAT_1042 (0x2000)
/* RFC-1042 frame */
#define HERMES_RXSTAT_1042 (0x2000)
/* RFC-1042 frame */
#define HERMES_RXSTAT_TUNNEL (0x4000)
/* bridge-tunnel encoded frame */
#define HERMES_RXSTAT_TUNNEL (0x4000)
/* bridge-tunnel encoded frame */
...
@@ -299,7 +300,7 @@ typedef struct hermes_response {
...
@@ -299,7 +300,7 @@ typedef struct hermes_response {
/* Function prototypes */
/* Function prototypes */
void
hermes_struct_init
(
hermes_t
*
hw
,
ulong
address
,
int
io_space
,
int
reg_spacing
);
void
hermes_struct_init
(
hermes_t
*
hw
,
ulong
address
,
int
io_space
,
int
reg_spacing
);
int
hermes_
rese
t
(
hermes_t
*
hw
);
int
hermes_
ini
t
(
hermes_t
*
hw
);
int
hermes_docmd_wait
(
hermes_t
*
hw
,
u16
cmd
,
u16
parm0
,
hermes_response_t
*
resp
);
int
hermes_docmd_wait
(
hermes_t
*
hw
,
u16
cmd
,
u16
parm0
,
hermes_response_t
*
resp
);
int
hermes_allocate
(
hermes_t
*
hw
,
u16
size
,
u16
*
fid
);
int
hermes_allocate
(
hermes_t
*
hw
,
u16
size
,
u16
*
fid
);
...
@@ -319,12 +320,6 @@ static inline int hermes_present(hermes_t *hw)
...
@@ -319,12 +320,6 @@ static inline int hermes_present(hermes_t *hw)
return
hermes_read_regn
(
hw
,
SWSUPPORT0
)
==
HERMES_MAGIC
;
return
hermes_read_regn
(
hw
,
SWSUPPORT0
)
==
HERMES_MAGIC
;
}
}
static
inline
void
hermes_enable_interrupt
(
hermes_t
*
hw
,
u16
events
)
{
hw
->
inten
|=
events
;
hermes_write_regn
(
hw
,
INTEN
,
hw
->
inten
);
}
static
inline
void
hermes_set_irqmask
(
hermes_t
*
hw
,
u16
events
)
static
inline
void
hermes_set_irqmask
(
hermes_t
*
hw
,
u16
events
)
{
{
hw
->
inten
=
events
;
hw
->
inten
=
events
;
...
@@ -350,7 +345,7 @@ static inline int hermes_inquire(hermes_t *hw, u16 rid)
...
@@ -350,7 +345,7 @@ static inline int hermes_inquire(hermes_t *hw, u16 rid)
return
hermes_docmd_wait
(
hw
,
HERMES_CMD_INQUIRE
,
rid
,
NULL
);
return
hermes_docmd_wait
(
hw
,
HERMES_CMD_INQUIRE
,
rid
,
NULL
);
}
}
#define HERMES_BYTES_TO_RECLEN(n) ( ((
n) % 2) ? (((n)+1)/2)+1 : ((n)/2)+
1 )
#define HERMES_BYTES_TO_RECLEN(n) ( ((
(n)+1)/2) +
1 )
#define HERMES_RECLEN_TO_BYTES(n) ( ((n)-1) * 2 )
#define HERMES_RECLEN_TO_BYTES(n) ( ((n)-1) * 2 )
/* Note that for the next two, the count is in 16-bit words, not bytes */
/* Note that for the next two, the count is in 16-bit words, not bytes */
...
...
drivers/net/wireless/ieee802_11.h
View file @
5bb7978a
...
@@ -3,8 +3,8 @@
...
@@ -3,8 +3,8 @@
#define IEEE802_11_DATA_LEN 2304
#define IEEE802_11_DATA_LEN 2304
/* Actually, the standard seems to be inconsistent about what the
/* Actually, the standard seems to be inconsistent about what the
maximum frame size really is. S
6.2.1.1.2 says 2304 octets, but the
maximum frame size really is. S
ection 6.2.1.1.2 says 2304 octets,
figure in s
ection 7.1.2 says 2312 octects. */
but the figure in S
ection 7.1.2 says 2312 octects. */
#define IEEE802_11_HLEN 30
#define IEEE802_11_HLEN 30
#define IEEE802_11_FRAME_LEN (IEEE802_11_DATA_LEN + IEEE802_11_HLEN)
#define IEEE802_11_FRAME_LEN (IEEE802_11_DATA_LEN + IEEE802_11_HLEN)
...
...
drivers/net/wireless/orinoco.c
View file @
5bb7978a
/* orinoco.c 0.1
1b
- (formerly known as dldwd_cs.c and orinoco_cs.c)
/* orinoco.c 0.1
3
- (formerly known as dldwd_cs.c and orinoco_cs.c)
*
*
* A driver for Hermes or Prism 2 chipset based PCMCIA wireless
* A driver for Hermes or Prism 2 chipset based PCMCIA wireless
* adaptors, with Lucent/Agere, Intersil or Symbol firmware.
* adaptors, with Lucent/Agere, Intersil or Symbol firmware.
...
@@ -240,7 +240,7 @@
...
@@ -240,7 +240,7 @@
* was never very useful.
* was never very useful.
* o Make Rx errors less noisy.
* o Make Rx errors less noisy.
*
*
* v0.10 -> v0.11 - 5 Apr
Mar
2002 - David Gibson
* v0.10 -> v0.11 - 5 Apr 2002 - David Gibson
* o Laid the groundwork in hermes.[ch] for devices which map
* o Laid the groundwork in hermes.[ch] for devices which map
* into PCI memory space rather than IO space.
* into PCI memory space rather than IO space.
* o Fixed bug in multicast handling (cleared multicast list when
* o Fixed bug in multicast handling (cleared multicast list when
...
@@ -256,7 +256,7 @@
...
@@ -256,7 +256,7 @@
* o Fixes for recent Symbol firmwares which lack AP density
* o Fixes for recent Symbol firmwares which lack AP density
* (Pavel Roskin).
* (Pavel Roskin).
*
*
* v0.11 -> v0.11
b
- 29 Apr 2002 - David Gibson
* v0.11 -> v0.11
a
- 29 Apr 2002 - David Gibson
* o Handle different register spacing, necessary for Prism 2.5
* o Handle different register spacing, necessary for Prism 2.5
* PCI adaptors (Steve Hill).
* PCI adaptors (Steve Hill).
* o Cleaned up initialization of card structures in orinoco_cs
* o Cleaned up initialization of card structures in orinoco_cs
...
@@ -279,44 +279,79 @@
...
@@ -279,44 +279,79 @@
* o Fixed multiple bad kfree() bugs introduced by the
* o Fixed multiple bad kfree() bugs introduced by the
* alloc_orinocodev() changes.
* alloc_orinocodev() changes.
*
*
* v0.11b -> v0.12 - 19 Jun 2002 - David Gibson
* o Support changing the MAC address.
* o Correct display of Intersil firmware revision numbers.
* o Entirely revised locking scheme. Should be both simpler and
* better.
* o Merged some common code in orinoco_plx, orinoco_pci and
* airport by creating orinoco_default_{open,stop,reset}()
* which are used as the dev->open, dev->stop, priv->reset
* callbacks if none are specified when alloc_orinocodev() is
* called.
* o Removed orinoco_plx_interupt() and orinoco_pci_interrupt().
* They didn't do anything.
*
* v0.12 -> v0.12a - 4 Jul 2002 - David Gibson
* o Some rearrangement of code.
* o Numerous fixups to locking and rest handling, particularly
* for PCMCIA.
* o This allows open and stop net_device methods to be in
* orinoco.c now, rather than in the init modules.
* o In orinoco_cs.c link->priv now points to the struct
* net_device not to the struct orinoco_private.
* o Added a check for undersized SNAP frames, which could cause
* crashes.
*
* v0.12a -> v0.12b - 11 Jul 2002 - David Gibson
* o Fix hw->num_init testing code, so num_init is actually
* incremented.
* o Fix very stupid bug in orinoco_cs which broke compile with
* CONFIG_SMP.
* o Squashed a warning.
*
* v0.12b -> v0.12c - 26 Jul 2002 - David Gibson
* o Change to C9X style designated initializers.
* o Add support for 3Com AirConnect PCI.
* o No longer ignore the hard_reset argument to
* alloc_orinocodev(). Oops.
*
* v0.12c -> v0.13 - 13 Sep 2002 - David Gibson
* o Revert the broken 0.12* locking scheme and go to a new yet
* simpler scheme.
* o Do firmware resets only in orinoco_init() and when waking
* the card from hard sleep.
*
* v0.13 -> v0.13 - 27 Sep 2002 - David Gibson
* o Re-introduced full resets (via schedule_task()) on Tx
* timeout.
*
* TODO
* TODO
* o New wireless extensions API
* o New wireless extensions API (patch forthcoming from Moustafa
* Youssef).
* o Handle de-encapsulation within network layer, provide 802.11
* o Handle de-encapsulation within network layer, provide 802.11
* headers
* headers
(patch from Thomas 'Dent' Mirlacher)
* o Fix possible races in SPY handling.
* o Fix possible races in SPY handling.
* o Disconnect wireless extensions from fundamental configuration.
* o Disconnect wireless extensions from fundamental configuration.
* o (maybe) Software WEP support (patch from Stano Meduna).
* o (maybe) Convert /proc debugging stuff to seqfile
* o (maybe) Use multiple Tx buffers - driver handling queue
* rather than firmware. */
/* Locking and synchronization:
*
*
* o Convert /proc debugging stuff to seqfile
* The basic principle is that everything is serialized through a
* o Use multiple Tx buffers
* single spinlock, priv->lock. The lock is used in user, bh and irq
*/
* context, so when taken outside hardirq context it should always be
/* Notes on locking:
* taken with interrupts disabled. The lock protects both the
*
* hardware and the struct orinoco_private.
* The basic principle of operation is that everything except the
* interrupt handler is serialized through a single spinlock in the
* struct orinoco_private structure, using orinoco_lock() and
* orinoco_unlock() (which in turn use spin_lock_bh() and
* spin_unlock_bh()).
*
* The kernel's IRQ handling stuff ensures that the interrupt handler
* does not re-enter itself. The interrupt handler is written such
* that everything it does is safe without a lock: chiefly this means
* that the Rx path uses one of the Hermes chipset's BAPs while
* everything else uses the other.
*
* Actually, strictly speaking, the updating of the statistics from
* the interrupt handler isn't safe without a lock. However the worst
* that can happen is that we perturb the packet/byte counts slightly.
* We could fix this to use atomic types, but it's probably not worth
* it.
*
*
* The big exception is that that we don't want the irq handler
* Another flag, priv->hw_unavailable indicates that the hardware is
* running when we actually reset or shut down the card, because
* unavailable for an extended period of time (e.g. suspended, or in
* strange things might happen (probably the worst would be one packet
* the middle of a hard reset). This flag is protected by the
* of garbage, but you can't be too careful). For this we use
* spinlock. All code which touches the hardware should check the
* __orinoco_stop_irqs() which will set a flag to disable the interrupt
* flag after taking the lock, and if it is set, give up on whatever
* handler, and wait for any outstanding instances of the handler to
* they are doing and drop the lock again. */
* complete. THIS WILL LOSE INTERRUPTS! so it shouldn't be used except
* for resets, where losing a few interrupts is acceptable. */
#include <linux/config.h>
#include <linux/config.h>
...
@@ -333,31 +368,20 @@
...
@@ -333,31 +368,20 @@
#include <asm/io.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/system.h>
#include <linux/proc_fs.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/etherdevice.h>
#include <linux/wireless.h>
#include <linux/wireless.h>
#include <linux/list.h>
#include "hermes.h"
#include "hermes.h"
#include "hermes_rid.h"
#include "hermes_rid.h"
#include "orinoco.h"
#include "orinoco.h"
#include "ieee802_11.h"
#include "ieee802_11.h"
/* Wireless extensions backwards compatibility */
/********************************************************************/
#ifndef SIOCIWFIRSTPRIV
/* Module information */
#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE
/********************************************************************/
#endif
/* SIOCIWFIRSTPRIV */
/* We do this this way to avoid ifdefs in the actual code */
#ifdef WIRELESS_SPY
#define SPY_NUMBER(priv) (priv->spy_number)
#else
#define SPY_NUMBER(priv) 0
#endif
/* WIRELESS_SPY */
static
char
version
[]
__initdata
=
"orinoco.c 0.11b (David Gibson <hermes@gibson.dropbear.id.au> and others)"
;
MODULE_AUTHOR
(
"David Gibson <hermes@gibson.dropbear.id.au>"
);
MODULE_AUTHOR
(
"David Gibson <hermes@gibson.dropbear.id.au>"
);
MODULE_DESCRIPTION
(
"Driver for Lucent Orinoco, Prism II based and similar wireless cards"
);
MODULE_DESCRIPTION
(
"Driver for Lucent Orinoco, Prism II based and similar wireless cards"
);
#ifdef MODULE_LICENSE
#ifdef MODULE_LICENSE
...
@@ -371,6 +395,26 @@ MODULE_PARM(orinoco_debug, "i");
...
@@ -371,6 +395,26 @@ MODULE_PARM(orinoco_debug, "i");
EXPORT_SYMBOL
(
orinoco_debug
);
EXPORT_SYMBOL
(
orinoco_debug
);
#endif
#endif
/********************************************************************/
/* Compile time configuration and compatibility stuff */
/********************************************************************/
/* Wireless extensions backwards compatibility */
#ifndef SIOCIWFIRSTPRIV
#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE
#endif
/* SIOCIWFIRSTPRIV */
/* We do this this way to avoid ifdefs in the actual code */
#ifdef WIRELESS_SPY
#define SPY_NUMBER(priv) (priv->spy_number)
#else
#define SPY_NUMBER(priv) 0
#endif
/* WIRELESS_SPY */
/********************************************************************/
/* Internal constants */
/********************************************************************/
#define ORINOCO_MIN_MTU 256
#define ORINOCO_MIN_MTU 256
#define ORINOCO_MAX_MTU (IEEE802_11_DATA_LEN - ENCAPS_OVERHEAD)
#define ORINOCO_MAX_MTU (IEEE802_11_DATA_LEN - ENCAPS_OVERHEAD)
...
@@ -386,6 +430,8 @@ EXPORT_SYMBOL(orinoco_debug);
...
@@ -386,6 +430,8 @@ EXPORT_SYMBOL(orinoco_debug);
#define DUMMY_FID 0xFFFF
#define DUMMY_FID 0xFFFF
#define RUP_EVEN(a) (((a) + 1) & (~1))
/*#define MAX_MULTICAST(priv) (priv->firmware_type == FIRMWARE_TYPE_AGERE ? \
/*#define MAX_MULTICAST(priv) (priv->firmware_type == FIRMWARE_TYPE_AGERE ? \
HERMES_MAX_MULTICAST : 0)*/
HERMES_MAX_MULTICAST : 0)*/
#define MAX_MULTICAST(priv) (HERMES_MAX_MULTICAST)
#define MAX_MULTICAST(priv) (HERMES_MAX_MULTICAST)
...
@@ -419,6 +465,10 @@ struct {
...
@@ -419,6 +465,10 @@ struct {
};
};
#define BITRATE_TABLE_SIZE (sizeof(bitrate_table) / sizeof(bitrate_table[0]))
#define BITRATE_TABLE_SIZE (sizeof(bitrate_table) / sizeof(bitrate_table[0]))
/********************************************************************/
/* Data types */
/********************************************************************/
struct
header_struct
{
struct
header_struct
{
/* 802.3 */
/* 802.3 */
u8
dest
[
ETH_ALEN
];
u8
dest
[
ETH_ALEN
];
...
@@ -438,27 +488,29 @@ u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
...
@@ -438,27 +488,29 @@ u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
/*
/*
*******************************************************************/
* Function prototypes
/* Function prototypes */
*/
/*******************************************************************
*/
static
void
orinoco_stat_gather
(
struct
net_device
*
dev
,
static
void
orinoco_stat_gather
(
struct
net_device
*
dev
,
struct
sk_buff
*
skb
,
struct
sk_buff
*
skb
,
struct
hermes_rx_descriptor
*
desc
);
struct
hermes_rx_descriptor
*
desc
);
static
struct
net_device_stats
*
orinoco_get_stats
(
struct
net_device
*
dev
);
static
struct
net_device_stats
*
orinoco_get_stats
(
struct
net_device
*
dev
);
static
struct
iw_statistics
*
orinoco_get_wireless_stats
(
struct
net_device
*
dev
);
static
struct
iw_statistics
*
orinoco_get_wireless_stats
(
struct
net_device
*
dev
);
/* Hardware control routines */
/* Hardware control routines */
static
int
__orinoco_program_rids
(
struct
orinoco_private
*
priv
);
static
int
__orinoco_hw_set_bitrate
(
struct
orinoco_private
*
priv
);
static
int
__orinoco_hw_set_bitrate
(
struct
orinoco_private
*
priv
);
static
int
__orinoco_hw_setup_wep
(
struct
orinoco_private
*
priv
);
static
int
__orinoco_hw_setup_wep
(
struct
orinoco_private
*
priv
);
static
int
orinoco_hw_get_bssid
(
struct
orinoco_private
*
priv
,
char
buf
[
ETH_ALEN
]);
static
int
orinoco_hw_get_bssid
(
struct
orinoco_private
*
priv
,
char
buf
[
ETH_ALEN
]);
static
int
orinoco_hw_get_essid
(
struct
orinoco_private
*
priv
,
int
*
active
,
static
int
orinoco_hw_get_essid
(
struct
orinoco_private
*
priv
,
int
*
active
,
char
buf
[
IW_ESSID_MAX_SIZE
+
1
]);
char
buf
[
IW_ESSID_MAX_SIZE
+
1
]);
static
long
orinoco_hw_get_freq
(
struct
orinoco_private
*
priv
);
static
long
orinoco_hw_get_freq
(
struct
orinoco_private
*
priv
);
static
int
orinoco_hw_get_bitratelist
(
struct
orinoco_private
*
priv
,
int
*
numrates
,
static
int
orinoco_hw_get_bitratelist
(
struct
orinoco_private
*
priv
,
int
*
numrates
,
s32
*
rates
,
int
max
);
s32
*
rates
,
int
max
);
static
void
__orinoco_set_multicast_list
(
struct
net_device
*
dev
);
static
void
__orinoco_set_multicast_list
(
struct
net_device
*
dev
);
/* Interrupt handling routines */
/* Interrupt handling routines */
...
@@ -471,6 +523,7 @@ static void __orinoco_ev_txexc(struct orinoco_private *priv, hermes_t *hw);
...
@@ -471,6 +523,7 @@ static void __orinoco_ev_txexc(struct orinoco_private *priv, hermes_t *hw);
static
void
__orinoco_ev_tx
(
struct
orinoco_private
*
priv
,
hermes_t
*
hw
);
static
void
__orinoco_ev_tx
(
struct
orinoco_private
*
priv
,
hermes_t
*
hw
);
static
void
__orinoco_ev_alloc
(
struct
orinoco_private
*
priv
,
hermes_t
*
hw
);
static
void
__orinoco_ev_alloc
(
struct
orinoco_private
*
priv
,
hermes_t
*
hw
);
/* ioctl() routines */
static
int
orinoco_ioctl_getiwrange
(
struct
net_device
*
dev
,
struct
iw_point
*
rrq
);
static
int
orinoco_ioctl_getiwrange
(
struct
net_device
*
dev
,
struct
iw_point
*
rrq
);
static
int
orinoco_ioctl_setiwencode
(
struct
net_device
*
dev
,
struct
iw_point
*
erq
);
static
int
orinoco_ioctl_setiwencode
(
struct
net_device
*
dev
,
struct
iw_point
*
erq
);
static
int
orinoco_ioctl_getiwencode
(
struct
net_device
*
dev
,
struct
iw_point
*
erq
);
static
int
orinoco_ioctl_getiwencode
(
struct
net_device
*
dev
,
struct
iw_point
*
erq
);
...
@@ -495,160 +548,161 @@ static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq);
...
@@ -495,160 +548,161 @@ static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq);
static
int
orinoco_proc_init
(
void
);
static
int
orinoco_proc_init
(
void
);
static
void
orinoco_proc_cleanup
(
void
);
static
void
orinoco_proc_cleanup
(
void
);
/*
int
__orinoco_up
(
struct
net_device
*
dev
)
* Inline functions
*/
static
inline
void
orinoco_lock
(
struct
orinoco_private
*
priv
)
{
{
spin_lock_bh
(
&
priv
->
lock
);
struct
orinoco_private
*
priv
=
dev
->
priv
;
}
struct
hermes
*
hw
=
&
priv
->
hw
;
int
err
;
static
inline
void
err
=
__orinoco_program_rids
(
priv
);
orinoco_unlock
(
struct
orinoco_private
*
priv
)
if
(
err
)
{
{
printk
(
KERN_ERR
"%s: Error %d configuring card
\n
"
,
spin_unlock_bh
(
&
priv
->
lock
);
dev
->
name
,
err
);
}
return
err
;
}
static
inline
int
/* Fire things up again */
orinoco_irqs_allowed
(
struct
orinoco_private
*
priv
)
hermes_set_irqmask
(
hw
,
ORINOCO_INTEN
);
{
err
=
hermes_enable_port
(
hw
,
0
);
return
test_bit
(
ORINOCO_STATE_DOIRQ
,
&
priv
->
state
);
if
(
err
)
{
}
printk
(
KERN_ERR
"%s: Error %d enabling MAC port
\n
"
,
dev
->
name
,
err
);
return
err
;
}
static
inline
void
netif_start_queue
(
dev
);
__orinoco_stop_irqs
(
struct
orinoco_private
*
priv
)
{
hermes_t
*
hw
=
&
priv
->
hw
;
hermes_set_irqmask
(
hw
,
0
);
return
0
;
clear_bit
(
ORINOCO_STATE_DOIRQ
,
&
priv
->
state
);
while
(
test_bit
(
ORINOCO_STATE_INIRQ
,
&
priv
->
state
))
;
}
}
static
inline
void
int
__orinoco_down
(
struct
net_device
*
dev
)
__orinoco_start_irqs
(
struct
orinoco_private
*
priv
,
u16
irqmask
)
{
{
hermes_t
*
hw
=
&
priv
->
hw
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
hermes
*
hw
=
&
priv
->
hw
;
int
err
;
TRACE_ENTER
(
priv
->
ndev
->
name
);
netif_stop_queue
(
dev
);
local_irq_disable
();
/* FIXME: is this necessary? */
err
=
hermes_disable_port
(
hw
,
0
);
set_bit
(
ORINOCO_STATE_DOIRQ
,
&
priv
->
state
);
if
(
err
)
{
hermes_set_irqmask
(
hw
,
irqmask
);
printk
(
KERN_ERR
"%s: Error %d disabling MAC port
\n
"
,
local_irq_enable
();
dev
->
name
,
err
);
return
err
;
}
hermes_set_irqmask
(
hw
,
0
);
hermes_write_regn
(
hw
,
EVACK
,
0xffff
);
TRACE_EXIT
(
priv
->
ndev
->
name
)
;
return
0
;
}
}
static
inline
void
int
orinoco_reinit_firmware
(
struct
net_device
*
dev
)
set_port_type
(
struct
orinoco_private
*
priv
)
{
{
switch
(
priv
->
iw_mode
)
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
case
IW_MODE_INFRA
:
struct
hermes
*
hw
=
&
priv
->
hw
;
priv
->
port_type
=
1
;
int
err
;
priv
->
allow_ibss
=
0
;
break
;
err
=
hermes_init
(
hw
);
case
IW_MODE_ADHOC
:
if
(
err
)
if
(
priv
->
prefer_port3
)
{
return
err
;
priv
->
port_type
=
3
;
priv
->
allow_ibss
=
0
;
err
=
hermes_allocate
(
hw
,
priv
->
nicbuf_size
,
&
priv
->
txfid
);
}
else
{
if
(
err
==
-
EIO
)
{
priv
->
port_type
=
priv
->
ibss_port
;
/* Try workaround for old Symbol firmware bug */
priv
->
allow_ibss
=
1
;
printk
(
KERN_WARNING
"%s: firmware ALLOC bug detected "
}
"(old Symbol firmware?). Trying to work around... "
,
break
;
dev
->
name
);
default:
printk
(
KERN_ERR
"%s: Invalid priv->iw_mode in set_port_type()
\n
"
,
priv
->
nicbuf_size
=
TX_NICBUF_SIZE_BUG
;
priv
->
ndev
->
name
);
err
=
hermes_allocate
(
hw
,
priv
->
nicbuf_size
,
&
priv
->
txfid
);
if
(
err
)
printk
(
"failed!
\n
"
);
else
printk
(
"ok.
\n
"
);
}
}
}
static
inline
int
return
err
;
is_snap
(
struct
header_struct
*
hdr
)
{
return
(
hdr
->
dsap
==
0xAA
)
&&
(
hdr
->
ssap
==
0xAA
)
&&
(
hdr
->
ctrl
==
0x3
);
}
}
static
void
static
int
orinoco_open
(
struct
net_device
*
dev
)
orinoco_set_multicast_list
(
struct
net_device
*
dev
)
{
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
unsigned
long
flags
;
int
err
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
__orinoco_set_multicast_list
(
dev
);
if
(
err
)
orinoco_unlock
(
priv
);
return
err
;
}
/*
priv
->
open
=
1
;
* Hardware control routines
*/
void
err
=
__orinoco_up
(
dev
);
orinoco_shutdown
(
struct
orinoco_private
*
priv
)
orinoco_unlock
(
priv
,
&
flags
);
return
err
;
}
static
int
orinoco_stop
(
struct
net_device
*
dev
)
{
{
int
err
=
0
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
unsigned
long
flags
;
int
err
;
TRACE_ENTER
(
priv
->
ndev
->
name
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
orinoco_lock
(
priv
);
priv
->
open
=
0
;
__orinoco_stop_irqs
(
priv
);
err
=
hermes_reset
(
&
priv
->
hw
);
err
=
__orinoco_down
(
dev
);
if
(
err
&&
err
!=
-
ENODEV
)
/* If the card is gone, we don't care about shutting it down */
printk
(
KERN_ERR
"%s: Error %d shutting down Hermes chipset
\n
"
,
priv
->
ndev
->
name
,
err
);
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
TRACE_EXIT
(
priv
->
ndev
->
name
)
;
return
err
;
}
}
int
static
int
__orinoco_program_rids
(
struct
orinoco_private
*
priv
)
orinoco_reset
(
struct
orinoco_private
*
priv
)
{
{
struct
net_device
*
dev
=
priv
->
ndev
;
struct
net_device
*
dev
=
priv
->
ndev
;
hermes_t
*
hw
=
&
priv
->
hw
;
hermes_t
*
hw
=
&
priv
->
hw
;
int
err
=
0
;
int
err
;
struct
hermes_idstring
idbuf
;
struct
hermes_idstring
idbuf
;
TRACE_ENTER
(
priv
->
ndev
->
name
);
/* Set the MAC address */
err
=
hermes_write_ltv
(
hw
,
USER_BAP
,
HERMES_RID_CNFOWNMACADDR
,
/* Stop other people bothering us */
HERMES_BYTES_TO_RECLEN
(
ETH_ALEN
),
dev
->
dev_addr
);
orinoco_lock
(
priv
);
if
(
err
)
{
__orinoco_stop_irqs
(
priv
);
printk
(
KERN_ERR
"%s: Error %d setting MAC address
\n
"
,
dev
->
name
,
err
);
return
err
;
/* Check if we need a card reset */
if
(
priv
->
hard_reset
)
priv
->
hard_reset
(
priv
);
/* Do standard firmware reset if we can */
err
=
hermes_reset
(
hw
);
if
(
err
)
goto
out
;
err
=
hermes_allocate
(
hw
,
priv
->
nicbuf_size
,
&
priv
->
txfid
);
if
(
err
==
-
EIO
)
{
/* Try workaround for old Symbol firmware bug */
priv
->
nicbuf_size
=
TX_NICBUF_SIZE_BUG
;
err
=
hermes_allocate
(
hw
,
priv
->
nicbuf_size
,
&
priv
->
txfid
);
if
(
err
)
goto
out
;
}
}
/* Now set up all the parameters on the card */
/* Set up the link mode */
/* Set up the link mode */
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFPORTTYPE
,
priv
->
port_type
);
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFPORTTYPE
,
priv
->
port_type
);
if
(
err
)
if
(
err
)
{
goto
out
;
printk
(
KERN_ERR
"%s: Error %d setting port type
\n
"
,
dev
->
name
,
err
);
return
err
;
}
/* Set the channel/frequency */
if
(
priv
->
channel
==
0
)
{
printk
(
KERN_DEBUG
"%s: Channel is 0 in __orinoco_program_rids()
\n
"
,
dev
->
name
);
if
(
priv
->
createibss
)
priv
->
channel
=
10
;
}
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFOWNCHANNEL
,
priv
->
channel
);
if
(
err
)
{
printk
(
KERN_ERR
"%s: Error %d setting channel
\n
"
,
dev
->
name
,
err
);
return
err
;
}
if
(
priv
->
has_ibss
)
{
if
(
priv
->
has_ibss
)
{
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFCREATEIBSS
,
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFCREATEIBSS
,
priv
->
allow_ibss
);
priv
->
createibss
);
if
(
err
)
if
(
err
)
{
goto
out
;
printk
(
KERN_ERR
"%s: Error %d setting CREATEIBSS
\n
"
,
dev
->
name
,
err
);
if
((
strlen
(
priv
->
desired_essid
)
==
0
)
&&
(
priv
->
allow_ibss
)
return
err
;
}
if
((
strlen
(
priv
->
desired_essid
)
==
0
)
&&
(
priv
->
createibss
)
&&
(
!
priv
->
has_ibss_any
))
{
&&
(
!
priv
->
has_ibss_any
))
{
printk
(
KERN_WARNING
"%s: This firmware requires an \
printk
(
KERN_WARNING
"%s: This firmware requires an \
ESSID in IBSS-Ad-Hoc mode.
\n
"
,
dev
->
name
);
ESSID in IBSS-Ad-Hoc mode.
\n
"
,
dev
->
name
);
...
@@ -665,13 +719,17 @@ ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
...
@@ -665,13 +719,17 @@ ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
err
=
hermes_write_ltv
(
hw
,
USER_BAP
,
HERMES_RID_CNFOWNSSID
,
err
=
hermes_write_ltv
(
hw
,
USER_BAP
,
HERMES_RID_CNFOWNSSID
,
HERMES_BYTES_TO_RECLEN
(
strlen
(
priv
->
desired_essid
)
+
2
),
HERMES_BYTES_TO_RECLEN
(
strlen
(
priv
->
desired_essid
)
+
2
),
&
idbuf
);
&
idbuf
);
if
(
err
)
if
(
err
)
{
goto
out
;
printk
(
KERN_ERR
"%s: Error %d setting OWNSSID
\n
"
,
dev
->
name
,
err
);
return
err
;
}
err
=
hermes_write_ltv
(
hw
,
USER_BAP
,
HERMES_RID_CNFDESIREDSSID
,
err
=
hermes_write_ltv
(
hw
,
USER_BAP
,
HERMES_RID_CNFDESIREDSSID
,
HERMES_BYTES_TO_RECLEN
(
strlen
(
priv
->
desired_essid
)
+
2
),
HERMES_BYTES_TO_RECLEN
(
strlen
(
priv
->
desired_essid
)
+
2
),
&
idbuf
);
&
idbuf
);
if
(
err
)
if
(
err
)
{
goto
out
;
printk
(
KERN_ERR
"%s: Error %d setting DESIREDSSID
\n
"
,
dev
->
name
,
err
);
return
err
;
}
/* Set the station name */
/* Set the station name */
idbuf
.
len
=
cpu_to_le16
(
strlen
(
priv
->
nick
));
idbuf
.
len
=
cpu_to_le16
(
strlen
(
priv
->
nick
));
...
@@ -679,26 +737,29 @@ ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
...
@@ -679,26 +737,29 @@ ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
err
=
hermes_write_ltv
(
hw
,
USER_BAP
,
HERMES_RID_CNFOWNNAME
,
err
=
hermes_write_ltv
(
hw
,
USER_BAP
,
HERMES_RID_CNFOWNNAME
,
HERMES_BYTES_TO_RECLEN
(
strlen
(
priv
->
nick
)
+
2
),
HERMES_BYTES_TO_RECLEN
(
strlen
(
priv
->
nick
)
+
2
),
&
idbuf
);
&
idbuf
);
if
(
err
)
if
(
err
)
{
goto
out
;
printk
(
KERN_ERR
"%s: Error %d setting nickname
\n
"
,
dev
->
name
,
err
);
return
err
;
/* Set the channel/frequency */
}
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFOWNCHANNEL
,
priv
->
channel
);
if
(
err
)
goto
out
;
/* Set AP density */
/* Set AP density */
if
(
priv
->
has_sensitivity
)
{
if
(
priv
->
has_sensitivity
)
{
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFSYSTEMSCALE
,
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFSYSTEMSCALE
,
priv
->
ap_density
);
priv
->
ap_density
);
if
(
err
)
if
(
err
)
{
printk
(
KERN_WARNING
"%s: Error %d setting SYSTEMSCALE. "
"Disabling sensitivity control
\n
"
,
dev
->
name
,
err
);
priv
->
has_sensitivity
=
0
;
priv
->
has_sensitivity
=
0
;
}
}
}
/* Set RTS threshold */
/* Set RTS threshold */
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFRTSTHRESHOLD
,
priv
->
rts_thresh
);
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFRTSTHRESHOLD
,
priv
->
rts_thresh
);
if
(
err
)
if
(
err
)
{
goto
out
;
printk
(
KERN_ERR
"%s: Error %d setting RTS threshold
\n
"
,
dev
->
name
,
err
);
return
err
;
}
/* Set fragmentation threshold or MWO robustness */
/* Set fragmentation threshold or MWO robustness */
if
(
priv
->
has_mwo
)
if
(
priv
->
has_mwo
)
...
@@ -709,35 +770,52 @@ ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
...
@@ -709,35 +770,52 @@ ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFFRAGMENTATIONTHRESHOLD
,
HERMES_RID_CNFFRAGMENTATIONTHRESHOLD
,
priv
->
frag_thresh
);
priv
->
frag_thresh
);
if
(
err
)
if
(
err
)
{
goto
out
;
printk
(
KERN_ERR
"%s: Error %d setting framentation
\n
"
,
dev
->
name
,
err
);
return
err
;
}
/* Set bitrate */
/* Set bitrate */
err
=
__orinoco_hw_set_bitrate
(
priv
);
err
=
__orinoco_hw_set_bitrate
(
priv
);
if
(
err
)
if
(
err
)
{
goto
out
;
printk
(
KERN_ERR
"%s: Error %d setting bitrate
\n
"
,
dev
->
name
,
err
);
return
err
;
}
/* Set power management */
/* Set power management */
if
(
priv
->
has_pm
)
{
if
(
priv
->
has_pm
)
{
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFPMENABLED
,
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFPMENABLED
,
priv
->
pm_on
);
priv
->
pm_on
);
if
(
err
)
if
(
err
)
{
goto
out
;
printk
(
KERN_ERR
"%s: Error %d setting up PM
\n
"
,
dev
->
name
,
err
);
return
err
;
}
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFMULTICASTRECEIVE
,
HERMES_RID_CNFMULTICASTRECEIVE
,
priv
->
pm_mcast
);
priv
->
pm_mcast
);
if
(
err
)
if
(
err
)
{
goto
out
;
printk
(
KERN_ERR
"%s: Error %d setting up PM
\n
"
,
dev
->
name
,
err
);
return
err
;
}
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFMAXSLEEPDURATION
,
HERMES_RID_CNFMAXSLEEPDURATION
,
priv
->
pm_period
);
priv
->
pm_period
);
if
(
err
)
if
(
err
)
{
goto
out
;
printk
(
KERN_ERR
"%s: Error %d setting up PM
\n
"
,
dev
->
name
,
err
);
return
err
;
}
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
err
=
hermes_write_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFPMHOLDOVERDURATION
,
HERMES_RID_CNFPMHOLDOVERDURATION
,
priv
->
pm_timeout
);
priv
->
pm_timeout
);
if
(
err
)
if
(
err
)
{
goto
out
;
printk
(
KERN_ERR
"%s: Error %d setting up PM
\n
"
,
dev
->
name
,
err
);
return
err
;
}
}
}
/* Set preamble - only for Symbol so far... */
/* Set preamble - only for Symbol so far... */
...
@@ -746,50 +824,171 @@ ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
...
@@ -746,50 +824,171 @@ ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
HERMES_RID_CNFPREAMBLE_SYMBOL
,
HERMES_RID_CNFPREAMBLE_SYMBOL
,
priv
->
preamble
);
priv
->
preamble
);
if
(
err
)
{
if
(
err
)
{
printk
(
KERN_WARNING
"%s: Can't set preamble!
\n
"
,
dev
->
name
);
printk
(
KERN_ERR
"%s: Error %d setting preamble
\n
"
,
goto
out
;
dev
->
name
,
err
);
return
err
;
}
}
}
}
/* Set up encryption */
/* Set up encryption */
if
(
priv
->
has_wep
)
{
if
(
priv
->
has_wep
)
{
err
=
__orinoco_hw_setup_wep
(
priv
);
err
=
__orinoco_hw_setup_wep
(
priv
);
if
(
err
)
{
if
(
err
)
{
printk
(
KERN_ERR
"%s: Error %d activating WEP.
\n
"
,
printk
(
KERN_ERR
"%s: Error %d activating WEP
\n
"
,
dev
->
name
,
err
);
dev
->
name
,
err
);
goto
out
;
return
err
;
}
}
/* Set promiscuity / multicast*/
priv
->
promiscuous
=
0
;
priv
->
mc_count
=
0
;
__orinoco_set_multicast_list
(
dev
);
/* FIXME: what about the xmit_lock */
return
0
;
}
/* xyzzy */
static
int
orinoco_reconfigure
(
struct
orinoco_private
*
priv
)
{
struct
hermes
*
hw
=
&
priv
->
hw
;
unsigned
long
flags
;
int
err
=
0
;
orinoco_lock
(
priv
,
&
flags
);
err
=
hermes_disable_port
(
hw
,
0
);
if
(
err
)
{
printk
(
KERN_ERR
"%s: Unable to disable port in orinco_reconfigure()
\n
"
,
priv
->
ndev
->
name
);
goto
out
;
}
err
=
__orinoco_program_rids
(
priv
);
if
(
err
)
goto
out
;
err
=
hermes_enable_port
(
hw
,
0
);
if
(
err
)
{
printk
(
KERN_ERR
"%s: Unable to enable port in orinco_reconfigure()
\n
"
,
priv
->
ndev
->
name
);
goto
out
;
}
out:
orinoco_unlock
(
priv
,
&
flags
);
return
err
;
}
/* This must be called from user context, without locks held - use
* schedule_task() */
static
void
orinoco_reset
(
struct
net_device
*
dev
)
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
int
err
;
unsigned
long
flags
;
printk
(
KERN_INFO
"%s: orinoco_reset()
\n
"
,
dev
->
name
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
;
priv
->
hw_unavailable
=
1
;
orinoco_unlock
(
priv
,
&
flags
);
if
(
priv
->
hard_reset
)
err
=
(
*
priv
->
hard_reset
)(
priv
);
if
(
err
)
{
printk
(
KERN_ERR
"%s: orinoco_reset: Error %d performing hard reset
\n
"
,
dev
->
name
,
err
);
/* FIXME: shutdown of some sort */
return
;
}
err
=
orinoco_reinit_firmware
(
dev
);
if
(
err
)
{
printk
(
KERN_ERR
"%s: orinoco_reset: Error %d re-initializing firmware
\n
"
,
dev
->
name
,
err
);
return
;
}
spin_lock_irqsave
(
&
priv
->
lock
,
flags
);
priv
->
hw_unavailable
=
0
;
err
=
__orinoco_up
(
dev
);
if
(
err
)
{
printk
(
KERN_ERR
"%s: orinoco_reset: Error %d reenabling card
\n
"
,
dev
->
name
,
err
);
}
else
dev
->
trans_start
=
jiffies
;
orinoco_unlock
(
priv
,
&
flags
);
return
;
}
/********************************************************************/
/* Internal helper functions */
/********************************************************************/
static
inline
void
set_port_type
(
struct
orinoco_private
*
priv
)
{
switch
(
priv
->
iw_mode
)
{
case
IW_MODE_INFRA
:
priv
->
port_type
=
1
;
priv
->
createibss
=
0
;
break
;
case
IW_MODE_ADHOC
:
if
(
priv
->
prefer_port3
)
{
priv
->
port_type
=
3
;
priv
->
createibss
=
0
;
}
else
{
priv
->
port_type
=
priv
->
ibss_port
;
priv
->
createibss
=
1
;
}
}
break
;
default:
printk
(
KERN_ERR
"%s: Invalid priv->iw_mode in set_port_type()
\n
"
,
priv
->
ndev
->
name
);
}
}
}
/* Set promiscuity / multicast*/
static
inline
int
priv
->
promiscuous
=
0
;
is_snap
(
struct
header_struct
*
hdr
)
priv
->
mc_count
=
0
;
{
__orinoco_set_multicast_list
(
dev
);
return
(
hdr
->
dsap
==
0xAA
)
&&
(
hdr
->
ssap
==
0xAA
)
&&
(
hdr
->
ctrl
==
0x3
);
}
__orinoco_start_irqs
(
priv
,
HERMES_EV_RX
|
HERMES_EV_ALLOC
|
HERMES_EV_TX
|
HERMES_EV_TXEXC
|
HERMES_EV_WTERR
|
HERMES_EV_INFO
|
HERMES_EV_INFDROP
);
err
=
hermes_enable_port
(
hw
,
0
);
if
(
err
)
goto
out
;
out:
static
void
orinoco_unlock
(
priv
);
orinoco_set_multicast_list
(
struct
net_device
*
dev
)
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
unsigned
long
flags
;
TRACE_EXIT
(
priv
->
ndev
->
name
);
if
(
orinoco_lock
(
priv
,
&
flags
)
!=
0
)
{
printk
(
KERN_DEBUG
"%s: orinoco_set_multicast_list() "
"called when hw_unavailable
\n
"
,
dev
->
name
);
return
;
}
return
err
;
__orinoco_set_multicast_list
(
dev
);
orinoco_unlock
(
priv
,
&
flags
);
}
}
/********************************************************************/
/* Hardware control functions */
/********************************************************************/
static
int
__orinoco_hw_set_bitrate
(
struct
orinoco_private
*
priv
)
static
int
__orinoco_hw_set_bitrate
(
struct
orinoco_private
*
priv
)
{
{
hermes_t
*
hw
=
&
priv
->
hw
;
hermes_t
*
hw
=
&
priv
->
hw
;
int
err
=
0
;
int
err
=
0
;
TRACE_ENTER
(
priv
->
ndev
->
name
);
if
(
priv
->
bitratemode
>=
BITRATE_TABLE_SIZE
)
{
if
(
priv
->
bitratemode
>=
BITRATE_TABLE_SIZE
)
{
printk
(
KERN_ERR
"%s: BUG: Invalid bitrate mode %d
\n
"
,
printk
(
KERN_ERR
"%s: BUG: Invalid bitrate mode %d
\n
"
,
priv
->
ndev
->
name
,
priv
->
bitratemode
);
priv
->
ndev
->
name
,
priv
->
bitratemode
);
...
@@ -812,8 +1011,6 @@ static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
...
@@ -812,8 +1011,6 @@ static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
BUG
();
BUG
();
}
}
TRACE_EXIT
(
priv
->
ndev
->
name
);
return
err
;
return
err
;
}
}
...
@@ -825,8 +1022,6 @@ static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
...
@@ -825,8 +1022,6 @@ static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
int
master_wep_flag
;
int
master_wep_flag
;
int
auth_flag
;
int
auth_flag
;
TRACE_ENTER
(
priv
->
ndev
->
name
);
switch
(
priv
->
firmware_type
)
{
switch
(
priv
->
firmware_type
)
{
case
FIRMWARE_TYPE_AGERE
:
/* Agere style WEP */
case
FIRMWARE_TYPE_AGERE
:
/* Agere style WEP */
if
(
priv
->
wep_on
)
{
if
(
priv
->
wep_on
)
{
...
@@ -920,8 +1115,6 @@ static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
...
@@ -920,8 +1115,6 @@ static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
}
}
}
}
TRACE_EXIT
(
priv
->
ndev
->
name
);
return
0
;
return
0
;
}
}
...
@@ -929,13 +1122,16 @@ static int orinoco_hw_get_bssid(struct orinoco_private *priv, char buf[ETH_ALEN]
...
@@ -929,13 +1122,16 @@ static int orinoco_hw_get_bssid(struct orinoco_private *priv, char buf[ETH_ALEN]
{
{
hermes_t
*
hw
=
&
priv
->
hw
;
hermes_t
*
hw
=
&
priv
->
hw
;
int
err
=
0
;
int
err
=
0
;
unsigned
long
flags
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
err
=
hermes_read_ltv
(
hw
,
USER_BAP
,
HERMES_RID_CURRENTBSSID
,
err
=
hermes_read_ltv
(
hw
,
USER_BAP
,
HERMES_RID_CURRENTBSSID
,
ETH_ALEN
,
NULL
,
buf
);
ETH_ALEN
,
NULL
,
buf
);
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
err
;
return
err
;
}
}
...
@@ -948,10 +1144,11 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
...
@@ -948,10 +1144,11 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
struct
hermes_idstring
essidbuf
;
struct
hermes_idstring
essidbuf
;
char
*
p
=
(
char
*
)(
&
essidbuf
.
val
);
char
*
p
=
(
char
*
)(
&
essidbuf
.
val
);
int
len
;
int
len
;
unsigned
long
flags
;
TRACE_ENTER
(
priv
->
ndev
->
name
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
orinoco_lock
(
priv
)
;
return
err
;
if
(
strlen
(
priv
->
desired_essid
)
>
0
)
{
if
(
strlen
(
priv
->
desired_essid
)
>
0
)
{
/* We read the desired SSID from the hardware rather
/* We read the desired SSID from the hardware rather
...
@@ -988,9 +1185,7 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
...
@@ -988,9 +1185,7 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
buf
[
len
]
=
'\0'
;
buf
[
len
]
=
'\0'
;
fail_unlock:
fail_unlock:
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
TRACE_EXIT
(
priv
->
ndev
->
name
);
return
err
;
return
err
;
}
}
...
@@ -1002,13 +1197,22 @@ static long orinoco_hw_get_freq(struct orinoco_private *priv)
...
@@ -1002,13 +1197,22 @@ static long orinoco_hw_get_freq(struct orinoco_private *priv)
int
err
=
0
;
int
err
=
0
;
u16
channel
;
u16
channel
;
long
freq
=
0
;
long
freq
=
0
;
unsigned
long
flags
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
err
=
hermes_read_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CURRENTCHANNEL
,
&
channel
);
err
=
hermes_read_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CURRENTCHANNEL
,
&
channel
);
if
(
err
)
if
(
err
)
goto
out
;
goto
out
;
/* Intersil firmware 1.3.5 returns 0 when the interface is down */
if
(
channel
==
0
)
{
err
=
-
EBUSY
;
goto
out
;
}
if
(
(
channel
<
1
)
||
(
channel
>
NUM_CHANNELS
)
)
{
if
(
(
channel
<
1
)
||
(
channel
>
NUM_CHANNELS
)
)
{
struct
net_device
*
dev
=
priv
->
ndev
;
struct
net_device
*
dev
=
priv
->
ndev
;
...
@@ -1020,7 +1224,7 @@ static long orinoco_hw_get_freq(struct orinoco_private *priv)
...
@@ -1020,7 +1224,7 @@ static long orinoco_hw_get_freq(struct orinoco_private *priv)
freq
=
channel_frequency
[
channel
-
1
]
*
100000
;
freq
=
channel_frequency
[
channel
-
1
]
*
100000
;
out:
out:
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
if
(
err
>
0
)
if
(
err
>
0
)
err
=
-
EBUSY
;
err
=
-
EBUSY
;
...
@@ -1036,11 +1240,15 @@ static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrate
...
@@ -1036,11 +1240,15 @@ static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrate
int
err
=
0
;
int
err
=
0
;
int
num
;
int
num
;
int
i
;
int
i
;
unsigned
long
flags
;
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
orinoco_lock
(
priv
);
err
=
hermes_read_ltv
(
hw
,
USER_BAP
,
HERMES_RID_SUPPORTEDDATARATES
,
err
=
hermes_read_ltv
(
hw
,
USER_BAP
,
HERMES_RID_SUPPORTEDDATARATES
,
sizeof
(
list
),
NULL
,
&
list
);
sizeof
(
list
),
NULL
,
&
list
);
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
if
(
err
)
if
(
err
)
return
err
;
return
err
;
...
@@ -1122,7 +1330,7 @@ static void show_rx_frame(struct orinoco_rxframe_hdr *frame)
...
@@ -1122,7 +1330,7 @@ static void show_rx_frame(struct orinoco_rxframe_hdr *frame)
/*
/*
* Interrupt handler
* Interrupt handler
*/
*/
void
orinoco_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
void
orinoco_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
{
struct
orinoco_private
*
priv
=
(
struct
orinoco_private
*
)
dev_id
;
struct
orinoco_private
*
priv
=
(
struct
orinoco_private
*
)
dev_id
;
hermes_t
*
hw
=
&
priv
->
hw
;
hermes_t
*
hw
=
&
priv
->
hw
;
...
@@ -1134,38 +1342,26 @@ void orinoco_interrupt(int irq, void * dev_id, struct pt_regs *regs)
...
@@ -1134,38 +1342,26 @@ void orinoco_interrupt(int irq, void * dev_id, struct pt_regs *regs)
* we panic and shut down the hardware */
* we panic and shut down the hardware */
static
int
last_irq_jiffy
=
0
;
/* jiffies value the last time we were called */
static
int
last_irq_jiffy
=
0
;
/* jiffies value the last time we were called */
static
int
loops_this_jiffy
=
0
;
static
int
loops_this_jiffy
=
0
;
unsigned
long
flags
;
if
(
test_and_set_bit
(
ORINOCO_STATE_INIRQ
,
&
priv
->
state
))
if
(
orinoco_lock
(
priv
,
&
flags
)
!=
0
)
{
BUG
();
/* If hw is unavailable */
if
(
!
orinoco_irqs_allowed
(
priv
))
{
clear_bit
(
ORINOCO_STATE_INIRQ
,
&
priv
->
state
);
return
;
return
;
}
}
DEBUG
(
3
,
"%s: orinoco_interrupt()
\n
"
,
priv
->
ndev
->
name
);
evstat
=
hermes_read_regn
(
hw
,
EVSTAT
);
evstat
=
hermes_read_regn
(
hw
,
EVSTAT
);
events
=
evstat
&
hw
->
inten
;
events
=
evstat
&
hw
->
inten
;
/* if (! events) { */
/* printk(KERN_WARNING "%s: Null event\n", dev->name); */
/* } */
if
(
jiffies
!=
last_irq_jiffy
)
if
(
jiffies
!=
last_irq_jiffy
)
loops_this_jiffy
=
0
;
loops_this_jiffy
=
0
;
last_irq_jiffy
=
jiffies
;
last_irq_jiffy
=
jiffies
;
while
(
events
&&
count
--
)
{
while
(
events
&&
count
--
)
{
DEBUG
(
3
,
"__orinoco_interrupt(): count=%d EVSTAT=0x%04x
\n
"
,
count
,
evstat
);
if
(
++
loops_this_jiffy
>
MAX_IRQLOOPS_PER_JIFFY
)
{
if
(
++
loops_this_jiffy
>
MAX_IRQLOOPS_PER_JIFFY
)
{
printk
(
KERN_CRIT
"%s: IRQ handler is looping too \
printk
(
KERN_CRIT
"%s: IRQ handler is looping too \
much! Shutting down.
\n
"
,
much! Shutting down.
\n
"
,
dev
->
name
);
dev
->
name
);
/* Perform an emergency shutdown */
/* Perform an emergency shutdown */
clear_bit
(
ORINOCO_STATE_DOIRQ
,
&
priv
->
state
);
hermes_set_irqmask
(
hw
,
0
);
hermes_set_irqmask
(
hw
,
0
);
break
;
break
;
}
}
...
@@ -1199,7 +1395,7 @@ much! Shutting down.\n",
...
@@ -1199,7 +1395,7 @@ much! Shutting down.\n",
events
=
evstat
&
hw
->
inten
;
events
=
evstat
&
hw
->
inten
;
};
};
clear_bit
(
ORINOCO_STATE_INIRQ
,
&
priv
->
state
);
orinoco_unlock
(
priv
,
&
flags
);
}
}
static
void
__orinoco_ev_tick
(
struct
orinoco_private
*
priv
,
hermes_t
*
hw
)
static
void
__orinoco_ev_tick
(
struct
orinoco_private
*
priv
,
hermes_t
*
hw
)
...
@@ -1211,8 +1407,8 @@ static void __orinoco_ev_wterr(struct orinoco_private *priv, hermes_t *hw)
...
@@ -1211,8 +1407,8 @@ static void __orinoco_ev_wterr(struct orinoco_private *priv, hermes_t *hw)
{
{
/* This seems to happen a fair bit under load, but ignoring it
/* This seems to happen a fair bit under load, but ignoring it
seems to work fine...*/
seems to work fine...*/
DEBUG
(
1
,
"%s: MAC controller error (WTERR). Ignoring.
\n
"
,
printk
(
KERN_DEBUG
"%s: MAC controller error (WTERR). Ignoring.
\n
"
,
priv
->
ndev
->
name
);
priv
->
ndev
->
name
);
}
}
static
void
__orinoco_ev_infdrop
(
struct
orinoco_private
*
priv
,
hermes_t
*
hw
)
static
void
__orinoco_ev_infdrop
(
struct
orinoco_private
*
priv
,
hermes_t
*
hw
)
...
@@ -1235,8 +1431,6 @@ static void __orinoco_ev_info(struct orinoco_private *priv, hermes_t *hw)
...
@@ -1235,8 +1431,6 @@ static void __orinoco_ev_info(struct orinoco_private *priv, hermes_t *hw)
* The controller return to us a pseudo frame containing
* The controller return to us a pseudo frame containing
* the information in question - Jean II */
* the information in question - Jean II */
infofid
=
hermes_read_regn
(
hw
,
INFOFID
);
infofid
=
hermes_read_regn
(
hw
,
INFOFID
);
DEBUG
(
3
,
"%s: __orinoco_ev_info(): INFOFID=0x%04x
\n
"
,
dev
->
name
,
infofid
);
/* Read the info frame header - don't try too hard */
/* Read the info frame header - don't try too hard */
err
=
hermes_bap_pread
(
hw
,
IRQ_BAP
,
&
info
,
sizeof
(
info
),
err
=
hermes_bap_pread
(
hw
,
IRQ_BAP
,
&
info
,
sizeof
(
info
),
...
@@ -1277,11 +1471,6 @@ static void __orinoco_ev_info(struct orinoco_private *priv, hermes_t *hw)
...
@@ -1277,11 +1471,6 @@ static void __orinoco_ev_info(struct orinoco_private *priv, hermes_t *hw)
wstats
->
discard
.
retries
+=
wstats
->
discard
.
retries
+=
le16_to_cpu
(
tallies
.
TxRetryLimitExceeded
);
le16_to_cpu
(
tallies
.
TxRetryLimitExceeded
);
/* wstats->miss.beacon - no match */
/* wstats->miss.beacon - no match */
#if ORINOCO_DEBUG > 3
/* Hack for debugging - should not be taken as an example */
wstats
->
discard
.
nwid
+=
le16_to_cpu
(
tallies
.
TxUnicastFrames
);
wstats
->
miss
.
beacon
+=
le16_to_cpu
(
tallies
.
RxUnicastFrames
);
#endif
#endif
/* WIRELESS_EXT > 11 */
#endif
/* WIRELESS_EXT > 11 */
}
}
break
;
break
;
...
@@ -1308,7 +1497,6 @@ static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw)
...
@@ -1308,7 +1497,6 @@ static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw)
int
err
;
int
err
;
rxfid
=
hermes_read_regn
(
hw
,
RXFID
);
rxfid
=
hermes_read_regn
(
hw
,
RXFID
);
DEBUG
(
3
,
"__orinoco_ev_rx(): RXFID=0x%04x
\n
"
,
rxfid
);
err
=
hermes_bap_pread
(
hw
,
IRQ_BAP
,
&
desc
,
sizeof
(
desc
),
err
=
hermes_bap_pread
(
hw
,
IRQ_BAP
,
&
desc
,
sizeof
(
desc
),
rxfid
,
0
);
rxfid
,
0
);
...
@@ -1349,11 +1537,11 @@ static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw)
...
@@ -1349,11 +1537,11 @@ static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw)
length
=
ntohs
(
hdr
.
len
);
length
=
ntohs
(
hdr
.
len
);
/* Sanity checks */
/* Sanity checks */
if
(
length
<
sizeof
(
struct
header_struct
))
{
if
(
length
<
3
)
{
/* No for even an 802.2 LLC header */
printk
(
KERN_WARNING
"%s: Undersized frame received (%d bytes)
\n
"
,
/* At least on Symbol firmware with PCF we get quite a
dev
->
name
,
length
);
lot of these legitimately - Poll frames with no
stats
->
rx_length_errors
++
;
data. */
stats
->
rx_
errors
++
;
stats
->
rx_
dropped
++
;
goto
drop
;
goto
drop
;
}
}
if
(
length
>
IEEE802_11_DATA_LEN
)
{
if
(
length
>
IEEE802_11_DATA_LEN
)
{
...
@@ -1373,7 +1561,6 @@ static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw)
...
@@ -1373,7 +1561,6 @@ static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw)
if
(
!
skb
)
{
if
(
!
skb
)
{
printk
(
KERN_WARNING
"%s: Can't allocate skb for Rx
\n
"
,
printk
(
KERN_WARNING
"%s: Can't allocate skb for Rx
\n
"
,
dev
->
name
);
dev
->
name
);
stats
->
rx_dropped
++
;
goto
drop
;
goto
drop
;
}
}
...
@@ -1383,8 +1570,7 @@ static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw)
...
@@ -1383,8 +1570,7 @@ static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw)
* In most cases, the firmware tell us about SNAP frames.
* In most cases, the firmware tell us about SNAP frames.
* For some reason, the SNAP frames sent by LinkSys APs
* For some reason, the SNAP frames sent by LinkSys APs
* are not properly recognised by most firmwares.
* are not properly recognised by most firmwares.
* So, check ourselves (note : only 3 bytes out of 6).
* So, check ourselves */
*/
if
(((
status
&
HERMES_RXSTAT_MSGTYPE
)
==
HERMES_RXSTAT_1042
)
||
if
(((
status
&
HERMES_RXSTAT_MSGTYPE
)
==
HERMES_RXSTAT_1042
)
||
((
status
&
HERMES_RXSTAT_MSGTYPE
)
==
HERMES_RXSTAT_TUNNEL
)
||
((
status
&
HERMES_RXSTAT_MSGTYPE
)
==
HERMES_RXSTAT_TUNNEL
)
||
is_snap
(
&
hdr
))
{
is_snap
(
&
hdr
))
{
...
@@ -1392,6 +1578,12 @@ static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw)
...
@@ -1392,6 +1578,12 @@ static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw)
802.11 frame which we'll need to de-encapsulate to
802.11 frame which we'll need to de-encapsulate to
the original EthernetII frame. */
the original EthernetII frame. */
if
(
length
<
ENCAPS_OVERHEAD
)
{
/* No room for full LLC+SNAP */
stats
->
rx_length_errors
++
;
stats
->
rx_dropped
++
;
goto
drop
;
}
/* Remove SNAP header, reconstruct EthernetII frame */
/* Remove SNAP header, reconstruct EthernetII frame */
data_len
=
length
-
ENCAPS_OVERHEAD
;
data_len
=
length
-
ENCAPS_OVERHEAD
;
data_off
=
HERMES_802_3_OFFSET
+
sizeof
(
hdr
);
data_off
=
HERMES_802_3_OFFSET
+
sizeof
(
hdr
);
...
@@ -1414,7 +1606,7 @@ static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw)
...
@@ -1414,7 +1606,7 @@ static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw)
err
=
hermes_bap_pread
(
hw
,
IRQ_BAP
,
p
,
RUP_EVEN
(
data_len
),
err
=
hermes_bap_pread
(
hw
,
IRQ_BAP
,
p
,
RUP_EVEN
(
data_len
),
rxfid
,
data_off
);
rxfid
,
data_off
);
if
(
err
)
{
if
(
err
)
{
printk
(
KERN_ERR
"%s: error %d reading frame
header
. "
printk
(
KERN_ERR
"%s: error %d reading frame. "
"Frame dropped.
\n
"
,
dev
->
name
,
err
);
"Frame dropped.
\n
"
,
dev
->
name
,
err
);
stats
->
rx_errors
++
;
stats
->
rx_errors
++
;
goto
drop
;
goto
drop
;
...
@@ -1436,6 +1628,8 @@ static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw)
...
@@ -1436,6 +1628,8 @@ static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw)
return
;
return
;
drop:
drop:
stats
->
rx_dropped
++
;
if
(
skb
)
if
(
skb
)
dev_kfree_skb_irq
(
skb
);
dev_kfree_skb_irq
(
skb
);
return
;
return
;
...
@@ -1469,11 +1663,7 @@ static void __orinoco_ev_txexc(struct orinoco_private *priv, hermes_t *hw)
...
@@ -1469,11 +1663,7 @@ static void __orinoco_ev_txexc(struct orinoco_private *priv, hermes_t *hw)
static
void
__orinoco_ev_tx
(
struct
orinoco_private
*
priv
,
hermes_t
*
hw
)
static
void
__orinoco_ev_tx
(
struct
orinoco_private
*
priv
,
hermes_t
*
hw
)
{
{
/* struct net_device *dev = priv->ndev; */
struct
net_device_stats
*
stats
=
&
priv
->
stats
;
struct
net_device_stats
*
stats
=
&
priv
->
stats
;
/* u16 fid = hermes_read_regn(hw, TXCOMPLFID); */
/* DEBUG(2, "%s: Transmit completed (FID=%04X)\n", priv->ndev->name, fid); */
stats
->
tx_packets
++
;
stats
->
tx_packets
++
;
...
@@ -1485,8 +1675,6 @@ static void __orinoco_ev_alloc(struct orinoco_private *priv, hermes_t *hw)
...
@@ -1485,8 +1675,6 @@ static void __orinoco_ev_alloc(struct orinoco_private *priv, hermes_t *hw)
struct
net_device
*
dev
=
priv
->
ndev
;
struct
net_device
*
dev
=
priv
->
ndev
;
u16
fid
=
hermes_read_regn
(
hw
,
ALLOCFID
);
u16
fid
=
hermes_read_regn
(
hw
,
ALLOCFID
);
DEBUG
(
3
,
"%s: Allocation complete FID=0x%04x
\n
"
,
priv
->
ndev
->
name
,
fid
);
if
(
fid
!=
priv
->
txfid
)
{
if
(
fid
!=
priv
->
txfid
)
{
if
(
fid
!=
DUMMY_FID
)
if
(
fid
!=
DUMMY_FID
)
printk
(
KERN_WARNING
"%s: Allocate event on unexpected fid (%04X)
\n
"
,
printk
(
KERN_WARNING
"%s: Allocate event on unexpected fid (%04X)
\n
"
,
...
@@ -1500,16 +1688,17 @@ static void __orinoco_ev_alloc(struct orinoco_private *priv, hermes_t *hw)
...
@@ -1500,16 +1688,17 @@ static void __orinoco_ev_alloc(struct orinoco_private *priv, hermes_t *hw)
}
}
struct
sta_id
{
struct
sta_id
{
u16
id
,
v
endor
,
major
,
minor
;
u16
id
,
v
ariant
,
major
,
minor
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
static
int
determine_firmware_type
(
struct
net_device
*
dev
,
struct
sta_id
*
sta_id
)
static
int
determine_firmware_type
(
struct
net_device
*
dev
,
struct
sta_id
*
sta_id
)
{
{
u32
firmver
=
((
u32
)
sta_id
->
major
<<
16
)
|
sta_id
->
minor
;
/* FIXME: this is fundamentally broken */
unsigned
int
firmver
=
((
u32
)
sta_id
->
major
<<
16
)
|
sta_id
->
minor
;
if
(
sta_id
->
v
endor
==
1
)
if
(
sta_id
->
v
ariant
==
1
)
return
FIRMWARE_TYPE_AGERE
;
return
FIRMWARE_TYPE_AGERE
;
else
if
((
sta_id
->
v
endor
==
2
)
&&
else
if
((
sta_id
->
v
ariant
==
2
)
&&
((
firmver
==
0x10001
)
||
(
firmver
==
0x20001
)))
((
firmver
==
0x10001
)
||
(
firmver
==
0x20001
)))
return
FIRMWARE_TYPE_SYMBOL
;
return
FIRMWARE_TYPE_SYMBOL
;
else
else
...
@@ -1522,7 +1711,7 @@ static void determine_firmware(struct net_device *dev)
...
@@ -1522,7 +1711,7 @@ static void determine_firmware(struct net_device *dev)
hermes_t
*
hw
=
&
priv
->
hw
;
hermes_t
*
hw
=
&
priv
->
hw
;
int
err
;
int
err
;
struct
sta_id
sta_id
;
struct
sta_id
sta_id
;
u
32
firmver
;
u
nsigned
int
firmver
;
char
tmp
[
SYMBOL_MAX_VER_LEN
+
1
];
char
tmp
[
SYMBOL_MAX_VER_LEN
+
1
];
/* Get the firmware version */
/* Get the firmware version */
...
@@ -1533,14 +1722,12 @@ static void determine_firmware(struct net_device *dev)
...
@@ -1533,14 +1722,12 @@ static void determine_firmware(struct net_device *dev)
memset
(
&
sta_id
,
0
,
sizeof
(
sta_id
));
memset
(
&
sta_id
,
0
,
sizeof
(
sta_id
));
}
}
le16_to_cpus
(
&
sta_id
.
id
);
le16_to_cpus
(
&
sta_id
.
id
);
le16_to_cpus
(
&
sta_id
.
v
endor
);
le16_to_cpus
(
&
sta_id
.
v
ariant
);
le16_to_cpus
(
&
sta_id
.
major
);
le16_to_cpus
(
&
sta_id
.
major
);
le16_to_cpus
(
&
sta_id
.
minor
);
le16_to_cpus
(
&
sta_id
.
minor
);
firmver
=
((
u32
)
sta_id
.
major
<<
16
)
|
sta_id
.
minor
;
printk
(
KERN_DEBUG
"%s: Station identity %04x:%04x:%04x:%04x
\n
"
,
printk
(
KERN_DEBUG
"%s: Station identity %04x:%04x:%04x:%04x
\n
"
,
dev
->
name
,
sta_id
.
id
,
sta_id
.
v
endor
,
dev
->
name
,
sta_id
.
id
,
sta_id
.
v
ariant
,
sta_id
.
major
,
sta_id
.
minor
);
sta_id
.
major
,
sta_id
.
minor
);
if
(
!
priv
->
firmware_type
)
if
(
!
priv
->
firmware_type
)
...
@@ -1555,7 +1742,6 @@ static void determine_firmware(struct net_device *dev)
...
@@ -1555,7 +1742,6 @@ static void determine_firmware(struct net_device *dev)
priv
->
has_ibss_any
=
0
;
priv
->
has_ibss_any
=
0
;
priv
->
has_wep
=
0
;
priv
->
has_wep
=
0
;
priv
->
has_big_wep
=
0
;
priv
->
has_big_wep
=
0
;
priv
->
broken_cor_reset
=
0
;
/* Determine capabilities from the firmware version */
/* Determine capabilities from the firmware version */
switch
(
priv
->
firmware_type
)
{
switch
(
priv
->
firmware_type
)
{
...
@@ -1566,6 +1752,8 @@ static void determine_firmware(struct net_device *dev)
...
@@ -1566,6 +1752,8 @@ static void determine_firmware(struct net_device *dev)
"version %d.%02d
\n
"
,
dev
->
name
,
"version %d.%02d
\n
"
,
dev
->
name
,
sta_id
.
major
,
sta_id
.
minor
);
sta_id
.
major
,
sta_id
.
minor
);
firmver
=
((
unsigned
long
)
sta_id
.
major
<<
16
)
|
sta_id
.
minor
;
priv
->
has_ibss
=
(
firmver
>=
0x60006
);
priv
->
has_ibss
=
(
firmver
>=
0x60006
);
priv
->
has_ibss_any
=
(
firmver
>=
0x60010
);
priv
->
has_ibss_any
=
(
firmver
>=
0x60010
);
priv
->
has_wep
=
(
firmver
>=
0x40020
);
priv
->
has_wep
=
(
firmver
>=
0x40020
);
...
@@ -1575,8 +1763,6 @@ static void determine_firmware(struct net_device *dev)
...
@@ -1575,8 +1763,6 @@ static void determine_firmware(struct net_device *dev)
priv
->
has_pm
=
(
firmver
>=
0x40020
);
/* Don't work in 7.52 ? */
priv
->
has_pm
=
(
firmver
>=
0x40020
);
/* Don't work in 7.52 ? */
priv
->
ibss_port
=
1
;
priv
->
ibss_port
=
1
;
/* FIXME: Which firmware really do have a broken reset */
priv
->
broken_cor_reset
=
(
firmver
<
0x60000
);
/* Tested with Agere firmware :
/* Tested with Agere firmware :
* 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
* 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
* Tested CableTron firmware : 4.32 => Anton */
* Tested CableTron firmware : 4.32 => Anton */
...
@@ -1628,18 +1814,21 @@ static void determine_firmware(struct net_device *dev)
...
@@ -1628,18 +1814,21 @@ static void determine_firmware(struct net_device *dev)
/* D-Link MAC : 00:40:05:* */
/* D-Link MAC : 00:40:05:* */
/* Addtron MAC : 00:90:D1:* */
/* Addtron MAC : 00:90:D1:* */
printk
(
KERN_DEBUG
"%s: Looks like an Intersil firmware "
printk
(
KERN_DEBUG
"%s: Looks like an Intersil firmware "
"version %d.%
02
d
\n
"
,
dev
->
name
,
"version %d.%
d.%
d
\n
"
,
dev
->
name
,
sta_id
.
major
,
sta_id
.
minor
);
sta_id
.
major
,
sta_id
.
minor
,
sta_id
.
variant
);
priv
->
has_ibss
=
(
firmver
>=
0x00007
);
/* FIXME */
firmver
=
((
unsigned
long
)
sta_id
.
major
<<
16
)
|
priv
->
has_big_wep
=
priv
->
has_wep
=
(
firmver
>=
0x00008
);
((
unsigned
long
)
sta_id
.
minor
<<
8
)
|
sta_id
.
variant
;
priv
->
has_pm
=
(
firmver
>=
0x00007
);
if
(
firmver
>=
0x00008
)
priv
->
has_ibss
=
(
firmver
>=
0x000700
);
/* FIXME */
priv
->
has_big_wep
=
priv
->
has_wep
=
(
firmver
>=
0x000800
);
priv
->
has_pm
=
(
firmver
>=
0x000700
);
if
(
firmver
>=
0x000800
)
priv
->
ibss_port
=
0
;
priv
->
ibss_port
=
0
;
else
{
else
{
printk
(
KERN_NOTICE
"%s: Intersil firmware earlier "
printk
(
KERN_NOTICE
"%s: Intersil firmware earlier "
"than v0.
08
- several features not supported
\n
"
,
"than v0.
8.x
- several features not supported
\n
"
,
dev
->
name
);
dev
->
name
);
priv
->
ibss_port
=
1
;
priv
->
ibss_port
=
1
;
}
}
...
@@ -1663,16 +1852,16 @@ orinoco_init(struct net_device *dev)
...
@@ -1663,16 +1852,16 @@ orinoco_init(struct net_device *dev)
u16
reclen
;
u16
reclen
;
int
len
;
int
len
;
TRACE_ENTER
(
"orinoco"
);
TRACE_ENTER
(
dev
->
name
);
orinoco_lock
(
priv
);
/* No need to lock, the resetting flag is already set in
* alloc_orinocodev() */
priv
->
nicbuf_size
=
IEEE802_11_FRAME_LEN
+
ETH_HLEN
;
priv
->
nicbuf_size
=
IEEE802_11_FRAME_LEN
+
ETH_HLEN
;
/*
Do standard firmware reset
*/
/*
Initialize the firmware
*/
err
=
hermes_
rese
t
(
hw
);
err
=
hermes_
ini
t
(
hw
);
if
(
err
!=
0
)
{
if
(
err
!=
0
)
{
printk
(
KERN_ERR
"%s: failed to
reset hard
ware (err = %d)
\n
"
,
printk
(
KERN_ERR
"%s: failed to
initialize firm
ware (err = %d)
\n
"
,
dev
->
name
,
err
);
dev
->
name
,
err
);
goto
out
;
goto
out
;
}
}
...
@@ -1801,20 +1990,38 @@ orinoco_init(struct net_device *dev)
...
@@ -1801,20 +1990,38 @@ orinoco_init(struct net_device *dev)
priv
->
wep_on
=
0
;
priv
->
wep_on
=
0
;
priv
->
tx_key
=
0
;
priv
->
tx_key
=
0
;
pri
ntk
(
KERN_DEBUG
"%s: ready
\n
"
,
dev
->
name
)
;
pri
v
->
hw_unavailable
=
0
;
out:
err
=
hermes_allocate
(
hw
,
priv
->
nicbuf_size
,
&
priv
->
txfid
);
orinoco_unlock
(
priv
);
if
(
err
==
-
EIO
)
{
/* Try workaround for old Symbol firmware bug */
printk
(
KERN_WARNING
"%s: firmware ALLOC bug detected "
"(old Symbol firmware?). Trying to work around... "
,
dev
->
name
);
priv
->
nicbuf_size
=
TX_NICBUF_SIZE_BUG
;
err
=
hermes_allocate
(
hw
,
priv
->
nicbuf_size
,
&
priv
->
txfid
);
if
(
err
)
printk
(
"failed!
\n
"
);
else
printk
(
"ok.
\n
"
);
}
if
(
err
)
{
printk
(
"%s: Error %d allocating Tx buffer
\n
"
,
dev
->
name
,
err
);
goto
out
;
}
TRACE_EXIT
(
"orinoco"
);
printk
(
KERN_DEBUG
"%s: ready
\n
"
,
dev
->
name
);
out:
TRACE_EXIT
(
dev
->
name
);
return
err
;
return
err
;
}
}
struct
net_device_stats
*
struct
net_device_stats
*
orinoco_get_stats
(
struct
net_device
*
dev
)
orinoco_get_stats
(
struct
net_device
*
dev
)
{
{
struct
orinoco_private
*
priv
=
(
struct
orinoco_private
*
)
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
return
&
priv
->
stats
;
return
&
priv
->
stats
;
}
}
...
@@ -1822,15 +2029,22 @@ orinoco_get_stats(struct net_device *dev)
...
@@ -1822,15 +2029,22 @@ orinoco_get_stats(struct net_device *dev)
struct
iw_statistics
*
struct
iw_statistics
*
orinoco_get_wireless_stats
(
struct
net_device
*
dev
)
orinoco_get_wireless_stats
(
struct
net_device
*
dev
)
{
{
struct
orinoco_private
*
priv
=
(
struct
orinoco_private
*
)
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
hermes_t
*
hw
=
&
priv
->
hw
;
hermes_t
*
hw
=
&
priv
->
hw
;
struct
iw_statistics
*
wstats
=
&
priv
->
wstats
;
struct
iw_statistics
*
wstats
=
&
priv
->
wstats
;
int
err
=
0
;
int
err
=
0
;
unsigned
long
flags
;
if
(
!
netif_device_present
(
dev
))
if
(
!
netif_device_present
(
dev
))
{
return
NULL
;
/* FIXME: We may be able to do better than this */
printk
(
KERN_WARNING
"%s: get_wireless_stats() called while device not present
\n
"
,
dev
->
name
);
return
NULL
;
/* FIXME: Can we do better than this? */
}
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
NULL
;
/* FIXME: Erg, we've been signalled, how
* do we propagate this back up? */
if
(
priv
->
iw_mode
==
IW_MODE_ADHOC
)
{
if
(
priv
->
iw_mode
==
IW_MODE_ADHOC
)
{
memset
(
&
wstats
->
qual
,
0
,
sizeof
(
wstats
->
qual
));
memset
(
&
wstats
->
qual
,
0
,
sizeof
(
wstats
->
qual
));
...
@@ -1850,9 +2064,6 @@ orinoco_get_wireless_stats(struct net_device *dev)
...
@@ -1850,9 +2064,6 @@ orinoco_get_wireless_stats(struct net_device *dev)
err
=
HERMES_READ_RECORD
(
hw
,
USER_BAP
,
err
=
HERMES_READ_RECORD
(
hw
,
USER_BAP
,
HERMES_RID_COMMSQUALITY
,
&
cq
);
HERMES_RID_COMMSQUALITY
,
&
cq
);
DEBUG
(
3
,
"%s: Global stats = %X-%X-%X
\n
"
,
dev
->
name
,
cq
.
qual
,
cq
.
signal
,
cq
.
noise
);
wstats
->
qual
.
qual
=
(
int
)
le16_to_cpu
(
cq
.
qual
);
wstats
->
qual
.
qual
=
(
int
)
le16_to_cpu
(
cq
.
qual
);
wstats
->
qual
.
level
=
(
int
)
le16_to_cpu
(
cq
.
signal
)
-
0x95
;
wstats
->
qual
.
level
=
(
int
)
le16_to_cpu
(
cq
.
signal
)
-
0x95
;
wstats
->
qual
.
noise
=
(
int
)
le16_to_cpu
(
cq
.
noise
)
-
0x95
;
wstats
->
qual
.
noise
=
(
int
)
le16_to_cpu
(
cq
.
noise
)
-
0x95
;
...
@@ -1862,11 +2073,11 @@ orinoco_get_wireless_stats(struct net_device *dev)
...
@@ -1862,11 +2073,11 @@ orinoco_get_wireless_stats(struct net_device *dev)
/* We can't really wait for the tallies inquiry command to
/* We can't really wait for the tallies inquiry command to
* complete, so we just use the previous results and trigger
* complete, so we just use the previous results and trigger
* a new tallies inquiry command for next time - Jean II */
* a new tallies inquiry command for next time - Jean II */
/* FIXME:
Hmm.. seems a bit ugly, I wonder if there's a way to
/* FIXME:
We're in user context (I think?), so we should just
do better - dgibson
*/
wait for the tallies to come through
*/
err
=
hermes_inquire
(
hw
,
HERMES_INQ_TALLIES
);
err
=
hermes_inquire
(
hw
,
HERMES_INQ_TALLIES
);
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
if
(
err
)
if
(
err
)
return
NULL
;
return
NULL
;
...
@@ -1926,21 +2137,31 @@ orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
...
@@ -1926,21 +2137,31 @@ orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
struct
ethhdr
*
eh
;
struct
ethhdr
*
eh
;
int
len
,
data_len
,
data_off
;
int
len
,
data_len
,
data_off
;
struct
hermes_tx_descriptor
desc
;
struct
hermes_tx_descriptor
desc
;
unsigned
long
flags
;
TRACE_ENTER
(
dev
->
name
);
if
(
!
netif_running
(
dev
))
{
if
(
!
netif_running
(
dev
))
{
printk
(
KERN_ERR
"%s: Tx on stopped device!
\n
"
,
printk
(
KERN_ERR
"%s: Tx on stopped device!
\n
"
,
dev
->
name
);
dev
->
name
);
TRACE_EXIT
(
dev
->
name
);
return
1
;
return
1
;
}
}
if
(
netif_queue_stopped
(
dev
))
{
if
(
netif_queue_stopped
(
dev
))
{
printk
(
KERN_
ERR
"%s: Tx while transmitter busy!
\n
"
,
printk
(
KERN_
DEBUG
"%s: Tx while transmitter busy!
\n
"
,
dev
->
name
);
dev
->
name
);
TRACE_EXIT
(
dev
->
name
);
return
1
;
return
1
;
}
}
orinoco_lock
(
priv
);
if
(
orinoco_lock
(
priv
,
&
flags
)
!=
0
)
{
printk
(
KERN_ERR
"%s: orinoco_xmit() called while hw_unavailable
\n
"
,
dev
->
name
);
TRACE_EXIT
(
dev
->
name
);
/* BUG(); */
return
1
;
}
/* Length of the packet body */
/* Length of the packet body */
/* FIXME: what if the skb is smaller than this? */
/* FIXME: what if the skb is smaller than this? */
...
@@ -2011,14 +2232,17 @@ orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
...
@@ -2011,14 +2232,17 @@ orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
dev
->
trans_start
=
jiffies
;
dev
->
trans_start
=
jiffies
;
stats
->
tx_bytes
+=
data_off
+
data_len
;
stats
->
tx_bytes
+=
data_off
+
data_len
;
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
dev_kfree_skb
(
skb
);
dev_kfree_skb
(
skb
);
TRACE_EXIT
(
dev
->
name
);
return
0
;
return
0
;
fail:
fail:
TRACE_EXIT
(
dev
->
name
);
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
err
;
return
err
;
}
}
...
@@ -2028,27 +2252,21 @@ orinoco_tx_timeout(struct net_device *dev)
...
@@ -2028,27 +2252,21 @@ orinoco_tx_timeout(struct net_device *dev)
struct
orinoco_private
*
priv
=
(
struct
orinoco_private
*
)
dev
->
priv
;
struct
orinoco_private
*
priv
=
(
struct
orinoco_private
*
)
dev
->
priv
;
struct
net_device_stats
*
stats
=
&
priv
->
stats
;
struct
net_device_stats
*
stats
=
&
priv
->
stats
;
struct
hermes
*
hw
=
&
priv
->
hw
;
struct
hermes
*
hw
=
&
priv
->
hw
;
int
err
=
0
;
printk
(
KERN_WARNING
"%s: Tx timeout! Resetting card. ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x
\n
"
,
dev
->
name
,
hermes_read_regn
(
hw
,
ALLOCFID
),
hermes_read_regn
(
hw
,
TXCOMPLFID
),
hermes_read_regn
(
hw
,
EVSTAT
));
printk
(
KERN_WARNING
"%s: Tx timeout! "
"ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x
\n
"
,
dev
->
name
,
hermes_read_regn
(
hw
,
ALLOCFID
),
hermes_read_regn
(
hw
,
TXCOMPLFID
),
hermes_read_regn
(
hw
,
EVSTAT
));
stats
->
tx_errors
++
;
stats
->
tx_errors
++
;
err
=
orinoco_reset
(
priv
);
schedule_task
(
&
priv
->
timeout_task
);
if
(
err
)
printk
(
KERN_ERR
"%s: Error %d resetting card on Tx timeout!
\n
"
,
dev
->
name
,
err
);
else
{
dev
->
trans_start
=
jiffies
;
netif_wake_queue
(
dev
);
}
}
}
static
int
static
int
orinoco_change_mtu
(
struct
net_device
*
dev
,
int
new_mtu
)
orinoco_change_mtu
(
struct
net_device
*
dev
,
int
new_mtu
)
{
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
TRACE_ENTER
(
dev
->
name
);
if
(
(
new_mtu
<
ORINOCO_MIN_MTU
)
||
(
new_mtu
>
ORINOCO_MAX_MTU
)
)
if
(
(
new_mtu
<
ORINOCO_MIN_MTU
)
||
(
new_mtu
>
ORINOCO_MAX_MTU
)
)
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -2059,11 +2277,10 @@ orinoco_change_mtu(struct net_device *dev, int new_mtu)
...
@@ -2059,11 +2277,10 @@ orinoco_change_mtu(struct net_device *dev, int new_mtu)
dev
->
mtu
=
new_mtu
;
dev
->
mtu
=
new_mtu
;
TRACE_EXIT
(
dev
->
name
);
return
0
;
return
0
;
}
}
/* FIXME: return int? */
static
void
static
void
__orinoco_set_multicast_list
(
struct
net_device
*
dev
)
__orinoco_set_multicast_list
(
struct
net_device
*
dev
)
{
{
...
@@ -2072,17 +2289,6 @@ __orinoco_set_multicast_list(struct net_device *dev)
...
@@ -2072,17 +2289,6 @@ __orinoco_set_multicast_list(struct net_device *dev)
int
err
=
0
;
int
err
=
0
;
int
promisc
,
mc_count
;
int
promisc
,
mc_count
;
/* We'll wait until it's ready. Anyway, the network doesn't call us
* here until we are open - Jean II */
/* FIXME: do we need this test at all? */
if
(
!
netif_device_present
(
dev
))
{
printk
(
KERN_WARNING
"%s: __orinoco_set_multicast_list() called while device "
"not present.
\n
"
,
dev
->
name
);
return
;
}
TRACE_ENTER
(
dev
->
name
);
/* The Hermes doesn't seem to have an allmulti mode, so we go
/* The Hermes doesn't seem to have an allmulti mode, so we go
* into promiscuous mode and let the upper levels deal. */
* into promiscuous mode and let the upper levels deal. */
if
(
(
dev
->
flags
&
IFF_PROMISC
)
||
(
dev
->
flags
&
IFF_ALLMULTI
)
||
if
(
(
dev
->
flags
&
IFF_PROMISC
)
||
(
dev
->
flags
&
IFF_ALLMULTI
)
||
...
@@ -2140,8 +2346,6 @@ __orinoco_set_multicast_list(struct net_device *dev)
...
@@ -2140,8 +2346,6 @@ __orinoco_set_multicast_list(struct net_device *dev)
dev
->
flags
|=
IFF_PROMISC
;
dev
->
flags
|=
IFF_PROMISC
;
else
else
dev
->
flags
&=
~
IFF_PROMISC
;
dev
->
flags
&=
~
IFF_PROMISC
;
TRACE_EXIT
(
dev
->
name
);
}
}
/********************************************************************/
/********************************************************************/
...
@@ -2156,6 +2360,7 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
...
@@ -2156,6 +2360,7 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
struct
iw_range
range
;
struct
iw_range
range
;
int
numrates
;
int
numrates
;
int
i
,
k
;
int
i
,
k
;
unsigned
long
flags
;
TRACE_ENTER
(
dev
->
name
);
TRACE_ENTER
(
dev
->
name
);
...
@@ -2165,9 +2370,12 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
...
@@ -2165,9 +2370,12 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
rrq
->
length
=
sizeof
(
range
);
rrq
->
length
=
sizeof
(
range
);
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
mode
=
priv
->
iw_mode
;
mode
=
priv
->
iw_mode
;
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
memset
(
&
range
,
0
,
sizeof
(
range
));
memset
(
&
range
,
0
,
sizeof
(
range
));
...
@@ -2240,7 +2448,9 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
...
@@ -2240,7 +2448,9 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
range
.
min_frag
=
256
;
range
.
min_frag
=
256
;
range
.
max_frag
=
2346
;
range
.
max_frag
=
2346
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
if
(
priv
->
has_wep
)
{
if
(
priv
->
has_wep
)
{
range
.
max_encoding_tokens
=
ORINOCO_MAX_KEYS
;
range
.
max_encoding_tokens
=
ORINOCO_MAX_KEYS
;
...
@@ -2255,7 +2465,7 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
...
@@ -2255,7 +2465,7 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
range
.
num_encoding_sizes
=
0
;
range
.
num_encoding_sizes
=
0
;
range
.
max_encoding_tokens
=
0
;
range
.
max_encoding_tokens
=
0
;
}
}
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
range
.
min_pmp
=
0
;
range
.
min_pmp
=
0
;
range
.
max_pmp
=
65535000
;
range
.
max_pmp
=
65535000
;
...
@@ -2297,6 +2507,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
...
@@ -2297,6 +2507,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
u16
xlen
=
0
;
u16
xlen
=
0
;
int
err
=
0
;
int
err
=
0
;
char
keybuf
[
ORINOCO_MAX_KEY_SIZE
];
char
keybuf
[
ORINOCO_MAX_KEY_SIZE
];
unsigned
long
flags
;
if
(
erq
->
pointer
)
{
if
(
erq
->
pointer
)
{
/* We actually have a key to set */
/* We actually have a key to set */
...
@@ -2307,7 +2518,9 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
...
@@ -2307,7 +2518,9 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
return
-
EFAULT
;
return
-
EFAULT
;
}
}
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
if
(
erq
->
pointer
)
{
if
(
erq
->
pointer
)
{
if
(
erq
->
length
>
ORINOCO_MAX_KEY_SIZE
)
{
if
(
erq
->
length
>
ORINOCO_MAX_KEY_SIZE
)
{
...
@@ -2371,9 +2584,10 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
...
@@ -2371,9 +2584,10 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
priv
->
tx_key
=
setindex
;
priv
->
tx_key
=
setindex
;
priv
->
wep_on
=
enable
;
priv
->
wep_on
=
enable
;
priv
->
wep_restrict
=
restricted
;
priv
->
wep_restrict
=
restricted
;
out:
out:
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
err
;
return
err
;
}
}
...
@@ -2384,9 +2598,12 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *er
...
@@ -2384,9 +2598,12 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *er
int
index
=
(
erq
->
flags
&
IW_ENCODE_INDEX
)
-
1
;
int
index
=
(
erq
->
flags
&
IW_ENCODE_INDEX
)
-
1
;
u16
xlen
=
0
;
u16
xlen
=
0
;
char
keybuf
[
ORINOCO_MAX_KEY_SIZE
];
char
keybuf
[
ORINOCO_MAX_KEY_SIZE
];
int
err
;
unsigned
long
flags
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
if
((
index
<
0
)
||
(
index
>=
ORINOCO_MAX_KEYS
))
if
((
index
<
0
)
||
(
index
>=
ORINOCO_MAX_KEYS
))
index
=
priv
->
tx_key
;
index
=
priv
->
tx_key
;
...
@@ -2412,7 +2629,7 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *er
...
@@ -2412,7 +2629,7 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *er
memcpy
(
keybuf
,
priv
->
keys
[
index
].
data
,
ORINOCO_MAX_KEY_SIZE
);
memcpy
(
keybuf
,
priv
->
keys
[
index
].
data
,
ORINOCO_MAX_KEY_SIZE
);
}
}
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
if
(
erq
->
pointer
)
{
if
(
erq
->
pointer
)
{
if
(
copy_to_user
(
erq
->
pointer
,
keybuf
,
xlen
))
if
(
copy_to_user
(
erq
->
pointer
,
keybuf
,
xlen
))
...
@@ -2426,6 +2643,8 @@ static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
...
@@ -2426,6 +2643,8 @@ static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
{
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
char
essidbuf
[
IW_ESSID_MAX_SIZE
+
1
];
char
essidbuf
[
IW_ESSID_MAX_SIZE
+
1
];
int
err
;
unsigned
long
flags
;
/* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
/* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
* anyway... - Jean II */
* anyway... - Jean II */
...
@@ -2442,11 +2661,13 @@ static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
...
@@ -2442,11 +2661,13 @@ static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
essidbuf
[
erq
->
length
]
=
'\0'
;
essidbuf
[
erq
->
length
]
=
'\0'
;
}
}
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
memcpy
(
priv
->
desired_essid
,
essidbuf
,
sizeof
(
priv
->
desired_essid
));
memcpy
(
priv
->
desired_essid
,
essidbuf
,
sizeof
(
priv
->
desired_essid
));
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
0
;
return
0
;
}
}
...
@@ -2457,6 +2678,7 @@ static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq)
...
@@ -2457,6 +2678,7 @@ static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq)
char
essidbuf
[
IW_ESSID_MAX_SIZE
+
1
];
char
essidbuf
[
IW_ESSID_MAX_SIZE
+
1
];
int
active
;
int
active
;
int
err
=
0
;
int
err
=
0
;
unsigned
long
flags
;
TRACE_ENTER
(
dev
->
name
);
TRACE_ENTER
(
dev
->
name
);
...
@@ -2465,9 +2687,11 @@ static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq)
...
@@ -2465,9 +2687,11 @@ static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq)
if
(
err
)
if
(
err
)
return
err
;
return
err
;
}
else
{
}
else
{
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
memcpy
(
essidbuf
,
priv
->
desired_essid
,
sizeof
(
essidbuf
));
memcpy
(
essidbuf
,
priv
->
desired_essid
,
sizeof
(
essidbuf
));
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
}
}
erq
->
flags
=
1
;
erq
->
flags
=
1
;
...
@@ -2485,6 +2709,8 @@ static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq)
...
@@ -2485,6 +2709,8 @@ static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq)
{
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
char
nickbuf
[
IW_ESSID_MAX_SIZE
+
1
];
char
nickbuf
[
IW_ESSID_MAX_SIZE
+
1
];
int
err
;
unsigned
long
flags
;
if
(
nrq
->
length
>
IW_ESSID_MAX_SIZE
)
if
(
nrq
->
length
>
IW_ESSID_MAX_SIZE
)
return
-
E2BIG
;
return
-
E2BIG
;
...
@@ -2496,11 +2722,13 @@ static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq)
...
@@ -2496,11 +2722,13 @@ static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq)
nickbuf
[
nrq
->
length
]
=
'\0'
;
nickbuf
[
nrq
->
length
]
=
'\0'
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
memcpy
(
priv
->
nick
,
nickbuf
,
sizeof
(
priv
->
nick
));
memcpy
(
priv
->
nick
,
nickbuf
,
sizeof
(
priv
->
nick
));
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
0
;
return
0
;
}
}
...
@@ -2509,10 +2737,15 @@ static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq)
...
@@ -2509,10 +2737,15 @@ static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq)
{
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
char
nickbuf
[
IW_ESSID_MAX_SIZE
+
1
];
char
nickbuf
[
IW_ESSID_MAX_SIZE
+
1
];
int
err
;
unsigned
long
flags
;
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
orinoco_lock
(
priv
);
memcpy
(
nickbuf
,
priv
->
nick
,
IW_ESSID_MAX_SIZE
+
1
);
memcpy
(
nickbuf
,
priv
->
nick
,
IW_ESSID_MAX_SIZE
+
1
);
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
nrq
->
length
=
strlen
(
nickbuf
)
+
1
;
nrq
->
length
=
strlen
(
nickbuf
)
+
1
;
...
@@ -2526,6 +2759,8 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq)
...
@@ -2526,6 +2759,8 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq)
{
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
int
chan
=
-
1
;
int
chan
=
-
1
;
int
err
;
unsigned
long
flags
;
/* We can only use this in Ad-Hoc demo mode to set the operating
/* We can only use this in Ad-Hoc demo mode to set the operating
* frequency, or in IBSS mode to set the frequency where the IBSS
* frequency, or in IBSS mode to set the frequency where the IBSS
...
@@ -2553,9 +2788,11 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq)
...
@@ -2553,9 +2788,11 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq)
!
(
priv
->
channel_mask
&
(
1
<<
(
chan
-
1
))
)
)
!
(
priv
->
channel_mask
&
(
1
<<
(
chan
-
1
))
)
)
return
-
EINVAL
;
return
-
EINVAL
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
priv
->
channel
=
chan
;
priv
->
channel
=
chan
;
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
0
;
return
0
;
}
}
...
@@ -2566,13 +2803,16 @@ static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq)
...
@@ -2566,13 +2803,16 @@ static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq)
hermes_t
*
hw
=
&
priv
->
hw
;
hermes_t
*
hw
=
&
priv
->
hw
;
u16
val
;
u16
val
;
int
err
;
int
err
;
unsigned
long
flags
;
if
(
!
priv
->
has_sensitivity
)
if
(
!
priv
->
has_sensitivity
)
return
-
EOPNOTSUPP
;
return
-
EOPNOTSUPP
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
err
=
hermes_read_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFSYSTEMSCALE
,
&
val
);
err
=
hermes_read_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFSYSTEMSCALE
,
&
val
);
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
if
(
err
)
if
(
err
)
return
err
;
return
err
;
...
@@ -2587,6 +2827,8 @@ static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq)
...
@@ -2587,6 +2827,8 @@ static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq)
{
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
int
val
=
srq
->
value
;
int
val
=
srq
->
value
;
int
err
;
unsigned
long
flags
;
if
(
!
priv
->
has_sensitivity
)
if
(
!
priv
->
has_sensitivity
)
return
-
EOPNOTSUPP
;
return
-
EOPNOTSUPP
;
...
@@ -2594,9 +2836,11 @@ static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq)
...
@@ -2594,9 +2836,11 @@ static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq)
if
((
val
<
1
)
||
(
val
>
3
))
if
((
val
<
1
)
||
(
val
>
3
))
return
-
EINVAL
;
return
-
EINVAL
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
priv
->
ap_density
=
val
;
priv
->
ap_density
=
val
;
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
0
;
return
0
;
}
}
...
@@ -2605,6 +2849,8 @@ static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
...
@@ -2605,6 +2849,8 @@ static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
{
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
int
val
=
rrq
->
value
;
int
val
=
rrq
->
value
;
int
err
;
unsigned
long
flags
;
if
(
rrq
->
disabled
)
if
(
rrq
->
disabled
)
val
=
2347
;
val
=
2347
;
...
@@ -2612,9 +2858,12 @@ static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
...
@@ -2612,9 +2858,12 @@ static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
if
(
(
val
<
0
)
||
(
val
>
2347
)
)
if
(
(
val
<
0
)
||
(
val
>
2347
)
)
return
-
EINVAL
;
return
-
EINVAL
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
priv
->
rts_thresh
=
val
;
priv
->
rts_thresh
=
val
;
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
0
;
return
0
;
}
}
...
@@ -2623,8 +2872,11 @@ static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq)
...
@@ -2623,8 +2872,11 @@ static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq)
{
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
int
err
=
0
;
int
err
=
0
;
unsigned
long
flags
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
if
(
priv
->
has_mwo
)
{
if
(
priv
->
has_mwo
)
{
if
(
frq
->
disabled
)
if
(
frq
->
disabled
)
...
@@ -2646,7 +2898,7 @@ supported on this firmware. Using MWO robust instead.\n", dev->name);
...
@@ -2646,7 +2898,7 @@ supported on this firmware. Using MWO robust instead.\n", dev->name);
}
}
}
}
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
err
;
return
err
;
}
}
...
@@ -2657,8 +2909,11 @@ static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq)
...
@@ -2657,8 +2909,11 @@ static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq)
hermes_t
*
hw
=
&
priv
->
hw
;
hermes_t
*
hw
=
&
priv
->
hw
;
int
err
=
0
;
int
err
=
0
;
u16
val
;
u16
val
;
unsigned
long
flags
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
if
(
priv
->
has_mwo
)
{
if
(
priv
->
has_mwo
)
{
err
=
hermes_read_wordrec
(
hw
,
USER_BAP
,
err
=
hermes_read_wordrec
(
hw
,
USER_BAP
,
...
@@ -2681,7 +2936,7 @@ static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq)
...
@@ -2681,7 +2936,7 @@ static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq)
frq
->
fixed
=
1
;
frq
->
fixed
=
1
;
}
}
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
err
;
return
err
;
}
}
...
@@ -2693,6 +2948,7 @@ static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq)
...
@@ -2693,6 +2948,7 @@ static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq)
int
ratemode
=
-
1
;
int
ratemode
=
-
1
;
int
bitrate
;
/* 100s of kilobits */
int
bitrate
;
/* 100s of kilobits */
int
i
;
int
i
;
unsigned
long
flags
;
/* As the user space doesn't know our highest rate, it uses -1
/* As the user space doesn't know our highest rate, it uses -1
* to ask us to set the highest rate. Test it using "iwconfig
* to ask us to set the highest rate. Test it using "iwconfig
...
@@ -2719,9 +2975,11 @@ static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq)
...
@@ -2719,9 +2975,11 @@ static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq)
if
(
ratemode
==
-
1
)
if
(
ratemode
==
-
1
)
return
-
EINVAL
;
return
-
EINVAL
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
priv
->
bitratemode
=
ratemode
;
priv
->
bitratemode
=
ratemode
;
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
err
;
return
err
;
}
}
...
@@ -2734,8 +2992,11 @@ static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq)
...
@@ -2734,8 +2992,11 @@ static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq)
int
ratemode
;
int
ratemode
;
int
i
;
int
i
;
u16
val
;
u16
val
;
unsigned
long
flags
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
ratemode
=
priv
->
bitratemode
;
ratemode
=
priv
->
bitratemode
;
...
@@ -2785,7 +3046,7 @@ static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq)
...
@@ -2785,7 +3046,7 @@ static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq)
}
}
out:
out:
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
err
;
return
err
;
}
}
...
@@ -2794,9 +3055,11 @@ static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq)
...
@@ -2794,9 +3055,11 @@ static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq)
{
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
int
err
=
0
;
int
err
=
0
;
unsigned
long
flags
;
err
=
orinoco_lock
(
priv
,
&
flags
);
orinoco_lock
(
priv
);
if
(
err
)
return
err
;
if
(
prq
->
disabled
)
{
if
(
prq
->
disabled
)
{
priv
->
pm_on
=
0
;
priv
->
pm_on
=
0
;
...
@@ -2836,7 +3099,7 @@ static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq)
...
@@ -2836,7 +3099,7 @@ static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq)
}
}
out:
out:
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
err
;
return
err
;
}
}
...
@@ -2847,8 +3110,11 @@ static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq)
...
@@ -2847,8 +3110,11 @@ static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq)
hermes_t
*
hw
=
&
priv
->
hw
;
hermes_t
*
hw
=
&
priv
->
hw
;
int
err
=
0
;
int
err
=
0
;
u16
enable
,
period
,
timeout
,
mcast
;
u16
enable
,
period
,
timeout
,
mcast
;
unsigned
long
flags
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
err
=
hermes_read_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFPMENABLED
,
&
enable
);
err
=
hermes_read_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_CNFPMENABLED
,
&
enable
);
if
(
err
)
if
(
err
)
...
@@ -2882,7 +3148,7 @@ static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq)
...
@@ -2882,7 +3148,7 @@ static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq)
prq
->
flags
|=
IW_POWER_UNICAST_R
;
prq
->
flags
|=
IW_POWER_UNICAST_R
;
out:
out:
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
err
;
return
err
;
}
}
...
@@ -2894,8 +3160,11 @@ static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq)
...
@@ -2894,8 +3160,11 @@ static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq)
hermes_t
*
hw
=
&
priv
->
hw
;
hermes_t
*
hw
=
&
priv
->
hw
;
int
err
=
0
;
int
err
=
0
;
u16
short_limit
,
long_limit
,
lifetime
;
u16
short_limit
,
long_limit
,
lifetime
;
unsigned
long
flags
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
err
=
hermes_read_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_SHORTRETRYLIMIT
,
err
=
hermes_read_wordrec
(
hw
,
USER_BAP
,
HERMES_RID_SHORTRETRYLIMIT
,
&
short_limit
);
&
short_limit
);
...
@@ -2932,7 +3201,7 @@ static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq)
...
@@ -2932,7 +3201,7 @@ static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq)
}
}
out:
out:
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
err
;
return
err
;
}
}
...
@@ -2942,14 +3211,19 @@ static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq)
...
@@ -2942,14 +3211,19 @@ static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq)
{
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
int
val
=
*
(
(
int
*
)
wrq
->
u
.
name
);
int
val
=
*
(
(
int
*
)
wrq
->
u
.
name
);
int
err
;
unsigned
long
flags
;
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
orinoco_lock
(
priv
);
priv
->
ibss_port
=
val
;
priv
->
ibss_port
=
val
;
/* Actually update the mode we are using */
/* Actually update the mode we are using */
set_port_type
(
priv
);
set_port_type
(
priv
);
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
0
;
return
0
;
}
}
...
@@ -2957,10 +3231,15 @@ static int orinoco_ioctl_getibssport(struct net_device *dev, struct iwreq *wrq)
...
@@ -2957,10 +3231,15 @@ static int orinoco_ioctl_getibssport(struct net_device *dev, struct iwreq *wrq)
{
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
int
*
val
=
(
int
*
)
wrq
->
u
.
name
;
int
*
val
=
(
int
*
)
wrq
->
u
.
name
;
int
err
;
unsigned
long
flags
;
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
orinoco_lock
(
priv
);
*
val
=
priv
->
ibss_port
;
*
val
=
priv
->
ibss_port
;
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
0
;
return
0
;
}
}
...
@@ -2970,15 +3249,18 @@ static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq)
...
@@ -2970,15 +3249,18 @@ static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq)
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
int
val
=
*
(
(
int
*
)
wrq
->
u
.
name
);
int
val
=
*
(
(
int
*
)
wrq
->
u
.
name
);
int
err
=
0
;
int
err
=
0
;
unsigned
long
flags
;
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
orinoco_lock
(
priv
);
switch
(
val
)
{
switch
(
val
)
{
case
0
:
/* Try to do IEEE ad-hoc mode */
case
0
:
/* Try to do IEEE ad-hoc mode */
if
(
!
priv
->
has_ibss
)
{
if
(
!
priv
->
has_ibss
)
{
err
=
-
EINVAL
;
err
=
-
EINVAL
;
break
;
break
;
}
}
DEBUG
(
2
,
"%s: Prefer IBSS Ad-Hoc mode
\n
"
,
dev
->
name
);
priv
->
prefer_port3
=
0
;
priv
->
prefer_port3
=
0
;
break
;
break
;
...
@@ -2988,7 +3270,6 @@ static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq)
...
@@ -2988,7 +3270,6 @@ static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq)
err
=
-
EINVAL
;
err
=
-
EINVAL
;
break
;
break
;
}
}
DEBUG
(
2
,
"%s: Prefer Ad-Hoc demo mode
\n
"
,
dev
->
name
);
priv
->
prefer_port3
=
1
;
priv
->
prefer_port3
=
1
;
break
;
break
;
...
@@ -3000,7 +3281,7 @@ static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq)
...
@@ -3000,7 +3281,7 @@ static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq)
/* Actually update the mode we are using */
/* Actually update the mode we are using */
set_port_type
(
priv
);
set_port_type
(
priv
);
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
err
;
return
err
;
}
}
...
@@ -3009,10 +3290,15 @@ static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq)
...
@@ -3009,10 +3290,15 @@ static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq)
{
{
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
int
*
val
=
(
int
*
)
wrq
->
u
.
name
;
int
*
val
=
(
int
*
)
wrq
->
u
.
name
;
int
err
;
unsigned
long
flags
;
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
orinoco_lock
(
priv
);
*
val
=
priv
->
prefer_port3
;
*
val
=
priv
->
prefer_port3
;
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
0
;
return
0
;
}
}
...
@@ -3026,6 +3312,7 @@ static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq)
...
@@ -3026,6 +3312,7 @@ static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq)
int
number
=
srq
->
length
;
int
number
=
srq
->
length
;
int
i
;
int
i
;
int
err
=
0
;
int
err
=
0
;
unsigned
long
flags
;
/* Check the number of addresses */
/* Check the number of addresses */
if
(
number
>
IW_MAX_SPY
)
if
(
number
>
IW_MAX_SPY
)
...
@@ -3039,7 +3326,9 @@ static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq)
...
@@ -3039,7 +3326,9 @@ static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq)
}
}
/* Make sure nobody mess with the structure while we do */
/* Make sure nobody mess with the structure while we do */
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
/* orinoco_lock() doesn't disable interrupts, so make sure the
/* orinoco_lock() doesn't disable interrupts, so make sure the
* interrupt rx path don't get confused while we copy */
* interrupt rx path don't get confused while we copy */
...
@@ -3057,18 +3346,8 @@ static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq)
...
@@ -3057,18 +3346,8 @@ static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq)
priv
->
spy_number
=
number
;
priv
->
spy_number
=
number
;
}
}
/* Time to show what we have done... */
DEBUG
(
0
,
"%s: New spy list:
\n
"
,
dev
->
name
);
for
(
i
=
0
;
i
<
number
;
i
++
)
{
DEBUG
(
0
,
"%s: %d - %02x:%02x:%02x:%02x:%02x:%02x
\n
"
,
dev
->
name
,
i
+
1
,
priv
->
spy_address
[
i
][
0
],
priv
->
spy_address
[
i
][
1
],
priv
->
spy_address
[
i
][
2
],
priv
->
spy_address
[
i
][
3
],
priv
->
spy_address
[
i
][
4
],
priv
->
spy_address
[
i
][
5
]);
}
/* Now, let the others play */
/* Now, let the others play */
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
return
err
;
return
err
;
}
}
...
@@ -3080,8 +3359,12 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq)
...
@@ -3080,8 +3359,12 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq)
struct
iw_quality
spy_stat
[
IW_MAX_SPY
];
struct
iw_quality
spy_stat
[
IW_MAX_SPY
];
int
number
;
int
number
;
int
i
;
int
i
;
int
err
;
unsigned
long
flags
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
number
=
priv
->
spy_number
;
number
=
priv
->
spy_number
;
if
((
number
>
0
)
&&
(
srq
->
pointer
))
{
if
((
number
>
0
)
&&
(
srq
->
pointer
))
{
...
@@ -3101,7 +3384,7 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq)
...
@@ -3101,7 +3384,7 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq)
priv
->
spy_stat
[
i
].
updated
=
0
;
priv
->
spy_stat
[
i
].
updated
=
0
;
}
}
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
/* Push stuff to user space */
/* Push stuff to user space */
srq
->
length
=
number
;
srq
->
length
=
number
;
...
@@ -3121,39 +3404,39 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
...
@@ -3121,39 +3404,39 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
iwreq
*
wrq
=
(
struct
iwreq
*
)
rq
;
struct
iwreq
*
wrq
=
(
struct
iwreq
*
)
rq
;
int
err
=
0
;
int
err
=
0
;
int
tmp
;
int
changed
=
0
;
int
changed
=
0
;
unsigned
long
flags
;
TRACE_ENTER
(
dev
->
name
);
TRACE_ENTER
(
dev
->
name
);
/* In theory, we could allow most of the the SET stuff to be
/* In theory, we could allow most of the the SET stuff to be
* done
In practice, the laps of time at startup when the card
* done
. In practice, the lapse of time at startup when the
*
is not ready is very short, so why bother... Note that
*
card is not ready is very short, so why bother... Note
*
netif_device_present is different from up/down (ifconfig),
*
that netif_device_present is different from up/down
*
when the device is not yet up, it is usually alread
y
*
(ifconfig), when the device is not yet up, it is usuall
y
* ready... Jean II */
*
already
ready... Jean II */
if
(
!
netif_device_present
(
dev
))
if
(
!
netif_device_present
(
dev
))
return
-
ENODEV
;
return
-
ENODEV
;
switch
(
cmd
)
{
switch
(
cmd
)
{
case
SIOCGIWNAME
:
case
SIOCGIWNAME
:
DEBUG
(
1
,
"%s: SIOCGIWNAME
\n
"
,
dev
->
name
);
strcpy
(
wrq
->
u
.
name
,
"IEEE 802.11-DS"
);
strcpy
(
wrq
->
u
.
name
,
"IEEE 802.11-DS"
);
break
;
break
;
case
SIOCGIWAP
:
case
SIOCGIWAP
:
DEBUG
(
1
,
"%s: SIOCGIWAP
\n
"
,
dev
->
name
);
wrq
->
u
.
ap_addr
.
sa_family
=
ARPHRD_ETHER
;
wrq
->
u
.
ap_addr
.
sa_family
=
ARPHRD_ETHER
;
err
=
orinoco_hw_get_bssid
(
priv
,
wrq
->
u
.
ap_addr
.
sa_data
);
err
=
orinoco_hw_get_bssid
(
priv
,
wrq
->
u
.
ap_addr
.
sa_data
);
break
;
break
;
case
SIOCGIWRANGE
:
case
SIOCGIWRANGE
:
DEBUG
(
1
,
"%s: SIOCGIWRANGE
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_getiwrange
(
dev
,
&
wrq
->
u
.
data
);
err
=
orinoco_ioctl_getiwrange
(
dev
,
&
wrq
->
u
.
data
);
break
;
break
;
case
SIOCSIWMODE
:
case
SIOCSIWMODE
:
DEBUG
(
1
,
"%s: SIOCSIWMODE
\n
"
,
dev
->
name
);
err
=
orinoco_lock
(
priv
,
&
flags
);
orinoco_lock
(
priv
);
if
(
err
)
return
err
;
switch
(
wrq
->
u
.
mode
)
{
switch
(
wrq
->
u
.
mode
)
{
case
IW_MODE_ADHOC
:
case
IW_MODE_ADHOC
:
if
(
!
(
priv
->
has_ibss
||
priv
->
has_port3
)
)
if
(
!
(
priv
->
has_ibss
||
priv
->
has_port3
)
)
...
@@ -3174,18 +3457,18 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
...
@@ -3174,18 +3457,18 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break
;
break
;
}
}
set_port_type
(
priv
);
set_port_type
(
priv
);
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
break
;
break
;
case
SIOCGIWMODE
:
case
SIOCGIWMODE
:
DEBUG
(
1
,
"%s: SIOCGIWMODE
\n
"
,
dev
->
name
);
err
=
orinoco_lock
(
priv
,
&
flags
);
orinoco_lock
(
priv
);
if
(
err
)
return
err
;
wrq
->
u
.
mode
=
priv
->
iw_mode
;
wrq
->
u
.
mode
=
priv
->
iw_mode
;
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
break
;
break
;
case
SIOCSIWENCODE
:
case
SIOCSIWENCODE
:
DEBUG
(
1
,
"%s: SIOCSIWENCODE
\n
"
,
dev
->
name
);
if
(
!
priv
->
has_wep
)
{
if
(
!
priv
->
has_wep
)
{
err
=
-
EOPNOTSUPP
;
err
=
-
EOPNOTSUPP
;
break
;
break
;
...
@@ -3197,7 +3480,6 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
...
@@ -3197,7 +3480,6 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break
;
break
;
case
SIOCGIWENCODE
:
case
SIOCGIWENCODE
:
DEBUG
(
1
,
"%s: SIOCGIWENCODE
\n
"
,
dev
->
name
);
if
(
!
priv
->
has_wep
)
{
if
(
!
priv
->
has_wep
)
{
err
=
-
EOPNOTSUPP
;
err
=
-
EOPNOTSUPP
;
break
;
break
;
...
@@ -3212,106 +3494,94 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
...
@@ -3212,106 +3494,94 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break
;
break
;
case
SIOCSIWESSID
:
case
SIOCSIWESSID
:
DEBUG
(
1
,
"%s: SIOCSIWESSID
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_setessid
(
dev
,
&
wrq
->
u
.
essid
);
err
=
orinoco_ioctl_setessid
(
dev
,
&
wrq
->
u
.
essid
);
if
(
!
err
)
if
(
!
err
)
changed
=
1
;
changed
=
1
;
break
;
break
;
case
SIOCGIWESSID
:
case
SIOCGIWESSID
:
DEBUG
(
1
,
"%s: SIOCGIWESSID
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_getessid
(
dev
,
&
wrq
->
u
.
essid
);
err
=
orinoco_ioctl_getessid
(
dev
,
&
wrq
->
u
.
essid
);
break
;
break
;
case
SIOCSIWNICKN
:
case
SIOCSIWNICKN
:
DEBUG
(
1
,
"%s: SIOCSIWNICKN
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_setnick
(
dev
,
&
wrq
->
u
.
data
);
err
=
orinoco_ioctl_setnick
(
dev
,
&
wrq
->
u
.
data
);
if
(
!
err
)
if
(
!
err
)
changed
=
1
;
changed
=
1
;
break
;
break
;
case
SIOCGIWNICKN
:
case
SIOCGIWNICKN
:
DEBUG
(
1
,
"%s: SIOCGIWNICKN
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_getnick
(
dev
,
&
wrq
->
u
.
data
);
err
=
orinoco_ioctl_getnick
(
dev
,
&
wrq
->
u
.
data
);
break
;
break
;
case
SIOCGIWFREQ
:
case
SIOCGIWFREQ
:
DEBUG
(
1
,
"%s: SIOCGIWFREQ
\n
"
,
dev
->
name
);
tmp
=
orinoco_hw_get_freq
(
priv
);
wrq
->
u
.
freq
.
m
=
orinoco_hw_get_freq
(
priv
);
if
(
tmp
<
0
)
{
wrq
->
u
.
freq
.
e
=
1
;
err
=
tmp
;
}
else
{
wrq
->
u
.
freq
.
m
=
tmp
;
wrq
->
u
.
freq
.
e
=
1
;
}
break
;
break
;
case
SIOCSIWFREQ
:
case
SIOCSIWFREQ
:
DEBUG
(
1
,
"%s: SIOCSIWFREQ
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_setfreq
(
dev
,
&
wrq
->
u
.
freq
);
err
=
orinoco_ioctl_setfreq
(
dev
,
&
wrq
->
u
.
freq
);
if
(
!
err
)
if
(
!
err
)
changed
=
1
;
changed
=
1
;
break
;
break
;
case
SIOCGIWSENS
:
case
SIOCGIWSENS
:
DEBUG
(
1
,
"%s: SIOCGIWSENS
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_getsens
(
dev
,
&
wrq
->
u
.
sens
);
err
=
orinoco_ioctl_getsens
(
dev
,
&
wrq
->
u
.
sens
);
break
;
break
;
case
SIOCSIWSENS
:
case
SIOCSIWSENS
:
DEBUG
(
1
,
"%s: SIOCSIWSENS
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_setsens
(
dev
,
&
wrq
->
u
.
sens
);
err
=
orinoco_ioctl_setsens
(
dev
,
&
wrq
->
u
.
sens
);
if
(
!
err
)
if
(
!
err
)
changed
=
1
;
changed
=
1
;
break
;
break
;
case
SIOCGIWRTS
:
case
SIOCGIWRTS
:
DEBUG
(
1
,
"%s: SIOCGIWRTS
\n
"
,
dev
->
name
);
wrq
->
u
.
rts
.
value
=
priv
->
rts_thresh
;
wrq
->
u
.
rts
.
value
=
priv
->
rts_thresh
;
wrq
->
u
.
rts
.
disabled
=
(
wrq
->
u
.
rts
.
value
==
2347
);
wrq
->
u
.
rts
.
disabled
=
(
wrq
->
u
.
rts
.
value
==
2347
);
wrq
->
u
.
rts
.
fixed
=
1
;
wrq
->
u
.
rts
.
fixed
=
1
;
break
;
break
;
case
SIOCSIWRTS
:
case
SIOCSIWRTS
:
DEBUG
(
1
,
"%s: SIOCSIWRTS
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_setrts
(
dev
,
&
wrq
->
u
.
rts
);
err
=
orinoco_ioctl_setrts
(
dev
,
&
wrq
->
u
.
rts
);
if
(
!
err
)
if
(
!
err
)
changed
=
1
;
changed
=
1
;
break
;
break
;
case
SIOCSIWFRAG
:
case
SIOCSIWFRAG
:
DEBUG
(
1
,
"%s: SIOCSIWFRAG
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_setfrag
(
dev
,
&
wrq
->
u
.
frag
);
err
=
orinoco_ioctl_setfrag
(
dev
,
&
wrq
->
u
.
frag
);
if
(
!
err
)
if
(
!
err
)
changed
=
1
;
changed
=
1
;
break
;
break
;
case
SIOCGIWFRAG
:
case
SIOCGIWFRAG
:
DEBUG
(
1
,
"%s: SIOCGIWFRAG
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_getfrag
(
dev
,
&
wrq
->
u
.
frag
);
err
=
orinoco_ioctl_getfrag
(
dev
,
&
wrq
->
u
.
frag
);
break
;
break
;
case
SIOCSIWRATE
:
case
SIOCSIWRATE
:
DEBUG
(
1
,
"%s: SIOCSIWRATE
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_setrate
(
dev
,
&
wrq
->
u
.
bitrate
);
err
=
orinoco_ioctl_setrate
(
dev
,
&
wrq
->
u
.
bitrate
);
if
(
!
err
)
if
(
!
err
)
changed
=
1
;
changed
=
1
;
break
;
break
;
case
SIOCGIWRATE
:
case
SIOCGIWRATE
:
DEBUG
(
1
,
"%s: SIOCGIWRATE
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_getrate
(
dev
,
&
wrq
->
u
.
bitrate
);
err
=
orinoco_ioctl_getrate
(
dev
,
&
wrq
->
u
.
bitrate
);
break
;
break
;
case
SIOCSIWPOWER
:
case
SIOCSIWPOWER
:
DEBUG
(
1
,
"%s: SIOCSIWPOWER
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_setpower
(
dev
,
&
wrq
->
u
.
power
);
err
=
orinoco_ioctl_setpower
(
dev
,
&
wrq
->
u
.
power
);
if
(
!
err
)
if
(
!
err
)
changed
=
1
;
changed
=
1
;
break
;
break
;
case
SIOCGIWPOWER
:
case
SIOCGIWPOWER
:
DEBUG
(
1
,
"%s: SIOCGIWPOWER
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_getpower
(
dev
,
&
wrq
->
u
.
power
);
err
=
orinoco_ioctl_getpower
(
dev
,
&
wrq
->
u
.
power
);
break
;
break
;
case
SIOCGIWTXPOW
:
case
SIOCGIWTXPOW
:
DEBUG
(
1
,
"%s: SIOCGIWTXPOW
\n
"
,
dev
->
name
);
/* The card only supports one tx power, so this is easy */
/* The card only supports one tx power, so this is easy */
wrq
->
u
.
txpower
.
value
=
15
;
/* dBm */
wrq
->
u
.
txpower
.
value
=
15
;
/* dBm */
wrq
->
u
.
txpower
.
fixed
=
1
;
wrq
->
u
.
txpower
.
fixed
=
1
;
...
@@ -3321,30 +3591,23 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
...
@@ -3321,30 +3591,23 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
#if WIRELESS_EXT > 10
#if WIRELESS_EXT > 10
case
SIOCSIWRETRY
:
case
SIOCSIWRETRY
:
DEBUG
(
1
,
"%s: SIOCSIWRETRY
\n
"
,
dev
->
name
);
err
=
-
EOPNOTSUPP
;
err
=
-
EOPNOTSUPP
;
break
;
break
;
case
SIOCGIWRETRY
:
case
SIOCGIWRETRY
:
DEBUG
(
1
,
"%s: SIOCGIWRETRY
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_getretry
(
dev
,
&
wrq
->
u
.
retry
);
err
=
orinoco_ioctl_getretry
(
dev
,
&
wrq
->
u
.
retry
);
break
;
break
;
#endif
/* WIRELESS_EXT > 10 */
#endif
/* WIRELESS_EXT > 10 */
case
SIOCSIWSPY
:
case
SIOCSIWSPY
:
DEBUG
(
1
,
"%s: SIOCSIWSPY
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_setspy
(
dev
,
&
wrq
->
u
.
data
);
err
=
orinoco_ioctl_setspy
(
dev
,
&
wrq
->
u
.
data
);
break
;
break
;
case
SIOCGIWSPY
:
case
SIOCGIWSPY
:
DEBUG
(
1
,
"%s: SIOCGIWSPY
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_getspy
(
dev
,
&
wrq
->
u
.
data
);
err
=
orinoco_ioctl_getspy
(
dev
,
&
wrq
->
u
.
data
);
break
;
break
;
case
SIOCGIWPRIV
:
case
SIOCGIWPRIV
:
DEBUG
(
1
,
"%s: SIOCGIWPRIV
\n
"
,
dev
->
name
);
if
(
wrq
->
u
.
data
.
pointer
)
{
if
(
wrq
->
u
.
data
.
pointer
)
{
struct
iw_priv_args
privtab
[]
=
{
struct
iw_priv_args
privtab
[]
=
{
{
SIOCIWFIRSTPRIV
+
0x0
,
0
,
0
,
"force_reset"
},
{
SIOCIWFIRSTPRIV
+
0x0
,
0
,
0
,
"force_reset"
},
...
@@ -3381,25 +3644,17 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
...
@@ -3381,25 +3644,17 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
case
SIOCIWFIRSTPRIV
+
0x0
:
/* force_reset */
case
SIOCIWFIRSTPRIV
+
0x0
:
/* force_reset */
case
SIOCIWFIRSTPRIV
+
0x1
:
/* card_reset */
case
SIOCIWFIRSTPRIV
+
0x1
:
/* card_reset */
DEBUG
(
1
,
"%s: SIOCIWFIRSTPRIV + 0x0 (force_reset)
\n
"
,
dev
->
name
);
if
(
!
capable
(
CAP_NET_ADMIN
))
{
if
(
!
capable
(
CAP_NET_ADMIN
))
{
err
=
-
EPERM
;
err
=
-
EPERM
;
break
;
break
;
}
}
printk
(
KERN_DEBUG
"%s: Forcing reset!
\n
"
,
dev
->
name
);
printk
(
KERN_DEBUG
"%s: Forc
e schedul
ing reset!
\n
"
,
dev
->
name
);
/* We need the xmit lock because it protects the
schedule_task
(
&
priv
->
timeout_task
);
multicast list which orinoco_reset() reads */
spin_lock_bh
(
&
dev
->
xmit_lock
);
orinoco_reset
(
priv
);
spin_unlock_bh
(
&
dev
->
xmit_lock
);
break
;
break
;
case
SIOCIWFIRSTPRIV
+
0x2
:
/* set_port3 */
case
SIOCIWFIRSTPRIV
+
0x2
:
/* set_port3 */
DEBUG
(
1
,
"%s: SIOCIWFIRSTPRIV + 0x2 (set_port3)
\n
"
,
dev
->
name
);
if
(
!
capable
(
CAP_NET_ADMIN
))
{
if
(
!
capable
(
CAP_NET_ADMIN
))
{
err
=
-
EPERM
;
err
=
-
EPERM
;
break
;
break
;
...
@@ -3411,14 +3666,10 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
...
@@ -3411,14 +3666,10 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break
;
break
;
case
SIOCIWFIRSTPRIV
+
0x3
:
/* get_port3 */
case
SIOCIWFIRSTPRIV
+
0x3
:
/* get_port3 */
DEBUG
(
1
,
"%s: SIOCIWFIRSTPRIV + 0x3 (get_port3)
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_getport3
(
dev
,
wrq
);
err
=
orinoco_ioctl_getport3
(
dev
,
wrq
);
break
;
break
;
case
SIOCIWFIRSTPRIV
+
0x4
:
/* set_preamble */
case
SIOCIWFIRSTPRIV
+
0x4
:
/* set_preamble */
DEBUG
(
1
,
"%s: SIOCIWFIRSTPRIV + 0x4 (set_preamble)
\n
"
,
dev
->
name
);
if
(
!
capable
(
CAP_NET_ADMIN
))
{
if
(
!
capable
(
CAP_NET_ADMIN
))
{
err
=
-
EPERM
;
err
=
-
EPERM
;
break
;
break
;
...
@@ -3432,32 +3683,32 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
...
@@ -3432,32 +3683,32 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if
(
priv
->
has_preamble
)
{
if
(
priv
->
has_preamble
)
{
int
val
=
*
(
(
int
*
)
wrq
->
u
.
name
);
int
val
=
*
(
(
int
*
)
wrq
->
u
.
name
);
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
val
)
if
(
err
)
return
err
;
if
(
val
)
priv
->
preamble
=
1
;
priv
->
preamble
=
1
;
else
else
priv
->
preamble
=
0
;
priv
->
preamble
=
0
;
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
changed
=
1
;
changed
=
1
;
}
else
}
else
err
=
-
EOPNOTSUPP
;
err
=
-
EOPNOTSUPP
;
break
;
break
;
case
SIOCIWFIRSTPRIV
+
0x5
:
/* get_preamble */
case
SIOCIWFIRSTPRIV
+
0x5
:
/* get_preamble */
DEBUG
(
1
,
"%s: SIOCIWFIRSTPRIV + 0x5 (get_preamble)
\n
"
,
dev
->
name
);
if
(
priv
->
has_preamble
)
{
if
(
priv
->
has_preamble
)
{
int
*
val
=
(
int
*
)
wrq
->
u
.
name
;
int
*
val
=
(
int
*
)
wrq
->
u
.
name
;
orinoco_lock
(
priv
);
err
=
orinoco_lock
(
priv
,
&
flags
);
if
(
err
)
return
err
;
*
val
=
priv
->
preamble
;
*
val
=
priv
->
preamble
;
orinoco_unlock
(
priv
);
orinoco_unlock
(
priv
,
&
flags
);
}
else
}
else
err
=
-
EOPNOTSUPP
;
err
=
-
EOPNOTSUPP
;
break
;
break
;
case
SIOCIWFIRSTPRIV
+
0x6
:
/* set_ibssport */
case
SIOCIWFIRSTPRIV
+
0x6
:
/* set_ibssport */
DEBUG
(
1
,
"%s: SIOCIWFIRSTPRIV + 0x6 (set_ibssport)
\n
"
,
dev
->
name
);
if
(
!
capable
(
CAP_NET_ADMIN
))
{
if
(
!
capable
(
CAP_NET_ADMIN
))
{
err
=
-
EPERM
;
err
=
-
EPERM
;
break
;
break
;
...
@@ -3469,8 +3720,6 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
...
@@ -3469,8 +3720,6 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break
;
break
;
case
SIOCIWFIRSTPRIV
+
0x7
:
/* get_ibssport */
case
SIOCIWFIRSTPRIV
+
0x7
:
/* get_ibssport */
DEBUG
(
1
,
"%s: SIOCIWFIRSTPRIV + 0x7 (get_ibssport)
\n
"
,
dev
->
name
);
err
=
orinoco_ioctl_getibssport
(
dev
,
wrq
);
err
=
orinoco_ioctl_getibssport
(
dev
,
wrq
);
break
;
break
;
...
@@ -3480,22 +3729,11 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
...
@@ -3480,22 +3729,11 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
}
if
(
!
err
&&
changed
&&
netif_running
(
dev
))
{
if
(
!
err
&&
changed
&&
netif_running
(
dev
))
{
/* We need the xmit lock because it protects the
err
=
orinoco_reconfigure
(
priv
);
multicast list which orinoco_reset() reads */
spin_lock_bh
(
&
dev
->
xmit_lock
);
err
=
orinoco_reset
(
priv
);
spin_unlock_bh
(
&
dev
->
xmit_lock
);
if
(
err
)
{
/* Ouch ! What are we supposed to do ? */
printk
(
KERN_ERR
"orinoco_cs: Failed to set parameters on %s
\n
"
,
dev
->
name
);
netif_device_detach
(
dev
);
orinoco_shutdown
(
priv
);
}
}
}
TRACE_EXIT
(
dev
->
name
);
TRACE_EXIT
(
dev
->
name
);
return
err
;
return
err
;
}
}
...
@@ -3833,8 +4071,6 @@ orinoco_proc_init(void)
...
@@ -3833,8 +4071,6 @@ orinoco_proc_init(void)
{
{
int
err
=
0
;
int
err
=
0
;
TRACE_ENTER
(
"orinoco"
);
/* create the directory for it to sit in */
/* create the directory for it to sit in */
dir_base
=
create_proc_entry
(
"hermes"
,
S_IFDIR
,
&
proc_root
);
dir_base
=
create_proc_entry
(
"hermes"
,
S_IFDIR
,
&
proc_root
);
if
(
dir_base
==
NULL
)
{
if
(
dir_base
==
NULL
)
{
...
@@ -3843,15 +4079,13 @@ orinoco_proc_init(void)
...
@@ -3843,15 +4079,13 @@ orinoco_proc_init(void)
err
=
-
ENOMEM
;
err
=
-
ENOMEM
;
}
}
TRACE_EXIT
(
"orinoco"
);
return
err
;
return
err
;
}
}
int
int
orinoco_proc_dev_init
(
struct
orinoco_private
*
pri
v
)
orinoco_proc_dev_init
(
struct
net_device
*
de
v
)
{
{
struct
net_device
*
dev
=
priv
->
nde
v
;
struct
orinoco_private
*
priv
=
dev
->
pri
v
;
struct
proc_dir_entry
*
e
;
struct
proc_dir_entry
*
e
;
priv
->
dir_dev
=
NULL
;
priv
->
dir_dev
=
NULL
;
...
@@ -3889,16 +4123,14 @@ orinoco_proc_dev_init(struct orinoco_private *priv)
...
@@ -3889,16 +4123,14 @@ orinoco_proc_dev_init(struct orinoco_private *priv)
return
0
;
return
0
;
fail:
fail:
orinoco_proc_dev_cleanup
(
pri
v
);
orinoco_proc_dev_cleanup
(
de
v
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
void
void
orinoco_proc_dev_cleanup
(
struct
orinoco_private
*
pri
v
)
orinoco_proc_dev_cleanup
(
struct
net_device
*
de
v
)
{
{
struct
net_device
*
dev
=
priv
->
ndev
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
TRACE_ENTER
(
priv
->
ndev
->
name
);
if
(
priv
->
dir_dev
)
{
if
(
priv
->
dir_dev
)
{
remove_proc_entry
(
"prof"
,
priv
->
dir_dev
);
remove_proc_entry
(
"prof"
,
priv
->
dir_dev
);
...
@@ -3907,29 +4139,22 @@ orinoco_proc_dev_cleanup(struct orinoco_private *priv)
...
@@ -3907,29 +4139,22 @@ orinoco_proc_dev_cleanup(struct orinoco_private *priv)
remove_proc_entry
(
dev
->
name
,
dir_base
);
remove_proc_entry
(
dev
->
name
,
dir_base
);
priv
->
dir_dev
=
NULL
;
priv
->
dir_dev
=
NULL
;
}
}
TRACE_EXIT
(
priv
->
ndev
->
name
);
}
}
static
void
static
void
orinoco_proc_cleanup
(
void
)
orinoco_proc_cleanup
(
void
)
{
{
TRACE_ENTER
(
"orinoco"
);
if
(
dir_base
)
{
if
(
dir_base
)
{
remove_proc_entry
(
"hermes"
,
&
proc_root
);
remove_proc_entry
(
"hermes"
,
&
proc_root
);
dir_base
=
NULL
;
dir_base
=
NULL
;
}
}
TRACE_EXIT
(
"orinoco"
);
}
}
struct
net_device
*
alloc_orinocodev
(
int
sizeof_card
)
struct
net_device
*
alloc_orinocodev
(
int
sizeof_card
,
int
(
*
hard_reset
)(
struct
orinoco_private
*
)
)
{
{
struct
net_device
*
dev
;
struct
net_device
*
dev
;
struct
orinoco_private
*
priv
;
struct
orinoco_private
*
priv
;
TRACE_ENTER
(
"orinoco"
);
dev
=
alloc_etherdev
(
sizeof
(
struct
orinoco_private
)
+
sizeof_card
);
dev
=
alloc_etherdev
(
sizeof
(
struct
orinoco_private
)
+
sizeof_card
);
priv
=
(
struct
orinoco_private
*
)
dev
->
priv
;
priv
=
(
struct
orinoco_private
*
)
dev
->
priv
;
priv
->
ndev
=
dev
;
priv
->
ndev
=
dev
;
...
@@ -3949,30 +4174,40 @@ struct net_device *alloc_orinocodev(int sizeof_card)
...
@@ -3949,30 +4174,40 @@ struct net_device *alloc_orinocodev(int sizeof_card)
dev
->
change_mtu
=
orinoco_change_mtu
;
dev
->
change_mtu
=
orinoco_change_mtu
;
dev
->
set_multicast_list
=
orinoco_set_multicast_list
;
dev
->
set_multicast_list
=
orinoco_set_multicast_list
;
dev
->
open
=
NULL
;
/* Caller *must* override these
*/
/* Set up default callbacks
*/
dev
->
stop
=
NULL
;
dev
->
open
=
orinoco_open
;
dev
->
stop
=
orinoco_stop
;
/* Setup the private structure */
priv
->
hard_reset
=
hard_reset
;
spin_lock_init
(
&
priv
->
lock
);
spin_lock_init
(
&
priv
->
lock
);
priv
->
hard_reset
=
NULL
;
/* Caller may override */
priv
->
open
=
0
;
priv
->
hw_unavailable
=
1
;
/* orinoco_init() must clear this
TRACE_EXIT
(
"orinoco"
);
* before anything else touches the
* hardware */
INIT_TQUEUE
(
&
priv
->
timeout_task
,
(
void
(
*
)(
void
*
))
orinoco_reset
,
dev
);
return
dev
;
return
dev
;
}
}
/********************************************************************/
/********************************************************************/
/*
module bookkeeping
*/
/*
Module initialization
*/
/********************************************************************/
/********************************************************************/
EXPORT_SYMBOL
(
alloc_orinocodev
);
EXPORT_SYMBOL
(
alloc_orinocodev
);
EXPORT_SYMBOL
(
orinoco_shutdown
);
EXPORT_SYMBOL
(
orinoco_reset
);
EXPORT_SYMBOL
(
__orinoco_up
);
EXPORT_SYMBOL
(
__orinoco_down
);
EXPORT_SYMBOL
(
orinoco_reinit_firmware
);
EXPORT_SYMBOL
(
orinoco_proc_dev_init
);
EXPORT_SYMBOL
(
orinoco_proc_dev_init
);
EXPORT_SYMBOL
(
orinoco_proc_dev_cleanup
);
EXPORT_SYMBOL
(
orinoco_proc_dev_cleanup
);
EXPORT_SYMBOL
(
orinoco_interrupt
);
EXPORT_SYMBOL
(
orinoco_interrupt
);
/* Can't be declared "const" or the whole __initdata section will
* become const */
static
char
version
[]
__initdata
=
"orinoco.c 0.13 (David Gibson <hermes@gibson.dropbear.id.au> and others)"
;
static
int
__init
init_orinoco
(
void
)
static
int
__init
init_orinoco
(
void
)
{
{
printk
(
KERN_DEBUG
"%s
\n
"
,
version
);
printk
(
KERN_DEBUG
"%s
\n
"
,
version
);
...
...
drivers/net/wireless/orinoco.h
View file @
5bb7978a
...
@@ -7,6 +7,8 @@
...
@@ -7,6 +7,8 @@
#ifndef _ORINOCO_H
#ifndef _ORINOCO_H
#define _ORINOCO_H
#define _ORINOCO_H
#include "hermes.h"
/* To enable debug messages */
/* To enable debug messages */
//#define ORINOCO_DEBUG 3
//#define ORINOCO_DEBUG 3
...
@@ -18,24 +20,26 @@
...
@@ -18,24 +20,26 @@
#define ORINOCO_MAX_KEY_SIZE 14
#define ORINOCO_MAX_KEY_SIZE 14
#define ORINOCO_MAX_KEYS 4
#define ORINOCO_MAX_KEYS 4
typedef
struct
orinoco_key
{
struct
orinoco_key
{
u16
len
;
/* always store little-endian */
u16
len
;
/* always store
d as
little-endian */
char
data
[
ORINOCO_MAX_KEY_SIZE
];
char
data
[
ORINOCO_MAX_KEY_SIZE
];
}
__attribute__
((
packed
))
orinoco_key_t
;
}
__attribute__
((
packed
));
typedef
orinoco_key_t
orinoco_keys_t
[
ORINOCO_MAX_KEYS
];
#define ORINOCO_INTEN ( HERMES_EV_RX | HERMES_EV_ALLOC | HERMES_EV_TX | \
HERMES_EV_TXEXC | HERMES_EV_WTERR | HERMES_EV_INFO | \
HERMES_EV_INFDROP )
/*====================================================================*/
struct
orinoco_private
{
struct
orinoco_private
{
void
*
card
;
/* Pointer to card dependant structure */
void
*
card
;
/* Pointer to card dependant structure */
/* card dependant extra reset code (i.e. bus/interface specific */
int
(
*
hard_reset
)(
struct
orinoco_private
*
);
int
(
*
hard_reset
)(
struct
orinoco_private
*
);
/* Synchronisation stuff */
spinlock_t
lock
;
spinlock_t
lock
;
long
state
;
int
hw_unavailable
;
#define ORINOCO_STATE_INIRQ 0
struct
tq_struct
timeout_task
;
#define ORINOCO_STATE_DOIRQ 1
int
open
;
/* Net device stuff */
/* Net device stuff */
struct
net_device
*
ndev
;
struct
net_device
*
ndev
;
...
@@ -58,14 +62,13 @@ struct orinoco_private {
...
@@ -58,14 +62,13 @@ struct orinoco_private {
int
has_preamble
;
int
has_preamble
;
int
has_sensitivity
;
int
has_sensitivity
;
int
nicbuf_size
;
int
nicbuf_size
;
int
broken_cor_reset
;
u16
channel_mask
;
u16
channel_mask
;
/* Configuration paramaters */
/* Configuration paramaters */
u32
iw_mode
;
u32
iw_mode
;
int
prefer_port3
;
int
prefer_port3
;
u16
wep_on
,
wep_restrict
,
tx_key
;
u16
wep_on
,
wep_restrict
,
tx_key
;
orinoco_keys_t
keys
;
struct
orinoco_key
keys
[
ORINOCO_MAX_KEYS
]
;
int
bitratemode
;
int
bitratemode
;
char
nick
[
IW_ESSID_MAX_SIZE
+
1
];
char
nick
[
IW_ESSID_MAX_SIZE
+
1
];
char
desired_essid
[
IW_ESSID_MAX_SIZE
+
1
];
char
desired_essid
[
IW_ESSID_MAX_SIZE
+
1
];
...
@@ -81,38 +84,58 @@ struct orinoco_private {
...
@@ -81,38 +84,58 @@ struct orinoco_private {
#endif
#endif
/* Configuration dependent variables */
/* Configuration dependent variables */
int
port_type
,
allow_
ibss
;
int
port_type
,
create
ibss
;
int
promiscuous
,
mc_count
;
int
promiscuous
,
mc_count
;
/* /proc based debugging stuff */
/* /proc based debugging stuff */
struct
proc_dir_entry
*
dir_dev
;
struct
proc_dir_entry
*
dir_dev
;
};
};
/*====================================================================*/
extern
struct
list_head
orinoco_instances
;
#ifdef ORINOCO_DEBUG
#ifdef ORINOCO_DEBUG
extern
int
orinoco_debug
;
extern
int
orinoco_debug
;
#define DEBUG(n, args...) do { if (orinoco_debug>(n)) printk(KERN_DEBUG args); } while(0)
#define DEBUG(n, args...) do { if (orinoco_debug>(n)) printk(KERN_DEBUG args); } while(0)
#define DEBUGMORE(n, args...) do { if (orinoco_debug>(n)) printk(args); } while (0)
#else
#else
#define DEBUG(n, args...) do { } while (0)
#define DEBUG(n, args...) do { } while (0)
#define DEBUGMORE(n, args...) do { } while (0)
#endif
/* ORINOCO_DEBUG */
#endif
/* ORINOCO_DEBUG */
#define TRACE_ENTER(devname) DEBUG(2, "%s: -> " __FUNCTION__ "()\n", devname);
#define TRACE_ENTER(devname) DEBUG(2, "%s: -> " __FUNCTION__ "()\n", devname);
#define TRACE_EXIT(devname) DEBUG(2, "%s: <- " __FUNCTION__ "()\n", devname);
#define TRACE_EXIT(devname) DEBUG(2, "%s: <- " __FUNCTION__ "()\n", devname);
#define RUP_EVEN(a) ( (a) % 2 ? (a) + 1 : (a) )
extern
struct
net_device
*
alloc_orinocodev
(
int
sizeof_card
,
int
(
*
hard_reset
)(
struct
orinoco_private
*
));
extern
int
__orinoco_up
(
struct
net_device
*
dev
);
extern
int
__orinoco_down
(
struct
net_device
*
dev
);
int
orinoco_reinit_firmware
(
struct
net_device
*
dev
);
/* utility routines */
extern
int
orinoco_proc_dev_init
(
struct
net_device
*
dev
);
struct
net_device
*
alloc_orinocodev
(
int
sizeof_card
);
extern
void
orinoco_proc_dev_cleanup
(
struct
net_device
*
dev
);
extern
void
orinoco_shutdown
(
struct
orinoco_private
*
dev
);
extern
int
orinoco_reset
(
struct
orinoco_private
*
dev
);
extern
int
orinoco_proc_dev_init
(
struct
orinoco_private
*
dev
);
extern
void
orinoco_proc_dev_cleanup
(
struct
orinoco_private
*
priv
);
extern
void
orinoco_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
extern
void
orinoco_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
/********************************************************************/
/* Locking and synchronization functions */
/********************************************************************/
/* These functions *must* be inline or they will break horribly on
* SPARC, due to its weird semantics for save/restore flags. extern
* inline should prevent the kernel from linking or module from
* loading if they are not inlined. */
extern
inline
int
orinoco_lock
(
struct
orinoco_private
*
priv
,
unsigned
long
*
flags
)
{
spin_lock_irqsave
(
&
priv
->
lock
,
*
flags
);
if
(
priv
->
hw_unavailable
)
{
printk
(
KERN_DEBUG
"orinoco_lock() called with hw_unavailable (dev=%p)
\n
"
,
priv
->
ndev
);
spin_unlock_irqrestore
(
&
priv
->
lock
,
*
flags
);
return
-
EBUSY
;
}
return
0
;
}
extern
inline
void
orinoco_unlock
(
struct
orinoco_private
*
priv
,
unsigned
long
*
flags
)
{
spin_unlock_irqrestore
(
&
priv
->
lock
,
*
flags
);
}
#endif
/* _ORINOCO_H */
#endif
/* _ORINOCO_H */
drivers/net/wireless/orinoco_cs.c
View file @
5bb7978a
/* orinoco_cs.c 0.1
1b
- (formerly known as dldwd_cs.c)
/* orinoco_cs.c 0.1
3
- (formerly known as dldwd_cs.c)
*
*
* A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
* A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
* as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
* as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
...
@@ -32,7 +32,6 @@
...
@@ -32,7 +32,6 @@
#include <linux/if_arp.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/etherdevice.h>
#include <linux/wireless.h>
#include <linux/wireless.h>
#include <linux/list.h>
#include <pcmcia/version.h>
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs_types.h>
...
@@ -42,12 +41,11 @@
...
@@ -42,12 +41,11 @@
#include <pcmcia/ds.h>
#include <pcmcia/ds.h>
#include <pcmcia/bus_ops.h>
#include <pcmcia/bus_ops.h>
#include "hermes.h"
#include "orinoco.h"
#include "orinoco.h"
/*
====================================================================
*/
/*
******************************************************************
*/
/* Module stuff */
static
char
version
[]
__initdata
=
"orinoco_cs.c 0.11b (David Gibson <hermes@gibson.dropbear.id.au> and others)"
;
/********************************************************************/
MODULE_AUTHOR
(
"David Gibson <hermes@gibson.dropbear.id.au>"
);
MODULE_AUTHOR
(
"David Gibson <hermes@gibson.dropbear.id.au>"
);
MODULE_DESCRIPTION
(
"Driver for PCMCIA Lucent Orinoco, Prism II based and similar wireless cards"
);
MODULE_DESCRIPTION
(
"Driver for PCMCIA Lucent Orinoco, Prism II based and similar wireless cards"
);
...
@@ -55,235 +53,131 @@ MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco, Prism II based and similar
...
@@ -55,235 +53,131 @@ MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco, Prism II based and similar
MODULE_LICENSE
(
"Dual MPL/GPL"
);
MODULE_LICENSE
(
"Dual MPL/GPL"
);
#endif
#endif
/*
Parameters that can be set with 'insmod'
*/
/*
Module parameters
*/
/* The old way: bit map of interrupts to choose from */
/* The old way: bit map of interrupts to choose from */
/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
static
uint
irq_mask
=
0xdeb8
;
static
uint
irq_mask
=
0xdeb8
;
/* Newer, simpler way of listing specific interrupts */
/* Newer, simpler way of listing specific interrupts */
static
int
irq_list
[
4
]
=
{
-
1
};
static
int
irq_list
[
4
]
=
{
-
1
};
/* Do a Pcmcia soft reset (may help some cards) */
static
int
reset_cor
=
-
1
;
/* Some D-Link cards have buggy CIS. They do work at 5v properly, but
/* Some D-Link cards have buggy CIS. They do work at 5v properly, but
* don't have any CIS entry for it. This workaround it... */
* don't have any CIS entry for it. This workaround it... */
static
int
ignore_cis_vcc
;
/* = 0 */
static
int
ignore_cis_vcc
;
/* = 0 */
MODULE_PARM
(
irq_mask
,
"i"
);
MODULE_PARM
(
irq_mask
,
"i"
);
MODULE_PARM
(
irq_list
,
"1-4i"
);
MODULE_PARM
(
irq_list
,
"1-4i"
);
MODULE_PARM
(
reset_cor
,
"i"
);
MODULE_PARM
(
ignore_cis_vcc
,
"i"
);
MODULE_PARM
(
ignore_cis_vcc
,
"i"
);
/* Pcmcia specific structure */
/********************************************************************/
/* Magic constants */
/********************************************************************/
/*
* The dev_info variable is the "key" that is used to match up this
* device driver with appropriate cards, through the card
* configuration database.
*/
static
dev_info_t
dev_info
=
"orinoco_cs"
;
/********************************************************************/
/* Data structures */
/********************************************************************/
/* PCMCIA specific device information (goes in the card field of
* struct orinoco_private */
struct
orinoco_pccard
{
struct
orinoco_pccard
{
dev_link_t
link
;
dev_link_t
link
;
dev_node_t
node
;
dev_node_t
node
;
/* Used to handle hard reset */
wait_queue_head_t
hard_reset_queue
;
int
hard_reset_flag
;
};
};
/*
/*
* Function prototypes
* A linked list of "instances" of the device. Each actual PCMCIA
* card corresponds to one device instance, and is described by one
* dev_link_t structure (defined in ds.h).
*/
*/
static
dev_link_t
*
dev_list
;
/* = NULL */
/* struct net_device methods */
/********************************************************************/
static
int
orinoco_cs_open
(
struct
net_device
*
dev
);
/* Function prototypes */
static
int
orinoco_cs_stop
(
struct
net_device
*
dev
);
/********************************************************************/
/* device methods */
static
int
orinoco_cs_hard_reset
(
struct
orinoco_private
*
priv
);
/* PCMCIA gumpf */
/* PCMCIA gumpf */
static
void
orinoco_cs_config
(
dev_link_t
*
link
);
static
void
orinoco_cs_config
(
dev_link_t
*
link
);
static
void
orinoco_cs_release
(
u_long
arg
);
static
void
orinoco_cs_release
(
u_long
arg
);
static
int
orinoco_cs_event
(
event_t
event
,
int
priority
,
static
int
orinoco_cs_event
(
event_t
event
,
int
priority
,
event_callback_args_t
*
args
);
event_callback_args_t
*
args
);
static
dev_link_t
*
orinoco_cs_attach
(
void
);
static
dev_link_t
*
orinoco_cs_attach
(
void
);
static
void
orinoco_cs_detach
(
dev_link_t
*
);
static
void
orinoco_cs_detach
(
dev_link_t
*
);
/*
/********************************************************************/
The dev_info variable is the "key" that is used to match up this
/* Device methods */
device driver with appropriate cards, through the card configuration
/********************************************************************/
database.
*/
static
dev_info_t
dev_info
=
"orinoco_cs"
;
/*
A linked list of "instances" of the dummy device. Each actual
PCMCIA card corresponds to one device instance, and is described
by one dev_link_t structure (defined in ds.h).
You may not want to use a linked list for this -- for example, the
memory card driver uses an array of dev_link_t pointers, where minor
device numbers are used to derive the corresponding array index.
*/
static
dev_link_t
*
dev_list
;
/* = NULL */
/*====================================================================*/
static
void
cs_error
(
client_handle_t
handle
,
int
func
,
int
ret
)
{
error_info_t
err
=
{
func
,
ret
};
CardServices
(
ReportError
,
handle
,
&
err
);
}
static
int
static
int
orinoco_cs_
open
(
struct
net_device
*
de
v
)
orinoco_cs_
hard_reset
(
struct
orinoco_private
*
pri
v
)
{
{
struct
orinoco_private
*
priv
=
(
struct
orinoco_private
*
)
dev
->
priv
;
struct
orinoco_pccard
*
card
=
priv
->
card
;
struct
orinoco_pccard
*
card
=
(
struct
orinoco_pccard
*
)
priv
->
card
;
dev_link_t
*
link
=
&
card
->
link
;
dev_link_t
*
link
=
&
card
->
link
;
int
err
;
int
err
;
TRACE_ENTER
(
dev
->
name
);
link
->
open
++
;
card
->
hard_reset_flag
=
0
;
netif_device_attach
(
dev
);
err
=
orinoco_reset
(
priv
);
if
(
err
)
orinoco_cs_stop
(
dev
);
else
netif_start_queue
(
dev
);
TRACE_EXIT
(
dev
->
name
);
return
err
;
err
=
CardServices
(
ResetCard
,
link
->
handle
,
NULL
);
}
if
(
err
)
return
err
;
static
int
orinoco_cs_stop
(
struct
net_device
*
dev
)
{
struct
orinoco_private
*
priv
=
(
struct
orinoco_private
*
)
dev
->
priv
;
struct
orinoco_pccard
*
card
=
(
struct
orinoco_pccard
*
)
priv
->
card
;
dev_link_t
*
link
=
&
card
->
link
;
TRACE_ENTER
(
dev
->
name
);
netif_stop_queue
(
dev
);
wait_event_interruptible
(
card
->
hard_reset_queue
,
card
->
hard_reset_flag
);
orinoco_shutdown
(
priv
);
link
->
open
--
;
if
(
link
->
state
&
DEV_STALE_CONFIG
)
mod_timer
(
&
link
->
release
,
jiffies
+
HZ
/
20
);
TRACE_EXIT
(
dev
->
name
);
return
0
;
return
0
;
}
}
/*
/********************************************************************/
* Do a soft reset of the Pcmcia card using the Configuration Option Register
/* PCMCIA stuff */
* Can't do any harm, and actually may do some good on some cards...
/********************************************************************/
* In fact, this seem necessary for Spectrum cards...
*/
static
int
orinoco_cs_cor_reset
(
struct
orinoco_private
*
priv
)
{
struct
orinoco_pccard
*
card
=
(
struct
orinoco_pccard
*
)
priv
->
card
;
dev_link_t
*
link
=
&
card
->
link
;
conf_reg_t
reg
;
u_int
default_cor
;
TRACE_ENTER
(
priv
->
ndev
->
name
);
/* Doing it if hardware is gone is guaranteed crash */
if
(
!
(
link
->
state
&
DEV_CONFIG
)
)
return
-
ENODEV
;
/* Save original COR value */
reg
.
Function
=
0
;
reg
.
Action
=
CS_READ
;
reg
.
Offset
=
CISREG_COR
;
reg
.
Value
=
0
;
CardServices
(
AccessConfigurationRegister
,
link
->
handle
,
&
reg
);
default_cor
=
reg
.
Value
;
DEBUG
(
2
,
"orinoco : orinoco_cs_cor_reset() : cor=0x%X
\n
"
,
default_cor
);
/* Soft-Reset card */
reg
.
Action
=
CS_WRITE
;
reg
.
Offset
=
CISREG_COR
;
reg
.
Value
=
(
default_cor
|
COR_SOFT_RESET
);
CardServices
(
AccessConfigurationRegister
,
link
->
handle
,
&
reg
);
/* Wait until the card has acknowledged our reset */
/* FIXME: mdelay() is deprecated -dgibson */
mdelay
(
1
);
#if 0 /* This seems to help on Symbol cards, but we're not sure why,
and we don't know what it will do to other cards */
reg.Action = CS_READ;
reg.Offset = CISREG_CCSR;
CardServices(AccessConfigurationRegister, link->handle, ®);
/* Write 7 (RUN) to CCSR, but preserve the original bit 4 */
reg.Action = CS_WRITE;
reg.Offset = CISREG_CCSR;
reg.Value = 7 | (reg.Value & 0x10);
CardServices(AccessConfigurationRegister, link->handle, ®);
mdelay(1);
#endif
/* Restore original COR configuration index */
reg
.
Action
=
CS_WRITE
;
reg
.
Offset
=
CISREG_COR
;
reg
.
Value
=
(
default_cor
&
~
COR_SOFT_RESET
);
CardServices
(
AccessConfigurationRegister
,
link
->
handle
,
&
reg
);
/* Wait until the card has finished restarting */
/* FIXME: mdelay() is deprecated -dgibson */
mdelay
(
1
);
TRACE_EXIT
(
priv
->
ndev
->
name
);
return
0
;
static
void
}
cs_error
(
client_handle_t
handle
,
int
func
,
int
ret
)
static
int
orinoco_cs_hard_reset
(
struct
orinoco_private
*
priv
)
{
{
if
(
!
priv
->
broken_cor_reset
)
error_info_t
err
=
{
func
,
ret
};
return
orinoco_cs_cor_reset
(
priv
);
CardServices
(
ReportError
,
handle
,
&
err
);
else
return
0
;
#if 0 /* We'd like to use ResetCard, but we can't for the moment - it sleeps */
/* Not sure what the second parameter is supposed to be - the
PCMCIA code doesn't actually use it */
if (in_interrupt()) {
printk("Not resetting card, in_interrupt() is true\n");
return 0;
} else {
printk("Doing ResetCard\n");
return CardServices(ResetCard, link->handle, NULL);
}
#endif
}
}
/* Remove zombie instances (card removed, detach pending) */
/* Remove zombie instances (card removed, detach pending) */
static
void
static
void
flush_stale_links
(
void
)
flush_stale_links
(
void
)
{
{
dev_link_t
*
link
,
*
next
;
dev_link_t
*
link
,
*
next
;
TRACE_ENTER
(
"orinoco"
);
TRACE_ENTER
(
""
);
for
(
link
=
dev_list
;
link
;
link
=
next
)
{
for
(
link
=
dev_list
;
link
;
link
=
next
)
{
next
=
link
->
next
;
next
=
link
->
next
;
if
(
link
->
state
&
DEV_STALE_LINK
)
if
(
link
->
state
&
DEV_STALE_LINK
)
{
orinoco_cs_detach
(
link
);
orinoco_cs_detach
(
link
);
}
}
}
TRACE_EXIT
(
"
orinoco
"
);
TRACE_EXIT
(
""
);
}
}
/*======================================================================
/*
orinoco_cs_attach() creates an "instance" of the driver, allocating
* This creates an "instance" of the driver, allocating local data
local data structures for one device. The device is registered
* structures for one device. The device is registered with Card
with Card Services.
* Services.
*
The dev_link structure is initialized, but we don't actually
* The dev_link structure is initialized, but we don't actually
configure the card at this point -- we wait until we receive a
* configure the card at this point -- we wait until we receive a card
card insertion event.
* insertion event. */
======================================================================*/
static
dev_link_t
*
static
dev_link_t
*
orinoco_cs_attach
(
void
)
orinoco_cs_attach
(
void
)
{
{
...
@@ -294,23 +188,19 @@ orinoco_cs_attach(void)
...
@@ -294,23 +188,19 @@ orinoco_cs_attach(void)
client_reg_t
client_reg
;
client_reg_t
client_reg
;
int
ret
,
i
;
int
ret
,
i
;
TRACE_ENTER
(
"orinoco"
);
/* A bit of cleanup */
/* A bit of cleanup */
flush_stale_links
();
flush_stale_links
();
dev
=
alloc_orinocodev
(
sizeof
(
*
card
));
dev
=
alloc_orinocodev
(
sizeof
(
*
card
)
,
orinoco_cs_hard_reset
);
if
(
!
dev
)
if
(
!
dev
)
return
NULL
;
return
NULL
;
priv
=
dev
->
priv
;
priv
=
dev
->
priv
;
card
=
priv
->
card
;
card
=
priv
->
card
;
/* Overrides */
init_waitqueue_head
(
&
card
->
hard_reset_queue
);
dev
->
open
=
orinoco_cs_open
;
dev
->
stop
=
orinoco_cs_stop
;
priv
->
hard_reset
=
orinoco_cs_hard_reset
;
/* Link both structures together */
/* Link both structures together */
link
=
&
card
->
link
;
link
=
&
card
->
link
;
link
->
priv
=
pri
v
;
link
->
priv
=
de
v
;
/* Initialize the dev_link_t structure */
/* Initialize the dev_link_t structure */
link
->
release
.
function
=
&
orinoco_cs_release
;
link
->
release
.
function
=
&
orinoco_cs_release
;
...
@@ -326,63 +216,59 @@ orinoco_cs_attach(void)
...
@@ -326,63 +216,59 @@ orinoco_cs_attach(void)
link
->
irq
.
IRQInfo2
|=
1
<<
irq_list
[
i
];
link
->
irq
.
IRQInfo2
|=
1
<<
irq_list
[
i
];
link
->
irq
.
Handler
=
NULL
;
link
->
irq
.
Handler
=
NULL
;
/*
/* General socket configuration defaults can go here. In this
General socket configuration defaults can go here. In this
* client, we assume very little, and rely on the CIS for
client, we assume very little, and rely on the CIS for almost
* almost everything. In most clients, many details (i.e.,
everything. In most clients, many details (i.e., number, sizes,
* number, sizes, and attributes of IO windows) are fixed by
and attributes of IO windows) are fixed by the nature of the
* the nature of the device, and can be hard-wired here. */
device, and can be hard-wired here.
*/
link
->
conf
.
Attributes
=
0
;
link
->
conf
.
Attributes
=
0
;
link
->
conf
.
IntType
=
INT_MEMORY_AND_IO
;
link
->
conf
.
IntType
=
INT_MEMORY_AND_IO
;
/* Register with Card Services */
/* Register with Card Services */
/* FIXME: need a lock? */
link
->
next
=
dev_list
;
link
->
next
=
dev_list
;
dev_list
=
link
;
dev_list
=
link
;
client_reg
.
dev_info
=
&
dev_info
;
client_reg
.
dev_info
=
&
dev_info
;
client_reg
.
Attributes
=
INFO_IO_CLIENT
|
INFO_CARD_SHARE
;
client_reg
.
Attributes
=
INFO_IO_CLIENT
|
INFO_CARD_SHARE
;
client_reg
.
EventMask
=
client_reg
.
EventMask
=
CS_EVENT_CARD_INSERTION
|
CS_EVENT_CARD_REMOVAL
|
CS_EVENT_CARD_INSERTION
|
CS_EVENT_CARD_REMOVAL
|
CS_EVENT_RESET_PHYSICAL
|
CS_EVENT_CARD_RESET
|
CS_EVENT_RESET_PHYSICAL
|
CS_EVENT_CARD_RESET
|
CS_EVENT_PM_SUSPEND
|
CS_EVENT_PM_RESUME
;
CS_EVENT_PM_SUSPEND
|
CS_EVENT_PM_RESUME
;
client_reg
.
event_handler
=
&
orinoco_cs_event
;
client_reg
.
event_handler
=
&
orinoco_cs_event
;
client_reg
.
Version
=
0x0210
;
client_reg
.
Version
=
0x0210
;
/* FIXME: what does this mean? */
client_reg
.
event_callback_args
.
client_data
=
link
;
client_reg
.
event_callback_args
.
client_data
=
link
;
ret
=
CardServices
(
RegisterClient
,
&
link
->
handle
,
&
client_reg
);
ret
=
CardServices
(
RegisterClient
,
&
link
->
handle
,
&
client_reg
);
if
(
ret
!=
CS_SUCCESS
)
{
if
(
ret
!=
CS_SUCCESS
)
{
cs_error
(
link
->
handle
,
RegisterClient
,
ret
);
cs_error
(
link
->
handle
,
RegisterClient
,
ret
);
orinoco_cs_detach
(
link
);
orinoco_cs_detach
(
link
);
link
=
NULL
;
return
NULL
;
goto
out
;
}
}
out:
TRACE_EXIT
(
"orinoco"
);
return
link
;
return
link
;
}
/* orinoco_cs_attach */
}
/* orinoco_cs_attach */
/*======================================================================
/*
This deletes a driver "instance". The device is de-registered
* This deletes a driver "instance". The device is de-registered with
with Card Services. If it has been released, all local data
* Card Services. If it has been released, all local data structures
structures are freed. Otherwise, the structures will be freed
* are freed. Otherwise, the structures will be freed when the device
when the device is released.
* is released.
======================================================================*/
*/
static
void
static
void
orinoco_cs_detach
(
dev_link_t
*
link
)
orinoco_cs_detach
(
dev_link_t
*
link
)
{
{
dev_link_t
**
linkp
;
dev_link_t
**
linkp
;
struct
orinoco_private
*
priv
=
link
->
priv
;
struct
net_device
*
dev
=
link
->
priv
;
struct
net_device
*
dev
=
priv
->
ndev
;
TRACE_ENTER
(
"orinoco"
);
/* Locate device structure */
/* Locate device structure */
for
(
linkp
=
&
dev_list
;
*
linkp
;
linkp
=
&
(
*
linkp
)
->
next
)
for
(
linkp
=
&
dev_list
;
*
linkp
;
linkp
=
&
(
*
linkp
)
->
next
)
if
(
*
linkp
==
link
)
if
(
*
linkp
==
link
)
break
;
break
;
if
(
*
linkp
==
NULL
)
if
(
*
linkp
==
NULL
)
{
goto
out
;
BUG
();
return
;
}
/*
/*
If the device is currently configured and active, we won't
If the device is currently configured and active, we won't
...
@@ -396,7 +282,7 @@ orinoco_cs_detach(dev_link_t * link)
...
@@ -396,7 +282,7 @@ orinoco_cs_detach(dev_link_t * link)
"still locked
\n
"
,
link
->
dev
->
dev_name
);
"still locked
\n
"
,
link
->
dev
->
dev_name
);
#endif
#endif
link
->
state
|=
DEV_STALE_LINK
;
link
->
state
|=
DEV_STALE_LINK
;
goto
out
;
return
;
}
}
/* Break the link with Card Services */
/* Break the link with Card Services */
...
@@ -408,50 +294,44 @@ orinoco_cs_detach(dev_link_t * link)
...
@@ -408,50 +294,44 @@ orinoco_cs_detach(dev_link_t * link)
DEBUG
(
0
,
"orinoco_cs: detach: link=%p link->dev=%p
\n
"
,
link
,
link
->
dev
);
DEBUG
(
0
,
"orinoco_cs: detach: link=%p link->dev=%p
\n
"
,
link
,
link
->
dev
);
if
(
link
->
dev
)
{
if
(
link
->
dev
)
{
DEBUG
(
0
,
"orinoco_cs: About to unregister net device %p
\n
"
,
DEBUG
(
0
,
"orinoco_cs: About to unregister net device %p
\n
"
,
priv
->
n
dev
);
dev
);
unregister_netdev
(
dev
);
unregister_netdev
(
dev
);
}
}
kfree
(
dev
);
kfree
(
dev
);
out:
TRACE_EXIT
(
"orinoco"
);
}
/* orinoco_cs_detach */
}
/* orinoco_cs_detach */
/*
======================================================================
/*
orinoco_cs_config() is scheduled to run after a CARD_INSERTION event
* orinoco_cs_config() is scheduled to run after a CARD_INSERTION
is received, to configure the PCMCIA socket, and to make the
* event
is received, to configure the PCMCIA socket, and to make the
device available to the system.
*
device available to the system.
======================================================================
*/
*/
#define CS_CHECK(fn, args...) \
#define CS_CHECK(fn, args...) \
while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed
while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed
#define CFG_CHECK(fn, args...) \
#define CFG_CHECK(fn, args...) \
if (CardServices(fn, args) != 0) goto next_entry
if (CardServices(fn, args) != 0) goto next_entry
static
void
static
void
orinoco_cs_config
(
dev_link_t
*
link
)
orinoco_cs_config
(
dev_link_t
*
link
)
{
{
struct
net_device
*
dev
=
link
->
priv
;
client_handle_t
handle
=
link
->
handle
;
client_handle_t
handle
=
link
->
handle
;
struct
orinoco_private
*
priv
=
link
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_pccard
*
card
=
(
struct
orinoco_pccard
*
)
priv
->
card
;
struct
orinoco_pccard
*
card
=
priv
->
card
;
hermes_t
*
hw
=
&
priv
->
hw
;
hermes_t
*
hw
=
&
priv
->
hw
;
struct
net_device
*
ndev
=
priv
->
ndev
;
tuple_t
tuple
;
cisparse_t
parse
;
int
last_fn
,
last_ret
;
int
last_fn
,
last_ret
;
u_char
buf
[
64
];
u_char
buf
[
64
];
config_info_t
conf
;
config_info_t
conf
;
cistpl_cftable_entry_t
dflt
=
{
0
};
cisinfo_t
info
;
cisinfo_t
info
;
tuple_t
tuple
;
TRACE_ENTER
(
"orinoco"
)
;
cisparse_t
parse
;
CS_CHECK
(
ValidateCIS
,
handle
,
&
info
);
CS_CHECK
(
ValidateCIS
,
handle
,
&
info
);
/*
/*
This reads the card's CONFIG tuple to find its configuration
* This reads the card's CONFIG tuple to find its
registers.
* configuration
registers.
*/
*/
tuple
.
DesiredTuple
=
CISTPL_CONFIG
;
tuple
.
DesiredTuple
=
CISTPL_CONFIG
;
tuple
.
Attributes
=
0
;
tuple
.
Attributes
=
0
;
...
@@ -471,31 +351,29 @@ orinoco_cs_config(dev_link_t * link)
...
@@ -471,31 +351,29 @@ orinoco_cs_config(dev_link_t * link)
CS_CHECK
(
GetConfigurationInfo
,
handle
,
&
conf
);
CS_CHECK
(
GetConfigurationInfo
,
handle
,
&
conf
);
link
->
conf
.
Vcc
=
conf
.
Vcc
;
link
->
conf
.
Vcc
=
conf
.
Vcc
;
DEBUG
(
0
,
"orinoco_cs_config: ConfigBase = 0x%x link->conf.Vcc = %d
\n
"
,
link
->
conf
.
ConfigBase
,
link
->
conf
.
Vcc
);
/*
/*
In this loop, we scan the CIS for configuration table entries,
* In this loop, we scan the CIS for configuration table
each of which describes a valid card configuration, including
* entries, each of which describes a valid card
voltage, IO window, memory window, and interrupt settings.
* configuration, including voltage, IO window, memory window,
* and interrupt settings.
We make no assumptions about the card to be configured: we use
*
just the information available in the CIS. In an ideal world,
* We make no assumptions about the card to be configured: we
this would work for any PCMCIA card, but it requires a complete
* use just the information available in the CIS. In an ideal
and accurate CIS. In practice, a driver usually "knows" most of
* world, this would work for any PCMCIA card, but it requires
these things without consulting the CIS, and most client drivers
* a complete and accurate CIS. In practice, a driver usually
will only use the CIS to fill in implementation-defined details.
* "knows" most of these things without consulting the CIS,
* and most client drivers will only use the CIS to fill in
* implementation-defined details.
*/
*/
tuple
.
DesiredTuple
=
CISTPL_CFTABLE_ENTRY
;
tuple
.
DesiredTuple
=
CISTPL_CFTABLE_ENTRY
;
CS_CHECK
(
GetFirstTuple
,
handle
,
&
tuple
);
CS_CHECK
(
GetFirstTuple
,
handle
,
&
tuple
);
while
(
1
)
{
while
(
1
)
{
cistpl_cftable_entry_t
*
cfg
=
&
(
parse
.
cftable_entry
);
cistpl_cftable_entry_t
*
cfg
=
&
(
parse
.
cftable_entry
);
cistpl_cftable_entry_t
dflt
=
{
index
:
0
};
CFG_CHECK
(
GetTupleData
,
handle
,
&
tuple
);
CFG_CHECK
(
GetTupleData
,
handle
,
&
tuple
);
CFG_CHECK
(
ParseTuple
,
handle
,
&
tuple
,
&
parse
);
CFG_CHECK
(
ParseTuple
,
handle
,
&
tuple
,
&
parse
);
DEBUG
(
0
,
"orinoco_cs_config: index = 0x%x, flags = 0x%x
\n
"
,
cfg
->
index
,
cfg
->
flags
);
if
(
cfg
->
flags
&
CISTPL_CFTABLE_DEFAULT
)
if
(
cfg
->
flags
&
CISTPL_CFTABLE_DEFAULT
)
dflt
=
*
cfg
;
dflt
=
*
cfg
;
if
(
cfg
->
index
==
0
)
if
(
cfg
->
index
==
0
)
...
@@ -509,7 +387,7 @@ orinoco_cs_config(dev_link_t * link)
...
@@ -509,7 +387,7 @@ orinoco_cs_config(dev_link_t * link)
}
}
/* Use power settings for Vcc and Vpp if present */
/* Use power settings for Vcc and Vpp if present */
/*
Note that the CIS values need to be rescaled */
/* Note that the CIS values need to be rescaled */
if
(
cfg
->
vcc
.
present
&
(
1
<<
CISTPL_POWER_VNOM
))
{
if
(
cfg
->
vcc
.
present
&
(
1
<<
CISTPL_POWER_VNOM
))
{
if
(
conf
.
Vcc
!=
cfg
->
vcc
.
param
[
CISTPL_POWER_VNOM
]
/
10000
)
{
if
(
conf
.
Vcc
!=
cfg
->
vcc
.
param
[
CISTPL_POWER_VNOM
]
/
10000
)
{
DEBUG
(
2
,
"orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)
\n
"
,
conf
.
Vcc
,
cfg
->
vcc
.
param
[
CISTPL_POWER_VNOM
]
/
10000
);
DEBUG
(
2
,
"orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)
\n
"
,
conf
.
Vcc
,
cfg
->
vcc
.
param
[
CISTPL_POWER_VNOM
]
/
10000
);
...
@@ -531,8 +409,6 @@ orinoco_cs_config(dev_link_t * link)
...
@@ -531,8 +409,6 @@ orinoco_cs_config(dev_link_t * link)
link
->
conf
.
Vpp1
=
link
->
conf
.
Vpp2
=
link
->
conf
.
Vpp1
=
link
->
conf
.
Vpp2
=
dflt
.
vpp1
.
param
[
CISTPL_POWER_VNOM
]
/
10000
;
dflt
.
vpp1
.
param
[
CISTPL_POWER_VNOM
]
/
10000
;
DEBUG
(
0
,
"orinoco_cs_config: We seem to have configured Vcc and Vpp
\n
"
);
/* Do we need to allocate an interrupt? */
/* Do we need to allocate an interrupt? */
if
(
cfg
->
irq
.
IRQInfo1
||
dflt
.
irq
.
IRQInfo1
)
if
(
cfg
->
irq
.
IRQInfo1
||
dflt
.
irq
.
IRQInfo1
)
link
->
conf
.
Attributes
|=
CONF_ENABLE_IRQ
;
link
->
conf
.
Attributes
|=
CONF_ENABLE_IRQ
;
...
@@ -581,9 +457,9 @@ orinoco_cs_config(dev_link_t * link)
...
@@ -581,9 +457,9 @@ orinoco_cs_config(dev_link_t * link)
}
}
/*
/*
Allocate an interrupt line. Note that this does not assign a
* Allocate an interrupt line. Note that this does not assign
handler to the interrupt, unless the 'Handler' member of the
* a handler to the interrupt, unless the 'Handler' member of
irq structure is initialized.
* the
irq structure is initialized.
*/
*/
if
(
link
->
conf
.
Attributes
&
CONF_ENABLE_IRQ
)
{
if
(
link
->
conf
.
Attributes
&
CONF_ENABLE_IRQ
)
{
int
i
;
int
i
;
...
@@ -603,33 +479,43 @@ orinoco_cs_config(dev_link_t * link)
...
@@ -603,33 +479,43 @@ orinoco_cs_config(dev_link_t * link)
}
}
/* We initialize the hermes structure before completing PCMCIA
/* We initialize the hermes structure before completing PCMCIA
configuration just in case the interrupt handler gets
*
configuration just in case the interrupt handler gets
called. */
*
called. */
hermes_struct_init
(
hw
,
link
->
io
.
BasePort1
,
hermes_struct_init
(
hw
,
link
->
io
.
BasePort1
,
HERMES_IO
,
HERMES_16BIT_REGSPACING
);
HERMES_IO
,
HERMES_16BIT_REGSPACING
);
/*
/*
This actually configures the PCMCIA socket -- setting up
*
This actually configures the PCMCIA socket -- setting up
the I/O windows and the interrupt mapping, and putting the
*
the I/O windows and the interrupt mapping, and putting the
card and host interface into "Memory and IO" mode.
*
card and host interface into "Memory and IO" mode.
*/
*/
CS_CHECK
(
RequestConfiguration
,
link
->
handle
,
&
link
->
conf
);
CS_CHECK
(
RequestConfiguration
,
link
->
handle
,
&
link
->
conf
);
ndev
->
base_addr
=
link
->
io
.
BasePort1
;
/* Ok, we have the configuration, prepare to register the netdev */
ndev
->
irq
=
link
->
irq
.
AssignedIRQ
;
dev
->
base_addr
=
link
->
io
.
BasePort1
;
dev
->
irq
=
link
->
irq
.
AssignedIRQ
;
SET_MODULE_OWNER
(
dev
);
card
->
node
.
major
=
card
->
node
.
minor
=
0
;
/* register_netdev will give us an ethX name */
/* register_netdev will give us an ethX name */
n
dev
->
name
[
0
]
=
'\0'
;
dev
->
name
[
0
]
=
'\0'
;
/* Tell the stack we exist */
/* Tell the stack we exist */
if
(
register_netdev
(
n
dev
)
!=
0
)
{
if
(
register_netdev
(
dev
)
!=
0
)
{
printk
(
KERN_ERR
"orinoco_cs: register_netdev() failed
\n
"
);
printk
(
KERN_ERR
"orinoco_cs: register_netdev() failed
\n
"
);
goto
failed
;
goto
failed
;
}
}
strcpy
(
card
->
node
.
dev_name
,
ndev
->
name
);
/* At this point, the dev_node_t structure(s) needs to be
* initialized and arranged in a linked list at link->dev. */
strcpy
(
card
->
node
.
dev_name
,
dev
->
name
);
link
->
dev
=
&
card
->
node
;
/* link->dev being non-NULL is also
used to indicate that the
net_device has been registered */
link
->
state
&=
~
DEV_CONFIG_PENDING
;
/* Finally, report what we've done */
/* Finally, report what we've done */
printk
(
KERN_DEBUG
"%s: index 0x%02x: Vcc %d.%d"
,
printk
(
KERN_DEBUG
"%s: index 0x%02x: Vcc %d.%d"
,
n
dev
->
name
,
link
->
conf
.
ConfigIndex
,
dev
->
name
,
link
->
conf
.
ConfigIndex
,
link
->
conf
.
Vcc
/
10
,
link
->
conf
.
Vcc
%
10
);
link
->
conf
.
Vcc
/
10
,
link
->
conf
.
Vcc
%
10
);
if
(
link
->
conf
.
Vpp1
)
if
(
link
->
conf
.
Vpp1
)
printk
(
", Vpp %d.%d"
,
link
->
conf
.
Vpp1
/
10
,
printk
(
", Vpp %d.%d"
,
link
->
conf
.
Vpp1
/
10
,
...
@@ -645,59 +531,40 @@ orinoco_cs_config(dev_link_t * link)
...
@@ -645,59 +531,40 @@ orinoco_cs_config(dev_link_t * link)
printk
(
"
\n
"
);
printk
(
"
\n
"
);
/* And give us the proc nodes for debugging */
/* And give us the proc nodes for debugging */
if
(
orinoco_proc_dev_init
(
pri
v
)
!=
0
)
{
if
(
orinoco_proc_dev_init
(
de
v
)
!=
0
)
{
printk
(
KERN_ERR
"orinoco_cs: Failed to create /proc node for %s
\n
"
,
printk
(
KERN_ERR
"orinoco_cs: Failed to create /proc node for %s
\n
"
,
n
dev
->
name
);
dev
->
name
);
goto
failed
;
goto
failed
;
}
}
/* Note to myself : this replace MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT */
SET_MODULE_OWNER
(
ndev
);
/* Let reset_cor parameter override determine_firmware()'s guess */
if
(
reset_cor
!=
-
1
)
priv
->
broken_cor_reset
=
!
reset_cor
;
/*
At this point, the dev_node_t structure(s) need to be
initialized and arranged in a linked list at link->dev.
*/
card
->
node
.
major
=
card
->
node
.
minor
=
0
;
link
->
dev
=
&
card
->
node
;
link
->
state
&=
~
DEV_CONFIG_PENDING
;
TRACE_EXIT
(
"orinoco"
);
return
;
return
;
cs_failed:
cs_failed:
cs_error
(
link
->
handle
,
last_fn
,
last_ret
);
cs_error
(
link
->
handle
,
last_fn
,
last_ret
);
failed:
failed:
orinoco_cs_release
((
u_long
)
link
);
orinoco_cs_release
((
u_long
)
link
);
TRACE_EXIT
(
"orinoco"
);
}
/* orinoco_cs_config */
}
/* orinoco_cs_config */
/*======================================================================
/*
After a card is removed, orinoco_cs_release() will unregister the
* After a card is removed, orinoco_cs_release() will unregister the
device, and release the PCMCIA configuration. If the device is
* device, and release the PCMCIA configuration. If the device is
still open, this will be postponed until it is closed.
* still open, this will be postponed until it is closed.
======================================================================*/
*/
static
void
static
void
orinoco_cs_release
(
u_long
arg
)
orinoco_cs_release
(
u_long
arg
)
{
{
dev_link_t
*
link
=
(
dev_link_t
*
)
arg
;
dev_link_t
*
link
=
(
dev_link_t
*
)
arg
;
struct
orinoco_private
*
priv
=
link
->
priv
;
struct
net_device
*
dev
=
link
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
TRACE_ENTER
(
link
->
dev
->
dev_name
);
/*
/*
If the device is currently in use, we won't release until it
If the device is currently in use, we won't release until it
is actually closed, because until then, we can't be sure that
is actually closed, because until then, we can't be sure that
no one will try to access the device or its data structures.
no one will try to access the device or its data structures.
*/
*/
if
(
link
->
open
)
{
if
(
priv
->
open
)
{
DEBUG
(
0
,
"orinoco_cs: release postponed, '%s' still open
\n
"
,
DEBUG
(
0
,
"orinoco_cs: release postponed, '%s' still open
\n
"
,
link
->
dev
->
dev_name
);
link
->
dev
->
dev_name
);
link
->
state
|=
DEV_STALE_CONFIG
;
link
->
state
|=
DEV_STALE_CONFIG
;
...
@@ -705,7 +572,7 @@ orinoco_cs_release(u_long arg)
...
@@ -705,7 +572,7 @@ orinoco_cs_release(u_long arg)
}
}
/* Unregister proc entry */
/* Unregister proc entry */
orinoco_proc_dev_cleanup
(
pri
v
);
orinoco_proc_dev_cleanup
(
de
v
);
/* Don't bother checking to see if these succeed or not */
/* Don't bother checking to see if these succeed or not */
CardServices
(
ReleaseConfiguration
,
link
->
handle
);
CardServices
(
ReleaseConfiguration
,
link
->
handle
);
...
@@ -714,62 +581,74 @@ orinoco_cs_release(u_long arg)
...
@@ -714,62 +581,74 @@ orinoco_cs_release(u_long arg)
if
(
link
->
irq
.
AssignedIRQ
)
if
(
link
->
irq
.
AssignedIRQ
)
CardServices
(
ReleaseIRQ
,
link
->
handle
,
&
link
->
irq
);
CardServices
(
ReleaseIRQ
,
link
->
handle
,
&
link
->
irq
);
link
->
state
&=
~
DEV_CONFIG
;
link
->
state
&=
~
DEV_CONFIG
;
TRACE_EXIT
(
link
->
dev
->
dev_name
);
}
/* orinoco_cs_release */
}
/* orinoco_cs_release */
/*======================================================================
/*
The card status event handler. Mostly, this schedules other
* The card status event handler. Mostly, this schedules other stuff
stuff to run after an event is received.
* to run after an event is received.
*/
When a CARD_REMOVAL event is received, we immediately set a
private flag to block future accesses to this device. All the
functions that actually access the device should check this flag
to make sure the card is still present.
======================================================================*/
static
int
static
int
orinoco_cs_event
(
event_t
event
,
int
priority
,
orinoco_cs_event
(
event_t
event
,
int
priority
,
event_callback_args_t
*
args
)
event_callback_args_t
*
args
)
{
{
dev_link_t
*
link
=
args
->
client_data
;
dev_link_t
*
link
=
args
->
client_data
;
struct
orinoco_private
*
priv
=
(
struct
orinoco_private
*
)
link
->
priv
;
struct
net_device
*
dev
=
link
->
priv
;
struct
net_device
*
dev
=
priv
->
nde
v
;
struct
orinoco_private
*
priv
=
dev
->
pri
v
;
int
err
=
0
;
TRACE_ENTER
(
"orinoco"
)
;
unsigned
long
flags
;
switch
(
event
)
{
switch
(
event
)
{
case
CS_EVENT_CARD_REMOVAL
:
case
CS_EVENT_CARD_REMOVAL
:
link
->
state
&=
~
DEV_PRESENT
;
link
->
state
&=
~
DEV_PRESENT
;
if
(
link
->
state
&
DEV_CONFIG
)
{
if
(
link
->
state
&
DEV_CONFIG
)
{
netif_stop_queue
(
dev
);
orinoco_lock
(
priv
,
&
flags
);
}
orinoco_shutdown
(
priv
);
if
(
link
->
state
&
DEV_CONFIG
)
{
netif_device_detach
(
dev
);
netif_device_detach
(
dev
);
priv
->
hw_unavailable
=
1
;
orinoco_unlock
(
priv
,
&
flags
);
/* if (link->open) */
/* orinoco_cs_stop(dev); */
mod_timer
(
&
link
->
release
,
jiffies
+
HZ
/
20
);
mod_timer
(
&
link
->
release
,
jiffies
+
HZ
/
20
);
}
}
break
;
break
;
case
CS_EVENT_CARD_INSERTION
:
case
CS_EVENT_CARD_INSERTION
:
link
->
state
|=
DEV_PRESENT
|
DEV_CONFIG_PENDING
;
link
->
state
|=
DEV_PRESENT
|
DEV_CONFIG_PENDING
;
orinoco_cs_config
(
link
);
orinoco_cs_config
(
link
);
break
;
break
;
case
CS_EVENT_PM_SUSPEND
:
case
CS_EVENT_PM_SUSPEND
:
link
->
state
|=
DEV_SUSPEND
;
link
->
state
|=
DEV_SUSPEND
;
/* Fall through... */
/* Fall through... */
case
CS_EVENT_RESET_PHYSICAL
:
case
CS_EVENT_RESET_PHYSICAL
:
orinoco_shutdown
(
priv
);
/* Mark the device as stopped, to block IO until later */
/* Mark the device as stopped, to block IO until later */
if
(
link
->
state
&
DEV_CONFIG
)
{
if
(
link
->
state
&
DEV_CONFIG
)
{
if
(
link
->
open
)
{
err
=
orinoco_lock
(
priv
,
&
flags
);
netif_stop_queue
(
dev
);
if
(
err
)
{
netif_device_detach
(
dev
);
printk
(
KERN_ERR
"%s: hw_unavailable on SUSPEND/RESET_PHYSICAL
\n
"
,
dev
->
name
);
break
;
}
}
err
=
__orinoco_down
(
dev
);
if
(
err
)
printk
(
KERN_WARNING
"%s: %s: Error %d downing interface
\n
"
,
dev
->
name
,
event
==
CS_EVENT_PM_SUSPEND
?
"SUSPEND"
:
"RESET_PHYSICAL"
,
err
);
netif_device_detach
(
dev
);
priv
->
hw_unavailable
=
1
;
orinoco_unlock
(
priv
,
&
flags
);
CardServices
(
ReleaseConfiguration
,
link
->
handle
);
CardServices
(
ReleaseConfiguration
,
link
->
handle
);
}
}
break
;
break
;
case
CS_EVENT_PM_RESUME
:
case
CS_EVENT_PM_RESUME
:
link
->
state
&=
~
DEV_SUSPEND
;
link
->
state
&=
~
DEV_SUSPEND
;
/* Fall through... */
/* Fall through... */
...
@@ -778,36 +657,49 @@ orinoco_cs_event(event_t event, int priority,
...
@@ -778,36 +657,49 @@ orinoco_cs_event(event_t event, int priority,
CardServices
(
RequestConfiguration
,
link
->
handle
,
CardServices
(
RequestConfiguration
,
link
->
handle
,
&
link
->
conf
);
&
link
->
conf
);
if
(
link
->
open
)
{
/* FIXME: should we double check that this is
if
(
orinoco_reset
(
priv
)
==
0
)
{
* the same card as we had before */
netif_device_attach
(
dev
);
err
=
orinoco_reinit_firmware
(
dev
);
netif_start_queue
(
dev
);
if
(
err
)
{
}
else
{
printk
(
KERN_ERR
"%s: Error %d re-initializing firmware
\n
"
,
printk
(
KERN_ERR
"%s: Error resetting device on PCMCIA event
\n
"
,
dev
->
name
,
err
);
dev
->
name
);
break
;
orinoco_cs_stop
(
dev
);
}
}
}
spin_lock_irqsave
(
&
priv
->
lock
,
flags
);
netif_device_attach
(
dev
);
priv
->
hw_unavailable
=
0
;
if
(
priv
->
open
)
{
err
=
__orinoco_up
(
dev
);
if
(
err
)
printk
(
KERN_ERR
"%s: Error %d restarting card
\n
"
,
dev
->
name
,
err
);
}
orinoco_unlock
(
priv
,
&
flags
);
}
}
/*
In a normal driver, additional code may go here to restore
the device state and restart IO.
*/
break
;
break
;
}
}
TRACE_EXIT
(
"orinoco"
);
return
err
;
return
0
;
}
/* orinoco_cs_event */
}
/* orinoco_cs_event */
/********************************************************************/
/* Module initialization */
/********************************************************************/
/* Can't be declared "const" or the whole __initdata section will
* become const */
static
char
version
[]
__initdata
=
"orinoco_cs.c 0.13 (David Gibson <hermes@gibson.dropbear.id.au> and others)"
;
static
int
__init
static
int
__init
init_orinoco_cs
(
void
)
init_orinoco_cs
(
void
)
{
{
servinfo_t
serv
;
servinfo_t
serv
;
TRACE_ENTER
(
"orinoco"
);
printk
(
KERN_DEBUG
"%s
\n
"
,
version
);
printk
(
KERN_DEBUG
"%s
\n
"
,
version
);
CardServices
(
GetCardServicesInfo
,
&
serv
);
CardServices
(
GetCardServicesInfo
,
&
serv
);
...
@@ -819,16 +711,12 @@ init_orinoco_cs(void)
...
@@ -819,16 +711,12 @@ init_orinoco_cs(void)
register_pccard_driver
(
&
dev_info
,
&
orinoco_cs_attach
,
&
orinoco_cs_detach
);
register_pccard_driver
(
&
dev_info
,
&
orinoco_cs_attach
,
&
orinoco_cs_detach
);
TRACE_EXIT
(
"orinoco"
);
return
0
;
return
0
;
}
}
static
void
__exit
static
void
__exit
exit_orinoco_cs
(
void
)
exit_orinoco_cs
(
void
)
{
{
TRACE_ENTER
(
"orinoco"
);
unregister_pccard_driver
(
&
dev_info
);
unregister_pccard_driver
(
&
dev_info
);
if
(
dev_list
)
if
(
dev_list
)
...
@@ -839,9 +727,8 @@ exit_orinoco_cs(void)
...
@@ -839,9 +727,8 @@ exit_orinoco_cs(void)
orinoco_cs_release
((
u_long
)
dev_list
);
orinoco_cs_release
((
u_long
)
dev_list
);
orinoco_cs_detach
(
dev_list
);
orinoco_cs_detach
(
dev_list
);
}
}
TRACE_EXIT
(
"orinoco"
);
}
}
module_init
(
init_orinoco_cs
);
module_init
(
init_orinoco_cs
);
module_exit
(
exit_orinoco_cs
);
module_exit
(
exit_orinoco_cs
);
drivers/net/wireless/orinoco_plx.c
View file @
5bb7978a
/* orinoco_plx.c 0.1
1b
/* orinoco_plx.c 0.1
3
*
*
* Driver for Prism II devices which would usually be driven by orinoco_cs,
* Driver for Prism II devices which would usually be driven by orinoco_cs,
* but are connected to the PCI bus by a PLX9052.
* but are connected to the PCI bus by a PLX9052.
...
@@ -134,13 +134,6 @@ not have time for a while..
...
@@ -134,13 +134,6 @@ not have time for a while..
#include "hermes.h"
#include "hermes.h"
#include "orinoco.h"
#include "orinoco.h"
static
char
version
[]
__initdata
=
"orinoco_plx.c 0.11b (Daniel Barlow <dan@telent.net>)"
;
MODULE_AUTHOR
(
"Daniel Barlow <dan@telent.net>"
);
MODULE_DESCRIPTION
(
"Driver for wireless LAN cards using the PLX9052 PCI bridge"
);
#ifdef MODULE_LICENSE
MODULE_LICENSE
(
"Dual MPL/GPL"
);
#endif
static
char
dev_info
[]
=
"orinoco_plx"
;
static
char
dev_info
[]
=
"orinoco_plx"
;
#define COR_OFFSET (0x3e0 / 2)
/* COR attribute offset of Prism2 PC card */
#define COR_OFFSET (0x3e0 / 2)
/* COR attribute offset of Prism2 PC card */
...
@@ -149,37 +142,6 @@ static char dev_info[] = "orinoco_plx";
...
@@ -149,37 +142,6 @@ static char dev_info[] = "orinoco_plx";
#define PLX_INTCSR 0x4c
/* Interrupt Control and Status Register */
#define PLX_INTCSR 0x4c
/* Interrupt Control and Status Register */
#define PLX_INTCSR_INTEN (1<<6)
/* Interrupt Enable bit */
#define PLX_INTCSR_INTEN (1<<6)
/* Interrupt Enable bit */
static
int
orinoco_plx_open
(
struct
net_device
*
dev
)
{
struct
orinoco_private
*
priv
=
(
struct
orinoco_private
*
)
dev
->
priv
;
int
err
;
netif_device_attach
(
dev
);
err
=
orinoco_reset
(
priv
);
if
(
err
)
printk
(
KERN_ERR
"%s: orinoco_reset failed in orinoco_plx_open()"
,
dev
->
name
);
else
netif_start_queue
(
dev
);
return
err
;
}
static
int
orinoco_plx_stop
(
struct
net_device
*
dev
)
{
struct
orinoco_private
*
priv
=
(
struct
orinoco_private
*
)
dev
->
priv
;
netif_stop_queue
(
dev
);
orinoco_shutdown
(
priv
);
return
0
;
}
static
void
orinoco_plx_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
orinoco_interrupt
(
irq
,
(
struct
orinoco_private
*
)
dev_id
,
regs
);
}
static
const
u16
cis_magic
[]
=
{
static
const
u16
cis_magic
[]
=
{
0x0001
,
0x0003
,
0x0000
,
0x0000
,
0x00ff
,
0x0017
,
0x0004
,
0x0067
0x0001
,
0x0003
,
0x0000
,
0x0000
,
0x00ff
,
0x0017
,
0x0004
,
0x0067
};
};
...
@@ -197,8 +159,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
...
@@ -197,8 +159,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
int
netdev_registered
=
0
;
int
netdev_registered
=
0
;
int
i
;
int
i
;
TRACE_ENTER
(
"orinoco_plx"
);
err
=
pci_enable_device
(
pdev
);
err
=
pci_enable_device
(
pdev
);
if
(
err
)
if
(
err
)
return
-
EIO
;
return
-
EIO
;
...
@@ -266,7 +226,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
...
@@ -266,7 +226,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
goto
fail
;
goto
fail
;
}
}
dev
=
alloc_orinocodev
(
0
);
dev
=
alloc_orinocodev
(
0
,
NULL
);
if
(
!
dev
)
{
if
(
!
dev
)
{
err
=
-
ENOMEM
;
err
=
-
ENOMEM
;
goto
fail
;
goto
fail
;
...
@@ -274,8 +234,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
...
@@ -274,8 +234,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
priv
=
dev
->
priv
;
priv
=
dev
->
priv
;
dev
->
base_addr
=
pccard_ioaddr
;
dev
->
base_addr
=
pccard_ioaddr
;
dev
->
open
=
orinoco_plx_open
;
dev
->
stop
=
orinoco_plx_stop
;
SET_MODULE_OWNER
(
dev
);
SET_MODULE_OWNER
(
dev
);
printk
(
KERN_DEBUG
printk
(
KERN_DEBUG
...
@@ -286,7 +244,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
...
@@ -286,7 +244,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
HERMES_IO
,
HERMES_16BIT_REGSPACING
);
HERMES_IO
,
HERMES_16BIT_REGSPACING
);
pci_set_drvdata
(
pdev
,
dev
);
pci_set_drvdata
(
pdev
,
dev
);
err
=
request_irq
(
pdev
->
irq
,
orinoco_
plx_
interrupt
,
SA_SHIRQ
,
dev
->
name
,
priv
);
err
=
request_irq
(
pdev
->
irq
,
orinoco_interrupt
,
SA_SHIRQ
,
dev
->
name
,
priv
);
if
(
err
)
{
if
(
err
)
{
printk
(
KERN_ERR
"orinoco_plx: Error allocating IRQ %d.
\n
"
,
pdev
->
irq
);
printk
(
KERN_ERR
"orinoco_plx: Error allocating IRQ %d.
\n
"
,
pdev
->
irq
);
err
=
-
EBUSY
;
err
=
-
EBUSY
;
...
@@ -299,19 +257,17 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
...
@@ -299,19 +257,17 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
goto
fail
;
goto
fail
;
netdev_registered
=
1
;
netdev_registered
=
1
;
err
=
orinoco_proc_dev_init
(
pri
v
);
err
=
orinoco_proc_dev_init
(
de
v
);
if
(
err
)
if
(
err
)
goto
fail
;
goto
fail
;
TRACE_EXIT
(
"orinoco_plx"
);
return
0
;
/* succeeded */
return
0
;
/* succeeded */
fail:
fail:
printk
(
KERN_DEBUG
"orinoco_plx: init_one(), FAIL!
\n
"
);
printk
(
KERN_DEBUG
"orinoco_plx: init_one(), FAIL!
\n
"
);
if
(
priv
)
{
if
(
priv
)
{
orinoco_proc_dev_cleanup
(
pri
v
);
orinoco_proc_dev_cleanup
(
de
v
);
if
(
netdev_registered
)
if
(
netdev_registered
)
unregister_netdev
(
dev
);
unregister_netdev
(
dev
);
...
@@ -330,8 +286,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
...
@@ -330,8 +286,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
pci_disable_device
(
pdev
);
pci_disable_device
(
pdev
);
TRACE_EXIT
(
"orinoco_plx"
);
return
err
;
return
err
;
}
}
...
@@ -340,12 +294,10 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
...
@@ -340,12 +294,10 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
struct
net_device
*
dev
=
pci_get_drvdata
(
pdev
);
struct
net_device
*
dev
=
pci_get_drvdata
(
pdev
);
struct
orinoco_private
*
priv
=
dev
->
priv
;
struct
orinoco_private
*
priv
=
dev
->
priv
;
TRACE_ENTER
(
"orinoco_plx"
);
if
(
!
dev
)
if
(
!
dev
)
BUG
();
BUG
();
orinoco_proc_dev_cleanup
(
pri
v
);
orinoco_proc_dev_cleanup
(
de
v
);
unregister_netdev
(
dev
);
unregister_netdev
(
dev
);
...
@@ -357,13 +309,10 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
...
@@ -357,13 +309,10 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
release_region
(
pci_resource_start
(
pdev
,
3
),
pci_resource_len
(
pdev
,
3
));
release_region
(
pci_resource_start
(
pdev
,
3
),
pci_resource_len
(
pdev
,
3
));
pci_disable_device
(
pdev
);
pci_disable_device
(
pdev
);
TRACE_EXIT
(
"orinoco_plx"
);
}
}
static
struct
pci_device_id
orinoco_plx_pci_id_table
[]
__devinitdata
=
{
static
struct
pci_device_id
orinoco_plx_pci_id_table
[]
__devinitdata
=
{
{
0x10b7
,
0x7770
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
/* 3ComAirConnect */
{
0x111a
,
0x1023
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
/* Siemens SpeedStream SS1023 */
{
0x111a
,
0x1023
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
/* Siemens SpeedStream SS1023 */
{
0x1385
,
0x4100
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
/* Netgear MA301 */
{
0x1385
,
0x4100
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
/* Netgear MA301 */
{
0x15e8
,
0x0130
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
/* Correga - does this work? */
{
0x15e8
,
0x0130
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
/* Correga - does this work? */
...
@@ -376,7 +325,8 @@ static struct pci_device_id orinoco_plx_pci_id_table[] __devinitdata = {
...
@@ -376,7 +325,8 @@ static struct pci_device_id orinoco_plx_pci_id_table[] __devinitdata = {
{
0x16ec
,
0x3685
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
/* USR 2415 */
{
0x16ec
,
0x3685
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
/* USR 2415 */
{
0xec80
,
0xec00
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
/* Belkin F5D6000 tested by
{
0xec80
,
0xec00
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
/* Belkin F5D6000 tested by
Brendan W. McAdams <rit@jacked-in.org> */
Brendan W. McAdams <rit@jacked-in.org> */
{
0x126c
,
0x8030
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
/* Nortel emobility */
{
0x10b7
,
0x7770
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
/* 3Com AirConnect PCI tested by
Damien Persohn <damien@persohn.net> */
{
0
,},
{
0
,},
};
};
...
@@ -387,8 +337,17 @@ static struct pci_driver orinoco_plx_driver = {
...
@@ -387,8 +337,17 @@ static struct pci_driver orinoco_plx_driver = {
.
id_table
=
orinoco_plx_pci_id_table
,
.
id_table
=
orinoco_plx_pci_id_table
,
.
probe
=
orinoco_plx_init_one
,
.
probe
=
orinoco_plx_init_one
,
.
remove
=
__devexit_p
(
orinoco_plx_remove_one
),
.
remove
=
__devexit_p
(
orinoco_plx_remove_one
),
.
suspend
=
0
,
.
resume
=
0
,
};
};
static
char
version
[]
__initdata
=
"orinoco_plx.c 0.13 (Daniel Barlow <dan@telent.net>, David Gibson <hermes@gibson.dropbear.id.au>)"
;
MODULE_AUTHOR
(
"Daniel Barlow <dan@telent.net>"
);
MODULE_DESCRIPTION
(
"Driver for wireless LAN cards using the PLX9052 PCI bridge"
);
#ifdef MODULE_LICENSE
MODULE_LICENSE
(
"Dual MPL/GPL"
);
#endif
static
int
__init
orinoco_plx_init
(
void
)
static
int
__init
orinoco_plx_init
(
void
)
{
{
printk
(
KERN_DEBUG
"%s
\n
"
,
version
);
printk
(
KERN_DEBUG
"%s
\n
"
,
version
);
...
...
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