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
f18ff4f7
Commit
f18ff4f7
authored
Sep 28, 2002
by
Jeff Garzik
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[net drivers] update hamachi.c and starfire.c to use MII lib
parent
f71c419e
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
159 additions
and
189 deletions
+159
-189
drivers/net/Makefile
drivers/net/Makefile
+2
-2
drivers/net/hamachi.c
drivers/net/hamachi.c
+86
-42
drivers/net/starfire.c
drivers/net/starfire.c
+71
-145
No files found.
drivers/net/Makefile
View file @
f18ff4f7
...
...
@@ -57,7 +57,7 @@ obj-$(CONFIG_TC35815) += tc35815.o
obj-$(CONFIG_SK98LIN)
+=
sk98lin/
obj-$(CONFIG_SKFP)
+=
skfp/
obj-$(CONFIG_VIA_RHINE)
+=
via-rhine.o mii.o
obj-$(CONFIG_ADAPTEC_STARFIRE)
+=
starfire.o
obj-$(CONFIG_ADAPTEC_STARFIRE)
+=
starfire.o
mii.o
#
# end link order section
...
...
@@ -71,7 +71,7 @@ obj-$(CONFIG_AIRONET4500_CS) += aironet4500_proc.o
obj-$(CONFIG_WINBOND_840)
+=
mii.o
obj-$(CONFIG_SUNDANCE)
+=
sundance.o mii.o
obj-$(CONFIG_HAMACHI)
+=
hamachi.o
obj-$(CONFIG_HAMACHI)
+=
hamachi.o
mii.o
obj-$(CONFIG_NET)
+=
Space.o setup.o net_init.o loopback.o
obj-$(CONFIG_SEEQ8005)
+=
seeq8005.o
obj-$(CONFIG_ETHERTAP)
+=
ethertap.o
...
...
drivers/net/hamachi.c
View file @
f18ff4f7
...
...
@@ -505,13 +505,11 @@ struct hamachi_private {
unsigned
int
cur_tx
,
dirty_tx
;
unsigned
int
rx_buf_sz
;
/* Based on MTU+slack. */
unsigned
int
tx_full
:
1
;
/* The Tx queue is full. */
unsigned
int
full_duplex
:
1
;
/* Full-duplex operation requested. */
unsigned
int
duplex_lock
:
1
;
unsigned
int
medialock
:
1
;
/* Do not sense media. */
unsigned
int
default_port
:
4
;
/* Last dev->if_port value. */
/* MII transceiver section. */
int
mii_cnt
;
/* MII device addresses. */
u16
advertising
;
/* NWay media advertisement
*/
struct
mii_if_info
mii_if
;
/* MII lib hooks/info
*/
unsigned
char
phys
[
MII_CNT
];
/* MII device addresses, only first one used. */
u32
rx_int_var
,
tx_int_var
;
/* interrupt control variables */
u32
option
;
/* Hold on to a copy of the options */
...
...
@@ -554,8 +552,8 @@ MODULE_PARM_DESC(full_duplex, "GNIC-II full duplex setting(s) (1)");
MODULE_PARM_DESC
(
force32
,
"GNIC-II: Bit 0: 32 bit PCI, bit 1: disable parity, bit 2: 64 bit PCI (all boards)"
);
static
int
read_eeprom
(
long
ioaddr
,
int
location
);
static
int
mdio_read
(
long
ioaddr
,
int
phy_id
,
int
location
);
static
void
mdio_write
(
long
ioaddr
,
int
phy_id
,
int
location
,
int
value
);
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
hamachi_open
(
struct
net_device
*
dev
);
static
int
netdev_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
);
static
void
hamachi_timer
(
unsigned
long
data
);
...
...
@@ -637,6 +635,12 @@ static int __init hamachi_init_one (struct pci_dev *pdev,
hmp
=
dev
->
priv
;
spin_lock_init
(
&
hmp
->
lock
);
hmp
->
mii_if
.
dev
=
dev
;
hmp
->
mii_if
.
mdio_read
=
mdio_read
;
hmp
->
mii_if
.
mdio_write
=
mdio_write
;
hmp
->
mii_if
.
phy_id_mask
=
0x1f
;
hmp
->
mii_if
.
reg_num_mask
=
0x1f
;
ring_space
=
pci_alloc_consistent
(
pdev
,
TX_TOTAL_SIZE
,
&
ring_dma
);
if
(
!
ring_space
)
goto
err_out_cleardev
;
...
...
@@ -685,18 +689,18 @@ static int __init hamachi_init_one (struct pci_dev *pdev,
if
(
option
>
0
)
{
hmp
->
option
=
option
;
if
(
option
&
0x200
)
hmp
->
full_duplex
=
1
;
hmp
->
mii_if
.
full_duplex
=
1
;
else
if
(
option
&
0x080
)
hmp
->
full_duplex
=
0
;
hmp
->
mii_if
.
full_duplex
=
0
;
hmp
->
default_port
=
option
&
15
;
if
(
hmp
->
default_port
)
hmp
->
m
edialock
=
1
;
hmp
->
m
ii_if
.
force_media
=
1
;
}
if
(
card_idx
<
MAX_UNITS
&&
full_duplex
[
card_idx
]
>
0
)
hmp
->
full_duplex
=
1
;
hmp
->
mii_if
.
full_duplex
=
1
;
/* lock the duplex mode if someone specified a value */
if
(
hmp
->
full_duplex
||
(
option
&
0x080
))
if
(
hmp
->
mii_if
.
full_duplex
||
(
option
&
0x080
))
hmp
->
duplex_lock
=
1
;
/* Set interrupt tuning parameters */
...
...
@@ -749,17 +753,21 @@ static int __init hamachi_init_one (struct pci_dev *pdev,
if
(
chip_tbl
[
hmp
->
chip_id
].
flags
&
CanHaveMII
)
{
int
phy
,
phy_idx
=
0
;
for
(
phy
=
0
;
phy
<
32
&&
phy_idx
<
MII_CNT
;
phy
++
)
{
int
mii_status
=
mdio_read
(
ioaddr
,
phy
,
1
);
int
mii_status
=
mdio_read
(
dev
,
phy
,
MII_BMSR
);
if
(
mii_status
!=
0xffff
&&
mii_status
!=
0x0000
)
{
hmp
->
phys
[
phy_idx
++
]
=
phy
;
hmp
->
advertising
=
mdio_read
(
ioaddr
,
phy
,
4
);
hmp
->
mii_if
.
advertising
=
mdio_read
(
dev
,
phy
,
MII_ADVERTISE
);
printk
(
KERN_INFO
"%s: MII PHY found at address %d, status "
"0x%4.4x advertising %4.4x.
\n
"
,
dev
->
name
,
phy
,
mii_status
,
hmp
->
advertising
);
dev
->
name
,
phy
,
mii_status
,
hmp
->
mii_if
.
advertising
);
}
}
hmp
->
mii_cnt
=
phy_idx
;
if
(
hmp
->
mii_cnt
>
0
)
hmp
->
mii_if
.
phy_id
=
hmp
->
phys
[
0
];
else
memset
(
&
hmp
->
mii_if
,
0
,
sizeof
(
hmp
->
mii_if
));
}
/* Configure gigabit autonegotiation. */
writew
(
0x0400
,
ioaddr
+
ANXchngCtrl
);
/* Enable legacy links. */
...
...
@@ -805,8 +813,9 @@ static int __init read_eeprom(long ioaddr, int location)
These routines assume the MDIO controller is idle, and do not exit until
the command is finished. */
static
int
mdio_read
(
long
ioaddr
,
int
phy_id
,
int
location
)
static
int
mdio_read
(
struct
net_device
*
dev
,
int
phy_id
,
int
location
)
{
long
ioaddr
=
dev
->
base_addr
;
int
i
;
/* We should check busy first - per docs -KDU */
...
...
@@ -821,8 +830,9 @@ static int mdio_read(long ioaddr, int phy_id, int location)
return
readw
(
ioaddr
+
MII_Rd_Data
);
}
static
void
mdio_write
(
long
ioaddr
,
int
phy_id
,
int
location
,
int
value
)
static
void
mdio_write
(
struct
net_device
*
dev
,
int
phy_id
,
int
location
,
int
value
)
{
long
ioaddr
=
dev
->
base_addr
;
int
i
;
/* We should check busy first - per docs -KDU */
...
...
@@ -912,7 +922,7 @@ static int hamachi_open(struct net_device *dev)
/* Setting the Rx mode will start the Rx process. */
/* If someone didn't choose a duplex, default to full-duplex */
if
(
hmp
->
duplex_lock
!=
1
)
hmp
->
full_duplex
=
1
;
hmp
->
mii_if
.
full_duplex
=
1
;
/* always 1, takes no more time to do it */
writew
(
0x0001
,
ioaddr
+
RxChecksum
);
...
...
@@ -1909,7 +1919,7 @@ static void set_rx_mode(struct net_device *dev)
static
int
netdev_ethtool_ioctl
(
struct
net_device
*
dev
,
void
*
useraddr
)
{
struct
hamachi_private
*
hm
p
=
dev
->
priv
;
struct
hamachi_private
*
n
p
=
dev
->
priv
;
u32
ethcmd
;
if
(
copy_from_user
(
&
ethcmd
,
useraddr
,
sizeof
(
ethcmd
)))
...
...
@@ -1920,12 +1930,53 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
struct
ethtool_drvinfo
info
=
{
ETHTOOL_GDRVINFO
};
strcpy
(
info
.
driver
,
DRV_NAME
);
strcpy
(
info
.
version
,
DRV_VERSION
);
strcpy
(
info
.
bus_info
,
hm
p
->
pci_dev
->
slot_name
);
strcpy
(
info
.
bus_info
,
n
p
->
pci_dev
->
slot_name
);
if
(
copy_to_user
(
useraddr
,
&
info
,
sizeof
(
info
)))
return
-
EFAULT
;
return
0
;
}
/* get settings */
case
ETHTOOL_GSET
:
{
struct
ethtool_cmd
ecmd
=
{
ETHTOOL_GSET
};
if
(
!
(
chip_tbl
[
np
->
chip_id
].
flags
&
CanHaveMII
))
return
-
EINVAL
;
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
;
}
/* set settings */
case
ETHTOOL_SSET
:
{
int
r
;
struct
ethtool_cmd
ecmd
;
if
(
!
(
chip_tbl
[
np
->
chip_id
].
flags
&
CanHaveMII
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
ecmd
,
useraddr
,
sizeof
(
ecmd
)))
return
-
EFAULT
;
spin_lock_irq
(
&
np
->
lock
);
r
=
mii_ethtool_sset
(
&
np
->
mii_if
,
&
ecmd
);
spin_unlock_irq
(
&
np
->
lock
);
return
r
;
}
/* restart autonegotiation */
case
ETHTOOL_NWAY_RST
:
{
if
(
!
(
chip_tbl
[
np
->
chip_id
].
flags
&
CanHaveMII
))
return
-
EINVAL
;
return
mii_nway_restart
(
&
np
->
mii_if
);
}
/* get link status */
case
ETHTOOL_GLINK
:
{
struct
ethtool_value
edata
=
{
ETHTOOL_GLINK
};
if
(
!
(
chip_tbl
[
np
->
chip_id
].
flags
&
CanHaveMII
))
return
-
EINVAL
;
edata
.
data
=
mii_link_ok
(
&
np
->
mii_if
);
if
(
copy_to_user
(
useraddr
,
&
edata
,
sizeof
(
edata
)))
return
-
EFAULT
;
return
0
;
}
}
return
-
EOPNOTSUPP
;
...
...
@@ -1933,29 +1984,17 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
static
int
netdev_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
)
{
long
ioaddr
=
dev
->
base_addr
;
struct
mii_ioctl_data
*
data
=
(
struct
mii_ioctl_data
*
)
&
rq
->
ifr_data
;
struct
hamachi_private
*
np
=
dev
->
priv
;
struct
mii_ioctl_data
*
data
=
(
struct
mii_ioctl_data
*
)
&
rq
->
ifr_data
;
int
rc
;
switch
(
cmd
)
{
case
SIOCETHTOOL
:
return
netdev_ethtool_ioctl
(
dev
,
(
void
*
)
rq
->
ifr_data
);
case
SIOCGMIIPHY
:
/* Get address of MII PHY in use. */
data
->
phy_id
=
((
struct
hamachi_private
*
)
dev
->
priv
)
->
phys
[
0
]
&
0x1f
;
/* Fall Through */
if
(
!
netif_running
(
dev
))
return
-
EINVAL
;
case
SIOCGMIIREG
:
/* Read MII PHY register. */
data
->
val_out
=
mdio_read
(
ioaddr
,
data
->
phy_id
&
0x1f
,
data
->
reg_num
&
0x1f
);
return
0
;
if
(
cmd
==
SIOCETHTOOL
)
rc
=
netdev_ethtool_ioctl
(
dev
,
(
void
*
)
rq
->
ifr_data
);
case
SIOCSMIIREG
:
/* Write MII PHY register. */
/* TODO: Check the sequencing of this. Might need to stop and
* restart Rx and Tx engines. -KDU
*/
if
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
mdio_write
(
ioaddr
,
data
->
phy_id
&
0x1f
,
data
->
reg_num
&
0x1f
,
data
->
val_in
);
return
0
;
case
SIOCDEVPRIVATE
+
3
:
{
/* set rx,tx intr params */
else
if
(
cmd
==
(
SIOCDEVPRIVATE
+
3
))
{
/* set rx,tx intr params */
u32
*
d
=
(
u32
*
)
&
rq
->
ifr_data
;
/* Should add this check here or an ordinary user can do nasty
* things. -KDU
...
...
@@ -1969,11 +2008,16 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
printk
(
KERN_NOTICE
"%s: tx %08x, rx %08x intr
\n
"
,
dev
->
name
,
(
u32
)
readl
(
dev
->
base_addr
+
TxIntrCtrl
),
(
u32
)
readl
(
dev
->
base_addr
+
RxIntrCtrl
));
r
eturn
0
;
r
c
=
0
;
}
default:
return
-
EOPNOTSUPP
;
else
{
spin_lock_irq
(
&
np
->
lock
);
rc
=
generic_mii_ioctl
(
&
np
->
mii_if
,
data
,
cmd
,
NULL
);
spin_unlock_irq
(
&
np
->
lock
);
}
return
rc
;
}
...
...
drivers/net/starfire.c
View file @
f18ff4f7
...
...
@@ -571,19 +571,18 @@ struct netdev_private {
struct
net_device_stats
stats
;
struct
pci_dev
*
pci_dev
;
/* Frequently used values: keep some adjacent for cache effect. */
spinlock_t
lock
;
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. */
unsigned
int
tx_full
:
1
,
/* The Tx queue is full. */
/* These values keep track of the transceiver/media in use. */
autoneg:
1
,
/* Autonegotiation allowed. */
full_duplex:
1
,
/* Full-duplex operation. */
speed100:
1
;
/* Set if speed == 100MBit. */
unsigned
int
intr_mitigation
;
u32
tx_mode
;
u8
tx_threshold
;
/* MII transceiver section. */
u16
advertising
;
/* NWay media advertisement
*/
struct
mii_if_info
mii_if
;
/* MII lib hooks/info
*/
int
phy_cnt
;
/* MII device addresses. */
unsigned
char
phys
[
PHY_CNT
];
/* MII device addresses. */
};
...
...
@@ -726,9 +725,17 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
dev
->
irq
=
irq
;
np
=
dev
->
priv
;
spin_lock_init
(
&
np
->
lock
);
pci_set_drvdata
(
pdev
,
dev
);
np
->
pci_dev
=
pdev
;
np
->
mii_if
.
dev
=
dev
;
np
->
mii_if
.
mdio_read
=
mdio_read
;
np
->
mii_if
.
mdio_write
=
mdio_write
;
np
->
mii_if
.
phy_id_mask
=
0x1f
;
np
->
mii_if
.
reg_num_mask
=
0x1f
;
drv_flags
=
netdrv_tbl
[
chip_idx
].
drv_flags
;
option
=
card_idx
<
MAX_UNITS
?
options
[
card_idx
]
:
0
;
...
...
@@ -737,15 +744,15 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
/* The lower four bits are the media type. */
if
(
option
&
0x200
)
np
->
full_duplex
=
1
;
np
->
mii_if
.
full_duplex
=
1
;
if
(
card_idx
<
MAX_UNITS
&&
full_duplex
[
card_idx
]
>
0
)
np
->
full_duplex
=
1
;
np
->
mii_if
.
full_duplex
=
1
;
if
(
np
->
full_duplex
)
np
->
autoneg
=
0
;
if
(
np
->
mii_if
.
full_duplex
)
np
->
mii_if
.
force_media
=
0
;
else
np
->
autoneg
=
1
;
np
->
mii_if
.
force_media
=
1
;
np
->
speed100
=
1
;
/* The chip-specific entries in the device structure. */
...
...
@@ -787,15 +794,19 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
mii_status
=
mdio_read
(
dev
,
phy
,
MII_BMSR
);
if
(
mii_status
!=
0
)
{
np
->
phys
[
phy_idx
++
]
=
phy
;
np
->
advertising
=
mdio_read
(
dev
,
phy
,
MII_ADVERTISE
);
np
->
mii_if
.
advertising
=
mdio_read
(
dev
,
phy
,
MII_ADVERTISE
);
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
);
/* there can be only one PHY on-board */
break
;
}
}
np
->
phy_cnt
=
phy_idx
;
if
(
np
->
phy_cnt
>
0
)
np
->
mii_if
.
phy_id
=
np
->
phys
[
0
];
else
memset
(
&
np
->
mii_if
,
0
,
sizeof
(
np
->
mii_if
));
}
#ifdef ZEROCOPY
...
...
@@ -842,7 +853,6 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
long
mdio_addr
=
dev
->
base_addr
+
MIICtrl
+
(
phy_id
<<
7
)
+
(
location
<<
2
);
writel
(
value
,
mdio_addr
);
/* The busy-wait will occur before a read. */
return
;
}
...
...
@@ -985,7 +995,7 @@ static int netdev_open(struct net_device *dev)
printk
(
KERN_DEBUG
"%s: Setting the Rx and Tx modes.
\n
"
,
dev
->
name
);
set_rx_mode
(
dev
);
np
->
advertising
=
mdio_read
(
dev
,
np
->
phys
[
0
],
MII_ADVERTISE
);
np
->
mii_if
.
advertising
=
mdio_read
(
dev
,
np
->
phys
[
0
],
MII_ADVERTISE
);
check_duplex
(
dev
);
/* Enable GPIO interrupts on link change */
...
...
@@ -1026,25 +1036,25 @@ static void check_duplex(struct net_device *dev)
struct
netdev_private
*
np
=
dev
->
priv
;
u16
reg0
;
mdio_write
(
dev
,
np
->
phys
[
0
],
MII_ADVERTISE
,
np
->
advertising
);
mdio_write
(
dev
,
np
->
phys
[
0
],
MII_ADVERTISE
,
np
->
mii_if
.
advertising
);
mdio_write
(
dev
,
np
->
phys
[
0
],
MII_BMCR
,
BMCR_RESET
);
udelay
(
500
);
while
(
mdio_read
(
dev
,
np
->
phys
[
0
],
MII_BMCR
)
&
BMCR_RESET
);
reg0
=
mdio_read
(
dev
,
np
->
phys
[
0
],
MII_BMCR
);
if
(
np
->
autoneg
)
{
if
(
!
np
->
mii_if
.
force_media
)
{
reg0
|=
BMCR_ANENABLE
|
BMCR_ANRESTART
;
}
else
{
reg0
&=
~
(
BMCR_ANENABLE
|
BMCR_ANRESTART
);
if
(
np
->
speed100
)
reg0
|=
BMCR_SPEED100
;
if
(
np
->
full_duplex
)
if
(
np
->
mii_if
.
full_duplex
)
reg0
|=
BMCR_FULLDPLX
;
printk
(
KERN_DEBUG
"%s: Link forced to %sMbit %s-duplex
\n
"
,
dev
->
name
,
np
->
speed100
?
"100"
:
"10"
,
np
->
full_duplex
?
"full"
:
"half"
);
np
->
mii_if
.
full_duplex
?
"full"
:
"half"
);
}
mdio_write
(
dev
,
np
->
phys
[
0
],
MII_BMCR
,
reg0
);
}
...
...
@@ -1555,16 +1565,16 @@ static void netdev_media_change(struct net_device *dev)
reg5
=
mdio_read
(
dev
,
np
->
phys
[
0
],
MII_LPA
);
if
(
reg4
&
ADVERTISE_100FULL
&&
reg5
&
LPA_100FULL
)
{
np
->
speed100
=
1
;
np
->
full_duplex
=
1
;
np
->
mii_if
.
full_duplex
=
1
;
}
else
if
(
reg4
&
ADVERTISE_100HALF
&&
reg5
&
LPA_100HALF
)
{
np
->
speed100
=
1
;
np
->
full_duplex
=
0
;
np
->
mii_if
.
full_duplex
=
0
;
}
else
if
(
reg4
&
ADVERTISE_10FULL
&&
reg5
&
LPA_10FULL
)
{
np
->
speed100
=
0
;
np
->
full_duplex
=
1
;
np
->
mii_if
.
full_duplex
=
1
;
}
else
{
np
->
speed100
=
0
;
np
->
full_duplex
=
0
;
np
->
mii_if
.
full_duplex
=
0
;
}
}
else
{
/* autonegotiation is disabled */
...
...
@@ -1573,17 +1583,17 @@ static void netdev_media_change(struct net_device *dev)
else
np
->
speed100
=
0
;
if
(
reg0
&
BMCR_FULLDPLX
)
np
->
full_duplex
=
1
;
np
->
mii_if
.
full_duplex
=
1
;
else
np
->
full_duplex
=
0
;
np
->
mii_if
.
full_duplex
=
0
;
}
printk
(
KERN_DEBUG
"%s: Link is up, running at %sMbit %s-duplex
\n
"
,
dev
->
name
,
np
->
speed100
?
"100"
:
"10"
,
np
->
full_duplex
?
"full"
:
"half"
);
np
->
mii_if
.
full_duplex
?
"full"
:
"half"
);
new_tx_mode
=
np
->
tx_mode
&
~
0x2
;
/* duplex setting */
if
(
np
->
full_duplex
)
if
(
np
->
mii_if
.
full_duplex
)
new_tx_mode
|=
2
;
if
(
np
->
tx_mode
!=
new_tx_mode
)
{
np
->
tx_mode
=
new_tx_mode
;
...
...
@@ -1718,77 +1728,6 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
return
-
EFAULT
;
switch
(
ecmd
.
cmd
)
{
case
ETHTOOL_GSET
:
ecmd
.
supported
=
SUPPORTED_10baseT_Half
|
SUPPORTED_10baseT_Full
|
SUPPORTED_100baseT_Half
|
SUPPORTED_100baseT_Full
|
SUPPORTED_Autoneg
|
SUPPORTED_MII
;
ecmd
.
advertising
=
ADVERTISED_MII
;
if
(
np
->
advertising
&
ADVERTISE_10HALF
)
ecmd
.
advertising
|=
ADVERTISED_10baseT_Half
;
if
(
np
->
advertising
&
ADVERTISE_10FULL
)
ecmd
.
advertising
|=
ADVERTISED_10baseT_Full
;
if
(
np
->
advertising
&
ADVERTISE_100HALF
)
ecmd
.
advertising
|=
ADVERTISED_100baseT_Half
;
if
(
np
->
advertising
&
ADVERTISE_100FULL
)
ecmd
.
advertising
|=
ADVERTISED_100baseT_Full
;
if
(
np
->
autoneg
)
{
ecmd
.
advertising
|=
ADVERTISED_Autoneg
;
ecmd
.
autoneg
=
AUTONEG_ENABLE
;
}
else
ecmd
.
autoneg
=
AUTONEG_DISABLE
;
ecmd
.
port
=
PORT_MII
;
ecmd
.
transceiver
=
XCVR_INTERNAL
;
ecmd
.
phy_address
=
np
->
phys
[
0
];
ecmd
.
speed
=
np
->
speed100
?
SPEED_100
:
SPEED_10
;
ecmd
.
duplex
=
np
->
full_duplex
?
DUPLEX_FULL
:
DUPLEX_HALF
;
ecmd
.
maxtxpkt
=
TX_RING_SIZE
;
ecmd
.
maxrxpkt
=
np
->
intr_mitigation
;
/* not 100% accurate */
if
(
copy_to_user
(
useraddr
,
&
ecmd
,
sizeof
(
ecmd
)))
return
-
EFAULT
;
return
0
;
case
ETHTOOL_SSET
:
{
u16
autoneg
,
speed100
,
full_duplex
;
autoneg
=
(
ecmd
.
autoneg
==
AUTONEG_ENABLE
);
speed100
=
(
ecmd
.
speed
==
SPEED_100
);
full_duplex
=
(
ecmd
.
duplex
==
DUPLEX_FULL
);
np
->
autoneg
=
autoneg
;
if
(
speed100
!=
np
->
speed100
||
full_duplex
!=
np
->
full_duplex
)
{
np
->
speed100
=
speed100
;
np
->
full_duplex
=
full_duplex
;
/* change advertising bits */
np
->
advertising
&=
~
(
ADVERTISE_10HALF
|
ADVERTISE_10FULL
|
ADVERTISE_100HALF
|
ADVERTISE_100FULL
|
ADVERTISE_100BASE4
);
if
(
speed100
)
{
if
(
full_duplex
)
np
->
advertising
|=
ADVERTISE_100FULL
;
else
np
->
advertising
|=
ADVERTISE_100HALF
;
}
else
{
if
(
full_duplex
)
np
->
advertising
|=
ADVERTISE_10FULL
;
else
np
->
advertising
|=
ADVERTISE_10HALF
;
}
}
check_duplex
(
dev
);
return
0
;
}
case
ETHTOOL_GDRVINFO
:
{
struct
ethtool_drvinfo
info
;
memset
(
&
info
,
0
,
sizeof
(
info
));
...
...
@@ -1802,26 +1741,35 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
return
0
;
}
/* restart autonegotiation */
case
ETHTOOL_NWAY_RST
:
{
int
tmp
;
int
r
=
-
EINVAL
;
/* if autoneg is off, it's an error */
tmp
=
mdio_read
(
dev
,
np
->
phys
[
0
],
MII_BMCR
);
if
(
tmp
&
BMCR_ANENABLE
)
{
tmp
|=
(
BMCR_ANRESTART
);
mdio_write
(
dev
,
np
->
phys
[
0
],
MII_BMCR
,
tmp
);
r
=
0
;
/* get settings */
case
ETHTOOL_GSET
:
{
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
;
}
/* set settings */
case
ETHTOOL_SSET
:
{
int
r
;
struct
ethtool_cmd
ecmd
;
if
(
copy_from_user
(
&
ecmd
,
useraddr
,
sizeof
(
ecmd
)))
return
-
EFAULT
;
spin_lock_irq
(
&
np
->
lock
);
r
=
mii_ethtool_sset
(
&
np
->
mii_if
,
&
ecmd
);
spin_unlock_irq
(
&
np
->
lock
);
return
r
;
}
/* restart autonegotiation */
case
ETHTOOL_NWAY_RST
:
{
return
mii_nway_restart
(
&
np
->
mii_if
);
}
/* get link status */
case
ETHTOOL_GLINK
:
{
struct
ethtool_value
edata
=
{
ETHTOOL_GLINK
};
if
(
mdio_read
(
dev
,
np
->
phys
[
0
],
MII_BMSR
)
&
BMSR_LSTATUS
)
edata
.
data
=
1
;
else
edata
.
data
=
0
;
edata
.
data
=
mii_link_ok
(
&
np
->
mii_if
);
if
(
copy_to_user
(
useraddr
,
&
edata
,
sizeof
(
edata
)))
return
-
EFAULT
;
return
0
;
...
...
@@ -1852,47 +1800,25 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
static
int
netdev_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
)
{
struct
netdev_private
*
np
=
dev
->
priv
;
struct
mii_ioctl_data
*
data
=
(
struct
mii_ioctl_data
*
)
&
rq
->
ifr_data
;
struct
mii_ioctl_data
*
data
=
(
struct
mii_ioctl_data
*
)
&
rq
->
ifr_data
;
int
rc
;
switch
(
cmd
)
{
case
SIOCETHTOOL
:
return
netdev_ethtool_ioctl
(
dev
,
(
void
*
)
rq
->
ifr_data
);
if
(
!
netif_running
(
dev
))
return
-
EINVAL
;
/* Legacy mii-diag interface */
case
SIOCGMIIPHY
:
/* Get address of MII PHY in use. */
data
->
phy_id
=
np
->
phys
[
0
]
&
0x1f
;
/* Fall Through */
if
(
cmd
==
SIOCETHTOOL
)
rc
=
netdev_ethtool_ioctl
(
dev
,
(
void
*
)
rq
->
ifr_data
);
case
SIOCGMIIREG
:
/* Read MII PHY register. */
data
->
val_out
=
mdio_read
(
dev
,
data
->
phy_id
&
0x1f
,
data
->
reg_num
&
0x1f
);
return
0
;
case
SIOCSMIIREG
:
/* Write MII PHY register. */
if
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
if
(
data
->
phy_id
==
np
->
phys
[
0
])
{
u16
value
=
data
->
val_in
;
switch
(
data
->
reg_num
)
{
case
0
:
if
(
value
&
(
BMCR_RESET
|
BMCR_ANENABLE
))
/* Autonegotiation. */
np
->
autoneg
=
1
;
else
{
np
->
full_duplex
=
(
value
&
BMCR_FULLDPLX
)
?
1
:
0
;
np
->
autoneg
=
0
;
}
break
;
case
4
:
np
->
advertising
=
value
;
break
;
}
spin_lock_irq
(
&
np
->
lock
);
rc
=
generic_mii_ioctl
(
&
np
->
mii_if
,
data
,
cmd
,
NULL
);
spin_unlock_irq
(
&
np
->
lock
);
if
((
cmd
==
SIOCSMIIREG
)
&&
(
data
->
phy_id
==
np
->
phys
[
0
]))
check_duplex
(
dev
);
}
mdio_write
(
dev
,
data
->
phy_id
&
0x1f
,
data
->
reg_num
&
0x1f
,
data
->
val_in
);
return
0
;
default:
return
-
EOPNOTSUPP
;
}
return
rc
;
}
static
int
netdev_close
(
struct
net_device
*
dev
)
...
...
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