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
nexedi
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