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
Kirill Smelkov
linux
Commits
74f54248
Commit
74f54248
authored
Oct 21, 2004
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net/jgarzik/net-drivers-2.6
into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents
4c8aded7
d1b610e5
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
1273 additions
and
657 deletions
+1273
-657
drivers/net/8139cp.c
drivers/net/8139cp.c
+1
-0
drivers/net/b44.c
drivers/net/b44.c
+83
-48
drivers/net/b44.h
drivers/net/b44.h
+5
-108
drivers/net/depca.c
drivers/net/depca.c
+4
-4
drivers/net/forcedeth.c
drivers/net/forcedeth.c
+28
-3
drivers/net/sis900.c
drivers/net/sis900.c
+142
-116
drivers/net/smc91x.c
drivers/net/smc91x.c
+258
-226
drivers/net/smc91x.h
drivers/net/smc91x.h
+18
-15
drivers/net/tokenring/lanstreamer.c
drivers/net/tokenring/lanstreamer.c
+1
-1
drivers/net/tulip/dmfe.c
drivers/net/tulip/dmfe.c
+1
-0
drivers/net/via-rhine.c
drivers/net/via-rhine.c
+4
-0
drivers/net/wireless/prism54/isl_38xx.c
drivers/net/wireless/prism54/isl_38xx.c
+5
-10
drivers/net/wireless/prism54/isl_38xx.h
drivers/net/wireless/prism54/isl_38xx.h
+4
-0
drivers/net/wireless/prism54/isl_ioctl.c
drivers/net/wireless/prism54/isl_ioctl.c
+554
-85
drivers/net/wireless/prism54/isl_ioctl.h
drivers/net/wireless/prism54/isl_ioctl.h
+2
-0
drivers/net/wireless/prism54/isl_oid.h
drivers/net/wireless/prism54/isl_oid.h
+9
-0
drivers/net/wireless/prism54/islpci_dev.c
drivers/net/wireless/prism54/islpci_dev.c
+32
-17
drivers/net/wireless/prism54/islpci_dev.h
drivers/net/wireless/prism54/islpci_dev.h
+4
-0
drivers/net/wireless/prism54/islpci_eth.c
drivers/net/wireless/prism54/islpci_eth.c
+3
-2
drivers/net/wireless/prism54/islpci_hotplug.c
drivers/net/wireless/prism54/islpci_hotplug.c
+0
-3
drivers/net/wireless/prism54/islpci_mgt.c
drivers/net/wireless/prism54/islpci_mgt.c
+1
-0
drivers/net/wireless/prism54/islpci_mgt.h
drivers/net/wireless/prism54/islpci_mgt.h
+0
-2
drivers/net/wireless/prism54/oid_mgt.c
drivers/net/wireless/prism54/oid_mgt.c
+110
-16
drivers/net/wireless/prism54/oid_mgt.h
drivers/net/wireless/prism54/oid_mgt.h
+4
-1
No files found.
drivers/net/8139cp.c
View file @
74f54248
...
...
@@ -71,6 +71,7 @@
#include <linux/udp.h>
#include <linux/cache.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
/* VLAN tagging feature enable/disable */
...
...
drivers/net/b44.c
View file @
74f54248
...
...
@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/ethtool.h>
...
...
@@ -27,8 +28,8 @@
#define DRV_MODULE_NAME "b44"
#define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "0.9
4
"
#define DRV_MODULE_RELDATE "
May 4
, 2004"
#define DRV_MODULE_VERSION "0.9
5
"
#define DRV_MODULE_RELDATE "
Aug 3
, 2004"
#define B44_DEF_MSG_ENABLE \
(NETIF_MSG_DRV | \
...
...
@@ -57,6 +58,7 @@
#define B44_DEF_TX_RING_PENDING (B44_TX_RING_SIZE - 1)
#define B44_TX_RING_BYTES (sizeof(struct dma_desc) * \
B44_TX_RING_SIZE)
#define B44_DMA_MASK 0x3fffffff
#define TX_RING_GAP(BP) \
(B44_TX_RING_SIZE - (BP)->tx_pending)
...
...
@@ -67,6 +69,7 @@
#define NEXT_TX(N) (((N) + 1) & (B44_TX_RING_SIZE - 1))
#define RX_PKT_BUF_SZ (1536 + bp->rx_offset + 64)
#define TX_PKT_BUF_SZ (B44_MAX_MTU + ETH_HLEN + 8)
/* minimum number of free TX descriptors required to wake up TX process */
#define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4)
...
...
@@ -74,13 +77,13 @@
static
char
version
[]
__devinitdata
=
DRV_MODULE_NAME
".c:v"
DRV_MODULE_VERSION
" ("
DRV_MODULE_RELDATE
")
\n
"
;
MODULE_AUTHOR
(
"
David S. Miller (davem@redhat.com)
"
);
MODULE_AUTHOR
(
"
Florian Schirmer, Pekka Pietikainen, David S. Miller
"
);
MODULE_DESCRIPTION
(
"Broadcom 4400 10/100 PCI ethernet driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
b44_debug
,
"i"
);
MODULE_PARM_DESC
(
b44_debug
,
"B44 bitmapped debugging message enable value"
);
static
int
b44_debug
=
-
1
;
/* -1 == use B44_DEF_MSG_ENABLE as value */
module_param
(
b44_debug
,
int
,
0
);
MODULE_PARM_DESC
(
b44_debug
,
"B44 bitmapped debugging message enable value"
);
static
struct
pci_device_id
b44_pci_tbl
[]
=
{
{
PCI_VENDOR_ID_BROADCOM
,
PCI_DEVICE_ID_BCM4401
,
...
...
@@ -97,6 +100,10 @@ MODULE_DEVICE_TABLE(pci, b44_pci_tbl);
static
void
b44_halt
(
struct
b44
*
);
static
void
b44_init_rings
(
struct
b44
*
);
static
void
b44_init_hw
(
struct
b44
*
);
static
int
b44_poll
(
struct
net_device
*
dev
,
int
*
budget
);
#ifdef CONFIG_NET_POLL_CONTROLLER
static
void
b44_poll_controller
(
struct
net_device
*
dev
);
#endif
static
inline
unsigned
long
br32
(
const
struct
b44
*
bp
,
unsigned
long
reg
)
{
...
...
@@ -141,41 +148,8 @@ static int b44_wait_bit(struct b44 *bp, unsigned long reg,
* interrupts disabled.
*/
#define SBID_SDRAM 0
#define SBID_PCI_MEM 1
#define SBID_PCI_CFG 2
#define SBID_PCI_DMA 3
#define SBID_SDRAM_SWAPPED 4
#define SBID_ENUM 5
#define SBID_REG_SDRAM 6
#define SBID_REG_ILINE20 7
#define SBID_REG_EMAC 8
#define SBID_REG_CODEC 9
#define SBID_REG_USB 10
#define SBID_REG_PCI 11
#define SBID_REG_MIPS 12
#define SBID_REG_EXTIF 13
#define SBID_EXTIF 14
#define SBID_EJTAG 15
#define SBID_MAX 16
static
u32
ssb_get_addr
(
struct
b44
*
bp
,
u32
id
,
u32
instance
)
{
switch
(
id
)
{
case
SBID_PCI_DMA
:
return
0x40000000
;
case
SBID_ENUM
:
return
0x18000000
;
case
SBID_REG_EMAC
:
return
0x18000000
;
case
SBID_REG_CODEC
:
return
0x18001000
;
case
SBID_REG_PCI
:
return
0x18002000
;
default:
return
0
;
};
}
#define SB_PCI_DMA 0x40000000
/* Client Mode PCI memory access space (1 GB) */
#define BCM4400_PCI_CORE_ADDR 0x18002000
/* Address of PCI core on BCM4400 cards */
static
u32
ssb_get_core_rev
(
struct
b44
*
bp
)
{
...
...
@@ -187,8 +161,7 @@ static u32 ssb_pci_setup(struct b44 *bp, u32 cores)
u32
bar_orig
,
pci_rev
,
val
;
pci_read_config_dword
(
bp
->
pdev
,
SSB_BAR0_WIN
,
&
bar_orig
);
pci_write_config_dword
(
bp
->
pdev
,
SSB_BAR0_WIN
,
ssb_get_addr
(
bp
,
SBID_REG_PCI
,
0
));
pci_write_config_dword
(
bp
->
pdev
,
SSB_BAR0_WIN
,
BCM4400_PCI_CORE_ADDR
);
pci_rev
=
ssb_get_core_rev
(
bp
);
val
=
br32
(
bp
,
B44_SBINTVEC
);
...
...
@@ -649,10 +622,30 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
if
(
skb
==
NULL
)
return
-
ENOMEM
;
skb
->
dev
=
bp
->
dev
;
mapping
=
pci_map_single
(
bp
->
pdev
,
skb
->
data
,
RX_PKT_BUF_SZ
,
PCI_DMA_FROMDEVICE
);
/* Hardware bug work-around, the chip is unable to do PCI DMA
to/from anything above 1GB :-( */
if
(
mapping
+
RX_PKT_BUF_SZ
>
B44_DMA_MASK
)
{
/* Sigh... */
pci_unmap_single
(
bp
->
pdev
,
mapping
,
RX_PKT_BUF_SZ
,
PCI_DMA_FROMDEVICE
);
dev_kfree_skb_any
(
skb
);
skb
=
__dev_alloc_skb
(
RX_PKT_BUF_SZ
,
GFP_DMA
);
if
(
skb
==
NULL
)
return
-
ENOMEM
;
mapping
=
pci_map_single
(
bp
->
pdev
,
skb
->
data
,
RX_PKT_BUF_SZ
,
PCI_DMA_FROMDEVICE
);
if
(
mapping
+
RX_PKT_BUF_SZ
>
B44_DMA_MASK
)
{
pci_unmap_single
(
bp
->
pdev
,
mapping
,
RX_PKT_BUF_SZ
,
PCI_DMA_FROMDEVICE
);
dev_kfree_skb_any
(
skb
);
return
-
ENOMEM
;
}
}
skb
->
dev
=
bp
->
dev
;
skb_reserve
(
skb
,
bp
->
rx_offset
);
rh
=
(
struct
rx_header
*
)
...
...
@@ -930,6 +923,12 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
entry
=
bp
->
tx_prod
;
mapping
=
pci_map_single
(
bp
->
pdev
,
skb
->
data
,
len
,
PCI_DMA_TODEVICE
);
if
(
mapping
+
len
>
B44_DMA_MASK
)
{
/* Chip can't handle DMA to/from >1GB, use bounce buffer */
pci_unmap_single
(
bp
->
pdev
,
mapping
,
len
,
PCI_DMA_TODEVICE
);
memcpy
(
bp
->
tx_bufs
+
entry
*
TX_PKT_BUF_SZ
,
skb
->
data
,
skb
->
len
);
mapping
=
pci_map_single
(
bp
->
pdev
,
bp
->
tx_bufs
+
entry
*
TX_PKT_BUF_SZ
,
len
,
PCI_DMA_TODEVICE
);
}
bp
->
tx_buffers
[
entry
].
skb
=
skb
;
pci_unmap_addr_set
(
&
bp
->
tx_buffers
[
entry
],
mapping
,
mapping
);
...
...
@@ -1077,6 +1076,11 @@ static void b44_free_consistent(struct b44 *bp)
bp
->
tx_ring
,
bp
->
tx_ring_dma
);
bp
->
tx_ring
=
NULL
;
}
if
(
bp
->
tx_bufs
)
{
pci_free_consistent
(
bp
->
pdev
,
B44_TX_RING_SIZE
*
TX_PKT_BUF_SZ
,
bp
->
tx_bufs
,
bp
->
tx_bufs_dma
);
bp
->
tx_bufs
=
NULL
;
}
}
/*
...
...
@@ -1099,6 +1103,12 @@ static int b44_alloc_consistent(struct b44 *bp)
goto
out_err
;
memset
(
bp
->
tx_buffers
,
0
,
size
);
size
=
B44_TX_RING_SIZE
*
TX_PKT_BUF_SZ
;
bp
->
tx_bufs
=
pci_alloc_consistent
(
bp
->
pdev
,
size
,
&
bp
->
tx_bufs_dma
);
if
(
!
bp
->
tx_bufs
)
goto
out_err
;
memset
(
bp
->
tx_bufs
,
0
,
size
);
size
=
DMA_TABLE_BYTES
;
bp
->
rx_ring
=
pci_alloc_consistent
(
bp
->
pdev
,
size
,
&
bp
->
rx_ring_dma
);
if
(
!
bp
->
rx_ring
)
...
...
@@ -1297,6 +1307,19 @@ static int b44_open(struct net_device *dev)
}
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
/*
* Polling receive - used by netconsole and other diagnostic tools
* to allow network i/o with interrupts disabled.
*/
static
void
b44_poll_controller
(
struct
net_device
*
dev
)
{
disable_irq
(
dev
->
irq
);
b44_interrupt
(
dev
->
irq
,
dev
,
NULL
);
enable_irq
(
dev
->
irq
);
}
#endif
static
int
b44_close
(
struct
net_device
*
dev
)
{
struct
b44
*
bp
=
netdev_priv
(
dev
);
...
...
@@ -1358,7 +1381,10 @@ static struct net_device_stats *b44_get_stats(struct net_device *dev)
hwstat
->
rx_symbol_errs
);
nstat
->
tx_aborted_errors
=
hwstat
->
tx_underruns
;
#if 0
/* Carrier lost counter seems to be broken for some devices */
nstat->tx_carrier_errors = hwstat->tx_carrier_lost;
#endif
return
nstat
;
}
...
...
@@ -1684,7 +1710,6 @@ static int __devinit b44_get_invariants(struct b44 *bp)
bp
->
dev
->
dev_addr
[
5
]
=
eeprom
[
82
];
bp
->
phy_addr
=
eeprom
[
90
]
&
0x1f
;
bp
->
mdc_port
=
(
eeprom
[
90
]
>>
14
)
&
0x1
;
/* With this, plus the rx_header prepended to the data by the
* hardware, we'll land the ethernet header on a 2-byte boundary.
...
...
@@ -1694,7 +1719,7 @@ static int __devinit b44_get_invariants(struct b44 *bp)
bp
->
imask
=
IMASK_DEF
;
bp
->
core_unit
=
ssb_core_unit
(
bp
);
bp
->
dma_offset
=
ssb_get_addr
(
bp
,
SBID_PCI_DMA
,
0
)
;
bp
->
dma_offset
=
SB_PCI_DMA
;
/* XXX - really required?
bp->flags |= B44_FLAG_BUGGY_TXPTR;
...
...
@@ -1738,12 +1763,19 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
pci_set_master
(
pdev
);
err
=
pci_set_dma_mask
(
pdev
,
(
u64
)
0xffffffff
);
err
=
pci_set_dma_mask
(
pdev
,
(
u64
)
B44_DMA_MASK
);
if
(
err
)
{
printk
(
KERN_ERR
PFX
"No usable DMA configuration, "
"aborting.
\n
"
);
goto
err_out_free_res
;
}
err
=
pci_set_consistent_dma_mask
(
pdev
,
(
u64
)
B44_DMA_MASK
);
if
(
err
)
{
printk
(
KERN_ERR
PFX
"No usable DMA configuration, "
"aborting.
\n
"
);
goto
err_out_free_res
;
}
b44reg_base
=
pci_resource_start
(
pdev
,
0
);
b44reg_len
=
pci_resource_len
(
pdev
,
0
);
...
...
@@ -1793,6 +1825,9 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
dev
->
poll
=
b44_poll
;
dev
->
weight
=
64
;
dev
->
watchdog_timeo
=
B44_TX_TIMEOUT
;
#ifdef CONFIG_NET_POLL_CONTROLLER
dev
->
poll_controller
=
b44_poll_controller
;
#endif
dev
->
change_mtu
=
b44_change_mtu
;
dev
->
irq
=
pdev
->
irq
;
SET_ETHTOOL_OPS
(
dev
,
&
b44_ethtool_ops
);
...
...
@@ -1870,7 +1905,7 @@ static void __devexit b44_remove_one(struct pci_dev *pdev)
static
int
b44_suspend
(
struct
pci_dev
*
pdev
,
u32
state
)
{
struct
net_device
*
dev
=
pci_get_drvdata
(
pdev
);
struct
b44
*
bp
=
dev
->
priv
;
struct
b44
*
bp
=
netdev_priv
(
dev
)
;
if
(
!
netif_running
(
dev
))
return
0
;
...
...
@@ -1891,7 +1926,7 @@ static int b44_suspend(struct pci_dev *pdev, u32 state)
static
int
b44_resume
(
struct
pci_dev
*
pdev
)
{
struct
net_device
*
dev
=
pci_get_drvdata
(
pdev
);
struct
b44
*
bp
=
dev
->
priv
;
struct
b44
*
bp
=
netdev_priv
(
dev
)
;
pci_restore_state
(
pdev
);
...
...
drivers/net/b44.h
View file @
74f54248
...
...
@@ -223,21 +223,8 @@
#define B44_RX_SYM 0x05D0UL
/* MIB RX Symbol Errors */
#define B44_RX_PAUSE 0x05D4UL
/* MIB RX Pause Packets */
#define B44_RX_NPAUSE 0x05D8UL
/* MIB RX Non-Pause Packets */
#define B44_SBIPSFLAG 0x0F08UL
/* SB Initiator Port OCP Slave Flag */
#define SBIPSFLAG_IMASK1 0x0000003f
/* Which sbflags --> mips interrupt 1 */
#define SBIPSFLAG_ISHIFT1 0
#define SBIPSFLAG_IMASK2 0x00003f00
/* Which sbflags --> mips interrupt 2 */
#define SBIPSFLAG_ISHIFT2 8
#define SBIPSFLAG_IMASK3 0x003f0000
/* Which sbflags --> mips interrupt 3 */
#define SBIPSFLAG_ISHIFT3 16
#define SBIPSFLAG_IMASK4 0x3f000000
/* Which sbflags --> mips interrupt 4 */
#define SBIPSFLAG_ISHIFT4 24
#define B44_SBTPSFLAG 0x0F18UL
/* SB Target Port OCP Slave Flag */
#define SBTPS_NUM0_MASK 0x0000003f
#define SBTPS_F0EN0 0x00000040
#define B44_SBADMATCH3 0x0F60UL
/* SB Address Match 3 */
#define B44_SBADMATCH2 0x0F68UL
/* SB Address Match 2 */
#define B44_SBADMATCH1 0x0F70UL
/* SB Address Match 1 */
/* Silicon backplane register definitions */
#define B44_SBIMSTATE 0x0F90UL
/* SB Initiator Agent State */
#define SBIMSTATE_PC 0x0000000f
/* Pipe Count */
#define SBIMSTATE_AP_MASK 0x00000030
/* Arbitration Priority */
...
...
@@ -269,86 +256,6 @@
#define SBTMSHIGH_GCR 0x20000000
/* Gated Clock Request */
#define SBTMSHIGH_BISTF 0x40000000
/* BIST Failed */
#define SBTMSHIGH_BISTD 0x80000000
/* BIST Done */
#define B44_SBBWA0 0x0FA0UL
/* SB Bandwidth Allocation Table 0 */
#define SBBWA0_TAB0_MASK 0x0000ffff
/* Lookup Table 0 */
#define SBBWA0_TAB0_SHIFT 0
#define SBBWA0_TAB1_MASK 0xffff0000
/* Lookup Table 0 */
#define SBBWA0_TAB1_SHIFT 16
#define B44_SBIMCFGLOW 0x0FA8UL
/* SB Initiator Configuration Low */
#define SBIMCFGLOW_STO_MASK 0x00000003
/* Service Timeout */
#define SBIMCFGLOW_RTO_MASK 0x00000030
/* Request Timeout */
#define SBIMCFGLOW_RTO_SHIFT 4
#define SBIMCFGLOW_CID_MASK 0x00ff0000
/* Connection ID */
#define SBIMCFGLOW_CID_SHIFT 16
#define B44_SBIMCFGHIGH 0x0FACUL
/* SB Initiator Configuration High */
#define SBIMCFGHIGH_IEM_MASK 0x0000000c
/* Inband Error Mode */
#define SBIMCFGHIGH_TEM_MASK 0x00000030
/* Timeout Error Mode */
#define SBIMCFGHIGH_TEM_SHIFT 4
#define SBIMCFGHIGH_BEM_MASK 0x000000c0
/* Bus Error Mode */
#define SBIMCFGHIGH_BEM_SHIFT 6
#define B44_SBADMATCH0 0x0FB0UL
/* SB Address Match 0 */
#define SBADMATCH0_TYPE_MASK 0x00000003
/* Address Type */
#define SBADMATCH0_AD64 0x00000004
/* Reserved */
#define SBADMATCH0_AI0_MASK 0x000000f8
/* Type0 Size */
#define SBADMATCH0_AI0_SHIFT 3
#define SBADMATCH0_AI1_MASK 0x000001f8
/* Type1 Size */
#define SBADMATCH0_AI1_SHIFT 3
#define SBADMATCH0_AI2_MASK 0x000001f8
/* Type2 Size */
#define SBADMATCH0_AI2_SHIFT 3
#define SBADMATCH0_ADEN 0x00000400
/* Enable */
#define SBADMATCH0_ADNEG 0x00000800
/* Negative Decode */
#define SBADMATCH0_BS0_MASK 0xffffff00
/* Type0 Base Address */
#define SBADMATCH0_BS0_SHIFT 8
#define SBADMATCH0_BS1_MASK 0xfffff000
/* Type1 Base Address */
#define SBADMATCH0_BS1_SHIFT 12
#define SBADMATCH0_BS2_MASK 0xffff0000
/* Type2 Base Address */
#define SBADMATCH0_BS2_SHIFT 16
#define B44_SBTMCFGLOW 0x0FB8UL
/* SB Target Configuration Low */
#define SBTMCFGLOW_CD_MASK 0x000000ff
/* Clock Divide Mask */
#define SBTMCFGLOW_CO_MASK 0x0000f800
/* Clock Offset Mask */
#define SBTMCFGLOW_CO_SHIFT 11
#define SBTMCFGLOW_IF_MASK 0x00fc0000
/* Interrupt Flags Mask */
#define SBTMCFGLOW_IF_SHIFT 18
#define SBTMCFGLOW_IM_MASK 0x03000000
/* Interrupt Mode Mask */
#define SBTMCFGLOW_IM_SHIFT 24
#define B44_SBTMCFGHIGH 0x0FBCUL
/* SB Target Configuration High */
#define SBTMCFGHIGH_BM_MASK 0x00000003
/* Busy Mode */
#define SBTMCFGHIGH_RM_MASK 0x0000000C
/* Retry Mode */
#define SBTMCFGHIGH_RM_SHIFT 2
#define SBTMCFGHIGH_SM_MASK 0x00000030
/* Stop Mode */
#define SBTMCFGHIGH_SM_SHIFT 4
#define SBTMCFGHIGH_EM_MASK 0x00000300
/* Error Mode */
#define SBTMCFGHIGH_EM_SHIFT 8
#define SBTMCFGHIGH_IM_MASK 0x00000c00
/* Interrupt Mode */
#define SBTMCFGHIGH_IM_SHIFT 10
#define B44_SBBCFG 0x0FC0UL
/* SB Broadcast Configuration */
#define SBBCFG_LAT_MASK 0x00000003
/* SB Latency */
#define SBBCFG_MAX0_MASK 0x000f0000
/* MAX Counter 0 */
#define SBBCFG_MAX0_SHIFT 16
#define SBBCFG_MAX1_MASK 0x00f00000
/* MAX Counter 1 */
#define SBBCFG_MAX1_SHIFT 20
#define B44_SBBSTATE 0x0FC8UL
/* SB Broadcast State */
#define SBBSTATE_SRD 0x00000001
/* ST Reg Disable */
#define SBBSTATE_HRD 0x00000002
/* Hold Reg Disable */
#define B44_SBACTCNFG 0x0FD8UL
/* SB Activate Configuration */
#define B44_SBFLAGST 0x0FE8UL
/* SB Current SBFLAGS */
#define B44_SBIDLOW 0x0FF8UL
/* SB Identification Low */
#define SBIDLOW_CS_MASK 0x00000003
/* Config Space Mask */
#define SBIDLOW_AR_MASK 0x00000038
/* Num Address Ranges Supported */
#define SBIDLOW_AR_SHIFT 3
#define SBIDLOW_SYNCH 0x00000040
/* Sync */
#define SBIDLOW_INIT 0x00000080
/* Initiator */
#define SBIDLOW_MINLAT_MASK 0x00000f00
/* Minimum Backplane Latency */
#define SBIDLOW_MINLAT_SHIFT 8
#define SBIDLOW_MAXLAT_MASK 0x0000f000
/* Maximum Backplane Latency */
#define SBIDLOW_MAXLAT_SHIFT 12
#define SBIDLOW_FIRST 0x00010000
/* This Initiator is First */
#define SBIDLOW_CW_MASK 0x000c0000
/* Cycle Counter Width */
#define SBIDLOW_CW_SHIFT 18
#define SBIDLOW_TP_MASK 0x00f00000
/* Target Ports */
#define SBIDLOW_TP_SHIFT 20
#define SBIDLOW_IP_MASK 0x0f000000
/* Initiator Ports */
#define SBIDLOW_IP_SHIFT 24
#define B44_SBIDHIGH 0x0FFCUL
/* SB Identification High */
#define SBIDHIGH_RC_MASK 0x0000000f
/* Revision Code */
#define SBIDHIGH_CC_MASK 0x0000fff0
/* Core Code */
...
...
@@ -356,23 +263,13 @@
#define SBIDHIGH_VC_MASK 0xffff0000
/* Vendor Code */
#define SBIDHIGH_VC_SHIFT 16
#define CORE_CODE_ILINE20 0x801
#define CORE_CODE_SDRAM 0x803
#define CORE_CODE_PCI 0x804
#define CORE_CODE_MIPS 0x805
#define CORE_CODE_ENET 0x806
#define CORE_CODE_CODEC 0x807
#define CORE_CODE_USB 0x808
#define CORE_CODE_ILINE100 0x80a
#define CORE_CODE_EXTIF 0x811
/* SSB PCI config space registers. */
#define SSB_BAR0_WIN 0x80
#define SSB_BAR1_WIN 0x84
#define SSB_SPROM_CONTROL 0x88
#define SSB_BAR1_CONTROL 0x8c
/* SSB core and h
so
t control registers. */
/* SSB core and h
os
t control registers. */
#define SSB_CONTROL 0x0000UL
#define SSB_ARBCONTROL 0x0010UL
#define SSB_ISTAT 0x0020UL
...
...
@@ -500,6 +397,7 @@ struct b44 {
struct
ring_info
*
rx_buffers
;
struct
ring_info
*
tx_buffers
;
unsigned
char
*
tx_bufs
;
u32
dma_offset
;
u32
flags
;
...
...
@@ -531,12 +429,11 @@ struct b44 {
struct
pci_dev
*
pdev
;
struct
net_device
*
dev
;
dma_addr_t
rx_ring_dma
,
tx_ring_dma
;
dma_addr_t
rx_ring_dma
,
tx_ring_dma
,
tx_bufs_dma
;
u32
rx_pending
;
u32
tx_pending
;
u8
phy_addr
;
u8
mdc_port
;
u8
core_unit
;
struct
mii_if_info
mii_if
;
...
...
drivers/net/depca.c
View file @
74f54248
...
...
@@ -1222,10 +1222,10 @@ static int InitRestartDepca(struct net_device *dev)
/* clear IDON by writing a "1", enable interrupts and start lance */
outw
(
IDON
|
INEA
|
STRT
,
DEPCA_DATA
);
if
(
depca_debug
>
2
)
{
printk
(
"%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.
\n
"
,
dev
->
name
,
i
,
virt_to_phys
(
lp
->
sh_mem
)
,
inw
(
DEPCA_DATA
));
printk
(
"%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.
\n
"
,
dev
->
name
,
i
,
lp
->
mem_start
,
inw
(
DEPCA_DATA
));
}
}
else
{
printk
(
"%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.
\n
"
,
dev
->
name
,
i
,
virt_to_phys
(
lp
->
sh_mem
)
,
inw
(
DEPCA_DATA
));
printk
(
"%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.
\n
"
,
dev
->
name
,
i
,
lp
->
mem_start
,
inw
(
DEPCA_DATA
));
status
=
-
1
;
}
...
...
@@ -1901,7 +1901,7 @@ static void depca_dbg_open(struct net_device *dev)
}
}
printk
(
"...0x%8.8x
\n
"
,
readl
(
&
lp
->
tx_ring
[
i
].
base
));
printk
(
"Initialisation block at 0x%8.8lx(Phys)
\n
"
,
virt_to_phys
(
lp
->
sh_mem
)
);
printk
(
"Initialisation block at 0x%8.8lx(Phys)
\n
"
,
lp
->
mem_start
);
printk
(
" mode: 0x%4.4x
\n
"
,
p
->
mode
);
printk
(
" physical address: "
);
for
(
i
=
0
;
i
<
ETH_ALEN
-
1
;
i
++
)
{
...
...
@@ -1915,7 +1915,7 @@ static void depca_dbg_open(struct net_device *dev)
printk
(
"%2.2x
\n
"
,
p
->
mcast_table
[
i
]);
printk
(
" rx_ring at: 0x%8.8x
\n
"
,
p
->
rx_ring
);
printk
(
" tx_ring at: 0x%8.8x
\n
"
,
p
->
tx_ring
);
printk
(
"buffers (Phys): 0x%8.8lx
\n
"
,
virt_to_phys
(
lp
->
sh_mem
)
+
lp
->
buffs_offset
);
printk
(
"buffers (Phys): 0x%8.8lx
\n
"
,
lp
->
mem_start
+
lp
->
buffs_offset
);
printk
(
"Ring size:
\n
RX: %d Log2(rxRingMask): 0x%8.8x
\n
"
,
(
int
)
lp
->
rxRingMask
+
1
,
lp
->
rx_rlen
);
printk
(
"TX: %d Log2(txRingMask): 0x%8.8x
\n
"
,
(
int
)
lp
->
txRingMask
+
1
,
lp
->
tx_rlen
);
outw
(
CSR2
,
DEPCA_ADDR
);
...
...
drivers/net/forcedeth.c
View file @
74f54248
...
...
@@ -76,6 +76,9 @@
* for registers, link status and other minor fixes.
* 0.28: 21 Jun 2004: Big cleanup, making driver mostly endian safe
* 0.29: 31 Aug 2004: Add backup timer for link change notification.
* 0.30: 25 Sep 2004: rx checksum support for nf 250 Gb. Add rx reset
* into nv_close, otherwise reenabling for wol can
* cause DMA to kfree'd memory.
*
* Known bugs:
* We suspect that on some hardware no TX done interrupts are generated.
...
...
@@ -87,7 +90,7 @@
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
* superfluous timer interrupts from the nic.
*/
#define FORCEDETH_VERSION "0.
29
"
#define FORCEDETH_VERSION "0.
30
"
#define DRV_NAME "forcedeth"
#include <linux/module.h>
...
...
@@ -217,6 +220,7 @@ enum {
#define NVREG_TXRXCTL_BIT2 0x0004
#define NVREG_TXRXCTL_IDLE 0x0008
#define NVREG_TXRXCTL_RESET 0x0010
#define NVREG_TXRXCTL_RXCHECK 0x0400
NvRegMIIStatus
=
0x180
,
#define NVREG_MIISTAT_ERROR 0x0001
#define NVREG_MIISTAT_LINKCHANGE 0x0008
...
...
@@ -313,6 +317,10 @@ struct ring_desc {
#define NV_RX_ERROR (1<<30)
#define NV_RX_AVAIL (1<<31)
#define NV_RX2_CHECKSUMMASK (0x1C000000)
#define NV_RX2_CHECKSUMOK1 (0x10000000)
#define NV_RX2_CHECKSUMOK2 (0x14000000)
#define NV_RX2_CHECKSUMOK3 (0x18000000)
#define NV_RX2_DESCRIPTORVALID (1<<29)
#define NV_RX2_SUBSTRACT1 (1<<25)
#define NV_RX2_ERROR1 (1<<18)
...
...
@@ -371,8 +379,15 @@ struct ring_desc {
#define POLL_WAIT (1+HZ/100)
#define LINK_TIMEOUT (3*HZ)
/*
* desc_ver values:
* This field has two purposes:
* - Newer nics uses a different ring layout. The layout is selected by
* comparing np->desc_ver with DESC_VER_xy.
* - It contains bits that are forced on when writing to NvRegTxRxControl.
*/
#define DESC_VER_1 0x0
#define DESC_VER_2
0x02100
#define DESC_VER_2
(0x02100|NVREG_TXRXCTL_RXCHECK)
/* PHY defines */
#define PHY_OUI_MARVELL 0x5043
...
...
@@ -1142,6 +1157,15 @@ static void nv_rx_process(struct net_device *dev)
goto
next_pkt
;
}
}
Flags
&=
NV_RX2_CHECKSUMMASK
;
if
(
Flags
==
NV_RX2_CHECKSUMOK1
||
Flags
==
NV_RX2_CHECKSUMOK2
||
Flags
==
NV_RX2_CHECKSUMOK3
)
{
dprintk
(
KERN_DEBUG
"%s: hw checksum hit!.
\n
"
,
dev
->
name
);
np
->
rx_skbuff
[
i
]
->
ip_summed
=
CHECKSUM_UNNECESSARY
;
}
else
{
dprintk
(
KERN_DEBUG
"%s: hwchecksum miss!.
\n
"
,
dev
->
name
);
}
}
/* got a valid packet - forward it to the network core */
skb
=
np
->
rx_skbuff
[
i
];
...
...
@@ -1634,9 +1658,10 @@ static int nv_close(struct net_device *dev)
spin_lock_irq
(
&
np
->
lock
);
nv_stop_tx
(
dev
);
nv_stop_rx
(
dev
);
base
=
get_hwbase
(
dev
);
nv_txrx_reset
(
dev
);
/* disable interrupts on the nic or we will lock up */
base
=
get_hwbase
(
dev
);
writel
(
0
,
base
+
NvRegIrqMask
);
pci_push
(
base
);
dprintk
(
KERN_INFO
"%s: Irqmask is zero again
\n
"
,
dev
->
name
);
...
...
drivers/net/sis900.c
View file @
74f54248
...
...
@@ -140,9 +140,9 @@ struct mii_phy {
};
typedef
struct
_BufferDesc
{
u32
link
;
u32
cmdsts
;
u32
bufptr
;
u32
link
;
u32
cmdsts
;
u32
bufptr
;
}
BufferDesc
;
struct
sis900_private
{
...
...
@@ -156,7 +156,7 @@ struct sis900_private {
unsigned
int
cur_phy
;
struct
timer_list
timer
;
/* Link status detection timer. */
u8
autong_complete
;
/* 1: auto-negotiate complete */
u8
autong_complete
;
/* 1: auto-negotiate complete */
unsigned
int
cur_rx
,
dirty_rx
;
/* producer/comsumer pointers for Tx/Rx ring */
unsigned
int
cur_tx
,
dirty_tx
;
...
...
@@ -170,7 +170,7 @@ struct sis900_private {
dma_addr_t
tx_ring_dma
;
dma_addr_t
rx_ring_dma
;
unsigned
int
tx_full
;
/* The Tx queue is full.
*/
unsigned
int
tx_full
;
/* The Tx queue is full.
*/
u8
host_bridge_rev
;
};
...
...
@@ -255,7 +255,8 @@ static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_de
* MAC address is read into @net_dev->dev_addr.
*/
static
int
__devinit
sis630e_get_mac_addr
(
struct
pci_dev
*
pci_dev
,
struct
net_device
*
net_dev
)
static
int
__devinit
sis630e_get_mac_addr
(
struct
pci_dev
*
pci_dev
,
struct
net_device
*
net_dev
)
{
struct
pci_dev
*
isa_bridge
=
NULL
;
u8
reg
;
...
...
@@ -292,7 +293,8 @@ static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev, struct net_d
* @net_dev->dev_addr.
*/
static
int
__devinit
sis635_get_mac_addr
(
struct
pci_dev
*
pci_dev
,
struct
net_device
*
net_dev
)
static
int
__devinit
sis635_get_mac_addr
(
struct
pci_dev
*
pci_dev
,
struct
net_device
*
net_dev
)
{
long
ioaddr
=
net_dev
->
base_addr
;
u32
rfcrSave
;
...
...
@@ -334,7 +336,8 @@ static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev, struct net_de
* MAC address is read into @net_dev->dev_addr.
*/
static
int
__devinit
sis96x_get_mac_addr
(
struct
pci_dev
*
pci_dev
,
struct
net_device
*
net_dev
)
static
int
__devinit
sis96x_get_mac_addr
(
struct
pci_dev
*
pci_dev
,
struct
net_device
*
net_dev
)
{
long
ioaddr
=
net_dev
->
base_addr
;
long
ee_addr
=
ioaddr
+
mear
;
...
...
@@ -371,7 +374,8 @@ static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev, struct net_de
* ie: sis900_open(), sis900_start_xmit(), sis900_close(), etc.
*/
static
int
__devinit
sis900_probe
(
struct
pci_dev
*
pci_dev
,
const
struct
pci_device_id
*
pci_id
)
static
int
__devinit
sis900_probe
(
struct
pci_dev
*
pci_dev
,
const
struct
pci_device_id
*
pci_id
)
{
struct
sis900_private
*
sis_priv
;
struct
net_device
*
net_dev
;
...
...
@@ -522,7 +526,7 @@ static int __devinit sis900_probe (struct pci_dev *pci_dev, const struct pci_dev
* return error if it failed to found.
*/
static
int
__init
sis900_mii_probe
(
struct
net_device
*
net_dev
)
static
int
__init
sis900_mii_probe
(
struct
net_device
*
net_dev
)
{
struct
sis900_private
*
sis_priv
=
net_dev
->
priv
;
u16
poll_bit
=
MII_STAT_LINK
,
status
=
0
;
...
...
@@ -572,9 +576,10 @@ static int __init sis900_mii_probe (struct net_device * net_dev)
mii_phy
->
phy_types
=
mii_chip_table
[
i
].
phy_types
;
if
(
mii_chip_table
[
i
].
phy_types
==
MIX
)
mii_phy
->
phy_types
=
(
mii_status
&
(
MII_STAT_CAN_TX_FDX
|
MII_STAT_CAN_TX
))
?
LAN
:
HOME
;
(
mii_status
&
(
MII_STAT_CAN_TX_FDX
|
MII_STAT_CAN_TX
))
?
LAN
:
HOME
;
printk
(
KERN_INFO
"%s: %s transceiver found at address %d.
\n
"
,
net_dev
->
name
,
mii_chip_table
[
i
].
name
,
phy_addr
);
net_dev
->
name
,
mii_chip_table
[
i
].
name
,
phy_addr
);
break
;
}
...
...
@@ -587,7 +592,7 @@ static int __init sis900_mii_probe (struct net_device * net_dev)
if
(
sis_priv
->
mii
==
NULL
)
{
printk
(
KERN_INFO
"%s: No MII transceivers found!
\n
"
,
net_dev
->
name
);
net_dev
->
name
);
return
0
;
}
...
...
@@ -611,7 +616,8 @@ static int __init sis900_mii_probe (struct net_device * net_dev)
poll_bit
^=
(
mdio_read
(
net_dev
,
sis_priv
->
cur_phy
,
MII_STATUS
)
&
poll_bit
);
if
(
time_after_eq
(
jiffies
,
timeout
))
{
printk
(
KERN_WARNING
"%s: reset phy and link down now
\n
"
,
net_dev
->
name
);
printk
(
KERN_WARNING
"%s: reset phy and link down now
\n
"
,
net_dev
->
name
);
return
-
ETIME
;
}
}
...
...
@@ -647,38 +653,41 @@ static int __init sis900_mii_probe (struct net_device * net_dev)
static
u16
sis900_default_phy
(
struct
net_device
*
net_dev
)
{
struct
sis900_private
*
sis_priv
=
net_dev
->
priv
;
struct
mii_phy
*
phy
=
NULL
,
*
phy_home
=
NULL
,
*
default_phy
=
NULL
,
*
phy_lan
=
NULL
;
struct
mii_phy
*
phy
=
NULL
,
*
phy_home
=
NULL
,
*
default_phy
=
NULL
,
*
phy_lan
=
NULL
;
u16
status
;
for
(
phy
=
sis_priv
->
first_mii
;
phy
;
phy
=
phy
->
next
)
{
for
(
phy
=
sis_priv
->
first_mii
;
phy
;
phy
=
phy
->
next
)
{
status
=
mdio_read
(
net_dev
,
phy
->
phy_addr
,
MII_STATUS
);
status
=
mdio_read
(
net_dev
,
phy
->
phy_addr
,
MII_STATUS
);
/* Link ON & Not select default PHY & not ghost PHY */
if
(
(
status
&
MII_STAT_LINK
)
&&
!
default_phy
&&
(
phy
->
phy_types
!=
UNKNOWN
)
)
if
((
status
&
MII_STAT_LINK
)
&&
!
default_phy
&&
(
phy
->
phy_types
!=
UNKNOWN
))
default_phy
=
phy
;
else
{
else
{
status
=
mdio_read
(
net_dev
,
phy
->
phy_addr
,
MII_CONTROL
);
mdio_write
(
net_dev
,
phy
->
phy_addr
,
MII_CONTROL
,
status
|
MII_CNTL_AUTO
|
MII_CNTL_ISOLATE
);
if
(
phy
->
phy_types
==
HOME
)
if
(
phy
->
phy_types
==
HOME
)
phy_home
=
phy
;
else
if
(
phy
->
phy_types
==
LAN
)
else
if
(
phy
->
phy_types
==
LAN
)
phy_lan
=
phy
;
}
}
if
(
!
default_phy
&&
phy_home
)
if
(
!
default_phy
&&
phy_home
)
default_phy
=
phy_home
;
else
if
(
!
default_phy
&&
phy_lan
)
else
if
(
!
default_phy
&&
phy_lan
)
default_phy
=
phy_lan
;
else
if
(
!
default_phy
)
else
if
(
!
default_phy
)
default_phy
=
sis_priv
->
first_mii
;
if
(
sis_priv
->
mii
!=
default_phy
)
{
if
(
sis_priv
->
mii
!=
default_phy
)
{
sis_priv
->
mii
=
default_phy
;
sis_priv
->
cur_phy
=
default_phy
->
phy_addr
;
printk
(
KERN_INFO
"%s: Using transceiver found at address %d as default
\n
"
,
net_dev
->
name
,
sis_priv
->
cur_phy
);
printk
(
KERN_INFO
"%s: Using transceiver found at address %d as default
\n
"
,
net_dev
->
name
,
sis_priv
->
cur_phy
);
}
status
=
mdio_read
(
net_dev
,
sis_priv
->
cur_phy
,
MII_CONTROL
);
...
...
@@ -701,7 +710,7 @@ static u16 sis900_default_phy(struct net_device * net_dev)
* mii status register. It's necessary before auto-negotiate.
*/
static
void
sis900_set_capability
(
struct
net_device
*
net_dev
,
struct
mii_phy
*
phy
)
static
void
sis900_set_capability
(
struct
net_device
*
net_dev
,
struct
mii_phy
*
phy
)
{
u16
cap
;
u16
status
;
...
...
@@ -851,7 +860,8 @@ static u16 mdio_read(struct net_device *net_dev, int phy_id, int location)
* please see SiS7014 or ICS spec
*/
static
void
mdio_write
(
struct
net_device
*
net_dev
,
int
phy_id
,
int
location
,
int
value
)
static
void
mdio_write
(
struct
net_device
*
net_dev
,
int
phy_id
,
int
location
,
int
value
)
{
long
mdio_addr
=
net_dev
->
base_addr
+
mear
;
int
mii_cmd
=
MIIwrite
|
(
phy_id
<<
MIIpmdShift
)
|
(
location
<<
MIIregShift
);
...
...
@@ -939,7 +949,8 @@ sis900_open(struct net_device *net_dev)
pci_read_config_byte
(
sis_priv
->
pci_dev
,
PCI_CLASS_REVISION
,
&
revision
);
sis630_set_eq
(
net_dev
,
revision
);
ret
=
request_irq
(
net_dev
->
irq
,
&
sis900_interrupt
,
SA_SHIRQ
,
net_dev
->
name
,
net_dev
);
ret
=
request_irq
(
net_dev
->
irq
,
&
sis900_interrupt
,
SA_SHIRQ
,
net_dev
->
name
,
net_dev
);
if
(
ret
)
return
ret
;
...
...
@@ -1136,48 +1147,55 @@ static void sis630_set_eq(struct net_device *net_dev, u8 revision)
return
;
if
(
netif_carrier_ok
(
net_dev
))
{
reg14h
=
mdio_read
(
net_dev
,
sis_priv
->
cur_phy
,
MII_RESV
);
mdio_write
(
net_dev
,
sis_priv
->
cur_phy
,
MII_RESV
,
(
0x2200
|
reg14h
)
&
0xBFFF
);
reg14h
=
mdio_read
(
net_dev
,
sis_priv
->
cur_phy
,
MII_RESV
);
mdio_write
(
net_dev
,
sis_priv
->
cur_phy
,
MII_RESV
,
(
0x2200
|
reg14h
)
&
0xBFFF
);
for
(
i
=
0
;
i
<
maxcount
;
i
++
)
{
eq_value
=
(
0x00F8
&
mdio_read
(
net_dev
,
sis_priv
->
cur_phy
,
MII_RESV
))
>>
3
;
eq_value
=
(
0x00F8
&
mdio_read
(
net_dev
,
sis_priv
->
cur_phy
,
MII_RESV
))
>>
3
;
if
(
i
==
0
)
max_value
=
min_value
=
eq_value
;
max_value
=
(
eq_value
>
max_value
)
?
eq_value
:
max_value
;
min_value
=
(
eq_value
<
min_value
)
?
eq_value
:
min_value
;
max_value
=
(
eq_value
>
max_value
)
?
eq_value
:
max_value
;
min_value
=
(
eq_value
<
min_value
)
?
eq_value
:
min_value
;
}
/* 630E rule to determine the equalizer value */
if
(
revision
==
SIS630E_900_REV
||
revision
==
SIS630EA1_900_REV
||
revision
==
SIS630ET_900_REV
)
{
if
(
max_value
<
5
)
eq_value
=
max_value
;
eq_value
=
max_value
;
else
if
(
max_value
>=
5
&&
max_value
<
15
)
eq_value
=
(
max_value
==
min_value
)
?
max_value
+
2
:
max_value
+
1
;
eq_value
=
(
max_value
==
min_value
)
?
max_value
+
2
:
max_value
+
1
;
else
if
(
max_value
>=
15
)
eq_value
=
(
max_value
==
min_value
)
?
max_value
+
6
:
max_value
+
5
;
eq_value
=
(
max_value
==
min_value
)
?
max_value
+
6
:
max_value
+
5
;
}
/* 630B0&B1 rule to determine the equalizer value */
if
(
revision
==
SIS630A_900_REV
&&
(
sis_priv
->
host_bridge_rev
==
SIS630B0
||
sis_priv
->
host_bridge_rev
==
SIS630B1
))
{
if
(
max_value
==
0
)
eq_value
=
3
;
eq_value
=
3
;
else
eq_value
=
(
max_value
+
min_value
+
1
)
/
2
;
eq_value
=
(
max_value
+
min_value
+
1
)
/
2
;
}
/* write equalizer value and setting */
reg14h
=
mdio_read
(
net_dev
,
sis_priv
->
cur_phy
,
MII_RESV
);
reg14h
=
(
reg14h
&
0xFF07
)
|
((
eq_value
<<
3
)
&
0x00F8
);
reg14h
=
(
reg14h
|
0x6000
)
&
0xFDFF
;
reg14h
=
mdio_read
(
net_dev
,
sis_priv
->
cur_phy
,
MII_RESV
);
reg14h
=
(
reg14h
&
0xFF07
)
|
((
eq_value
<<
3
)
&
0x00F8
);
reg14h
=
(
reg14h
|
0x6000
)
&
0xFDFF
;
mdio_write
(
net_dev
,
sis_priv
->
cur_phy
,
MII_RESV
,
reg14h
);
}
else
{
reg14h
=
mdio_read
(
net_dev
,
sis_priv
->
cur_phy
,
MII_RESV
);
}
else
{
reg14h
=
mdio_read
(
net_dev
,
sis_priv
->
cur_phy
,
MII_RESV
);
if
(
revision
==
SIS630A_900_REV
&&
(
sis_priv
->
host_bridge_rev
==
SIS630B0
||
sis_priv
->
host_bridge_rev
==
SIS630B1
))
mdio_write
(
net_dev
,
sis_priv
->
cur_phy
,
MII_RESV
,
(
reg14h
|
0x2200
)
&
0xBFFF
);
mdio_write
(
net_dev
,
sis_priv
->
cur_phy
,
MII_RESV
,
(
reg14h
|
0x2200
)
&
0xBFFF
);
else
mdio_write
(
net_dev
,
sis_priv
->
cur_phy
,
MII_RESV
,
(
reg14h
|
0x2000
)
&
0xBFFF
);
mdio_write
(
net_dev
,
sis_priv
->
cur_phy
,
MII_RESV
,
(
reg14h
|
0x2000
)
&
0xBFFF
);
}
return
;
}
...
...
@@ -1205,7 +1223,8 @@ static void sis900_timer(unsigned long data)
sis900_read_mode
(
net_dev
,
&
speed
,
&
duplex
);
if
(
duplex
){
sis900_set_mode
(
net_dev
->
base_addr
,
speed
,
duplex
);
pci_read_config_byte
(
sis_priv
->
pci_dev
,
PCI_CLASS_REVISION
,
&
revision
);
pci_read_config_byte
(
sis_priv
->
pci_dev
,
PCI_CLASS_REVISION
,
&
revision
);
sis630_set_eq
(
net_dev
,
revision
);
netif_start_queue
(
net_dev
);
}
...
...
@@ -1229,9 +1248,8 @@ static void sis900_timer(unsigned long data)
sis900_check_mode
(
net_dev
,
mii_phy
);
netif_carrier_on
(
net_dev
);
}
}
}
else
{
/* Link ON -> OFF */
else
{
if
(
!
(
status
&
MII_STAT_LINK
)){
netif_carrier_off
(
net_dev
);
printk
(
KERN_INFO
"%s: Media Link Off
\n
"
,
net_dev
->
name
);
...
...
@@ -1241,7 +1259,8 @@ static void sis900_timer(unsigned long data)
((
mii_phy
->
phy_id1
&
0xFFF0
)
==
0x8000
))
sis900_reset_phy
(
net_dev
,
sis_priv
->
cur_phy
);
pci_read_config_byte
(
sis_priv
->
pci_dev
,
PCI_CLASS_REVISION
,
&
revision
);
pci_read_config_byte
(
sis_priv
->
pci_dev
,
PCI_CLASS_REVISION
,
&
revision
);
sis630_set_eq
(
net_dev
,
revision
);
goto
LookForLink
;
...
...
@@ -1264,18 +1283,18 @@ static void sis900_timer(unsigned long data)
* and autong_complete should be set to 1.
*/
static
void
sis900_check_mode
(
struct
net_device
*
net_dev
,
struct
mii_phy
*
mii_phy
)
static
void
sis900_check_mode
(
struct
net_device
*
net_dev
,
struct
mii_phy
*
mii_phy
)
{
struct
sis900_private
*
sis_priv
=
net_dev
->
priv
;
long
ioaddr
=
net_dev
->
base_addr
;
int
speed
,
duplex
;
if
(
mii_phy
->
phy_types
==
LAN
)
{
outl
(
~
EXD
&
inl
(
ioaddr
+
cfg
),
ioaddr
+
cfg
);
if
(
mii_phy
->
phy_types
==
LAN
)
{
outl
(
~
EXD
&
inl
(
ioaddr
+
cfg
),
ioaddr
+
cfg
);
sis900_set_capability
(
net_dev
,
mii_phy
);
sis900_auto_negotiate
(
net_dev
,
sis_priv
->
cur_phy
);
}
else
{
outl
(
EXD
|
inl
(
ioaddr
+
cfg
),
ioaddr
+
cfg
);
}
else
{
outl
(
EXD
|
inl
(
ioaddr
+
cfg
),
ioaddr
+
cfg
);
speed
=
HW_SPEED_HOME
;
duplex
=
FDX_CAPABLE_HALF_SELECTED
;
sis900_set_mode
(
ioaddr
,
speed
,
duplex
);
...
...
@@ -1300,20 +1319,20 @@ static void sis900_set_mode (long ioaddr, int speed, int duplex)
{
u32
tx_flags
=
0
,
rx_flags
=
0
;
if
(
inl
(
ioaddr
+
cfg
)
&
EDB_MASTER_EN
){
tx_flags
=
TxATP
|
(
DMA_BURST_64
<<
TxMXDMA_shift
)
|
(
TX_FILL_THRESH
<<
TxFILLT_shift
);
if
(
inl
(
ioaddr
+
cfg
)
&
EDB_MASTER_EN
)
{
tx_flags
=
TxATP
|
(
DMA_BURST_64
<<
TxMXDMA_shift
)
|
(
TX_FILL_THRESH
<<
TxFILLT_shift
);
rx_flags
=
DMA_BURST_64
<<
RxMXDMA_shift
;
}
else
{
tx_flags
=
TxATP
|
(
DMA_BURST_512
<<
TxMXDMA_shift
)
|
(
TX_FILL_THRESH
<<
TxFILLT_shift
);
}
else
{
tx_flags
=
TxATP
|
(
DMA_BURST_512
<<
TxMXDMA_shift
)
|
(
TX_FILL_THRESH
<<
TxFILLT_shift
);
rx_flags
=
DMA_BURST_512
<<
RxMXDMA_shift
;
}
if
(
speed
==
HW_SPEED_HOME
||
speed
==
HW_SPEED_10_MBPS
)
{
if
(
speed
==
HW_SPEED_HOME
||
speed
==
HW_SPEED_10_MBPS
)
{
rx_flags
|=
(
RxDRNT_10
<<
RxDRNT_shift
);
tx_flags
|=
(
TxDRNT_10
<<
TxDRNT_shift
);
}
else
{
}
else
{
rx_flags
|=
(
RxDRNT_100
<<
RxDRNT_shift
);
tx_flags
|=
(
TxDRNT_100
<<
TxDRNT_shift
);
}
...
...
@@ -1403,19 +1422,19 @@ static void sis900_read_mode(struct net_device *net_dev, int *speed, int *duplex
sis_priv
->
autong_complete
=
1
;
/* Workaround for Realtek RTL8201 PHY issue */
if
((
phy
->
phy_id0
==
0x0000
)
&&
((
phy
->
phy_id1
&
0xFFF0
)
==
0x8200
))
{
if
(
mdio_read
(
net_dev
,
phy_addr
,
MII_CONTROL
)
&
MII_CNTL_FDX
)
if
((
phy
->
phy_id0
==
0x0000
)
&&
((
phy
->
phy_id1
&
0xFFF0
)
==
0x8200
))
{
if
(
mdio_read
(
net_dev
,
phy_addr
,
MII_CONTROL
)
&
MII_CNTL_FDX
)
*
duplex
=
FDX_CAPABLE_FULL_SELECTED
;
if
(
mdio_read
(
net_dev
,
phy_addr
,
0x0019
)
&
0x01
)
if
(
mdio_read
(
net_dev
,
phy_addr
,
0x0019
)
&
0x01
)
*
speed
=
HW_SPEED_100_MBPS
;
}
printk
(
KERN_INFO
"%s: Media Link On %s %s-duplex
\n
"
,
net_dev
->
name
,
*
speed
==
HW_SPEED_100_MBPS
?
"100mbps"
:
"10mbps"
,
*
duplex
==
FDX_CAPABLE_FULL_SELECTED
?
"full"
:
"half"
);
net_dev
->
name
,
*
speed
==
HW_SPEED_100_MBPS
?
"100mbps"
:
"10mbps"
,
*
duplex
==
FDX_CAPABLE_FULL_SELECTED
?
"full"
:
"half"
);
}
/**
...
...
@@ -1677,13 +1696,13 @@ static int sis900_rx(struct net_device *net_dev)
sis_priv
->
stats
.
rx_bytes
+=
rx_size
;
sis_priv
->
stats
.
rx_packets
++
;
/* refill the Rx buffer, what if there is not enought
memory for
new socket buffer ?? */
/* refill the Rx buffer, what if there is not enought
* memory for
new socket buffer ?? */
if
((
skb
=
dev_alloc_skb
(
RX_BUF_SIZE
))
==
NULL
)
{
/* not enough memory for skbuff, this makes a
"hole"
on the buffer ring, it is not clear how the
hardware will react to this kind of degenerate
d
buffer */
/* not enough memory for skbuff, this makes a
* "hole" on the buffer ring, it is not clear
* how the hardware will react to this kin
d
* of degenerated
buffer */
printk
(
KERN_INFO
"%s: Memory squeeze,"
"deferring packet.
\n
"
,
net_dev
->
name
);
...
...
@@ -1707,8 +1726,8 @@ static int sis900_rx(struct net_device *net_dev)
rx_status
=
sis_priv
->
rx_ring
[
entry
].
cmdsts
;
}
// while
/* refill the Rx buffer, what if the rate of refilling is slower
than
consuming ?? */
/* refill the Rx buffer, what if the rate of refilling is slower
* than
consuming ?? */
for
(;
sis_priv
->
cur_rx
-
sis_priv
->
dirty_rx
>
0
;
sis_priv
->
dirty_rx
++
)
{
struct
sk_buff
*
skb
;
...
...
@@ -1716,10 +1735,10 @@ static int sis900_rx(struct net_device *net_dev)
if
(
sis_priv
->
rx_skbuff
[
entry
]
==
NULL
)
{
if
((
skb
=
dev_alloc_skb
(
RX_BUF_SIZE
))
==
NULL
)
{
/* not enough memory for skbuff, this makes a
"hole"
on the buffer ring, it is not clear how the
hardware will react to this kind of degenerated
buffer */
/* not enough memory for skbuff, this makes a
* "hole" on the buffer ring, it is not clear
* how the hardware will react to this kind
* of degenerated
buffer */
printk
(
KERN_INFO
"%s: Memory squeeze,"
"deferring packet.
\n
"
,
net_dev
->
name
);
...
...
@@ -1764,8 +1783,8 @@ static void sis900_finish_xmit (struct net_device *net_dev)
if
(
tx_status
&
OWN
)
{
/* The packet is not transmitted yet (owned by hardware) !
Note: the interrupt is generated only when Tx Machine
is idle, so this is an almost impossible case */
*
Note: the interrupt is generated only when Tx Machine
*
is idle, so this is an almost impossible case */
break
;
}
...
...
@@ -1803,8 +1822,8 @@ static void sis900_finish_xmit (struct net_device *net_dev)
if
(
sis_priv
->
tx_full
&&
netif_queue_stopped
(
net_dev
)
&&
sis_priv
->
cur_tx
-
sis_priv
->
dirty_tx
<
NUM_TX_DESC
-
4
)
{
/* The ring is no longer full, clear tx_full and schedule
more transmission
by netif_wake_queue(net_dev) */
/* The ring is no longer full, clear tx_full and schedule
* more transmission
by netif_wake_queue(net_dev) */
sis_priv
->
tx_full
=
0
;
netif_wake_queue
(
net_dev
);
}
...
...
@@ -1818,8 +1837,7 @@ static void sis900_finish_xmit (struct net_device *net_dev)
* free Tx and RX socket buffer
*/
static
int
sis900_close
(
struct
net_device
*
net_dev
)
static
int
sis900_close
(
struct
net_device
*
net_dev
)
{
long
ioaddr
=
net_dev
->
base_addr
;
struct
sis900_private
*
sis_priv
=
net_dev
->
priv
;
...
...
@@ -1955,27 +1973,28 @@ static int sis900_set_config(struct net_device *dev, struct ifmap *map)
if
((
map
->
port
!=
(
u_char
)(
-
1
))
&&
(
map
->
port
!=
dev
->
if_port
))
{
/* we switch on the ifmap->port field. I couldn't find anything
like a definition or standard for the values of that field.
I think the meaning of those values is device specific. But
since I would like to change the media type via the ifconfig
command I use the definition from linux/netdevice.h
(which seems to be different from the ifport(pcmcia) definition)
*/
* like a definition or standard for the values of that field.
* I think the meaning of those values is device specific. But
* since I would like to change the media type via the ifconfig
* command I use the definition from linux/netdevice.h
* (which seems to be different from the ifport(pcmcia) definition) */
switch
(
map
->
port
){
case
IF_PORT_UNKNOWN
:
/* use auto here */
dev
->
if_port
=
map
->
port
;
/* we are going to change the media type, so the Link will
be temporary down and we need to reflect that here. When
the Link comes up again, it will be sensed by the sis_timer
procedure, which also does all the rest for us */
/* we are going to change the media type, so the Link
* will be temporary down and we need to reflect that
* here. When the Link comes up again, it will be
* sensed by the sis_timer procedure, which also does
* all the rest for us */
netif_carrier_off
(
dev
);
/* read current state */
status
=
mdio_read
(
dev
,
mii_phy
->
phy_addr
,
MII_CONTROL
);
/* enable auto negotiation and reset the negotioation
(I don't really know what the auto negatiotiation reset
really means, but it sounds for me right to do one here)*/
* (I don't really know what the auto negatiotiation
* reset really means, but it sounds for me right to
* do one here) */
mdio_write
(
dev
,
mii_phy
->
phy_addr
,
MII_CONTROL
,
status
|
MII_CNTL_AUTO
|
MII_CNTL_RST_AUTO
);
...
...
@@ -1984,10 +2003,11 @@ static int sis900_set_config(struct net_device *dev, struct ifmap *map)
case
IF_PORT_10BASET
:
/* 10BaseT */
dev
->
if_port
=
map
->
port
;
/* we are going to change the media type, so the Link will
be temporary down and we need to reflect that here. When
the Link comes up again, it will be sensed by the sis_timer
procedure, which also does all the rest for us */
/* we are going to change the media type, so the Link
* will be temporary down and we need to reflect that
* here. When the Link comes up again, it will be
* sensed by the sis_timer procedure, which also does
* all the rest for us */
netif_carrier_off
(
dev
);
/* set Speed to 10Mbps */
...
...
@@ -1996,24 +2016,27 @@ static int sis900_set_config(struct net_device *dev, struct ifmap *map)
/* disable auto negotiation and force 10MBit mode*/
mdio_write
(
dev
,
mii_phy
->
phy_addr
,
MII_CONTROL
,
status
&
~
(
MII_CNTL_SPEED
|
MII_CNTL_AUTO
));
MII_CONTROL
,
status
&
~
(
MII_CNTL_SPEED
|
MII_CNTL_AUTO
));
break
;
case
IF_PORT_100BASET
:
/* 100BaseT */
case
IF_PORT_100BASETX
:
/* 100BaseTx */
dev
->
if_port
=
map
->
port
;
/* we are going to change the media type, so the Link will
be temporary down and we need to reflect that here. When
the Link comes up again, it will be sensed by the sis_timer
procedure, which also does all the rest for us */
/* we are going to change the media type, so the Link
* will be temporary down and we need to reflect that
* here. When the Link comes up again, it will be
* sensed by the sis_timer procedure, which also does
* all the rest for us */
netif_carrier_off
(
dev
);
/* set Speed to 100Mbps */
/* disable auto negotiation and enable 100MBit Mode */
status
=
mdio_read
(
dev
,
mii_phy
->
phy_addr
,
MII_CONTROL
);
mdio_write
(
dev
,
mii_phy
->
phy_addr
,
MII_CONTROL
,
(
status
&
~
MII_CNTL_SPEED
)
|
MII_CNTL_SPEED
);
MII_CONTROL
,
(
status
&
~
MII_CNTL_SPEED
)
|
MII_CNTL_SPEED
);
break
;
...
...
@@ -2093,12 +2116,14 @@ static void set_rx_mode(struct net_device *net_dev)
for
(
i
=
0
;
i
<
table_entries
;
i
++
)
mc_filter
[
i
]
=
0xffff
;
}
else
{
/* Accept Broadcast packet, destination address matchs our MAC address,
use Receive Filter to reject unwanted MCAST packet */
/* Accept Broadcast packet, destination address matchs our
* MAC address, use Receive Filter to reject unwanted MCAST
* packets */
struct
dev_mc_list
*
mclist
;
rx_mode
=
RFAAB
;
for
(
i
=
0
,
mclist
=
net_dev
->
mc_list
;
mclist
&&
i
<
net_dev
->
mc_count
;
i
++
,
mclist
=
mclist
->
next
)
{
for
(
i
=
0
,
mclist
=
net_dev
->
mc_list
;
mclist
&&
i
<
net_dev
->
mc_count
;
i
++
,
mclist
=
mclist
->
next
)
{
unsigned
int
bit_nr
=
sis900_mcast_bitnr
(
mclist
->
dmi_addr
,
revision
);
mc_filter
[
bit_nr
>>
4
]
|=
(
1
<<
(
bit_nr
&
0xf
));
...
...
@@ -2114,7 +2139,8 @@ static void set_rx_mode(struct net_device *net_dev)
outl
(
RFEN
|
rx_mode
,
ioaddr
+
rfcr
);
/* sis900 is capatable of looping back packet at MAC level for debugging purpose */
/* sis900 is capable of looping back packets at MAC level for
* debugging purpose */
if
(
net_dev
->
flags
&
IFF_LOOPBACK
)
{
u32
cr_saved
;
/* We must disable Tx/Rx before setting loopback mode */
...
...
drivers/net/smc91x.c
View file @
74f54248
...
...
@@ -55,12 +55,10 @@
* smc_phy_configure
* - clean up (and fix stack overrun) in PHY
* MII read/write functions
* 09/15/04 Hayato Fujiwara - Add m32r support.
* - Modify for SMP kernel; Change spin-locked
* regions.
* 22/09/04 Nicolas Pitre big update (see commit log for details)
*/
static
const
char
version
[]
=
"smc91x.c: v1.
0, mar 07 2003
by Nicolas Pitre <nico@cam.org>
\n
"
;
"smc91x.c: v1.
1, sep 22 2004
by Nicolas Pitre <nico@cam.org>
\n
"
;
/* Debugging level */
#ifndef SMC_DEBUG
...
...
@@ -75,7 +73,7 @@ static const char version[] =
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/
timer
.h>
#include <linux/
interrupt
.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/crc32.h>
...
...
@@ -83,6 +81,7 @@ static const char version[] =
#include <linux/spinlock.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/workqueue.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
...
...
@@ -177,7 +176,8 @@ struct smc_local {
* packet, I will store the skbuff here, until I get the
* desired memory. Then, I'll send it out and free it.
*/
struct
sk_buff
*
saved_skb
;
struct
sk_buff
*
pending_tx_skb
;
struct
tasklet_struct
tx_task
;
/*
* these are things that the kernel wants me to keep, so users
...
...
@@ -203,6 +203,8 @@ struct smc_local {
u32
msg_enable
;
u32
phy_type
;
struct
mii_if_info
mii
;
struct
work_struct
phy_configure
;
spinlock_t
lock
;
#ifdef SMC_USE_PXA_DMA
...
...
@@ -215,7 +217,7 @@ struct smc_local {
#define DBG(n, args...) \
do { \
if (SMC_DEBUG >= (n)) \
printk(
KERN_DEBUG
args); \
printk(args); \
} while (0)
#define PRINTK(args...) printk(args)
...
...
@@ -260,17 +262,21 @@ static void PRINT_PKT(u_char *buf, int length)
/* this enables an interrupt in the interrupt mask register */
#define SMC_ENABLE_INT(x) do { \
unsigned char mask; \
spin_lock_irq(&lp->lock); \
mask = SMC_GET_INT_MASK(); \
mask |= (x); \
SMC_SET_INT_MASK(mask); \
spin_unlock_irq(&lp->lock); \
} while (0)
/* this disables an interrupt from the interrupt mask register */
#define SMC_DISABLE_INT(x) do { \
unsigned char mask; \
spin_lock_irq(&lp->lock); \
mask = SMC_GET_INT_MASK(); \
mask &= ~(x); \
SMC_SET_INT_MASK(mask); \
spin_unlock_irq(&lp->lock); \
} while (0)
/*
...
...
@@ -299,10 +305,17 @@ static void PRINT_PKT(u_char *buf, int length)
static
void
smc_reset
(
struct
net_device
*
dev
)
{
unsigned
long
ioaddr
=
dev
->
base_addr
;
struct
smc_local
*
lp
=
netdev_priv
(
dev
);
unsigned
int
ctl
,
cfg
;
DBG
(
2
,
"%s: %s
\n
"
,
dev
->
name
,
__FUNCTION__
);
/* Disable all interrupts */
spin_lock
(
&
lp
->
lock
);
SMC_SELECT_BANK
(
2
);
SMC_SET_INT_MASK
(
0
);
spin_unlock
(
&
lp
->
lock
);
/*
* This resets the registers mostly to defaults, but doesn't
* affect EEPROM. That seems unnecessary
...
...
@@ -358,20 +371,24 @@ static void smc_reset(struct net_device *dev)
* transmitted packets, to make the best use out of our limited
* memory
*/
#if ! THROTTLE_TX_PKTS
ctl
|=
CTL_AUTO_RELEASE
;
#else
ctl
&=
~
CTL_AUTO_RELEASE
;
#endif
if
(
!
THROTTLE_TX_PKTS
)
ctl
|=
CTL_AUTO_RELEASE
;
else
ctl
&=
~
CTL_AUTO_RELEASE
;
SMC_SET_CTL
(
ctl
);
/* Disable all interrupts */
SMC_SELECT_BANK
(
2
);
SMC_SET_INT_MASK
(
0
);
/* Reset the MMU */
SMC_SELECT_BANK
(
2
);
SMC_SET_MMU_CMD
(
MC_RESET
);
SMC_WAIT_MMU_BUSY
();
/* clear anything saved */
if
(
lp
->
pending_tx_skb
!=
NULL
)
{
dev_kfree_skb
(
lp
->
pending_tx_skb
);
lp
->
pending_tx_skb
=
NULL
;
lp
->
stats
.
tx_errors
++
;
lp
->
stats
.
tx_aborted_errors
++
;
}
}
/*
...
...
@@ -390,24 +407,39 @@ static void smc_enable(struct net_device *dev)
SMC_SET_TCR
(
lp
->
tcr_cur_mode
);
SMC_SET_RCR
(
lp
->
rcr_cur_mode
);
SMC_SELECT_BANK
(
1
);
SMC_SET_MAC_ADDR
(
dev
->
dev_addr
);
/* now, enable interrupts */
mask
=
IM_EPH_INT
|
IM_RX_OVRN_INT
|
IM_RCV_INT
;
if
(
lp
->
version
>=
(
CHIP_91100
<<
4
))
mask
|=
IM_MDINT
;
SMC_SELECT_BANK
(
2
);
SMC_SET_INT_MASK
(
mask
);
/*
* From this point the register bank must _NOT_ be switched away
* to something else than bank 2 without proper locking against
* races with any tasklet or interrupt handlers until smc_shutdown()
* or smc_reset() is called.
*/
}
/*
* this puts the device in an inactive state
*/
static
void
smc_shutdown
(
unsigned
long
ioaddr
)
static
void
smc_shutdown
(
struct
net_device
*
dev
)
{
unsigned
long
ioaddr
=
dev
->
base_addr
;
struct
smc_local
*
lp
=
netdev_priv
(
dev
);
DBG
(
2
,
"%s: %s
\n
"
,
CARDNAME
,
__FUNCTION__
);
/* no more interrupts for me */
spin_lock
(
&
lp
->
lock
);
SMC_SELECT_BANK
(
2
);
SMC_SET_INT_MASK
(
0
);
spin_unlock
(
&
lp
->
lock
);
/* and tell the card to stay away from that nasty outside world */
SMC_SELECT_BANK
(
0
);
...
...
@@ -449,6 +481,8 @@ static inline void smc_rcv(struct net_device *dev)
packet_len
,
packet_len
);
if
(
unlikely
(
status
&
RS_ERRORS
))
{
SMC_WAIT_MMU_BUSY
();
SMC_SET_MMU_CMD
(
MC_RELEASE
);
lp
->
stats
.
rx_errors
++
;
if
(
status
&
RS_ALGNERR
)
lp
->
stats
.
rx_frame_errors
++
;
...
...
@@ -466,17 +500,21 @@ static inline void smc_rcv(struct net_device *dev)
lp
->
stats
.
multicast
++
;
/*
* Actual payload is packet_len -
4 (or 3
if odd byte).
* Actual payload is packet_len -
6 (or 5
if odd byte).
* We want skb_reserve(2) and the final ctrl word
* (2 bytes, possibly containing the payload odd byte).
* Ence packet_len - 4 + 2 + 2.
* Furthermore, we add 2 bytes to allow rounding up to
* multiple of 4 bytes on 32 bit buses.
* Ence packet_len - 6 + 2 + 2 + 2.
*/
skb
=
dev_alloc_skb
(
packet_len
);
if
(
unlikely
(
skb
==
NULL
))
{
printk
(
KERN_NOTICE
"%s: Low memory, packet dropped.
\n
"
,
dev
->
name
);
SMC_WAIT_MMU_BUSY
();
SMC_SET_MMU_CMD
(
MC_RELEASE
);
lp
->
stats
.
rx_dropped
++
;
goto
done
;
return
;
}
/* Align IP header to 32 bits */
...
...
@@ -487,14 +525,18 @@ static inline void smc_rcv(struct net_device *dev)
status
|=
RS_ODDFRAME
;
/*
* If odd length: packet_len - 3,
* otherwise packet_len - 4.
* If odd length: packet_len - 5,
* otherwise packet_len - 6.
* With the trailing ctrl byte it's packet_len - 4.
*/
data_len
=
packet_len
-
((
status
&
RS_ODDFRAME
)
?
3
:
4
);
data_len
=
packet_len
-
((
status
&
RS_ODDFRAME
)
?
5
:
6
);
data
=
skb_put
(
skb
,
data_len
);
SMC_PULL_DATA
(
data
,
packet_len
-
2
);
SMC_PULL_DATA
(
data
,
packet_len
-
4
);
SMC_WAIT_MMU_BUSY
();
SMC_SET_MMU_CMD
(
MC_RELEASE
);
PRINT_PKT
(
data
,
packet_len
-
2
);
PRINT_PKT
(
data
,
packet_len
-
4
);
dev
->
last_rx
=
jiffies
;
skb
->
dev
=
dev
;
...
...
@@ -503,34 +545,76 @@ static inline void smc_rcv(struct net_device *dev)
lp
->
stats
.
rx_packets
++
;
lp
->
stats
.
rx_bytes
+=
data_len
;
}
done:
SMC_WAIT_MMU_BUSY
();
SMC_SET_MMU_CMD
(
MC_RELEASE
);
}
#ifdef CONFIG_SMP
/*
* On SMP we have the following problem:
*
* A = smc_hardware_send_pkt()
* B = smc_hard_start_xmit()
* C = smc_interrupt()
*
* A and B can never be executed simultaneously. However, at least on UP,
* it is possible (and even desirable) for C to interrupt execution of
* A or B in order to have better RX reliability and avoid overruns.
* C, just like A and B, must have exclusive access to the chip and
* each of them must lock against any other concurrent access.
* Unfortunately this is not possible to have C suspend execution of A or
* B taking place on another CPU. On UP this is no an issue since A and B
* are run from softirq context and C from hard IRQ context, and there is
* no other CPU where concurrent access can happen.
* If ever there is a way to force at least B and C to always be executed
* on the same CPU then we could use read/write locks to protect against
* any other concurrent access and C would always interrupt B. But life
* isn't that easy in a SMP world...
*/
#define smc_special_trylock(lock) \
({ \
int __ret; \
local_irq_disable(); \
__ret = spin_trylock(lock); \
if (!__ret) \
local_irq_enable(); \
__ret; \
})
#define smc_special_lock(lock) spin_lock_irq(lock)
#define smc_special_unlock(lock) spin_unlock_irq(lock)
#else
#define smc_special_trylock(lock) (1)
#define smc_special_lock(lock) do { } while (0)
#define smc_special_unlock(lock) do { } while (0)
#endif
/*
* This is called to actually send a packet to the chip.
* Returns non-zero when successful.
*/
static
void
smc_hardware_send_p
acket
(
struct
net_device
*
dev
)
static
void
smc_hardware_send_p
kt
(
unsigned
long
data
)
{
struct
net_device
*
dev
=
(
struct
net_device
*
)
data
;
struct
smc_local
*
lp
=
netdev_priv
(
dev
);
unsigned
long
ioaddr
=
dev
->
base_addr
;
struct
sk_buff
*
skb
=
lp
->
saved_skb
;
struct
sk_buff
*
skb
;
unsigned
int
packet_no
,
len
;
unsigned
char
*
buf
;
DBG
(
3
,
"%s: %s
\n
"
,
dev
->
name
,
__FUNCTION__
);
if
(
!
smc_special_trylock
(
&
lp
->
lock
))
{
netif_stop_queue
(
dev
);
tasklet_schedule
(
&
lp
->
tx_task
);
return
;
}
skb
=
lp
->
pending_tx_skb
;
lp
->
pending_tx_skb
=
NULL
;
packet_no
=
SMC_GET_AR
();
if
(
unlikely
(
packet_no
&
AR_FAILED
))
{
printk
(
"%s: Memory allocation failed.
\n
"
,
dev
->
name
);
lp
->
saved_skb
=
NULL
;
lp
->
stats
.
tx_errors
++
;
lp
->
stats
.
tx_fifo_errors
++
;
dev_kfree_skb_any
(
skb
);
return
;
smc_special_unlock
(
&
lp
->
lock
);
goto
done
;
}
/* point to the beginning of the packet */
...
...
@@ -555,15 +639,33 @@ static void smc_hardware_send_packet(struct net_device *dev)
/* Send final ctl word with the last byte if there is one */
SMC_outw
(((
len
&
1
)
?
(
0x2000
|
buf
[
len
-
1
])
:
0
),
ioaddr
,
DATA_REG
);
/* and let the chipset deal with it */
/*
* If THROTTLE_TX_PKTS is set, we look at the TX_EMPTY flag
* before queueing this packet for TX, and if it's clear then
* we stop the queue here. This will have the effect of
* having at most 2 packets queued for TX in the chip's memory
* at all time. If THROTTLE_TX_PKTS is not set then the queue
* is stopped only when memory allocation (MC_ALLOC) does not
* succeed right away.
*/
if
(
THROTTLE_TX_PKTS
&&
!
(
SMC_GET_INT
()
&
IM_TX_EMPTY_INT
))
netif_stop_queue
(
dev
);
/* queue the packet for TX */
SMC_SET_MMU_CMD
(
MC_ENQUEUE
);
SMC_ACK_INT
(
IM_TX_EMPTY_INT
);
smc_special_unlock
(
&
lp
->
lock
);
dev
->
trans_start
=
jiffies
;
dev_kfree_skb_any
(
skb
);
lp
->
saved_skb
=
NULL
;
lp
->
stats
.
tx_packets
++
;
lp
->
stats
.
tx_bytes
+=
len
;
SMC_ENABLE_INT
(
IM_TX_INT
|
IM_TX_EMPTY_INT
);
done:
if
(
!
THROTTLE_TX_PKTS
)
netif_wake_queue
(
dev
);
dev_kfree_skb
(
skb
);
}
/*
...
...
@@ -576,15 +678,12 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct
smc_local
*
lp
=
netdev_priv
(
dev
);
unsigned
long
ioaddr
=
dev
->
base_addr
;
unsigned
int
numPages
,
poll_count
,
status
,
saved_bank
;
unsigned
long
flags
;
unsigned
int
numPages
,
poll_count
,
status
;
DBG
(
3
,
"%s: %s
\n
"
,
dev
->
name
,
__FUNCTION__
);
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
BUG_ON
(
lp
->
saved_skb
!=
NULL
);
lp
->
saved_skb
=
skb
;
BUG_ON
(
lp
->
pending_tx_skb
!=
NULL
);
lp
->
pending_tx_skb
=
skb
;
/*
* The MMU wants the number of pages to be the number of 256 bytes
...
...
@@ -600,17 +699,16 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
numPages
=
((
skb
->
len
&
~
1
)
+
(
6
-
1
))
>>
8
;
if
(
unlikely
(
numPages
>
7
))
{
printk
(
"%s: Far too big packet error.
\n
"
,
dev
->
name
);
lp
->
saved
_skb
=
NULL
;
lp
->
pending_tx
_skb
=
NULL
;
lp
->
stats
.
tx_errors
++
;
lp
->
stats
.
tx_dropped
++
;
dev_kfree_skb
(
skb
);
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
return
0
;
}
smc_special_lock
(
&
lp
->
lock
);
/* now, try to allocate the memory */
saved_bank
=
SMC_CURRENT_BANK
();
SMC_SELECT_BANK
(
2
);
SMC_SET_MMU_CMD
(
MC_ALLOC
|
numPages
);
/*
...
...
@@ -626,6 +724,8 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
}
while
(
--
poll_count
);
smc_special_unlock
(
&
lp
->
lock
);
if
(
!
poll_count
)
{
/* oh well, wait until the chip finds memory later */
netif_stop_queue
(
dev
);
...
...
@@ -635,25 +735,10 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
/*
* Allocation succeeded: push packet to the chip's own memory
* immediately.
*
* If THROTTLE_TX_PKTS is selected that means we don't want
* more than a single TX packet taking up space in the chip's
* internal memory at all time, in which case we stop the
* queue right here until we're notified of TX completion.
*
* Otherwise we're quite happy to feed more TX packets right
* away for better TX throughput, in which case the queue is
* left active.
*/
#if THROTTLE_TX_PKTS
netif_stop_queue
(
dev
);
#endif
smc_hardware_send_packet
(
dev
);
SMC_ENABLE_INT
(
IM_TX_INT
|
IM_TX_EMPTY_INT
);
smc_hardware_send_pkt
((
unsigned
long
)
dev
);
}
SMC_SELECT_BANK
(
saved_bank
);
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
return
0
;
}
...
...
@@ -767,10 +852,8 @@ static unsigned int smc_mii_in(struct net_device *dev, int bits)
static
int
smc_phy_read
(
struct
net_device
*
dev
,
int
phyaddr
,
int
phyreg
)
{
unsigned
long
ioaddr
=
dev
->
base_addr
;
unsigned
int
phydata
,
old_bank
;
unsigned
int
phydata
;
/* Save the current bank, and select bank 3 */
old_bank
=
SMC_CURRENT_BANK
();
SMC_SELECT_BANK
(
3
);
/* Idle - 32 ones */
...
...
@@ -785,12 +868,10 @@ static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg)
/* Return to idle state */
SMC_SET_MII
(
SMC_GET_MII
()
&
~
(
MII_MCLK
|
MII_MDOE
|
MII_MDO
));
/* And select original bank */
SMC_SELECT_BANK
(
old_bank
);
DBG
(
3
,
"%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x
\n
"
,
__FUNCTION__
,
phyaddr
,
phyreg
,
phydata
);
SMC_SELECT_BANK
(
2
);
return
phydata
;
}
...
...
@@ -801,10 +882,7 @@ static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg,
int
phydata
)
{
unsigned
long
ioaddr
=
dev
->
base_addr
;
unsigned
int
old_bank
;
/* Save the current bank, and select bank 3 */
old_bank
=
SMC_CURRENT_BANK
();
SMC_SELECT_BANK
(
3
);
/* Idle - 32 ones */
...
...
@@ -816,11 +894,10 @@ static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg,
/* Return to idle state */
SMC_SET_MII
(
SMC_GET_MII
()
&
~
(
MII_MCLK
|
MII_MDOE
|
MII_MDO
));
/* And select original bank */
SMC_SELECT_BANK
(
old_bank
);
DBG
(
3
,
"%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x
\n
"
,
__FUNCTION__
,
phyaddr
,
phyreg
,
phydata
);
SMC_SELECT_BANK
(
2
);
}
/*
...
...
@@ -893,7 +970,9 @@ static int smc_phy_fixed(struct net_device *dev)
smc_phy_write
(
dev
,
phyaddr
,
MII_BMCR
,
bmcr
);
/* Re-Configure the Receive/Phy Control register */
SMC_SELECT_BANK
(
0
);
SMC_SET_RPC
(
lp
->
rpc_cur_mode
);
SMC_SELECT_BANK
(
2
);
return
1
;
}
...
...
@@ -941,13 +1020,10 @@ static int smc_phy_reset(struct net_device *dev, int phy)
*/
static
void
smc_phy_powerdown
(
struct
net_device
*
dev
,
int
phy
)
{
struct
smc_local
*
lp
=
netdev_priv
(
dev
);
unsigned
int
bmcr
;
spin_lock_irq
(
&
lp
->
lock
);
bmcr
=
smc_phy_read
(
dev
,
phy
,
MII_BMCR
);
smc_phy_write
(
dev
,
phy
,
MII_BMCR
,
bmcr
|
BMCR_PDOWN
);
spin_unlock_irq
(
&
lp
->
lock
);
}
/*
...
...
@@ -964,8 +1040,6 @@ static void smc_phy_check_media(struct net_device *dev, int init)
unsigned
long
ioaddr
=
dev
->
base_addr
;
if
(
mii_check_media
(
&
lp
->
mii
,
netif_msg_link
(
lp
),
init
))
{
unsigned
int
old_bank
;
/* duplex state has changed */
if
(
lp
->
mii
.
full_duplex
)
{
lp
->
tcr_cur_mode
|=
TCR_SWFDUP
;
...
...
@@ -973,10 +1047,8 @@ static void smc_phy_check_media(struct net_device *dev, int init)
lp
->
tcr_cur_mode
&=
~
TCR_SWFDUP
;
}
old_bank
=
SMC_CURRENT_BANK
();
SMC_SELECT_BANK
(
0
);
SMC_SET_TCR
(
lp
->
tcr_cur_mode
);
SMC_SELECT_BANK
(
old_bank
);
}
}
...
...
@@ -989,8 +1061,9 @@ static void smc_phy_check_media(struct net_device *dev, int init)
* of autonegotiation.) If the RPC ANEG bit is cleared, the selection
* is controlled by the RPC SPEED and RPC DPLX bits.
*/
static
void
smc_phy_configure
(
struct
net_device
*
dev
)
static
void
smc_phy_configure
(
void
*
data
)
{
struct
net_device
*
dev
=
data
;
struct
smc_local
*
lp
=
netdev_priv
(
dev
);
unsigned
long
ioaddr
=
dev
->
base_addr
;
int
phyaddr
=
lp
->
mii
.
phy_id
;
...
...
@@ -1117,12 +1190,13 @@ static void smc_10bt_check_media(struct net_device *dev, int init)
{
struct
smc_local
*
lp
=
netdev_priv
(
dev
);
unsigned
long
ioaddr
=
dev
->
base_addr
;
unsigned
int
old_carrier
,
new_carrier
,
old_bank
;
unsigned
int
old_carrier
,
new_carrier
;
old_bank
=
SMC_CURRENT_BANK
();
SMC_SELECT_BANK
(
0
);
old_carrier
=
netif_carrier_ok
(
dev
)
?
1
:
0
;
SMC_SELECT_BANK
(
0
);
new_carrier
=
SMC_inw
(
ioaddr
,
EPH_STATUS_REG
)
&
ES_LINK_OK
?
1
:
0
;
SMC_SELECT_BANK
(
2
);
if
(
init
||
(
old_carrier
!=
new_carrier
))
{
if
(
!
new_carrier
)
{
...
...
@@ -1134,24 +1208,20 @@ static void smc_10bt_check_media(struct net_device *dev, int init)
printk
(
KERN_INFO
"%s: link %s
\n
"
,
dev
->
name
,
new_carrier
?
"up"
:
"down"
);
}
SMC_SELECT_BANK
(
old_bank
);
}
static
void
smc_eph_interrupt
(
struct
net_device
*
dev
)
{
unsigned
long
ioaddr
=
dev
->
base_addr
;
unsigned
int
old_bank
,
ctl
;
unsigned
int
ctl
;
smc_10bt_check_media
(
dev
,
0
);
old_bank
=
SMC_CURRENT_BANK
();
SMC_SELECT_BANK
(
1
);
ctl
=
SMC_GET_CTL
();
SMC_SET_CTL
(
ctl
&
~
CTL_LE_ENABLE
);
SMC_SET_CTL
(
ctl
);
SMC_SELECT_BANK
(
old_bank
);
SMC_SELECT_BANK
(
2
);
}
/*
...
...
@@ -1164,14 +1234,12 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
unsigned
long
ioaddr
=
dev
->
base_addr
;
struct
smc_local
*
lp
=
netdev_priv
(
dev
);
int
status
,
mask
,
timeout
,
card_stats
;
int
saved_
bank
,
saved_
pointer
;
int
saved_pointer
;
DBG
(
3
,
"%s: %s
\n
"
,
dev
->
name
,
__FUNCTION__
);
spin_lock
(
&
lp
->
lock
);
saved_bank
=
SMC_CURRENT_BANK
();
SMC_SELECT_BANK
(
2
);
saved_pointer
=
SMC_GET_PTR
();
mask
=
SMC_GET_INT_MASK
();
SMC_SET_INT_MASK
(
0
);
...
...
@@ -1182,7 +1250,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
do
{
status
=
SMC_GET_INT
();
DBG
(
2
,
"%s: I
RQ
0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x
\n
"
,
DBG
(
2
,
"%s: I
NT
0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x
\n
"
,
dev
->
name
,
status
,
mask
,
({
int
meminfo
;
SMC_SELECT_BANK
(
0
);
meminfo
=
SMC_GET_MIR
();
...
...
@@ -1200,17 +1268,12 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
DBG
(
3
,
"%s: TX int
\n
"
,
dev
->
name
);
smc_tx
(
dev
);
SMC_ACK_INT
(
IM_TX_INT
);
#if THROTTLE_TX_PKTS
netif_wake_queue
(
dev
);
#endif
if
(
THROTTLE_TX_PKTS
)
netif_wake_queue
(
dev
);
}
else
if
(
status
&
IM_ALLOC_INT
)
{
DBG
(
3
,
"%s: Allocation irq
\n
"
,
dev
->
name
);
smc_hardware_send_packet
(
dev
);
mask
|=
(
IM_TX_INT
|
IM_TX_EMPTY_INT
);
tasklet_hi_schedule
(
&
lp
->
tx_task
);
mask
&=
~
IM_ALLOC_INT
;
#if ! THROTTLE_TX_PKTS
netif_wake_queue
(
dev
);
#endif
}
else
if
(
status
&
IM_TX_EMPTY_INT
)
{
DBG
(
3
,
"%s: TX empty
\n
"
,
dev
->
name
);
mask
&=
~
IM_TX_EMPTY_INT
;
...
...
@@ -1240,17 +1303,16 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
SMC_ACK_INT
(
IM_ERCV_INT
);
PRINTK
(
"%s: UNSUPPORTED: ERCV INTERRUPT
\n
"
,
dev
->
name
);
}
}
while
(
--
timeout
);
/* restore register states */
SMC_SET_INT_MASK
(
mask
);
SMC_SET_PTR
(
saved_pointer
);
SMC_SELECT_BANK
(
saved_bank
);
SMC_SET_INT_MASK
(
mask
);
spin_unlock
(
&
lp
->
lock
);
DBG
(
3
,
"%s: Interrupt done (%d loops)
\n
"
,
dev
->
name
,
8
-
timeout
);
spin_unlock
(
&
lp
->
lock
);
/*
* We return IRQ_HANDLED unconditionally here even if there was
* nothing to do. There is a possibility that a packet might
...
...
@@ -1266,100 +1328,38 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static
void
smc_timeout
(
struct
net_device
*
dev
)
{
struct
smc_local
*
lp
=
netdev_priv
(
dev
);
unsigned
long
flags
;
unsigned
long
ioaddr
=
dev
->
base_addr
;
int
status
,
mask
,
meminfo
,
fifo
;
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
DBG
(
2
,
"%s: %s
\n
"
,
dev
->
name
,
__FUNCTION__
);
spin_lock_irq
(
&
lp
->
lock
);
status
=
SMC_GET_INT
();
mask
=
SMC_GET_INT_MASK
();
fifo
=
SMC_GET_FIFO
();
SMC_SELECT_BANK
(
0
);
meminfo
=
SMC_GET_MIR
();
SMC_SELECT_BANK
(
2
);
spin_unlock_irq
(
&
lp
->
lock
);
PRINTK
(
"%s: INT 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x
\n
"
,
dev
->
name
,
status
,
mask
,
meminfo
,
fifo
);
smc_reset
(
dev
);
smc_enable
(
dev
);
#if 0
/*
* Reconfiguring the PHY doesn't seem like a bad idea here, but
* it introduced a problem. Now that this is a timeout routine,
* we are getting called from within an interrupt context.
* smc_phy_configure() calls msleep() which calls
* schedule_timeout() which calls schedule(). When schedule()
* is called from an interrupt context, it prints out
* "Scheduling in interrupt" and then calls BUG(). This is
* obviously not desirable. This was worked around by removing
* the call to smc_phy_configure() here because it didn't seem
* absolutely necessary. Ultimately, if msleep() is
* supposed to be usable from an interrupt context (which it
* looks like it thinks it should handle), it should be fixed.
* smc_phy_configure() calls msleep() which calls schedule_timeout()
* which calls schedule(). Ence we use a work queue.
*/
if
(
lp
->
phy_type
!=
0
)
smc_phy_configure(dev);
#endif
schedule_work
(
&
lp
->
phy_configure
);
/* clear anything saved */
if
(
lp
->
saved_skb
!=
NULL
)
{
dev_kfree_skb
(
lp
->
saved_skb
);
lp
->
saved_skb
=
NULL
;
lp
->
stats
.
tx_errors
++
;
lp
->
stats
.
tx_aborted_errors
++
;
}
/* We can accept TX packets again */
dev
->
trans_start
=
jiffies
;
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
netif_wake_queue
(
dev
);
}
/*
* This sets the internal hardware table to filter out unwanted multicast
* packets before they take up memory.
*
* The SMC chip uses a hash table where the high 6 bits of the CRC of
* address are the offset into the table. If that bit is 1, then the
* multicast packet is accepted. Otherwise, it's dropped silently.
*
* To use the 6 bits as an offset into the table, the high 3 bits are the
* number of the 8 bit register, while the low 3 bits are the bit within
* that register.
*
* This routine is based very heavily on the one provided by Peter Cammaert.
*/
static
void
smc_setmulticast
(
unsigned
long
ioaddr
,
int
count
,
struct
dev_mc_list
*
addrs
)
{
int
i
;
unsigned
char
multicast_table
[
8
];
struct
dev_mc_list
*
cur_addr
;
/* table for flipping the order of 3 bits */
static
unsigned
char
invert3
[]
=
{
0
,
4
,
2
,
6
,
1
,
5
,
3
,
7
};
/* start with a table of all zeros: reject all */
memset
(
multicast_table
,
0
,
sizeof
(
multicast_table
));
cur_addr
=
addrs
;
for
(
i
=
0
;
i
<
count
;
i
++
,
cur_addr
=
cur_addr
->
next
)
{
int
position
;
/* do we have a pointer here? */
if
(
!
cur_addr
)
break
;
/* make sure this is a multicast address - shouldn't this
be a given if we have it here ? */
if
(
!
(
*
cur_addr
->
dmi_addr
&
1
))
continue
;
/* only use the low order bits */
position
=
crc32_le
(
~
0
,
cur_addr
->
dmi_addr
,
6
)
&
0x3f
;
/* do some messy swapping to put the bit in the right spot */
multicast_table
[
invert3
[
position
&
7
]]
|=
(
1
<<
invert3
[(
position
>>
3
)
&
7
]);
}
/* now, the table can be loaded into the chipset */
SMC_SELECT_BANK
(
3
);
SMC_SET_MCAST
(
multicast_table
);
}
/*
* This routine will, depending on the values passed to it,
* either make it accept multicast packets, go into
...
...
@@ -1370,14 +1370,14 @@ static void smc_set_multicast_list(struct net_device *dev)
{
struct
smc_local
*
lp
=
netdev_priv
(
dev
);
unsigned
long
ioaddr
=
dev
->
base_addr
;
unsigned
char
multicast_table
[
8
];
int
update_multicast
=
0
;
DBG
(
2
,
"%s: %s
\n
"
,
dev
->
name
,
__FUNCTION__
);
SMC_SELECT_BANK
(
0
);
if
(
dev
->
flags
&
IFF_PROMISC
)
{
DBG
(
2
,
"%s: RCR_PRMS
\n
"
,
dev
->
name
);
lp
->
rcr_cur_mode
|=
RCR_PRMS
;
SMC_SET_RCR
(
lp
->
rcr_cur_mode
);
}
/* BUG? I never disable promiscuous mode if multicasting was turned on.
...
...
@@ -1391,38 +1391,78 @@ static void smc_set_multicast_list(struct net_device *dev)
* checked before the table is
*/
else
if
(
dev
->
flags
&
IFF_ALLMULTI
||
dev
->
mc_count
>
16
)
{
lp
->
rcr_cur_mode
|=
RCR_ALMUL
;
SMC_SET_RCR
(
lp
->
rcr_cur_mode
);
DBG
(
2
,
"%s: RCR_ALMUL
\n
"
,
dev
->
name
);
lp
->
rcr_cur_mode
|=
RCR_ALMUL
;
}
/*
* We just get all multicast packets even if we only want them
* from one source. This will be changed at some future point.
* This sets the internal hardware table to filter out unwanted
* multicast packets before they take up memory.
*
* The SMC chip uses a hash table where the high 6 bits of the CRC of
* address are the offset into the table. If that bit is 1, then the
* multicast packet is accepted. Otherwise, it's dropped silently.
*
* To use the 6 bits as an offset into the table, the high 3 bits are
* the number of the 8 bit register, while the low 3 bits are the bit
* within that register.
*/
else
if
(
dev
->
mc_count
)
{
/* support hardware multicasting */
int
i
;
struct
dev_mc_list
*
cur_addr
;
/* table for flipping the order of 3 bits */
static
const
unsigned
char
invert3
[]
=
{
0
,
4
,
2
,
6
,
1
,
5
,
3
,
7
};
/* start with a table of all zeros: reject all */
memset
(
multicast_table
,
0
,
sizeof
(
multicast_table
));
cur_addr
=
dev
->
mc_list
;
for
(
i
=
0
;
i
<
dev
->
mc_count
;
i
++
,
cur_addr
=
cur_addr
->
next
)
{
int
position
;
/* do we have a pointer here? */
if
(
!
cur_addr
)
break
;
/* make sure this is a multicast address -
shouldn't this be a given if we have it here ? */
if
(
!
(
*
cur_addr
->
dmi_addr
&
1
))
continue
;
/* only use the low order bits */
position
=
crc32_le
(
~
0
,
cur_addr
->
dmi_addr
,
6
)
&
0x3f
;
/* do some messy swapping to put the bit in the right spot */
multicast_table
[
invert3
[
position
&
7
]]
|=
(
1
<<
invert3
[(
position
>>
3
)
&
7
]);
}
/* be sure I get rid of flags I might have set */
lp
->
rcr_cur_mode
&=
~
(
RCR_PRMS
|
RCR_ALMUL
);
SMC_SET_RCR
(
lp
->
rcr_cur_mode
);
/*
* NOTE: this has to set the bank, so make sure it is the
* last thing called. The bank is set to zero at the top
*/
smc_setmulticast
(
ioaddr
,
dev
->
mc_count
,
dev
->
mc_list
);
/* now, the table can be loaded into the chipset */
update_multicast
=
1
;
}
else
{
DBG
(
2
,
"%s: ~(RCR_PRMS|RCR_ALMUL)
\n
"
,
dev
->
name
);
lp
->
rcr_cur_mode
&=
~
(
RCR_PRMS
|
RCR_ALMUL
);
SMC_SET_RCR
(
lp
->
rcr_cur_mode
);
/*
* since I'm disabling all multicast entirely, I need to
* clear the multicast list
*/
memset
(
multicast_table
,
0
,
sizeof
(
multicast_table
));
update_multicast
=
1
;
}
spin_lock_irq
(
&
lp
->
lock
);
SMC_SELECT_BANK
(
0
);
SMC_SET_RCR
(
lp
->
rcr_cur_mode
);
if
(
update_multicast
)
{
SMC_SELECT_BANK
(
3
);
SMC_
CLEAR_MCAST
(
);
SMC_
SET_MCAST
(
multicast_table
);
}
SMC_SELECT_BANK
(
2
);
spin_unlock_irq
(
&
lp
->
lock
);
}
...
...
@@ -1435,7 +1475,6 @@ static int
smc_open
(
struct
net_device
*
dev
)
{
struct
smc_local
*
lp
=
netdev_priv
(
dev
);
unsigned
long
ioaddr
=
dev
->
base_addr
;
DBG
(
2
,
"%s: %s
\n
"
,
dev
->
name
,
__FUNCTION__
);
...
...
@@ -1445,13 +1484,10 @@ smc_open(struct net_device *dev)
* address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
*/
if
(
!
is_valid_ether_addr
(
dev
->
dev_addr
))
{
DBG
(
2
,
"smc_open: no valid ethernet hw addr
\n
"
);
PRINTK
(
"%s: no valid ethernet hw addr
\n
"
,
__FUNCTION__
);
return
-
EINVAL
;
}
/* clear out all the junk that was put here before... */
lp
->
saved_skb
=
NULL
;
/* Setup the default Register Modes */
lp
->
tcr_cur_mode
=
TCR_DEFAULT
;
lp
->
rcr_cur_mode
=
RCR_DEFAULT
;
...
...
@@ -1468,10 +1504,7 @@ smc_open(struct net_device *dev)
smc_reset
(
dev
);
smc_enable
(
dev
);
SMC_SELECT_BANK
(
1
);
SMC_SET_MAC_ADDR
(
dev
->
dev_addr
);
/* Configure the PHY */
/* Configure the PHY, initialize the link state */
if
(
lp
->
phy_type
!=
0
)
smc_phy_configure
(
dev
);
else
{
...
...
@@ -1480,12 +1513,6 @@ smc_open(struct net_device *dev)
spin_unlock_irq
(
&
lp
->
lock
);
}
/*
* make sure to initialize the link state with netif_carrier_off()
* somewhere, too --jgarzik
*
* smc_phy_configure() and smc_10bt_check_media() does that. --rmk
*/
netif_start_queue
(
dev
);
return
0
;
}
...
...
@@ -1507,10 +1534,17 @@ static int smc_close(struct net_device *dev)
netif_carrier_off
(
dev
);
/* clear everything */
smc_shutdown
(
dev
->
base_addr
);
smc_shutdown
(
dev
);
if
(
lp
->
phy_type
!=
0
)
if
(
lp
->
phy_type
!=
0
)
{
flush_scheduled_work
();
smc_phy_powerdown
(
dev
,
lp
->
mii
.
phy_id
);
}
if
(
lp
->
pending_tx_skb
)
{
dev_kfree_skb
(
lp
->
pending_tx_skb
);
lp
->
pending_tx_skb
=
NULL
;
}
return
0
;
}
...
...
@@ -1800,6 +1834,7 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
/* fill in some of the fields */
dev
->
base_addr
=
ioaddr
;
lp
->
version
=
revision_register
&
0xff
;
spin_lock_init
(
&
lp
->
lock
);
/* Get the MAC address */
SMC_SELECT_BANK
(
1
);
...
...
@@ -1855,7 +1890,8 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
dev
->
set_multicast_list
=
smc_set_multicast_list
;
dev
->
ethtool_ops
=
&
smc_ethtool_ops
;
spin_lock_init
(
&
lp
->
lock
);
tasklet_init
(
&
lp
->
tx_task
,
smc_hardware_send_pkt
,
(
unsigned
long
)
dev
);
INIT_WORK
(
&
lp
->
phy_configure
,
smc_phy_configure
,
dev
);
lp
->
mii
.
phy_id_mask
=
0x1f
;
lp
->
mii
.
reg_num_mask
=
0x1f
;
lp
->
mii
.
force_media
=
0
;
...
...
@@ -1885,9 +1921,8 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
if
(
retval
)
goto
err_out
;
#if !defined(__m32r__)
set_irq_type
(
dev
->
irq
,
IRQT_RISING
);
#endif
#ifdef SMC_USE_PXA_DMA
{
int
dma
=
pxa_request_dma
(
dev
->
name
,
DMA_PRIO_LOW
,
...
...
@@ -2121,7 +2156,7 @@ static int smc_drv_suspend(struct device *dev, u32 state, u32 level)
if
(
ndev
&&
level
==
SUSPEND_DISABLE
)
{
if
(
netif_running
(
ndev
))
{
netif_device_detach
(
ndev
);
smc_shutdown
(
ndev
->
base_addr
);
smc_shutdown
(
ndev
);
}
}
return
0
;
...
...
@@ -2134,15 +2169,12 @@ static int smc_drv_resume(struct device *dev, u32 level)
if
(
ndev
&&
level
==
RESUME_ENABLE
)
{
struct
smc_local
*
lp
=
netdev_priv
(
ndev
);
unsigned
long
ioaddr
=
ndev
->
base_addr
;
if
(
pdev
->
num_resources
==
3
)
smc_enable_device
(
pdev
->
resource
[
2
].
start
);
if
(
netif_running
(
ndev
))
{
smc_reset
(
ndev
);
smc_enable
(
ndev
);
SMC_SELECT_BANK
(
1
);
SMC_SET_MAC_ADDR
(
ndev
->
dev_addr
);
if
(
lp
->
phy_type
!=
0
)
smc_phy_configure
(
ndev
);
netif_device_attach
(
ndev
);
...
...
drivers/net/smc91x.h
View file @
74f54248
...
...
@@ -173,6 +173,11 @@ SMC_outw(u16 val, unsigned long ioaddr, int reg)
#define SMC_insw(a, r, p, l) insw((a) + (r) - 0xa0000000, p, l)
#define SMC_outsw(a, r, p, l) outsw((a) + (r) - 0xa0000000, p, l)
#define set_irq_type(irq, type) do {} while(0)
#define RPC_LSA_DEFAULT RPC_LED_TX_RX
#define RPC_LSB_DEFAULT RPC_LED_100_10
#else
#define SMC_CAN_USE_8BIT 1
...
...
@@ -202,8 +207,9 @@ SMC_outw(u16 val, unsigned long ioaddr, int reg)
* different and probably not worth it for that reason, and not as critical
* as RX which can overrun memory and lose packets.
*/
#include <linux/
pci
.h>
#include <linux/
dma-mapping
.h>
#include <asm/dma.h>
#include <asm/arch/pxa-regs.h>
#ifdef SMC_insl
#undef SMC_insl
...
...
@@ -223,19 +229,21 @@ smc_pxa_dma_insl(u_long ioaddr, u_long physaddr, int reg, int dma,
/* 64 bit alignment is required for memory to memory DMA */
if
((
long
)
buf
&
4
)
{
*
((
u32
*
)
buf
)
++
=
SMC_inl
(
ioaddr
,
reg
);
*
((
u32
*
)
buf
)
=
SMC_inl
(
ioaddr
,
reg
);
buf
+=
4
;
len
--
;
}
len
*=
4
;
dmabuf
=
dma_map_single
(
NULL
,
buf
,
len
,
PCI_DMA_FROM
DEVICE
);
dmabuf
=
dma_map_single
(
NULL
,
buf
,
len
,
DMA_FROM_
DEVICE
);
DCSR
(
dma
)
=
DCSR_NODESC
;
DTADR
(
dma
)
=
dmabuf
;
DSADR
(
dma
)
=
physaddr
+
reg
;
DCMD
(
dma
)
=
(
DCMD_INCTRGADDR
|
DCMD_BURST32
|
DCMD_WIDTH4
|
(
DCMD_LENGTH
&
len
));
DCSR
(
dma
)
=
DCSR_NODESC
|
DCSR_RUN
;
while
(
!
(
DCSR
(
dma
)
&
DCSR_STOPSTATE
));
while
(
!
(
DCSR
(
dma
)
&
DCSR_STOPSTATE
))
cpu_relax
();
DCSR
(
dma
)
=
0
;
dma_unmap_single
(
NULL
,
dmabuf
,
len
,
PCI_DMA_FROMDEVICE
);
}
...
...
@@ -259,7 +267,8 @@ smc_pxa_dma_insw(u_long ioaddr, u_long physaddr, int reg, int dma,
/* 64 bit alignment is required for memory to memory DMA */
while
((
long
)
buf
&
6
)
{
*
((
u16
*
)
buf
)
++
=
SMC_inw
(
ioaddr
,
reg
);
*
((
u16
*
)
buf
)
=
SMC_inw
(
ioaddr
,
reg
);
buf
+=
2
;
len
--
;
}
...
...
@@ -271,9 +280,10 @@ smc_pxa_dma_insw(u_long ioaddr, u_long physaddr, int reg, int dma,
DCMD
(
dma
)
=
(
DCMD_INCTRGADDR
|
DCMD_BURST32
|
DCMD_WIDTH2
|
(
DCMD_LENGTH
&
len
));
DCSR
(
dma
)
=
DCSR_NODESC
|
DCSR_RUN
;
while
(
!
(
DCSR
(
dma
)
&
DCSR_STOPSTATE
));
while
(
!
(
DCSR
(
dma
)
&
DCSR_STOPSTATE
))
cpu_relax
();
DCSR
(
dma
)
=
0
;
dma_unmap_single
(
NULL
,
dmabuf
,
len
,
PCI_DMA_FROM
DEVICE
);
dma_unmap_single
(
NULL
,
dmabuf
,
len
,
DMA_FROM_
DEVICE
);
}
#endif
...
...
@@ -762,16 +772,9 @@ static const char * chip_ids[ 16 ] = {
SMC_outw( addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG ); \
} while (0)
#define SMC_CLEAR_MCAST() \
do { \
SMC_outw( 0, ioaddr, MCAST_REG1 ); \
SMC_outw( 0, ioaddr, MCAST_REG2 ); \
SMC_outw( 0, ioaddr, MCAST_REG3 ); \
SMC_outw( 0, ioaddr, MCAST_REG4 ); \
} while (0)
#define SMC_SET_MCAST(x) \
do { \
unsigned char *mt = (x); \
const
unsigned char *mt = (x); \
SMC_outw( mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1 ); \
SMC_outw( mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2 ); \
SMC_outw( mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3 ); \
...
...
drivers/net/tokenring/lanstreamer.c
View file @
74f54248
...
...
@@ -1606,7 +1606,7 @@ static void streamer_arb_cmd(struct net_device *dev)
i
+=
2
;
}
memcpy
_fromio
(
skb_put
(
mac_frame
,
buffer_len
),
memcpy
(
skb_put
(
mac_frame
,
buffer_len
),
frame_data
,
buffer_len
);
}
while
(
next_ptr
&&
(
buff_off
=
next_ptr
));
...
...
drivers/net/tulip/dmfe.c
View file @
74f54248
...
...
@@ -92,6 +92,7 @@
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
/* Board/System/Debug information/definition ---------------- */
...
...
drivers/net/via-rhine.c
View file @
74f54248
...
...
@@ -1957,6 +1957,7 @@ static int rhine_suspend(struct pci_dev *pdev, u32 state)
rhine_shutdown
(
&
pdev
->
dev
);
spin_unlock_irqrestore
(
&
rp
->
lock
,
flags
);
free_irq
(
dev
->
irq
,
dev
);
return
0
;
}
...
...
@@ -1970,6 +1971,9 @@ static int rhine_resume(struct pci_dev *pdev)
if
(
!
netif_running
(
dev
))
return
0
;
if
(
request_irq
(
dev
->
irq
,
rhine_interrupt
,
SA_SHIRQ
,
dev
->
name
,
dev
))
printk
(
KERN_ERR
"via-rhine %s: request_irq failed
\n
"
,
dev
->
name
);
ret
=
pci_set_power_state
(
pdev
,
0
);
if
(
debug
>
1
)
printk
(
KERN_INFO
"%s: Entering power state D0 %s (%d).
\n
"
,
...
...
drivers/net/wireless/prism54/isl_38xx.c
View file @
74f54248
...
...
@@ -133,8 +133,8 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base)
readl
(
device_base
+
ISL38XX_CTRL_STAT_REG
));
udelay
(
ISL38XX_WRITEIO_DELAY
);
if
(
reg
=
readl
(
device_base
+
ISL38XX_INT_IDENT_REG
),
reg
==
0xabadface
)
{
reg
=
readl
(
device_base
+
ISL38XX_INT_IDENT_REG
);
if
(
reg
==
0xabadface
)
{
#if VERBOSE > SHOW_ERROR_MESSAGES
do_gettimeofday
(
&
current_time
);
DEBUG
(
SHOW_TRACING
,
...
...
@@ -192,10 +192,8 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base)
void
isl38xx_interface_reset
(
void
__iomem
*
device_base
,
dma_addr_t
host_address
)
{
u32
reg
;
#if VERBOSE > SHOW_ERROR_MESSAGES
DEBUG
(
SHOW_FUNCTION_CALLS
,
"isl38xx_interface_reset
\n
"
);
DEBUG
(
SHOW_FUNCTION_CALLS
,
"isl38xx_interface_reset
\n
"
);
#endif
/* load the address of the control block in the device */
...
...
@@ -203,8 +201,7 @@ isl38xx_interface_reset(void __iomem *device_base, dma_addr_t host_address)
udelay
(
ISL38XX_WRITEIO_DELAY
);
/* set the reset bit in the Device Interrupt Register */
isl38xx_w32_flush
(
device_base
,
ISL38XX_DEV_INT_RESET
,
ISL38XX_DEV_INT_REG
);
isl38xx_w32_flush
(
device_base
,
ISL38XX_DEV_INT_RESET
,
ISL38XX_DEV_INT_REG
);
udelay
(
ISL38XX_WRITEIO_DELAY
);
/* enable the interrupt for detecting initialization */
...
...
@@ -212,9 +209,7 @@ isl38xx_interface_reset(void __iomem *device_base, dma_addr_t host_address)
/* Note: Do not enable other interrupts here. We want the
* device to have come up first 100% before allowing any other
* interrupts. */
reg
=
ISL38XX_INT_IDENT_INIT
;
isl38xx_w32_flush
(
device_base
,
reg
,
ISL38XX_INT_EN_REG
);
isl38xx_w32_flush
(
device_base
,
ISL38XX_INT_IDENT_INIT
,
ISL38XX_INT_EN_REG
);
udelay
(
ISL38XX_WRITEIO_DELAY
);
/* allow complete full reset */
}
...
...
drivers/net/wireless/prism54/isl_38xx.h
View file @
74f54248
...
...
@@ -95,6 +95,10 @@ isl38xx_w32_flush(void __iomem *base, u32 val, unsigned long offset)
#define ISL38XX_INT_SOURCES 0x001E
/* Control/Status register bits */
/* Looks like there are other meaningful bits
0x20004400 seen in normal operation,
0x200044db at 'timeout waiting for mgmt response'
*/
#define ISL38XX_CTRL_STAT_SLEEPMODE 0x00000200
#define ISL38XX_CTRL_STAT_CLKRUN 0x00800000
#define ISL38XX_CTRL_STAT_RESET 0x10000000
...
...
drivers/net/wireless/prism54/isl_ioctl.c
View file @
74f54248
...
...
@@ -36,38 +36,6 @@
#include <net/iw_handler.h>
/* New driver API */
static
int
init_mode
=
CARD_DEFAULT_IW_MODE
;
static
int
init_channel
=
CARD_DEFAULT_CHANNEL
;
static
int
init_wep
=
CARD_DEFAULT_WEP
;
static
int
init_filter
=
CARD_DEFAULT_FILTER
;
static
int
init_authen
=
CARD_DEFAULT_AUTHEN
;
static
int
init_dot1x
=
CARD_DEFAULT_DOT1X
;
static
int
init_conformance
=
CARD_DEFAULT_CONFORMANCE
;
static
int
init_mlme
=
CARD_DEFAULT_MLME_MODE
;
module_param
(
init_mode
,
int
,
0
);
MODULE_PARM_DESC
(
init_mode
,
"Set card mode:
\n
0: Auto
\n
1: Ad-Hoc
\n
2: Managed Client (Default)
\n
3: Master / Access Point
\n
4: Repeater (Not supported yet)
\n
5: Secondary (Not supported yet)
\n
6: Monitor"
);
module_param
(
init_channel
,
int
,
0
);
MODULE_PARM_DESC
(
init_channel
,
"Check `iwpriv ethx channel` for available channels"
);
module_param
(
init_wep
,
int
,
0
);
module_param
(
init_filter
,
int
,
0
);
module_param
(
init_authen
,
int
,
0
);
MODULE_PARM_DESC
(
init_authen
,
"Authentication method. Can be of seven types:
\n
0 0x0000: None
\n
1 0x0001: DOT11_AUTH_OS (Default)
\n
2 0x0002: DOT11_AUTH_SK
\n
3 0x0003: DOT11_AUTH_BOTH"
);
module_param
(
init_dot1x
,
int
,
0
);
MODULE_PARM_DESC
(
init_dot1x
,
"
\n
0: None/not set (Default)
\n
1: DOT11_DOT1X_AUTHENABLED
\n
2: DOT11_DOT1X_KEYTXENABLED"
);
module_param
(
init_mlme
,
int
,
0
);
MODULE_PARM_DESC
(
init_mlme
,
"Sets the MAC layer management entity (MLME) mode of operation,
\n
0: DOT11_MLME_AUTO (Default)
\n
1: DOT11_MLME_INTERMEDIATE
\n
2: DOT11_MLME_EXTENDED"
);
/**
* prism54_mib_mode_helper - MIB change mode helper function
* @mib: the &struct islpci_mib object to modify
...
...
@@ -141,36 +109,34 @@ prism54_mib_mode_helper(islpci_private *priv, u32 iw_mode)
void
prism54_mib_init
(
islpci_private
*
priv
)
{
u32
t
;
u32
channel
,
authen
,
wep
,
filter
,
dot1x
,
mlme
,
conformance
,
power
,
mode
;
struct
obj_buffer
psm_buffer
=
{
.
size
=
PSM_BUFFER_SIZE
,
.
addr
=
priv
->
device_psm_buffer
};
mgt_set
(
priv
,
DOT11_OID_CHANNEL
,
&
init_channel
);
mgt_set
(
priv
,
DOT11_OID_AUTHENABLE
,
&
init_authen
);
mgt_set
(
priv
,
DOT11_OID_PRIVACYINVOKED
,
&
init_wep
);
channel
=
CARD_DEFAULT_CHANNEL
;
authen
=
CARD_DEFAULT_AUTHEN
;
wep
=
CARD_DEFAULT_WEP
;
filter
=
CARD_DEFAULT_FILTER
;
/* (0) Do not filter un-encrypted data */
dot1x
=
CARD_DEFAULT_DOT1X
;
mlme
=
CARD_DEFAULT_MLME_MODE
;
conformance
=
CARD_DEFAULT_CONFORMANCE
;
power
=
127
;
mode
=
CARD_DEFAULT_IW_MODE
;
mgt_set
(
priv
,
DOT11_OID_CHANNEL
,
&
channel
);
mgt_set
(
priv
,
DOT11_OID_AUTHENABLE
,
&
authen
);
mgt_set
(
priv
,
DOT11_OID_PRIVACYINVOKED
,
&
wep
);
mgt_set
(
priv
,
DOT11_OID_PSMBUFFER
,
&
psm_buffer
);
mgt_set
(
priv
,
DOT11_OID_EXUNENCRYPTED
,
&
init_filter
);
mgt_set
(
priv
,
DOT11_OID_DOT1XENABLE
,
&
init_dot1x
);
mgt_set
(
priv
,
DOT11_OID_MLMEAUTOLEVEL
,
&
init_mlme
);
mgt_set
(
priv
,
OID_INL_DOT11D_CONFORMANCE
,
&
init_conformance
);
t
=
127
;
mgt_set
(
priv
,
OID_INL_OUTPUTPOWER
,
&
t
);
/* Important: we are setting a default wireless mode and we are
* forcing a valid one, so prism54_mib_mode_helper should just set
* mib values depending on what the wireless mode given is. No need
* for it save old values */
if
(
init_mode
>
IW_MODE_MONITOR
||
init_mode
<
IW_MODE_AUTO
)
{
printk
(
KERN_DEBUG
"%s(): You passed a non-valid init_mode. "
"Using default mode
\n
"
,
__FUNCTION__
);
init_mode
=
CARD_DEFAULT_IW_MODE
;
}
mgt_set
(
priv
,
DOT11_OID_EXUNENCRYPTED
,
&
filter
);
mgt_set
(
priv
,
DOT11_OID_DOT1XENABLE
,
&
dot1x
);
mgt_set
(
priv
,
DOT11_OID_MLMEAUTOLEVEL
,
&
mlme
);
mgt_set
(
priv
,
OID_INL_DOT11D_CONFORMANCE
,
&
conformance
);
mgt_set
(
priv
,
OID_INL_OUTPUTPOWER
,
&
power
);
/* This sets all of the mode-dependent values */
prism54_mib_mode_helper
(
priv
,
init_
mode
);
prism54_mib_mode_helper
(
priv
,
mode
);
}
/* this will be executed outside of atomic context thanks to
...
...
@@ -374,7 +340,10 @@ prism54_set_mode(struct net_device *ndev, struct iw_request_info *info,
mgt_set
(
priv
,
DOT11_OID_MLMEAUTOLEVEL
,
&
mlmeautolevel
);
mgt_commit
(
priv
);
if
(
mgt_commit
(
priv
))
{
up_write
(
&
priv
->
mib_sem
);
return
-
EIO
;
}
priv
->
ndev
->
type
=
(
priv
->
iw_mode
==
IW_MODE_MONITOR
)
?
priv
->
monitor_type
:
ARPHRD_ETHER
;
up_write
(
&
priv
->
mib_sem
);
...
...
@@ -485,6 +454,15 @@ prism54_get_range(struct net_device *ndev, struct iw_request_info *info,
/* txpower is supported in dBm's */
range
->
txpower_capa
=
IW_TXPOW_DBM
;
#if WIRELESS_EXT > 16
/* Event capability (kernel + driver) */
range
->
event_capa
[
0
]
=
(
IW_EVENT_CAPA_K_0
|
IW_EVENT_CAPA_MASK
(
SIOCGIWTHRSPY
)
|
IW_EVENT_CAPA_MASK
(
SIOCGIWAP
));
range
->
event_capa
[
1
]
=
IW_EVENT_CAPA_K_1
;
range
->
event_capa
[
4
]
=
IW_EVENT_CAPA_MASK
(
IWEVCUSTOM
);
#endif
/* WIRELESS_EXT > 16 */
if
(
islpci_get_state
(
priv
)
<
PRV_STATE_INIT
)
return
0
;
...
...
@@ -629,8 +607,8 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev,
current_ev
=
iwe_stream_add_point
(
current_ev
,
end_buf
,
&
iwe
,
NULL
);
/* Add frequency. (short) bss->channel is the frequency in MHz */
iwe
.
u
.
freq
.
m
=
channel_of_freq
(
bss
->
channel
)
;
iwe
.
u
.
freq
.
e
=
0
;
iwe
.
u
.
freq
.
m
=
bss
->
channel
;
iwe
.
u
.
freq
.
e
=
6
;
iwe
.
cmd
=
SIOCGIWFREQ
;
current_ev
=
iwe_stream_add_event
(
current_ev
,
end_buf
,
&
iwe
,
IW_EV_FREQ_LEN
);
...
...
@@ -690,19 +668,33 @@ prism54_get_scan(struct net_device *ndev, struct iw_request_info *info,
rvalue
=
mgt_get_request
(
priv
,
DOT11_OID_NOISEFLOOR
,
0
,
NULL
,
&
r
);
noise
=
r
.
u
;
/* Ask the device for a list of known bss. We can report at most
* IW_MAX_AP=64 to the range struct. But the device won't repport anything
* if you change the value of IWMAX_BSS=24.
*/
/* Ask the device for a list of known bss.
* The old API, using SIOCGIWAPLIST, had a hard limit of IW_MAX_AP=64.
* The new API, using SIOCGIWSCAN, is only limited by the buffer size.
* WE-14->WE-16, the buffer is limited to IW_SCAN_MAX_DATA bytes.
* Starting with WE-17, the buffer can be as big as needed.
* But the device won't repport anything if you change the value
* of IWMAX_BSS=24. */
rvalue
|=
mgt_get_request
(
priv
,
DOT11_OID_BSSLIST
,
0
,
NULL
,
&
r
);
bsslist
=
r
.
ptr
;
/* ok now, scan the list and translate its info */
for
(
i
=
0
;
i
<
min
(
IW_MAX_AP
,
(
int
)
bsslist
->
nr
);
i
++
)
for
(
i
=
0
;
i
<
(
int
)
bsslist
->
nr
;
i
++
)
{
current_ev
=
prism54_translate_bss
(
ndev
,
current_ev
,
extra
+
IW_SCAN_MAX_DATA
,
extra
+
dwrq
->
length
,
&
(
bsslist
->
bsslist
[
i
]),
noise
);
#if WIRELESS_EXT > 16
/* Check if there is space for one more entry */
if
((
extra
+
dwrq
->
length
-
current_ev
)
<=
IW_EV_ADDR_LEN
)
{
/* Ask user space to try again with a bigger buffer */
rvalue
=
-
E2BIG
;
break
;
}
#endif
/* WIRELESS_EXT > 16 */
}
kfree
(
bsslist
);
dwrq
->
length
=
(
current_ev
-
extra
);
dwrq
->
flags
=
0
;
/* todo */
...
...
@@ -1412,7 +1404,10 @@ prism54_set_policy(struct net_device *ndev, struct iw_request_info *info,
mlmeautolevel
=
DOT11_MLME_EXTENDED
;
mgt_set
(
priv
,
DOT11_OID_MLMEAUTOLEVEL
,
&
mlmeautolevel
);
/* restart the card with our new policy */
mgt_commit
(
priv
);
if
(
mgt_commit
(
priv
))
{
up_write
(
&
priv
->
mib_sem
);
return
-
EIO
;
}
up_write
(
&
priv
->
mib_sem
);
return
0
;
...
...
@@ -1746,11 +1741,13 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
char
*
data
)
{
struct
obj_mlme
*
mlme
=
(
struct
obj_mlme
*
)
data
;
size_t
len
;
u8
*
payload
,
*
pos
=
(
u8
*
)
(
mlme
+
1
);
len
=
pos
[
0
]
|
(
pos
[
1
]
<<
8
);
/* little endian data length */
payload
=
pos
+
2
;
struct
obj_mlmeex
*
mlmeex
=
(
struct
obj_mlmeex
*
)
data
;
struct
obj_mlmeex
*
confirm
;
u8
wpa_ie
[
MAX_WPA_IE_LEN
];
int
wpa_ie_len
;
size_t
len
=
0
;
/* u16, better? */
u8
*
payload
=
0
,
*
pos
=
0
;
int
ret
;
/* I think all trapable objects are listed here.
* Some oids have a EX version. The difference is that they are emitted
...
...
@@ -1760,9 +1757,14 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
* suited. We use the more flexible custom event facility.
*/
if
(
oid
>=
DOT11_OID_BEACON
)
{
len
=
mlmeex
->
size
;
payload
=
pos
=
mlmeex
->
data
;
}
/* I fear prism54_process_bss_data won't work with big endian data */
if
((
oid
==
DOT11_OID_BEACON
)
||
(
oid
==
DOT11_OID_PROBE
))
prism54_process_bss_data
(
priv
,
oid
,
mlme
->
address
,
prism54_process_bss_data
(
priv
,
oid
,
mlme
ex
->
address
,
payload
,
len
);
mgt_le_to_cpu
(
isl_oid
[
oid
].
flags
&
OID_FLAG_TYPE
,
(
void
*
)
mlme
);
...
...
@@ -1822,21 +1824,134 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
case
DOT11_OID_AUTHENTICATEEX
:
handle_request
(
priv
,
mlme
,
oid
);
send_formatted_event
(
priv
,
"Authenticate request"
,
mlme
,
1
);
send_formatted_event
(
priv
,
"Authenticate request (ex)"
,
mlme
,
1
);
if
(
priv
->
iw_mode
!=
IW_MODE_MASTER
&&
mlmeex
->
state
!=
DOT11_STATE_AUTHING
)
break
;
confirm
=
kmalloc
(
sizeof
(
struct
obj_mlmeex
)
+
6
,
GFP_ATOMIC
);
if
(
!
confirm
)
break
;
memcpy
(
&
confirm
->
address
,
mlmeex
->
address
,
ETH_ALEN
);
printk
(
KERN_DEBUG
"Authenticate from: address:
\t
%02x:%02x:%02x:%02x:%02x:%02x
\n
"
,
mlmeex
->
address
[
0
],
mlmeex
->
address
[
1
],
mlmeex
->
address
[
2
],
mlmeex
->
address
[
3
],
mlmeex
->
address
[
4
],
mlmeex
->
address
[
5
]
);
confirm
->
id
=
-
1
;
/* or mlmeex->id ? */
confirm
->
state
=
0
;
/* not used */
confirm
->
code
=
0
;
confirm
->
size
=
6
;
confirm
->
data
[
0
]
=
0x00
;
confirm
->
data
[
1
]
=
0x00
;
confirm
->
data
[
2
]
=
0x02
;
confirm
->
data
[
3
]
=
0x00
;
confirm
->
data
[
4
]
=
0x00
;
confirm
->
data
[
5
]
=
0x00
;
ret
=
mgt_set_varlen
(
priv
,
DOT11_OID_ASSOCIATEEX
,
confirm
,
6
);
kfree
(
confirm
);
if
(
ret
)
return
ret
;
break
;
case
DOT11_OID_DISASSOCIATEEX
:
send_formatted_event
(
priv
,
"Disassociate request"
,
mlme
,
0
);
send_formatted_event
(
priv
,
"Disassociate request
(ex)
"
,
mlme
,
0
);
break
;
case
DOT11_OID_ASSOCIATEEX
:
handle_request
(
priv
,
mlme
,
oid
);
send_formatted_event
(
priv
,
"Associate request"
,
mlme
,
1
);
send_formatted_event
(
priv
,
"Associate request (ex)"
,
mlme
,
1
);
if
(
priv
->
iw_mode
!=
IW_MODE_MASTER
&&
mlmeex
->
state
!=
DOT11_STATE_AUTHING
)
break
;
confirm
=
kmalloc
(
sizeof
(
struct
obj_mlmeex
),
GFP_ATOMIC
);
if
(
!
confirm
)
break
;
memcpy
(
&
confirm
->
address
,
mlmeex
->
address
,
ETH_ALEN
);
confirm
->
id
=
((
struct
obj_mlmeex
*
)
mlme
)
->
id
;
confirm
->
state
=
0
;
/* not used */
confirm
->
code
=
0
;
wpa_ie_len
=
prism54_wpa_ie_get
(
priv
,
mlmeex
->
address
,
wpa_ie
);
if
(
!
wpa_ie_len
)
{
printk
(
KERN_DEBUG
"No WPA IE found from "
"address:
\t
%02x:%02x:%02x:%02x:%02x:%02x
\n
"
,
mlmeex
->
address
[
0
],
mlmeex
->
address
[
1
],
mlmeex
->
address
[
2
],
mlmeex
->
address
[
3
],
mlmeex
->
address
[
4
],
mlmeex
->
address
[
5
]
);
kfree
(
confirm
);
break
;
}
confirm
->
size
=
wpa_ie_len
;
memcpy
(
&
confirm
->
data
,
wpa_ie
,
wpa_ie_len
);
mgt_set_varlen
(
priv
,
oid
,
confirm
,
wpa_ie_len
);
kfree
(
confirm
);
break
;
case
DOT11_OID_REASSOCIATEEX
:
handle_request
(
priv
,
mlme
,
oid
);
send_formatted_event
(
priv
,
"Reassociate request"
,
mlme
,
1
);
send_formatted_event
(
priv
,
"Reassociate request (ex)"
,
mlme
,
1
);
if
(
priv
->
iw_mode
!=
IW_MODE_MASTER
&&
mlmeex
->
state
!=
DOT11_STATE_ASSOCING
)
break
;
confirm
=
kmalloc
(
sizeof
(
struct
obj_mlmeex
),
GFP_ATOMIC
);
if
(
!
confirm
)
break
;
memcpy
(
&
confirm
->
address
,
mlmeex
->
address
,
ETH_ALEN
);
confirm
->
id
=
mlmeex
->
id
;
confirm
->
state
=
0
;
/* not used */
confirm
->
code
=
0
;
wpa_ie_len
=
prism54_wpa_ie_get
(
priv
,
mlmeex
->
address
,
wpa_ie
);
if
(
!
wpa_ie_len
)
{
printk
(
KERN_DEBUG
"No WPA IE found from "
"address:
\t
%02x:%02x:%02x:%02x:%02x:%02x
\n
"
,
mlmeex
->
address
[
0
],
mlmeex
->
address
[
1
],
mlmeex
->
address
[
2
],
mlmeex
->
address
[
3
],
mlmeex
->
address
[
4
],
mlmeex
->
address
[
5
]
);
kfree
(
confirm
);
break
;
}
confirm
->
size
=
wpa_ie_len
;
memcpy
(
&
confirm
->
data
,
wpa_ie
,
wpa_ie_len
);
mgt_set_varlen
(
priv
,
oid
,
confirm
,
wpa_ie_len
);
kfree
(
confirm
);
break
;
default:
...
...
@@ -1879,23 +1994,367 @@ prism54_set_mac_address(struct net_device *ndev, void *addr)
return
ret
;
}
/* Note: currently, use hostapd ioctl from the Host AP driver for WPA
* support. This is to be replaced with Linux wireless extensions once they
* get WPA support. */
/* Note II: please leave all this together as it will be easier to remove later,
* once wireless extensions add WPA support -mcgrof */
/* PRISM54_HOSTAPD ioctl() cmd: */
enum
{
PRISM2_SET_ENCRYPTION
=
6
,
PRISM2_HOSTAPD_SET_GENERIC_ELEMENT
=
12
,
PRISM2_HOSTAPD_MLME
=
13
,
PRISM2_HOSTAPD_SCAN_REQ
=
14
,
};
#define PRISM54_SET_WPA SIOCIWFIRSTPRIV+12
#define PRISM54_HOSTAPD SIOCIWFIRSTPRIV+25
#define PRISM54_DROP_UNENCRYPTED SIOCIWFIRSTPRIV+26
#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024
#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \
((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
/* Maximum length for algorithm names (-1 for nul termination)
* used in ioctl() */
#define HOSTAP_CRYPT_ALG_NAME_LEN 16
struct
prism2_hostapd_param
{
u32
cmd
;
u8
sta_addr
[
ETH_ALEN
];
union
{
struct
{
u8
alg
[
HOSTAP_CRYPT_ALG_NAME_LEN
];
u32
flags
;
u32
err
;
u8
idx
;
u8
seq
[
8
];
/* sequence counter (set: RX, get: TX) */
u16
key_len
;
u8
key
[
0
];
}
crypt
;
struct
{
u8
len
;
u8
data
[
0
];
}
generic_elem
;
struct
{
#define MLME_STA_DEAUTH 0
#define MLME_STA_DISASSOC 1
u16
cmd
;
u16
reason_code
;
}
mlme
;
struct
{
u8
ssid_len
;
u8
ssid
[
32
];
}
scan_req
;
}
u
;
};
static
int
prism2_ioctl_set_encryption
(
struct
net_device
*
dev
,
struct
prism2_hostapd_param
*
param
,
int
param_len
)
{
islpci_private
*
priv
=
netdev_priv
(
dev
);
int
rvalue
=
0
,
force
=
0
;
int
authen
=
DOT11_AUTH_OS
,
invoke
=
0
,
exunencrypt
=
0
;
union
oid_res_t
r
;
/* with the new API, it's impossible to get a NULL pointer.
* New version of iwconfig set the IW_ENCODE_NOKEY flag
* when no key is given, but older versions don't. */
if
(
param
->
u
.
crypt
.
key_len
>
0
)
{
/* we have a key to set */
int
index
=
param
->
u
.
crypt
.
idx
;
int
current_index
;
struct
obj_key
key
=
{
DOT11_PRIV_TKIP
,
0
,
""
};
/* get the current key index */
rvalue
=
mgt_get_request
(
priv
,
DOT11_OID_DEFKEYID
,
0
,
NULL
,
&
r
);
current_index
=
r
.
u
;
/* Verify that the key is not marked as invalid */
if
(
!
(
param
->
u
.
crypt
.
flags
&
IW_ENCODE_NOKEY
))
{
key
.
length
=
param
->
u
.
crypt
.
key_len
>
sizeof
(
param
->
u
.
crypt
.
key
)
?
sizeof
(
param
->
u
.
crypt
.
key
)
:
param
->
u
.
crypt
.
key_len
;
memcpy
(
key
.
key
,
param
->
u
.
crypt
.
key
,
key
.
length
);
if
(
key
.
length
==
32
)
/* we want WPA-PSK */
key
.
type
=
DOT11_PRIV_TKIP
;
if
((
index
<
0
)
||
(
index
>
3
))
/* no index provided use the current one */
index
=
current_index
;
/* now send the key to the card */
rvalue
|=
mgt_set_request
(
priv
,
DOT11_OID_DEFKEYX
,
index
,
&
key
);
}
/*
* If a valid key is set, encryption should be enabled
* (user may turn it off later).
* This is also how "iwconfig ethX key on" works
*/
if
((
index
==
current_index
)
&&
(
key
.
length
>
0
))
force
=
1
;
}
else
{
int
index
=
(
param
->
u
.
crypt
.
flags
&
IW_ENCODE_INDEX
)
-
1
;
if
((
index
>=
0
)
&&
(
index
<=
3
))
{
/* we want to set the key index */
rvalue
|=
mgt_set_request
(
priv
,
DOT11_OID_DEFKEYID
,
0
,
&
index
);
}
else
{
if
(
!
param
->
u
.
crypt
.
flags
&
IW_ENCODE_MODE
)
{
/* we cannot do anything. Complain. */
return
-
EINVAL
;
}
}
}
/* now read the flags */
if
(
param
->
u
.
crypt
.
flags
&
IW_ENCODE_DISABLED
)
{
/* Encoding disabled,
* authen = DOT11_AUTH_OS;
* invoke = 0;
* exunencrypt = 0; */
}
if
(
param
->
u
.
crypt
.
flags
&
IW_ENCODE_OPEN
)
/* Encode but accept non-encoded packets. No auth */
invoke
=
1
;
if
((
param
->
u
.
crypt
.
flags
&
IW_ENCODE_RESTRICTED
)
||
force
)
{
/* Refuse non-encoded packets. Auth */
authen
=
DOT11_AUTH_BOTH
;
invoke
=
1
;
exunencrypt
=
1
;
}
/* do the change if requested */
if
((
param
->
u
.
crypt
.
flags
&
IW_ENCODE_MODE
)
||
force
)
{
rvalue
|=
mgt_set_request
(
priv
,
DOT11_OID_AUTHENABLE
,
0
,
&
authen
);
rvalue
|=
mgt_set_request
(
priv
,
DOT11_OID_PRIVACYINVOKED
,
0
,
&
invoke
);
rvalue
|=
mgt_set_request
(
priv
,
DOT11_OID_EXUNENCRYPTED
,
0
,
&
exunencrypt
);
}
return
rvalue
;
}
static
int
prism2_ioctl_set_generic_element
(
struct
net_device
*
ndev
,
struct
prism2_hostapd_param
*
param
,
int
param_len
)
{
islpci_private
*
priv
=
netdev_priv
(
ndev
);
int
max_len
,
len
,
alen
,
ret
=
0
;
struct
obj_attachment
*
attach
;
len
=
param
->
u
.
generic_elem
.
len
;
max_len
=
param_len
-
PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN
;
if
(
max_len
<
0
||
max_len
<
len
)
return
-
EINVAL
;
alen
=
sizeof
(
*
attach
)
+
len
;
attach
=
kmalloc
(
alen
,
GFP_KERNEL
);
if
(
attach
==
NULL
)
return
-
ENOMEM
;
memset
(
attach
,
0
,
alen
);
#define WLAN_FC_TYPE_MGMT 0
#define WLAN_FC_STYPE_ASSOC_REQ 0
#define WLAN_FC_STYPE_REASSOC_REQ 2
/* Note: endianness is covered by mgt_set_varlen */
attach
->
type
=
(
WLAN_FC_TYPE_MGMT
<<
2
)
|
(
WLAN_FC_STYPE_ASSOC_REQ
<<
4
);
attach
->
id
=
-
1
;
attach
->
size
=
len
;
memcpy
(
attach
->
data
,
param
->
u
.
generic_elem
.
data
,
len
);
ret
=
mgt_set_varlen
(
priv
,
DOT11_OID_ATTACHMENT
,
attach
,
len
);
if
(
ret
==
0
)
{
attach
->
type
=
(
WLAN_FC_TYPE_MGMT
<<
2
)
|
(
WLAN_FC_STYPE_REASSOC_REQ
<<
4
);
ret
=
mgt_set_varlen
(
priv
,
DOT11_OID_ATTACHMENT
,
attach
,
len
);
if
(
ret
==
0
)
printk
(
KERN_DEBUG
"%s: WPA IE Attachment was set
\n
"
,
ndev
->
name
);
}
kfree
(
attach
);
return
ret
;
}
static
int
prism2_ioctl_mlme
(
struct
net_device
*
dev
,
struct
prism2_hostapd_param
*
param
)
{
return
-
EOPNOTSUPP
;
}
static
int
prism2_ioctl_scan_req
(
struct
net_device
*
ndev
,
struct
prism2_hostapd_param
*
param
)
{
islpci_private
*
priv
=
netdev_priv
(
ndev
);
int
i
,
rvalue
;
struct
obj_bsslist
*
bsslist
;
u32
noise
=
0
;
char
*
extra
=
""
;
char
*
current_ev
=
"foo"
;
union
oid_res_t
r
;
if
(
islpci_get_state
(
priv
)
<
PRV_STATE_INIT
)
{
/* device is not ready, fail gently */
return
0
;
}
/* first get the noise value. We will use it to report the link quality */
rvalue
=
mgt_get_request
(
priv
,
DOT11_OID_NOISEFLOOR
,
0
,
NULL
,
&
r
);
noise
=
r
.
u
;
/* Ask the device for a list of known bss. We can report at most
* IW_MAX_AP=64 to the range struct. But the device won't repport anything
* if you change the value of IWMAX_BSS=24.
*/
rvalue
|=
mgt_get_request
(
priv
,
DOT11_OID_BSSLIST
,
0
,
NULL
,
&
r
);
bsslist
=
r
.
ptr
;
/* ok now, scan the list and translate its info */
for
(
i
=
0
;
i
<
min
(
IW_MAX_AP
,
(
int
)
bsslist
->
nr
);
i
++
)
current_ev
=
prism54_translate_bss
(
ndev
,
current_ev
,
extra
+
IW_SCAN_MAX_DATA
,
&
(
bsslist
->
bsslist
[
i
]),
noise
);
kfree
(
bsslist
);
return
rvalue
;
}
static
int
prism54_hostapd
(
struct
net_device
*
ndev
,
struct
iw_point
*
p
)
{
struct
prism2_hostapd_param
*
param
;
int
ret
=
0
;
u32
uwrq
;
printk
(
KERN_DEBUG
"prism54_hostapd - len=%d
\n
"
,
p
->
length
);
if
(
p
->
length
<
sizeof
(
struct
prism2_hostapd_param
)
||
p
->
length
>
PRISM2_HOSTAPD_MAX_BUF_SIZE
||
!
p
->
pointer
)
return
-
EINVAL
;
param
=
(
struct
prism2_hostapd_param
*
)
kmalloc
(
p
->
length
,
GFP_KERNEL
);
if
(
param
==
NULL
)
return
-
ENOMEM
;
if
(
copy_from_user
(
param
,
p
->
pointer
,
p
->
length
))
{
kfree
(
param
);
return
-
EFAULT
;
}
switch
(
param
->
cmd
)
{
case
PRISM2_SET_ENCRYPTION
:
printk
(
KERN_DEBUG
"%s: Caught WPA supplicant set encryption request
\n
"
,
ndev
->
name
);
ret
=
prism2_ioctl_set_encryption
(
ndev
,
param
,
p
->
length
);
break
;
case
PRISM2_HOSTAPD_SET_GENERIC_ELEMENT
:
printk
(
KERN_DEBUG
"%s: Caught WPA supplicant set WPA IE request
\n
"
,
ndev
->
name
);
ret
=
prism2_ioctl_set_generic_element
(
ndev
,
param
,
p
->
length
);
break
;
case
PRISM2_HOSTAPD_MLME
:
printk
(
KERN_DEBUG
"%s: Caught WPA supplicant MLME request
\n
"
,
ndev
->
name
);
ret
=
prism2_ioctl_mlme
(
ndev
,
param
);
break
;
case
PRISM2_HOSTAPD_SCAN_REQ
:
printk
(
KERN_DEBUG
"%s: Caught WPA supplicant scan request
\n
"
,
ndev
->
name
);
ret
=
prism2_ioctl_scan_req
(
ndev
,
param
);
break
;
case
PRISM54_SET_WPA
:
printk
(
KERN_DEBUG
"%s: Caught WPA supplicant wpa init request
\n
"
,
ndev
->
name
);
uwrq
=
1
;
ret
=
prism54_set_wpa
(
ndev
,
NULL
,
&
uwrq
,
NULL
);
break
;
case
PRISM54_DROP_UNENCRYPTED
:
printk
(
KERN_DEBUG
"%s: Caught WPA drop unencrypted request
\n
"
,
ndev
->
name
);
#if 0
uwrq = 0x01;
mgt_set(priv, DOT11_OID_EXUNENCRYPTED, &uwrq);
down_write(&priv->mib_sem);
mgt_commit(priv);
up_write(&priv->mib_sem);
#endif
/* Not necessary, as set_wpa does it, should we just do it here though? */
ret
=
0
;
break
;
default:
printk
(
KERN_DEBUG
"%s: Caught a WPA supplicant request that is not supported
\n
"
,
ndev
->
name
);
ret
=
-
EOPNOTSUPP
;
break
;
}
if
(
ret
==
0
&&
copy_to_user
(
p
->
pointer
,
param
,
p
->
length
))
ret
=
-
EFAULT
;
kfree
(
param
);
return
ret
;
}
int
prism54_set_wpa
(
struct
net_device
*
ndev
,
struct
iw_request_info
*
info
,
__u32
*
uwrq
,
char
*
extra
)
{
islpci_private
*
priv
=
netdev_priv
(
ndev
);
u32
mlme
,
authen
,
dot1x
,
filter
,
wep
;
down_write
(
&
priv
->
mib_sem
);
if
(
islpci_get_state
(
priv
)
<
PRV_STATE_INIT
)
return
0
;
wep
=
1
;
/* For privacy invoked */
filter
=
1
;
/* Filter out all unencrypted frames */
dot1x
=
0x01
;
/* To enable eap filter */
mlme
=
DOT11_MLME_EXTENDED
;
authen
=
DOT11_AUTH_OS
;
/* Only WEP uses _SK and _BOTH */
down_write
(
&
priv
->
mib_sem
);
priv
->
wpa
=
*
uwrq
;
if
(
priv
->
wpa
)
{
u32
l
=
DOT11_MLME_EXTENDED
;
mgt_set
(
priv
,
DOT11_OID_MLMEAUTOLEVEL
,
&
l
);
switch
(
priv
->
wpa
)
{
default:
case
0
:
/* Clears/disables WPA and friends */
wep
=
0
;
filter
=
0
;
/* Do not filter un-encrypted data */
dot1x
=
0
;
mlme
=
DOT11_MLME_AUTO
;
printk
(
"%s: Disabling WPA
\n
"
,
ndev
->
name
);
break
;
case
2
:
case
1
:
/* WPA */
printk
(
"%s: Enabling WPA
\n
"
,
ndev
->
name
);
break
;
}
/* restart the card with new level. Needed ? */
mgt_commit
(
priv
);
up_write
(
&
priv
->
mib_sem
);
mgt_set_request
(
priv
,
DOT11_OID_AUTHENABLE
,
0
,
&
authen
);
mgt_set_request
(
priv
,
DOT11_OID_PRIVACYINVOKED
,
0
,
&
wep
);
mgt_set_request
(
priv
,
DOT11_OID_EXUNENCRYPTED
,
0
,
&
filter
);
mgt_set_request
(
priv
,
DOT11_OID_DOT1XENABLE
,
0
,
&
dot1x
);
mgt_set_request
(
priv
,
DOT11_OID_MLMEAUTOLEVEL
,
0
,
&
mlme
);
return
0
;
}
...
...
@@ -1947,7 +2406,7 @@ prism54_debug_get_oid(struct net_device *ndev, struct iw_request_info *info,
struct
iw_point
*
data
,
char
*
extra
)
{
islpci_private
*
priv
=
netdev_priv
(
ndev
);
struct
islpci_mgmtframe
*
response
=
NULL
;
struct
islpci_mgmtframe
*
response
;
int
ret
=
-
EIO
;
printk
(
"%s: get_oid 0x%08X
\n
"
,
ndev
->
name
,
priv
->
priv_oid
);
...
...
@@ -1983,7 +2442,7 @@ prism54_debug_set_oid(struct net_device *ndev, struct iw_request_info *info,
struct
iw_point
*
data
,
char
*
extra
)
{
islpci_private
*
priv
=
netdev_priv
(
ndev
);
struct
islpci_mgmtframe
*
response
=
NULL
;
struct
islpci_mgmtframe
*
response
;
int
ret
=
0
,
response_op
=
PIMFOR_OP_ERROR
;
printk
(
"%s: set_oid 0x%08X
\t
len: %d
\n
"
,
ndev
->
name
,
priv
->
priv_oid
,
...
...
@@ -2256,14 +2715,24 @@ const struct iw_handler_def prism54_handler_def = {
.
standard
=
(
iw_handler
*
)
prism54_handler
,
.
private
=
(
iw_handler
*
)
prism54_private_handler
,
.
private_args
=
(
struct
iw_priv_args
*
)
prism54_private_args
,
#if WIRELESS_EXT == 16
.
spy_offset
=
offsetof
(
islpci_private
,
spy_data
),
#endif
/* WIRELESS_EXT == 16 */
};
/* For
ioctls that don't work with the new API
*/
/* For
wpa_supplicant
*/
int
prism54_ioctl
(
struct
net_device
*
ndev
,
struct
ifreq
*
rq
,
int
cmd
)
{
struct
iwreq
*
wrq
=
(
struct
iwreq
*
)
rq
;
int
ret
=
-
1
;
switch
(
cmd
)
{
case
PRISM54_HOSTAPD
:
if
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
ret
=
prism54_hostapd
(
ndev
,
&
wrq
->
u
.
data
);
return
ret
;
}
return
-
EOPNOTSUPP
;
}
drivers/net/wireless/prism54/isl_ioctl.h
View file @
74f54248
...
...
@@ -48,6 +48,8 @@ size_t prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie);
int
prism54_set_mac_address
(
struct
net_device
*
,
void
*
);
int
prism54_ioctl
(
struct
net_device
*
,
struct
ifreq
*
,
int
);
int
prism54_set_wpa
(
struct
net_device
*
,
struct
iw_request_info
*
,
__u32
*
,
char
*
);
extern
const
struct
iw_handler_def
prism54_handler_def
;
...
...
drivers/net/wireless/prism54/isl_oid.h
View file @
74f54248
...
...
@@ -91,6 +91,14 @@ struct obj_frequencies {
u16
mhz
[
0
];
}
__attribute__
((
packed
));
struct
obj_attachment
{
char
type
;
char
reserved
;
short
id
;
short
size
;
char
data
[
0
];
}
__attribute__
((
packed
));
/*
* in case everything's ok, the inlined function below will be
* optimized away by the compiler...
...
...
@@ -472,6 +480,7 @@ enum oid_num_t {
#define OID_TYPE_MLMEEX 0x09
#define OID_TYPE_ADDR 0x0A
#define OID_TYPE_RAW 0x0B
#define OID_TYPE_ATTACH 0x0C
/* OID_TYPE_MLMEEX is special because of a variable size field when sending.
* Not yet implemented (not used in driver anyway).
...
...
drivers/net/wireless/prism54/islpci_dev.c
View file @
74f54248
...
...
@@ -105,7 +105,7 @@ isl_upload_firmware(islpci_private *priv)
"%s: firmware '%s' size is not multiple of 32bit, aborting!
\n
"
,
"prism54"
,
priv
->
firmware
);
release_firmware
(
fw_entry
);
return
EILSEQ
;
/* Illegal byte sequence */
;
return
-
EILSEQ
;
/* Illegal byte sequence */
;
}
while
(
fw_len
>
0
)
{
...
...
@@ -142,6 +142,10 @@ isl_upload_firmware(islpci_private *priv)
BUG_ON
(
fw_len
!=
0
);
/* Firmware version is at offset 40 (also for "newmac") */
printk
(
KERN_DEBUG
"%s: firmware version: %.8s
\n
"
,
priv
->
ndev
->
name
,
fw_entry
->
data
+
40
);
release_firmware
(
fw_entry
);
}
...
...
@@ -375,8 +379,6 @@ islpci_open(struct net_device *ndev)
u32
rc
;
islpci_private
*
priv
=
netdev_priv
(
ndev
);
printk
(
KERN_DEBUG
"%s: islpci_open()
\n
"
,
ndev
->
name
);
/* reset data structures, upload firmware and reset device */
rc
=
islpci_reset
(
priv
,
1
);
if
(
rc
)
{
...
...
@@ -462,8 +464,7 @@ islpci_upload_fw(islpci_private *priv)
return
rc
;
}
printk
(
KERN_DEBUG
"%s: firmware uploaded done, now triggering reset...
\n
"
,
printk
(
KERN_DEBUG
"%s: firmware upload complete
\n
"
,
priv
->
ndev
->
name
);
islpci_set_state
(
priv
,
PRV_STATE_POSTBOOT
);
...
...
@@ -489,6 +490,7 @@ islpci_reset_if(islpci_private *priv)
/* The software reset acknowledge needs about 220 msec here.
* Be conservative and wait for up to one second. */
set_current_state
(
TASK_UNINTERRUPTIBLE
);
remaining
=
schedule_timeout
(
HZ
);
if
(
remaining
>
0
)
{
...
...
@@ -499,15 +501,16 @@ islpci_reset_if(islpci_private *priv)
/* If we're here it's because our IRQ hasn't yet gone through.
* Retry a bit more...
*/
printk
(
KERN_ERR
"%s: device soft reset timed out
\n
"
,
priv
->
ndev
->
name
);
printk
(
KERN_ERR
"%s: no 'reset complete' IRQ seen - retrying
\n
"
,
priv
->
ndev
->
name
);
}
finish_wait
(
&
priv
->
reset_done
,
&
wait
);
if
(
result
)
if
(
result
)
{
printk
(
KERN_ERR
"%s: interface reset failure
\n
"
,
priv
->
ndev
->
name
);
return
result
;
}
islpci_set_state
(
priv
,
PRV_STATE_INIT
);
...
...
@@ -519,11 +522,17 @@ islpci_reset_if(islpci_private *priv)
isl38xx_enable_common_interrupts
(
priv
->
device_base
);
down_write
(
&
priv
->
mib_sem
);
mgt_commit
(
priv
);
result
=
mgt_commit
(
priv
);
if
(
result
)
{
printk
(
KERN_ERR
"%s: interface reset failure
\n
"
,
priv
->
ndev
->
name
);
up_write
(
&
priv
->
mib_sem
);
return
result
;
}
up_write
(
&
priv
->
mib_sem
);
islpci_set_state
(
priv
,
PRV_STATE_READY
);
printk
(
KERN_DEBUG
"%s: interface reset complete
\n
"
,
priv
->
ndev
->
name
);
return
0
;
}
...
...
@@ -584,18 +593,18 @@ islpci_reset(islpci_private *priv, int reload_firmware)
/* now that the data structures are cleaned up, upload
* firmware and reset interface */
rc
=
islpci_upload_fw
(
priv
);
if
(
rc
)
if
(
rc
)
{
printk
(
KERN_ERR
"%s: islpci_reset: failure
\n
"
,
priv
->
ndev
->
name
);
return
rc
;
}
}
/* finally reset interface */
rc
=
islpci_reset_if
(
priv
);
if
(
!
rc
)
/* If successful */
return
rc
;
printk
(
KERN_DEBUG
"prism54: Your card/socket may be faulty, or IRQ line too busy :(
\n
"
);
if
(
rc
)
printk
(
KERN_ERR
"prism54: Your card/socket may be faulty, or IRQ line too busy :(
\n
"
);
return
rc
;
}
struct
net_device_stats
*
...
...
@@ -604,7 +613,7 @@ islpci_statistics(struct net_device *ndev)
islpci_private
*
priv
=
netdev_priv
(
ndev
);
#if VERBOSE > SHOW_ERROR_MESSAGES
DEBUG
(
SHOW_FUNCTION_CALLS
,
"islpci_statistics
\n
"
);
DEBUG
(
SHOW_FUNCTION_CALLS
,
"islpci_statistics
\n
"
);
#endif
return
&
priv
->
statistics
;
...
...
@@ -830,6 +839,12 @@ islpci_setup(struct pci_dev *pdev)
priv
->
ndev
->
type
=
(
priv
->
iw_mode
==
IW_MODE_MONITOR
)
?
priv
->
monitor_type
:
ARPHRD_ETHER
;
#if WIRELESS_EXT > 16
/* Add pointers to enable iwspy support. */
priv
->
wireless_data
.
spy_data
=
&
priv
->
spy_data
;
ndev
->
wireless_data
=
&
priv
->
wireless_data
;
#endif
/* WIRELESS_EXT > 16 */
/* save the start and end address of the PCI memory area */
ndev
->
mem_start
=
(
unsigned
long
)
priv
->
device_base
;
ndev
->
mem_end
=
ndev
->
mem_start
+
ISL38XX_PCI_MEM_SIZE
;
...
...
drivers/net/wireless/prism54/islpci_dev.h
View file @
74f54248
...
...
@@ -100,6 +100,10 @@ typedef struct {
struct
iw_spy_data
spy_data
;
/* iwspy support */
#if WIRELESS_EXT > 16
struct
iw_public_data
wireless_data
;
#endif
/* WIRELESS_EXT > 16 */
int
monitor_type
;
/* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */
struct
islpci_acl
acl
;
...
...
drivers/net/wireless/prism54/islpci_eth.c
View file @
74f54248
...
...
@@ -508,11 +508,12 @@ islpci_eth_tx_timeout(struct net_device *ndev)
/* increment the transmit error counter */
statistics
->
tx_errors
++
;
printk
(
KERN_WARNING
"%s: tx_timeout"
,
ndev
->
name
);
if
(
!
priv
->
reset_task_pending
)
{
priv
->
reset_task_pending
=
1
;
printk
(
", scheduling a reset"
);
netif_stop_queue
(
ndev
);
schedule_work
(
&
priv
->
reset_task
);
}
return
;
printk
(
"
\n
"
);
}
drivers/net/wireless/prism54/islpci_hotplug.c
View file @
74f54248
...
...
@@ -107,9 +107,6 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
islpci_private
*
priv
;
int
rvalue
;
/* TRACE(DRV_NAME); */
/* Enable the pci device */
if
(
pci_enable_device
(
pdev
))
{
printk
(
KERN_ERR
"%s: pci_enable_device() failed.
\n
"
,
DRV_NAME
);
...
...
drivers/net/wireless/prism54/islpci_mgt.c
View file @
74f54248
...
...
@@ -473,6 +473,7 @@ islpci_mgt_transaction(struct net_device *ndev,
int
timeleft
;
struct
islpci_mgmtframe
*
frame
;
set_current_state
(
TASK_UNINTERRUPTIBLE
);
timeleft
=
schedule_timeout
(
wait_cycle_jiffies
);
frame
=
xchg
(
&
priv
->
mgmt_received
,
NULL
);
if
(
frame
)
{
...
...
drivers/net/wireless/prism54/islpci_mgt.h
View file @
74f54248
...
...
@@ -31,8 +31,6 @@
#define K_DEBUG(f, m, args...) do { if(f & m) printk(KERN_DEBUG args); } while(0)
#define DEBUG(f, args...) K_DEBUG(f, pc_debug, args)
#define TRACE(devname) K_DEBUG(SHOW_TRACING, VERBOSE, "%s: -> " __FUNCTION__ "()\n", devname)
extern
int
pc_debug
;
#define init_wds 0
/* help compiler optimize away dead code */
...
...
drivers/net/wireless/prism54/oid_mgt.c
View file @
74f54248
...
...
@@ -201,7 +201,8 @@ struct oid_t isl_oid[] = {
OID_U32
(
DOT11_OID_STATIMEOUT
,
0x19000000
),
OID_U32_C
(
DOT11_OID_MLMEAUTOLEVEL
,
0x19000001
),
OID_U32
(
DOT11_OID_BSSTIMEOUT
,
0x19000002
),
OID_UNKNOWN
(
DOT11_OID_ATTACHMENT
,
0x19000003
),
[
DOT11_OID_ATTACHMENT
]
=
{
0x19000003
,
0
,
sizeof
(
struct
obj_attachment
),
OID_TYPE_ATTACH
},
OID_STRUCT_C
(
DOT11_OID_PSMBUFFER
,
0x19000004
,
struct
obj_buffer
,
OID_TYPE_BUFFER
),
...
...
@@ -329,6 +330,12 @@ mgt_le_to_cpu(int type, void *data)
mlme
->
size
=
le16_to_cpu
(
mlme
->
size
);
break
;
}
case
OID_TYPE_ATTACH
:{
struct
obj_attachment
*
attach
=
data
;
attach
->
id
=
le16_to_cpu
(
attach
->
id
);
attach
->
size
=
le16_to_cpu
(
attach
->
size
);;
break
;
}
case
OID_TYPE_SSID
:
case
OID_TYPE_KEY
:
case
OID_TYPE_ADDR
:
...
...
@@ -392,6 +399,12 @@ mgt_cpu_to_le(int type, void *data)
mlme
->
size
=
cpu_to_le16
(
mlme
->
size
);
break
;
}
case
OID_TYPE_ATTACH
:{
struct
obj_attachment
*
attach
=
data
;
attach
->
id
=
cpu_to_le16
(
attach
->
id
);
attach
->
size
=
cpu_to_le16
(
attach
->
size
);;
break
;
}
case
OID_TYPE_SSID
:
case
OID_TYPE_KEY
:
case
OID_TYPE_ADDR
:
...
...
@@ -465,6 +478,42 @@ mgt_set_request(islpci_private *priv, enum oid_num_t n, int extra, void *data)
return
ret
;
}
/* None of these are cached */
int
mgt_set_varlen
(
islpci_private
*
priv
,
enum
oid_num_t
n
,
void
*
data
,
int
extra_len
)
{
int
ret
=
0
;
struct
islpci_mgmtframe
*
response
;
int
response_op
=
PIMFOR_OP_ERROR
;
int
dlen
;
u32
oid
;
BUG_ON
(
OID_NUM_LAST
<=
n
);
dlen
=
isl_oid
[
n
].
size
;
oid
=
isl_oid
[
n
].
oid
;
mgt_cpu_to_le
(
isl_oid
[
n
].
flags
&
OID_FLAG_TYPE
,
data
);
if
(
islpci_get_state
(
priv
)
>=
PRV_STATE_READY
)
{
ret
=
islpci_mgt_transaction
(
priv
->
ndev
,
PIMFOR_OP_SET
,
oid
,
data
,
dlen
+
extra_len
,
&
response
);
if
(
!
ret
)
{
response_op
=
response
->
header
->
operation
;
islpci_mgt_release
(
response
);
}
if
(
ret
||
response_op
==
PIMFOR_OP_ERROR
)
ret
=
-
EIO
;
}
else
ret
=
-
EIO
;
/* re-set given data to what it was */
if
(
data
)
mgt_le_to_cpu
(
isl_oid
[
n
].
flags
&
OID_FLAG_TYPE
,
data
);
return
ret
;
}
int
mgt_get_request
(
islpci_private
*
priv
,
enum
oid_num_t
n
,
int
extra
,
void
*
data
,
union
oid_res_t
*
res
)
...
...
@@ -555,15 +604,18 @@ mgt_commit_list(islpci_private *priv, enum oid_num_t *l, int n)
u32
oid
=
t
->
oid
;
BUG_ON
(
data
==
NULL
);
while
(
j
<=
t
->
range
)
{
response
=
NULL
;
ret
|=
islpci_mgt_transaction
(
priv
->
ndev
,
PIMFOR_OP_SET
,
int
r
=
islpci_mgt_transaction
(
priv
->
ndev
,
PIMFOR_OP_SET
,
oid
,
data
,
t
->
size
,
&
response
);
if
(
response
)
{
ret
|=
(
response
->
header
->
operation
==
PIMFOR_OP_ERROR
);
r
|=
(
response
->
header
->
operation
==
PIMFOR_OP_ERROR
);
islpci_mgt_release
(
response
);
}
if
(
r
)
printk
(
KERN_ERR
"%s: mgt_commit_list: failure. "
"oid=%08x err=%d
\n
"
,
priv
->
ndev
->
name
,
oid
,
r
);
ret
|=
r
;
j
++
;
oid
++
;
data
+=
t
->
size
;
...
...
@@ -624,7 +676,7 @@ static enum oid_num_t commit_part2[] = {
static
int
mgt_update_addr
(
islpci_private
*
priv
)
{
struct
islpci_mgmtframe
*
res
=
NULL
;
struct
islpci_mgmtframe
*
res
;
int
ret
;
ret
=
islpci_mgt_transaction
(
priv
->
ndev
,
PIMFOR_OP_GET
,
...
...
@@ -638,26 +690,26 @@ mgt_update_addr(islpci_private *priv)
if
(
res
)
islpci_mgt_release
(
res
);
if
(
ret
)
printk
(
KERN_ERR
"%s: mgt_update_addr: failure
\n
"
,
priv
->
ndev
->
name
);
return
ret
;
}
void
#define VEC_SIZE(a) (sizeof(a)/sizeof(a[0]))
int
mgt_commit
(
islpci_private
*
priv
)
{
int
rvalue
;
u32
u
;
if
(
islpci_get_state
(
priv
)
<
PRV_STATE_INIT
)
return
;
return
0
;
rvalue
=
mgt_commit_list
(
priv
,
commit_part1
,
sizeof
(
commit_part1
)
/
sizeof
(
commit_part1
[
0
]));
rvalue
=
mgt_commit_list
(
priv
,
commit_part1
,
VEC_SIZE
(
commit_part1
));
if
(
priv
->
iw_mode
!=
IW_MODE_MONITOR
)
rvalue
|=
mgt_commit_list
(
priv
,
commit_part2
,
sizeof
(
commit_part2
)
/
sizeof
(
commit_part2
[
0
]));
rvalue
|=
mgt_commit_list
(
priv
,
commit_part2
,
VEC_SIZE
(
commit_part2
));
u
=
OID_INL_MODE
;
rvalue
|=
mgt_commit_list
(
priv
,
&
u
,
1
);
...
...
@@ -666,9 +718,43 @@ mgt_commit(islpci_private *priv)
if
(
rvalue
)
{
/* some request have failed. The device might be in an
incoherent state. We should reset it ! */
printk
(
KERN_DEBUG
"%s: mgt_commit has failed. Restart the "
"device
\n
"
,
priv
->
ndev
->
name
);
printk
(
KERN_DEBUG
"%s: mgt_commit: failure
\n
"
,
priv
->
ndev
->
name
);
}
return
rvalue
;
}
/* The following OIDs need to be "unlatched":
*
* MEDIUMLIMIT,BEACONPERIOD,DTIMPERIOD,ATIMWINDOW,LISTENINTERVAL
* FREQUENCY,EXTENDEDRATES.
*
* The way to do this is to set ESSID. Note though that they may get
* unlatch before though by setting another OID. */
void
mgt_unlatch_all
(
islpci_private
*
priv
)
{
u32
u
;
int
rvalue
=
0
;
if
(
islpci_get_state
(
priv
)
<
PRV_STATE_INIT
)
return
;
u
=
DOT11_OID_SSID
;
rvalue
=
mgt_commit_list
(
priv
,
&
u
,
1
);
/* Necessary if in MANUAL RUN mode? */
#if 0
u = OID_INL_MODE;
rvalue |= mgt_commit_list(priv, &u, 1);
u = DOT11_OID_MLMEAUTOLEVEL;
rvalue |= mgt_commit_list(priv, &u, 1);
u = OID_INL_MODE;
rvalue |= mgt_commit_list(priv, &u, 1);
#endif
if
(
rvalue
)
printk
(
KERN_DEBUG
"%s: Unlatching OIDs failed
\n
"
,
priv
->
ndev
->
name
);
}
/* This will tell you if you are allowed to answer a mlme(ex) request .*/
...
...
@@ -771,6 +857,14 @@ mgt_response_to_str(enum oid_num_t n, union oid_res_t *r, char *str)
mlme
->
state
,
mlme
->
code
,
mlme
->
size
);
}
break
;
case
OID_TYPE_ATTACH
:{
struct
obj_attachment
*
attach
=
r
->
ptr
;
return
snprintf
(
str
,
PRIV_STR_SIZE
,
"id=%d
\n
size=%d
\n
"
,
attach
->
id
,
attach
->
size
);
}
break
;
case
OID_TYPE_SSID
:{
struct
obj_ssid
*
ssid
=
r
->
ptr
;
return
snprintf
(
str
,
PRIV_STR_SIZE
,
...
...
drivers/net/wireless/prism54/oid_mgt.h
View file @
74f54248
...
...
@@ -36,6 +36,8 @@ int channel_of_freq(int);
void
mgt_le_to_cpu
(
int
,
void
*
);
int
mgt_set_request
(
islpci_private
*
,
enum
oid_num_t
,
int
,
void
*
);
int
mgt_set_varlen
(
islpci_private
*
,
enum
oid_num_t
,
void
*
,
int
);
int
mgt_get_request
(
islpci_private
*
,
enum
oid_num_t
,
int
,
void
*
,
union
oid_res_t
*
);
...
...
@@ -46,7 +48,8 @@ void mgt_set(islpci_private *, enum oid_num_t, void *);
void
mgt_get
(
islpci_private
*
,
enum
oid_num_t
,
void
*
);
void
mgt_commit
(
islpci_private
*
);
int
mgt_commit
(
islpci_private
*
);
void
mgt_unlatch_all
(
islpci_private
*
);
int
mgt_mlme_answer
(
islpci_private
*
);
...
...
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