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
6896827e
Commit
6896827e
authored
Sep 19, 2002
by
Jeff Garzik
Browse files
Options
Browse Files
Download
Plain Diff
Merge mandrakesoft.com:/home/jgarzik/repo/linus-2.5
into mandrakesoft.com:/home/jgarzik/repo/net-drivers-2.5
parents
461a50a3
7d42b087
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
270 additions
and
256 deletions
+270
-256
drivers/net/Config.help
drivers/net/Config.help
+7
-0
drivers/net/Config.in
drivers/net/Config.in
+1
-0
drivers/net/Makefile
drivers/net/Makefile
+1
-1
drivers/net/eepro100.c
drivers/net/eepro100.c
+46
-16
drivers/net/sundance.c
drivers/net/sundance.c
+215
-239
No files found.
drivers/net/Config.help
View file @
6896827e
...
...
@@ -1525,6 +1525,13 @@ CONFIG_SUNDANCE
More specific information and updates are available from
<http://www.scyld.com/network/sundance.html>.
CONFIG_SUNDANCE_MMIO
Enable memory-mapped I/O for interaction with Sundance NIC registers.
Do NOT enable this by default, PIO (enabled when MMIO is disabled)
is known to solve bugs on certain chips.
If unsure, say N.
CONFIG_ZNET
The Zenith Z-Note notebook computer has a built-in network
(Ethernet) card, and this is the Linux driver for it. Note that the
...
...
drivers/net/Config.in
View file @
6896827e
...
...
@@ -177,6 +177,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
dep_tristate ' SiS 900/7016 PCI Fast Ethernet Adapter support' CONFIG_SIS900 $CONFIG_PCI
dep_tristate ' SMC EtherPower II' CONFIG_EPIC100 $CONFIG_PCI
dep_tristate ' Sundance Alta support' CONFIG_SUNDANCE $CONFIG_PCI
dep_mbool ' Use MMIO instead of PIO' CONFIG_SUNDANCE_MMIO $CONFIG_SUNDANCE
if [ "$CONFIG_PCI" = "y" -o "$CONFIG_EISA" = "y" ]; then
tristate ' TI ThunderLAN support' CONFIG_TLAN
fi
...
...
drivers/net/Makefile
View file @
6896827e
...
...
@@ -70,7 +70,7 @@ obj-$(CONFIG_AIRONET4500_PROC) += aironet4500_proc.o
obj-$(CONFIG_AIRONET4500_CS)
+=
aironet4500_proc.o
obj-$(CONFIG_WINBOND_840)
+=
mii.o
obj-$(CONFIG_SUNDANCE)
+=
sundance.o
obj-$(CONFIG_SUNDANCE)
+=
sundance.o
mii.o
obj-$(CONFIG_HAMACHI)
+=
hamachi.o
obj-$(CONFIG_NET)
+=
Space.o setup.o net_init.o loopback.o
obj-$(CONFIG_SEEQ8005)
+=
seeq8005.o
...
...
drivers/net/eepro100.c
View file @
6896827e
...
...
@@ -850,7 +850,30 @@ static int __devinit speedo_found1(struct pci_dev *pdev,
return
0
;
}
static
void
do_slow_command
(
struct
net_device
*
dev
,
int
cmd
)
{
long
cmd_ioaddr
=
dev
->
base_addr
+
SCBCmd
;
int
wait
=
0
;
do
if
(
inb
(
cmd_ioaddr
)
==
0
)
break
;
while
(
++
wait
<=
200
);
if
(
wait
>
100
)
printk
(
KERN_ERR
"Command %4.4x never accepted (%d polls)!
\n
"
,
inb
(
cmd_ioaddr
),
wait
);
outb
(
cmd
,
cmd_ioaddr
);
for
(
wait
=
0
;
wait
<=
100
;
wait
++
)
if
(
inb
(
cmd_ioaddr
)
==
0
)
return
;
for
(;
wait
<=
20000
;
wait
++
)
if
(
inb
(
cmd_ioaddr
)
==
0
)
return
;
else
udelay
(
1
);
printk
(
KERN_ERR
"Command %4.4x was not accepted after %d polls!"
" Current status %8.8x.
\n
"
,
cmd
,
wait
,
inl
(
dev
->
base_addr
+
SCBStatus
));
}
/* Serial EEPROM section.
A "bit" grungy, but we work our way through bit-by-bit :->. */
/* EEPROM_Ctrl bits. */
...
...
@@ -1015,7 +1038,7 @@ speedo_open(struct net_device *dev)
/* Start the chip hardware after a full reset. */
static
void
speedo_resume
(
struct
net_device
*
dev
)
{
struct
speedo_private
*
sp
=
(
struct
speedo_private
*
)
dev
->
priv
;
struct
speedo_private
*
sp
=
dev
->
priv
;
long
ioaddr
=
dev
->
base_addr
;
/* Start with a Tx threshold of 256 (0x..20.... 8 byte units). */
...
...
@@ -1023,34 +1046,40 @@ static void speedo_resume(struct net_device *dev)
/* Set the segment registers to '0'. */
wait_for_cmd_done
(
ioaddr
+
SCBCmd
);
outl
(
0
,
ioaddr
+
SCBPointer
);
/* impose a delay to avoid a bug */
inl
(
ioaddr
+
SCBPointer
);
udelay
(
10
);
outb
(
RxAddrLoad
,
ioaddr
+
SCBCmd
);
wait_for_cmd_done
(
ioaddr
+
SCBCmd
);
outb
(
CUCmdBase
,
ioaddr
+
SCBCmd
);
if
(
inb
(
ioaddr
+
SCBCmd
))
{
outl
(
PortPartialReset
,
ioaddr
+
SCBPort
);
udelay
(
10
);
}
outl
(
0
,
ioaddr
+
SCBPointer
);
inl
(
ioaddr
+
SCBPointer
);
/* Flush to PCI. */
udelay
(
10
);
/* Bogus, but it avoids the bug. */
/* Note: these next two operations can take a while. */
do_slow_command
(
dev
,
RxAddrLoad
);
do_slow_command
(
dev
,
CUCmdBase
);
/* Load the statistics block and rx ring addresses. */
wait_for_cmd_done
(
ioaddr
+
SCBCmd
);
outl
(
sp
->
lstats_dma
,
ioaddr
+
SCBPointer
);
inl
(
ioaddr
+
SCBPointer
);
/* Flush to PCI */
outb
(
CUStatsAddr
,
ioaddr
+
SCBCmd
);
sp
->
lstats
->
done_marker
=
0
;
wait_for_cmd_done
(
ioaddr
+
SCBCmd
);
if
(
sp
->
rx_ringp
[
sp
->
cur_rx
%
RX_RING_SIZE
]
==
NULL
)
{
if
(
speedo_debug
>
2
)
printk
(
KERN_DEBUG
"%s: NULL cur_rx in speedo_resume().
\n
"
,
dev
->
name
);
}
else
{
wait_for_cmd_done
(
ioaddr
+
SCBCmd
);
outl
(
sp
->
rx_ring_dma
[
sp
->
cur_rx
%
RX_RING_SIZE
],
ioaddr
+
SCBPointer
);
outb
(
RxStart
,
ioaddr
+
SCBCmd
);
inl
(
ioaddr
+
SCBPointer
);
/* Flush to PCI */
}
wait_for_cmd_done
(
ioaddr
+
SCBCmd
);
outb
(
CUDumpStats
,
ioaddr
+
SCBCmd
);
udelay
(
30
);
/* Note: RxStart should complete instantly. */
do_slow_command
(
dev
,
RxStart
);
do_slow_command
(
dev
,
CUDumpStats
);
/* Fill the first command with our physical address. */
{
...
...
@@ -1063,11 +1092,12 @@ static void speedo_resume(struct net_device *dev)
ias_cmd
->
link
=
cpu_to_le32
(
TX_RING_ELEM_DMA
(
sp
,
sp
->
cur_tx
%
TX_RING_SIZE
));
memcpy
(
ias_cmd
->
params
,
dev
->
dev_addr
,
6
);
if
(
sp
->
last_cmd
)
clear_suspend
(
sp
->
last_cmd
);
sp
->
last_cmd
=
ias_cmd
;
}
/* Start the chip's Tx process and unmask interrupts. */
wait_for_cmd_done
(
ioaddr
+
SCBCmd
);
outl
(
TX_RING_ELEM_DMA
(
sp
,
sp
->
dirty_tx
%
TX_RING_SIZE
),
ioaddr
+
SCBPointer
);
/* We are not ACK-ing FCP and ER in the interrupt handler yet so they should
...
...
drivers/net/sundance.c
View file @
6896827e
...
...
@@ -18,26 +18,54 @@
http://www.scyld.com/network/sundance.html
Version 1.01a (jgarzik):
Version
LK
1.01a (jgarzik):
- Replace some MII-related magic numbers with constants
Version 1.02 (D-Link):
Version
LK
1.02 (D-Link):
- Add new board to PCI ID list
- Fix multicast bug
Version 1.03 (D-Link):
Version
LK
1.03 (D-Link):
- New Rx scheme, reduce Rx congestion
- Option to disable flow control
Version 1.04 (D-Link):
Version
LK
1.04 (D-Link):
- Tx timeout recovery
- More support for ethtool.
Version LK1.04a:
- Remove unused/constant members from struct pci_id_info
(which then allows removal of 'drv_flags' from private struct)
(jgarzik)
- If no phy is found, fail to load that board (jgarzik)
- Always start phy id scan at id 1 to avoid problems (Donald Becker)
- Autodetect where mii_preable_required is needed,
default to not needed. (Donald Becker)
Version LK1.04b:
- Remove mii_preamble_required module parameter (Donald Becker)
- Add per-interface mii_preamble_required (setting is autodetected)
(Donald Becker)
- Remove unnecessary cast from void pointer (jgarzik)
- Re-align comments in private struct (jgarzik)
Version LK1.04c (jgarzik):
- Support bitmapped message levels (NETIF_MSG_xxx), and the
two ethtool ioctls that get/set them
- Don't hand-code MII ethtool support, use standard API/lib
Version LK1.04d:
- Merge from Donald Becker's sundance.c: (Jason Lunz)
* proper support for variably-sized MTUs
* default to PIO, to fix chip bugs
- Add missing unregister_netdev (Jason Lunz)
- Add CONFIG_SUNDANCE_MMIO config option (jgarzik)
*/
#define DRV_NAME "sundance"
#define DRV_VERSION "1.0
4
"
#define DRV_RELDATE "19-
Aug
-2002"
#define DRV_VERSION "1.0
1+LK1.04d
"
#define DRV_RELDATE "19-
Sep
-2002"
/* The user-configurable values.
...
...
@@ -45,7 +73,6 @@
static
int
debug
=
1
;
/* 1 normal messages, 0 quiet .. 7 verbose. */
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static
int
max_interrupt_work
=
0
;
static
int
mtu
;
/* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
Typical is a 64 element hash table based on the Ethernet CRC. */
static
int
multicast_filter_limit
=
32
;
...
...
@@ -70,8 +97,10 @@ static int flowctrl=1;
3 100Mbps half duplex.
4 100Mbps full duplex.
*/
#define MAX_UNITS 8
#define MAX_UNITS 8
static
char
*
media
[
MAX_UNITS
];
/* Operational parameters that are set at compile time. */
/* Keep the ring sizes a power of two for compile efficiency.
...
...
@@ -140,16 +169,15 @@ MODULE_DESCRIPTION("Sundance Alta Ethernet driver");
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
max_interrupt_work
,
"i"
);
MODULE_PARM
(
mtu
,
"i"
);
MODULE_PARM
(
debug
,
"i"
);
MODULE_PARM
(
rx_copybreak
,
"i"
);
MODULE_PARM
(
media
,
"1-"
__MODULE_STRING
(
MAX_UNITS
)
"s"
);
MODULE_PARM
(
flowctrl
,
"i"
);
MODULE_PARM_DESC
(
max_interrupt_work
,
"Sundance Alta maximum events handled per interrupt"
);
MODULE_PARM_DESC
(
mtu
,
"Sundance Alta MTU (all boards)"
);
MODULE_PARM_DESC
(
debug
,
"Sundance Alta debug level (0-5)"
);
MODULE_PARM_DESC
(
rx_copybreak
,
"Sundance Alta copy breakpoint for copy-only-tiny-frames"
);
MODULE_PARM_DESC
(
flowctrl
,
"Sundance Alta flow control [0|1]"
);
/*
Theory of Operation
...
...
@@ -224,19 +252,9 @@ IVc. Errata
*/
enum
pci_id_flags_bits
{
/* Set PCI command register bits before calling probe1(). */
PCI_USES_IO
=
1
,
PCI_USES_MEM
=
2
,
PCI_USES_MASTER
=
4
,
/* Read and map the single following PCI BAR. */
PCI_ADDR0
=
0
<<
4
,
PCI_ADDR1
=
1
<<
4
,
PCI_ADDR2
=
2
<<
4
,
PCI_ADDR3
=
3
<<
4
,
PCI_ADDR_64BITS
=
0x100
,
PCI_NO_ACPI_WAKE
=
0x200
,
PCI_NO_MIN_LATENCY
=
0x400
,
};
enum
chip_capability_flags
{
CanHaveMII
=
1
,
};
#ifdef USE_IO_OPS
#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0)
#else
#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_MEM | PCI_ADDR1)
/* Work-around for Kendin chip bugs. */
#ifndef CONFIG_SUNDANCE_MMIO
#define USE_IO_OPS 1
#endif
static
struct
pci_device_id
sundance_pci_tbl
[]
__devinitdata
=
{
...
...
@@ -250,31 +268,20 @@ static struct pci_device_id sundance_pci_tbl[] __devinitdata = {
};
MODULE_DEVICE_TABLE
(
pci
,
sundance_pci_tbl
);
enum
{
netdev_io_size
=
128
};
struct
pci_id_info
{
const
char
*
name
;
struct
match_info
{
int
pci
,
pci_mask
,
subsystem
,
subsystem_mask
;
int
revision
,
revision_mask
;
/* Only 8 bits. */
}
id
;
enum
pci_id_flags_bits
pci_flags
;
int
io_size
;
/* Needed for I/O region check or ioremap(). */
int
drv_flags
;
/* Driver use, intended as capability flags. */
};
static
struct
pci_id_info
pci_id_tbl
[]
=
{
{
"D-Link DFE-550TX FAST Ethernet Adapter"
,
{
0x10021186
,
0xffffffff
,},
PCI_IOTYPE
,
128
,
CanHaveMII
},
{
"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"
,
{
0x10031186
,
0xffffffff
,},
PCI_IOTYPE
,
128
,
CanHaveMII
},
{
"D-Link DFE-580TX 4 port Server Adapter"
,
{
0x10121186
,
0xffffffff
,},
PCI_IOTYPE
,
128
,
CanHaveMII
},
{
"D-Link DFE-530TXS FAST Ethernet Adapter"
,
{
0x10021186
,
0xffffffff
,},
PCI_IOTYPE
,
128
,
CanHaveMII
},
{
"D-Link DL10050-based FAST Ethernet Adapter"
,
{
0x10021186
,
0xffffffff
,},
PCI_IOTYPE
,
128
,
CanHaveMII
},
{
"Sundance Technology Alta"
,
{
0x020113F0
,
0xffffffff
,},
PCI_IOTYPE
,
128
,
CanHaveMII
},
{
"D-Link DFE-550TX FAST Ethernet Adapter"
},
{
"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"
},
{
"D-Link DFE-580TX 4 port Server Adapter"
},
{
"D-Link DFE-530TXS FAST Ethernet Adapter"
},
{
"D-Link DL10050-based FAST Ethernet Adapter"
},
{
"Sundance Technology Alta"
},
{
0
,},
/* 0 terminated list. */
};
...
...
@@ -331,7 +338,7 @@ enum alta_offsets {
MACCtrl0
=
0x50
,
MACCtrl1
=
0x52
,
StationAddr
=
0x54
,
Max
Tx
Size
=
0x5A
,
Max
Frame
Size
=
0x5A
,
RxMode
=
0x5c
,
MIICtrl
=
0x5e
,
MulticastFilter0
=
0x60
,
...
...
@@ -360,7 +367,7 @@ enum alta_offsets {
enum
ASICCtrl_HiWord_bit
{
GlobalReset
=
0x0001
,
RxReset
=
0x0002
,
TxReset
=
0x0004
,
TxReset
=
0x0004
,
DMAReset
=
0x0008
,
FIFOReset
=
0x0010
,
NetworkReset
=
0x0020
,
...
...
@@ -426,17 +433,17 @@ struct netdev_private {
dma_addr_t
tx_ring_dma
;
dma_addr_t
rx_ring_dma
;
struct
net_device_stats
stats
;
struct
timer_list
timer
;
/* Media monitoring timer. */
struct
timer_list
timer
;
/* Media monitoring timer. */
/* Frequently used values: keep some adjacent for cache effect. */
spinlock_t
lock
;
spinlock_t
rx_lock
;
/* Group with Tx control cache line. */
int
chip_id
,
drv_flags
;
spinlock_t
rx_lock
;
/* Group with Tx control cache line. */
int
msg_enable
;
int
chip_id
;
unsigned
int
cur_rx
,
dirty_rx
;
/* Producer/consumer ring indices */
unsigned
int
rx_buf_sz
;
/* Based on MTU+slack. */
unsigned
int
rx_buf_sz
;
/* Based on MTU+slack. */
struct
netdev_desc
*
last_tx
;
/* Last Tx descriptor used. */
unsigned
int
cur_tx
,
dirty_tx
;
/* These values are keep track of the transceiver/media in use. */
unsigned
int
full_duplex
:
1
;
/* Full-duplex operation requested. */
unsigned
int
flowctrl
:
1
;
unsigned
int
default_port
:
4
;
/* Last dev->if_port value. */
unsigned
int
an_enable
:
1
;
...
...
@@ -444,11 +451,11 @@ struct netdev_private {
struct
tasklet_struct
rx_tasklet
;
int
budget
;
/* Multicast and receive mode. */
spinlock_t
mcastlock
;
/* SMP lock multicast updates. */
spinlock_t
mcastlock
;
/* SMP lock multicast updates. */
u16
mcast_filter
[
4
];
/* MII transceiver section. */
int
mii_cnt
;
/* MII device addresses. */
u16
advertising
;
/* NWay media advertisement */
struct
mii_if_info
mii_if
;
int
mii_preamble_required
;
unsigned
char
phys
[
MII_CNT
];
/* MII device addresses, only first one used. */
struct
pci_dev
*
pci_dev
;
};
...
...
@@ -459,6 +466,7 @@ struct netdev_private {
IntrDrvRqst | IntrTxDone | StatsMax | \
LinkChange)
static
int
change_mtu
(
struct
net_device
*
dev
,
int
new_mtu
);
static
int
eeprom_read
(
long
ioaddr
,
int
location
);
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
);
...
...
@@ -479,7 +487,7 @@ static struct net_device_stats *get_stats(struct net_device *dev);
static
int
netdev_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
);
static
int
netdev_close
(
struct
net_device
*
dev
);
static
int
__devinit
sundance_probe1
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
...
...
@@ -521,7 +529,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
ioaddr
=
pci_resource_start
(
pdev
,
0
);
#else
ioaddr
=
pci_resource_start
(
pdev
,
1
);
ioaddr
=
(
long
)
ioremap
(
ioaddr
,
pci_id_tbl
[
chip_idx
].
io_size
);
ioaddr
=
(
long
)
ioremap
(
ioaddr
,
netdev_
io_size
);
if
(
!
ioaddr
)
goto
err_out_res
;
#endif
...
...
@@ -534,9 +542,9 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
dev
->
irq
=
irq
;
np
=
dev
->
priv
;
np
->
chip_id
=
chip_idx
;
np
->
drv_flags
=
pci_id_tbl
[
chip_idx
].
drv_flags
;
np
->
pci_dev
=
pdev
;
np
->
chip_id
=
chip_idx
;
np
->
msg_enable
=
(
1
<<
debug
)
-
1
;
spin_lock_init
(
&
np
->
lock
);
tasklet_init
(
&
np
->
rx_tasklet
,
rx_poll
,
(
unsigned
long
)
dev
);
...
...
@@ -552,6 +560,10 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
np
->
rx_ring
=
(
struct
netdev_desc
*
)
ring_space
;
np
->
rx_ring_dma
=
ring_dma
;
np
->
mii_if
.
dev
=
dev
;
np
->
mii_if
.
mdio_read
=
mdio_read
;
np
->
mii_if
.
mdio_write
=
mdio_write
;
/* The chip-specific entries in the device structure. */
dev
->
open
=
&
netdev_open
;
dev
->
hard_start_xmit
=
&
start_tx
;
...
...
@@ -561,11 +573,9 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
dev
->
do_ioctl
=
&
netdev_ioctl
;
dev
->
tx_timeout
=
&
tx_timeout
;
dev
->
watchdog_timeo
=
TX_TIMEOUT
;
dev
->
change_mtu
=
&
change_mtu
;
pci_set_drvdata
(
pdev
,
dev
);
if
(
mtu
)
dev
->
mtu
=
mtu
;
i
=
register_netdev
(
dev
);
if
(
i
)
goto
err_out_unmap_rx
;
...
...
@@ -579,21 +589,30 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
if
(
1
)
{
int
phy
,
phy_idx
=
0
;
np
->
phys
[
0
]
=
1
;
/* Default setting */
for
(
phy
=
0
;
phy
<
32
&&
phy_idx
<
MII_CNT
;
phy
++
)
{
int
mii_status
=
mdio_read
(
dev
,
phy
,
1
);
np
->
mii_preamble_required
++
;
for
(
phy
=
1
;
phy
<
32
&&
phy_idx
<
MII_CNT
;
phy
++
)
{
int
mii_status
=
mdio_read
(
dev
,
phy
,
MII_BMSR
);
if
(
mii_status
!=
0xffff
&&
mii_status
!=
0x0000
)
{
np
->
phys
[
phy_idx
++
]
=
phy
;
np
->
advertising
=
mdio_read
(
dev
,
phy
,
4
);
np
->
mii_if
.
advertising
=
mdio_read
(
dev
,
phy
,
MII_ADVERTISE
);
if
((
mii_status
&
0x0040
)
==
0
)
np
->
mii_preamble_required
++
;
printk
(
KERN_INFO
"%s: MII PHY found at address %d, status "
"0x%4.4x advertising %4.4x.
\n
"
,
dev
->
name
,
phy
,
mii_status
,
np
->
advertising
);
dev
->
name
,
phy
,
mii_status
,
np
->
mii_if
.
advertising
);
}
}
np
->
mii_cnt
=
phy_idx
;
if
(
phy_idx
==
0
)
printk
(
KERN_INFO
"%s: No MII transceiver found!, ASIC status %x
\n
"
,
np
->
mii_preamble_required
--
;
if
(
phy_idx
==
0
)
{
printk
(
KERN_INFO
"%s: No MII transceiver found, aborting. ASIC status %x
\n
"
,
dev
->
name
,
readl
(
ioaddr
+
ASICCtrl
));
goto
err_out_unregister
;
}
np
->
mii_if
.
phy_id
=
np
->
phys
[
0
];
}
/* Parse override configuration */
np
->
an_enable
=
1
;
if
(
card_idx
<
MAX_UNITS
)
{
...
...
@@ -602,24 +621,24 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
if
(
strcmp
(
media
[
card_idx
],
"100mbps_fd"
)
==
0
||
strcmp
(
media
[
card_idx
],
"4"
)
==
0
)
{
np
->
speed
=
100
;
np
->
full_duplex
=
1
;
np
->
mii_if
.
full_duplex
=
1
;
}
else
if
(
strcmp
(
media
[
card_idx
],
"100mbps_hd"
)
==
0
||
strcmp
(
media
[
card_idx
],
"3"
)
==
0
)
{
np
->
speed
=
100
;
np
->
full_duplex
=
0
;
np
->
mii_if
.
full_duplex
=
0
;
}
else
if
(
strcmp
(
media
[
card_idx
],
"10mbps_fd"
)
==
0
||
strcmp
(
media
[
card_idx
],
"2"
)
==
0
)
{
np
->
speed
=
10
;
np
->
full_duplex
=
1
;
np
->
mii_if
.
full_duplex
=
1
;
}
else
if
(
strcmp
(
media
[
card_idx
],
"10mbps_hd"
)
==
0
||
strcmp
(
media
[
card_idx
],
"1"
)
==
0
)
{
np
->
speed
=
10
;
np
->
full_duplex
=
0
;
np
->
mii_if
.
full_duplex
=
0
;
}
else
{
np
->
an_enable
=
1
;
}
}
if
(
tx_coalesce
<
1
)
if
(
tx_coalesce
<
1
)
tx_coalesce
=
1
;
else
if
(
tx_coalesce
>
TX_QUEUE_LEN
-
1
)
tx_coalesce
=
TX_QUEUE_LEN
-
1
;
...
...
@@ -632,7 +651,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
/* Default 100Mbps Full */
if
(
np
->
an_enable
)
{
np
->
speed
=
100
;
np
->
full_duplex
=
1
;
np
->
mii_if
.
full_duplex
=
1
;
np
->
an_enable
=
0
;
}
}
...
...
@@ -644,24 +663,26 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
if
(
!
np
->
an_enable
)
{
mii_ctl
=
0
;
mii_ctl
|=
(
np
->
speed
==
100
)
?
BMCR_SPEED100
:
0
;
mii_ctl
|=
(
np
->
full_duplex
)
?
BMCR_FULLDPLX
:
0
;
mii_ctl
|=
(
np
->
mii_if
.
full_duplex
)
?
BMCR_FULLDPLX
:
0
;
mdio_write
(
dev
,
np
->
phys
[
0
],
MII_BMCR
,
mii_ctl
);
printk
(
KERN_INFO
"Override speed=%d, %s duplex
\n
"
,
np
->
speed
,
np
->
full_duplex
?
"Full"
:
"Half"
);
np
->
speed
,
np
->
mii_if
.
full_duplex
?
"Full"
:
"Half"
);
}
/* Perhaps move the reset here? */
/* Reset the chip to erase previous misconfiguration. */
if
(
debug
>
1
)
if
(
netif_msg_hw
(
np
)
)
printk
(
"ASIC Control is %x.
\n
"
,
readl
(
ioaddr
+
ASICCtrl
));
writew
(
0x007f
,
ioaddr
+
ASICCtrl
+
2
);
if
(
debug
>
1
)
if
(
netif_msg_hw
(
np
)
)
printk
(
"ASIC Control is now %x.
\n
"
,
readl
(
ioaddr
+
ASICCtrl
));
card_idx
++
;
return
0
;
err_out_unregister:
unregister_netdev
(
dev
);
err_out_unmap_rx:
pci_free_consistent
(
pdev
,
RX_TOTAL_SIZE
,
np
->
rx_ring
,
np
->
rx_ring_dma
);
err_out_unmap_tx:
...
...
@@ -678,7 +699,16 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
return
-
ENODEV
;
}
static
int
change_mtu
(
struct
net_device
*
dev
,
int
new_mtu
)
{
if
((
new_mtu
<
68
)
||
(
new_mtu
>
8191
))
/* Set by RxDMAFrameLen */
return
-
EINVAL
;
if
(
netif_running
(
dev
))
return
-
EBUSY
;
dev
->
mtu
=
new_mtu
;
return
0
;
}
/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */
static
int
__devinit
eeprom_read
(
long
ioaddr
,
int
location
)
{
...
...
@@ -701,11 +731,6 @@ static int __devinit eeprom_read(long ioaddr, int location)
met by back-to-back 33Mhz PCI cycles. */
#define mdio_delay() readb(mdio_addr)
/* Set iff a MII transceiver on any interface requires mdio preamble.
This only set with older tranceivers, so the extra
code size of a per-interface flag is not worthwhile. */
static
const
char
mii_preamble_required
=
1
;
enum
mii_reg_bits
{
MDIO_ShiftClk
=
0x0001
,
MDIO_Data
=
0x0002
,
MDIO_EnbOutput
=
0x0004
,
};
...
...
@@ -730,11 +755,12 @@ static void mdio_sync(long mdio_addr)
static
int
mdio_read
(
struct
net_device
*
dev
,
int
phy_id
,
int
location
)
{
struct
netdev_private
*
np
=
dev
->
priv
;
long
mdio_addr
=
dev
->
base_addr
+
MIICtrl
;
int
mii_cmd
=
(
0xf6
<<
10
)
|
(
phy_id
<<
5
)
|
location
;
int
i
,
retval
=
0
;
if
(
mii_preamble_required
)
if
(
np
->
mii_preamble_required
)
mdio_sync
(
mdio_addr
);
/* Shift the read command bits out. */
...
...
@@ -759,11 +785,12 @@ 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
)
{
struct
netdev_private
*
np
=
dev
->
priv
;
long
mdio_addr
=
dev
->
base_addr
+
MIICtrl
;
int
mii_cmd
=
(
0x5002
<<
16
)
|
(
phy_id
<<
23
)
|
(
location
<<
18
)
|
value
;
int
i
;
if
(
mii_preamble_required
)
if
(
np
->
mii_preamble_required
)
mdio_sync
(
mdio_addr
);
/* Shift the command bits out. */
...
...
@@ -797,7 +824,7 @@ static int netdev_open(struct net_device *dev)
if
(
i
)
return
i
;
if
(
debug
>
1
)
if
(
netif_msg_ifup
(
np
)
)
printk
(
KERN_DEBUG
"%s: netdev_open() irq %d.
\n
"
,
dev
->
name
,
dev
->
irq
);
...
...
@@ -810,6 +837,10 @@ static int netdev_open(struct net_device *dev)
writeb
(
dev
->
dev_addr
[
i
],
ioaddr
+
StationAddr
+
i
);
/* Initialize other registers. */
writew
(
dev
->
mtu
+
14
,
ioaddr
+
MaxFrameSize
);
if
(
dev
->
mtu
>
2047
)
writel
(
readl
(
ioaddr
+
ASICCtrl
)
|
0x0C
,
ioaddr
+
ASICCtrl
);
/* Configure the PCI bus bursts and FIFO thresholds. */
if
(
dev
->
if_port
==
0
)
...
...
@@ -827,7 +858,7 @@ static int netdev_open(struct net_device *dev)
writew
(
StatsEnable
|
RxEnable
|
TxEnable
,
ioaddr
+
MACCtrl1
);
if
(
debug
>
2
)
if
(
netif_msg_ifup
(
np
)
)
printk
(
KERN_DEBUG
"%s: Done netdev_open(), status: Rx %x Tx %x "
"MAC Control %x, %4.4x %4.4x.
\n
"
,
dev
->
name
,
readl
(
ioaddr
+
RxStatus
),
readb
(
ioaddr
+
TxStatus
),
...
...
@@ -840,7 +871,7 @@ static int netdev_open(struct net_device *dev)
np
->
timer
.
data
=
(
unsigned
long
)
dev
;
np
->
timer
.
function
=
&
netdev_timer
;
/* timer handler */
add_timer
(
&
np
->
timer
);
/* Enable interrupts by setting the interrupt mask. */
writew
(
DEFAULT_INTR
,
ioaddr
+
IntrEnable
);
...
...
@@ -852,21 +883,22 @@ static void check_duplex(struct net_device *dev)
struct
netdev_private
*
np
=
dev
->
priv
;
long
ioaddr
=
dev
->
base_addr
;
int
mii_lpa
=
mdio_read
(
dev
,
np
->
phys
[
0
],
MII_LPA
);
int
negotiated
=
mii_lpa
&
np
->
advertising
;
int
negotiated
=
mii_lpa
&
np
->
mii_if
.
advertising
;
int
duplex
;
/* Force media */
if
(
!
np
->
an_enable
||
mii_lpa
==
0xffff
)
{
if
(
np
->
full_duplex
)
if
(
np
->
mii_if
.
full_duplex
)
writew
(
readw
(
ioaddr
+
MACCtrl0
)
|
EnbFullDuplex
,
ioaddr
+
MACCtrl0
);
return
;
}
/* Autonegotiation */
duplex
=
(
negotiated
&
0x0100
)
||
(
negotiated
&
0x01C0
)
==
0x0040
;
if
(
np
->
full_duplex
!=
duplex
)
{
np
->
full_duplex
=
duplex
;
if
(
debug
)
if
(
np
->
mii_if
.
full_duplex
!=
duplex
)
{
np
->
mii_if
.
full_duplex
=
duplex
;
if
(
netif_msg_link
(
np
)
)
printk
(
KERN_INFO
"%s: Setting %s-duplex based on MII #%d "
"negotiated capability %4.4x.
\n
"
,
dev
->
name
,
duplex
?
"full"
:
"half"
,
np
->
phys
[
0
],
negotiated
);
...
...
@@ -881,7 +913,7 @@ static void netdev_timer(unsigned long data)
long
ioaddr
=
dev
->
base_addr
;
int
next_tick
=
10
*
HZ
;
if
(
debug
>
3
)
{
if
(
netif_msg_timer
(
np
)
)
{
printk
(
KERN_DEBUG
"%s: Media selection timer tick, intr status %4.4x, "
"Tx %x Rx %x.
\n
"
,
dev
->
name
,
readw
(
ioaddr
+
IntrEnable
),
...
...
@@ -941,11 +973,11 @@ static void init_ring(struct net_device *dev)
np
->
cur_rx
=
np
->
cur_tx
=
0
;
np
->
dirty_rx
=
np
->
dirty_tx
=
0
;
np
->
rx_buf_sz
=
(
dev
->
mtu
<=
1500
?
PKT_BUF_SZ
:
dev
->
mtu
+
3
2
);
np
->
rx_buf_sz
=
(
dev
->
mtu
<=
1500
?
PKT_BUF_SZ
:
dev
->
mtu
+
3
6
);
/* Initialize all Rx descriptors. */
for
(
i
=
0
;
i
<
RX_RING_SIZE
;
i
++
)
{
np
->
rx_ring
[
i
].
next_desc
=
cpu_to_le32
(
np
->
rx_ring_dma
+
np
->
rx_ring
[
i
].
next_desc
=
cpu_to_le32
(
np
->
rx_ring_dma
+
((
i
+
1
)
%
RX_RING_SIZE
)
*
sizeof
(
*
np
->
rx_ring
));
np
->
rx_ring
[
i
].
status
=
0
;
np
->
rx_ring
[
i
].
frag
[
0
].
length
=
0
;
...
...
@@ -961,7 +993,7 @@ static void init_ring(struct net_device *dev)
skb
->
dev
=
dev
;
/* Mark as being used by this device. */
skb_reserve
(
skb
,
2
);
/* 16 byte align the IP header. */
np
->
rx_ring
[
i
].
frag
[
0
].
addr
=
cpu_to_le32
(
pci_map_single
(
np
->
pci_dev
,
skb
->
tail
,
np
->
rx_buf_sz
,
pci_map_single
(
np
->
pci_dev
,
skb
->
tail
,
np
->
rx_buf_sz
,
PCI_DMA_FROMDEVICE
));
np
->
rx_ring
[
i
].
frag
[
0
].
length
=
cpu_to_le32
(
np
->
rx_buf_sz
|
LastFrag
);
}
...
...
@@ -977,7 +1009,7 @@ static void init_ring(struct net_device *dev)
static
int
start_tx
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
struct
netdev_private
*
np
=
(
struct
netdev_private
*
)
dev
->
priv
;
struct
netdev_private
*
np
=
dev
->
priv
;
struct
netdev_desc
*
txdesc
;
unsigned
entry
;
long
ioaddr
=
dev
->
base_addr
;
...
...
@@ -992,9 +1024,9 @@ start_tx (struct sk_buff *skb, struct net_device *dev)
txdesc
->
next_desc
=
0
;
/* Note: disable the interrupt generation here before releasing. */
if
(
entry
%
tx_coalesce
==
0
)
{
txdesc
->
status
=
cpu_to_le32
((
entry
<<
2
)
|
txdesc
->
status
=
cpu_to_le32
((
entry
<<
2
)
|
DescIntrOnTx
|
DisableAlign
);
}
else
{
txdesc
->
status
=
cpu_to_le32
((
entry
<<
2
)
|
DisableAlign
);
}
...
...
@@ -1009,7 +1041,7 @@ start_tx (struct sk_buff *skb, struct net_device *dev)
np
->
cur_tx
++
;
/* On some architectures: explicitly flush cache lines here. */
if
(
np
->
cur_tx
-
np
->
dirty_tx
<
TX_QUEUE_LEN
-
1
if
(
np
->
cur_tx
-
np
->
dirty_tx
<
TX_QUEUE_LEN
-
1
&&
!
netif_queue_stopped
(
dev
))
{
/* do nothing */
}
else
{
...
...
@@ -1022,7 +1054,7 @@ start_tx (struct sk_buff *skb, struct net_device *dev)
dev
->
trans_start
=
jiffies
;
if
(
debug
>
4
)
{
if
(
netif_msg_tx_queued
(
np
)
)
{
printk
(
KERN_DEBUG
"%s: Transmit frame #%d queued in slot %d.
\n
"
,
dev
->
name
,
np
->
cur_tx
,
entry
);
...
...
@@ -1038,7 +1070,7 @@ reset_tx (struct net_device *dev, int irq)
long
ioaddr
=
dev
->
base_addr
;
int
i
;
int
frame_id
;
frame_id
=
readb
(
ioaddr
+
TxFrameId
);
writew
(
TxReset
|
DMAReset
|
FIFOReset
|
NetworkReset
,
ioaddr
+
ASICCtrl
+
2
);
...
...
@@ -1054,8 +1086,8 @@ reset_tx (struct net_device *dev, int irq)
break
;
skb
=
np
->
tx_skbuff
[
entry
];
/* Free the original skb. */
pci_unmap_single
(
np
->
pci_dev
,
np
->
tx_ring
[
entry
].
frag
[
0
].
addr
,
pci_unmap_single
(
np
->
pci_dev
,
np
->
tx_ring
[
entry
].
frag
[
0
].
addr
,
skb
->
len
,
PCI_DMA_TODEVICE
);
if
(
irq
)
dev_kfree_skb_irq
(
np
->
tx_skbuff
[
entry
]);
...
...
@@ -1085,7 +1117,7 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
int
intr_status
=
readw
(
ioaddr
+
IntrStatus
);
writew
(
intr_status
,
ioaddr
+
IntrStatus
);
if
(
debug
>
4
)
if
(
netif_msg_intr
(
np
)
)
printk
(
KERN_DEBUG
"%s: Interrupt, status %4.4x.
\n
"
,
dev
->
name
,
intr_status
);
...
...
@@ -1093,7 +1125,7 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
break
;
if
(
intr_status
&
(
IntrRxDMADone
))
{
writew
(
DEFAULT_INTR
&
~
(
IntrRxDone
|
IntrRxDMADone
),
writew
(
DEFAULT_INTR
&
~
(
IntrRxDone
|
IntrRxDMADone
),
ioaddr
+
IntrEnable
);
if
(
np
->
budget
<
0
)
np
->
budget
=
RX_BUDGET
;
...
...
@@ -1104,7 +1136,7 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
int
boguscnt
=
32
;
int
tx_status
=
readw
(
ioaddr
+
TxStatus
);
while
(
tx_status
&
0x80
)
{
if
(
debug
>
4
)
if
(
netif_msg_tx_done
(
np
)
)
printk
(
"%s: Transmit status is %2.2x.
\n
"
,
dev
->
name
,
tx_status
);
...
...
@@ -1142,14 +1174,14 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
break
;
skb
=
np
->
tx_skbuff
[
entry
];
/* Free the original skb. */
pci_unmap_single
(
np
->
pci_dev
,
np
->
tx_ring
[
entry
].
frag
[
0
].
addr
,
pci_unmap_single
(
np
->
pci_dev
,
np
->
tx_ring
[
entry
].
frag
[
0
].
addr
,
skb
->
len
,
PCI_DMA_TODEVICE
);
dev_kfree_skb_irq
(
np
->
tx_skbuff
[
entry
]);
np
->
tx_skbuff
[
entry
]
=
0
;
}
spin_unlock
(
&
np
->
lock
);
if
(
netif_queue_stopped
(
dev
)
&&
if
(
netif_queue_stopped
(
dev
)
&&
np
->
cur_tx
-
np
->
dirty_tx
<
TX_QUEUE_LEN
-
4
)
{
/* The ring is no longer full, clear tbusy. */
netif_wake_queue
(
dev
);
...
...
@@ -1160,14 +1192,14 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
netdev_error
(
dev
,
intr_status
);
if
(
--
boguscnt
<
0
)
{
get_stats
(
dev
);
if
(
debug
>
1
)
if
(
netif_msg_hw
(
np
))
printk
(
KERN_WARNING
"%s: Too much work at interrupt, "
"status=0x%4.4x / 0x%4.4x.
\n
"
,
dev
->
name
,
intr_status
,
readw
(
ioaddr
+
IntrClear
));
break
;
}
}
while
(
1
);
if
(
debug
>
3
)
if
(
netif_msg_intr
(
np
)
)
printk
(
KERN_DEBUG
"%s: exiting interrupt, status=%#4.4x.
\n
"
,
dev
->
name
,
readw
(
ioaddr
+
IntrStatus
));
if
(
np
->
cur_tx
-
np
->
dirty_tx
>
0
&&
tx_coalesce
>
1
)
...
...
@@ -1196,15 +1228,15 @@ static void rx_poll(unsigned long data)
if
(
!
(
desc
->
status
&
DescOwn
))
break
;
pkt_len
=
frame_status
&
0x1fff
;
/* Chip omits the CRC. */
if
(
debug
>
4
)
if
(
netif_msg_rx_status
(
np
)
)
printk
(
KERN_DEBUG
" netdev_rx() status was %8.8x.
\n
"
,
frame_status
);
pci_dma_sync_single
(
np
->
pci_dev
,
desc
->
frag
[
0
].
addr
,
np
->
rx_buf_sz
,
PCI_DMA_FROMDEVICE
);
if
(
frame_status
&
0x001f4000
)
{
/* There was a error. */
if
(
debug
>
2
)
if
(
netif_msg_rx_err
(
np
)
)
printk
(
KERN_DEBUG
" netdev_rx() Rx error was %8.8x.
\n
"
,
frame_status
);
np
->
stats
.
rx_errors
++
;
...
...
@@ -1220,7 +1252,7 @@ static void rx_poll(unsigned long data)
}
else
{
struct
sk_buff
*
skb
;
#ifndef final_version
if
(
debug
>
4
)
if
(
netif_msg_rx_status
(
np
)
)
printk
(
KERN_DEBUG
" netdev_rx() normal Rx pkt length %d"
", bogus_cnt %d.
\n
"
,
pkt_len
,
boguscnt
);
...
...
@@ -1234,9 +1266,9 @@ static void rx_poll(unsigned long data)
eth_copy_and_sum
(
skb
,
np
->
rx_skbuff
[
entry
]
->
tail
,
pkt_len
,
0
);
skb_put
(
skb
,
pkt_len
);
}
else
{
pci_unmap_single
(
np
->
pci_dev
,
pci_unmap_single
(
np
->
pci_dev
,
desc
->
frag
[
0
].
addr
,
np
->
rx_buf_sz
,
np
->
rx_buf_sz
,
PCI_DMA_FROMDEVICE
);
skb_put
(
skb
=
np
->
rx_skbuff
[
entry
],
pkt_len
);
np
->
rx_skbuff
[
entry
]
=
NULL
;
...
...
@@ -1255,7 +1287,7 @@ static void rx_poll(unsigned long data)
writew
(
DEFAULT_INTR
,
ioaddr
+
IntrEnable
);
return
;
not_done:
not_done:
np
->
cur_rx
=
entry
;
refill_rx
(
dev
);
if
(
!
received
)
...
...
@@ -1286,7 +1318,7 @@ static void refill_rx (struct net_device *dev)
skb
->
dev
=
dev
;
/* Mark as being used by this device. */
skb_reserve
(
skb
,
2
);
/* Align IP on 16 byte boundaries */
np
->
rx_ring
[
entry
].
frag
[
0
].
addr
=
cpu_to_le32
(
pci_map_single
(
np
->
pci_dev
,
skb
->
tail
,
pci_map_single
(
np
->
pci_dev
,
skb
->
tail
,
np
->
rx_buf_sz
,
PCI_DMA_FROMDEVICE
));
}
/* Perhaps we need not reset this field. */
...
...
@@ -1303,7 +1335,7 @@ static void netdev_error(struct net_device *dev, int intr_status)
struct
netdev_private
*
np
=
dev
->
priv
;
u16
mii_ctl
,
mii_advertise
,
mii_lpa
;
int
speed
;
if
(
intr_status
&
LinkChange
)
{
if
(
np
->
an_enable
)
{
mii_advertise
=
mdio_read
(
dev
,
np
->
phys
[
0
],
MII_ADVERTISE
);
...
...
@@ -1421,12 +1453,12 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
{
struct
netdev_private
*
np
=
dev
->
priv
;
u32
ethcmd
;
long
ioaddr
=
dev
->
base_addr
;
if
(
copy_from_user
(
&
ethcmd
,
useraddr
,
sizeof
(
ethcmd
)))
return
-
EFAULT
;
switch
(
ethcmd
)
{
/* get constant driver settings/info */
case
ETHTOOL_GDRVINFO
:
{
struct
ethtool_drvinfo
info
=
{
ETHTOOL_GDRVINFO
};
strcpy
(
info
.
driver
,
DRV_NAME
);
...
...
@@ -1437,116 +1469,60 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
return
-
EFAULT
;
return
0
;
}
/* get media settings */
case
ETHTOOL_GSET
:
{
struct
ethtool_cmd
cmd
=
{
ETHTOOL_GSET
};
if
(
readl
(
ioaddr
+
ASICCtrl
)
&
0x80
)
{
/* fiber device */
cmd
.
supported
=
SUPPORTED_Autoneg
|
SUPPORTED_FIBRE
;
cmd
.
advertising
=
ADVERTISED_Autoneg
|
ADVERTISED_FIBRE
;
cmd
.
port
=
PORT_FIBRE
;
cmd
.
transceiver
=
XCVR_INTERNAL
;
}
else
{
/* copper device */
cmd
.
supported
=
SUPPORTED_10baseT_Half
|
SUPPORTED_10baseT_Full
|
SUPPORTED_100baseT_Half
|
SUPPORTED_100baseT_Full
|
SUPPORTED_Autoneg
|
SUPPORTED_MII
;
cmd
.
advertising
=
ADVERTISED_10baseT_Half
|
ADVERTISED_10baseT_Full
|
ADVERTISED_100baseT_Half
|
ADVERTISED_100baseT_Full
|
ADVERTISED_Autoneg
|
ADVERTISED_MII
;
cmd
.
port
=
PORT_MII
;
cmd
.
transceiver
=
XCVR_INTERNAL
;
}
if
(
readb
(
ioaddr
+
MIICtrl
)
&
0x80
)
{
cmd
.
speed
=
np
->
speed
;
cmd
.
duplex
=
np
->
full_duplex
?
DUPLEX_FULL
:
DUPLEX_HALF
;
}
else
{
cmd
.
speed
=
-
1
;
cmd
.
duplex
=
-
1
;
}
if
(
np
->
an_enable
)
cmd
.
autoneg
=
AUTONEG_ENABLE
;
else
cmd
.
autoneg
=
AUTONEG_DISABLE
;
cmd
.
phy_address
=
np
->
phys
[
0
];
if
(
copy_to_user
(
useraddr
,
&
cmd
,
sizeof
(
cmd
)))
struct
ethtool_cmd
ecmd
=
{
ETHTOOL_GSET
};
spin_lock_irq
(
&
np
->
lock
);
mii_ethtool_gset
(
&
np
->
mii_if
,
&
ecmd
);
spin_unlock_irq
(
&
np
->
lock
);
if
(
copy_to_user
(
useraddr
,
&
ecmd
,
sizeof
(
ecmd
)))
return
-
EFAULT
;
return
0
;
return
0
;
}
/* set media settings */
case
ETHTOOL_SSET
:
{
struct
ethtool_cmd
cmd
;
if
(
copy_from_user
(
&
cmd
,
useraddr
,
sizeof
(
cmd
)))
int
r
;
struct
ethtool_cmd
ecmd
;
if
(
copy_from_user
(
&
ecmd
,
useraddr
,
sizeof
(
ecmd
)))
return
-
EFAULT
;
netif_carrier_off
(
dev
);
if
(
cmd
.
autoneg
==
AUTONEG_ENABLE
)
{
if
(
np
->
an_enable
)
return
0
;
else
{
np
->
an_enable
=
1
;
/* Reset PHY */
mdio_write
(
dev
,
np
->
phys
[
0
],
MII_BMCR
,
BMCR_RESET
);
mdelay
(
300
);
/* Start auto negotiation */
mdio_write
(
dev
,
np
->
phys
[
0
],
MII_BMCR
,
BMCR_ANENABLE
|
BMCR_ANRESTART
);
return
0
;
}
}
else
{
/* Reset PHY */
mdio_write
(
dev
,
np
->
phys
[
0
],
MII_BMCR
,
BMCR_RESET
);
mdelay
(
300
);
np
->
an_enable
=
0
;
switch
(
cmd
.
speed
+
cmd
.
duplex
){
case
SPEED_10
+
DUPLEX_HALF
:
np
->
speed
=
10
;
np
->
full_duplex
=
0
;
break
;
case
SPEED_10
+
DUPLEX_FULL
:
np
->
speed
=
10
;
np
->
full_duplex
=
1
;
break
;
case
SPEED_100
+
DUPLEX_HALF
:
np
->
speed
=
100
;
np
->
full_duplex
=
0
;
break
;
case
SPEED_100
+
DUPLEX_FULL
:
np
->
speed
=
100
;
np
->
full_duplex
=
1
;
break
;
default:
return
-
EINVAL
;
}
mdio_write
(
dev
,
np
->
phys
[
0
],
MII_BMCR
,
((
np
->
speed
==
100
)
?
BMCR_SPEED100
:
0
)
|
((
np
->
full_duplex
)
?
BMCR_FULLDPLX
:
0
)
);
spin_lock_irq
(
&
np
->
lock
);
r
=
mii_ethtool_sset
(
&
np
->
mii_if
,
&
ecmd
);
spin_unlock_irq
(
&
np
->
lock
);
return
r
;
}
}
return
0
;
/* restart autonegotiation */
case
ETHTOOL_NWAY_RST
:
{
return
mii_nway_restart
(
&
np
->
mii_if
);
}
#ifdef ETHTOOL_GLINK
case
ETHTOOL_GLINK
:{
struct
ethtool_value
link
=
{
ETHTOOL_GLINK
};
link
.
data
=
readb
(
ioaddr
+
MIICtrl
)
&
0x80
;
if
(
copy_to_user
(
useraddr
,
&
link
,
sizeof
(
link
)))
return
-
EFAULT
;
return
0
;
}
#endif
/* get link status */
case
ETHTOOL_GLINK
:
{
struct
ethtool_value
edata
=
{
ETHTOOL_GLINK
};
edata
.
data
=
mii_link_ok
(
&
np
->
mii_if
);
if
(
copy_to_user
(
useraddr
,
&
edata
,
sizeof
(
edata
)))
return
-
EFAULT
;
return
0
;
}
/* get message-level */
case
ETHTOOL_GMSGLVL
:
{
struct
ethtool_value
edata
=
{
ETHTOOL_GMSGLVL
};
edata
.
data
=
np
->
msg_enable
;
if
(
copy_to_user
(
useraddr
,
&
edata
,
sizeof
(
edata
)))
return
-
EFAULT
;
return
0
;
}
/* set message-level */
case
ETHTOOL_SMSGLVL
:
{
struct
ethtool_value
edata
;
if
(
copy_from_user
(
&
edata
,
useraddr
,
sizeof
(
edata
)))
return
-
EFAULT
;
np
->
msg_enable
=
edata
.
data
;
return
0
;
}
default:
return
-
EOPNOTSUPP
;
...
...
@@ -1587,7 +1563,7 @@ static int netdev_close(struct net_device *dev)
netif_stop_queue
(
dev
);
if
(
debug
>
1
)
{
if
(
netif_msg_ifdown
(
np
)
)
{
printk
(
KERN_DEBUG
"%s: Shutting down ethercard, status was Tx %2.2x "
"Rx %4.4x Int %2.2x.
\n
"
,
dev
->
name
,
readb
(
ioaddr
+
TxStatus
),
...
...
@@ -1603,7 +1579,7 @@ static int netdev_close(struct net_device *dev)
writew
(
TxDisable
|
RxDisable
|
StatsDisable
,
ioaddr
+
MACCtrl1
);
#ifdef __i386__
if
(
debug
>
2
)
{
if
(
netif_msg_hw
(
np
)
)
{
printk
(
"
\n
"
KERN_DEBUG
" Tx ring at %8.8x:
\n
"
,
(
int
)(
np
->
tx_ring_dma
));
for
(
i
=
0
;
i
<
TX_RING_SIZE
;
i
++
)
...
...
@@ -1630,8 +1606,8 @@ static int netdev_close(struct net_device *dev)
np
->
rx_ring
[
i
].
frag
[
0
].
addr
=
0xBADF00D0
;
/* An invalid address. */
skb
=
np
->
rx_skbuff
[
i
];
if
(
skb
)
{
pci_unmap_single
(
np
->
pci_dev
,
np
->
rx_ring
[
i
].
frag
[
0
].
addr
,
np
->
rx_buf_sz
,
pci_unmap_single
(
np
->
pci_dev
,
np
->
rx_ring
[
i
].
frag
[
0
].
addr
,
np
->
rx_buf_sz
,
PCI_DMA_FROMDEVICE
);
dev_kfree_skb
(
skb
);
np
->
rx_skbuff
[
i
]
=
0
;
...
...
@@ -1640,7 +1616,7 @@ static int netdev_close(struct net_device *dev)
for
(
i
=
0
;
i
<
TX_RING_SIZE
;
i
++
)
{
skb
=
np
->
tx_skbuff
[
i
];
if
(
skb
)
{
pci_unmap_single
(
np
->
pci_dev
,
pci_unmap_single
(
np
->
pci_dev
,
np
->
tx_ring
[
i
].
frag
[
0
].
addr
,
skb
->
len
,
PCI_DMA_TODEVICE
);
dev_kfree_skb
(
skb
);
...
...
@@ -1654,15 +1630,15 @@ static int netdev_close(struct net_device *dev)
static
void
__devexit
sundance_remove1
(
struct
pci_dev
*
pdev
)
{
struct
net_device
*
dev
=
pci_get_drvdata
(
pdev
);
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
if
(
dev
)
{
struct
netdev_private
*
np
=
dev
->
priv
;
unregister_netdev
(
dev
);
pci_free_consistent
(
pdev
,
RX_TOTAL_SIZE
,
np
->
rx_ring
,
pci_free_consistent
(
pdev
,
RX_TOTAL_SIZE
,
np
->
rx_ring
,
np
->
rx_ring_dma
);
pci_free_consistent
(
pdev
,
TX_TOTAL_SIZE
,
np
->
tx_ring
,
pci_free_consistent
(
pdev
,
TX_TOTAL_SIZE
,
np
->
tx_ring
,
np
->
tx_ring_dma
);
pci_release_regions
(
pdev
);
#ifndef USE_IO_OPS
...
...
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