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
645870ac
Commit
645870ac
authored
Oct 27, 2002
by
Alan Cox
Committed by
Linus Torvalds
Oct 27, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] resurrect the 3c589_cs pcmcia
parent
a0e8dc91
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
48 additions
and
40 deletions
+48
-40
drivers/net/pcmcia/3c589_cs.c
drivers/net/pcmcia/3c589_cs.c
+48
-40
No files found.
drivers/net/pcmcia/3c589_cs.c
View file @
645870ac
...
...
@@ -14,11 +14,13 @@
distributed according to the terms of the GNU General Public License,
incorporated herein by reference.
Donald Becker may be reached at becker@scyld.com
Updated for 2.5.x by Alan Cox <alan@redhat.com>
======================================================================*/
#define DRV_NAME "3c589_cs"
#define DRV_VERSION "1.162"
#define DRV_VERSION "1.162
-ac
"
#include <linux/module.h>
#include <linux/init.h>
...
...
@@ -111,9 +113,10 @@ struct el3_private {
struct
net_device_stats
stats
;
/* For transceiver monitoring */
struct
timer_list
media
;
u_short
media_status
;
u_short
fast_poll
;
u_long
last_irq
;
u16
media_status
;
u16
fast_poll
;
unsigned
long
last_irq
;
spinlock_t
lock
;
};
static
char
*
if_names
[]
=
{
"auto"
,
"10baseT"
,
"10base2"
,
"AUI"
};
...
...
@@ -148,13 +151,13 @@ DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)";
/*====================================================================*/
static
void
tc589_config
(
dev_link_t
*
link
);
static
void
tc589_release
(
u
_
long
arg
);
static
void
tc589_release
(
u
nsigned
long
arg
);
static
int
tc589_event
(
event_t
event
,
int
priority
,
event_callback_args_t
*
args
);
static
u
_short
read_eeprom
(
ioaddr_t
ioaddr
,
int
index
);
static
u
16
read_eeprom
(
ioaddr_t
ioaddr
,
int
index
);
static
void
tc589_reset
(
struct
net_device
*
dev
);
static
void
media_check
(
u
_
long
arg
);
static
void
media_check
(
u
nsigned
long
arg
);
static
int
el3_config
(
struct
net_device
*
dev
,
struct
ifmap
*
map
);
static
int
el3_open
(
struct
net_device
*
dev
);
static
int
el3_start_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
);
...
...
@@ -223,11 +226,13 @@ static dev_link_t *tc589_attach(void)
lp
=
kmalloc
(
sizeof
(
*
lp
),
GFP_KERNEL
);
if
(
!
lp
)
return
NULL
;
memset
(
lp
,
0
,
sizeof
(
*
lp
));
spin_lock_init
(
&
lp
->
lock
);
link
=
&
lp
->
link
;
dev
=
&
lp
->
dev
;
link
->
priv
=
dev
->
priv
=
link
->
irq
.
Instance
=
lp
;
link
->
release
.
function
=
&
tc589_release
;
link
->
release
.
data
=
(
u
_
long
)
link
;
link
->
release
.
data
=
(
u
nsigned
long
)
link
;
link
->
io
.
NumPorts1
=
16
;
link
->
io
.
Attributes1
=
IO_DATA_PATH_WIDTH_16
;
link
->
irq
.
Attributes
=
IRQ_TYPE_EXCLUSIVE
|
IRQ_HANDLE_PRESENT
;
...
...
@@ -302,9 +307,9 @@ static void tc589_detach(dev_link_t *link)
if
(
*
linkp
==
NULL
)
return
;
del_timer
(
&
link
->
release
);
del_timer
_sync
(
&
link
->
release
);
if
(
link
->
state
&
DEV_CONFIG
)
{
tc589_release
((
u
_
long
)
link
);
tc589_release
((
u
nsigned
long
)
link
);
if
(
link
->
state
&
DEV_STALE_CONFIG
)
{
link
->
state
|=
DEV_STALE_LINK
;
return
;
...
...
@@ -340,14 +345,14 @@ static void tc589_config(dev_link_t *link)
struct
net_device
*
dev
=
&
lp
->
dev
;
tuple_t
tuple
;
cisparse_t
parse
;
u
_short
buf
[
32
],
*
phys_addr
;
u
16
buf
[
32
],
*
phys_addr
;
int
last_fn
,
last_ret
,
i
,
j
,
multi
=
0
;
ioaddr_t
ioaddr
;
char
*
ram_split
[]
=
{
"5:3"
,
"3:1"
,
"1:1"
,
"3:5"
};
DEBUG
(
0
,
"3c589_config(0x%p)
\n
"
,
link
);
phys_addr
=
(
u
_short
*
)
dev
->
dev_addr
;
phys_addr
=
(
u
16
*
)
dev
->
dev_addr
;
tuple
.
Attributes
=
0
;
tuple
.
DesiredTuple
=
CISTPL_CONFIG
;
CS_CHECK
(
GetFirstTuple
,
handle
,
&
tuple
);
...
...
@@ -391,7 +396,7 @@ static void tc589_config(dev_link_t *link)
dev
->
irq
=
link
->
irq
.
AssignedIRQ
;
dev
->
base_addr
=
link
->
io
.
BasePort1
;
if
(
register_netdev
(
dev
)
!=
0
)
{
printk
(
KERN_
NOTICE
"3c589_cs: register_netdev() failed
\n
"
);
printk
(
KERN_
ERR
"3c589_cs: register_netdev() failed
\n
"
);
goto
failed
;
}
...
...
@@ -409,7 +414,7 @@ static void tc589_config(dev_link_t *link)
for
(
i
=
0
;
i
<
3
;
i
++
)
phys_addr
[
i
]
=
htons
(
read_eeprom
(
ioaddr
,
i
));
if
(
phys_addr
[
0
]
==
0x6060
)
{
printk
(
KERN_
NOTICE
"3c589_cs: IO port conflict at 0x%03lx"
printk
(
KERN_
ERR
"3c589_cs: IO port conflict at 0x%03lx"
"-0x%03lx
\n
"
,
dev
->
base_addr
,
dev
->
base_addr
+
15
);
goto
failed
;
}
...
...
@@ -427,7 +432,7 @@ static void tc589_config(dev_link_t *link)
if
((
if_port
>=
0
)
&&
(
if_port
<=
3
))
dev
->
if_port
=
if_port
;
else
printk
(
KERN_
NOTICE
"3c589_cs: invalid if_port requested
\n
"
);
printk
(
KERN_
ERR
"3c589_cs: invalid if_port requested
\n
"
);
printk
(
KERN_INFO
"%s: 3Com 3c%s, io %#3lx, irq %d, hw_addr "
,
dev
->
name
,
(
multi
?
"562"
:
"589"
),
dev
->
base_addr
,
...
...
@@ -443,7 +448,7 @@ static void tc589_config(dev_link_t *link)
cs_failed:
cs_error
(
link
->
handle
,
last_fn
,
last_ret
);
failed:
tc589_release
((
u
_
long
)
link
);
tc589_release
((
u
nsigned
long
)
link
);
return
;
}
/* tc589_config */
...
...
@@ -456,7 +461,7 @@ static void tc589_config(dev_link_t *link)
======================================================================*/
static
void
tc589_release
(
u
_
long
arg
)
static
void
tc589_release
(
u
nsigned
long
arg
)
{
dev_link_t
*
link
=
(
dev_link_t
*
)
arg
;
...
...
@@ -545,7 +550,7 @@ static void tc589_wait_for_completion(struct net_device *dev, int cmd)
while
(
--
i
>
0
)
if
(
!
(
inw
(
dev
->
base_addr
+
EL3_STATUS
)
&
0x1000
))
break
;
if
(
i
==
0
)
printk
(
KERN_
NOTICE
"%s: command 0x%04x did not complete!
\n
"
,
printk
(
KERN_
WARNING
"%s: command 0x%04x did not complete!
\n
"
,
dev
->
name
,
cmd
);
}
...
...
@@ -553,7 +558,7 @@ static void tc589_wait_for_completion(struct net_device *dev, int cmd)
Read a word from the EEPROM using the regular EEPROM access register.
Assume that we are in register window zero.
*/
static
u
_short
read_eeprom
(
ioaddr_t
ioaddr
,
int
index
)
static
u
16
read_eeprom
(
ioaddr_t
ioaddr
,
int
index
)
{
int
i
;
outw
(
EEPROM_READ
+
index
,
ioaddr
+
10
);
...
...
@@ -741,7 +746,7 @@ static int el3_open(struct net_device *dev)
tc589_reset
(
dev
);
lp
->
media
.
function
=
&
media_check
;
lp
->
media
.
data
=
(
u
_
long
)
lp
;
lp
->
media
.
data
=
(
u
nsigned
long
)
lp
;
lp
->
media
.
expires
=
jiffies
+
HZ
;
add_timer
(
&
lp
->
media
);
...
...
@@ -756,7 +761,7 @@ static void el3_tx_timeout(struct net_device *dev)
struct
el3_private
*
lp
=
(
struct
el3_private
*
)
dev
->
priv
;
ioaddr_t
ioaddr
=
dev
->
base_addr
;
printk
(
KERN_
NOTICE
"%s: Transmit timed out!
\n
"
,
dev
->
name
);
printk
(
KERN_
WARNING
"%s: Transmit timed out!
\n
"
,
dev
->
name
);
dump_status
(
dev
);
lp
->
stats
.
tx_errors
++
;
dev
->
trans_start
=
jiffies
;
...
...
@@ -832,7 +837,8 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
DEBUG
(
3
,
"%s: interrupt, status %4.4x.
\n
"
,
dev
->
name
,
inw
(
ioaddr
+
EL3_STATUS
));
spin_lock
(
&
lp
->
lock
);
while
((
status
=
inw
(
ioaddr
+
EL3_STATUS
))
&
(
IntLatch
|
RxComplete
|
StatsFull
))
{
if
(
!
netif_device_present
(
dev
)
||
...
...
@@ -867,7 +873,7 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
EL3WINDOW
(
4
);
fifo_diag
=
inw
(
ioaddr
+
4
);
EL3WINDOW
(
1
);
printk
(
KERN_
NOTICE
"%s: adapter failure, FIFO diagnostic"
printk
(
KERN_
WARNING
"%s: adapter failure, FIFO diagnostic"
" register %04x.
\n
"
,
dev
->
name
,
fifo_diag
);
if
(
fifo_diag
&
0x0400
)
{
/* Tx overrun */
...
...
@@ -885,7 +891,7 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
if
(
++
i
>
10
)
{
printk
(
KERN_
NOTICE
"%s: infinite loop in interrupt, "
printk
(
KERN_
ERR
"%s: infinite loop in interrupt, "
"status %4.4x.
\n
"
,
dev
->
name
,
status
);
/* Clear all interrupts */
outw
(
AckIntr
|
0xFF
,
ioaddr
+
EL3_CMD
);
...
...
@@ -896,18 +902,19 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
lp
->
last_irq
=
jiffies
;
spin_unlock
(
&
lp
->
lock
);
DEBUG
(
3
,
"%s: exiting interrupt, status %4.4x.
\n
"
,
dev
->
name
,
inw
(
ioaddr
+
EL3_STATUS
));
return
;
}
static
void
media_check
(
u
_
long
arg
)
static
void
media_check
(
u
nsigned
long
arg
)
{
struct
el3_private
*
lp
=
(
struct
el3_private
*
)(
arg
);
struct
net_device
*
dev
=
&
lp
->
dev
;
ioaddr_t
ioaddr
=
dev
->
base_addr
;
u
_short
media
,
errs
;
u
_
long
flags
;
u
16
media
,
errs
;
u
nsigned
long
flags
;
if
(
!
netif_device_present
(
dev
))
goto
reschedule
;
...
...
@@ -917,7 +924,7 @@ static void media_check(u_long arg)
if
((
inw
(
ioaddr
+
EL3_STATUS
)
&
IntLatch
)
&&
(
inb
(
ioaddr
+
EL3_TIMER
)
==
0xff
))
{
if
(
!
lp
->
fast_poll
)
printk
(
KERN_
INFO
"%s: interrupt(s) dropped!
\n
"
,
dev
->
name
);
printk
(
KERN_
WARNING
"%s: interrupt(s) dropped!
\n
"
,
dev
->
name
);
el3_interrupt
(
dev
->
irq
,
lp
,
NULL
);
lp
->
fast_poll
=
HZ
;
}
...
...
@@ -927,9 +934,10 @@ static void media_check(u_long arg)
add_timer
(
&
lp
->
media
);
return
;
}
save_flags
(
flags
);
cli
();
/* lp->lock guards the EL3 window. Window should always be 1 except
when the lock is held */
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
EL3WINDOW
(
4
);
media
=
inw
(
ioaddr
+
WN4_MEDIA
)
&
0xc810
;
...
...
@@ -974,7 +982,7 @@ static void media_check(u_long arg)
}
EL3WINDOW
(
1
);
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
reschedule:
lp
->
media
.
expires
=
jiffies
+
HZ
;
...
...
@@ -988,10 +996,9 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev)
dev_link_t
*
link
=
&
lp
->
link
;
if
(
DEV_OK
(
link
))
{
save_flags
(
flags
);
cli
();
spin_lock_irqsave
(
&
lp
->
lock
,
flags
);
update_stats
(
dev
);
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
lp
->
lock
,
flags
);
}
return
&
lp
->
stats
;
}
...
...
@@ -1001,6 +1008,8 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev)
single-threaded if the device is active. This is expected to be a rare
operation, and it's simpler for the rest of the driver to assume that
window 1 is always valid rather than use a special window-state variable.
Caller must hold the lock for this
*/
static
void
update_stats
(
struct
net_device
*
dev
)
{
...
...
@@ -1079,7 +1088,7 @@ static int el3_rx(struct net_device *dev)
tc589_wait_for_completion
(
dev
,
RxDiscard
);
}
if
(
worklimit
==
0
)
printk
(
KERN_
NOTICE
"%s: too much work in el3_rx!
\n
"
,
dev
->
name
);
printk
(
KERN_
WARNING
"%s: too much work in el3_rx!
\n
"
,
dev
->
name
);
return
0
;
}
...
...
@@ -1088,7 +1097,7 @@ static void set_multicast_list(struct net_device *dev)
struct
el3_private
*
lp
=
dev
->
priv
;
dev_link_t
*
link
=
&
lp
->
link
;
ioaddr_t
ioaddr
=
dev
->
base_addr
;
u
_short
opts
=
SetRxFilter
|
RxStation
|
RxBroadcast
;
u
16
opts
=
SetRxFilter
|
RxStation
|
RxBroadcast
;
if
(
!
(
DEV_OK
(
link
)))
return
;
if
(
dev
->
flags
&
IFF_PROMISC
)
...
...
@@ -1135,7 +1144,7 @@ static int el3_close(struct net_device *dev)
link
->
open
--
;
netif_stop_queue
(
dev
);
del_timer
(
&
lp
->
media
);
del_timer
_sync
(
&
lp
->
media
);
if
(
link
->
state
&
DEV_STALE_CONFIG
)
mod_timer
(
&
link
->
release
,
jiffies
+
HZ
/
20
);
...
...
@@ -1152,8 +1161,7 @@ static int __init init_3c589_cs(void)
DEBUG
(
0
,
"%s
\n
"
,
version
);
CardServices
(
GetCardServicesInfo
,
&
serv
);
if
(
serv
.
Revision
!=
CS_RELEASE_CODE
)
{
printk
(
KERN_NOTICE
"3c589_cs: Card Services release "
"does not match!
\n
"
);
printk
(
KERN_ERR
"3c589_cs: Card Services release does not match!
\n
"
);
return
-
1
;
}
register_pccard_driver
(
&
dev_info
,
&
tc589_attach
,
&
tc589_detach
);
...
...
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