Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
4a5e8e29
Commit
4a5e8e29
authored
Mar 21, 2006
by
Jeff Garzik
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[netdrvr] pcnet32: Lindent
parent
3d781a02
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
2156 additions
and
1999 deletions
+2156
-1999
drivers/net/pcnet32.c
drivers/net/pcnet32.c
+2156
-1999
No files found.
drivers/net/pcnet32.c
View file @
4a5e8e29
...
...
@@ -26,8 +26,8 @@
#define DRV_RELDATE "18.Mar.2006"
#define PFX DRV_NAME ": "
static
const
char
*
const
version
=
DRV_NAME
".c:v"
DRV_VERSION
" "
DRV_RELDATE
" tsbogend@alpha.franken.de
\n
"
;
static
const
char
*
const
version
=
DRV_NAME
".c:v"
DRV_VERSION
" "
DRV_RELDATE
" tsbogend@alpha.franken.de
\n
"
;
#include <linux/module.h>
#include <linux/kernel.h>
...
...
@@ -58,18 +58,23 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n";
* PCI device identifiers for "new style" Linux PCI Device Drivers
*/
static
struct
pci_device_id
pcnet32_pci_tbl
[]
=
{
{
PCI_VENDOR_ID_AMD
,
PCI_DEVICE_ID_AMD_LANCE_HOME
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
{
PCI_VENDOR_ID_AMD
,
PCI_DEVICE_ID_AMD_LANCE
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
{
PCI_VENDOR_ID_AMD
,
PCI_DEVICE_ID_AMD_LANCE_HOME
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
{
PCI_VENDOR_ID_AMD
,
PCI_DEVICE_ID_AMD_LANCE
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
/*
* Adapters that were sold with IBM's RS/6000 or pSeries hardware have
* the incorrect vendor id.
*/
{
PCI_VENDOR_ID_TRIDENT
,
PCI_DEVICE_ID_AMD_LANCE
,
PCI_ANY_ID
,
PCI_ANY_ID
,
PCI_CLASS_NETWORK_ETHERNET
<<
8
,
0xffff00
,
0
},
{
0
,
}
{
PCI_VENDOR_ID_TRIDENT
,
PCI_DEVICE_ID_AMD_LANCE
,
PCI_ANY_ID
,
PCI_ANY_ID
,
PCI_CLASS_NETWORK_ETHERNET
<<
8
,
0xffff00
,
0
},
{
}
/* terminate list */
};
MODULE_DEVICE_TABLE
(
pci
,
pcnet32_pci_tbl
);
MODULE_DEVICE_TABLE
(
pci
,
pcnet32_pci_tbl
);
static
int
cards_found
;
...
...
@@ -79,8 +84,6 @@ static int cards_found;
static
unsigned
int
pcnet32_portlist
[]
__initdata
=
{
0x300
,
0x320
,
0x340
,
0x360
,
0
};
static
int
pcnet32_debug
=
0
;
static
int
tx_start
=
1
;
/* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */
static
int
pcnet32vlb
;
/* check for VLB cards ? */
...
...
@@ -124,13 +127,15 @@ static const unsigned char options_mapping[] = {
PCNET32_PORT_MII
,
/* 11 MII (autosel) */
PCNET32_PORT_10BT
,
/* 12 10BaseT */
PCNET32_PORT_MII
|
PCNET32_PORT_100
,
/* 13 MII 100BaseTx */
PCNET32_PORT_MII
|
PCNET32_PORT_100
|
PCNET32_PORT_FD
,
/* 14 MII 100BaseTx-FD */
/* 14 MII 100BaseTx-FD */
PCNET32_PORT_MII
|
PCNET32_PORT_100
|
PCNET32_PORT_FD
,
PCNET32_PORT_ASEL
/* 15 not supported */
};
static
const
char
pcnet32_gstrings_test
[][
ETH_GSTRING_LEN
]
=
{
"Loopback test (offline)"
};
#define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN)
#define PCNET32_NUM_REGS 136
...
...
@@ -270,7 +275,6 @@ static int homepna[MAX_UNITS];
* Philippe Seewer assisted with auto negotiation and testing.
*/
/*
* Set the number of Tx and Rx buffers, using Log_2(# buffers).
* Reasonable default values are 4 Tx buffers, and 16 Rx buffers.
...
...
@@ -335,13 +339,13 @@ struct pcnet32_init_block {
/* PCnet32 access functions */
struct
pcnet32_access
{
u16
(
*
read_csr
)
(
unsigned
long
,
int
);
void
(
*
write_csr
)
(
unsigned
long
,
int
,
u16
);
u16
(
*
read_bcr
)
(
unsigned
long
,
int
);
void
(
*
write_bcr
)
(
unsigned
long
,
int
,
u16
);
u16
(
*
read_rap
)
(
unsigned
long
);
void
(
*
write_rap
)
(
unsigned
long
,
u16
);
void
(
*
reset
)
(
unsigned
long
);
u16
(
*
read_csr
)
(
unsigned
long
,
int
);
void
(
*
write_csr
)
(
unsigned
long
,
int
,
u16
);
u16
(
*
read_bcr
)
(
unsigned
long
,
int
);
void
(
*
write_bcr
)
(
unsigned
long
,
int
,
u16
);
u16
(
*
read_rap
)
(
unsigned
long
);
void
(
*
write_rap
)
(
unsigned
long
,
u16
);
void
(
*
reset
)
(
unsigned
long
);
};
/*
...
...
@@ -400,7 +404,7 @@ static int pcnet32_open(struct net_device *);
static
int
pcnet32_init_ring
(
struct
net_device
*
);
static
int
pcnet32_start_xmit
(
struct
sk_buff
*
,
struct
net_device
*
);
static
int
pcnet32_rx
(
struct
net_device
*
);
static
void
pcnet32_tx_timeout
(
struct
net_device
*
dev
);
static
void
pcnet32_tx_timeout
(
struct
net_device
*
dev
);
static
irqreturn_t
pcnet32_interrupt
(
int
,
void
*
,
struct
pt_regs
*
);
static
int
pcnet32_close
(
struct
net_device
*
);
static
struct
net_device_stats
*
pcnet32_get_stats
(
struct
net_device
*
);
...
...
@@ -409,11 +413,12 @@ static void pcnet32_set_multicast_list(struct net_device *);
static
int
pcnet32_ioctl
(
struct
net_device
*
,
struct
ifreq
*
,
int
);
static
void
pcnet32_watchdog
(
struct
net_device
*
);
static
int
mdio_read
(
struct
net_device
*
dev
,
int
phy_id
,
int
reg_num
);
static
void
mdio_write
(
struct
net_device
*
dev
,
int
phy_id
,
int
reg_num
,
int
val
);
static
void
mdio_write
(
struct
net_device
*
dev
,
int
phy_id
,
int
reg_num
,
int
val
);
static
void
pcnet32_restart
(
struct
net_device
*
dev
,
unsigned
int
csr0_bits
);
static
void
pcnet32_ethtool_test
(
struct
net_device
*
dev
,
struct
ethtool_test
*
eth_test
,
u64
*
data
);
static
int
pcnet32_loopback_test
(
struct
net_device
*
dev
,
uint64_t
*
data1
);
struct
ethtool_test
*
eth_test
,
u64
*
data
);
static
int
pcnet32_loopback_test
(
struct
net_device
*
dev
,
uint64_t
*
data1
);
static
int
pcnet32_phys_id
(
struct
net_device
*
dev
,
u32
data
);
static
void
pcnet32_led_blink_callback
(
struct
net_device
*
dev
);
static
int
pcnet32_get_regs_len
(
struct
net_device
*
dev
);
...
...
@@ -424,56 +429,55 @@ static int pcnet32_alloc_ring(struct net_device *dev, char *name);
static
void
pcnet32_free_ring
(
struct
net_device
*
dev
);
static
void
pcnet32_check_media
(
struct
net_device
*
dev
,
int
verbose
);
enum
pci_flags_bit
{
PCI_USES_IO
=
1
,
PCI_USES_MEM
=
2
,
PCI_USES_MASTER
=
4
,
PCI_ADDR0
=
0x10
<<
0
,
PCI_ADDR1
=
0x10
<<
1
,
PCI_ADDR2
=
0x10
<<
2
,
PCI_ADDR3
=
0x10
<<
3
,
PCI_USES_IO
=
1
,
PCI_USES_MEM
=
2
,
PCI_USES_MASTER
=
4
,
PCI_ADDR0
=
0x10
<<
0
,
PCI_ADDR1
=
0x10
<<
1
,
PCI_ADDR2
=
0x10
<<
2
,
PCI_ADDR3
=
0x10
<<
3
,
};
static
u16
pcnet32_wio_read_csr
(
unsigned
long
addr
,
int
index
)
static
u16
pcnet32_wio_read_csr
(
unsigned
long
addr
,
int
index
)
{
outw
(
index
,
addr
+
PCNET32_WIO_RAP
);
return
inw
(
addr
+
PCNET32_WIO_RDP
);
outw
(
index
,
addr
+
PCNET32_WIO_RAP
);
return
inw
(
addr
+
PCNET32_WIO_RDP
);
}
static
void
pcnet32_wio_write_csr
(
unsigned
long
addr
,
int
index
,
u16
val
)
static
void
pcnet32_wio_write_csr
(
unsigned
long
addr
,
int
index
,
u16
val
)
{
outw
(
index
,
addr
+
PCNET32_WIO_RAP
);
outw
(
val
,
addr
+
PCNET32_WIO_RDP
);
outw
(
index
,
addr
+
PCNET32_WIO_RAP
);
outw
(
val
,
addr
+
PCNET32_WIO_RDP
);
}
static
u16
pcnet32_wio_read_bcr
(
unsigned
long
addr
,
int
index
)
static
u16
pcnet32_wio_read_bcr
(
unsigned
long
addr
,
int
index
)
{
outw
(
index
,
addr
+
PCNET32_WIO_RAP
);
return
inw
(
addr
+
PCNET32_WIO_BDP
);
outw
(
index
,
addr
+
PCNET32_WIO_RAP
);
return
inw
(
addr
+
PCNET32_WIO_BDP
);
}
static
void
pcnet32_wio_write_bcr
(
unsigned
long
addr
,
int
index
,
u16
val
)
static
void
pcnet32_wio_write_bcr
(
unsigned
long
addr
,
int
index
,
u16
val
)
{
outw
(
index
,
addr
+
PCNET32_WIO_RAP
);
outw
(
val
,
addr
+
PCNET32_WIO_BDP
);
outw
(
index
,
addr
+
PCNET32_WIO_RAP
);
outw
(
val
,
addr
+
PCNET32_WIO_BDP
);
}
static
u16
pcnet32_wio_read_rap
(
unsigned
long
addr
)
static
u16
pcnet32_wio_read_rap
(
unsigned
long
addr
)
{
return
inw
(
addr
+
PCNET32_WIO_RAP
);
return
inw
(
addr
+
PCNET32_WIO_RAP
);
}
static
void
pcnet32_wio_write_rap
(
unsigned
long
addr
,
u16
val
)
static
void
pcnet32_wio_write_rap
(
unsigned
long
addr
,
u16
val
)
{
outw
(
val
,
addr
+
PCNET32_WIO_RAP
);
outw
(
val
,
addr
+
PCNET32_WIO_RAP
);
}
static
void
pcnet32_wio_reset
(
unsigned
long
addr
)
static
void
pcnet32_wio_reset
(
unsigned
long
addr
)
{
inw
(
addr
+
PCNET32_WIO_RESET
);
inw
(
addr
+
PCNET32_WIO_RESET
);
}
static
int
pcnet32_wio_check
(
unsigned
long
addr
)
static
int
pcnet32_wio_check
(
unsigned
long
addr
)
{
outw
(
88
,
addr
+
PCNET32_WIO_RAP
);
return
(
inw
(
addr
+
PCNET32_WIO_RAP
)
==
88
);
outw
(
88
,
addr
+
PCNET32_WIO_RAP
);
return
(
inw
(
addr
+
PCNET32_WIO_RAP
)
==
88
);
}
static
struct
pcnet32_access
pcnet32_wio
=
{
...
...
@@ -486,49 +490,49 @@ static struct pcnet32_access pcnet32_wio = {
.
reset
=
pcnet32_wio_reset
};
static
u16
pcnet32_dwio_read_csr
(
unsigned
long
addr
,
int
index
)
static
u16
pcnet32_dwio_read_csr
(
unsigned
long
addr
,
int
index
)
{
outl
(
index
,
addr
+
PCNET32_DWIO_RAP
);
return
(
inl
(
addr
+
PCNET32_DWIO_RDP
)
&
0xffff
);
outl
(
index
,
addr
+
PCNET32_DWIO_RAP
);
return
(
inl
(
addr
+
PCNET32_DWIO_RDP
)
&
0xffff
);
}
static
void
pcnet32_dwio_write_csr
(
unsigned
long
addr
,
int
index
,
u16
val
)
static
void
pcnet32_dwio_write_csr
(
unsigned
long
addr
,
int
index
,
u16
val
)
{
outl
(
index
,
addr
+
PCNET32_DWIO_RAP
);
outl
(
val
,
addr
+
PCNET32_DWIO_RDP
);
outl
(
index
,
addr
+
PCNET32_DWIO_RAP
);
outl
(
val
,
addr
+
PCNET32_DWIO_RDP
);
}
static
u16
pcnet32_dwio_read_bcr
(
unsigned
long
addr
,
int
index
)
static
u16
pcnet32_dwio_read_bcr
(
unsigned
long
addr
,
int
index
)
{
outl
(
index
,
addr
+
PCNET32_DWIO_RAP
);
return
(
inl
(
addr
+
PCNET32_DWIO_BDP
)
&
0xffff
);
outl
(
index
,
addr
+
PCNET32_DWIO_RAP
);
return
(
inl
(
addr
+
PCNET32_DWIO_BDP
)
&
0xffff
);
}
static
void
pcnet32_dwio_write_bcr
(
unsigned
long
addr
,
int
index
,
u16
val
)
static
void
pcnet32_dwio_write_bcr
(
unsigned
long
addr
,
int
index
,
u16
val
)
{
outl
(
index
,
addr
+
PCNET32_DWIO_RAP
);
outl
(
val
,
addr
+
PCNET32_DWIO_BDP
);
outl
(
index
,
addr
+
PCNET32_DWIO_RAP
);
outl
(
val
,
addr
+
PCNET32_DWIO_BDP
);
}
static
u16
pcnet32_dwio_read_rap
(
unsigned
long
addr
)
static
u16
pcnet32_dwio_read_rap
(
unsigned
long
addr
)
{
return
(
inl
(
addr
+
PCNET32_DWIO_RAP
)
&
0xffff
);
return
(
inl
(
addr
+
PCNET32_DWIO_RAP
)
&
0xffff
);
}
static
void
pcnet32_dwio_write_rap
(
unsigned
long
addr
,
u16
val
)
static
void
pcnet32_dwio_write_rap
(
unsigned
long
addr
,
u16
val
)
{
outl
(
val
,
addr
+
PCNET32_DWIO_RAP
);
outl
(
val
,
addr
+
PCNET32_DWIO_RAP
);
}
static
void
pcnet32_dwio_reset
(
unsigned
long
addr
)
static
void
pcnet32_dwio_reset
(
unsigned
long
addr
)
{
inl
(
addr
+
PCNET32_DWIO_RESET
);
inl
(
addr
+
PCNET32_DWIO_RESET
);
}
static
int
pcnet32_dwio_check
(
unsigned
long
addr
)
static
int
pcnet32_dwio_check
(
unsigned
long
addr
)
{
outl
(
88
,
addr
+
PCNET32_DWIO_RAP
);
return
((
inl
(
addr
+
PCNET32_DWIO_RAP
)
&
0xffff
)
==
88
);
outl
(
88
,
addr
+
PCNET32_DWIO_RAP
);
return
((
inl
(
addr
+
PCNET32_DWIO_RAP
)
&
0xffff
)
==
88
);
}
static
struct
pcnet32_access
pcnet32_dwio
=
{
...
...
@@ -550,7 +554,6 @@ static void pcnet32_poll_controller(struct net_device *dev)
}
#endif
static
int
pcnet32_get_settings
(
struct
net_device
*
dev
,
struct
ethtool_cmd
*
cmd
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
...
...
@@ -580,14 +583,15 @@ static int pcnet32_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return
r
;
}
static
void
pcnet32_get_drvinfo
(
struct
net_device
*
dev
,
struct
ethtool_drvinfo
*
info
)
static
void
pcnet32_get_drvinfo
(
struct
net_device
*
dev
,
struct
ethtool_drvinfo
*
info
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
strcpy
(
info
->
driver
,
DRV_NAME
);
strcpy
(
info
->
version
,
DRV_VERSION
);
strcpy
(
info
->
driver
,
DRV_NAME
);
strcpy
(
info
->
version
,
DRV_VERSION
);
if
(
lp
->
pci_dev
)
strcpy
(
info
->
bus_info
,
pci_name
(
lp
->
pci_dev
));
strcpy
(
info
->
bus_info
,
pci_name
(
lp
->
pci_dev
));
else
sprintf
(
info
->
bus_info
,
"VLB 0x%lx"
,
dev
->
base_addr
);
}
...
...
@@ -636,7 +640,8 @@ static int pcnet32_nway_reset(struct net_device *dev)
return
r
;
}
static
void
pcnet32_get_ringparam
(
struct
net_device
*
dev
,
struct
ethtool_ringparam
*
ering
)
static
void
pcnet32_get_ringparam
(
struct
net_device
*
dev
,
struct
ethtool_ringparam
*
ering
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
...
...
@@ -646,7 +651,8 @@ static void pcnet32_get_ringparam(struct net_device *dev, struct ethtool_ringpar
ering
->
rx_pending
=
lp
->
rx_ring_size
-
1
;
}
static
int
pcnet32_set_ringparam
(
struct
net_device
*
dev
,
struct
ethtool_ringparam
*
ering
)
static
int
pcnet32_set_ringparam
(
struct
net_device
*
dev
,
struct
ethtool_ringparam
*
ering
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
unsigned
long
flags
;
...
...
@@ -660,8 +666,10 @@ static int pcnet32_set_ringparam(struct net_device *dev, struct ethtool_ringpara
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
pcnet32_free_ring
(
dev
);
lp
->
tx_ring_size
=
min
(
ering
->
tx_pending
,
(
unsigned
int
)
TX_MAX_RING_SIZE
);
lp
->
rx_ring_size
=
min
(
ering
->
rx_pending
,
(
unsigned
int
)
RX_MAX_RING_SIZE
);
lp
->
tx_ring_size
=
min
(
ering
->
tx_pending
,
(
unsigned
int
)
TX_MAX_RING_SIZE
);
lp
->
rx_ring_size
=
min
(
ering
->
rx_pending
,
(
unsigned
int
)
RX_MAX_RING_SIZE
);
/* set the minimum ring size to 4, to allow the loopback test to work
* unchanged.
...
...
@@ -691,8 +699,9 @@ static int pcnet32_set_ringparam(struct net_device *dev, struct ethtool_ringpara
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
if
(
pcnet32_debug
&
NETIF_MSG_DRV
)
printk
(
KERN_INFO
PFX
"%s: Ring Param Settings: RX: %d, TX: %d
\n
"
,
dev
->
name
,
lp
->
rx_ring_size
,
lp
->
tx_ring_size
);
printk
(
KERN_INFO
PFX
"%s: Ring Param Settings: RX: %d, TX: %d
\n
"
,
dev
->
name
,
lp
->
rx_ring_size
,
lp
->
tx_ring_size
);
if
(
netif_running
(
dev
))
pcnet32_open
(
dev
);
...
...
@@ -700,7 +709,8 @@ static int pcnet32_set_ringparam(struct net_device *dev, struct ethtool_ringpara
return
0
;
}
static
void
pcnet32_get_strings
(
struct
net_device
*
dev
,
u32
stringset
,
u8
*
data
)
static
void
pcnet32_get_strings
(
struct
net_device
*
dev
,
u32
stringset
,
u8
*
data
)
{
memcpy
(
data
,
pcnet32_gstrings_test
,
sizeof
(
pcnet32_gstrings_test
));
}
...
...
@@ -711,7 +721,7 @@ static int pcnet32_self_test_count(struct net_device *dev)
}
static
void
pcnet32_ethtool_test
(
struct
net_device
*
dev
,
struct
ethtool_test
*
test
,
u64
*
data
)
struct
ethtool_test
*
test
,
u64
*
data
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
int
rc
;
...
...
@@ -720,15 +730,19 @@ static void pcnet32_ethtool_test(struct net_device *dev,
rc
=
pcnet32_loopback_test
(
dev
,
data
);
if
(
rc
)
{
if
(
netif_msg_hw
(
lp
))
printk
(
KERN_DEBUG
"%s: Loopback test failed.
\n
"
,
dev
->
name
);
printk
(
KERN_DEBUG
"%s: Loopback test failed.
\n
"
,
dev
->
name
);
test
->
flags
|=
ETH_TEST_FL_FAILED
;
}
else
if
(
netif_msg_hw
(
lp
))
printk
(
KERN_DEBUG
"%s: Loopback test passed.
\n
"
,
dev
->
name
);
printk
(
KERN_DEBUG
"%s: Loopback test passed.
\n
"
,
dev
->
name
);
}
else
if
(
netif_msg_hw
(
lp
))
printk
(
KERN_DEBUG
"%s: No tests to run (specify 'Offline' on ethtool)."
,
dev
->
name
);
printk
(
KERN_DEBUG
"%s: No tests to run (specify 'Offline' on ethtool)."
,
dev
->
name
);
}
/* end pcnet32_ethtool_test */
static
int
pcnet32_loopback_test
(
struct
net_device
*
dev
,
uint64_t
*
data1
)
static
int
pcnet32_loopback_test
(
struct
net_device
*
dev
,
uint64_t
*
data1
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
struct
pcnet32_access
*
a
=
&
lp
->
a
;
/* access to registers */
...
...
@@ -754,12 +768,13 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
/* Reset the PCNET32 */
lp
->
a
.
reset
(
ioaddr
);
lp
->
a
.
reset
(
ioaddr
);
/* switch pcnet32 to 32bit mode */
lp
->
a
.
write_bcr
(
ioaddr
,
20
,
2
);
lp
->
a
.
write_bcr
(
ioaddr
,
20
,
2
);
lp
->
init_block
.
mode
=
le16_to_cpu
((
lp
->
options
&
PCNET32_PORT_PORTSEL
)
<<
7
);
lp
->
init_block
.
mode
=
le16_to_cpu
((
lp
->
options
&
PCNET32_PORT_PORTSEL
)
<<
7
);
lp
->
init_block
.
filter
[
0
]
=
0
;
lp
->
init_block
.
filter
[
1
]
=
0
;
...
...
@@ -770,10 +785,11 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
/* Initialize Transmit buffers. */
size
=
data_len
+
15
;
for
(
x
=
0
;
x
<
numbuffs
;
x
++
)
{
for
(
x
=
0
;
x
<
numbuffs
;
x
++
)
{
if
(
!
(
skb
=
dev_alloc_skb
(
size
)))
{
if
(
netif_msg_hw
(
lp
))
printk
(
KERN_DEBUG
"%s: Cannot allocate skb at line: %d!
\n
"
,
printk
(
KERN_DEBUG
"%s: Cannot allocate skb at line: %d!
\n
"
,
dev
->
name
,
__LINE__
);
goto
clean_up
;
}
else
{
...
...
@@ -784,9 +800,9 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
lp
->
tx_ring
[
x
].
misc
=
0
;
/* put DA and SA into the skb */
for
(
i
=
0
;
i
<
6
;
i
++
)
for
(
i
=
0
;
i
<
6
;
i
++
)
*
packet
++
=
dev
->
dev_addr
[
i
];
for
(
i
=
0
;
i
<
6
;
i
++
)
for
(
i
=
0
;
i
<
6
;
i
++
)
*
packet
++
=
dev
->
dev_addr
[
i
];
/* type */
*
packet
++
=
0x08
;
...
...
@@ -794,12 +810,14 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
/* packet number */
*
packet
++
=
x
;
/* fill packet with data */
for
(
i
=
0
;
i
<
data_len
;
i
++
)
for
(
i
=
0
;
i
<
data_len
;
i
++
)
*
packet
++
=
i
;
lp
->
tx_dma_addr
[
x
]
=
pci_map_single
(
lp
->
pci_dev
,
skb
->
data
,
skb
->
len
,
PCI_DMA_TODEVICE
);
lp
->
tx_ring
[
x
].
base
=
(
u32
)
le32_to_cpu
(
lp
->
tx_dma_addr
[
x
]);
lp
->
tx_dma_addr
[
x
]
=
pci_map_single
(
lp
->
pci_dev
,
skb
->
data
,
skb
->
len
,
PCI_DMA_TODEVICE
);
lp
->
tx_ring
[
x
].
base
=
(
u32
)
le32_to_cpu
(
lp
->
tx_dma_addr
[
x
]);
wmb
();
/* Make sure owner changes after all others are visible */
lp
->
tx_ring
[
x
].
status
=
le16_to_cpu
(
status
);
}
...
...
@@ -809,13 +827,13 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
x
=
x
|
0x0002
;
a
->
write_bcr
(
ioaddr
,
32
,
x
);
lp
->
a
.
write_csr
(
ioaddr
,
15
,
0x0044
);
/* set int loopback in CSR15 */
lp
->
a
.
write_csr
(
ioaddr
,
15
,
0x0044
);
/* set int loopback in CSR15 */
teststatus
=
le16_to_cpu
(
0x8000
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0002
);
/* Set STRT bit */
/* Check status of descriptors */
for
(
x
=
0
;
x
<
numbuffs
;
x
++
)
{
for
(
x
=
0
;
x
<
numbuffs
;
x
++
)
{
ticks
=
0
;
rmb
();
while
((
lp
->
rx_ring
[
x
].
status
&
teststatus
)
&&
(
ticks
<
200
))
{
...
...
@@ -827,7 +845,8 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
}
if
(
ticks
==
200
)
{
if
(
netif_msg_hw
(
lp
))
printk
(
"%s: Desc %d failed to reset!
\n
"
,
dev
->
name
,
x
);
printk
(
"%s: Desc %d failed to reset!
\n
"
,
dev
->
name
,
x
);
break
;
}
}
...
...
@@ -837,11 +856,11 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
if
(
netif_msg_hw
(
lp
)
&&
netif_msg_pktdata
(
lp
))
{
printk
(
KERN_DEBUG
"%s: RX loopback packets:
\n
"
,
dev
->
name
);
for
(
x
=
0
;
x
<
numbuffs
;
x
++
)
{
for
(
x
=
0
;
x
<
numbuffs
;
x
++
)
{
printk
(
KERN_DEBUG
"%s: Packet %d:
\n
"
,
dev
->
name
,
x
);
skb
=
lp
->
rx_skbuff
[
x
];
for
(
i
=
0
;
i
<
size
;
i
++
)
{
printk
(
"%02x "
,
*
(
skb
->
data
+
i
));
for
(
i
=
0
;
i
<
size
;
i
++
)
{
printk
(
"%02x "
,
*
(
skb
->
data
+
i
));
}
printk
(
"
\n
"
);
}
...
...
@@ -849,14 +868,16 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
x
=
0
;
rc
=
0
;
while
(
x
<
numbuffs
&&
!
rc
)
{
while
(
x
<
numbuffs
&&
!
rc
)
{
skb
=
lp
->
rx_skbuff
[
x
];
packet
=
lp
->
tx_skbuff
[
x
]
->
data
;
for
(
i
=
0
;
i
<
size
;
i
++
)
{
if
(
*
(
skb
->
data
+
i
)
!=
packet
[
i
])
{
for
(
i
=
0
;
i
<
size
;
i
++
)
{
if
(
*
(
skb
->
data
+
i
)
!=
packet
[
i
])
{
if
(
netif_msg_hw
(
lp
))
printk
(
KERN_DEBUG
"%s: Error in compare! %2x - %02x %02x
\n
"
,
dev
->
name
,
i
,
*
(
skb
->
data
+
i
),
packet
[
i
]);
printk
(
KERN_DEBUG
"%s: Error in compare! %2x - %02x %02x
\n
"
,
dev
->
name
,
i
,
*
(
skb
->
data
+
i
),
packet
[
i
]);
rc
=
1
;
break
;
}
...
...
@@ -867,7 +888,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
*
data1
=
0
;
}
clean_up:
clean_up:
pcnet32_purge_tx_ring
(
dev
);
x
=
a
->
read_csr
(
ioaddr
,
15
)
&
0xFFFF
;
a
->
write_csr
(
ioaddr
,
15
,
(
x
&
~
0x0044
));
/* reset bits 6 and 2 */
...
...
@@ -881,10 +902,10 @@ clean_up:
if
(
netif_running
(
dev
))
{
pcnet32_open
(
dev
);
}
else
{
lp
->
a
.
write_bcr
(
ioaddr
,
20
,
4
);
/* return to 16bit mode */
lp
->
a
.
write_bcr
(
ioaddr
,
20
,
4
);
/* return to 16bit mode */
}
return
(
rc
);
return
(
rc
);
}
/* end pcnet32_loopback_test */
static
void
pcnet32_led_blink_callback
(
struct
net_device
*
dev
)
...
...
@@ -896,7 +917,7 @@ static void pcnet32_led_blink_callback(struct net_device *dev)
int
i
;
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
for
(
i
=
4
;
i
<
8
;
i
++
)
{
for
(
i
=
4
;
i
<
8
;
i
++
)
{
a
->
write_bcr
(
ioaddr
,
i
,
a
->
read_bcr
(
ioaddr
,
i
)
^
0x4000
);
}
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
...
...
@@ -914,30 +935,30 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data)
if
(
!
lp
->
blink_timer
.
function
)
{
init_timer
(
&
lp
->
blink_timer
);
lp
->
blink_timer
.
function
=
(
void
*
)
pcnet32_led_blink_callback
;
lp
->
blink_timer
.
data
=
(
unsigned
long
)
dev
;
lp
->
blink_timer
.
function
=
(
void
*
)
pcnet32_led_blink_callback
;
lp
->
blink_timer
.
data
=
(
unsigned
long
)
dev
;
}
/* Save the current value of the bcrs */
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
for
(
i
=
4
;
i
<
8
;
i
++
)
{
regs
[
i
-
4
]
=
a
->
read_bcr
(
ioaddr
,
i
);
for
(
i
=
4
;
i
<
8
;
i
++
)
{
regs
[
i
-
4
]
=
a
->
read_bcr
(
ioaddr
,
i
);
}
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
mod_timer
(
&
lp
->
blink_timer
,
jiffies
);
set_current_state
(
TASK_INTERRUPTIBLE
);
if
((
!
data
)
||
(
data
>
(
u32
)
(
MAX_SCHEDULE_TIMEOUT
/
HZ
)))
data
=
(
u32
)
(
MAX_SCHEDULE_TIMEOUT
/
HZ
);
if
((
!
data
)
||
(
data
>
(
u32
)
(
MAX_SCHEDULE_TIMEOUT
/
HZ
)))
data
=
(
u32
)
(
MAX_SCHEDULE_TIMEOUT
/
HZ
);
msleep_interruptible
(
data
*
1000
);
del_timer_sync
(
&
lp
->
blink_timer
);
/* Restore the original value of the bcrs */
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
for
(
i
=
4
;
i
<
8
;
i
++
)
{
a
->
write_bcr
(
ioaddr
,
i
,
regs
[
i
-
4
]);
for
(
i
=
4
;
i
<
8
;
i
++
)
{
a
->
write_bcr
(
ioaddr
,
i
,
regs
[
i
-
4
]);
}
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
...
...
@@ -951,7 +972,7 @@ static int pcnet32_get_regs_len(struct net_device *dev)
struct
pcnet32_private
*
lp
=
dev
->
priv
;
int
j
=
lp
->
phycount
*
PCNET32_REGS_PER_PHY
;
return
((
PCNET32_NUM_REGS
+
j
)
*
sizeof
(
u16
));
return
((
PCNET32_NUM_REGS
+
j
)
*
sizeof
(
u16
));
}
static
void
pcnet32_get_regs
(
struct
net_device
*
dev
,
struct
ethtool_regs
*
regs
,
...
...
@@ -981,7 +1002,8 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
ticks
++
;
if
(
ticks
>
200
)
{
if
(
netif_msg_hw
(
lp
))
printk
(
KERN_DEBUG
"%s: Error getting into suspend!
\n
"
,
printk
(
KERN_DEBUG
"%s: Error getting into suspend!
\n
"
,
dev
->
name
);
break
;
}
...
...
@@ -989,11 +1011,11 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
}
/* read address PROM */
for
(
i
=
0
;
i
<
16
;
i
+=
2
)
for
(
i
=
0
;
i
<
16
;
i
+=
2
)
*
buff
++
=
inw
(
ioaddr
+
i
);
/* read control and status registers */
for
(
i
=
0
;
i
<
90
;
i
++
)
{
for
(
i
=
0
;
i
<
90
;
i
++
)
{
*
buff
++
=
a
->
read_csr
(
ioaddr
,
i
);
}
...
...
@@ -1001,21 +1023,22 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
*
buff
++
=
a
->
read_csr
(
ioaddr
,
114
);
/* read bus configuration registers */
for
(
i
=
0
;
i
<
30
;
i
++
)
{
for
(
i
=
0
;
i
<
30
;
i
++
)
{
*
buff
++
=
a
->
read_bcr
(
ioaddr
,
i
);
}
*
buff
++
=
0
;
/* skip bcr30 so as not to hang 79C976 */
for
(
i
=
31
;
i
<
36
;
i
++
)
{
for
(
i
=
31
;
i
<
36
;
i
++
)
{
*
buff
++
=
a
->
read_bcr
(
ioaddr
,
i
);
}
/* read mii phy registers */
if
(
lp
->
mii
)
{
int
j
;
for
(
j
=
0
;
j
<
PCNET32_MAX_PHYS
;
j
++
)
{
for
(
j
=
0
;
j
<
PCNET32_MAX_PHYS
;
j
++
)
{
if
(
lp
->
phymask
&
(
1
<<
j
))
{
for
(
i
=
0
;
i
<
PCNET32_REGS_PER_PHY
;
i
++
)
{
lp
->
a
.
write_bcr
(
ioaddr
,
33
,
(
j
<<
5
)
|
i
);
for
(
i
=
0
;
i
<
PCNET32_REGS_PER_PHY
;
i
++
)
{
lp
->
a
.
write_bcr
(
ioaddr
,
33
,
(
j
<<
5
)
|
i
);
*
buff
++
=
lp
->
a
.
read_bcr
(
ioaddr
,
34
);
}
}
...
...
@@ -1055,16 +1078,17 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
/* only probes for non-PCI devices, the rest are handled by
* pci_register_driver via pcnet32_probe_pci */
static
void
__devinit
pcnet32_probe_vlbus
(
void
)
static
void
__devinit
pcnet32_probe_vlbus
(
void
)
{
unsigned
int
*
port
,
ioaddr
;
/* search for PCnet32 VLB cards at known addresses */
for
(
port
=
pcnet32_portlist
;
(
ioaddr
=
*
port
);
port
++
)
{
if
(
request_region
(
ioaddr
,
PCNET32_TOTAL_SIZE
,
"pcnet32_probe_vlbus"
))
{
if
(
request_region
(
ioaddr
,
PCNET32_TOTAL_SIZE
,
"pcnet32_probe_vlbus"
))
{
/* check if there is really a pcnet chip on that ioaddr */
if
((
inb
(
ioaddr
+
14
)
==
0x57
)
&&
(
inb
(
ioaddr
+
15
)
==
0x57
))
{
if
((
inb
(
ioaddr
+
14
)
==
0x57
)
&&
(
inb
(
ioaddr
+
15
)
==
0x57
))
{
pcnet32_probe1
(
ioaddr
,
0
,
NULL
);
}
else
{
release_region
(
ioaddr
,
PCNET32_TOTAL_SIZE
);
...
...
@@ -1073,7 +1097,6 @@ pcnet32_probe_vlbus(void)
}
}
static
int
__devinit
pcnet32_probe_pci
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
{
...
...
@@ -1083,26 +1106,31 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent)
err
=
pci_enable_device
(
pdev
);
if
(
err
<
0
)
{
if
(
pcnet32_debug
&
NETIF_MSG_PROBE
)
printk
(
KERN_ERR
PFX
"failed to enable device -- err=%d
\n
"
,
err
);
printk
(
KERN_ERR
PFX
"failed to enable device -- err=%d
\n
"
,
err
);
return
err
;
}
pci_set_master
(
pdev
);
ioaddr
=
pci_resource_start
(
pdev
,
0
);
ioaddr
=
pci_resource_start
(
pdev
,
0
);
if
(
!
ioaddr
)
{
if
(
pcnet32_debug
&
NETIF_MSG_PROBE
)
printk
(
KERN_ERR
PFX
"card has no PCI IO resources, aborting
\n
"
);
printk
(
KERN_ERR
PFX
"card has no PCI IO resources, aborting
\n
"
);
return
-
ENODEV
;
}
if
(
!
pci_dma_supported
(
pdev
,
PCNET32_DMA_MASK
))
{
if
(
pcnet32_debug
&
NETIF_MSG_PROBE
)
printk
(
KERN_ERR
PFX
"architecture does not support 32bit PCI busmaster DMA
\n
"
);
printk
(
KERN_ERR
PFX
"architecture does not support 32bit PCI busmaster DMA
\n
"
);
return
-
ENODEV
;
}
if
(
request_region
(
ioaddr
,
PCNET32_TOTAL_SIZE
,
"pcnet32_probe_pci"
)
==
NULL
)
{
if
(
request_region
(
ioaddr
,
PCNET32_TOTAL_SIZE
,
"pcnet32_probe_pci"
)
==
NULL
)
{
if
(
pcnet32_debug
&
NETIF_MSG_PROBE
)
printk
(
KERN_ERR
PFX
"io address range already allocated
\n
"
);
printk
(
KERN_ERR
PFX
"io address range already allocated
\n
"
);
return
-
EBUSY
;
}
...
...
@@ -1113,7 +1141,6 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent)
return
err
;
}
/* pcnet32_probe1
* Called from both pcnet32_probe_vlbus and pcnet_probe_pci.
* pdev will be NULL when called from pcnet32_probe_vlbus.
...
...
@@ -1140,15 +1167,18 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
a
=
&
pcnet32_wio
;
}
else
{
pcnet32_dwio_reset
(
ioaddr
);
if
(
pcnet32_dwio_read_csr
(
ioaddr
,
0
)
==
4
&&
pcnet32_dwio_check
(
ioaddr
))
{
if
(
pcnet32_dwio_read_csr
(
ioaddr
,
0
)
==
4
&&
pcnet32_dwio_check
(
ioaddr
))
{
a
=
&
pcnet32_dwio
;
}
else
goto
err_release_region
;
}
chip_version
=
a
->
read_csr
(
ioaddr
,
88
)
|
(
a
->
read_csr
(
ioaddr
,
89
)
<<
16
);
chip_version
=
a
->
read_csr
(
ioaddr
,
88
)
|
(
a
->
read_csr
(
ioaddr
,
89
)
<<
16
);
if
((
pcnet32_debug
&
NETIF_MSG_PROBE
)
&&
(
pcnet32_debug
&
NETIF_MSG_HW
))
printk
(
KERN_INFO
" PCnet chip version is %#x.
\n
"
,
chip_version
);
printk
(
KERN_INFO
" PCnet chip version is %#x.
\n
"
,
chip_version
);
if
((
chip_version
&
0xfff
)
!=
0x003
)
{
if
(
pcnet32_debug
&
NETIF_MSG_PROBE
)
printk
(
KERN_INFO
PFX
"Unsupported chip version.
\n
"
);
...
...
@@ -1175,15 +1205,20 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
break
;
case
0x2623
:
chipname
=
"PCnet/FAST 79C971"
;
/* PCI */
fdx
=
1
;
mii
=
1
;
fset
=
1
;
fdx
=
1
;
mii
=
1
;
fset
=
1
;
break
;
case
0x2624
:
chipname
=
"PCnet/FAST+ 79C972"
;
/* PCI */
fdx
=
1
;
mii
=
1
;
fset
=
1
;
fdx
=
1
;
mii
=
1
;
fset
=
1
;
break
;
case
0x2625
:
chipname
=
"PCnet/FAST III 79C973"
;
/* PCI */
fdx
=
1
;
mii
=
1
;
fdx
=
1
;
mii
=
1
;
break
;
case
0x2626
:
chipname
=
"PCnet/Home 79C978"
;
/* PCI */
...
...
@@ -1205,15 +1240,18 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
break
;
case
0x2627
:
chipname
=
"PCnet/FAST III 79C975"
;
/* PCI */
fdx
=
1
;
mii
=
1
;
fdx
=
1
;
mii
=
1
;
break
;
case
0x2628
:
chipname
=
"PCnet/PRO 79C976"
;
fdx
=
1
;
mii
=
1
;
fdx
=
1
;
mii
=
1
;
break
;
default:
if
(
pcnet32_debug
&
NETIF_MSG_PROBE
)
printk
(
KERN_INFO
PFX
"PCnet version %#x, no PCnet32 chip.
\n
"
,
printk
(
KERN_INFO
PFX
"PCnet version %#x, no PCnet32 chip.
\n
"
,
chip_version
);
goto
err_release_region
;
}
...
...
@@ -1228,7 +1266,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
if
(
fset
)
{
a
->
write_bcr
(
ioaddr
,
18
,
(
a
->
read_bcr
(
ioaddr
,
18
)
|
0x0860
));
a
->
write_csr
(
ioaddr
,
80
,
(
a
->
read_csr
(
ioaddr
,
80
)
&
0x0C00
)
|
0x0c00
);
a
->
write_csr
(
ioaddr
,
80
,
(
a
->
read_csr
(
ioaddr
,
80
)
&
0x0C00
)
|
0x0c00
);
dxsuflo
=
1
;
}
...
...
@@ -1253,10 +1292,10 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
*/
for
(
i
=
0
;
i
<
3
;
i
++
)
{
unsigned
int
val
;
val
=
a
->
read_csr
(
ioaddr
,
i
+
12
)
&
0x0ffff
;
val
=
a
->
read_csr
(
ioaddr
,
i
+
12
)
&
0x0ffff
;
/* There may be endianness issues here. */
dev
->
dev_addr
[
2
*
i
]
=
val
&
0x0ff
;
dev
->
dev_addr
[
2
*
i
+
1
]
=
(
val
>>
8
)
&
0x0ff
;
dev
->
dev_addr
[
2
*
i
]
=
val
&
0x0ff
;
dev
->
dev_addr
[
2
*
i
+
1
]
=
(
val
>>
8
)
&
0x0ff
;
}
/* read PROM address and compare with CSR address */
...
...
@@ -1268,7 +1307,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
if
(
is_valid_ether_addr
(
promaddr
))
{
if
(
pcnet32_debug
&
NETIF_MSG_PROBE
)
{
printk
(
" warning: CSR address invalid,
\n
"
);
printk
(
KERN_INFO
" using instead PROM address of"
);
printk
(
KERN_INFO
" using instead PROM address of"
);
}
memcpy
(
dev
->
dev_addr
,
promaddr
,
6
);
}
...
...
@@ -1286,33 +1326,48 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
/* Version 0x2623 and 0x2624 */
if
(((
chip_version
+
1
)
&
0xfffe
)
==
0x2624
)
{
i
=
a
->
read_csr
(
ioaddr
,
80
)
&
0x0C00
;
/* Check tx_start_pt */
printk
(
"
\n
"
KERN_INFO
" tx_start_pt(0x%04x):"
,
i
);
switch
(
i
>>
10
)
{
case
0
:
printk
(
" 20 bytes,"
);
break
;
case
1
:
printk
(
" 64 bytes,"
);
break
;
case
2
:
printk
(
" 128 bytes,"
);
break
;
case
3
:
printk
(
"~220 bytes,"
);
break
;
printk
(
"
\n
"
KERN_INFO
" tx_start_pt(0x%04x):"
,
i
);
switch
(
i
>>
10
)
{
case
0
:
printk
(
" 20 bytes,"
);
break
;
case
1
:
printk
(
" 64 bytes,"
);
break
;
case
2
:
printk
(
" 128 bytes,"
);
break
;
case
3
:
printk
(
"~220 bytes,"
);
break
;
}
i
=
a
->
read_bcr
(
ioaddr
,
18
);
/* Check Burst/Bus control */
printk
(
" BCR18(%x):"
,
i
&
0xffff
);
if
(
i
&
(
1
<<
5
))
printk
(
"BurstWrEn "
);
if
(
i
&
(
1
<<
6
))
printk
(
"BurstRdEn "
);
if
(
i
&
(
1
<<
7
))
printk
(
"DWordIO "
);
if
(
i
&
(
1
<<
11
))
printk
(
"NoUFlow "
);
printk
(
" BCR18(%x):"
,
i
&
0xffff
);
if
(
i
&
(
1
<<
5
))
printk
(
"BurstWrEn "
);
if
(
i
&
(
1
<<
6
))
printk
(
"BurstRdEn "
);
if
(
i
&
(
1
<<
7
))
printk
(
"DWordIO "
);
if
(
i
&
(
1
<<
11
))
printk
(
"NoUFlow "
);
i
=
a
->
read_bcr
(
ioaddr
,
25
);
printk
(
"
\n
"
KERN_INFO
" SRAMSIZE=0x%04x,"
,
i
<<
8
);
printk
(
"
\n
"
KERN_INFO
" SRAMSIZE=0x%04x,"
,
i
<<
8
);
i
=
a
->
read_bcr
(
ioaddr
,
26
);
printk
(
" SRAM_BND=0x%04x,"
,
i
<<
8
);
printk
(
" SRAM_BND=0x%04x,"
,
i
<<
8
);
i
=
a
->
read_bcr
(
ioaddr
,
27
);
if
(
i
&
(
1
<<
14
))
printk
(
"LowLatRx"
);
if
(
i
&
(
1
<<
14
))
printk
(
"LowLatRx"
);
}
}
dev
->
base_addr
=
ioaddr
;
/* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */
if
((
lp
=
pci_alloc_consistent
(
pdev
,
sizeof
(
*
lp
),
&
lp_dma_addr
))
==
NULL
)
{
if
((
lp
=
pci_alloc_consistent
(
pdev
,
sizeof
(
*
lp
),
&
lp_dma_addr
))
==
NULL
)
{
if
(
pcnet32_debug
&
NETIF_MSG_PROBE
)
printk
(
KERN_ERR
PFX
"Consistent memory allocation failed.
\n
"
);
printk
(
KERN_ERR
PFX
"Consistent memory allocation failed.
\n
"
);
ret
=
-
ENOMEM
;
goto
err_free_netdev
;
}
...
...
@@ -1340,7 +1395,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
lp
->
dxsuflo
=
dxsuflo
;
lp
->
mii
=
mii
;
lp
->
msg_enable
=
pcnet32_debug
;
if
((
cards_found
>=
MAX_UNITS
)
||
(
options
[
cards_found
]
>
sizeof
(
options_mapping
)))
if
((
cards_found
>=
MAX_UNITS
)
||
(
options
[
cards_found
]
>
sizeof
(
options_mapping
)))
lp
->
options
=
PCNET32_PORT_ASEL
;
else
lp
->
options
=
options_mapping
[
options
[
cards_found
]];
...
...
@@ -1349,7 +1405,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
lp
->
mii_if
.
mdio_write
=
mdio_write
;
if
(
fdx
&&
!
(
lp
->
options
&
PCNET32_PORT_ASEL
)
&&
((
cards_found
>=
MAX_UNITS
)
||
full_duplex
[
cards_found
]))
((
cards_found
>=
MAX_UNITS
)
||
full_duplex
[
cards_found
]))
lp
->
options
|=
PCNET32_PORT_FD
;
if
(
!
a
)
{
...
...
@@ -1371,13 +1427,14 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
lp
->
options
=
PCNET32_PORT_FD
|
PCNET32_PORT_GPSI
;
lp
->
init_block
.
mode
=
le16_to_cpu
(
0x0003
);
/* Disable Rx and Tx. */
lp
->
init_block
.
tlen_rlen
=
le16_to_cpu
(
lp
->
tx_len_bits
|
lp
->
rx_len_bits
);
lp
->
init_block
.
tlen_rlen
=
le16_to_cpu
(
lp
->
tx_len_bits
|
lp
->
rx_len_bits
);
for
(
i
=
0
;
i
<
6
;
i
++
)
lp
->
init_block
.
phys_addr
[
i
]
=
dev
->
dev_addr
[
i
];
lp
->
init_block
.
filter
[
0
]
=
0x00000000
;
lp
->
init_block
.
filter
[
1
]
=
0x00000000
;
lp
->
init_block
.
rx_ring
=
(
u32
)
le32_to_cpu
(
lp
->
rx_ring_dma_addr
);
lp
->
init_block
.
tx_ring
=
(
u32
)
le32_to_cpu
(
lp
->
tx_ring_dma_addr
);
lp
->
init_block
.
rx_ring
=
(
u32
)
le32_to_cpu
(
lp
->
rx_ring_dma_addr
);
lp
->
init_block
.
tx_ring
=
(
u32
)
le32_to_cpu
(
lp
->
tx_ring_dma_addr
);
/* switch pcnet32 to 32bit mode */
a
->
write_bcr
(
ioaddr
,
20
,
2
);
...
...
@@ -1400,10 +1457,10 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
* boards will work.
*/
/* Trigger an initialization just for the interrupt. */
a
->
write_csr
(
ioaddr
,
0
,
0x41
);
mdelay
(
1
);
a
->
write_csr
(
ioaddr
,
0
,
0x41
);
mdelay
(
1
);
dev
->
irq
=
probe_irq_off
(
irq_mask
);
dev
->
irq
=
probe_irq_off
(
irq_mask
);
if
(
!
dev
->
irq
)
{
if
(
pcnet32_debug
&
NETIF_MSG_PROBE
)
printk
(
", failed to detect IRQ line.
\n
"
);
...
...
@@ -1418,9 +1475,9 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
if
(
lp
->
mii
)
{
/* lp->phycount and lp->phymask are set to 0 by memset above */
lp
->
mii_if
.
phy_id
=
((
lp
->
a
.
read_bcr
(
ioaddr
,
33
))
>>
5
)
&
0x1f
;
lp
->
mii_if
.
phy_id
=
((
lp
->
a
.
read_bcr
(
ioaddr
,
33
))
>>
5
)
&
0x1f
;
/* scan for PHYs */
for
(
i
=
0
;
i
<
PCNET32_MAX_PHYS
;
i
++
)
{
for
(
i
=
0
;
i
<
PCNET32_MAX_PHYS
;
i
++
)
{
unsigned
short
id1
,
id2
;
id1
=
mdio_read
(
dev
,
i
,
MII_PHYSID1
);
...
...
@@ -1435,7 +1492,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
lp
->
phymask
|=
(
1
<<
i
);
lp
->
mii_if
.
phy_id
=
i
;
if
(
pcnet32_debug
&
NETIF_MSG_PROBE
)
printk
(
KERN_INFO
PFX
"Found PHY %04x:%04x at address %d.
\n
"
,
printk
(
KERN_INFO
PFX
"Found PHY %04x:%04x at address %d.
\n
"
,
id1
,
id2
,
i
);
}
lp
->
a
.
write_bcr
(
ioaddr
,
33
,
(
lp
->
mii_if
.
phy_id
)
<<
5
);
...
...
@@ -1444,9 +1502,9 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
}
}
init_timer
(
&
lp
->
watchdog_timer
);
lp
->
watchdog_timer
.
data
=
(
unsigned
long
)
dev
;
lp
->
watchdog_timer
.
function
=
(
void
*
)
&
pcnet32_watchdog
;
init_timer
(
&
lp
->
watchdog_timer
);
lp
->
watchdog_timer
.
data
=
(
unsigned
long
)
dev
;
lp
->
watchdog_timer
.
function
=
(
void
*
)
&
pcnet32_watchdog
;
/* The PCNET32-specific entries in the device structure. */
dev
->
open
=
&
pcnet32_open
;
...
...
@@ -1457,7 +1515,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
dev
->
do_ioctl
=
&
pcnet32_ioctl
;
dev
->
ethtool_ops
=
&
pcnet32_ethtool_ops
;
dev
->
tx_timeout
=
pcnet32_tx_timeout
;
dev
->
watchdog_timeo
=
(
5
*
HZ
);
dev
->
watchdog_timeo
=
(
5
*
HZ
);
#ifdef CONFIG_NET_POLL_CONTROLLER
dev
->
poll_controller
=
pcnet32_poll_controller
;
...
...
@@ -1483,39 +1541,42 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
return
0
;
err_free_ring:
err_free_ring:
pcnet32_free_ring
(
dev
);
err_free_consistent:
err_free_consistent:
pci_free_consistent
(
lp
->
pci_dev
,
sizeof
(
*
lp
),
lp
,
lp
->
dma_addr
);
err_free_netdev:
err_free_netdev:
free_netdev
(
dev
);
err_release_region:
err_release_region:
release_region
(
ioaddr
,
PCNET32_TOTAL_SIZE
);
return
ret
;
}
/* if any allocation fails, caller must also call pcnet32_free_ring */
static
int
pcnet32_alloc_ring
(
struct
net_device
*
dev
,
char
*
name
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
lp
->
tx_ring
=
pci_alloc_consistent
(
lp
->
pci_dev
,
sizeof
(
struct
pcnet32_tx_head
)
*
lp
->
tx_ring_size
,
sizeof
(
struct
pcnet32_tx_head
)
*
lp
->
tx_ring_size
,
&
lp
->
tx_ring_dma_addr
);
if
(
lp
->
tx_ring
==
NULL
)
{
if
(
pcnet32_debug
&
NETIF_MSG_DRV
)
printk
(
"
\n
"
KERN_ERR
PFX
"%s: Consistent memory allocation failed.
\n
"
,
printk
(
"
\n
"
KERN_ERR
PFX
"%s: Consistent memory allocation failed.
\n
"
,
name
);
return
-
ENOMEM
;
}
lp
->
rx_ring
=
pci_alloc_consistent
(
lp
->
pci_dev
,
sizeof
(
struct
pcnet32_rx_head
)
*
lp
->
rx_ring_size
,
sizeof
(
struct
pcnet32_rx_head
)
*
lp
->
rx_ring_size
,
&
lp
->
rx_ring_dma_addr
);
if
(
lp
->
rx_ring
==
NULL
)
{
if
(
pcnet32_debug
&
NETIF_MSG_DRV
)
printk
(
"
\n
"
KERN_ERR
PFX
"%s: Consistent memory allocation failed.
\n
"
,
printk
(
"
\n
"
KERN_ERR
PFX
"%s: Consistent memory allocation failed.
\n
"
,
name
);
return
-
ENOMEM
;
}
...
...
@@ -1524,7 +1585,8 @@ static int pcnet32_alloc_ring(struct net_device *dev, char *name)
GFP_ATOMIC
);
if
(
!
lp
->
tx_dma_addr
)
{
if
(
pcnet32_debug
&
NETIF_MSG_DRV
)
printk
(
"
\n
"
KERN_ERR
PFX
"%s: Memory allocation failed.
\n
"
,
name
);
printk
(
"
\n
"
KERN_ERR
PFX
"%s: Memory allocation failed.
\n
"
,
name
);
return
-
ENOMEM
;
}
memset
(
lp
->
tx_dma_addr
,
0
,
sizeof
(
dma_addr_t
)
*
lp
->
tx_ring_size
);
...
...
@@ -1533,7 +1595,8 @@ static int pcnet32_alloc_ring(struct net_device *dev, char *name)
GFP_ATOMIC
);
if
(
!
lp
->
rx_dma_addr
)
{
if
(
pcnet32_debug
&
NETIF_MSG_DRV
)
printk
(
"
\n
"
KERN_ERR
PFX
"%s: Memory allocation failed.
\n
"
,
name
);
printk
(
"
\n
"
KERN_ERR
PFX
"%s: Memory allocation failed.
\n
"
,
name
);
return
-
ENOMEM
;
}
memset
(
lp
->
rx_dma_addr
,
0
,
sizeof
(
dma_addr_t
)
*
lp
->
rx_ring_size
);
...
...
@@ -1542,7 +1605,8 @@ static int pcnet32_alloc_ring(struct net_device *dev, char *name)
GFP_ATOMIC
);
if
(
!
lp
->
tx_skbuff
)
{
if
(
pcnet32_debug
&
NETIF_MSG_DRV
)
printk
(
"
\n
"
KERN_ERR
PFX
"%s: Memory allocation failed.
\n
"
,
name
);
printk
(
"
\n
"
KERN_ERR
PFX
"%s: Memory allocation failed.
\n
"
,
name
);
return
-
ENOMEM
;
}
memset
(
lp
->
tx_skbuff
,
0
,
sizeof
(
struct
sk_buff
*
)
*
lp
->
tx_ring_size
);
...
...
@@ -1551,7 +1615,8 @@ static int pcnet32_alloc_ring(struct net_device *dev, char *name)
GFP_ATOMIC
);
if
(
!
lp
->
rx_skbuff
)
{
if
(
pcnet32_debug
&
NETIF_MSG_DRV
)
printk
(
"
\n
"
KERN_ERR
PFX
"%s: Memory allocation failed.
\n
"
,
name
);
printk
(
"
\n
"
KERN_ERR
PFX
"%s: Memory allocation failed.
\n
"
,
name
);
return
-
ENOMEM
;
}
memset
(
lp
->
rx_skbuff
,
0
,
sizeof
(
struct
sk_buff
*
)
*
lp
->
rx_ring_size
);
...
...
@@ -1559,7 +1624,6 @@ static int pcnet32_alloc_ring(struct net_device *dev, char *name)
return
0
;
}
static
void
pcnet32_free_ring
(
struct
net_device
*
dev
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
...
...
@@ -1577,21 +1641,23 @@ static void pcnet32_free_ring(struct net_device *dev)
lp
->
rx_dma_addr
=
NULL
;
if
(
lp
->
tx_ring
)
{
pci_free_consistent
(
lp
->
pci_dev
,
sizeof
(
struct
pcnet32_tx_head
)
*
lp
->
tx_ring_size
,
lp
->
tx_ring
,
lp
->
tx_ring_dma_addr
);
pci_free_consistent
(
lp
->
pci_dev
,
sizeof
(
struct
pcnet32_tx_head
)
*
lp
->
tx_ring_size
,
lp
->
tx_ring
,
lp
->
tx_ring_dma_addr
);
lp
->
tx_ring
=
NULL
;
}
if
(
lp
->
rx_ring
)
{
pci_free_consistent
(
lp
->
pci_dev
,
sizeof
(
struct
pcnet32_rx_head
)
*
lp
->
rx_ring_size
,
lp
->
rx_ring
,
lp
->
rx_ring_dma_addr
);
pci_free_consistent
(
lp
->
pci_dev
,
sizeof
(
struct
pcnet32_rx_head
)
*
lp
->
rx_ring_size
,
lp
->
rx_ring
,
lp
->
rx_ring_dma_addr
);
lp
->
rx_ring
=
NULL
;
}
}
static
int
pcnet32_open
(
struct
net_device
*
dev
)
static
int
pcnet32_open
(
struct
net_device
*
dev
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
unsigned
long
ioaddr
=
dev
->
base_addr
;
...
...
@@ -1601,7 +1667,8 @@ pcnet32_open(struct net_device *dev)
unsigned
long
flags
;
if
(
request_irq
(
dev
->
irq
,
&
pcnet32_interrupt
,
lp
->
shared_irq
?
SA_SHIRQ
:
0
,
dev
->
name
,
(
void
*
)
dev
))
{
lp
->
shared_irq
?
SA_SHIRQ
:
0
,
dev
->
name
,
(
void
*
)
dev
))
{
return
-
EAGAIN
;
}
...
...
@@ -1613,27 +1680,28 @@ pcnet32_open(struct net_device *dev)
}
/* Reset the PCNET32 */
lp
->
a
.
reset
(
ioaddr
);
lp
->
a
.
reset
(
ioaddr
);
/* switch pcnet32 to 32bit mode */
lp
->
a
.
write_bcr
(
ioaddr
,
20
,
2
);
lp
->
a
.
write_bcr
(
ioaddr
,
20
,
2
);
if
(
netif_msg_ifup
(
lp
))
printk
(
KERN_DEBUG
"%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.
\n
"
,
dev
->
name
,
dev
->
irq
,
(
u32
)
(
lp
->
tx_ring_dma_addr
),
printk
(
KERN_DEBUG
"%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.
\n
"
,
dev
->
name
,
dev
->
irq
,
(
u32
)
(
lp
->
tx_ring_dma_addr
),
(
u32
)
(
lp
->
rx_ring_dma_addr
),
(
u32
)
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
init_block
)));
(
u32
)
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
init_block
)));
/* set/reset autoselect bit */
val
=
lp
->
a
.
read_bcr
(
ioaddr
,
2
)
&
~
2
;
val
=
lp
->
a
.
read_bcr
(
ioaddr
,
2
)
&
~
2
;
if
(
lp
->
options
&
PCNET32_PORT_ASEL
)
val
|=
2
;
lp
->
a
.
write_bcr
(
ioaddr
,
2
,
val
);
lp
->
a
.
write_bcr
(
ioaddr
,
2
,
val
);
/* handle full duplex setting */
if
(
lp
->
mii_if
.
full_duplex
)
{
val
=
lp
->
a
.
read_bcr
(
ioaddr
,
9
)
&
~
3
;
val
=
lp
->
a
.
read_bcr
(
ioaddr
,
9
)
&
~
3
;
if
(
lp
->
options
&
PCNET32_PORT_FD
)
{
val
|=
1
;
if
(
lp
->
options
==
(
PCNET32_PORT_FD
|
PCNET32_PORT_AUI
))
...
...
@@ -1641,18 +1709,19 @@ pcnet32_open(struct net_device *dev)
}
else
if
(
lp
->
options
&
PCNET32_PORT_ASEL
)
{
/* workaround of xSeries250, turn on for 79C975 only */
i
=
((
lp
->
a
.
read_csr
(
ioaddr
,
88
)
|
(
lp
->
a
.
read_csr
(
ioaddr
,
89
)
<<
16
))
>>
12
)
&
0xffff
;
(
lp
->
a
.
read_csr
(
ioaddr
,
89
)
<<
16
))
>>
12
)
&
0xffff
;
if
(
i
==
0x2627
)
val
|=
3
;
}
lp
->
a
.
write_bcr
(
ioaddr
,
9
,
val
);
lp
->
a
.
write_bcr
(
ioaddr
,
9
,
val
);
}
/* set/reset GPSI bit in test register */
val
=
lp
->
a
.
read_csr
(
ioaddr
,
124
)
&
~
0x10
;
val
=
lp
->
a
.
read_csr
(
ioaddr
,
124
)
&
~
0x10
;
if
((
lp
->
options
&
PCNET32_PORT_PORTSEL
)
==
PCNET32_PORT_GPSI
)
val
|=
0x10
;
lp
->
a
.
write_csr
(
ioaddr
,
124
,
val
);
lp
->
a
.
write_csr
(
ioaddr
,
124
,
val
);
/* Allied Telesyn AT 2700/2701 FX are 100Mbit only and do not negotiate */
if
(
lp
->
pci_dev
->
subsystem_vendor
==
PCI_VENDOR_ID_AT
&&
...
...
@@ -1661,7 +1730,8 @@ pcnet32_open(struct net_device *dev)
if
(
lp
->
options
&
PCNET32_PORT_ASEL
)
{
lp
->
options
=
PCNET32_PORT_FD
|
PCNET32_PORT_100
;
if
(
netif_msg_link
(
lp
))
printk
(
KERN_DEBUG
"%s: Setting 100Mb-Full Duplex.
\n
"
,
printk
(
KERN_DEBUG
"%s: Setting 100Mb-Full Duplex.
\n
"
,
dev
->
name
);
}
}
...
...
@@ -1680,11 +1750,12 @@ pcnet32_open(struct net_device *dev)
val
|=
0x10
;
if
(
lp
->
options
&
PCNET32_PORT_100
)
val
|=
0x08
;
lp
->
a
.
write_bcr
(
ioaddr
,
32
,
val
);
lp
->
a
.
write_bcr
(
ioaddr
,
32
,
val
);
}
else
{
if
(
lp
->
options
&
PCNET32_PORT_ASEL
)
{
lp
->
a
.
write_bcr
(
ioaddr
,
32
,
lp
->
a
.
read_bcr
(
ioaddr
,
32
)
|
0x0080
);
lp
->
a
.
read_bcr
(
ioaddr
,
32
)
|
0x0080
);
/* enable auto negotiate, setup, disable fd */
val
=
lp
->
a
.
read_bcr
(
ioaddr
,
32
)
&
~
0x98
;
val
|=
0x20
;
...
...
@@ -1711,7 +1782,9 @@ pcnet32_open(struct net_device *dev)
ecmd
.
port
=
PORT_MII
;
ecmd
.
transceiver
=
XCVR_INTERNAL
;
ecmd
.
autoneg
=
AUTONEG_DISABLE
;
ecmd
.
speed
=
lp
->
options
&
PCNET32_PORT_100
?
SPEED_100
:
SPEED_10
;
ecmd
.
speed
=
lp
->
options
&
PCNET32_PORT_100
?
SPEED_100
:
SPEED_10
;
bcr9
=
lp
->
a
.
read_bcr
(
ioaddr
,
9
);
if
(
lp
->
options
&
PCNET32_PORT_FD
)
{
...
...
@@ -1724,15 +1797,17 @@ pcnet32_open(struct net_device *dev)
lp
->
a
.
write_bcr
(
ioaddr
,
9
,
bcr9
);
}
for
(
i
=
0
;
i
<
PCNET32_MAX_PHYS
;
i
++
)
{
for
(
i
=
0
;
i
<
PCNET32_MAX_PHYS
;
i
++
)
{
if
(
lp
->
phymask
&
(
1
<<
i
))
{
/* isolate all but the first PHY */
bmcr
=
mdio_read
(
dev
,
i
,
MII_BMCR
);
if
(
first_phy
==
-
1
)
{
first_phy
=
i
;
mdio_write
(
dev
,
i
,
MII_BMCR
,
bmcr
&
~
BMCR_ISOLATE
);
mdio_write
(
dev
,
i
,
MII_BMCR
,
bmcr
&
~
BMCR_ISOLATE
);
}
else
{
mdio_write
(
dev
,
i
,
MII_BMCR
,
bmcr
|
BMCR_ISOLATE
);
mdio_write
(
dev
,
i
,
MII_BMCR
,
bmcr
|
BMCR_ISOLATE
);
}
/* use mii_ethtool_sset to setup PHY */
lp
->
mii_if
.
phy_id
=
i
;
...
...
@@ -1746,18 +1821,20 @@ pcnet32_open(struct net_device *dev)
}
lp
->
mii_if
.
phy_id
=
first_phy
;
if
(
netif_msg_link
(
lp
))
printk
(
KERN_INFO
"%s: Using PHY number %d.
\n
"
,
dev
->
name
,
first_phy
);
printk
(
KERN_INFO
"%s: Using PHY number %d.
\n
"
,
dev
->
name
,
first_phy
);
}
#ifdef DO_DXSUFLO
if
(
lp
->
dxsuflo
)
{
/* Disable transmit stop on underflow */
val
=
lp
->
a
.
read_csr
(
ioaddr
,
3
);
val
=
lp
->
a
.
read_csr
(
ioaddr
,
3
);
val
|=
0x40
;
lp
->
a
.
write_csr
(
ioaddr
,
3
,
val
);
lp
->
a
.
write_csr
(
ioaddr
,
3
,
val
);
}
#endif
lp
->
init_block
.
mode
=
le16_to_cpu
((
lp
->
options
&
PCNET32_PORT_PORTSEL
)
<<
7
);
lp
->
init_block
.
mode
=
le16_to_cpu
((
lp
->
options
&
PCNET32_PORT_PORTSEL
)
<<
7
);
pcnet32_load_multicast
(
dev
);
if
(
pcnet32_init_ring
(
dev
))
{
...
...
@@ -1766,33 +1843,37 @@ pcnet32_open(struct net_device *dev)
}
/* Re-initialize the PCNET32, and start it when done. */
lp
->
a
.
write_csr
(
ioaddr
,
1
,
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
init_block
))
&
0xffff
);
lp
->
a
.
write_csr
(
ioaddr
,
2
,
(
lp
->
dma_addr
+
lp
->
a
.
write_csr
(
ioaddr
,
1
,
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
init_block
))
&
0xffff
);
lp
->
a
.
write_csr
(
ioaddr
,
2
,
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
init_block
))
>>
16
);
lp
->
a
.
write_csr
(
ioaddr
,
4
,
0x0915
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0001
);
lp
->
a
.
write_csr
(
ioaddr
,
4
,
0x0915
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0001
);
netif_start_queue
(
dev
);
/* Print the link status and start the watchdog */
pcnet32_check_media
(
dev
,
1
);
mod_timer
(
&
(
lp
->
watchdog_timer
),
PCNET32_WATCHDOG_TIMEOUT
);
pcnet32_check_media
(
dev
,
1
);
mod_timer
(
&
(
lp
->
watchdog_timer
),
PCNET32_WATCHDOG_TIMEOUT
);
i
=
0
;
while
(
i
++
<
100
)
if
(
lp
->
a
.
read_csr
(
ioaddr
,
0
)
&
0x0100
)
if
(
lp
->
a
.
read_csr
(
ioaddr
,
0
)
&
0x0100
)
break
;
/*
* We used to clear the InitDone bit, 0x0100, here but Mark Stockton
* reports that doing so triggers a bug in the '974.
*/
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0042
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0042
);
if
(
netif_msg_ifup
(
lp
))
printk
(
KERN_DEBUG
"%s: pcnet32 open after %d ticks, init block %#x csr0 %4.4x.
\n
"
,
dev
->
name
,
i
,
(
u32
)
(
lp
->
dma_addr
+
printk
(
KERN_DEBUG
"%s: pcnet32 open after %d ticks, init block %#x csr0 %4.4x.
\n
"
,
dev
->
name
,
i
,
(
u32
)
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
init_block
)),
lp
->
a
.
read_csr
(
ioaddr
,
0
));
...
...
@@ -1800,13 +1881,13 @@ pcnet32_open(struct net_device *dev)
return
0
;
/* Always succeed */
err_free_ring:
err_free_ring:
/* free any allocated skbuffs */
for
(
i
=
0
;
i
<
lp
->
rx_ring_size
;
i
++
)
{
lp
->
rx_ring
[
i
].
status
=
0
;
if
(
lp
->
rx_skbuff
[
i
])
{
pci_unmap_single
(
lp
->
pci_dev
,
lp
->
rx_dma_addr
[
i
],
PKT_BUF_SZ
-
2
,
PCI_DMA_FROMDEVICE
);
pci_unmap_single
(
lp
->
pci_dev
,
lp
->
rx_dma_addr
[
i
]
,
PKT_BUF_SZ
-
2
,
PCI_DMA_FROMDEVICE
);
dev_kfree_skb
(
lp
->
rx_skbuff
[
i
]);
}
lp
->
rx_skbuff
[
i
]
=
NULL
;
...
...
@@ -1819,9 +1900,9 @@ err_free_ring:
* Switch back to 16bit mode to avoid problems with dumb
* DOS packet driver after a warm reboot
*/
lp
->
a
.
write_bcr
(
ioaddr
,
20
,
4
);
lp
->
a
.
write_bcr
(
ioaddr
,
20
,
4
);
err_free_irq:
err_free_irq:
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
free_irq
(
dev
->
irq
,
dev
);
return
rc
;
...
...
@@ -1840,8 +1921,7 @@ err_free_irq:
* restarting the chip, but I'm too lazy to do so right now. dplatt@3do.com
*/
static
void
pcnet32_purge_tx_ring
(
struct
net_device
*
dev
)
static
void
pcnet32_purge_tx_ring
(
struct
net_device
*
dev
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
int
i
;
...
...
@@ -1851,7 +1931,8 @@ pcnet32_purge_tx_ring(struct net_device *dev)
wmb
();
/* Make sure adapter sees owner change */
if
(
lp
->
tx_skbuff
[
i
])
{
pci_unmap_single
(
lp
->
pci_dev
,
lp
->
tx_dma_addr
[
i
],
lp
->
tx_skbuff
[
i
]
->
len
,
PCI_DMA_TODEVICE
);
lp
->
tx_skbuff
[
i
]
->
len
,
PCI_DMA_TODEVICE
);
dev_kfree_skb_any
(
lp
->
tx_skbuff
[
i
]);
}
lp
->
tx_skbuff
[
i
]
=
NULL
;
...
...
@@ -1859,10 +1940,8 @@ pcnet32_purge_tx_ring(struct net_device *dev)
}
}
/* Initialize the PCNET32 Rx and Tx rings. */
static
int
pcnet32_init_ring
(
struct
net_device
*
dev
)
static
int
pcnet32_init_ring
(
struct
net_device
*
dev
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
int
i
;
...
...
@@ -1874,22 +1953,26 @@ pcnet32_init_ring(struct net_device *dev)
for
(
i
=
0
;
i
<
lp
->
rx_ring_size
;
i
++
)
{
struct
sk_buff
*
rx_skbuff
=
lp
->
rx_skbuff
[
i
];
if
(
rx_skbuff
==
NULL
)
{
if
(
!
(
rx_skbuff
=
lp
->
rx_skbuff
[
i
]
=
dev_alloc_skb
(
PKT_BUF_SZ
)))
{
if
(
!
(
rx_skbuff
=
lp
->
rx_skbuff
[
i
]
=
dev_alloc_skb
(
PKT_BUF_SZ
)))
{
/* there is not much, we can do at this point */
if
(
pcnet32_debug
&
NETIF_MSG_DRV
)
printk
(
KERN_ERR
"%s: pcnet32_init_ring dev_alloc_skb failed.
\n
"
,
printk
(
KERN_ERR
"%s: pcnet32_init_ring dev_alloc_skb failed.
\n
"
,
dev
->
name
);
return
-
1
;
}
skb_reserve
(
rx_skbuff
,
2
);
skb_reserve
(
rx_skbuff
,
2
);
}
rmb
();
if
(
lp
->
rx_dma_addr
[
i
]
==
0
)
lp
->
rx_dma_addr
[
i
]
=
pci_map_single
(
lp
->
pci_dev
,
rx_skbuff
->
data
,
PKT_BUF_SZ
-
2
,
PCI_DMA_FROMDEVICE
);
lp
->
rx_ring
[
i
].
base
=
(
u32
)
le32_to_cpu
(
lp
->
rx_dma_addr
[
i
]);
lp
->
rx_ring
[
i
].
buf_length
=
le16_to_cpu
(
2
-
PKT_BUF_SZ
);
lp
->
rx_dma_addr
[
i
]
=
pci_map_single
(
lp
->
pci_dev
,
rx_skbuff
->
data
,
PKT_BUF_SZ
-
2
,
PCI_DMA_FROMDEVICE
);
lp
->
rx_ring
[
i
].
base
=
(
u32
)
le32_to_cpu
(
lp
->
rx_dma_addr
[
i
]);
lp
->
rx_ring
[
i
].
buf_length
=
le16_to_cpu
(
2
-
PKT_BUF_SZ
);
wmb
();
/* Make sure owner changes after all others are visible */
lp
->
rx_ring
[
i
].
status
=
le16_to_cpu
(
0x8000
);
}
...
...
@@ -1902,11 +1985,12 @@ pcnet32_init_ring(struct net_device *dev)
lp
->
tx_dma_addr
[
i
]
=
0
;
}
lp
->
init_block
.
tlen_rlen
=
le16_to_cpu
(
lp
->
tx_len_bits
|
lp
->
rx_len_bits
);
lp
->
init_block
.
tlen_rlen
=
le16_to_cpu
(
lp
->
tx_len_bits
|
lp
->
rx_len_bits
);
for
(
i
=
0
;
i
<
6
;
i
++
)
lp
->
init_block
.
phys_addr
[
i
]
=
dev
->
dev_addr
[
i
];
lp
->
init_block
.
rx_ring
=
(
u32
)
le32_to_cpu
(
lp
->
rx_ring_dma_addr
);
lp
->
init_block
.
tx_ring
=
(
u32
)
le32_to_cpu
(
lp
->
tx_ring_dma_addr
);
lp
->
init_block
.
rx_ring
=
(
u32
)
le32_to_cpu
(
lp
->
rx_ring_dma_addr
);
lp
->
init_block
.
tx_ring
=
(
u32
)
le32_to_cpu
(
lp
->
tx_ring_dma_addr
);
wmb
();
/* Make sure all changes are visible */
return
0
;
}
...
...
@@ -1915,20 +1999,20 @@ pcnet32_init_ring(struct net_device *dev)
* then flush the pending transmit operations, re-initialize the ring,
* and tell the chip to initialize.
*/
static
void
pcnet32_restart
(
struct
net_device
*
dev
,
unsigned
int
csr0_bits
)
static
void
pcnet32_restart
(
struct
net_device
*
dev
,
unsigned
int
csr0_bits
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
unsigned
long
ioaddr
=
dev
->
base_addr
;
int
i
;
/* wait for stop */
for
(
i
=
0
;
i
<
100
;
i
++
)
for
(
i
=
0
;
i
<
100
;
i
++
)
if
(
lp
->
a
.
read_csr
(
ioaddr
,
0
)
&
0x0004
)
break
;
if
(
i
>=
100
&&
netif_msg_drv
(
lp
))
printk
(
KERN_ERR
"%s: pcnet32_restart timed out waiting for stop.
\n
"
,
printk
(
KERN_ERR
"%s: pcnet32_restart timed out waiting for stop.
\n
"
,
dev
->
name
);
pcnet32_purge_tx_ring
(
dev
);
...
...
@@ -1936,18 +2020,16 @@ pcnet32_restart(struct net_device *dev, unsigned int csr0_bits)
return
;
/* ReInit Ring */
lp
->
a
.
write_csr
(
ioaddr
,
0
,
1
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
1
);
i
=
0
;
while
(
i
++
<
1000
)
if
(
lp
->
a
.
read_csr
(
ioaddr
,
0
)
&
0x0100
)
if
(
lp
->
a
.
read_csr
(
ioaddr
,
0
)
&
0x0100
)
break
;
lp
->
a
.
write_csr
(
ioaddr
,
0
,
csr0_bits
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
csr0_bits
);
}
static
void
pcnet32_tx_timeout
(
struct
net_device
*
dev
)
static
void
pcnet32_tx_timeout
(
struct
net_device
*
dev
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
unsigned
long
ioaddr
=
dev
->
base_addr
,
flags
;
...
...
@@ -1955,22 +2037,24 @@ pcnet32_tx_timeout (struct net_device *dev)
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
/* Transmitter timeout, serious problems. */
if
(
pcnet32_debug
&
NETIF_MSG_DRV
)
printk
(
KERN_ERR
"%s: transmit timed out, status %4.4x, resetting.
\n
"
,
printk
(
KERN_ERR
"%s: transmit timed out, status %4.4x, resetting.
\n
"
,
dev
->
name
,
lp
->
a
.
read_csr
(
ioaddr
,
0
));
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0004
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0004
);
lp
->
stats
.
tx_errors
++
;
if
(
netif_msg_tx_err
(
lp
))
{
int
i
;
printk
(
KERN_DEBUG
" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d."
,
printk
(
KERN_DEBUG
" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d."
,
lp
->
dirty_tx
,
lp
->
cur_tx
,
lp
->
tx_full
?
" (full)"
:
""
,
lp
->
cur_rx
);
for
(
i
=
0
;
i
<
lp
->
rx_ring_size
;
i
++
)
for
(
i
=
0
;
i
<
lp
->
rx_ring_size
;
i
++
)
printk
(
"%s %08x %04x %08x %04x"
,
i
&
1
?
""
:
"
\n
"
,
le32_to_cpu
(
lp
->
rx_ring
[
i
].
base
),
(
-
le16_to_cpu
(
lp
->
rx_ring
[
i
].
buf_length
))
&
0xffff
,
le32_to_cpu
(
lp
->
rx_ring
[
i
].
msg_length
),
(
-
le16_to_cpu
(
lp
->
rx_ring
[
i
].
buf_length
))
&
0xffff
,
le32_to_cpu
(
lp
->
rx_ring
[
i
].
msg_length
),
le16_to_cpu
(
lp
->
rx_ring
[
i
].
status
));
for
(
i
=
0
;
i
<
lp
->
tx_ring_size
;
i
++
)
for
(
i
=
0
;
i
<
lp
->
tx_ring_size
;
i
++
)
printk
(
"%s %08x %04x %08x %04x"
,
i
&
1
?
""
:
"
\n
"
,
le32_to_cpu
(
lp
->
tx_ring
[
i
].
base
),
(
-
le16_to_cpu
(
lp
->
tx_ring
[
i
].
length
))
&
0xffff
,
...
...
@@ -1986,9 +2070,7 @@ pcnet32_tx_timeout (struct net_device *dev)
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
}
static
int
pcnet32_start_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
static
int
pcnet32_start_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
unsigned
long
ioaddr
=
dev
->
base_addr
;
...
...
@@ -1999,7 +2081,8 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
if
(
netif_msg_tx_queued
(
lp
))
{
printk
(
KERN_DEBUG
"%s: pcnet32_start_xmit() called, csr0 %4.4x.
\n
"
,
printk
(
KERN_DEBUG
"%s: pcnet32_start_xmit() called, csr0 %4.4x.
\n
"
,
dev
->
name
,
lp
->
a
.
read_csr
(
ioaddr
,
0
));
}
...
...
@@ -2021,9 +2104,9 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
lp
->
tx_ring
[
entry
].
misc
=
0x00000000
;
lp
->
tx_skbuff
[
entry
]
=
skb
;
lp
->
tx_dma_addr
[
entry
]
=
pci_map_single
(
lp
->
pci_dev
,
skb
->
data
,
skb
->
len
,
PCI_DMA_TODEVICE
);
lp
->
tx_ring
[
entry
].
base
=
(
u32
)
le32_to_cpu
(
lp
->
tx_dma_addr
[
entry
]);
lp
->
tx_dma_addr
[
entry
]
=
pci_map_single
(
lp
->
pci_dev
,
skb
->
data
,
skb
->
len
,
PCI_DMA_TODEVICE
);
lp
->
tx_ring
[
entry
].
base
=
(
u32
)
le32_to_cpu
(
lp
->
tx_dma_addr
[
entry
]);
wmb
();
/* Make sure owner changes after all others are visible */
lp
->
tx_ring
[
entry
].
status
=
le16_to_cpu
(
status
);
...
...
@@ -2031,11 +2114,11 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
lp
->
stats
.
tx_bytes
+=
skb
->
len
;
/* Trigger an immediate send poll. */
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0048
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0048
);
dev
->
trans_start
=
jiffies
;
if
(
lp
->
tx_ring
[(
entry
+
1
)
&
lp
->
tx_mod_mask
].
base
!=
0
)
{
if
(
lp
->
tx_ring
[(
entry
+
1
)
&
lp
->
tx_mod_mask
].
base
!=
0
)
{
lp
->
tx_full
=
1
;
netif_stop_queue
(
dev
);
}
...
...
@@ -2045,18 +2128,18 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* The PCNET32 interrupt handler. */
static
irqreturn_t
pcnet32_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
pcnet32_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
struct
net_device
*
dev
=
dev_id
;
struct
pcnet32_private
*
lp
;
unsigned
long
ioaddr
;
u16
csr0
,
rap
;
u16
csr0
,
rap
;
int
boguscnt
=
max_interrupt_work
;
int
must_restart
;
if
(
!
dev
)
{
if
(
pcnet32_debug
&
NETIF_MSG_INTR
)
printk
(
KERN_DEBUG
"%s(): irq %d for unknown device
\n
"
,
printk
(
KERN_DEBUG
"%s(): irq %d for unknown device
\n
"
,
__FUNCTION__
,
irq
);
return
IRQ_NONE
;
}
...
...
@@ -2067,18 +2150,19 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
spin_lock
(
&
lp
->
lock
);
rap
=
lp
->
a
.
read_rap
(
ioaddr
);
while
((
csr0
=
lp
->
a
.
read_csr
(
ioaddr
,
0
))
&
0x8f00
&&
--
boguscnt
>=
0
)
{
while
((
csr0
=
lp
->
a
.
read_csr
(
ioaddr
,
0
))
&
0x8f00
&&
--
boguscnt
>=
0
)
{
if
(
csr0
==
0xffff
)
{
break
;
/* PCMCIA remove happened */
}
/* Acknowledge all of the current interrupt sources ASAP. */
lp
->
a
.
write_csr
(
ioaddr
,
0
,
csr0
&
~
0x004f
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
csr0
&
~
0x004f
);
must_restart
=
0
;
if
(
netif_msg_intr
(
lp
))
printk
(
KERN_DEBUG
"%s: interrupt csr0=%#2.2x new csr=%#2.2x.
\n
"
,
dev
->
name
,
csr0
,
lp
->
a
.
read_csr
(
ioaddr
,
0
));
printk
(
KERN_DEBUG
"%s: interrupt csr0=%#2.2x new csr=%#2.2x.
\n
"
,
dev
->
name
,
csr0
,
lp
->
a
.
read_csr
(
ioaddr
,
0
));
if
(
csr0
&
0x0400
)
/* Rx interrupt */
pcnet32_rx
(
dev
);
...
...
@@ -2089,7 +2173,9 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
while
(
dirty_tx
!=
lp
->
cur_tx
)
{
int
entry
=
dirty_tx
&
lp
->
tx_mod_mask
;
int
status
=
(
short
)
le16_to_cpu
(
lp
->
tx_ring
[
entry
].
status
);
int
status
=
(
short
)
le16_to_cpu
(
lp
->
tx_ring
[
entry
].
status
);
if
(
status
<
0
)
break
;
/* It still hasn't been Txed */
...
...
@@ -2098,33 +2184,45 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
if
(
status
&
0x4000
)
{
/* There was an major error, log it. */
int
err_status
=
le32_to_cpu
(
lp
->
tx_ring
[
entry
].
misc
);
int
err_status
=
le32_to_cpu
(
lp
->
tx_ring
[
entry
].
misc
);
lp
->
stats
.
tx_errors
++
;
if
(
netif_msg_tx_err
(
lp
))
printk
(
KERN_ERR
"%s: Tx error status=%04x err_status=%08x
\n
"
,
dev
->
name
,
status
,
err_status
);
if
(
err_status
&
0x04000000
)
lp
->
stats
.
tx_aborted_errors
++
;
if
(
err_status
&
0x08000000
)
lp
->
stats
.
tx_carrier_errors
++
;
if
(
err_status
&
0x10000000
)
lp
->
stats
.
tx_window_errors
++
;
printk
(
KERN_ERR
"%s: Tx error status=%04x err_status=%08x
\n
"
,
dev
->
name
,
status
,
err_status
);
if
(
err_status
&
0x04000000
)
lp
->
stats
.
tx_aborted_errors
++
;
if
(
err_status
&
0x08000000
)
lp
->
stats
.
tx_carrier_errors
++
;
if
(
err_status
&
0x10000000
)
lp
->
stats
.
tx_window_errors
++
;
#ifndef DO_DXSUFLO
if
(
err_status
&
0x40000000
)
{
lp
->
stats
.
tx_fifo_errors
++
;
/* Ackk! On FIFO errors the Tx unit is turned off! */
/* Remove this verbosity later! */
if
(
netif_msg_tx_err
(
lp
))
printk
(
KERN_ERR
"%s: Tx FIFO error! CSR0=%4.4x
\n
"
,
printk
(
KERN_ERR
"%s: Tx FIFO error! CSR0=%4.4x
\n
"
,
dev
->
name
,
csr0
);
must_restart
=
1
;
}
#else
if
(
err_status
&
0x40000000
)
{
lp
->
stats
.
tx_fifo_errors
++
;
if
(
!
lp
->
dxsuflo
)
{
/* If controller doesn't recover ... */
if
(
!
lp
->
dxsuflo
)
{
/* If controller doesn't recover ... */
/* Ackk! On FIFO errors the Tx unit is turned off! */
/* Remove this verbosity later! */
if
(
netif_msg_tx_err
(
lp
))
printk
(
KERN_ERR
"%s: Tx FIFO error! CSR0=%4.4x
\n
"
,
dev
->
name
,
csr0
);
if
(
netif_msg_tx_err
(
lp
))
printk
(
KERN_ERR
"%s: Tx FIFO error! CSR0=%4.4x
\n
"
,
dev
->
name
,
csr0
);
must_restart
=
1
;
}
}
...
...
@@ -2137,8 +2235,10 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
/* We must free the original skb */
if
(
lp
->
tx_skbuff
[
entry
])
{
pci_unmap_single
(
lp
->
pci_dev
,
lp
->
tx_dma_addr
[
entry
],
lp
->
tx_skbuff
[
entry
]
->
len
,
PCI_DMA_TODEVICE
);
pci_unmap_single
(
lp
->
pci_dev
,
lp
->
tx_dma_addr
[
entry
],
lp
->
tx_skbuff
[
entry
]
->
len
,
PCI_DMA_TODEVICE
);
dev_kfree_skb_irq
(
lp
->
tx_skbuff
[
entry
]);
lp
->
tx_skbuff
[
entry
]
=
NULL
;
lp
->
tx_dma_addr
[
entry
]
=
0
;
...
...
@@ -2146,11 +2246,15 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
dirty_tx
++
;
}
delta
=
(
lp
->
cur_tx
-
dirty_tx
)
&
(
lp
->
tx_mod_mask
+
lp
->
tx_ring_size
);
delta
=
(
lp
->
cur_tx
-
dirty_tx
)
&
(
lp
->
tx_mod_mask
+
lp
->
tx_ring_size
);
if
(
delta
>
lp
->
tx_ring_size
)
{
if
(
netif_msg_drv
(
lp
))
printk
(
KERN_ERR
"%s: out-of-sync dirty pointer, %d vs. %d, full=%d.
\n
"
,
dev
->
name
,
dirty_tx
,
lp
->
cur_tx
,
lp
->
tx_full
);
printk
(
KERN_ERR
"%s: out-of-sync dirty pointer, %d vs. %d, full=%d.
\n
"
,
dev
->
name
,
dirty_tx
,
lp
->
cur_tx
,
lp
->
tx_full
);
dirty_tx
+=
lp
->
tx_ring_size
;
delta
-=
lp
->
tx_ring_size
;
}
...
...
@@ -2160,13 +2264,14 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
delta
<
lp
->
tx_ring_size
-
2
)
{
/* The ring is no longer full, clear tbusy. */
lp
->
tx_full
=
0
;
netif_wake_queue
(
dev
);
netif_wake_queue
(
dev
);
}
lp
->
dirty_tx
=
dirty_tx
;
}
/* Log misc errors. */
if
(
csr0
&
0x4000
)
lp
->
stats
.
tx_errors
++
;
/* Tx babble. */
if
(
csr0
&
0x4000
)
lp
->
stats
.
tx_errors
++
;
/* Tx babble. */
if
(
csr0
&
0x1000
)
{
/*
* this happens when our receive ring is full. This shouldn't
...
...
@@ -2183,7 +2288,8 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
}
if
(
csr0
&
0x0800
)
{
if
(
netif_msg_drv
(
lp
))
printk
(
KERN_ERR
"%s: Bus master arbitration failure, status %4.4x.
\n
"
,
printk
(
KERN_ERR
"%s: Bus master arbitration failure, status %4.4x.
\n
"
,
dev
->
name
,
csr0
);
/* unlike for the lance, there is no restart needed */
}
...
...
@@ -2198,20 +2304,19 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
}
/* Set interrupt enable. */
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0040
);
lp
->
a
.
write_rap
(
ioaddr
,
rap
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0040
);
lp
->
a
.
write_rap
(
ioaddr
,
rap
);
if
(
netif_msg_intr
(
lp
))
printk
(
KERN_DEBUG
"%s: exiting interrupt, csr0=%#4.4x.
\n
"
,
dev
->
name
,
lp
->
a
.
read_csr
(
ioaddr
,
0
));
dev
->
name
,
lp
->
a
.
read_csr
(
ioaddr
,
0
));
spin_unlock
(
&
lp
->
lock
);
return
IRQ_HANDLED
;
}
static
int
pcnet32_rx
(
struct
net_device
*
dev
)
static
int
pcnet32_rx
(
struct
net_device
*
dev
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
int
entry
=
lp
->
cur_rx
&
lp
->
rx_mod_mask
;
...
...
@@ -2229,26 +2334,34 @@ pcnet32_rx(struct net_device *dev)
* buffers, with only the last correctly noting the error.
*/
if
(
status
&
0x01
)
/* Only count a general error at the */
lp
->
stats
.
rx_errors
++
;
/* end of a packet.*/
if
(
status
&
0x20
)
lp
->
stats
.
rx_frame_errors
++
;
if
(
status
&
0x10
)
lp
->
stats
.
rx_over_errors
++
;
if
(
status
&
0x08
)
lp
->
stats
.
rx_crc_errors
++
;
if
(
status
&
0x04
)
lp
->
stats
.
rx_fifo_errors
++
;
lp
->
stats
.
rx_errors
++
;
/* end of a packet. */
if
(
status
&
0x20
)
lp
->
stats
.
rx_frame_errors
++
;
if
(
status
&
0x10
)
lp
->
stats
.
rx_over_errors
++
;
if
(
status
&
0x08
)
lp
->
stats
.
rx_crc_errors
++
;
if
(
status
&
0x04
)
lp
->
stats
.
rx_fifo_errors
++
;
lp
->
rx_ring
[
entry
].
status
&=
le16_to_cpu
(
0x03ff
);
}
else
{
/* Malloc up new buffer, compatible with net-2e. */
short
pkt_len
=
(
le32_to_cpu
(
lp
->
rx_ring
[
entry
].
msg_length
)
&
0xfff
)
-
4
;
short
pkt_len
=
(
le32_to_cpu
(
lp
->
rx_ring
[
entry
].
msg_length
)
&
0xfff
)
-
4
;
struct
sk_buff
*
skb
;
/* Discard oversize frames. */
if
(
unlikely
(
pkt_len
>
PKT_BUF_SZ
-
2
))
{
if
(
netif_msg_drv
(
lp
))
printk
(
KERN_ERR
"%s: Impossible packet size %d!
\n
"
,
printk
(
KERN_ERR
"%s: Impossible packet size %d!
\n
"
,
dev
->
name
,
pkt_len
);
lp
->
stats
.
rx_errors
++
;
}
else
if
(
pkt_len
<
60
)
{
if
(
netif_msg_rx_err
(
lp
))
printk
(
KERN_ERR
"%s: Runt packet!
\n
"
,
dev
->
name
);
printk
(
KERN_ERR
"%s: Runt packet!
\n
"
,
dev
->
name
);
lp
->
stats
.
rx_errors
++
;
}
else
{
int
rx_in_place
=
0
;
...
...
@@ -2256,38 +2369,56 @@ pcnet32_rx(struct net_device *dev)
if
(
pkt_len
>
rx_copybreak
)
{
struct
sk_buff
*
newskb
;
if
((
newskb
=
dev_alloc_skb
(
PKT_BUF_SZ
)))
{
skb_reserve
(
newskb
,
2
);
if
((
newskb
=
dev_alloc_skb
(
PKT_BUF_SZ
)))
{
skb_reserve
(
newskb
,
2
);
skb
=
lp
->
rx_skbuff
[
entry
];
pci_unmap_single
(
lp
->
pci_dev
,
lp
->
rx_dma_addr
[
entry
],
PKT_BUF_SZ
-
2
,
PCI_DMA_FROMDEVICE
);
skb_put
(
skb
,
pkt_len
);
pci_unmap_single
(
lp
->
pci_dev
,
lp
->
rx_dma_addr
[
entry
],
PKT_BUF_SZ
-
2
,
PCI_DMA_FROMDEVICE
);
skb_put
(
skb
,
pkt_len
);
lp
->
rx_skbuff
[
entry
]
=
newskb
;
newskb
->
dev
=
dev
;
lp
->
rx_dma_addr
[
entry
]
=
pci_map_single
(
lp
->
pci_dev
,
newskb
->
data
,
PKT_BUF_SZ
-
2
,
PCI_DMA_FROMDEVICE
);
lp
->
rx_ring
[
entry
].
base
=
le32_to_cpu
(
lp
->
rx_dma_addr
[
entry
]);
pci_map_single
(
lp
->
pci_dev
,
newskb
->
data
,
PKT_BUF_SZ
-
2
,
PCI_DMA_FROMDEVICE
);
lp
->
rx_ring
[
entry
].
base
=
le32_to_cpu
(
lp
->
rx_dma_addr
[
entry
]);
rx_in_place
=
1
;
}
else
skb
=
NULL
;
}
else
{
skb
=
dev_alloc_skb
(
pkt_len
+
2
);
skb
=
dev_alloc_skb
(
pkt_len
+
2
);
}
if
(
skb
==
NULL
)
{
int
i
;
if
(
netif_msg_drv
(
lp
))
printk
(
KERN_ERR
"%s: Memory squeeze, deferring packet.
\n
"
,
printk
(
KERN_ERR
"%s: Memory squeeze, deferring packet.
\n
"
,
dev
->
name
);
for
(
i
=
0
;
i
<
lp
->
rx_ring_size
;
i
++
)
if
((
short
)
le16_to_cpu
(
lp
->
rx_ring
[(
entry
+
i
)
&
lp
->
rx_mod_mask
].
status
)
<
0
)
if
((
short
)
le16_to_cpu
(
lp
->
rx_ring
[(
entry
+
i
)
&
lp
->
rx_mod_mask
].
status
)
<
0
)
break
;
if
(
i
>
lp
->
rx_ring_size
-
2
)
{
if
(
i
>
lp
->
rx_ring_size
-
2
)
{
lp
->
stats
.
rx_dropped
++
;
lp
->
rx_ring
[
entry
].
status
|=
le16_to_cpu
(
0x8000
);
lp
->
rx_ring
[
entry
].
status
|=
le16_to_cpu
(
0x8000
);
wmb
();
/* Make sure adapter sees owner change */
lp
->
cur_rx
++
;
}
...
...
@@ -2295,22 +2426,32 @@ pcnet32_rx(struct net_device *dev)
}
skb
->
dev
=
dev
;
if
(
!
rx_in_place
)
{
skb_reserve
(
skb
,
2
);
/* 16 byte align */
skb_put
(
skb
,
pkt_len
);
/* Make room */
skb_reserve
(
skb
,
2
);
/* 16 byte align */
skb_put
(
skb
,
pkt_len
);
/* Make room */
pci_dma_sync_single_for_cpu
(
lp
->
pci_dev
,
lp
->
rx_dma_addr
[
entry
],
PKT_BUF_SZ
-
2
,
lp
->
rx_dma_addr
[
entry
],
PKT_BUF_SZ
-
2
,
PCI_DMA_FROMDEVICE
);
eth_copy_and_sum
(
skb
,
(
unsigned
char
*
)(
lp
->
rx_skbuff
[
entry
]
->
data
),
pkt_len
,
0
);
pci_dma_sync_single_for_device
(
lp
->
pci_dev
,
lp
->
rx_dma_addr
[
entry
],
PKT_BUF_SZ
-
2
,
(
unsigned
char
*
)(
lp
->
rx_skbuff
[
entry
]
->
data
),
pkt_len
,
0
);
pci_dma_sync_single_for_device
(
lp
->
pci_dev
,
lp
->
rx_dma_addr
[
entry
],
PKT_BUF_SZ
-
2
,
PCI_DMA_FROMDEVICE
);
}
lp
->
stats
.
rx_bytes
+=
skb
->
len
;
skb
->
protocol
=
eth_type_trans
(
skb
,
dev
);
skb
->
protocol
=
eth_type_trans
(
skb
,
dev
);
netif_rx
(
skb
);
dev
->
last_rx
=
jiffies
;
lp
->
stats
.
rx_packets
++
;
...
...
@@ -2320,18 +2461,18 @@ pcnet32_rx(struct net_device *dev)
* The docs say that the buffer length isn't touched, but Andrew Boyd
* of QNX reports that some revs of the 79C965 clear it.
*/
lp
->
rx_ring
[
entry
].
buf_length
=
le16_to_cpu
(
2
-
PKT_BUF_SZ
);
lp
->
rx_ring
[
entry
].
buf_length
=
le16_to_cpu
(
2
-
PKT_BUF_SZ
);
wmb
();
/* Make sure owner changes after all others are visible */
lp
->
rx_ring
[
entry
].
status
|=
le16_to_cpu
(
0x8000
);
entry
=
(
++
lp
->
cur_rx
)
&
lp
->
rx_mod_mask
;
if
(
--
boguscnt
<=
0
)
break
;
/* don't stay in loop forever */
if
(
--
boguscnt
<=
0
)
break
;
/* don't stay in loop forever */
}
return
0
;
}
static
int
pcnet32_close
(
struct
net_device
*
dev
)
static
int
pcnet32_close
(
struct
net_device
*
dev
)
{
unsigned
long
ioaddr
=
dev
->
base_addr
;
struct
pcnet32_private
*
lp
=
dev
->
priv
;
...
...
@@ -2344,20 +2485,21 @@ pcnet32_close(struct net_device *dev)
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
lp
->
stats
.
rx_missed_errors
=
lp
->
a
.
read_csr
(
ioaddr
,
112
);
lp
->
stats
.
rx_missed_errors
=
lp
->
a
.
read_csr
(
ioaddr
,
112
);
if
(
netif_msg_ifdown
(
lp
))
printk
(
KERN_DEBUG
"%s: Shutting down ethercard, status was %2.2x.
\n
"
,
dev
->
name
,
lp
->
a
.
read_csr
(
ioaddr
,
0
));
printk
(
KERN_DEBUG
"%s: Shutting down ethercard, status was %2.2x.
\n
"
,
dev
->
name
,
lp
->
a
.
read_csr
(
ioaddr
,
0
));
/* We stop the PCNET32 here -- it occasionally polls memory if we don't. */
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0004
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0004
);
/*
* Switch back to 16bit mode to avoid problems with dumb
* DOS packet driver after a warm reboot
*/
lp
->
a
.
write_bcr
(
ioaddr
,
20
,
4
);
lp
->
a
.
write_bcr
(
ioaddr
,
20
,
4
);
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
...
...
@@ -2370,8 +2512,8 @@ pcnet32_close(struct net_device *dev)
lp
->
rx_ring
[
i
].
status
=
0
;
wmb
();
/* Make sure adapter sees owner change */
if
(
lp
->
rx_skbuff
[
i
])
{
pci_unmap_single
(
lp
->
pci_dev
,
lp
->
rx_dma_addr
[
i
],
PKT_BUF_SZ
-
2
,
PCI_DMA_FROMDEVICE
);
pci_unmap_single
(
lp
->
pci_dev
,
lp
->
rx_dma_addr
[
i
]
,
PKT_BUF_SZ
-
2
,
PCI_DMA_FROMDEVICE
);
dev_kfree_skb
(
lp
->
rx_skbuff
[
i
]);
}
lp
->
rx_skbuff
[
i
]
=
NULL
;
...
...
@@ -2383,7 +2525,8 @@ pcnet32_close(struct net_device *dev)
wmb
();
/* Make sure adapter sees owner change */
if
(
lp
->
tx_skbuff
[
i
])
{
pci_unmap_single
(
lp
->
pci_dev
,
lp
->
tx_dma_addr
[
i
],
lp
->
tx_skbuff
[
i
]
->
len
,
PCI_DMA_TODEVICE
);
lp
->
tx_skbuff
[
i
]
->
len
,
PCI_DMA_TODEVICE
);
dev_kfree_skb
(
lp
->
tx_skbuff
[
i
]);
}
lp
->
tx_skbuff
[
i
]
=
NULL
;
...
...
@@ -2395,8 +2538,7 @@ pcnet32_close(struct net_device *dev)
return
0
;
}
static
struct
net_device_stats
*
pcnet32_get_stats
(
struct
net_device
*
dev
)
static
struct
net_device_stats
*
pcnet32_get_stats
(
struct
net_device
*
dev
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
unsigned
long
ioaddr
=
dev
->
base_addr
;
...
...
@@ -2405,7 +2547,7 @@ pcnet32_get_stats(struct net_device *dev)
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
saved_addr
=
lp
->
a
.
read_rap
(
ioaddr
);
lp
->
stats
.
rx_missed_errors
=
lp
->
a
.
read_csr
(
ioaddr
,
112
);
lp
->
stats
.
rx_missed_errors
=
lp
->
a
.
read_csr
(
ioaddr
,
112
);
lp
->
a
.
write_rap
(
ioaddr
,
saved_addr
);
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
...
...
@@ -2413,12 +2555,12 @@ pcnet32_get_stats(struct net_device *dev)
}
/* taken from the sunlance driver, which it took from the depca driver */
static
void
pcnet32_load_multicast
(
struct
net_device
*
dev
)
static
void
pcnet32_load_multicast
(
struct
net_device
*
dev
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
volatile
struct
pcnet32_init_block
*
ib
=
&
lp
->
init_block
;
volatile
u16
*
mcast_table
=
(
u16
*
)
&
ib
->
filter
;
struct
dev_mc_list
*
dmi
=
dev
->
mc_list
;
volatile
u16
*
mcast_table
=
(
u16
*
)
&
ib
->
filter
;
struct
dev_mc_list
*
dmi
=
dev
->
mc_list
;
char
*
addrs
;
int
i
;
u32
crc
;
...
...
@@ -2444,13 +2586,13 @@ static void pcnet32_load_multicast (struct net_device *dev)
crc
=
ether_crc_le
(
6
,
addrs
);
crc
=
crc
>>
26
;
mcast_table
[
crc
>>
4
]
=
le16_to_cpu
(
le16_to_cpu
(
mcast_table
[
crc
>>
4
])
|
(
1
<<
(
crc
&
0xf
)));
mcast_table
[
crc
>>
4
]
=
le16_to_cpu
(
le16_to_cpu
(
mcast_table
[
crc
>>
4
])
|
(
1
<<
(
crc
&
0xf
)));
}
return
;
}
/*
* Set or clear the multicast filter for this adaptor.
*/
...
...
@@ -2460,17 +2602,21 @@ static void pcnet32_set_multicast_list(struct net_device *dev)
struct
pcnet32_private
*
lp
=
dev
->
priv
;
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
if
(
dev
->
flags
&
IFF_PROMISC
)
{
if
(
dev
->
flags
&
IFF_PROMISC
)
{
/* Log any net taps. */
if
(
netif_msg_hw
(
lp
))
printk
(
KERN_INFO
"%s: Promiscuous mode enabled.
\n
"
,
dev
->
name
);
lp
->
init_block
.
mode
=
le16_to_cpu
(
0x8000
|
(
lp
->
options
&
PCNET32_PORT_PORTSEL
)
<<
7
);
printk
(
KERN_INFO
"%s: Promiscuous mode enabled.
\n
"
,
dev
->
name
);
lp
->
init_block
.
mode
=
le16_to_cpu
(
0x8000
|
(
lp
->
options
&
PCNET32_PORT_PORTSEL
)
<<
7
);
}
else
{
lp
->
init_block
.
mode
=
le16_to_cpu
((
lp
->
options
&
PCNET32_PORT_PORTSEL
)
<<
7
);
pcnet32_load_multicast
(
dev
);
lp
->
init_block
.
mode
=
le16_to_cpu
((
lp
->
options
&
PCNET32_PORT_PORTSEL
)
<<
7
);
pcnet32_load_multicast
(
dev
);
}
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0004
);
/* Temporarily stop the lance. */
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0004
);
/* Temporarily stop the lance. */
pcnet32_restart
(
dev
,
0x0042
);
/* Resume normal operation */
netif_wake_queue
(
dev
);
...
...
@@ -2539,15 +2685,20 @@ static int pcnet32_check_otherphy(struct net_device *dev)
if
(
mii_link_ok
(
&
mii
))
{
/* found PHY with active link */
if
(
netif_msg_link
(
lp
))
printk
(
KERN_INFO
"%s: Using PHY number %d.
\n
"
,
dev
->
name
,
i
);
printk
(
KERN_INFO
"%s: Using PHY number %d.
\n
"
,
dev
->
name
,
i
);
/* isolate inactive phy */
bmcr
=
mdio_read
(
dev
,
lp
->
mii_if
.
phy_id
,
MII_BMCR
);
mdio_write
(
dev
,
lp
->
mii_if
.
phy_id
,
MII_BMCR
,
bmcr
|
BMCR_ISOLATE
);
bmcr
=
mdio_read
(
dev
,
lp
->
mii_if
.
phy_id
,
MII_BMCR
);
mdio_write
(
dev
,
lp
->
mii_if
.
phy_id
,
MII_BMCR
,
bmcr
|
BMCR_ISOLATE
);
/* de-isolate new phy */
bmcr
=
mdio_read
(
dev
,
i
,
MII_BMCR
);
mdio_write
(
dev
,
i
,
MII_BMCR
,
bmcr
&
~
BMCR_ISOLATE
);
mdio_write
(
dev
,
i
,
MII_BMCR
,
bmcr
&
~
BMCR_ISOLATE
);
/* set new phy address */
lp
->
mii_if
.
phy_id
=
i
;
...
...
@@ -2595,10 +2746,12 @@ static void pcnet32_check_media(struct net_device *dev, int verbose)
if
(
netif_msg_link
(
lp
))
{
struct
ethtool_cmd
ecmd
;
mii_ethtool_gset
(
&
lp
->
mii_if
,
&
ecmd
);
printk
(
KERN_INFO
"%s: link up, %sMbps, %s-duplex
\n
"
,
printk
(
KERN_INFO
"%s: link up, %sMbps, %s-duplex
\n
"
,
dev
->
name
,
(
ecmd
.
speed
==
SPEED_100
)
?
"100"
:
"10"
,
(
ecmd
.
duplex
==
DUPLEX_FULL
)
?
"full"
:
"half"
);
(
ecmd
.
duplex
==
DUPLEX_FULL
)
?
"full"
:
"half"
);
}
bcr9
=
lp
->
a
.
read_bcr
(
dev
->
base_addr
,
9
);
if
((
bcr9
&
(
1
<<
0
))
!=
lp
->
mii_if
.
full_duplex
)
{
...
...
@@ -2630,7 +2783,7 @@ static void pcnet32_watchdog(struct net_device *dev)
pcnet32_check_media
(
dev
,
0
);
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
mod_timer
(
&
(
lp
->
watchdog_timer
),
PCNET32_WATCHDOG_TIMEOUT
);
mod_timer
(
&
(
lp
->
watchdog_timer
),
PCNET32_WATCHDOG_TIMEOUT
);
}
static
void
__devexit
pcnet32_remove_one
(
struct
pci_dev
*
pdev
)
...
...
@@ -2665,9 +2818,11 @@ static int pcnet32_have_pci;
module_param
(
debug
,
int
,
0
);
MODULE_PARM_DESC
(
debug
,
DRV_NAME
" debug level"
);
module_param
(
max_interrupt_work
,
int
,
0
);
MODULE_PARM_DESC
(
max_interrupt_work
,
DRV_NAME
" maximum events handled per interrupt"
);
MODULE_PARM_DESC
(
max_interrupt_work
,
DRV_NAME
" maximum events handled per interrupt"
);
module_param
(
rx_copybreak
,
int
,
0
);
MODULE_PARM_DESC
(
rx_copybreak
,
DRV_NAME
" copy breakpoint for copy-only-tiny-frames"
);
MODULE_PARM_DESC
(
rx_copybreak
,
DRV_NAME
" copy breakpoint for copy-only-tiny-frames"
);
module_param
(
tx_start_pt
,
int
,
0
);
MODULE_PARM_DESC
(
tx_start_pt
,
DRV_NAME
" transmit start point (0-3)"
);
module_param
(
pcnet32vlb
,
int
,
0
);
...
...
@@ -2678,7 +2833,9 @@ module_param_array(full_duplex, int, NULL, 0);
MODULE_PARM_DESC
(
full_duplex
,
DRV_NAME
" full duplex setting(s) (1)"
);
/* Module Parameter for HomePNA cards added by Patrick Simmons, 2004 */
module_param_array
(
homepna
,
int
,
NULL
,
0
);
MODULE_PARM_DESC
(
homepna
,
DRV_NAME
" mode for 79C978 cards (1 for HomePNA, 0 for Ethernet, default Ethernet"
);
MODULE_PARM_DESC
(
homepna
,
DRV_NAME
" mode for 79C978 cards (1 for HomePNA, 0 for Ethernet, default Ethernet"
);
MODULE_AUTHOR
(
"Thomas Bogendoerfer"
);
MODULE_DESCRIPTION
(
"Driver for PCnet32 and PCnetPCI based ethercards"
);
...
...
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