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
6e38a55b
Commit
6e38a55b
authored
Nov 23, 2007
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import 1.1.53
parent
5f50b72d
Changes
30
Show whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
1317 additions
and
965 deletions
+1317
-965
Makefile
Makefile
+6
-2
drivers/char/console.c
drivers/char/console.c
+16
-4
drivers/net/3c501.c
drivers/net/3c501.c
+139
-114
drivers/net/3c503.c
drivers/net/3c503.c
+86
-49
drivers/net/3c507.c
drivers/net/3c507.c
+68
-48
drivers/net/3c509.c
drivers/net/3c509.c
+113
-97
drivers/net/8390.c
drivers/net/8390.c
+18
-15
drivers/net/8390.h
drivers/net/8390.h
+6
-6
drivers/net/at1700.c
drivers/net/at1700.c
+78
-53
drivers/net/auto_irq.c
drivers/net/auto_irq.c
+58
-47
drivers/net/hp-plus.c
drivers/net/hp-plus.c
+29
-17
drivers/net/hp.c
drivers/net/hp.c
+42
-26
drivers/net/lance.c
drivers/net/lance.c
+127
-91
drivers/net/loopback.c
drivers/net/loopback.c
+1
-1
drivers/net/ne.c
drivers/net/ne.c
+97
-62
drivers/net/net_init.c
drivers/net/net_init.c
+9
-9
drivers/net/skeleton.c
drivers/net/skeleton.c
+110
-58
drivers/net/smc-ultra.c
drivers/net/smc-ultra.c
+196
-179
drivers/net/wd.c
drivers/net/wd.c
+67
-53
drivers/net/znet.c
drivers/net/znet.c
+2
-2
drivers/scsi/scsi.c
drivers/scsi/scsi.c
+1
-1
fs/nfs/proc.c
fs/nfs/proc.c
+1
-1
fs/nfs/sock.c
fs/nfs/sock.c
+3
-1
fs/nfs/symlink.c
fs/nfs/symlink.c
+6
-0
include/linux/resource.h
include/linux/resource.h
+1
-1
include/linux/signal.h
include/linux/signal.h
+2
-15
kernel/sched.c
kernel/sched.c
+12
-4
kernel/signal.c
kernel/signal.c
+2
-2
kernel/vm86.c
kernel/vm86.c
+2
-2
net/inet/icmp.c
net/inet/icmp.c
+19
-5
No files found.
Makefile
View file @
6e38a55b
VERSION
=
1
VERSION
=
1
PATCHLEVEL
=
1
PATCHLEVEL
=
1
SUBLEVEL
=
5
2
SUBLEVEL
=
5
3
ARCH
=
i386
ARCH
=
i386
...
@@ -136,7 +136,11 @@ tools/version.h: $(CONFIGURE) Makefile
...
@@ -136,7 +136,11 @@ tools/version.h: $(CONFIGURE) Makefile
@
echo
\#
define LINUX_COMPILE_TIME
\"
`
date
+%T
`
\"
>>
tools/version.h
@
echo
\#
define LINUX_COMPILE_TIME
\"
`
date
+%T
`
\"
>>
tools/version.h
@
echo
\#
define LINUX_COMPILE_BY
\"
`
whoami
`
\"
>>
tools/version.h
@
echo
\#
define LINUX_COMPILE_BY
\"
`
whoami
`
\"
>>
tools/version.h
@
echo
\#
define LINUX_COMPILE_HOST
\"
`
hostname
`
\"
>>
tools/version.h
@
echo
\#
define LINUX_COMPILE_HOST
\"
`
hostname
`
\"
>>
tools/version.h
@
echo
\#
define LINUX_COMPILE_DOMAIN
\"
`
domainname
`
\"
>>
tools/version.h
@
if
[
-x
/bin/dnsdomainname
]
;
then
\
echo
\#
define LINUX_COMPILE_DOMAIN
\"
`
dnsdomainname
`
\"
;
\
else
\
echo
\#
define LINUX_COMPILE_DOMAIN
\"
`
domainname
`
\"
;
\
fi
>>
tools/version.h
@
echo
\#
define LINUX_COMPILER
\"
`
$(HOSTCC)
-v
2>&1 |
tail
-1
`
\"
>>
tools/version.h
@
echo
\#
define LINUX_COMPILER
\"
`
$(HOSTCC)
-v
2>&1 |
tail
-1
`
\"
>>
tools/version.h
tools/build
:
tools/build.c $(CONFIGURE)
tools/build
:
tools/build.c $(CONFIGURE)
...
...
drivers/char/console.c
View file @
6e38a55b
...
@@ -1081,20 +1081,32 @@ static void reset_terminal(int currcons, int do_clear)
...
@@ -1081,20 +1081,32 @@ static void reset_terminal(int currcons, int do_clear)
}
}
/*
/*
* Turn the Scroll-Lock LED on when the tty is stopped
(with a ^S)
* Turn the Scroll-Lock LED on when the tty is stopped
*/
*/
static
void
con_stop
(
struct
tty_struct
*
tty
)
static
void
con_stop
(
struct
tty_struct
*
tty
)
{
{
set_vc_kbd_led
(
kbd_table
+
fg_console
,
VC_SCROLLOCK
);
int
console_num
;
if
(
!
tty
)
return
;
console_num
=
MINOR
(
tty
->
device
)
-
(
tty
->
driver
.
minor_start
);
if
(
console_num
<
0
||
console_num
>=
NR_CONSOLES
)
return
;
set_vc_kbd_led
(
kbd_table
+
console_num
,
VC_SCROLLOCK
);
set_leds
();
set_leds
();
}
}
/*
/*
* Turn the Scroll-Lock LED off when the console is started
(with a ^Q)
* Turn the Scroll-Lock LED off when the console is started
*/
*/
static
void
con_start
(
struct
tty_struct
*
tty
)
static
void
con_start
(
struct
tty_struct
*
tty
)
{
{
clr_vc_kbd_led
(
kbd_table
+
fg_console
,
VC_SCROLLOCK
);
int
console_num
;
if
(
!
tty
)
return
;
console_num
=
MINOR
(
tty
->
device
)
-
(
tty
->
driver
.
minor_start
);
if
(
console_num
<
0
||
console_num
>=
NR_CONSOLES
)
return
;
clr_vc_kbd_led
(
kbd_table
+
console_num
,
VC_SCROLLOCK
);
set_leds
();
set_leds
();
}
}
...
...
drivers/net/3c501.c
View file @
6e38a55b
/* 3c501.c: A 3Com 3c501 ethernet driver for linux. */
/* 3c501.c: A 3Com 3c501 ethernet driver for linux. */
/*
/*
Copyright (C) 1992,1993
Donald Becker
Written 1992,1993,1994
Donald Becker
Copyright 1993 United States Government as represented by the
Copyright 1993 United States Government as represented by the
Director, National Security Agency. This software may be used and
Director, National Security Agency. This software may be used and
...
@@ -11,13 +11,13 @@
...
@@ -11,13 +11,13 @@
Do not purchase this card, even as a joke. It's performance is horrible,
Do not purchase this card, even as a joke. It's performance is horrible,
and it breaks in many ways.
and it breaks in many ways.
The
Author may be reached as becker@super.org or
The
author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
C
/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
C
enter of Excellence in Space Data and Information Sciences
I'll only accept bug fixes, not reports, for the 3c501 driver.
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
*/
*/
static
char
*
version
=
static
char
*
version
=
"3c501.c:
3/3/94 Donald Becker (becker@super.org
).
\n
"
;
"3c501.c:
9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov
).
\n
"
;
/*
/*
Braindamage remaining:
Braindamage remaining:
...
@@ -32,6 +32,7 @@ static char *version =
...
@@ -32,6 +32,7 @@ static char *version =
#include <linux/ioport.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/malloc.h>
#include <linux/malloc.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/ioport.h>
#include <asm/bitops.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/io.h>
...
@@ -46,16 +47,18 @@ static char *version =
...
@@ -46,16 +47,18 @@ static char *version =
#include "../../tools/version.h"
#include "../../tools/version.h"
#endif
#endif
#ifndef HAVE_AUTOIRQ
extern
struct
device
*
init_etherdev
(
struct
device
*
dev
,
int
sizeof_private
,
/* From auto_irq.c, should be in a *.h file. */
unsigned
long
*
mem_startp
);
extern
void
autoirq_setup
(
int
waittime
);
extern
int
autoirq_report
(
int
waittime
);
/* A zero-terminated list of I/O addresses to be probed.
extern
struct
device
*
irq2dev_map
[
16
];
The 3c501 can be at many locations, but here are the popular ones. */
#endif
static
unsigned
int
netcard_portlist
[]
=
{
0x280
,
0x300
,
0
};
/* Index to functions. */
/* Index to functions. */
int
el1_probe
(
struct
device
*
dev
);
int
el1_probe
(
struct
device
*
dev
);
static
int
el1_probe1
(
struct
device
*
dev
,
int
ioaddr
);
static
int
el_open
(
struct
device
*
dev
);
static
int
el_open
(
struct
device
*
dev
);
static
int
el_start_xmit
(
struct
sk_buff
*
skb
,
struct
device
*
dev
);
static
int
el_start_xmit
(
struct
sk_buff
*
skb
,
struct
device
*
dev
);
static
void
el_interrupt
(
int
reg_ptr
);
static
void
el_interrupt
(
int
reg_ptr
);
...
@@ -65,37 +68,34 @@ static int el1_close(struct device *dev);
...
@@ -65,37 +68,34 @@ static int el1_close(struct device *dev);
static
struct
enet_statistics
*
el1_get_stats
(
struct
device
*
dev
);
static
struct
enet_statistics
*
el1_get_stats
(
struct
device
*
dev
);
static
void
set_multicast_list
(
struct
device
*
dev
,
int
num_addrs
,
void
*
addrs
);
static
void
set_multicast_list
(
struct
device
*
dev
,
int
num_addrs
,
void
*
addrs
);
#define EL
_NAME "EtherLink 3c501"
#define EL
1_IO_EXTENT 16
#ifndef EL_DEBUG
#ifndef EL_DEBUG
#define EL_DEBUG 2
/* use 0 for production, 1 for devel., >2 for debug */
#define EL_DEBUG 2
/* use 0 for production, 1 for devel., >2 for debug */
#endif
/* Anything above 5 is wordy death! */
#endif
/* Anything above 5 is wordy death! */
static
int
el_debug
=
EL_DEBUG
;
static
int
el_debug
=
EL_DEBUG
;
static
int
el_base
;
static
struct
device
*
eldev
;
/* Only for consistency checking. */
/* We could easily have this struct kmalloc()ed per-board, but
/* Board-specific info in dev->priv. */
who would want more than one 3c501?. */
struct
net_local
{
static
struct
{
struct
enet_statistics
stats
;
struct
enet_statistics
stats
;
int
tx_pkt_start
;
/* The length of the current Tx packet. */
int
tx_pkt_start
;
/* The length of the current Tx packet. */
int
collisions
;
/* Tx collisions this packet */
int
collisions
;
/* Tx collisions this packet */
}
el_status
;
/* This should be stored per-board */
}
;
#define RX_STATUS (
el_base
+ 0x06)
#define RX_STATUS (
ioaddr
+ 0x06)
#define RX_CMD RX_STATUS
#define RX_CMD RX_STATUS
#define TX_STATUS (
el_base
+ 0x07)
#define TX_STATUS (
ioaddr
+ 0x07)
#define TX_CMD TX_STATUS
#define TX_CMD TX_STATUS
#define GP_LOW (
el_base
+ 0x08)
#define GP_LOW (
ioaddr
+ 0x08)
#define GP_HIGH (
el_base
+ 0x09)
#define GP_HIGH (
ioaddr
+ 0x09)
#define RX_BUF_CLR (
el_base
+ 0x0A)
#define RX_BUF_CLR (
ioaddr
+ 0x0A)
#define RX_LOW (
el_base
+ 0x0A)
#define RX_LOW (
ioaddr
+ 0x0A)
#define RX_HIGH (
el_base
+ 0x0B)
#define RX_HIGH (
ioaddr
+ 0x0B)
#define SAPROM (
el_base
+ 0x0C)
#define SAPROM (
ioaddr
+ 0x0C)
#define AX_STATUS (
el_base
+ 0x0E)
#define AX_STATUS (
ioaddr
+ 0x0E)
#define AX_CMD AX_STATUS
#define AX_CMD AX_STATUS
#define DATAPORT (
el_base
+ 0x0F)
#define DATAPORT (
ioaddr
+ 0x0F)
#define TX_RDY 0x08
/* In TX_STATUS */
#define TX_RDY 0x08
/* In TX_STATUS */
#define EL1_DATAPTR 0x08
#define EL1_DATAPTR 0x08
...
@@ -128,37 +128,64 @@ static struct {
...
@@ -128,37 +128,64 @@ static struct {
#define RX_GOOD 0x30
/* Good packet 0x20, or simple overflow 0x10. */
#define RX_GOOD 0x30
/* Good packet 0x20, or simple overflow 0x10. */
/* The boilerplate probe code. */
#ifdef HAVE_DEVLIST
struct
netdev_entry
el1_drv
=
{
"3c501"
,
el1_probe1
,
EL1_IO_EXTENT
,
netcard_portlist
};
#else
int
int
el1_probe
(
struct
device
*
dev
)
el1_probe
(
struct
device
*
dev
)
{
{
int
i
;
int
i
;
int
ioaddr
;
int
base_addr
=
dev
?
dev
->
base_addr
:
0
;
unsigned
char
station_addr
[
6
];
int
autoirq
=
0
;
if
(
base_addr
>
0x1ff
)
/* Check a single specified location. */
return
el1_probe1
(
dev
,
base_addr
);
eldev
=
dev
;
/* Store for debugging. */
else
if
(
base_addr
!=
0
)
/* Don't probe at all. */
el_base
=
dev
->
base_addr
;
return
ENXIO
;
for
(
i
=
0
;
netcard_portlist
[
i
];
i
++
)
{
int
ioaddr
=
netcard_portlist
[
i
];
if
(
check_region
(
ioaddr
,
EL1_IO_EXTENT
))
continue
;
if
(
el1_probe1
(
dev
,
ioaddr
)
==
0
)
return
0
;
}
if
(
el_base
<
0x40
)
/* Invalid? Probe for it. */
return
ENODEV
;
el_base
=
0x280
;
}
#endif
ioaddr
=
el_base
;
/* The actual probe. */
static
int
el1_probe1
(
struct
device
*
dev
,
int
ioaddr
)
{
char
*
mname
;
/* Vendor name */
unsigned
char
station_addr
[
6
];
int
autoirq
=
0
;
int
i
;
/* Read the station address PROM data from the special port. */
/* Read the station address PROM data from the special port. */
for
(
i
=
0
;
i
<
6
;
i
++
)
{
for
(
i
=
0
;
i
<
6
;
i
++
)
{
outw
(
i
,
ioaddr
+
EL1_DATAPTR
);
outw
(
i
,
ioaddr
+
EL1_DATAPTR
);
station_addr
[
i
]
=
inb
(
ioaddr
+
EL1_SAPROM
);
station_addr
[
i
]
=
inb
(
ioaddr
+
EL1_SAPROM
);
}
}
/* Check the first three octets of the S.A. for 3Com's code. */
/* Check the first three octets of the S.A. for 3Com's prefix, or
if
(
station_addr
[
0
]
!=
0x02
||
station_addr
[
1
]
!=
0x60
for the Sager NP943 prefix. */
||
station_addr
[
2
]
!=
0x8c
)
{
if
(
station_addr
[
0
]
==
0x02
&&
station_addr
[
1
]
==
0x60
&&
station_addr
[
2
]
==
0x8c
)
{
mname
=
"3c501"
;
}
else
if
(
station_addr
[
0
]
==
0x00
&&
station_addr
[
1
]
==
0x80
&&
station_addr
[
2
]
==
0xC8
)
{
mname
=
"NP943"
;
}
else
return
ENODEV
;
return
ENODEV
;
}
#ifdef HAVE_PORTRESERVE
/* Grab the region so we can find the another board if autoIRQ fails. */
/* Grab the region so we can find the another board if autoIRQ fails. */
snarf_region
(
ioaddr
,
16
);
snarf_region
(
ioaddr
,
EL1_IO_EXTENT
);
#endif
if
(
dev
==
NULL
)
dev
=
init_etherdev
(
0
,
sizeof
(
struct
net_local
),
0
);
/* We auto-IRQ by shutting off the interrupt line and letting it float
/* We auto-IRQ by shutting off the interrupt line and letting it float
high. */
high. */
...
@@ -175,25 +202,33 @@ el1_probe(struct device *dev)
...
@@ -175,25 +202,33 @@ el1_probe(struct device *dev)
autoirq
=
autoirq_report
(
1
);
autoirq
=
autoirq_report
(
1
);
if
(
autoirq
==
0
)
{
if
(
autoirq
==
0
)
{
printk
(
"%s: 3c501 probe failed to detect IRQ line.
\n
"
,
dev
->
name
);
printk
(
"%s probe at %#x failed to detect IRQ line.
\n
"
,
mname
,
ioaddr
);
return
EAGAIN
;
return
EAGAIN
;
}
}
dev
->
irq
=
autoirq
;
}
}
outb
(
AX_RESET
+
AX_LOOP
,
AX_CMD
);
/* Loopback mode. */
outb
(
AX_RESET
+
AX_LOOP
,
AX_CMD
);
/* Loopback mode. */
dev
->
base_addr
=
el_base
;
dev
->
base_addr
=
ioaddr
;
memcpy
(
dev
->
dev_addr
,
station_addr
,
ETH_ALEN
);
memcpy
(
dev
->
dev_addr
,
station_addr
,
ETH_ALEN
);
if
(
dev
->
mem_start
&
0xf
)
if
(
dev
->
mem_start
&
0xf
)
el_debug
=
dev
->
mem_start
&
0x7
;
el_debug
=
dev
->
mem_start
&
0x7
;
if
(
autoirq
)
dev
->
irq
=
autoirq
;
printk
(
"%s: 3c501 EtherLink at %#x, using %sIRQ %d, melting ethernet.
\n
"
,
printk
(
"%s: %s EtherLink at %#x, using %sIRQ %d, melting ethernet.
\n
"
,
dev
->
name
,
dev
->
base_addr
,
autoirq
?
"auto"
:
"assigned "
,
dev
->
irq
);
dev
->
name
,
mname
,
dev
->
base_addr
,
autoirq
?
"auto"
:
"assigned "
,
dev
->
irq
);
if
(
el_debug
)
if
(
el_debug
)
printk
(
"%s"
,
version
);
printk
(
"%s"
,
version
);
/* Initialize the device structure. */
if
(
dev
->
priv
==
NULL
)
dev
->
priv
=
kmalloc
(
sizeof
(
struct
net_local
),
GFP_KERNEL
);
memset
(
dev
->
priv
,
0
,
sizeof
(
struct
net_local
));
/* The EL1-specific entries in the device structure. */
/* The EL1-specific entries in the device structure. */
dev
->
open
=
&
el_open
;
dev
->
open
=
&
el_open
;
dev
->
hard_start_xmit
=
&
el_start_xmit
;
dev
->
hard_start_xmit
=
&
el_start_xmit
;
...
@@ -210,13 +245,12 @@ el1_probe(struct device *dev)
...
@@ -210,13 +245,12 @@ el1_probe(struct device *dev)
static
int
static
int
el_open
(
struct
device
*
dev
)
el_open
(
struct
device
*
dev
)
{
{
int
ioaddr
=
dev
->
base_addr
;
if
(
el_debug
>
2
)
if
(
el_debug
>
2
)
printk
(
"%s: Doing el_open()..."
,
dev
->
name
);
printk
(
"%s: Doing el_open()..."
,
dev
->
name
);
if
(
request_irq
(
dev
->
irq
,
&
el_interrupt
,
0
,
"3c501"
))
{
if
(
request_irq
(
dev
->
irq
,
&
el_interrupt
,
0
,
"3c501"
))
{
if
(
el_debug
>
2
)
printk
(
"interrupt busy, exiting el_open().
\n
"
);
return
-
EAGAIN
;
return
-
EAGAIN
;
}
}
irq2dev_map
[
dev
->
irq
]
=
dev
;
irq2dev_map
[
dev
->
irq
]
=
dev
;
...
@@ -226,20 +260,18 @@ el_open(struct device *dev)
...
@@ -226,20 +260,18 @@ el_open(struct device *dev)
dev
->
start
=
1
;
dev
->
start
=
1
;
outb
(
AX_RX
,
AX_CMD
);
/* Aux control, irq and receive enabled */
outb
(
AX_RX
,
AX_CMD
);
/* Aux control, irq and receive enabled */
if
(
el_debug
>
2
)
printk
(
"finished el_open().
\n
"
);
#ifdef MODULE
#ifdef MODULE
MOD_INC_USE_COUNT
;
MOD_INC_USE_COUNT
;
#endif
#endif
return
(
0
)
;
return
0
;
}
}
static
int
static
int
el_start_xmit
(
struct
sk_buff
*
skb
,
struct
device
*
dev
)
el_start_xmit
(
struct
sk_buff
*
skb
,
struct
device
*
dev
)
{
{
unsigned
long
flags
;
struct
net_local
*
lp
=
(
struct
net_local
*
)
dev
->
priv
;
int
ioaddr
=
dev
->
base_addr
;
save_flags
(
flags
);
if
(
dev
->
tbusy
)
{
if
(
dev
->
tbusy
)
{
if
(
jiffies
-
dev
->
trans_start
<
20
)
{
if
(
jiffies
-
dev
->
trans_start
<
20
)
{
if
(
el_debug
>
2
)
if
(
el_debug
>
2
)
...
@@ -249,18 +281,12 @@ el_start_xmit(struct sk_buff *skb, struct device *dev)
...
@@ -249,18 +281,12 @@ el_start_xmit(struct sk_buff *skb, struct device *dev)
if
(
el_debug
)
if
(
el_debug
)
printk
(
"%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.
\n
"
,
printk
(
"%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.
\n
"
,
dev
->
name
,
inb
(
TX_STATUS
),
inb
(
AX_STATUS
),
inb
(
RX_STATUS
));
dev
->
name
,
inb
(
TX_STATUS
),
inb
(
AX_STATUS
),
inb
(
RX_STATUS
));
el_status
.
stats
.
tx_errors
++
;
lp
->
stats
.
tx_errors
++
;
#ifdef oldway
el_reset
(
dev
);
#else
cli
();
outb
(
TX_NORM
,
TX_CMD
);
outb
(
TX_NORM
,
TX_CMD
);
outb
(
RX_NORM
,
RX_CMD
);
outb
(
RX_NORM
,
RX_CMD
);
outb
(
AX_OFF
,
AX_CMD
);
/* Just trigger a false interrupt. */
outb
(
AX_OFF
,
AX_CMD
);
/* Just trigger a false interrupt. */
#endif
outb
(
AX_RX
,
AX_CMD
);
/* Aux control, irq and receive enabled */
outb
(
AX_RX
,
AX_CMD
);
/* Aux control, irq and receive enabled */
dev
->
tbusy
=
0
;
dev
->
tbusy
=
0
;
restore_flags
(
flags
);
dev
->
trans_start
=
jiffies
;
dev
->
trans_start
=
jiffies
;
}
}
...
@@ -269,28 +295,21 @@ el_start_xmit(struct sk_buff *skb, struct device *dev)
...
@@ -269,28 +295,21 @@ el_start_xmit(struct sk_buff *skb, struct device *dev)
return
0
;
return
0
;
}
}
if
(
skb
->
len
<=
0
)
return
0
;
/* Avoid timer-based retransmission conflicts. */
/* Avoid timer-based retransmission conflicts. */
cli
();
if
(
set_bit
(
0
,
(
void
*
)
&
dev
->
tbusy
)
!=
0
)
if
(
set_bit
(
0
,
(
void
*
)
&
dev
->
tbusy
)
!=
0
)
{
printk
(
"%s: Transmitter access conflict.
\n
"
,
dev
->
name
);
printk
(
"%s: Transmitter access conflict.
\n
"
,
dev
->
name
);
restore_flags
(
flags
);
else
{
}
else
{
int
gp_start
=
0x800
-
(
ETH_ZLEN
<
skb
->
len
?
skb
->
len
:
ETH_ZLEN
);
int
gp_start
=
0x800
-
(
ETH_ZLEN
<
skb
->
len
?
skb
->
len
:
ETH_ZLEN
);
unsigned
char
*
buf
=
skb
->
data
;
unsigned
char
*
buf
=
skb
->
data
;
el_status
.
tx_pkt_start
=
gp_start
;
lp
->
tx_pkt_start
=
gp_start
;
el_status
.
collisions
=
0
;
lp
->
collisions
=
0
;
outb
(
AX_SYS
,
AX_CMD
);
outb
(
AX_SYS
,
AX_CMD
);
inb
(
RX_STATUS
);
inb
(
RX_STATUS
);
inb
(
TX_STATUS
);
inb
(
TX_STATUS
);
out
b
(
0x00
,
RX_BUF_CLR
);
/* Set rx packet area to 0. */
out
w
(
0x00
,
RX_BUF_CLR
);
/* Set rx packet area to 0. */
outw
(
gp_start
,
GP_LOW
);
outw
(
gp_start
,
GP_LOW
);
restore_flags
(
flags
);
outsb
(
DATAPORT
,
buf
,
skb
->
len
);
outsb
(
DATAPORT
,
buf
,
skb
->
len
);
outw
(
gp_start
,
GP_LOW
);
outw
(
gp_start
,
GP_LOW
);
outb
(
AX_XMIT
,
AX_CMD
);
/* Trigger xmit. */
outb
(
AX_XMIT
,
AX_CMD
);
/* Trigger xmit. */
...
@@ -310,18 +329,18 @@ static void
...
@@ -310,18 +329,18 @@ static void
el_interrupt
(
int
reg_ptr
)
el_interrupt
(
int
reg_ptr
)
{
{
int
irq
=
-
(((
struct
pt_regs
*
)
reg_ptr
)
->
orig_eax
+
2
);
int
irq
=
-
(((
struct
pt_regs
*
)
reg_ptr
)
->
orig_eax
+
2
);
/*struct device *dev = (struct device *)(irq2dev_map[irq]);*/
struct
device
*
dev
=
(
struct
device
*
)(
irq2dev_map
[
irq
]);
struct
device
*
dev
=
eldev
;
struct
net_local
*
lp
;
int
ioaddr
;
int
axsr
;
/* Aux. status reg. */
int
axsr
;
/* Aux. status reg. */
short
ioaddr
;
if
(
el
dev
->
irq
!=
irq
)
{
if
(
dev
==
NULL
||
dev
->
irq
!=
irq
)
{
printk
(
EL_NAME
": irq %d for unknown device
\n
"
,
irq
);
printk
(
"3c501 driver: irq %d for unknown device.
\n
"
,
irq
);
return
;
return
;
}
}
ioaddr
=
dev
->
base_addr
;
ioaddr
=
dev
->
base_addr
;
lp
=
(
struct
net_local
*
)
dev
->
priv
;
axsr
=
inb
(
AX_STATUS
);
axsr
=
inb
(
AX_STATUS
);
if
(
el_debug
>
3
)
if
(
el_debug
>
3
)
...
@@ -348,18 +367,18 @@ el_interrupt(int reg_ptr)
...
@@ -348,18 +367,18 @@ el_interrupt(int reg_ptr)
printk
(
"%s: Transmit failed 16 times, ethernet jammed?
\n
"
,
printk
(
"%s: Transmit failed 16 times, ethernet jammed?
\n
"
,
dev
->
name
);
dev
->
name
);
outb
(
AX_SYS
,
AX_CMD
);
outb
(
AX_SYS
,
AX_CMD
);
el_status
.
stats
.
tx_aborted_errors
++
;
lp
->
stats
.
tx_aborted_errors
++
;
}
else
if
(
txsr
&
TX_COLLISION
)
{
/* Retrigger xmit. */
}
else
if
(
txsr
&
TX_COLLISION
)
{
/* Retrigger xmit. */
if
(
el_debug
>
6
)
if
(
el_debug
>
6
)
printk
(
" retransmitting after a collision.
\n
"
);
printk
(
" retransmitting after a collision.
\n
"
);
outb
(
AX_SYS
,
AX_CMD
);
outb
(
AX_SYS
,
AX_CMD
);
outw
(
el_status
.
tx_pkt_start
,
GP_LOW
);
outw
(
lp
->
tx_pkt_start
,
GP_LOW
);
outb
(
AX_XMIT
,
AX_CMD
);
outb
(
AX_XMIT
,
AX_CMD
);
el_status
.
stats
.
collisions
++
;
lp
->
stats
.
collisions
++
;
dev
->
interrupt
=
0
;
dev
->
interrupt
=
0
;
return
;
return
;
}
else
{
}
else
{
el_status
.
stats
.
tx_packets
++
;
lp
->
stats
.
tx_packets
++
;
if
(
el_debug
>
6
)
if
(
el_debug
>
6
)
printk
(
" Tx succeeded %s
\n
"
,
printk
(
" Tx succeeded %s
\n
"
,
(
txsr
&
TX_RDY
)
?
"."
:
"but tx is busy!"
);
(
txsr
&
TX_RDY
)
?
"."
:
"but tx is busy!"
);
...
@@ -374,24 +393,24 @@ el_interrupt(int reg_ptr)
...
@@ -374,24 +393,24 @@ el_interrupt(int reg_ptr)
/* Just reading rx_status fixes most errors. */
/* Just reading rx_status fixes most errors. */
if
(
rxsr
&
RX_MISSED
)
if
(
rxsr
&
RX_MISSED
)
el_status
.
stats
.
rx_missed_errors
++
;
lp
->
stats
.
rx_missed_errors
++
;
if
(
rxsr
&
RX_RUNT
)
{
/* Handled to avoid board lock-up. */
if
(
rxsr
&
RX_RUNT
)
{
/* Handled to avoid board lock-up. */
el_status
.
stats
.
rx_length_errors
++
;
lp
->
stats
.
rx_length_errors
++
;
if
(
el_debug
>
5
)
printk
(
" runt.
\n
"
);
if
(
el_debug
>
5
)
printk
(
" runt.
\n
"
);
}
else
if
(
rxsr
&
RX_GOOD
)
{
}
else
if
(
rxsr
&
RX_GOOD
)
{
el_receive
(
el
dev
);
el_receive
(
dev
);
}
else
{
/* Nothing? Something is broken! */
}
else
{
/* Nothing? Something is broken! */
if
(
el_debug
>
2
)
if
(
el_debug
>
2
)
printk
(
"%s: No packet seen, rxsr=%02x **resetting 3c501***
\n
"
,
printk
(
"%s: No packet seen, rxsr=%02x **resetting 3c501***
\n
"
,
dev
->
name
,
rxsr
);
dev
->
name
,
rxsr
);
el_reset
(
el
dev
);
el_reset
(
dev
);
}
}
if
(
el_debug
>
3
)
if
(
el_debug
>
3
)
printk
(
".
\n
"
);
printk
(
".
\n
"
);
}
}
outb
(
AX_RX
,
AX_CMD
);
outb
(
AX_RX
,
AX_CMD
);
out
b
(
0x00
,
RX_BUF_CLR
);
out
w
(
0x00
,
RX_BUF_CLR
);
inb
(
RX_STATUS
);
/* Be certain that interrupts are cleared. */
inb
(
RX_STATUS
);
/* Be certain that interrupts are cleared. */
inb
(
TX_STATUS
);
inb
(
TX_STATUS
);
dev
->
interrupt
=
0
;
dev
->
interrupt
=
0
;
...
@@ -404,6 +423,8 @@ el_interrupt(int reg_ptr)
...
@@ -404,6 +423,8 @@ el_interrupt(int reg_ptr)
static
void
static
void
el_receive
(
struct
device
*
dev
)
el_receive
(
struct
device
*
dev
)
{
{
struct
net_local
*
lp
=
(
struct
net_local
*
)
dev
->
priv
;
int
ioaddr
=
dev
->
base_addr
;
int
pkt_len
;
int
pkt_len
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
...
@@ -415,7 +436,7 @@ el_receive(struct device *dev)
...
@@ -415,7 +436,7 @@ el_receive(struct device *dev)
if
((
pkt_len
<
60
)
||
(
pkt_len
>
1536
))
{
if
((
pkt_len
<
60
)
||
(
pkt_len
>
1536
))
{
if
(
el_debug
)
if
(
el_debug
)
printk
(
"%s: bogus packet, length=%d
\n
"
,
dev
->
name
,
pkt_len
);
printk
(
"%s: bogus packet, length=%d
\n
"
,
dev
->
name
,
pkt_len
);
el_status
.
stats
.
rx_over_errors
++
;
lp
->
stats
.
rx_over_errors
++
;
return
;
return
;
}
}
outb
(
AX_SYS
,
AX_CMD
);
outb
(
AX_SYS
,
AX_CMD
);
...
@@ -424,7 +445,7 @@ el_receive(struct device *dev)
...
@@ -424,7 +445,7 @@ el_receive(struct device *dev)
outw
(
0x00
,
GP_LOW
);
outw
(
0x00
,
GP_LOW
);
if
(
skb
==
NULL
)
{
if
(
skb
==
NULL
)
{
printk
(
"%s: Memory squeeze, dropping packet.
\n
"
,
dev
->
name
);
printk
(
"%s: Memory squeeze, dropping packet.
\n
"
,
dev
->
name
);
el_status
.
stats
.
rx_dropped
++
;
lp
->
stats
.
rx_dropped
++
;
return
;
return
;
}
else
{
}
else
{
skb
->
len
=
pkt_len
;
skb
->
len
=
pkt_len
;
...
@@ -433,7 +454,7 @@ el_receive(struct device *dev)
...
@@ -433,7 +454,7 @@ el_receive(struct device *dev)
insb
(
DATAPORT
,
skb
->
data
,
pkt_len
);
insb
(
DATAPORT
,
skb
->
data
,
pkt_len
);
netif_rx
(
skb
);
netif_rx
(
skb
);
el_status
.
stats
.
rx_packets
++
;
lp
->
stats
.
rx_packets
++
;
}
}
return
;
return
;
}
}
...
@@ -441,6 +462,8 @@ el_receive(struct device *dev)
...
@@ -441,6 +462,8 @@ el_receive(struct device *dev)
static
void
static
void
el_reset
(
struct
device
*
dev
)
el_reset
(
struct
device
*
dev
)
{
{
int
ioaddr
=
dev
->
base_addr
;
if
(
el_debug
>
2
)
if
(
el_debug
>
2
)
printk
(
"3c501 reset..."
);
printk
(
"3c501 reset..."
);
outb
(
AX_RESET
,
AX_CMD
);
/* Reset the chip */
outb
(
AX_RESET
,
AX_CMD
);
/* Reset the chip */
...
@@ -448,10 +471,10 @@ el_reset(struct device *dev)
...
@@ -448,10 +471,10 @@ el_reset(struct device *dev)
{
{
int
i
;
int
i
;
for
(
i
=
0
;
i
<
6
;
i
++
)
/* Set the station address. */
for
(
i
=
0
;
i
<
6
;
i
++
)
/* Set the station address. */
outb
(
dev
->
dev_addr
[
i
],
el_base
+
i
);
outb
(
dev
->
dev_addr
[
i
],
ioaddr
+
i
);
}
}
out
b
(
0
,
RX_BUF_CLR
);
/* Set rx packet area to 0. */
out
w
(
0
,
RX_BUF_CLR
);
/* Set rx packet area to 0. */
cli
();
/* Avoid glitch on writes to CMD regs */
cli
();
/* Avoid glitch on writes to CMD regs */
outb
(
TX_NORM
,
TX_CMD
);
/* tx irq on done, collision */
outb
(
TX_NORM
,
TX_CMD
);
/* tx irq on done, collision */
outb
(
RX_NORM
,
RX_CMD
);
/* Set Rx commands. */
outb
(
RX_NORM
,
RX_CMD
);
/* Set Rx commands. */
...
@@ -487,7 +510,8 @@ el1_close(struct device *dev)
...
@@ -487,7 +510,8 @@ el1_close(struct device *dev)
static
struct
enet_statistics
*
static
struct
enet_statistics
*
el1_get_stats
(
struct
device
*
dev
)
el1_get_stats
(
struct
device
*
dev
)
{
{
return
&
el_status
.
stats
;
struct
net_local
*
lp
=
(
struct
net_local
*
)
dev
->
priv
;
return
&
lp
->
stats
;
}
}
/* Set or clear the multicast filter for this adaptor.
/* Set or clear the multicast filter for this adaptor.
...
@@ -499,6 +523,8 @@ el1_get_stats(struct device *dev)
...
@@ -499,6 +523,8 @@ el1_get_stats(struct device *dev)
static
void
static
void
set_multicast_list
(
struct
device
*
dev
,
int
num_addrs
,
void
*
addrs
)
set_multicast_list
(
struct
device
*
dev
,
int
num_addrs
,
void
*
addrs
)
{
{
int
ioaddr
=
dev
->
base_addr
;
if
(
num_addrs
>
0
)
{
if
(
num_addrs
>
0
)
{
outb
(
RX_MULT
,
RX_CMD
);
outb
(
RX_MULT
,
RX_CMD
);
inb
(
RX_STATUS
);
/* Clear status. */
inb
(
RX_STATUS
);
/* Clear status. */
...
@@ -510,14 +536,6 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
...
@@ -510,14 +536,6 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
inb
(
RX_STATUS
);
inb
(
RX_STATUS
);
}
}
}
}
/*
* Local variables:
* compile-command: "gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -m486 -c -o 3c501.o 3c501.c"
* kept-new-versions: 5
* End:
*/
#ifdef MODULE
#ifdef MODULE
char
kernel_version
[]
=
UTS_RELEASE
;
char
kernel_version
[]
=
UTS_RELEASE
;
static
struct
device
dev_3c501
=
{
static
struct
device
dev_3c501
=
{
...
@@ -545,3 +563,10 @@ cleanup_module(void)
...
@@ -545,3 +563,10 @@ cleanup_module(void)
}
}
}
}
#endif
/* MODULE */
#endif
/* MODULE */
/*
* Local variables:
* compile-command: "gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -m486 -c -o 3c501.o 3c501.c"
* kept-new-versions: 5
* End:
*/
drivers/net/3c503.c
View file @
6e38a55b
/* 3c503.c: A shared-memory NS8390 ethernet driver for linux. */
/* 3c503.c: A shared-memory NS8390 ethernet driver for linux. */
/*
/*
Written 1992
,1993
by Donald Becker.
Written 1992
-94
by Donald Becker.
Copyright 1993 United States Government as represented by the
Copyright 1993 United States Government as represented by the
Director, National Security Agency. This software may be used and
Director, National Security Agency. This software may be used and
distributed according to the terms of the GNU Public License,
distributed according to the terms of the GNU Public License,
incorporated herein by reference.
incorporated herein by reference.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This driver should work with the 3c503 and 3c503/16. It should be used
This driver should work with the 3c503 and 3c503/16. It should be used
in shared memory mode for best performance, although it may also work
in shared memory mode for best performance, although it may also work
in programmed-I/O mode.
in programmed-I/O mode.
The Author may be reached as becker@super.org or
Sources:
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
EtherLink II Technical Reference Guide,
3Com Corporation, 5400 Bayfront Plaza, Santa Clara CA 95052-8145
The Crynwr 3c503 packet driver.
*/
*/
static
char
*
version
=
static
char
*
version
=
"3c503.c:v
0.99.15k 3/3/93 Donald Becker (becker@super.org
)
\n
"
;
"3c503.c:v
1.10 9/23/93 Donald Becker (becker@cesdis.gsfc.nasa.gov
)
\n
"
;
#include <linux/config.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
...
@@ -31,9 +38,27 @@ static char *version =
...
@@ -31,9 +38,27 @@ static char *version =
#include "8390.h"
#include "8390.h"
#include "3c503.h"
#include "3c503.h"
extern
struct
device
*
init_etherdev
(
struct
device
*
dev
,
int
sizeof_private
,
unsigned
long
*
mem_startp
);
int
el2_probe
(
struct
device
*
dev
);
int
el2_probe
(
struct
device
*
dev
);
int
el2_pio_autoprobe
(
struct
device
*
dev
);
int
el2_pio_probe
(
struct
device
*
dev
);
int
el2probe1
(
int
ioaddr
,
struct
device
*
dev
);
int
el2_probe1
(
struct
device
*
dev
,
int
ioaddr
);
/* A zero-terminated list of I/O addresses to be probed in PIO mode. */
static
unsigned
int
netcard_portlist
[]
=
{
0x300
,
0x310
,
0x330
,
0x350
,
0x250
,
0x280
,
0x2a0
,
0x2e0
,
0
};
#define EL2_IO_EXTENT 16
#ifdef HAVE_DEVLIST
/* The 3c503 uses two entries, one for the safe memory-mapped probe and
the other for the typical I/O probe. */
struct
netdev_entry
el2_drv
=
{
"3c503"
,
el2_probe
,
EL1_IO_EXTENT
,
0
};
struct
netdev_entry
el2pio_drv
=
{
"3c503pio"
,
el2_pioprobe1
,
EL1_IO_EXTENT
,
netcard_portlist
};
#endif
static
int
el2_open
(
struct
device
*
dev
);
static
int
el2_open
(
struct
device
*
dev
);
static
int
el2_close
(
struct
device
*
dev
);
static
int
el2_close
(
struct
device
*
dev
);
...
@@ -52,19 +77,16 @@ static int el2_block_input(struct device *dev, int count, char *buf,
...
@@ -52,19 +77,16 @@ static int el2_block_input(struct device *dev, int count, char *buf,
If the ethercard isn't found there is an optional probe for
If the ethercard isn't found there is an optional probe for
ethercard jumpered to programmed-I/O mode.
ethercard jumpered to programmed-I/O mode.
*/
*/
static
int
ports
[]
=
{
0x300
,
0x310
,
0x330
,
0x350
,
0x250
,
0x280
,
0x2a0
,
0x2e0
,
0
};
int
int
el2_probe
(
struct
device
*
dev
)
el2_probe
(
struct
device
*
dev
)
{
{
int
*
addr
,
addrs
[]
=
{
0xddffe
,
0xd9ffe
,
0xcdffe
,
0xc9ffe
,
0
};
int
*
addr
,
addrs
[]
=
{
0xddffe
,
0xd9ffe
,
0xcdffe
,
0xc9ffe
,
0
};
short
io
addr
=
dev
->
base_addr
;
int
base_
addr
=
dev
->
base_addr
;
if
(
ioaddr
<
0
)
if
(
base_addr
>
0x1ff
)
/* Check a single specified location. */
return
ENXIO
;
/* Don't probe at all. */
return
el2_probe1
(
dev
,
base_addr
);
if
(
ioaddr
>
0
)
else
if
(
base_addr
!=
0
)
/* Don't probe at all. */
return
!
el2probe1
(
ioaddr
,
dev
)
;
return
ENXIO
;
for
(
addr
=
addrs
;
*
addr
;
addr
++
)
{
for
(
addr
=
addrs
;
*
addr
;
addr
++
)
{
int
i
;
int
i
;
...
@@ -75,86 +97,99 @@ el2_probe(struct device *dev)
...
@@ -75,86 +97,99 @@ el2_probe(struct device *dev)
break
;
break
;
if
(
base_bits
!=
1
)
if
(
base_bits
!=
1
)
continue
;
continue
;
#ifdef HAVE_PORTRESERVE
if
(
check_region
(
netcard_portlist
[
i
],
EL2_IO_EXTENT
))
if
(
check_region
(
ports
[
i
],
16
))
continue
;
continue
;
#endif
if
(
el2_probe1
(
dev
,
netcard_portlist
[
i
])
==
0
)
if
(
el2probe1
(
ports
[
i
],
dev
))
return
0
;
return
0
;
}
}
#if
ndef no_probe_nonshared_memory
#if
! defined(no_probe_nonshared_memory) && ! defined (HAVE_DEVLIST)
return
el2_pio_
auto
probe
(
dev
);
return
el2_pio_probe
(
dev
);
#else
#else
return
ENODEV
;
return
ENODEV
;
#endif
#endif
}
}
#ifndef HAVE_DEVLIST
/* Try all of the locations that aren't obviously empty. This touches
/* Try all of the locations that aren't obviously empty. This touches
a lot of locations, and is much riskier than the code above. */
a lot of locations, and is much riskier than the code above. */
int
int
el2_pio_
auto
probe
(
struct
device
*
dev
)
el2_pio_probe
(
struct
device
*
dev
)
{
{
int
i
;
int
i
;
for
(
i
=
0
;
i
<
8
;
i
++
)
{
int
base_addr
=
dev
?
dev
->
base_addr
:
0
;
#ifdef HAVE_PORTRESERVE
if
(
check_region
(
ports
[
i
],
16
))
if
(
base_addr
>
0x1ff
)
/* Check a single specified location. */
continue
;
return
el2_probe1
(
dev
,
base_addr
);
#endif
else
if
(
base_addr
!=
0
)
/* Don't probe at all. */
/* Reset and/or avoid any lurking NE2000 */
return
ENXIO
;
if
(
inb_p
(
ports
[
i
]
+
0x408
)
==
0xff
)
for
(
i
=
0
;
netcard_portlist
[
i
];
i
++
)
{
int
ioaddr
=
netcard_portlist
[
i
];
if
(
check_region
(
ioaddr
,
EL2_IO_EXTENT
))
continue
;
continue
;
if
(
inb
(
ports
[
i
]
+
0x403
)
==
(
0x80
>>
i
)
/* Preliminary check */
if
(
el2_probe1
(
dev
,
ioaddr
)
==
0
)
&&
el2probe1
(
ports
[
i
],
dev
))
return
0
;
return
0
;
}
}
return
ENODEV
;
return
ENODEV
;
}
}
#endif
/* Probe for the Etherlink II card at I/O port base IOADDR,
/* Probe for the Etherlink II card at I/O port base IOADDR,
returning non-zero on success. If found, set the station
returning non-zero on success. If found, set the station
address and memory parameters in DEVICE. */
address and memory parameters in DEVICE. */
int
int
el2
probe1
(
int
ioaddr
,
struct
device
*
dev
)
el2
_probe1
(
struct
device
*
dev
,
int
ioaddr
)
{
{
int
i
,
iobase_reg
,
membase_reg
,
saved_406
;
int
i
,
iobase_reg
,
membase_reg
,
saved_406
;
unsigned
char
*
station_addr
=
dev
->
dev_addr
;
static
unsigned
version_printed
=
0
;
/* Reset and/or avoid any lurking NE2000 */
if
(
inb
(
ioaddr
+
0x408
)
==
0xff
)
return
ENODEV
;
/* We verify that it's a 3C503 board by checking the first three octets
/* We verify that it's a 3C503 board by checking the first three octets
of its ethernet address. */
of its ethernet address. */
printk
(
"3c503 probe at %#3x:"
,
ioaddr
);
iobase_reg
=
inb
(
ioaddr
+
0x403
);
iobase_reg
=
inb
(
ioaddr
+
0x403
);
membase_reg
=
inb
(
ioaddr
+
0x404
);
membase_reg
=
inb
(
ioaddr
+
0x404
);
/*
Verify ASIC register that should be 0 or have
a single bit set. */
/*
ASIC location registers should be 0 or have only
a single bit set. */
if
(
(
iobase_reg
&
(
iobase_reg
-
1
))
if
(
(
iobase_reg
&
(
iobase_reg
-
1
))
||
(
membase_reg
&
(
membase_reg
-
1
)))
{
||
(
membase_reg
&
(
membase_reg
-
1
)))
{
printk
(
" not found.
\n
"
);
return
ENODEV
;
return
0
;
}
}
saved_406
=
inb_p
(
ioaddr
+
0x406
);
saved_406
=
inb_p
(
ioaddr
+
0x406
);
outb_p
(
ECNTRL_RESET
|
ECNTRL_THIN
,
ioaddr
+
0x406
);
/* Reset it... */
outb_p
(
ECNTRL_RESET
|
ECNTRL_THIN
,
ioaddr
+
0x406
);
/* Reset it... */
outb_p
(
ECNTRL_THIN
,
ioaddr
+
0x406
);
outb_p
(
ECNTRL_THIN
,
ioaddr
+
0x406
);
/* Map the station addr PROM into the lower I/O ports. */
/* Map the station addr PROM into the lower I/O ports. */
outb
(
ECNTRL_SAPROM
|
ECNTRL_THIN
,
ioaddr
+
0x406
);
outb
(
ECNTRL_SAPROM
|
ECNTRL_THIN
,
ioaddr
+
0x406
);
for
(
i
=
0
;
i
<
ETHER_ADDR_LEN
;
i
++
)
{
if
(
inb
(
ioaddr
+
0
)
!=
0x02
printk
(
" %2.2X"
,
(
station_addr
[
i
]
=
inb
(
ioaddr
+
i
)));
||
inb
(
ioaddr
+
1
)
!=
0x60
}
||
inb
(
ioaddr
+
2
)
!=
0x8c
)
{
if
(
station_addr
[
0
]
!=
0x02
||
station_addr
[
1
]
!=
0x60
||
station_addr
[
2
]
!=
0x8c
)
{
printk
(
" 3C503 not found.
\n
"
);
/* Restore the register we frobbed. */
/* Restore the register we frobbed. */
outb
(
saved_406
,
ioaddr
+
0x406
);
outb
(
saved_406
,
ioaddr
+
0x406
);
return
0
;
return
ENODEV
;
}
}
#ifdef HAVE_PORTRESERVE
snarf_region
(
ioaddr
,
EL2_IO_EXTENT
);
snarf_region
(
ioaddr
,
16
);
#endif
if
(
dev
==
NULL
)
dev
=
init_etherdev
(
0
,
sizeof
(
struct
ei_device
),
0
);
if
(
ei_debug
&&
version_printed
++
==
0
)
printk
(
version
);
dev
->
base_addr
=
ioaddr
;
ethdev_init
(
dev
);
ethdev_init
(
dev
);
printk
(
"%s: 3c503 at %#3x,"
,
dev
->
name
,
ioaddr
);
/* Retrive and print the ethernet address. */
for
(
i
=
0
;
i
<
6
;
i
++
)
printk
(
" %2.2x"
,
dev
->
dev_addr
[
i
]
=
inb
(
ioaddr
+
i
));
/* Map the 8390 back into the window. */
/* Map the 8390 back into the window. */
outb
(
ECNTRL_THIN
,
ioaddr
+
0x406
);
outb
(
ECNTRL_THIN
,
ioaddr
+
0x406
);
dev
->
base_addr
=
ioaddr
;
/* Probe for, turn on and clear the board's shared memory. */
/* Probe for, turn on and clear the board's shared memory. */
if
(
ei_debug
>
2
)
printk
(
" memory jumpers %2.2x "
,
membase_reg
);
if
(
ei_debug
>
2
)
printk
(
" memory jumpers %2.2x "
,
membase_reg
);
outb
(
EGACFR_NORM
,
ioaddr
+
0x405
);
/* Enable RAM */
outb
(
EGACFR_NORM
,
ioaddr
+
0x405
);
/* Enable RAM */
...
@@ -231,10 +266,11 @@ el2probe1(int ioaddr, struct device *dev)
...
@@ -231,10 +266,11 @@ el2probe1(int ioaddr, struct device *dev)
else
else
printk
(
"
\n
%s: %s using programmed I/O (REJUMPER for SHARED MEMORY).
\n
"
,
printk
(
"
\n
%s: %s using programmed I/O (REJUMPER for SHARED MEMORY).
\n
"
,
dev
->
name
,
ei_status
.
name
);
dev
->
name
,
ei_status
.
name
);
if
(
ei_debug
>
1
)
if
(
ei_debug
>
1
)
printk
(
version
);
printk
(
version
);
return
ioaddr
;
return
0
;
}
}
static
int
static
int
...
@@ -425,5 +461,6 @@ el2_block_input(struct device *dev, int count, char *buf, int ring_offset)
...
@@ -425,5 +461,6 @@ el2_block_input(struct device *dev, int count, char *buf, int ring_offset)
* Local variables:
* Local variables:
* version-control: t
* version-control: t
* kept-new-versions: 5
* kept-new-versions: 5
* c-indent-level: 4
* End:
* End:
*/
*/
drivers/net/3c507.c
View file @
6e38a55b
/* 3c507.c: An EtherLink16 device driver for Linux. */
/* 3c507.c: An EtherLink16 device driver for Linux. */
/*
/*
Written 1993 by Donald Becker.
Written 1993,1994 by Donald Becker.
Copyright 1993 United States Government as represented by the Director,
National Security Agency. This software may only be used and distributed
according to the terms of the GNU Public License as modified by SRC,
incorporated herein by reference.
The author may be reached as becker@super.org or
Copyright 1993 United States Government as represented by the
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
Director, National Security Agency.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
Thanks go to jennings@Montrouge.SMR.slb.com ( Patrick Jennings)
Thanks go to jennings@Montrouge.SMR.slb.com ( Patrick Jennings)
and jrs@world.std.com (Rick Sladkey) for testing and bugfixes.
and jrs@world.std.com (Rick Sladkey) for testing and bugfixes.
...
@@ -21,7 +24,7 @@
...
@@ -21,7 +24,7 @@
*/
*/
static
char
*
version
=
static
char
*
version
=
"3c507.c:v
0.99-15f 2/17/94 Donald Becker (becker@super.org
)
\n
"
;
"3c507.c:v
1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov
)
\n
"
;
#include <linux/config.h>
#include <linux/config.h>
...
@@ -33,7 +36,7 @@ static char *version =
...
@@ -33,7 +36,7 @@ static char *version =
for Russ Nelson.
for Russ Nelson.
Intel Microcommunications Databook, Vol. 1, 1990. It provides just enough
Intel Microcommunications Databook, Vol. 1, 1990. It provides just enough
info that the casual reader might think that it documents the i82586.
info that the casual reader might think that it documents the i82586
:-<
.
*/
*/
#include <linux/kernel.h>
#include <linux/kernel.h>
...
@@ -56,12 +59,20 @@ static char *version =
...
@@ -56,12 +59,20 @@ static char *version =
#include <linux/skbuff.h>
#include <linux/skbuff.h>
#include <linux/malloc.h>
#include <linux/malloc.h>
extern
struct
device
*
init_etherdev
(
struct
device
*
dev
,
int
sizeof_private
,
unsigned
long
*
mem_startp
);
/* use 0 for production, 1 for verification, 2..7 for debug */
/* use 0 for production, 1 for verification, 2..7 for debug */
#ifndef NET_DEBUG
#ifndef NET_DEBUG
#define NET_DEBUG 1
#define NET_DEBUG 1
#endif
#endif
static
unsigned
int
net_debug
=
NET_DEBUG
;
static
unsigned
int
net_debug
=
NET_DEBUG
;
/* A zero-terminated list of common I/O addresses to be probed. */
static
unsigned
int
netcard_portlist
[]
=
{
0x300
,
0x320
,
0x340
,
0x280
,
0
};
/*
/*
Details of the i82586.
Details of the i82586.
...
@@ -130,6 +141,7 @@ struct net_local {
...
@@ -130,6 +141,7 @@ struct net_local {
#define ROM_CONFIG 13
#define ROM_CONFIG 13
#define MEM_CONFIG 14
#define MEM_CONFIG 14
#define IRQ_CONFIG 15
#define IRQ_CONFIG 15
#define EL16_IO_EXTENT 16
/* The ID port is used at boot-time to locate the ethercard. */
/* The ID port is used at boot-time to locate the ethercard. */
#define ID_PORT 0x100
#define ID_PORT 0x100
...
@@ -267,7 +279,7 @@ unsigned short init_words[] = {
...
@@ -267,7 +279,7 @@ unsigned short init_words[] = {
extern
int
el16_probe
(
struct
device
*
dev
);
/* Called from Space.c */
extern
int
el16_probe
(
struct
device
*
dev
);
/* Called from Space.c */
static
int
el16_probe1
(
struct
device
*
dev
,
shor
t
ioaddr
);
static
int
el16_probe1
(
struct
device
*
dev
,
in
t
ioaddr
);
static
int
el16_open
(
struct
device
*
dev
);
static
int
el16_open
(
struct
device
*
dev
);
static
int
el16_send_packet
(
struct
sk_buff
*
skb
,
struct
device
*
dev
);
static
int
el16_send_packet
(
struct
sk_buff
*
skb
,
struct
device
*
dev
);
static
void
el16_interrupt
(
int
reg_ptr
);
static
void
el16_interrupt
(
int
reg_ptr
);
...
@@ -279,6 +291,11 @@ static void hardware_send_packet(struct device *dev, void *buf, short length);
...
@@ -279,6 +291,11 @@ static void hardware_send_packet(struct device *dev, void *buf, short length);
void
init_82586_mem
(
struct
device
*
dev
);
void
init_82586_mem
(
struct
device
*
dev
);
#ifdef HAVE_DEVLIST
struct
netdev_entry
netcard_drv
=
{
"3c507"
,
el16_probe1
,
EL16_IO_EXTENT
,
netcard_portlist
};
#endif
/* Check for a network adaptor of this type, and return '0' iff one exists.
/* Check for a network adaptor of this type, and return '0' iff one exists.
If dev->base_addr == 0, probe all likely locations.
If dev->base_addr == 0, probe all likely locations.
If dev->base_addr == 1, always return failure.
If dev->base_addr == 1, always return failure.
...
@@ -288,17 +305,33 @@ void init_82586_mem(struct device *dev);
...
@@ -288,17 +305,33 @@ void init_82586_mem(struct device *dev);
int
int
el16_probe
(
struct
device
*
dev
)
el16_probe
(
struct
device
*
dev
)
{
{
/* Don't probe all settable addresses, 0x[23][0-F]0, just common ones. */
int
base_addr
=
dev
?
dev
->
base_addr
:
0
;
int
*
port
,
ports
[]
=
{
0x300
,
0x320
,
0x340
,
0x280
,
0
};
int
i
;
int
base_addr
=
dev
->
base_addr
;
ushort
lrs_state
=
0xff
,
i
;
if
(
base_addr
>
0x1ff
)
/* Check a single specified location. */
if
(
base_addr
>
0x1ff
)
/* Check a single specified location. */
return
el16_probe1
(
dev
,
base_addr
);
return
el16_probe1
(
dev
,
base_addr
);
else
if
(
base_addr
>
0
)
else
if
(
base_addr
!=
0
)
return
ENXIO
;
/* Don't probe at all. */
return
ENXIO
;
/* Don't probe at all. */
/* Send the ID sequence to the ID_PORT to enable the board. */
for
(
i
=
0
;
netcard_portlist
[
i
];
i
++
)
{
int
ioaddr
=
netcard_portlist
[
i
];
if
(
check_region
(
ioaddr
,
EL16_IO_EXTENT
))
continue
;
if
(
el16_probe1
(
dev
,
ioaddr
)
==
0
)
return
0
;
}
return
ENODEV
;
/* ENODEV would be more accurate. */
}
int
el16_probe1
(
struct
device
*
dev
,
int
ioaddr
)
{
static
unsigned
char
init_ID_done
=
0
,
version_printed
=
0
;
int
i
,
irq
,
irqval
;
if
(
init_ID_done
==
0
)
{
ushort
lrs_state
=
0xff
;
/* Send the ID sequence to the ID_PORT to enable the board(s). */
outb
(
0x00
,
ID_PORT
);
outb
(
0x00
,
ID_PORT
);
for
(
i
=
0
;
i
<
255
;
i
++
)
{
for
(
i
=
0
;
i
<
255
;
i
++
)
{
outb
(
lrs_state
,
ID_PORT
);
outb
(
lrs_state
,
ID_PORT
);
...
@@ -307,35 +340,21 @@ el16_probe(struct device *dev)
...
@@ -307,35 +340,21 @@ el16_probe(struct device *dev)
lrs_state
^=
0xe7
;
lrs_state
^=
0xe7
;
}
}
outb
(
0x00
,
ID_PORT
);
outb
(
0x00
,
ID_PORT
);
init_ID_done
=
1
;
}
for
(
port
=
&
ports
[
0
];
*
port
;
port
++
)
{
short
ioaddr
=
*
port
;
#if 0
/* This is my original code. */
if
(
inb
(
ioaddr
)
==
'*'
&&
inb
(
ioaddr
+
1
)
==
'3'
if
(
inb
(
ioaddr
)
==
'*'
&&
inb
(
ioaddr
+
1
)
==
'3'
&& inb(ioaddr+2) == 'C' && inb(ioaddr+3) == 'O'
&&
inb
(
ioaddr
+
2
)
==
'C'
&&
inb
(
ioaddr
+
3
)
==
'O'
)
&& el16_probe1(dev, *port) == 0)
;
return 0;
else
#else
return
ENODEV
;
/* This is code from jennings@Montrouge.SMR.slb.com, done so that
the string can be printed out. */
char
res
[
5
];
res
[
0
]
=
inb
(
ioaddr
);
res
[
1
]
=
inb
(
ioaddr
+
1
);
res
[
2
]
=
inb
(
ioaddr
+
2
);
res
[
3
]
=
inb
(
ioaddr
+
3
);
res
[
4
]
=
0
;
if
(
res
[
0
]
==
'*'
&&
res
[
1
]
==
'3'
&&
res
[
2
]
==
'C'
&&
res
[
3
]
==
'O'
&&
el16_probe1
(
dev
,
*
port
)
==
0
)
return
0
;
#endif
}
return
ENODEV
;
/* ENODEV would be more accurate. */
/* Allocate a new 'dev' if needed. */
}
if
(
dev
==
NULL
)
dev
=
init_etherdev
(
0
,
sizeof
(
struct
net_local
),
0
);
int
el16_probe1
(
struct
device
*
dev
,
short
ioaddr
)
if
(
net_debug
&&
version_printed
++
==
0
)
{
printk
(
version
);
int
i
,
irq
,
irqval
;
printk
(
"%s: 3c507 at %#x,"
,
dev
->
name
,
ioaddr
);
printk
(
"%s: 3c507 at %#x,"
,
dev
->
name
,
ioaddr
);
...
@@ -351,7 +370,7 @@ int el16_probe1(struct device *dev, short ioaddr)
...
@@ -351,7 +370,7 @@ int el16_probe1(struct device *dev, short ioaddr)
}
}
/* We've committed to using the board, and can start filling in *dev. */
/* We've committed to using the board, and can start filling in *dev. */
snarf_region
(
ioaddr
,
16
);
snarf_region
(
ioaddr
,
EL16_IO_EXTENT
);
dev
->
base_addr
=
ioaddr
;
dev
->
base_addr
=
ioaddr
;
outb
(
0x01
,
ioaddr
+
MISC_CTRL
);
outb
(
0x01
,
ioaddr
+
MISC_CTRL
);
...
@@ -394,6 +413,7 @@ int el16_probe1(struct device *dev, short ioaddr)
...
@@ -394,6 +413,7 @@ int el16_probe1(struct device *dev, short ioaddr)
printk
(
version
);
printk
(
version
);
/* Initialize the device structure. */
/* Initialize the device structure. */
if
(
dev
->
priv
==
NULL
)
dev
->
priv
=
kmalloc
(
sizeof
(
struct
net_local
),
GFP_KERNEL
);
dev
->
priv
=
kmalloc
(
sizeof
(
struct
net_local
),
GFP_KERNEL
);
memset
(
dev
->
priv
,
0
,
sizeof
(
struct
net_local
));
memset
(
dev
->
priv
,
0
,
sizeof
(
struct
net_local
));
...
...
drivers/net/3c509.c
View file @
6e38a55b
...
@@ -24,7 +24,7 @@
...
@@ -24,7 +24,7 @@
practice this rarely happens.
practice this rarely happens.
*/
*/
static
char
*
version
=
"3c509.c:1.0
1 7/5
/94 becker@cesdis.gsfc.nasa.gov
\n
"
;
static
char
*
version
=
"3c509.c:1.0
3 10/8
/94 becker@cesdis.gsfc.nasa.gov
\n
"
;
#include <linux/config.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
...
@@ -65,7 +65,23 @@ int el3_debug = 2;
...
@@ -65,7 +65,23 @@ int el3_debug = 2;
#define ID_PORT 0x100
#define ID_PORT 0x100
#define EEPROM_READ 0x80
#define EEPROM_READ 0x80
#define EL3WINDOW(win_num) outw(0x0800+(win_num), ioaddr + EL3_CMD)
#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
/* The top five bits written to EL3_CMD are a command, the lower
11 bits are the parameter, if applicable. */
enum
c509cmd
{
TotalReset
=
0
<<
11
,
SelectWindow
=
1
<<
11
,
StartCoax
=
2
<<
11
,
RxDisable
=
3
<<
11
,
RxEnable
=
4
<<
11
,
RxReset
=
5
<<
11
,
RxDiscard
=
8
<<
11
,
TxEnable
=
9
<<
11
,
TxDisable
=
10
<<
11
,
TxReset
=
11
<<
11
,
FakeIntr
=
12
<<
11
,
AckIntr
=
13
<<
11
,
SetIntrMask
=
14
<<
11
,
SetReadZero
=
15
<<
11
,
SetRxFilter
=
16
<<
11
,
SetRxThreshold
=
17
<<
11
,
SetTxThreshold
=
18
<<
11
,
SetTxStart
=
19
<<
11
,
StatsEnable
=
21
<<
11
,
StatsDisable
=
22
<<
11
,
StopCoax
=
23
<<
11
,};
/* The SetRxFilter command accepts the following classes: */
enum
RxFilter
{
RxStation
=
1
,
RxMulticast
=
2
,
RxBroadcast
=
4
,
RxProm
=
8
};
/* Register window 1 offsets, the window used in normal operation. */
/* Register window 1 offsets, the window used in normal operation. */
#define TX_FIFO 0x00
#define TX_FIFO 0x00
...
@@ -74,7 +90,8 @@ int el3_debug = 2;
...
@@ -74,7 +90,8 @@ int el3_debug = 2;
#define TX_STATUS 0x0B
#define TX_STATUS 0x0B
#define TX_FREE 0x0C
/* Remaining free bytes in Tx buffer. */
#define TX_FREE 0x0C
/* Remaining free bytes in Tx buffer. */
#define WN4_MEDIA 0x0A
/* Window 4: Various transceiver/media bits. */
#define WN0_IRQ 0x08
/* Window 0: Set IRQ line in bits 12-15. */
#define WN4_MEDIA 0x0A
/* Window 4: Various transcvr/media bits. */
#define MEDIA_TP 0x00C0
/* Enable link beat and jabber for 10baseT. */
#define MEDIA_TP 0x00C0
/* Enable link beat and jabber for 10baseT. */
struct
el3_private
{
struct
el3_private
{
...
@@ -116,9 +133,9 @@ int el3_probe(struct device *dev)
...
@@ -116,9 +133,9 @@ int el3_probe(struct device *dev)
continue
;
continue
;
/* Change the register set to the configuration window 0. */
/* Change the register set to the configuration window 0. */
outw
(
0x080
0
,
ioaddr
+
0xC80
+
EL3_CMD
);
outw
(
SelectWindow
|
0
,
ioaddr
+
0xC80
+
EL3_CMD
);
irq
=
inw
(
ioaddr
+
8
)
>>
12
;
irq
=
inw
(
ioaddr
+
WN0_IRQ
)
>>
12
;
if_port
=
inw
(
ioaddr
+
6
)
>>
14
;
if_port
=
inw
(
ioaddr
+
6
)
>>
14
;
for
(
i
=
0
;
i
<
3
;
i
++
)
for
(
i
=
0
;
i
<
3
;
i
++
)
phys_addr
[
i
]
=
htons
(
read_eeprom
(
ioaddr
,
i
));
phys_addr
[
i
]
=
htons
(
read_eeprom
(
ioaddr
,
i
));
...
@@ -137,7 +154,7 @@ int el3_probe(struct device *dev)
...
@@ -137,7 +154,7 @@ int el3_probe(struct device *dev)
for
(
i
=
0
;
i
<
8
;
i
++
)
for
(
i
=
0
;
i
<
8
;
i
++
)
if
((
mca_adaptor_id
(
i
)
|
1
)
==
0x627c
)
{
if
((
mca_adaptor_id
(
i
)
|
1
)
==
0x627c
)
{
ioaddr
=
mca_pos_base_addr
(
i
);
ioaddr
=
mca_pos_base_addr
(
i
);
irq
=
inw
(
ioaddr
+
8
)
>>
12
;
irq
=
inw
(
ioaddr
+
WN0_IRQ
)
>>
12
;
if_port
=
inw
(
ioaddr
+
6
)
>>
14
;
if_port
=
inw
(
ioaddr
+
6
)
>>
14
;
for
(
i
=
0
;
i
<
3
;
i
++
)
for
(
i
=
0
;
i
<
3
;
i
++
)
phys_addr
[
i
]
=
htons
(
read_eeprom
(
ioaddr
,
i
));
phys_addr
[
i
]
=
htons
(
read_eeprom
(
ioaddr
,
i
));
...
@@ -201,6 +218,8 @@ int el3_probe(struct device *dev)
...
@@ -201,6 +218,8 @@ int el3_probe(struct device *dev)
if
(
inw
(
ioaddr
)
!=
0x6d50
)
if
(
inw
(
ioaddr
)
!=
0x6d50
)
return
-
ENODEV
;
return
-
ENODEV
;
/* Free the interrupt so that some other card can use it. */
outw
(
0x0f00
,
ioaddr
+
WN0_IRQ
);
found:
found:
dev
->
base_addr
=
ioaddr
;
dev
->
base_addr
=
ioaddr
;
dev
->
irq
=
irq
;
dev
->
irq
=
irq
;
...
@@ -283,6 +302,10 @@ el3_open(struct device *dev)
...
@@ -283,6 +302,10 @@ el3_open(struct device *dev)
int
ioaddr
=
dev
->
base_addr
;
int
ioaddr
=
dev
->
base_addr
;
int
i
;
int
i
;
outw
(
TxReset
,
ioaddr
+
EL3_CMD
);
outw
(
RxReset
,
ioaddr
+
EL3_CMD
);
outw
(
SetReadZero
|
0x00
,
ioaddr
+
EL3_CMD
);
if
(
request_irq
(
dev
->
irq
,
&
el3_interrupt
,
0
,
"3c509"
))
{
if
(
request_irq
(
dev
->
irq
,
&
el3_interrupt
,
0
,
"3c509"
))
{
return
-
EAGAIN
;
return
-
EAGAIN
;
}
}
...
@@ -298,7 +321,7 @@ el3_open(struct device *dev)
...
@@ -298,7 +321,7 @@ el3_open(struct device *dev)
irq2dev_map
[
dev
->
irq
]
=
dev
;
irq2dev_map
[
dev
->
irq
]
=
dev
;
/* Set the IRQ line. */
/* Set the IRQ line. */
outw
((
dev
->
irq
<<
12
)
|
0x0f00
,
ioaddr
+
8
);
outw
((
dev
->
irq
<<
12
)
|
0x0f00
,
ioaddr
+
WN0_IRQ
);
/* Set the station address in window 2 each time opened. */
/* Set the station address in window 2 each time opened. */
EL3WINDOW
(
2
);
EL3WINDOW
(
2
);
...
@@ -308,25 +331,38 @@ el3_open(struct device *dev)
...
@@ -308,25 +331,38 @@ el3_open(struct device *dev)
if
(
dev
->
if_port
==
3
)
if
(
dev
->
if_port
==
3
)
/* Start the thinnet transceiver. We should really wait 50ms...*/
/* Start the thinnet transceiver. We should really wait 50ms...*/
outw
(
0x1000
,
ioaddr
+
EL3_CMD
);
outw
(
StartCoax
,
ioaddr
+
EL3_CMD
);
else
if
(
dev
->
if_port
==
0
)
{
else
if
(
dev
->
if_port
==
0
)
{
/* 10baseT interface, enabled link beat and jabber check. */
/* 10baseT interface, enabled link beat and jabber check. */
EL3WINDOW
(
4
);
EL3WINDOW
(
4
);
outw
(
inw
(
ioaddr
+
WN4_MEDIA
)
|
MEDIA_TP
,
ioaddr
+
WN4_MEDIA
);
outw
(
inw
(
ioaddr
+
WN4_MEDIA
)
|
MEDIA_TP
,
ioaddr
+
WN4_MEDIA
);
}
}
/* Switch to the stats window, and clear all stats by reading. */
outw
(
StatsDisable
,
ioaddr
+
EL3_CMD
);
EL3WINDOW
(
6
);
for
(
i
=
0
;
i
<
9
;
i
++
)
inb
(
ioaddr
+
i
);
inb
(
ioaddr
+
10
);
inb
(
ioaddr
+
12
);
/* Switch to register set 1 for normal use. */
/* Switch to register set 1 for normal use. */
EL3WINDOW
(
1
);
EL3WINDOW
(
1
);
outw
(
0x8005
,
ioaddr
+
EL3_CMD
);
/* Accept b-case and phys addr only. */
/* Accept b-case and phys addr only. */
outw
(
0xA800
,
ioaddr
+
EL3_CMD
);
/* Turn on statistics. */
outw
(
SetRxFilter
|
RxStation
|
RxBroadcast
,
ioaddr
+
EL3_CMD
);
outw
(
0x2000
,
ioaddr
+
EL3_CMD
);
/* Enable the receiver. */
outw
(
StatsEnable
,
ioaddr
+
EL3_CMD
);
/* Turn on statistics. */
outw
(
0x4800
,
ioaddr
+
EL3_CMD
);
/* Enable transmitter. */
outw
(
0x78ff
,
ioaddr
+
EL3_CMD
);
/* Allow all status bits to be seen. */
dev
->
interrupt
=
0
;
dev
->
interrupt
=
0
;
dev
->
tbusy
=
0
;
dev
->
tbusy
=
0
;
dev
->
start
=
1
;
dev
->
start
=
1
;
outw
(
0x7098
,
ioaddr
+
EL3_CMD
);
/* Set interrupt mask. */
outw
(
RxEnable
,
ioaddr
+
EL3_CMD
);
/* Enable the receiver. */
outw
(
TxEnable
,
ioaddr
+
EL3_CMD
);
/* Enable transmitter. */
/* Allow status bits to be seen. */
outw
(
SetReadZero
|
0xff
,
ioaddr
+
EL3_CMD
);
outw
(
AckIntr
|
0x69
,
ioaddr
+
EL3_CMD
);
/* Ack IRQ */
outw
(
SetIntrMask
|
0x98
,
ioaddr
+
EL3_CMD
);
/* Set interrupt mask. */
if
(
el3_debug
>
3
)
if
(
el3_debug
>
3
)
printk
(
"%s: Opened 3c509 IRQ %d status %4.4x.
\n
"
,
printk
(
"%s: Opened 3c509 IRQ %d status %4.4x.
\n
"
,
...
@@ -353,8 +389,8 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
...
@@ -353,8 +389,8 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
dev
->
name
,
inb
(
ioaddr
+
TX_STATUS
),
inw
(
ioaddr
+
EL3_STATUS
));
dev
->
name
,
inb
(
ioaddr
+
TX_STATUS
),
inw
(
ioaddr
+
EL3_STATUS
));
dev
->
trans_start
=
jiffies
;
dev
->
trans_start
=
jiffies
;
/* Issue TX_RESET and TX_START commands. */
/* Issue TX_RESET and TX_START commands. */
outw
(
0x5800
,
ioaddr
+
EL3_CMD
);
/* TX_RESET */
outw
(
TxReset
,
ioaddr
+
EL3_CMD
);
outw
(
0x4800
,
ioaddr
+
EL3_CMD
);
/* TX_START */
outw
(
TxEnable
,
ioaddr
+
EL3_CMD
);
dev
->
tbusy
=
0
;
dev
->
tbusy
=
0
;
}
}
...
@@ -371,7 +407,7 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
...
@@ -371,7 +407,7 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
dev
->
name
,
skb
->
len
,
inw
(
ioaddr
+
EL3_STATUS
));
dev
->
name
,
skb
->
len
,
inw
(
ioaddr
+
EL3_STATUS
));
}
}
#ifndef final_version
#ifndef final_version
{
/* Error-checking code, delete for 1.
0
0. */
{
/* Error-checking code, delete for 1.
3
0. */
ushort
status
=
inw
(
ioaddr
+
EL3_STATUS
);
ushort
status
=
inw
(
ioaddr
+
EL3_STATUS
);
if
(
status
&
0x0001
/* IRQ line active, missed one. */
if
(
status
&
0x0001
/* IRQ line active, missed one. */
&&
inw
(
ioaddr
+
EL3_STATUS
)
&
1
)
{
/* Make sure. */
&&
inw
(
ioaddr
+
EL3_STATUS
)
&
1
)
{
/* Make sure. */
...
@@ -379,9 +415,10 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
...
@@ -379,9 +415,10 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
" Tx %2.2x Rx %4.4x.
\n
"
,
dev
->
name
,
status
,
" Tx %2.2x Rx %4.4x.
\n
"
,
dev
->
name
,
status
,
inw
(
ioaddr
+
EL3_STATUS
),
inb
(
ioaddr
+
TX_STATUS
),
inw
(
ioaddr
+
EL3_STATUS
),
inb
(
ioaddr
+
TX_STATUS
),
inw
(
ioaddr
+
RX_STATUS
));
inw
(
ioaddr
+
RX_STATUS
));
outw
(
0x7800
,
ioaddr
+
EL3_CMD
);
/* Fake interrupt trigger. */
/* Fake interrupt trigger by masking, acknowledge interrupts. */
outw
(
0x6899
,
ioaddr
+
EL3_CMD
);
/* Ack IRQ */
outw
(
SetReadZero
|
0x00
,
ioaddr
+
EL3_CMD
);
outw
(
0x78ff
,
ioaddr
+
EL3_CMD
);
/* Set all status bits visible. */
outw
(
AckIntr
|
0x69
,
ioaddr
+
EL3_CMD
);
/* Ack IRQ */
outw
(
SetReadZero
|
0xff
,
ioaddr
+
EL3_CMD
);
}
}
}
}
#endif
#endif
...
@@ -398,10 +435,10 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
...
@@ -398,10 +435,10 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
dev
->
trans_start
=
jiffies
;
dev
->
trans_start
=
jiffies
;
if
(
inw
(
ioaddr
+
TX_FREE
)
>
1536
)
{
if
(
inw
(
ioaddr
+
TX_FREE
)
>
1536
)
{
dev
->
tbusy
=
0
;
dev
->
tbusy
=
0
;
}
else
}
else
/* Interrupt us when the FIFO has room for max-sized packet. */
/* Interrupt us when the FIFO has room for max-sized packet. */
outw
(
0x9000
+
1536
,
ioaddr
+
EL3_CMD
);
outw
(
SetTxThreshold
+
1536
,
ioaddr
+
EL3_CMD
);
}
}
dev_kfree_skb
(
skb
,
FREE_WRITE
);
dev_kfree_skb
(
skb
,
FREE_WRITE
);
...
@@ -412,11 +449,9 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
...
@@ -412,11 +449,9 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
int
i
=
4
;
int
i
=
4
;
while
(
--
i
>
0
&&
(
tx_status
=
inb
(
ioaddr
+
TX_STATUS
))
>
0
)
{
while
(
--
i
>
0
&&
(
tx_status
=
inb
(
ioaddr
+
TX_STATUS
))
>
0
)
{
if
(
el3_debug
>
5
)
printk
(
" Tx status %4.4x.
\n
"
,
tx_status
);
if
(
tx_status
&
0x38
)
lp
->
stats
.
tx_aborted_errors
++
;
if
(
tx_status
&
0x38
)
lp
->
stats
.
tx_aborted_errors
++
;
if
(
tx_status
&
0x30
)
outw
(
0x5800
,
ioaddr
+
EL3_CMD
);
if
(
tx_status
&
0x30
)
outw
(
TxReset
,
ioaddr
+
EL3_CMD
);
if
(
tx_status
&
0x3C
)
outw
(
0x4800
,
ioaddr
+
EL3_CMD
);
if
(
tx_status
&
0x3C
)
outw
(
TxEnable
,
ioaddr
+
EL3_CMD
);
outb
(
0x00
,
ioaddr
+
TX_STATUS
);
/* Pop the status stack. */
outb
(
0x00
,
ioaddr
+
TX_STATUS
);
/* Pop the status stack. */
}
}
}
}
...
@@ -447,7 +482,7 @@ el3_interrupt(int reg_ptr)
...
@@ -447,7 +482,7 @@ el3_interrupt(int reg_ptr)
if
(
el3_debug
>
4
)
if
(
el3_debug
>
4
)
printk
(
"%s: interrupt, status %4.4x.
\n
"
,
dev
->
name
,
status
);
printk
(
"%s: interrupt, status %4.4x.
\n
"
,
dev
->
name
,
status
);
while
((
status
=
inw
(
ioaddr
+
EL3_STATUS
))
&
0x
0
1
)
{
while
((
status
=
inw
(
ioaddr
+
EL3_STATUS
))
&
0x
9
1
)
{
if
(
status
&
0x10
)
if
(
status
&
0x10
)
el3_rx
(
dev
);
el3_rx
(
dev
);
...
@@ -456,7 +491,7 @@ el3_interrupt(int reg_ptr)
...
@@ -456,7 +491,7 @@ el3_interrupt(int reg_ptr)
if
(
el3_debug
>
5
)
if
(
el3_debug
>
5
)
printk
(
" TX room bit was handled.
\n
"
);
printk
(
" TX room bit was handled.
\n
"
);
/* There's room in the FIFO for a full-sized packet. */
/* There's room in the FIFO for a full-sized packet. */
outw
(
0x6808
,
ioaddr
+
EL3_CMD
);
/* Ack IRQ */
outw
(
AckIntr
|
0x08
,
ioaddr
+
EL3_CMD
);
dev
->
tbusy
=
0
;
dev
->
tbusy
=
0
;
mark_bh
(
NET_BH
);
mark_bh
(
NET_BH
);
}
}
...
@@ -466,12 +501,13 @@ el3_interrupt(int reg_ptr)
...
@@ -466,12 +501,13 @@ el3_interrupt(int reg_ptr)
if
(
++
i
>
10
)
{
if
(
++
i
>
10
)
{
printk
(
"%s: Infinite loop in interrupt, status %4.4x.
\n
"
,
printk
(
"%s: Infinite loop in interrupt, status %4.4x.
\n
"
,
dev
->
name
,
status
);
dev
->
name
,
status
);
/* Clear all interrupts
we have handled
*/
/* Clear all interrupts
.
*/
outw
(
0x68
FF
,
ioaddr
+
EL3_CMD
);
outw
(
AckIntr
|
0x
FF
,
ioaddr
+
EL3_CMD
);
break
;
break
;
}
}
/* Acknowledge the IRQ. */
/* Acknowledge the IRQ. */
outw
(
0x6891
,
ioaddr
+
EL3_CMD
);
/* Ack IRQ */
outw
(
AckIntr
|
0x41
,
ioaddr
+
EL3_CMD
);
/* Ack IRQ */
}
}
if
(
el3_debug
>
4
)
{
if
(
el3_debug
>
4
)
{
...
@@ -488,10 +524,12 @@ static struct enet_statistics *
...
@@ -488,10 +524,12 @@ static struct enet_statistics *
el3_get_stats
(
struct
device
*
dev
)
el3_get_stats
(
struct
device
*
dev
)
{
{
struct
el3_private
*
lp
=
(
struct
el3_private
*
)
dev
->
priv
;
struct
el3_private
*
lp
=
(
struct
el3_private
*
)
dev
->
priv
;
unsigned
long
flags
;
sti
();
save_flags
(
flags
);
update_stats
(
dev
->
base_addr
,
dev
);
cli
();
cli
();
update_stats
(
dev
->
base_addr
,
dev
);
restore_flags
(
flags
);
return
&
lp
->
stats
;
return
&
lp
->
stats
;
}
}
...
@@ -507,7 +545,7 @@ static void update_stats(int ioaddr, struct device *dev)
...
@@ -507,7 +545,7 @@ static void update_stats(int ioaddr, struct device *dev)
if
(
el3_debug
>
5
)
if
(
el3_debug
>
5
)
printk
(
" Updating the statistics.
\n
"
);
printk
(
" Updating the statistics.
\n
"
);
/* Turn off statistics updates while reading. */
/* Turn off statistics updates while reading. */
outw
(
0xB000
,
ioaddr
+
EL3_CMD
);
outw
(
StatsDisable
,
ioaddr
+
EL3_CMD
);
/* Switch to the stats window, and read everything. */
/* Switch to the stats window, and read everything. */
EL3WINDOW
(
6
);
EL3WINDOW
(
6
);
lp
->
stats
.
tx_carrier_errors
+=
inb
(
ioaddr
+
0
);
lp
->
stats
.
tx_carrier_errors
+=
inb
(
ioaddr
+
0
);
...
@@ -517,14 +555,14 @@ static void update_stats(int ioaddr, struct device *dev)
...
@@ -517,14 +555,14 @@ static void update_stats(int ioaddr, struct device *dev)
lp
->
stats
.
tx_window_errors
+=
inb
(
ioaddr
+
4
);
lp
->
stats
.
tx_window_errors
+=
inb
(
ioaddr
+
4
);
lp
->
stats
.
rx_fifo_errors
+=
inb
(
ioaddr
+
5
);
lp
->
stats
.
rx_fifo_errors
+=
inb
(
ioaddr
+
5
);
lp
->
stats
.
tx_packets
+=
inb
(
ioaddr
+
6
);
lp
->
stats
.
tx_packets
+=
inb
(
ioaddr
+
6
);
lp
->
stats
.
rx_packets
+=
inb
(
ioaddr
+
7
);
/* Rx packets */
inb
(
ioaddr
+
7
);
/* Tx deferrals */
inb
(
ioaddr
+
8
);
/* Tx deferrals */
inb
(
ioaddr
+
8
);
inw
(
ioaddr
+
10
);
/* Total Rx and Tx octets. */
inw
(
ioaddr
+
10
);
/* Total Rx and Tx octets. */
inw
(
ioaddr
+
12
);
inw
(
ioaddr
+
12
);
/* Back to window 1, and turn statistics back on. */
/* Back to window 1, and turn statistics back on. */
EL3WINDOW
(
1
);
EL3WINDOW
(
1
);
outw
(
0xA800
,
ioaddr
+
EL3_CMD
);
outw
(
StatsEnable
,
ioaddr
+
EL3_CMD
);
return
;
return
;
}
}
...
@@ -550,9 +588,7 @@ el3_rx(struct device *dev)
...
@@ -550,9 +588,7 @@ el3_rx(struct device *dev)
case
0x2000
:
lp
->
stats
.
rx_frame_errors
++
;
break
;
case
0x2000
:
lp
->
stats
.
rx_frame_errors
++
;
break
;
case
0x2800
:
lp
->
stats
.
rx_crc_errors
++
;
break
;
case
0x2800
:
lp
->
stats
.
rx_crc_errors
++
;
break
;
}
}
}
}
else
{
if
(
(
!
(
rx_status
&
0x4000
))
||
!
(
rx_status
&
0x1000
))
{
/* Dribble bits are OK. */
short
pkt_len
=
rx_status
&
0x7ff
;
short
pkt_len
=
rx_status
&
0x7ff
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
...
@@ -568,45 +604,21 @@ el3_rx(struct device *dev)
...
@@ -568,45 +604,21 @@ el3_rx(struct device *dev)
insl
(
ioaddr
+
RX_FIFO
,
skb
->
data
,
insl
(
ioaddr
+
RX_FIFO
,
skb
->
data
,
(
pkt_len
+
3
)
>>
2
);
(
pkt_len
+
3
)
>>
2
);
#ifdef HAVE_NETIF_RX
netif_rx
(
skb
);
netif_rx
(
skb
);
outw
(
0x4000
,
ioaddr
+
EL3_CMD
);
/* Rx discard */
outw
(
RxDiscard
,
ioaddr
+
EL3_CMD
);
/* Pop top Rx packet. */
lp
->
stats
.
rx_packets
++
;
continue
;
continue
;
#else
skb
->
lock
=
0
;
if
(
dev_rint
((
unsigned
char
*
)
skb
,
pkt_len
,
IN_SKBUFF
,
dev
)
==
0
){
if
(
el3_debug
>
6
)
printk
(
" dev_rint() happy, status %4.4x.
\n
"
,
inb
(
ioaddr
+
EL3_STATUS
));
outw
(
0x4000
,
ioaddr
+
EL3_CMD
);
/* Rx discard */
while
(
inw
(
ioaddr
+
EL3_STATUS
)
&
0x1000
)
printk
(
" Waiting for 3c509 to discard packet, status %x.
\n
"
,
inw
(
ioaddr
+
EL3_STATUS
)
);
if
(
el3_debug
>
6
)
printk
(
" discarded packet, status %4.4x.
\n
"
,
inb
(
ioaddr
+
EL3_STATUS
));
continue
;
}
else
{
printk
(
"%s: receive buffers full.
\n
"
,
dev
->
name
);
kfree_s
(
skb
,
FREE_READ
);
}
#endif
}
else
if
(
el3_debug
)
}
else
if
(
el3_debug
)
printk
(
"%s: Couldn't allocate a sk_buff of size %d.
\n
"
,
printk
(
"%s: Couldn't allocate a sk_buff of size %d.
\n
"
,
dev
->
name
,
pkt_len
);
dev
->
name
,
pkt_len
);
}
}
lp
->
stats
.
rx_dropped
++
;
lp
->
stats
.
rx_dropped
++
;
outw
(
0x4000
,
ioaddr
+
EL3_CMD
);
/* Rx discard */
outw
(
RxDiscard
,
ioaddr
+
EL3_CMD
);
while
(
inw
(
ioaddr
+
EL3_STATUS
)
&
0x1000
)
while
(
inw
(
ioaddr
+
EL3_STATUS
)
&
0x1000
)
printk
(
" Waiting for 3c509 to discard packet, status %x.
\n
"
,
printk
(
" Waiting for 3c509 to discard packet, status %x.
\n
"
,
inw
(
ioaddr
+
EL3_STATUS
)
);
inw
(
ioaddr
+
EL3_STATUS
)
);
}
}
if
(
el3_debug
>
5
)
printk
(
" Exiting rx_packet(), status %4.4x, rx_status %4.4x.
\n
"
,
inw
(
ioaddr
+
EL3_STATUS
),
inw
(
ioaddr
+
8
));
return
0
;
return
0
;
}
}
...
@@ -621,12 +633,15 @@ static void
...
@@ -621,12 +633,15 @@ static void
set_multicast_list
(
struct
device
*
dev
,
int
num_addrs
,
void
*
addrs
)
set_multicast_list
(
struct
device
*
dev
,
int
num_addrs
,
void
*
addrs
)
{
{
short
ioaddr
=
dev
->
base_addr
;
short
ioaddr
=
dev
->
base_addr
;
if
(
el3_debug
>
1
)
printk
(
"%s: Setting Rx mode to %d addresses.
\n
"
,
dev
->
name
,
num_addrs
);
if
(
num_addrs
>
0
)
{
if
(
num_addrs
>
0
)
{
outw
(
0x8007
,
ioaddr
+
EL3_CMD
);
outw
(
SetRxFilter
|
RxStation
|
RxMulticast
|
RxBroadcast
,
ioaddr
+
EL3_CMD
);
}
else
if
(
num_addrs
<
0
)
{
}
else
if
(
num_addrs
<
0
)
{
outw
(
0x8008
,
ioaddr
+
EL3_CMD
);
outw
(
SetRxFilter
|
RxStation
|
RxMulticast
|
RxBroadcast
|
RxProm
,
ioaddr
+
EL3_CMD
);
}
else
}
else
outw
(
0x8005
,
ioaddr
+
EL3_CMD
);
outw
(
SetRxFilter
|
RxStation
|
RxBroadcast
,
ioaddr
+
EL3_CMD
);
}
}
#endif
#endif
...
@@ -641,16 +656,16 @@ el3_close(struct device *dev)
...
@@ -641,16 +656,16 @@ el3_close(struct device *dev)
dev
->
tbusy
=
1
;
dev
->
tbusy
=
1
;
dev
->
start
=
0
;
dev
->
start
=
0
;
/* Turn off statistics
.
We update lp->stats below. */
/* Turn off statistics
ASAP.
We update lp->stats below. */
outw
(
0xB000
,
ioaddr
+
EL3_CMD
);
outw
(
StatsDisable
,
ioaddr
+
EL3_CMD
);
/* Disable the receiver and transmitter. */
/* Disable the receiver and transmitter. */
outw
(
0x1800
,
ioaddr
+
EL3_CMD
);
outw
(
RxDisable
,
ioaddr
+
EL3_CMD
);
outw
(
0x5000
,
ioaddr
+
EL3_CMD
);
outw
(
TxDisable
,
ioaddr
+
EL3_CMD
);
if
(
dev
->
if_port
==
3
)
if
(
dev
->
if_port
==
3
)
/* Turn off thinnet power. */
/* Turn off thinnet power.
Green!
*/
outw
(
0xb800
,
ioaddr
+
EL3_CMD
);
outw
(
StopCoax
,
ioaddr
+
EL3_CMD
);
else
if
(
dev
->
if_port
==
0
)
{
else
if
(
dev
->
if_port
==
0
)
{
/* Disable link beat and jabber, if_port may change ere next open(). */
/* Disable link beat and jabber, if_port may change ere next open(). */
EL3WINDOW
(
4
);
EL3WINDOW
(
4
);
...
@@ -661,7 +676,7 @@ el3_close(struct device *dev)
...
@@ -661,7 +676,7 @@ el3_close(struct device *dev)
/* Switching back to window 0 disables the IRQ. */
/* Switching back to window 0 disables the IRQ. */
EL3WINDOW
(
0
);
EL3WINDOW
(
0
);
/* But we explicitly zero the IRQ line select anyway. */
/* But we explicitly zero the IRQ line select anyway. */
outw
(
0x0f00
,
ioaddr
+
8
);
outw
(
0x0f00
,
ioaddr
+
WN0_IRQ
);
irq2dev_map
[
dev
->
irq
]
=
0
;
irq2dev_map
[
dev
->
irq
]
=
0
;
...
@@ -672,15 +687,7 @@ el3_close(struct device *dev)
...
@@ -672,15 +687,7 @@ el3_close(struct device *dev)
#endif
#endif
return
0
;
return
0
;
}
}
/*
* Local variables:
* compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c 3c509.c"
* version-control: t
* kept-new-versions: 5
* tab-width: 4
* End:
*/
#ifdef MODULE
#ifdef MODULE
char
kernel_version
[]
=
UTS_RELEASE
;
char
kernel_version
[]
=
UTS_RELEASE
;
static
struct
device
dev_3c509
=
{
static
struct
device
dev_3c509
=
{
...
@@ -707,3 +714,12 @@ cleanup_module(void)
...
@@ -707,3 +714,12 @@ cleanup_module(void)
}
}
}
}
#endif
/* MODULE */
#endif
/* MODULE */
/*
* Local variables:
* compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c 3c509.c"
* version-control: t
* kept-new-versions: 5
* tab-width: 4
* End:
*/
drivers/net/8390.c
View file @
6e38a55b
/* 8390.c: A general NS8390 ethernet driver core for linux. */
/* 8390.c: A general NS8390 ethernet driver core for linux. */
/*
/*
Written 1992,1993
by Donald Becker.
Written 1992-94
by Donald Becker.
Copyright 1993 United States Government as represented by the
Copyright 1993 United States Government as represented by the
Director, National Security Agency. This software may be used and
Director, National Security Agency.
distributed according to the terms of the GNU Public License,
incorporated herein by reference.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This is the chip-specific code for many 8390-based ethernet adaptors.
This is the chip-specific code for many 8390-based ethernet adaptors.
This is not a complete driver, it must be combined with board-specific
This is not a complete driver, it must be combined with board-specific
code such as ne.c, wd.c, 3c503.c, etc.
code such as ne.c, wd.c, 3c503.c, etc.
The Author may be reached as becker@super.org or
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
*/
*/
static
char
*
version
=
static
char
*
version
=
"8390.c:v
0.99-15e 2/16/94 Donald Becker (becker@super.org
)
\n
"
;
"8390.c:v
1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov
)
\n
"
;
#include <linux/config.h>
#include <linux/config.h>
/*
/*
Braindamage remaining:
Braindamage remaining:
Much of this code should
be cleaned up post-1.00, but it has been
Much of this code should
have been cleaned up, but every attempt
extensively beta tested in the current form
.
has broken some clone part
.
Sources:
Sources:
The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
The NE* programming info came from the Crynwr packet driver, and figuring
out that the those boards are similar to the NatSemi evaluation board
described in AN-729. Thanks NS, no thanks to Novell/Eagle.
*/
*/
#include <linux/config.h>
#include <linux/config.h>
...
@@ -302,6 +301,10 @@ void ei_interrupt(int reg_ptr)
...
@@ -302,6 +301,10 @@ void ei_interrupt(int reg_ptr)
}
}
if
(
interrupts
&&
ei_debug
)
{
if
(
interrupts
&&
ei_debug
)
{
if
(
boguscount
==
9
)
printk
(
"%s: Too much work at interrupt, status %#2.2x
\n
"
,
dev
->
name
,
interrupts
);
else
printk
(
"%s: unknown interrupt %#2x
\n
"
,
dev
->
name
,
interrupts
);
printk
(
"%s: unknown interrupt %#2x
\n
"
,
dev
->
name
,
interrupts
);
outb_p
(
E8390_NODMA
+
E8390_PAGE0
+
E8390_START
,
e8390_base
+
E8390_CMD
);
outb_p
(
E8390_NODMA
+
E8390_PAGE0
+
E8390_START
,
e8390_base
+
E8390_CMD
);
outb_p
(
0xff
,
e8390_base
+
EN0_ISR
);
/* Ack. all intrs. */
outb_p
(
0xff
,
e8390_base
+
EN0_ISR
);
/* Ack. all intrs. */
...
...
drivers/net/8390.h
View file @
6e38a55b
...
@@ -41,12 +41,12 @@ struct ei_device {
...
@@ -41,12 +41,12 @@ struct ei_device {
void
(
*
reset_8390
)(
struct
device
*
);
void
(
*
reset_8390
)(
struct
device
*
);
void
(
*
block_output
)(
struct
device
*
,
int
,
const
unsigned
char
*
,
int
);
void
(
*
block_output
)(
struct
device
*
,
int
,
const
unsigned
char
*
,
int
);
int
(
*
block_input
)(
struct
device
*
,
int
,
char
*
,
int
);
int
(
*
block_input
)(
struct
device
*
,
int
,
char
*
,
int
);
int
open
:
1
;
unsigned
open
:
1
;
int
word16
:
1
;
/* We have the 16-bit (vs 8-bit) version of the card. */
unsigned
word16
:
1
;
/* We have the 16-bit (vs 8-bit) version of the card. */
int
txing
:
1
;
/* Transmit Active */
unsigned
txing
:
1
;
/* Transmit Active */
int
dmaing
:
2
;
/* Remote DMA Active */
unsigned
dmaing
:
2
;
/* Remote DMA Active */
int
irqlock
:
1
;
/* 8390's intrs disabled when '1'. */
unsigned
irqlock
:
1
;
/* 8390's intrs disabled when '1'. */
int
pingpong
:
1
;
/* Using the ping-pong driver */
unsigned
pingpong
:
1
;
/* Using the ping-pong driver */
unsigned
char
tx_start_page
,
rx_start_page
,
stop_page
;
unsigned
char
tx_start_page
,
rx_start_page
,
stop_page
;
unsigned
char
current_page
;
/* Read pointer in buffer */
unsigned
char
current_page
;
/* Read pointer in buffer */
unsigned
char
interface_num
;
/* Net port (AUI, 10bT.) to use. */
unsigned
char
interface_num
;
/* Net port (AUI, 10bT.) to use. */
...
...
drivers/net/at1700.c
View file @
6e38a55b
/* at1700.c: A network device driver for the Allied Telesis AT1700.
/* at1700.c: A network device driver for the Allied Telesis AT1700.
Written 1993 by Donald Becker. This is a alpha test limited release.
Written 1993-94 by Donald Becker.
This version may only be used and distributed according to the terms of the
GNU Public License, incorporated herein by reference.
The author may be reached as becker@super.org or
Copyright 1993 United States Government as represented by the
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
Director, National Security Agency.
This is a device driver for the Allied Telesis AT1700, which is a
This software may be used and distributed according to the terms
straightforward Fujitsu MB86965 implementation.
of the GNU Public License, incorporated herein by reference.
*/
static
char
*
version
=
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
"at1700.c:v0.06 3/3/94 Donald Becker (becker@super.org)
\n
"
;
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
#include <linux/config.h>
This is a device driver for the Allied Telesis AT1700, which is a
straight-forward Fujitsu MB86965 implementation.
/*
Sources:
Sources:
The Fujitsu MB86695 datasheet.
The Fujitsu MB86695 datasheet.
After this driver was written, ATI provided their EEPROM configuration
After the initial version of this driver was written Gerry Sockins of
code header file. Thanks to Gerry Sockins of ATI.
ATI provided their EEPROM configurationcode header file.
Thanks to NIIBE Yutaka <gniibe@mri.co.jp> for bug fixes.
Bugs:
The MB86695 has a design flaw that makes all probes unreliable. Not
only is it difficult to detect, it also moves around in I/O space in
response to inb()s from other device probes!
*/
*/
static
char
*
version
=
"at1700.c:v1.10 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)
\n
"
;
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/types.h>
...
@@ -43,19 +52,16 @@ static char *version =
...
@@ -43,19 +52,16 @@ static char *version =
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/skbuff.h>
extern
struct
device
*
init_etherdev
(
struct
device
*
dev
,
int
sizeof_private
,
unsigned
long
*
mem_startp
);
#ifndef HAVE_AUTOIRQ
/* This unusual address order is used to verify the CONFIG register. */
/* From auto_irq.c, in ioport.h for later versions. */
static
int
at1700_probe_list
[]
=
extern
void
autoirq_setup
(
int
waittime
);
{
0x260
,
0x280
,
0x2a0
,
0x240
,
0x340
,
0x320
,
0x380
,
0x300
,
0
};
extern
int
autoirq_report
(
int
waittime
);
/* The map from IRQ number (as passed to the interrupt handler) to
'struct device'. */
extern
struct
device
*
irq2dev_map
[
16
];
#endif
/* use 0 for production, 1 for verification, >2 for debug */
/* use 0 for production, 1 for verification, >2 for debug */
#ifndef NET_DEBUG
#ifndef NET_DEBUG
#define NET_DEBUG
2
#define NET_DEBUG
1
#endif
#endif
static
unsigned
int
net_debug
=
NET_DEBUG
;
static
unsigned
int
net_debug
=
NET_DEBUG
;
...
@@ -87,6 +93,9 @@ struct net_local {
...
@@ -87,6 +93,9 @@ struct net_local {
#define MODE13 13
#define MODE13 13
#define EEPROM_Ctrl 16
#define EEPROM_Ctrl 16
#define EEPROM_Data 17
#define EEPROM_Data 17
#define IOCONFIG 19
#define RESET 31
/* Write to reset some parts of the chip. */
#define AT1700_IO_EXTENT 32
/* EEPROM_Ctrl bits. */
/* EEPROM_Ctrl bits. */
#define EE_SHIFT_CLK 0x40
/* EEPROM shift clock, in reg. 16. */
#define EE_SHIFT_CLK 0x40
/* EEPROM shift clock, in reg. 16. */
...
@@ -124,20 +133,26 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
...
@@ -124,20 +133,26 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
If dev->base_addr == 2, allocate space for the device and return success
If dev->base_addr == 2, allocate space for the device and return success
(detachable devices only).
(detachable devices only).
*/
*/
#ifdef HAVE_DEVLIST
/* Support for a alternate probe manager, which will eliminate the
boilerplate below. */
struct
netdev_entry
at1700_drv
=
{
"at1700"
,
at1700_probe1
,
AT1700_IO_EXTENT
,
at1700_probe_list
};
#else
int
int
at1700_probe
(
struct
device
*
dev
)
at1700_probe
(
struct
device
*
dev
)
{
{
short
ports
[]
=
{
0x300
,
0x280
,
0x380
,
0x320
,
0x340
,
0x260
,
0x2a0
,
0x240
,
0
}
;
int
i
;
short
*
port
,
base_addr
=
dev
->
base_addr
;
int
base_addr
=
dev
?
dev
->
base_addr
:
0
;
if
(
base_addr
>
0x1ff
)
/* Check a single specified location. */
if
(
base_addr
>
0x1ff
)
/* Check a single specified location. */
return
at1700_probe1
(
dev
,
base_addr
);
return
at1700_probe1
(
dev
,
base_addr
);
else
if
(
base_addr
>
0
)
/* Don't probe at all. */
else
if
(
base_addr
!=
0
)
/* Don't probe at all. */
return
ENXIO
;
return
ENXIO
;
for
(
port
=
&
ports
[
0
];
*
port
;
port
++
)
{
for
(
i
=
0
;
at1700_probe_list
[
i
];
i
++
)
{
int
ioaddr
=
*
port
;
int
ioaddr
=
at1700_probe_list
[
i
]
;
if
(
check_region
(
ioaddr
,
32
))
if
(
check_region
(
ioaddr
,
AT1700_IO_EXTENT
))
continue
;
continue
;
if
(
at1700_probe1
(
dev
,
ioaddr
)
==
0
)
if
(
at1700_probe1
(
dev
,
ioaddr
)
==
0
)
return
0
;
return
0
;
...
@@ -145,6 +160,7 @@ at1700_probe(struct device *dev)
...
@@ -145,6 +160,7 @@ at1700_probe(struct device *dev)
return
ENODEV
;
return
ENODEV
;
}
}
#endif
/* The Fujitsu datasheet suggests that the NIC be probed for by checking its
/* The Fujitsu datasheet suggests that the NIC be probed for by checking its
"signature", the default bit pattern after a reset. This *doesn't* work --
"signature", the default bit pattern after a reset. This *doesn't* work --
...
@@ -156,29 +172,24 @@ at1700_probe(struct device *dev)
...
@@ -156,29 +172,24 @@ at1700_probe(struct device *dev)
int
at1700_probe1
(
struct
device
*
dev
,
short
ioaddr
)
int
at1700_probe1
(
struct
device
*
dev
,
short
ioaddr
)
{
{
unsigned
short
signature
[
4
]
=
{
0xffff
,
0xffff
,
0x7ff7
,
0xff5f
};
unsigned
short
signature_invalid
[
4
]
=
{
0xffff
,
0xffff
,
0x7ff7
,
0xdf0f
};
char
irqmap
[
8
]
=
{
3
,
4
,
5
,
9
,
10
,
11
,
14
,
15
};
char
irqmap
[
8
]
=
{
3
,
4
,
5
,
9
,
10
,
11
,
14
,
15
};
unsigned
short
*
station_address
=
(
unsigned
short
*
)
dev
->
dev_addr
;
unsigned
int
i
,
irq
;
unsigned
int
i
,
irq
;
/* Resetting the chip doesn't reset the ISA interface, so don't bother.
/* Resetting the chip doesn't reset the ISA interface, so don't bother.
That means we have to be careful with the register values we probe for.
That means we have to be careful with the register values we probe for.
*/
*/
for
(
i
=
0
;
i
<
4
;
i
++
)
#ifdef notdef
if
((
inw
(
ioaddr
+
2
*
i
)
|
signature_invalid
[
i
])
!=
signature
[
i
])
{
printk
(
"at1700 probe at %#x, eeprom is %4.4x %4.4x %4.4x ctrl %4.4x.
\n
"
,
if
(
net_debug
>
2
)
ioaddr
,
read_eeprom
(
ioaddr
,
4
),
read_eeprom
(
ioaddr
,
5
),
printk
(
"AT1700 signature match failed at %d (%04x vs. %04x)
\n
"
,
read_eeprom
(
ioaddr
,
6
),
inw
(
ioaddr
+
EEPROM_Ctrl
));
i
,
inw
(
ioaddr
+
2
*
i
),
signature
[
i
]);
#endif
return
-
ENODEV
;
if
(
at1700_probe_list
[
inb
(
ioaddr
+
IOCONFIG
)
&
0x07
]
!=
ioaddr
}
||
read_eeprom
(
ioaddr
,
4
)
!=
0x0000
if
(
read_eeprom
(
ioaddr
,
4
)
!=
0x0000
||
read_eeprom
(
ioaddr
,
5
)
&
0xff00
!=
0xF400
)
||
read_eeprom
(
ioaddr
,
5
)
&
0x00ff
!=
0x00F4
)
return
-
ENODEV
;
return
-
ENODEV
;
/* Grab the region so that we can find another board if the IRQ request
/* Reset the internal state machines. */
fails. */
outb
(
0
,
ioaddr
+
RESET
);
snarf_region
(
ioaddr
,
32
);
irq
=
irqmap
[(
read_eeprom
(
ioaddr
,
12
)
&
0x04
)
irq
=
irqmap
[(
read_eeprom
(
ioaddr
,
12
)
&
0x04
)
|
(
read_eeprom
(
ioaddr
,
0
)
>>
14
)];
|
(
read_eeprom
(
ioaddr
,
0
)
>>
14
)];
...
@@ -190,6 +201,14 @@ int at1700_probe1(struct device *dev, short ioaddr)
...
@@ -190,6 +201,14 @@ int at1700_probe1(struct device *dev, short ioaddr)
return
EAGAIN
;
return
EAGAIN
;
}
}
/* Allocate a new 'dev' if needed. */
if
(
dev
==
NULL
)
dev
=
init_etherdev
(
0
,
sizeof
(
struct
net_local
),
0
);
/* Grab the region so that we can find another board if the IRQ request
fails. */
snarf_region
(
ioaddr
,
AT1700_IO_EXTENT
);
printk
(
"%s: AT1700 found at %#3x, IRQ %d, address "
,
dev
->
name
,
printk
(
"%s: AT1700 found at %#3x, IRQ %d, address "
,
dev
->
name
,
ioaddr
,
irq
);
ioaddr
,
irq
);
...
@@ -200,7 +219,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
...
@@ -200,7 +219,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
for
(
i
=
0
;
i
<
3
;
i
++
)
{
for
(
i
=
0
;
i
<
3
;
i
++
)
{
unsigned
short
eeprom_val
=
read_eeprom
(
ioaddr
,
4
+
i
);
unsigned
short
eeprom_val
=
read_eeprom
(
ioaddr
,
4
+
i
);
printk
(
"%04x"
,
eeprom_val
);
printk
(
"%04x"
,
eeprom_val
);
station_address
[
i
]
=
ntohs
(
eeprom_val
);
((
unsigned
short
*
)
dev
->
dev_addr
)
[
i
]
=
ntohs
(
eeprom_val
);
}
}
/* The EEPROM word 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
/* The EEPROM word 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
...
@@ -214,8 +233,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
...
@@ -214,8 +233,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
ushort
setup_value
=
read_eeprom
(
ioaddr
,
12
);
ushort
setup_value
=
read_eeprom
(
ioaddr
,
12
);
dev
->
if_port
=
setup_value
>>
8
;
dev
->
if_port
=
setup_value
>>
8
;
printk
(
" %s interface (%04x).
\n
"
,
porttype
[(
dev
->
if_port
>>
3
)
&
3
],
printk
(
" %s interface.
\n
"
,
porttype
[(
dev
->
if_port
>>
3
)
&
3
]);
setup_value
);
}
}
/* Set the station address in bank zero. */
/* Set the station address in bank zero. */
...
@@ -243,6 +261,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
...
@@ -243,6 +261,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
printk
(
version
);
printk
(
version
);
/* Initialize the device structure. */
/* Initialize the device structure. */
if
(
dev
->
priv
==
NULL
)
dev
->
priv
=
kmalloc
(
sizeof
(
struct
net_local
),
GFP_KERNEL
);
dev
->
priv
=
kmalloc
(
sizeof
(
struct
net_local
),
GFP_KERNEL
);
memset
(
dev
->
priv
,
0
,
sizeof
(
struct
net_local
));
memset
(
dev
->
priv
,
0
,
sizeof
(
struct
net_local
));
...
@@ -252,7 +271,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
...
@@ -252,7 +271,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
dev
->
get_stats
=
net_get_stats
;
dev
->
get_stats
=
net_get_stats
;
dev
->
set_multicast_list
=
&
set_multicast_list
;
dev
->
set_multicast_list
=
&
set_multicast_list
;
/* Fill in the fields of
the device structure
with ethernet-generic values. */
/* Fill in the fields of
'dev'
with ethernet-generic values. */
ether_setup
(
dev
);
ether_setup
(
dev
);
return
0
;
return
0
;
...
@@ -400,7 +419,9 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
...
@@ -400,7 +419,9 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
lp
->
tx_queue_len
=
0
;
lp
->
tx_queue_len
=
0
;
dev
->
trans_start
=
jiffies
;
dev
->
trans_start
=
jiffies
;
lp
->
tx_started
=
1
;
lp
->
tx_started
=
1
;
}
else
if
(
lp
->
tx_queue_len
<
4096
-
1502
)
/* Room for one more packet? */
dev
->
tbusy
=
0
;
}
else
if
(
lp
->
tx_queue_len
<
4096
-
1502
)
/* Yes, there is room for one more packet. */
dev
->
tbusy
=
0
;
dev
->
tbusy
=
0
;
/* Turn on Tx interrupts back on. */
/* Turn on Tx interrupts back on. */
...
@@ -453,10 +474,12 @@ net_interrupt(int reg_ptr)
...
@@ -453,10 +474,12 @@ net_interrupt(int reg_ptr)
/* Turn on Tx interrupts off. */
/* Turn on Tx interrupts off. */
outb
(
0x00
,
ioaddr
+
TX_INTR
);
outb
(
0x00
,
ioaddr
+
TX_INTR
);
dev
->
tbusy
=
0
;
dev
->
tbusy
=
0
;
mark_bh
(
NET_BH
);
/* Inform upper layers. */
}
}
}
}
}
}
dev
->
interrupt
=
0
;
return
;
return
;
}
}
...
@@ -499,7 +522,7 @@ net_rx(struct device *dev)
...
@@ -499,7 +522,7 @@ net_rx(struct device *dev)
lp
->
stats
.
rx_errors
++
;
lp
->
stats
.
rx_errors
++
;
break
;
break
;
}
}
skb
=
alloc_skb
(
pkt_len
,
GFP_ATOMIC
);
skb
=
alloc_skb
(
pkt_len
+
1
,
GFP_ATOMIC
);
if
(
skb
==
NULL
)
{
if
(
skb
==
NULL
)
{
printk
(
"%s: Memory squeeze, dropping packet (len %d).
\n
"
,
printk
(
"%s: Memory squeeze, dropping packet (len %d).
\n
"
,
dev
->
name
,
pkt_len
);
dev
->
name
,
pkt_len
);
...
@@ -535,6 +558,7 @@ net_rx(struct device *dev)
...
@@ -535,6 +558,7 @@ net_rx(struct device *dev)
for
(
i
=
0
;
i
<
20
;
i
++
)
{
for
(
i
=
0
;
i
<
20
;
i
++
)
{
if
((
inb
(
ioaddr
+
RX_MODE
)
&
0x40
)
==
0x40
)
if
((
inb
(
ioaddr
+
RX_MODE
)
&
0x40
)
==
0x40
)
break
;
break
;
inw
(
ioaddr
+
DATAPORT
);
/* dummy status read */
outb
(
0x05
,
ioaddr
+
14
);
outb
(
0x05
,
ioaddr
+
14
);
}
}
...
@@ -592,9 +616,9 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
...
@@ -592,9 +616,9 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
{
{
short
ioaddr
=
dev
->
base_addr
;
short
ioaddr
=
dev
->
base_addr
;
if
(
num_addrs
)
{
if
(
num_addrs
)
{
out
w
(
3
,
ioaddr
+
RX_MODE
);
/* Enable promiscuous mode */
out
b
(
3
,
ioaddr
+
RX_MODE
);
/* Enable promiscuous mode */
}
else
}
else
out
w
(
2
,
ioaddr
+
RX_MODE
);
/* Disable promiscuous, use normal mode */
out
b
(
2
,
ioaddr
+
RX_MODE
);
/* Disable promiscuous, use normal mode */
}
}
/*
/*
...
@@ -603,5 +627,6 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
...
@@ -603,5 +627,6 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
* version-control: t
* version-control: t
* kept-new-versions: 5
* kept-new-versions: 5
* tab-width: 4
* tab-width: 4
* c-indent-level: 4
* End:
* End:
*/
*/
drivers/net/auto_irq.c
View file @
6e38a55b
/* auto_irq.c: Auto-configure IRQ lines for linux. */
/* auto_irq.c: Auto-configure IRQ lines for linux. */
/*
/*
Written 199
3
by Donald Becker.
Written 199
4
by Donald Becker.
The Author may be reached as becker@super.org or
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This code is a general-purpose IRQ line detector for devices with
This code is a general-purpose IRQ line detector for devices with
jumpered IRQ lines. If you can make the device raise an IRQ (and
jumpered IRQ lines. If you can make the device raise an IRQ (and
...
@@ -12,7 +13,7 @@
...
@@ -12,7 +13,7 @@
device probes!
device probes!
To use this, first call autoirq_setup(timeout). TIMEOUT is how many
To use this, first call autoirq_setup(timeout). TIMEOUT is how many
'jiffies' (1/1
8
sec.) to detect other devices that have active IRQ lines,
'jiffies' (1/1
00
sec.) to detect other devices that have active IRQ lines,
and can usually be zero at boot. 'autoirq_setup()' returns the bit
and can usually be zero at boot. 'autoirq_setup()' returns the bit
vector of nominally-available IRQ lines (lines may be physically in-use,
vector of nominally-available IRQ lines (lines may be physically in-use,
but not yet registered to a device).
but not yet registered to a device).
...
@@ -27,23 +28,26 @@
...
@@ -27,23 +28,26 @@
#ifdef version
#ifdef version
static
char
*
version
=
"auto_irq.c:v0.02 1993 Donald Becker (becker@super.org)"
;
static
char
*
version
=
"auto_irq.c:v1.11 Donald Becker (becker@cesdis.gsfc.nasa.gov)"
;
#endif
#endif
/*#include <linux/config.h>*/
/*#include <linux/config.h>*/
/*#include <linux/kernel.h>*/
/*#include <linux/kernel.h>*/
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <asm/bitops.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/netdevice.h>
#include <linux/netdevice.h>
/*#include <asm/system.h>*/
/*#include <asm/system.h>*/
struct
device
*
irq2dev_map
[
16
]
=
{
0
,
0
,
/* ... zeroed */
};
struct
device
*
irq2dev_map
[
16
]
=
{
0
,
0
,
/* ... zeroed */
};
int
irqs_busy
=
0x
01
;
/* The set of fixed IRQs always enabled
*/
int
irqs_busy
=
0x
2147
;
/* The set of fixed IRQs (keyboard, timer, etc)
*/
int
irqs_used
=
0x01
;
/* The set of fixed IRQs sometimes enabled. */
int
irqs_used
=
0x0
00
1
;
/* The set of fixed IRQs sometimes enabled. */
int
irqs_reserved
=
0x00
;
/* An advisory "reserved" table. */
int
irqs_reserved
=
0x00
00
;
/* An advisory "reserved" table. */
int
irqs_shared
=
0x00
;
/* IRQ lines "shared" among conforming cards.*/
int
irqs_shared
=
0x00
00
;
/* IRQ lines "shared" among conforming cards.*/
static
volatile
int
irq_number
;
/* The latest irq number we actually found. */
static
volatile
int
irq_number
;
/* The latest irq number we actually found. */
static
volatile
int
irq_bitmap
;
/* The irqs we actually found. */
static
volatile
int
irq_bitmap
;
/* The irqs we actually found. */
...
@@ -53,17 +57,20 @@ static void autoirq_probe(int irq)
...
@@ -53,17 +57,20 @@ static void autoirq_probe(int irq)
{
{
irq_number
=
irq
;
irq_number
=
irq
;
set_bit
(
irq
,
(
void
*
)
&
irq_bitmap
);
/* irq_bitmap |= 1 << irq; */
set_bit
(
irq
,
(
void
*
)
&
irq_bitmap
);
/* irq_bitmap |= 1 << irq; */
disable_irq
(
irq
);
return
;
return
;
}
}
int
autoirq_setup
(
int
waittime
)
int
autoirq_setup
(
int
waittime
)
{
{
int
i
,
mask
;
int
i
,
mask
;
int
timeout
=
jiffies
+
waittime
;
int
timeout
=
jiffies
+
waittime
;
int
boguscount
=
(
waittime
*
loops_per_sec
)
/
100
;
irq_handled
=
0
;
irq_handled
=
0
;
for
(
i
=
0
;
i
<
16
;
i
++
)
{
for
(
i
=
0
;
i
<
16
;
i
++
)
{
if
(
!
request_irq
(
i
,
autoirq_probe
,
SA_INTERRUPT
,
"irq probe"
))
if
(
test_bit
(
i
,
&
irqs_busy
)
==
0
&&
request_irq
(
i
,
autoirq_probe
,
SA_INTERRUPT
,
"irq probe"
)
==
0
)
set_bit
(
i
,
(
void
*
)
&
irq_handled
);
/* irq_handled |= 1 << i;*/
set_bit
(
i
,
(
void
*
)
&
irq_handled
);
/* irq_handled |= 1 << i;*/
}
}
/* Update our USED lists. */
/* Update our USED lists. */
...
@@ -72,7 +79,7 @@ int autoirq_setup(int waittime)
...
@@ -72,7 +79,7 @@ int autoirq_setup(int waittime)
irq_bitmap
=
0
;
irq_bitmap
=
0
;
/* Hang out at least <waittime> jiffies waiting for bogus IRQ hits. */
/* Hang out at least <waittime> jiffies waiting for bogus IRQ hits. */
while
(
timeout
>
jiffies
)
while
(
timeout
>
jiffies
&&
--
boguscount
>
0
)
;
;
for
(
i
=
0
,
mask
=
0x01
;
i
<
16
;
i
++
,
mask
<<=
1
)
{
for
(
i
=
0
,
mask
=
0x01
;
i
<
16
;
i
++
,
mask
<<=
1
)
{
...
@@ -91,9 +98,11 @@ int autoirq_report(int waittime)
...
@@ -91,9 +98,11 @@ int autoirq_report(int waittime)
{
{
int
i
;
int
i
;
int
timeout
=
jiffies
+
waittime
;
int
timeout
=
jiffies
+
waittime
;
int
boguscount
=
(
waittime
*
loops_per_sec
)
/
100
;
/* Hang out at least <waittime> jiffies waiting for the IRQ. */
/* Hang out at least <waittime> jiffies waiting for the IRQ. */
while
(
timeout
>
jiffies
)
while
(
timeout
>
jiffies
&&
--
boguscount
>
0
)
if
(
irq_number
)
if
(
irq_number
)
break
;
break
;
...
@@ -110,5 +119,7 @@ int autoirq_report(int waittime)
...
@@ -110,5 +119,7 @@ int autoirq_report(int waittime)
* compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c auto_irq.c"
* compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c auto_irq.c"
* version-control: t
* version-control: t
* kept-new-versions: 5
* kept-new-versions: 5
* c-indent-level: 4
* tab-width: 4
* End:
* End:
*/
*/
drivers/net/hp-plus.c
View file @
6e38a55b
...
@@ -19,7 +19,7 @@
...
@@ -19,7 +19,7 @@
*/
*/
static
char
*
version
=
static
char
*
version
=
"hp-plus.c:v
0.04 6/16
/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)
\n
"
;
"hp-plus.c:v
1.10 9/24
/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)
\n
"
;
#include <linux/config.h>
#include <linux/config.h>
#include <linux/string.h>
/* Important -- this inlines word moves. */
#include <linux/string.h>
/* Important -- this inlines word moves. */
...
@@ -38,6 +38,12 @@ static char *version =
...
@@ -38,6 +38,12 @@ static char *version =
#endif
#endif
#include "8390.h"
#include "8390.h"
extern
struct
device
*
init_etherdev
(
struct
device
*
dev
,
int
sizeof_private
,
unsigned
long
*
mem_startp
);
/* A zero-terminated list of I/O addresses to be probed. */
static
unsigned
int
hpplus_portlist
[]
=
{
0x200
,
0x240
,
0x280
,
0x2C0
,
0x300
,
0x320
,
0x340
,
0
}
/*
/*
The HP EtherTwist chip implementation is a fairly routine DP8390
The HP EtherTwist chip implementation is a fairly routine DP8390
...
@@ -64,10 +70,6 @@ static char *version =
...
@@ -64,10 +70,6 @@ static char *version =
register.
register.
*/
*/
#define HPP_PROBE_LIST {0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0}
#define HP_IO_EXTENT 32
#define HP_ID 0x00
/* ID register, always 0x4850. */
#define HP_ID 0x00
/* ID register, always 0x4850. */
#define HP_PAGING 0x02
/* Registers visible @ 8-f, see PageName. */
#define HP_PAGING 0x02
/* Registers visible @ 8-f, see PageName. */
#define HPP_OPTION 0x04
/* Bitmapped options, see HP_Option. */
#define HPP_OPTION 0x04
/* Bitmapped options, see HP_Option. */
...
@@ -75,6 +77,7 @@ static char *version =
...
@@ -75,6 +77,7 @@ static char *version =
#define HPP_IN_ADDR 0x0A
/* I/O input location in Perf_Page. */
#define HPP_IN_ADDR 0x0A
/* I/O input location in Perf_Page. */
#define HP_DATAPORT 0x0c
/* I/O data transfer in Perf_Page. */
#define HP_DATAPORT 0x0c
/* I/O data transfer in Perf_Page. */
#define NIC_OFFSET 0x10
/* Offset to the 8390 registers. */
#define NIC_OFFSET 0x10
/* Offset to the 8390 registers. */
#define HP_IO_EXTENT 32
#define HP_START_PG 0x00
/* First page of TX buffer */
#define HP_START_PG 0x00
/* First page of TX buffer */
#define HP_STOP_PG 0x80
/* Last page +1 of RX ring */
#define HP_STOP_PG 0x80
/* Last page +1 of RX ring */
...
@@ -111,26 +114,34 @@ static void hpp_io_block_output(struct device *dev, int count,
...
@@ -111,26 +114,34 @@ static void hpp_io_block_output(struct device *dev, int count,
/* Probe a list of addresses for an HP LAN+ adaptor.
/* Probe a list of addresses for an HP LAN+ adaptor.
This routine is almost boilerplate. */
This routine is almost boilerplate. */
#ifdef HAVE_DEVLIST
/* Support for a alternate probe manager, which will eliminate the
boilerplate below. */
struct
netdev_entry
hpplus_drv
=
{
"hpplus"
,
hpp_probe1
,
HP_IO_EXTENT
,
hpplus_portlist
};
#else
int
hp_plus_probe
(
struct
device
*
dev
)
int
hp_plus_probe
(
struct
device
*
dev
)
{
{
int
*
port
,
ports
[]
=
HPP_PROBE_LIST
;
int
i
;
short
ioaddr
=
dev
->
base_addr
;
int
base_addr
=
dev
?
dev
->
base_addr
:
0
;
if
(
ioaddr
>
0x1ff
)
/* Check a single specified location. */
if
(
base_addr
>
0x1ff
)
/* Check a single specified location. */
return
hpp_probe1
(
dev
,
io
addr
);
return
hpp_probe1
(
dev
,
base_
addr
);
else
if
(
ioaddr
>
0
)
/* Don't probe at all. */
else
if
(
base_addr
!=
0
)
/* Don't probe at all. */
return
ENXIO
;
return
ENXIO
;
for
(
port
=
&
ports
[
0
];
*
port
;
port
++
)
{
for
(
i
=
0
;
hpplus_portlist
[
i
];
i
++
)
{
if
(
check_region
(
*
port
,
HP_IO_EXTENT
))
int
ioaddr
=
hpplus_portlist
[
i
];
if
(
check_region
(
ioaddr
,
HP_IO_EXTENT
))
continue
;
continue
;
if
(
hpp_probe1
(
dev
,
*
port
)
==
0
)
{
if
(
hpp_probe1
(
dev
,
ioaddr
)
==
0
)
return
0
;
return
0
;
}
}
}
return
ENODEV
;
return
ENODEV
;
}
}
#endif
/* Do the interesting part of the probe at a single address. */
/* Do the interesting part of the probe at a single address. */
int
hpp_probe1
(
struct
device
*
dev
,
int
ioaddr
)
int
hpp_probe1
(
struct
device
*
dev
,
int
ioaddr
)
...
@@ -138,7 +149,6 @@ int hpp_probe1(struct device *dev, int ioaddr)
...
@@ -138,7 +149,6 @@ int hpp_probe1(struct device *dev, int ioaddr)
int
i
;
int
i
;
unsigned
char
checksum
=
0
;
unsigned
char
checksum
=
0
;
char
*
name
=
"HP-PC-LAN+"
;
char
*
name
=
"HP-PC-LAN+"
;
unsigned
char
*
station_addr
=
dev
->
dev_addr
;
int
mem_start
;
int
mem_start
;
/* Check for the HP+ signature, 50 48 0x 53. */
/* Check for the HP+ signature, 50 48 0x 53. */
...
@@ -146,7 +156,9 @@ int hpp_probe1(struct device *dev, int ioaddr)
...
@@ -146,7 +156,9 @@ int hpp_probe1(struct device *dev, int ioaddr)
||
(
inw
(
ioaddr
+
HP_PAGING
)
&
0xfff0
)
!=
0x5300
)
||
(
inw
(
ioaddr
+
HP_PAGING
)
&
0xfff0
)
!=
0x5300
)
return
ENODEV
;
return
ENODEV
;
/* OK, we think that we have it. Get and checksum the physical address. */
if
(
dev
==
NULL
)
dev
=
init_etherdev
(
0
,
sizeof
(
struct
ei_device
),
0
);
printk
(
"%s: %s at %#3x,"
,
dev
->
name
,
name
,
ioaddr
);
printk
(
"%s: %s at %#3x,"
,
dev
->
name
,
name
,
ioaddr
);
/* Retrieve and checksum the station address. */
/* Retrieve and checksum the station address. */
...
@@ -154,7 +166,7 @@ int hpp_probe1(struct device *dev, int ioaddr)
...
@@ -154,7 +166,7 @@ int hpp_probe1(struct device *dev, int ioaddr)
for
(
i
=
0
;
i
<
ETHER_ADDR_LEN
;
i
++
)
{
for
(
i
=
0
;
i
<
ETHER_ADDR_LEN
;
i
++
)
{
unsigned
char
inval
=
inb
(
ioaddr
+
8
+
i
);
unsigned
char
inval
=
inb
(
ioaddr
+
8
+
i
);
station
_addr
[
i
]
=
inval
;
dev
->
dev
_addr
[
i
]
=
inval
;
checksum
+=
inval
;
checksum
+=
inval
;
printk
(
" %2.2x"
,
inval
);
printk
(
" %2.2x"
,
inval
);
}
}
...
...
drivers/net/hp.c
View file @
6e38a55b
/* hp.c: A HP LAN ethernet driver for linux. */
/* hp.c: A HP LAN ethernet driver for linux. */
/*
/*
Written 1993 by Donald Becker.
Written 1993-94 by Donald Becker.
Copyright 1993 United States Government as represented by the
Copyright 1993 United States Government as represented by the
Director, National Security Agency. This software may be used and
Director, National Security Agency.
distributed according to the terms of the GNU Public License,
incorporated herein by reference.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This is a driver for the HP LAN adaptors.
This is a driver for the HP
PC-
LAN adaptors.
The Author may be reached as becker@super.org or
Sources:
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
The Crynwr packet driver.
*/
*/
static
char
*
version
=
static
char
*
version
=
"hp.c:v
0.99.15k 3/3/94 Donald Becker (becker@super.org
)
\n
"
;
"hp.c:v
1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov
)
\n
"
;
#include <linux/config.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
...
@@ -26,10 +32,12 @@ static char *version =
...
@@ -26,10 +32,12 @@ static char *version =
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include "8390.h"
#include "8390.h"
#ifndef HAVE_PORTRESERVE
extern
struct
device
*
init_etherdev
(
struct
device
*
dev
,
int
sizeof_private
,
#define check_region(ioaddr, size) 0
unsigned
long
*
mem_startp
);
#define snarf_region(ioaddr, size); do ; while (0)
#endif
/* A zero-terminated list of I/O addresses to be probed. */
static
unsigned
int
hppclan_portlist
[]
=
{
0x300
,
0x320
,
0x340
,
0x280
,
0x2C0
,
0x200
,
0x240
,
0
};
#define HP_IO_EXTENT 32
#define HP_IO_EXTENT 32
...
@@ -46,7 +54,7 @@ static char *version =
...
@@ -46,7 +54,7 @@ static char *version =
#define HP_16BSTOP_PG 0xFF
/* Same, for 16 bit cards. */
#define HP_16BSTOP_PG 0xFF
/* Same, for 16 bit cards. */
int
hp_probe
(
struct
device
*
dev
);
int
hp_probe
(
struct
device
*
dev
);
int
hpprobe1
(
struct
device
*
dev
,
int
ioaddr
);
int
hp
_
probe1
(
struct
device
*
dev
,
int
ioaddr
);
static
void
hp_reset_8390
(
struct
device
*
dev
);
static
void
hp_reset_8390
(
struct
device
*
dev
);
static
int
hp_block_input
(
struct
device
*
dev
,
int
count
,
static
int
hp_block_input
(
struct
device
*
dev
,
int
count
,
...
@@ -63,32 +71,37 @@ static char irqmap[16] = { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0};
...
@@ -63,32 +71,37 @@ static char irqmap[16] = { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0};
/* Probe for an HP LAN adaptor.
/* Probe for an HP LAN adaptor.
Also initialize the card and fill in STATION_ADDR with the station
Also initialize the card and fill in STATION_ADDR with the station
address. */
address. */
#ifdef HAVE_DEVLIST
struct
netdev_entry
netcard_drv
=
{
"hp"
,
hp_probe1
,
HP_IO_EXTENT
,
hppclan_portlist
};
#else
int
hp_probe
(
struct
device
*
dev
)
int
hp_probe
(
struct
device
*
dev
)
{
{
int
*
port
,
ports
[]
=
{
0x300
,
0x320
,
0x340
,
0x280
,
0x2C0
,
0x200
,
0x240
,
0
}
;
int
i
;
short
ioaddr
=
dev
->
base_addr
;
int
base_addr
=
dev
?
dev
->
base_addr
:
0
;
if
(
ioaddr
>
0x1ff
)
/* Check a single specified location. */
if
(
base_addr
>
0x1ff
)
/* Check a single specified location. */
return
hp
probe1
(
dev
,
io
addr
);
return
hp
_probe1
(
dev
,
base_
addr
);
else
if
(
ioaddr
>
0
)
/* Don't probe at all. */
else
if
(
base_addr
!=
0
)
/* Don't probe at all. */
return
ENXIO
;
return
ENXIO
;
for
(
port
=
&
ports
[
0
];
*
port
;
port
++
)
{
for
(
i
=
0
;
hppclan_portlist
[
i
];
i
++
)
{
if
(
check_region
(
*
port
,
HP_IO_EXTENT
))
int
ioaddr
=
hppclan_portlist
[
i
];
if
(
check_region
(
ioaddr
,
HP_IO_EXTENT
))
continue
;
continue
;
if
(
hp
probe1
(
dev
,
*
port
)
==
0
)
{
if
(
hp
_probe1
(
dev
,
ioaddr
)
==
0
)
return
0
;
return
0
;
}
}
}
return
ENODEV
;
return
ENODEV
;
}
}
#endif
int
hpprobe1
(
struct
device
*
dev
,
int
ioaddr
)
int
hp
_
probe1
(
struct
device
*
dev
,
int
ioaddr
)
{
{
int
i
,
board_id
,
wordmode
;
int
i
,
board_id
,
wordmode
;
char
*
name
;
char
*
name
;
unsigned
char
*
station_addr
=
dev
->
dev_addr
;
/* Check for the HP physical address, 08 00 09 xx xx xx. */
/* Check for the HP physical address, 08 00 09 xx xx xx. */
/* This really isn't good enough: we may pick up HP LANCE boards
/* This really isn't good enough: we may pick up HP LANCE boards
...
@@ -100,7 +113,7 @@ int hpprobe1(struct device *dev, int ioaddr)
...
@@ -100,7 +113,7 @@ int hpprobe1(struct device *dev, int ioaddr)
return
ENODEV
;
return
ENODEV
;
/* Set up the parameters based on the board ID.
/* Set up the parameters based on the board ID.
If you have additional mappings, please mail them to
becker@super.org
. */
If you have additional mappings, please mail them to
me -djb
. */
if
((
board_id
=
inb
(
ioaddr
+
HP_ID
))
&
0x80
)
{
if
((
board_id
=
inb
(
ioaddr
+
HP_ID
))
&
0x80
)
{
name
=
"HP27247"
;
name
=
"HP27247"
;
wordmode
=
1
;
wordmode
=
1
;
...
@@ -109,13 +122,16 @@ int hpprobe1(struct device *dev, int ioaddr)
...
@@ -109,13 +122,16 @@ int hpprobe1(struct device *dev, int ioaddr)
wordmode
=
0
;
wordmode
=
0
;
}
}
if
(
dev
==
NULL
)
dev
=
init_etherdev
(
0
,
sizeof
(
struct
ei_device
),
0
);
/* Grab the region so we can find another board if something fails. */
/* Grab the region so we can find another board if something fails. */
snarf_region
(
ioaddr
,
HP_IO_EXTENT
);
snarf_region
(
ioaddr
,
HP_IO_EXTENT
);
printk
(
"%s: %s (ID %02x) at %#3x,"
,
dev
->
name
,
name
,
board_id
,
ioaddr
);
printk
(
"%s: %s (ID %02x) at %#3x,"
,
dev
->
name
,
name
,
board_id
,
ioaddr
);
for
(
i
=
0
;
i
<
ETHER_ADDR_LEN
;
i
++
)
for
(
i
=
0
;
i
<
ETHER_ADDR_LEN
;
i
++
)
printk
(
" %2.2x"
,
station
_addr
[
i
]
=
inb
(
ioaddr
+
i
));
printk
(
" %2.2x"
,
dev
->
dev
_addr
[
i
]
=
inb
(
ioaddr
+
i
));
/* Snarf the interrupt now. Someday this could be moved to open(). */
/* Snarf the interrupt now. Someday this could be moved to open(). */
if
(
dev
->
irq
<
2
)
{
if
(
dev
->
irq
<
2
)
{
...
...
drivers/net/lance.c
View file @
6e38a55b
...
@@ -15,7 +15,7 @@
...
@@ -15,7 +15,7 @@
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
*/
*/
static
char
*
version
=
"lance.c:v1.0
1 8/31
/94 becker@cesdis.gsfc.nasa.gov
\n
"
;
static
char
*
version
=
"lance.c:v1.0
5 9/23
/94 becker@cesdis.gsfc.nasa.gov
\n
"
;
#include <linux/config.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
...
@@ -72,7 +72,7 @@ have on-board buffer memory needed to support the slower shared memory mode.)
...
@@ -72,7 +72,7 @@ have on-board buffer memory needed to support the slower shared memory mode.)
Most ISA boards have jumpered settings for the I/O base, IRQ line, and DMA
Most ISA boards have jumpered settings for the I/O base, IRQ line, and DMA
channel. This driver probes the likely base addresses:
channel. This driver probes the likely base addresses:
{0x300, 0x320, 0x340, 0x360}.
{0x300, 0x320, 0x340, 0x360}.
After the board is found it generates a DMA-timeout interrupt and uses
After the board is found it generates a
n
DMA-timeout interrupt and uses
autoIRQ to find the IRQ line. The DMA channel can be set with the low bits
autoIRQ to find the IRQ line. The DMA channel can be set with the low bits
of the otherwise-unused dev->mem_start value (aka PARAM1). If unset it is
of the otherwise-unused dev->mem_start value (aka PARAM1). If unset it is
probed for by enabling each free DMA channel in turn and checking if
probed for by enabling each free DMA channel in turn and checking if
...
@@ -102,14 +102,14 @@ statically allocates full-sized (slightly oversized -- PKT_BUF_SZ) buffers to
...
@@ -102,14 +102,14 @@ statically allocates full-sized (slightly oversized -- PKT_BUF_SZ) buffers to
avoid the administrative overhead. For the Rx side this avoids dynamically
avoid the administrative overhead. For the Rx side this avoids dynamically
allocating full-sized buffers "just in case", at the expense of a
allocating full-sized buffers "just in case", at the expense of a
memory-to-memory data copy for each packet received. For most systems this
memory-to-memory data copy for each packet received. For most systems this
is a good tradeoff: the Rx buffer will always be in low memory, the copy
is a
n
good tradeoff: the Rx buffer will always be in low memory, the copy
is inexpensive, and it primes the cache for later packet processing. For Tx
is inexpensive, and it primes the cache for later packet processing. For Tx
the buffers are only used when needed as low-memory bounce buffers.
the buffers are only used when needed as low-memory bounce buffers.
IIIB. 16M memory limitations.
IIIB. 16M memory limitations.
For the ISA bus master mode all structures used directly by the LANCE,
For the ISA bus master mode all structures used directly by the LANCE,
the initialization block, Rx and Tx rings, and data buffers, must be
the initialization block, Rx and Tx rings, and data buffers, must be
access
i
ble from the ISA bus, i.e. in the lower 16M of real memory.
access
a
ble from the ISA bus, i.e. in the lower 16M of real memory.
This is a problem for current Linux kernels on >16M machines. The network
This is a problem for current Linux kernels on >16M machines. The network
devices are initialized after memory initialization, and the kernel doles out
devices are initialized after memory initialization, and the kernel doles out
memory from the top of memory downward. The current solution is to have a
memory from the top of memory downward. The current solution is to have a
...
@@ -206,7 +206,9 @@ struct lance_private {
...
@@ -206,7 +206,9 @@ struct lance_private {
int
pad0
,
pad1
;
/* Used for 8-byte alignment */
int
pad0
,
pad1
;
/* Used for 8-byte alignment */
};
};
/* A mapping from the chip ID number to the part number and features. */
/* A mapping from the chip ID number to the part number and features.
These are fro the datasheets -- in real life the '970 version
reportedly has the same ID as the '965. */
static
struct
lance_chip_type
{
static
struct
lance_chip_type
{
int
id_number
;
int
id_number
;
char
*
name
;
char
*
name
;
...
@@ -214,8 +216,8 @@ static struct lance_chip_type {
...
@@ -214,8 +216,8 @@ static struct lance_chip_type {
}
chip_table
[]
=
{
}
chip_table
[]
=
{
{
0x0000
,
"LANCE 7990"
,
0
},
/* Ancient lance chip. */
{
0x0000
,
"LANCE 7990"
,
0
},
/* Ancient lance chip. */
{
0x0003
,
"PCnet/ISA 79C960"
,
0
},
/* 79C960 PCnet/ISA. */
{
0x0003
,
"PCnet/ISA 79C960"
,
0
},
/* 79C960 PCnet/ISA. */
{
0x2260
,
"PCnet/ISA+ 79C961"
,
0
},
/* 79C961 PCnet/ISA+
for
Plug-n-Play. */
{
0x2260
,
"PCnet/ISA+ 79C961"
,
0
},
/* 79C961 PCnet/ISA+
,
Plug-n-Play. */
{
0x2420
,
"PCnet/PCI 79C970"
,
0
},
/* 79C970 or 79C974 PCnet-SCSI
for PCI
*/
{
0x2420
,
"PCnet/PCI 79C970"
,
0
},
/* 79C970 or 79C974 PCnet-SCSI
, PCI.
*/
{
0x2430
,
"PCnet/VLB 79C965"
,
0
},
/* 79C965 PCnet for VL bus. */
{
0x2430
,
"PCnet/VLB 79C965"
,
0
},
/* 79C965 PCnet for VL bus. */
{
0x0
,
"PCnet (unknown)"
,
0
},
{
0x0
,
"PCnet (unknown)"
,
0
},
};
};
...
@@ -237,7 +239,7 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
...
@@ -237,7 +239,7 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
/* This lance probe is unlike the other board probes in 1.0.*. The LANCE may
/* This lance probe is unlike the other board probes in 1.0.*. The LANCE may
have to allocate a contiguous low-memory region for bounce buffers.
have to allocate a contiguous low-memory region for bounce buffers.
This requirement is sati
s
fied by having the lance initialization occur before the
This requirement is satified by having the lance initialization occur before the
memory management system is started, and thus well before the other probes. */
memory management system is started, and thus well before the other probes. */
unsigned
long
lance_init
(
unsigned
long
mem_start
,
unsigned
long
mem_end
)
unsigned
long
lance_init
(
unsigned
long
mem_start
,
unsigned
long
mem_end
)
{
{
...
@@ -260,6 +262,7 @@ unsigned long lance_probe1(short ioaddr, unsigned long mem_start)
...
@@ -260,6 +262,7 @@ unsigned long lance_probe1(short ioaddr, unsigned long mem_start)
{
{
struct
device
*
dev
;
struct
device
*
dev
;
struct
lance_private
*
lp
;
struct
lance_private
*
lp
;
short
dma_channels
;
/* Mark spuriously-busy DMA channels */
int
i
,
reset_val
,
lance_version
;
int
i
,
reset_val
,
lance_version
;
/* Flags for specific chips or boards. */
/* Flags for specific chips or boards. */
unsigned
char
hpJ2405A
=
0
;
/* HP ISA adaptor */
unsigned
char
hpJ2405A
=
0
;
/* HP ISA adaptor */
...
@@ -268,18 +271,18 @@ unsigned long lance_probe1(short ioaddr, unsigned long mem_start)
...
@@ -268,18 +271,18 @@ unsigned long lance_probe1(short ioaddr, unsigned long mem_start)
/* First we look for special cases.
/* First we look for special cases.
Check for HP's on-board ethernet by looking for 'HP' in the BIOS.
Check for HP's on-board ethernet by looking for 'HP' in the BIOS.
This method provided by Laurent Julliard, Laurent_Julliard@grenoble.hp.com.
There are two HP versions, check the BIOS for the configuration port.
This method provided by L. Julliard, Laurent_Julliard@grenoble.hp.com.
*/
*/
if
(
*
((
unsigned
short
*
)
0x000f0102
)
==
0x5048
)
{
if
(
*
((
unsigned
short
*
)
0x000f0102
)
==
0x5048
)
{
short
ioaddr_table
[]
=
{
0x300
,
0x320
,
0x340
,
0x360
};
short
ioaddr_table
[]
=
{
0x300
,
0x320
,
0x340
,
0x360
};
/* There are two HP versions, check the BIOS for the configuration port. */
int
hp_port
=
(
*
((
unsigned
char
*
)
0x000f00f1
)
&
1
)
?
0x499
:
0x99
;
int
hp_port
=
(
*
((
unsigned
char
*
)
0x000f00f1
)
&
1
)
?
0x499
:
0x99
;
/* We can have boards other than the built-in! Verify this is on-board. */
/* We can have boards other than the built-in! Verify this is on-board. */
if
((
inb
(
hp_port
)
&
0xc0
)
==
0x80
if
((
inb
(
hp_port
)
&
0xc0
)
==
0x80
&&
ioaddr_table
[
inb
(
hp_port
)
&
3
]
==
ioaddr
)
&&
ioaddr_table
[
inb
(
hp_port
)
&
3
]
==
ioaddr
)
hp_builtin
=
hp_port
;
hp_builtin
=
hp_port
;
}
}
/* We
might misrecognize the HP Vectra on-board here, but we
check below. */
/* We
also recognize the HP Vectra on-board here, but
check below. */
hpJ2405A
=
(
inb
(
ioaddr
)
==
0x08
&&
inb
(
ioaddr
+
1
)
==
0x00
hpJ2405A
=
(
inb
(
ioaddr
)
==
0x08
&&
inb
(
ioaddr
+
1
)
==
0x00
&&
inb
(
ioaddr
+
2
)
==
0x09
);
&&
inb
(
ioaddr
+
2
)
==
0x09
);
...
@@ -388,6 +391,12 @@ unsigned long lance_probe1(short ioaddr, unsigned long mem_start)
...
@@ -388,6 +391,12 @@ unsigned long lance_probe1(short ioaddr, unsigned long mem_start)
dev
->
dma
=
dev
->
mem_start
&
0x07
;
dev
->
dma
=
dev
->
mem_start
&
0x07
;
}
}
if
(
dev
->
dma
==
0
)
{
/* Read the DMA channel status register, so that we can avoid
stuck DMA channels in the DMA detection below. */
dma_channels
=
((
inb
(
DMA1_STAT_REG
)
>>
4
)
&
0x0f
)
|
(
inb
(
DMA2_STAT_REG
)
&
0xf0
);
}
if
(
dev
->
irq
>=
2
)
if
(
dev
->
irq
>=
2
)
printk
(
" assigned IRQ %d"
,
dev
->
irq
);
printk
(
" assigned IRQ %d"
,
dev
->
irq
);
else
{
else
{
...
@@ -422,15 +431,20 @@ unsigned long lance_probe1(short ioaddr, unsigned long mem_start)
...
@@ -422,15 +431,20 @@ unsigned long lance_probe1(short ioaddr, unsigned long mem_start)
}
else
}
else
printk
(
", assigned DMA %d.
\n
"
,
dev
->
dma
);
printk
(
", assigned DMA %d.
\n
"
,
dev
->
dma
);
}
else
{
/* OK, we have to auto-DMA. */
}
else
{
/* OK, we have to auto-DMA. */
int
dmas
[]
=
{
5
,
6
,
7
,
3
},
boguscnt
;
int
dmas
[]
=
{
5
,
6
,
7
,
3
},
boguscnt
;
for
(
i
=
0
;
i
<
4
;
i
++
)
{
for
(
i
=
0
;
i
<
4
;
i
++
)
{
int
dma
=
dmas
[
i
];
int
dma
=
dmas
[
i
];
/* Don't enable a permanently busy DMA channel, or the machine
will hang. */
if
(
test_bit
(
dma
,
&
dma_channels
))
continue
;
outw
(
0x7f04
,
ioaddr
+
LANCE_DATA
);
/* Clear the memory error bits. */
outw
(
0x7f04
,
ioaddr
+
LANCE_DATA
);
/* Clear the memory error bits. */
if
(
request_dma
(
dma
,
"lance"
))
if
(
request_dma
(
dma
,
"lance"
))
continue
;
continue
;
enable_dma
(
dma
);
set_dma_mode
(
dma
,
DMA_MODE_CASCADE
);
set_dma_mode
(
dma
,
DMA_MODE_CASCADE
);
enable_dma
(
dma
);
/* Trigger an initialization. */
/* Trigger an initialization. */
outw
(
0x0001
,
ioaddr
+
LANCE_DATA
);
outw
(
0x0001
,
ioaddr
+
LANCE_DATA
);
...
@@ -493,8 +507,10 @@ lance_open(struct device *dev)
...
@@ -493,8 +507,10 @@ lance_open(struct device *dev)
inw
(
ioaddr
+
LANCE_RESET
);
inw
(
ioaddr
+
LANCE_RESET
);
/* The DMA controller is used as a no-operation slave, "cascade mode". */
/* The DMA controller is used as a no-operation slave, "cascade mode". */
if
(
dev
->
dma
!=
4
)
{
enable_dma
(
dev
->
dma
);
enable_dma
(
dev
->
dma
);
set_dma_mode
(
dev
->
dma
,
DMA_MODE_CASCADE
);
set_dma_mode
(
dev
->
dma
,
DMA_MODE_CASCADE
);
}
/* Un-Reset the LANCE, needed only for the NE2100. */
/* Un-Reset the LANCE, needed only for the NE2100. */
if
(
lp
->
chip_version
==
OLD_LANCE
)
if
(
lp
->
chip_version
==
OLD_LANCE
)
...
@@ -580,24 +596,25 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
...
@@ -580,24 +596,25 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
/* Transmitter timeout, serious problems. */
/* Transmitter timeout, serious problems. */
if
(
dev
->
tbusy
)
{
if
(
dev
->
tbusy
)
{
int
tickssofar
=
jiffies
-
dev
->
trans_start
;
int
tickssofar
=
jiffies
-
dev
->
trans_start
;
if
(
tickssofar
<
1
0
)
if
(
tickssofar
<
2
0
)
return
1
;
return
1
;
outw
(
0
,
ioaddr
+
LANCE_ADDR
);
outw
(
0
,
ioaddr
+
LANCE_ADDR
);
printk
(
"%s: transmit timed out, status %4.4x, resetting.
\n
"
,
printk
(
"%s: transmit timed out, status %4.4x, resetting.
\n
"
,
dev
->
name
,
inw
(
ioaddr
+
LANCE_DATA
));
dev
->
name
,
inw
(
ioaddr
+
LANCE_DATA
));
outw
(
0x000
1
,
ioaddr
+
LANCE_DATA
);
outw
(
0x000
4
,
ioaddr
+
LANCE_DATA
);
lp
->
stats
.
tx_errors
++
;
lp
->
stats
.
tx_errors
++
;
#ifndef final_version
#ifndef final_version
{
{
int
i
;
int
i
;
printk
(
" Ring data dump: dirty_tx %d cur_tx %d cur_rx %d."
,
printk
(
" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d."
,
lp
->
dirty_tx
,
lp
->
cur_tx
,
lp
->
cur_rx
);
lp
->
dirty_tx
,
lp
->
cur_tx
,
lp
->
tx_full
?
" (full)"
:
""
,
lp
->
cur_rx
);
for
(
i
=
0
;
i
<
RX_RING_SIZE
;
i
++
)
for
(
i
=
0
;
i
<
RX_RING_SIZE
;
i
++
)
printk
(
"%s %08x %04x %04x"
,
i
&
0x3
?
""
:
"
\n
"
,
printk
(
"%s %08x %04x %04x"
,
i
&
0x3
?
""
:
"
\n
"
,
lp
->
rx_ring
[
i
].
base
,
-
lp
->
rx_ring
[
i
].
buf_length
,
lp
->
rx_ring
[
i
].
base
,
-
lp
->
rx_ring
[
i
].
buf_length
,
lp
->
rx_ring
[
i
].
msg_length
);
lp
->
rx_ring
[
i
].
msg_length
);
for
(
i
=
0
;
i
<
TX_RING_SIZE
;
i
++
)
for
(
i
=
0
;
i
<
TX_RING_SIZE
;
i
++
)
printk
(
"
%s
%08x %04x %04x"
,
i
&
0x3
?
""
:
"
\n
"
,
printk
(
"
%s
%08x %04x %04x"
,
i
&
0x3
?
""
:
"
\n
"
,
lp
->
tx_ring
[
i
].
base
,
-
lp
->
tx_ring
[
i
].
length
,
lp
->
tx_ring
[
i
].
base
,
-
lp
->
tx_ring
[
i
].
length
,
lp
->
tx_ring
[
i
].
misc
);
lp
->
tx_ring
[
i
].
misc
);
printk
(
"
\n
"
);
printk
(
"
\n
"
);
...
@@ -635,7 +652,7 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
...
@@ -635,7 +652,7 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
}
}
if
(
set_bit
(
0
,
(
void
*
)
&
lp
->
lock
)
!=
0
)
{
if
(
set_bit
(
0
,
(
void
*
)
&
lp
->
lock
)
!=
0
)
{
if
(
lance_debug
>
2
)
if
(
lance_debug
>
0
)
printk
(
"%s: tx queue lock!.
\n
"
,
dev
->
name
);
printk
(
"%s: tx queue lock!.
\n
"
,
dev
->
name
);
/* don't clear dev->tbusy flag. */
/* don't clear dev->tbusy flag. */
return
1
;
return
1
;
...
@@ -698,7 +715,7 @@ lance_interrupt(int reg_ptr)
...
@@ -698,7 +715,7 @@ lance_interrupt(int reg_ptr)
int
irq
=
-
(((
struct
pt_regs
*
)
reg_ptr
)
->
orig_eax
+
2
);
int
irq
=
-
(((
struct
pt_regs
*
)
reg_ptr
)
->
orig_eax
+
2
);
struct
device
*
dev
=
(
struct
device
*
)(
irq2dev_map
[
irq
]);
struct
device
*
dev
=
(
struct
device
*
)(
irq2dev_map
[
irq
]);
struct
lance_private
*
lp
;
struct
lance_private
*
lp
;
int
csr0
,
ioaddr
;
int
csr0
,
ioaddr
,
boguscnt
=
10
;
if
(
dev
==
NULL
)
{
if
(
dev
==
NULL
)
{
printk
(
"lance_interrupt(): irq %d for unknown device.
\n
"
,
irq
);
printk
(
"lance_interrupt(): irq %d for unknown device.
\n
"
,
irq
);
...
@@ -713,8 +730,8 @@ lance_interrupt(int reg_ptr)
...
@@ -713,8 +730,8 @@ lance_interrupt(int reg_ptr)
dev
->
interrupt
=
1
;
dev
->
interrupt
=
1
;
outw
(
0x00
,
dev
->
base_addr
+
LANCE_ADDR
);
outw
(
0x00
,
dev
->
base_addr
+
LANCE_ADDR
);
csr0
=
inw
(
dev
->
base_addr
+
LANCE_DATA
);
while
((
csr0
=
inw
(
dev
->
base_addr
+
LANCE_DATA
))
&
0x8600
&&
--
boguscnt
>=
0
)
{
/* Acknowledge all of the current interrupt sources ASAP. */
/* Acknowledge all of the current interrupt sources ASAP. */
outw
(
csr0
&
~
0x004f
,
dev
->
base_addr
+
LANCE_DATA
);
outw
(
csr0
&
~
0x004f
,
dev
->
base_addr
+
LANCE_DATA
);
...
@@ -737,14 +754,22 @@ lance_interrupt(int reg_ptr)
...
@@ -737,14 +754,22 @@ lance_interrupt(int reg_ptr)
lp
->
tx_ring
[
entry
].
base
=
0
;
lp
->
tx_ring
[
entry
].
base
=
0
;
if
(
status
&
0x40000000
)
{
/* There was a major error, log it. */
if
(
status
&
0x40000000
)
{
/* There was an major error, log it. */
int
err_status
=
lp
->
tx_ring
[
entry
].
misc
;
int
err_status
=
lp
->
tx_ring
[
entry
].
misc
;
lp
->
stats
.
tx_errors
++
;
lp
->
stats
.
tx_errors
++
;
if
(
err_status
&
0x0400
)
lp
->
stats
.
tx_aborted_errors
++
;
if
(
err_status
&
0x0400
)
lp
->
stats
.
tx_aborted_errors
++
;
if
(
err_status
&
0x0800
)
lp
->
stats
.
tx_carrier_errors
++
;
if
(
err_status
&
0x0800
)
lp
->
stats
.
tx_carrier_errors
++
;
if
(
err_status
&
0x1000
)
lp
->
stats
.
tx_window_errors
++
;
if
(
err_status
&
0x1000
)
lp
->
stats
.
tx_window_errors
++
;
if
(
err_status
&
0x4000
)
lp
->
stats
.
tx_fifo_errors
++
;
if
(
err_status
&
0x4000
)
{
/* Perhaps we should re-init() after the FIFO error. */
/* Ackk! On FIFO errors the Tx unit is turned off! */
lp
->
stats
.
tx_fifo_errors
++
;
/* Remove this verbosity later! */
printk
(
"%s: Tx FIFO error! Status %4.4x.
\n
"
,
dev
->
name
,
csr0
);
/* Restart the chip. */
outw
(
0x0002
,
dev
->
base_addr
+
LANCE_DATA
);
}
}
else
{
}
else
{
if
(
status
&
0x18000000
)
if
(
status
&
0x18000000
)
lp
->
stats
.
collisions
++
;
lp
->
stats
.
collisions
++
;
...
@@ -762,13 +787,14 @@ lance_interrupt(int reg_ptr)
...
@@ -762,13 +787,14 @@ lance_interrupt(int reg_ptr)
#ifndef final_version
#ifndef final_version
if
(
lp
->
cur_tx
-
dirty_tx
>=
TX_RING_SIZE
)
{
if
(
lp
->
cur_tx
-
dirty_tx
>=
TX_RING_SIZE
)
{
printk
(
"out-of-sync dirty pointer, %d vs.
%d.
\n
"
,
printk
(
"out-of-sync dirty pointer, %d vs. %d, full=
%d.
\n
"
,
dirty_tx
,
lp
->
cur_tx
);
dirty_tx
,
lp
->
cur_tx
,
lp
->
tx_full
);
dirty_tx
+=
TX_RING_SIZE
;
dirty_tx
+=
TX_RING_SIZE
;
}
}
#endif
#endif
if
(
lp
->
tx_full
&&
dev
->
tbusy
&&
dirty_tx
>
lp
->
cur_tx
-
TX_RING_SIZE
+
2
)
{
if
(
lp
->
tx_full
&&
dev
->
tbusy
&&
dirty_tx
>
lp
->
cur_tx
-
TX_RING_SIZE
+
2
)
{
/* The ring is no longer full, clear tbusy. */
/* The ring is no longer full, clear tbusy. */
lp
->
tx_full
=
0
;
lp
->
tx_full
=
0
;
dev
->
tbusy
=
0
;
dev
->
tbusy
=
0
;
...
@@ -778,14 +804,20 @@ lance_interrupt(int reg_ptr)
...
@@ -778,14 +804,20 @@ lance_interrupt(int reg_ptr)
lp
->
dirty_tx
=
dirty_tx
;
lp
->
dirty_tx
=
dirty_tx
;
}
}
if
(
csr0
&
0x8000
)
{
/* Check the error summary bit
. */
/* Log misc errors
. */
if
(
csr0
&
0x4000
)
lp
->
stats
.
tx_errors
++
;
/* Tx babble. */
if
(
csr0
&
0x4000
)
lp
->
stats
.
tx_errors
++
;
/* Tx babble. */
if
(
csr0
&
0x1000
)
lp
->
stats
.
rx_errors
++
;
/* Missed a Rx frame. */
if
(
csr0
&
0x1000
)
lp
->
stats
.
rx_errors
++
;
/* Missed a Rx frame. */
if
(
csr0
&
0x0800
)
{
printk
(
"%s: Bus master arbitration failure, status %4.4x.
\n
"
,
dev
->
name
,
csr0
);
/* Restart the chip. */
outw
(
0x0002
,
dev
->
base_addr
+
LANCE_DATA
);
}
}
}
/* Clear any other interrupt. */
/* Clear any other interrupt
, and set interrupt enable
. */
outw
(
0x0000
,
dev
->
base_addr
+
LANCE_ADDR
);
outw
(
0x0000
,
dev
->
base_addr
+
LANCE_ADDR
);
outw
(
0x7
f
40
,
dev
->
base_addr
+
LANCE_DATA
);
outw
(
0x7
9
40
,
dev
->
base_addr
+
LANCE_DATA
);
if
(
lance_debug
>
4
)
if
(
lance_debug
>
4
)
printk
(
"%s: exiting interrupt, csr%d=%#4.4x.
\n
"
,
printk
(
"%s: exiting interrupt, csr%d=%#4.4x.
\n
"
,
...
@@ -808,7 +840,7 @@ lance_rx(struct device *dev)
...
@@ -808,7 +840,7 @@ lance_rx(struct device *dev)
int
status
=
lp
->
rx_ring
[
entry
].
base
>>
24
;
int
status
=
lp
->
rx_ring
[
entry
].
base
>>
24
;
if
(
status
!=
0x03
)
{
/* There was an error. */
if
(
status
!=
0x03
)
{
/* There was an error. */
/* There is a tricky error noted by John Murphy,
/* There is a
n
tricky error noted by John Murphy,
<murf@perftech.com> to Russ Nelson: Even with full-sized
<murf@perftech.com> to Russ Nelson: Even with full-sized
buffers it's possible for a jabber packet to use two
buffers it's possible for a jabber packet to use two
buffers, with only the last correctly noting the error. */
buffers, with only the last correctly noting the error. */
...
@@ -847,10 +879,10 @@ lance_rx(struct device *dev)
...
@@ -847,10 +879,10 @@ lance_rx(struct device *dev)
lp
->
stats
.
rx_packets
++
;
lp
->
stats
.
rx_packets
++
;
}
}
lp
->
rx_ring
[
entry
].
base
|=
0x80000000
;
/* The docs say that the buffer length isn't touched, but Andrew Boyd
/* The docs say that the buffer length isn't touched, but Andrew Boyd
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
=
-
PKT_BUF_SZ
;
lp
->
rx_ring
[
entry
].
buf_length
=
-
PKT_BUF_SZ
;
lp
->
rx_ring
[
entry
].
base
|=
0x80000000
;
entry
=
(
++
lp
->
cur_rx
)
&
RX_RING_MOD_MASK
;
entry
=
(
++
lp
->
cur_rx
)
&
RX_RING_MOD_MASK
;
}
}
...
@@ -869,9 +901,10 @@ lance_close(struct device *dev)
...
@@ -869,9 +901,10 @@ lance_close(struct device *dev)
dev
->
start
=
0
;
dev
->
start
=
0
;
dev
->
tbusy
=
1
;
dev
->
tbusy
=
1
;
if
(
lp
->
chip_version
!=
OLD_LANCE
)
{
outw
(
112
,
ioaddr
+
LANCE_ADDR
);
outw
(
112
,
ioaddr
+
LANCE_ADDR
);
lp
->
stats
.
rx_missed_errors
=
inw
(
ioaddr
+
LANCE_DATA
);
lp
->
stats
.
rx_missed_errors
=
inw
(
ioaddr
+
LANCE_DATA
);
}
outw
(
0
,
ioaddr
+
LANCE_ADDR
);
outw
(
0
,
ioaddr
+
LANCE_ADDR
);
if
(
lance_debug
>
1
)
if
(
lance_debug
>
1
)
...
@@ -882,6 +915,7 @@ lance_close(struct device *dev)
...
@@ -882,6 +915,7 @@ lance_close(struct device *dev)
memory if we don't. */
memory if we don't. */
outw
(
0x0004
,
ioaddr
+
LANCE_DATA
);
outw
(
0x0004
,
ioaddr
+
LANCE_DATA
);
if
(
dev
->
dma
!=
4
)
disable_dma
(
dev
->
dma
);
disable_dma
(
dev
->
dma
);
free_irq
(
dev
->
irq
);
free_irq
(
dev
->
irq
);
...
@@ -898,12 +932,14 @@ lance_get_stats(struct device *dev)
...
@@ -898,12 +932,14 @@ lance_get_stats(struct device *dev)
short
ioaddr
=
dev
->
base_addr
;
short
ioaddr
=
dev
->
base_addr
;
short
saved_addr
;
short
saved_addr
;
if
(
lp
->
chip_version
!=
OLD_LANCE
)
{
cli
();
cli
();
saved_addr
=
inw
(
ioaddr
+
LANCE_ADDR
);
saved_addr
=
inw
(
ioaddr
+
LANCE_ADDR
);
outw
(
112
,
ioaddr
+
LANCE_ADDR
);
outw
(
112
,
ioaddr
+
LANCE_ADDR
);
lp
->
stats
.
rx_missed_errors
=
inw
(
ioaddr
+
LANCE_DATA
);
lp
->
stats
.
rx_missed_errors
=
inw
(
ioaddr
+
LANCE_DATA
);
outw
(
saved_addr
,
ioaddr
+
LANCE_ADDR
);
outw
(
saved_addr
,
ioaddr
+
LANCE_ADDR
);
sti
();
sti
();
}
return
&
lp
->
stats
;
return
&
lp
->
stats
;
}
}
...
...
drivers/net/loopback.c
View file @
6e38a55b
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
*
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Donald Becker, <becker@
super.org
>
* Donald Becker, <becker@
cesdis.gsfc.nasa.gov
>
*
*
* Alan Cox : Fixed oddments for NET3.014
* Alan Cox : Fixed oddments for NET3.014
*
*
...
...
drivers/net/ne.c
View file @
6e38a55b
/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
/*
/*
Written 1992
,1993
by Donald Becker.
Written 1992
-94
by Donald Becker.
Copyright 1993 United States Government as represented by the
Copyright 1993 United States Government as represented by the
Director, National Security Agency. This software may be used and
Director, National Security Agency.
distributed according to the terms of the GNU Public License,
incorporated herein by reference.
This
driver should work with many 8390-based ethernet boards. Currently
This
software may be used and distributed according to the terms
it support the NE1000, NE2000, clones, and some Cabletron products
.
of the GNU Public License, incorporated herein by reference
.
The Author may be reached as becker@super.org or
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This driver should work with many programmed-I/O 8390-based ethernet
boards. Currently it support the NE1000, NE2000, many clones,
and some Cabletron products.
*/
*/
/* Routines for the NatSemi-based designs (NE[12]000). */
/* Routines for the NatSemi-based designs (NE[12]000). */
static
char
*
version
=
static
char
*
version
=
"ne.c:v
0.99-15k 3/3/94 Donald Becker (becker@super.org
)
\n
"
;
"ne.c:v
1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov
)
\n
"
;
#include <linux/config.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
...
@@ -28,11 +31,28 @@ static char *version =
...
@@ -28,11 +31,28 @@ static char *version =
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include "8390.h"
#include "8390.h"
extern
struct
device
*
init_etherdev
(
struct
device
*
dev
,
int
sizeof_private
,
unsigned
long
*
mem_startp
);
/* A zero-terminated list of I/O addresses to be probed. */
static
unsigned
int
netcard_portlist
[]
=
{
0x300
,
0x280
,
0x320
,
0x340
,
0x360
,
0
};
/* A list of bad clones that we none-the-less recognize. */
static
struct
{
char
*
name8
,
*
name16
;
unsigned
char
SAprefix
[
4
];}
bad_clone_list
[]
=
{
{
"DE100"
,
"DE200"
,
{
0x00
,
0xDE
,
0x01
,}},
{
"DE120"
,
"DE220"
,
{
0x00
,
0x80
,
0xc8
,}},
{
"DFI1000"
,
"DFI2000"
,
{
'D'
,
'F'
,
'I'
,}},
/* Original, eh? */
{
0
,}
};
#define NE_BASE (dev->base_addr)
#define NE_BASE (dev->base_addr)
#define NE_CMD 0x00
#define NE_CMD 0x00
#define NE_DATAPORT 0x10
/* NatSemi-defined port window offset. */
#define NE_DATAPORT 0x10
/* NatSemi-defined port window offset. */
#define NE_RESET 0x1f
/* Issue a read to reset, a write to clear. */
#define NE_RESET 0x1f
/* Issue a read to reset, a write to clear. */
#define NE_IO_EXTENT 0x20
#define NE1SM_START_PG 0x20
/* First page of TX buffer */
#define NE1SM_START_PG 0x20
/* First page of TX buffer */
#define NE1SM_STOP_PG 0x40
/* Last page +1 of RX ring */
#define NE1SM_STOP_PG 0x40
/* Last page +1 of RX ring */
...
@@ -40,7 +60,7 @@ static char *version =
...
@@ -40,7 +60,7 @@ static char *version =
#define NESM_STOP_PG 0x80
/* Last page +1 of RX ring */
#define NESM_STOP_PG 0x80
/* Last page +1 of RX ring */
int
ne_probe
(
struct
device
*
dev
);
int
ne_probe
(
struct
device
*
dev
);
static
int
ne
probe1
(
int
ioaddr
,
struct
device
*
dev
,
int
verbose
);
static
int
ne
_probe1
(
struct
device
*
dev
,
int
ioaddr
);
static
void
ne_reset_8390
(
struct
device
*
dev
);
static
void
ne_reset_8390
(
struct
device
*
dev
);
static
int
ne_block_input
(
struct
device
*
dev
,
int
count
,
static
int
ne_block_input
(
struct
device
*
dev
,
int
count
,
...
@@ -70,44 +90,47 @@ static void ne_block_output(struct device *dev, const int count,
...
@@ -70,44 +90,47 @@ static void ne_block_output(struct device *dev, const int count,
E2010 starts at 0x100 and ends at 0x4000.
E2010 starts at 0x100 and ends at 0x4000.
E2010-x starts at 0x100 and ends at 0xffff. */
E2010-x starts at 0x100 and ends at 0xffff. */
#ifdef HAVE_DEVLIST
struct
netdev_entry
netcard_drv
=
{
"ne"
,
ne_probe1
,
NE_IO_EXTENT
,
netcard_portlist
};
#else
int
ne_probe
(
struct
device
*
dev
)
int
ne_probe
(
struct
device
*
dev
)
{
{
int
*
port
,
ports
[]
=
{
0x300
,
0x280
,
0x320
,
0x340
,
0x360
,
0
}
;
int
i
;
short
ioaddr
=
dev
->
base_addr
;
int
base_addr
=
dev
?
dev
->
base_addr
:
0
;
if
(
ioaddr
<
0
)
if
(
base_addr
>
0x1ff
)
/* Check a single specified location. */
return
ENXIO
;
/* Don't probe at all. */
return
ne_probe1
(
dev
,
base_addr
);
if
(
ioaddr
>
0x100
)
else
if
(
base_addr
!=
0
)
/* Don't probe at all. */
return
!
neprobe1
(
ioaddr
,
dev
,
1
)
;
return
ENXIO
;
for
(
port
=
&
ports
[
0
];
*
port
;
port
++
)
{
for
(
i
=
0
;
netcard_portlist
[
i
];
i
++
)
{
#ifdef HAVE_PORTRESERVE
int
ioaddr
=
netcard_portlist
[
i
];
if
(
check_region
(
*
port
,
32
))
if
(
check_region
(
ioaddr
,
NE_IO_EXTENT
))
continue
;
continue
;
#endif
if
(
ne_probe1
(
dev
,
ioaddr
)
==
0
)
if
(
inb_p
(
*
port
)
!=
0xff
&&
neprobe1
(
*
port
,
dev
,
0
))
{
dev
->
base_addr
=
*
port
;
return
0
;
return
0
;
}
}
}
dev
->
base_addr
=
ioaddr
;
return
ENODEV
;
return
ENODEV
;
}
}
#endif
static
int
ne
probe1
(
int
ioaddr
,
struct
device
*
dev
,
int
verbose
)
static
int
ne
_probe1
(
struct
device
*
dev
,
int
ioaddr
)
{
{
int
i
;
int
i
;
unsigned
char
SA_prom
[
32
];
unsigned
char
SA_prom
[
32
];
int
wordlength
=
2
;
int
wordlength
=
2
;
char
*
name
;
char
*
name
=
NULL
;
int
start_page
,
stop_page
;
int
start_page
,
stop_page
;
int
neX000
,
ctron
,
dlink
,
dfi
;
int
neX000
,
ctron
;
int
reg0
=
inb
(
ioaddr
);
int
reg0
=
inb
(
ioaddr
);
if
(
reg0
==
0xFF
)
if
(
reg0
==
0xFF
)
return
0
;
return
ENODEV
;
/* Do a
quick preliminary check
that we have a 8390. */
/* Do a
preliminary verification
that we have a 8390. */
{
int
regd
;
{
int
regd
;
outb_p
(
E8390_NODMA
+
E8390_PAGE1
+
E8390_STOP
,
ioaddr
+
E8390_CMD
);
outb_p
(
E8390_NODMA
+
E8390_PAGE1
+
E8390_STOP
,
ioaddr
+
E8390_CMD
);
regd
=
inb_p
(
ioaddr
+
0x0d
);
regd
=
inb_p
(
ioaddr
+
0x0d
);
...
@@ -117,14 +140,13 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
...
@@ -117,14 +140,13 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
if
(
inb_p
(
ioaddr
+
EN0_COUNTER0
)
!=
0
)
{
if
(
inb_p
(
ioaddr
+
EN0_COUNTER0
)
!=
0
)
{
outb_p
(
reg0
,
ioaddr
);
outb_p
(
reg0
,
ioaddr
);
outb
(
regd
,
ioaddr
+
0x0d
);
/* Restore the old values. */
outb
(
regd
,
ioaddr
+
0x0d
);
/* Restore the old values. */
return
0
;
return
ENODEV
;
}
}
}
}
printk
(
"NE*000 ethercard probe at %#3x:"
,
ioaddr
);
printk
(
"NE*000 ethercard probe at %#3x:"
,
ioaddr
);
/* Read the 16 bytes of station address prom, returning 1 for
/* Read the 16 bytes of station address PROM.
an eight-bit interface and 2 for a 16-bit interface.
We must first initialize registers, similar to NS8390_init(eifdev, 0).
We must first initialize registers, similar to NS8390_init(eifdev, 0).
We can't reliably read the SAPROM address without this.
We can't reliably read the SAPROM address without this.
(I learned the hard way!). */
(I learned the hard way!). */
...
@@ -162,43 +184,53 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
...
@@ -162,43 +184,53 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
/* Un-double the SA_prom values. */
/* Un-double the SA_prom values. */
for
(
i
=
0
;
i
<
16
;
i
++
)
for
(
i
=
0
;
i
<
16
;
i
++
)
SA_prom
[
i
]
=
SA_prom
[
i
+
i
];
SA_prom
[
i
]
=
SA_prom
[
i
+
i
];
start_page
=
NESM_START_PG
;
stop_page
=
NESM_STOP_PG
;
}
else
{
start_page
=
NE1SM_START_PG
;
stop_page
=
NE1SM_STOP_PG
;
}
}
#if defined(show_all_SAPROM)
/* If your ethercard isn't detected define this to see the SA_PROM. */
for
(
i
=
0
;
i
<
sizeof
(
SA_prom
);
i
++
)
printk
(
" %2.2x"
,
SA_prom
[
i
]);
#else
for
(
i
=
0
;
i
<
ETHER_ADDR_LEN
;
i
++
)
{
for
(
i
=
0
;
i
<
ETHER_ADDR_LEN
;
i
++
)
{
dev
->
dev_addr
[
i
]
=
SA_prom
[
i
];
dev
->
dev_addr
[
i
]
=
SA_prom
[
i
];
printk
(
" %2.2x"
,
SA_prom
[
i
]);
printk
(
" %2.2x"
,
SA_prom
[
i
]);
}
}
#endif
neX000
=
(
SA_prom
[
14
]
==
0x57
&&
SA_prom
[
15
]
==
0x57
);
neX000
=
(
SA_prom
[
14
]
==
0x57
&&
SA_prom
[
15
]
==
0x57
);
ctron
=
(
SA_prom
[
0
]
==
0x00
&&
SA_prom
[
1
]
==
0x00
&&
SA_prom
[
2
]
==
0x1d
);
ctron
=
(
SA_prom
[
0
]
==
0x00
&&
SA_prom
[
1
]
==
0x00
&&
SA_prom
[
2
]
==
0x1d
);
dlink
=
(
SA_prom
[
0
]
==
0x00
&&
SA_prom
[
1
]
==
0xDE
&&
SA_prom
[
2
]
==
0x01
);
dfi
=
(
SA_prom
[
0
]
==
'D'
&&
SA_prom
[
1
]
==
'F'
&&
SA_prom
[
2
]
==
'I'
);
/* Set up the rest of the parameters. */
/* Set up the rest of the parameters. */
if
(
neX000
||
dlink
||
dfi
)
{
if
(
neX000
)
{
if
(
wordlength
==
2
)
{
name
=
(
wordlength
==
2
)
?
"NE2000"
:
"NE1000"
;
name
=
dlink
?
"DE200"
:
"NE2000"
;
start_page
=
NESM_START_PG
;
stop_page
=
NESM_STOP_PG
;
}
else
{
name
=
dlink
?
"DE100"
:
"NE1000"
;
start_page
=
NE1SM_START_PG
;
stop_page
=
NE1SM_STOP_PG
;
}
}
else
if
(
ctron
)
{
}
else
if
(
ctron
)
{
name
=
"Cabletron"
;
name
=
"Cabletron"
;
start_page
=
0x01
;
start_page
=
0x01
;
stop_page
=
(
wordlength
==
2
)
?
0x40
:
0x20
;
stop_page
=
(
wordlength
==
2
)
?
0x40
:
0x20
;
}
else
{
}
else
{
printk
(
" not found.
\n
"
);
/* Ack! Well, there might be a *bad* NE*000 clone there.
return
0
;
Check for total bogus addresses. */
for
(
i
=
0
;
bad_clone_list
[
i
].
name8
;
i
++
)
{
if
(
SA_prom
[
0
]
==
bad_clone_list
[
i
].
SAprefix
[
0
]
&&
SA_prom
[
1
]
==
bad_clone_list
[
i
].
SAprefix
[
1
]
&&
SA_prom
[
2
]
==
bad_clone_list
[
i
].
SAprefix
[
2
])
{
if
(
wordlength
==
2
)
{
name
=
bad_clone_list
[
i
].
name16
;
}
else
{
name
=
bad_clone_list
[
i
].
name8
;
}
}
break
;
}
}
if
(
bad_clone_list
[
i
].
name8
==
NULL
)
{
printk
(
" not found (invalid signature %2.2x %2.2x).
\n
"
,
SA_prom
[
14
],
SA_prom
[
15
]);
return
ENXIO
;
}
}
if
(
dev
==
NULL
)
dev
=
init_etherdev
(
0
,
sizeof
(
struct
ei_device
),
0
);
if
(
dev
->
irq
<
2
)
{
if
(
dev
->
irq
<
2
)
{
autoirq_setup
(
0
);
autoirq_setup
(
0
);
...
@@ -221,15 +253,16 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
...
@@ -221,15 +253,16 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
int
irqval
=
request_irq
(
dev
->
irq
,
ei_interrupt
,
0
,
"ne"
);
int
irqval
=
request_irq
(
dev
->
irq
,
ei_interrupt
,
0
,
"ne"
);
if
(
irqval
)
{
if
(
irqval
)
{
printk
(
" unable to get IRQ %d (irqval=%d).
\n
"
,
dev
->
irq
,
irqval
);
printk
(
" unable to get IRQ %d (irqval=%d).
\n
"
,
dev
->
irq
,
irqval
);
return
0
;
return
EAGAIN
;
}
}
}
}
dev
->
base_addr
=
ioaddr
;
dev
->
base_addr
=
ioaddr
;
#ifdef HAVE_PORTRESERVE
snarf_region
(
ioaddr
,
NE_IO_EXTENT
);
snarf_region
(
ioaddr
,
32
);
#endif
for
(
i
=
0
;
i
<
ETHER_ADDR_LEN
;
i
++
)
dev
->
dev_addr
[
i
]
=
SA_prom
[
i
];
ethdev_init
(
dev
);
ethdev_init
(
dev
);
printk
(
"
\n
%s: %s found at %#x, using IRQ %d.
\n
"
,
printk
(
"
\n
%s: %s found at %#x, using IRQ %d.
\n
"
,
...
@@ -253,7 +286,7 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
...
@@ -253,7 +286,7 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
ei_status
.
block_input
=
&
ne_block_input
;
ei_status
.
block_input
=
&
ne_block_input
;
ei_status
.
block_output
=
&
ne_block_output
;
ei_status
.
block_output
=
&
ne_block_output
;
NS8390_init
(
dev
,
0
);
NS8390_init
(
dev
,
0
);
return
dev
->
base_addr
;
return
0
;
}
}
/* Hard reset the card. This used to pause for the same period that a
/* Hard reset the card. This used to pause for the same period that a
...
@@ -289,9 +322,10 @@ ne_block_input(struct device *dev, int count, char *buf, int ring_offset)
...
@@ -289,9 +322,10 @@ ne_block_input(struct device *dev, int count, char *buf, int ring_offset)
if
(
ei_status
.
dmaing
)
{
if
(
ei_status
.
dmaing
)
{
if
(
ei_debug
>
0
)
if
(
ei_debug
>
0
)
printk
(
"%s: DMAing conflict in ne_block_input."
printk
(
"%s: DMAing conflict in ne_block_input "
"[DMAstat:%1x][irqlock:%1x]
\n
"
,
"[DMAstat:%d][irqlock:%d][intr:%d].
\n
"
,
dev
->
name
,
ei_status
.
dmaing
,
ei_status
.
irqlock
);
dev
->
name
,
ei_status
.
dmaing
,
ei_status
.
irqlock
,
dev
->
interrupt
);
return
0
;
return
0
;
}
}
ei_status
.
dmaing
|=
0x01
;
ei_status
.
dmaing
|=
0x01
;
...
@@ -348,8 +382,9 @@ ne_block_output(struct device *dev, int count,
...
@@ -348,8 +382,9 @@ ne_block_output(struct device *dev, int count,
if
(
ei_status
.
dmaing
)
{
if
(
ei_status
.
dmaing
)
{
if
(
ei_debug
>
0
)
if
(
ei_debug
>
0
)
printk
(
"%s: DMAing conflict in ne_block_output."
printk
(
"%s: DMAing conflict in ne_block_output."
"[DMAstat:%1x][irqlock:%1x]
\n
"
,
"[DMAstat:%d][irqlock:%d][intr:%d]
\n
"
,
dev
->
name
,
ei_status
.
dmaing
,
ei_status
.
irqlock
);
dev
->
name
,
ei_status
.
dmaing
,
ei_status
.
irqlock
,
dev
->
interrupt
);
return
;
return
;
}
}
ei_status
.
dmaing
|=
0x02
;
ei_status
.
dmaing
|=
0x02
;
...
...
drivers/net/net_init.c
View file @
6e38a55b
/* netdrv_init.c: Initialization for network devices. */
/* netdrv_init.c: Initialization for network devices. */
/*
/*
Written 1993 by Donald Becker.
Written 1993,1994 by Donald Becker.
Copyright 1993 United States Government as represented by the Director,
National Security Agency. This software may only be used and distributed
according to the terms of the GNU Public License as modified by SRC,
incorporated herein by reference.
The author may be reached as becker@super.org or
The author may be reached as becker@cesdis.gsfc.nasa.gov or
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
C/O Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This file contains the initialization for the "pl14+" style ethernet
This file contains the initialization for the "pl14+" style ethernet
drivers. It should eventually replace most of drivers/net/Space.c.
drivers. It should eventually replace most of drivers/net/Space.c.
...
@@ -95,7 +92,10 @@ init_etherdev(struct device *dev, int sizeof_private, unsigned long *mem_startp)
...
@@ -95,7 +92,10 @@ init_etherdev(struct device *dev, int sizeof_private, unsigned long *mem_startp)
if
(
dev
==
NULL
)
{
if
(
dev
==
NULL
)
{
int
alloc_size
=
sizeof
(
struct
device
)
+
sizeof
(
"eth%d "
)
int
alloc_size
=
sizeof
(
struct
device
)
+
sizeof
(
"eth%d "
)
+
sizeof_private
;
+
sizeof_private
+
3
;
alloc_size
&=
~
3
;
/* Round to dword boundary. */
if
(
mem_startp
&&
*
mem_startp
)
{
if
(
mem_startp
&&
*
mem_startp
)
{
dev
=
(
struct
device
*
)
*
mem_startp
;
dev
=
(
struct
device
*
)
*
mem_startp
;
*
mem_startp
+=
alloc_size
;
*
mem_startp
+=
alloc_size
;
...
...
drivers/net/skeleton.c
View file @
6e38a55b
/* skeleton.c: A
sample network driver cor
e for linux. */
/* skeleton.c: A
network driver outlin
e for linux. */
/*
/*
Written 1993 by Donald Becker.
Written 1993-94 by Donald Becker.
Copyright 1993 United States Government as represented by the Director,
National Security Agency. This software may only be used and distributed
according to the terms of the GNU Public License as modified by SRC,
incorporated herein by reference.
The author may be reached as becker@super.org or
Copyright 1993 United States Government as represented by the
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
Director, National Security Agency.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This file is an outline for writing a network device driver for the
This file is an outline for writing a network device driver for the
the Linux operating system.
the Linux operating system.
...
@@ -19,7 +22,7 @@
...
@@ -19,7 +22,7 @@
*/
*/
static
char
*
version
=
static
char
*
version
=
"skeleton.c:v
0.05 11/16/93 Donald Becker (becker@super.org
)
\n
"
;
"skeleton.c:v
1.51 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov
)
\n
"
;
/* Always include 'config.h' first in case the user wants to turn on
/* Always include 'config.h' first in case the user wants to turn on
or override something. */
or override something. */
...
@@ -59,20 +62,13 @@ static char *version =
...
@@ -59,20 +62,13 @@ static char *version =
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/skbuff.h>
extern
struct
device
*
init_etherdev
(
struct
device
*
dev
,
int
sizeof_private
,
unsigned
long
*
mem_startp
);
#ifndef HAVE_AUTOIRQ
/* First, a few definitions that the brave might change. */
/* From auto_irq.c, in ioport.h for later versions. */
/* A zero-terminated list of I/O addresses to be probed. */
extern
void
autoirq_setup
(
int
waittime
);
static
unsigned
int
netcard_portlist
[]
=
extern
int
autoirq_report
(
int
waittime
);
{
0x200
,
0x240
,
0x280
,
0x2C0
,
0x300
,
0x320
,
0x340
,
0
};
/* The map from IRQ number (as passed to the interrupt handler) to
'struct device'. */
extern
struct
device
*
irq2dev_map
[
16
];
#endif
#ifndef HAVE_PORTRESERVE
#define check_region(ioaddr, size) 0
#define snarf_region(ioaddr, size); do ; while (0)
#endif
/* use 0 for production, 1 for verification, >2 for debug */
/* use 0 for production, 1 for verification, >2 for debug */
#ifndef NET_DEBUG
#ifndef NET_DEBUG
...
@@ -80,15 +76,15 @@ extern struct device *irq2dev_map[16];
...
@@ -80,15 +76,15 @@ extern struct device *irq2dev_map[16];
#endif
#endif
static
unsigned
int
net_debug
=
NET_DEBUG
;
static
unsigned
int
net_debug
=
NET_DEBUG
;
/* The number of low I/O ports used by the ethercard. */
#define NETCARD_IO_EXTENT 32
/* Information that need to be kept for each board. */
/* Information that need to be kept for each board. */
struct
net_local
{
struct
net_local
{
struct
enet_statistics
stats
;
struct
enet_statistics
stats
;
long
open_time
;
/* Useless example local info. */
long
open_time
;
/* Useless example local info. */
};
};
/* The number of low I/O ports used by the ethercard. */
#define ETHERCARD_TOTAL_SIZE 16
/* The station (ethernet) address prefix, used for IDing the board. */
/* The station (ethernet) address prefix, used for IDing the board. */
#define SA_ADDR0 0x00
#define SA_ADDR0 0x00
#define SA_ADDR1 0x42
#define SA_ADDR1 0x42
...
@@ -98,7 +94,7 @@ struct net_local {
...
@@ -98,7 +94,7 @@ struct net_local {
extern
int
netcard_probe
(
struct
device
*
dev
);
extern
int
netcard_probe
(
struct
device
*
dev
);
static
int
netcard_probe1
(
struct
device
*
dev
,
shor
t
ioaddr
);
static
int
netcard_probe1
(
struct
device
*
dev
,
in
t
ioaddr
);
static
int
net_open
(
struct
device
*
dev
);
static
int
net_open
(
struct
device
*
dev
);
static
int
net_send_packet
(
struct
sk_buff
*
skb
,
struct
device
*
dev
);
static
int
net_send_packet
(
struct
sk_buff
*
skb
,
struct
device
*
dev
);
static
void
net_interrupt
(
int
reg_ptr
);
static
void
net_interrupt
(
int
reg_ptr
);
...
@@ -119,54 +115,75 @@ extern void chipset_init(struct device *dev, int startp);
...
@@ -119,54 +115,75 @@ extern void chipset_init(struct device *dev, int startp);
If dev->base_addr == 2, allocate space for the device and return success
If dev->base_addr == 2, allocate space for the device and return success
(detachable devices only).
(detachable devices only).
*/
*/
#ifdef HAVE_DEVLIST
/* Support for a alternate probe manager, which will eliminate the
boilerplate below. */
struct
netdev_entry
netcard_drv
=
{
"netcard"
,
netcard_probe1
,
NETCARD_IO_EXTENT
,
netcard_portlist
};
#else
int
int
netcard_probe
(
struct
device
*
dev
)
netcard_probe
(
struct
device
*
dev
)
{
{
int
*
port
,
ports
[]
=
{
0x300
,
0x280
,
0
}
;
int
i
;
int
base_addr
=
dev
->
base_addr
;
int
base_addr
=
dev
?
dev
->
base_addr
:
0
;
if
(
base_addr
>
0x1ff
)
/* Check a single specified location. */
if
(
base_addr
>
0x1ff
)
/* Check a single specified location. */
return
netcard_probe1
(
dev
,
base_addr
);
return
netcard_probe1
(
dev
,
base_addr
);
else
if
(
base_addr
>
0
)
/* Don't probe at all. */
else
if
(
base_addr
!=
0
)
/* Don't probe at all. */
return
ENXIO
;
return
ENXIO
;
for
(
port
=
&
ports
[
0
];
*
port
;
port
++
)
{
for
(
i
=
0
;
netcard_portlist
[
i
];
i
++
)
{
int
ioaddr
=
*
port
;
int
ioaddr
=
netcard_portlist
[
i
];
if
(
check_region
(
ioaddr
,
ETHERCARD_TOTAL_SIZE
))
if
(
check_region
(
ioaddr
,
NETCARD_IO_EXTENT
))
continue
;
if
(
inb
(
ioaddr
)
!=
0x57
)
continue
;
continue
;
dev
->
base_addr
=
ioaddr
;
if
(
netcard_probe1
(
dev
,
ioaddr
)
==
0
)
if
(
netcard_probe1
(
dev
,
ioaddr
)
==
0
)
return
0
;
return
0
;
}
}
dev
->
base_addr
=
base_addr
;
return
ENODEV
;
return
ENODEV
;
}
}
#endif
/* This is the real probe routine. Linux has a history of friendly device
probes on the ISA bus. A good device probes avoids doing writes, and
verifies that the correct device exists and functions. */
int
netcard_probe1
(
struct
device
*
dev
,
shor
t
ioaddr
)
static
int
netcard_probe1
(
struct
device
*
dev
,
in
t
ioaddr
)
{
{
unsigned
char
station_addr
[
6
]
;
static
unsigned
version_printed
=
0
;
int
i
;
int
i
;
/* Read the station address PROM. */
/* For ethernet adaptors the first three octets of the station address contains
for
(
i
=
0
;
i
<
6
;
i
++
)
{
the manufacturer's unique code. That might be a good probe method.
station_addr
[
i
]
=
inb
(
ioaddr
+
i
);
Ideally you would add additional checks. */
}
if
(
inb
(
ioaddr
+
0
)
!=
SA_ADDR0
/* Check the first three octets of the S.A. for the manufacturer's code. */
||
inb
(
ioaddr
+
1
)
!=
SA_ADDR1
if
(
station_addr
[
0
]
!=
SA_ADDR0
||
inb
(
ioaddr
+
2
)
!=
SA_ADDR2
)
{
||
station_addr
[
1
]
!=
SA_ADDR1
||
station_addr
[
2
]
!=
SA_ADDR2
)
{
return
ENODEV
;
return
ENODEV
;
}
}
printk
(
"%s: %s found at %#3x, IRQ %d.
\n
"
,
dev
->
name
,
/* Allocate a new 'dev' if needed. */
"network card"
,
dev
->
base_addr
,
dev
->
irq
);
if
(
dev
==
NULL
)
dev
=
init_etherdev
(
0
,
sizeof
(
struct
net_local
),
0
);
if
(
net_debug
&&
version_printed
++
==
0
)
printk
(
version
);
printk
(
"%s: %s found at %#3x, "
,
dev
->
name
,
"network card"
,
ioaddr
);
/* Fill in the 'dev' fields. */
dev
->
base_addr
=
ioaddr
;
/* Retrive and print the ethernet address. */
for
(
i
=
0
;
i
<
6
;
i
++
)
printk
(
" %2.2x"
,
dev
->
dev_addr
[
i
]
=
inb
(
ioaddr
+
i
));
#ifdef jumpered_interrupts
#ifdef jumpered_interrupts
/* If this board has jumpered interrupts, snarf the interrupt vector
/* If this board has jumpered interrupts, snarf the interrupt vector
now. There is no point in waiting since no other device can use
now. There is no point in waiting since no other device can use
the interrupt, and this marks the irq as busy. */
the interrupt, and this marks the irq as busy.
Jumpered interrupts are typically not reported by the boards, and
we must used autoIRQ to find them. */
if
(
dev
->
irq
==
-
1
)
if
(
dev
->
irq
==
-
1
)
;
/* Do nothing: a user-level program will set it. */
;
/* Do nothing: a user-level program will set it. */
...
@@ -190,14 +207,50 @@ int netcard_probe1(struct device *dev, short ioaddr)
...
@@ -190,14 +207,50 @@ int netcard_probe1(struct device *dev, short ioaddr)
}
}
}
}
#endif
/* jumpered interrupt */
#endif
/* jumpered interrupt */
#ifdef jumpered_dma
/* If we use a jumpered DMA channel, that should be probed for and
allocated here as well. See lance.c for an example. */
if
(
dev
->
dma
==
0
)
{
if
(
request_dma
(
dev
->
dma
,
"netcard"
))
{
printk
(
"DMA %d allocation failed.
\n
"
,
dev
->
dma
);
return
EAGAIN
;
}
else
printk
(
", assigned DMA %d.
\n
"
,
dev
->
dma
);
}
else
{
short
dma_status
,
new_dma_status
;
/* Read the DMA channel status registers. */
dma_status
=
((
inb
(
DMA1_STAT_REG
)
>>
4
)
&
0x0f
)
|
(
inb
(
DMA2_STAT_REG
)
&
0xf0
);
/* Trigger a DMA request, perhaps pause a bit. */
outw
(
0x1234
,
ioaddr
+
8
);
/* Re-read the DMA status registers. */
new_dma_status
=
((
inb
(
DMA1_STAT_REG
)
>>
4
)
&
0x0f
)
|
(
inb
(
DMA2_STAT_REG
)
&
0xf0
);
/* Eliminate the old and floating requests and DMA4, the cascade. */
new_dma_status
^=
dma_status
;
new_dma_status
&=
~
0x10
;
for
(
i
=
7
;
i
>
0
;
i
--
)
if
(
test_bit
(
new_dma
,
&
new_dma_status
))
{
dev
->
dma
=
i
;
break
;
}
if
(
i
<=
0
)
{
printk
(
"DMA probe failed.
\n
"
);
return
EAGAIN
;
}
if
(
request_dma
(
dev
->
dma
,
"netcard"
))
{
printk
(
"probed DMA %d allocation failed.
\n
"
,
dev
->
dma
);
return
EAGAIN
;
}
}
#endif
/* jumpered DMA */
/* Grab the region so we can find another board if autoIRQ fails. */
/* Grab the region so we can find another board if autoIRQ fails. */
snarf_region
(
ioaddr
,
ETHERCARD_TOTAL_SIZE
);
snarf_region
(
ioaddr
,
NETCARD_IO_EXTENT
);
if
(
net_debug
)
printk
(
version
);
/* Initialize the device structure. */
/* Initialize the device structure. */
if
(
dev
->
priv
==
NULL
)
dev
->
priv
=
kmalloc
(
sizeof
(
struct
net_local
),
GFP_KERNEL
);
dev
->
priv
=
kmalloc
(
sizeof
(
struct
net_local
),
GFP_KERNEL
);
memset
(
dev
->
priv
,
0
,
sizeof
(
struct
net_local
));
memset
(
dev
->
priv
,
0
,
sizeof
(
struct
net_local
));
...
@@ -207,8 +260,7 @@ int netcard_probe1(struct device *dev, short ioaddr)
...
@@ -207,8 +260,7 @@ int netcard_probe1(struct device *dev, short ioaddr)
dev
->
get_stats
=
net_get_stats
;
dev
->
get_stats
=
net_get_stats
;
dev
->
set_multicast_list
=
&
set_multicast_list
;
dev
->
set_multicast_list
=
&
set_multicast_list
;
/* Fill in the fields of the device structure with ethernet-generic values. */
/* Fill in the fields of the device structure with ethernet values. */
ether_setup
(
dev
);
ether_setup
(
dev
);
return
0
;
return
0
;
...
@@ -234,15 +286,14 @@ net_open(struct device *dev)
...
@@ -234,15 +286,14 @@ net_open(struct device *dev)
return
-
EAGAIN
;
return
-
EAGAIN
;
}
}
/* Always snarf the DMA channel after the IRQ, and clean up on failure. */
/* Always snarf a DMA channel after the IRQ. */
if
(
request_dma
(
dev
->
dma
,
"skeleton ethernet"
))
{
if
(
request_dma
(
dev
->
dma
,
"skeleton ethernet"
))
{
free_irq
(
dev
->
irq
);
free_irq
(
dev
->
irq
);
return
-
EAGAIN
;
return
-
EAGAIN
;
}
}
irq2dev_map
[
dev
->
irq
]
=
dev
;
irq2dev_map
[
dev
->
irq
]
=
dev
;
/* Reset the hardware here. */
/* Reset the hardware here.
Don't forget to set the station address.
*/
/*chipset_init(dev, 1);*/
/*chipset_init(dev, 1);*/
outb
(
0x00
,
ioaddr
);
outb
(
0x00
,
ioaddr
);
lp
->
open_time
=
jiffies
;
lp
->
open_time
=
jiffies
;
...
@@ -337,6 +388,7 @@ net_interrupt(int reg_ptr)
...
@@ -337,6 +388,7 @@ net_interrupt(int reg_ptr)
}
}
}
while
(
++
boguscount
<
20
)
;
}
while
(
++
boguscount
<
20
)
;
dev
->
interrupt
=
0
;
return
;
return
;
}
}
...
...
drivers/net/smc-ultra.c
View file @
6e38a55b
/* smc-ultra.c: A SMC Ultra ethernet driver for linux. */
/* smc-ultra.c: A SMC Ultra ethernet driver for linux. */
/*
/*
Written 1993 by Donald Becker. If released, this code will be
Written 1993-94 by Donald Becker.
Copyright 1993 United States Government as represented by the
Copyright 1993 United States Government as represented by the
Director, National Security Agency. This software may be used and
Director, National Security Agency.
distributed according to the terms of the GNU Public License,
incorporated herein by reference.
This is a driver for the SMC Ultra ethercard.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
The Author may be reached as becker@super.org or
This is a driver for the SMC Ultra ethercard.
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
*/
*/
static
char
*
version
=
static
char
*
version
=
"smc-ultra.c:v0.07 3/1/94 Donald Becker (becker@super.org
)
\n
"
;
"smc-ultra.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov
)
\n
"
;
#include <linux/config.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
...
@@ -26,15 +29,15 @@ static char *version =
...
@@ -26,15 +29,15 @@ static char *version =
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include "8390.h"
#include "8390.h"
extern
struct
device
*
init_etherdev
(
struct
device
*
dev
,
int
sizeof_private
,
unsigned
long
*
mem_startp
);
/* Compatibility definitions for earlier kernel versions. */
/* A zero-terminated list of I/O addresses to be probed. */
#ifndef HAVE_PORTRESERVE
static
unsigned
int
ultra_portlist
[]
=
#define check_region(ioaddr, size) 0
{
0x200
,
0x220
,
0x240
,
0x280
,
0x300
,
0x340
,
0x380
,
0
};
#define snarf_region(ioaddr, size); do ; while (0)
#endif
int
ultra
probe
(
int
ioaddr
,
struct
device
*
dev
);
int
ultra
_probe
(
struct
device
*
dev
);
int
ultra
probe1
(
int
ioaddr
,
struct
device
*
dev
);
int
ultra
_probe1
(
struct
device
*
dev
,
int
ioaddr
);
static
int
ultra_open
(
struct
device
*
dev
);
static
int
ultra_open
(
struct
device
*
dev
);
static
void
ultra_reset_8390
(
struct
device
*
dev
);
static
void
ultra_reset_8390
(
struct
device
*
dev
);
...
@@ -51,43 +54,51 @@ static int ultra_close_card(struct device *dev);
...
@@ -51,43 +54,51 @@ static int ultra_close_card(struct device *dev);
#define ULTRA_RESET 0x80
/* Board reset, in ULTRA_CMDREG. */
#define ULTRA_RESET 0x80
/* Board reset, in ULTRA_CMDREG. */
#define ULTRA_MEMENB 0x40
/* Enable the shared memory. */
#define ULTRA_MEMENB 0x40
/* Enable the shared memory. */
#define ULTRA_NIC_OFFSET 16
/* NIC register offset from the base_addr. */
#define ULTRA_NIC_OFFSET 16
/* NIC register offset from the base_addr. */
#define ULTRA_IO_EXTENT 32
/* Probe for the Ultra. This looks like a 8013 with the station
/* Probe for the Ultra. This looks like a 8013 with the station
address PROM at I/O ports <base>+8 to <base>+13, with a checksum
address PROM at I/O ports <base>+8 to <base>+13, with a checksum
following.
following.
*/
*/
#ifdef HAVE_DEVLIST
struct
netdev_entry
ultra_drv
=
{
"ultra"
,
ultra_probe1
,
NETCARD_IO_EXTENT
,
netcard_portlist
};
#else
int
ultra_probe
(
struct
device
*
dev
)
int
ultra_probe
(
struct
device
*
dev
)
{
{
int
*
port
,
ports
[]
=
{
0x200
,
0x220
,
0x240
,
0x280
,
0x300
,
0x340
,
0x380
,
0
}
;
int
i
;
unsigned
short
ioaddr
=
dev
->
base_addr
;
int
base_addr
=
dev
?
dev
->
base_addr
:
0
;
if
(
ioaddr
>
0x1ff
)
if
(
base_addr
>
0x1ff
)
/* Check a single specified location. */
return
ultraprobe1
(
ioaddr
,
dev
);
return
ultra_probe1
(
dev
,
base_addr
);
else
if
(
ioaddr
>
0
)
else
if
(
base_addr
!=
0
)
/* Don't probe at all. */
return
ENXIO
;
/* Don't probe at all. */
return
ENXIO
;
for
(
port
=
&
ports
[
0
];
*
port
;
port
++
)
{
for
(
i
=
0
;
ultra_portlist
[
i
];
i
++
)
{
if
(
check_region
(
*
port
,
32
))
int
ioaddr
=
ultra_portlist
[
i
];
if
(
check_region
(
ioaddr
,
ULTRA_IO_EXTENT
))
continue
;
continue
;
if
((
inb
(
*
port
+
7
)
&
0xF0
)
==
0x20
/* Check chip ID nibble. */
if
(
ultra_probe1
(
dev
,
ioaddr
)
==
0
)
&&
ultraprobe1
(
*
port
,
dev
)
==
0
)
return
0
;
return
0
;
}
}
dev
->
base_addr
=
ioaddr
;
return
ENODEV
;
return
ENODEV
;
}
}
#endif
int
ultra
probe1
(
int
ioaddr
,
struct
device
*
dev
)
int
ultra
_probe1
(
struct
device
*
dev
,
int
ioaddr
)
{
{
int
i
;
int
i
;
unsigned
char
*
station_addr
=
dev
->
dev_addr
;
int
checksum
=
0
;
int
checksum
=
0
;
char
*
model_name
;
char
*
model_name
;
unsigned
char
eeprom_irq
=
0
;
unsigned
char
eeprom_irq
=
0
;
/* Values from various config regs. */
/* Values from various config regs. */
unsigned
char
num_pages
,
irqreg
,
addr
,
reg4
=
inb
(
ioaddr
+
4
)
&
0x7f
;
unsigned
char
num_pages
,
irqreg
,
addr
,
reg4
=
inb
(
ioaddr
+
4
)
&
0x7f
;
/* Check the ID nibble. */
if
((
inb
(
ioaddr
+
7
)
&
0xF0
)
!=
0x20
)
return
ENODEV
;
/* Select the station address register set. */
/* Select the station address register set. */
outb
(
reg4
,
ioaddr
+
4
);
outb
(
reg4
,
ioaddr
+
4
);
...
@@ -97,15 +108,19 @@ int ultraprobe1(int ioaddr, struct device *dev)
...
@@ -97,15 +108,19 @@ int ultraprobe1(int ioaddr, struct device *dev)
if
((
checksum
&
0xff
)
!=
0xFF
)
if
((
checksum
&
0xff
)
!=
0xFF
)
return
ENODEV
;
return
ENODEV
;
if
(
dev
==
NULL
)
dev
=
init_etherdev
(
0
,
sizeof
(
struct
ei_device
),
0
);
printk
(
"%s: SMC Ultra at %#3x,"
,
dev
->
name
,
ioaddr
);
printk
(
"%s: SMC Ultra at %#3x,"
,
dev
->
name
,
ioaddr
);
for
(
i
=
0
;
i
<
6
;
i
++
)
for
(
i
=
0
;
i
<
6
;
i
++
)
printk
(
" %2.2X"
,
station
_addr
[
i
]
=
inb
(
ioaddr
+
8
+
i
));
printk
(
" %2.2X"
,
dev
->
dev
_addr
[
i
]
=
inb
(
ioaddr
+
8
+
i
));
/* Switch from the station address to the alternate register set and
/* Switch from the station address to the alternate register set and
read the useful registers there. */
read the useful registers there. */
outb
(
0x80
|
reg4
,
ioaddr
+
4
);
outb
(
0x80
|
reg4
,
ioaddr
+
4
);
/* Enabled FINE16 mode to avoid BIOS ROM width mismatches during
reboot. */
/* Enabled FINE16 mode to avoid BIOS ROM width mismatches @
reboot. */
outb
(
0x80
|
inb
(
ioaddr
+
0x0c
),
ioaddr
+
0x0c
);
outb
(
0x80
|
inb
(
ioaddr
+
0x0c
),
ioaddr
+
0x0c
);
irqreg
=
inb
(
ioaddr
+
0xd
);
irqreg
=
inb
(
ioaddr
+
0xd
);
addr
=
inb
(
ioaddr
+
0xb
);
addr
=
inb
(
ioaddr
+
0xb
);
...
@@ -264,5 +279,7 @@ ultra_close_card(struct device *dev)
...
@@ -264,5 +279,7 @@ ultra_close_card(struct device *dev)
* compile-command: "gcc -D__KERNEL__ -Wall -O6 -I/usr/src/linux/net/inet -c smc-ultra.c"
* compile-command: "gcc -D__KERNEL__ -Wall -O6 -I/usr/src/linux/net/inet -c smc-ultra.c"
* version-control: t
* version-control: t
* kept-new-versions: 5
* kept-new-versions: 5
* c-indent-level: 4
* tab-width: 4
* End:
* End:
*/
*/
drivers/net/wd.c
View file @
6e38a55b
/* wd.c: A WD80x3 ethernet driver for linux. */
/* wd.c: A WD80x3 ethernet driver for linux. */
/*
/*
Written 1993 by Donald Becker.
Written 1993-94 by Donald Becker.
Copyright 1993 United States Government as represented by the
Copyright 1993 United States Government as represented by the
Director, National Security Agency. This software may be used and
Director, National Security Agency.
distributed according to the terms of the GNU Public License,
incorporated herein by reference.
This is a driver for WD8003 and WD8013 "compatible" ethercards.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
The Author may be reached as becker@super.org or
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This is a driver for WD8003 and WD8013 "compatible" ethercards.
Thanks to Russ Nelson (nelson@crnwyr.com) for loaning me a WD8013.
Thanks to Russ Nelson (nelson@crnwyr.com) for loaning me a WD8013.
*/
*/
static
char
*
version
=
static
char
*
version
=
"wd.c:v
0.99-14 11/21/93 Donald Becker (becker@super.org
)
\n
"
;
"wd.c:v
1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov
)
\n
"
;
#include <linux/config.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
...
@@ -27,15 +30,15 @@ static char *version =
...
@@ -27,15 +30,15 @@ static char *version =
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include "8390.h"
#include "8390.h"
extern
struct
device
*
init_etherdev
(
struct
device
*
dev
,
int
sizeof_private
,
unsigned
long
*
mem_startp
);
/* Compatibility definitions for earlier kernel versions. */
/* A zero-terminated list of I/O addresses to be probed. */
#ifndef HAVE_PORTRESERVE
static
unsigned
int
wd_portlist
[]
=
#define check_region(ioaddr, size) 0
{
0x300
,
0x280
,
0x380
,
0x240
,
0
};
#define snarf_region(ioaddr, size) do ; while (0)
#endif
int
wd_probe
(
struct
device
*
dev
);
int
wd_probe
(
struct
device
*
dev
);
int
wd
probe1
(
int
ioaddr
,
struct
device
*
dev
);
int
wd
_probe1
(
struct
device
*
dev
,
int
ioaddr
);
static
int
wd_open
(
struct
device
*
dev
);
static
int
wd_open
(
struct
device
*
dev
);
static
void
wd_reset_8390
(
struct
device
*
dev
);
static
void
wd_reset_8390
(
struct
device
*
dev
);
...
@@ -56,42 +59,48 @@ static int wd_close_card(struct device *dev);
...
@@ -56,42 +59,48 @@ static int wd_close_card(struct device *dev);
#define WD_CMDREG5 5
/* Offset to 16-bit-only ASIC register 5. */
#define WD_CMDREG5 5
/* Offset to 16-bit-only ASIC register 5. */
#define ISA16 0x80
/* Enable 16 bit access from the ISA bus. */
#define ISA16 0x80
/* Enable 16 bit access from the ISA bus. */
#define NIC16 0x40
/* Enable 16 bit access from the 8390. */
#define NIC16 0x40
/* Enable 16 bit access from the 8390. */
#define WD_NIC_OFFSET 16
/* Offset to the 8390 NIC from the base_addr. */
#define WD_NIC_OFFSET 16
/* Offset to the 8390 from the base_addr. */
#define WD_IO_EXTENT 32
/* Probe for the WD8003 and WD8013. These cards have the station
/* Probe for the WD8003 and WD8013. These cards have the station
address PROM at I/O ports <base>+8 to <base>+13, with a checksum
address PROM at I/O ports <base>+8 to <base>+13, with a checksum
following. A Soundblaster can have the same checksum as an WDethercard,
following. A Soundblaster can have the same checksum as an WDethercard,
so we have an extra exclusionary check for it.
so we have an extra exclusionary check for it.
The wdprobe1() routine initializes the card and fills the
The wd
_
probe1() routine initializes the card and fills the
station address field. */
station address field. */
#ifdef HAVE_DEVLIST
struct
netdev_entry
wd_drv
=
{
"wd"
,
wd_probe1
,
WD_IO_EXTENT
,
wd_portlist
};
#else
int
wd_probe
(
struct
device
*
dev
)
int
wd_probe
(
struct
device
*
dev
)
{
{
int
*
port
,
ports
[]
=
{
0x300
,
0x280
,
0x380
,
0x240
,
0
}
;
int
i
;
short
ioaddr
=
dev
->
base_addr
;
int
base_addr
=
dev
?
dev
->
base_addr
:
0
;
if
(
ioaddr
<
0
)
if
(
base_addr
>
0x1ff
)
/* Check a single specified location. */
return
ENXIO
;
/* Don't probe at all. */
return
wd_probe1
(
dev
,
base_addr
);
if
(
ioaddr
>
0x100
)
else
if
(
base_addr
!=
0
)
/* Don't probe at all. */
return
!
wdprobe1
(
ioaddr
,
dev
)
;
return
ENXIO
;
for
(
port
=
&
ports
[
0
];
*
port
;
port
++
)
{
for
(
i
=
0
;
wd_portlist
[
i
];
i
++
)
{
if
(
check_region
(
*
port
,
32
))
int
ioaddr
=
wd_portlist
[
i
];
if
(
check_region
(
ioaddr
,
WD_IO_EXTENT
))
continue
;
continue
;
if
(
inb
(
*
port
+
8
)
!=
0xff
if
(
wd_probe1
(
dev
,
ioaddr
)
==
0
)
&&
inb
(
*
port
+
9
)
!=
0xff
/* Extra check to avoid soundcard. */
&&
wdprobe1
(
*
port
,
dev
))
return
0
;
return
0
;
}
}
dev
->
base_addr
=
ioaddr
;
return
ENODEV
;
return
ENODEV
;
}
}
#endif
int
wd
probe1
(
int
ioaddr
,
struct
device
*
dev
)
int
wd
_probe1
(
struct
device
*
dev
,
int
ioaddr
)
{
{
int
i
;
int
i
;
unsigned
char
*
station_addr
=
dev
->
dev_addr
;
int
checksum
=
0
;
int
checksum
=
0
;
int
ancient
=
0
;
/* An old card without config registers. */
int
ancient
=
0
;
/* An old card without config registers. */
int
word16
=
0
;
/* 0 = 8 bit, 1 = 16 bit */
int
word16
=
0
;
/* 0 = 8 bit, 1 = 16 bit */
...
@@ -99,12 +108,17 @@ int wdprobe1(int ioaddr, struct device *dev)
...
@@ -99,12 +108,17 @@ int wdprobe1(int ioaddr, struct device *dev)
for
(
i
=
0
;
i
<
8
;
i
++
)
for
(
i
=
0
;
i
<
8
;
i
++
)
checksum
+=
inb
(
ioaddr
+
8
+
i
);
checksum
+=
inb
(
ioaddr
+
8
+
i
);
if
((
checksum
&
0xff
)
!=
0xFF
)
if
(
inb
(
ioaddr
+
8
)
==
0xff
/* Extra check to avoid soundcard. */
return
0
;
||
inb
(
ioaddr
+
9
)
==
0xff
||
(
checksum
&
0xff
)
!=
0xFF
)
return
ENODEV
;
if
(
dev
==
NULL
)
dev
=
init_etherdev
(
0
,
sizeof
(
struct
ei_device
),
0
);
printk
(
"%s: WD80x3 at %#3x, "
,
dev
->
name
,
ioaddr
);
printk
(
"%s: WD80x3 at %#3x, "
,
dev
->
name
,
ioaddr
);
for
(
i
=
0
;
i
<
6
;
i
++
)
for
(
i
=
0
;
i
<
6
;
i
++
)
printk
(
" %2.2X"
,
station
_addr
[
i
]
=
inb
(
ioaddr
+
8
+
i
));
printk
(
" %2.2X"
,
dev
->
dev
_addr
[
i
]
=
inb
(
ioaddr
+
8
+
i
));
/* The following PureData probe code was contributed by
/* The following PureData probe code was contributed by
Mike Jagdis <jaggy@purplet.demon.co.uk>. Puredata does software
Mike Jagdis <jaggy@purplet.demon.co.uk>. Puredata does software
...
@@ -218,11 +232,11 @@ int wdprobe1(int ioaddr, struct device *dev)
...
@@ -218,11 +232,11 @@ int wdprobe1(int ioaddr, struct device *dev)
share and the board will usually be enabled. */
share and the board will usually be enabled. */
if
(
request_irq
(
dev
->
irq
,
ei_interrupt
,
0
,
"wd"
))
{
if
(
request_irq
(
dev
->
irq
,
ei_interrupt
,
0
,
"wd"
))
{
printk
(
" unable to get IRQ %d.
\n
"
,
dev
->
irq
);
printk
(
" unable to get IRQ %d.
\n
"
,
dev
->
irq
);
return
0
;
return
EAGAIN
;
}
}
/* OK, were are certain this is going to work. Setup the device. */
/* OK, were are certain this is going to work. Setup the device. */
snarf_region
(
ioaddr
,
32
);
snarf_region
(
ioaddr
,
WD_IO_EXTENT
);
ethdev_init
(
dev
);
ethdev_init
(
dev
);
ei_status
.
name
=
model_name
;
ei_status
.
name
=
model_name
;
...
@@ -248,7 +262,7 @@ int wdprobe1(int ioaddr, struct device *dev)
...
@@ -248,7 +262,7 @@ int wdprobe1(int ioaddr, struct device *dev)
dev
->
stop
=
&
wd_close_card
;
dev
->
stop
=
&
wd_close_card
;
NS8390_init
(
dev
,
0
);
NS8390_init
(
dev
,
0
);
return
dev
->
base_addr
;
return
0
;
}
}
static
int
static
int
...
...
drivers/net/znet.c
View file @
6e38a55b
/* znet.c: An Zenith Z-Note ethernet driver for linux. */
/* znet.c: An Zenith Z-Note ethernet driver for linux. */
static
char
*
version
=
"znet.c:v1.0
1 7/1
/94 becker@cesdis.gsfc.nasa.gov
\n
"
;
static
char
*
version
=
"znet.c:v1.0
2 9/23
/94 becker@cesdis.gsfc.nasa.gov
\n
"
;
/*
/*
Written by Donald Becker.
Written by Donald Becker.
...
@@ -81,7 +81,7 @@ static char *version = "znet.c:v1.01 7/1/94 becker@cesdis.gsfc.nasa.gov\n";
...
@@ -81,7 +81,7 @@ static char *version = "znet.c:v1.01 7/1/94 becker@cesdis.gsfc.nasa.gov\n";
#include <linux/if_arp.h>
#include <linux/if_arp.h>
#ifndef ZNET_DEBUG
#ifndef ZNET_DEBUG
#define ZNET_DEBUG
3
#define ZNET_DEBUG
1
#endif
#endif
static
unsigned
int
znet_debug
=
ZNET_DEBUG
;
static
unsigned
int
znet_debug
=
ZNET_DEBUG
;
...
...
drivers/scsi/scsi.c
View file @
6e38a55b
...
@@ -1804,7 +1804,7 @@ unsigned long scsi_dev_init (unsigned long memory_start,unsigned long memory_end
...
@@ -1804,7 +1804,7 @@ unsigned long scsi_dev_init (unsigned long memory_start,unsigned long memory_end
host
->
hostt
->
cmd_per_lun
;
host
->
hostt
->
cmd_per_lun
;
if
(
host
->
unchecked_isa_dma
&&
if
(
host
->
unchecked_isa_dma
&&
memory_end
>
ISA_DMA_THRESHOLD
&&
memory_end
-
1
>
ISA_DMA_THRESHOLD
&&
SDpnt
->
type
!=
TYPE_TAPE
)
{
SDpnt
->
type
!=
TYPE_TAPE
)
{
dma_sectors
+=
(
PAGE_SIZE
>>
9
)
*
host
->
sg_tablesize
*
dma_sectors
+=
(
PAGE_SIZE
>>
9
)
*
host
->
sg_tablesize
*
host
->
hostt
->
cmd_per_lun
;
host
->
hostt
->
cmd_per_lun
;
...
...
fs/nfs/proc.c
View file @
6e38a55b
fs/nfs/sock.c
View file @
6e38a55b
...
@@ -209,7 +209,9 @@ static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end, int
...
@@ -209,7 +209,9 @@ static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end, int
size
+
1024
,
1
,
0
,
NULL
,
size
+
1024
,
1
,
0
,
NULL
,
/* Here is NFS_SLACK_SPACE..., hack */
/* Here is NFS_SLACK_SPACE..., hack */
&
addrlen
);
&
addrlen
);
if
(
result
<
addrlen
)
{
if
(
result
<
0
)
{
printk
(
"NFS: notice message: result=%d
\n
"
,
result
);
}
else
if
(
result
<
addrlen
)
{
printk
(
"NFS: just caught a too small read memory size..., email to NET channel
\n
"
);
printk
(
"NFS: just caught a too small read memory size..., email to NET channel
\n
"
);
printk
(
"NFS: result=%d,addrlen=%d
\n
"
,
result
,
addrlen
);
printk
(
"NFS: result=%d,addrlen=%d
\n
"
,
result
,
addrlen
);
result
=
-
EIO
;
result
=
-
EIO
;
...
...
fs/nfs/symlink.c
View file @
6e38a55b
...
@@ -71,10 +71,16 @@ static int nfs_follow_link(struct inode *dir, struct inode *inode,
...
@@ -71,10 +71,16 @@ static int nfs_follow_link(struct inode *dir, struct inode *inode,
}
}
error
=
nfs_proc_readlink
(
NFS_SERVER
(
inode
),
NFS_FH
(
inode
),
&
mem
,
error
=
nfs_proc_readlink
(
NFS_SERVER
(
inode
),
NFS_FH
(
inode
),
&
mem
,
&
res
,
&
len
,
NFS_MAXPATHLEN
);
&
res
,
&
len
,
NFS_MAXPATHLEN
);
#if 1
if
((
res2
=
(
char
*
)
kmalloc
(
NFS_MAXPATHLEN
+
1
,
GFP_KERNEL
))
==
NULL
)
{
if
((
res2
=
(
char
*
)
kmalloc
(
NFS_MAXPATHLEN
+
1
,
GFP_KERNEL
))
==
NULL
)
{
printk
(
"NFS: no memory in nfs_follow_link
\n
"
);
printk
(
"NFS: no memory in nfs_follow_link
\n
"
);
error
=
-
EIO
;
error
=
-
EIO
;
}
}
#else
while
((
res2
=
(
char
*
)
kmalloc
(
NFS_MAXPATHLEN
+
1
,
GFP_KERNEL
))
==
NULL
)
{
schedule
();
}
#endif
if
(
error
)
{
if
(
error
)
{
iput
(
inode
);
iput
(
inode
);
iput
(
dir
);
iput
(
dir
);
...
...
include/linux/resource.h
View file @
6e38a55b
...
@@ -54,7 +54,7 @@ struct rusage {
...
@@ -54,7 +54,7 @@ struct rusage {
#define RLIM_NLIMITS 6
#define RLIM_NLIMITS 6
#define RLIM_INFINITY
0x7FFFFFFF
#define RLIM_INFINITY
((long)(~0UL>>1))
struct
rlimit
{
struct
rlimit
{
int
rlim_cur
;
int
rlim_cur
;
...
...
include/linux/signal.h
View file @
6e38a55b
...
@@ -13,7 +13,7 @@ typedef unsigned int sigset_t; /* 32 bits */
...
@@ -13,7 +13,7 @@ typedef unsigned int sigset_t; /* 32 bits */
#define SIGTRAP 5
#define SIGTRAP 5
#define SIGABRT 6
#define SIGABRT 6
#define SIGIOT 6
#define SIGIOT 6
#define SIG
UNUSED
7
#define SIG
BUS
7
#define SIGFPE 8
#define SIGFPE 8
#define SIGKILL 9
#define SIGKILL 9
#define SIGUSR1 10
#define SIGUSR1 10
...
@@ -29,32 +29,19 @@ typedef unsigned int sigset_t; /* 32 bits */
...
@@ -29,32 +29,19 @@ typedef unsigned int sigset_t; /* 32 bits */
#define SIGTSTP 20
#define SIGTSTP 20
#define SIGTTIN 21
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGTTOU 22
/*
* Most of these aren't used yet (and perhaps never will),
* so they are commented out.
*/
#define SIGIO 23
#define SIGIO 23
#define SIGPOLL SIGIO
#define SIGPOLL SIGIO
#define SIGURG SIGIO
#define SIGURG SIGIO
#define SIGXCPU 24
#define SIGXCPU 24
#define SIGXFSZ 25
#define SIGXFSZ 25
#define SIGVTALRM 26
#define SIGVTALRM 26
#define SIGPROF 27
#define SIGPROF 27
#define SIGWINCH 28
#define SIGWINCH 28
/*
/*
#define SIGLOST 29
#define SIGLOST 29
*/
*/
#define SIGPWR 30
#define SIGPWR 30
#define SIGUNUSED 31
/* Arggh. Bad user source code wants this.. */
#define SIGBUS SIGUNUSED
/*
/*
* sa_flags values: SA_STACK is not currently supported, but will allow the
* sa_flags values: SA_STACK is not currently supported, but will allow the
...
...
kernel/sched.c
View file @
6e38a55b
...
@@ -600,7 +600,7 @@ static void do_timer(struct pt_regs * regs)
...
@@ -600,7 +600,7 @@ static void do_timer(struct pt_regs * regs)
unsigned
long
mask
;
unsigned
long
mask
;
struct
timer_struct
*
tp
;
struct
timer_struct
*
tp
;
long
ltemp
;
long
ltemp
,
psecs
;
/* Advance the phase, once it gets to one microsecond, then
/* Advance the phase, once it gets to one microsecond, then
* advance the tick more.
* advance the tick more.
...
@@ -679,12 +679,20 @@ static void do_timer(struct pt_regs * regs)
...
@@ -679,12 +679,20 @@ static void do_timer(struct pt_regs * regs)
/*
/*
* check the cpu time limit on the process.
* check the cpu time limit on the process.
*/
*/
if
((
current
->
rlim
[
RLIMIT_CPU
].
rlim_cur
!=
RLIM_INFINITY
)
&&
(((
current
->
stime
+
current
->
utime
)
/
HZ
)
>=
current
->
rlim
[
RLIMIT_CPU
].
rlim_cur
))
send_sig
(
SIGXCPU
,
current
,
1
);
if
((
current
->
rlim
[
RLIMIT_CPU
].
rlim_max
!=
RLIM_INFINITY
)
&&
if
((
current
->
rlim
[
RLIMIT_CPU
].
rlim_max
!=
RLIM_INFINITY
)
&&
(((
current
->
stime
+
current
->
utime
)
/
HZ
)
>=
current
->
rlim
[
RLIMIT_CPU
].
rlim_max
))
(((
current
->
stime
+
current
->
utime
)
/
HZ
)
>=
current
->
rlim
[
RLIMIT_CPU
].
rlim_max
))
send_sig
(
SIGKILL
,
current
,
1
);
send_sig
(
SIGKILL
,
current
,
1
);
if
((
current
->
rlim
[
RLIMIT_CPU
].
rlim_cur
!=
RLIM_INFINITY
)
&&
(((
current
->
stime
+
current
->
utime
)
%
HZ
)
==
0
))
{
psecs
=
(
current
->
stime
+
current
->
utime
)
/
HZ
;
/* send when equal */
if
(
psecs
==
current
->
rlim
[
RLIMIT_CPU
].
rlim_cur
)
send_sig
(
SIGXCPU
,
current
,
1
);
/* and every five seconds thereafter. */
else
if
((
psecs
>
current
->
rlim
[
RLIMIT_CPU
].
rlim_cur
)
&&
((
psecs
-
current
->
rlim
[
RLIMIT_CPU
].
rlim_cur
)
%
5
)
==
0
)
send_sig
(
SIGXCPU
,
current
,
1
);
}
if
(
current
!=
task
[
0
]
&&
0
>
--
current
->
counter
)
{
if
(
current
!=
task
[
0
]
&&
0
>
--
current
->
counter
)
{
current
->
counter
=
0
;
current
->
counter
=
0
;
...
...
kernel/signal.c
View file @
6e38a55b
...
@@ -217,8 +217,8 @@ if (!(context.x & 0xfffc) || (context.x & 3) != 3) goto badframe; COPY(x);
...
@@ -217,8 +217,8 @@ if (!(context.x & 0xfffc) || (context.x & 3) != 3) goto badframe; COPY(x);
COPY
(
ebx
);
COPY
(
ebx
);
COPY
(
esp
);
COPY
(
ebp
);
COPY
(
esp
);
COPY
(
ebp
);
COPY
(
edi
);
COPY
(
esi
);
COPY
(
edi
);
COPY
(
esi
);
regs
->
eflags
&=
~
0x
C
D5
;
regs
->
eflags
&=
~
0x
40D
D5
;
regs
->
eflags
|=
context
.
eflags
&
0x
C
D5
;
regs
->
eflags
|=
context
.
eflags
&
0x
40D
D5
;
regs
->
orig_eax
=
-
1
;
/* disable syscall checks */
regs
->
orig_eax
=
-
1
;
/* disable syscall checks */
return
context
.
eax
;
return
context
.
eax
;
badframe:
badframe:
...
...
kernel/vm86.c
View file @
6e38a55b
...
@@ -45,8 +45,8 @@
...
@@ -45,8 +45,8 @@
#define set_flags(X,new,mask) \
#define set_flags(X,new,mask) \
((X) = ((X) & ~(mask)) | ((new) & (mask)))
((X) = ((X) & ~(mask)) | ((new) & (mask)))
#define SAFE_MASK (0xDD5)
#define SAFE_MASK (0x
40
DD5)
#define RETURN_MASK (0xDFF)
#define RETURN_MASK (0x
40
DFF)
asmlinkage
struct
pt_regs
*
save_v86_state
(
struct
vm86_regs
*
regs
)
asmlinkage
struct
pt_regs
*
save_v86_state
(
struct
vm86_regs
*
regs
)
{
{
...
...
net/inet/icmp.c
View file @
6e38a55b
...
@@ -23,6 +23,7 @@
...
@@ -23,6 +23,7 @@
* Alan Cox : Removed old debugging junk
* Alan Cox : Removed old debugging junk
* Alan Cox : Fixed the ICMP error status of net/host unreachable
* Alan Cox : Fixed the ICMP error status of net/host unreachable
* Gerhard Koerting : Fixed broadcast ping properly
* Gerhard Koerting : Fixed broadcast ping properly
* Ulrich Kunitz : Fixed ICMP timestamp reply
*
*
*
*
*
*
...
@@ -425,7 +426,20 @@ static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct de
...
@@ -425,7 +426,20 @@ static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct de
unsigned
long
*
timeptr
,
midtime
;
unsigned
long
*
timeptr
,
midtime
;
struct
device
*
ndev
=
NULL
;
struct
device
*
ndev
=
NULL
;
size
=
dev
->
hard_header_len
+
64
+
len
;
if
(
len
!=
20
)
{
printk
(
"ICMP: Size (%d) of ICMP_TIMESTAMP request should be 20!
\n
"
,
len
);
icmp_statistics
.
IcmpInErrors
++
;
#if 1
/* correct answers are possible for everything >= 12 */
if
(
len
<
12
)
#endif
return
;
}
size
=
dev
->
hard_header_len
+
84
;
if
(
!
(
skb2
=
alloc_skb
(
size
,
GFP_ATOMIC
)))
if
(
!
(
skb2
=
alloc_skb
(
size
,
GFP_ATOMIC
)))
{
{
...
@@ -454,14 +468,14 @@ static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct de
...
@@ -454,14 +468,14 @@ static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct de
/*
/*
* Re-adjust length according to actual IP header size.
* Re-adjust length according to actual IP header size.
*/
*/
skb2
->
len
=
offset
+
len
;
skb2
->
len
=
offset
+
20
;
/*
/*
* Build ICMP_TIMESTAMP Response message.
* Build ICMP_TIMESTAMP Response message.
*/
*/
icmphr
=
(
struct
icmphdr
*
)
((
char
*
)
(
skb2
+
1
)
+
offset
);
icmphr
=
(
struct
icmphdr
*
)
((
char
*
)
(
skb2
+
1
)
+
offset
);
memcpy
((
char
*
)
icmphr
,
(
char
*
)
icmph
,
len
);
memcpy
((
char
*
)
icmphr
,
(
char
*
)
icmph
,
12
);
icmphr
->
type
=
ICMP_TIMESTAMPREPLY
;
icmphr
->
type
=
ICMP_TIMESTAMPREPLY
;
icmphr
->
code
=
icmphr
->
checksum
=
0
;
icmphr
->
code
=
icmphr
->
checksum
=
0
;
...
@@ -473,7 +487,7 @@ static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct de
...
@@ -473,7 +487,7 @@ static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct de
*/
*/
timeptr
[
1
]
=
timeptr
[
2
]
=
htonl
(
midtime
);
timeptr
[
1
]
=
timeptr
[
2
]
=
htonl
(
midtime
);
icmphr
->
checksum
=
ip_compute_csum
((
unsigned
char
*
)
icmphr
,
len
);
icmphr
->
checksum
=
ip_compute_csum
((
unsigned
char
*
)
icmphr
,
20
);
/*
/*
* Ship it out - free it when done
* Ship it out - free it when done
...
...
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