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
5ef7ab1c
Commit
5ef7ab1c
authored
Feb 24, 2004
by
Jeff Garzik
Browse files
Options
Browse Files
Download
Plain Diff
Merge redhat.com:/spare/repo/netdev-2.6/pcnet32
into redhat.com:/spare/repo/net-drivers-2.5
parents
9e6b8ac3
62d90976
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
602 additions
and
339 deletions
+602
-339
drivers/net/pcnet32.c
drivers/net/pcnet32.c
+602
-339
No files found.
drivers/net/pcnet32.c
View file @
5ef7ab1c
...
@@ -22,8 +22,8 @@
...
@@ -22,8 +22,8 @@
*************************************************************************/
*************************************************************************/
#define DRV_NAME "pcnet32"
#define DRV_NAME "pcnet32"
#define DRV_VERSION "1.2
7b
"
#define DRV_VERSION "1.2
8
"
#define DRV_RELDATE "0
1.10.2002
"
#define DRV_RELDATE "0
2.20.2004
"
#define PFX DRV_NAME ": "
#define PFX DRV_NAME ": "
static
const
char
*
version
=
static
const
char
*
version
=
...
@@ -58,6 +58,12 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n";
...
@@ -58,6 +58,12 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n";
static
struct
pci_device_id
pcnet32_pci_tbl
[]
=
{
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_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
,
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
,
}
{
0
,
}
};
};
...
@@ -73,7 +79,7 @@ static unsigned int pcnet32_portlist[] __initdata =
...
@@ -73,7 +79,7 @@ static unsigned int pcnet32_portlist[] __initdata =
static
int
pcnet32_debug
=
1
;
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
tx_start
=
1
;
/* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */
static
int
pcnet32vlb
;
/* check for VLB cards ? */
static
int
pcnet32vlb
;
/* check for VLB cards ? */
...
@@ -119,6 +125,11 @@ static unsigned char options_mapping[] = {
...
@@ -119,6 +125,11 @@ static unsigned char options_mapping[] = {
PCNET32_PORT_ASEL
/* 15 not supported */
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 MAX_UNITS 8
/* More are supported, limit only on options */
#define MAX_UNITS 8
/* More are supported, limit only on options */
static
int
options
[
MAX_UNITS
];
static
int
options
[
MAX_UNITS
];
static
int
full_duplex
[
MAX_UNITS
];
static
int
full_duplex
[
MAX_UNITS
];
...
@@ -213,6 +224,11 @@ static int full_duplex[MAX_UNITS];
...
@@ -213,6 +224,11 @@ static int full_duplex[MAX_UNITS];
* clean up and using new mii module
* clean up and using new mii module
* v1.27b Sep 30 2002 Kent Yoder <yoder1@us.ibm.com>
* v1.27b Sep 30 2002 Kent Yoder <yoder1@us.ibm.com>
* Added timer for cable connection state changes.
* Added timer for cable connection state changes.
* v1.28 20 Feb 2004 Don Fry <brazilnut@us.ibm.com>
* Jon Lewis <jonmason@us.ibm.com>, Chinmay Albal <albal@in.ibm.com>
* Now uses ethtool_ops, netif_msg_* and generic_mii_ioctl.
* Fixes bogus 'Bus master arbitration failure', pci_[un]map_single
* length errors, and transmit hangs. Cleans up after errors in open.
*/
*/
...
@@ -298,9 +314,11 @@ struct pcnet32_private {
...
@@ -298,9 +314,11 @@ struct pcnet32_private {
struct
pcnet32_rx_head
rx_ring
[
RX_RING_SIZE
];
struct
pcnet32_rx_head
rx_ring
[
RX_RING_SIZE
];
struct
pcnet32_tx_head
tx_ring
[
TX_RING_SIZE
];
struct
pcnet32_tx_head
tx_ring
[
TX_RING_SIZE
];
struct
pcnet32_init_block
init_block
;
struct
pcnet32_init_block
init_block
;
dma_addr_t
dma_addr
;
/* DMA address of beginning of this object,
dma_addr_t
dma_addr
;
/* DMA address of beginning of this
returned by pci_alloc_consistent */
object, returned by
struct
pci_dev
*
pci_dev
;
/* Pointer to the associated pci device structure */
pci_alloc_consistent */
struct
pci_dev
*
pci_dev
;
/* Pointer to the associated pci device
structure */
const
char
*
name
;
const
char
*
name
;
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
struct
sk_buff
*
tx_skbuff
[
TX_RING_SIZE
];
struct
sk_buff
*
tx_skbuff
[
TX_RING_SIZE
];
...
@@ -321,6 +339,7 @@ struct pcnet32_private {
...
@@ -321,6 +339,7 @@ struct pcnet32_private {
struct
net_device
*
next
;
struct
net_device
*
next
;
struct
mii_if_info
mii_if
;
struct
mii_if_info
mii_if
;
struct
timer_list
watchdog_timer
;
struct
timer_list
watchdog_timer
;
u32
msg_enable
;
/* debug message level */
};
};
static
void
pcnet32_probe_vlbus
(
void
);
static
void
pcnet32_probe_vlbus
(
void
);
...
@@ -339,6 +358,10 @@ static int pcnet32_ioctl(struct net_device *, struct ifreq *, int);
...
@@ -339,6 +358,10 @@ static int pcnet32_ioctl(struct net_device *, struct ifreq *, int);
static
void
pcnet32_watchdog
(
struct
net_device
*
);
static
void
pcnet32_watchdog
(
struct
net_device
*
);
static
int
mdio_read
(
struct
net_device
*
dev
,
int
phy_id
,
int
reg_num
);
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
);
enum
pci_flags_bit
{
enum
pci_flags_bit
{
PCI_USES_IO
=
1
,
PCI_USES_MEM
=
2
,
PCI_USES_MASTER
=
4
,
PCI_USES_IO
=
1
,
PCI_USES_MEM
=
2
,
PCI_USES_MASTER
=
4
,
...
@@ -458,6 +481,273 @@ static struct pcnet32_access pcnet32_dwio = {
...
@@ -458,6 +481,273 @@ static struct pcnet32_access pcnet32_dwio = {
static
int
pcnet32_get_settings
(
struct
net_device
*
dev
,
struct
ethtool_cmd
*
cmd
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
unsigned
long
flags
;
int
r
=
-
EOPNOTSUPP
;
if
(
lp
->
mii
)
{
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
mii_ethtool_gset
(
&
lp
->
mii_if
,
cmd
);
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
r
=
0
;
}
return
r
;
}
static
int
pcnet32_set_settings
(
struct
net_device
*
dev
,
struct
ethtool_cmd
*
cmd
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
unsigned
long
flags
;
int
r
=
-
EOPNOTSUPP
;
if
(
lp
->
mii
)
{
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
r
=
mii_ethtool_sset
(
&
lp
->
mii_if
,
cmd
);
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
}
return
r
;
}
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
);
if
(
lp
->
pci_dev
)
strcpy
(
info
->
bus_info
,
pci_name
(
lp
->
pci_dev
));
else
sprintf
(
info
->
bus_info
,
"VLB 0x%lx"
,
dev
->
base_addr
);
}
static
u32
pcnet32_get_link
(
struct
net_device
*
dev
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
unsigned
long
flags
;
int
r
=
1
;
if
(
lp
->
mii
)
{
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
r
=
mii_link_ok
(
&
lp
->
mii_if
);
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
}
return
r
;
}
static
u32
pcnet32_get_msglevel
(
struct
net_device
*
dev
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
return
lp
->
msg_enable
;
}
static
void
pcnet32_set_msglevel
(
struct
net_device
*
dev
,
u32
value
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
lp
->
msg_enable
=
value
;
}
static
int
pcnet32_nway_reset
(
struct
net_device
*
dev
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
unsigned
long
flags
;
int
r
=
-
EOPNOTSUPP
;
if
(
lp
->
mii
)
{
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
r
=
mii_nway_restart
(
&
lp
->
mii_if
);
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
}
return
r
;
}
static
void
pcnet32_get_ringparam
(
struct
net_device
*
dev
,
struct
ethtool_ringparam
*
ering
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
ering
->
tx_max_pending
=
TX_RING_SIZE
-
1
;
ering
->
tx_pending
=
lp
->
cur_tx
-
lp
->
dirty_tx
;
ering
->
rx_max_pending
=
RX_RING_SIZE
-
1
;
ering
->
rx_pending
=
lp
->
cur_rx
&
RX_RING_MOD_MASK
;
}
static
void
pcnet32_get_strings
(
struct
net_device
*
dev
,
u32
stringset
,
u8
*
data
)
{
memcpy
(
data
,
pcnet32_gstrings_test
,
sizeof
(
pcnet32_gstrings_test
));
}
static
int
pcnet32_self_test_count
(
struct
net_device
*
dev
)
{
return
PCNET32_TEST_LEN
;
}
static
void
pcnet32_ethtool_test
(
struct
net_device
*
dev
,
struct
ethtool_test
*
test
,
u64
*
data
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
int
rc
;
if
(
test
->
flags
==
ETH_TEST_FL_OFFLINE
)
{
rc
=
pcnet32_loopback_test
(
dev
,
data
);
if
(
rc
)
{
if
(
netif_msg_hw
(
lp
))
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
);
}
else
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
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
struct
pcnet32_access
*
a
=
&
lp
->
a
;
/* access to registers */
ulong
ioaddr
=
dev
->
base_addr
;
/* card base I/O address */
struct
sk_buff
*
skb
;
/* sk buff */
int
x
,
y
,
i
;
/* counters */
int
numbuffs
=
4
;
/* number of TX/RX buffers and descs */
u16
status
=
0x8300
;
/* TX ring status */
int
rc
;
/* return code */
int
size
;
/* size of packets */
unsigned
char
*
packet
;
/* source packet data */
static
int
data_len
=
60
;
/* length of source packets */
unsigned
long
flags
;
*
data1
=
1
;
/* status of test, default to fail */
rc
=
1
;
/* default to fail */
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x7904
);
del_timer_sync
(
&
lp
->
watchdog_timer
);
netif_stop_queue
(
dev
);
/* purge & init rings but don't actually restart */
pcnet32_restart
(
dev
,
0x0000
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0004
);
/* Set STOP bit */
x
=
a
->
read_bcr
(
ioaddr
,
32
);
/* set internal loopback in BSR32 */
x
=
x
|
0x00000002
;
a
->
write_bcr
(
ioaddr
,
32
,
x
);
/* Initialize Transmit buffers. */
size
=
data_len
+
15
;
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
"
,
dev
->
name
,
__LINE__
);
goto
clean_up
;
}
else
{
packet
=
skb
->
data
;
skb_put
(
skb
,
size
);
/* create space for data */
lp
->
tx_skbuff
[
x
]
=
skb
;
lp
->
tx_ring
[
x
].
length
=
le16_to_cpu
(
-
skb
->
len
);
lp
->
tx_ring
[
x
].
misc
=
0x00000000
;
/* put DA and SA into the skb */
for
(
i
=
0
;
i
<
12
;
i
++
)
*
packet
++
=
0xff
;
/* type */
*
packet
++
=
0x08
;
*
packet
++
=
0x06
;
/* packet number */
*
packet
++
=
x
;
/* fill packet with data */
for
(
y
=
0
;
y
<
data_len
;
y
++
)
*
packet
++
=
y
;
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
);
}
}
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0002
);
/* Set STRT bit */
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
mdelay
(
50
);
/* wait a bit */
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0004
);
/* Set STOP bit */
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
++
)
{
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
));
}
printk
(
"
\n
"
);
}
}
x
=
0
;
rc
=
0
;
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
])
{
if
(
netif_msg_hw
(
lp
))
printk
(
KERN_DEBUG
"%s: Error in compare! %2x - %02x %02x
\n
"
,
dev
->
name
,
i
,
*
(
skb
->
data
+
i
),
packet
[
i
]);
rc
=
1
;
break
;
}
}
x
++
;
}
if
(
!
rc
)
{
*
data1
=
0
;
}
clean_up:
x
=
a
->
read_csr
(
ioaddr
,
15
)
&
0xFFFF
;
a
->
write_csr
(
ioaddr
,
15
,
(
x
&
~
0x0044
));
/* reset bits 6 and 2 */
x
=
a
->
read_bcr
(
ioaddr
,
32
);
/* reset internal loopback */
x
=
x
&
~
0x00000002
;
a
->
write_bcr
(
ioaddr
,
32
,
x
);
pcnet32_restart
(
dev
,
0x0042
);
/* resume normal operation */
netif_wake_queue
(
dev
);
mod_timer
(
&
(
lp
->
watchdog_timer
),
PCNET32_WATCHDOG_TIMEOUT
);
/* Clear interrupts, and set interrupt enable. */
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x7940
);
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
return
(
rc
);
}
/* end pcnet32_loopback_test */
static
struct
ethtool_ops
pcnet32_ethtool_ops
=
{
.
get_settings
=
pcnet32_get_settings
,
.
set_settings
=
pcnet32_set_settings
,
.
get_drvinfo
=
pcnet32_get_drvinfo
,
.
get_msglevel
=
pcnet32_get_msglevel
,
.
set_msglevel
=
pcnet32_set_msglevel
,
.
nway_reset
=
pcnet32_nway_reset
,
.
get_link
=
pcnet32_get_link
,
.
get_ringparam
=
pcnet32_get_ringparam
,
.
get_tx_csum
=
ethtool_op_get_tx_csum
,
.
get_sg
=
ethtool_op_get_sg
,
.
get_tso
=
ethtool_op_get_tso
,
.
get_strings
=
pcnet32_get_strings
,
.
self_test_count
=
pcnet32_self_test_count
,
.
self_test
=
pcnet32_ethtool_test
,
};
/* only probes for non-PCI devices, the rest are handled by
/* only probes for non-PCI devices, the rest are handled by
* pci_register_driver via pcnet32_probe_pci */
* pci_register_driver via pcnet32_probe_pci */
...
@@ -546,10 +836,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
...
@@ -546,10 +836,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
}
}
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
>
2
)
if
(
pcnet32_debug
&
NETIF_MSG_PROBE
)
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
((
chip_version
&
0xfff
)
!=
0x003
)
{
printk
(
KERN_INFO
PFX
"Unsupported chip version.
\n
"
);
goto
err_release_region
;
goto
err_release_region
;
}
/* initialize variables */
/* initialize variables */
fdx
=
mii
=
fset
=
dxsuflo
=
ltint
=
0
;
fdx
=
mii
=
fset
=
dxsuflo
=
ltint
=
0
;
...
@@ -594,13 +886,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
...
@@ -594,13 +886,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
*/
*/
/* switch to home wiring mode */
/* switch to home wiring mode */
media
=
a
->
read_bcr
(
ioaddr
,
49
);
media
=
a
->
read_bcr
(
ioaddr
,
49
);
#if 0
if
(
pcnet32_debug
&
NETIF_MSG_PROBE
)
if (pcnet32_debug > 2)
printk(KERN_DEBUG PFX "media value %#x.\n", media);
media &= ~3;
media |= 1;
#endif
if
(
pcnet32_debug
>
2
)
printk
(
KERN_DEBUG
PFX
"media reset to %#x.
\n
"
,
media
);
printk
(
KERN_DEBUG
PFX
"media reset to %#x.
\n
"
,
media
);
a
->
write_bcr
(
ioaddr
,
49
,
media
);
a
->
write_bcr
(
ioaddr
,
49
,
media
);
break
;
break
;
...
@@ -621,8 +907,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
...
@@ -621,8 +907,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
* have FIFO's smaller than a packet, so you can't do this.
* have FIFO's smaller than a packet, so you can't do this.
*/
*/
if
(
fset
)
if
(
fset
)
{
{
a
->
write_bcr
(
ioaddr
,
18
,
(
a
->
read_bcr
(
ioaddr
,
18
)
|
0x0800
));
a
->
write_bcr
(
ioaddr
,
18
,
(
a
->
read_bcr
(
ioaddr
,
18
)
|
0x0800
));
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
;
dxsuflo
=
1
;
...
@@ -630,7 +915,8 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
...
@@ -630,7 +915,8 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
}
}
dev
=
alloc_etherdev
(
0
);
dev
=
alloc_etherdev
(
0
);
if
(
!
dev
)
{
if
(
!
dev
)
{
printk
(
KERN_ERR
PFX
"Memory allocation failed.
\n
"
);
ret
=
-
ENOMEM
;
ret
=
-
ENOMEM
;
goto
err_release_region
;
goto
err_release_region
;
}
}
...
@@ -657,12 +943,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
...
@@ -657,12 +943,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
for
(
i
=
0
;
i
<
6
;
i
++
)
for
(
i
=
0
;
i
<
6
;
i
++
)
promaddr
[
i
]
=
inb
(
ioaddr
+
i
);
promaddr
[
i
]
=
inb
(
ioaddr
+
i
);
if
(
memcmp
(
promaddr
,
dev
->
dev_addr
,
6
)
if
(
memcmp
(
promaddr
,
dev
->
dev_addr
,
6
)
||
!
is_valid_ether_addr
(
dev
->
dev_addr
)
)
{
||
!
is_valid_ether_addr
(
dev
->
dev_addr
))
{
#ifndef __powerpc__
#ifndef __powerpc__
if
(
is_valid_ether_addr
(
promaddr
)
)
{
if
(
is_valid_ether_addr
(
promaddr
))
{
#else
#else
if
(
!
is_valid_ether_addr
(
dev
->
dev_addr
)
if
(
!
is_valid_ether_addr
(
dev
->
dev_addr
)
&&
is_valid_ether_addr
(
promaddr
))
{
&&
is_valid_ether_addr
(
promaddr
))
{
#endif
#endif
printk
(
" warning: CSR address invalid,
\n
"
);
printk
(
" warning: CSR address invalid,
\n
"
);
...
@@ -672,13 +958,13 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
...
@@ -672,13 +958,13 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
}
}
/* if the ethernet address is not valid, force to 00:00:00:00:00:00 */
/* if the ethernet address is not valid, force to 00:00:00:00:00:00 */
if
(
!
is_valid_ether_addr
(
dev
->
dev_addr
)
)
if
(
!
is_valid_ether_addr
(
dev
->
dev_addr
)
)
memset
(
dev
->
dev_addr
,
0
,
sizeof
(
dev
->
dev_addr
));
memset
(
dev
->
dev_addr
,
0
,
sizeof
(
dev
->
dev_addr
));
for
(
i
=
0
;
i
<
6
;
i
++
)
for
(
i
=
0
;
i
<
6
;
i
++
)
printk
(
" %2.2x"
,
dev
->
dev_addr
[
i
]
);
printk
(
" %2.2x"
,
dev
->
dev_addr
[
i
]
);
if
(((
chip_version
+
1
)
&
0xfffe
)
==
0x2624
)
{
/* Version 0x2623
or
0x2624 */
if
(((
chip_version
+
1
)
&
0xfffe
)
==
0x2624
)
{
/* Version 0x2623
-
0x2624 */
i
=
a
->
read_csr
(
ioaddr
,
80
)
&
0x0C00
;
/* Check tx_start_pt */
i
=
a
->
read_csr
(
ioaddr
,
80
)
&
0x0C00
;
/* Check tx_start_pt */
printk
(
"
\n
"
KERN_INFO
" tx_start_pt(0x%04x):"
,
i
);
printk
(
"
\n
"
KERN_INFO
" tx_start_pt(0x%04x):"
,
i
);
switch
(
i
>>
10
)
{
switch
(
i
>>
10
)
{
...
@@ -704,6 +990,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
...
@@ -704,6 +990,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
dev
->
base_addr
=
ioaddr
;
dev
->
base_addr
=
ioaddr
;
/* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */
/* 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
)
{
printk
(
KERN_ERR
PFX
"Consistent memory allocation failed.
\n
"
);
ret
=
-
ENOMEM
;
ret
=
-
ENOMEM
;
goto
err_free_netdev
;
goto
err_free_netdev
;
}
}
...
@@ -725,6 +1012,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
...
@@ -725,6 +1012,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
lp
->
dxsuflo
=
dxsuflo
;
lp
->
dxsuflo
=
dxsuflo
;
lp
->
ltint
=
ltint
;
lp
->
ltint
=
ltint
;
lp
->
mii
=
mii
;
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
;
lp
->
options
=
PCNET32_PORT_ASEL
;
else
else
...
@@ -745,7 +1033,8 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
...
@@ -745,7 +1033,8 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
lp
->
a
=
*
a
;
lp
->
a
=
*
a
;
/* detect special T1/E1 WAN card by checking for MAC address */
/* detect special T1/E1 WAN card by checking for MAC address */
if
(
dev
->
dev_addr
[
0
]
==
0x00
&&
dev
->
dev_addr
[
1
]
==
0xe0
&&
dev
->
dev_addr
[
2
]
==
0x75
)
if
(
dev
->
dev_addr
[
0
]
==
0x00
&&
dev
->
dev_addr
[
1
]
==
0xe0
&&
dev
->
dev_addr
[
2
]
==
0x75
)
lp
->
options
=
PCNET32_PORT_FD
|
PCNET32_PORT_GPSI
;
lp
->
options
=
PCNET32_PORT_FD
|
PCNET32_PORT_GPSI
;
lp
->
init_block
.
mode
=
le16_to_cpu
(
0x0003
);
/* Disable Rx and Tx. */
lp
->
init_block
.
mode
=
le16_to_cpu
(
0x0003
);
/* Disable Rx and Tx. */
...
@@ -754,14 +1043,18 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
...
@@ -754,14 +1043,18 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
lp
->
init_block
.
phys_addr
[
i
]
=
dev
->
dev_addr
[
i
];
lp
->
init_block
.
phys_addr
[
i
]
=
dev
->
dev_addr
[
i
];
lp
->
init_block
.
filter
[
0
]
=
0x00000000
;
lp
->
init_block
.
filter
[
0
]
=
0x00000000
;
lp
->
init_block
.
filter
[
1
]
=
0x00000000
;
lp
->
init_block
.
filter
[
1
]
=
0x00000000
;
lp
->
init_block
.
rx_ring
=
(
u32
)
le32_to_cpu
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
rx_ring
));
lp
->
init_block
.
rx_ring
=
(
u32
)
le32_to_cpu
(
lp
->
dma_addr
+
lp
->
init_block
.
tx_ring
=
(
u32
)
le32_to_cpu
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
tx_ring
));
offsetof
(
struct
pcnet32_private
,
rx_ring
));
lp
->
init_block
.
tx_ring
=
(
u32
)
le32_to_cpu
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
tx_ring
));
/* switch pcnet32 to 32bit mode */
/* switch pcnet32 to 32bit mode */
a
->
write_bcr
(
ioaddr
,
20
,
2
);
a
->
write_bcr
(
ioaddr
,
20
,
2
);
a
->
write_csr
(
ioaddr
,
1
,
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
init_block
))
&
0xffff
);
a
->
write_csr
(
ioaddr
,
1
,
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
a
->
write_csr
(
ioaddr
,
2
,
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
init_block
))
>>
16
);
init_block
))
&
0xffff
);
a
->
write_csr
(
ioaddr
,
2
,
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
init_block
))
>>
16
);
if
(
irq_line
)
{
if
(
irq_line
)
{
dev
->
irq
=
irq_line
;
dev
->
irq
=
irq_line
;
...
@@ -805,6 +1098,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
...
@@ -805,6 +1098,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
dev
->
get_stats
=
&
pcnet32_get_stats
;
dev
->
get_stats
=
&
pcnet32_get_stats
;
dev
->
set_multicast_list
=
&
pcnet32_set_multicast_list
;
dev
->
set_multicast_list
=
&
pcnet32_set_multicast_list
;
dev
->
do_ioctl
=
&
pcnet32_ioctl
;
dev
->
do_ioctl
=
&
pcnet32_ioctl
;
dev
->
ethtool_ops
=
&
pcnet32_ethtool_ops
;
dev
->
tx_timeout
=
pcnet32_tx_timeout
;
dev
->
tx_timeout
=
pcnet32_tx_timeout
;
dev
->
watchdog_timeo
=
(
5
*
HZ
);
dev
->
watchdog_timeo
=
(
5
*
HZ
);
...
@@ -812,8 +1106,13 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
...
@@ -812,8 +1106,13 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
if
(
register_netdev
(
dev
))
if
(
register_netdev
(
dev
))
goto
err_free_consistent
;
goto
err_free_consistent
;
if
(
pdev
)
{
pci_set_drvdata
(
pdev
,
dev
);
}
else
{
lp
->
next
=
pcnet32_dev
;
lp
->
next
=
pcnet32_dev
;
pcnet32_dev
=
dev
;
pcnet32_dev
=
dev
;
}
printk
(
KERN_INFO
"%s: registered as %s
\n
"
,
dev
->
name
,
lp
->
name
);
printk
(
KERN_INFO
"%s: registered as %s
\n
"
,
dev
->
name
,
lp
->
name
);
cards_found
++
;
cards_found
++
;
return
0
;
return
0
;
...
@@ -835,6 +1134,7 @@ pcnet32_open(struct net_device *dev)
...
@@ -835,6 +1134,7 @@ pcnet32_open(struct net_device *dev)
unsigned
long
ioaddr
=
dev
->
base_addr
;
unsigned
long
ioaddr
=
dev
->
base_addr
;
u16
val
;
u16
val
;
int
i
;
int
i
;
int
rc
;
if
(
dev
->
irq
==
0
||
if
(
dev
->
irq
==
0
||
request_irq
(
dev
->
irq
,
&
pcnet32_interrupt
,
request_irq
(
dev
->
irq
,
&
pcnet32_interrupt
,
...
@@ -843,8 +1143,10 @@ pcnet32_open(struct net_device *dev)
...
@@ -843,8 +1143,10 @@ pcnet32_open(struct net_device *dev)
}
}
/* Check for a valid station address */
/* Check for a valid station address */
if
(
!
is_valid_ether_addr
(
dev
->
dev_addr
)
)
if
(
!
is_valid_ether_addr
(
dev
->
dev_addr
))
{
return
-
EINVAL
;
rc
=
-
EINVAL
;
goto
err_free_irq
;
}
/* Reset the PCNET32 */
/* Reset the PCNET32 */
lp
->
a
.
reset
(
ioaddr
);
lp
->
a
.
reset
(
ioaddr
);
...
@@ -852,7 +1154,7 @@ pcnet32_open(struct net_device *dev)
...
@@ -852,7 +1154,7 @@ pcnet32_open(struct net_device *dev)
/* switch pcnet32 to 32bit mode */
/* switch pcnet32 to 32bit mode */
lp
->
a
.
write_bcr
(
ioaddr
,
20
,
2
);
lp
->
a
.
write_bcr
(
ioaddr
,
20
,
2
);
if
(
pcnet32_debug
>
1
)
if
(
netif_msg_ifup
(
lp
)
)
printk
(
KERN_DEBUG
"%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.
\n
"
,
printk
(
KERN_DEBUG
"%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.
\n
"
,
dev
->
name
,
dev
->
irq
,
dev
->
name
,
dev
->
irq
,
(
u32
)
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
tx_ring
)),
(
u32
)
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
tx_ring
)),
...
@@ -874,8 +1176,10 @@ pcnet32_open(struct net_device *dev)
...
@@ -874,8 +1176,10 @@ pcnet32_open(struct net_device *dev)
val
|=
2
;
val
|=
2
;
}
else
if
(
lp
->
options
&
PCNET32_PORT_ASEL
)
{
}
else
if
(
lp
->
options
&
PCNET32_PORT_ASEL
)
{
/* workaround of xSeries250, turn on for 79C975 only */
/* workaround of xSeries250, turn on for 79C975 only */
i
=
((
lp
->
a
.
read_csr
(
ioaddr
,
88
)
|
(
lp
->
a
.
read_csr
(
ioaddr
,
89
)
<<
16
))
>>
12
)
&
0xffff
;
i
=
((
lp
->
a
.
read_csr
(
ioaddr
,
88
)
|
if
(
i
==
0x2627
)
val
|=
3
;
(
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
);
}
}
...
@@ -887,14 +1191,16 @@ pcnet32_open(struct net_device *dev)
...
@@ -887,14 +1191,16 @@ pcnet32_open(struct net_device *dev)
lp
->
a
.
write_csr
(
ioaddr
,
124
,
val
);
lp
->
a
.
write_csr
(
ioaddr
,
124
,
val
);
if
(
lp
->
mii
&&
!
(
lp
->
options
&
PCNET32_PORT_ASEL
))
{
if
(
lp
->
mii
&&
!
(
lp
->
options
&
PCNET32_PORT_ASEL
))
{
val
=
lp
->
a
.
read_bcr
(
ioaddr
,
32
)
&
~
0x38
;
/* disable Auto Negotiation, set 10Mpbs, HD */
/* disable Auto Negotiation, set 10Mpbs, HD */
val
=
lp
->
a
.
read_bcr
(
ioaddr
,
32
)
&
~
0x38
;
if
(
lp
->
options
&
PCNET32_PORT_FD
)
if
(
lp
->
options
&
PCNET32_PORT_FD
)
val
|=
0x10
;
val
|=
0x10
;
if
(
lp
->
options
&
PCNET32_PORT_100
)
if
(
lp
->
options
&
PCNET32_PORT_100
)
val
|=
0x08
;
val
|=
0x08
;
lp
->
a
.
write_bcr
(
ioaddr
,
32
,
val
);
lp
->
a
.
write_bcr
(
ioaddr
,
32
,
val
);
}
else
{
}
else
{
if
(
lp
->
options
&
PCNET32_PORT_ASEL
)
{
/* enable auto negotiate, setup, disable fd */
if
(
lp
->
options
&
PCNET32_PORT_ASEL
)
{
/* enable auto negotiate, setup, disable fd */
val
=
lp
->
a
.
read_bcr
(
ioaddr
,
32
)
&
~
0x98
;
val
=
lp
->
a
.
read_bcr
(
ioaddr
,
32
)
&
~
0x98
;
val
|=
0x20
;
val
|=
0x20
;
lp
->
a
.
write_bcr
(
ioaddr
,
32
,
val
);
lp
->
a
.
write_bcr
(
ioaddr
,
32
,
val
);
...
@@ -918,12 +1224,16 @@ pcnet32_open(struct net_device *dev)
...
@@ -918,12 +1224,16 @@ pcnet32_open(struct net_device *dev)
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
]
=
0x00000000
;
lp
->
init_block
.
filter
[
0
]
=
0x00000000
;
lp
->
init_block
.
filter
[
1
]
=
0x00000000
;
lp
->
init_block
.
filter
[
1
]
=
0x00000000
;
if
(
pcnet32_init_ring
(
dev
))
if
(
pcnet32_init_ring
(
dev
))
{
return
-
ENOMEM
;
rc
=
-
ENOMEM
;
goto
err_free_ring
;
}
/* Re-initialize the PCNET32, and start it when done. */
/* 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
,
1
,
(
lp
->
dma_addr
+
lp
->
a
.
write_csr
(
ioaddr
,
2
,
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
init_block
))
>>
16
);
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
,
4
,
0x0915
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0001
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0001
);
...
@@ -946,13 +1256,36 @@ pcnet32_open(struct net_device *dev)
...
@@ -946,13 +1256,36 @@ pcnet32_open(struct net_device *dev)
*/
*/
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0042
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x0042
);
if
(
pcnet32_debug
>
2
)
if
(
netif_msg_ifup
(
lp
)
)
printk
(
KERN_DEBUG
"%s: pcnet32 open after %d ticks, init block %#x csr0 %4.4x.
\n
"
,
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
)),
dev
->
name
,
i
,
(
u32
)
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
init_block
)),
lp
->
a
.
read_csr
(
ioaddr
,
0
));
lp
->
a
.
read_csr
(
ioaddr
,
0
));
return
0
;
/* Always succeed */
return
0
;
/* Always succeed */
err_free_ring:
/* free any allocated skbuffs */
for
(
i
=
0
;
i
<
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
);
dev_kfree_skb
(
lp
->
rx_skbuff
[
i
]);
}
lp
->
rx_skbuff
[
i
]
=
NULL
;
lp
->
rx_dma_addr
[
i
]
=
0
;
}
/*
* Switch back to 16bit mode to avoid problems with dumb
* DOS packet driver after a warm reboot
*/
lp
->
a
.
write_bcr
(
ioaddr
,
20
,
4
);
err_free_irq:
free_irq
(
dev
->
irq
,
dev
);
return
rc
;
}
}
/*
/*
...
@@ -976,7 +1309,8 @@ pcnet32_purge_tx_ring(struct net_device *dev)
...
@@ -976,7 +1309,8 @@ pcnet32_purge_tx_ring(struct net_device *dev)
for
(
i
=
0
;
i
<
TX_RING_SIZE
;
i
++
)
{
for
(
i
=
0
;
i
<
TX_RING_SIZE
;
i
++
)
{
if
(
lp
->
tx_skbuff
[
i
])
{
if
(
lp
->
tx_skbuff
[
i
])
{
pci_unmap_single
(
lp
->
pci_dev
,
lp
->
tx_dma_addr
[
i
],
lp
->
tx_skbuff
[
i
]
->
len
,
PCI_DMA_TODEVICE
);
pci_unmap_single
(
lp
->
pci_dev
,
lp
->
tx_dma_addr
[
i
],
lp
->
tx_skbuff
[
i
]
->
len
,
PCI_DMA_TODEVICE
);
dev_kfree_skb_any
(
lp
->
tx_skbuff
[
i
]);
dev_kfree_skb_any
(
lp
->
tx_skbuff
[
i
]);
lp
->
tx_skbuff
[
i
]
=
NULL
;
lp
->
tx_skbuff
[
i
]
=
NULL
;
lp
->
tx_dma_addr
[
i
]
=
0
;
lp
->
tx_dma_addr
[
i
]
=
0
;
...
@@ -1001,32 +1335,36 @@ pcnet32_init_ring(struct net_device *dev)
...
@@ -1001,32 +1335,36 @@ pcnet32_init_ring(struct net_device *dev)
if
(
rx_skbuff
==
NULL
)
{
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 */
/* there is not much, we can do at this point */
printk
(
KERN_ERR
"%s: pcnet32_init_ring dev_alloc_skb failed.
\n
"
,
dev
->
name
);
printk
(
KERN_ERR
"%s: pcnet32_init_ring dev_alloc_skb failed.
\n
"
,
dev
->
name
);
return
-
1
;
return
-
1
;
}
}
skb_reserve
(
rx_skbuff
,
2
);
skb_reserve
(
rx_skbuff
,
2
);
}
}
if
(
lp
->
rx_dma_addr
[
i
]
==
0
)
if
(
lp
->
rx_dma_addr
[
i
]
==
0
)
lp
->
rx_dma_addr
[
i
]
=
pci_map_single
(
lp
->
pci_dev
,
lp
->
rx_dma_addr
[
i
]
=
pci_map_single
(
lp
->
pci_dev
,
rx_skbuff
->
tail
,
rx_skbuff
->
tail
,
PKT_BUF_SZ
-
2
,
PCI_DMA_FROMDEVICE
);
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
].
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_ring
[
i
].
buf_length
=
le16_to_cpu
(
2
-
PKT_BUF_SZ
);
lp
->
rx_ring
[
i
].
status
=
le16_to_cpu
(
0x8000
);
lp
->
rx_ring
[
i
].
status
=
le16_to_cpu
(
0x8000
);
}
}
/* The Tx buffer address is filled in as needed, but we do need to clear
/* The Tx buffer address is filled in as needed, but we do need to clear
the upper ownership bit. */
*
the upper ownership bit. */
for
(
i
=
0
;
i
<
TX_RING_SIZE
;
i
++
)
{
for
(
i
=
0
;
i
<
TX_RING_SIZE
;
i
++
)
{
lp
->
tx_ring
[
i
].
base
=
0
;
lp
->
tx_ring
[
i
].
base
=
0
;
lp
->
tx_ring
[
i
].
status
=
0
;
lp
->
tx_ring
[
i
].
status
=
0
;
lp
->
tx_dma_addr
[
i
]
=
0
;
lp
->
tx_dma_addr
[
i
]
=
0
;
}
}
wmb
();
/* Make sure all changes are visible */
lp
->
init_block
.
tlen_rlen
=
le16_to_cpu
(
TX_RING_LEN_BITS
|
RX_RING_LEN_BITS
);
lp
->
init_block
.
tlen_rlen
=
le16_to_cpu
(
TX_RING_LEN_BITS
|
RX_RING_LEN_BITS
);
for
(
i
=
0
;
i
<
6
;
i
++
)
for
(
i
=
0
;
i
<
6
;
i
++
)
lp
->
init_block
.
phys_addr
[
i
]
=
dev
->
dev_addr
[
i
];
lp
->
init_block
.
phys_addr
[
i
]
=
dev
->
dev_addr
[
i
];
lp
->
init_block
.
rx_ring
=
(
u32
)
le32_to_cpu
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
rx_ring
));
lp
->
init_block
.
rx_ring
=
(
u32
)
le32_to_cpu
(
lp
->
dma_addr
+
lp
->
init_block
.
tx_ring
=
(
u32
)
le32_to_cpu
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
tx_ring
));
offsetof
(
struct
pcnet32_private
,
rx_ring
));
lp
->
init_block
.
tx_ring
=
(
u32
)
le32_to_cpu
(
lp
->
dma_addr
+
offsetof
(
struct
pcnet32_private
,
tx_ring
));
return
0
;
return
0
;
}
}
...
@@ -1064,7 +1402,7 @@ pcnet32_tx_timeout (struct net_device *dev)
...
@@ -1064,7 +1402,7 @@ pcnet32_tx_timeout (struct net_device *dev)
dev
->
name
,
lp
->
a
.
read_csr
(
ioaddr
,
0
));
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
++
;
lp
->
stats
.
tx_errors
++
;
if
(
pcnet32_debug
>
2
)
{
if
(
netif_msg_tx_err
(
lp
)
)
{
int
i
;
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
->
dirty_tx
,
lp
->
cur_tx
,
lp
->
tx_full
?
" (full)"
:
""
,
...
@@ -1097,7 +1435,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
...
@@ -1097,7 +1435,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
int
entry
;
int
entry
;
unsigned
long
flags
;
unsigned
long
flags
;
if
(
pcnet32_debug
>
3
)
{
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
));
dev
->
name
,
lp
->
a
.
read_csr
(
ioaddr
,
0
));
}
}
...
@@ -1127,14 +1465,15 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
...
@@ -1127,14 +1465,15 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
entry
=
lp
->
cur_tx
&
TX_RING_MOD_MASK
;
entry
=
lp
->
cur_tx
&
TX_RING_MOD_MASK
;
/* Caution: the write order is important here, set the status
/* Caution: the write order is important here, set the status
with the "ownership" bits last. */
*
with the "ownership" bits last. */
lp
->
tx_ring
[
entry
].
length
=
le16_to_cpu
(
-
skb
->
len
);
lp
->
tx_ring
[
entry
].
length
=
le16_to_cpu
(
-
skb
->
len
);
lp
->
tx_ring
[
entry
].
misc
=
0x00000000
;
lp
->
tx_ring
[
entry
].
misc
=
0x00000000
;
lp
->
tx_skbuff
[
entry
]
=
skb
;
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_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_ring
[
entry
].
base
=
(
u32
)
le32_to_cpu
(
lp
->
tx_dma_addr
[
entry
]);
wmb
();
/* Make sure owner changes after all others are visible */
wmb
();
/* Make sure owner changes after all others are visible */
lp
->
tx_ring
[
entry
].
status
=
le16_to_cpu
(
status
);
lp
->
tx_ring
[
entry
].
status
=
le16_to_cpu
(
status
);
...
@@ -1147,9 +1486,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
...
@@ -1147,9 +1486,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev
->
trans_start
=
jiffies
;
dev
->
trans_start
=
jiffies
;
if
(
lp
->
tx_ring
[(
entry
+
1
)
&
TX_RING_MOD_MASK
].
base
==
0
)
if
(
lp
->
tx_ring
[(
entry
+
1
)
&
TX_RING_MOD_MASK
].
base
!=
0
)
{
netif_wake_queue
(
dev
);
else
{
lp
->
tx_full
=
1
;
lp
->
tx_full
=
1
;
netif_stop_queue
(
dev
);
netif_stop_queue
(
dev
);
}
}
...
@@ -1181,12 +1518,15 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
...
@@ -1181,12 +1518,15 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
rap
=
lp
->
a
.
read_rap
(
ioaddr
);
rap
=
lp
->
a
.
read_rap
(
ioaddr
);
while
((
csr0
=
lp
->
a
.
read_csr
(
ioaddr
,
0
))
&
0x8600
&&
--
boguscnt
>=
0
)
{
while
((
csr0
=
lp
->
a
.
read_csr
(
ioaddr
,
0
))
&
0x8600
&&
--
boguscnt
>=
0
)
{
if
(
csr0
==
0xffff
)
{
break
;
/* PCMCIA remove happened */
}
/* Acknowledge all of the current interrupt sources ASAP. */
/* 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
;
must_restart
=
0
;
if
(
pcnet32_debug
>
5
)
if
(
netif_msg_intr
(
lp
)
)
printk
(
KERN_DEBUG
"%s: interrupt csr0=%#2.2x new csr=%#2.2x.
\n
"
,
printk
(
KERN_DEBUG
"%s: interrupt csr0=%#2.2x new csr=%#2.2x.
\n
"
,
dev
->
name
,
csr0
,
lp
->
a
.
read_csr
(
ioaddr
,
0
));
dev
->
name
,
csr0
,
lp
->
a
.
read_csr
(
ioaddr
,
0
));
...
@@ -1275,11 +1615,12 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
...
@@ -1275,11 +1615,12 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
/*
/*
* this happens when our receive ring is full. This shouldn't
* this happens when our receive ring is full. This shouldn't
* be a problem as we will see normal rx interrupts for the frames
* be a problem as we will see normal rx interrupts for the frames
* in the receive ring. But there are some PCI chipsets (I can reproduce
* in the receive ring. But there are some PCI chipsets (I can
* this on SP3G with Intel saturn chipset) which have sometimes problems
* reproduce this on SP3G with Intel saturn chipset) which have
* and will fill up the receive ring with error descriptors. In this
* sometimes problems and will fill up the receive ring with
* situation we don't get a rx interrupt, but a missed frame interrupt sooner
* error descriptors. In this situation we don't get a rx
* or later. So we try to clean up our receive ring here.
* interrupt, but a missed frame interrupt sooner or later.
* So we try to clean up our receive ring here.
*/
*/
pcnet32_rx
(
dev
);
pcnet32_rx
(
dev
);
lp
->
stats
.
rx_errors
++
;
/* Missed a Rx frame. */
lp
->
stats
.
rx_errors
++
;
/* Missed a Rx frame. */
...
@@ -1301,7 +1642,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
...
@@ -1301,7 +1642,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x7940
);
lp
->
a
.
write_csr
(
ioaddr
,
0
,
0x7940
);
lp
->
a
.
write_rap
(
ioaddr
,
rap
);
lp
->
a
.
write_rap
(
ioaddr
,
rap
);
if
(
pcnet32_debug
>
4
)
if
(
netif_msg_intr
(
lp
)
)
printk
(
KERN_DEBUG
"%s: exiting interrupt, csr0=%#4.4x.
\n
"
,
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
));
...
@@ -1339,7 +1680,7 @@ pcnet32_rx(struct net_device *dev)
...
@@ -1339,7 +1680,7 @@ pcnet32_rx(struct net_device *dev)
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
;
struct
sk_buff
*
skb
;
if
(
pkt_len
<
60
)
{
if
(
pkt_len
<
60
)
{
printk
(
KERN_ERR
"%s: Runt packet!
\n
"
,
dev
->
name
);
printk
(
KERN_ERR
"%s: Runt packet!
\n
"
,
dev
->
name
);
lp
->
stats
.
rx_errors
++
;
lp
->
stats
.
rx_errors
++
;
}
else
{
}
else
{
...
@@ -1348,7 +1689,7 @@ pcnet32_rx(struct net_device *dev)
...
@@ -1348,7 +1689,7 @@ pcnet32_rx(struct net_device *dev)
if
(
pkt_len
>
rx_copybreak
)
{
if
(
pkt_len
>
rx_copybreak
)
{
struct
sk_buff
*
newskb
;
struct
sk_buff
*
newskb
;
if
((
newskb
=
dev_alloc_skb
(
PKT_BUF_SZ
)))
{
if
((
newskb
=
dev_alloc_skb
(
PKT_BUF_SZ
)))
{
skb_reserve
(
newskb
,
2
);
skb_reserve
(
newskb
,
2
);
skb
=
lp
->
rx_skbuff
[
entry
];
skb
=
lp
->
rx_skbuff
[
entry
];
pci_unmap_single
(
lp
->
pci_dev
,
lp
->
rx_dma_addr
[
entry
],
pci_unmap_single
(
lp
->
pci_dev
,
lp
->
rx_dma_addr
[
entry
],
...
@@ -1369,9 +1710,11 @@ pcnet32_rx(struct net_device *dev)
...
@@ -1369,9 +1710,11 @@ pcnet32_rx(struct net_device *dev)
if
(
skb
==
NULL
)
{
if
(
skb
==
NULL
)
{
int
i
;
int
i
;
printk
(
KERN_ERR
"%s: Memory squeeze, deferring packet.
\n
"
,
dev
->
name
);
printk
(
KERN_ERR
"%s: Memory squeeze, deferring packet.
\n
"
,
dev
->
name
);
for
(
i
=
0
;
i
<
RX_RING_SIZE
;
i
++
)
for
(
i
=
0
;
i
<
RX_RING_SIZE
;
i
++
)
if
((
short
)
le16_to_cpu
(
lp
->
rx_ring
[(
entry
+
i
)
&
RX_RING_MOD_MASK
].
status
)
<
0
)
if
((
short
)
le16_to_cpu
(
lp
->
rx_ring
[(
entry
+
i
)
&
RX_RING_MOD_MASK
].
status
)
<
0
)
break
;
break
;
if
(
i
>
RX_RING_SIZE
-
2
)
{
if
(
i
>
RX_RING_SIZE
-
2
)
{
...
@@ -1405,6 +1748,7 @@ pcnet32_rx(struct net_device *dev)
...
@@ -1405,6 +1748,7 @@ pcnet32_rx(struct net_device *dev)
* of QNX reports that some revs of the 79C965 clear it.
* 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
);
lp
->
rx_ring
[
entry
].
status
|=
le16_to_cpu
(
0x8000
);
entry
=
(
++
lp
->
cur_rx
)
&
RX_RING_MOD_MASK
;
entry
=
(
++
lp
->
cur_rx
)
&
RX_RING_MOD_MASK
;
}
}
...
@@ -1425,7 +1769,7 @@ pcnet32_close(struct net_device *dev)
...
@@ -1425,7 +1769,7 @@ pcnet32_close(struct net_device *dev)
lp
->
stats
.
rx_missed_errors
=
lp
->
a
.
read_csr
(
ioaddr
,
112
);
lp
->
stats
.
rx_missed_errors
=
lp
->
a
.
read_csr
(
ioaddr
,
112
);
if
(
pcnet32_debug
>
1
)
if
(
netif_msg_ifdown
(
lp
)
)
printk
(
KERN_DEBUG
"%s: Shutting down ethercard, status was %2.2x.
\n
"
,
printk
(
KERN_DEBUG
"%s: Shutting down ethercard, status was %2.2x.
\n
"
,
dev
->
name
,
lp
->
a
.
read_csr
(
ioaddr
,
0
));
dev
->
name
,
lp
->
a
.
read_csr
(
ioaddr
,
0
));
...
@@ -1454,7 +1798,8 @@ pcnet32_close(struct net_device *dev)
...
@@ -1454,7 +1798,8 @@ pcnet32_close(struct net_device *dev)
for
(
i
=
0
;
i
<
TX_RING_SIZE
;
i
++
)
{
for
(
i
=
0
;
i
<
TX_RING_SIZE
;
i
++
)
{
if
(
lp
->
tx_skbuff
[
i
])
{
if
(
lp
->
tx_skbuff
[
i
])
{
pci_unmap_single
(
lp
->
pci_dev
,
lp
->
tx_dma_addr
[
i
],
lp
->
tx_skbuff
[
i
]
->
len
,
PCI_DMA_TODEVICE
);
pci_unmap_single
(
lp
->
pci_dev
,
lp
->
tx_dma_addr
[
i
],
lp
->
tx_skbuff
[
i
]
->
len
,
PCI_DMA_TODEVICE
);
dev_kfree_skb
(
lp
->
tx_skbuff
[
i
]);
dev_kfree_skb
(
lp
->
tx_skbuff
[
i
]);
}
}
lp
->
tx_skbuff
[
i
]
=
NULL
;
lp
->
tx_skbuff
[
i
]
=
NULL
;
...
@@ -1493,7 +1838,7 @@ static void pcnet32_load_multicast (struct net_device *dev)
...
@@ -1493,7 +1838,7 @@ static void pcnet32_load_multicast (struct net_device *dev)
u32
crc
;
u32
crc
;
/* set all multicast bits */
/* set all multicast bits */
if
(
dev
->
flags
&
IFF_ALLMULTI
)
{
if
(
dev
->
flags
&
IFF_ALLMULTI
)
{
ib
->
filter
[
0
]
=
0xffffffff
;
ib
->
filter
[
0
]
=
0xffffffff
;
ib
->
filter
[
1
]
=
0xffffffff
;
ib
->
filter
[
1
]
=
0xffffffff
;
return
;
return
;
...
@@ -1503,7 +1848,7 @@ static void pcnet32_load_multicast (struct net_device *dev)
...
@@ -1503,7 +1848,7 @@ static void pcnet32_load_multicast (struct net_device *dev)
ib
->
filter
[
1
]
=
0
;
ib
->
filter
[
1
]
=
0
;
/* Add addresses */
/* Add addresses */
for
(
i
=
0
;
i
<
dev
->
mc_count
;
i
++
){
for
(
i
=
0
;
i
<
dev
->
mc_count
;
i
++
)
{
addrs
=
dmi
->
dmi_addr
;
addrs
=
dmi
->
dmi_addr
;
dmi
=
dmi
->
next
;
dmi
=
dmi
->
next
;
...
@@ -1514,8 +1859,7 @@ static void pcnet32_load_multicast (struct net_device *dev)
...
@@ -1514,8 +1859,7 @@ static void pcnet32_load_multicast (struct net_device *dev)
crc
=
ether_crc_le
(
6
,
addrs
);
crc
=
ether_crc_le
(
6
,
addrs
);
crc
=
crc
>>
26
;
crc
=
crc
>>
26
;
mcast_table
[
crc
>>
4
]
=
le16_to_cpu
(
mcast_table
[
crc
>>
4
]
=
le16_to_cpu
(
le16_to_cpu
(
mcast_table
[
crc
>>
4
])
|
(
1
<<
(
crc
&
0xf
))
le16_to_cpu
(
mcast_table
[
crc
>>
4
])
|
(
1
<<
(
crc
&
0xf
)));
);
}
}
return
;
return
;
}
}
...
@@ -1580,100 +1924,6 @@ static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val)
...
@@ -1580,100 +1924,6 @@ static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val)
lp
->
a
.
write_bcr
(
ioaddr
,
33
,
phyaddr
);
lp
->
a
.
write_bcr
(
ioaddr
,
33
,
phyaddr
);
}
}
static
int
pcnet32_ethtool_ioctl
(
struct
net_device
*
dev
,
void
*
useraddr
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
u32
ethcmd
;
int
phyaddr
=
0
;
int
phy_id
=
0
;
unsigned
long
ioaddr
=
dev
->
base_addr
;
if
(
lp
->
mii
)
{
phyaddr
=
lp
->
a
.
read_bcr
(
ioaddr
,
33
);
phy_id
=
(
phyaddr
>>
5
)
&
0x1f
;
lp
->
mii_if
.
phy_id
=
phy_id
;
}
if
(
copy_from_user
(
&
ethcmd
,
useraddr
,
sizeof
(
ethcmd
)))
return
-
EFAULT
;
switch
(
ethcmd
)
{
case
ETHTOOL_GDRVINFO
:
{
struct
ethtool_drvinfo
info
=
{
ETHTOOL_GDRVINFO
};
strcpy
(
info
.
driver
,
DRV_NAME
);
strcpy
(
info
.
version
,
DRV_VERSION
);
if
(
lp
->
pci_dev
)
strcpy
(
info
.
bus_info
,
pci_name
(
lp
->
pci_dev
));
else
sprintf
(
info
.
bus_info
,
"VLB 0x%lx"
,
dev
->
base_addr
);
if
(
copy_to_user
(
useraddr
,
&
info
,
sizeof
(
info
)))
return
-
EFAULT
;
return
0
;
}
/* get settings */
case
ETHTOOL_GSET
:
{
struct
ethtool_cmd
ecmd
=
{
ETHTOOL_GSET
};
spin_lock_irq
(
&
lp
->
lock
);
mii_ethtool_gset
(
&
lp
->
mii_if
,
&
ecmd
);
spin_unlock_irq
(
&
lp
->
lock
);
if
(
copy_to_user
(
useraddr
,
&
ecmd
,
sizeof
(
ecmd
)))
return
-
EFAULT
;
return
0
;
}
/* set settings */
case
ETHTOOL_SSET
:
{
int
r
;
struct
ethtool_cmd
ecmd
;
if
(
copy_from_user
(
&
ecmd
,
useraddr
,
sizeof
(
ecmd
)))
return
-
EFAULT
;
spin_lock_irq
(
&
lp
->
lock
);
r
=
mii_ethtool_sset
(
&
lp
->
mii_if
,
&
ecmd
);
spin_unlock_irq
(
&
lp
->
lock
);
return
r
;
}
/* restart autonegotiation */
case
ETHTOOL_NWAY_RST
:
{
int
r
;
spin_lock_irq
(
&
lp
->
lock
);
r
=
mii_nway_restart
(
&
lp
->
mii_if
);
spin_unlock_irq
(
&
lp
->
lock
);
return
r
;
}
/* get link status */
case
ETHTOOL_GLINK
:
{
struct
ethtool_value
edata
=
{
ETHTOOL_GLINK
};
spin_lock_irq
(
&
lp
->
lock
);
edata
.
data
=
mii_link_ok
(
&
lp
->
mii_if
);
spin_unlock_irq
(
&
lp
->
lock
);
if
(
copy_to_user
(
useraddr
,
&
edata
,
sizeof
(
edata
)))
return
-
EFAULT
;
return
0
;
}
/* get message-level */
case
ETHTOOL_GMSGLVL
:
{
struct
ethtool_value
edata
=
{
ETHTOOL_GMSGLVL
};
edata
.
data
=
pcnet32_debug
;
if
(
copy_to_user
(
useraddr
,
&
edata
,
sizeof
(
edata
)))
return
-
EFAULT
;
return
0
;
}
/* set message-level */
case
ETHTOOL_SMSGLVL
:
{
struct
ethtool_value
edata
;
if
(
copy_from_user
(
&
edata
,
useraddr
,
sizeof
(
edata
)))
return
-
EFAULT
;
pcnet32_debug
=
edata
.
data
;
return
0
;
}
default:
break
;
}
return
-
EOPNOTSUPP
;
}
static
int
pcnet32_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
)
static
int
pcnet32_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
)
{
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
struct
pcnet32_private
*
lp
=
dev
->
priv
;
...
@@ -1681,9 +1931,6 @@ static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
...
@@ -1681,9 +1931,6 @@ static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
int
rc
;
int
rc
;
unsigned
long
flags
;
unsigned
long
flags
;
if
(
cmd
==
SIOCETHTOOL
)
return
pcnet32_ethtool_ioctl
(
dev
,
(
void
*
)
rq
->
ifr_data
);
/* SIOC[GS]MIIxxx ioctls */
/* SIOC[GS]MIIxxx ioctls */
if
(
lp
->
mii
)
{
if
(
lp
->
mii
)
{
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
...
@@ -1711,14 +1958,30 @@ static void pcnet32_watchdog(struct net_device *dev)
...
@@ -1711,14 +1958,30 @@ static void pcnet32_watchdog(struct net_device *dev)
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
)
{
struct
net_device
*
dev
=
pci_get_drvdata
(
pdev
);
if
(
dev
)
{
struct
pcnet32_private
*
lp
=
dev
->
priv
;
unregister_netdev
(
dev
);
release_region
(
dev
->
base_addr
,
PCNET32_TOTAL_SIZE
);
pci_free_consistent
(
lp
->
pci_dev
,
sizeof
(
*
lp
),
lp
,
lp
->
dma_addr
);
free_netdev
(
dev
);
pci_set_drvdata
(
pdev
,
NULL
);
}
}
static
struct
pci_driver
pcnet32_driver
=
{
static
struct
pci_driver
pcnet32_driver
=
{
.
name
=
DRV_NAME
,
.
name
=
DRV_NAME
,
.
probe
=
pcnet32_probe_pci
,
.
probe
=
pcnet32_probe_pci
,
.
remove
=
__devexit_p
(
pcnet32_remove_one
),
.
id_table
=
pcnet32_pci_tbl
,
.
id_table
=
pcnet32_pci_tbl
,
};
};
MODULE_PARM
(
debug
,
"i"
);
MODULE_PARM
(
debug
,
"i"
);
MODULE_PARM_DESC
(
debug
,
DRV_NAME
" debug level
(0-6)
"
);
MODULE_PARM_DESC
(
debug
,
DRV_NAME
" debug level"
);
MODULE_PARM
(
max_interrupt_work
,
"i"
);
MODULE_PARM
(
max_interrupt_work
,
"i"
);
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_PARM
(
rx_copybreak
,
"i"
);
MODULE_PARM
(
rx_copybreak
,
"i"
);
...
@@ -1745,8 +2008,8 @@ static int __init pcnet32_init_module(void)
...
@@ -1745,8 +2008,8 @@ static int __init pcnet32_init_module(void)
{
{
printk
(
KERN_INFO
"%s"
,
version
);
printk
(
KERN_INFO
"%s"
,
version
);
if
(
debug
>
0
)
if
(
debug
>
=
0
&&
debug
<
(
sizeof
(
int
)
-
1
)
)
pcnet32_debug
=
debug
;
pcnet32_debug
=
1
<<
debug
;
if
((
tx_start_pt
>=
0
)
&&
(
tx_start_pt
<=
3
))
if
((
tx_start_pt
>=
0
)
&&
(
tx_start_pt
<=
3
))
tx_start
=
tx_start_pt
;
tx_start
=
tx_start_pt
;
...
...
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