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
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
Show 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_check_duplex
(
dev
);
RHINE_WAIT_FOR
((
readb
(
ioaddr
+
MIIRegAddr
)
&
0x20
)
);
/* 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
);
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
);
/* 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