Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
58b2a6d4
Commit
58b2a6d4
authored
Jul 27, 2004
by
Jeff Garzik
Browse files
Options
Browse Files
Download
Plain Diff
Merge pobox.com:/spare/repo/linux-2.6
into pobox.com:/spare/repo/netdev-2.6/via-rhine
parents
a6ba40b5
f851943e
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
354 additions
and
337 deletions
+354
-337
drivers/net/via-rhine.c
drivers/net/via-rhine.c
+354
-337
No files found.
drivers/net/via-rhine.c
View file @
58b2a6d4
...
...
@@ -125,11 +125,16 @@
LK1.1.19 (Roger Luethi)
- Increase Tx threshold for unspecified errors
LK1.2.0-2.6 (Roger Luethi)
- Massive clean-up
- Rewrite PHY, media handling (remove options, full_duplex, backoff)
- Fix Tx engine race for good
*/
#define DRV_NAME "via-rhine"
#define DRV_VERSION "1.
1.2
0-2.6"
#define DRV_RELDATE "
May-23
-2004"
#define DRV_VERSION "1.
2.
0-2.6"
#define DRV_RELDATE "
June-10
-2004"
/* A few user-configurable values.
...
...
@@ -142,22 +147,10 @@ static int max_interrupt_work = 20;
Setting to > 1518 effectively disables this feature. */
static
int
rx_copybreak
;
/* Select a backoff algorithm (Ethernet capture effect) */
static
int
backoff
;
/* Used to pass the media type, etc.
Both 'options[]' and 'full_duplex[]' should exist for driver
interoperability.
The media type is usually passed in 'options[]'.
The default is autonegotiation for speed and duplex.
This should rarely be overridden.
Use option values 0x10/0x20 for 10Mbps, 0x100,0x200 for 100Mbps.
Use option values 0x10 and 0x100 for forcing half duplex fixed speed.
Use option values 0x20 and 0x200 for forcing full duplex operation.
*/
#define MAX_UNITS 8
/* More are supported, limit only on options */
static
int
options
[
MAX_UNITS
]
=
{
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
};
static
int
full_duplex
[
MAX_UNITS
]
=
{
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
};
/*
* In case you are looking for 'options[]' or 'full_duplex[]', they
* are gone. Use ethtool(8) instead.
*/
/* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
The Rhine has a 64 element 8390-like hash table. */
...
...
@@ -210,9 +203,6 @@ static const int multicast_filter_limit = 32;
static
char
version
[]
__devinitdata
=
KERN_INFO
DRV_NAME
".c:v1.10-LK"
DRV_VERSION
" "
DRV_RELDATE
" Written by Donald Becker
\n
"
;
static
char
shortname
[]
=
DRV_NAME
;
/* This driver was written to use PCI memory space. Some early versions
of the Rhine may only work correctly with I/O space accesses. */
#ifdef CONFIG_VIA_RHINE_MMIO
...
...
@@ -239,15 +229,9 @@ MODULE_LICENSE("GPL");
MODULE_PARM
(
max_interrupt_work
,
"i"
);
MODULE_PARM
(
debug
,
"i"
);
MODULE_PARM
(
rx_copybreak
,
"i"
);
MODULE_PARM
(
backoff
,
"i"
);
MODULE_PARM
(
options
,
"1-"
__MODULE_STRING
(
MAX_UNITS
)
"i"
);
MODULE_PARM
(
full_duplex
,
"1-"
__MODULE_STRING
(
MAX_UNITS
)
"i"
);
MODULE_PARM_DESC
(
max_interrupt_work
,
"VIA Rhine maximum events handled per interrupt"
);
MODULE_PARM_DESC
(
debug
,
"VIA Rhine debug level (0-7)"
);
MODULE_PARM_DESC
(
rx_copybreak
,
"VIA Rhine copy breakpoint for copy-only-tiny-frames"
);
MODULE_PARM_DESC
(
backoff
,
"VIA Rhine: Bits 0-3: backoff algorithm"
);
MODULE_PARM_DESC
(
options
,
"VIA Rhine: Bits 0-3: media type, bit 17: full duplex"
);
MODULE_PARM_DESC
(
full_duplex
,
"VIA Rhine full duplex setting(s) (1)"
);
/*
Theory of Operation
...
...
@@ -350,24 +334,24 @@ The chip does not pad to minimum transmit length.
enum
rhine_revs
{
VT86C100A
=
0x00
,
VTunknown0
=
0x20
,
VT6102
=
0x40
,
VT8231
=
0x50
,
/* Integrated MAC */
VT8233
=
0x60
,
/* Integrated MAC */
VT8235
=
0x74
,
/* Integrated MAC */
VT8237
=
0x78
,
/* Integrated MAC */
VTunknown
0
=
0x7C
,
VTunknown
1
=
0x7C
,
VT6105
=
0x80
,
VT6105_B0
=
0x83
,
VT6105L
=
0x8A
,
VT6107
=
0x8C
,
VTunknown
1
=
0x8E
,
VTunknown
2
=
0x8E
,
VT6105M
=
0x90
,
};
enum
rhine_quirks
{
rqWOL
=
0x0001
,
/* Wake-On-LAN support */
rqForceReset
=
0x0002
,
rqDavicomPhy
=
0x0020
,
rq6patterns
=
0x0040
,
/* 6 instead of 4 patterns for WOL */
rqStatusWBRace
=
0x0080
,
/* Tx Status Writeback Error possible */
rqRhineI
=
0x0100
,
/* See comment below */
...
...
@@ -395,6 +379,7 @@ MODULE_DEVICE_TABLE(pci, rhine_pci_tbl);
/* Offsets to the device registers. */
enum
register_offsets
{
StationAddr
=
0x00
,
RxConfig
=
0x06
,
TxConfig
=
0x07
,
ChipCmd
=
0x08
,
ChipCmd1
=
0x09
,
IntrStatus
=
0x0C
,
IntrEnable
=
0x0E
,
MulticastFilter0
=
0x10
,
MulticastFilter1
=
0x14
,
RxRingPtr
=
0x18
,
TxRingPtr
=
0x1C
,
GFIFOTest
=
0x54
,
...
...
@@ -403,8 +388,8 @@ enum register_offsets {
ConfigA
=
0x78
,
ConfigB
=
0x79
,
ConfigC
=
0x7A
,
ConfigD
=
0x7B
,
RxMissed
=
0x7C
,
RxCRCErrs
=
0x7E
,
MiscCmd
=
0x81
,
StickyHW
=
0x83
,
IntrStatus2
=
0x84
,
WOLcrSet
=
0xA0
,
WOLcrClr
=
0xA4
,
WOLcrClr1
=
0xA6
,
WOLcgClr
=
0xA7
,
WOLcrSet
=
0xA0
,
PwcfgSet
=
0xA1
,
WOLcgSet
=
0xA3
,
WOLcrClr
=
0xA4
,
WOLc
rClr1
=
0xA6
,
WOLc
gClr
=
0xA7
,
PwrcsrSet
=
0xA8
,
PwrcsrSet1
=
0xA9
,
PwrcsrClr
=
0xAC
,
PwrcsrClr1
=
0xAD
,
};
...
...
@@ -436,6 +421,15 @@ enum intr_status_bits {
IntrTxErrSummary
=
0x082218
,
};
/* Bits in WOLcrSet/WOLcrClr and PwrcsrSet/PwrcsrClr */
enum
wol_bits
{
WOLucast
=
0x10
,
WOLmagic
=
0x20
,
WOLbmcast
=
0x30
,
WOLlnkon
=
0x40
,
WOLlnkoff
=
0x80
,
};
/* The Rx and Tx buffer descriptors. */
struct
rx_desc
{
s32
rx_status
;
...
...
@@ -464,13 +458,12 @@ enum desc_status_bits {
/* Bits in ChipCmd. */
enum
chip_cmd_bits
{
CmdInit
=
0x0
001
,
CmdStart
=
0x0002
,
CmdStop
=
0x0004
,
CmdRxOn
=
0x00
08
,
CmdTxOn
=
0x
0010
,
CmdTxDemand
=
0x0020
,
CmdRxDemand
=
0x00
40
,
Cmd
EarlyRx
=
0x0100
,
CmdEarlyTx
=
0x0200
,
CmdFDuplex
=
0x0400
,
Cmd
NoTxPoll
=
0x0800
,
CmdReset
=
0x800
0
,
CmdInit
=
0x0
1
,
CmdStart
=
0x02
,
CmdStop
=
0x04
,
CmdRxOn
=
0x
08
,
CmdTxOn
=
0x
10
,
Cmd1TxDemand
=
0x20
,
CmdRxDemand
=
0x
40
,
Cmd
1EarlyRx
=
0x01
,
Cmd1EarlyTx
=
0x02
,
Cmd1FDuplex
=
0x04
,
Cmd
1NoTxPoll
=
0x08
,
Cmd1Reset
=
0x8
0
,
};
#define MAX_MII_CNT 4
struct
rhine_private
{
/* Descriptor rings */
struct
rx_desc
*
rx_ring
;
...
...
@@ -493,7 +486,6 @@ struct rhine_private {
struct
pci_dev
*
pdev
;
struct
net_device_stats
stats
;
struct
timer_list
timer
;
/* Media monitoring timer. */
spinlock_t
lock
;
/* Frequently used values: keep some adjacent for cache effect. */
...
...
@@ -502,23 +494,16 @@ struct rhine_private {
unsigned
int
cur_rx
,
dirty_rx
;
/* Producer/consumer ring indices */
unsigned
int
cur_tx
,
dirty_tx
;
unsigned
int
rx_buf_sz
;
/* Based on MTU+slack. */
u
16
chip_cmd
;
/* Current setting for ChipCmd */
u
8
wolopts
;
/* These values are keep track of the transceiver/media in use. */
u8
tx_thresh
,
rx_thresh
;
/* MII transceiver section. */
unsigned
char
phys
[
MAX_MII_CNT
];
/* MII device addresses. */
unsigned
int
mii_cnt
;
/* number of MIIs found, but only the first one is used */
u16
mii_status
;
/* last read MII status */
struct
mii_if_info
mii_if
;
};
static
int
mdio_read
(
struct
net_device
*
dev
,
int
phy_id
,
int
location
);
static
void
mdio_write
(
struct
net_device
*
dev
,
int
phy_id
,
int
location
,
int
value
);
static
int
rhine_open
(
struct
net_device
*
dev
);
static
void
rhine_check_duplex
(
struct
net_device
*
dev
);
static
void
rhine_timer
(
unsigned
long
data
);
static
void
rhine_tx_timeout
(
struct
net_device
*
dev
);
static
int
rhine_start_tx
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
);
static
irqreturn_t
rhine_interrupt
(
int
irq
,
void
*
dev_instance
,
struct
pt_regs
*
regs
);
...
...
@@ -530,6 +515,16 @@ static struct net_device_stats *rhine_get_stats(struct net_device *dev);
static
int
netdev_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
);
static
struct
ethtool_ops
netdev_ethtool_ops
;
static
int
rhine_close
(
struct
net_device
*
dev
);
static
void
rhine_shutdown
(
struct
device
*
gdev
);
#define RHINE_WAIT_FOR(condition) do { \
int i=1024; \
while (!(condition) && --i) \
; \
if (debug > 1 && i < 512) \
printk(KERN_INFO "%s: %4d cycles used @ %s:%d\n", \
DRV_NAME, 1024-i, __func__, __LINE__); \
} while(0)
static
inline
u32
get_intr_status
(
struct
net_device
*
dev
)
{
...
...
@@ -546,12 +541,13 @@ static inline u32 get_intr_status(struct net_device *dev)
/*
* Get power related registers into sane state.
*
Returns content of power-event (WOL) registers
.
*
Notify user about past WOL event
.
*/
static
void
rhine_power_init
(
struct
net_device
*
dev
)
{
long
ioaddr
=
dev
->
base_addr
;
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
u16
wolstat
;
if
(
rp
->
quirks
&
rqWOL
)
{
/* Make sure chip is in power state D0 */
...
...
@@ -566,63 +562,109 @@ static void rhine_power_init(struct net_device *dev)
if
(
rp
->
quirks
&
rq6patterns
)
writeb
(
0x03
,
ioaddr
+
WOLcrClr1
);
/* Save power-event status bits */
wolstat
=
readb
(
ioaddr
+
PwrcsrSet
);
if
(
rp
->
quirks
&
rq6patterns
)
wolstat
|=
(
readb
(
ioaddr
+
PwrcsrSet1
)
&
0x03
)
<<
8
;
/* Clear power-event status bits */
writeb
(
0xFF
,
ioaddr
+
PwrcsrClr
);
if
(
rp
->
quirks
&
rq6patterns
)
writeb
(
0x03
,
ioaddr
+
PwrcsrClr1
);
if
(
wolstat
)
{
char
*
reason
;
switch
(
wolstat
)
{
case
WOLmagic
:
reason
=
"Magic packet"
;
break
;
case
WOLlnkon
:
reason
=
"Link went up"
;
break
;
case
WOLlnkoff
:
reason
=
"Link went down"
;
break
;
case
WOLucast
:
reason
=
"Unicast packet"
;
break
;
case
WOLbmcast
:
reason
=
"Multicast/broadcast packet"
;
break
;
default:
reason
=
"Unknown"
;
}
printk
(
"%s: Woke system up. Reason: %s.
\n
"
,
DRV_NAME
,
reason
);
}
}
}
static
void
wait_for_reset
(
struct
net_device
*
dev
,
u32
quirks
,
char
*
name
)
static
void
rhine_chip_reset
(
struct
net_device
*
dev
)
{
long
ioaddr
=
dev
->
base_addr
;
int
boguscnt
=
20
;
struct
rhine_private
*
rp
=
netdev_priv
(
dev
)
;
writeb
(
Cmd1Reset
,
ioaddr
+
ChipCmd1
);
IOSYNC
;
if
(
read
w
(
ioaddr
+
ChipCmd
)
&
Cmd
Reset
)
{
if
(
read
b
(
ioaddr
+
ChipCmd1
)
&
Cmd1
Reset
)
{
printk
(
KERN_INFO
"%s: Reset not complete yet. "
"Trying harder.
\n
"
,
name
);
"Trying harder.
\n
"
,
DRV_NAME
);
/*
Rhine-II needs to be forced sometimes
*/
if
(
quirks
&
rqForceReset
)
/*
Force reset
*/
if
(
rp
->
quirks
&
rqForceReset
)
writeb
(
0x40
,
ioaddr
+
MiscCmd
);
/* VT86C100A may need long delay after reset (dlink) */
/* Seen on Rhine-II as well (rl) */
while
((
readw
(
ioaddr
+
ChipCmd
)
&
CmdReset
)
&&
--
boguscnt
)
udelay
(
5
);
/* Reset can take somewhat longer (rare) */
RHINE_WAIT_FOR
(
!
(
readb
(
ioaddr
+
ChipCmd1
)
&
Cmd1Reset
));
}
if
(
debug
>
1
)
printk
(
KERN_INFO
"%s: Reset %s.
\n
"
,
name
,
boguscnt
?
"succeeded"
:
"failed"
);
printk
(
KERN_INFO
"%s: Reset %s.
\n
"
,
dev
->
name
,
(
readb
(
ioaddr
+
ChipCmd1
)
&
Cmd1Reset
)
?
"failed"
:
"succeeded"
);
}
#ifdef USE_MMIO
static
void
__devinit
enable_mmio
(
long
ioaddr
,
u32
quirks
)
static
void
__devinit
enable_mmio
(
long
p
ioaddr
,
u32
quirks
)
{
int
n
;
if
(
quirks
&
rqRhineI
)
{
/* More recent docs say that this bit is reserved ... */
n
=
inb
(
ioaddr
+
ConfigA
)
|
0x20
;
outb
(
n
,
ioaddr
+
ConfigA
);
n
=
inb
(
p
ioaddr
+
ConfigA
)
|
0x20
;
outb
(
n
,
p
ioaddr
+
ConfigA
);
}
else
{
n
=
inb
(
ioaddr
+
ConfigD
)
|
0x80
;
outb
(
n
,
ioaddr
+
ConfigD
);
n
=
inb
(
p
ioaddr
+
ConfigD
)
|
0x80
;
outb
(
n
,
p
ioaddr
+
ConfigD
);
}
}
#endif
static
void
__devinit
reload_eeprom
(
long
ioaddr
)
/*
* Loads bytes 0x00-0x05, 0x6E-0x6F, 0x78-0x7B from EEPROM
* (plus 0x6C for Rhine-I/II)
*/
static
void
__devinit
rhine_reload_eeprom
(
long
pioaddr
,
struct
net_device
*
dev
)
{
int
i
;
outb
(
0x20
,
ioaddr
+
MACRegEEcsr
);
/* Typically 2 cycles to reload. */
for
(
i
=
0
;
i
<
150
;
i
++
)
if
(
!
(
inb
(
ioaddr
+
MACRegEEcsr
)
&
0x20
))
break
;
long
ioaddr
=
dev
->
base_addr
;
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
outb
(
0x20
,
pioaddr
+
MACRegEEcsr
);
RHINE_WAIT_FOR
(
!
(
inb
(
pioaddr
+
MACRegEEcsr
)
&
0x20
));
#ifdef USE_MMIO
/*
* Reloading from EEPROM overwrites ConfigA-D, so we must re-enable
* MMIO. If reloading EEPROM was done first this could be avoided, but
* it is not known if that still works with the "win98-reboot" problem.
*/
enable_mmio
(
pioaddr
,
rp
->
quirks
);
#endif
/* Turn off EEPROM-controlled wake-up (magic packet) */
if
(
rp
->
quirks
&
rqWOL
)
writeb
(
readb
(
ioaddr
+
ConfigA
)
&
0xFE
,
ioaddr
+
ConfigA
);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
...
...
@@ -634,23 +676,34 @@ static void rhine_poll(struct net_device *dev)
}
#endif
static
void
rhine_hw_init
(
struct
net_device
*
dev
,
long
pioaddr
)
{
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
/* Reset the chip to erase previous misconfiguration. */
rhine_chip_reset
(
dev
);
/* Rhine-I needs extra time to recuperate before EEPROM reload */
if
(
rp
->
quirks
&
rqRhineI
)
msleep
(
5
);
/* Reload EEPROM controlled bytes cleared by soft reset */
rhine_reload_eeprom
(
pioaddr
,
dev
);
}
static
int
__devinit
rhine_init_one
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
{
struct
net_device
*
dev
;
struct
rhine_private
*
rp
;
int
i
,
option
,
rc
;
int
i
,
rc
;
u8
pci_rev
;
u32
quirks
;
static
int
card_idx
=
-
1
;
long
ioaddr
;
long
pioaddr
;
long
memaddr
;
int
io_size
;
int
phy
,
phy_idx
=
0
;
#ifdef USE_MMIO
long
ioaddr0
;
#endif
const
char
*
name
;
long
ioaddr
;
int
io_size
,
phy_id
;
const
char
*
name
,
*
mname
;
/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
...
...
@@ -659,26 +712,47 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
printk
(
version
);
#endif
card_idx
++
;
option
=
card_idx
<
MAX_UNITS
?
options
[
card_idx
]
:
0
;
pci_read_config_byte
(
pdev
,
PCI_REVISION_ID
,
&
pci_rev
);
io_size
=
256
;
if
(
pci_rev
<
VT6102
)
{
quirks
=
rqRhineI
|
rqDavicomPhy
;
phy_id
=
0
;
quirks
=
0
;
name
=
"Rhine"
;
mname
=
"unknown"
;
if
(
pci_rev
<
VTunknown0
)
{
quirks
=
rqRhineI
;
io_size
=
128
;
name
=
"VT86C100A Rhine
"
;
mname
=
"VT86C100A
"
;
}
else
{
else
if
(
pci_rev
>=
VT6102
)
{
quirks
=
rqWOL
|
rqForceReset
;
if
(
pci_rev
<
VT6105
)
{
name
=
"Rhine II"
;
quirks
|=
rqStatusWBRace
;
/* Rhine-II exclusive */
if
(
pci_rev
<
VT8231
)
mname
=
"VT6102"
;
else
if
(
pci_rev
<
VT8233
)
mname
=
"VT8231"
;
else
if
(
pci_rev
<
VT8235
)
mname
=
"VT8233"
;
else
if
(
pci_rev
<
VT8237
)
mname
=
"VT8235"
;
else
if
(
pci_rev
<
VTunknown1
)
mname
=
"VT8237"
;
}
else
{
name
=
"Rhine III"
;
phy_id
=
1
;
/* Integrated PHY, phy_id fixed to 1 */
if
(
pci_rev
>=
VT6105_B0
)
quirks
|=
rq6patterns
;
if
(
pci_rev
<
VT6105L
)
mname
=
"VT6105"
;
else
if
(
pci_rev
<
VT6107
)
mname
=
"VT6105L"
;
else
if
(
pci_rev
<
VT6105M
)
mname
=
"VT6107"
;
else
if
(
pci_rev
>=
VT6105M
)
mname
=
"Management Adapter VT6105M"
;
}
}
...
...
@@ -702,28 +776,26 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
goto
err_out
;
}
ioaddr
=
pci_resource_start
(
pdev
,
0
);
p
ioaddr
=
pci_resource_start
(
pdev
,
0
);
memaddr
=
pci_resource_start
(
pdev
,
1
);
pci_set_master
(
pdev
);
dev
=
alloc_etherdev
(
sizeof
(
*
rp
));
if
(
dev
==
NULL
)
{
dev
=
alloc_etherdev
(
sizeof
(
struct
rhine_private
));
if
(
!
dev
)
{
rc
=
-
ENOMEM
;
printk
(
KERN_ERR
"init_ethernet failed for card #%d
\n
"
,
card_idx
);
printk
(
KERN_ERR
"alloc_etherdev failed
\n
"
);
goto
err_out
;
}
SET_MODULE_OWNER
(
dev
);
SET_NETDEV_DEV
(
dev
,
&
pdev
->
dev
);
rc
=
pci_request_regions
(
pdev
,
shortname
);
rc
=
pci_request_regions
(
pdev
,
DRV_NAME
);
if
(
rc
)
goto
err_out_free_netdev
;
#ifdef USE_MMIO
ioaddr0
=
ioaddr
;
enable_mmio
(
ioaddr0
,
quirks
);
enable_mmio
(
pioaddr
,
quirks
);
ioaddr
=
(
long
)
ioremap
(
memaddr
,
io_size
);
if
(
!
ioaddr
)
{
...
...
@@ -737,7 +809,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
i
=
0
;
while
(
mmio_verify_registers
[
i
])
{
int
reg
=
mmio_verify_registers
[
i
++
];
unsigned
char
a
=
inb
(
ioaddr0
+
reg
);
unsigned
char
a
=
inb
(
pioaddr
+
reg
);
unsigned
char
b
=
readb
(
ioaddr
+
reg
);
if
(
a
!=
b
)
{
rc
=
-
EIO
;
...
...
@@ -746,65 +818,41 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
goto
err_out_unmap
;
}
}
#else
ioaddr
=
pioaddr
;
#endif
/* USE_MMIO */
dev
->
base_addr
=
ioaddr
;
rp
=
netdev_priv
(
dev
);
rp
->
quirks
=
quirks
;
/* Get chip registers into a sane state */
rhine_power_init
(
dev
);
/* Reset the chip to erase previous misconfiguration. */
writew
(
CmdReset
,
ioaddr
+
ChipCmd
);
wait_for_reset
(
dev
,
quirks
,
shortname
);
/* Reload the station address from the EEPROM. */
#ifdef USE_MMIO
reload_eeprom
(
ioaddr0
);
/* Reloading from eeprom overwrites cfgA-D, so we must re-enable MMIO.
If reload_eeprom() was done first this could be avoided, but it is
not known if that still works with the "win98-reboot" problem. */
enable_mmio
(
ioaddr0
,
quirks
);
#else
reload_eeprom
(
ioaddr
);
#endif
rhine_hw_init
(
dev
,
pioaddr
);
for
(
i
=
0
;
i
<
6
;
i
++
)
dev
->
dev_addr
[
i
]
=
readb
(
ioaddr
+
StationAddr
+
i
);
if
(
!
is_valid_ether_addr
(
dev
->
dev_addr
))
{
rc
=
-
EIO
;
printk
(
KERN_ERR
"Invalid MAC address
for card #%d
\n
"
,
card_idx
);
printk
(
KERN_ERR
"Invalid MAC address
\n
"
);
goto
err_out_unmap
;
}
if
(
quirks
&
rqWOL
)
{
/*
* for 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA
* turned on. it makes MAC receive magic packet
* automatically. So, we turn it off. (D-Link)
*/
writeb
(
readb
(
ioaddr
+
ConfigA
)
&
0xFE
,
ioaddr
+
ConfigA
);
}
/* Select backoff algorithm */
if
(
backoff
)
writeb
(
readb
(
ioaddr
+
ConfigD
)
&
(
0xF0
|
backoff
),
ioaddr
+
ConfigD
);
/* For Rhine-I/II, phy_id is loaded from EEPROM */
if
(
!
phy_id
)
phy_id
=
readb
(
ioaddr
+
0x6C
);
dev
->
irq
=
pdev
->
irq
;
rp
=
netdev_priv
(
dev
);
spin_lock_init
(
&
rp
->
lock
);
rp
->
pdev
=
pdev
;
rp
->
quirks
=
quirks
;
rp
->
mii_if
.
dev
=
dev
;
rp
->
mii_if
.
mdio_read
=
mdio_read
;
rp
->
mii_if
.
mdio_write
=
mdio_write
;
rp
->
mii_if
.
phy_id_mask
=
0x1f
;
rp
->
mii_if
.
reg_num_mask
=
0x1f
;
if
(
dev
->
mem_start
)
option
=
dev
->
mem_start
;
/* The chip-specific entries in the device structure. */
dev
->
open
=
rhine_open
;
dev
->
hard_start_xmit
=
rhine_start_tx
;
...
...
@@ -826,22 +874,8 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
if
(
rc
)
goto
err_out_unmap
;
/* The lower four bits are the media type. */
if
(
option
>
0
)
{
if
(
option
&
0x220
)
rp
->
mii_if
.
full_duplex
=
1
;
}
if
(
card_idx
<
MAX_UNITS
&&
full_duplex
[
card_idx
]
>
0
)
rp
->
mii_if
.
full_duplex
=
1
;
if
(
rp
->
mii_if
.
full_duplex
)
{
printk
(
KERN_INFO
"%s: Set to forced full duplex, "
"autonegotiation disabled.
\n
"
,
dev
->
name
);
rp
->
mii_if
.
force_media
=
1
;
}
printk
(
KERN_INFO
"%s: VIA %s at 0x%lx, "
,
dev
->
name
,
name
,
printk
(
KERN_INFO
"%s: VIA %s (%s) at 0x%lx, "
,
dev
->
name
,
name
,
mname
,
#ifdef USE_MMIO
memaddr
#else
...
...
@@ -855,17 +889,15 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
pci_set_drvdata
(
pdev
,
dev
);
rp
->
phys
[
0
]
=
1
;
/* Standard for this chip. */
for
(
phy
=
1
;
phy
<
32
&&
phy_idx
<
MAX_MII_CNT
;
phy
++
)
{
int
mii_status
=
mdio_read
(
dev
,
phy
,
1
);
{
int
mii_status
=
mdio_read
(
dev
,
phy_id
,
1
);
if
(
mii_status
!=
0xffff
&&
mii_status
!=
0x0000
)
{
rp
->
phys
[
phy_idx
++
]
=
phy
;
rp
->
mii_if
.
advertising
=
mdio_read
(
dev
,
phy
,
4
);
rp
->
mii_if
.
advertising
=
mdio_read
(
dev
,
phy_id
,
4
);
printk
(
KERN_INFO
"%s: MII PHY found at address "
"%d, status 0x%4.4x advertising %4.4x "
"Link %4.4x.
\n
"
,
dev
->
name
,
phy
,
"Link %4.4x.
\n
"
,
dev
->
name
,
phy
_id
,
mii_status
,
rp
->
mii_if
.
advertising
,
mdio_read
(
dev
,
phy
,
5
));
mdio_read
(
dev
,
phy
_id
,
5
));
/* set IFF_RUNNING */
if
(
mii_status
&
BMSR_LSTATUS
)
...
...
@@ -873,27 +905,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
else
netif_carrier_off
(
dev
);
break
;
}
}
rp
->
mii_cnt
=
phy_idx
;
rp
->
mii_if
.
phy_id
=
rp
->
phys
[
0
];
/* Allow forcing the media type. */
if
(
option
>
0
)
{
if
(
option
&
0x220
)
rp
->
mii_if
.
full_duplex
=
1
;
if
(
option
&
0x330
)
{
printk
(
KERN_INFO
" Forcing %dMbs %s-duplex "
"operation.
\n
"
,
(
option
&
0x300
?
100
:
10
),
(
option
&
0x220
?
"full"
:
"half"
));
if
(
rp
->
mii_cnt
)
mdio_write
(
dev
,
rp
->
phys
[
0
],
MII_BMCR
,
((
option
&
0x300
)
?
0x2000
:
0
)
|
/* 100mbps? */
((
option
&
0x220
)
?
0x0100
:
0
));
/* Full duplex? */
}
}
rp
->
mii_if
.
phy_id
=
phy_id
;
return
0
;
...
...
@@ -1065,6 +1079,21 @@ static void free_tbufs(struct net_device* dev)
}
}
static
void
rhine_check_media
(
struct
net_device
*
dev
,
unsigned
int
init_media
)
{
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
long
ioaddr
=
dev
->
base_addr
;
mii_check_media
(
&
rp
->
mii_if
,
debug
,
init_media
);
if
(
rp
->
mii_if
.
full_duplex
)
writeb
(
readb
(
ioaddr
+
ChipCmd1
)
|
Cmd1FDuplex
,
ioaddr
+
ChipCmd1
);
else
writeb
(
readb
(
ioaddr
+
ChipCmd1
)
&
~
Cmd1FDuplex
,
ioaddr
+
ChipCmd1
);
}
static
void
init_registers
(
struct
net_device
*
dev
)
{
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
...
...
@@ -1080,7 +1109,6 @@ static void init_registers(struct net_device *dev)
writeb
(
0x20
,
ioaddr
+
TxConfig
);
rp
->
tx_thresh
=
0x20
;
rp
->
rx_thresh
=
0x60
;
/* Written in rhine_set_rx_mode(). */
rp
->
mii_if
.
full_duplex
=
0
;
writel
(
rp
->
rx_ring_dma
,
ioaddr
+
RxRingPtr
);
writel
(
rp
->
tx_ring_dma
,
ioaddr
+
TxRingPtr
);
...
...
@@ -1094,17 +1122,44 @@ static void init_registers(struct net_device *dev)
IntrPCIErr
|
IntrStatsMax
|
IntrLinkChange
,
ioaddr
+
IntrEnable
);
rp
->
chip_cmd
=
CmdStart
|
CmdTxOn
|
CmdRxOn
|
CmdNoTxPoll
;
if
(
rp
->
mii_if
.
force_media
)
rp
->
chip_cmd
|=
CmdFDuplex
;
writew
(
rp
->
chip_cmd
,
ioaddr
+
ChipCmd
);
writew
(
CmdStart
|
CmdTxOn
|
CmdRxOn
|
(
Cmd1NoTxPoll
<<
8
),
ioaddr
+
ChipCmd
);
rhine_check_media
(
dev
,
1
);
}
/* Enable MII link status auto-polling (required for IntrLinkChange) */
static
void
rhine_enable_linkmon
(
long
ioaddr
)
{
writeb
(
0
,
ioaddr
+
MIICmd
);
writeb
(
MII_BMSR
,
ioaddr
+
MIIRegAddr
);
writeb
(
0x80
,
ioaddr
+
MIICmd
);
RHINE_WAIT_FOR
((
readb
(
ioaddr
+
MIIRegAddr
)
&
0x20
));
rhine_check_duplex
(
dev
);
writeb
(
MII_BMSR
|
0x40
,
ioaddr
+
MIIRegAddr
);
}
/* Disable MII link status auto-polling (required for MDIO access) */
static
void
rhine_disable_linkmon
(
long
ioaddr
,
u32
quirks
)
{
writeb
(
0
,
ioaddr
+
MIICmd
);
if
(
quirks
&
rqRhineI
)
{
writeb
(
0x01
,
ioaddr
+
MIIRegAddr
);
// MII_BMSR
/* Can be called from ISR. Evil. */
mdelay
(
1
);
/* The LED outputs of various MII xcvrs should be configured. */
/* For NS or Mison phys, turn on bit 1 in register 0x17 */
mdio_write
(
dev
,
rp
->
phys
[
0
],
0x17
,
mdio_read
(
dev
,
rp
->
phys
[
0
],
0x17
)
|
0x0001
);
/* 0x80 must be set immediately before turning it off */
writeb
(
0x80
,
ioaddr
+
MIICmd
);
RHINE_WAIT_FOR
(
readb
(
ioaddr
+
MIIRegAddr
)
&
0x20
);
/* Heh. Now clear 0x80 again. */
writeb
(
0
,
ioaddr
+
MIICmd
);
}
else
RHINE_WAIT_FOR
(
readb
(
ioaddr
+
MIIRegAddr
)
&
0x80
);
}
/* Read and write over the MII Management Data I/O (MDIO) interface. */
...
...
@@ -1112,156 +1167,72 @@ static void init_registers(struct net_device *dev)
static
int
mdio_read
(
struct
net_device
*
dev
,
int
phy_id
,
int
regnum
)
{
long
ioaddr
=
dev
->
base_addr
;
int
boguscnt
=
1024
;
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
int
result
;
rhine_disable_linkmon
(
ioaddr
,
rp
->
quirks
);
/* Wait for a previous command to complete. */
while
((
readb
(
ioaddr
+
MIICmd
)
&
0x60
)
&&
--
boguscnt
>
0
)
;
writeb
(
0x00
,
ioaddr
+
MIICmd
);
writeb
(
0
,
ioaddr
+
MIICmd
);
writeb
(
phy_id
,
ioaddr
+
MIIPhyAddr
);
writeb
(
regnum
,
ioaddr
+
MIIRegAddr
);
writeb
(
0x40
,
ioaddr
+
MIICmd
);
/* Trigger read */
boguscnt
=
1024
;
while
((
readb
(
ioaddr
+
MIICmd
)
&
0x40
)
&&
--
boguscnt
>
0
)
;
return
readw
(
ioaddr
+
MIIData
);
RHINE_WAIT_FOR
(
!
(
readb
(
ioaddr
+
MIICmd
)
&
0x40
));
result
=
readw
(
ioaddr
+
MIIData
);
rhine_enable_linkmon
(
ioaddr
);
return
result
;
}
static
void
mdio_write
(
struct
net_device
*
dev
,
int
phy_id
,
int
regnum
,
int
value
)
{
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
long
ioaddr
=
dev
->
base_addr
;
int
boguscnt
=
1024
;
if
(
phy_id
==
rp
->
phys
[
0
])
{
switch
(
regnum
)
{
case
MII_BMCR
:
/* Is user forcing speed/duplex? */
if
(
value
&
0x9000
)
/* Autonegotiation. */
rp
->
mii_if
.
force_media
=
0
;
else
rp
->
mii_if
.
full_duplex
=
(
value
&
0x0100
)
?
1
:
0
;
break
;
case
MII_ADVERTISE
:
rp
->
mii_if
.
advertising
=
value
;
break
;
}
}
rhine_disable_linkmon
(
ioaddr
,
rp
->
quirks
);
/* Wait for a previous command to complete. */
while
((
readb
(
ioaddr
+
MIICmd
)
&
0x60
)
&&
--
boguscnt
>
0
)
;
writeb
(
0x00
,
ioaddr
+
MIICmd
);
writeb
(
0
,
ioaddr
+
MIICmd
);
writeb
(
phy_id
,
ioaddr
+
MIIPhyAddr
);
writeb
(
regnum
,
ioaddr
+
MIIRegAddr
);
writew
(
value
,
ioaddr
+
MIIData
);
writeb
(
0x20
,
ioaddr
+
MIICmd
);
/* Trigger write
.
*/
}
writeb
(
0x20
,
ioaddr
+
MIICmd
);
/* Trigger write */
RHINE_WAIT_FOR
(
!
(
readb
(
ioaddr
+
MIICmd
)
&
0x20
));
rhine_enable_linkmon
(
ioaddr
);
}
static
int
rhine_open
(
struct
net_device
*
dev
)
{
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
long
ioaddr
=
dev
->
base_addr
;
int
i
;
/* Reset the chip. */
writew
(
CmdReset
,
ioaddr
+
ChipCmd
);
int
rc
;
i
=
request_irq
(
rp
->
pdev
->
irq
,
&
rhine_interrupt
,
SA_SHIRQ
,
dev
->
name
,
rc
=
request_irq
(
rp
->
pdev
->
irq
,
&
rhine_interrupt
,
SA_SHIRQ
,
dev
->
name
,
dev
);
if
(
i
)
return
i
;
if
(
rc
)
return
rc
;
if
(
debug
>
1
)
printk
(
KERN_DEBUG
"%s: rhine_open() irq %d.
\n
"
,
dev
->
name
,
rp
->
pdev
->
irq
);
i
=
alloc_ring
(
dev
);
if
(
i
)
return
i
;
rc
=
alloc_ring
(
dev
);
if
(
rc
)
return
rc
;
alloc_rbufs
(
dev
);
alloc_tbufs
(
dev
);
wait_for_reset
(
dev
,
rp
->
quirks
,
dev
->
name
);
rhine_chip_reset
(
dev
);
init_registers
(
dev
);
if
(
debug
>
2
)
printk
(
KERN_DEBUG
"%s: Done rhine_open(), status %4.4x "
"MII status: %4.4x.
\n
"
,
dev
->
name
,
readw
(
ioaddr
+
ChipCmd
),
mdio_read
(
dev
,
rp
->
phys
[
0
]
,
MII_BMSR
));
mdio_read
(
dev
,
rp
->
mii_if
.
phy_id
,
MII_BMSR
));
netif_start_queue
(
dev
);
/* Set the timer to check for link beat. */
init_timer
(
&
rp
->
timer
);
rp
->
timer
.
expires
=
jiffies
+
2
*
HZ
/
100
;
rp
->
timer
.
data
=
(
unsigned
long
)
dev
;
rp
->
timer
.
function
=
&
rhine_timer
;
/* timer handler */
add_timer
(
&
rp
->
timer
);
return
0
;
}
static
void
rhine_check_duplex
(
struct
net_device
*
dev
)
{
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
long
ioaddr
=
dev
->
base_addr
;
int
mii_lpa
=
mdio_read
(
dev
,
rp
->
phys
[
0
],
MII_LPA
);
int
negotiated
=
mii_lpa
&
rp
->
mii_if
.
advertising
;
int
duplex
;
if
(
rp
->
mii_if
.
force_media
||
mii_lpa
==
0xffff
)
return
;
duplex
=
(
negotiated
&
0x0100
)
||
(
negotiated
&
0x01C0
)
==
0x0040
;
if
(
rp
->
mii_if
.
full_duplex
!=
duplex
)
{
rp
->
mii_if
.
full_duplex
=
duplex
;
if
(
debug
)
printk
(
KERN_INFO
"%s: Setting %s-duplex based on "
"MII #%d link partner capability of %4.4x.
\n
"
,
dev
->
name
,
duplex
?
"full"
:
"half"
,
rp
->
phys
[
0
],
mii_lpa
);
if
(
duplex
)
rp
->
chip_cmd
|=
CmdFDuplex
;
else
rp
->
chip_cmd
&=
~
CmdFDuplex
;
writew
(
rp
->
chip_cmd
,
ioaddr
+
ChipCmd
);
}
}
static
void
rhine_timer
(
unsigned
long
data
)
{
struct
net_device
*
dev
=
(
struct
net_device
*
)
data
;
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
long
ioaddr
=
dev
->
base_addr
;
int
next_tick
=
10
*
HZ
;
int
mii_status
;
if
(
debug
>
3
)
{
printk
(
KERN_DEBUG
"%s: VIA Rhine monitor tick, status %4.4x.
\n
"
,
dev
->
name
,
readw
(
ioaddr
+
IntrStatus
));
}
spin_lock_irq
(
&
rp
->
lock
);
rhine_check_duplex
(
dev
);
/* make IFF_RUNNING follow the MII status bit "Link established" */
mii_status
=
mdio_read
(
dev
,
rp
->
phys
[
0
],
MII_BMSR
);
if
((
mii_status
&
BMSR_LSTATUS
)
!=
(
rp
->
mii_status
&
BMSR_LSTATUS
))
{
if
(
mii_status
&
BMSR_LSTATUS
)
netif_carrier_on
(
dev
);
else
netif_carrier_off
(
dev
);
}
rp
->
mii_status
=
mii_status
;
spin_unlock_irq
(
&
rp
->
lock
);
rp
->
timer
.
expires
=
jiffies
+
next_tick
;
add_timer
(
&
rp
->
timer
);
}
static
void
rhine_tx_timeout
(
struct
net_device
*
dev
)
{
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
...
...
@@ -1270,16 +1241,13 @@ static void rhine_tx_timeout(struct net_device *dev)
printk
(
KERN_WARNING
"%s: Transmit timed out, status %4.4x, PHY status "
"%4.4x, resetting...
\n
"
,
dev
->
name
,
readw
(
ioaddr
+
IntrStatus
),
mdio_read
(
dev
,
rp
->
phys
[
0
]
,
MII_BMSR
));
mdio_read
(
dev
,
rp
->
mii_if
.
phy_id
,
MII_BMSR
));
/* protect against concurrent rx interrupts */
disable_irq
(
rp
->
pdev
->
irq
);
spin_lock
(
&
rp
->
lock
);
/* Reset the chip. */
writew
(
CmdReset
,
ioaddr
+
ChipCmd
);
/* clear all descriptors */
free_tbufs
(
dev
);
free_rbufs
(
dev
);
...
...
@@ -1287,7 +1255,7 @@ static void rhine_tx_timeout(struct net_device *dev)
alloc_rbufs
(
dev
);
/* Reinitialize the hardware. */
wait_for_reset
(
dev
,
rp
->
quirks
,
dev
->
name
);
rhine_chip_reset
(
dev
);
init_registers
(
dev
);
spin_unlock
(
&
rp
->
lock
);
...
...
@@ -1301,8 +1269,8 @@ static void rhine_tx_timeout(struct net_device *dev)
static
int
rhine_start_tx
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
long
ioaddr
=
dev
->
base_addr
;
unsigned
entry
;
u32
intr_status
;
/* Caution: the write order is important here, set the field
with the "ownership" bits last. */
...
...
@@ -1353,14 +1321,9 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
/* Non-x86 Todo: explicitly flush cache lines here. */
/*
* Wake the potentially-idle transmit channel unless errors are
* pending (the ISR must sort them out first).
*/
intr_status
=
get_intr_status
(
dev
);
if
((
intr_status
&
IntrTxErrSummary
)
==
0
)
{
writew
(
CmdTxDemand
|
rp
->
chip_cmd
,
dev
->
base_addr
+
ChipCmd
);
}
/* Wake the potentially-idle transmit channel */
writeb
(
readb
(
ioaddr
+
ChipCmd1
)
|
Cmd1TxDemand
,
ioaddr
+
ChipCmd1
);
IOSYNC
;
if
(
rp
->
cur_tx
==
rp
->
dirty_tx
+
TX_QUEUE_LEN
)
...
...
@@ -1408,11 +1371,10 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *
if
(
intr_status
&
(
IntrTxErrSummary
|
IntrTxDone
))
{
if
(
intr_status
&
IntrTxErrSummary
)
{
int
cnt
=
20
;
/* Avoid scavenging before Tx engine turned off */
while
((
readw
(
ioaddr
+
ChipCmd
)
&
CmdTxOn
)
&&
--
cnt
)
udelay
(
5
);
if
(
debug
>
2
&&
!
cnt
)
RHINE_WAIT_FOR
(
!
(
readb
(
ioaddr
+
ChipCmd
)
&
CmdTxOn
));
if
(
debug
>
2
&&
readb
(
ioaddr
+
ChipCmd
)
&
CmdTxOn
)
printk
(
KERN_WARNING
"%s: "
"rhine_interrupt() Tx engine"
"still on.
\n
"
,
dev
->
name
);
...
...
@@ -1572,10 +1534,6 @@ static void rhine_rx(struct net_device *dev)
rp
->
rx_buf_sz
,
PCI_DMA_FROMDEVICE
);
/* *_IP_COPYSUM isn't defined anywhere and
eth_copy_and_sum is memcpy for all archs so
this is kind of pointless right now
... or? */
eth_copy_and_sum
(
skb
,
rp
->
rx_skbuff
[
entry
]
->
tail
,
pkt_len
,
0
);
...
...
@@ -1627,10 +1585,6 @@ static void rhine_rx(struct net_device *dev)
}
rp
->
rx_ring
[
entry
].
rx_status
=
cpu_to_le32
(
DescOwn
);
}
/* Pre-emptively restart Rx engine. */
writew
(
readw
(
dev
->
base_addr
+
ChipCmd
)
|
CmdRxOn
|
CmdRxDemand
,
dev
->
base_addr
+
ChipCmd
);
}
/*
...
...
@@ -1664,7 +1618,10 @@ static void rhine_restart_tx(struct net_device *dev) {
writel
(
rp
->
tx_ring_dma
+
entry
*
sizeof
(
struct
tx_desc
),
ioaddr
+
TxRingPtr
);
writew
(
CmdTxDemand
|
rp
->
chip_cmd
,
ioaddr
+
ChipCmd
);
writeb
(
readb
(
ioaddr
+
ChipCmd
)
|
CmdTxOn
,
ioaddr
+
ChipCmd
);
writeb
(
readb
(
ioaddr
+
ChipCmd1
)
|
Cmd1TxDemand
,
ioaddr
+
ChipCmd1
);
IOSYNC
;
}
else
{
...
...
@@ -1684,20 +1641,8 @@ static void rhine_error(struct net_device *dev, int intr_status)
spin_lock
(
&
rp
->
lock
);
if
(
intr_status
&
(
IntrLinkChange
))
{
if
(
readb
(
ioaddr
+
MIIStatus
)
&
0x02
)
{
/* Link failed, restart autonegotiation. */
if
(
rp
->
quirks
&
rqRhineI
)
mdio_write
(
dev
,
rp
->
phys
[
0
],
MII_BMCR
,
0x3300
);
}
else
rhine_check_duplex
(
dev
);
if
(
debug
)
printk
(
KERN_ERR
"%s: MII status changed: "
"Autonegotiation advertising %4.4x partner "
"%4.4x.
\n
"
,
dev
->
name
,
mdio_read
(
dev
,
rp
->
phys
[
0
],
MII_ADVERTISE
),
mdio_read
(
dev
,
rp
->
phys
[
0
],
MII_LPA
));
}
if
(
intr_status
&
IntrLinkChange
)
rhine_check_media
(
dev
,
0
);
if
(
intr_status
&
IntrStatsMax
)
{
rp
->
stats
.
rx_crc_errors
+=
readw
(
ioaddr
+
RxCRCErrs
);
rp
->
stats
.
rx_missed_errors
+=
readw
(
ioaddr
+
RxMissed
);
...
...
@@ -1790,7 +1735,7 @@ static void rhine_set_rx_mode(struct net_device *dev)
i
++
,
mclist
=
mclist
->
next
)
{
int
bit_nr
=
ether_crc
(
ETH_ALEN
,
mclist
->
dmi_addr
)
>>
26
;
mc_filter
[
bit_nr
>>
5
]
|=
cpu_to_le32
(
1
<<
(
bit_nr
&
31
)
);
mc_filter
[
bit_nr
>>
5
]
|=
1
<<
(
bit_nr
&
31
);
}
writel
(
mc_filter
[
0
],
ioaddr
+
MulticastFilter0
);
writel
(
mc_filter
[
1
],
ioaddr
+
MulticastFilter1
);
...
...
@@ -1856,6 +1801,39 @@ static void netdev_set_msglevel(struct net_device *dev, u32 value)
debug
=
value
;
}
static
void
rhine_get_wol
(
struct
net_device
*
dev
,
struct
ethtool_wolinfo
*
wol
)
{
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
if
(
!
(
rp
->
quirks
&
rqWOL
))
return
;
spin_lock_irq
(
&
rp
->
lock
);
wol
->
supported
=
WAKE_PHY
|
WAKE_MAGIC
|
WAKE_UCAST
|
WAKE_MCAST
|
WAKE_BCAST
;
/* Untested */
wol
->
wolopts
=
rp
->
wolopts
;
spin_unlock_irq
(
&
rp
->
lock
);
}
static
int
rhine_set_wol
(
struct
net_device
*
dev
,
struct
ethtool_wolinfo
*
wol
)
{
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
u32
support
=
WAKE_PHY
|
WAKE_MAGIC
|
WAKE_UCAST
|
WAKE_MCAST
|
WAKE_BCAST
;
/* Untested */
if
(
!
(
rp
->
quirks
&
rqWOL
))
return
-
EINVAL
;
if
(
wol
->
wolopts
&
~
support
)
return
-
EINVAL
;
spin_lock_irq
(
&
rp
->
lock
);
rp
->
wolopts
=
wol
->
wolopts
;
spin_unlock_irq
(
&
rp
->
lock
);
return
0
;
}
static
struct
ethtool_ops
netdev_ethtool_ops
=
{
.
get_drvinfo
=
netdev_get_drvinfo
,
.
get_settings
=
netdev_get_settings
,
...
...
@@ -1864,6 +1842,8 @@ static struct ethtool_ops netdev_ethtool_ops = {
.
get_link
=
netdev_get_link
,
.
get_msglevel
=
netdev_get_msglevel
,
.
set_msglevel
=
netdev_set_msglevel
,
.
get_wol
=
rhine_get_wol
,
.
set_wol
=
rhine_set_wol
,
.
get_sg
=
ethtool_op_get_sg
,
.
get_tx_csum
=
ethtool_op_get_tx_csum
,
};
...
...
@@ -1888,8 +1868,6 @@ static int rhine_close(struct net_device *dev)
long
ioaddr
=
dev
->
base_addr
;
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
del_timer_sync
(
&
rp
->
timer
);
spin_lock_irq
(
&
rp
->
lock
);
netif_stop_queue
(
dev
);
...
...
@@ -1936,12 +1914,51 @@ static void __devexit rhine_remove_one(struct pci_dev *pdev)
pci_set_drvdata
(
pdev
,
NULL
);
}
static
void
rhine_shutdown
(
struct
device
*
gendev
)
{
struct
pci_dev
*
pdev
=
to_pci_dev
(
gendev
);
struct
net_device
*
dev
=
pci_get_drvdata
(
pdev
);
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
long
ioaddr
=
dev
->
base_addr
;
rhine_power_init
(
dev
);
/* Make sure we use pattern 0, 1 and not 4, 5 */
if
(
rp
->
quirks
&
rq6patterns
)
writeb
(
0x04
,
ioaddr
+
0xA7
);
if
(
rp
->
wolopts
&
WAKE_MAGIC
)
writeb
(
WOLmagic
,
ioaddr
+
WOLcrSet
);
if
(
rp
->
wolopts
&
(
WAKE_BCAST
|
WAKE_MCAST
))
writeb
(
WOLbmcast
,
ioaddr
+
WOLcgSet
);
if
(
rp
->
wolopts
&
WAKE_PHY
)
writeb
(
WOLlnkon
|
WOLlnkoff
,
ioaddr
+
WOLcrSet
);
if
(
rp
->
wolopts
&
WAKE_UCAST
)
writeb
(
WOLucast
,
ioaddr
+
WOLcrSet
);
/* Enable legacy WOL (for old motherboards) */
writeb
(
0x01
,
ioaddr
+
PwcfgSet
);
writeb
(
readb
(
ioaddr
+
StickyHW
)
|
0x04
,
ioaddr
+
StickyHW
);
/* Hit power state D3 (sleep) */
writeb
(
readb
(
ioaddr
+
StickyHW
)
|
0x03
,
ioaddr
+
StickyHW
);
/* TODO: Check use of pci_enable_wake() */
}
static
struct
pci_driver
rhine_driver
=
{
.
name
=
"via-rhine"
,
.
name
=
DRV_NAME
,
.
id_table
=
rhine_pci_tbl
,
.
probe
=
rhine_init_one
,
.
remove
=
__devexit_p
(
rhine_remove_one
),
.
driver
=
{
.
shutdown
=
rhine_shutdown
,
}
};
...
...
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