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
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 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
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 @@ pcnet32_open(struct net_device *dev)
* 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 @@ pcnet32_open(struct net_device *dev)
* 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